Commit graph

176 commits

Author SHA1 Message Date
Lex Christopherson
b3f18401c4 Merge feat/work-narration: add work narration to prompts 2026-03-12 10:37:41 -06:00
Lex Christopherson
e9e22b4007 feat(prompts): add work narration instructions to system and phase prompts
Adds a Work Narration section to system.md and per-phase hints to
research, plan, and execute prompts. Instructs the LLM to emit brief
status messages between tool calls covering decisions, discoveries,
phase transitions, and verification results — without narrating
routine reads or trivial commands.
2026-03-12 10:37:37 -06:00
Lex Christopherson
077542994c chore: auto-commit before switching to gsd/M001/S01 2026-03-12 10:27:39 -06:00
Lex Christopherson
f18a547e05 docs(M001): context, requirements, and roadmap 2026-03-12 10:27:34 -06:00
Lex Christopherson
2a5c270bb0 2.3.11 2026-03-12 10:06:22 -06:00
Lex Christopherson
c6b3019504 docs: update changelog for v2.3.11 2026-03-12 10:06:13 -06:00
Lex Christopherson
19fe2c2a50 docs: update README for onboarding wizard and gsd config 2026-03-12 10:03:20 -06:00
TÂCHES
e93a44d967 feat: add clack-based onboarding wizard and gsd config command (#118)
Replace the plain-text API-key-only wizard with a branded, clack-based
onboarding experience that guides first-launch users through LLM provider
authentication (OAuth or API key), optional tool API keys, and a summary.

- Create src/logo.ts as single source of truth for ASCII logo
- Create src/onboarding.ts with shouldRunOnboarding() and runOnboarding()
- Trim src/wizard.ts to env hydration only (loadStoredEnvKeys)
- Wire onboarding into src/cli.ts, add `gsd config` subcommand
- Remove duplicate first-launch banner from src/loader.ts

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 10:02:00 -06:00
Lex Christopherson
56f079009b fix: remove 200-char truncation on parallel subagent results
Parallel mode was slicing each agent's output to 200 characters before
returning to the parent agent, destroying researcher/scout findings.
Single and chain modes already return full output — this aligns parallel.

Closes #116

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:43:37 -06:00
Lex Christopherson
e554490de1 chore: remove failing npm publish workflow
Publishing handled manually via /publish-version command.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:23:22 -06:00
Lex Christopherson
17a409f8cb 2.3.10 2026-03-12 09:21:38 -06:00
Lex Christopherson
f9c0c23c08 docs: update changelog for v2.3.10
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:21:33 -06:00
Lex Christopherson
0dc0ccbacb fix: show slash-command fallback when terminal lacks Ctrl+Alt support
Terminals like macOS Terminal.app and JetBrains IDEs don't support
the Kitty keyboard protocol, so Ctrl+Alt shortcuts silently fail.
Shortcut descriptions now detect unsupported terminals and surface
the equivalent slash command (e.g. /gsd status, /bg, /voice).

Closes #100, closes #104

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:20:10 -06:00
TÂCHES
46c88e6494 feat: branded postinstall with @clack/prompts (#115)
* feat: branded postinstall with @clack/prompts

Replace raw ANSI ASCII art dump with structured, branded installer
flow using @clack/prompts and picocolors:

- Branded intro header with product name and version
- Animated spinners during patch and Playwright install steps
- Subprocess output captured (no more raw npm/Playwright noise)
- Boxed summary note with status indicators (✓/⚠)
- Clean outro with next-step instructions
- Graceful fallback to minimal output if clack unavailable
- All output routed to stderr for npm lifecycle visibility
- Async subprocess execution (not execSync) so spinners animate

* fix: restore ASCII banner alongside clack postinstall UI

The branded ASCII art banner is a key differentiator. Keep it as the
first thing users see, then follow with clack spinner steps for the
setup progress. Fallback path also simplified since the banner already
shows the version.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:18:13 -06:00
Lex Christopherson
2a292e1981 2.3.9 2026-03-12 09:08:46 -06:00
Lex Christopherson
934a55463c docs: update changelog for v2.3.9
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:08:40 -06:00
Lex Christopherson
98d9b63894 docs: update README for v2.3.9 — add Tavily search provider
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:06:08 -06:00
Lex Christopherson
19bfcd797c fix: address review nits from #113 merge
- Fix misleading "atomically" comment on persistCompletedKey
- Consolidate duplicate "(attempt N)" strings in recovery notifications
- Add setImmediate yield in idempotency skip to prevent tight recursion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:03:00 -06:00
Lex Christopherson
1a308bd23d fix: resolve auto-mode infinite loop and closeout instability (#96, #109)
- D1: Move complete-slice dispatch before needsReassess so mergeSliceToMain
  cannot be bypassed by early reassessment
- D2: Preserve main's slice-branch-chaining guard (branch from current HEAD
  when not on a slice branch, fall back to main otherwise)
- D3: Replace consecutive-repeat stuck detection with per-unit total dispatch
  counter that catches A→B→A→B alternating loops
- Atomic closeout: write unit completion to .gsd/completed-units.json before
  in-memory update for crash recovery
- Persistent idempotency: completedKeySet loaded from disk on start/resume
- Startup self-heal: scan runtime records and clear stale ones
- Recovery backoff: exponential backoff between cross-invocation recovery attempts

Closes #96
Closes #109

Co-Authored-By: omarsharaf96 <omarsharaf96@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:01:53 -06:00
Lex Christopherson
527b63ac36 Merge origin/main into fix/auto-mode-infinite-loop-96-109
Resolve conflicts keeping PR's improvements (idempotency, recovery backoff,
self-heal, completedKeySet) merged with main's existing partial fixes
(dispatch reorder, alternating loop detection, slice-branch-chaining guard).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:01:27 -06:00
Lex Christopherson
b28299bd60 fix: allow migration without ROADMAP.md (#93, #90)
ROADMAP.md was the only fatal requirement for .planning → .gsd migration,
but the transformer already had a null-roadmap fallback that infers
milestones from the phases/ directory. Downgrade to warning so partial
v1 projects can migrate successfully.

Closes #93
Closes #90

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:55:49 -06:00
jonathancostin
0607fba4dc fix: worktree branch safety — namespacing and slice branch base selection (#92)
* fix: worktree branch namespacing and fresh-start flow

- Namespace slice branches by worktree name (gsd/<wt>/<M>/<S>) to prevent
  git checkout conflicts when multiple worktrees work on the same milestone
- getMainBranch() returns worktree/<name> inside a worktree so slice merges
  target the worktree branch instead of main (which is checked out elsewhere)
- Add continue/fresh-start prompt when creating a worktree with existing milestones
- Restyle all worktree command output with consistent semantic color palette
- Add parseSliceBranch() and SLICE_BRANCH_RE for robust branch name parsing
- Fix duplicate getCurrentBranch import in auto.ts
- Add 40-assertion integration test covering full worktree lifecycle

* fix: branch slice from current branch, not main

ensureSliceBranch always branched from getMainBranch() (main/master),
but planning artifacts (CONTEXT, ROADMAP, etc.) may only exist on the
working branch (e.g. "developer"). The slice branch would lose all
planning artifacts, causing deriveState to see pre-planning and the
rebuildState post-hook to overwrite STATE.md with a blank state.

Now branches from the current branch when it is not itself a slice
branch. Falls back to main when on a slice branch to avoid chaining.

Adds regression tests for both cases.
2026-03-12 08:48:04 -06:00
Lex Christopherson
3230cd65e9 fix: address review feedback — indentation, resume state, and regression tests
- Fix auto.ts indentation: properly indent inner if-else chain inside summarizing guard
- Clear unitDispatchCount on resume path (paused → active) to prevent stale counts
- Add parseSummary regression tests for #91: bare scalar "none" coerced to string[]
- Add parseSummary test for missing frontmatter fields yielding empty arrays
- Verify .slice().join() works on coerced arrays (the original crash pattern)

Test results: 273 passed, 0 failed (24 new assertions)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:37:00 -06:00
Lex Christopherson
254c3c8931 fix: address 11 community-reported bugs across CLI, auto-mode, and extensions
CLI routing (#81, #107):
- Import and route --mode rpc to runRpcMode() instead of silently falling through to runPrintMode
- Add TTY guard before interactive mode — exit with helpful message when stdin is not a TTY
- Add --version and --help flags

Auto-mode infinite loop (#96):
- Move summarizing/complete-slice dispatch before reassessment check (D1) — ensures mergeSliceToMain always runs
- Add per-unit dispatch counter to detect alternating loops like A→B→A→B (D3)

Windows shell escaping (#106, #98):
- Platform-aware escapeShellArg() in mcporter extension — double quotes on Windows, single quotes on Unix

CRASH: parseSummary (#91):
- Add asStringArray() helper to safely coerce YAML bare scalars (e.g. "none") to string arrays
- Applied to all 7 frontmatter fields that expect string[]

Google Search model (#99):
- Replace hardcoded gemini-3-flash-preview with env var GEMINI_SEARCH_MODEL (default: gemini-2.5-flash)

Worktree branch collision (#84):
- Check git worktree list before checkout to detect branches already in use by another worktree

Migration UX (#90, #93):
- Improve error messages to distinguish migration from new project setup, suggest /gsd:new-project

Keyboard shortcuts (#100, #104):
- Document terminal protocol requirement in shortcut descriptions — Ctrl+Alt combos need Kitty/modifyOtherKeys

Closes #81, #84, #91, #96, #99, #106, #107
Addresses #90, #93, #95, #98, #100, #104

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:37:00 -06:00
omarsharaf96
62d4ca74a2 fix: resolve auto-mode infinite loop and closeout instability (#96, #109)
Three defects in auto.ts + worktree.ts combined to produce an infinite
alternating loop and unreliable unit closeout in GSD auto-mode.

**D1 (auto.ts)** — `state.phase === "summarizing"` is now the first
branch in the dispatch if-else chain, evaluated before `needsRunUat`
and `needsReassess`. Previously, if an execute-task agent wrote
slice-level artifacts early, `needsReassess` fired instead and
`mergeSliceToMain` was permanently skipped.

**D2 (worktree.ts)** — New slice branches are now created from the
current HEAD instead of `main`. When a prior slice merge was skipped,
the new branch would inherit a stale ROADMAP from main, creating
divergent state that drove the A→B→A→B alternation.

**D3 (auto.ts)** — Replaced `lastUnit`/`retryCount` consecutive-repeat
detection with a `unitDispatchCount` map that tracks total dispatches
per unit key. The old guard reset to 0 on every ID change; the map
catches alternating-loop patterns and stops after MAX_UNIT_DISPATCHES=3.

**Atomic closeout (auto.ts)** — `persistCompletedKey` writes the unit
key to `.gsd/completed-units.json` before any in-memory update. A crash
mid-closeout is now recoverable: on next start `loadPersistedKeys`
re-populates `completedKeySet` and the idempotency guard skips already-
completed units.

**Persistent idempotency (auto.ts)** — `completedKeySet` is loaded from
disk on `startAuto` and checked before every dispatch, preventing re-
dispatch of units completed in a prior session even after a restart.

**Startup self-heal (auto.ts + unit-runtime.ts)** — `selfHealRuntimeRecords`
runs on start and resume; it scans all on-disk runtime records, checks
whether each unit's expected artifact exists, and clears any orphaned
records. Added `listUnitRuntimeRecords` to unit-runtime.ts to support
this scan.

**Recovery backoff (auto.ts)** — `recoverTimedOutUnit` now tracks
cross-invocation recovery attempts per unit in `unitRecoveryCount` and
applies exponential backoff (1s→2s→4s…30s cap) between attempts.
Attempt number is included in all recovery notify messages for
traceability.

Closes #96
Closes #109

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 10:27:18 -04:00
deseltrus
9fb348b123 feat: add Tavily as alternative search provider (#102)
Add Tavily Search API as an alternative backend for search-the-web and
search_and_read tools. Tavily is selected automatically when TAVILY_API_KEY
is set (preferred over Brave when both keys present). Existing Brave
Search paths are completely unchanged.

Motivation: Brave Search API signup requires Stripe payment which may
not be available in all regions. Tavily offers a free tier and also
provides a Deep Research API for future expansion.

Changes:
- Auth: Tavily API key in wizard, auth.json storage, env hydration
- search-the-web: Tavily POST backend with response normalization
- search_and_read: Tavily advanced search with client-side token budgeting
- /search-provider: slash command for explicit provider switching
- 61 new tests covering all Tavily integration paths
- Zero changes to existing Brave code paths
2026-03-12 07:12:19 -06:00
RoomWithOutRoof
9df0224bdd fix: use execFile on Windows to avoid single-quote issues (#103)
On Windows, cmd.exe does not strip single quotes like Unix shells.
This caused MCP tools (mcp_servers, mcp_discover, mcp_call) to fail
with 'Unknown command list' errors because mcporter received
literal 'list' instead of just list.

The fix uses execFile with shell=true on Windows, which properly
passes arguments without the shell interpreting quotes.

Closes #98

Co-authored-by: OpenClaw AI <ai@openclaw.dev>
2026-03-12 07:10:50 -06:00
Marcel Reschke
f3d995112a fix: replace broken read @GSD-WORKFLOW.md references with /gsd command (#88)
Line 5's 'When to read this' guidance updated to reflect the actual
mechanism — the file is injected programmatically by /gsd, not read
directly by the agent.

Line 659's context-pressure resume instruction updated from:
  'read @GSD-WORKFLOW.md - what\''s next?'
to:
  'run /gsd to pick up where you left off, or /gsd auto to resume in
   auto-execution mode.'

The read @GSD-WORKFLOW.md instruction was broken — the file is not
accessible via the read tool; it only enters context through
dispatchWorkflow(). Users who followed the old instruction got nothing.

Relates to #38 (same file, different problem).
2026-03-12 06:47:33 -06:00
RoomWithOutRoof
353bf7b00a docs: clarify ROADMAP.md requirement for migration (#94)
Add note that ROADMAP.md is required for migration to help
users understand why migration fails without it.

Co-authored-by: SparkLab Scout <sparklab@openclaw.ai>
2026-03-12 06:47:30 -06:00
Vedant
40f21c08a0 fix: use gemini-2.5-flash for google-search extension (#83)
gemini-3-flash-preview is not available on Vertex AI and has lower
rate limits on the Gemini Developer API. gemini-2.5-flash is the
stable model available on both Vertex AI and Gemini API.
2026-03-12 06:47:27 -06:00
Marcel Reschke
46b735ea9f fix: remove duplicate getCurrentBranch import in auto.ts (#87) 2026-03-12 06:47:16 -06:00
jonathancostin
6e1e634251 chore: remove .gsd folder from tracking and consolidate gitignore (#78)
The .gsd/ directory contains user-specific GSD project artifacts that
should never be committed. Remove all tracked .gsd files and consolidate
the .gitignore entries to a single .gsd/ rule.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 18:55:43 -06:00
Lex Christopherson
b10b78cb75 fix: guard formatCost against non-number cost values (#74)
Handle both plain number and { total: number } shapes for msg.usage.cost
in snapshotUnitMetrics, and coerce formatCost input to prevent crashes
when cost is null/undefined/NaN from corrupted ledger data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:28:25 -06:00
Lex Christopherson
7b049ea539 chore(M001): auto-commit after complete-milestone 2026-03-11 18:28:25 -06:00
Lex Christopherson
9f8d9ce7f1 feat(gsd): complete M001 — milestone summary, project update, state tracking 2026-03-11 18:28:25 -06:00
dan bachelder
dfebda73af fix: avoid sudo prompts in postinstall (#73)
Co-authored-by: Ada <ada@clawdbot>
2026-03-11 18:19:33 -06:00
jonathancostin
b1e769b4d9 feat: hide footer during auto-mode, show all stats in progress widget (#75)
During auto-mode, the built-in footer is hidden entirely via setFooter()
and all its info is moved into the progress widget:

- pwd + git branch shown inside the widget
- Token stats (↑/↓/R/W) from current unit session
- Cumulative cost from metrics ledger (survives across unit resets)
- Context window usage with color coding (warning >70%, error >90%)
- Model name right-aligned
- Footer restored to built-in on pause or stop
- No model duplication (removed from hints)
2026-03-11 18:18:08 -06:00
Lex Christopherson
9fa0d657a5 2.3.8 2026-03-11 18:12:56 -06:00
Lex Christopherson
22b92a2864 docs: update changelog for v2.3.8
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:12:53 -06:00
jonathancostin
bf6fefa16e fix: register dynamic-cwd write/read/edit tools for worktree support (#72)
The built-in write, read, and edit tools capture process.cwd() once at
startup. When /worktree switch calls process.chdir() into a worktree,
these tools still resolve relative paths against the original launch
directory. This caused GSD auto-mode to write .gsd/ artifacts to the
main project instead of the worktree.

The bash tool was already patched with a spawnHook for dynamic CWD.
Apply the same pattern to write, read, and edit: each execute() call
creates a fresh tool instance with the current process.cwd(), so
relative paths always resolve against the active working directory.
2026-03-11 17:44:57 -06:00
jonathancostin
2b9451dfd4 fix: general merge guard prevents infinite loop when complete-slice is bypassed (#71)
Replace the narrow 'if currentUnit === complete-slice' merge check with a
general merge guard that detects any completed slice branch and merges it
to main before dispatching the next unit.

The old check only triggered merges after the complete-slice unit type.
When the LLM or the doctor post-hook completed slice bookkeeping during
task execution, complete-slice was skipped entirely, leaving the slice
branch unmerged. On milestone transition, the next slice branch (forked
from main) couldn't see the prior milestone's summary, causing deriveState
to oscillate between milestones in an infinite loop.

The new guard checks: are we on a gsd/MID/SID branch where the roadmap
entry is [x]? If so, merge to main and re-derive state before dispatching.
2026-03-11 17:44:55 -06:00
Lex Christopherson
6c91434a80 2.3.7 2026-03-11 17:43:14 -06:00
Lex Christopherson
a9c4c93007 docs: update changelog for v2.3.7
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:43:00 -06:00
Lex Christopherson
1872e8db78 fix: prevent auto-mode model switches from persisting as global default (#30) and harden resume resilience (#16)
Patch SDK setModel() to accept { persist: false } so per-unit model
switching in auto-mode no longer overwrites the user's global default.
Add state rebuild + doctor on resume, guard logging for silent dispatch
failures, and active-state check before prompt injection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:39:46 -06:00
Lex Christopherson
f4c46516a6 fix: harden remote questions — validate IDs before test-send, remove dead code
- Validate channel IDs via isValidChannelId() before URL interpolation
  in setup wizard, preventing SSRF during test-send
- Add 15s fetch timeout to setup API calls (fetchJson, Discord test-send)
- Sanitize Discord error responses before surfacing to user
- Remove dead send.ts + channels.ts (unused parallel implementation)
- Add poll retry tolerance in manager.ts (1 transient error before fail)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:37:24 -06:00
TÂCHES
28a30c2cc3 Merge pull request #42 from FacuVCanale/feat/remote-user-questions
Merging — minor cleanup items will be handled in a follow-up commit. Thanks @FacuVCanale for the solid work and patience through the review rounds.
2026-03-11 17:30:23 -06:00
Lex Christopherson
c092ff97a9 2.3.6 2026-03-11 17:23:04 -06:00
Lex Christopherson
237f253f83 docs: update changelog for v2.3.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:23:02 -06:00
Lex Christopherson
1c5edbd309 fix: drop --with-deps from postinstall to prevent hidden sudo prompt
On Linux, Playwright's --with-deps flag runs sudo to install system
packages. npm's spinner hides the password prompt, making the install
appear to hang. Now installs without --with-deps and directs Linux
users to run it manually if browser tools fail.

Closes #67

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:18:25 -06:00
Lex Christopherson
a21022a3ef docs: update README for current state, remove github extension
- Remove github extension (3 files) and its test
- Fix GitHub badge/link URLs (glittercowboy/gsd-pi → gsd-build/GSD-2)
- Update /gsd description: wizard → step mode (default since /gsd next)
- Add missing commands: /gsd next, /worktree, /voice, /exit, /clear, keybindings
- Update bundled extensions: 9 → 13 (add Google Search, Mac Tools, MCPorter, Voice)
- Add Google Gemini API key to first launch, requirements, architecture tree
2026-03-11 17:10:51 -06:00