Commit graph

946 commits

Author SHA1 Message Date
Jeremy McSpadden
2df27c5179 feat(vscode): add marketplace-ready files for VS Code extension publishing
Adds everything needed to publish the extension to the VS Code Marketplace:

- README.md — full feature documentation with commands table, keyboard
  shortcuts, configuration reference, quick start guide, and @gsd chat
  participant usage
- CHANGELOG.md — initial 0.1.0 release notes
- .vscodeignore — excludes src/, tsconfig, maps from the .vsix package
- .gitignore — excludes dist/ and *.vsix from version control
- LICENSE — MIT license copied from repo root
- package.json — adds repository, homepage, bugs, keywords, galleryBanner
  fields required by the marketplace; adds @vscode/vsce to devDependencies;
  adds publish script

Verified: `npm run package` produces a clean 30KB .vsix with no warnings.
Run `npm run publish` with a VSCE_PAT token to publish.
2026-03-16 19:09:28 -05:00
Jeremy McSpadden
add9e8cf3c fix: address PR review — CSP nonce, dead branch, restart cooldown
1. Webview CSP nonce (security): Added Content-Security-Policy meta tag
   with nonce-based script-src to sidebar.ts. Replaced all inline
   onclick handlers with data-command attributes and a single delegated
   event listener, which CSP requires over inline handlers.

2. Dead branch in chat-participant.ts: Removed the isSlashCommand
   conditional that ran identical code for both paths — slash commands
   and regular messages both call sendPrompt() the same way.

3. Restart loop cooldown in gsd-client.ts: Added a 60-second sliding
   window that tracks crash timestamps. If the process crashes more
   than 3 times within 60 seconds, auto-restart is disabled and an
   error is surfaced to the user via the onError event emitter.
2026-03-16 17:28:32 -05:00
Jeremy McSpadden
6ed9cd5359 fix: resolve CI failures in VS Code extension PR
- Fix Windows MCP test failures: use pathToFileURL() instead of bare
  join() paths for dynamic imports, fixing ERR_UNSUPPORTED_ESM_URL_SCHEME
  on Windows where D:\ paths are not valid ESM import specifiers

- Remove parallel orchestration code that was WIP from another feature
  branch and not part of the VS Code extension scope (commands.ts,
  preferences.ts, types.ts changes reverted to main)

- Rebase cleanly onto main, resolving mcp-server.ts merge conflict by
  keeping main's dynamic import approach with PR's exported interface
  and JSDoc documentation
2026-03-16 16:53:34 -05:00
Jeremy McSpadden
d5e664c580 feat: fully flesh out VS Code extension with all RPC features
GsdClient — expose all 25 RPC commands:
- Prompting: steer, followUp
- Thinking: setThinkingLevel, cycleThinkingLevel
- Compaction: compact, setAutoCompaction
- Retry: setAutoRetry, abortRetry
- Bash: runBash, abortBash
- Session: getSessionStats, exportHtml, switchSession, setSessionName,
  getMessages, getLastAssistantText, getCommands
- Model: cycleModel

Extension — register 15 commands with full UI:
- switchModel (QuickPick with context windows)
- setThinking (QuickPick off/low/medium/high)
- sessionStats (formatted token/cost display)
- exportHtml (save dialog)
- steer/runBash (input boxes)
- listCommands (QuickPick, select to execute)
- Keybindings: ctrl+shift+g chords for new session, cycle model, cycle thinking
- Config: gsd.autoStart, gsd.autoCompaction

Sidebar — full dashboard:
- Thinking level badge and toggle
- Token usage (input/output) and cost from session stats
- Streaming spinner indicator
- Model selector and quick action buttons (compact, export, abort)
- Auto-compaction toggle
- 10s periodic refresh for live stats

Chat participant — enhanced event handling:
- Tool-specific details (file paths, bash commands, grep patterns)
- Thinking block display
- Token usage summary at end of each response
2026-03-16 16:46:21 -05:00
Jeremy McSpadden
48feced87d feat: add VS Code extension scaffold and MCP server compiled module
- Add vscode-extension/ with full MVP scaffold:
  - GsdClient: spawns gsd --mode rpc, JSON line communication
  - @gsd Chat participant: forward messages to agent, stream responses
  - Sidebar panel: connection status, model info, start/stop controls
  - Command palette: gsd.start, gsd.stop, gsd.newSession, gsd.sendMessage
  - Extension config: gsd.binaryPath setting
- Add compiled MCP server module at src/mcp-server.ts for tsc output
- Add MCP server tests verifying module import and instantiation
2026-03-16 16:46:20 -05:00
Lex Christopherson
580823c154 2.22.0 2026-03-16 15:27:24 -06:00
Lex Christopherson
fe79222bda docs: update changelog and README for v2.22.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 15:26:55 -06:00
TÂCHES
da25c0b692 Merge pull request #703 from rangoc/fix/auto-mode-skill-loading
fix(prompts): make skill loading an active directive in auto-mode units
2026-03-16 15:22:50 -06:00
TÂCHES
915112ca1f Merge pull request #710 from jeremymcs/fix/707-execute-task-verification-budget
fix: pass verificationBudget to execute-task prompt template
2026-03-16 15:17:31 -06:00
TÂCHES
f550904724 Merge pull request #708 from jeremymcs/fix/gsd-cleanup-command
fix: handle bare /gsd cleanup command
2026-03-16 15:17:10 -06:00
TÂCHES
bbe665ac04 Merge pull request #702 from ryharrin/fix/gsd-bg-shell-stale-cwd
fix: stop bg-shell from persisting into stale auto-worktree paths
2026-03-16 15:16:38 -06:00
Jeremy McSpadden
b8e6294e6b fix: pass verificationBudget to execute-task prompt template
buildExecuteTaskPrompt() was missing the verificationBudget variable
that the execute-task.md template expects. The prompt-loader's strict
placeholder validator threw on every auto-mode task dispatch, blocking
all execution entirely.

Compute the budget from the executor's context window using the existing
computeBudgets() engine and pass it as ~NNK chars format string.

Fixes #707
2026-03-16 16:07:53 -05:00
Jeremy McSpadden
d19e213010 fix: handle bare /gsd cleanup command
Previously, running `/gsd cleanup` without a subcommand (branches or
snapshots) fell through to the unknown command handler, producing a
warning. Now bare `/gsd cleanup` runs both branch and snapshot cleanup.
2026-03-16 16:04:00 -05:00
Ryan Harrington
f87b4938ca fix/gsd-bg-shell-stale-cwd: normalize bg-shell worktree cwd detection 2026-03-16 17:02:58 -04:00
rangoc
b5ee1def82 fix(prompts): make skill loading an active directive in auto-mode units
The execute-task, plan-slice, and research-slice prompts all include a
passive instruction to 'use GSD Skill Preferences to decide which skills
to load.' In practice, auto-mode agents never act on this — across 30+
execution units in a real milestone, zero skill files were read.

The root cause is that the passive wording ('use it to decide') gets
overridden by the stronger 'don't re-research, just build what the plan
says' directive in execute-task. The agent treats skill loading as
optional and skips it 100% of the time.

This change rewrites the skill instruction in all three prompts from
passive guidance to an explicit action:
- execute-task: 'read its SKILL.md file now — before writing any code'
- plan-slice: 'read any skill files relevant to this slice's technology
  stack before decomposing'
- research-slice: 'read any skill files relevant to this slice's
  technology stack before exploring code'

The execute-task change also points agents to both the GSD Skill
Preferences block AND the <available_skills> catalog, since both are
present in the system prompt but the old instruction only referenced
the preferences block.

The plan-slice change adds guidance to note relevant skills in task
plans, so executors know which skills to load without rediscovering
them.
2026-03-16 21:48:31 +01:00
Ryan Harrington
8b8ba0d207 fix/gsd-bg-shell-stale-cwd: resync bg-shell cwd after auto-worktree exit 2026-03-16 16:45:21 -04:00
TÂCHES
2b0c0064cd Merge pull request #697 from gsd-build/feat/forensics 2026-03-16 14:41:03 -06:00
Lex Christopherson
76f73243eb fix: handle undefined return from ctx.ui.input in forensics
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:32:21 -06:00
TÂCHES
a5cf0f88b1 Merge pull request #696 from trek-e/fix/695-stray-worktree-detection
fix: validate auto-worktree is a real git worktree before use (#695)
2026-03-16 14:29:40 -06:00
TÂCHES
f73b17f55b Merge pull request #694 from gsd-build/fix/pr-673-security-fixes
fix: command injection and path traversal in PR #673
2026-03-16 14:29:19 -06:00
TÂCHES
966e5e80fb Merge pull request #673 from jeremymcs/feat/v2.20-phase2-3-features
feat: v2.20 Phase 2-4 — skills, integrations, MCP server
2026-03-16 14:29:07 -06:00
TÂCHES
b1b8a1f782 Merge pull request #693 from trek-e/fix/692-mcp-json-project-root
fix: discover MCP servers from project-root .mcp.json (#692)
2026-03-16 14:28:30 -06:00
Lex Christopherson
14f8135972 feat: add /gsd forensics subcommand for auto-mode failure investigation
Scans activity logs, metrics, crash locks, and doctor diagnostics for
anomalies, generates a structured forensic report, saves it locally,
and hands it to the LLM for interactive root-cause analysis with
optional GitHub issue creation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:25:23 -06:00
Tom Boucher
e9a2928ce7 fix: validate auto-worktree is a real git worktree before use (#695)
getAutoWorktreePath() only checked existsSync() on the worktree
directory, treating any directory under .gsd/worktrees/<MID>/ as a
valid auto-worktree. A stray (non-git) directory would be accepted,
causing auto-mode to derive state from an empty/invalid path and
conclude no milestones exist.

Add git worktree validation to both getAutoWorktreePath() and
enterAutoWorktree(): check that the directory contains a .git file
(not directory) with a 'gitdir:' pointer, which is the hallmark of
a real git worktree checkout. Return null / throw if validation fails.

This ensures stray directories are ignored and auto-mode falls through
to normal worktree creation or root-state derivation.

Closes #695
2026-03-16 16:24:19 -04:00
TÂCHES
9838ef3781 Merge pull request #689 from jeremymcs/fix/visualizer-completedAt-date-coercion
fix: coerce completedAt to String in visualizer changelog sort
2026-03-16 14:18:09 -06:00
TÂCHES
e4d47de1f6 Merge pull request #690 from trek-e/fix/688-thinking-minimal-gpt5
fix: clamp 'minimal' thinking level to 'low' for gpt-5.x models (#688)
2026-03-16 14:17:51 -06:00
Tom Boucher
7b11faa150 fix: discover MCP servers from project-root .mcp.json (#692)
The mcporter extension only discovered servers that the mcporter CLI
itself knew about (via .vscode/mcp.json, Claude Desktop config, etc.).
Servers configured in the standard .mcp.json at the project root —
used by Claude Code, Cursor, and other AI coding tools — were invisible.

Changes:

1. mcporter extension (index.ts):
   - Add readProjectMcpJson() that reads .mcp.json from cwd and returns
     servers not already discovered by mcporter
   - Merge .mcp.json servers into getServerList() results
   - Add getMcpJsonServerUrl() to resolve HTTP URLs for .mcp.json servers
   - Update getServerDetail() to pass HTTP URLs directly to mcporter
     for servers only known via .mcp.json
   - Update mcp_call to use HTTP URL as server reference for .mcp.json
     servers

2. discover_configs scanner (scanners.ts):
   - Add .mcp.json to the project-level MCP config scan path alongside
     .claude/.mcp.json and .claude/mcp.json

Closes #692
2026-03-16 16:15:02 -04:00
Lex Christopherson
d87a4423b0 fix: eliminate command injection surface in diff-context, harden file-watcher path resolution
Use execFileSync with argument arrays instead of execSync with string
interpolation to prevent shell injection via sinceDays parameter.
Validate sinceDays as a positive integer. Replace string-based path
resolution in file-watcher with path.relative() to prevent traversal
via symlinks or .. segments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:10:29 -06:00
Tom Boucher
1a499aecb2 fix: clamp 'minimal' thinking level to 'low' for gpt-5.x models (#688)
gpt-5.x models (via Copilot/OpenAI/Azure) don't support 'minimal' as a
reasoning effort level — they only accept 'none', 'low', 'medium',
'high', and 'xhigh'. Setting /thinking minimal with gpt-5.4 causes a
400 error.

The openai-codex-responses provider already had this clamping, but the
openai-responses and azure-openai-responses providers passed the value
through unclamped.

Add clampReasoningForModel() to both providers that maps 'minimal' to
'low' for gpt-5.x models, matching the existing behavior in
openai-codex-responses.

Fixes the bug portion of #688
2026-03-16 16:02:54 -04:00
Jeremy McSpadden
a01df1f110 fix: coerce completedAt to String in visualizer changelog sort
YAML frontmatter parsers can return Date objects for ISO date strings
instead of plain strings. This caused a TypeError when calling
.localeCompare() on a Date object in the changelog sort.

Wrap completedAt with String() at both assignment and sort to handle
both native and JS parser paths safely.
2026-03-16 14:59:29 -05:00
TÂCHES
72223d0a7a Merge pull request #685 from gsd-build/fix/643-warp-unsupported-shortcuts
fix: add Warp to unsupported Ctrl+Alt shortcut list
2026-03-16 13:43:40 -06:00
Jeremy McSpadden
062b5c65eb fix: skip environment-dependent tests in CI
- Skip E2E --print test when no API key is configured (process hangs
  waiting for onboarding wizard input in non-TTY CI environments)
- Skip file-watcher extensions subdirectory test on Windows (chokidar
  subdirectory event delivery is unreliable in Windows CI runners)
2026-03-16 14:38:59 -05:00
Lex Christopherson
36345c12fc fix: add Warp terminal to unsupported Ctrl+Alt shortcut list
Warp terminal (both macOS and Windows) does not emit recognized escape
sequences for Ctrl+Alt key combos. This adds Warp to the unsupported
terminals list so users see the /gsd status fallback hint.

Closes #643

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 13:37:53 -06:00
Jeremy McSpadden
3690e7a8ca fix: stabilize file-watcher and E2E smoke tests for CI
- Increase file-watcher extension directory test delay to 1500ms with
  500ms settle time (Windows filesystem events are slower)
- Make E2E --print test more permissive on exit code 1: check for
  unhandled crash indicators instead of specific error messages
  (error text varies by CI environment)
2026-03-16 14:32:25 -05:00
TÂCHES
07effd64cc Merge pull request #471 from Jamie-BitFlight/feat/claude-import-skills-plugins
feat: import Claude marketplace plugins with namespaced components
2026-03-16 13:32:09 -06:00
TÂCHES
c03505dd69 Merge pull request #684 from trek-e/fix/677-plan-slice-executor-constraints
fix: provide executorContextConstraints to plan-slice template (#677)
2026-03-16 13:31:51 -06:00
TÂCHES
0ad5bebc33 Merge pull request #683 from trek-e/fix/681-fractional-slice-id
fix: support fractional slice IDs (e.g. S03.5) in roadmap parser (#681)
2026-03-16 13:31:10 -06:00
Tom Boucher
7b014e13fb fix: support fractional slice IDs (e.g. S03.5) in roadmap parser (#681)
The roadmap parser regex used (\w+) to capture slice/task IDs, which
only matches [a-zA-Z0-9_]. Fractional IDs like S03.5 (created by
/gsd steer) contain a dot, causing the parser to skip the entire line.

The dispatcher then jumps from S03 to S04, finds S04 blocked by
the unparsed S03.5, and gives up with 'earlier slice is not complete'.

Update the ID capture group to ([\w.]+) in both:
- roadmap-slices.ts (primary roadmap parser)
- files.ts (plan task parser, for consistency)

This allows dots in slice/task IDs while preserving all existing
behavior for standard IDs like S01, S02, T01, etc.

Closes #681
2026-03-16 15:25:58 -04:00
Jeremy McSpadden
4f8a4a76b3 fix: add compiled MCP server module for --mode mcp support
Create src/mcp-server.ts with dynamic imports to bypass TypeScript's
static module resolution for @modelcontextprotocol/sdk subpath exports
that use wildcard patterns (./*) without matching type declarations.
2026-03-16 14:24:32 -05:00
Tom Boucher
523debee6c fix: provide executorContextConstraints to plan-slice template (#677)
The plan-slice.md template declares {{executorContextConstraints}} but
buildPlanSlicePrompt() never passed this variable, causing loadPrompt()
to throw: 'template declares {{executorContextConstraints}} but no value
was provided.'

Add formatExecutorConstraints() that uses the budget engine
(computeBudgets + resolveExecutorContextWindow) to generate the
executor context constraints block with task count ranges and inline
context budgets based on the configured executor model's context window.

Pass the formatted string to loadPrompt() as executorContextConstraints.

Closes #677
2026-03-16 15:23:39 -04:00
TÂCHES
5a2d194f64 Merge pull request #678 from trek-e/fix/654-worktree-state-sync
fix: sync worktree .gsd/ state to project root after each unit (#654)
2026-03-16 13:21:51 -06:00
TÂCHES
0112a0f390 Merge pull request #680 from trek-e/fix/658-warp-cursor-visibility
fix: auto-enable hardware cursor in Warp terminal (#658)
2026-03-16 13:20:37 -06:00
TÂCHES
36d5ad7a0e Merge pull request #679 from trek-e/fix/455-tui-scrollback-disruption
fix: remove CSI 3J scrollback clear from TUI full redraws (#455)
2026-03-16 13:20:13 -06:00
TÂCHES
d66679e6ad Merge pull request #675 from deseltrus/fix/worktree-edge-cases
fix: worktree edge cases (resolveGitDir, captureIntegrationBranch, doctor)
2026-03-16 13:19:52 -06:00
Tom Boucher
bdbd3579c9 fix: sync worktree state to project root after each unit (#654)
When auto-mode runs in a worktree, .gsd/ metadata (STATE.md, roadmap
checkboxes, slice plans, task summaries) only updates inside the
worktree directory. The project root on main retains stale state.

If auto-mode restarts, startAutoMode() calls deriveState(projectRoot)
which reads the stale .gsd/ from main, sees completed units as
incomplete, and re-dispatches them — causing an infinite loop on
already-finished work.

Add syncStateToProjectRoot() that copies STATE.md and the active
milestone directory from worktree → project root after each unit's
rebuildState + autoCommit. This ensures deriveState(projectRoot) on
restart reads current completion state.

The sync is fully non-fatal (try/catch wrapped). Failure falls back
to existing behavior. Uses cpSync with recursive:true for the
milestone directory tree.
2026-03-16 15:13:24 -04:00
deseltrus
35f63f050a fix: derive initial state from worktree when one exists (#654)
When auto-mode restarts after being stopped, the initial deriveState()
reads from the project root which has stale .gsd/ metadata. Completed
units appear incomplete, causing re-dispatch of finished work.

The auto-worktree (if it exists from the previous run) has the current
state. After the initial deriveState(base), check if an auto-worktree
exists for the active milestone and re-derive from there.

This is safe because:
- Only triggers when worktree isolation is enabled
- Only when not already inside a worktree
- Only when an auto-worktree actually exists for the milestone
- The worktree setup at lines 976+ still runs normally after

Fixes #654

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 20:13:16 +01:00
deseltrus
25eab8f368 test: fix worktree-bugfix tests for CI (git config + Windows compat)
Use separate git commands instead of && chains (fails on Windows).
Configure git user.name/email before commit (not set in CI runners).
Mirrors the pattern from worktree-e2e.test.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 20:13:02 +01:00
Tom Boucher
d862c43424 fix: auto-enable hardware cursor in Warp terminal (#658)
Warp terminal does not correctly re-render inverse video (\x1b[7m)
cursor indicators on arrow key movement, making the cursor appear
invisible when navigating with arrow keys.

Auto-detect Warp via TERM_PROGRAM=WarpTerminal and enable the hardware
cursor by default (same as PI_HARDWARE_CURSOR=1). The hardware cursor
is positioned correctly via CURSOR_MARKER and provides reliable visual
feedback in Warp.

Terminals that render inverse video correctly (iTerm2, Terminal.app)
are unaffected — they continue using the fake cursor by default.
2026-03-16 15:11:58 -04:00
TÂCHES
feccaf2998 Merge pull request #674 from trek-e/chore/docs-v2.20.0
docs: update documentation for v2.20.0 release
2026-03-16 13:11:50 -06:00
TÂCHES
2f1abf7aae Merge pull request #676 from adamdry/f-opt-out-of-worktrees
feat: add git.isolation "none" mode — no worktree, no milestone branch
2026-03-16 13:11:35 -06:00