From 28268ecc03c4e9f9d364d1cf408ac9322194f820 Mon Sep 17 00:00:00 2001 From: Craig Truitt Date: Wed, 14 Oct 2026 09:57:23 -0500 Subject: [PATCH] docs(plan): record plan for 0015-recursive-workflow-guards/0004-recursive-integrity-guard Republish the revised plan. design.md now owns reconciling the deliberate dual-spelling fixture with the committed AC13 migration guard: tests/checks/80-cycle-fixture.sh's whole-set roadmap.md assertion is narrowed to exclude the one documented deliberate drift alias, keeping the guard sensitive to any third alias. tasks.md inserts T1 (the 80-cycle-fixture relaxation) and renumbers the implementation tasks to T2-T9. Plan publication commits only the plan artifacts; the item's build fixtures and backtrack record are left for the ship phase. --- .../0004-recursive-integrity-guard/design.md | 94 ++++++++++++++++--- .../0004-recursive-integrity-guard/tasks.md | 40 +++++--- 2 files changed, 107 insertions(+), 27 deletions(-) diff --git a/work/0015-recursive-workflow-guards/0004-recursive-integrity-guard/design.md b/work/0015-recursive-workflow-guards/0004-recursive-integrity-guard/design.md index 5a29d1a..62ba1bc 100644 --- a/work/0015-recursive-workflow-guards/0004-recursive-integrity-guard/design.md +++ b/work/0015-recursive-workflow-guards/0004-recursive-integrity-guard/design.md @@ -24,7 +24,10 @@ renumber and asserts no reference to the old canonical reference remains across the full rewrite set. The area references the sibling agreement areas that own overlapping literals (structure, cycle, packaging, renumber-sweep) by name and re-asserts none of them. One line is added to `tests/mutation.sh`'s staged-copy -list so the opt-in whole-suite runs stay green. +list so the opt-in whole-suite runs stay green, and +`tests/checks/80-cycle-fixture.sh`'s AC13 whole-set `roadmap.md` assertion is +narrowed to exclude the one documented deliberate drift alias so the committed +migration guard stays green with the dual-spelling fixture present. ## Approach @@ -155,6 +158,37 @@ into the scratch copy. Without it the opt-in whole-suite runs (steps 1–2) woul fail once the check exists. The `tests/README.md` Checks row and the per-rule mutation jobs remain `0005-guard-registration-sweep`'s responsibility. +### Reconciling the deliberate dual-spelling fixture with the committed AC13 guard + +`tests/checks/80-cycle-fixture.sh` carries an AC13 **negative** assertion +(`80-cycle-fixture.sh:61-71`) that pins the `0012-roadmap-deprecation` migration: +`find tests/fixtures -name roadmap.md` must resolve to exactly the one retained +legacy alias `tests/fixtures/cyclic-roadmap/roadmap.md`, so a stray un-migrated +`roadmap.md` cannot hide behind the manifest-first resolver. The +`9203-spelling-both` node's deliberate second `roadmap.md` would otherwise break +that exact-equality and fail `bash tests/run.sh`. + +This item owns the reconciliation. The assertion is **narrowed, not re-pinned**: +the stray-alias set is computed by excluding the single documented deliberate path +`tests/fixtures/recursive-integrity/items/9203-spelling-both/roadmap.md` +(`find … -name roadmap.md | grep -vxF `) and the remainder is still +compared for exact equality to the retained cyclic alias. The guard therefore still +fails on any *third* alias, and its intent — no *stray* alias survives migration — +is preserved: a *documented, deliberate* drift fixture is not a stray. The cycle +diagnostic itself (the `Children` parse and the `CYCLIC-DEP` contract assertions, +`80-cycle-fixture.sh:73-166`) is untouched, and the mutation job `job_8` is +unchanged. `89` references `80-cycle-fixture` by name for the migration guard and +re-asserts none of its literals (AC6). This is a scoped, intent-preserving +relaxation of the committed test suite, permitted by AC12 ("only the committed +test suite … are touched"); it edits no live surface. + +The `80` edit is a focused single-item change, not one of the shared append-only +registries the four guards contend on, so it is **not** added to this item's +`conflicts-with` declaration. That declaration stays the parent cell's two +registries (`tests/README.md`, `tests/mutation.sh`, `manifest.md:126`), which +avoids a self-inflicted `DRIFT-FACT` and keeps the declared set semantically exact: +the two registries are where sibling plans actually collide. + ## Alternatives considered - **A prose-only agreement check (pin the recursive authority phrases, no fixture @@ -163,15 +197,27 @@ mutation jobs remain `0005-guard-registration-sweep`'s responsibility. levels, missed a nested graph fault, or treated a dual-spelling node as clean. Rejected: the spec's decided open question requires an exercised fixture, and a prose-only check is the exact gap this item closes. -- **Extend `80-cycle-fixture.sh` / `88-renumber-sweep.sh` in place.** Pros: fewer - files. Cons: breaches single-owner agreement areas and forces re-asserting - sibling literals, failing AC6/AC11; conflates the cycle diagnostic and the - renumber prose list with a new recursive-integrity concern. Rejected. +- **Host the new integrity/renumber assertions inside `80-cycle-fixture.sh` / + `88-renumber-sweep.sh` instead of a new area.** Pros: fewer files. Cons: + breaches single-owner agreement areas and forces re-asserting sibling literals, + failing AC6/AC11; conflates the cycle diagnostic and the renumber prose list + with a new recursive-integrity concern. Rejected. (This is distinct from the + accepted, narrowly scoped narrowing of `80`'s AC13 whole-set `roadmap.md` + assertion — that relaxes the migration guard's stray-alias set for the one + documented deliberate drift fixture, and hosts no new assertion.) - **Renumber half re-pins the authority's prose lists (like `88`).** Pros: cheap. Cons: `88-renumber-sweep.sh` already owns the prose rewrite lists; re-pinning is duplication (AC9/AC11) and proves nothing about a *completed* renumber. Rejected in favor of the completed-renumber fixture plus a single unowned intermediate-manifest pin. +- **Move the deliberate drift alias out of the `tests/fixtures/**` find root (a + second fixture root, or a root outside `tests/fixtures/`) instead of narrowing + `80`'s AC13 assertion.** Pros: leaves the committed migration guard + byte-identical. Cons: breaks the single-`tests/fixtures/` fixture convention and + splits one fixture root across two locations; leaves the whole-set assertion with + a blind spot for the relocated root. Rejected in favor of the scoped narrowing, + which keeps the fixture in the canonical tree and the guard still sensitive to + any *third* alias. ## Interfaces and data model @@ -181,21 +227,31 @@ mutation jobs remain `0005-guard-registration-sweep`'s responsibility. - **New fixture root** `tests/fixtures/recursive-integrity/` — root-local `92xx` entity ids; item references resolve inside `items/`, never against live `work/`. -- **Changed file** `tests/mutation.sh` — one additive `cp -R` line in - `stage_copy()`; no job, no `JOB_COUNT` change. +- **Changed files** `tests/mutation.sh` — one additive `cp -R` line in + `stage_copy()`; no job, no `JOB_COUNT` change — and + `tests/checks/80-cycle-fixture.sh` — the AC13 whole-set `roadmap.md` assertion + narrowed to exclude the one documented deliberate drift alias; the cycle + diagnostic and `job_8` unchanged. - **No production interface.** No `phase` value, state file, command, agent, skill, or committed production checker is added or changed. The authority docs and prompts are the pinned target, not the guarded artifact. -**Backward compatibility.** The change is purely additive: a new auto-sourced -check file, a new fixture root, and one staged-copy line. No existing area, -fixture, selector, or harness behavior changes, so `bash tests/run.sh` and the -existing area selections stay green with no migration. +**Backward compatibility.** The change is essentially additive — a new +auto-sourced check file, a new fixture root, and one staged-copy line — plus one +scoped, intent-preserving relaxation of `tests/checks/80-cycle-fixture.sh`'s AC13 +whole-set `roadmap.md` assertion so the deliberate drift fixture is permitted while +any *stray* alias still fails (see "Reconciling the deliberate dual-spelling +fixture…"). No other area, fixture, selector, or harness behavior changes, so +`bash tests/run.sh` and the existing area selections stay green with no migration. ## Affected areas - `tests/checks/89-integrity-guard.sh` (new). - `tests/fixtures/recursive-integrity/**` (new). +- `tests/checks/80-cycle-fixture.sh` — the AC13 whole-set `roadmap.md` assertion + narrowed to exclude the one documented deliberate drift alias (see "Reconciling + the deliberate dual-spelling fixture…"); the cycle diagnostic and `job_8` + untouched. - `tests/mutation.sh` (`stage_copy()` — one line). - Explicitly **not** touched here: `tests/README.md` and the mutation jobs (`0005-guard-registration-sweep`); `docs/**`, `AGENTS.md`, `template/**`, @@ -207,7 +263,15 @@ existing area selections stay green with no migration. declares `tests/README.md, tests/mutation.sh`; if this item's `design.md` declaration differed, the read-only check would report drift. — Likelihood medium / impact low / mitigation: declare the identical set in this design's - frontmatter (no self-reference, no duplicate). + frontmatter (no self-reference, no duplicate); the `80-cycle-fixture.sh` edit is + deliberately not declared because it is not a shared collision surface (see + "Reconciling the deliberate dual-spelling fixture…"). +- **The AC13 migration guard is weakened by the relaxation.** — Likelihood low / + impact medium / mitigation: exclude only the one exact documented deliberate + path; the remainder must still equal the retained cyclic alias, so any third or + stray alias still fails. T1's `Verify:` reintroduces a scratch third alias under + `tests/fixtures/` and confirms `80` fails naming `unexpected roadmap.md fixture + set`. - **Filename/prefix collision with a sibling guard authoring a check in parallel.** — Likelihood medium / impact low / mitigation: the name `89-integrity-guard.sh` is distinct; the two append-only registries are @@ -221,7 +285,7 @@ existing area selections stay green with no migration. literal scan over the whole fixture root; the constant lives only in the check. - **Whole-suite runs fail because the fixture is not staged.** — Likelihood high if forgotten / impact medium / mitigation: stage the root in - `tests/mutation.sh` (T7) and assert its presence (T6). + `tests/mutation.sh` (T8) and assert its presence (T7). - **The renumber assertion proves nothing if the fixture is empty.** — Likelihood low / impact medium / mitigation: assert new-reference presence in each enumerated rewrite position alongside old-reference absence. @@ -233,12 +297,12 @@ existing area selections stay green with no migration. | AC1 | integration — fixture-existence fails on a missing fixture; read-only contract | `AC30 fixture-existence` / `AC30 read-only-contract` in the area; full-suite run | | AC2 | integration — recursive analyzer over the depth-3 fixture | `AC30 per-node-eval` expected block | | AC3 | integration — graph-fault fixture | `AC30 structural-graph` expected block | -| AC4 | integration — dual-spelling and phase-mismatch fixtures | `AC30 spelling-drift` expected block | +| AC4 | integration — dual-spelling and phase-mismatch fixtures; the `80` AC13 whole-set assertion is narrowed so the dual-spelling fixture is permitted | `AC30 spelling-drift` expected block; `FRAMEWORK_TEST_AREAS=80-cycle-fixture bash tests/run.sh` green | | AC5 | integration — report-only contract pins + clean node | `AC30 report-only` | | AC6 | unit — header references + forbidden-literal scan | `AC30 no-duplication` | | AC7 | integration — completed-renumber fixture | `AC30 renumber-sweep` | | AC8 | manual-in-scratch + registered mutation (0005) | reintroduce an old ref in a scratch copy; area fails naming `renumber-sweep` | | AC9 | unit — authority/mirror intermediate-manifest pins | `AC30 renumber-sweep` | | AC10 | unit — token/sub-area labels + staged-copy assertion | all `AC30` labels; `AC30 mutation-staging` | -| AC11 | integration — full suite + no-duplication | `bash tests/run.sh` green; `AC30 no-duplication` | +| AC11 | integration — full suite + no-duplication | `bash tests/run.sh` green; `AC30 no-duplication`; `FRAMEWORK_TEST_AREAS=80-cycle-fixture` still green after the relaxation | | AC12 | manual — scope inspection of the diff | `git diff --name-only` limited to `tests/**` + this item | diff --git a/work/0015-recursive-workflow-guards/0004-recursive-integrity-guard/tasks.md b/work/0015-recursive-workflow-guards/0004-recursive-integrity-guard/tasks.md index 73c241a..c088ffe 100644 --- a/work/0015-recursive-workflow-guards/0004-recursive-integrity-guard/tasks.md +++ b/work/0015-recursive-workflow-guards/0004-recursive-integrity-guard/tasks.md @@ -11,22 +11,38 @@ parent: 0015-recursive-workflow-guards Ordered, dependency-aware. One task ≈ one focused commit. The exact check filename (`tests/checks/89-integrity-guard.sh`), fixture root -(`tests/fixtures/recursive-integrity/`), sub-area names, and the old/new renumber -constants are fixed by `design.md`; no task below re-decides them. +(`tests/fixtures/recursive-integrity/`), sub-area names, the old/new renumber +constants, and the `tests/checks/80-cycle-fixture.sh` AC13 relaxation are fixed by +`design.md`; no task below re-decides them. -- [ ] **T1** — Author the integrity fixture tree `tests/fixtures/recursive-integrity/items/`: `9201-clean` (clean node + `.gitkeep` leaf), `9202-graph-faults` (row `0002-missing` with no directory, `0003-dangling` with `Depends on 0099-ghost`, directory `0004-withdrawn` recorded as a withdrawal under `## Open issues`, directory `0005-unlisted` with no record), `9203-spelling-both` (`manifest.md` + `roadmap.md`), `9204-phase-mismatch` (`manifest.md` with `phase: roadmap`), the top-level prefix pair `9210-dup-a`/`9210-dup-b`, and the depth-3 collision `9211-deep/0001-mid/{0001-alpha,0001-beta}`. Use the six-column `Children` header and `manifest.md` `phase: manifest` exactly as `docs/artifact-conventions.md` defines. [AC2] [AC3] [AC4] - Verify: `bash tests/run.sh` exits 0 (nothing reads the fixture yet) and the fixture paths exist (`ls tests/fixtures/recursive-integrity/items/9202-graph-faults/` shows the four child dirs; `grep -c '^| 0' tests/fixtures/recursive-integrity/items/9202-graph-faults/manifest.md` shows the rows). -- [ ] **T2** — Author the renumber fixture `9220-renamed-parent/`: `manifest.md` with a `0002-new` row (Local id + Canonical reference `9220-renamed-parent/0002-new`) and a `0003-follower` row with `Depends on: 0002-new`; the intermediate `0002-new/manifest.md`; a descendant `0001-leaf/spec.md` carrying the new `feature:` and `parent:` values; `0003-follower/design.md` with `conflicts-with: 0002-new`; and `0003-follower/ship.md` recording a handoff path naming the new reference. The old local id `0001-old` and old canonical reference `9220-renamed-parent/0001-old` must appear nowhere in the fixture. [AC7] [depends: T1] +- [ ] **T1** — Narrow `tests/checks/80-cycle-fixture.sh`'s AC13 whole-set + `roadmap.md` assertion (`80-cycle-fixture.sh:61-71`): compute the stray-alias + set as `find tests/fixtures -name roadmap.md | grep -vxF + 'tests/fixtures/recursive-integrity/items/9203-spelling-both/roadmap.md'` and + keep the exact-equality comparison against the retained cyclic alias, + updating the explanatory comment to name the one documented deliberate + exception. Change no cycle-diagnostic assertion and no mutation job. [AC11] + [AC4] + Verify: `FRAMEWORK_TEST_AREAS=80-cycle-fixture bash tests/run.sh` exits 0; in + a scratch copy of `tests/` (never the repository) add a third + `tests/fixtures/scratch-third/roadmap.md` and confirm `80` fails naming + `unexpected roadmap.md fixture set`. +- [ ] **T2** — Author the integrity fixture tree `tests/fixtures/recursive-integrity/items/`: `9201-clean` (clean node + `.gitkeep` leaf), `9202-graph-faults` (row `0002-missing` with no directory, `0003-dangling` with `Depends on 0099-ghost`, directory `0004-withdrawn` recorded as a withdrawal under `## Open issues`, directory `0005-unlisted` with no record), `9203-spelling-both` (`manifest.md` + `roadmap.md`), `9204-phase-mismatch` (`manifest.md` with `phase: roadmap`), the top-level prefix pair `9210-dup-a`/`9210-dup-b`, and the depth-3 collision `9211-deep/0001-mid/{0001-alpha,0001-beta}`. Use the six-column `Children` header and `manifest.md` `phase: manifest` exactly as `docs/artifact-conventions.md` defines. [AC2] [AC3] [AC4] [depends: T1] + Verify: `bash tests/run.sh` exits 0 (the `80` relaxation keeps the migration + guard green with the dual-spelling fixture present) and the fixture paths + exist (`ls tests/fixtures/recursive-integrity/items/9202-graph-faults/` shows + the four child dirs; `grep -c '^| 0' tests/fixtures/recursive-integrity/items/9202-graph-faults/manifest.md` shows the rows). +- [ ] **T3** — Author the renumber fixture `9220-renamed-parent/`: `manifest.md` with a `0002-new` row (Local id + Canonical reference `9220-renamed-parent/0002-new`) and a `0003-follower` row with `Depends on: 0002-new`; the intermediate `0002-new/manifest.md`; a descendant `0001-leaf/spec.md` carrying the new `feature:` and `parent:` values; `0003-follower/design.md` with `conflicts-with: 0002-new`; and `0003-follower/ship.md` recording a handoff path naming the new reference. The old local id `0001-old` and old canonical reference `9220-renamed-parent/0001-old` must appear nowhere in the fixture. [AC7] [depends: T2] Verify: `bash tests/run.sh` exits 0 and `grep -rF '0001-old' tests/fixtures/recursive-integrity/` prints nothing (exit 1). -- [ ] **T3** — Create `tests/checks/89-integrity-guard.sh`: header (naming the areas deferred to), Bash 3.2-compatible helpers, and the recursive analyzer (`fig_manifest`, `fig_children_rows`, `fig_scan_node`, top-level prefix grouping) that emits normalized `CODE|offender[,offender]` findings into the three category blocks `fixture_duplicates`, `fixture_graph`, and `fixture_drift`; compare each against its reviewed expected block, labelled `AC30 per-node-eval`, `AC30 structural-graph`, and `AC30 spelling-drift`; assert the depth-3 collision is attributed to `9211-deep/0001-mid` and that `9202-graph-faults/0004-withdrawn` yields no `UNLISTED-CHILD` fault. [AC2] [AC3] [AC4] [depends: T1] +- [ ] **T4** — Create `tests/checks/89-integrity-guard.sh`: header (naming the areas deferred to), Bash 3.2-compatible helpers, and the recursive analyzer (`fig_manifest`, `fig_children_rows`, `fig_scan_node`, top-level prefix grouping) that emits normalized `CODE|offender[,offender]` findings into the three category blocks `fixture_duplicates`, `fixture_graph`, and `fixture_drift`; compare each against its reviewed expected block, labelled `AC30 per-node-eval`, `AC30 structural-graph`, and `AC30 spelling-drift`; assert the depth-3 collision is attributed to `9211-deep/0001-mid` and that `9202-graph-faults/0004-withdrawn` yields no `UNLISTED-CHILD` fault. [AC2] [AC3] [AC4] [depends: T2] Verify: `FRAMEWORK_TEST_AREAS=89-integrity-guard bash tests/run.sh` exits 0 and prints the three `AC30` labelled blocks with no `FAIL`. -- [ ] **T4** — Add the `report-only` sub-area: pin the non-fatal / never-truncated / not-auto-repaired / modifies-no-file contract on `docs/workflow.md` → "Merge-integrity guard" and the operational mirror `.opencode/skill/merge-conflict/SKILL.md`; assert the clean `9201-clean` node yields empty findings and does not error; and pin the recursive authority phrases (the invariant set is evaluated at every node; no node's check depends on another's; every node at every depth). Reference the pinned surfaces by path; restate no sibling literal. [AC5] [AC2] [depends: T3] +- [ ] **T5** — Add the `report-only` sub-area: pin the non-fatal / never-truncated / not-auto-repaired / modifies-no-file contract on `docs/workflow.md` → "Merge-integrity guard" and the operational mirror `.opencode/skill/merge-conflict/SKILL.md`; assert the clean `9201-clean` node yields empty findings and does not error; and pin the recursive authority phrases (the invariant set is evaluated at every node; no node's check depends on another's; every node at every depth). Reference the pinned surfaces by path; restate no sibling literal. [AC5] [AC2] [depends: T4] Verify: `FRAMEWORK_TEST_AREAS=89-integrity-guard bash tests/run.sh` exits 0 with the `AC30 report-only` lines present and passing. -- [ ] **T5** — Add the `renumber-sweep` sub-area: assert the fixture's new directory exists and contains the new reference in each enumerated rewrite position (directory, `feature:`, `parent:`, owning manifest `Local id`/`Canonical reference`, intermediate manifest `Canonical reference`, `Depends on`, `conflicts-with`, ship path), and assert by a recursive literal scan that the old local id and old canonical reference appear nowhere under `tests/fixtures/recursive-integrity/`; pin that `docs/artifact-conventions.md` and `.opencode/skill/merge-conflict/SKILL.md` name the intermediate manifest on the changed path, referencing `tests/checks/88-renumber-sweep.sh` by name and restating none of its literals. [AC7] [AC8] [AC9] [depends: T2] [depends: T3] +- [ ] **T6** — Add the `renumber-sweep` sub-area: assert the fixture's new directory exists and contains the new reference in each enumerated rewrite position (directory, `feature:`, `parent:`, owning manifest `Local id`/`Canonical reference`, intermediate manifest `Canonical reference`, `Depends on`, `conflicts-with`, ship path), and assert by a recursive literal scan that the old local id and old canonical reference appear nowhere under `tests/fixtures/recursive-integrity/`; pin that `docs/artifact-conventions.md` and `.opencode/skill/merge-conflict/SKILL.md` name the intermediate manifest on the changed path, referencing `tests/checks/88-renumber-sweep.sh` by name and restating none of its literals. [AC7] [AC8] [AC9] [depends: T3] [depends: T4] Verify: `FRAMEWORK_TEST_AREAS=89-integrity-guard bash tests/run.sh` exits 0 with the `AC30 renumber-sweep` lines passing. -- [ ] **T6** — Add the structural assertions: `fixture-existence` fails (never skips) when a required fixture file is missing; `read-only-contract` asserts the fixture references no live `work/` path and adds no committed executable checker; `mutation-staging` asserts `tests/mutation.sh`'s staged-copy list names `tests/fixtures/recursive-integrity`; `no-duplication` asserts the header references `10-readiness`, `20-lifecycle`, `80-cycle-fixture`, `85-conflict-guards`, `87-backtrack-guards`, `88-renumber-sweep`, `90-packaging`, `96-signature-sweep`, and the structure guard `0001-recursive-structure-guard` by name and re-asserts none of their owned literals. Every assertion carries the `AC30` token. [AC1] [AC6] [AC10] [AC11] [depends: T3] +- [ ] **T7** — Add the structural assertions: `fixture-existence` fails (never skips) when a required fixture file is missing; `read-only-contract` asserts the fixture references no live `work/` path and adds no committed executable checker; `mutation-staging` asserts `tests/mutation.sh`'s staged-copy list names `tests/fixtures/recursive-integrity`; `no-duplication` asserts the header references `10-readiness`, `20-lifecycle`, `80-cycle-fixture`, `85-conflict-guards`, `87-backtrack-guards`, `88-renumber-sweep`, `90-packaging`, `96-signature-sweep`, and the structure guard `0001-recursive-structure-guard` by name and re-asserts none of their owned literals. Every assertion carries the `AC30` token. [AC1] [AC6] [AC10] [AC11] [depends: T4] Verify: `FRAMEWORK_TEST_AREAS=89-integrity-guard bash tests/run.sh` exits 0 with the `fixture-existence`, `read-only-contract`, `mutation-staging`, and `no-duplication` lines present and passing. -- [ ] **T7** — Add the new fixture root to `tests/mutation.sh`'s `stage_copy()` as one additive `cp -R "$REPO_ROOT/tests/fixtures/recursive-integrity" "$copy/tests/fixtures/recursive-integrity"` line beside the existing fixture copies. Do not add mutation jobs or change `JOB_COUNT`; those remain `0005-guard-registration-sweep`'s. [AC10] [depends: T1] +- [ ] **T8** — Add the new fixture root to `tests/mutation.sh`'s `stage_copy()` as one additive `cp -R "$REPO_ROOT/tests/fixtures/recursive-integrity" "$copy/tests/fixtures/recursive-integrity"` line beside the existing fixture copies. Do not add mutation jobs or change `JOB_COUNT`; those remain `0005-guard-registration-sweep`'s. [AC10] [depends: T2] Verify: `bash tests/mutation.sh` exits 0 (the whole-suite clean copy passes with the fixture staged) and `grep -F 'recursive-integrity' tests/mutation.sh` matches the new line. -- [ ] **T8** — Run the full suite and prove the renumber assertion is sensitive and the scope is clean. [AC8] [AC11] [AC12] [depends: T5] [depends: T6] [depends: T7] - Verify: `bash tests/run.sh` exits 0 (all areas green); in a scratch copy of `tests/` (never the repository) reintroduce `9220-renamed-parent/0001-old` into one fixture file and run `FRAMEWORK_TEST_AREAS=89-integrity-guard bash tests/run.sh ` — it must exit non-zero and print a line containing `AC30 renumber-sweep`; and `git diff --name-only` lists only files under `tests/` plus this work item. +- [ ] **T9** — Run the full suite and prove the renumber assertion is sensitive and the scope is clean. [AC8] [AC11] [AC12] [depends: T5] [depends: T6] [depends: T7] [depends: T8] + Verify: `bash tests/run.sh` exits 0 (all areas green, including `80-cycle-fixture`); in a scratch copy of `tests/` (never the repository) reintroduce `9220-renamed-parent/0001-old` into one fixture file and run `FRAMEWORK_TEST_AREAS=89-integrity-guard bash tests/run.sh ` — it must exit non-zero and print a line containing `AC30 renumber-sweep`; and `git diff --name-only` lists only files under `tests/` plus this work item.