Commit graph

253 commits

Author SHA1 Message Date
Lex Christopherson
3a705cb501 perf: add content-hash-keyed parse cache for file parsing
parseRoadmap, parsePlan, parseSummary, and parseContinue are pure
functions that get called repeatedly with the same content during
deriveState dispatch cycles. A module-scoped Map keyed by a fast
composite key (length + first 100 chars + last 100 chars) avoids
redundant parsing. Cache caps at 50 entries and clears when full.
Exports clearParseCache() for explicit invalidation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:34:40 -06: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
TÂCHES
f01858a4c9 Merge branch 'main' into fix/301-remove-delivery-retry 2026-03-13 22:42:56 -06:00
Lex Christopherson
9feca64496 fix: eliminate branch checkout during slice merge that caused STATE.md conflicts (#302)
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:38:54 -06:00