session 2026-08-08 night: REVIEWED-99/100/101 placed; PENDING-117 amended + PENDING-118 filed; harvest #192 collision -> #194, #195 filed

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 15:11:29 +02:00
co-authored by Claude Opus 5
parent c86b82512b
commit ac4745b599
8 changed files with 444 additions and 16 deletions
+95 -1
View File
@@ -1540,7 +1540,7 @@ This is harmless today only because voice ⟺ source: measured, **max distinct v
**Date:** 2026-08-08
**Tag:** [PROPOSAL]
**Related:** REVIEWED-97 · PENDING-115 · skill-harvest register #192. **PROPOSAL, not FIX** — it changes what a gate accepts (a hook that can refuse a commit), which the amendment discipline puts above the FIX lane regardless of how small the diff is.
**Related:** REVIEWED-97 · PENDING-115 · skill-harvest register **#194** (cited here as `#192` when filed; that number was already held by the cited-vs-placed check of 2026-08-07 night, and the later filing was renumbered 2026-08-08 — see the register's renumbering note). **PROPOSAL, not FIX** — it changes what a gate accepts (a hook that can refuse a commit), which the amendment discipline puts above the FIX lane regardless of how small the diff is.
**Summary.** `118f411` split the Mauss sidecar's `body` section into `body-01…13`. That invalidated `test_navigate.py`'s hardcoded node id, and **the fleet sat 202/203 red for a full day** — through two separate rounds of correction to that very commit — surfacing only because the steward asked an unrelated question about instrument reliability. Nothing runs the suites on the change that breaks them.
@@ -1568,3 +1568,97 @@ This is harmless today only because voice ⟺ source: measured, **max distinct v
**Awaiting:** Steward authorization.
---
## PENDING-117 — The cross-repo half: a chamber edit invalidates engine bindings with no commit on either side (resuming PENDING-53 Option 3)
**Date:** 2026-08-08
**Tag:** [PROPOSAL]
**Related:** PENDING-53 (archived, REVIEWED-53 2026-07-10) · PENDING-116 / REVIEWED-100 (built today) · chamber `_curation/graduation-spec.yaml` `engine_source_binding` · `_curation/conversion-runbook.yaml` `reanchor:` block.
**Summary.** REVIEWED-100 landed a pre-commit trigger that runs the engine fleet when `corpus/` changes. It closes the **same-repo** half only. The canonical texts live in `chamber-library`, and a chamber-side re-anchor or re-clean invalidates the engine's `manifest.yaml` sha, the sidecars' `source_sha256` and the coverage ledger **with no engine-side commit at all** — so no hook fires on either side. This resumes PENDING-53's **Option 3**, which was deferred rather than rejected.
**The deferral condition, stated precisely rather than favourably.** PENDING-53's recommendation reads: *"Option 3 as a follow-on if re-hash/re-anchor recurs across the ~30-source Making batch."* That condition is **NOT met** — the Making batch is sourced but not ingested. The "5 standing FAILED rows since 2026-07-10" cited at REVIEWED-73 are **repaired**: the ledger today reads `validated: 14, failed: 0, failures: []`. There is **one** documented cross-repo incident, the founding one (Weil P1, 2026-07-09, recorded in PENDING-53 as *"caught only by chance during P2 diagnosis"*). `118f411` is the **same-repo analog** and is evidence about the firing-moment diagnosis generalizing, not a second instance of this class. Filing this now is therefore **not** a claim that the trigger fired.
**Rationale — why now, on different grounds.** Building half a gate raises confidence faster than it raises coverage. Before today, "does anything check the corpus↔engine binding?" answered *no*, uniformly. After REVIEWED-100 it answers *yes, visibly* — the hook prints `Staged change touches [corpus/] — running declared check` and refuses on red. A reader who has seen that fire has every reason to believe corpus changes are covered. They are covered **only when the edit originates engine-side.** The asymmetry is now invisible from the surface that demonstrates the protection, which is a worse epistemic state than the uniform *no*, and is Constraint #4 (honest degradation) applied to the gate's own advertised extent. The `.precommit-triggers` header and the engine `CLAUDE.md` both name the gap in prose — but PENDING-116's own argument is that a named risk is not a mechanized check.
**A second-order finding, filed here rather than separately.** PENDING-53's deferral was invisible to every standing instrument. `governance-drift-check.py` reports *"deferred decisions: 2 tracked, none due"* — it does not read **archived** PENDING bodies, where this deferral lives. The gap surfaced only because a chamber YAML header cited "PENDING-53" and the citation did not resolve in the live register. Same shape as skill-harvest #191: a detector correct everywhere it looks, not looking where the quarry lives.
**Options.**
- **(a) Scheduled binding check.** A periodic job recomputes each manifested source's live sha against `manifest.yaml`, the sidecar `source_sha256` and the coverage ledger, and reports drift. Catches the case with no commit on either side — the only option that does. Cost: a scheduler, and a report nobody is obliged to read.
- **(b) Chamber-side `.precommit-triggers`.** Declare in `chamber-library` that a change under `canonical_texts/` runs a checker which greps the engine repo for the affected sha. Fires at the moment of the edit and needs no scheduler. ⚠ Requires the chamber hook to reach into a sibling repo, which couples them at a path — and fails silently if the engine is not cloned beside it.
- **(c) The PENDING-53 Option 3 tool as written** — a `reanchor` helper that, given a canonical, greps both repos for the old sha, updates all bindings and runs both gates. Repairs rather than detects; still requires someone to invoke it.
- **(d) Do nothing; the prose warnings stand.** Refuted by PENDING-116's own reasoning, and now additionally by the confidence asymmetry above.
**Recommendation: (a) + (c), in that order, and NOT (b).** (a) because it is the only option that fires when there is no commit to hang a hook on, which is the defining feature of this class. (c) second because detection without a repair path just relocates the manual work; PENDING-53 already specified it. (b) rejected: a hook in one repo reaching into another reintroduces exactly the coupling REVIEWED-100 rejected when it refused to bake studium-engine's paths into the global hook.
**Check that it worked — both directions required.** Re-hash a chamber canonical without touching the engine: the check must report drift naming all three binding surfaces. Then re-hash and correctly re-anchor: it must report clean. A drift detector that has never reported clean on a genuinely-clean corpus has not been shown to discriminate.
**⚠ What this does not establish.** Neither (a) nor (c) makes anyone *read* the report. A scheduled check that fires into an unwatched log is the disarmed-tripwire class this repo already names, one layer out. Whether the report needs an escalation path is a real open question and is deliberately not answered here.
**Files affected:** a new scheduled checker (home undecided — engine `scripts/` vs `~/dotfiles/scripts/`, and that placement is itself part of what needs ruling); `corpus/manifest.yaml` + `corpus/sidecars/*.meta.json` + `corpus/coverage-ledger.json` as read-only inputs. No gate acceptance changes.
**Awaiting:** Steward authorization.
---
### AMENDMENT 1 — 2026-08-08, on the steward's conditional authorization
*Appended, not substituted: the body above is what was ruled on and stays legible. Where a stated reason is withdrawn it is struck here and the replacement named, per the REVIEWED-87 lesson that an amendment joins its record rather than replacing it.*
**§A — Condition 1 accepted. (a) is authorized only jointly with a spec amendment; the item's `Files affected` was incomplete.** `graduation-spec.yaml` carries `engine_source_binding` as a **prose string**. A scheduled checker cannot consume it, so it must either hardcode the surfaces — creating a second home for one enumeration, which the hash-locality principle four lines below it forbids — or the spec gains a structured `surfaces:` list. `Files affected` therefore gains **`_curation/graduation-spec.yaml`**. Change-class: ratified convention-data → **[PROPOSAL]**, jurist design-gate, per the lane rule discussed at REVIEWED-53 (lane tracks change-class for machine-convention-data files). **Without it the fix reproduces the drift class one layer out.**
**§B — Condition 2 accepted. The stated reason for rejecting (b) is WITHDRAWN.** ~~"a hook in one repo reaching into another reintroduces exactly the coupling REVIEWED-100 rejected"~~ — that is **borrowed authority and factually wrong**: REVIEWED-100 rejected coupling a *globally shared* hook to one repo's layout; (b) is a *repo-local declaration*, the authorized mechanism, whose command reaches a sibling path. Different object, different failure mode. **Recorded reason, which was already the item's own parenthetical and is the stronger one: (b) fails silently when the engine is not cloned beside the chamber — a detector that cannot see where the quarry lives, which is this item's own subject class.** Noted for the future: a rejection resting on borrowed precedent becomes precedent; cheap to correct now, expensive later.
**§C — Condition 3 RESOLVED. The framing stands; the MECHANISM does not.** Checked: `git show --name-only 177e2b3` returns **exactly one file**, `reading-indices/alexander-a-pattern-language.yaml`, and **zero** under `canonical_texts/`; `shasum -a 256` of the live canonical equals the engine-declared `accf235d…`. So it **did not touch the engine's three-sha binding surface**, the item does not understate its case, and *"not a claim the trigger fired"* stands **uncorrected**.
**Detection latency, now recorded as this item's key empirical number: 56 days** (partial re-anchor 2026-06-12 → repair 2026-08-07). This is the quantity the (a)-versus-(d) trade turns on, and it is the only measured one we have.
⚠ **But the datum breaks the proposal's scope, and that is the finding.** Nothing hashes the reading index. Measured: `content_sha256` occurs **0 times** in its 689 lines; `source_sha256` occurs 3 times and binds **outward** to the canonical text; the manifest declares `reading_index:` (a path) and `reading_index_status: RE-ANCHORED-BOUND` (a **prose status**, which `177e2b3`'s own message calls out as having read bound-throughout while the file was stale in one region). **The binding runs index→text; nothing binds to the index.** Therefore **all three surfaces named in (a) and (e) would have read GREEN for the entire 56 days** — the proposal as filed is silent on the best-documented incident in the record.
**Consequence: the surface list is FOUR, not three** — the reading index needs a content hash of its own, or the checker inherits the exact blindness that let this drift live. And an enumeration that was wrong the moment it was written is itself the argument for §A: it must be **declared data with one home**, never hardcoded in a consumer.
**Also noted:** PENDING-111 is open on Alexander (`fidelity_equivalence@3`, escaped emphasis, 293 instances). With this item and the R0 region-verification gap, **three open threads now converge on one canonical.**
**§D — Condition 4 accepted; (e) added and sequenced FIRST.**
- **(e) Check the binding shas unconditionally on every studium-engine commit**, in the hook REVIEWED-100 already landed. Not path-triggered — unconditional, milliseconds. **Fires where a human is already in the invocation path**, which is the gap PENDING-98 names and the gap this item's own ⚠ concedes (a) leaves open.
- **Measured, rather than assumed:** engine cadence over the last 30 commits is **median gap 0.01 d, mean 0.09 d, max 0.8 d**, repo `ahead 11`. So (e)'s latency during active work is **hours, not days**. ⚠ That sample spans two days and is a burst, not lifetime cadence — which is exactly why (a) is retained.
- **Revised sequence: (e) → (a) → (c)**, with **(a) demoted to backstop for the engine-quiet case** (the chamber moves while the engine is silent — where (e) cannot fire by construction). **(b) rejected on §B's corrected reason.**
**§E — Condition 6 accepted. Placement: `~/dotfiles/scripts/`.** Steward's reasoning recorded: a cross-repo invariant is owned by neither repo, and putting it in either makes that repo the authority over a relationship it is only one half of. Convention data in the ratified spec (§A), thin consumer in dotfiles — the pattern REVIEWED-100 authorized.
**§F — Condition 5 accepted. The second-order finding is REMOVED from this item** and filed as **PENDING-118** (`governance-drift-check.py` does not read archived PENDING bodies, so *"deferred decisions: N tracked, none due"* is structurally blind to every archived deferral). It concerned an instrument and all archived deferrals, not this item; filed inside a [PROPOSAL] it would have died with a DEFERRAL or REJECTION of its host.
**Awaiting:** placement of the ruling. Build sequence on placement: **(e) → spec amendment (§A, jurist-gated) → (a) → (c)**.
---
## PENDING-118 — The deferred-decision checker is structurally blind to every archived deferral
**Date:** 2026-08-08
**Tag:** [HARDENING]
**Related:** PENDING-117 §F (split from it on steward's condition 5) · **PENDING-108** (a jurist ruling is filed as a document only when someone remembers) · **PENDING-110** (`REVIEWED-N`/`PENDING-N` are independent sequences) — the same family: **the register's own instruments not reaching parts of the register.**
**Summary.** `governance-drift-check.py` runs at every wake and reports, today, *"deferred decisions: 2 tracked, none due (2 checkable, 0 manual-only)"*. It reads `~/PENDING.md`. It does **not** read `~/PENDING-archive.md`. Every deferral inside a **closed** item is therefore invisible to it — and a deferral inside a closed item is the normal case, because an item is typically closed *by* a ruling that defers part of what it proposed.
**How it surfaced — not by looking for it.** Chamber `_curation/graduation-spec.yaml` cites "PENDING-53" for the cross-repo binding gap. The citation **did not resolve** in the live register (`grep -c "^## PENDING-53" ~/PENDING.md` → 0). It resolved in the archive, where PENDING-53's ruling had deferred its Option 3 against a named condition. The checker had reported "none due" at that same wake, correctly by its own lights and uninformatively about the question.
**Rationale.** A deferral is the claim *not yet*, carrying a condition that makes it *now*. Archiving the item does not retire the condition — it removes the only place anything looks for it. The instrument's silence therefore certifies the wrong set, and its output sentence (*"N tracked"*) reads as a census of deferrals when it is a census of deferrals **in one file**. That is Constraint #4 applied to the instrument: it does not report its own extent. It is also skill-harvest **#191**'s shape exactly — *a detector correct everywhere it looks, and not looking where the quarry lives* — which is the second instance of that shape in eight days and argues the pattern is worth treating as a class rather than a coincidence.
**⚠ Size unmeasured, deliberately.** How many archived deferrals exist, and how many have conditions that have since fired, is **not known** — establishing it is part of the work, not a premise of it. PENDING-53 is one confirmed instance (condition *not* met on strict reading; see PENDING-117 §C). One instance is not a rate, and this item does not claim one.
**Options.**
- **(1) Widen the scan to `~/PENDING-archive.md`.** Smallest change; the checker already parses that exact format. ⚠ Every archived deferral becomes a standing report line, so the first run needs a triage pass or it reports a wall.
- **(2) Widen the scan, plus a one-time census** classifying each archived deferral as condition-met / not-met / unconditional, so the standing report starts from a known baseline rather than a backlog.
- **(3) Require deferrals to be re-filed as live items at close time** — a discipline, not a mechanism. Rejected on this register's own evidence: it depends on someone remembering at exactly the moment attention is leaving the item.
**Recommendation: (2).** (1) alone converts an invisible backlog into an unread one, which is the same failure wearing a report. The census is the thing that makes the widened scan legible on its first run, and it is bounded — the archive is a finite file.
**Check that it worked — both directions required.** A known archived deferral whose condition HAS fired must be reported; one whose condition has NOT must stay silent. **PENDING-53 is available as the negative** (strictly read, its Making-batch condition is unmet), and it is a *real* archived instance rather than a synthetic fixture — which is the standard the discrimination gate demands. A positive requires finding one, and if the census finds **none**, that is a reportable result, not a failed build.
**⚠ What this does not establish.** Widening the scan makes archived deferrals *visible*; it does not make anyone act on them, and it says nothing about deferrals living in the third place they occur — inside `~/REVIEWED.md` ruling bodies, which neither file's scan covers. Named, not absorbed.
**Files affected:** `~/dotfiles/scripts/governance-drift-check.py`; a one-time census artifact (home to be decided with the ruling).
**Awaiting:** Steward authorization.
---