test(#3309): update stale W002/W020 test expectations to match the fixes

Both tests were written against the pre-fix behavior and never updated
once the real fixes landed:

- state-consistency.test.cjs's "KNOWN GAP" test hardcoded the
  expectation that W002 incorrectly fires for a STATE.md phase
  reference whose only home is an archived milestone — that gap is
  now closed (0 diagnostics, confirmed against real buildPlanningSnapshot
  output), so the test is renamed and its expectation flipped.
- worktree-health.test.cjs's two W020 tests asserted the OLD single
  combined "timed out or failed" message/remedy — verified against
  the real pre-migration src/verify.cts:2204-2219 that git_timed_out
  and git_list_failed always had distinct messages; the fix that
  restored this distinction is correct, these tests just never
  caught up to it.
This commit is contained in:
sim
2026-08-13 04:53:08 -04:00
parent 7ddcc19823
commit ce0999bf84
2 changed files with 31 additions and 23 deletions

View File

@@ -208,12 +208,11 @@ describe('W002 — STATE.md references a phase not declared on disk or ROADMAP',
assert.deepEqual(ruleFor('W002').check(snapshot), []);
});
// KNOWN GAP (implementer report): archived-phase-token coverage
// (`forEachArchivedPhaseToken`) is not in any PlanningSnapshot field, so a
// STATE.md reference to a phase that lives only in a milestone archive is
// reported as undeclared here, unlike the original `verify.cts` check.
// Documents the gap rather than silently absorbing it.
test('KNOWN GAP: fires on a phase reference whose only home is an archived milestone (not modeled by any snapshot field)', (t) => {
// `snapshot.archivedPhaseTokens` (#3652) now covers archived-milestone
// phase-dir tokens, so `buildValidPhaseSet` includes them — a STATE.md
// reference to a phase whose only home is an archived milestone is
// correctly treated as declared and does NOT fire.
test('does not fire on a phase reference whose only home is an archived milestone', (t) => {
const cwd = createTempDir('gsd-3309-w002-4-');
t.after(() => cleanup(cwd));
writeRoadmap(cwd, '## v2.0 Current 🚧\n\n### Phase 3: Baz\n');
@@ -232,15 +231,14 @@ describe('W002 — STATE.md references a phase not declared on disk or ROADMAP',
'',
'### Decisions',
'',
'- Phase 1: this phase is archived, not currently exposed by any snapshot field',
'- Phase 1: this phase is archived, covered by snapshot.archivedPhaseTokens',
'',
].join('\n'),
);
const snapshot = buildPlanningSnapshot(cwd);
const diagnostics = ruleFor('W002').check(snapshot);
assert.equal(diagnostics.length, 1);
assert.match(diagnostics[0].message, /STATE\.md references phase 1,/);
assert.deepEqual(diagnostics, []);
});
});

View File

@@ -122,7 +122,7 @@ describe('RULES (worktree-health group)', () => {
// ─── W020 — worktree health scan itself is degraded ────────────────────────
describe('W020 — worktree health scan degraded', () => {
test('fires the combined scan-degraded message when git worktree list times out', (t) => {
test('fires the git_timed_out-specific scan-degraded message when git worktree list times out', (t) => {
const cwd = createTempDir('gsd-3309-w020-timeout-');
t.after(() => cleanup(cwd));
fs.mkdirSync(planningDirOf(cwd), { recursive: true });
@@ -136,25 +136,25 @@ describe('W020 — worktree health scan degraded', () => {
code: 'W020',
severity: SEVERITY.WARNING,
message:
'Worktree health check degraded: git worktree list timed out or failed — orphan/stale worktrees could not be inspected',
'Worktree health check degraded: git worktree list timed out after 10s — orphan/stale worktrees could not be inspected',
remedy: {
action: REMEDY_ACTION.ADVISE,
risk: REMEDY_RISK.NONE,
args: {
command:
'Run: git worktree list --porcelain to diagnose; check for .git/index.lock, a hung git process, or repository permissions',
'Run: git worktree list --porcelain to diagnose; check for .git/index.lock or a hung git process',
},
},
});
});
// GAP (documented in the rule module's own header comment, gap 1):
// `buildWorktreeHealthField` discards `inspectWorktreeHealth`'s `reason`
// field ('git_timed_out' vs 'git_list_failed'), so the snapshot alone
// cannot distinguish a timeout from an outright failure. This rule
// therefore fires the IDENTICAL combined message for both — asserted
// explicitly here, per §8.5 fixture-proof, rather than left undocumented.
test('GAP: fires the SAME combined message when git worktree list fails outright (not a timeout) — scope alone cannot distinguish', (t) => {
// `inspectWorktreeHealth`'s `reason` field ('git_timed_out' vs
// 'git_list_failed') is carried straight through on
// `PlanningSnapshot.worktreeHealth` (`planning-snapshot.cts`'s
// `buildWorktreeHealthField`), so `checkW020` distinguishes the two scan
// failures with distinct messages/remedies (verify.cts:2204-2219) — this
// asserts the git_list_failed-specific one.
test('fires the git_list_failed-specific message when git worktree list fails outright (not a timeout)', (t) => {
const cwd = createTempDir('gsd-3309-w020-failed-');
t.after(() => cleanup(cwd));
fs.mkdirSync(planningDirOf(cwd), { recursive: true });
@@ -164,10 +164,20 @@ describe('W020 — worktree health scan degraded', () => {
const diagnostics = ruleFor('W020').check(snapshot);
assert.equal(diagnostics.length, 1);
assert.equal(
diagnostics[0].message,
'Worktree health check degraded: git worktree list timed out or failed — orphan/stale worktrees could not be inspected',
);
assert.deepEqual(diagnostics[0], {
code: 'W020',
severity: SEVERITY.WARNING,
message:
'Worktree health check degraded: git worktree list failed — orphan/stale worktrees could not be inspected',
remedy: {
action: REMEDY_ACTION.ADVISE,
risk: REMEDY_RISK.NONE,
args: {
command:
'Run: git worktree list --porcelain to diagnose; check git repository state and permissions',
},
},
});
});
test('fires once per unverified finding — exact port of verify.cts:2256-2263', (t) => {