Skip to content

Gate rooms hold one canonical Briefing file; request.json is retired - #762

Merged
clkao merged 2 commits into
mainfrom
spacedock-ensign/request-less-gate-rooms-by-default
Aug 26, 2026
Merged

Gate rooms hold one canonical Briefing file; request.json is retired#762
clkao merged 2 commits into
mainfrom
spacedock-ensign/request-less-gate-rooms-by-default

Conversation

@clkao

@clkao clkao commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

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

  • Prepare writes one index.json per room; request.json is retired.
  • Replace the request-digest test with a prepared-room predicate at six sites.
  • Extend retained-authority validation to one-file rooms; record and prepare refuse a tampered Briefing.
  • Keep legacy room names readable; fix the deleted-Briefing inversion.
  • Update the gate spec and site docs to the new contract.

Evidence

  • go test ./... and -race: fresh green from their own exit codes.
  • status --validate byte-identical over the real 700-room state checkout.
  • q0 preflight contract exercised cross-repo against rooms this build minted.

rx
Related: gate-record-prepared-room-guard (filed deferred-risk remedy)

`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
clkao merged commit 0853186 into main Aug 26, 2026
14 of 18 checks passed
@clkao
clkao deleted the spacedock-ensign/request-less-gate-rooms-by-default branch August 26, 2026 15:41
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant