From 5e212df97de1ee0b91c5695317382f2e1feac3f7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 26 Aug 2026 09:09:26 +0000 Subject: [PATCH] ci: gate the supersession index on being current The table went stale within the hour of #1046 merging. #1047 landed a plan naming GateDecision and ThinkingStyle without citing the ruling -- a 63rd blind plan -- so the index committed minutes earlier no longer reproduced (RESCOPE 50->51, GateDecision 19->20, ThinkingStyle 23->24). Nothing was wrong with the generator. It reads .claude/plans/ + crates/ + COMPONENT-MAP.md, so any PR that adds a plan makes the committed table stale, and generation was manual. That is the same defect the index was built to fix, one level up: generating it removed the transcription error and left the staleness. A generated artifact with no staleness gate is a hand-maintained artifact with extra steps. The workflow regenerates, diffs, and fails with the regenerate command. It watches the generator's INPUTS, not just the generator, because the inputs are what made it stale. Falsified both ways: appending one comment to the index makes it exit 1; regenerating makes it pass. Also refreshes the index to current. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01AGVLyRZNEKKBSfBDJfbY3V --- .claude/board/SUPERSESSION-INDEX.md | 9 ++-- ...-e-the-archive-route-was-3-of-3-wrong-1.md | 31 ++++++++++++++ .github/workflows/supersession-index.yml | 42 +++++++++++++++++++ 3 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/supersession-index.yml diff --git a/.claude/board/SUPERSESSION-INDEX.md b/.claude/board/SUPERSESSION-INDEX.md index e9a57060f..b5928bd20 100644 --- a/.claude/board/SUPERSESSION-INDEX.md +++ b/.claude/board/SUPERSESSION-INDEX.md @@ -56,15 +56,15 @@ coverage instead. | `persist_cycle` | BLOCKED | — | 10 | 6 | 5 | | `CognitiveMarkers` | REPURPOSE | `Commit` | 2 | 0 | 0 | | `DominoCascade` | REPURPOSE | `Commit` | 8 | 0 | 0 | -| `GateDecision` | REPURPOSE | — | 24 | 19 | 17 | +| `GateDecision` | REPURPOSE | — | 24 | 20 | 18 | | `GateState` | REPURPOSE | — | 14 | 1 | 1 | | `MergeMode` | REPURPOSE | — | 8 | 11 | 11 | | `ResonanceDto` | REPURPOSE | `PerturbationDto` | 2 | 6 | 5 | | `BindSpace` | RETIRE | — | 67 | 41 | 40 | | `CollapseGateEmission` | RETIRE | — | 5 | 12 | 12 | -| `ThinkingStyle` | RETIRE-toward-contract | — | 51 | 23 | 20 | +| `ThinkingStyle` | RETIRE-toward-contract | — | 51 | 24 | 21 | -## Table 2 — plans naming a ruled symbol without citing the ruling (62) +## Table 2 — plans naming a ruled symbol without citing the ruling (63) Route is **mechanical triage, not a verdict**: `ARCHIVE?` = the plan's own status says it shipped; `RESCOPE` = it targets a symbol marked RETIRE; `READ` = neither signal fires @@ -110,6 +110,7 @@ a licence to act on it. | **RESCOPE** | `Palette256-3DSB-PhiSpiral-attention-integration-plan` | `BindSpace`, `CollapseGateEmission` | — | 0/0 | | **RESCOPE** | `anatomy-realtime-v1` | `BindSpace`, `ThinkingStyle` | — | 0/1 | | **RESCOPE** | `elegant-herding-rocket-v1` | `BindSpace`, `ThinkingStyle` | — | 0/0 | +| **RESCOPE** | `grounding-descent-cognitive-maslow-v1` | `GateDecision`, `ThinkingStyle` | PROPOSED (unbuilt; every mechanism cited exi | 1/7 | | **RESCOPE** | `kognitionswirtschaft-v1` | `GateDecision`, `ThinkingStyle` | PROPOSED (unbuilt, unprobed). Operator-initi | 1/7 | | **RESCOPE** | `lance-graph-ontology-v5` | `BindSpace`, `GateDecision` | Drafted (2026-05-07). Picks up where v4 (`cl | 3/16 | | **RESCOPE** | `north-star-integration-v1` | `CollapseGateEmission`, `ThinkingStyle` | RATIFIED (council resolved + gates ratified | 1/1 | @@ -143,6 +144,6 @@ a licence to act on it. | **RESCOPE** | `unified-soa-rubikon-integration-v1` | `BindSpace` | — | 8/8 | - **ARCHIVE?**: 0 -- **RESCOPE**: 50 +- **RESCOPE**: 51 - **READ**: 12 - ruled symbols tracked: 14 diff --git a/.claude/board/entries/2026-08-26-e-the-archive-route-was-3-of-3-wrong-1.md b/.claude/board/entries/2026-08-26-e-the-archive-route-was-3-of-3-wrong-1.md index d54920247..0aa7d8e5e 100644 --- a/.claude/board/entries/2026-08-26-e-the-archive-route-was-3-of-3-wrong-1.md +++ b/.claude/board/entries/2026-08-26-e-the-archive-route-was-3-of-3-wrong-1.md @@ -101,3 +101,34 @@ prompt to read, never a licence to act. This correction is the same error one level up — I fixed the *instance* I had measured rather than the *class* it belonged to, and shipped a table with a fabricated value in it. Naming the failing input is not the same as naming the failure. + +--- + +**⊕ THE GENERATED TABLE WENT STALE WITHIN THE HOUR (same day, post-merge).** +#1046 merged at 09:06 alongside #1045 and #1047. #1047 added +`grounding-descent-cognitive-maslow-v1`, which names `GateDecision` and +`ThinkingStyle` without citing the ruling — a 63rd blind plan. So the index +committed minutes earlier no longer reproduced: `RESCOPE` 50 → 51, +`GateDecision` 19 → 20 plans, `ThinkingStyle` 23 → 24. + +Nothing was wrong with the generator. The table is generated from +`.claude/plans/` + `crates/` + `COMPONENT-MAP.md`, and **any PR that adds a +plan makes it stale** — generation was manual, so the freshness lasted exactly +as long as nobody else merged. + +This is the same defect the index was built to solve, one level up. The +original argument was that *a hand-kept supersession table goes stale at the +next rename, and a stale one authorises work against a retired symbol.* +Generating it removed the transcription error and left the staleness — because +"generated" only means current at the moment someone last ran it. **A generated +artifact with no staleness gate is a hand-maintained artifact with extra +steps.** + +Closed with `.github/workflows/supersession-index.yml`: regenerate, `diff`, fail +with the regenerate command on drift. It watches the generator's **inputs** +(`.claude/plans/**`, `COMPONENT-MAP.md`) and not merely the generator, since +inputs are what actually made it stale. Falsified both ways before committing — +appending one comment to the index makes it exit 1; regenerating makes it pass. + +**Standing limit, unfixed:** the gate proves the table is *current*, never that +a route is *right*. The ARCHIVE? batch was current and 3/3 wrong. diff --git a/.github/workflows/supersession-index.yml b/.github/workflows/supersession-index.yml new file mode 100644 index 000000000..72b829e2a --- /dev/null +++ b/.github/workflows/supersession-index.yml @@ -0,0 +1,42 @@ +name: Supersession index is current +on: + push: + branches: + - main + pull_request: + paths: + # The generator's INPUTS, not just the generator. A plan or a ruled-symbol + # verdict is what makes the committed table stale -- that is how it went + # stale the first time (#1047 added a plan naming two ruled symbols, and + # nothing noticed). + - .claude/plans/** + - .claude/v3/COMPONENT-MAP.md + - .claude/tools/supersession_index.py + - .claude/board/SUPERSESSION-INDEX.md + - .github/workflows/supersession-index.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + regenerate-and-diff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Regenerate and compare + run: | + python3 .claude/tools/supersession_index.py > /tmp/regen.md + if ! diff -u .claude/board/SUPERSESSION-INDEX.md /tmp/regen.md; then + echo + echo "::error::SUPERSESSION-INDEX.md is stale." + echo "It is GENERATED from .claude/plans/ + crates/ + COMPONENT-MAP.md," + echo "so adding a plan that names a ruled symbol makes it stale." + echo "Regenerate and commit:" + echo " python3 .claude/tools/supersession_index.py > .claude/board/SUPERSESSION-INDEX.md" + exit 1 + fi + echo "index is current"