fix(gsd): open DB before bootstrap deriveState

This commit is contained in:
mastertyko 2026-04-09 17:45:46 +02:00
parent 335535b506
commit fe7e20a116
3 changed files with 48 additions and 0 deletions

View file

@ -117,6 +117,8 @@ export function registerHooks(pi: ExtensionAPI): void {
return { cancel: true };
}
const basePath = process.cwd();
const { ensureDbOpen } = await import("./dynamic-tools.js");
await ensureDbOpen();
const state = await deriveState(basePath);
if (!state.activeMilestone || !state.activeSlice || !state.activeTask) return;
if (state.phase !== "executing") return;

View file

@ -289,6 +289,11 @@ function buildWorktreeContextBlock(): string {
const RESUME_INTENT_PATTERNS = /^(continue|resume|ok|go|go ahead|proceed|keep going|carry on|next|yes|yeah|yep|sure|do it|let's go|pick up where you left off)$/;
async function buildGuidedExecuteContextInjection(prompt: string, basePath: string): Promise<string | null> {
const ensureStateDbOpen = async () => {
const { ensureDbOpen } = await import("./dynamic-tools.js");
await ensureDbOpen();
};
const executeMatch = prompt.match(/Execute the next task:\s+(T\d+)\s+\("([^"]+)"\)\s+in slice\s+(S\d+)\s+of milestone\s+(M\d+(?:-[a-z0-9]{6})?)/i);
if (executeMatch) {
const [, taskId, taskTitle, sliceId, milestoneId] = executeMatch;
@ -298,6 +303,7 @@ async function buildGuidedExecuteContextInjection(prompt: string, basePath: stri
const resumeMatch = prompt.match(/Resume interrupted work\.[\s\S]*?slice\s+(S\d+)\s+of milestone\s+(M\d+(?:-[a-z0-9]{6})?)/i);
if (resumeMatch) {
const [, sliceId, milestoneId] = resumeMatch;
await ensureStateDbOpen();
const state = await deriveState(basePath);
if (state.activeMilestone?.id === milestoneId && state.activeSlice?.id === sliceId && state.activeTask) {
return buildTaskExecutionContextInjection(basePath, milestoneId, sliceId, state.activeTask.id, state.activeTask.title);
@ -313,6 +319,7 @@ async function buildGuidedExecuteContextInjection(prompt: string, basePath: stri
// replanning, gate evaluation, or other non-execution phases.
const trimmed = prompt.trim().toLowerCase().replace(/[.!?,]+$/g, "");
if (RESUME_INTENT_PATTERNS.test(trimmed)) {
await ensureStateDbOpen();
const state = await deriveState(basePath);
if (state.phase === "executing" && state.activeTask && state.activeMilestone && state.activeSlice) {
return buildTaskExecutionContextInjection(

View file

@ -0,0 +1,39 @@
import { describe, test } from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { join } from "node:path";
const systemContextSrc = readFileSync(
join(import.meta.dirname, "..", "bootstrap", "system-context.ts"),
"utf-8",
);
const registerHooksSrc = readFileSync(
join(import.meta.dirname, "..", "bootstrap", "register-hooks.ts"),
"utf-8",
);
describe("bootstrap deriveState DB guards (#3844)", () => {
test("system-context opens DB before deriveState in resume flows", () => {
const helperIdx = systemContextSrc.indexOf("const ensureStateDbOpen = async () => {");
const firstDeriveIdx = systemContextSrc.indexOf("const state = await deriveState(basePath);");
assert.ok(helperIdx > -1, "system-context should define a DB-open helper for deriveState callers");
assert.ok(firstDeriveIdx > -1, "system-context should still derive state for resume flows");
assert.ok(helperIdx < firstDeriveIdx, "system-context should prepare DB opening before deriveState resume calls");
assert.match(
systemContextSrc,
/await ensureStateDbOpen\(\);\s*\n\s*const state = await deriveState\(basePath\);/g,
"system-context resume flows should open DB before deriveState",
);
});
test("register-hooks opens DB before deriveState in session_before_compact", () => {
const compactIdx = registerHooksSrc.indexOf('pi.on("session_before_compact"');
assert.ok(compactIdx > -1, "register-hooks should define session_before_compact");
const compactSection = registerHooksSrc.slice(compactIdx, compactIdx + 1600);
const ensureIdx = compactSection.indexOf("ensureDbOpen()");
const deriveIdx = compactSection.indexOf("deriveState(basePath)");
assert.ok(ensureIdx > -1, "session_before_compact should call ensureDbOpen()");
assert.ok(deriveIdx > -1, "session_before_compact should derive state");
assert.ok(ensureIdx < deriveIdx, "session_before_compact should open DB before deriveState");
});
});