[HARDENING] PENDING-126 + PENDING-122 Amendment 2 — what inducing red revealed, and REVIEWED-102..105 placed

All three findings came from contact while building a red fixture for the
REVIEWED-103 acceptance. None was sought; the search for a control that worked is
what exposed them.

The fleet already violates the condition REVIEWED-104 attached to the NEW
live-binding assertion, on a dependency the ruling did not consider. Three suites
crash on a gitignored corpus/index.db with a raw sqlite traceback, and run-fleet
reports FLEET RED indistinguishably from a code defect — while store.py rebuilds
that file in 0.628 seconds and the clone then runs 7/7 green. So the condition is
retroactive, not prospective. And test_retrieve.py already detects the absence and
skips with a named reason, which makes PENDING-124 recommendation (d) concrete: the
honest third state exists in this fleet, in one suite, and three others lack it.

R0's section_end bound is unguarded. Removing it leaves 31/31 passing. That is the
rule R0 was created to establish after two consumers disagreed on 3 of 253 patterns
with neither right — asserted in prose, correct-but-inert on the live corpus, and
therefore invisible to every test.

test_navigate crashes with StopIteration rather than naming a failure. The exit code
was always right; the legibility is missing — REVIEWED-100's own distinction,
recurring where its fix does not reach.

Also commits REVIEWED-102 through -105, placed by the steward and left uncommitted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A35wiD55yRHj5U1ECZAX4t
This commit is contained in:
David F Glidden
2026-08-08 18:15:20 +02:00
co-authored by Claude Opus 5
parent 448ce373ca
commit 2472ed8e88
3 changed files with 214 additions and 2 deletions
+126 -1
View File
@@ -1168,4 +1168,129 @@ data in the ratified spec, thin consumer in dotfiles — the pattern REVIEWED-10
→ (a) → (c). Tag commits with REVIEWED-101. The spec amendment gates (a), not (e): (e) reads
the engine's own manifest and sidecars and needs no cross-repo enumeration. Each stage carries
a both-directions control — drift reported when a binding is stale, clean reported on a
genuinely clean corpus.
genuinely clean corpus.
## REVIEWED-102 — PENDING-119 — REVIEWED-101 condition 6 placed (e)'s consumer in dotfiles, on reasoning the same ruling says (e) does not engage
**Date:** 2026-08-08
**Decision:** AUTHORIZED — option (i), with condition 6 of REVIEWED-101 explicitly narrowed on the record, and one condition on (i).
**Notes:** The ambiguity is mine. Condition 6 was drafted flat, under a heading that read "Placement", and left its scope to be inferred from a
sentence four lines below it. That is a jurist defect, not an executor misreading. The item is right that the two texts admit both readings, and
right that the narrow reading is the one the reasoning supports: condition 6's argument is ownership of a cross-repo invariant, and (e) does not
enumerate one. It follows the engine's own declared pointers into the chamber; the surface list that (a) needs is precisely what (e) does not need.
That was already the stated basis for severing (e) from the spec amendment, and the same severance carries the placement.
1. NARROWING, recorded as a ruling and not as a charitable reading: condition 6 of REVIEWED-101 governs consumers that must ENUMERATE the
cross-repo binding surface — (a) and (c). It does not govern (e). Left unrecorded, the next reader relitigates this.
2. The recorded reason for rejecting (ii) is that it inverts the condition it honours. A ~/dotfiles/scripts/check-source-binding.sh whose body is
one exec of engine/ingest_gate.py --check-only puts an engine path and an engine flag into the global layer. That is the coupling REVIEWED-100
rejected, reintroduced in the name of a condition written to prevent coupling. A rule that produces the outcome it exists to forbid is being read
at the wrong grain.
3. Kept in view, because the reflex runs the other way: the placement question only became live because the executor delegated to ingest_gate
instead of writing a fresh sha-comparing script. Had it duplicated the logic, condition 6 would have been straightforwardly correct. The better
implementation is what made the condition misfit — a rule's misfit is not automatically an implementation error.
4. The fleet-census finding is SPLIT OUT as PENDING-122. "No fleet suite validates live binding" is not evidence for a placement dispute; it is a
standing correction to what fleet-green certifies, owed to anyone reading a green fleet. Filed inside PENDING-119 it dies if PENDING-119 is
deferred. Same objection made at REVIEWED-101 condition 5; consistency requires making it again. It belongs with PENDING-96 as one family — a green
that attests less than its surface suggests.
5. CONDITION on (i): 0.218 s over 14 sources is honest about being burst-sized, and the check is unconditional on every commit, scaling with
sources × file size. State the threshold now with its action — when it exceeds ~1 s, (e) re-scopes or hands off to (a)'s scheduled job. A
per-commit cost that grows unremarked converts a tripwire into a --no-verify habit, which is this thread's own failure class arriving by the back
door.
**If AUTHORIZED:** Proceed with (i) — one line in the engine's .precommit-triggers. Record the condition-5 threshold beside it. Tag commits with
REVIEWED-102.
## REVIEWED-103 — PENDING-120 — The fleet trigger covers corpus/ but not the engine code the fleet exists to test
**Date:** 2026-08-08
**Decision:** AUTHORIZED — option (a), with the scope framing corrected and the acceptance fixture decomposed.
**Notes:** The demonstration is the strongest part: eecc8bb touched the gate and the gate's own test floor, and the hook printed nothing. First
real non-probe commit since the trigger landed, and it ran nothing. That is a measured failure, not a reasoned risk — the same standard
REVIEWED-100 credited PENDING-116 for.
1. CORRECTION to the scope-honesty note. The item says REVIEWED-100 "did not rule the pathspec". As to the ruling, that is accurate — REVIEWED-100
authorizes the mechanism and the both-halves acceptance and says nothing about paths. But PENDING-116's own Costs section does: "the trigger paths
must be scoped tightly (corpus/, corpus/sidecars/) so ordinary docs commits do not pay it." So the pathspec was not silence — it was a cost
commitment in the authorized item. This does not change the outcome; it changes the bar. The widening must be SHOWN to preserve the discrimination
that commitment bought, which is exactly why (b) is correctly rejected and (a) is not. Record it as revising a stated cost-control with its
justification intact, not as filling a gap. In-scope repair is the more comfortable framing and the less accurate one.
2. The acceptance test DECOMPOSES; one fixture cannot meet "neither may be a synthetic probe if a real one is available". (i) Fires on a real
engine change — replay eecc8bb against the widened pathspec; genuinely real, genuinely available, and it is the commit that demonstrated the gap —
but eecc8bb was green, so it proves firing only. (ii) Refuses on red — requires an induced red unless history holds a real red engine/ commit; if
one exists use it, and if not, say the fixture is synthetic rather than letting "real fixture" cover both halves. (iii) Docs-only still runs
nothing — unchanged, and the half that proves discrimination.
3. The adjacent gap was checked and the answer is NO; filed as PENDING-123. The hook does not distinguish "no trigger path matched" from "the
declaration is malformed or its command is missing". Five disarming faults were tested against a positive control, each staging a real corpus/
change the hook must catch: pathspec typo, no separator, empty command, comments-only, empty file. All five silent, all exit 0. A typo disarms the
gate permanently and invisibly. This is also why eecc8bb running nothing went unremarked — its output is byte-identical to a fully disarmed hook's.
4. INTERACTION with PENDING-119. If both land, .precommit-triggers carries two lines with overlapping paths and engine commits pay ~2 s (fleet) +
0.218 s (binding). Declare the order in the file so a red is attributable to one check without reading both.
**If AUTHORIZED:** Proceed with (a) — corpus/ engine/ tests/ scripts/run-fleet.sh. Land the three-part acceptance separately, labelling the
induced-red fixture synthetic if no real red engine/ commit exists. Tag commits with REVIEWED-103.
## REVIEWED-104 — PENDING-122 — What a green fleet certifies, and what it does not: no suite validates live binding
**Date:** 2026-08-08
**Decision:** AUTHORIZED — option (a), with a required third result state.
**Notes:** A live-corpus assertion makes one suite depend on chamber-library being present and reachable. Every other suite builds under tmp and is
portable; this one will not be. The item does not say what happens on a fresh clone with no chamber beside it, and both obvious answers are wrong.
Red on absent is a suite going red for reasons unrelated to the code under test, which trains people to discount fleet red — the worst possible
outcome for this particular thread. Skip on absent is the silent net, in the very assertion added to correct an overstatement.
1. CONDITION: three states — bound / drifted / cannot-assess — and cannot-assess must be distinguishable in the fleet summary, never folded into
green. A green fleet that includes an unassessed binding case is the same overstatement one layer along.
2. The REVIEWED-83 A1 leg of the analogy was challenged as uncorroborated and has been verified against ~/REVIEWED.md, which is authoritative.
REVIEWED-83 Amendment 1 (2026-08-01) IS the classifier layer-error: "The classifier's controls exercise its decision rule … They cannot test
whether three signals are enough … In both cases the control was correct and sat at the wrong layer." The 0 of 17 → 0 of 14 figure visible in
e341242 is a secondary paragraph of that same amendment, labelled "Consequential correction, routed not applied." Third subsystem stands on checked
ground, and the amendment itself names the first two as one shape.
3. Does not prejudge PENDING-121, confirmed from both sides. Option (a) closes the distance between "the gate works" and "the corpus is bound" at
whole-file granularity only; anchor correctness is 121's gate and the two land independently. Recorded with it: REVIEWED-101 §C's "fourth surface —
the reading index carries no hash" was wrong, and 121 corrects it — the runbook binds the index outward by source_sha256, and the real gap is
finer and worse.
4. The three-state requirement is raised to doctrine as PENDING-124 rather than conditioned again per item.
**If AUTHORIZED:** Proceed with (a), three-valued. Tag commits with REVIEWED-104. Land after REVIEWED-105 if both are authorized.
## REVIEWED-105 — PENDING-123 — The pre-commit hook cannot distinguish "nothing to check" from "I am disarmed"
**Date:** 2026-08-08
**Decision:** AUTHORIZED — (b) now, plus (e) in place of a flag; (a)'s full listing retained on --verbose.
**Notes:** The strongest item of this set. Positive control first, six rows, mechanism read from the hook's own source down to the two lines that
swallow the difference — `[ -n "$cmd" ] || continue` and the `2>/dev/null` that erases "git could not resolve this pathspec". And it answers
PENDING-120 §C: "Running pre-commit checks…" with nothing after it is what a fully disarmed hook prints, which is why eecc8bb went unremarked.
1. Instead of (a) behind a flag — a flag nobody sets is a capability nobody has — option (e): print the per-rule line ONLY when a
.precommit-triggers file exists and no rule matched. A rule ran, existing output already says so; nothing matched, one line naming the declared
rules and the staged paths; no triggers file, print nothing, so no noise in any other repo. Zero cost in the normal case, and the line appears in
exactly the ambiguous case. It also partly closes the fifth silence: a typo'd corpuss/ shows as a declared rule that did not match on a commit that
touched corpus/, catchable at the moment the reader is already looking — PENDING-98's mitigation shape, not a log. Keep (a)'s full per-rule
listing on --verbose for the never-yet-matched rule, which stays honestly unknown.
2. The item's own standard, turned on the item: the summary claimed silence when the declaration is "malformed, mis-typed, empty, or absent", and
the table had no absent row, nor one for the hook itself missing or core.hooksPath unset. Rows added. Measuring them found something stronger than
the claim — with the hook file missing, the commit produces ZERO output, not an ambiguous silence — and found the executor wrong in the other
direction: unsetting core.hooksPath locally falls back to an armed global, so that row is a robustness property, not a fault, and is recorded as
one.
3. Blast radius of (b). The hook is global, so a refusal on malformed declarations arms in every repo carrying a triggers file, present and future.
Censused 2026-08-08: exactly one exists today (studium-engine), across ten repos under the global hooksPath. Today's radius is one repo; the
condition is about the future and stands. Required: the refusal message names file, line number and fault, and states --no-verify. A gate that
blocks without saying why is replaced by habit within a week.
4. SEQUENCING across the four open items: land 123 before 119(i) and 120(a). Both add lines to .precommit-triggers; a validator that catches a
malformed line should exist before the file grows. In the other order, the first thing to test the new declarations is the declarations themselves.
**If AUTHORIZED:** Proceed with (b) + (e). Build order: REVIEWED-105 → REVIEWED-102 (i) → REVIEWED-103 (a). Tag commits with REVIEWED-105.