fix(tests): invalidate path cache between deriveState calls that expect fresh disk state
Tests that write files and immediately call deriveState() got stale results because the path resolution cache (dirEntryCache/dirListCache) returned cached directory listings that didn't include newly written files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1b6fdd6aa6
commit
d7faf8a4e5
4 changed files with 14 additions and 1 deletions
|
|
@ -3,6 +3,7 @@ import { join, dirname } from "node:path";
|
|||
import { tmpdir } from "node:os";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createTestContext } from './test-helpers.ts';
|
||||
import { clearPathCache } from '../paths.ts';
|
||||
|
||||
// loadPrompt reads from ~/.gsd/agent/extensions/gsd/prompts/ (main checkout).
|
||||
// In a worktree the file may not exist there yet, so we resolve prompts
|
||||
|
|
@ -179,6 +180,7 @@ async function main(): Promise<void> {
|
|||
|
||||
// Now add the summary and verify it transitions to complete
|
||||
writeMilestoneSummary(base, "M001", "# M001 Summary\n\nDone.");
|
||||
clearPathCache();
|
||||
const stateAfter = await deriveState(base);
|
||||
assertEq(stateAfter.phase, "complete", "deriveState returns complete after summary exists");
|
||||
assertEq(stateAfter.registry[0]?.status, "complete", "registry shows complete status");
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { join } from "node:path";
|
|||
import { tmpdir } from "node:os";
|
||||
|
||||
import { deriveState } from "../state.js";
|
||||
import { resolveMilestoneFile } from "../paths.js";
|
||||
import { resolveMilestoneFile, clearPathCache } from "../paths.js";
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
|
@ -40,6 +40,7 @@ assert(
|
|||
const contextPath = join(gsd, "milestones", "M001", "M001-CONTEXT.md");
|
||||
writeFileSync(contextPath, "# M001: Full Context\n\nDeep discussion output.\n");
|
||||
|
||||
clearPathCache();
|
||||
const state2 = await deriveState(tmpBase);
|
||||
assert(
|
||||
state2.phase === "pre-planning",
|
||||
|
|
@ -65,6 +66,7 @@ assert(
|
|||
);
|
||||
|
||||
// Step 4: After cleanup, state is still pre-planning (CONTEXT.md exists)
|
||||
clearPathCache();
|
||||
const state3 = await deriveState(tmpBase);
|
||||
assert(
|
||||
state3.phase === "pre-planning",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import {
|
|||
parseSliceBranch,
|
||||
switchToMain,
|
||||
} from '../worktree.ts';
|
||||
import { clearPathCache } from '../paths.ts';
|
||||
import { createTestContext } from './test-helpers.ts';
|
||||
|
||||
// ─── Assertion Helpers ────────────────────────────────────────────────────
|
||||
|
|
@ -437,6 +438,7 @@ Built the legacy feature successfully.
|
|||
`);
|
||||
run('git add .', base);
|
||||
run('git commit -m add-m001', base);
|
||||
clearPathCache();
|
||||
|
||||
// M001 (seq=1) < M001-abc123 (seq=1) — but M001 has incomplete S02
|
||||
// Since M001 seq=1 and M002-abc123 seq=2, blocker should reference M001/S02
|
||||
|
|
@ -459,6 +461,7 @@ Built the legacy feature successfully.
|
|||
`);
|
||||
run('git add .', base);
|
||||
run('git commit -m complete-m001', base);
|
||||
clearPathCache();
|
||||
|
||||
assertEq(
|
||||
getPriorSliceCompletionBlocker(base, 'main', 'plan-slice', 'M002-abc123/S01'),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
readUnitRuntimeRecord,
|
||||
writeUnitRuntimeRecord,
|
||||
} from "../unit-runtime.ts";
|
||||
import { clearPathCache } from '../paths.ts';
|
||||
import { createTestContext } from './test-helpers.ts';
|
||||
|
||||
const { assertEq, assertTrue, report } = createTestContext();
|
||||
|
|
@ -48,6 +49,7 @@ console.log("\n=== execute-task durability inspection ===");
|
|||
"utf-8",
|
||||
);
|
||||
writeFileSync(join(base, ".gsd", "STATE.md"), "## Next Action\nExecute T10 for S02: next thing\n", "utf-8");
|
||||
clearPathCache();
|
||||
|
||||
status = await inspectExecuteTaskDurability(base, "M100/S02/T09");
|
||||
assertEq(status!.summaryExists, true, "summary found after write");
|
||||
|
|
@ -128,6 +130,7 @@ console.log("\n=== must-haves: partially mentioned in summary ===");
|
|||
);
|
||||
writeFileSync(join(mhBase, ".gsd", "STATE.md"), "## Next Action\nExecute T02 for S02: next thing\n", "utf-8");
|
||||
|
||||
clearPathCache();
|
||||
const status = await inspectExecuteTaskDurability(mhBase, "M200/S02/T01");
|
||||
assertTrue(status !== null, "mh-partial: status exists");
|
||||
assertEq(status!.mustHaveCount, 3, "mh-partial: mustHaveCount is 3");
|
||||
|
|
@ -155,6 +158,7 @@ console.log("\n=== must-haves: no task plan file ===");
|
|||
);
|
||||
writeFileSync(join(mhBase, ".gsd", "STATE.md"), "## Next Action\nExecute T02 for S03: next thing\n", "utf-8");
|
||||
|
||||
clearPathCache();
|
||||
const status = await inspectExecuteTaskDurability(mhBase, "M200/S03/T01");
|
||||
assertTrue(status !== null, "mh-noplan: status exists");
|
||||
assertEq(status!.mustHaveCount, 0, "mh-noplan: mustHaveCount is 0 when no task plan");
|
||||
|
|
@ -179,6 +183,7 @@ console.log("\n=== must-haves: present but no summary file ===");
|
|||
);
|
||||
writeFileSync(join(mhBase, ".gsd", "STATE.md"), "## Next Action\nExecute T01 for S04: build parser\n", "utf-8");
|
||||
|
||||
clearPathCache();
|
||||
const status = await inspectExecuteTaskDurability(mhBase, "M200/S04/T01");
|
||||
assertTrue(status !== null, "mh-nosummary: status exists");
|
||||
assertEq(status!.mustHaveCount, 2, "mh-nosummary: mustHaveCount is 2");
|
||||
|
|
@ -210,6 +215,7 @@ console.log("\n=== must-haves: substring matching (no backtick tokens) ===");
|
|||
);
|
||||
writeFileSync(join(mhBase, ".gsd", "STATE.md"), "## Next Action\nExecute T02 for S05: next thing\n", "utf-8");
|
||||
|
||||
clearPathCache();
|
||||
const status = await inspectExecuteTaskDurability(mhBase, "M200/S05/T01");
|
||||
assertTrue(status !== null, "mh-substr: status exists");
|
||||
assertEq(status!.mustHaveCount, 3, "mh-substr: mustHaveCount is 3");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue