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>
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>
Model variants like `claude-opus-4-6[1m]` use bracket suffixes to
differentiate context window configurations internally, but the
Anthropic API only accepts base model IDs (e.g. `claude-opus-4-6`).
Sending the full variant ID via OAuth (Claude Max/Pro) causes a 404:
{"type":"not_found_error","message":"model: claude-opus-4-6[1m]"}
Strip any `[...]` suffix from model.id for OAuth requests only.
API key auth is left unchanged since the behavior there is unverified.
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>
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>
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>