Commit graph

657 commits

Author SHA1 Message Date
Flux Labs
e6d55f8aaf Perf/gsd startup speed (#497)
* docs: add startup performance analysis and optimization plan

Profiled GSD CLI startup finding 2.2s for --version and ~3.8s for
interactive mode. Identified 5 root causes with measured timings and
created a phased optimization plan targeting <0.2s for --version
and ~0.8s for interactive startup.

* perf: speed up GSD startup with lazy loading and fast paths

- Fast-path --version/-v and --help/-h in loader.ts before importing
  any heavy dependencies (2.2s → 0.15s, 14x faster)
- Lazy-load undici (~200ms) only when HTTP_PROXY env vars are set
- Skip initResources cpSync when managed-resources.json version
  matches current GSD version (~128ms saved per launch)
- Lazy-load Mistral SDK (~369ms) on first API call instead of startup
- Lazy-load Google GenAI SDK (~186ms) on first API call instead of
  startup
- Parallelize extension loading with Promise.all() instead of
  sequential for-loop

---------

Co-authored-by: TÂCHES <afromanguy@me.com>
2026-03-15 13:33:43 -06:00
TÂCHES
ed47018496 refactor(git): branchless worktree architecture (#506)
Eliminate slice branches — all work commits sequentially on milestone/<MID>
within auto-mode worktrees. No branch creation, switching, or merging
within a worktree. Planning artifacts (.gsd/milestones/) tracked in git
properly instead of being blanket-gitignored then force-added.

Removes ~2,600 lines: ensureSliceBranch, switchToMain, mergeSliceToMain,
mergeSliceToMilestone, shouldUseWorktreeIsolation, getMergeToMainMode,
withMergeHeal, recoverCheckout, fix-merge dispatch/labels, and associated
tests. Adds legacy_slice_branches doctor check, deprecation warnings for
git.isolation and git.merge_to_main preferences.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 13:21:58 -06:00
TÂCHES
2d4a14b7ca Merge pull request #491 from fluxlabs/fix/hook-orchestration
fix: hook orchestration — finalize records, add supervision, fix retry
2026-03-15 11:27:12 -06:00
Flux Labs
71f33de869 Merge branch 'main' into fix/hook-orchestration 2026-03-15 12:16:41 -05:00
Flux Labs
94336dd445 fix: hook orchestration — finalize runtime records, add supervision, fix retry
Hooks were dispatched (runtime record created with phase="dispatched") but
never properly tracked through completion. Four issues fixed:

1. Hook runtime records now finalized: handleAgentEnd writes phase="finalized"
   and clears the record when a hook completes. Previously records stayed at
   "dispatched" forever because verifyExpectedArtifact returned false for
   hook types.

2. Supervision timer for hooks: hook dispatch now sets a hard timeout so
   stuck hooks don't hang auto-mode indefinitely.

3. Hook retry removes completion key: when a hook requests retry via
   retry_on, the trigger unit's completion key is removed from the
   idempotency set so dispatchNextUnit will re-dispatch it.

4. Hook closeout in dispatchNextUnit: hook units are properly closed out
   (pushed to completedUnits, runtime cleared) without polluting the
   idempotency set. verifyExpectedArtifact returns true for hook/ types.

Fixes #140 (comment 4063396798)
2026-03-15 12:14:30 -05:00
Lex Christopherson
e147b2dfdf fix(state): empty slice plan stays in planning, not summarizing (#454)
A plan file with zero tasks caused `find(t => !t.done)` to return
undefined, which was treated as "all tasks done" → summarizing phase.
Now requires `tasks.length > 0` before entering summarizing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 10:05:03 -06:00
TÂCHES
65acf67762 Merge pull request #461 from deseltrus/feat/multi-milestone-enforcement
feat(discuss): three-layer enforcement for multi-milestone discussions
2026-03-15 10:02:00 -06:00
TÂCHES
58506cf833 Merge pull request #459 from deseltrus/fix/session-config
feat: session-internal /gsd config + fix key hydration in gsd config
2026-03-15 09:53:49 -06:00
TÂCHES
c0ab967f35 Merge pull request #457 from deseltrus/fix/skill-diagnostics-ux
fix(ux): improve preferences wizard and skill diagnostics
2026-03-15 09:53:46 -06:00
TÂCHES
2b34d79f8d Merge pull request #443 from fluxlabs/fix/discuss-needs-discussion-deadlock-440
fix: /gsd discuss routes to draft discussion when phase is needs-discussion
2026-03-15 09:53:43 -06:00
TÂCHES
f347572758 Merge branch 'main' into feat/multi-milestone-enforcement 2026-03-15 09:49:51 -06:00
Lex Christopherson
9f12e6a8c3 2.13.1 2026-03-15 09:30:52 -06:00
Lex Christopherson
eef3ee4a5f docs: update changelog for v2.13.1 2026-03-15 09:30:52 -06:00
Lex Christopherson
7f7f373e15 fix(tests): skip worktree path-matching tests on Windows
Git worktree path resolution on Windows CI uses UNC/8.3 temp dir forms
that don't survive normalization for path matching. The underlying source
logic works correctly (tested on macOS/Linux); these tests exercise git
worktree infrastructure that has inherent platform differences in path
representation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 09:25:40 -06:00
TÂCHES
4b167509c8 Merge pull request #484 from gsd-build/fix/m003-windows-path-compat
fix(doctor): Windows path compatibility for worktree/branch detection
2026-03-15 09:16:09 -06:00
Lex Christopherson
954e333228 fix(doctor): Windows path compatibility for worktree/branch detection
Three fixes for Windows CI failures:

1. Remove single quotes from git branch --list glob patterns. On Windows,
   cmd.exe passes single quotes literally to git, preventing glob expansion.
   Affects shouldUseWorktreeIsolation() and stale branch detection.

2. Extend listWorktrees() branch-name fallback to cover milestone/* branches,
   not just worktree/* branches. On Windows, path normalization can prevent
   path-based worktree matching; the branch-name fallback is the safety net.

3. Use path.sep instead of hardcoded "/" in CWD prefix checks (doctor.ts
   orphan fix guard, worktree-manager.ts removeWorktree guard).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 09:15:30 -06:00
Lex Christopherson
d27bf45740 fix(auto-worktree): use execFileSync for git commands with user content
Shell string interpolation of multi-line commit messages breaks on
Windows — the closing quote gets consumed mid-message, causing the
branch name suffix to be parsed as a second argument to git merge
(producing "fatal: No remote for the current branch").

Switch to execFileSync with argument arrays for merge, commit, and
add commands that include user-generated content.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 09:05:07 -06:00
TÂCHES
39540ecef1 Merge pull request #483 from gsd-build/fix/m003-windows-test-portability
fix(tests): Windows portability for M003 worktree tests
2026-03-15 09:04:44 -06:00
Lex Christopherson
23d310cd3b fix(tests): Windows portability for M003 worktree tests
- Replace single-quoted git commit messages with double quotes
- Replace bash redirect syntax with cross-platform alternatives
- Add git branch -M main to git-self-heal test setup for consistent branch naming

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 09:01:30 -06:00
Lex Christopherson
eaf909cd4b 2.13.0 2026-03-15 08:44:31 -06:00
Lex Christopherson
4504e2d6f4 docs: update changelog for v2.13.0 2026-03-15 08:44:10 -06:00
TÂCHES
2fdcc08eb0 Merge pull request #475 from gsd-build/feat/m003-worktree-isolation
feat(M003): Worktree isolation — auto-worktree lifecycle, merge strategies, self-healing git
2026-03-15 08:33:23 -06:00
Lex Christopherson
f2fc9df922 chore(M003): auto-commit after complete-milestone 2026-03-15 08:33:13 -06:00
Lex Christopherson
599c0b7648 test(M003/S07): Test suite for worktree-isolated flow
Tasks:
- chore(M003/S07): auto-commit after complete-slice
- chore(M003/S07/T01): auto-commit after execute-task
- chore(M003/S07): auto-commit after plan-slice
- docs(S07): add slice plan

Branch: gsd/M003/S07
2026-03-15 08:33:13 -06:00
Lex Christopherson
8100a1b5a0 docs(M003): reassess roadmap after S06 2026-03-15 08:33:13 -06:00
Lex Christopherson
f9b9f6bf32 chore(M003/S06): Doctor + cleanup + code simplification
Tasks:
- chore(M003/S06): auto-commit after complete-slice
- chore(M003/S06/T02): auto-commit after execute-task
- chore(M003/S06/T01): auto-commit after execute-task
- chore(M003/S06): auto-commit after plan-slice
- docs(S06): add slice plan

Branch: gsd/M003/S06
2026-03-15 08:33:13 -06:00
Lex Christopherson
34cd1056ea feat(M003/S05): Self-healing git repair
Tasks:
- chore(M003/S05): auto-commit after complete-slice
- docs: tighten GSD system prompt tool-routing — prescriptive rules + anti-patterns
- chore(M003/S05/T02): auto-commit after execute-task
- chore(M003/S05/T01): auto-commit after execute-task
- chore(M003/S05): auto-commit after plan-slice
- docs(S05): add slice plan

Branch: gsd/M003/S05
2026-03-15 08:33:13 -06:00
Lex Christopherson
4ec30cdc2d chore(M003/S04): auto-commit after reassess-roadmap 2026-03-15 08:33:13 -06:00
Lex Christopherson
01f5d2bf7f docs(M003): reassess roadmap after S04 2026-03-15 08:33:13 -06:00
Lex Christopherson
4d60b49f25 feat(M003/S04): worktree-aware merge + isolation preferences 2026-03-15 08:33:13 -06:00
Lex Christopherson
84b6f80399 docs(M003): reassess roadmap after S03 2026-03-15 08:33:13 -06:00
Lex Christopherson
b001005869 feat(M003/S03): Milestone-to-main squash merge + worktree teardown
Tasks:
- chore(M003/S03): auto-commit after complete-slice
- chore(M003/S03/T02): auto-commit after execute-task
- chore(M003/S03/T01): auto-commit after execute-task
- chore(M003/S03): auto-commit after plan-slice
- docs(S03): add slice plan

Branch: gsd/M003/S03
2026-03-15 08:33:13 -06:00
Lex Christopherson
dbc89e5b23 feat(M003/S02): --no-ff slice merges + conflict elimination
Tasks:
- chore(M003/S02): auto-commit after complete-slice
- chore(M003/S02/T02): auto-commit after execute-task
- chore(M003/S02/T01): auto-commit after execute-task
- chore(M003/S02): auto-commit after plan-slice
- docs(S02): add slice plan

Branch: gsd/M003/S02
2026-03-15 08:33:13 -06:00
Lex Christopherson
a9d97a8d4b docs(M003): reassess roadmap after S01 2026-03-15 08:33:13 -06:00
Lex Christopherson
d67c3ff5e8 feat(M003/S01): Auto-worktree lifecycle in auto-mode
Tasks:
- chore(M003/S01): auto-commit after complete-slice
- chore(M003/S01/T03): auto-commit after execute-task
- chore(M003/S01/T02): auto-commit after execute-task
- chore(M003/S01/T01): auto-commit after execute-task
- chore(M003/S01): auto-commit after plan-slice
- chore: untrack .gsd/ runtime files from git index
- docs(S01): add slice plan

Branch: gsd/M003/S01
2026-03-15 08:33:13 -06:00
Lex Christopherson
948e8983b5 chore(M003): record integration branch 2026-03-15 08:33:13 -06:00
Lex Christopherson
24597873a0 docs(M003): context, requirements, and roadmap 2026-03-15 08:33:13 -06:00
TÂCHES
ac33781fd0 Merge pull request #477 from gsd-build/fix/dispatch-loop-parse-cache-and-completion
fix(auto): kill dispatch loop paths A and B
2026-03-15 08:33:06 -06:00
Lex Christopherson
85960464eb fix(auto): clear parse cache in dispatch + verify completion in handleAgentEnd
Kills two independent failure paths causing the recurring dispatch loop bug:

Path B: dispatchNextUnit() called clearPathCache() but not clearParseCache(),
allowing stale parsed roadmap data (with [ ] instead of [x]) to persist
through the doctor→dispatch transition.

Path A: handleAgentEnd() never verified whether the just-completed unit
produced its expected artifact before re-entering the dispatch loop.
Now persists completion key after verification, so the idempotency
check in dispatchNextUnit() skips already-completed units.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 08:23:57 -06:00
TÂCHES
85b9c10265 Merge pull request #465 from deseltrus/fix/loop-recovery-all-unit-types
fix: verify artifacts on disk before bailing on dispatch loop limit
2026-03-15 08:06:01 -06:00
TÂCHES
8234e818eb Merge pull request #463 from ggomaeng/fix/loop-recovery-infinite-dispatch
fix: persist completion key in loop-recovery/self-repair to prevent infinite dispatch loops
2026-03-15 08:05:54 -06:00
deseltrus
271ab39576 fix: verify artifacts on disk before bailing on dispatch loop limit
The loop detection in dispatchNextUnit stops auto-mode when a unit has
been dispatched MAX_UNIT_DISPATCHES (3) times. Previously, only
execute-task had reconciliation logic to check whether the artifact
actually exists on disk before bailing. All other unit types
(complete-slice, plan-slice, research-slice, etc.) would immediately
stop — even if the Nth attempt successfully produced the artifact.

This is a race between the dispatch counter and disk verification:
the counter increments at dispatch time, but artifact verification
only runs during closeout of the NEXT unit. If the last allowed
attempt succeeds, the counter is already at the limit when the next
dispatch tries to run, and nobody checks disk state.

Reproduction scenario:
1. complete-slice dispatched 3 times (LLM missed writing UAT on
   attempts 1-2, succeeded on attempt 3)
2. Attempt 3 produces both SUMMARY and UAT — auto-committed to disk
3. Dispatch 4 fires: prevCount (3) >= MAX_UNIT_DISPATCHES (3)
4. No disk check for complete-slice → pipeline stops with
   'Expected artifact not found' despite artifacts existing

Fix: add a general verifyExpectedArtifact() check after the
execute-task-specific reconciliation and before the final bail-out.
If artifacts exist on disk, clear the counter and advance. If not,
same error as before — no behavior change for genuinely stuck units.
2026-03-15 10:52:50 +01:00
0xggoma
88e6957f64 fix: persist completion key in loop-recovery/self-repair to prevent infinite dispatch loops
When loop-recovery or self-repair reconciliation succeeds (artifacts exist on
disk), the dispatch counter is reset but the unit is never marked complete in
completed-units.json. If deriveState() continues returning the same unit, the
cycle repeats indefinitely: 3 dispatches → stuck detection → reconciliation
→ counter reset → 3 more dispatches...

This was observed in production burning $93.87 on 103 dispatches of a single
already-completed task over 4.9 hours.

Changes:
1. Persist completed key (persistCompletedKey + completedKeySet.add) in both
   the loop-recovery and self-repair success paths, so the idempotency check
   at the top of dispatchNextUnit prevents re-dispatch.
2. Add invalidateStateCache() after reconciliation writes to ensure the next
   deriveState() call sees fresh disk state.
3. Add a hard lifetime dispatch counter (unitLifetimeDispatches) that survives
   counter resets from reconciliation paths. Caps any single unit at 6 total
   dispatches across all reconciliation cycles.

Fixes #462
2026-03-15 01:39:19 -07:00
deseltrus
3b914033f4 fix(test): update draft-promotion test for expanded checkAutoStartAfterDiscuss
The static assertion searched the first 1200 chars of checkAutoStartAfterDiscuss
for CONTEXT-DRAFT and unlinkSync references, but the function grew to 4164 chars
after adding Gates 2-4 (STATE.md, PROJECT.md, manifest validation). The search
window now extends to the next export statement.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 09:23:26 +01:00
deseltrus
f27ed34fc0 feat(discuss): add discussion manifest for mechanical process verification
Closes the remaining gap in multi-milestone enforcement: the code
previously validated only the END STATE (files exist) but not the
PROCESS (each gate was presented to the user).

New mechanism:
- discuss.md instructs the LLM to write .gsd/DISCUSSION-MANIFEST.json
  after EACH Phase 3 gate decision, tracking gates_completed vs total
- checkAutoStartAfterDiscuss() Gate 4: BLOCKS auto-start if
  gates_completed < total (not just a warning)
- Manifest is deleted after auto-start (only needed during discussion)
- Single-milestone discussions don't use manifest (backward-compatible)
- DISCUSSION-MANIFEST.json added to baseline gitignore patterns

This creates a three-layer enforcement:
  Layer 1 (Prompt): ask_user_questions calls at each gate
  Layer 2 (Files):  CONTEXT.md/DRAFT/directory existence check
  Layer 3 (Manifest): gates_completed == total process verification

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 09:15:56 +01:00
deseltrus
ccb2a08d67 feat(discuss): harden multi-milestone gates with two-layer enforcement
Layer 1 (Prompt): discuss.md now enforces:
- Document ingestion rule: read ALL user-provided files before reflection
- Mandatory milestone confirmation gate via ask_user_questions
- 1M context awareness: prefer discussing all milestones in-session
- Phase 3 gates marked MANDATORY with progress tracking
- Default-recommend "Discuss now" over "Draft for later"

Layer 2 (Code): checkAutoStartAfterDiscuss() now validates:
- Gate 1: Primary CONTEXT.md exists
- Gate 2: STATE.md exists (written last in Phase 4, prevents
  premature auto-start during Phase 3 readiness gates)
- Gate 3: Multi-milestone completeness check against PROJECT.md
  milestone sequence — warns if milestones are missing from filesystem

Also fixes conflict markers in discuss.md from gsd/M005/S05 merge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 09:15:56 +01:00
deseltrus
d154d992dd feat(config): session-internal /gsd config + fix key hydration
Three fixes for config/setup UX:

1. cli.ts: Add missing loadStoredEnvKeys() call in gsd config flow.
   Previously, gsd config showed keys as "not configured" even when
   they existed in auth.json because env vars weren't hydrated first.

2. commands.ts: New /gsd config slash command that lets users configure
   API keys (Tavily, Brave, Context7, Jina, Groq) from within a running
   session. Keys are saved to auth.json and activated immediately.
   No need to exit the session and run gsd config externally.

3. command-search-provider.ts: Show native Anthropic web search status
   when using Claude models, so users know search works even without
   Brave/Tavily keys.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 08:35:27 +01:00
deseltrus
9aeacc803c feat(prefs): model selection via select list instead of free-text input
The preferences wizard now shows available models from the model
registry as a selectable list instead of requiring users to manually
type model IDs. Falls back to text input when no authenticated
models are available.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 07:33:12 +01:00
deseltrus
b97a47db42 feat(tui): add placeholder support to Input component
The Input component had no placeholder text support — when empty, it
showed only "> " with a blinking cursor and no hint of expected input.

The ExtensionInputComponent received a placeholder parameter but
discarded it (_placeholder with underscore = intentionally unused).

Fix: Input now has a public placeholder property. When value is empty,
renders the placeholder in dim text. ExtensionInputComponent passes
the placeholder through to Input.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 07:23:59 +01:00
deseltrus
be2492b48d fix(prefs): break parse/serialize cycle for empty arrays and objects
The preferences parser treated [] and {} as strings instead of empty
array/object. On next serialize, yamlSafeString quoted them as "[]"
and "{}", permanently corrupting the preferences file. This caused
the wizard to show empty fields (models, auto_supervisor, etc.).

Fix: parseScalar now recognizes [] and {} (quoted or unquoted) as
empty array/object. Serializer omits empty values entirely instead
of writing key: [] or key: {}.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 07:19:13 +01:00