docs: gate framing revision 3 --- a witness that can fail, and the ledger

Two findings, both about a claim that could not be falsified.

The --self-test plan put the failing step last. With the failure last,
a runner that ABORTS on failure and one that CONTINUES produce
identical output, so the witness for Q#GR-2 policy --- the suite keeps
going --- would have passed on a runner doing the exact opposite. The
plan is now three lines with a passing SENTINEL after build-crdt,
asserted to have written its own log. That is the only thing that
distinguishes the two behaviours, and it turns Q#GR-2 from a declared
policy into an observed one.

The plan test also now pins the EXACT command, not only the step name
and its position. A build-crdt running plain cargo build would leave
the gate exactly as unsound while looking repaired --- the crdt sweep
needs those specific features, which is the whole defect.

The ledger still recorded the superseded boundary decision: "section 3
gains it, section 5 keeps the incident, and the script cites both".
Revision 2 replaced that with section 3 as the sole normative home and
the script citing section 3 alone. active-work.md is the volatile
cross-machine record, so a recovering machine reading the stale entry
would have rebuilt revision 1 wrong boundary. Now updated, and it says
which decision it supersedes rather than silently replacing it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
This commit is contained in:
Levi Neuwirth 2026-08-09 16:10:09 +02:00
parent 4e02cb09b4
commit 12affd78e1
No known key found for this signature in database
2 changed files with 50 additions and 10 deletions

View File

@ -275,7 +275,7 @@ from #171 and #215.
authoritative tip** — the ref, not a SHA. Recover with
`git fetch githubsucks && git checkout gate-protocol-build`.
- **Framing `docs/gate-protocol-build-framing.md`, revision 2**, in
- **Framing `docs/gate-protocol-build-framing.md`, revision 3**, in
review. Narrow by design: one missing step in one script, plus the
boundary question that let it go missing. No `src/`, no protocol, no
feature work.
@ -298,8 +298,16 @@ authoritative tip** — the ref, not a SHA. Recover with
- **The durable half is a boundary question.** `scripts/gate`'s header
names handoff **§3** as the owner of its reasoning, and this
precondition lives in **§5** — a coherent cause for the omission, not
mere oversight. Q#GR-3 proposes §3 gains it, §5 keeps the incident,
and the script cites both.
mere oversight.
**Resolved in framing revision 2: §3 becomes the SOLE normative home,
§5 keeps the incident and its signature as history, and the script's
header keeps citing §3 ALONE.** Revision 1 proposed citing both,
which splits one executable contract across two homes and weakens the
script's only clean boundary at the same time as Q#GR-4 declines to
build any automated check for prose drift. This entry recorded that
superseded decision until now; a recovering machine reading the stale
version would have rebuilt revision 1's wrong boundary.
- **Q#GR-1 must be settled by OBSERVATION before implementation**
whether the default sweep needs the binary too. The entire defect is
a precondition nobody checked; establishing its replacement by

View File

@ -1,8 +1,18 @@
# `scripts/gate --protocol` — the build its sweep depends on
**Status: framing pass, revision 2. Pre-implementation. Awaiting
**Status: framing pass, revision 3. Pre-implementation. Awaiting
approval.**
**Revision 3 fixes a witness that could not fail.** Revision 2's
`--self-test` plan put the failing step **last**, so an aborting runner
and a continuing one produce identical output — the witness for
Q#GR-2's "the suite keeps going" policy would have passed on a runner
doing the opposite. A passing **sentinel after** the failure, asserted
to have written its log, is what separates them. §7 also now pins the
**exact** build command rather than only the step's name and position,
since a `build-crdt` running plain `cargo build` would leave the gate
just as unsound while looking repaired.
**Revision 2 takes three review findings.** The normative requirement
goes **entirely** into handoff §3 rather than being split across §3 and
§5 (§5, Q#GR-3). Q#GR-1's observation procedure is respecified on a
@ -201,10 +211,20 @@ parse time. Reintroducing it one lane later, in the tool whose purpose
is to be trustworthy, is not a trade worth making.
*My vote: **a `--self-test` mode running a HARDCODED synthetic plan***
— two lines, `true` and `false`, with the failing one named
`build-crdt`. It asserts what actually needs asserting: the runner
prints the failing gate's name, lists it under `FAILED:`, writes its
log where it says it does, and exits non-zero.
**three** lines: a passing step, a failing one named `build-crdt`,
and **a passing SENTINEL after it**.
**The third line is not padding, and revision 2's two-line plan was
broken without it.** With the failure last, a runner that **aborts** on
failure and one that **continues** produce identical output, so the
witness passes either way — and Q#GR-2's whole answer is that the suite
keeps going. A sentinel *after* the failing step, asserted to have run
and written its log, is the only thing that distinguishes them.
So it asserts: the runner names the failing gate, lists it under
`FAILED:`, writes its log where it says it does, exits non-zero, **and
the sentinel after the failure has its own log** — which is Q#GR-2's
policy made observable rather than declared.
- **No injection.** The synthetic plan is a literal inside the script;
nothing external supplies a command.
@ -230,8 +250,14 @@ named so it is not mistaken for an oversight.
## 7. Verification
- **`--print-plan --protocol` emits `build-crdt` immediately before
`sweep-crdt`.** Order asserted, not just presence: a build after the
sweep it feeds is the same defect with an extra line.
`sweep-crdt`, carrying the EXACT command.** All three asserted —
presence, position, and the literal
`cargo build --workspace --no-default-features --features luajit,crdt`.
Name and position alone would pass on a step that builds the wrong
feature set, which is the failure this lane is fixing: the crdt sweep
needs *those* features, and a `build-crdt` that ran plain
`cargo build` would leave the gate exactly as unsound while looking
repaired.
- **`--print-plan` WITHOUT `--protocol` does not emit it** (subject to
Q#GR-1 — if the default sweep turns out to need the binary too, this
assertion inverts and §4 changes with it).
@ -243,6 +269,12 @@ named so it is not mistaken for an oversight.
prints `build-crdt` as the failing step, lists it under `FAILED:`,
and writes the log path it claims. This is the criterion revision 1
stated with no way to observe it.
- **The suite CONTINUES past a failed gate** (Q#GR-2) — the sentinel
step after `build-crdt` in the synthetic plan has its own log.
**Revision 2's two-line plan could not assert this**: with the
failure last, an aborting runner and a continuing one are
indistinguishable, so the witness would have passed on a runner that
does the opposite of the stated policy.
- **The existing 15 `tests/gate_script_acceptance.rs` tests still
pass**, and the new assertions join them on the **no-gates paths**
(`--print-plan` runs nothing), keeping the suite cheap.