Commit graph

3295 commits

Author SHA1 Message Date
Jeremy
4a2045d290 fix(state): DB-authoritative milestone completeness (#4179)
Read-side twin of #4175. `deriveStateFromDb` had a SUMMARY-file fallback
that could mark a milestone complete even when the DB row said otherwise,
allowing an orphan SUMMARY.md (crashed complete-milestone turn, partial
merge, manual edit) to cascade into a false auto-merge.

- buildCompletenessSet: drop SUMMARY fallback; only DB status decides.
- buildRegistryAndFindActive: remove SUMMARY from the completeness check;
  still consult SUMMARY as a title fallback for DB-certified milestones.
- allSlicesDone branch: drop `!summaryFile` clause so a terminal-validation
  + orphan-SUMMARY path flows through to `completing-milestone` instead of
  short-circuiting, letting complete-milestone re-run idempotently.

Regression tests: orphan SUMMARY with in-flight slice stays active; orphan
SUMMARY with all-slices-done + validation-terminal lands at
completing-milestone (does not report as already complete).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 07:43:29 -05:00
Jeremy
d07b9bf473 test(#4175): add regression guards for complete-milestone false-merge
Guards the three cooperating fixes shipped in #4178 via source inspection
so a future refactor cannot silently reintroduce the false-merge path:

- stopAuto now uses the DB getMilestone() status as the authoritative
  milestone-complete signal (falls back to SUMMARY presence only when
  the project DB is unavailable).
- postUnitPreVerification pauses auto-mode for complete-milestone after
  retries are exhausted instead of writing a stub blocker placeholder.
- recoverTimedOutUnit pauses complete-milestone instead of writing a
  stub blocker placeholder.

Unblocks the CI lint / require-tests.sh gate on PR #4178.
2026-04-14 07:35:00 -05:00
Jeremy
9957152024 fix(auto-mode): prevent false milestone merge after complete-milestone failure (#4175)
When complete-milestone failed verification, auto-mode could end up merging
the worktree to main anyway and emit a metadata-only merge warning, creating
a misleading near-complete signal while the SUMMARY was never actually written.

The blocker-placeholder path for complete-milestone wrote a stub SUMMARY
without updating DB status, and stopAuto's SUMMARY-presence check treated
the stub as a legitimate completion signal.

- auto-post-unit.ts: skip blocker placeholder and pause auto-mode on
  complete-milestone verification retry exhaustion.
- auto-timeout-recovery.ts: same guard for the idle/hard timeout path.
- auto.ts: make stopAuto Step 4 DB-authoritative (getMilestone.status ===
  "complete") with SUMMARY-presence fallback only for DB-unavailable
  legacy projects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 07:24:12 -05:00
Jeremy McSpadden
3a529f7a95 Merge pull request #4100 from jeremymcs/claude/cleanup-mcp-stream-output-9uCeK
Improve MCP tool rendering with name parsing and compact args
2026-04-13 00:54:38 -05:00
Claude
2d1081f1cc fix: clean up MCP tool rendering in Claude Code CLI stream
Strip the `mcp__<server>__` prefix from tool_use blocks emitted by the
Claude Agent SDK so registered GSD extension renderers (gsd_plan_milestone,
gsd_task_complete, etc.) match instead of falling through to the generic
JSON-dump fallback. The original server name is preserved on the toolCall
block under `mcpServer` for downstream rendering.

Tighten the generic ToolExecutionComponent fallback for any remaining
prefixed names (third-party MCP servers): show a muted `server·tool`
title, render primitive args as compact `key=value` pairs, and truncate
output to 10 lines when collapsed.
2026-04-13 05:46:35 +00:00
github-actions[bot]
f188b94761 release: v2.72.0 2026-04-13 05:13:11 +00:00
Jeremy McSpadden
c8e5414812 Merge pull request #4095 from jeremymcs/fix/ci-integration-tests-build-prereqs
fix(ci): build artifacts in integration-tests job
2026-04-12 23:55:30 -05:00
Jeremy
6dfcb6a049 fix(ci): build artifacts in integration-tests job
PR #4093 split build and integration-tests into parallel CI jobs but the new
integration-tests job only ran `npm ci`, leaving tests without the compiled
artifacts they spawn at runtime. That caused 8 failures on main (run 24325713845):

- e2e-headless, e2e-smoke, pack-install — throw "dist/loader.js not found"
- 4 web-session-parity / web-live-state tests — "session manager module not
  found; checked=packages/pi-coding-agent/dist/core/session-manager.js"
- web-mode-onboarding — "sh: 1: next: not found" when the test shells
  `npm run build:web-host` at runtime (web/node_modules/.bin/next absent)

Add `npm --prefix web ci` and `npm run build` to the integration-tests job
before `test:integration`, matching what the build job already does. Using
`needs: build` + artifact sharing would serialize the two jobs and undo the
parallelism PR #4093 was buying, so the build is duplicated intentionally.
2026-04-12 23:47:03 -05:00
Jeremy McSpadden
b0fa373d2b Merge pull request #4093 from jeremymcs/perf/parallel-integration-tests
perf(ci): run integration tests in parallel with build
2026-04-12 23:30:07 -05:00
Jeremy
852ddf3bdd perf(ci): run integration tests in parallel with build
Split integration tests into a separate job that runs concurrently with
the build+unit test job. Integration tests run from TypeScript source
(no build artifact dependency), so they can start immediately after
detect-changes without waiting for compilation.
2026-04-12 23:18:08 -05:00
Jeremy McSpadden
c189b2152e Merge pull request #4092 from jeremymcs/fix/openrouter-credit-retry
fix(auto): recover from OpenRouter affordability 402 errors
2026-04-12 23:04:58 -05:00
Jeremy McSpadden
94b3e8c59a Merge pull request #4090 from jeremymcs/perf/nextjs-build-cache
perf(ci): cache Next.js build artifacts with Blacksmith
2026-04-12 22:51:25 -05:00
Jeremy
724464c7ae fix(auto): recover from OpenRouter credit affordability errors 2026-04-12 22:48:55 -05:00
Jeremy
bdcf2c5c24 perf(ci): cache Next.js build artifacts with Blacksmith cache
Add useblacksmith/cache@v5 to persist web/.next/cache across CI runs,
eliminating redundant Webpack recompilation of unchanged pages. Applied
to ci.yml build job and pipeline.yml dev-publish/prod-release jobs.
2026-04-12 22:38:30 -05:00
Jeremy McSpadden
cac4f8ac37 Merge pull request #4087 from jeremymcs/feat/add-specialist-agents
feat(agents): add 8 specialist subagents, slim pro agents, add GSD phase guard
2026-04-12 22:11:43 -05:00
Jeremy
0c19ca88f2 feat(agents): add GSD phase guard to prevent subagent/phase conflicts
When GSD auto-mode is running a planning phase, the planner subagent
could bypass GSD's state machine and artifact system. This adds a
shared state module and conflict check to block agents that overlap
with the active GSD phase.

- Add shared/gsd-phase-state.ts for cross-extension phase coordination
- Add conflicts_with frontmatter field to agent definitions
- Block conflicting agents with clear error directing to GSD workflow
- Tag planner agent with conflicts_with for plan/research phases
- 10 new tests for phase state and conflict parsing
2026-04-12 21:56:52 -05:00
Jeremy
66f0d45a8c feat(agents): add 8 specialist subagents and slim pro agents
Add focused, token-efficient specialist agents:
- reviewer: structured code review with severity ratings
- debugger: hypothesis-driven bug investigation
- tester: test writing, fixing, and coverage gap analysis
- refactorer: safe code transformations (extract, inline, rename)
- security: OWASP security audit and secrets detection
- planner: architecture/implementation planning (no code output)
- git-ops: conflict resolution, rebase strategy, PR prep
- doc-writer: documentation generation from code

Slim typescript-pro (256→64 lines) and javascript-pro (281→69 lines):
- Remove verbose code examples (the LLM already knows these patterns)
- Remove persistent memory sections (not used in this project)
- Keep core principles, key patterns list, and verification checklist
- Total token savings ~75% per invocation of these agents
2026-04-12 21:56:40 -05:00
Jeremy McSpadden
6d0b8b4b27 Merge pull request #4084 from jeremymcs/claude/prompt-system-validation-gates-FK9NB
Introduce gate registry as single source of truth for quality gates
2026-04-12 21:54:17 -05:00
Jeremy
c6ba27f371 fix(gsd): cast unknown gate id in test to satisfy GateId type
The gate-registry test intentionally passes an invalid gate id "Q999"
to verify error handling, but the strict GateId union type rejects it
at compile time. Cast to GateId to fix the typecheck:extensions CI step.
2026-04-12 21:30:56 -05:00
Claude
8f58481875 fix(gsd): route quality gates through a per-turn registry
Every workflow turn that needed a quality gate either let it drop
silently or bulk-stamped it at closeout. Q8 was the worst case: seeded
as scope:"slice" by plan-slice, treated as a blocker for the
evaluating-gates phase by state.ts, then filtered out of the
gate-evaluate prompt via `if (!meta) continue;` and never closed by
complete-slice — a guaranteed auto-loop stall once slice gates were
enabled.

Introduce gate-registry.ts as the single source of truth for which
turn owns which gate (Q3/Q4 → gate-evaluate, Q5/Q6/Q7 → execute-task,
Q8 → complete-slice, MV01–MV04 → validate-milestone). Every layer of
the prompt system now consults it:

- state.ts derives pending counts by owner turn, not scope, so Q8
  never stalls evaluating-gates again.
- auto-prompts.ts builders call assertGateCoverage() and render a
  "Gates to Close" block from the registry instead of a hand-rolled
  GATE_QUESTIONS table.
- complete-slice and complete-task handlers saveGateResult for every
  gate they own, mapping gate id → params field so empty sections
  become `omitted` and populated sections become `pass`.
- milestone-validation-gates sources its MV id list from the registry.
- prompt-validation.ts adds validateSliceSummaryOutput /
  validateTaskSummaryOutput / validateMilestoneValidationOutput
  schema checks.
- gsd_save_gate_result accepts MV01–MV04 (via the registry keys) in
  the MCP server and bootstrap tool registration.

Tests: new gate-registry + prompt-system-gate-coverage +
complete-slice-gate-closure suites, plus a Q8 regression case in
gate-dispatch.test.ts. 161 related tests pass end-to-end.

https://claude.ai/code/session_019PT3EmrkMxr4TsgGGLSYK3
2026-04-12 21:13:16 -05:00
Jeremy McSpadden
da7a7e255f Merge pull request #4082 from jeremymcs/claude/review-mcp-server-tools-2Gchv
Add query filtering, abort handling, and permission mode control
2026-04-12 20:54:51 -05:00
Claude
1eb357ca46 fix(mcp): expose every registered tool and fix SDK subpath resolution
Two related fixes for `gsd --mode mcp` that the audit missed on first pass:

1. Tool inventory — session.agent.state.tools was the *active* subset, not
   the full registry. Before this change, MCP clients connected to GSD saw
   63 tools and four built-ins were silently missing: `find`, `grep`, `ls`,
   and `hashline_edit`. After: 67 tools, matching the full _toolRegistry.
   Fix: call session.getAllTools() + session.setActiveToolsByName() before
   starting the MCP transport so every registered tool is active for the
   lifetime of the MCP session.

2. SDK subpath resolution — the #3603 createRequire workaround no longer
   works with @modelcontextprotocol/sdk 1.27.x + current Node. The
   wildcard export ./* → ./dist/cjs/* does NOT auto-append `.js`, and
   _require.resolve fails with "Cannot find module .../server/stdio".
   End-to-end handshake was actually broken in src/mcp-server.ts even
   before my earlier F5 change. Fix: use explicit `.js` suffixes on
   every subpath import (server/index.js, server/stdio.js, types.js),
   matching the convention already in use by packages/mcp-server/.

The regression test is rewritten to enforce the `.js`-suffix convention
and reject any bare subpath or lingering createRequire resolution.

Verified end-to-end via raw JSON-RPC against `gsd --mode mcp --bare`:
  BEFORE_COUNT=63
  AFTER_COUNT=67
  diff: +find +grep +hashline_edit +ls

Test sweep: 76 tests pass across mcp-createRequire, stream-adapter,
mcp-server, workflow-tools.

https://claude.ai/code/session_0174sYny3VvdwYTdCNTmY4Do
2026-04-13 01:40:05 +00:00
Jeremy McSpadden
5c271e72e7 Merge pull request #3790 from salioglu/fix/3718-sessions-stdin-cleanup
fix(cli): clean up stdin after sessions command readline interface closes
2026-04-12 20:18:09 -05:00
Jeremy
dc489f0a07 fix(mcp): resolve rebase regressions in stream-adapter
Rename intermediateToolCalls → intermediateToolBlocks to match upstream
rename, and pass onElicitation via extraOptions (4th arg) instead of
overrides (3rd arg) in buildSdkOptions test.
2026-04-12 20:09:36 -05:00
Claude
d4f139c5bf chore: sync package-lock.json version fields to 2.68.0
The lockfile was still pointing at 2.66.1 after the v2.68.0 release;
`npm install` during the audit work resynced it. No dependency graph
changes, just version-string alignment.

https://claude.ai/code/session_0174sYny3VvdwYTdCNTmY4Do
2026-04-12 20:04:47 -05:00
Claude
1be15758ec fix(mcp): thread abort signals, restore tool fidelity, and fix subpath imports
Audit-driven fixes across the two MCP server surfaces and the Claude Code
streaming adapter:

- src/mcp-server.ts: propagate `extra.signal` into `tool.execute` so MCP
  clients can actually cancel long-running Bash/WebFetch/grep calls, and
  route the remaining `/server` subpath import through `createRequire`
  for #3603 consistency.
- src/tests/mcp-createRequire.test.ts: extend regression coverage to the
  `/server` subpath.
- claude-code-cli/stream-adapter.ts: (a) classify aborts as `aborted`
  instead of the retry-eligible `stream_exhausted_without_result`,
  (b) merge final-turn toolCall blocks from the builder into the
  AssistantMessage via the new `mergePendingToolCalls` helper so a turn
  ending in `tool_use` stop_reason no longer drops its tool calls, and
  (c) resolve the SDK permission mode via `resolveClaudePermissionMode`
  (auto-mode → bypass, interactive → acceptEdits, env override).
- packages/mcp-server/src/server.ts: make `gsd_query` actually respect
  its `query` argument with known categories + forward-compatible
  fallback, and thread `extra.signal` into `gsd_execute` so an aborted
  RPC request cancels the newly-created session instead of leaking a
  background RpcClient process.
- stream-adapter test suite: add regression tests for abort
  classification, final-turn tool-call merging, and permission mode
  resolution.

Verified via: mcp-createRequire, stream-adapter (27), partial-builder,
mcp-server package (31), workflow-tools (13) — 83 tests green.

https://claude.ai/code/session_0174sYny3VvdwYTdCNTmY4Do
2026-04-12 20:04:47 -05:00
Jeremy McSpadden
bf5078eb30 Merge pull request #4083 from jeremymcs/docs/readme-latest-updates
docs: update README for v2.71 and add Ecosystem section
2026-04-12 19:59:40 -05:00
Jeremy
da14ebbd0d docs: update README What's New for v2.71 and add Ecosystem section
Add post-release fixes (model selection hardening, credential cooldown
recovery, TUI improvements, provider fixes) and GSD2 Config Utility link.
2026-04-12 19:58:50 -05:00
Jeremy McSpadden
99a68c05b7 Merge pull request #4081 from jeremymcs/fix/doctor-cli-auth-providers
fix(doctor): skip key check for CLI-authenticated providers
2026-04-12 19:37:10 -05:00
Jeremy
e9e2850165 test(doctor): add regression test for claude-code CLI auth provider
Verifies that claude-code provider is reported as ok without any API
key, since it uses external CLI authentication.
2026-04-12 19:24:29 -05:00
Jeremy
20f627fb67 fix(doctor): skip key check for CLI-authenticated providers
Providers like claude-code, openai-codex, google-gemini-cli use external
CLI auth — they don't need API keys. The doctor was incorrectly reporting
"claude-code key missing" for subscription users.
2026-04-12 19:16:16 -05:00
Jeremy McSpadden
79f79b617d Merge pull request #4077 from jeremymcs/fix/tui-notification-overlay-wiring
fix(tui): overlay subscription + Ctrl+Shift+P shortcut conflict
2026-04-12 18:29:28 -05:00
Jeremy
df1a7a76d0 fix(tui): overlay subscription + Ctrl+Shift+P shortcut conflict
- Replace notification overlay 3s polling with onNotificationStoreChange
  subscription for immediate updates; keep 30s safety-net for cross-process
- Remove Ctrl+Shift+P parallel fallback that conflicts with cycleModelBackward
- Add hasFallback flag to GSDShortcutDef so hint text is accurate
- Fix misleading _withLock comment; rename ownsLock → createdLock

Closes gsd-build/gsd-2#4076
2026-04-12 18:14:01 -05:00
Jeremy McSpadden
cdecbf2d68 Merge pull request #4074 from jeremymcs/fix/ollama-footer-status
fix(ollama): clear footer status when provider unavailable
2026-04-12 18:08:25 -05:00
Jeremy McSpadden
9b892a86e5 Merge pull request #4072 from jeremymcs/claude/fix-unconfigured-models-uXM3A
Fix unconfigured model selection in defaults and scoped models
2026-04-12 17:39:27 -05:00
Claude
701ab18d81 fix(models): block unconfigured models from selection surfaces
Filter models whose provider has no working API key or OAuth out of
every user-facing selection path. Previously, stale defaults and scoped
sets could leak unconfigured models into /model, /gsd model, and auto
run — the user could "pick" a model that immediately threw on use.

- model-selector: filter scopedModels via isProviderRequestReady;
  default to "all" scope when no scoped model is ready.
- model-controller: same filter for getModelCandidates, so exact-match
  resolution from /model <term> can't return an unauth'd scoped model.
- model-resolver: gate findInitialModel step 3 on provider readiness so
  a stale saved default falls through to the available-models path.
- startup-model-validation: check configuredExists against getAvailable
  instead of getAll, so a configured-but-unauth default triggers the
  fallback picker and thinking-level reset.
- auto-start: validate resolveDefaultSessionModel against the live
  registry + auth before snapshotting, and warn when PREFERENCES.md
  names an unconfigured model.

https://claude.ai/code/session_015q6b23ap9Pyqdogzz2FXGh
2026-04-12 17:25:06 -05:00
Jeremy
61166a6f17 fix(ollama): clear footer status when provider unavailable 2026-04-12 17:23:23 -05:00
Jeremy McSpadden
c3aa3a3bf0 Merge pull request #4067 from jeremymcs/fix/gsd-model-session-override 2026-04-12 12:50:12 -05:00
Jeremy McSpadden
3ecaf1eb35 Merge pull request #4066 from mastertyko/fix/2156-clean-merged-worktree-branch 2026-04-12 12:48:18 -05:00
Jeremy
5842e2834a fix(gsd): guard model override in minimal command contexts 2026-04-12 12:28:52 -05:00
Jeremy McSpadden
17e3ef6a28 Merge pull request #4064 from mastertyko/fix/3402-full-oauth-login-url
fix(pi-coding-agent): show full OAuth login URLs
2026-04-12 12:26:25 -05:00
Jeremy
c96d01acb7 fix(model): require provider readiness for saved default selection 2026-04-12 12:24:49 -05:00
Jeremy
e247f2fe61 fix(gsd): honor /gsd model as session override across dispatch 2026-04-12 11:48:06 -05:00
mastertyko
8a37e2ce10 fix(gsd): use milestone branch for merged worktree cleanup 2026-04-12 18:45:36 +02:00
mastertyko
f15938ea4c fix(pi-coding-agent): show full OAuth login URLs 2026-04-12 18:45:28 +02:00
Jeremy McSpadden
c8996c40bd Merge pull request #4040 from mastertyko/fix/3733-start-auto-fire-and-forget
fix(gsd): detach auto start from active turns
2026-04-12 09:43:16 -05:00
Jeremy McSpadden
564a71da37 Merge pull request #4053 from jeremymcs/fix/auto-session-credential-cooldown
fix(auto): survive transient 429 credential cooldown
2026-04-12 09:42:37 -05:00
Jeremy
4f2e90e1e8 test(auto): add tests for credential cooldown fix
- auth-storage.test.ts: 8 tests for getEarliestBackoffExpiry()
- sdk.test.ts: 12 tests for CredentialCooldownError class
- infra-errors-cooldown.test.ts: 35 tests for isTransientCooldownError(),
  getCooldownRetryAfterMs(), and exported constants

Required by CI lint (require-tests.sh) per CONTRIBUTING.md.

Closes #4052
2026-04-12 09:30:52 -05:00
Jeremy McSpadden
28379f4429 Merge pull request #4051 from jeremymcs/feat/tui-work
feat(tui): improve gsd overlays, shortcuts, and notification flows
2026-04-12 09:26:30 -05:00
Jeremy
d0afe018eb fix(auto): add structured cooldown error and bounded retry budget
Address Codex adversarial review findings:

- Replace string-matched cooldown detection with typed
  CredentialCooldownError (code: AUTH_COOLDOWN, retryAfterMs)
- Add MAX_COOLDOWN_RETRIES (5) cap so cooldown retries can't spin for
  hours on persistent quota exhaustion
- Auto-loop uses retryAfterMs from structured error when available,
  falls back to 35s default
- Export CredentialCooldownError from pi-coding-agent package
- Retain regex fallback for cross-process error propagation

Closes #4052
2026-04-12 09:16:05 -05:00