You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The surface lock proves a change was noticed, not that the version moved
1d5cb24 (#573 AC2) added a fingerprint over the published tool surface, keyed by MCP_SERVER_VERSION, in workers/mcp/src/conformance.test.ts. It works — it caught #574's 0.1.2 bump on first contact, unstaged.
Its stated limit, written into the code by its author rather than discovered later:
this makes a surface change impossible to ship silently, but does not mechanically prove the
version moved — the entry can be edited in place.
Concretely: change the tool surface, then edit SURFACE_LOCK["0.1.1"] to the new hash instead of
adding SURFACE_LOCK["0.1.2"]. Every gate stays green and the version never moves. The lock is
keyed by version specifically so that rewrite reads in a diff as what it is — that is a review
defence, not a mechanical one, and this repo has recorded what happens when the only defence is
someone reading carefully.
The precedent that already exists here
scripts/check-migrations.mjs --require-history (ci.yml:63) solves the same problem for
migrations: it is not enough that the file is well-formed, its history must show it was added
rather than rewritten. The same arm applied here would assert that a commit changing the surface
hash also adds a new SURFACE_LOCK entry rather than mutating an existing one.
Why it is worth doing rather than accepting
A silent surface change is the failure #573 was filed for, and the observed consequence was real:
the ChatGPT connector served a stale unannotated tool list because nothing signalled a change.
An in-place lock edit reproduces exactly that state while passing CI. The gap is narrower than
before — it now requires someone to actively rewrite a line rather than simply not think about
it — but "narrower" is the whole claim, and it should be stated rather than assumed closed.
Acceptance criteria
A commit that changes the published surface hash and mutates an existing SURFACE_LOCK
entry instead of adding one fails CI.
A commit that adds a new entry passes.
A commit touching neither is unaffected and costs nothing measurable.
Modelled on check-migrations.mjs --require-history's approach to the same question — read it
first and say where this legitimately differs, rather than copying its shape by default.
Per ADR 0002 the success line states its denominator, and the input set is asserted rather
than assumed.
Demonstrated red on a deliberate in-place rewrite.
Verified vs inferred
Verified: the limitation is quoted from 1d5cb24's own header; the lock is keyed by MCP_SERVER_VERSION (conformance.test.ts:483-484); check-migrations.mjs --require-history
runs at ci.yml:63; the guard caught A ticket's reasoning can be written over MCP and never read back #574's bump.
Inferred: nothing. That an in-place edit passes follows from the lock being a keyed lookup,
but it is not yet demonstrated — AC6 exists to demonstrate it, and if it turns out some
other arm already catches it, that is the better finding and this issue should close.
The surface lock proves a change was noticed, not that the version moved
1d5cb24(#573 AC2) added a fingerprint over the published tool surface, keyed byMCP_SERVER_VERSION, inworkers/mcp/src/conformance.test.ts. It works — it caught #574's0.1.2bump on first contact, unstaged.Its stated limit, written into the code by its author rather than discovered later:
Concretely: change the tool surface, then edit
SURFACE_LOCK["0.1.1"]to the new hash instead ofadding
SURFACE_LOCK["0.1.2"]. Every gate stays green and the version never moves. The lock iskeyed by version specifically so that rewrite reads in a diff as what it is — that is a review
defence, not a mechanical one, and this repo has recorded what happens when the only defence is
someone reading carefully.
The precedent that already exists here
scripts/check-migrations.mjs --require-history(ci.yml:63) solves the same problem formigrations: it is not enough that the file is well-formed, its history must show it was added
rather than rewritten. The same arm applied here would assert that a commit changing the surface
hash also adds a new
SURFACE_LOCKentry rather than mutating an existing one.Why it is worth doing rather than accepting
A silent surface change is the failure #573 was filed for, and the observed consequence was real:
the ChatGPT connector served a stale unannotated tool list because nothing signalled a change.
An in-place lock edit reproduces exactly that state while passing CI. The gap is narrower than
before — it now requires someone to actively rewrite a line rather than simply not think about
it — but "narrower" is the whole claim, and it should be stated rather than assumed closed.
Acceptance criteria
SURFACE_LOCKentry instead of adding one fails CI.
check-migrations.mjs --require-history's approach to the same question — read itfirst and say where this legitimately differs, rather than copying its shape by default.
than assumed.
Verified vs inferred
1d5cb24's own header; the lock is keyed byMCP_SERVER_VERSION(conformance.test.ts:483-484);check-migrations.mjs --require-historyruns at
ci.yml:63; the guard caught A ticket's reasoning can be written over MCP and never read back #574's bump.but it is not yet demonstrated — AC6 exists to demonstrate it, and if it turns out some
other arm already catches it, that is the better finding and this issue should close.