gsd-pi 2.76.0 → 2.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -25
- package/dist/claude-cli-check.js +32 -3
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.js +35 -1
- package/dist/onboarding.js +45 -0
- package/dist/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +2 -8
- package/dist/resources/agents/researcher.md +1 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +31 -8
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +77 -17
- package/dist/resources/extensions/gsd/auto/loop.js +9 -0
- package/dist/resources/extensions/gsd/auto/phases.js +104 -11
- package/dist/resources/extensions/gsd/auto/run-unit.js +38 -2
- package/dist/resources/extensions/gsd/auto/session.js +22 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -3
- package/dist/resources/extensions/gsd/auto-model-selection.js +53 -16
- package/dist/resources/extensions/gsd/auto-post-unit.js +25 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +32 -1
- package/dist/resources/extensions/gsd/auto-start.js +58 -57
- package/dist/resources/extensions/gsd/auto-verification.js +33 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +51 -53
- package/dist/resources/extensions/gsd/auto.js +70 -28
- package/dist/resources/extensions/gsd/blocked-models.js +68 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +93 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +3 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +12 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +52 -6
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +84 -23
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +54 -89
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
- package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
- package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
- package/dist/resources/extensions/gsd/db-writer.js +88 -16
- package/dist/resources/extensions/gsd/doctor-git-checks.js +23 -29
- package/dist/resources/extensions/gsd/doctor-providers.js +51 -5
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +1 -0
- package/dist/resources/extensions/gsd/error-classifier.js +31 -3
- package/dist/resources/extensions/gsd/exec-history.js +120 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +168 -23
- package/dist/resources/extensions/gsd/guided-flow.js +190 -1
- package/dist/resources/extensions/gsd/health-widget.js +4 -1
- package/dist/resources/extensions/gsd/hook-emitter.js +108 -0
- package/dist/resources/extensions/gsd/init-wizard.js +15 -1
- package/dist/resources/extensions/gsd/key-manager.js +28 -0
- package/dist/resources/extensions/gsd/memory-backfill.js +126 -0
- package/dist/resources/extensions/gsd/memory-store.js +19 -0
- package/dist/resources/extensions/gsd/model-router.js +36 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +44 -9
- package/dist/resources/extensions/gsd/preferences-types.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
- package/dist/resources/extensions/gsd/preferences.js +17 -17
- package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +13 -5
- package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
- package/dist/resources/extensions/gsd/state.js +43 -4
- package/dist/resources/extensions/gsd/token-counter.js +22 -5
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +26 -1
- package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +20 -3
- package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +6 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
- package/dist/resources/extensions/search-the-web/command-search-provider.js +5 -4
- package/dist/resources/extensions/search-the-web/native-search.js +45 -13
- package/dist/resources/skills/api-design/SKILL.md +190 -0
- package/dist/resources/skills/create-mcp-server/SKILL.md +121 -0
- package/dist/resources/skills/decompose-into-slices/SKILL.md +139 -0
- package/dist/resources/skills/dependency-upgrade/SKILL.md +158 -0
- package/dist/resources/skills/design-an-interface/SKILL.md +102 -0
- package/dist/resources/skills/forensics/SKILL.md +153 -0
- package/dist/resources/skills/grill-me/SKILL.md +93 -0
- package/dist/resources/skills/handoff/SKILL.md +121 -0
- package/dist/resources/skills/observability/SKILL.md +174 -0
- package/dist/resources/skills/security-review/SKILL.md +181 -0
- package/dist/resources/skills/spike-wrap-up/SKILL.md +138 -0
- package/dist/resources/skills/tdd/SKILL.md +112 -0
- package/dist/resources/skills/verify-before-complete/SKILL.md +98 -0
- package/dist/resources/skills/write-docs/SKILL.md +82 -0
- package/dist/resources/skills/write-milestone-brief/SKILL.md +135 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.js +6 -1
- package/dist/wizard.js +2 -0
- package/package.json +1 -1
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
- package/packages/mcp-server/dist/remote-questions.js +732 -0
- package/packages/mcp-server/dist/remote-questions.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +7 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +70 -8
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/session-manager.d.ts +14 -0
- package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
- package/packages/mcp-server/dist/session-manager.js +49 -1
- package/packages/mcp-server/dist/session-manager.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +163 -25
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -3
- package/packages/mcp-server/src/mcp-server.test.ts +67 -0
- package/packages/mcp-server/src/remote-questions.test.ts +294 -0
- package/packages/mcp-server/src/remote-questions.ts +916 -0
- package/packages/mcp-server/src/server.ts +89 -14
- package/packages/mcp-server/src/session-manager.ts +43 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +146 -1
- package/packages/mcp-server/src/workflow-tools.ts +215 -43
- package/packages/mcp-server/tsconfig.test.json +19 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +12 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +30 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/src/agent-loop.ts +14 -0
- package/packages/pi-agent-core/src/types.ts +34 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/custom.d.ts +38 -0
- package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/custom.js +41 -0
- package/packages/pi-ai/dist/models/custom.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +13 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +13 -4
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +16 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +12 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +164 -14
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.js +15 -3
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +67 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js +16 -3
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +67 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +289 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +1 -0
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/models/custom.ts +42 -0
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
- package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
- package/packages/pi-ai/src/providers/anthropic.ts +15 -4
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
- package/packages/pi-ai/src/providers/simple-options.ts +17 -1
- package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
- package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +200 -23
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +12 -2
- package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +84 -0
- package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +15 -5
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +84 -0
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +16 -5
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +363 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +32 -2
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +35 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +233 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +205 -2
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts +53 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.js +337 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +234 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
- package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js +40 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +90 -10
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +10 -6
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +45 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +55 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
- package/packages/pi-coding-agent/src/core/agent-session.ts +38 -2
- package/packages/pi-coding-agent/src/core/extensions/index.ts +16 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +351 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +258 -0
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +269 -0
- package/packages/pi-coding-agent/src/core/hooks-runner.ts +460 -0
- package/packages/pi-coding-agent/src/core/index.ts +10 -0
- package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
- package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
- package/packages/pi-coding-agent/src/core/model-registry-auth-header.test.ts +44 -0
- package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
- package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +102 -10
- package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -1
- package/packages/pi-coding-agent/src/core/session-manager.ts +10 -6
- package/packages/pi-coding-agent/src/core/settings-manager.ts +57 -0
- package/packages/pi-coding-agent/src/index.ts +16 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/scripts/link-workspace-packages.cjs +1 -0
- package/src/resources/agents/researcher.md +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +32 -8
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +78 -17
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +149 -5
- package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -0
- package/src/resources/extensions/gsd/auto/loop.ts +9 -0
- package/src/resources/extensions/gsd/auto/phases.ts +131 -10
- package/src/resources/extensions/gsd/auto/run-unit.ts +40 -2
- package/src/resources/extensions/gsd/auto/session.ts +35 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -3
- package/src/resources/extensions/gsd/auto-model-selection.ts +71 -15
- package/src/resources/extensions/gsd/auto-post-unit.ts +29 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +26 -1
- package/src/resources/extensions/gsd/auto-start.ts +60 -68
- package/src/resources/extensions/gsd/auto-verification.ts +33 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +62 -63
- package/src/resources/extensions/gsd/auto.ts +73 -28
- package/src/resources/extensions/gsd/blocked-models.ts +98 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +120 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +54 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +89 -26
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
- package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +55 -90
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
- package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
- package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
- package/src/resources/extensions/gsd/db-writer.ts +88 -17
- package/src/resources/extensions/gsd/doctor-git-checks.ts +23 -27
- package/src/resources/extensions/gsd/doctor-providers.ts +59 -6
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +2 -0
- package/src/resources/extensions/gsd/error-classifier.ts +36 -3
- package/src/resources/extensions/gsd/exec-history.ts +153 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -1
- package/src/resources/extensions/gsd/gsd-db.ts +186 -23
- package/src/resources/extensions/gsd/guided-flow.ts +222 -1
- package/src/resources/extensions/gsd/health-widget.ts +3 -1
- package/src/resources/extensions/gsd/hook-emitter.ts +188 -0
- package/src/resources/extensions/gsd/init-wizard.ts +15 -1
- package/src/resources/extensions/gsd/journal.ts +2 -1
- package/src/resources/extensions/gsd/key-manager.ts +28 -0
- package/src/resources/extensions/gsd/memory-backfill.ts +140 -0
- package/src/resources/extensions/gsd/memory-store.ts +26 -0
- package/src/resources/extensions/gsd/model-router.ts +42 -1
- package/src/resources/extensions/gsd/pre-execution-checks.ts +46 -10
- package/src/resources/extensions/gsd/preferences-types.ts +46 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
- package/src/resources/extensions/gsd/preferences.ts +17 -17
- package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +17 -4
- package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
- package/src/resources/extensions/gsd/state.ts +45 -4
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +188 -2
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +95 -1
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +68 -66
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +148 -3
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +306 -1
- package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +237 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +40 -9
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +447 -1
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/load-memory-block.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
- package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
- package/src/resources/extensions/gsd/token-counter.ts +22 -5
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
- package/src/resources/extensions/gsd/tools/memory-tools.ts +31 -1
- package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +26 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +6 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
- package/src/resources/extensions/search-the-web/command-search-provider.ts +5 -4
- package/src/resources/extensions/search-the-web/native-search.ts +48 -12
- package/src/resources/skills/api-design/SKILL.md +190 -0
- package/src/resources/skills/create-mcp-server/SKILL.md +121 -0
- package/src/resources/skills/decompose-into-slices/SKILL.md +139 -0
- package/src/resources/skills/dependency-upgrade/SKILL.md +158 -0
- package/src/resources/skills/design-an-interface/SKILL.md +102 -0
- package/src/resources/skills/forensics/SKILL.md +153 -0
- package/src/resources/skills/grill-me/SKILL.md +93 -0
- package/src/resources/skills/handoff/SKILL.md +121 -0
- package/src/resources/skills/observability/SKILL.md +174 -0
- package/src/resources/skills/security-review/SKILL.md +181 -0
- package/src/resources/skills/spike-wrap-up/SKILL.md +138 -0
- package/src/resources/skills/tdd/SKILL.md +112 -0
- package/src/resources/skills/verify-before-complete/SKILL.md +98 -0
- package/src/resources/skills/write-docs/SKILL.md +82 -0
- package/src/resources/skills/write-milestone-brief/SKILL.md +135 -0
- /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_ssgManifest.js +0 -0
|
@@ -16,8 +16,30 @@ import { existsSync, unlinkSync } from "node:fs";
|
|
|
16
16
|
import { randomUUID } from "node:crypto";
|
|
17
17
|
import { join } from "node:path";
|
|
18
18
|
import { debugLog } from "./debug-logger.js";
|
|
19
|
-
import { MergeConflictError } from "./git-service.js";
|
|
20
19
|
import { emitJournalEvent } from "./journal.js";
|
|
20
|
+
// ─── Path Helpers ──────────────────────────────────────────────────────────
|
|
21
|
+
/**
|
|
22
|
+
* Worktree marker segment — present in any path produced by worktreePath().
|
|
23
|
+
* Used to strip the worktree suffix and recover the project root (#3729).
|
|
24
|
+
*/
|
|
25
|
+
const WORKTREE_MARKER = "/.gsd/worktrees/";
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the project root from session path state.
|
|
28
|
+
*
|
|
29
|
+
* Prefers `originalBasePath` (always the project root when set), but falls
|
|
30
|
+
* back to `basePath` when `originalBasePath` is falsy (e.g. fresh AutoSession
|
|
31
|
+
* with default empty string). If `basePath` itself is inside a worktree
|
|
32
|
+
* directory (contains `/.gsd/worktrees/`), strip that suffix to recover the
|
|
33
|
+
* actual project root — preventing double-nested worktree paths (#3729).
|
|
34
|
+
*/
|
|
35
|
+
export function resolveProjectRoot(originalBasePath, basePath) {
|
|
36
|
+
let resolved = originalBasePath || basePath;
|
|
37
|
+
const markerIdx = resolved.indexOf(WORKTREE_MARKER);
|
|
38
|
+
if (markerIdx !== -1) {
|
|
39
|
+
resolved = resolved.slice(0, markerIdx);
|
|
40
|
+
}
|
|
41
|
+
return resolved;
|
|
42
|
+
}
|
|
21
43
|
// ─── WorktreeResolver ──────────────────────────────────────────────────────
|
|
22
44
|
export class WorktreeResolver {
|
|
23
45
|
s;
|
|
@@ -33,11 +55,11 @@ export class WorktreeResolver {
|
|
|
33
55
|
}
|
|
34
56
|
/** Original project root — always the non-worktree path. */
|
|
35
57
|
get projectRoot() {
|
|
36
|
-
return this.s.originalBasePath
|
|
58
|
+
return resolveProjectRoot(this.s.originalBasePath, this.s.basePath);
|
|
37
59
|
}
|
|
38
60
|
/** Path for auto.lock file — same as the old lockBase(). */
|
|
39
61
|
get lockPath() {
|
|
40
|
-
return this.s.originalBasePath
|
|
62
|
+
return resolveProjectRoot(this.s.originalBasePath, this.s.basePath);
|
|
41
63
|
}
|
|
42
64
|
// ── Private Helpers ────────────────────────────────────────────────────
|
|
43
65
|
rebuildGitService() {
|
|
@@ -99,7 +121,10 @@ export class WorktreeResolver {
|
|
|
99
121
|
});
|
|
100
122
|
return;
|
|
101
123
|
}
|
|
102
|
-
|
|
124
|
+
// Resolve the project root for worktree operations via shared helper.
|
|
125
|
+
// Handles the case where originalBasePath is falsy and basePath is itself
|
|
126
|
+
// a worktree path — prevents double-nested worktree paths (#3729).
|
|
127
|
+
const basePath = resolveProjectRoot(this.s.originalBasePath, this.s.basePath);
|
|
103
128
|
debugLog("WorktreeResolver", {
|
|
104
129
|
action: "enterMilestone",
|
|
105
130
|
milestoneId,
|
|
@@ -429,11 +454,13 @@ export class WorktreeResolver {
|
|
|
429
454
|
/* best-effort */
|
|
430
455
|
}
|
|
431
456
|
}
|
|
432
|
-
//
|
|
433
|
-
//
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
457
|
+
// Restore state before re-throwing so callers always get a consistent
|
|
458
|
+
// session (#4380).
|
|
459
|
+
this.restoreToProjectRoot();
|
|
460
|
+
// Re-throw: MergeConflictError stops the auto loop (#2330); non-conflict
|
|
461
|
+
// errors (permission denied, filesystem failures) must also propagate so
|
|
462
|
+
// broken states are diagnosable (#4380).
|
|
463
|
+
throw err;
|
|
437
464
|
}
|
|
438
465
|
// Always restore basePath and rebuild — whether merge succeeded or failed
|
|
439
466
|
this.restoreToProjectRoot();
|
|
@@ -500,6 +527,8 @@ export class WorktreeResolver {
|
|
|
500
527
|
error: msg,
|
|
501
528
|
});
|
|
502
529
|
ctx.notify(`Milestone merge failed (branch mode): ${msg}`, "warning");
|
|
530
|
+
// Re-throw all errors so callers can apply their own recovery logic (#4380).
|
|
531
|
+
throw err;
|
|
503
532
|
}
|
|
504
533
|
}
|
|
505
534
|
// ── Merge and Enter Next ───────────────────────────────────────────────
|
|
@@ -516,7 +545,18 @@ export class WorktreeResolver {
|
|
|
516
545
|
currentMilestoneId,
|
|
517
546
|
nextMilestoneId,
|
|
518
547
|
});
|
|
519
|
-
|
|
548
|
+
try {
|
|
549
|
+
this.mergeAndExit(currentMilestoneId, ctx);
|
|
550
|
+
}
|
|
551
|
+
catch (err) {
|
|
552
|
+
// mergeAndExit emits a warning and restores state when it fails during
|
|
553
|
+
// merge/cleanup. But if it throws before recovery runs (e.g., in
|
|
554
|
+
// validateMilestoneId or emitJournalEvent), basePath won't be restored
|
|
555
|
+
// to projectRoot — re-throw so we don't enter the next milestone with
|
|
556
|
+
// the current one unmerged.
|
|
557
|
+
if (this.s.basePath !== this.projectRoot)
|
|
558
|
+
throw err;
|
|
559
|
+
}
|
|
520
560
|
this.enterMilestone(nextMilestoneId, ctx);
|
|
521
561
|
}
|
|
522
562
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* All provider logic lives in provider.ts (S01) — this is pure UI wiring.
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { supportsNativeWebSearch } from './native-search.js';
|
|
11
11
|
import { getTavilyApiKey, getBraveApiKey, getOllamaApiKey, getSearchProviderPreference, setSearchProviderPreference, resolveSearchProvider, } from './provider.js';
|
|
12
12
|
const VALID_PREFERENCES = ['tavily', 'brave', 'ollama', 'auto'];
|
|
13
13
|
function keyStatus(provider) {
|
|
@@ -72,9 +72,10 @@ export function registerSearchProviderCommand(pi) {
|
|
|
72
72
|
}
|
|
73
73
|
setSearchProviderPreference(chosen);
|
|
74
74
|
const effective = resolveSearchProvider();
|
|
75
|
-
// Gate on api
|
|
76
|
-
//
|
|
77
|
-
|
|
75
|
+
// Gate on api shape + provider allowlist: the info note must match the
|
|
76
|
+
// actual runtime behavior in native-search.ts. Claude served via copilot
|
|
77
|
+
// / minimax / kimi is anthropic-shaped but does NOT run native search.
|
|
78
|
+
const isAnthropic = supportsNativeWebSearch(ctx.model);
|
|
78
79
|
const nativeNote = isAnthropic ? '\nNote: Native Anthropic web search is also active (automatic, no API key needed).' : '';
|
|
79
80
|
ctx.ui.notify(`Search provider set to ${chosen}. Effective provider: ${effective ?? 'none (no API keys)'}${nativeNote}`, 'info');
|
|
80
81
|
},
|
|
@@ -12,6 +12,38 @@ export const BRAVE_TOOL_NAMES = ["search-the-web", "search_and_read"];
|
|
|
12
12
|
export const CUSTOM_SEARCH_TOOL_NAMES = ["search-the-web", "search_and_read", "google_search"];
|
|
13
13
|
/** Thinking block types that require signature validation by the API */
|
|
14
14
|
const THINKING_TYPES = new Set(["thinking", "redacted_thinking"]);
|
|
15
|
+
/**
|
|
16
|
+
* Providers whose Anthropic-Messages endpoint is known to accept the native
|
|
17
|
+
* `web_search_20250305` server tool. Anthropic-shaped transports NOT in this
|
|
18
|
+
* set (github-copilot, minimax, kimi-coding, opencode, vercel-ai-gateway,
|
|
19
|
+
* etc.) route Claude or Claude-compatible models through the Messages API
|
|
20
|
+
* but do NOT expose the server-side search tool — injecting it yields a
|
|
21
|
+
* 400 "unsupported_value" from their endpoints (regression from #4492).
|
|
22
|
+
*
|
|
23
|
+
* Keep this allowlist tight — err on the side of custom/Brave search rather
|
|
24
|
+
* than a runtime 400. Add a provider here only after confirming its endpoint
|
|
25
|
+
* accepts the tool type.
|
|
26
|
+
*/
|
|
27
|
+
const NATIVE_WEB_SEARCH_PROVIDERS = new Set([
|
|
28
|
+
"anthropic",
|
|
29
|
+
"claude-code",
|
|
30
|
+
"anthropic-vertex",
|
|
31
|
+
"vercel-ai-gateway",
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* True when the model is an Anthropic-shaped transport AND the provider is
|
|
35
|
+
* known to accept the native `web_search_20250305` tool. Gate both on api
|
|
36
|
+
* shape (#4478 / ADR-012) and on provider identity (#444 regression guard
|
|
37
|
+
* and #4492 scope correction) — provider-level discrimination is legitimate
|
|
38
|
+
* per ADR-012 for credential/behavior differences that api shape can't
|
|
39
|
+
* express.
|
|
40
|
+
*/
|
|
41
|
+
export function supportsNativeWebSearch(model) {
|
|
42
|
+
if (!isAnthropicApi(model))
|
|
43
|
+
return false;
|
|
44
|
+
const provider = model?.provider;
|
|
45
|
+
return typeof provider === "string" && NATIVE_WEB_SEARCH_PROVIDERS.has(provider);
|
|
46
|
+
}
|
|
15
47
|
/**
|
|
16
48
|
* Maximum number of native web searches allowed per session (agent unit).
|
|
17
49
|
* The Anthropic API's `max_uses` is per-request — it resets on each API call.
|
|
@@ -76,10 +108,11 @@ export function registerNativeSearchHooks(pi) {
|
|
|
76
108
|
pi.on("model_select", async (event, ctx) => {
|
|
77
109
|
modelSelectFired = true;
|
|
78
110
|
const wasAnthropic = isAnthropicProvider;
|
|
79
|
-
// Gate on
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
|
|
111
|
+
// Gate on api shape AND provider allowlist: direct Anthropic, claude-code
|
|
112
|
+
// OAuth, and anthropic-vertex accept `web_search_20250305`; copilot /
|
|
113
|
+
// minimax / kimi / opencode route Claude-compat models through the same
|
|
114
|
+
// wire protocol but reject the server-side tool (#4492 regression).
|
|
115
|
+
isAnthropicProvider = supportsNativeWebSearch(event.model);
|
|
83
116
|
const hasBrave = !!process.env.BRAVE_API_KEY;
|
|
84
117
|
// When Anthropic (and not preferring Brave): disable custom search tools —
|
|
85
118
|
// native web_search is server-side and more reliable.
|
|
@@ -120,20 +153,19 @@ export function registerNativeSearchHooks(pi) {
|
|
|
120
153
|
// modelsAreEqual suppresses model_select AND the SDK doesn't pass model.
|
|
121
154
|
const eventModel = event.model;
|
|
122
155
|
let isAnthropic;
|
|
123
|
-
if (eventModel?.api) {
|
|
124
|
-
// Preferred path: gate on
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// `anthropic` maps unambiguously without the api field. Other Anthropic
|
|
130
|
-
// transports will arrive via the modelSelectFired or model-name branch.
|
|
131
|
-
isAnthropic = eventModel.provider === "anthropic";
|
|
156
|
+
if (eventModel?.api || eventModel?.provider) {
|
|
157
|
+
// Preferred path: gate on api shape + provider allowlist. Both fields
|
|
158
|
+
// are authoritative when present — do NOT fall back to the model-name
|
|
159
|
+
// heuristic, which would misclassify copilot-served Claude as Anthropic
|
|
160
|
+
// (#444 regression) or minimax-served Claude-compat as Anthropic (#4492).
|
|
161
|
+
isAnthropic = supportsNativeWebSearch(eventModel);
|
|
132
162
|
}
|
|
133
163
|
else if (modelSelectFired) {
|
|
134
164
|
isAnthropic = isAnthropicProvider;
|
|
135
165
|
}
|
|
136
166
|
else {
|
|
167
|
+
// Last resort: session-restore paths where the SDK doesn't pass model.
|
|
168
|
+
// The model-name prefix is best-effort and assumes direct Anthropic.
|
|
137
169
|
const modelName = typeof payload.model === "string" ? payload.model : "";
|
|
138
170
|
isAnthropic = modelName.startsWith("claude-");
|
|
139
171
|
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-design
|
|
3
|
+
description: Design or review an HTTP/REST/GraphQL API for versioning, pagination, error shapes, idempotency, auth, and evolvability. Use when asked to "design an API", "shape the endpoints", "design the schema", "add a new endpoint", "review this API", or when building/modifying a public or internal HTTP surface. Complements `design-an-interface` (which is interface-agnostic) by covering HTTP-specific concerns like status codes, cache headers, and breaking-change management.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<objective>
|
|
7
|
+
Shape an HTTP or GraphQL API so callers get predictable, evolvable, and honest semantics. The deliverable is a concrete endpoint/schema sketch with: URL or operation names, method/verb, request shape, response shape, error shape, auth model, pagination strategy, and versioning stance. Optimize for "clients that exist in 2 years" over "client that's easy to write today".
|
|
8
|
+
</objective>
|
|
9
|
+
|
|
10
|
+
<context>
|
|
11
|
+
GSD-2 has `design-an-interface` for general module-interface design; this skill is the HTTP/GraphQL specialization. REST and GraphQL carry baggage — status codes, verbs, nullability, pagination — that a generic interface-design discussion glosses over.
|
|
12
|
+
|
|
13
|
+
Invocation points:
|
|
14
|
+
- Adding a new public API endpoint
|
|
15
|
+
- Redesigning an internal API boundary between services
|
|
16
|
+
- Code review of a PR that introduces HTTP handlers
|
|
17
|
+
- A slice whose acceptance criteria include "the API works"
|
|
18
|
+
- A GraphQL schema change
|
|
19
|
+
</context>
|
|
20
|
+
|
|
21
|
+
<core_principle>
|
|
22
|
+
**CALLERS OUTLIVE YOUR ASSUMPTIONS.** An API you ship today has to keep working when your internals change, when the mobile app version two is still in use, and when a third party integrates against it. Design for extension, not just for the current caller.
|
|
23
|
+
|
|
24
|
+
**HONEST STATUS CODES.** 200 OK with `{"error": "not found"}` is a lie. 404 says not found. Use the HTTP semantics the protocol offers — HTTP clients, caches, and intermediaries rely on them.
|
|
25
|
+
|
|
26
|
+
**PAGINATION IS NON-OPTIONAL.** Any list endpoint that doesn't paginate will eventually get a request for "all records" that kills your database.
|
|
27
|
+
</core_principle>
|
|
28
|
+
|
|
29
|
+
<process>
|
|
30
|
+
|
|
31
|
+
## Step 1: Gather the contract
|
|
32
|
+
|
|
33
|
+
Answer, or ask (one round, 1–3 questions):
|
|
34
|
+
|
|
35
|
+
1. **Who are the callers?** Internal service / mobile app / public third-party / same-repo frontend.
|
|
36
|
+
2. **What's the versioning stance?** None / URL-path (`/v1/`) / header-based / GraphQL schema evolution.
|
|
37
|
+
3. **Auth model?** Public / API key / OAuth / session cookie / mTLS / none-but-internal-only.
|
|
38
|
+
4. **Idempotency expectation?** Is a retry safe? Required?
|
|
39
|
+
5. **Consistency model?** Read-your-writes, eventual, serializable?
|
|
40
|
+
|
|
41
|
+
## Step 2: Resource and operation naming
|
|
42
|
+
|
|
43
|
+
### REST
|
|
44
|
+
|
|
45
|
+
- Nouns not verbs in URLs: `POST /users`, not `POST /createUser`.
|
|
46
|
+
- Plural resources: `/users/42`, not `/user/42`.
|
|
47
|
+
- Nested only when the relationship is hierarchical and the child has no independent identity: `/users/42/sessions/3`. Otherwise flat: `/sessions/3?userId=42`.
|
|
48
|
+
- Use subresources for actions that don't fit CRUD: `POST /users/42:deactivate` (colon syntax) or `POST /users/42/actions/deactivate`.
|
|
49
|
+
|
|
50
|
+
### GraphQL
|
|
51
|
+
|
|
52
|
+
- Queries are nouns; mutations are verbs: `user(id)`, `createUser(input)`, `deactivateUser(id)`.
|
|
53
|
+
- Group related mutations under an input type: `createUser(input: CreateUserInput!)`.
|
|
54
|
+
- Return the affected object plus any derived/computed fields from mutations — lets clients avoid a refetch.
|
|
55
|
+
|
|
56
|
+
## Step 3: Methods and status codes
|
|
57
|
+
|
|
58
|
+
### REST
|
|
59
|
+
|
|
60
|
+
| Method | Intent | Idempotent? | Default success |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| GET | Read | Yes | 200, or 304 if conditional |
|
|
63
|
+
| POST | Create or non-idempotent action | No | 201 with `Location` on create, 200 on action |
|
|
64
|
+
| PUT | Replace (full-object) | Yes | 200 with body, or 204 |
|
|
65
|
+
| PATCH | Partial update | No (usually) | 200 with body |
|
|
66
|
+
| DELETE | Remove | Yes | 204 |
|
|
67
|
+
|
|
68
|
+
Errors:
|
|
69
|
+
- 400: caller screwed up the request shape
|
|
70
|
+
- 401: no/invalid auth
|
|
71
|
+
- 403: authed but not allowed
|
|
72
|
+
- 404: resource doesn't exist
|
|
73
|
+
- 409: conflict (version mismatch, unique constraint)
|
|
74
|
+
- 410: gone (vs 404 when the resource previously existed and you want to signal that)
|
|
75
|
+
- 422: validation failed
|
|
76
|
+
- 429: rate-limited — include `Retry-After`
|
|
77
|
+
- 500: genuinely unexpected server error
|
|
78
|
+
- 503: service down or overloaded — include `Retry-After`
|
|
79
|
+
|
|
80
|
+
Never 200-with-error-body. Never 500 for a 4xx cause.
|
|
81
|
+
|
|
82
|
+
### GraphQL
|
|
83
|
+
|
|
84
|
+
- Top-level errors (`errors[]`) for transport-level failures. Domain errors (validation, not-found, forbidden) go in the typed return — use a union or result type.
|
|
85
|
+
- Partial results are expected; design the schema so `null` on a field is meaningful, not a signal of generic failure.
|
|
86
|
+
|
|
87
|
+
## Step 4: Pagination
|
|
88
|
+
|
|
89
|
+
- **Cursor-based by default.** Opaque cursor string, `limit`, return `nextCursor` when more exists. Scales, stable under writes.
|
|
90
|
+
- **Offset-based only when:** dataset is small, user needs jump-to-page semantics (admin tables), and you're willing to accept stability drift.
|
|
91
|
+
- **Never "return everything"** as default. Put a hard upper bound on `limit` (e.g., 200).
|
|
92
|
+
- GraphQL: use Relay-style connections (`edges`, `pageInfo`) if the ecosystem expects it; otherwise a simpler `{items, nextCursor}` is fine.
|
|
93
|
+
|
|
94
|
+
## Step 5: Error shape
|
|
95
|
+
|
|
96
|
+
Standardize one shape and use it everywhere. Example REST:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"error": {
|
|
101
|
+
"code": "user_not_found",
|
|
102
|
+
"message": "No user with id 42",
|
|
103
|
+
"details": { "userId": 42 },
|
|
104
|
+
"requestId": "req_abc123"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- `code` is machine-readable; stable; documented.
|
|
110
|
+
- `message` is human-readable; can change.
|
|
111
|
+
- `details` carries structured context.
|
|
112
|
+
- `requestId` lets callers report bugs.
|
|
113
|
+
|
|
114
|
+
Errors don't leak stack traces, file paths, or internal queries.
|
|
115
|
+
|
|
116
|
+
## Step 6: Idempotency, caching, concurrency
|
|
117
|
+
|
|
118
|
+
- **Idempotency keys** for POST operations that mustn't double-execute on retry. Caller passes `Idempotency-Key: <uuid>`; server dedupes for a window.
|
|
119
|
+
- **ETags** for GET + conditional updates (`If-Match` on PUT/PATCH).
|
|
120
|
+
- **Cache-Control** on GETs that are safely cacheable.
|
|
121
|
+
- **Optimistic concurrency:** when multiple writers collide, 409 with the current state. Don't silently clobber.
|
|
122
|
+
|
|
123
|
+
## Step 7: Versioning and evolution
|
|
124
|
+
|
|
125
|
+
- **Additive changes are free:** new optional fields, new endpoints, new optional query params.
|
|
126
|
+
- **Breaking changes need a plan:** path-versioned (`/v2/`), sunset headers on `/v1/`, deprecation window communicated. Or, for GraphQL, `@deprecated` on fields with a migration note.
|
|
127
|
+
- **Document the contract:** OpenAPI/GraphQL SDL. Keep it in the repo. Make it part of the PR that introduces the change.
|
|
128
|
+
|
|
129
|
+
## Step 8: Review or write it up
|
|
130
|
+
|
|
131
|
+
If this is a review, produce findings in the same shape as `security-review` / `review` — file:line, category, recommendation.
|
|
132
|
+
|
|
133
|
+
If this is a new design, produce:
|
|
134
|
+
|
|
135
|
+
```markdown
|
|
136
|
+
## <API name>
|
|
137
|
+
|
|
138
|
+
### Scope
|
|
139
|
+
<what the API is for, who calls it>
|
|
140
|
+
|
|
141
|
+
### Endpoints / Operations
|
|
142
|
+
- `POST /users` — create user. Request: `{email, name}`. Response 201: `{id, email, name, createdAt}` + `Location: /users/<id>`. Errors: 409 email taken, 422 invalid.
|
|
143
|
+
- ...
|
|
144
|
+
|
|
145
|
+
### Auth
|
|
146
|
+
<model + where to put the credential>
|
|
147
|
+
|
|
148
|
+
### Pagination
|
|
149
|
+
<cursor shape, max limit>
|
|
150
|
+
|
|
151
|
+
### Error shape
|
|
152
|
+
<one canonical shape>
|
|
153
|
+
|
|
154
|
+
### Idempotency / concurrency
|
|
155
|
+
<rules>
|
|
156
|
+
|
|
157
|
+
### Versioning
|
|
158
|
+
<stance + how breaking changes will be handled>
|
|
159
|
+
|
|
160
|
+
### OpenAPI / SDL
|
|
161
|
+
<link or inline>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Append architectural decisions to `.gsd/DECISIONS.md`.
|
|
165
|
+
|
|
166
|
+
</process>
|
|
167
|
+
|
|
168
|
+
<anti_patterns>
|
|
169
|
+
|
|
170
|
+
- **200 OK with `{"error": "..."}`.** Lies to caches, proxies, retry libraries.
|
|
171
|
+
- **Unbounded list endpoints.** `GET /users` without a `limit` cap will bite you.
|
|
172
|
+
- **Offset pagination at scale.** Drifts under writes; slow at high offsets.
|
|
173
|
+
- **Free-form error messages with no code.** Machine callers can't branch on prose.
|
|
174
|
+
- **Breaking changes in-place.** Callers break; versioning exists for a reason.
|
|
175
|
+
- **Ignoring idempotency on retriable POSTs.** Double-charges, duplicate records.
|
|
176
|
+
- **Auth checks at the handler only, not the service layer.** Defense in depth.
|
|
177
|
+
|
|
178
|
+
</anti_patterns>
|
|
179
|
+
|
|
180
|
+
<success_criteria>
|
|
181
|
+
|
|
182
|
+
- [ ] Every endpoint/operation has named request, response, and error shapes.
|
|
183
|
+
- [ ] Status codes match HTTP semantics — no 200-with-error.
|
|
184
|
+
- [ ] List endpoints paginate; max limit is documented.
|
|
185
|
+
- [ ] A single error shape is used everywhere, with a machine-readable code.
|
|
186
|
+
- [ ] Versioning stance is stated — even if the answer is "additive only for now."
|
|
187
|
+
- [ ] OpenAPI/SDL reflects the design and lives in the repo.
|
|
188
|
+
- [ ] Decisions appear in `.gsd/DECISIONS.md`.
|
|
189
|
+
|
|
190
|
+
</success_criteria>
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-mcp-server
|
|
3
|
+
description: Build, iterate, and evaluate Model Context Protocol (MCP) servers that expose external services as tools an LLM can call. Use when asked to "build an MCP server", "create an MCP tool", "wrap this API as MCP", "expose X to Claude", or when extending GSD with custom tool integrations. Covers research, schema/tool design, error handling, pagination, testing via MCP Inspector, and producing a 10-question eval set that proves the server actually enables real work.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<objective>
|
|
7
|
+
Produce a high-quality MCP server that an LLM can actually use — not one that merely parses spec-compliant. Quality is measured by how well the server enables real-world task completion, which means the tool descriptions, error messages, and pagination behave under model reasoning, not just at the wire level.
|
|
8
|
+
</objective>
|
|
9
|
+
|
|
10
|
+
<context>
|
|
11
|
+
GSD-2 consumes MCP heavily — see `src/resources/extensions/mcp-client/`, `src/resources/extensions/gsd/mcp-project-config.ts`, `src/resources/extensions/gsd/workflow-mcp.ts`, and `/gsd mcp` commands. Users frequently want to extend GSD with project-specific MCP servers (internal APIs, data sources, domain tools). This skill fills the authoring gap between "MCP exists" and "I have a working server."
|
|
12
|
+
|
|
13
|
+
Invocation points:
|
|
14
|
+
- User describes a service or API they want an LLM to reach
|
|
15
|
+
- `/gsd mcp init` scaffolds config but there's a tool integration to build
|
|
16
|
+
- Replacing a hand-rolled extension with a standard MCP server
|
|
17
|
+
</context>
|
|
18
|
+
|
|
19
|
+
<core_principle>
|
|
20
|
+
**THE QUALITY METRIC IS TASK COMPLETION, NOT SCHEMA VALIDITY.** A server that lists 30 tools with cryptic names and empty descriptions passes the protocol but fails the point. The tool description is the only thing an LLM has to decide whether to call it — write it like documentation for a stranger under time pressure.
|
|
21
|
+
|
|
22
|
+
**DESIGN FOR THE MODEL, NOT THE API.** A raw REST endpoint is rarely the right tool. Group, filter, and pre-shape responses so the model gets what it needs to reason, not a 40KB JSON blob it has to summarize. Fewer, deeper tools beat many, shallow ones.
|
|
23
|
+
</core_principle>
|
|
24
|
+
|
|
25
|
+
<process>
|
|
26
|
+
|
|
27
|
+
## Step 1: Research and scope
|
|
28
|
+
|
|
29
|
+
1. **Study modern MCP design.** Read the latest MCP protocol docs (not training data — fetch them). Read 2–3 reference implementations to see current patterns.
|
|
30
|
+
2. **Pick a framework.** TypeScript is the default — the reference SDK is the most mature. Python is fine for data-heavy or ML adjacencies.
|
|
31
|
+
3. **Analyze the target API.** Map the external service's endpoints, auth, rate limits, pagination, error shapes. Identify what a human workflow on top of it actually looks like — that's the cut line for tool design.
|
|
32
|
+
4. **Produce a brief.** One page: what the server does, who calls it, the 5–10 tools you plan to expose, and the top 3 design trade-offs. Confirm with the user.
|
|
33
|
+
|
|
34
|
+
## Step 2: Set up the project
|
|
35
|
+
|
|
36
|
+
Skeleton:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
server/
|
|
40
|
+
src/
|
|
41
|
+
index.ts # MCP entry point — stdio or sse transport
|
|
42
|
+
client.ts # API client with auth, retries, typed errors
|
|
43
|
+
tools/ # one file per tool, or grouped by domain
|
|
44
|
+
pagination.ts # shared cursor handling
|
|
45
|
+
errors.ts # MCP-friendly error formatting
|
|
46
|
+
package.json # @modelcontextprotocol/sdk as dep
|
|
47
|
+
tsconfig.json
|
|
48
|
+
README.md # how to run, env vars, rate-limit notes
|
|
49
|
+
evals.xml # 10 eval questions (Phase 4)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Core infrastructure goes first: API client with typed errors, pagination helpers, consistent retry/timeout behavior. Do not inline these per tool.
|
|
53
|
+
|
|
54
|
+
## Step 3: Implement tools
|
|
55
|
+
|
|
56
|
+
For each tool:
|
|
57
|
+
|
|
58
|
+
1. **Name:** verb-noun, lowercase, snake_case. `search_issues`, `get_customer`, `create_deployment`. Not `do_thing` or `api_v2_post`.
|
|
59
|
+
2. **Description (frontmatter):** 2–4 sentences. State what the tool does, when to use it, when NOT to use it, and any required fields or quirks. This is the model's entire interface to the tool — write it carefully.
|
|
60
|
+
3. **Input schema (JSON Schema):** required fields marked, every field has a description, enums enumerated, examples included for free-form strings.
|
|
61
|
+
4. **Output shape:** typed, minimal, decision-ready. If the raw API returns 40 fields and only 6 matter for follow-up calls, return 6.
|
|
62
|
+
5. **Error handling:** never return raw HTTP errors. Translate to human-readable messages: "Rate limit exceeded (retry in 30s)", "Authorization expired", "No record found for ID X". Include the action the caller should take next.
|
|
63
|
+
6. **Pagination:** expose cursors explicitly. Do not leak "page N of M" into the model — leak "more results available, pass `cursor: abc123` to continue."
|
|
64
|
+
|
|
65
|
+
## Step 4: Build and test with MCP Inspector
|
|
66
|
+
|
|
67
|
+
1. Run the server under MCP Inspector. Verify it registers, every tool lists with its description, inputs schema-validate, outputs shape correctly.
|
|
68
|
+
2. Call every tool at least once manually through the Inspector UI. Check error paths.
|
|
69
|
+
3. Fix any "looks fine in isolation, breaks under the Inspector's framing" issues.
|
|
70
|
+
|
|
71
|
+
## Step 5: Produce the eval set
|
|
72
|
+
|
|
73
|
+
Write 10 evaluation questions in `evals.xml` that exercise the server end-to-end. Each question should require 2+ tool calls and at least one decision the model has to make based on earlier output. Cover:
|
|
74
|
+
|
|
75
|
+
- Happy path (2–3 questions)
|
|
76
|
+
- Error recovery (2 questions — "the first call failed, what next?")
|
|
77
|
+
- Pagination (1 question)
|
|
78
|
+
- Decision under partial information (2–3 questions)
|
|
79
|
+
- Cross-tool composition (1–2 questions)
|
|
80
|
+
|
|
81
|
+
Format:
|
|
82
|
+
|
|
83
|
+
```xml
|
|
84
|
+
<evals>
|
|
85
|
+
<eval id="1">
|
|
86
|
+
<question>...user request...</question>
|
|
87
|
+
<expected>...concrete observable answer or tool-call sequence...</expected>
|
|
88
|
+
</eval>
|
|
89
|
+
</evals>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Run the evals. If the model can't complete them, the server — not the model — needs work. Iterate on descriptions, error messages, and tool granularity.
|
|
93
|
+
|
|
94
|
+
## Step 6: Wire into GSD
|
|
95
|
+
|
|
96
|
+
Write the project's `.mcp.json` entry using `/gsd mcp init` as a starting point. Document env vars and startup in README.md. If the server is globally useful, suggest the user file it as a durable skill via `spike-wrap-up` or publish it.
|
|
97
|
+
|
|
98
|
+
</process>
|
|
99
|
+
|
|
100
|
+
<anti_patterns>
|
|
101
|
+
|
|
102
|
+
- **One-to-one REST mapping.** If the API has 30 endpoints, you likely want 6 tools.
|
|
103
|
+
- **Empty or auto-generated descriptions.** "Calls the /users endpoint" tells the model nothing it can reason with.
|
|
104
|
+
- **Raw error passthrough.** `{"error": "500"}` is useless. Translate.
|
|
105
|
+
- **Page-based pagination leaked as "page 1 of 5".** Use opaque cursors.
|
|
106
|
+
- **Skipping the Inspector.** If you didn't run it under the Inspector, you didn't test it.
|
|
107
|
+
- **No evals.** Without evals you have no signal on whether real task completion works.
|
|
108
|
+
|
|
109
|
+
</anti_patterns>
|
|
110
|
+
|
|
111
|
+
<success_criteria>
|
|
112
|
+
|
|
113
|
+
- [ ] Every tool has a description that could guide a cold-start model correctly.
|
|
114
|
+
- [ ] Errors are translated to actionable, human-readable messages.
|
|
115
|
+
- [ ] Pagination uses opaque cursors; no leaked page numbers.
|
|
116
|
+
- [ ] `evals.xml` has 10 questions; the model completes ≥8 without handholding.
|
|
117
|
+
- [ ] MCP Inspector test passes cleanly.
|
|
118
|
+
- [ ] README documents env, startup, and rate-limit behavior.
|
|
119
|
+
- [ ] Server is reachable from GSD via `.mcp.json` entry.
|
|
120
|
+
|
|
121
|
+
</success_criteria>
|