Commit graph

2543 commits

Author SHA1 Message Date
Tom Boucher
5c2d8988bb fix: track remote-questions in managed-resources manifest (#3312)
* fix: track remote-questions extension in managed-resources manifest

writeManagedResourceManifest only checked for index.js/index.ts when
deciding if a subdirectory is an extension. remote-questions uses mod.ts
as its entry point and was missed, causing it to be pruned on upgrades.

Also check for extension-manifest.json which is the canonical marker for
bundled extensions.

Fixes #2367

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

* chore: retrigger CI

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 01:04:44 -04:00
Tom Boucher
5d194d8701 fix(auto): add timeout guard for postUnitPostVerification in runFinalize (#3314)
* fix(auto): add timeout guard for postUnitPostVerification in runFinalize (#2344)

After plan-slice completes, the auto-loop can hang indefinitely if
postUnitPostVerification() never resolves (e.g., module import deadlock,
SQLite transaction hang). The terminal becomes unresponsive with no
error, no notification, and no recovery path.

Changes:
- Add withTimeout() utility in auto/finalize-timeout.ts that races a
  promise against a configurable timeout, returning a discriminated
  result instead of throwing
- Wrap the postUnitPostVerification() call in runFinalize() with a 60s
  timeout guard — on timeout, log a warning and force-return "next" so
  the loop continues to the next iteration
- Emit iteration-end journal event in the catch block of autoLoop() so
  the journal always records iteration completion, even on error

Fixes #2344

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

* chore: retrigger CI

* fix(ts): remove duplicate imports introduced during rebase

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 01:04:41 -04:00
Tom Boucher
ff5015431e fix(gsd): handle large markdown parameters in complete-milestone JSON parsing (#3316)
* fix(gsd): sanitize complete-milestone params to handle LLM JSON quirks

When smaller models (e.g. claude-haiku) generate tool-call JSON with large
markdown parameters, the deserialized params can arrive with wrong types:
numbers instead of strings, null instead of arrays, string "true" instead
of boolean true. This caused crashes in handleCompleteMilestone.

Add sanitizeCompleteMilestoneParams() that normalizes all fields before
the handler runs, preventing TypeError crashes on type mismatches.

Closes #3013

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

* fix: add type narrowing for optional fields in sanitize-complete-milestone

followUps and deviations are required strings in CompleteMilestoneParams,
so use toStr() directly (which returns "" for nullish values) instead of
conditionally returning undefined.

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

* fix: update test assertion to match toStr empty string default

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

* chore: retrigger CI

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 01:04:38 -04:00
Tom Boucher
3e7a8d8556 fix(metrics): deduplicate idle-watchdog entries and fix forensics false-positives (#1973)
* fix(metrics): deduplicate idle-watchdog entries on ledger load and fix forensics false-positives

The idle watchdog creates duplicate metrics entries with the same
(type, id, startedAt) triple, inflating reported cost by ~35% and
causing false-positive stuck-loop anomalies in forensics.

Add a deduplicateUnits() pass in loadLedger() that collapses entries
sharing the same (type, id, startedAt) key, keeping the one with the
highest finishedAt. The cleaned ledger is persisted back to disk so
duplicates do not re-accumulate across sessions.

Fix detectStuckLoops() in forensics.ts to count distinct startedAt
values per type/id instead of raw entry count, so idle-watchdog
snapshots of the same dispatch are not flagged as stuck loops.

Fixes #1943

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

* fix: export ForensicAnomaly type and use in test

The test declared a local ForensicAnomaly interface with `type: string`
which was incompatible with the real union literal type, causing CI
typecheck failure.

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-04-05 00:54:44 -04:00
Tom Boucher
c8f11019f5 fix: prevent milestone/slice artifact rendering corruption (#3293)
* fix: prevent milestone/slice artifact rendering corruption (#2630)

Three renderer bugs caused markdown artifact corruption after slice
completion and milestone closeout:

1. Milestone title double-prefixing: when params.title already contained
   the milestone ID prefix (e.g. "M001: Topic"), renderers produced
   "M001: M001: Topic". Added stripIdPrefix() helper and applied it in
   renderRoadmapContent, renderStateContent, and
   renderMilestoneSummaryMarkdown.

2. full_uat_md demo fallback: renderPlanContent and renderRoadmapContent
   fell back to raw full_uat_md (multi-line UAT documents) when
   slice.demo was empty, injecting entire UAT bodies into PLAN.md and
   ROADMAP.md table cells. Changed fallback to "TBD" instead.

3. STATE.md active milestone/slice/registry entries also double-prefixed
   titles. Applied stripIdPrefix() to all title renderings in
   renderStateContent.

Closes #2630

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

* fix: correct Phase type and null/undefined in artifact-corruption test

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

* fix(workflow-projections): apply stripIdPrefix in renderPlanContent

renderPlanContent was missed in the original fix — sliceRow.title
containing an ID prefix (e.g. "S04: Title") produced double-prefixed
PLAN.md headings ("# S04: S04: Title"). Apply stripIdPrefix consistent
with renderRoadmapContent and renderStateContent.

Adds two test cases covering prefixed and non-prefixed slice titles.

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

* chore: retrigger CI

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 00:53:02 -04:00
Tom Boucher
4d9b8acadb fix(doctor): strip --fix flag before positional parse (#1919) (#1926)
The flag-stripping regex in handleDoctor() removed --json, --dry-run,
--build, and --test but not --fix. When a user ran `/gsd doctor --fix`,
"--fix" leaked into requestedScope, mode stayed "doctor", and fix was
never enabled -- silently suppressing all issues and fixes.

Extract parseDoctorArgs() as a pure, exported function. Add --fix to
the stripping regex and propagate fixFlag into the fix option passed
to runGSDDoctor.

Fixes #1919

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 00:52:11 -04:00
Tom Boucher
c609d813d3 fix: resolve external-state worktree DB path (#2952) (#3303)
* fix: resolve external-state worktree DB path in resolveProjectRootDbPath (#2952)

Add regex check for ~/.gsd/projects/<hash>/worktrees/<MID> path layout
so DB writes from external-state worktrees target the canonical project
DB instead of creating an isolated local DB that is lost on teardown.

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

* chore: retrigger CI (flaky #2912 MERGE_HEAD test)

* chore: retrigger CI

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 00:51:46 -04:00
Tom Boucher
b6fcc1bb49 fix(gsd): worktree teardown path validation prevents data loss (#3311)
* fix(gsd): validate worktree paths before removal to prevent data loss

Fixes #2365

removeWorktree() overrides its computed path with whatever git reports
from `git worktree list`. When .gsd/ was a symlink, git resolves it at
creation time, so the registered path can point to an external directory.
Teardown with --force on that path destroys user data.

Add isInsideWorktreesDir() containment check that resolves ".." traversals
and validates the target is under .gsd/worktrees/ before any destructive
operation (nativeWorktreeRemove --force, rmSync). Paths outside containment
get a non-force git worktree remove only, with a warning logged.

Also guard the fallback rmSync in teardownAutoWorktree() with the same
containment check.

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

* refactor: convert worktree-teardown-safety test to node:test format

Replace main() function wrapper pattern with proper describe/it blocks
using node:test, matching the project's standard test conventions.

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

* fix: replace empty catch blocks with logWarning in worktree-manager

* fix(test): increase removeWorktree slice window from 3000 to 6000 chars

The PR's path-validation additions expanded removeWorktree beyond the
3000-char snapshot window, pushing the submodule safety section out of
scope and causing Tests 3 and 4 to see empty strings.

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

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 00:51:19 -04:00
Tom Boucher
fb63c15bc9 fix: prevent auto-mode from dispatching deferred slices (#3309)
* fix: prevent auto-mode from dispatching deferred slices (#2661)

When a decision deferred a slice via gsd_decision_save, the deferral was
recorded in DECISIONS.md but the slice status in the DB remained "active".
The dispatcher reads slice status (not DECISIONS.md) to choose work, so it
kept dispatching the deferred slice — burning tokens on the wrong work.

Three changes fix the split-brain:

1. status-guards.ts: add isDeferredStatus() and isInactiveStatus() predicates
2. state.ts: skip slices with "deferred" status in active-slice selection
3. db-writer.ts: when saveDecisionToDb detects a deferral decision referencing
   a slice (M###/S## pattern in scope/choice/decision), update that slice's DB
   status to "deferred" so the state machine sees it immediately

Closes #2661

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

* fix(db-writer): consistent deferral regex + add extractDeferredSliceRef tests

The scope regex was missing "ring" and "s" variants (deferring, defers)
while choice/decision had the complete pattern. Unified all three to use
/\bdefer(?:ral|red|ring|s)?\b/i.

Added 8 unit tests for extractDeferredSliceRef covering: scope/choice/
decision deferral detection, missing M###/S## patterns, "deferring" and
"defers" variants, multiple pattern matches, and non-deferral keywords.

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

* chore: retrigger CI

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 00:50:44 -04:00
Tom Boucher
e0a5f6866e fix: preserve completed slice status on plan-milestone re-plan (#3318)
* fix: preserve completed slice status on plan-milestone re-plan (#2558)

When plan-milestone re-plans a milestone that has already-completed slices,
the handler now checks existing slice status before inserting. Completed
slices retain their status instead of being reset to "pending".

Three changes:

1. handlePlanMilestone() checks getSlice() before insertSlice() and passes
   the existing completed/done status instead of hardcoding "pending".

2. insertSlice() changed from INSERT OR IGNORE to INSERT ... ON CONFLICT
   upsert that updates non-status fields (title, risk, depends, demo,
   planning metadata) but preserves completed/done status at the DB layer.

3. reconcileWorktreeDb() slice and task merges now use LEFT JOIN to detect
   existing completed rows in the main DB and never downgrade their status
   when merging stale worktree data.

Closes #2558

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

* fix: relax completed-slice guard to allow re-plan when slices are retained

The #2960 guard blocked re-planning entirely when any completed slices
existed, conflicting with the #2558 preserve-completed-status logic.
Now only blocks when the new plan would drop completed slices.

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

* fix(gsd-db): prevent insertSlice ON CONFLICT from wiping populated fields

The ON CONFLICT clause unconditionally overwrote all non-status fields with
excluded values. Callers like complete-task.ts and complete-slice.ts use
insertSlice as an idempotent "ensure row exists" guard with only id and
milestoneId, causing defaults (empty strings, 0) to silently destroy
populated titles, demos, goals, and planning data.

Fix: use raw sentinel bind params (NULL when caller omitted the field) in
CASE guards so the ON CONFLICT UPDATE only overwrites fields the caller
actually provided. Initial INSERTs still get proper defaults.

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

* chore: retrigger CI

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 00:49:59 -04:00
Tom Boucher
0908adcb4e fix: reopen DB on cold resume, recognize heavy check mark (#3319)
* fix: reopen DB on cold resume and recognize U+2714 check mark

The paused-session resume path in auto.ts called rebuildState/deriveState
without first opening the project database, causing state derivation to
fall back to markdown parsing. This misparsed roadmap table rows with
glyph done markers and could redispatch wrong slices.

Export openProjectDbIfPresent from auto-start.ts and call it in the
resume path before rebuildState, matching the fresh bootstrap ordering.

Also add U+2714 (heavy check mark) to the table parser done-detection
regex alongside the existing U+2705/U+2611/U+2713 glyphs.

Closes #2940

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

* fix: remove duplicate openProjectDbIfPresent from rebase conflict

The rebase onto main introduced a duplicate `openProjectDbIfPresent`
function declaration (one from the PR, one from main), causing TS2393.
Keep the exported version that uses the static import.

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

* fix: use logWarning instead of process.stderr in openProjectDbIfPresent

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 00:49:29 -04:00
Tom Boucher
b1ae782876 fix: dashboard model label shows dispatched model, not stale previous unit (#3320)
* fix: dashboard model label shows dispatched model, not stale previous unit model

Move updateProgressWidget and ensurePreconditions after selectAndApplyModel
in phases.ts so the widget's first render tick reads the correct model.
Store currentDispatchedModelId in session state after model selection + hook
overrides, expose it via widgetStateAccessors, and update auto-dashboard.ts
to prefer the dispatched model ID over cmdCtx.model which can be stale.

Closes #2899

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

* fix(test): widen runUnitPhase slice in ordering test to accommodate grown function body

The structural test for selectAndApplyModel ordering sliced only 8000
chars of runUnitPhase, but the function grew past that limit after
rebase, causing updateProgressWidget to fall outside the window.

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

* chore: retrigger CI

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 00:48:50 -04:00
Tom Boucher
9b6ff01471 docs: add provider setup guide for third-party LLM providers (#3294)
* docs: add provider setup guide and improve onboarding hints

Fixes #2161

Add docs/providers.md with step-by-step setup instructions for every
supported LLM provider: OpenRouter, Ollama, LM Studio, vLLM, SGLang,
and all built-in providers. Includes env var names, example configs,
common pitfalls, and verification steps.

Improve onboarding wizard:
- Add URL hints to provider selection list
- Show common local endpoints when choosing Custom (OpenAI-compatible)
- Add post-setup guidance for OpenRouter and custom endpoints
- Reference docs/providers.md for compat troubleshooting

Update cross-references in getting-started.md, troubleshooting.md,
docs/README.md, and help-text.ts to link to the new guide.

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

* test: verify config help mentions OpenRouter, Ollama, and docs/providers.md

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: trek-e <trek-e@users.noreply.github.com>
2026-04-05 00:48:19 -04:00
github-actions[bot]
647954098a release: v2.63.0 2026-04-05 03:48:56 +00:00
Jeremy McSpadden
ab38f60cc2 Merge pull request #3525 from jeremymcs/fix/diagnostic-messaging
fix(gsd): enrich vague diagnostic messages with root-cause context
2026-04-04 21:20:43 -05:00
Jeremy
53639aee5d fix(gsd): enrich vague diagnostic messages with root-cause context
Closes #3524
2026-04-04 21:04:26 -05:00
github-actions[bot]
b8cb665ba5 release: v2.62.1 2026-04-05 01:33:15 +00:00
github-actions[bot]
546c93cae7 release: v2.62.1 2026-04-05 01:33:15 +00:00
Jeremy McSpadden
9e3ee58619 Merge pull request #3514 from jeremymcs/fix/ask-user-questions-dedup
fix(gsd): prevent duplicate ask_user_questions dispatches
2026-04-04 20:12:48 -05:00
Jeremy
ca55b5c269 fix(test): reset dedup cache between ask-user-freetext tests
The per-turn dedup cache introduced in the parent commit persists across
test cases since they all use the same question signature. Test 1 populates
the cache, causing tests 2 and 3 to get cached results instead of exercising
their intended code paths.
2026-04-04 19:59:54 -05:00
Jeremy McSpadden
74d5200cfd Merge pull request #3516 from jeremymcs/feat/mcp-server-readonly-tools
feat(mcp-server): add 6 read-only tools for project state queries
2026-04-04 19:56:49 -05:00
Jeremy McSpadden
34baf57e40 Merge pull request #3518 from jeremymcs/fix/bootstrap-prefer-gsd-preferences
fix(gsd): prefer PREFERENCES.md over settings.json for bootstrap model
2026-04-04 19:50:09 -05:00
Jeremy McSpadden
56153c9096 Merge pull request #3520 from jeremymcs/fix/worktree-orphaned-wal-shm
fix(db): delete orphaned WAL/SHM files alongside empty gsd.db
2026-04-04 19:47:14 -05:00
Jeremy
e4987f5337 fix(db): delete orphaned WAL/SHM files alongside empty gsd.db (#2478)
syncProjectRootToWorktree deleted empty gsd.db but left companion
-wal and -shm files on disk. On Node 24, node:sqlite attempts WAL
recovery from orphaned files, triggering a synchronous CPU spin loop
(227% CPU, 1.4GB RSS). Now deletes gsd.db-wal and gsd.db-shm when
the main DB is deleted or already missing.
2026-04-04 19:36:43 -05:00
Jeremy McSpadden
b0697f24f6 Merge pull request #3519 from jeremymcs/fix/auto-wrapup-inflight-interrupt
fix(gsd): prevent auto-wrapup from interrupting in-flight tool calls
2026-04-04 19:26:02 -05:00
Jeremy
fd96a1a30b fix(gsd): prevent auto-wrapup from interrupting in-flight tool calls (#3512)
Gate triggerTurn behind getInFlightToolCount() === 0 for both soft
timeout and context-pressure wrapup messages. Add clearQueue() to
stopAuto() and pauseAuto() to flush late async follow-ups.
2026-04-04 19:14:23 -05:00
Jeremy McSpadden
246e706991 Merge pull request #3495 from Tibsfox/fix/tool-argument-json-robustness
fix(pi-ai): extend repairToolJson to handle XML tags and truncated numbers
2026-04-04 19:02:28 -05:00
Jeremy McSpadden
12ef95024c Merge pull request #3451 from deseltrus/fix/stale-retries-after-model-switch
fix: cancel stale retries after model switch
2026-04-04 18:27:33 -05:00
Jeremy McSpadden
dbaf37ae78 Merge pull request #3491 from Tibsfox/fix/claude-code-skill-directory-support
fix(gsd): add Claude Code official skill directories to skill resolution
2026-04-04 18:24:51 -05:00
Jeremy McSpadden
677ca806df Merge pull request #3494 from Tibsfox/fix/decision-save-transaction-race
fix(gsd): wrap decision and requirement saves in transaction to prevent ID races
2026-04-04 18:23:15 -05:00
Jeremy
eed833138d chore: untrack .repowise/ and add to .gitignore
Machine-local indexing state (LanceDB, sync cursors, job files) was
being tracked in Git, causing merge conflicts and stale cursor
propagation across branches. Gitignore alone doesn't affect
already-tracked files, so this removes them from the index while
keeping them on disk.
2026-04-04 18:22:39 -05:00
Jeremy
70c76d9a1a fix(gsd): handle bare model IDs in resolveDefaultSessionModel (#3517)
resolveDefaultSessionModel() previously only returned a result for
provider/model format strings, silently ignoring valid bare model IDs
like "gpt-5.4". This meant preferences could fail to override stale
settings.json defaults when users configured models without explicit
provider prefixes.

Now accepts sessionProvider param (ctx.model?.provider) to resolve bare
IDs. Also handles object configs without explicit provider field.
2026-04-04 18:10:50 -05:00
Tibsfox
c70eacea89 fix(gsd): wrap decision and requirement saves in transaction to prevent ID races
nextDecisionId() and nextRequirementId() compute the next ID via
SELECT MAX then pass it to a separate upsertDecision/upsertRequirement
call. When parallel tool calls hit these functions concurrently, both
read the same MAX value and produce the same ID — the second insert
silently overwrites the first.

Move the SELECT MAX + INSERT into a single transaction() call from
gsd-db.ts, which uses BEGIN/COMMIT/ROLLBACK and works on both
better-sqlite3 and node:sqlite providers. The transaction is
re-entrant safe (nested calls skip the BEGIN).

Same fix applied to saveRequirementToDb for consistency.

Closes #3326, closes #3339, closes #3459
2026-04-04 15:16:52 -07:00
Jeremy
fbcd722cf4 fix(gsd): prefer PREFERENCES.md over settings.json for session bootstrap model (#3517)
Session bootstrap used ctx.model (from settings.json defaultProvider/defaultModel)
as the autoModeStartModel snapshot. When settings.json had a stale provider
(e.g. claude-code) but PREFERENCES.md was fully configured for openai-codex,
sessions would start with the wrong provider and fail with auth errors.

Add resolveDefaultSessionModel() to preferences-models.ts which extracts the
default model from GSD preferences (execution → planning → first configured).
In auto-start.ts, the preferred model now takes priority over ctx.model when
building startModelSnapshot, so PREFERENCES.md always wins over stale settings.
2026-04-04 17:15:43 -05:00
Tibsfox
e107828363 fix(gsd): add Claude Code official skill directories to skill resolution
GSD-2 only searches ~/.agents/skills/ and .agents/skills/ for skills.
Claude Code's official skill directories (~/.claude/skills/ and
.claude/skills/) are not included in the search path, making GSD-2
blind to any skills managed there.

The skills.sh CLI (npx skills list -g) already recognises both
~/.agents/skills/ and ~/.claude/skills/ as valid global skill
directories. This commit aligns GSD-2's resolution logic with
that behaviour.

Affected functions:
- getSkillSearchDirs(): adds ~/.claude/skills/ and .claude/skills/
- captureAvailableSkills(): includes Claude Code dir in telemetry
- detectStaleSkills(): includes Claude Code dir in staleness checks
- detectNewSkills(): resolves SKILL.md from either directory
- isPackInstalled(): checks both dirs before recommending installs
- formatSkillDetail(): finds SKILL.md in either directory
2026-04-04 15:15:29 -07:00
Jeremy
75a5be9278 fix(dedup): hash full question payload, not just IDs
The questionSignature() function only hashed sorted question IDs,
meaning calls with the same IDs but different text/options would
return stale cached answers. Now hashes the full canonicalized
payload (id, header, question, options, allowMultiple).

Adds 4 regression tests for signature correctness.
2026-04-04 17:02:59 -05:00
Jeremy
45b606744f feat(mcp-server): add 6 read-only tools for project state queries (#3515)
Add gsd_progress, gsd_roadmap, gsd_history, gsd_doctor, gsd_captures,
and gsd_knowledge tools that parse .gsd/ on disk — no session needed.

Inline lightweight readers in src/readers/ keep the package standalone
(zero new dependencies). 33 new tests, 64 total passing.
2026-04-04 16:41:24 -05:00
Jeremy
f0759086e4 fix(gsd): prevent duplicate ask_user_questions dispatches with per-turn dedup cache
Closes #3513

- Add per-turn dedup cache in ask_user_questions keyed by hashed question IDs;
  duplicate calls return cached results instead of re-dispatching to Discord
- Lower loop guard threshold for interactive tools (ask_user_questions) from 4
  to 1 — blocks 2nd identical call immediately
- Wire cache reset into session_start, session_switch, and agent_end hooks
- Harden discuss prompts with "call exactly once per turn" instruction
- Add regression tests covering strict threshold and dedup behavior
2026-04-04 16:33:36 -05:00
Jeremy McSpadden
099e6f3120 Merge pull request #3511 from jeremymcs/fix/steer-worktree-path
fix(gsd): steer writes overrides to worktree when active
2026-04-04 16:10:30 -05:00
github-actions[bot]
40fc92a2a6 release: v2.62.0 2026-04-04 21:10:16 +00:00
github-actions[bot]
f6521cd92e release: v2.61.0 2026-04-04 20:53:42 +00:00
Jeremy
ee87924636 fix(gsd): gate steer worktree routing on active session, fix messaging
Address adversarial review findings:

1. [high] Override routing now requires an active auto-mode session
   (in-process or remote via checkRemoteAutoSession) before writing
   to a worktree path. Previously, any existing worktree directory
   would receive the override even if no agent was running there —
   a leftover worktree from a previous session would silently eat
   the override.

2. [medium] Success messages now report the actual resolved override
   location (worktree vs project root .gsd/OVERRIDES.md) so operators
   know exactly where to look during recovery or manual rewrite.

Additional tests cover: inactive worktree fallback, double-gate
(autoRunning + valid .git), and getAutoWorktreePath null on missing .git.

Closes #3476
2026-04-04 15:37:13 -05:00
Jeremy McSpadden
82906524a8 Merge pull request #3482 from NilsR0711/fix/remote-questions-interactive-mode
fix(remote-questions): fire configured channels in interactive mode
2026-04-04 15:32:19 -05:00
Jeremy
bd863e3e21 fix(gsd): resolve steer overrides to worktree path when worktree is active
handleSteer used process.cwd() as the base path for appendOverride,
which writes to project/.gsd/OVERRIDES.md. When auto-mode runs in a
worktree, it reads from worktree/.gsd/ — so overrides written from a
second terminal were never seen by the agent.

Now checks for an active worktree via getAutoWorktreePath and writes
the override there when one exists, falling back to the project root
when no worktree is active.

Closes #3476
2026-04-04 15:25:26 -05:00
Jeremy McSpadden
af82c37041 Merge pull request #2755 from jeremymcs/feat/capability-aware-model-routing-pr
feat: capability-aware model routing (ADR-004)
2026-04-04 15:23:38 -05:00
Jeremy McSpadden
2acf5292d0 Merge pull request #3508 from jeremymcs/fix/audit-log-hardening
fix(gsd): harden audit log persistence and demote probe warnings
2026-04-04 15:12:14 -05:00
Jeremy McSpadden
1c4219ee2e Merge pull request #3510 from jeremymcs/feat/codebase-map-enhancements
feat(gsd): enhance /gsd codebase with preferences, --collapse-threshold, and auto-init
2026-04-04 15:11:36 -05:00
Jeremy
4ddb9ca8a5 fix(gsd): add codebase validation in validatePreferences so preferences are not silently dropped
The codebase preferences block was accepted as a known key but never
validated or assigned in validatePreferences(), causing all user-configured
codebase defaults to be silently discarded. Adds validation for
exclude_patterns (string[]), max_files (positive int), and collapse_threshold
(positive int) with unknown-key warnings and 4 new tests.
2026-04-04 15:01:15 -05:00
Jeremy
bbe67da02c feat(gsd): enhance /gsd codebase with preferences, --collapse-threshold, and auto-init
Add configurable codebase map options via preferences.md (exclude_patterns,
max_files, collapse_threshold), expose --collapse-threshold as a CLI flag,
and auto-generate CODEBASE.md during project init for instant agent orientation.

Closes #3509
2026-04-04 14:51:51 -05:00
Jeremy McSpadden
5cd25cf5df Remove copyright notice from test file
Removed copyright notice from capability-router tests.
2026-04-04 14:33:50 -05:00