Skip to content

feat: close MCP AC gap + sync SKILL.md version on release (SMI-4324, SMI-4325)#20

Merged
wrsmith108 merged 2 commits into
mainfrom
ryansmith108/smi-4324-close-mcp-save_issue-gap-in-ac-enforcement
Apr 19, 2026
Merged

feat: close MCP AC gap + sync SKILL.md version on release (SMI-4324, SMI-4325)#20
wrsmith108 merged 2 commits into
mainfrom
ryansmith108/smi-4324-close-mcp-save_issue-gap-in-ac-enforcement

Conversation

@wrsmith108

Copy link
Copy Markdown
Owner

Summary

Follow-up to the v3.0.0 AC enforcement release. Two independent fixes shipped together as they share the same Linear project (Issue Description Validation).

  • SMI-4324 — Close the MCP save_issue gap in AC enforcement. The Linear MCP server is hosted, so we can't server-side-gate it. Adds a pre-flight CLI validator (validate-description) for Claude to run before save_issue, plus a retroactive lint-issues audit script.
  • SMI-4325 — Teach semantic-release to sync SKILL.md frontmatter version: to match package.json. Drift recurred after v3.0.0 (commit d5487f1 fixed it by hand). Skillsmith's trust-tier validator reads SKILL.md version — drift here demotes trust tier, not just cosmetics.

Enforcement model (SMI-4324)

Honest framing: CLI + SDK paths are hard-gated; the MCP path is instruction + retroactive audit, not a mechanical block.

  1. Pre-flight: SKILL.md tells Claude to pipe drafts through validate-description --stdin before save_issue.
  2. Retroactive: npm run lint-issues -- --since 24h surfaces any instruction-layer drift.
  3. Rejected: a PreToolUse hook — only fires in Claude Code runtime, install is per-user, payload shape is harness-version-dependent.

Changes

SMI-4324:

  • scripts/linear-ops.ts — new validate-description subcommand (positional body / --file / --stdin, --strict=false supported, exit 0/5/2, no LINEAR_API_KEY required)
  • scripts/lint-issues.ts — new audit script (--since, --project, --limit, --json), mutates nothing
  • SKILL.md — rewrote the MCP callout (lines 180, 207) with a --stdin example and the tiered-enforcement note
  • scripts/__tests__/validate-description.test.ts + lint-issues.test.ts — 18 new end-to-end tests, all env: { ...process.env, LINEAR_API_KEY: '' } so they don't inherit a real key
  • package.jsonlint-issues npm script

SMI-4325:

  • scripts/sync-skill-version.mjs — plain-ESM helper that rewrites only the version: line inside SKILL.md's frontmatter block (scoped by first --- fences, fails loud on missing frontmatter/version line)
  • release.config.js@semantic-release/exec runs the helper as prepareCmd between @semantic-release/npm and @semantic-release/git; added SKILL.md to git assets
  • package.json@semantic-release/exec ^6.0.3 devDep

Verification

  • npm run build — typecheck + esbuild clean
  • npm test47/47 pass (18 new tests across two new files)
  • Manual CLI: empty body → 5, SKILL.md (no AC) → 5, valid --stdin → 0, lint-issues no-flags → 2, lint-issues no-API-key → 1
  • sync-skill-version.mjs isolated run rewrites frontmatter only; missing-version → 1; missing-file → 1
  • release.config.js parses with 7 plugins in correct order

Test plan

  • Reviewer: npm ci && npm run build && npm test — expect 47/47 green
  • Reviewer: echo "" | node dist/linear-ops.js validate-description --stdin — expect exit 5
  • Reviewer: printf '## Context\nBody text long enough to satisfy the minimum body length threshold used by the validator.\n\n## Acceptance Criteria\n- [ ] one\n- [ ] two\n' | node dist/linear-ops.js validate-description --stdin — expect exit 0
  • On merge, the next release commit touches CHANGELOG.md, package.json, package-lock.json, and SKILL.md with matching versions

Review-deferred follow-ups

Captured in ~/.claude/plans/jiggly-inventing-coral.md:

  • Smoke test guard: SKILL.md frontmatter version equals package.json version (5 lines in smoke.test.ts)
  • Exit-code harmonization: migrate create-issue strict-failure exit 1EXIT_CODES.VALIDATION_ERROR (5)
  • Scheduled GitHub Action to run lint-issues --since 24h nightly (out of scope here)

🤖 Generated with Ruflo

wrsmith108 and others added 2 commits April 19, 2026 12:17
…(SMI-4324)

Closes the MCP save_issue gap left by v3.0.0 — the Linear MCP server is
hosted, so we can't server-side-gate it. Adds a pre-flight CLI validator
for Claude to run before save_issue, plus a retroactive audit script.

Changes:
- validate-description subcommand (scripts/linear-ops.ts): pure-logic
  wrapper around validateIssueDescription. Supports positional body,
  --file <path>, --stdin. Exit 0 = valid, 5 = invalid + strict, 2 = bad
  args. Runs without LINEAR_API_KEY.
- lint-issues script (scripts/lint-issues.ts): audits issues matching
  --since <duration> and/or --project <name>. Mutates nothing, emits a
  table or --json. Exits 5 if any scanned issue fails AC validation.
- SKILL.md: tiered enforcement model — CLI/SDK hard-gated, MCP is
  instruction + retroactive audit. Rejected a PreToolUse hook (only
  fires in Claude Code runtime; harness-version-dependent payloads).
- Two new end-to-end test files with env-scrubbing (LINEAR_API_KEY: '')
  following the smoke.test.ts pattern. 18 new tests; 47/47 pass.

Co-Authored-By: claude-flow <ruv@ruv.net>
Co-Authored-By: Claude <noreply@anthropic.com>
…MI-4325)

After the v3.0.0 release, SKILL.md frontmatter still said version: 2.6.1
until commit d5487f1 fixed it by hand. Skillsmith's trust-tier validator
reads the version: field from SKILL.md, not package.json — so drift here
demotes the trust tier, not just cosmetics.

Changes:
- scripts/sync-skill-version.mjs: plain-ESM helper that rewrites only the
  version: line inside SKILL.md's YAML frontmatter block. Scoped by the
  first --- fences so prose/code-example mentions of version: below are
  never touched. Fails loud with a clear error + recovery hint if the
  frontmatter or version: line is missing.
- release.config.js: @semantic-release/exec runs the helper as prepareCmd
  between @semantic-release/npm and @semantic-release/git. Added SKILL.md
  to the git assets so the synced frontmatter lands in the release commit
  alongside CHANGELOG.md, package.json, and package-lock.json.
- package.json: @semantic-release/exec ^6.0.3 devDep.

Verified:
- Helper updates version: in frontmatter only (isolated run)
- Missing version arg → exit 1 with usage
- Missing SKILL.md → exit 1 with ENOENT
- release.config.js parses with 7 plugins in correct order
- npm test: 47/47 pass

Co-Authored-By: claude-flow <ruv@ruv.net>
Co-Authored-By: Claude <noreply@anthropic.com>
@wrsmith108 wrsmith108 merged commit 2c2350c into main Apr 19, 2026
2 checks passed
@wrsmith108 wrsmith108 deleted the ryansmith108/smi-4324-close-mcp-save_issue-gap-in-ac-enforcement branch April 19, 2026 19:31
github-actions Bot pushed a commit that referenced this pull request Apr 19, 2026
# [3.1.0](v3.0.0...v3.1.0) (2026-04-19)

### Features

* close MCP AC gap + sync SKILL.md version on release (SMI-4324, SMI-4325) ([#20](#20)) ([2c2350c](2c2350c))
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 3.1.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant