Commit graph

605 commits

Author SHA1 Message Date
Lex Christopherson
1b6fdd6aa6 perf: add session-scoped directory listing cache to path resolution
resolveDir(), resolveFile(), and resolveTaskFiles() call readdirSync()
on every invocation with no caching. These are called dozens of times
per dispatch cycle through resolveMilestonePath, resolveSliceFile,
relTaskFile, etc. This adds a module-level Map cache for directory
listings with an exported clearPathCache() function for invalidation
at dispatch cycle boundaries and milestone transitions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:34:29 -06:00
Lex Christopherson
7e9b792dc4 perf: reduce dispatch gap timeout from 30s to 5s
The dispatch gap watchdog is a safety net for when the dispatch chain
silently breaks. 30s is unnecessarily long and makes failures feel
sluggish. 5s is plenty of time to detect a stall without the wait.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:34:24 -06:00
Ahmad Ragab
5af1f752cb fix: add missing front matter to github-workflows skill 2026-03-14 15:24:07 -04:00
Kassie Povinelli
a883008be6 feat(gsd): implement auto-mode fallback model rotation on network errors (#386) 2026-03-14 13:13:22 -06:00
TÂCHES
33cf0dcabd feat(native): add libgit2-backed git read operations for dispatch hotpath (#388) 2026-03-14 13:07:02 -06:00
TÂCHES
ea439b99e4 perf(state): wire native batch parser into deriveState() hotpath (#389) 2026-03-14 13:06:36 -06:00
Flux Labs
fd459041f5 fix: bypass pre-commit hooks on GSD infrastructure commits to prevent lint-staged empty commit errors (#385)
GSD's internal git commits (auto-commits, slice merges, runtime file cleanup)
trigger pre-commit hooks like lint-staged. When lint-staged runs formatters
(e.g. prettier) on already-formatted files, it detects no changes from its
tasks and blocks the commit with "Prevented an empty git commit!" — even
though there are legitimate staged changes.

This is a known incompatibility between lint-staged's backup/restore mechanism
and squash-merge commits. The code being committed already passed hooks when
originally committed on the slice branch, so re-running hooks on the merge
commit is redundant.

Adds --no-verify to all 7 internal commit calls in git-service.ts:
- writeIntegrationBranch() — records integration branch metadata
- smartStage() cleanup — untracks runtime files from git index
- commit() — general commit method used by GSD
- autoCommit() — auto-commits dirty working tree between units
- mergeSliceToMain() — pre-merge runtime file untracking (2 calls)
- mergeSliceToMain() — squash-merge commit and --no-ff amend
2026-03-14 12:48:23 -06:00
Flux Labs
95643861ec fix(auto): prevent hang when dispatch chain breaks after slice tasks complete (#381) (#382) 2026-03-14 12:31:37 -06:00
Flux Labs
b6ec4f9fad Fix packaging verification and path portability (#378) 2026-03-14 12:28:14 -06:00
deseltrus
5d510ca6aa fix: read resources from dist/ to prevent branch-drift in npm-link setups (#314)
* fix: read resources from dist/ to prevent branch-drift in npm-link setups

initResources() reads extensions, prompts, skills, and agents from
src/resources/ — which points into the live working tree when gsd is
installed via npm link. Switching branches in the gsd repo changes
src/resources/ for ALL projects using gsd, causing stale or broken
extensions to be synced to ~/.gsd/agent/ on next launch.

Fix: the build step now copies src/resources/ to dist/resources/.
At runtime, resource-loader.ts and loader.ts prefer dist/resources/
(stable, set at build time) over src/resources/ (live working tree).
Fallback to src/resources/ is preserved for setups without a build.

Also adds npm run dev watch-resources watcher that syncs src/resources/
to dist/resources/ on file changes, running alongside tsc --watch.

* fix: cache prompt templates per session to prevent cross-session invalidation

When two gsd sessions run concurrently, the second session's
initResources() overwrites ~/.gsd/agent/ templates on disk. The first
session then reads a newer template that expects variables its in-memory
code doesn't know about, causing 'template declares {{X}} but no value
was provided' crashes that hang auto-mode indefinitely.

Fix: cache each template on first read. A running session uses the
template versions from when it first loaded them, immune to later
disk overwrites by other sessions.
2026-03-14 11:47:03 -06:00
Juan Francisco Lebrero
f6f1f9aa27 fix(search): always use native Anthropic web search when available (#374)
Three bugs prevented native web_search from being used with Anthropic:

1. model_select never fires on session restore (SDK's modelsAreEqual
   guard suppresses it when the default model matches the restored one),
   so isAnthropicProvider stayed false and native search was never
   injected. Fix: fall back to detecting "claude-" in the payload model
   name when model_select hasn't fired.

2. Custom search tools (search-the-web, search_and_read) were only
   removed from the payload when BRAVE_API_KEY was missing. With the
   key present, the model saw both native and Brave tools and often
   picked the Brave ones, which failed with network errors. Fix: always
   remove custom search tools from Anthropic requests.

3. google_search (Gemini-based) was not included in the disable list,
   so the model could call it even without GEMINI_API_KEY set. Fix: new
   CUSTOM_SEARCH_TOOL_NAMES list covers all three custom search tools.
2026-03-14 11:46:50 -06:00
TÂCHES
c69be2078f fix: npx fails — loader creates workspace symlinks at runtime (#380)
npx runs with --ignore-scripts, skipping postinstall. The loader now
creates node_modules/@gsd/* symlinks pointing to packages/* before
importing cli.js, so @gsd/* packages resolve without postinstall.

Bumps to v2.10.12.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 11:38:33 -06:00
deseltrus
8a64ac054c feat: multi-milestone readiness flow with per-milestone discussion gate (#377) 2026-03-14 11:26:30 -06:00
jpmarques19
41555b6f1e fix(voice): check GROQ_API_KEY before entering voice mode (#367) 2026-03-14 10:15:23 -06:00
jpmarques19
6a39f7226b feat(voice): Groq Whisper API backend for Linux voice mode (#366) 2026-03-14 09:08:36 -06:00
Flux Labs
a7ac787165 fix: handle empty index after runtime file stripping in squash-merge (#364) 2026-03-14 08:50:22 -06:00
Juan Francisco Lebrero
3a1b8f457d feat: opus 4.6 1M default, model selector UX, Discord onboarding (#290) 2026-03-14 08:43:56 -06:00
Copilot
8f8a9db7cb fix(auto): stale lock detection, SIGTERM handler, live-session guard (#362) 2026-03-14 08:43:33 -06:00
Adam Dry
db2c864e9e refactor: PR quality fixes — deduplicate findMilestoneIds, rename prefix→suffix, shared test helpers, fix typo (#360) 2026-03-14 08:42:22 -06:00
Copilot
7b17138ea4 Fix infinite loop when complete-slice merges to main are interrupted (#345)
* Initial plan

* fix: detect and merge orphaned completed slice branches at startup to prevent infinite loop

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.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>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: add missing closing brace in mergeOrphanedSliceBranches

The for-loop body was missing its closing brace, causing a parse error
that broke all tests importing auto.ts.

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

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>
Co-authored-by: TÂCHES <afromanguy@me.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Lex Christopherson <lex@glittercowboy.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 07:38:02 -06:00
TÂCHES
4c33642e3c fix: normalize .ts import extensions to .js for Node 22.22+ compatibility (#354)
Node 22.22.0's --experimental-strip-types handles .ts import specifiers
differently, causing ERR_INVALID_TYPESCRIPT_SYNTAX in CI. The project
convention uses .js specifiers with a custom resolve hook that rewrites
them to .ts at test time.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 07:27:32 -06:00
Copilot
ce7bde14f3 Fix execute-task loop detection: adaptive reconciliation instead of hard stop (#342)
* Initial plan

* Add adaptive reconciliation, concrete remediation steps, and xxHash32 JS fallback

- auto.ts: final reconciliation pass before halting on loop detection
  (runs skipExecuteTask to write blocker artifacts and advance pipeline)
- auto.ts: adaptive retry on prevCount>=2: write stub summary when still
  missing after two agent sessions, so the agent has a recovery context
- auto.ts: buildLoopRemediationSteps() helper with concrete manual steps
  when automatic reconciliation cannot resolve the unit
- xxhash/index.ts: pure-JS xxHash32 fallback when native addon does not
  export xxHash32 (prevents 'native.xxHash32 is not a function' crash)
- idle-recovery.test.ts: tests for buildLoopRemediationSteps and loop-recovery
  path in skipExecuteTask

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>

* Address code review feedback

- xxhash/index.ts: extract accumulate() helper to remove duplicate lane
  processing lines in the 16-byte loop
- auto.ts: replace magic number 2 with named constant STUB_RECOVERY_THRESHOLD
- idle-recovery.test.ts: add comment explaining the 3 (== MAX_UNIT_DISPATCHES)
  used in the loop-recovery test

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>

* Address PR review: verify post-state, fix stub wording, fix checkbox syntax, add fallback test

- auto.ts (MAX branch): check verifyExpectedArtifact() after skipExecuteTask()
  before advancing; annotate both conditions explaining what each validates
- auto.ts (self-repair branch): guard advance with verifyExpectedArtifact() so
  regex mismatches in the slice plan don't silently re-dispatch
- auto.ts (stub-recovery): write stub summary directly with "PARTIAL RECOVERY"
  wording instead of using skipExecuteTask (which would claim "exhausted N attempts")
- auto.ts (remediation): fix checkbox example to "- [x] **${tid}:" (no trailing **)
- xxhash/index.ts: export xxHash32Fallback so CI can test JS path independently
- native/src/index.ts: re-export xxHash32Fallback
- xxhash.test.mjs: add "xxHash32Fallback (pure-JS path)" describe block that
  validates the JS implementation against the reference on all test cases

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>

* chore: retrigger CI

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>
Co-authored-by: CI Trigger <noreply@github.com>
2026-03-14 07:26:10 -06:00
TÂCHES
d4312c60ec fix: handle secrets skip gracefully in auto mode without crashing (#352)
Fixes #296

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 07:08:49 -06:00
Copilot
2f15affeb5 fix: discard untracked runtime files before branch switch to prevent checkout conflicts (#346)
* Initial plan

* fix: add discardUntrackedRuntimeFiles to handle STATE.md checkout conflicts

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: TÂCHES <afromanguy@me.com>
Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>
2026-03-14 07:03:58 -06:00
Adam Dry
cf8dfc8c37 feat: Allow teams to work together without milestone name clashes and share context by checking in certain .gsd/ directory artifacts (#338)
* feat(M001/S01): ID generation and config plumbing

Tasks:
- chore(M001/S01/T02): auto-commit after execute-task
- chore(M001/S01): auto-commit after plan-slice
- docs(S01): add slice plan

Branch: gsd/M001/S01

* feat(M001/S02): Regex hardening and backwards compat

Tasks:
- chore(M001/S02/T02): auto-commit after execute-task
- chore(M001/S02/T01): auto-commit after execute-task
- chore: untrack .gsd/ runtime files from git index
- docs(S02): add slice plan

Branch: gsd/M001/S02

* docs(M001/S03): UX — wizard toggle and documentation

Tasks:
- chore(M001/S03/T01): auto-commit after execute-task
- docs(S03): add slice plan

Branch: gsd/M001/S03

* test(M001/S04): Integration tests and end-to-end verification

Tasks:
- chore(M001/S04/T02): auto-commit after execute-task
- chore(M001/S04/T01): auto-commit after execute-task
- docs(S04): add slice plan

Branch: gsd/M001/S04

* chore(M001): record integration branch

* chore(M002): record integration branch

* docs(M002/S01): Format swap — production code, tests, and docs

Tasks:
- chore(gsd/M002/S01): auto-commit after pre-switch
- chore(M002/S01/T01): auto-commit after execute-task
- chore: untrack .gsd/ runtime files from git index
- docs(S01): add slice plan

Branch: gsd/M002/S01

* chore(M002): auto-commit after complete-milestone

* Updated to document that we don't automatically always squash to main if you started on a different branch (like a dev or feature branch)

* fix: replace vitest import with node:test in regex-hardening test

The test imported from 'vitest' which isn't installed, causing
ERR_MODULE_NOT_FOUND and failing the CI unit test step. All other
test files use node:test. Swapped the import and removed the
vitest conditional wrapper.

* chore: untrack .gsd/ (already gitignored)

* docs: fix stale 'main' references in merge comments and prompts

The slice merge code correctly resolves to the integration branch
(which may be a feature branch, worktree branch, etc.), but comments,
JSDoc, and prompt templates still said 'main' as if it were always
the literal main branch.

Updated git-service.ts, worktree.ts, system.md, and
guided-complete-slice.md to say 'integration branch' with a clear
explanation of what that means.

* Fixed preferences.md case mismatch; Added fallback for backwards compat

* Updated preferences file example to show new unique_milestone_ids setting

* Updated readme to explain best practice for working in teams

---------

Co-authored-by: TÂCHES <afromanguy@me.com>
2026-03-14 07:00:14 -06:00
deseltrus
c13b1bfc6e fix: force-add .gsd/ planning artifacts and guard handleAgentEnd reentrancy (#341)
Two bugs that interact to silently kill auto-mode:

1. smartStage() uses `git add -A` which respects .gitignore. When .gsd/
   is gitignored (common — GSD's own baseline patterns only ignore runtime
   files, but many projects ignore all of .gsd/), new planning artifacts
   (CONTEXT.md, SUMMARY.md, PLAN.md, UAT.md, DECISIONS.md) are never
   staged. They exist on disk but not in git. Squash-merges then delete
   them on main because they appear as "removed relative to main."

   Fix: after `git add -A`, force-add `.gsd/milestones/` and root
   planning files. Runtime paths are still excluded by the subsequent
   `git reset HEAD` step.

2. handleAgentEnd() has no reentrancy guard. Background job notifications
   (async_bash results) trigger additional agent_end events while the
   first handler is still running (it yields at every await). Concurrent
   dispatchNextUnit() calls race on newSession() — one cancels the other,
   silently stopping auto-mode. Combined with bug #1, the second
   dispatchNextUnit call may find the active milestone's CONTEXT.md
   missing (never committed, lost during branch switch) and stop with
   "No context or roadmap yet."

   Fix: boolean guard prevents concurrent execution. Reset in stopAuto()
   so restarts aren't blocked.

Fixes #TBD

Co-authored-by: TÂCHES <afromanguy@me.com>
2026-03-14 07:00:07 -06:00
copilot-swe-agent[bot]
097cd3c8e0 fix: break infinite skip loop in gsd auto by adding roadmap [x] check to verifyExpectedArtifact
After a crash where complete-slice wrote SUMMARY+UAT but didn't mark
the roadmap [x], the idempotency check incorrectly reported the unit
as "done" (artifacts exist), while the state machine kept returning
the same complete-slice unit (roadmap shows [ ]). This caused
dispatchNextUnit to recurse forever.

Fix: verifyExpectedArtifact for complete-slice now also checks that
the slice is marked [x] in the roadmap. If not, it returns false so
the stale completion key is evicted and the unit re-runs.

Lenient if roadmap file is missing or corrupt (returns true).

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>
2026-03-14 12:34:54 +00:00
copilot-swe-agent[bot]
a89f45ce91 fix(#300): update stale comments that described old buggy behavior
Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>
2026-03-14 06:10:42 +00:00
TÂCHES
500cb5f6f3 Merge branch 'main' into fix/stale-completed-unit-oom-313 2026-03-13 23:51:34 -06:00
Lex Christopherson
fe11285ed5 fix: treat unresolvable artifact paths as stale completion state (#313)
verifyExpectedArtifact() returned true when resolveExpectedArtifactPath()
returned null, conflating "unit type has no artifact" with "slice directory
missing on disk". This caused /gsd auto to infinitely skip and re-dispatch
the same stale completed-unit entry until OOM.

Now only replan-slice (the sole type with no verifiable artifact) passes
on null; all other types return false, triggering the existing eviction
logic that removes the stale key and re-runs the unit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 23:51:04 -06:00
Lex Christopherson
9298467ece fix: update integration branch test to match #300 behavior
writeIntegrationBranch now intentionally updates when the branch changes
(#300). Updated the stale "idempotent — doesn't overwrite" test to assert
the new behavior, and added a separate test for same-branch idempotency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 23:37:56 -06:00
TÂCHES
ff1d7c5af9 Merge branch 'main' into feat/fix-merge-session 2026-03-13 23:37:31 -06:00
Lex Christopherson
33e5ec6d37 fix: replace TS parameter properties with explicit fields for Node strip-types compatibility
MergeConflictError used `public readonly` constructor parameter properties,
which are not supported by Node's --experimental-strip-types mode (type
stripping only, no TS-to-JS transforms). This crashed 19 test files on import.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 23:33:28 -06:00
TÂCHES
3fd7b9d8e2 Merge branch 'main' into feat/fix-merge-session 2026-03-13 23:21:25 -06:00
TÂCHES
1302e06f75 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 23:21:14 -06:00
TÂCHES
bdb5defa3a Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 23:20:59 -06:00
TÂCHES
742e26abc1 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 23:20:48 -06:00
TÂCHES
8b068f98bc Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 23:20:39 -06:00
TÂCHES
d887cf40d1 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 23:20:28 -06:00
TÂCHES
c9d626b030 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 23:20:17 -06:00
TÂCHES
a6be172829 Merge branch 'main' into fix/macos-keybinding-display 2026-03-13 23:18:34 -06:00
TÂCHES
079d1751b0 Merge branch 'main' into feat/fix-merge-session 2026-03-13 23:17:02 -06:00
TÂCHES
9ef7536f3d Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 23:13:06 -06:00
TÂCHES
0810aec739 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 23:12:49 -06:00
Lex Christopherson
a68fa00b4c feat: auto-resolve merge conflicts via fix-merge LLM session
When auto-mode merges a completed slice and hits code conflicts in
non-.gsd files, dispatch a fix-merge session to resolve them instead
of hard-resetting and stopping. This eliminates the #1 cause of
unnecessary auto-mode stops.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 23:12:08 -06:00
Lex Christopherson
2b96b1a247 fix: re-check secrets manifest before every dispatch, not just at startAuto
When plan-milestone writes SECRETS-MANIFEST.md, the secrets gate at
startAuto has already fired (manifest didn't exist yet). Without a
re-check, the model proceeds into plan-slice / execute-task with no
real credentials and mocks external services — cascading risk into
every downstream slice.

Added a secrets re-check gate inside dispatchNextUnit that runs before
every unit dispatch. getManifestStatus is cheap (file read + .env
scan) so the check is a no-op when no manifest exists or all secrets
are already collected. Idempotent: skips keys already present in .env.

Closes #303
2026-03-13 23:07:01 -06:00
Lex Christopherson
4924bbe6b2 fix: update integration branch when user starts auto-mode from a different branch (#300)
writeIntegrationBranch was unconditionally skipping if any integration
branch was already recorded, even if the user started auto-mode from a
different branch. Now it only skips when the recorded branch matches —
if it differs, the record is updated so slices merge to the correct target.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 22:47:14 -06:00
TÂCHES
8536d028bf Merge branch 'main' into fix/301-remove-delivery-retry 2026-03-13 22:46:38 -06:00
TÂCHES
dca35ab3ea Merge branch 'main' into fix/macos-keybinding-display 2026-03-13 22:46:13 -06:00
TÂCHES
770132b20e fix: eliminate branch checkout during slice merge that caused STATE.md conflicts (#302) (#307)
The merge flow checked out the slice branch mid-merge to untrack runtime
files, which failed when .gsd/STATE.md had uncommitted working tree changes.
Instead, strip runtime files from the staged merge result post-merge — no
branch switching needed.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 22:43:02 -06:00