Two issues with headless new-milestone:
1. Default 300s timeout is too short — codebase investigation + artifact
writing for a new milestone regularly exceeds 5 minutes. Bumped to
600s (10 min) when the default hasn't been explicitly overridden.
2. The discuss-headless prompt's 'Investigate' step had no guidance on
how much time to spend scouting. LLMs would exhaustively explore the
codebase (50+ tool calls) before writing any artifacts, running out
of time. Added 'brief' qualifier and 5-6 tool call budget with a
note that the research phase does deeper investigation later.
The commit_docs: false preference is already respected — the prompt
correctly says 'Do not commit' when commit_docs is false, and
ensureGitignore idempotently skips when .gsd/ is already in .gitignore.
Fixes#1227
Allow orchestrators to filter the JSONL event stream to specific event
types, reducing stdout noise. The filter applies only to output —
internal processing (completion detection, supervised mode, answer
injection) is unaffected.
- New `--events <types>` flag (comma-separated, implies `--json`)
- Filter applied at stdout write point, all events still processed internally
- Updated help-text and SKILL.md with examples
- Tests for argument parsing and filter matching logic
Pre-supply answers and secrets for non-interactive headless runs via a
declarative JSON file. Two main use cases:
1. Provide secrets that today get lost in headless mode (secure_env_collect
returns null in RPC mode). Secrets are injected as env vars into the
RPC child process.
2. Override default auto-responses when the first option isn't desired.
Uses two-phase correlation: observe tool_execution_start events for
question metadata, then match extension_ui_request events by title to
look up pre-supplied answers. Out-of-order events are buffered with a
500ms timeout.
Coexists with --supervised: injector tries first, then supervised mode,
then auto-responder.
* feat: add `gsd headless query` for structured state inspection
Add read-only query commands that return parseable JSON without
spawning an LLM session. Decouples orchestrators from .gsd/ internals.
Targets: phase, cost, progress, next
* simplify: single `query` command returning full snapshot
Replace 4 query targets (phase/cost/progress/next) with one command
that returns everything in a single JSON object. Caller uses jq.
Also document query in README.md and docs/commands.md.
* docs: update gsd-headless skill and references
- SKILL.md: add missing flags (--supervised, --max-restarts, --response-timeout)
- references/commands.md: add query, discuss, remote, inspect, forensics
- references/multi-session.md: fix spawning syntax, use query for budget
* fix: remove integration tests that entered via merge
These files belong to the feat/headless-orchestration-skill branch
and were accidentally included during the upstream/main merge.
They contain TS errors (sessionTerminated scope issue) that break CI.
* fix: restore headless-command.ts deleted by accident
When the headless child process crashes or errors out, auto-restart
with exponential backoff (5s, 10s, 15s... up to 30s) instead of
exiting immediately. This enables overnight 'fire and forget' runs.
- --max-restarts N (default 3, 0 to disable): controls restart budget
- Only restarts on crashes (exit code !== 0), not on success or blocked
- SIGINT/SIGTERM bypasses restart (user intent to stop)
- Restart count shown in summary output
- Backoff prevents rapid crash loops from burning API credits
The inner loop function (runHeadlessOnce) returns exit status instead
of calling process.exit, letting the outer loop decide whether to
restart or terminate.
This is the first step toward the 'absolute autonomy' goal described
in #886 — process-level resilience for long-running sessions.
isTerminalNotification() used broad substring matching against
['complete', 'stopped', 'blocked']. Any notification containing these
words triggered early exit — including progress messages like:
'All slices are complete — nothing to discuss.'
'Override(s) resolved — rewrite-docs completed.'
'Skipped 5+ completed units. Yielding to UI before continuing.'
Fix: Replace substring matching with prefix matching against the actual
stop signals emitted by stopAuto():
'Auto-mode stopped...'
'Step-mode stopped...'
These are the ONLY notifications that indicate auto-mode has genuinely
terminated. All other notifications (slice completion, override
resolution, skip yielding) are progress events and must not trigger
exit.
Also tighten isBlockedNotification to match 'blocked:' (with colon)
instead of bare 'blocked' to avoid false positives from unrelated
messages.
Added 15 regression tests covering:
- All real terminal notification variants
- 6 false-positive cases from the issue report
- Non-notify event rejection
- Blocked detection with and without colon
- Remove --verbose flag from headless (use --json for detailed output)
- Remove redundant sawToolExecution state variable
- Remove unused rejectCompletion
- Add missing build*Prompt imports in auto.ts (fixes CI typecheck:extensions)
- Document headless mode in README.md and docs/commands.md
- Simplify help text with examples instead of exhaustive command catalog
Replace --step flag with positional command routing so any /gsd
subcommand can run headlessly. Add /gsd dispatch <phase> for direct
unit-type dispatch (research, plan, execute, complete, reassess, uat,
replan) with state-aware resolution.
Quick commands (status, queue, doctor, etc.) resolve on first agent_end.
Long-running commands (auto, next, dispatch) use idle timer + terminal
notification detection.
Adds a first-class `gsd headless` command that runs auto-mode without a
TUI by spawning a child process in RPC mode via RpcClient. Useful for
CI/CD pipelines, scripts, and unattended execution.
CLI interface:
gsd headless - Run auto-mode until complete
gsd headless --step - Run one unit only (sends /gsd next)
gsd headless --timeout 300000 - Custom timeout (default 5 min)
gsd headless --json - Forward RPC events as JSONL to stdout
gsd headless --verbose - Show full agent text and tool results
gsd headless --model <id> - Override model
Exit codes: 0 = complete, 1 = error/timeout, 2 = blocked
Features:
- Extension UI auto-responder (handles select, confirm, input, editor,
notify, setStatus, setWidget, setTitle, set_editor_text)
- Completion detection via terminal notification keywords + idle timeout
- Human-readable progress output to stderr
- SIGINT/SIGTERM forwarding for clean shutdown
- Child process crash detection
- Completion summary with diagnostics on failure