fix(gsd): create empty DB for fresh projects with empty .gsd/ (#2510)
ensureDbOpen() and the auto-start DB lifecycle block both gated DB creation on the presence of Markdown files (DECISIONS.md, REQUIREMENTS.md, milestones/). In a brand new project, .gsd/ exists but contains no Markdown yet, so gsd_decision_save returned db_unavailable and the agent derailed. Create an empty DB whenever .gsd/ exists, regardless of Markdown content. Migration runs only when Markdown files are present. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9490f2c45c
commit
ae0029b49f
3 changed files with 18 additions and 11 deletions
|
|
@ -549,17 +549,17 @@ export async function bootstrapAutoSession(
|
|||
const hasDecisions = existsSync(join(gsdDirPath, "DECISIONS.md"));
|
||||
const hasRequirements = existsSync(join(gsdDirPath, "REQUIREMENTS.md"));
|
||||
const hasMilestones = existsSync(join(gsdDirPath, "milestones"));
|
||||
if (hasDecisions || hasRequirements || hasMilestones) {
|
||||
try {
|
||||
const { openDatabase: openDb } = await import("./gsd-db.js");
|
||||
try {
|
||||
const { openDatabase: openDb } = await import("./gsd-db.js");
|
||||
openDb(gsdDbPath);
|
||||
if (hasDecisions || hasRequirements || hasMilestones) {
|
||||
const { migrateFromMarkdown } = await import("./md-importer.js");
|
||||
openDb(gsdDbPath);
|
||||
migrateFromMarkdown(s.basePath);
|
||||
} catch (err) {
|
||||
process.stderr.write(
|
||||
`gsd-migrate: auto-migration failed: ${(err as Error).message}\n`,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
process.stderr.write(
|
||||
`gsd-migrate: auto-migration failed: ${(err as Error).message}\n`,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (existsSync(gsdDbPath) && !isDbAvailable()) {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ export async function ensureDbOpen(): Promise<boolean> {
|
|||
}
|
||||
return opened;
|
||||
}
|
||||
|
||||
// .gsd/ exists but has no Markdown content (fresh project) — create empty DB
|
||||
return db.openDatabase(dbPath);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -136,9 +136,10 @@ describe('ensure-db-open', () => {
|
|||
// ensureDbOpen returns false for empty .gsd/ (no Markdown, no DB)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
test('ensureDbOpen: empty .gsd/ returns false', async () => {
|
||||
test('ensureDbOpen: empty .gsd/ creates empty DB (#2510)', async () => {
|
||||
const tmpDir = makeTmpDir();
|
||||
fs.mkdirSync(path.join(tmpDir, '.gsd'), { recursive: true });
|
||||
const gsdDir = path.join(tmpDir, '.gsd');
|
||||
fs.mkdirSync(gsdDir, { recursive: true });
|
||||
// .gsd/ exists but no DECISIONS.md, REQUIREMENTS.md, or milestones/
|
||||
|
||||
try { closeDatabase(); } catch { /* ok */ }
|
||||
|
|
@ -148,9 +149,12 @@ describe('ensure-db-open', () => {
|
|||
try {
|
||||
const { ensureDbOpen } = await import('../bootstrap/dynamic-tools.ts');
|
||||
const result = await ensureDbOpen();
|
||||
assert.ok(result === false, 'ensureDbOpen should return false for empty .gsd/');
|
||||
assert.ok(result === true, 'ensureDbOpen should create empty DB for fresh .gsd/');
|
||||
assert.ok(fs.existsSync(path.join(gsdDir, 'gsd.db')), 'DB file should be created');
|
||||
assert.ok(isDbAvailable(), 'DB should be available');
|
||||
} finally {
|
||||
process.cwd = origCwd;
|
||||
closeDatabase();
|
||||
cleanupDir(tmpDir);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue