92 Commits
Author SHA1 Message Date
cliffhallandClaude Opus 5.5 163a5e9357 test: skip the dispatch-status script tests without bash or jq
The job's script calls jq; on a machine without it the latest-run case
posts error instead of success, failing the gate over a missing test
prerequisite. Copilot round 1 on #5179.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-19 02:21:31 -04:00
cliffhallandClaude Opus 5.5 d533150b98 fix(ci): a superseded dispatched run posts no status, whatever its jobs did
dispatch-status checked for a newer dispatched run only in its
cancellation branch, so a superseded run whose job had already failed
posted `failure` over the newer run's status. The check now runs first,
in both python.yml and typescript.yml. A behavioral test runs each job's
script with a stub gh. Found by Copilot on #5166.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-19 02:13:35 -04:00
cliffhallandClaude Opus 5.5 521ddb24e3 ci: finalize a cancelled dispatched run's status, and pin the path
A dispatched run cancelled for any reason other than supersession left
its "(dispatched)" status pending forever (Copilot). The result job now
runs under always(): it stays silent only when a newer dispatched run of
the same workflow exists on the commit, and otherwise reports the
cancellation as an error. scripts/version-pr-ci.test.mjs pins each link
of the version-PR CI path, since nothing exercises it before a release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-13 01:34:51 -04:00
cliffhallandClaude Opus 5.5 fd55745f66 fix(scripts): double backslashes before a quote in win-shell-args
An argument ending in a backslash was quoted as "...\\", which the CRT
parser reads as an escaped quote, swallowing the rest of the command line.
Backslash runs before an embedded quote or the closing quote are now doubled,
with tests including a round trip through a reference CRT parser.

Closes #5111

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-13 00:48:54 -04:00
cliffhallandClaude Opus 5.5 c059fb6563 chore(release-notes): put the release-ledger line under the Packages table
The ledger line came after every package's PR list, the Repository section
and GitHub's trailer, so in v1.0.0 it sat below 102 PR lines and was moved
by hand before publishing. assembleNotes() now emits it directly after the
Packages table; the file header, the tests and the release skill's step 5a
list follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-11 23:23:26 -04:00
cliffhallandClaude Opus 5.5 9422c3f231 test: pin main-source.yml's safety properties; name the guard as a gate exception
Addresses Copilot round 1 on #5120.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-11 00:56:16 -04:00
cliffhallandClaude Opus 5.5 a8a13d3e25 ci: guard main so a PR into it brings nothing not already on v2/main
Adds scripts/verify-main-source.mjs and the main-source.yml workflow
(pull_request_target into main), which fails unless the PR's head commit
is on origin/v2/main. GitHub rulesets cannot restrict a PR's source
branch, so this check, made required on main, is what enforces the
milestone-merge-only rule in AGENTS.md.

Closes #5119

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-11 00:45:27 -04:00
cliffhallandClaude Opus 5.5 28b468edb7 test(release): pin the ./ tarball path npm publish needs
npm publish reads a bare dir/file argument as GitHub owner/repo shorthand and tries to clone it over SSH; the MCP Inspector's first release through the same split publish job failed that way (modelcontextprotocol/inspector#2551). release.yml already passes ./release-artifact/*.tgz; this asserts it, so the ./ cannot be lost in an edit. Reproduced locally with Node 24.21.0's npm: the bare path exits 128 on 'git ls-remote ssh://git@github.com/release-artifact/...', the ./ path dry-run-publishes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-10 13:05:44 -04:00
cliffhallandClaude Opus 5.5 4d13264593 test(release): pin the publish job's npm floor check and its no-install shape
scripts/release-npm-floor.test.mjs reads publish-npm out of release.yml, as release-dist-tag.test.mjs does, and runs the npm floor step with a stub npm on PATH: 11.5.1, 11.6.0, 11.19.0 and 12.0.0 pass, 11.5.0, 11.4.9, 10.9.9 and 9.0.0 fail. It also asserts an exact Node pin whose bundled npm meets the floor, the check ahead of the download and the publish, and no step that installs or runs a fetched package (comment lines ignored). The previous workflow fails all five; loosening the floor to 11.5.0 fails the refusal test (Copilot on #5105 and #5106).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-10 13:02:38 -04:00
cliffhallandClaude Opus 5.5 9d7128ca3b fix(interface-diff): drop target_ref; keep both streams in errors (#4860)
Copilot round 7 on #4975:
- Remove the dispatch `target_ref` input: a target that predates the
  script has no `npm run interface-diff`, so the run failed. The head is
  the branch chosen in "Use workflow from".
- A failed base install or build now reports the tail of both stdout and
  stderr, so tsc diagnostics are not lost behind an npm footer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-09 23:25:14 -04:00
cliffhallandClaude Opus 5.5 fe4cef3927 fix(interface-diff): never pass a report without a verdict (#4860)
Copilot round 5 on #4975:
- A result with no boolean hasDifferences is an error, not "unchanged".
- On a probe failure, report the CLI's contextual message ("Base server
  probe failed" / "Target probe failed") rather than the bare exception.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-09 23:25:14 -04:00
cliffhallandClaude Opus 5.5 a793ed4d99 fix(interface-diff): Dependabot, root tsconfig, Windows quoting (#4860)
Copilot round 3 on #4975 ("previously missed"):
- Skip the comment job on Dependabot PRs, which are same-repo but get a
  read-only token; they keep the summary and artifact like fork PRs.
- Trigger on the root tsconfig.json, which everything's tsconfig extends.
- Spawn only npm through a shell on Windows, with its arguments quoted by
  winShellArgs; git needs no shell.
- Silence the expected usage error in the script test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-09 23:25:14 -04:00
cliffhallandClaude Opus 5.5 f242458df7 fix(interface-diff): check out the event's SHA; report the CLI's stderr (#4860)
Copilot round 1 on #4975:
- Check out github.sha rather than github.ref, so a push run diffs the
  commit it was triggered for against that event's `before`, not a
  branch tip a later push moved.
- When mcp-server-diff prints no JSON report, include its stderr (where
  a fatal error goes) in the error, so the reason is not blank.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-09 23:25:14 -04:00
cliffhallandClaude Opus 5.5 e5ca90c71e ci(everything): run the interface diff as an npm script on v2/main (#4860)
Adapt #3260's workflow for v2/main:

- Run the check as `npm run interface-diff` (scripts/interface-diff.mjs),
  driving the mcp-server-diff 3.0.0 CLI as an exact-pinned root
  devDependency instead of the SHA-pinned v2.3.5 action. The same script
  is a new last stage of local:gate, which workflow-gate.test.mjs now
  requires, so the gate keeps running every check CI runs.
- Choose the base per event (the PR's base, the commit before a push, the
  previous release tag, or a dispatch input) instead of the tool's
  default merge-base with origin/main, which is wrong for v2/main PRs.
- Trigger pushes on main and v2/main, PRs on any base, and published
  Releases instead of the retired typescript-servers-* tags.
- Run the PR's code only in a read-only job with no persisted
  credentials; post the sticky comment from a separate job that holds
  pull-requests: write, runs no PR code, and only runs for same-repo PRs.
  Fork PRs keep the job summary and the report artifact.
- Give every job a timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-09 23:24:48 -04:00
Cliff Hall 6246e0f361 Merge branch 'v2/main' into v2/chore/4856-ts-sdk-v2 2026-10-07 17:10:05 -04:00
cliffhallandClaude Opus 5.5 473c531ef9 Record the SDK watch's accepted credential-channel risk (#5069)
The maintainers accepted the analysis job's residual credential channel on
#5069: every upstream the SDK watch reads is an MCP-org SDK, and those are
trusted, including their generated release notes' outside PR titles. The
workflow note now cites that decision instead of the Inspector's reasoning,
AGENTS.md states the rule, and a test fails on an SDK group outside the
modelcontextprotocol org, so the decision is taken again before one is added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 16:35:56 -04:00
cliffhallandClaude Opus 5.5 2b65349aa5 Warn about vulnerable intervals above an alert target, and ask for the fix to be verified against every range
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 15:30:03 -04:00
cliffhallandClaude Opus 5.5 a969a9d378 Keep the unverified advisory comment from naming the unsafe version; add the pre-merge triage fallback; reword the verified target row
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 15:18:50 -04:00
cliffhallandClaude Opus 5.5 83b2fb9ee0 Name the version actually checked when an alert target is unverified, and stop advertising it in the title
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 15:07:17 -04:00
cliffhallandClaude Opus 5.5 5090addb51 Scope npm alert issues by the workspaces their vulnerable copies belong to
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 14:53:55 -04:00
cliffhall 24d7ed53ed Merge remote-tracking branch 'origin/v2/main' into v2/feat/4874-issue-filing-sweeps
Signed-off-by: cliffhall <cliff@futurescale.com>

# Conflicts:
#	AGENTS.md
2026-10-07 14:51:41 -04:00
cliffhallandClaude Opus 5.5 acbae3534e Order PEP 440 local version labels, and ignore them in specifier matching as packaging does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 14:44:10 -04:00
cliffhallandClaude Opus 5.5 f227e79dfa Never target below an affected copy; rank a SHA pin only by an exact # vX.Y.Z; scope the alert row to advisories with a fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 14:22:42 -04:00
cliffhallandClaude Opus 5.5 21eb81b22b Pin nothing in an alert issue's fix when no listed patch clears every range
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 14:13:07 -04:00
cliffhallandClaude Opus 5.5 04e22efd1a Describe the alert target as pickTarget chooses it, in AGENTS.md and the script header
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 14:06:19 -04:00
cliffhallandClaude Opus 5.5 129a0a0fc8 Verify an alert issue's target against every applicable range; scope SDK labels to servers behind; qualify the milestone and issue-flow wording
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 13:56:20 -04:00
cliffhallandClaude Opus 5.5 1b5f6ae651 Match a workspace's own npm copy to its own manifest; report every locked mcp version
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 13:47:04 -04:00
cliffhallandClaude Opus 5.5 c47051ab76 Treat npm outdated's exit 1 without a payload as a failure; compare epochs in PEP 440 prefix matching
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 13:38:46 -04:00
cliffhallandClaude Opus 5.5 fbfea0c6f1 File the monthly issue when unranked SHA pins are its only finding
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 13:32:19 -04:00
cliffhallandClaude Opus 5.5 715bde0d9d Apply PEP 440's exclusive-bound rules; preview the supersession note in a dry run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 13:25:45 -04:00
cliffhallandClaude Opus 5.5 93c8df42ae Read an empty automated-security-fixes success as enabled; analyze from the lowest installed SDK; state what each sweep does when work goes away
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 13:16:31 -04:00
cliffhallandClaude Opus 5.5 138d1eddf3 Map npm's workspace spelling either way; dispatch a sweep rather than file a duplicate; reword the overview's opening
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 13:06:12 -04:00
cliffhallandClaude Opus 5.5 2b728ecbbf Route sweep warnings through an injectable sink, so tests keep them off the console
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 12:45:12 -04:00
cliffhallandClaude Opus 5.5 d3bd74d6d0 chore(scripts): one release-wide Thanks section, as the Inspector's; drop Credit lines
Thanks is now a single `## Thanks for helping us improve` list at the end
of the notes, laid out as the Inspector's release notes are, rather than a
subsection per server. The maintainer-written `Credit: @login` convention
is removed: outside-PR authors are added to the draft's Thanks by hand, as
before, and the harvest docs are back to their v2/main wording.

From Copilot's review: refuse a milestone tag that already exists (GitHub
would use its commit, not --merge-sha), and count a rename's source path
when bucketing a PR by server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 12:43:04 -04:00
cliffhallandClaude Opus 5.5 abb1c902bf Replace Dependabot PRs with issue-filing sweeps; add the SDK watch and the factory overview
Three scheduled workflows replace Dependabot's PRs, ported from the MCP
Inspector and extended to this repo's second ecosystem:

- dependency-refresh (monthly): one tracking issue covering npm outdated
  across the root and workspaces, each Python server's uv lock --upgrade
  dry run, and every workflow uses: ref, with SHA pins ranked by their
  # vX.Y.Z comment through scripts/lib/action-refs.mjs.
- dependabot-alerts (daily): one issue per vulnerable package per
  lockfile, npm and pip, re-checked against v2/main, targeting the highest
  patched version of the advisories that apply.
- sdk-watch (nightly): one issue per MCP SDK group behind its registry
  (npm @modelcontextprotocol/*, PyPI mcp), with the Inspector's hardened
  three-job Claude analysis kept unchanged.

Shared plumbing (the trust rule, milestone pick, scope labels and a writer
whose --dry-run writes nothing) lives in scripts/lib/sweep.mjs, with PEP 440
and uv.lock readers beside it. No sweep writes the board: GITHUB_TOKEN cannot
hold organization projects: write, so issues arrive labeled and milestoned
for issue-triage, and boarding from the workflows waits on a GitHub App
(#5061).

Deletes .github/dependabot.yml, removes the temporary Dependabot exception
from AGENTS.md and adds the issue-driven dependency rules, and adds
docs/ai-software-factory.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 12:42:49 -04:00
cliffhallandClaude Opus 5.5 b1df103649 chore(scripts): script per-server release notes with a reporter Thanks section (release:notes)
Add scripts/release-notes.mjs (npm run release:notes), modeled on the
Inspector's helper and adapted to a seven-package release. It builds the
Packages table at the merge SHA (registry-checked), one section per
published package with its PRs and the community reporters it thanks, a
Repository catch-all so no generated PR is dropped, GitHub's trailer, the
ledger line and any known issues. Outside-PR authors are credited from a
maintainer-written `Credit: @login` line. Preview by default; --draft
creates the draft Release at the merge SHA; publishing stays manual.

The release skill's step 5a uses the helper in place of the shell
recipe, and 5b publishes the draft. The harvest instructions adopt the
Credit line.

Closes #5056

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 12:27:59 -04:00
cliffhallandClaude Opus 5.5 b5af226685 chore: migrate the TypeScript servers to TS SDK v2 (#4856)
Run @modelcontextprotocol/codemod v1-to-v2 (2.3.1) on everything,
filesystem, memory and sequentialthinking, and finish what it leaves:

- Manifests: drop @modelcontextprotocol/sdk; depend on
  @modelcontextprotocol/server (plus node and server-legacy in
  everything), with client (and core, for everything's skipped task
  tests) as devDependencies; zod ^4.2.0; engines node >=20. The root
  devDependency for the boot smoke moves to @modelcontextprotocol/client.
- everything: wrap the three raw-shape prompt argsSchemas in z.object();
  drop the result schemas from ctx.mcpReq.send(); keep HTTP+SSE on the
  frozen server-legacy bridge.
- Experimental tasks are gone in v2 (SEP-2663): remove
  simulate-research-query and the two trigger-*-async tools and the
  tasks capability, pending #4852. Their tests stay, skipped, behind
  typed stand-ins for the removed v1 surface.
- Re-baseline the Part 1 (#4854) assertions that SDK v2's documented
  wire changes move: unknown tools reject with -32602, the
  "MCP error <code>: " prefix is gone, validation issues read
  "field: message", tool schemas declare JSON Schema 2020-12, tools
  no longer advertise execution.taskSupport, and the resource-not-found
  message reads "Resource not found: <uri>".
- Docs, skills and the smoke script follow; one major changeset per
  server records the breaking changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-07 12:24:56 -04:00
Cliff Hall b5cea9df5f Merge pull request #5055 from modelcontextprotocol/v2/chore/4919-dco-check
Add a DCO signoff check to CI and the gate
2026-10-05 01:58:38 -04:00
Cliff Hall 088b0de8a3 Merge pull request #5052 from modelcontextprotocol/v2/fix/4934-action-pins-case-insensitive
fix(scripts): verify:action-pins matches contexts and job ids case-insensitively
2026-10-05 01:45:35 -04:00
cliffhallandClaude Opus 5.5 988aa910c9 verify-dco: read signoffs from git's trailer block, not the whole message
Copilot review on #5055: scanning every line of the message accepted a
`Signed-off-by:` quoted in the body, or written as the subject, so an
unsigned commit could pass. Read the signoffs with
`%(trailers:key=Signed-off-by,valueonly,unfold)`, git's own trailer
parser (the one `git commit -s` writes for), and add a regression test
for both cases plus a folded trailer that must still pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-05 01:38:59 -04:00
cliffhallandClaude Opus 5.5 45d059d5d8 Add a DCO signoff check to CI and the gate (#4919)
The probot DCO app never ran on this repo, so nothing failed an unsigned
commit. Replace it with a check we own:

- scripts/verify-dco.mjs (+ tests): every commit in <base>..<head> needs a
  Signed-off-by trailer matching its author or committer; merge and
  bot-authored commits are exempt. A failure names each commit and the
  `git rebase --signoff` repair.
- .github/workflows/dco.yml: runs it on pull requests over
  base.sha..head.sha, contents: read only, with a timeout.
- `verify:dco` joins local:gate:stages, over origin/v2/main..HEAD.
- AGENTS.md states the signoff rule; pr-flow step 3 describes the job
  instead of the app; quality-gate.md and pre-push-gate cover the stage;
  the skills-index table is Prettier-clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-05 01:28:32 -04:00
cliffhallandClaude Opus 5.5 c63255ae96 chore(everything): keep compiled tests and vitest config out of dist
everything's build tsconfig had no exclude, so tsc emitted __tests__/**
and vitest.config.ts into dist/ and the package published them. Exclude
them as filesystem does. memory and sequentialthinking excluded only
*.test.ts and so packed __tests__/helpers.js; exclude __tests__/** there
too.

pack:verify now fails an npm tarball that ships a test, test helper or
test-runner config, so this cannot come back in any server.

Closes #4930

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-05 01:24:22 -04:00
cliffhallandClaude Opus 5.5 4daf4a7416 fix(scripts): verify:action-pins matches contexts and job ids case-insensitively
GitHub resolves expression contexts, property names and job ids without
regard to case, so `SECRETS.X`, `NEEDS.detect.outputs` and
`needs.DETECT.outputs` slipped past the guard. Match `secrets`, the
GITHUB_TOKEN exemption and `needs` case-insensitively, and resolve every job
id (in `needs:` and in expressions) to its key in `jobs:` in any case.

Closes #4934

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-05 01:21:52 -04:00
cliffhallandClaude Opus 5.5 c584a4d2a4 fix(smoke): start fetch with --allow-private-ips for its loopback page (#4838)
fetch now refuses loopback addresses by default, and the boot smoke serves
fetch's page from 127.0.0.1, so the smoke opts out of the guard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-04 19:56:19 -04:00
cliffhallandClaude Opus 5.5 38f9e6dfec fix(coverage-py): refuse a report measured without branch coverage
coverage.py writes num_branches: 0 for every file when branch measurement
is off, which the per-file check counted as 100% on branches, so removing
`branch = true` would have let every file pass that dimension. Require
meta.branch_coverage === true and fail with a message pointing at
[tool.coverage.run] branch = true. Regression tests for false, a missing
flag and a missing meta.

Signed-off-by: cliffhall <cliff@futurescale.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 19:05:19 -04:00
cliffhallandClaude Opus 5.5 1cdd4a7038 chore(python): per-file coverage gate in CI and local:gate
Add `npm run coverage:py` (scripts/coverage-py.mjs): for each Python
server, a locked sync, then `uv run --frozen pytest --cov
--cov-report=term-missing --cov-report=json`, then a per-file check of
coverage.json (scripts/lib/py-coverage.mjs) that fails any file below 90%
on lines or on branches. coverage.py's fail_under is global, hence the
script. Discovery, server selection and the carry-on-after-a-failure shape
are shared with validate-py.mjs.

Wire it in as a parallel `coverage` matrix job in python.yml and as a
stage of local:gate:stages after validate:py, and document it in
docs/quality-gate.md, AGENTS.md (the Python half of the coverage rule),
CONTRIBUTING.md and the pre-push-gate and testing skills.

Signed-off-by: cliffhall <cliff@futurescale.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 19:05:19 -04:00
cliffhallandClaude Opus 5.5 f149a2a61f ci(coverage): enforce the TypeScript per-file coverage gate in CI and local:gate
Adds a parallel `coverage` job to typescript.yml (one leg per TypeScript
server, beside `validate`, as the Inspector's CI does) and a `coverage` stage
to `local:gate:stages` right after `validate`. The workflow guard derives the
stage from the new CI job, and its stage list now pins `coverage` by name.

Documents the stage in docs/quality-gate.md, the TypeScript half of the
coverage rule in AGENTS.md, how to diagnose a red coverage stage in the
pre-push-gate skill, and the in-process harness and coverage gate in the
testing skill. The docs describe the state after the four per-server
coverage PRs for #4854 land, which add the 90/90/90/90 per-file thresholds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-04 18:31:00 -04:00
cliffhallandClaude Opus 5.5 feb251d2fd fix(everything): SSE reports a port already in use instead of "Server is running"
Express 5 passes a listen error to the same callback it calls on success, and
sse.ts had no error listener, so on EADDRINUSE it printed its success line
while bound to nothing. Both HTTP transports now bind through listenOrExit
(transports/listen.ts), which prints the listening line only for a real bind
and otherwise names the port and exits 1. That also removes the false
listening line Streamable HTTP printed ahead of its error.

Closes #4923

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-01 09:53:59 -04:00
cliffhallandClaude Opus 5.5 205cc847c2 fix: release the verified commit by SHA; queue every release run; count the needs context read whole
- The release skill targets the merge PR's merge commit by SHA for the notes
  and the Release, so the tag lands on the tree the ledger verified even if
  main has moved since.
- release.yml uses queue: max, so a waiting release run is kept rather than
  replaced by a later one.
- verify:action-pins counts any use of the needs context except a job's
  result as reading that job's outputs, including toJSON(needs).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-01 09:45:15 -04:00
cliffhallandClaude Opus 5.5 938b106770 fix: pin jobs whose outputs a credentialed job reads; serialize release runs
- verify:action-pins counts a job as credentialed when a credentialed job
  reads its outputs. release.yml's detect-packages supplies the name and
  version an artifact must match, so it is now held to the pin too.
- release.yml runs one release at a time and never cancels one, so two runs
  cannot each read the old latest and publish out of order.
- The release skill's Python audit counts a server as audited only when
  pip-audit's output holds a verdict, and lists changesets recursively.
- The guard's failure message reads as sentences.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-10-01 09:45:15 -04:00