Merge pull request #3691 from Tibsfox/fix/status-open-db-cold-session

fix(gsd): open DB before status derivation + respect isolation:none in quick
This commit is contained in:
Jeremy McSpadden 2026-04-07 07:02:31 -05:00 committed by GitHub
commit 57e9063580
3 changed files with 70 additions and 15 deletions

View file

@ -71,6 +71,9 @@ export function showHelp(ctx: ExtensionCommandContext): void {
export async function handleStatus(ctx: ExtensionCommandContext): Promise<void> {
const basePath = projectRoot();
// Open DB in cold sessions so status uses DB-backed state, not filesystem fallback (#3385)
const { ensureDbOpen } = await import("../../bootstrap/dynamic-tools.js");
await ensureDbOpen();
const state = await deriveState(basePath);
if (state.registry.length === 0) {

View file

@ -192,28 +192,33 @@ export async function handleQuick(
const taskDirRel = `.gsd/quick/${taskNum}-${slug}`;
const date = new Date().toISOString().split("T")[0];
// Create git branch for the quick task
// Create git branch for the quick task (unless isolation:none — #3337)
const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git ?? {};
const git = new GitServiceImpl(basePath, gitPrefs);
const branchName = `gsd/quick/${taskNum}-${slug}`;
let originalBranch = git.getCurrentBranch();
let branchCreated = false;
try {
const current = originalBranch;
if (current !== branchName) {
// Auto-commit any dirty state before switching
try {
git.autoCommit("quick-task", `Q${taskNum}`, []);
} catch { /* nothing to commit — fine */ }
const { getIsolationMode } = await import("./preferences.js");
const usesBranch = getIsolationMode() !== "none";
runGit(basePath, ["checkout", "-b", branchName]);
branchCreated = true;
let branchCreated = false;
if (usesBranch) {
try {
const current = originalBranch;
if (current !== branchName) {
// Auto-commit any dirty state before switching
try {
git.autoCommit("quick-task", `Q${taskNum}`, []);
} catch { /* nothing to commit — fine */ }
runGit(basePath, ["checkout", "-b", branchName]);
branchCreated = true;
}
} catch (err) {
// Branch creation failed — continue on current branch
const message = err instanceof Error ? err.message : String(err);
ctx.ui.notify(`Could not create branch ${branchName}: ${message}. Working on current branch.`, "warning");
}
} catch (err) {
// Branch creation failed — continue on current branch
const message = err instanceof Error ? err.message : String(err);
ctx.ui.notify(`Could not create branch ${branchName}: ${message}. Working on current branch.`, "warning");
}
const actualBranch = branchCreated ? branchName : git.getCurrentBranch();

View file

@ -0,0 +1,47 @@
/**
* Regression test for #3691 /gsd status opens DB before deriveState
*
* In cold sessions the DB was not opened before deriveState, causing
* status to fall back to filesystem-only state. The fix adds an
* ensureDbOpen() call before deriveState in handleStatus.
*
* Also verifies that quick.ts checks getIsolationMode before branching.
*/
import { describe, test } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const coreSrc = readFileSync(
join(__dirname, '..', 'commands', 'handlers', 'core.ts'),
'utf-8',
);
const quickSrc = readFileSync(
join(__dirname, '..', 'quick.ts'),
'utf-8',
);
describe('status opens DB before deriveState (#3691)', () => {
test('handleStatus calls ensureDbOpen before deriveState', () => {
const ensureIdx = coreSrc.indexOf('ensureDbOpen');
const deriveIdx = coreSrc.indexOf('deriveState(basePath)');
assert.ok(ensureIdx > -1, 'ensureDbOpen call should exist in core.ts');
assert.ok(deriveIdx > -1, 'deriveState(basePath) call should exist in core.ts');
assert.ok(
ensureIdx < deriveIdx,
'ensureDbOpen must appear before deriveState so DB is ready',
);
});
test('quick.ts checks getIsolationMode before branching', () => {
assert.match(quickSrc, /getIsolationMode\(\)/,
'quick.ts should call getIsolationMode()');
assert.match(quickSrc, /getIsolationMode\(\)\s*!==\s*"none"/,
'quick.ts should compare isolation mode against "none"');
});
});