docs(tooling): reserve --rewrite-governed-file by its condition, not by actor - #9383
Conversation
…by actor `check-upstream-port-parity.mjs`'s usage header reserved the flag for "the human merging it". The reservation's real target is a SILENT rewrite of a governed file from another repository's bytes, and that hazard is decidable before the run: compute each upstream digest independently first and require it to equal what the pin will hold afterwards. Stated as an actor, the rule had to be re-ruled per card; stated as a condition it is falsifiable, and a digest mismatch is loud. Restate it in all four places the file addressed the actor: - the usage header, keeping the comment column; - the `## --resync REFUSES to rewrite governed surface` prose, which repeated the actor framing, plus the worked example the ruling names: on PR #9300 every re-synced file came back byte-identical and every new `upstreamSha256` had been shown to equal the sha256 of `git show origin/main:PATH` taken in the objectstack checkout before the run; - the doc comment on `RESYNC_GOVERNED_FLAG`; - the refusal's own instruction line, which now asks for the proof first and keeps the merging human as the fallback. No behaviour change: the gating predicate (`resyncWriteVerdict`), the governed set it borrows from `check-governed-queue-guard.mjs`, the pin ledger and every pinned copy are untouched. The self-test's assertions on the refusal text (path, flag, matched surface, "drifted governed port reds this gate") all still hold: 58 cases pass, and the live verify still reports 11 ported files at their own refs. Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewHead: ① derived judgments — one file, Implemented-by: claude/issue-9303-resync-reservation-names-its-condition (mode:subagent) Verdict: PASS. Path face clean (measured NOT GOVERNED): the seat lands it — ready + auto-merge SQUASH once every check on Generated by Claude Code |
|
CI reading (skills seat, 2026-09-13T09:00Z) — Generated by Claude Code |
Fixes #9303
Ruling B (director seat, decision batch #131 item 4, maintainer 「同意」; the skills seat's
verbatim supplement). The usage header of
scripts/check-upstream-port-parity.mjsreserved--rewrite-governed-filefor "the human merging it". It now reserves it for whoever can PROVEthe re-sync content-neutral beforehand — digests computed independently before the run, equal to
what the pin holds after it — and for the merging human otherwise.
Why naming an actor was the wrong shape
The reservation's target is a SILENT rewrite of a governed file from another repository's bytes,
not the identity of the person at the keyboard. That hazard is decidable in advance and the check
is cheap, so the condition can be stated as a falsifiable rule instead of being re-ruled per card —
and it fails loudly (a digest mismatch), which is the property that makes it safe to state as a
rule at all.
What changed — one file, comments plus one operator-facing message
Four places addressed the actor; all four now state the condition.
## --resync REFUSES to rewrite governed surface unless told, by nameprose, whichrepeated the actor framing ("it is for the human doing the merge"). It now states the condition
in one sentence and carries the worked example the ruling names: on PR hooks: the three remaining guards name the environment their hatch variable must be set in, never a command prefix #9300 the six drifted
pinned hook entries were re-synced, and before the run every new
upstreamSha256was shown toequal the sha256 of
git show origin/main:PATHtaken in the objectstack checkout; everyre-synced file then came back byte-identical to the committed one. The paragraph also states the
half that is easy to lose: the same digests computed AFTERWARDS do not qualify, because by then
the bytes are written.
RESYNC_GOVERNED_FLAG, which repeated it a third time.for the proof first and keeps the merging human as the fallback.
⛔ No behaviour change. The gating predicate
resyncWriteVerdictis untouched, the governed setis still borrowed from
check-governed-queue-guard.mjsrather than re-listed, and neither the pinledger nor any pinned copy is touched. The self-test's four assertions on the refusal text — it
names the path, names the flag, names the matched surface, and says "drifted governed port reds
this gate" — all still hold by construction.
Readers of this file's header: measured, and there are none
rewrite-governed-fileappears in exactly two other tracked files, and neither reads THIS file'sheader text, so neither changes here:
scripts/check-bash32-floor.mjs— one prose mention of the flag by name in that file's ownheader, saying
--resyncrefuses governed paths without it. It does not quote this file'swording. It is also itself a pinned ported copy, so editing it would red the very gate this
PR edits.
scripts/upstream-port-pin.json— the same sentence again, stored as theportedside of one ofthat file's declared divergences. Same reason, and it is ledger content.
No self-test or test file asserts on the header.
scripts/__tests__/upstream-port-parity-wiring.test.tsreads the workflow wiring, the pin's shape and the gate's stdout, never the header; the four test
files that mention the script by name all still pass (below).
Acceptance readings —
scripts/check-upstream-port-parity.mjs, before to afterthe human merging ithuman doing the mergehuman doing that mergemerging human(the fallback, in the ruling's own words)content-neutralRESYNC_GOVERNED_FLAG = '--rewrite-governed-file'rewrite-governed-file(all forms)Stated exactly, since the card asked for it: the actor phrasing did not survive as a sole
condition and did not survive at all in that spelling — the fallback is now written "the
merging human", which is the wording of the ruling itself ("stays reserved for the merging human
otherwise"). The file grows 834 to 855 lines, all of it comment text plus two message lines.
git diff --stat origin/mainis exactly one file:scripts/check-upstream-port-parity.mjs,28 insertions, 7 deletions. No changeset:
node scripts/check-changeset-presence.mjsexits 0 with"0 of them published source of a package the release covers ... no changeset is owed" — a
scripts/file is not published source. ⛔ Noskip-changesetlabel is used in this repository.Gates — each exit code captured before any pipe
node scripts/check-upstream-port-parity.mjs --self-testnode scripts/check-upstream-port-parity.mjsnode scripts/check-bash32-floor.mjs --self-testnode scripts/check-bash32-floor.mjsnode scripts/check-governed-queue-guard.mjs --test scripts/check-upstream-port-parity.mjsnode scripts/check-changeset-presence.mjsnode scripts/check-control-bytes.mjsnode scripts/check-entry-guard.mjs --self-testand the live runnode scripts/check-lint-coverage.mjsnode scripts/check-new-cross-file-line-citations.mjspnpm exec vitest runon the four test files naming this scriptpnpm exec eslint --no-inline-config --format jsonon the changed fileThe eslint run is a declared narrowing, with its three readings: the repository lints per
package via
turbo run lintand this file is a.mjsunderscripts/, matching no typed ruleblock in
eslint.config.js(whose rule blocks target TS and TSX); the--format jsonoutputcarries exactly 1 result object; and no type-aware linting is configured anywhere in that config
(no
parserOptions.project, noprojectService), so a comment edit in this file cannot move theverdict on any file it does not touch. The repository-wide sweep is CI's run, not this PR's.
Landing
Draft, base
main. Measured rather than assumed:check-governed-queue-guard.mjs --teston thechanged path exits 0 with "NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none
matched", so objectui
scripts/is an ordinary path. This PR nevertheless stays a DRAFT for theseat to land after review: ⛔ not flipped ready, ⛔ not enqueued, ⛔ no auto-merge, ⛔ no self-review.
Acceptance notes
declared-contract violation, or a metadata trap.
listed — the third (
RESYNC_GOVERNED_FLAG's doc comment) and fourth (the refusal's instructionline) were found by reading, and both are inside the surface the ruling opened ("the flag's own
refusal/usage text"). Carrier: this PR.
08:27Z read (9376, 9377, 9378, 9381), none touches this file.
Drafted by the
domain:skillsseat, sessionsession_01DAcomhvR9kKizeYgg89Vo8—https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8
Generated by Claude Code