fix(auto): clear parse and path caches alongside state cache

Ensures auto-mode reads fresh file data after unit completion,
slice merges, and self-healing — prevents stale cached parses
from the memoized deriveState pipeline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lex Christopherson 2026-03-14 17:02:32 -06:00
parent 1b5b413eb1
commit 9c82a1b79f

View file

@ -18,7 +18,7 @@ import type {
import { deriveState, invalidateStateCache } from "./state.js";
import type { GSDState } from "./types.js";
import { loadFile, parseContinue, parsePlan, parseRoadmap, parseSummary, extractUatType, inlinePriorMilestoneSummary, getManifestStatus } from "./files.js";
import { loadFile, parseContinue, parsePlan, parseRoadmap, parseSummary, extractUatType, inlinePriorMilestoneSummary, getManifestStatus, clearParseCache } from "./files.js";
export { inlinePriorMilestoneSummary };
import type { UatType } from "./files.js";
import { collectSecretsFromManifest } from "../get-secrets-from-user.js";
@ -29,6 +29,7 @@ import {
relMilestoneFile, relSliceFile, relTaskFile, relSlicePath, relMilestonePath,
milestonesDir, resolveGsdRootFile, relGsdRootFile,
buildMilestoneFileName, buildSliceFileName, buildTaskFileName,
clearPathCache,
} from "./paths.js";
import { saveActivityLog } from "./activity-log.js";
import { synthesizeCrashRecovery, getDeepDiagnostic } from "./session-forensics.js";
@ -575,6 +576,8 @@ export async function startAuto(
// Self-heal: clear stale runtime records where artifacts already exist
await selfHealRuntimeRecords(base, ctx);
invalidateStateCache();
clearParseCache();
clearPathCache();
await dispatchNextUnit(ctx, pi);
return;
}
@ -767,6 +770,8 @@ export async function handleAgentEnd(
// Invalidate deriveState() cache — the unit just completed and may have
// written planning files (task summaries, roadmap checkboxes, etc.)
invalidateStateCache();
clearParseCache();
clearPathCache();
// Small delay to let files settle (git commits, file writes)
await new Promise(r => setTimeout(r, 500));
@ -1338,6 +1343,8 @@ async function dispatchNextUnit(
}
// Re-derive state from the now-merged working tree
invalidateStateCache();
clearParseCache();
clearPathCache();
state = await deriveState(basePath);
mid = state.activeMilestone?.id;
midTitle = state.activeMilestone?.title;
@ -1403,6 +1410,8 @@ async function dispatchNextUnit(
);
// Re-derive state from main so downstream logic sees merged state
invalidateStateCache();
clearParseCache();
clearPathCache();
state = await deriveState(basePath);
mid = state.activeMilestone?.id;
midTitle = state.activeMilestone?.title;