Skip to content

ci: pin both MCP tool surfaces with truecopy and gate them - #131

Merged
askalf merged 1 commit into
masterfrom
ci/truecopy-gate
Sep 27, 2026
Merged

askalf merged 1 commit into
masterfrom
ci/truecopy-gate

Conversation

@askalf

@askalf askalf commented Sep 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • Pins the tool surface of both MCP servers in this repo with truecopy and gates it in CI through askalf/truecopy-action. mcp-server.mjs exposes browser_evaluate, browser_type and browser_click, and fieldpass exposes the picket_* gate tools. A tool description is text an agent reads and acts on, so a change to one now has to be regenerated and re-pinned on purpose, and it is poison-scanned when it is.
  • The chain is code -> manifest -> lock:
    • scripts/dump-tools.mjs reads each server's real tools/list response through an MCP client over an in-memory transport and writes mcp/browser-bridge.json and mcp/fieldpass.json. Listing tools never opens a browser, because the bridge server connects on the first tool call.
    • --check fails if a committed manifest no longer matches the code.
    • truecopy.lock pins both manifests (truecopy 0.10.4, redstamp 0.7.5, both clean). truecopy verify fails on drift, or on the same bytes turning poisonous under a newer detector.
  • The manifests write non-ASCII characters as \u escapes. The tool descriptions carry em dashes, which check-hygiene.mjs rejects on added lines. The parsed JSON is the same.
  • Adds truecopy gate to the fleet-status workflow_run list (the fleet-status test requires every pull_request workflow to be listed). Adds the new paths to the mcp label.

What's NOT in this PR

  • It does not make truecopy gate a required check. That is a branch-rule change for the operator.
  • There are no Dockerfile or image changes. The manifests and the lock are CI inputs only.

Test plan

  • node scripts/dump-tools.mjs --check: both manifests match (9 tools each). This also passes with policy/ installed --omit=optional, the way CI installs it.
  • truecopy scan on both manifests: clean. truecopy verify: 2 of 2 pinned verified.
  • npm test 129/129, node scripts/fleet-status.test.mjs 97/97, actionlint clean, check-hygiene.mjs --range origin/master..HEAD clean.
  • CI: truecopy gate / verify pinned tool surface green.

scripts/dump-tools.mjs writes the tools/list response of the bridge MCP server and of fieldpass to mcp/, truecopy.lock pins both, and the truecopy gate workflow fails when the code no longer matches the manifest or the manifest no longer matches the lock.
@github-actions github-actions Bot added github_actions Pull requests that update GitHub Actions code size/L 200-799 hand-written lines labels Sep 27, 2026

@sprayberry-redline sprayberry-redline left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at 9b164d8.

The generator drives the real tools/list path of both servers through an in-memory MCP client, so the manifests cannot drift from what a connected agent would actually see; the bridge server's lazy rec.resolve() means the noConnect thrower is never reached during listing, and createPicketServer({ judge: null, cdp: null }) builds a GovernedBrowser with no network side effects. Ordering the workflow as dump-tools.mjs --check then truecopy verify gives the code -> manifest -> lock chain a failure at the first broken link, and the new job passed at this head in 17s, which confirms both npm ci steps supply what the script imports.

Minor, non-blocking:

  • scripts/dump-tools.mjs:54: the character class upper bound is a raw U+FFFF byte sequence in the source rather than the escape \uffff. It works, but editors and diff tools tend to mangle or hide that byte; the escape form is safer to keep in the file.
  • scripts/dump-tools.mjs:41: localeCompare on tool names is locale-sensitive. The current names never tie on an underscore versus a letter, so the output is stable today; a plain a.name < b.name ? -1 : 1 comparison would keep the manifest byte-identical regardless of the runner's ICU locale.

@askalf
askalf merged commit 978a648 into master Sep 27, 2026
15 checks passed
@askalf
askalf deleted the ci/truecopy-gate branch September 27, 2026 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

github_actions Pull requests that update GitHub Actions code size/L 200-799 hand-written lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants