Add missing parameters (signal, onUpdate, ctx) to tool execute signatures
and details property to return objects to satisfy AgentToolResult<T> type.
Fix string-to-boolean type mismatch on display property in sendMessage calls.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Export TOOL_KEYS constant and add loadToolApiKeys() function to load
API keys from ~/.gsd/agent/auth.json into environment variables.
Called in session_start handler so tool-based extensions (Context7,
Brave Search, Jina, Tavily, Groq) work immediately without requiring
/gsd config.
* fix(auto): add missing import for resolveSkillDiscoveryMode
Used at line 687 but not imported, causing "resolveSkillDiscoveryMode is
not defined" crash on auto-mode startup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(auto): add workingDirectory to all auto-mode prompt templates
Six prompt templates (reassess-roadmap, complete-milestone, replan-slice,
run-uat, research-milestone, plan-milestone) were missing the working
directory directive. Without it, the LLM infers the main repo path from
system context and cd's there instead of staying in the worktree. This
causes artifacts to be written to the wrong location, preventing the
dispatch loop from detecting completion and triggering infinite
re-dispatches of the same unit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(auto): detect mid-session resource updates and stop gracefully
Templates are read from disk on each dispatch but extension code is
loaded once at startup. If resources are re-synced mid-session (via
/gsd:update, npm update, or dev copy-resources), templates may expect
variables the in-memory code doesn't provide, causing a crash.
Add a syncedAt timestamp to managed-resources.json. Auto-mode captures
this at startup and checks before each dispatch. If resources changed,
it stops with a clear message instead of crashing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add workingDirectory to prompt template test fixtures
Tests that load prompt templates via loadPromptFromWorktree now pass the
workingDirectory variable, matching the updated templates that include
the {{workingDirectory}} directive.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After deleting summary files and modifying PLAN files, only
invalidateStateCache() was called. Path and parse caches remained
stale, causing deriveState() to return incorrect results — showing
undone tasks as still complete.
Four fixes to auto-recovery logic that caused silent failures or
inconsistent state:
1. skipExecuteTask: return false when checkbox regex doesn't match the
plan format, so callers fall through to other recovery strategies
instead of assuming success (lines 252-255)
2. verifyExpectedArtifact: fail verification on corrupt/unparseable
roadmap instead of silently passing. Prevents advancing past an
incomplete complete-slice when the roadmap file is malformed (line 152)
3. removePersistedKey: use atomic tmp+rename write (matching
persistCompletedKey) to prevent completed-units.json corruption
on crash mid-write (line 293)
4. selfHealRuntimeRecords: use verifyExpectedArtifact instead of bare
existsSync for execute-task healing, so tasks with summary but
unchecked plan checkbox aren't incorrectly marked complete (line 374)
Co-authored-by: TÂCHES <afromanguy@me.com>
The progress bar in the auto-mode widget was snapshot-based — only
updated at dispatch time via updateSliceProgressCache(). During
long-running units (especially after the worktree architecture in
PR #506), the bar appeared frozen even as tasks completed on disk.
Add a 5-second interval inside the widget that re-reads the roadmap
and plan files from disk, so slice/task progress reflects reality
without waiting for the next unit dispatch.
Closes#549
#536 changed git.isolation from deprecated to an active setting.
Update the test to verify it passes through correctly instead of
expecting a deprecation warning. Add separate test for the still-
deprecated git.merge_to_main.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce typed error hierarchy (GSDError with stable error codes) for
programmatic error matching and crash diagnostics. Convert
MergeConflictError to extend GSDError. Capture error references in the
most impactful silent catch blocks across crash-recovery, auto-recovery,
and activity-log — errors remain non-fatal but are no longer discarded.
Closes#525
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three independent caches (state, path, parse) required manual coordination
on every dispatch cycle. Forgetting any one caused stale reads (#431).
Add a single invalidateAllCaches() in cache.ts that clears all three,
and replace grouped call sites in auto.ts and tests.
Individual clear functions are preserved for callers that legitimately
only need to clear one cache.
Closes#527
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the 130-line if-else chain in dispatchNextUnit with a
declarative DispatchRule[] table in auto-dispatch.ts.
Each rule maps a GSD state to the unit type, unit ID, and prompt
builder. Rules are evaluated in order; first match wins. The table
is inspectable, testable per-rule, and extensible without modifying
orchestration code.
- auto-dispatch.ts: 258 lines, 12 named rules
- auto.ts dispatch section: 130 lines → 20 lines
- Updated auto-draft-pause test to verify rules in new location
- 123/123 tests pass, zero TypeScript errors
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Validates parsed preferences against known keys and expected types.
Unknown keys produce warnings instead of being silently ignored.
Previously unvalidated fields (budget_enforcement, context_pause_threshold,
models, auto_supervisor, notifications, remote_questions) are now
type-checked. Warnings surface through LoadedGSDPreferences so callers
can inspect validation results.
Closes#522
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three fixes for slice transition crashes and git isolation regression:
1. dispatch-guard reads from disk instead of git branch — prevents
false blockers when roadmap state is committed on milestone branch
but not yet on the integration branch (#530).
2. Auto-resolve .gsd/ state file conflicts during milestone merge and
in the mid-merge safety check. STATE.md, completed-units.json, and
auto.lock diverge between branches during normal operation — always
prefer the milestone branch version. Only escalate non-.gsd conflicts
to MergeConflictError (#530).
3. Restore git.isolation preference with two values (#531):
- "worktree" (default): creates milestone worktrees for isolated work
- "branch": works directly in the project root, skipping worktree
creation — for submodule-heavy repos where worktrees fail
The branchless worktree architecture remains the default. Branch mode
simply gates worktree entry points so no worktree is ever created.
Comprehensive prompt and template overhaul addressing multiple issues
discovered during auto-mode execution:
**Worktree cwd fix** — Executor agents wrote code to the main repo
instead of the worktree because prompts never stated the working
directory. Added ## Working Directory section with explicit path to
execute-task, plan-slice, research-slice, complete-slice prompts.
Passed workingDirectory: base to all loadPrompt() calls in
auto-prompts.ts and guided-flow.ts.
**Stale branch references** — Removed all "slice branch" references
(branchless since v2.14.0). Updated system.md with Worktree Model
section. Updated preferences-reference.md descriptions.
**System prompt updates** — Added REQUIREMENTS.md, CONTEXT.md docs,
system-managed directories (runtime/, activity/, worktrees/) to
directory structure.
**Pipeline awareness** — Every phase now knows its role: researchers
are scouts writing for planners, planners trust research and don't
re-explore, executors build from task plans, completers write for
downstream readers. Eliminates redundant work between phases.
**Research depth calibration** — Three-tier system (deep/targeted/light)
across research-slice, guided-research-slice, research-milestone.
Light research for known patterns can be 15-20 lines.
**Template improvements:**
- research.md: "Existing Code and Patterns" → "Implementation Landscape"
with Key Files, Build Order, Verification Approach subsections
- plan.md: reduced task examples from 3 to 2 to avoid anchoring
- state.md: removed dead Active Workspace field
- reassessment.md: added depth guidance for no-change vs modified
- Carry-forward now extracts key_files (was missing — executors
couldn't see which files prior tasks created)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The dispatch gap watchdog is a one-shot timer that fires 5s after a unit
completes without a follow-up dispatch. Previously, if the watchdog's
dispatchNextUnit() call returned without actually dispatching a unit
(no sendMessage called), auto-mode was left permanently active but idle
— no new watchdog was started and no stopAuto was called.
This happened when:
- State between milestones had no dispatchable unit
- Stale completed-units.json after GSD updates caused skip loops
- dispatchNextUnit silently returned without finding work
Now the watchdog checks whether a unit was actually dispatched after its
retry attempt. If not, it stops auto-mode cleanly with a user-facing
message instead of leaving it stuck.
Closes#537
The migrate/ directory (1,862 lines across 9 files) is one-time migration
code for .planning/ → .gsd/ conversion. Replace the static top-level
import with a dynamic import() that only loads when `/gsd migrate` is
invoked, matching the existing pattern used for hooks and metrics.
Closes#523
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace existsSync collision loop with atomic O_CREAT|O_EXCL file
creation, hoist regex to module-level constant, and memoize
getPackageDir() to avoid repeated directory walks.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Arrow keys produce `^[[D`/`^[[C` instead of moving the cursor when event
loop latency causes the StdinBuffer to split escape sequences.
Three layered fixes:
1. Increase StdinBuffer timeout from 10ms to 50ms (matches xterm default)
so split escape sequences are reassembled even under load.
2. Clean up stale readline listeners after @clack/prompts onboarding —
readline.emitKeypressEvents() leaves a permanent data listener that
is unnecessary for the TUI.
3. Guard in editor against CSI remnants: if a split still occurs, reject
text matching navigation escape patterns ([A-F, [H, [Z, [n~) instead
of inserting them as characters.
Closes#493
Auto-worktrees are fresh git checkouts — untracked .gsd/ files don't
carry over. Projects with the old blanket .gsd/ gitignore have planning
artifacts on disk but not in git. When createAutoWorktree makes a new
worktree, the milestones/, DECISIONS.md, REQUIREMENTS.md etc are missing,
causing auto-mode to loop on plan-slice (plan file not found in worktree).
Copy .gsd/ planning artifacts from the source repo into the new worktree
after git worktree add. Skips runtime files and the worktrees/ dir.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ensureGitignore() now detects and removes standalone ".gsd/" lines that
blanket-ignore the entire directory. Replaces with explicit runtime-only
patterns so .gsd/milestones/ planning artifacts are tracked in git.
Without this, existing projects keep the old blanket ignore forever.
New worktrees start with zero planning state because artifacts aren't
in git, causing auto-mode to re-execute completed work.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- auto.ts: wrap dispatchNextUnit body in try/finally to always reset
_dispatching to false. Without this, the reentrancy guard permanently
blocked all subsequent dispatches after the first one, causing the
dispatch gap watchdog to fire and auto-mode to stall.
- discuss.md: render depth summary as chat text (where markdown renders)
then use ask_user_questions for the short confirmation only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Downgrade internal recovery machinery to info/verbose-only so users
only see warnings when action is needed:
- "Dispatch gap detected" → verbose-only info (recovery is automatic)
- "Model not found, trying fallback" → verbose-only info
- "Failed to set model, trying fallback" → verbose-only info
- "Could not set any preferred model" → deleted (redundant)
- "New session cancelled" → info (user action, not error)
- "Unexpected phase" → info with doctor suggestion
- "No command context" → info with restart suggestion
Kept as warnings (user-actionable):
- Budget ceiling, blockers, prior slice incomplete, pre-flight,
no context, stub summary, model ambiguity, all fallbacks exhausted
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(auto): prevent infinite re-dispatch when completion key is missing
Root cause: When a task completed successfully on the first attempt,
the idempotency key was never persisted to completed-units.json.
The persistence logic (persistCompletedKey) only triggered at the
retry threshold (MAX_UNIT_DISPATCHES=3). After session restart, the
key was missing and auto-mode re-dispatched the same task endlessly.
Evidence: M008/S01/T01 was dispatched 15+ times over 3.5 hours.
T01-SUMMARY.md existed, S01-PLAN.md marked T01 as [x], but
completed-units.json had no execute-task/M008/S01/T01 entry.
Fix: Added fallback artifact check before dispatch. If the expected
artifact already exists on disk but the completion key is missing,
the key is repaired (persisted + added to in-memory set) and the
unit is skipped. This catches the gap between the closeout-based
persistence (which requires the NEXT dispatch to fire) and the
retry-threshold persistence (which requires MAX attempts).
Also fixes guided-flow-escape.test.ts: added missing cache
invalidation after rmSync (clearPathCache + invalidateStateCache).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(auto): prevent TUI freeze on cascading skip-dispatches
When multiple completed tasks are skipped in sequence (T01 artifact
fallback → T02 idempotency skip → T03 dispatch), the recursive
dispatchNextUnit calls can freeze the TUI.
Fix: invalidateStateCache() after key repair so deriveState returns
the correct next task, and use setTimeout(50ms) instead of
setImmediate to yield more generously to the event loop between
cascading skips.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(auto): systematic hardening of dispatch recovery pipeline
Five fixes addressing the 20 failure modes identified in the auto-mode
dispatch loop audit:
1. Stale runtime record cleanup: selfHealRuntimeRecords now clears
records older than 1h with phase=dispatched (crash orphans), and
also persists completion keys for records with existing artifacts.
2. Recursion depth limit: _skipDepth counter prevents TUI freeze when
many completed units are skipped in cascade. After MAX_SKIP_DEPTH
(20) skips, yields 200ms to the event loop before continuing.
3. Atomic completed-units.json writes: persistCompletedKey now uses
tmp file + renameSync to prevent partial writes on crash.
4. Skip depth tracking on both skip paths (idempotency check at L1815
and artifact fallback at L1844) with setTimeout(50ms) between skips.
5. Self-heal now also repairs missing completion keys when artifact
exists, closing the gap where crash between completion and closeout
leaves the key unwritten.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(auto): add reentrancy guard to dispatchNextUnit itself
The _handlingAgentEnd boolean only guards calls from agent_end hooks.
Direct calls from watchdog timers, step wizard, and crash recovery
can still race with an in-progress dispatch. Added _dispatching guard
that blocks concurrent external calls while allowing recursive skip
calls (_skipDepth > 0). Cleared on stopAuto.
Audit confirmed: double watchdog (#11) already prevented by existing
clearDispatchGapWatchdog in startDispatchGapWatchdog + catch/return.
Counter cleanup (#16) already handled by unitDispatchCount.clear()
in startAuto before selfHealRuntimeRecords.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(auto): final hardening for unattended multi-milestone runs
Three fixes from paranoid stress-test audit:
1. Git index.lock cleanup: Remove stale .git/index.lock (>60s old) at
auto-start. A crash during git commit/merge leaves this file behind,
blocking ALL subsequent git operations with no recovery.
2. Stub summary for complete-milestone: If the LLM fails to write a
milestone SUMMARY after MAX_UNIT_DISPATCHES attempts, generate a
stub summary to unblock the pipeline. Without this, auto-mode
loops forever in "completing-milestone" phase.
3. Pre-flight queue validation: At auto-start with multiple milestones,
scan for CONTEXT-DRAFT.md files (will pause for discussion) and
report milestone count. Gives the user early visibility into what
will happen during the run.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: deseltrus <simulacraverse@protonmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(auto): prevent nested worktree creation inside existing worktrees
When auto-mode starts inside a manual worktree (e.g., /worktree memory-db),
it unconditionally created an auto-worktree for the milestone, nesting
.gsd/worktrees/M001 inside the existing worktree. This caused GSD to
chdir into the inner worktree, read state from the wrong repo, and
report "All milestones complete" or loop on artifact verification.
Add detectWorktreeName() guard to both the start and resume paths:
if already inside a worktree, skip auto-worktree creation and work
directly on the current branch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
The multi-milestone discussion flow writes CONTEXT.md files for each
milestone but never adds depends_on YAML frontmatter. The QUEUE.md
documents the dependency chain, but the auto-mode state machine reads
dependencies from CONTEXT.md frontmatter only — not from QUEUE.md.
Without frontmatter, milestones execute in filesystem order regardless
of their actual dependency chain, causing out-of-order execution.
Fix: Added MANDATORY depends_on documentation to both discuss.md
(Phase 2, after primary milestone) and queue.md (output section).
Instructs the LLM to write frontmatter with the exact milestone IDs
from the dependency chain confirmed during the milestone split gate.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: TÂCHES <afromanguy@me.com>
* docs: add startup performance analysis and optimization plan
Profiled GSD CLI startup finding 2.2s for --version and ~3.8s for
interactive mode. Identified 5 root causes with measured timings and
created a phased optimization plan targeting <0.2s for --version
and ~0.8s for interactive startup.
* perf: speed up GSD startup with lazy loading and fast paths
- Fast-path --version/-v and --help/-h in loader.ts before importing
any heavy dependencies (2.2s → 0.15s, 14x faster)
- Lazy-load undici (~200ms) only when HTTP_PROXY env vars are set
- Skip initResources cpSync when managed-resources.json version
matches current GSD version (~128ms saved per launch)
- Lazy-load Mistral SDK (~369ms) on first API call instead of startup
- Lazy-load Google GenAI SDK (~186ms) on first API call instead of
startup
- Parallelize extension loading with Promise.all() instead of
sequential for-loop
---------
Co-authored-by: TÂCHES <afromanguy@me.com>
Eliminate slice branches — all work commits sequentially on milestone/<MID>
within auto-mode worktrees. No branch creation, switching, or merging
within a worktree. Planning artifacts (.gsd/milestones/) tracked in git
properly instead of being blanket-gitignored then force-added.
Removes ~2,600 lines: ensureSliceBranch, switchToMain, mergeSliceToMain,
mergeSliceToMilestone, shouldUseWorktreeIsolation, getMergeToMainMode,
withMergeHeal, recoverCheckout, fix-merge dispatch/labels, and associated
tests. Adds legacy_slice_branches doctor check, deprecation warnings for
git.isolation and git.merge_to_main preferences.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>