Problem
When a TODO decision arises inside a Conductor session (e.g. during /plan-ceo-review), gstack currently:
- Tries to call
AskUserQuestion — immediately blocked by the question-preference-hook's isConductor() guard.
- Falls back to a prose decision brief in the chat: D label, ELI10, Recommendation, one paragraph per option, "reply with a letter, then STOP."
The prose fallback is still synchronous. The user must be present and reply in-chat before the skill continues. It also means multiple pending TODO decisions arrive as separate, sequential prose blocks — no way to batch-review them.
This is a subset of the broader AUQ-in-Conductor problem (#2035, #2006), but it's worth treating separately because the goal here is different: TODO proposals don't need an immediate answer. They can be deferred without blocking the session.
Proposed alternative: write proposals to TODOS.md
Instead of rendering a prose brief and stopping, when gstack is in a Conductor session and needs a TODO decision, it should:
- Write the proposed item directly to TODOS.md using a new
proposed status (or **Status:** pending-decision).
- Include the full decision context inline — What, Why, Pros, Cons, Options (A/Add · B/Skip · C/Build now), Effort, Priority — so the user has everything they need to decide without digging into chat history.
- Continue the session rather than blocking. The user reviews TODOS.md at their own pace.
Conductor has an inline diff comment feature: the user can leave a comment on any line of a modified file directly in the Conductor UI. This makes TODOS.md a natural async communication channel — the user comments on a proposed item with their decision (A/B/C), and the agent picks it up next session.
The comment-reading gap
Conductor's current MCP surface exposes DiffComment for writing inline comments, but no tool for reading them back. gstack cannot programmatically check whether the user has already responded to a proposed TODO via a Conductor diff comment.
Two paths forward:
Option A — Conductor adds a read tool.
A GetDiffComments MCP tool (or similar) that returns comments on a given file would let gstack read responses and resolve proposals automatically. This would be a Conductor-side feature request.
Option B — User updates the TODOS.md status field directly.
Require the user to change **Status:** proposed to accepted / skipped / build-now in TODOS.md after reviewing. This keeps everything in the file, no MCP round-trip needed. gstack can read the file to check resolution.
Option B requires less infrastructure and keeps TODOS.md as the single source of truth. Option A is more ergonomic for users who prefer the Conductor comment UI.
/ship guard
Regardless of which option is chosen, /ship Step 14 should block (or warn loudly) if TODOS.md contains any items in proposed / pending-decision status. The intent is to prevent shipping past unreviewed TODO proposals.
If Option A lands, the guard could additionally check whether any Conductor diff comments on TODOS.md are unresolved.
Opt-in / user preference
This could be gated behind a preference (gstack-config set todos-decision-mode file-async) so users who prefer the current prose-brief flow aren't affected. Conductor-session detection could auto-enable it, with an explicit always-prose escape hatch.
Related issues
Acceptance criteria
Problem
When a TODO decision arises inside a Conductor session (e.g. during
/plan-ceo-review), gstack currently:AskUserQuestion— immediately blocked by thequestion-preference-hook'sisConductor()guard.The prose fallback is still synchronous. The user must be present and reply in-chat before the skill continues. It also means multiple pending TODO decisions arrive as separate, sequential prose blocks — no way to batch-review them.
This is a subset of the broader AUQ-in-Conductor problem (#2035, #2006), but it's worth treating separately because the goal here is different: TODO proposals don't need an immediate answer. They can be deferred without blocking the session.
Proposed alternative: write proposals to TODOS.md
Instead of rendering a prose brief and stopping, when gstack is in a Conductor session and needs a TODO decision, it should:
proposedstatus (or**Status:** pending-decision).Conductor has an inline diff comment feature: the user can leave a comment on any line of a modified file directly in the Conductor UI. This makes TODOS.md a natural async communication channel — the user comments on a proposed item with their decision (A/B/C), and the agent picks it up next session.
The comment-reading gap
Conductor's current MCP surface exposes
DiffCommentfor writing inline comments, but no tool for reading them back. gstack cannot programmatically check whether the user has already responded to a proposed TODO via a Conductor diff comment.Two paths forward:
Option A — Conductor adds a read tool.
A
GetDiffCommentsMCP tool (or similar) that returns comments on a given file would let gstack read responses and resolve proposals automatically. This would be a Conductor-side feature request.Option B — User updates the TODOS.md status field directly.
Require the user to change
**Status:** proposedtoaccepted/skipped/build-nowin TODOS.md after reviewing. This keeps everything in the file, no MCP round-trip needed. gstack can read the file to check resolution.Option B requires less infrastructure and keeps TODOS.md as the single source of truth. Option A is more ergonomic for users who prefer the Conductor comment UI.
/shipguardRegardless of which option is chosen,
/shipStep 14 should block (or warn loudly) if TODOS.md contains any items inproposed/pending-decisionstatus. The intent is to prevent shipping past unreviewed TODO proposals.If Option A lands, the guard could additionally check whether any Conductor diff comments on TODOS.md are unresolved.
Opt-in / user preference
This could be gated behind a preference (
gstack-config set todos-decision-mode file-async) so users who prefer the current prose-brief flow aren't affected. Conductor-session detection could auto-enable it, with an explicitalways-proseescape hatch.Related issues
question-preference-hookemitspermissionDecision: "defer"on no-op paths, breaking AUQ in recent Claude Code builds (same reporter, macOS/VSCode). Proposed fix: changedefer()to emit nopermissionDecision.~/.gstack/projects/docs stay local? No maintainer response yet. The async-proposal flow here reinforces that TODOS.md is the right place for shared, persistent decisions.clarifytool instead of AUQ. Demonstrates gstack already routes question UI per host. Conductor could be treated similarly: same host-specific routing, different target (file write instead of tool call).Acceptance criteria
isConductor()and a TODO decision is triggered, gstack writes aproposeditem to TODOS.md instead of rendering a prose briefTODOS-format.md/shipStep 14 detectsproposed-status items and blocks or warns before pushing