Commit graph

878 commits

Author SHA1 Message Date
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
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
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
Jeremy McSpadden
ce6e684899 fix: increase file-watcher test delay for CI stability 2026-03-16 14:00:47 -05:00
Jeremy McSpadden
084fb35c1e ci: trigger CI run after force push 2026-03-16 13:57:29 -05:00
Jeremy McSpadden
8d56ab2893 feat: add MCP server mode, /lint skill, E2E smoke tests
- Add native MCP server mode (--mode mcp): exposes GSD's tools via
  Model Context Protocol over stdin/stdout for Claude Desktop, VS Code,
  and other MCP-compatible clients. Uses @modelcontextprotocol/sdk.
- Add /lint skill: auto-detects ESLint, Biome, Prettier, rustfmt,
  gofmt, Black, Ruff and runs with structured output
- Add 6 E2E smoke tests: --version, --help, config --help, update
  --help, --list-models, and --mode text --print startup
- Fix diff-context.ts stdio type for CI compatibility
- Fix token-counter.ts tiktoken import for extensions typecheck
- Update help text and CLI to include --mode mcp
2026-03-16 13:56:31 -05:00
Jeremy McSpadden
973b8992e5 feat: add GitHub API client, diff-aware context, tiktoken token counting
- Add GitHub API integration via @octokit/rest: createGitHubClient,
  getRepoInfo (parses HTTPS/SSH remotes), createPullRequest,
  getPullRequest, listPullRequestReviews, createIssueComment
- Add diff-aware context module: getRecentlyChangedFiles,
  getChangedFilesWithContext, rankFilesByRelevance — prioritizes
  recently-changed files for context window budget allocation
- Add accurate token counting via tiktoken: countTokens (async),
  countTokensSync, initTokenCounter — falls back to chars/4 heuristic
  when tiktoken is unavailable
- 27 new tests across 3 test files
2026-03-16 13:50:00 -05:00
Jeremy McSpadden
0b3163d297 feat: add /review skill, /test skill, chokidar file watcher, subcommand help
- Add /review skill: reviews staged/unstaged/commit changes for security,
  performance, bugs, and quality with structured findings by severity
- Add /test skill: auto-detects test framework, generates comprehensive
  tests for source files, or runs suites with failure analysis
- Add chokidar file watcher: watches ~/.gsd/agent/ for config changes
  (settings.json, auth.json, models.json, extensions/) with debounced
  events on an EventBus
- Add --help per subcommand: `gsd config --help` and `gsd update --help`
  show subcommand-specific usage information
- 8 new file-watcher tests (start/stop, event emission, debouncing,
  unrelated file filtering)
2026-03-16 13:47:25 -05:00
TÂCHES
a90aa0c8d6 Merge pull request #666 from jeremymcs/fix/v2.19.0-phase1-quick-wins
fix: v2.20 Phase 1+2 — bugs, security, performance, code quality
2026-03-16 12:44:17 -06:00
TÂCHES
0a43e6de4e Merge pull request #671 from gsd-build/fix/665-auto-resume-recovery
fix: auto-mode resume preserves context from paused session
2026-03-16 12:44:08 -06:00
Jeremy McSpadden
6a46c9df1a fix: resolve browser-tools TypeScript type errors in CI
Fix type compatibility issues introduced in the JS→TS conversion:
- Restore PageEntry.page to `any` (holds Playwright Page instance)
- Use Record<string, any> for session parameters in
  buildFailureHypothesis and summarizeBrowserSession (callers pass
  rich objects with extra properties)
- Use Record<string, unknown> for formatTimelineEntries options
- Add explicit type annotations to local variables and callbacks
  to satisfy noImplicitAny in tsconfig.extensions.json
2026-03-16 13:39:14 -05:00
TÂCHES
26b4e483bd Merge pull request #669 from gsd-build/fix/662-task-count-display
fix: clamp task counter to prevent display overflow after loop recovery
2026-03-16 12:36:02 -06:00
Jeremy McSpadden
ebbcbe363a security: add SSRF protection to fetch_page tool
Block requests to private/internal addresses in the fetch_page tool:
- Private IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x)
- Cloud metadata endpoints (metadata.google.internal, instance-data)
- localhost
- Non-HTTP protocols (file://, ftp://)
- IPv6 private ranges (::1, fc00:, fd, fe80:)

Add isBlockedUrl() to url-utils.ts with 11 new tests covering all
blocked and allowed URL patterns.
2026-03-16 13:35:48 -05:00
TÂCHES
970479d5b4 Merge pull request #668 from gsd-build/fix/663-small-issues
fix: resolve 4 small issues (#663)
2026-03-16 12:35:48 -06:00
Lex Christopherson
38c300fd80 fix: reuse crash recovery infrastructure for pause/resume context (#665)
Capture the session file path on pause and synthesize a recovery briefing
on resume, so the next agent knows what already happened instead of
restarting the unit from scratch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:35:03 -06:00
Jeremy McSpadden
d41338cafb refactor: extract inline build scripts from package.json to files
- Extract copy-resources, copy-themes, copy-export-html from root
  package.json inline node -e commands to proper .cjs script files
- Extract pi-coding-agent copy-assets (356-char inline command) to
  scripts/copy-assets.cjs with readable multi-line formatting
- All scripts use .cjs extension for CommonJS compatibility in ESM
  package context
2026-03-16 13:34:05 -05:00
Jeremy McSpadden
4af3e5b741 fix: move @types/mime-types to devDependencies, align chalk versions
- Move @types/mime-types from dependencies to devDependencies in pi-tui
  (type declarations are only needed at compile time)
- Align chalk version: upgrade root from ^5.5.0 to ^5.6.2 to match
  pi-ai and avoid version skew
2026-03-16 13:31:15 -05:00
Jeremy McSpadden
a79e953caa refactor: deduplicate help text, cross-platform validate-pack, fix dev.js
- Extract duplicated help text from loader.ts and cli.ts into shared
  help-text.ts module (single source of truth)
- Convert validate-pack.sh to Node.js for Windows compatibility
- Fix dev.js using unnecessary npx for tsc (it's a devDependency,
  use node_modules/.bin/tsc directly)
2026-03-16 13:29:31 -05:00
Lex Christopherson
3399852f6d fix: clamp task counter to prevent "task 5/4" display after loop recovery
When auto-mode loop recovery marks tasks as [x] in the plan file and
auto is restarted, the done count can equal total. The display always
showed done+1 (assuming "currently working on next task"), causing
values like "task 5/4". Clamp to total so it never exceeds the max.

Closes #662

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:26:06 -06:00
TÂCHES
1a856ec109 Merge pull request #667 from gsd-build/fix/664-cancel-stale-async-jobs
fix: cancel stale async jobs after source edits (#664)
2026-03-16 12:25:53 -06:00
Jeremy McSpadden
9c8a24042f feat: convert browser-tools/core.js to TypeScript, add c8 test coverage
- Convert browser-tools/core.js (1058 lines) to native TypeScript with
  full type annotations from the existing .d.ts file. Remove the
  separate .d.ts declaration file (types are now inline).
- Add c8 test coverage reporting: `npm run test:coverage` generates
  text + lcov reports with 50% statement threshold baseline.
- Add coverage/ to .gitignore

All 712 unit tests, 63 browser-tools tests, and 11 integration tests
pass with zero regressions.
2026-03-16 13:25:52 -05:00
Lex Christopherson
a58e256e42 fix: resolve 4 small issues reported in #663
1. Windows: `start` command opens CMD instead of browser during GitHub
   Copilot login — pass empty title arg so URL is treated as target
2. Launch banner missing Tavily provider in web search status display
3. MCPorter auto-installs via npm when not found (like ripgrep auto-download)
4. Notification prefs showing [object Object] — guard against non-boolean values

Closes #663

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:23:20 -06:00
Lex Christopherson
d6cf8b4358 fix: add stale async job cancellation heuristic to system prompt (#664)
Agent now cancels in-flight async_bash jobs after editing source files
before re-running them, preventing stale results from polluting context.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:20:54 -06:00
Jeremy McSpadden
2c926c12e3 fix: Phase 1 quick wins — bug fixes, security hardening, and performance
- Fix loadStoredEnvKeys divergent provider lists: add telegram_bot and
  custom-openai to wizard.ts (the canonical copy used by CLI), remove
  dead duplicate from onboarding.ts
- Security: add SAFE_COMMAND_PREFIXES allowlist to resolveConfigValue
  to prevent arbitrary RCE via settings.json shell commands
- Security: add TOFU (Trust On First Use) model for project-local
  extensions — skip untrusted .pi/extensions/ with stderr warning
- Performance: debounce sql.js MemoryStorage persistence (500ms window)
  so rapid mutations coalesce into a single db.export()+writeFileSync
- Fix double lstatSync call in tool-bootstrap.ts isRegularFile
- Add 26 new tests covering all changes
2026-03-16 13:18:02 -05:00
Lex Christopherson
2966be30cb 2.20.0 2026-03-16 12:16:27 -06:00
Lex Christopherson
04424de6b2 docs: update changelog and README for v2.20.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:16:05 -06:00
TÂCHES
26facfca51 Merge pull request #661 from gsd-build/fix/456-milestone-detection-loop
fix: prevent infinite loop when milestone detection silently fails (#456)
2026-03-16 12:08:06 -06:00
Lex Christopherson
2da97b2382 merge: sync with main 2026-03-16 12:03:54 -06:00
TÂCHES
445528e865 Merge pull request #573 from gsd-build/test/extension-smoke-test
test: add extension smoke test to catch import failures in CI
2026-03-16 12:02:00 -06:00
Lex Christopherson
cae7d08879 fix: prevent infinite loop when milestone detection silently fails (#456)
findMilestoneIds() had a bare catch that returned [] on any error,
causing showSmartEntry() to think no milestones exist and restart
the new-project discuss flow in a loop. Add error logging when the
directory exists but scanning fails, and a sanity check that warns
the user instead of looping when the directory has entries that
weren't recognized.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:57:54 -06:00
Lex Christopherson
3d2f294f6a fix: google-search OAuth test mock and Windows path separator in smoke test
- google-search test: mock getApiKeyForProvider to return JSON string
  matching real OAuth provider behavior (token+projectId), instead of
  using AuthStorage.inMemory which bypasses the OAuth getApiKey transform
- smoke test: split on /[/\\]/ for Windows path separator compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:56:46 -06:00
Lex Christopherson
e66c73daae fix: add missing ProjectTotals fields in visualizer-views test fixture
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:49:58 -06:00
Lex Christopherson
20e0fe2460 Merge remote-tracking branch 'origin/main' into test/extension-smoke-test 2026-03-16 11:48:44 -06:00
Lex Christopherson
d187a1ed2d fix: use file:// URL for dynamic imports in smoke test (Windows compat)
On Windows, raw paths like D:\... are interpreted as protocol "d:" by
the ESM loader. Convert via pathToFileURL before dynamic import.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:46:04 -06:00
TÂCHES
c6ec4eef50 Merge pull request #660 from gsd-build/copilot/add-blacklist-feature
[WIP] Add blacklist feature for certain directories in chat
2026-03-16 11:34:38 -06:00
Lex Christopherson
8715b5f604 merge: add Google OAuth search support (#466)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:33:56 -06:00
Lex Christopherson
02ff88d711 Merge remote-tracking branch 'origin/main' into feat-google-oauth-search 2026-03-16 11:33:50 -06:00
Lex Christopherson
413dbe48eb Merge branch 'main' of https://github.com/gsd-build/GSD-2 2026-03-16 11:27:20 -06:00
TÂCHES
9c62cb97df Merge pull request #657 from gsd-build/merge-fix/594-context-budget
feat(gsd): context-window budget engine — proportional prompt sizing for 1M context models
2026-03-16 11:26:39 -06:00
Lex Christopherson
a0397682a4 merge: fix CPU spinning from regex backtracking (#495)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:26:33 -06:00
Lex Christopherson
79d3765379 merge: resolve conflicts with upstream main
Kept both health gate (main) and debug timer (PR) in auto.ts.
Added agentInstructionsBlock to fullSystem composition in index.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:26:13 -06:00
Lex Christopherson
545ccf58d7 merge: resolve metrics.ts conflict with main
Combine budget fields (contextWindowTokens, truncationSections,
continueHereFired) from PR #594 with prompt char tracking fields
(promptCharCount, baselineCharCount) from main.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:25:53 -06:00
copilot-swe-agent[bot]
73fc14c440 Initial plan 2026-03-16 17:23:36 +00:00
TÂCHES
011ed1df71 feat: add Telegram as remote questions channel (#645) (#655)
Add Telegram Bot API as a third remote questions channel alongside
Discord and Slack. Implements the ChannelAdapter interface with inline
keyboard buttons, callback query handling, text reply polling, and
supergroup message URL generation.

Closes #645

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:09:39 -06:00
Rebecca Chernoff
17fbf7d925 fix: skip onboarding wizard when extension provider already configured (#589)
Extension-based providers like pi-claude-cli may not require credentials
in auth.json, causing shouldRunOnboarding() to always return true and
repeat the wizard every launch. Now checks if a defaultProvider is
already set in settings before triggering the wizard.
2026-03-16 11:07:15 -06:00
Lex Christopherson
daf36d2b7a fix: resolve merge conflicts with main for PR #594
Merge main into feat/context-window-budget, combining:
- Budget fields (contextWindowTokens, truncationSections, continueHereFired)
  from the PR with routing fields (tier, modelDowngraded) from main in
  UnitMetrics interface
- Unified opts parameter pattern in snapshotUnitMetrics
- KNOWLEDGE.md step from main with template path references from the PR
  in execute-task.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:04:58 -06:00
Jeremy McSpadden
2042a30232 feat: workflow mode system (solo/team) with /gsd mode command (#651)
* feat: add workflow mode system (solo/team) with /gsd mode command

Introduces a `mode` preference that bundles sensible defaults for solo
developers vs team workflows, replacing the need to manually configure
5-8 individual git preferences.

* fix: resolve TS2339 — use string narrowing for ctx.ui.select return type
2026-03-16 11:04:51 -06:00
Tom Boucher
cdf42fe001 fix: prevent model config bleed between concurrent GSD instances (#650) (#652)
Two fixes for the model configuration bleeding between simultaneous
GSD instances that share the same global settings.json.

## Root Cause

1. `setDefaultModelAndProvider()` always persisted to `~/.gsd/agent/settings.json`
   (global), so when either instance's interactive mode changed models (via
   Ctrl+P or /model), it overwrote the other instance's saved default.

2. When auto-mode dispatched a new unit (after context wipe), if no
   per-unit-type model preference was configured, the session picked up
   the default from the now-contaminated global settings file.

## Fix 1: Project-scoped model persistence (settings-manager.ts)

`setDefaultModelAndProvider()`, `setDefaultModel()`, and `setDefaultProvider()`
now persist to project-level settings (`.pi/settings.json`) when a project
settings file exists, falling back to global only when no project context
is available. This prevents concurrent instances from overwriting each
other's model choice.

Added `hasProjectSettingsFile()` helper to detect project context.

## Fix 2: Auto-mode model capture (auto.ts)

Captures the session's model at auto-mode start (`autoModeStartModel`).
At each unit dispatch, if no model preference is configured for the unit
type, the captured model is re-applied with `persist: false`. This
ensures each auto-mode session maintains its own model regardless of
what other instances write to the shared settings file.

## Tests

3 new tests covering:
- Project settings file isolates model from global
- Two projects have independent model configs
- autoModeStartModel concept prevents model drift

All 448 existing tests pass.

Fixes #650
2026-03-16 10:59:12 -06:00
Jeremy McSpadden
53edf284fa feat: /gsd quick command & agent-instructions.md injection (#437)
* fix: bg_shell ready_port timeout and error handling (#428)

When a server fails to bind to the configured ready_port, the process
would stay in "starting" status indefinitely after the probing interval
cleared, with no error surfaced to the agent. This fixes the hang by:

- Transitioning process to "error" status when port probing times out
- Detecting process exit during port polling and reporting stderr context
- Adding ready_timeout parameter for custom timeout values
- Including stderr output in waitForReady timeout/error responses
- Registering SIGTERM/SIGINT handlers to clean up bg processes on exit

Closes #428

* feat: add /gsd quick command and agent-instructions.md injection (#425)

Implements two features from issue #425:

1. `/gsd quick <task>` — lightweight task execution with GSD guarantees
   (atomic commits, state tracking) without the full milestone ceremony.
   Creates `.gsd/quick/<num>-<slug>/` directory, a git branch, and
   dispatches a focused prompt for in-session execution.

2. Agent instructions file — loads `~/.gsd/agent-instructions.md` (global)
   and `.gsd/agent-instructions.md` (project), injects into every GSD
   agent session via the before_agent_start hook. Lets users add durable
   instructions like notification preferences or environment constraints.

Closes #425

---------

Co-authored-by: TÂCHES <afromanguy@me.com>
2026-03-16 10:45:50 -06:00
Jeremy McSpadden
061d826a4e feat(doctor): add 7 runtime health checks with auto-fix (#646)
* feat(doctor): add 7 runtime health checks with auto-fix

Add comprehensive runtime health monitoring to /gsd doctor:

- stale_crash_lock: detect dead auto.lock from crashed sessions, auto-clear
- orphaned_completed_units: find completed-unit keys referencing missing artifacts, auto-remove
- stale_hook_state: detect residual hook cycle counts with no running session, auto-clear
- activity_log_bloat: flag activity/ dir exceeding 500 files or 100MB, auto-prune (7-day retention)
- state_file_missing: detect missing STATE.md when milestones exist, auto-generate
- state_file_stale: detect STATE.md drift (wrong phase/milestone/slice), auto-rebuild
- gitignore_missing_patterns: detect missing critical GSD runtime patterns in .gitignore, auto-fix

All checks are non-fatal (gracefully degrade on read errors) and respect
the existing fix/fixLevel system. Includes 34 new test assertions across
9 test scenarios in doctor-runtime.test.ts.

* feat(doctor): add proactive healing layer for auto-mode

Three new mechanisms for automatic health monitoring:

1. Pre-dispatch health gate: runs before each unit dispatch in auto-mode.
   Checks for stale crash locks (auto-clears) and corrupt merge state
   (auto-heals via abortAndReset). Pauses auto-mode if critical issues
   can't be resolved.

2. Health score tracking: records error/warning/fix counts after each
   post-unit doctor run. Tracks trends (improving/stable/degrading)
   across a sliding window of 50 snapshots. Monitors consecutive
   error unit streaks.

3. Auto-heal escalation: when deterministic fixes can't resolve errors
   after 5 consecutive units AND health trend is not improving,
   automatically dispatches LLM-assisted heal (dispatchDoctorHeal).
   Single-fire per session to prevent spam. Defers escalation when
   trend is improving (fixes are working, just slowly).

Integration points in auto.ts:
- resetProactiveHealing() on start/stop
- preDispatchHealthGate() before deriveState in dispatchNextUnit
- recordHealthSnapshot() + checkHealEscalation() in post-unit hook
- formatHealthSummary() available for dashboard display

Includes 30 test assertions across 15 scenarios.
2026-03-16 10:34:26 -06:00