Kept both health gate (main) and debug timer (PR) in auto.ts.
Added agentInstructionsBlock to fullSystem composition in index.ts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Combine budget fields (contextWindowTokens, truncationSections,
continueHereFired) from PR #594 with prompt char tracking fields
(promptCharCount, baselineCharCount) from main.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Telegram Bot API as a third remote questions channel alongside
Discord and Slack. Implements the ChannelAdapter interface with inline
keyboard buttons, callback query handling, text reply polling, and
supergroup message URL generation.
Closes#645
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extension-based providers like pi-claude-cli may not require credentials
in auth.json, causing shouldRunOnboarding() to always return true and
repeat the wizard every launch. Now checks if a defaultProvider is
already set in settings before triggering the wizard.
Merge main into feat/context-window-budget, combining:
- Budget fields (contextWindowTokens, truncationSections, continueHereFired)
from the PR with routing fields (tier, modelDowngraded) from main in
UnitMetrics interface
- Unified opts parameter pattern in snapshotUnitMetrics
- KNOWLEDGE.md step from main with template path references from the PR
in execute-task.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add workflow mode system (solo/team) with /gsd mode command
Introduces a `mode` preference that bundles sensible defaults for solo
developers vs team workflows, replacing the need to manually configure
5-8 individual git preferences.
* fix: resolve TS2339 — use string narrowing for ctx.ui.select return type
Two fixes for the model configuration bleeding between simultaneous
GSD instances that share the same global settings.json.
## Root Cause
1. `setDefaultModelAndProvider()` always persisted to `~/.gsd/agent/settings.json`
(global), so when either instance's interactive mode changed models (via
Ctrl+P or /model), it overwrote the other instance's saved default.
2. When auto-mode dispatched a new unit (after context wipe), if no
per-unit-type model preference was configured, the session picked up
the default from the now-contaminated global settings file.
## Fix 1: Project-scoped model persistence (settings-manager.ts)
`setDefaultModelAndProvider()`, `setDefaultModel()`, and `setDefaultProvider()`
now persist to project-level settings (`.pi/settings.json`) when a project
settings file exists, falling back to global only when no project context
is available. This prevents concurrent instances from overwriting each
other's model choice.
Added `hasProjectSettingsFile()` helper to detect project context.
## Fix 2: Auto-mode model capture (auto.ts)
Captures the session's model at auto-mode start (`autoModeStartModel`).
At each unit dispatch, if no model preference is configured for the unit
type, the captured model is re-applied with `persist: false`. This
ensures each auto-mode session maintains its own model regardless of
what other instances write to the shared settings file.
## Tests
3 new tests covering:
- Project settings file isolates model from global
- Two projects have independent model configs
- autoModeStartModel concept prevents model drift
All 448 existing tests pass.
Fixes#650
* fix: bg_shell ready_port timeout and error handling (#428)
When a server fails to bind to the configured ready_port, the process
would stay in "starting" status indefinitely after the probing interval
cleared, with no error surfaced to the agent. This fixes the hang by:
- Transitioning process to "error" status when port probing times out
- Detecting process exit during port polling and reporting stderr context
- Adding ready_timeout parameter for custom timeout values
- Including stderr output in waitForReady timeout/error responses
- Registering SIGTERM/SIGINT handlers to clean up bg processes on exit
Closes#428
* feat: add /gsd quick command and agent-instructions.md injection (#425)
Implements two features from issue #425:
1. `/gsd quick <task>` — lightweight task execution with GSD guarantees
(atomic commits, state tracking) without the full milestone ceremony.
Creates `.gsd/quick/<num>-<slug>/` directory, a git branch, and
dispatches a focused prompt for in-session execution.
2. Agent instructions file — loads `~/.gsd/agent-instructions.md` (global)
and `.gsd/agent-instructions.md` (project), injects into every GSD
agent session via the before_agent_start hook. Lets users add durable
instructions like notification preferences or environment constraints.
Closes#425
---------
Co-authored-by: TÂCHES <afromanguy@me.com>
* feat(doctor): add 7 runtime health checks with auto-fix
Add comprehensive runtime health monitoring to /gsd doctor:
- stale_crash_lock: detect dead auto.lock from crashed sessions, auto-clear
- orphaned_completed_units: find completed-unit keys referencing missing artifacts, auto-remove
- stale_hook_state: detect residual hook cycle counts with no running session, auto-clear
- activity_log_bloat: flag activity/ dir exceeding 500 files or 100MB, auto-prune (7-day retention)
- state_file_missing: detect missing STATE.md when milestones exist, auto-generate
- state_file_stale: detect STATE.md drift (wrong phase/milestone/slice), auto-rebuild
- gitignore_missing_patterns: detect missing critical GSD runtime patterns in .gitignore, auto-fix
All checks are non-fatal (gracefully degrade on read errors) and respect
the existing fix/fixLevel system. Includes 34 new test assertions across
9 test scenarios in doctor-runtime.test.ts.
* feat(doctor): add proactive healing layer for auto-mode
Three new mechanisms for automatic health monitoring:
1. Pre-dispatch health gate: runs before each unit dispatch in auto-mode.
Checks for stale crash locks (auto-clears) and corrupt merge state
(auto-heals via abortAndReset). Pauses auto-mode if critical issues
can't be resolved.
2. Health score tracking: records error/warning/fix counts after each
post-unit doctor run. Tracks trends (improving/stable/degrading)
across a sliding window of 50 snapshots. Monitors consecutive
error unit streaks.
3. Auto-heal escalation: when deterministic fixes can't resolve errors
after 5 consecutive units AND health trend is not improving,
automatically dispatches LLM-assisted heal (dispatchDoctorHeal).
Single-fire per session to prevent spam. Defers escalation when
trend is improving (fixes are working, just slowly).
Integration points in auto.ts:
- resetProactiveHealing() on start/stop
- preDispatchHealthGate() before deriveState in dispatchNextUnit
- recordHealthSnapshot() + checkHealEscalation() in post-unit hook
- formatHealthSummary() available for dashboard display
Includes 30 test assertions across 15 scenarios.
* feat: add worktree post-create hook for environment setup (#597)
Add git.worktree_post_create preference — a script path that GSD
runs after creating any worktree (both auto-mode and manual /worktree).
The script receives SOURCE_DIR and WORKTREE_DIR as environment
variables, enabling users to copy .env files, symlink asset
directories, or run other setup commands that git worktrees don't
inherit from the main tree.
Implementation:
- Add worktree_post_create field to GitPreferences interface
- Add validation in validatePreferences (must be non-empty string)
- Add runWorktreePostCreateHook() in auto-worktree.ts — resolves
relative paths against project root, runs with 30s timeout,
failure is non-fatal (warning only)
- Integrate hook call in createAutoWorktree() (auto-mode path)
- Integrate hook call in worktree-command.ts (manual /worktree path)
- Update docs/configuration.md with full usage guide and example
hook script
- Update preferences-reference.md with field documentation
Example configuration:
git:
worktree_post_create: .gsd/hooks/post-worktree-create
Example hook script:
#!/bin/bash
cp "$SOURCE_DIR/.env" "$WORKTREE_DIR/.env"
ln -sf "$SOURCE_DIR/assets" "$WORKTREE_DIR/assets"
Closes#597
* fix: use Node.js scripts in hook tests for Windows compatibility
Replace bash hook scripts with cross-platform Node.js scripts in
worktree-post-create-hook.test.ts. On macOS/Linux, scripts use
#!/usr/bin/env node shebang. On Windows, generates batch files
that invoke node -e. Fixes windows-portability CI failures.
* fix: Windows CI failures in worktree post-create hook tests
- Use path.isAbsolute() instead of startsWith("/") to detect absolute
paths on Windows (fixes double-path bug like C:\...\C:\...)
- Add .bat extension to hook scripts on Windows so they are recognized
as executable by cmd.exe
- Extract isWin constant and hookPath() helper for consistent
platform-aware test setup
Fixes 3 failing tests in windows-portability CI job:
- executes hook script with correct env vars
- supports absolute hook paths
- hook can copy files from source to worktree
* fix: adopt main's help command and error message in commands.ts
The auto-merge missed main's addition of the help handler, showHelp
function, and updated description/subcommands array. Added them
manually and updated the visualizer help text to reflect 7-tab TUI.
* fix: write Windows hook scripts as .bat + companion .js file
The previous approach embedded multi-line JavaScript in a node -e "..."
argument inside the .bat file. cmd.exe splits on newlines, so each JS
line was interpreted as a separate batch command ('const' is not
recognized...).
Now writes the JS code to a companion .js file and the .bat invokes
it with `node "%~dp0<file>.js"`, which works reliably on Windows.
---------
Co-authored-by: TÂCHES <afromanguy@me.com>
* docs(M004): context, requirements, and roadmap
* chore(M004): record integration branch
* chore(M004/S01): auto-commit after research-slice
* docs(S01): add slice plan
* chore(M004/S01/T01): auto-commit after execute-task
* chore(M004/S01/T02): auto-commit after execute-task
* chore(M004/S01): auto-commit after complete-slice
* chore(M004/S01): auto-commit after reassess-roadmap
* chore(M004/S02): auto-commit after research-slice
* docs(S02): add slice plan
* chore(M004/S02/T01): auto-commit after execute-task
* chore(M004/S02/T02): auto-commit after execute-task
* chore(M004/S02): auto-commit after complete-slice
* docs(M004): reassess roadmap after S02
* chore(M004/S03): auto-commit after research-slice
* docs(S03): add slice plan
* chore(M004/S03/T01): auto-commit after execute-task
* chore(M004/S03/T02): auto-commit after execute-task
* chore(M004/S03/T03): auto-commit after execute-task
* chore(M004/S03): auto-commit after complete-slice
* chore(M004): record integration branch
* chore(M004/S04): auto-commit after research-slice
* docs(S04): add slice plan
* chore: update state to executing S04
* chore(M004/S04/T01): auto-commit after execute-task
* chore(M004/S04/T02): auto-commit after execute-task
* chore(M004/S04): auto-commit after complete-slice
* docs(M004): reassess roadmap after S04
* chore(M004/S05): auto-commit after research-slice
* docs(S05): add slice plan
* chore(M004/S05/T01): auto-commit after execute-task
* chore(M004/S05/T02): auto-commit after execute-task
* chore(M004/S05): auto-commit after complete-slice
* chore(M004/S05): auto-commit after reassess-roadmap
* chore(M004/S06): auto-commit after research-slice
* docs(S06): add slice plan
* chore: update STATE.md for S06 execution
* chore(M004/S06/T01): auto-commit after execute-task
* chore(M004/S06/T02): auto-commit after execute-task
* chore(M004/S06): auto-commit after complete-slice
* chore(M004/S06): auto-commit after reassess-roadmap
* chore(M004/S07): auto-commit after research-slice
* docs(S07): add slice plan
* chore(M004/S07/T01): auto-commit after execute-task
* chore(M004/S07): auto-commit after complete-slice
* chore(M004): auto-commit after complete-milestone
* docs(M004): milestone summary and state update
* fix: path traversal guard, ATTACH allowlist, restore deleted export-html
- db-writer.ts: validate saveArtifactToDb path stays within .gsd/ using
resolve() to prevent directory traversal via LLM tool input
- gsd-db.ts: replace single-quote-only ATTACH guard with strict character
allowlist regex for worktree DB path validation
- Restore accidentally deleted pkg/dist/core/export-html/ templates
(removed in b30baeb7 during S04/T01 auto-execution)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove .gsd/ from tracking — private project work docs
.gsd/ contains personal planning artifacts, not public source code.
Replace granular runtime gitignore rules with blanket .gsd/ ignore.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: resolve 4 strict typecheck errors for tsconfig.extensions.json
- gsd-db.ts: cast origEmit.apply return to boolean
- md-importer.ts: double-cast Requirement to Record<string, unknown>
- gsd-inspect.test.ts: remove extraneous arg from report()
- md-importer.test.ts: nullish coalesce on optional chain to boolean
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: update compression test to accept DB-aware helper pattern
The context-compression test checks auto-prompts.ts source for
inlineGsdRootFile calls, but M004 replaces these with DB-aware
helpers (inlineRequirementsFromDb etc). Accept either pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use single-quote blocklist instead of path allowlist for ATTACH guard
Allowlist regex broke on Windows temp paths containing tildes (RUNNER~1),
parens, and other valid OS path chars. The only actual injection vector
for ATTACH DATABASE '...' is a single quote breaking the SQL literal.
Block that one char instead of trying to enumerate all valid path chars.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* revert: restore .gsd/ tracking and original gitignore rules
The blanket .gsd/ ignore was incorrect — GSD users need planning
files tracked. Restore main's granular runtime-only gitignore and
re-add all .gsd/ planning files from main.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use double quotes in git commit message for Windows compatibility
Single quotes in shell commands don't work on Windows PowerShell.
The commit message 'add gsd dir' was split into separate pathspecs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add workflow visualizer TUI overlay with 4-tab interactive view
Add `/gsd visualize` command that opens a full-screen TUI overlay with
four tabs: Progress (milestone/slice/task tree), Dependencies (ASCII
dep graph), Metrics (cost/token bar charts), and Timeline (chronological
execution history). Supports Tab/1-4 switching, per-tab scrolling, and
auto-refresh every 2s. Opt-in auto-trigger hint after milestone
completion via `auto_visualize` preference.
New files:
- visualizer-data.ts: async data loader aggregating state + metrics
- visualizer-views.ts: 4 pure view renderers
- visualizer-overlay.ts: overlay class with tab/scroll/cache management
- tests/visualizer-views.test.ts: 21 assertions on view renderers
- tests/visualizer-data.test.ts: 33 source contract assertions
Modified:
- commands.ts: register "visualize" subcommand + handler
- auto.ts: milestone completion hint when auto_visualize enabled
- preferences.ts: add auto_visualize preference key
* feat: expand workflow visualizer with 8 new features across 7 tabs
Add critical path analysis, risk heatmap, cost projections, Gantt
timeline, live agent activity, diff/changelog, search/filter, and
export capabilities to the workflow visualizer overlay.
- Critical path: O(V+E) topological sort + longest path algorithm
with slack computation for milestones and slices
- Risk heatmap: colored block grid with legend and summary counts
- Cost projections: avg cost/slice, burn rate, sparkline, budget warnings
- Gantt timeline: horizontal bars with phase coloring and time axis
(falls back to list view on narrow terminals)
- Agent activity: real-time status, progress bar, completion rate
- Changelog: parsed SUMMARY files with mtime-based caching
- Search/filter: / enters filter mode, f cycles field, supports
keyword/status/risk filtering
- Export: standalone writeExportFile() + m/j/s keys for
markdown/JSON/snapshot export from overlay
Tab bar expanded from 4 to 7 tabs. 146 new test assertions across
4 test files. All 604 tests pass with zero regressions.
* fix: update help text to reflect 7-tab visualizer
LSP was never activated in interactive sessions because the default
active tools list hardcoded only read/bash/edit/write. This adds lsp
to that list and ships four new capabilities alongside edit sync and
stronger prompt guidance.
- Add "lsp" to default active tools in agent-session.ts
- New actions: incoming_calls, outgoing_calls, format, signature
- Wire edit/write tools to notify LSP clients on file changes
- Strengthen system prompt and GSD prompt with full LSP operation catalog
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: allow extensions to use 'yaml' and rework frontmatter parsing
* feat: add run-hook command for manual hook execution
* fix: sanitize slashes in unitType for runtime file paths
* fix(auto): preserve milestone branch on stop to prevent work loss (#601)
When auto-mode stops mid-milestone, the worktree teardown was
force-deleting the milestone branch (git branch -D). On the next
/gsd auto, a fresh branch was created from the integration branch,
losing all committed work from the prior session. This caused
auto-mode to re-trigger milestone planning instead of resuming
execution.
Three changes:
1. stopAuto: pass preserveBranch: true to teardownAutoWorktree so the
milestone branch survives. Also auto-commit dirty state before
leaving the worktree.
2. createAutoWorktree: when the milestone branch already exists,
re-attach the worktree to it as-is instead of force-resetting it
to the integration branch (which would also destroy prior work).
3. startAuto: detect surviving milestone branches when state appears
to be pre-planning. Skip the early-return to discuss/plan flow
and let the worktree setup + dispatch handle it from the branch's
actual state.
The branch is still deleted during mergeMilestoneToMain (milestone
completion) after the work has been squash-merged, so no cleanup
change is needed there.
* fix: add null guard for state.activeMilestone to satisfy TypeScript
* refactor: replace serial prefs wizard with categorized menu
The /gsd prefs wizard previously dumped 20+ prompts in sequence, which
was overwhelming. This refactors it into a category picker loop where
users select from 7 categories (Models, Timeouts, Git, Skills, Budget,
Notifications, Advanced), configure only what they need, and return to
the menu with updated summaries showing current values at a glance.
- Extract 7 category functions from monolithic handlePrefsWizard
- Add buildCategorySummaries() for current-value display in menu
- Category loop with Save & Exit / Escape to serialize and write
- No logic changes to individual prompts — pure structural refactor
* fix: narrow ctx.ui.select return type for TypeScript strict mode
ctx.ui.select returns string | string[], so startsWith is not available
without narrowing. Extract to string with typeof guard before dispatching.
When /gsd auto is called with no milestone, it delegates to the
discussion flow (showSmartEntry). Previously, if the LLM didn't follow
the discussion protocol — e.g. for simple tasks where it judged the
ceremony overkill and started editing directly — auto mode never
activated. The function returned after showSmartEntry with no retry
or notification, leaving the user in a loop.
Fix: After showSmartEntry returns in both the no-milestone and
pre-planning paths, re-derive state from disk. If the LLM produced
enough artifacts (CONTEXT.md, ROADMAP.md, or advanced the phase),
auto mode proceeds instead of returning. If not, a clear warning
tells the user what happened and what to do next.
This handles the case where the LLM writes files but doesn't follow
the exact discussion → CONTEXT.md → checkAutoStartAfterDiscuss flow.
Adds /gsd help (aliases: h, ?) that displays a grouped reference of
every available subcommand with usage, flags, and shortcuts.
Commands are organized by category: Workflow, Visibility, Course
Correction, Project Knowledge, Configuration, and Maintenance.
Also simplifies the "Unknown command" error to point users to /gsd help
instead of listing all commands inline.
In worktree contexts, the LLM received relative output paths like
`.gsd/milestones/M002/slices/S01/S01-RESEARCH.md` combined with a
working directory containing `.gsd/worktrees/M002`. The double .gsd
in the resulting path confused the LLM, which resolved the relative
path against the project root instead of the worktree — writing
artifacts to the wrong location and triggering loop detection.
All write-target path variables (outputPath, taskSummaryPath,
sliceSummaryPath, milestoneSummaryPath, replanPath, planPath,
uatResultPath, assessmentPath, secretsOutputPath) are now passed
as absolute paths via join(base, relPath), eliminating the need
for the LLM to do path arithmetic in confusing worktree layouts.
Solo developers can fire-and-forget thoughts during auto-mode execution
via /gsd capture. The system triages accumulated captures at natural seams
between tasks, classifies their impact into five types (quick-task, inject,
defer, replan, note), and proposes appropriate action with user confirmation
for plan-modifying resolutions.
Pipeline: capture → triage → confirm → resolve → resume
- /gsd capture appends to .gsd/CAPTURES.md (worktree-aware)
- Triage fires automatically between tasks in handleAgentEnd
- Five resolution types: inline quick task, inject task into plan,
defer for reassess, trigger replan with context, acknowledge as note
- Dashboard overlay shows pending capture count badge
- Capture context injected into replan-slice and reassess-roadmap prompts
- Parse failure falls back to note — pipeline never blocks
New modules: captures.ts, triage-ui.ts, triage-resolution.ts
New prompt: triage-captures.md
52 tests across 3 test files, all passing
Requirements R045-R051 validated
Closes#505
chore: pre-merge cleanup — remove dead code, single-read dashboard optimization
- Remove processTriageResults() and associated types (dead code, superseded by
inline resolution in auto.ts dispatch loop)
- Add countPendingCaptures() for single-read regex count on dashboard hot path
(replaces two-phase hasPendingCaptures + loadPendingCaptures)
- Update triage-dispatch tests to match new implementation
* feat: dynamic model routing for token consumption optimization (#575)
Add complexity-based model routing that classifies units into light/standard/heavy
tiers and routes to cheaper models when appropriate. Reduces token consumption
by 20-50% for users on capped plans.
- Complexity classifier with heuristic-based tier assignment (no LLM call)
- Model router with downgrade-only semantics (user's config is ceiling)
- Budget-pressure-aware routing (more aggressive as budget fills)
- Cross-provider cost comparison via bundled cost table
- Hook classification support
- Escalation on failure (light → standard → heavy)
- Full preference validation and merge support
- Metrics tracking with tier and downgrade fields
- 40 new tests (classifier, router, cost table)
Closes#575
* feat: phases 2-4 — dashboard, adaptive learning, task introspection
Phase 2 — Observability & Dashboard:
- Tier badge [L]/[S]/[H] displayed in progress widget next to phase label
- Dynamic routing savings summary shown in footer when units have been downgraded
- Tier and modelDowngraded fields passed through snapshotUnitMetrics
Phase 3 — Adaptive Learning:
- New routing-history.ts: tracks success/failure per tier per unit-type pattern
- Rolling window of 50 entries per pattern to prevent stale data
- User feedback support (over/under/ok) with 2x weight vs automatic
- Failure rate >20% auto-bumps tier for that pattern
- Tag-specific patterns (e.g. execute-task:docs) for granular learning
- History persists to .gsd/routing-history.json
- Classifier consults adaptive history before finalizing tier
Phase 4 — Task Plan Introspection:
- Code block counting in task plans (5+ blocks → heavy)
- Complexity keyword detection: migration, architecture, security,
performance, concurrency, compatibility
- Multiple complexity keywords (2+) → heavy, single → standard
- New codeBlockCount and complexityKeywords fields in TaskMetadata
Tests: 16 new tests (routing history + introspection), 419 total passing
* test: add feature-branch lifecycle integration test
Proves the core invariant: milestone worktrees branch from and merge
back to the feature branch, never touching main. Covers:
- Full lifecycle with unique milestone IDs (M001-xxxxxx format)
- Untracked .gsd/ planning files copied into worktree
- Multiple successive milestones on the same feature branch
- Main branch completely untouched throughout
* fix: commitCount return type (parseInt)
Update both docs/configuration.md (user-facing) and
src/resources/extensions/gsd/docs/preferences-reference.md (internal)
with complete coverage of all GSD preferences:
- Add /gsd prefs subcommands table (global, project, status, wizard, setup)
- Document token_profile (budget/balanced/quality) and phases settings
- Document context_pause_threshold field
- Document remote_questions configuration (Slack/Discord)
- Document git.merge_strategy (squash/merge) and git.isolation (worktree/branch)
- Expand post_unit_hooks with missing agent field
- Expand pre_dispatch_hooks with skip_if, unit_type, model fields
and action validation rules
- Add known unit types list for hook before/after arrays
- Add examples for pre-dispatch hooks (modify/skip/replace)
- Add examples for token profile, phases, and remote questions
- Update models to show all 6 phases (research, planning, execution,
execution_simple, completion, subagent)
- Add full example combining all major settings
In RPC mode, ctx.ui.custom() returns undefined without emitting any event.
This caused showNextAction() — and all 13+ call sites in guided-flow.ts —
to silently complete without taking action. No error thrown, no event
emitted, command handler returns normally.
Fix: After custom() returns, check for undefined/null and fall back to
ctx.ui.select() which IS implemented in RPC mode. Maps the action list
to select labels and resolves the chosen action id.
Four bugfixes for open issues:
1. Worktree created from integration branch, not main (#606)
- createAutoWorktree reads integration branch from META.json
- mergeMilestoneToMain merges to integration branch, not hardcoded main
- createWorktree accepts optional startPoint parameter
2. Resolve project root from worktree paths in all commands (#608, #602)
- Add resolveProjectRoot() to detect .gsd/worktrees/ in cwd
- All GSD commands use projectRoot() instead of raw process.cwd()
- Fixes stale cwd after milestone completion (#608)
- Fixes discuss/status basepath disagreement (#602)
3. Milestone merge skipped in branch isolation mode (#603)
- Add branch-mode fallback when isInAutoWorktree() is false
- Detects milestone/* branch and performs squash-merge
- Uses same mergeMilestoneToMain flow as worktree mode
4. Remote questions onboarding missing .js module (#592)
- Extract saveRemoteQuestionsConfig into compiled src/ helper
- Avoids cross-boundary import from compiled JS to raw .ts
After milestone completion and merge, the process cwd could remain
inside .gsd/worktrees/<MID>/, causing new milestone writes to land
in the wrong directory.
Three-layer fix:
1. escapeStaleWorktree() at startAuto entry — detects if base path
is inside .gsd/worktrees/ and chdir back to project root
2. stopAuto() unconditionally restores cwd to originalBasePath,
not just when isInAutoWorktree returns true (module state may
have been cleared by mergeMilestoneToMain already)
3. Milestone merge error handler restores cwd on partial failure
where mergeMilestoneToMain chdir'd but then threw
Closes#608
Multiple sources of unbounded memory growth caused V8 to OOM after
~50 minutes of auto-mode operation:
1. activity-log.ts: saveActivityLog serialized ALL session entries
into a single string for SHA1 dedup, allocating hundreds of MB
per unit cycle. Now uses streaming writes (writeSync per entry)
and a lightweight fingerprint (entry count + last 3 entries hash)
instead of full-content hashing.
2. activity-log.ts: activityLogState Map was never cleared between
sessions, accumulating lastSnapshotKeyByUnit entries indefinitely.
Added clearActivityLogState() export, called from stopAuto().
3. auto.ts: completedUnits array grew unbounded for dashboard
display. Now capped at 200 entries and cleared on stopAuto().
4. paths.ts: dirEntryCache and dirListCache Maps grew without bounds
between clearPathCache() calls. Added DIR_CACHE_MAX (200) eviction
— when cache exceeds limit, it's cleared before adding new entries.
Closes#611
Adds context-window-aware token allocation to GSD auto-mode. Prompts
are sized proportionally to the model's context window, content is
truncated at markdown section boundaries, and a continue-here monitor
fires at 70% context usage.
This is NOT related to dollar budget ceilings (getBudgetAlertLevel,
budget_enforcement) which already exist in v2.17. This PR adds a
completely separate concern: context window token allocation.
New module: context-budget.ts (243 lines)
- computeBudgets(contextWindow) → proportional char allocations
- truncateAtSectionBoundary(content, budget) → TruncationResult
- resolveExecutorContextWindow(registry, prefs, session) → number
Extended: metrics.ts (3 optional fields on UnitMetrics)
- contextWindowTokens, truncationSections, continueHereFired
- Backward-compatible: old metrics.json parses without them
Extended: dashboard-overlay.ts (widget indicators)
- ▼N marker when sections truncated
- → wrap-up marker when continue-here fired
Extended: prompts (template variables)
- {{verificationBudget}} in execute-task.md
- {{executorContextConstraints}} in plan-slice.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: avoid native hangs in gsd auto paths
* fix: use .js extension in edit-diff.test.ts import for tsc compatibility
* fix: prevent OOM on large file diffs and implement context-line windowing
- Add size guard (MAX_DP_CELLS=4M) to buildLineDiff that falls back to a
linear-time prefix/suffix matching algorithm for large files, preventing
the O(n*m) DP table from causing OOM crashes
- Implement contextLines parameter in generateDiffString so only lines
within N lines of a change are rendered (with "..." separators), matching
unified diff behavior — the parameter was previously accepted but ignored
- Add tests for both context windowing and large-file fallback
---------
Co-authored-by: TÂCHES <afromanguy@me.com>
Reduces auto-mode token consumption by 40-60% through coordinated
optimizations driven by a single token_profile preference.
Profile presets (budget/balanced/quality):
- One preference key coordinates model selection, phase skipping,
context compression, and subagent routing
- Balanced is the default for new projects (D046)
- Explicit user preferences always override profile defaults
Phase skipping:
- Guard clauses on research-milestone, research-slice, and
reassess-roadmap dispatch rules
- Skipped phases return null (fall-through), preserving state machine
- Budget profile skips all research + reassess; balanced skips slice
research only
Context compression:
- inlineLevel parameter (full/standard/minimal) on 6 prompt builders
- Minimal: only output template + essential context (≥30% reduction)
- Standard: skip redundant templates
- Full: current behavior unchanged
Complexity routing:
- classifyTaskComplexity() for task plans (step/file/signal heuristics)
- classifyUnitComplexity() for unit types with budget pressure
thresholds at 50/75/90% (from #579)
- execution_simple model config for cheap simple-task routing
- escalateTier() for failure recovery (light→standard→heavy)
Adaptive learning (from #579):
- routing-history.ts tracks success/failure per tier per pattern
- Rolling 50-entry window, 20% failure threshold auto-bumps tier
- User feedback weighted 2x vs automatic detection
- Persists to .gsd/routing-history.json
Budget prediction:
- getAverageCostPerUnitType() + predictRemainingCost() in metrics
- projectedRemainingCost + profileDowngraded in AutoDashboardData
- One-way auto-downgrade within a milestone (D048)
Addresses #575
95 tests across 5 test files, all passing.