Gate rooms hold one canonical Briefing file; request.json is retired - #762
Merged
Merged
Conversation
`gate prepare` published two files. A scan of the dev state checkout found 499 of 499 prepared rooms carrying `request.json`, and about 8 July-era rooms that ever had a provider result. The request repeated facts the entity frontmatter already held: its gate, attempt, and Briefing id and digest mirror the binding, and its actor and approver were the constant `person:captain`. The room is now one file, named `index.json` to mirror `<slug>/index.md`. Removing the file was not the whole change. Eight code sites read `request-digest != ""` to mean "this attempt has a prepared room", so dropping the file silently drops four guards with it. Two were measured, not read: the shipped `gate withdraw` exits 1 on a request-less room, and the shipped recorder DURABLY RECORDS a captain approval over a corrupted Briefing. - `preparedRoomBinding` replaces that test at the six runtime sites. It reads the archived `briefing.json` name, not the reserved name, so a room whose Briefing is deleted stays a prepared room and keeps failing loudly. - `boundBriefingPath` resolves every binding shape in one place, reading `index.json` first and the earlier `gate-briefing.json` second. - The withdraw guard moves from the frontmatter validator to the verb, which can stat the room. Validate reads frontmatter and cannot. - Retained-authority validation now covers request-less prepared rooms. The request checks stay, and run for a binding that froze a request digest. - Room-entry validation follows the binding rather than a flag. - `validateGateRoomRequest` and its three request-locating helpers are removed: preparation no longer mints a request for them to validate. Nothing migrates. Rooms prepared before this change keep both files, keep their bound digest, and keep the full request validation. `status --validate` over the real 703-room state checkout is byte-identical before and after. Cross-repo: a room this version prepares is refused by name by the unamended q0 preflight. The amended preflight reads the canonical Briefing alone; the recorder remains the authority wall. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CI reported the same line on both required lanes: "successor room is not the emitted two-file room: entries=[- index.json]". The product behaved as the approved design requires; the assertion was stale. The assertion is at claude_live_runner_test.go:334. CI attributed it to shared_live_runner_test.go:162 because liveJourney calls t.Helper(), which walks the reported line up to the test function. It now requires the one-file contract: exactly one regular entry named index.json, and a successor binding that carries no request-digest. This was a fifth room-shape site. The `live` build tag excludes it from `go test ./...`, so the cycle-2 sweep could not see it. Swept every build-constrained file in the repo: 15 carry `//go:build live`, all in internal/ensigncycle, and 4 carry unix constraints in internal/cli with no room references. Only this one asserted a gate-room shape. A filename grep alone would have missed it, because the assertion counted entries rather than naming a file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
clkao
added a commit
that referenced
this pull request
Aug 26, 2026
…762) * gates: one canonical Briefing file per room, request.json retired `gate prepare` published two files. A scan of the dev state checkout found 499 of 499 prepared rooms carrying `request.json`, and about 8 July-era rooms that ever had a provider result. The request repeated facts the entity frontmatter already held: its gate, attempt, and Briefing id and digest mirror the binding, and its actor and approver were the constant `person:captain`. The room is now one file, named `index.json` to mirror `<slug>/index.md`. Removing the file was not the whole change. Eight code sites read `request-digest != ""` to mean "this attempt has a prepared room", so dropping the file silently drops four guards with it. Two were measured, not read: the shipped `gate withdraw` exits 1 on a request-less room, and the shipped recorder DURABLY RECORDS a captain approval over a corrupted Briefing. - `preparedRoomBinding` replaces that test at the six runtime sites. It reads the archived `briefing.json` name, not the reserved name, so a room whose Briefing is deleted stays a prepared room and keeps failing loudly. - `boundBriefingPath` resolves every binding shape in one place, reading `index.json` first and the earlier `gate-briefing.json` second. - The withdraw guard moves from the frontmatter validator to the verb, which can stat the room. Validate reads frontmatter and cannot. - Retained-authority validation now covers request-less prepared rooms. The request checks stay, and run for a binding that froze a request digest. - Room-entry validation follows the binding rather than a flag. - `validateGateRoomRequest` and its three request-locating helpers are removed: preparation no longer mints a request for them to validate. Nothing migrates. Rooms prepared before this change keep both files, keep their bound digest, and keep the full request validation. `status --validate` over the real 703-room state checkout is byte-identical before and after. Cross-repo: a room this version prepares is refused by name by the unamended q0 preflight. The amended preflight reads the canonical Briefing alone; the recorder remains the authority wall. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * gates: fix the live-tagged room-shape assertion for the one-file room CI reported the same line on both required lanes: "successor room is not the emitted two-file room: entries=[- index.json]". The product behaved as the approved design requires; the assertion was stale. The assertion is at claude_live_runner_test.go:334. CI attributed it to shared_live_runner_test.go:162 because liveJourney calls t.Helper(), which walks the reported line up to the test function. It now requires the one-file contract: exactly one regular entry named index.json, and a successor binding that carries no request-digest. This was a fifth room-shape site. The `live` build tag excludes it from `go test ./...`, so the cycle-2 sweep could not see it. Swept every build-constrained file in the repo: 15 carry `//go:build live`, all in internal/ensigncycle, and 4 carry unix constraints in internal/cli with no room references. Only this one asserted a gate-room shape. A filename grep alone would have missed it, because the assertion counted entries rather than naming a file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every gate room carried a request.json whose fields were constants or copies of the Briefing, and a tampered Briefing could be durably approved. Rooms now hold one canonical file, and tampering is refused.
What changed
index.jsonper room; request.json is retired.Evidence
go test ./...and-race: fresh green from their own exit codes.status --validatebyte-identical over the real 700-room state checkout.rx
Related: gate-record-prepared-room-guard (filed deferred-risk remedy)