From 12affd78e19e50e74c1addd5c636bfbf3e88f73a Mon Sep 17 00:00:00 2001 From: Levi Neuwirth Date: Sun, 9 Aug 2026 16:10:09 +0200 Subject: [PATCH] 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 Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai --- docs/active-work.md | 14 +++++++-- docs/gate-protocol-build-framing.md | 46 ++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/docs/active-work.md b/docs/active-work.md index 7cfd6e3..305bb99 100644 --- a/docs/active-work.md +++ b/docs/active-work.md @@ -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 diff --git a/docs/gate-protocol-build-framing.md b/docs/gate-protocol-build-framing.md index d1750e4..5ee8dd2 100644 --- a/docs/gate-protocol-build-framing.md +++ b/docs/gate-protocol-build-framing.md @@ -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.