Commit graph

660 commits

Author SHA1 Message Date
TÂCHES
61f4693f16 perf: add concurrency limits to unbounded Promise.all operations (#1029)
Cap parallel async operations to prevent memory spikes when processing
large numbers of items:
- session-manager.ts: limit file loading to 10 concurrent reads
- pipeline.ts: limit job execution to 5 concurrent LLM calls
- discovery.ts: limit tool scanning to 5 concurrent scanners

Uses an inline pLimit utility in each file to avoid adding a dependency.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:29:28 -06:00
Jeremy McSpadden
fd9565299c feat(autocomplete): add /thinking completions, GSD subcommand descriptions, and test coverage (#1019)
- Add argument completions for /thinking command with all 6 levels
  (off, minimal, low, medium, high, xhigh) and descriptions
- Add descriptions to all GSD 2nd-level subcommand completions across
  14 subcommand groups (auto, mode, parallel, setup, prefs, remote,
  next, history, undo, export, cleanup, knowledge, doctor, dispatch)
- Add 35 new tests for autocomplete and fuzzy matching systems
2026-03-17 18:27:17 -06:00
Tom Boucher
2e34e83a26 fix: prevent duplicate milestone IDs when generating multiple before persisting (#961) (#1018)
gsd_generate_milestone_id scans disk for existing milestone dirs.
When called multiple times before any artifacts are written, it
returned the same ID (e.g. M001) every time because no dirs existed
yet.

Added an in-memory reservation set that tracks IDs returned by the
tool. Subsequent calls merge reserved IDs with on-disk IDs before
computing the next sequential ID, ensuring M001, M002, M003 are
returned in sequence even without intermediate disk writes.
2026-03-17 18:07:31 -06:00
TÂCHES
29e3409903 fix: consolidate duplicate formatting functions (#1011)
* fix: consolidate duplicate formatting functions

- Rename private formatDuration in verification-evidence.ts to
  formatDurationSecs to clarify its distinct fixed-seconds behavior
- Replace formatUptime implementation in bg-shell/utilities.ts with
  import of shared formatDuration (functionally equivalent for >=1s)
- Replace inline fmt lambda in cli.ts with shared formatTokenCount

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: revert cli.ts import from extensions path that breaks at runtime

The extensions directory uses a separate compilation/bundle path and
cannot be imported from cli.ts. Restores the inline fmt lambda.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:07:04 -06:00
TÂCHES
47cff561f0 fix(gsd): delete orphaned complexity.ts (#1005)
* fix(gsd): delete orphaned complexity.ts (superseded by complexity-classifier.ts)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(test): update complexity-routing tests for complexity-classifier.ts

The test file imported from the deleted complexity.ts. Removed tests
for the defunct classifyTaskComplexity function and updated all source
reads to reference complexity-classifier.ts with its actual exports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:06:58 -06:00
TÂCHES
13f9d5585d fix(search): consolidate duplicate Brave API helpers (#1010)
* fix(search): consolidate duplicate Brave API helper functions

getBraveApiKey() and braveHeaders() were duplicated across provider.ts,
tool-llm-context.ts, and tool-search.ts. Export both from provider.ts
and import in the tool files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(test): update provider export count to include braveHeaders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:06:23 -06:00
Jeremy McSpadden
818d77d5a2 fix: merge worktree to main when all milestones complete (#962) (#1007)
When the final milestone completed with no queued follow-up, stopAuto()
tore down the worktree with preserveBranch: true but never called
mergeMilestoneToMain(). All work stayed on the milestone branch,
unmerged to main.

Add merge logic to the "all milestones complete" path in
dispatchNextUnit(), mirroring the existing merge handling in the
single-milestone-complete path. Handles both worktree isolation and
branch isolation modes.
2026-03-17 18:03:35 -06:00
TÂCHES
ea0dcef576 fix(gsd): deduplicate resolveGitHeadPath function (#1015)
Move resolveGitHeadPath() and nudgeGitBranchCache() to worktree.ts as
the canonical shared location. Both auto-worktree.ts and
worktree-command.ts now import from worktree.ts instead of defining
their own copies.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:02:00 -06:00
TÂCHES
e8de7dfa30 fix(gsd): consolidate string-array normalizer functions into shared utility (#1009)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:01:52 -06:00
TÂCHES
5ecb6c6abb fix(browser-tools): document intentional silent catches, add debug logging for others (#1013)
Replaces 11 silent `.catch(() => {})` patterns with descriptive comments
(for intentional best-effort operations like networkidle waits, dialog
dismissal, browser close) or GSD_DEBUG-gated error logging (for page.goto
restore in device emulation and ensureMutationCounter in settle).

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:01:44 -06:00
TÂCHES
b1ad5c431f fix: consolidate duplicate VerificationCheck/Result type definitions (#1008)
Rename browser-tools VerificationCheck/Result to BrowserVerificationCheck/Result
to eliminate name collisions with the semantically different types in gsd/types.ts.
The browser-tools types track UI element state verification (name/passed/value),
while gsd/types.ts types track command execution verification (command/exitCode/stdout).

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:01:42 -06:00
TÂCHES
46dc70f4f6 fix(gsd): add GIT_NO_PROMPT_ENV to gitFileExec and deduplicate constant (#1006)
gitFileExec() was missing the GIT_NO_PROMPT_ENV env overlay, which meant
git could prompt for credentials and hang the process on write operations
(add, commit, revert, checkout). Extract the shared constant into
git-constants.ts to avoid duplication between git-service.ts and
native-git-bridge.ts.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:01:38 -06:00
TÂCHES
1ae7b07237 fix(remote-questions): add null coalesce for optional threadUrl (#1004)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:01:22 -06:00
Tom Boucher
a9a0f6f29f fix: auto-resume on transient server errors, not just rate limits (#886) (#957)
Previously, only rate-limit errors (429/too many requests) triggered
auto-resume with a delay. Server errors (500 Internal Server Error,
503 Service Unavailable, overloaded) paused auto-mode indefinitely,
requiring manual /gsd auto to resume. This was the core complaint in
sit idle until morning.

Now all transient provider errors auto-resume:
- Rate limits: auto-resume after retry-after delay (or 60s default)
- Server errors (500/502/503/overloaded/api_error): auto-resume after 30s
- Permanent errors (auth/billing/quota): still pause indefinitely

New classifyProviderError() function in provider-error-pause.ts provides
structured error classification with suggested delays. The agent_end
handler in index.ts now uses this instead of a simple regex check.

14 new tests cover all error categories and edge cases.

Files changed:
- provider-error-pause.ts: Add classifyProviderError(), update
  pauseAutoForProviderError() to support isTransient flag
- index.ts: Use classifyProviderError() for structured error handling
- tests/provider-error-classify.test.ts: 14 new tests
2026-03-17 18:00:43 -06:00
Tom Boucher
f432eea5a7 fix: replace ambiguous compound question in reflection step (#963) (#1002)
* Add CI/CD pipeline design spec

Three-stage promotion pipeline (Dev → Test → Prod) using npm dist-tags,
GitHub Environments, Docker images, and an LLM fixture recording system.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: replace ambiguous compound question in reflection step (#963)

The reflection prompt 'Did I get that right, or did I miss something?'
is a compound question where 'yes' maps to both possible answers.

Replaced with 'Does that capture it? If not, tell me what I missed.'
— one closed question plus an instruction, removing ambiguity.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:00:08 -06:00
TÂCHES
01e28bc345 feat(prefs): add search_provider to preferences.md (#1001)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:59:38 -06:00
Juan Francisco Lebrero
fe0f4f35e6 feat: add --events flag for JSONL stream filtering (#1000)
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
2026-03-17 17:35:44 -06:00
TÂCHES
fc44ea3fbe fix(gsd): remove STATE.md update instructions from all prompts (#983)
* fix(gsd): clear all caches after discuss dispatch so picker sees new CONTEXT files

guided-flow.ts called only invalidateStateCache() after waitForIdle(),
leaving dirEntryCache stale. resolveSliceFile("CONTEXT") missed files
written during the discuss session, keeping the just-discussed slice
recommended and preventing the allDiscussed exit gate from firing.

Swap to invalidateAllCaches() at both call sites (discuss loop and
queue reorder), matching the pattern used throughout auto.ts.

Fixes #977

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(gsd): remove STATE.md update instructions from all prompts (#978)

STATE.md is a derived runtime file rebuilt by auto.ts after every unit.
Prompts telling LLMs to update it caused git staging errors when the
LLM ran `git add .gsd/` and hit the gitignore barrier, leaving sessions
stuck. Removed redundant STATE.md instructions from 13 prompts, made
commit instructions explicit about which files to stage, and switched
bootstrap `nativeAddPaths` to `nativeAddAll` to respect .gitignore in
the CLI fallback path.

Closes #978

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:27:40 -06:00
TÂCHES
dfc41e105d fix(gsd): clear all caches after discuss dispatch so picker sees new CONTEXT files (#981)
guided-flow.ts called only invalidateStateCache() after waitForIdle(),
leaving dirEntryCache stale. resolveSliceFile("CONTEXT") missed files
written during the discuss session, keeping the just-discussed slice
recommended and preventing the allDiscussed exit gate from firing.

Swap to invalidateAllCaches() at both call sites (discuss loop and
queue reorder), matching the pattern used throughout auto.ts.

Fixes #977

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:25:59 -06:00
Juan Francisco Lebrero
7868761ca0 feat: add 10 bundled skills for UI, quality, and code optimization (#999)
Add community-sourced skills covering:

Coding & Quality:
- code-optimizer: 13-domain parallel optimization audit
- react-best-practices: 57 React/Next.js performance rules (Vercel)
- best-practices: Web security, CSP, HTTPS, HTML validity

UI & Design:
- userinterface-wiki: 152 UI/UX rules (animations, springs, UX laws, typography)
- make-interfaces-feel-better: 16 practical polish principles

Testing & Audit:
- web-quality-audit: Lighthouse-style 150+ checks
- accessibility: WCAG guidelines and ARIA patterns
- core-web-vitals: LCP/CLS/INP deep dive
- web-design-guidelines: Vercel Web Interface Guidelines

Tooling:
- agent-browser: Browser automation CLI for testing and scraping
2026-03-17 17:23:39 -06:00
Jeremy McSpadden
642323a489 fix(auto): dispatch retry after verification gate failure (#998)
When the verification gate fails with retries remaining, handleAgentEnd
sets pendingVerificationRetry and deletes the completion key, but then
returns early without calling dispatchNextUnit. This leaves auto-mode
active but permanently stalled — no new unit is ever dispatched because
the dispatch chain is broken.

Fix: call dispatchNextUnit immediately after setting up the retry state,
with a fallback to the dispatch gap watchdog if dispatch throws.
2026-03-17 17:20:29 -06:00
Jeremy McSpadden
f85c41c693 feat(ux): group model list by provider in /gsd prefs wizard (#993)
* feat(ux): group model list by provider in /gsd prefs wizard

The model selection in configureModels() was a single flat alphabetical
list that became unwieldy with many providers. This groups models under
provider headers (e.g. "─── anthropic (24) ───") so users can quickly
scan to the right provider section.

Changes:
- ExtensionSelectorComponent: add SEPARATOR_PREFIX convention for
  non-selectable group headers. Navigation skips separators, Enter
  ignores them, and they render with borderAccent styling.
- configureModels: build grouped option list with provider headers
  instead of flat map.
- New test: extension-selector-separator.test.ts (6 tests).

* fix(ci): use node:test instead of vitest in extension-selector test

tsconfig.extensions.json does not include vitest type declarations,
causing TS2307 in CI. Rewrite test to use node:test + node:assert
to match the convention used by other extension tests.

* fix(ci): rewrite separator test to avoid TS parameter property issue

The extension-selector component transitively imports countdown-timer.ts
which uses TypeScript parameter properties (private tui: TUI). Node's
--experimental-strip-types cannot handle these, causing ERR_UNSUPPORTED_
TYPESCRIPT_SYNTAX in CI.

Rewrite the test to verify the separator detection logic and model
grouping contract without importing the component. Duplicates the
isSeparator/nextSelectable helpers and tests them directly.
2026-03-17 17:20:13 -06:00
Juan Francisco Lebrero
8df6f7b75a feat: add --answers flag for headless answer injection (#982)
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.
2026-03-17 17:19:55 -06:00
TÂCHES
f2838d326f fix: enforce GSDError usage and activate unused error codes (#997)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:14:07 -06:00
TÂCHES
196be59d71 fix: deduplicate tierLabel/tierOrdinal exports (#988)
* fix: deduplicate tierLabel and tierOrdinal exports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: update tierLabel test to accept re-export pattern

The test was checking source text for "export function tierLabel" which
doesn't match the re-export syntax "export { tierLabel } from ...".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:11:52 -06:00
TÂCHES
2687f97a6b fix: deduplicate getMainBranch implementations (#994)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:06:20 -06:00
TÂCHES
6b3572c858 fix: add error handling for unhandled promise rejections (#992)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:06:17 -06:00
TÂCHES
058f682f67 fix: deduplicate formatTokenCount into shared format-utils (#987)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:06:14 -06:00
TÂCHES
eded07a257 fix: add debug logging to silent catch blocks in auto.ts (#986)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:06:11 -06:00
TÂCHES
2bdcabfbfc fix: deduplicate formatDuration into shared format-utils (#989)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:06:06 -06:00
TÂCHES
8877e01083 refactor: add domain-grouped re-exports for preferences module (#996)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:05:54 -06:00
TÂCHES
2df7a2320b fix: remove dead github-client.ts (never imported) (#990)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:05:44 -06:00
TÂCHES
482bbf678b fix: deduplicate parseJSONL and unify MAX_JSONL_BYTES constant (#985)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:05:35 -06:00
TÂCHES
fbadd369f4 Merge pull request #976 from jeremymcs/feature/onboarding-detection-wizard
feat: project onboarding detection and init wizard
2026-03-17 16:52:16 -06:00
Jeremy McSpadden
a2a701b129 fix: inline bundled extension path parsing in subagent
The subagent extension imported parseBundledExtensionPaths via a
relative path (../../../bundled-extension-paths.js) that resolves
correctly in the source tree but breaks when extensions are synced
to ~/.gsd/agent/extensions/ at runtime. Inline the trivial split
logic so the extension is self-contained.
2026-03-17 17:45:48 -05:00
Jeremy McSpadden
d5161fddb9 feat: add project onboarding detection and init wizard
Replace the silent .gsd/ bootstrap with an interactive init wizard that
detects project state, offers v1 migration, and guides users through
per-project configuration before their first milestone.

New commands:
- /gsd init — project init wizard (detect, configure, bootstrap .gsd/)
- /gsd setup — global setup status and routing to existing config commands

Detection engine (detection.ts):
- detectProjectState() identifies none/v1-planning/v2-gsd/v2-gsd-empty
- detectProjectSignals() scans for language, monorepo, CI, tests, package manager
- Auto-detects verification commands from package.json, Cargo.toml, go.mod, etc.
- isFirstEverLaunch() / hasGlobalSetup() for global state checks

Init wizard (init-wizard.ts):
- 8-step wizard: git → mode → verification → git prefs → instructions → advanced → bootstrap
- Every step skippable with sensible defaults
- offerMigration() when .planning/ detected (migrate/fresh/cancel)
- handleReinit() for safe re-init on existing projects
- Writes preferences.md from wizard answers + seeds CONTEXT.md with detected signals

Smart entry integration (guided-flow.ts):
- showSmartEntry() now runs detection before any bootstrap
- v1 .planning/ → migration offer before anything else
- No .gsd/ → init wizard instead of silent bootstrap
- Existing .gsd/ → unchanged behavior (zero regression)
2026-03-17 17:31:52 -05:00
Lex Christopherson
c9c0c41983 fix(gsd): require grammatical narration in prompts 2026-03-17 16:26:23 -06:00
Lex Christopherson
8aa8e6c494 docs: document all preferences.md fields in reference and template
Add 9 missing fields to preferences-reference.md: skill_staleness_days,
git.manage_gitignore, dynamic_routing, auto_visualize, auto_report,
parallel, verification_commands, verification_auto_fix, and
verification_max_retries. Add examples for dynamic routing, parallel
execution, and verification. Update the preferences template to include
all fields from the schema.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:26:23 -06:00
TÂCHES
ecedbfe9df Merge pull request #967 from jeremymcs/feat/export-html-all
feat: add /gsd export --html --all for retrospective milestone reports
2026-03-17 16:25:42 -06:00
TÂCHES
7b2feb64e4 Merge pull request #969 from gsd-build/fix/duplicate-marketplace-test
fix: remove duplicate marketplace-discovery test
2026-03-17 16:23:27 -06:00
TÂCHES
23bc77fc56 Merge pull request #968 from gsd-build/fix/duplicate-bundled-extension-paths
fix: consolidate duplicate bundled-extension-paths.ts
2026-03-17 16:23:11 -06:00
TÂCHES
afeb6f5e3b Merge pull request #966 from gsd-build/fix/duplicate-mcp-server
fix: consolidate duplicate mcp-server.ts
2026-03-17 16:23:04 -06:00
Lex Christopherson
6114ede489 fix: remove duplicate marketplace-discovery test
Migrated unique resolvePluginRoot and inspectPlugin tests from the older
file into the comprehensive contract test file at src/tests/, then
deleted the duplicate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:18:45 -06:00
Lex Christopherson
12e65afd36 fix: consolidate duplicate bundled-extension-paths.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:17:53 -06:00
Jeremy McSpadden
c9f63f8e93 feat: add /gsd export --html --all for retrospective milestone reports
When --all is passed alongside --html, generates a report snapshot for
every milestone that doesn't already have one in the reports index.
This fills the progression timeline with cards for completed milestones
that were finished before the HTML report feature existed.

- Deduplicates against existing reports.json entries to avoid duplicates
- Tags completed milestones with kind "milestone", active with "manual"
- Tracks cumulative slice/milestone progress per snapshot for the index
- Adds --html and --html --all to export autocomplete suggestions
- Updates help text to show [--all] flag
2026-03-17 17:17:50 -05:00
Lex Christopherson
e50e6458b6 fix: consolidate duplicate mcp-server.ts
Remove the unused copy at src/resources/extensions/gsd/mcp-server.ts.
The canonical implementation lives at src/mcp-server.ts and is the only
one imported by cli.ts and tested by mcp-server.test.ts. The extension
copy had zero imports and was dead code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:17:39 -06:00
Jeremy McSpadden
add957ed31 feat: add /gsd update slash command for in-session self-update (#964)
The update banner already referenced `/gsd:update` but the command
didn't exist. This adds `/gsd update` as a proper subcommand that
checks the npm registry and runs `npm install -g gsd-pi@latest`
when a newer version is available.

- Register `update` in subcommand completions and help text
- Add `handleUpdate()` that reuses `compareSemver` from update-check
- Fix banner text from `/gsd:update` to `/gsd update` (space, not colon)
- Add tests for completion registration and help description
2026-03-17 16:13:02 -06:00
Juan Francisco Lebrero
99c3375f18 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 16:03:59 -06:00
Jeremy McSpadden
0e0f47ef9f fix: failure recovery & resume safeguards (all 4 waves) (#956)
* fix: prevent data loss on crash with atomic writes, file locking, and error handling

Wave 1 of failure recovery safeguards:

1. Atomic session file rewrites (tmp+rename) — _rewriteFile() and forkFrom()
   now use atomicWriteFileSync to prevent session file corruption on crash
2. Atomic auto.lock writes — crash-recovery.ts writeLock() uses tmp+rename
   so the crash detection system itself can't be corrupted
3. unhandledRejection handler — catches silent process death from unhandled
   promise rejections in OAuth, extensions, LSP, or MCP connections
4. try/catch in emitToolCall — matches pattern used by emitUserBash,
   emitContext, and emitToolResult to prevent extension handler crashes
   from killing the entire agent turn
5. File locking on session appends — prevents concurrent pi instances from
   interleaving partial JSON lines in session JSONL files using the same
   proper-lockfile pattern established in auth-storage.ts and settings-manager.ts

* fix: add OAuth timeouts, RPC exit detection, and command context guards

Wave 2 of failure recovery safeguards:

1. OAuth fetch timeouts — all fetch() calls across all OAuth providers
   (Anthropic, OpenAI Codex, Google Antigravity, Google Gemini CLI,
   GitHub Copilot) now have 30-second AbortSignal.timeout() to prevent
   indefinite hangs when OAuth servers are unresponsive
2. RPC subprocess exit detection — pending requests are now rejected
   when the agent subprocess exits unexpectedly, preventing indefinite
   hangs in the RPC client
3. Extension command context guards — default handlers for newSession,
   fork, navigateTree, switchSession, and reload now throw explicit
   errors instead of silently returning success when called before
   bindCommandContext()
4. OAuth error detail preservation — token refresh errors now preserve
   the original error as `cause` for better diagnostics

* fix: resource cleanup, LSP retry, and crash detection on session resume

Wave 3 of failure recovery safeguards:

1. Atomic completed-units.json cleanup — milestone completion writes
   now use tmp+rename pattern for consistency with auto-recovery.ts
2. Bash temp file cleanup — track temp files created for large output
   and register a process exit handler to clean them up
3. Settings write queue flush on shutdown — call settingsManager.flush()
   during interactive mode shutdown so queued writes aren't lost
4. LSP initialization retry — wrap getOrCreateClient with up to 2 retries
   with exponential backoff (1s, 2s) for transient spawn failures
5. Crash detection on session resume — wasInterrupted() checks if last
   assistant turn had tool calls without results, shows warning on resume

* fix: blob garbage collection and LSP debug logging

Wave 4 of failure recovery safeguards:

1. Blob garbage collection — BlobStore.gc(referencedHashes) removes
   orphaned blobs not referenced by any session file, plus totalSize()
   for monitoring blob directory growth
2. LSP JSON parse error logging — malformed LSP messages are now logged
   at debug level (when DEBUG env is set) instead of being silently dropped
2026-03-17 16:03:49 -06:00
Tom Boucher
614012f38a fix: add git.manage_gitignore preference to opt out of .gitignore changes (#950) (#952)
When set to false in .gsd/preferences.md, GSD will not modify .gitignore
at all — no baseline patterns added, no self-healing, no untracking.

Usage in preferences.md:
  git:
    manage_gitignore: false

Files changed:
- git-service.ts: Add manage_gitignore to GitPreferences interface
- gitignore.ts: Early return when manageGitignore is false
- auto.ts: Pass manage_gitignore preference to ensureGitignore
- preferences.ts: Parse and validate manage_gitignore in git config
2026-03-17 15:27:34 -06:00