Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ conflicts-with: "tests/README.md, tests/mutation.sh"

## Summary

Add one new fixture-based agreement area, `tests/checks/89-integrity-guard.sh`
Add one new fixture-based agreement area, `tests/checks/91-integrity-guard.sh`
(suite token `AC30`), plus its committed fixture root
`tests/fixtures/recursive-integrity/`. The area reimplements, read-only, the
merge-integrity invariant evaluation as a genuine recursive scan over the fixture
Expand All @@ -27,13 +27,16 @@ 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, 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.
migration guard stays green with the dual-spelling fixture present. The area is
renamed off the collided `89-` numeric stem to the free `91-` stem so no two
merged areas share a selector prefix; the `AC30` token and sub-area labels are
unchanged (see "Renaming the area off the collided `89-` stem").

## Approach

### New agreement area

- **File.** `tests/checks/89-integrity-guard.sh`, sourced by the existing
- **File.** `tests/checks/91-integrity-guard.sh`, sourced by the existing
`tests/run.sh` glob (no `run.sh` edit), never calling `exit`, Bash 3.2
compatible (no associative arrays, no `mapfile`, no empty-array expansion under
`set -u`). It mirrors the structure of `tests/checks/85-conflict-guards.sh`
Expand Down Expand Up @@ -189,6 +192,43 @@ 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.

### Renaming the area off the collided `89-` stem

The merged default branch carries `tests/checks/89-recursive-status-guards.sh`
(the `0002` readiness/status guard). Two distinct agreement areas sharing the
`89-` prefix would make every prefix selector ambiguous — `tests/README.md` →
"Area selection" defines a prefix matching two or more areas as a setup error —
so this area takes the free stem `91-integrity-guard.sh` (verified against
`origin/main:tests/checks`: no `91-` area exists, and the merged sibling guards
occupy `81-`, `85-`, and `89-`). The rename keeps the suite token `AC30` and every
sub-area label unchanged, so it is invisible to `0005-guard-registration-sweep`'s
mapping and to any mutation job. This resolves the collision the review found
rather than deferring it; the earlier "only an area-selector ambiguity, not a
suite failure" acceptance was wrong, because the merged tree would leave the
documented `FRAMEWORK_TEST_AREAS=89` selector a setup error.

The rename sweeps **every** textual reference to the old stem — not only the
three the review named. The complete set, each rewritten `89-integrity-guard` →
`91-integrity-guard`:

- the new check file's own name (`tests/checks/91-integrity-guard.sh`);
- its `FIG_SELF="$FIG_CHECKS_DIR/91-integrity-guard.sh"` resolver;
- its `read-only-contract` self-reference scan
(`grep -rqF '91-integrity-guard' .opencode/`);
- its header comment naming the area;
- the AC13 cross-reference in `tests/checks/80-cycle-fixture.sh` (the deliberate
dual-spelling exception's owning area, `80-cycle-fixture.sh:66`); and
- the six fixture-prose references under `tests/fixtures/recursive-integrity/`
(`items/9201-clean/manifest.md`, `items/9220-renamed-parent/manifest.md`,
`items/9220-renamed-parent/0002-new/manifest.md`,
`items/9220-renamed-parent/0002-new/0001-leaf/spec.md`,
`items/9220-renamed-parent/0003-follower/design.md`, and
`items/9220-renamed-parent/0003-follower/ship.md`).

`T4` owns the rename and this sweep; its `Verify:` runs the area under the new
selector and asserts `grep -rF '89-integrity-guard' tests/` prints nothing, so a
leftover reference cannot survive green.

## Alternatives considered

- **A prose-only agreement check (pin the recursive authority phrases, no fixture
Expand Down Expand Up @@ -218,12 +258,21 @@ the two registries are where sibling plans actually collide.
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.
- **Defer the area rename to `0005-guard-registration-sweep` instead of renaming
it here.** Pros: leaves this item's stated check filename unchanged and touches
one fewer path. Cons: `0005`'s scope (`manifest.md:127`) is only the
`tests/README.md` Checks row/paragraph and the mutation jobs — it does not
include renaming this area's check — so deferral would leave two distinct areas
sharing the `89-` stem in the merged tree and the documented
`FRAMEWORK_TEST_AREAS=89` selector a setup error, i.e. an unresolved collision,
not a handled one. Rejected: the owning plan renames its own area (see
"Renaming the area off the collided `89-` stem").

## Interfaces and data model

- **New file** `tests/checks/89-integrity-guard.sh` — sourced, not executed; no
- **New file** `tests/checks/91-integrity-guard.sh` — sourced, not executed; no
`exit`; read-only; prints `ok`/`FAIL` lines labelled `AC30 <sub-area>`. Public
surface for `0005`: the area name `89-integrity-guard` and the sub-area labels.
surface for `0005`: the area name `91-integrity-guard` and the sub-area labels.
- **New fixture root** `tests/fixtures/recursive-integrity/` — root-local
`92xx` entity ids; item references resolve inside `items/`, never against live
`work/`.
Expand All @@ -246,7 +295,7 @@ fixture…"). No other area, fixture, selector, or harness behavior changes, so

## Affected areas

- `tests/checks/89-integrity-guard.sh` (new).
- `tests/checks/91-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
Expand All @@ -272,11 +321,19 @@ fixture…"). No other area, fixture, selector, or harness behavior changes, so
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
declared conflicts and the registration child reconciles; a duplicate `89`
prefix is only an area-selector ambiguity, not a suite failure.
- **Numeric-prefix collision with the merged sibling area.** — Likelihood low /
impact medium / mitigation: the area is renamed off the collided `89-` stem to
the free `91-integrity-guard.sh`, verified free against
`origin/main:tests/checks` (the sibling guards occupy `81-`, `85-`, and `89-`);
no two areas then share a numeric stem, so every prefix selector resolves
uniquely. The `AC30` token and sub-area labels are unchanged, and the two
append-only registries (`tests/README.md`, `tests/mutation.sh`) stay declared
conflicts reconciled by `0005`.
- **A leftover `89-integrity-guard` reference survives the rename.** —
Likelihood low / impact low / mitigation: `T4` sweeps every enumerated site
(see "Renaming the area off the collided `89-` stem") and its `Verify:` asserts
`grep -rF '89-integrity-guard' tests/` prints nothing, so a stale reference
cannot survive green.
- **Fixture/analyzer not Bash 3.2 compatible.** — Likelihood low / impact high /
mitigation: no associative arrays, no `mapfile`, no empty-array expansion under
`set -u`; mirror the shipped `85`/`87` helpers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ parent: 0015-recursive-workflow-guards
# Tasks — Committed recursive merge-integrity and renumber guards

Ordered, dependency-aware. One task ≈ one focused commit. The exact check
filename (`tests/checks/89-integrity-guard.sh`), fixture root
filename (`tests/checks/91-integrity-guard.sh`), fixture root
(`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.
`design.md`; no task below re-decides them. The area is renamed off the collided
`89-` stem to the free `91-` stem (see `design.md` → "Renaming the area off the
collided `89-` stem"); `T4` owns the rename and the full reference sweep, so
`T5`–`T7` and `T9` (whose `Verify:` names the area) are re-opened, while `T1`–`T3`
and `T8` stay checked — their substantive deliverables are unchanged and `T4`
sweeps the incidental area references in `T1`–`T3`'s files.

- [ ] **T1** — Narrow `tests/checks/80-cycle-fixture.sh`'s AC13 whole-set
- [x] **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
Expand All @@ -27,22 +32,22 @@ constants, and the `tests/checks/80-cycle-fixture.sh` AC13 relaxation are fixed
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]
- [x] **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]
- [x] **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).
- [ ] **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** — Rename the area to `tests/checks/91-integrity-guard.sh` (off the collided `89-` stem) and sweep every reference: `mv tests/checks/89-integrity-guard.sh tests/checks/91-integrity-guard.sh`; set `FIG_SELF="$FIG_CHECKS_DIR/91-integrity-guard.sh"`; change the `.opencode/` self-reference scan literal to `91-integrity-guard`; update the header comment; and rewrite the remaining `89-integrity-guard` references — the `tests/checks/80-cycle-fixture.sh` AC13 cross-reference (`80-cycle-fixture.sh:66`) and the six fixture-prose references under `tests/fixtures/recursive-integrity/` — enumerated in `design.md` → "Renaming the area off the collided `89-` stem". Keep the header (naming the areas deferred to), the 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=91-integrity-guard bash tests/run.sh` exits 0 and prints the three `AC30` labelled blocks with no `FAIL`; `grep -rF '89-integrity-guard' tests/` prints nothing.
- [ ] **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.
Verify: `FRAMEWORK_TEST_AREAS=91-integrity-guard bash tests/run.sh` exits 0 with the `AC30 report-only` lines present and passing.
- [ ] **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.
Verify: `FRAMEWORK_TEST_AREAS=91-integrity-guard bash tests/run.sh` exits 0 with the `AC30 renumber-sweep` lines passing.
- [ ] **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.
- [ ] **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: `FRAMEWORK_TEST_AREAS=91-integrity-guard bash tests/run.sh` exits 0 with the `fixture-existence`, `read-only-contract`, `mutation-staging`, and `no-duplication` lines present and passing.
- [x] **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.
- [ ] **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 <scratch-root>` — 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.
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=91-integrity-guard bash tests/run.sh <scratch-root>` — 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.
Loading