feat: add `gsd headless query` for instant state inspection (#951)
* 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
2026-03-17 19:03:59 -03:00
|
|
|
/**
|
|
|
|
|
* Headless Query — `gsd headless query`
|
|
|
|
|
*
|
|
|
|
|
* Single read-only command that returns the full project snapshot as JSON
|
|
|
|
|
* to stdout, without spawning an LLM session. Instant (~50ms).
|
|
|
|
|
*
|
|
|
|
|
* Output: { state, next, cost }
|
|
|
|
|
* state — deriveState() output (phase, milestones, progress, blockers)
|
|
|
|
|
* next — dry-run dispatch preview (what auto-mode would do next)
|
|
|
|
|
* cost — aggregated parallel worker costs
|
2026-03-18 10:34:18 -04:00
|
|
|
*
|
|
|
|
|
* Note: Extension modules are .ts files loaded via jiti (not compiled to .js).
|
|
|
|
|
* We use createJiti() here because this module is imported directly from cli.ts,
|
|
|
|
|
* bypassing the extension loader's jiti setup (#1137).
|
feat: add `gsd headless query` for instant state inspection (#951)
* 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
2026-03-17 19:03:59 -03:00
|
|
|
*/
|
|
|
|
|
|
2026-03-18 10:34:18 -04:00
|
|
|
import { createJiti } from '@mariozechner/jiti'
|
|
|
|
|
import { fileURLToPath } from 'node:url'
|
feat: add `gsd headless query` for instant state inspection (#951)
* 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
2026-03-17 19:03:59 -03:00
|
|
|
import type { GSDState } from './resources/extensions/gsd/types.js'
|
M001: The Minimal Machine — linear auto-loop, sole-authority state, sidecar queue, WorktreeResolver (#1419)
* refactor: replace recursive auto-dispatch with linear autoLoop, delete ~3k lines of dead code
Replace the complex recursive dispatch system (dispatchNextUnit, reentrancy
guards, stall detection, idempotency tracking, skip-depth machinery) with a
simple linear while(s.active) loop in auto-loop.ts.
Key changes:
- New auto-loop.ts with autoLoop(), runUnit(), resolveAgentEnd()
- Deleted auto-idempotency.ts, auto-stuck-detection.ts, session-lock.ts,
mechanical-completion.ts, progress-score.ts, auto-constants.ts, unit-id.ts
- Extracted WorktreeResolver class for worktree path resolution
- Added auto-worktree-sync.ts for worktree synchronization
- Simplified auto.ts from ~1400 lines to ~400 lines
- Fixed 9 TypeScript errors (NotifyCtx type widening, capture typing)
- Comprehensive test coverage: 32 auto-loop tests + worktree resolver/DB tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address 6 audit findings in auto-loop refactor
1. CRITICAL: Move pendingResolve to AutoSession + queue orphaned agent_end
events instead of silently dropping them. Prevents permanent stalls when
error-recovery sendMessage retries fire between loop iterations.
2. HIGH: Scope pendingResolve per-session via _activeSession ref, preventing
concurrent /gsd auto sessions from corrupting each other's promises.
3. HIGH: Replace console.log in dispatchHookUnit with debugLog to prevent
hook prompt content (potentially containing secrets) from leaking to stdout.
4. HIGH: Restore parked milestone handling in state.ts — Phase 1 skips
parked milestones so they don't satisfy depends_on, Phase 2 registers
them as 'parked' status. Add 'parked' to MilestoneRegistryEntry type.
5. MEDIUM: Restore queuePhaseActive parameter in shouldBlockContextWrite
and re-export setQueuePhaseActive for guided-flow-queue.ts consumers.
6. MEDIUM: Add MAX_LOOP_ITERATIONS (500) lifetime cap to autoLoop to prevent
runaway loops when units alternate between IDs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: resolve build breakers, add correctness fixes, and graduated recovery
Build breakers (CRITICAL):
- Restore unit-id.ts (deleted but still imported by complexity-classifier.ts, metrics.ts)
- Restore progress-score.ts (deleted but still imported by commands.ts, dashboard-overlay.ts, doctor.ts)
- Rewrite worktree-sync-milestones.test.ts to use new syncProjectRootToWorktree API
Correctness fixes (MEDIUM):
- Cap pendingAgentEndQueue to 3 entries to prevent unbounded growth from stale events
- Add milestoneId path traversal validation in WorktreeResolver
- Clear depthVerificationDone on session_start to prevent cross-session leaks in RPC mode
- Add verification gate for non-hook sidecar units (triage, quick-tasks)
- Remove dead handleAgentEnd import from index.ts
Graduated recovery (Jeremy's feedback):
- Blanket try/catch around loop body — one bad iteration no longer kills the session
- Graduated stuck recovery: at count 3 try artifact verification + cache invalidation,
at count 5 hard stop (was: binary stop at 5 with no recovery attempt)
- Graduated error recovery: 1st error retries, 2nd invalidates caches, 3rd stops
Test results: 32/32 auto-loop, 28/28 worktree-resolver, 11/11 sidecar-queue, tsc clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: restore copyWorktreeDb/reconcileWorktreeDb exports and fix loadToolApiKeys import
Two missing exports caused ~90% of the 120 pre-existing test failures:
1. copyWorktreeDb + reconcileWorktreeDb — imported by auto-worktree.ts but
never added to gsd-db.ts. Restored with the original implementations.
2. loadToolApiKeys — moved to commands-config.ts but index.ts still imported
from commands.ts. Fixed the import path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move loadToolApiKeys import to commands-config.js
loadToolApiKeys was moved to commands-config.ts but index.ts still
imported it from commands.ts, causing runtime failures in all tests
that transitively load the extension entry point.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: fix provider error assertion on windows
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:56:00 -06:00
|
|
|
import { resolveBundledSourceResource } from './bundled-resource-path.js'
|
feat: add `gsd headless query` for instant state inspection (#951)
* 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
2026-03-17 19:03:59 -03:00
|
|
|
|
2026-03-18 10:34:18 -04:00
|
|
|
const jiti = createJiti(fileURLToPath(import.meta.url), { interopDefault: true, debug: false })
|
M001: The Minimal Machine — linear auto-loop, sole-authority state, sidecar queue, WorktreeResolver (#1419)
* refactor: replace recursive auto-dispatch with linear autoLoop, delete ~3k lines of dead code
Replace the complex recursive dispatch system (dispatchNextUnit, reentrancy
guards, stall detection, idempotency tracking, skip-depth machinery) with a
simple linear while(s.active) loop in auto-loop.ts.
Key changes:
- New auto-loop.ts with autoLoop(), runUnit(), resolveAgentEnd()
- Deleted auto-idempotency.ts, auto-stuck-detection.ts, session-lock.ts,
mechanical-completion.ts, progress-score.ts, auto-constants.ts, unit-id.ts
- Extracted WorktreeResolver class for worktree path resolution
- Added auto-worktree-sync.ts for worktree synchronization
- Simplified auto.ts from ~1400 lines to ~400 lines
- Fixed 9 TypeScript errors (NotifyCtx type widening, capture typing)
- Comprehensive test coverage: 32 auto-loop tests + worktree resolver/DB tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address 6 audit findings in auto-loop refactor
1. CRITICAL: Move pendingResolve to AutoSession + queue orphaned agent_end
events instead of silently dropping them. Prevents permanent stalls when
error-recovery sendMessage retries fire between loop iterations.
2. HIGH: Scope pendingResolve per-session via _activeSession ref, preventing
concurrent /gsd auto sessions from corrupting each other's promises.
3. HIGH: Replace console.log in dispatchHookUnit with debugLog to prevent
hook prompt content (potentially containing secrets) from leaking to stdout.
4. HIGH: Restore parked milestone handling in state.ts — Phase 1 skips
parked milestones so they don't satisfy depends_on, Phase 2 registers
them as 'parked' status. Add 'parked' to MilestoneRegistryEntry type.
5. MEDIUM: Restore queuePhaseActive parameter in shouldBlockContextWrite
and re-export setQueuePhaseActive for guided-flow-queue.ts consumers.
6. MEDIUM: Add MAX_LOOP_ITERATIONS (500) lifetime cap to autoLoop to prevent
runaway loops when units alternate between IDs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: resolve build breakers, add correctness fixes, and graduated recovery
Build breakers (CRITICAL):
- Restore unit-id.ts (deleted but still imported by complexity-classifier.ts, metrics.ts)
- Restore progress-score.ts (deleted but still imported by commands.ts, dashboard-overlay.ts, doctor.ts)
- Rewrite worktree-sync-milestones.test.ts to use new syncProjectRootToWorktree API
Correctness fixes (MEDIUM):
- Cap pendingAgentEndQueue to 3 entries to prevent unbounded growth from stale events
- Add milestoneId path traversal validation in WorktreeResolver
- Clear depthVerificationDone on session_start to prevent cross-session leaks in RPC mode
- Add verification gate for non-hook sidecar units (triage, quick-tasks)
- Remove dead handleAgentEnd import from index.ts
Graduated recovery (Jeremy's feedback):
- Blanket try/catch around loop body — one bad iteration no longer kills the session
- Graduated stuck recovery: at count 3 try artifact verification + cache invalidation,
at count 5 hard stop (was: binary stop at 5 with no recovery attempt)
- Graduated error recovery: 1st error retries, 2nd invalidates caches, 3rd stops
Test results: 32/32 auto-loop, 28/28 worktree-resolver, 11/11 sidecar-queue, tsc clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: restore copyWorktreeDb/reconcileWorktreeDb exports and fix loadToolApiKeys import
Two missing exports caused ~90% of the 120 pre-existing test failures:
1. copyWorktreeDb + reconcileWorktreeDb — imported by auto-worktree.ts but
never added to gsd-db.ts. Restored with the original implementations.
2. loadToolApiKeys — moved to commands-config.ts but index.ts still imported
from commands.ts. Fixed the import path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move loadToolApiKeys import to commands-config.js
loadToolApiKeys was moved to commands-config.ts but index.ts still
imported it from commands.ts, causing runtime failures in all tests
that transitively load the extension entry point.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: fix provider error assertion on windows
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:56:00 -06:00
|
|
|
const gsdExtensionPath = (...segments: string[]) =>
|
|
|
|
|
resolveBundledSourceResource(import.meta.url, 'extensions', 'gsd', ...segments)
|
2026-03-18 10:34:18 -04:00
|
|
|
|
|
|
|
|
async function loadExtensionModules() {
|
M001: The Minimal Machine — linear auto-loop, sole-authority state, sidecar queue, WorktreeResolver (#1419)
* refactor: replace recursive auto-dispatch with linear autoLoop, delete ~3k lines of dead code
Replace the complex recursive dispatch system (dispatchNextUnit, reentrancy
guards, stall detection, idempotency tracking, skip-depth machinery) with a
simple linear while(s.active) loop in auto-loop.ts.
Key changes:
- New auto-loop.ts with autoLoop(), runUnit(), resolveAgentEnd()
- Deleted auto-idempotency.ts, auto-stuck-detection.ts, session-lock.ts,
mechanical-completion.ts, progress-score.ts, auto-constants.ts, unit-id.ts
- Extracted WorktreeResolver class for worktree path resolution
- Added auto-worktree-sync.ts for worktree synchronization
- Simplified auto.ts from ~1400 lines to ~400 lines
- Fixed 9 TypeScript errors (NotifyCtx type widening, capture typing)
- Comprehensive test coverage: 32 auto-loop tests + worktree resolver/DB tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address 6 audit findings in auto-loop refactor
1. CRITICAL: Move pendingResolve to AutoSession + queue orphaned agent_end
events instead of silently dropping them. Prevents permanent stalls when
error-recovery sendMessage retries fire between loop iterations.
2. HIGH: Scope pendingResolve per-session via _activeSession ref, preventing
concurrent /gsd auto sessions from corrupting each other's promises.
3. HIGH: Replace console.log in dispatchHookUnit with debugLog to prevent
hook prompt content (potentially containing secrets) from leaking to stdout.
4. HIGH: Restore parked milestone handling in state.ts — Phase 1 skips
parked milestones so they don't satisfy depends_on, Phase 2 registers
them as 'parked' status. Add 'parked' to MilestoneRegistryEntry type.
5. MEDIUM: Restore queuePhaseActive parameter in shouldBlockContextWrite
and re-export setQueuePhaseActive for guided-flow-queue.ts consumers.
6. MEDIUM: Add MAX_LOOP_ITERATIONS (500) lifetime cap to autoLoop to prevent
runaway loops when units alternate between IDs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: resolve build breakers, add correctness fixes, and graduated recovery
Build breakers (CRITICAL):
- Restore unit-id.ts (deleted but still imported by complexity-classifier.ts, metrics.ts)
- Restore progress-score.ts (deleted but still imported by commands.ts, dashboard-overlay.ts, doctor.ts)
- Rewrite worktree-sync-milestones.test.ts to use new syncProjectRootToWorktree API
Correctness fixes (MEDIUM):
- Cap pendingAgentEndQueue to 3 entries to prevent unbounded growth from stale events
- Add milestoneId path traversal validation in WorktreeResolver
- Clear depthVerificationDone on session_start to prevent cross-session leaks in RPC mode
- Add verification gate for non-hook sidecar units (triage, quick-tasks)
- Remove dead handleAgentEnd import from index.ts
Graduated recovery (Jeremy's feedback):
- Blanket try/catch around loop body — one bad iteration no longer kills the session
- Graduated stuck recovery: at count 3 try artifact verification + cache invalidation,
at count 5 hard stop (was: binary stop at 5 with no recovery attempt)
- Graduated error recovery: 1st error retries, 2nd invalidates caches, 3rd stops
Test results: 32/32 auto-loop, 28/28 worktree-resolver, 11/11 sidecar-queue, tsc clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: restore copyWorktreeDb/reconcileWorktreeDb exports and fix loadToolApiKeys import
Two missing exports caused ~90% of the 120 pre-existing test failures:
1. copyWorktreeDb + reconcileWorktreeDb — imported by auto-worktree.ts but
never added to gsd-db.ts. Restored with the original implementations.
2. loadToolApiKeys — moved to commands-config.ts but index.ts still imported
from commands.ts. Fixed the import path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move loadToolApiKeys import to commands-config.js
loadToolApiKeys was moved to commands-config.ts but index.ts still
imported it from commands.ts, causing runtime failures in all tests
that transitively load the extension entry point.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: fix provider error assertion on windows
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:56:00 -06:00
|
|
|
const stateModule = await jiti.import(gsdExtensionPath('state.ts'), {}) as any
|
|
|
|
|
const dispatchModule = await jiti.import(gsdExtensionPath('auto-dispatch.ts'), {}) as any
|
|
|
|
|
const sessionModule = await jiti.import(gsdExtensionPath('session-status-io.ts'), {}) as any
|
|
|
|
|
const prefsModule = await jiti.import(gsdExtensionPath('preferences.ts'), {}) as any
|
2026-03-18 10:34:18 -04:00
|
|
|
return {
|
|
|
|
|
deriveState: stateModule.deriveState as (basePath: string) => Promise<GSDState>,
|
|
|
|
|
resolveDispatch: dispatchModule.resolveDispatch as (opts: any) => Promise<any>,
|
|
|
|
|
readAllSessionStatuses: sessionModule.readAllSessionStatuses as (basePath: string) => any[],
|
|
|
|
|
loadEffectiveGSDPreferences: prefsModule.loadEffectiveGSDPreferences as () => any,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
feat: add `gsd headless query` for instant state inspection (#951)
* 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
2026-03-17 19:03:59 -03:00
|
|
|
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
export interface QuerySnapshot {
|
|
|
|
|
state: GSDState
|
|
|
|
|
next: {
|
|
|
|
|
action: 'dispatch' | 'stop' | 'skip'
|
|
|
|
|
unitType?: string
|
|
|
|
|
unitId?: string
|
|
|
|
|
reason?: string
|
|
|
|
|
}
|
|
|
|
|
cost: {
|
|
|
|
|
workers: Array<{
|
|
|
|
|
milestoneId: string
|
|
|
|
|
pid: number
|
|
|
|
|
state: string
|
|
|
|
|
cost: number
|
|
|
|
|
lastHeartbeat: number
|
|
|
|
|
}>
|
|
|
|
|
total: number
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface QueryResult {
|
|
|
|
|
exitCode: number
|
|
|
|
|
data?: QuerySnapshot
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ─── Implementation ─────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
export async function handleQuery(basePath: string): Promise<QueryResult> {
|
2026-03-18 10:34:18 -04:00
|
|
|
const { deriveState, resolveDispatch, readAllSessionStatuses, loadEffectiveGSDPreferences } = await loadExtensionModules()
|
feat: add `gsd headless query` for instant state inspection (#951)
* 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
2026-03-17 19:03:59 -03:00
|
|
|
const state = await deriveState(basePath)
|
|
|
|
|
|
|
|
|
|
// Derive next dispatch action
|
|
|
|
|
let next: QuerySnapshot['next']
|
2026-03-26 20:05:19 -06:00
|
|
|
if (!state.activeMilestone?.id) {
|
feat: add `gsd headless query` for instant state inspection (#951)
* 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
2026-03-17 19:03:59 -03:00
|
|
|
next = {
|
|
|
|
|
action: 'stop',
|
|
|
|
|
reason: state.phase === 'complete' ? 'All milestones complete.' : state.nextAction,
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const loaded = loadEffectiveGSDPreferences()
|
|
|
|
|
const dispatch = await resolveDispatch({
|
|
|
|
|
basePath,
|
|
|
|
|
mid: state.activeMilestone.id,
|
|
|
|
|
midTitle: state.activeMilestone.title,
|
|
|
|
|
state,
|
|
|
|
|
prefs: loaded?.preferences,
|
|
|
|
|
})
|
|
|
|
|
next = {
|
|
|
|
|
action: dispatch.action,
|
|
|
|
|
unitType: dispatch.action === 'dispatch' ? dispatch.unitType : undefined,
|
|
|
|
|
unitId: dispatch.action === 'dispatch' ? dispatch.unitId : undefined,
|
|
|
|
|
reason: dispatch.action === 'stop' ? dispatch.reason : undefined,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Aggregate parallel worker costs
|
|
|
|
|
const statuses = readAllSessionStatuses(basePath)
|
|
|
|
|
const workers = statuses.map((s) => ({
|
|
|
|
|
milestoneId: s.milestoneId,
|
|
|
|
|
pid: s.pid,
|
|
|
|
|
state: s.state,
|
|
|
|
|
cost: s.cost,
|
|
|
|
|
lastHeartbeat: s.lastHeartbeat,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
const snapshot: QuerySnapshot = {
|
|
|
|
|
state,
|
|
|
|
|
next,
|
|
|
|
|
cost: { workers, total: workers.reduce((sum, w) => sum + w.cost, 0) },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
process.stdout.write(JSON.stringify(snapshot) + '\n')
|
|
|
|
|
return { exitCode: 0, data: snapshot }
|
|
|
|
|
}
|