Skip to content

Bug: /gsd discuss reports "All slices complete — nothing to discuss" when DB is not yet open #2560

@yoshi280

Description

@yoshi280

Summary

showDiscuss() in guided-flow.ts calls isDbAvailable() to decide whether to load slices from the DB. When /gsd discuss is invoked as a slash command in a fresh session (before any GSD tool has been called), isDbAvailable() returns false because the DB singleton is never initialized. The fallback is normSlices = [], an empty list filters to zero pending slices, and the function exits with the misleading "All slices are complete — nothing to discuss." notification — even when all slices are genuinely pending.

Steps to Reproduce

  1. Have an active milestone with 2–3 pending slices (all pending in the DB, all unchecked in ROADMAP)
  2. Open a fresh GSD session (no tool calls have been made yet)
  3. Run /gsd discuss
  4. Expected: Slice picker appears showing the pending slices
  5. Actual: "All slices are complete — nothing to discuss." toast and immediate exit

Root Cause

gsd-db.ts keeps a currentDb singleton that starts null. openDatabase() sets it. ensureDbOpen() (in dynamic-tools.ts) calls openDatabase() — and ensureDbOpen() is called at the top of every GSD tool handler (e.g. gsd_plan_slice, gsd_task_complete). It is not called from command handlers.

showDiscuss() is a command handler. It calls isDbAvailable() directly with no prior ensureDbOpen(), so in a fresh session isDbAvailable() is always false.

// guided-flow.ts — showDiscuss() — "Normalize slices" block
if (isDbAvailable()) {
  normSlices = getMilestoneSlices(mid).map(...);
} else {
  normSlices = [];   // reached on every cold-start invocation of /gsd discuss
}
const pendingSlices = normSlices.filter(s => !s.done);
if (pendingSlices.length === 0) {
  ctx.ui.notify("All slices are complete — nothing to discuss.", "info");  // false positive
  return;
}

The early-exit guard at the top (if (!roadmapContent && !isDbAvailable())) does not protect this path when a ROADMAP file exists — execution falls through to the broken normalization.

Proposed Fix

Add ensureDbOpen() before the slice normalization block in showDiscuss():

// guided-flow.ts — showDiscuss(), before "Normalize slices":
const { ensureDbOpen } = await import("./bootstrap/dynamic-tools.js");
await ensureDbOpen();

// existing logic now works correctly:
if (isDbAvailable()) {
  normSlices = getMilestoneSlices(mid).map(...);
} else {
  normSlices = []; // now only reached if DB file genuinely does not exist
}

A secondary instance of the same pattern exists in buildSliceDiscussContext() (~line 357 in compiled JS) where getMilestoneSlices is called to inline completed-slice summaries into the discussion prompt. This one does not cause an abort, but it produces incomplete context when the DB is cold.

Secondary Note: Not Related to #2556

Issue #2556 (deriveState sorts by milestone ID, dispatch-guard sorts by queue-order.json) is a different bug in a different code path — an ordering/priority conflict. This bug is a missing DB initialization call in a command handler. Different root causes, different fixes.

Workaround

Any GSD tool call in the session before /gsd discuss will open the DB as a side effect (e.g. trigger one agent turn). After that, /gsd discuss works correctly.

Environment

  • GSD version: 2.48.0
  • Platform: macOS
  • Project config: DB-backed, isolation mode: none

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions