From 9ed543f1c8bd334ac02d5597f0cb77532376e1f9 Mon Sep 17 00:00:00 2001 From: mastertyko <11311479+mastertyko@users.noreply.github.com> Date: Thu, 9 Apr 2026 21:25:37 +0200 Subject: [PATCH] fix(gsd): resync managed resources on auto resume --- src/resources/extensions/gsd/auto.ts | 7 ++++++- .../gsd/tests/cold-resume-db-reopen.test.ts | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/resources/extensions/gsd/auto.ts b/src/resources/extensions/gsd/auto.ts index 54f8b4da5..089ae11aa 100644 --- a/src/resources/extensions/gsd/auto.ts +++ b/src/resources/extensions/gsd/auto.ts @@ -118,6 +118,7 @@ import { formatTokenCount, } from "./metrics.js"; import { setLogBasePath, logWarning, logError } from "./workflow-logger.js"; +import { homedir } from "node:os"; import { join } from "node:path"; import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs"; import { atomicWriteSync } from "./atomic-write.js"; @@ -1248,6 +1249,11 @@ export async function startAuto( "info", ); restoreHookState(s.basePath); + // Re-sync managed resources on resume so long-lived auto sessions pick up + // bundled extension updates before resume-time verification/state logic runs. + const agentDir = process.env.GSD_CODING_AGENT_DIR || join(process.env.GSD_HOME || homedir(), ".gsd", "agent"); + const { initResources } = await import("../../../" + "resource-loader.js"); + initResources(agentDir); // Open the project DB before rebuild/derive so resume uses DB-backed // state instead of falling back to stale markdown parsing (#2940). await openProjectDbIfPresent(s.basePath); @@ -1569,4 +1575,3 @@ export { buildLoopRemediationSteps, } from "./auto-recovery.js"; export { resolveExpectedArtifactPath } from "./auto-artifact-paths.js"; - diff --git a/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts b/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts index ae31af280..7f4806424 100644 --- a/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +++ b/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts @@ -18,22 +18,33 @@ const { assertTrue, report } = createTestContext(); const autoSrc = readFileSync(join(import.meta.dirname, "..", "auto.ts"), "utf-8"); -console.log("\n=== #2940: resume path opens DB before rebuildState/deriveState ==="); +console.log("\n=== resume path refreshes resources and opens DB before rebuildState/deriveState ==="); // The resume block is the `if (s.paused) { ... }` section that calls rebuildState/deriveState. // Locate the resume section by finding `s.paused = false;` followed by `rebuildState`. const resumeSectionStart = autoSrc.indexOf("if (s.paused) {", autoSrc.indexOf("// If resuming from paused state")); assertTrue(resumeSectionStart > 0, "auto.ts has the paused-session resume block"); -const resumeSection = autoSrc.slice(resumeSectionStart, resumeSectionStart + 3000); +const resumeSectionEnd = autoSrc.indexOf("await autoLoop(", resumeSectionStart); +assertTrue(resumeSectionEnd > resumeSectionStart, "resume block reaches autoLoop"); -// The resume path must open the DB before rebuildState/deriveState +const resumeSection = autoSrc.slice(resumeSectionStart, resumeSectionEnd); + +// The resume path must refresh managed resources and open the DB before +// rebuildState/deriveState so resumed auto-mode uses current extension code. const rebuildIdx = resumeSection.indexOf("rebuildState("); assertTrue(rebuildIdx > 0, "resume block calls rebuildState"); const deriveIdx = resumeSection.indexOf("deriveState("); assertTrue(deriveIdx > 0, "resume block calls deriveState"); +const preDeriveSection = resumeSection.slice(0, rebuildIdx); + +assertTrue( + preDeriveSection.includes("initResources("), + "resume path must refresh managed resources before rebuildState/deriveState (#3761)", +); + // There must be a DB open call before the first rebuildState call const dbOpenPatterns = [ "openProjectDbIfPresent(", @@ -41,7 +52,6 @@ const dbOpenPatterns = [ "ensureDbOpen(", ]; -const preDeriveSection = resumeSection.slice(0, rebuildIdx); const hasDbOpen = dbOpenPatterns.some(pat => preDeriveSection.includes(pat)); assertTrue( hasDbOpen,