diff --git a/openspec/changes/spec-anchors-name-the-capability/proposal.md b/openspec/changes/spec-anchors-name-the-capability/proposal.md index 59118eff1..41da068d5 100644 --- a/openspec/changes/spec-anchors-name-the-capability/proposal.md +++ b/openspec/changes/spec-anchors-name-the-capability/proposal.md @@ -91,6 +91,31 @@ same backlog, so `git log origin/development -5 -- ` comes before building not after. This branch went out CONFLICTING with 4 of 49 checks green, which is the shape a conflicting PR always has. +## The correction this change had to make to itself + +The first version of this proposal claimed 6,244 anchors and zero unresolvable. +That was measured with a REIMPLEMENTATION of the resolver rather than the +resolver, and it was wrong in both directions. + +Mine ignored two things the real one does. The flat `openspec/specs/.md` +spelling, which predates the directory form: that alone made it call 13 of +planix's healthy anchors dangling. And fragment checking: the real helper +verifies that a `#fragment` names a heading somebody wrote, and mine only +checked the file. + +Run properly, this repo has **28 unresolved `@e2e` anchors**, every one of them +"anchor not found". Two of the 28 were broken by this session's own #2057, which +renumbered two scenarios from `DASH-V1-006d/e` to `006f/g` to clear a collision +and left two `@e2e` citations naming the old ids. Every check passed. Those two +are repointed here; the other 26 are pre-existing and are the debt the gate fix +in "Not in this change" would surface. + +The lesson is the one this whole investigation keeps teaching: every wrong +number came from a hand-rolled resolver, and every right one came from running +`check_spec_anchors.py`. `@e2e` was eventually measured by rewriting the tags to +`@spec` in a probe file OUTSIDE the repo and running the real helper with cwd set +to the app, which is exact and touches nothing. + ## Not in this change - **Gate 46 does not read `@e2e`.** Its pattern is `@spec\s+(openspec/...)`, so @@ -100,4 +125,6 @@ the shape a conflicting PR always has. `scripts/` are never opened. Both live in `ConductionNL/.github`, `hydra-gates/scripts/lib/check_spec_anchors.py`, -and neither is fixable here. +and neither is fixable here. Filed as ConductionNL/.github#726 (1,964 `@e2e` +anchors fleet-wide, 194 dangling) and #727 (52 anchors under `appinfo/` and +`scripts/` never opened, 8 of openregister's 9 in `routes.php` dangling). diff --git a/openspec/changes/spec-anchors-name-the-capability/tasks.md b/openspec/changes/spec-anchors-name-the-capability/tasks.md index 645867f49..6baf875dc 100644 --- a/openspec/changes/spec-anchors-name-the-capability/tasks.md +++ b/openspec/changes/spec-anchors-name-the-capability/tasks.md @@ -42,16 +42,44 @@ ## 4. Raise upstream, not here -- [ ] 4.1 Gate 46 reads only `@spec`. Its pattern is `@spec\s+(openspec/...)`, +- [x] 4.1 Filed as ConductionNL/.github#726. Gate 46 reads only `@spec`. Its pattern is `@spec\s+(openspec/...)`, so 286 `@e2e` anchors in this repo are checked by nothing. This is why the six were found by hand, twice, rather than by CI once. Belongs in `ConductionNL/.github`, `hydra-gates/scripts/lib/check_spec_anchors.py`. -- [ ] 4.2 Gate 46 enumerates `lib src tests`. Two anchors under `appinfo/` and +- [x] 4.2 Filed as ConductionNL/.github#727. Gate 46 enumerates `lib src tests`. Two anchors under `appinfo/` and `scripts/` are never opened. Same helper. -## 5. Process, recorded because it cost a branch +## 5. The claim this change first made was wrong, twice over -- [x] 5.1 Search before building. `git log origin/development -5 -- ` comes +- [x] 5.1 "6,244 anchors, zero unresolvable" was measured with a REIMPLEMENTATION + of the resolver, not the resolver. Mine ignored two things the real one does: + the flat `openspec/specs/.md` spelling, and fragment checking. It called + 13 of planix's anchors dangling that are fine, and it called 28 of this repo's + `@e2e` anchors fine that are not. + - the real resolver, run over all 284 `@e2e` targets here, reports 28 + unresolved. Every one is "anchor not found": the file resolves and the + `#fragment` names a heading nobody wrote. +- [x] 5.2 Two of the 28 were broken by this session's own #2057, and nothing + caught it. + - #2057 renumbered the kanban delta's scenarios from `DASH-V1-006d/e` to + `006f/g` to clear a collision with two scenarios the spec already had. + `tests/e2e/spec-coverage/kanban-board-keyboard-status-transition.spec.ts` + still cited `006d` and `006e`. Gate 46 did not look, because they are `@e2e`. + Repointed at the canonical `openspec/specs/dashboard/spec.md` per the rule + this change writes down. +- [ ] 5.3 The other 26 are pre-existing dossiq debt that the gate fix in section + 4 would surface on the next PR touching those files. Not fixed here: each one + needs a judgement about which scenario it meant, which is the work, not the + sed. +- [x] 5.4 Stop reimplementing the instrument. Every wrong number in this + investigation came from a hand-rolled resolver; every correct one came from + running `check_spec_anchors.py`. `@e2e` was measured by rewriting the tags to + `@spec` in a probe file outside the repo and running the real helper against + it, which is how the fleet numbers in section 4 were taken. + +## 6. Process, recorded because it cost a branch + +- [x] 6.1 Search before building. `git log origin/development -5 -- ` comes first: two PRs on this exact topic landed while this branch was being written, and the PR went out CONFLICTING with 4 of 49 checks passing, which is the shape a conflicting PR always has and reads green. diff --git a/tests/e2e/spec-coverage/kanban-board-keyboard-status-transition.spec.ts b/tests/e2e/spec-coverage/kanban-board-keyboard-status-transition.spec.ts index 46000ced7..a28a73559 100644 --- a/tests/e2e/spec-coverage/kanban-board-keyboard-status-transition.spec.ts +++ b/tests/e2e/spec-coverage/kanban-board-keyboard-status-transition.spec.ts @@ -142,7 +142,7 @@ test.describe('Workflow Board keyboard status transition', () => { return card } - // @e2e openspec/changes/archive/2026-09-09-kanban-board-keyboard-status-transition/specs/dashboard/spec.md#scenario-dash-v1-006d-keyboard-only-status-transition-new + // @e2e openspec/specs/dashboard/spec.md#scenario-dash-v1-006f-keyboard-only-status-transition-new test('a case card exposes a keyboard-operable "Move to…" menu', async ({ page, }) => { @@ -171,7 +171,7 @@ test.describe('Workflow Board keyboard status transition', () => { await page.keyboard.press('Escape') }) - // @e2e openspec/changes/archive/2026-09-09-kanban-board-keyboard-status-transition/specs/dashboard/spec.md#scenario-dash-v1-006e-drag-path-unchanged-new + // @e2e openspec/specs/dashboard/spec.md#scenario-dash-v1-006g-drag-path-unchanged-new test('case cards remain draggable for mouse/touch users', async ({ page }) => { const card = await openBoardAndFindSeededCard(page) await expect(card).toHaveAttribute('draggable', 'true')