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
|
@@ -22,7 +22,11 @@ async function getEncoder(): Promise<TokenEncoder | null> {
|
|
|
22
22
|
try {
|
|
23
23
|
// @ts-ignore — tiktoken may not have type declarations in extensions tsconfig
|
|
24
24
|
const tiktoken = await import("tiktoken");
|
|
25
|
-
|
|
25
|
+
// Use cl100k_base — the most conservative and broadly compatible BPE encoding.
|
|
26
|
+
// It is shared by GPT-3.5/GPT-4 and gives a safer (larger) estimate than
|
|
27
|
+
// gpt-4o's o200k_base encoding, which produces fewer tokens for the same text
|
|
28
|
+
// and would cause context windows for non-OpenAI providers to be under-counted.
|
|
29
|
+
encoder = tiktoken.get_encoding("cl100k_base") as TokenEncoder;
|
|
26
30
|
return encoder;
|
|
27
31
|
} catch {
|
|
28
32
|
encoderFailed = true;
|
|
@@ -30,20 +34,33 @@ async function getEncoder(): Promise<TokenEncoder | null> {
|
|
|
30
34
|
}
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Count tokens in `text` using tiktoken (cl100k_base) when available.
|
|
39
|
+
*
|
|
40
|
+
* When tiktoken is not loaded, falls back to a provider-aware character-ratio
|
|
41
|
+
* estimate via `estimateTokensForProvider`. Passing `provider` is recommended
|
|
42
|
+
* so the heuristic fallback is as accurate as possible.
|
|
43
|
+
*/
|
|
44
|
+
export async function countTokens(text: string, provider?: TokenProvider): Promise<number> {
|
|
34
45
|
const enc = await getEncoder();
|
|
35
46
|
if (enc) {
|
|
36
47
|
const tokens = enc.encode(text);
|
|
37
48
|
return tokens.length;
|
|
38
49
|
}
|
|
39
|
-
return
|
|
50
|
+
return estimateTokensForProvider(text, provider ?? "unknown");
|
|
40
51
|
}
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Synchronous token count — only accurate after `initTokenCounter()` resolves.
|
|
55
|
+
*
|
|
56
|
+
* Before init, or when tiktoken is unavailable, falls back to a provider-aware
|
|
57
|
+
* character-ratio estimate. Passing `provider` is recommended.
|
|
58
|
+
*/
|
|
59
|
+
export function countTokensSync(text: string, provider?: TokenProvider): number {
|
|
43
60
|
if (encoder) {
|
|
44
61
|
return encoder.encode(text).length;
|
|
45
62
|
}
|
|
46
|
-
return
|
|
63
|
+
return estimateTokensForProvider(text, provider ?? "unknown");
|
|
47
64
|
}
|
|
48
65
|
|
|
49
66
|
export async function initTokenCounter(): Promise<boolean> {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
|
-
import { mkdirSync } from "node:fs";
|
|
10
|
+
import { mkdirSync, existsSync } from "node:fs";
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
13
|
transaction,
|
|
@@ -202,14 +202,20 @@ export async function handleCompleteMilestone(
|
|
|
202
202
|
summaryPath = join(manualDir, `${params.milestoneId}-SUMMARY.md`);
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
205
|
+
// Guard (#4598): if SUMMARY.md already exists on disk, do not overwrite it.
|
|
206
|
+
// This handles re-dispatch scenarios (DB/disk state divergence) where a prior
|
|
207
|
+
// completion already wrote the file. Overwriting would silently destroy the
|
|
208
|
+
// richer content the agent produced during the original completion run.
|
|
209
|
+
if (!existsSync(summaryPath)) {
|
|
210
|
+
try {
|
|
211
|
+
await saveFile(summaryPath, summaryMd);
|
|
212
|
+
} catch (renderErr) {
|
|
213
|
+
// Disk render failed — roll back DB status so state stays consistent
|
|
214
|
+
logWarning("tool", `complete_milestone — disk render failed, rolling back DB status: ${(renderErr as Error).message}`);
|
|
215
|
+
updateMilestoneStatus(params.milestoneId, 'active', null);
|
|
216
|
+
invalidateStateCache();
|
|
217
|
+
return { error: `disk render failed: ${(renderErr as Error).message}` };
|
|
218
|
+
}
|
|
213
219
|
}
|
|
214
220
|
|
|
215
221
|
// Invalidate all caches
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// GSD Exec Search Tool — lists and filters prior gsd_exec runs.
|
|
2
|
+
//
|
|
3
|
+
// Scans .gsd/exec/*.meta.json and returns a ranked summary so agents can
|
|
4
|
+
// re-discover past runs without re-executing. Read-only; no DB writes.
|
|
5
|
+
|
|
6
|
+
import { searchExecHistory, type ExecSearchOptions } from "../exec-history.js";
|
|
7
|
+
|
|
8
|
+
export interface ExecSearchToolParams {
|
|
9
|
+
query?: string;
|
|
10
|
+
runtime?: "bash" | "node" | "python";
|
|
11
|
+
failing_only?: boolean;
|
|
12
|
+
limit?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ToolExecutionResult {
|
|
16
|
+
content: Array<{ type: "text"; text: string }>;
|
|
17
|
+
details: Record<string, unknown>;
|
|
18
|
+
isError?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function executeExecSearch(
|
|
22
|
+
params: ExecSearchToolParams,
|
|
23
|
+
opts: { baseDir: string },
|
|
24
|
+
): ToolExecutionResult {
|
|
25
|
+
const searchOpts: ExecSearchOptions = {
|
|
26
|
+
query: typeof params.query === "string" ? params.query : undefined,
|
|
27
|
+
runtime: params.runtime,
|
|
28
|
+
failing_only: params.failing_only === true,
|
|
29
|
+
limit: typeof params.limit === "number" ? params.limit : undefined,
|
|
30
|
+
};
|
|
31
|
+
const hits = searchExecHistory(opts.baseDir, searchOpts);
|
|
32
|
+
|
|
33
|
+
if (hits.length === 0) {
|
|
34
|
+
return {
|
|
35
|
+
content: [{ type: "text", text: "No prior gsd_exec runs match those filters." }],
|
|
36
|
+
details: { operation: "gsd_exec_search", matches: 0 },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const lines: string[] = [`Found ${hits.length} exec run(s), most recent first:`];
|
|
41
|
+
for (const hit of hits) {
|
|
42
|
+
const e = hit.entry;
|
|
43
|
+
const status = formatStatus(e);
|
|
44
|
+
const purpose = e.purpose ? ` — ${e.purpose}` : "";
|
|
45
|
+
const truncated = e.stdout_truncated ? " (stdout truncated)" : "";
|
|
46
|
+
lines.push(
|
|
47
|
+
`- [${e.id}] ${e.runtime} ${status} ${e.duration_ms}ms${truncated}${purpose}`,
|
|
48
|
+
` stdout: ${e.stdout_path}`,
|
|
49
|
+
);
|
|
50
|
+
if (hit.digest_preview) {
|
|
51
|
+
const preview = hit.digest_preview.replace(/\n/g, "\n ");
|
|
52
|
+
lines.push(` preview:\n ${preview}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
58
|
+
details: {
|
|
59
|
+
operation: "gsd_exec_search",
|
|
60
|
+
matches: hits.length,
|
|
61
|
+
results: hits.map((hit) => ({
|
|
62
|
+
id: hit.entry.id,
|
|
63
|
+
runtime: hit.entry.runtime,
|
|
64
|
+
exit_code: hit.entry.exit_code,
|
|
65
|
+
timed_out: hit.entry.timed_out,
|
|
66
|
+
duration_ms: hit.entry.duration_ms,
|
|
67
|
+
purpose: hit.entry.purpose,
|
|
68
|
+
stdout_path: hit.entry.stdout_path,
|
|
69
|
+
stderr_path: hit.entry.stderr_path,
|
|
70
|
+
meta_path: hit.entry.meta_path,
|
|
71
|
+
})),
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function formatStatus(entry: { exit_code: number | null; timed_out: boolean; signal: string | null }): string {
|
|
77
|
+
if (entry.timed_out) return "timeout";
|
|
78
|
+
if (entry.signal) return `signal:${entry.signal}`;
|
|
79
|
+
if (entry.exit_code === null) return "exit:null";
|
|
80
|
+
return `exit:${entry.exit_code}`;
|
|
81
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// GSD Exec Tool — executor for the gsd_exec MCP tool.
|
|
2
|
+
//
|
|
3
|
+
// Thin wrapper around exec-sandbox.ts that reads effective options from
|
|
4
|
+
// the project preferences (context_mode block) and formats the result
|
|
5
|
+
// for MCP return.
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
EXEC_DEFAULTS,
|
|
9
|
+
runExecSandbox,
|
|
10
|
+
type ExecSandboxOptions,
|
|
11
|
+
type ExecSandboxRequest,
|
|
12
|
+
type ExecSandboxResult,
|
|
13
|
+
} from "../exec-sandbox.js";
|
|
14
|
+
import { isContextModeEnabled, type ContextModeConfig } from "../preferences-types.js";
|
|
15
|
+
|
|
16
|
+
export interface ExecToolParams {
|
|
17
|
+
runtime: ExecSandboxRequest["runtime"];
|
|
18
|
+
script: string;
|
|
19
|
+
purpose?: string;
|
|
20
|
+
timeout_ms?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ToolExecutionResult {
|
|
24
|
+
content: Array<{ type: "text"; text: string }>;
|
|
25
|
+
details: Record<string, unknown>;
|
|
26
|
+
isError?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ExecToolDeps {
|
|
30
|
+
baseDir: string;
|
|
31
|
+
preferences: { context_mode?: ContextModeConfig } | null;
|
|
32
|
+
/** Optional override for testing. */
|
|
33
|
+
run?: (req: ExecSandboxRequest, opts: ExecSandboxOptions) => Promise<ExecSandboxResult>;
|
|
34
|
+
now?: () => Date;
|
|
35
|
+
generateId?: () => string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function buildExecOptions(
|
|
39
|
+
baseDir: string,
|
|
40
|
+
cfg: ContextModeConfig | undefined,
|
|
41
|
+
extras?: Pick<ExecSandboxOptions, "env" | "now" | "generateId">,
|
|
42
|
+
): ExecSandboxOptions {
|
|
43
|
+
const allowlist = Array.isArray(cfg?.exec_env_allowlist) ? cfg!.exec_env_allowlist! : EXEC_DEFAULTS.envAllowlist;
|
|
44
|
+
const stdoutCap = clampNumber(
|
|
45
|
+
cfg?.exec_stdout_cap_bytes,
|
|
46
|
+
EXEC_DEFAULTS.stdoutCapBytes,
|
|
47
|
+
4_096,
|
|
48
|
+
16_777_216,
|
|
49
|
+
);
|
|
50
|
+
const defaultTimeout = clampNumber(
|
|
51
|
+
cfg?.exec_timeout_ms,
|
|
52
|
+
EXEC_DEFAULTS.defaultTimeoutMs,
|
|
53
|
+
1_000,
|
|
54
|
+
EXEC_DEFAULTS.clampTimeoutMs,
|
|
55
|
+
);
|
|
56
|
+
const digestChars = clampNumber(cfg?.exec_digest_chars, EXEC_DEFAULTS.digestChars, 0, 4_000);
|
|
57
|
+
return {
|
|
58
|
+
baseDir,
|
|
59
|
+
clamp_timeout_ms: EXEC_DEFAULTS.clampTimeoutMs,
|
|
60
|
+
default_timeout_ms: defaultTimeout,
|
|
61
|
+
stdout_cap_bytes: stdoutCap,
|
|
62
|
+
stderr_cap_bytes: EXEC_DEFAULTS.stderrCapBytes,
|
|
63
|
+
digest_chars: digestChars,
|
|
64
|
+
env_allowlist: allowlist,
|
|
65
|
+
...extras,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function clampNumber(value: unknown, fallback: number, min: number, max: number): number {
|
|
70
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
71
|
+
if (value < min) return min;
|
|
72
|
+
if (value > max) return max;
|
|
73
|
+
return Math.floor(value);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function isEnabled(prefs: ExecToolDeps["preferences"]): boolean {
|
|
77
|
+
return isContextModeEnabled(prefs);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function disabledResult(): ToolExecutionResult {
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "text",
|
|
85
|
+
text:
|
|
86
|
+
"gsd_exec is disabled by `context_mode.enabled: false` in preferences. Remove that " +
|
|
87
|
+
"override (or set it to true) to re-enable sandboxed tool-output execution.",
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
details: { operation: "gsd_exec", error: "context_mode_disabled" },
|
|
91
|
+
isError: true,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function paramError(message: string): ToolExecutionResult {
|
|
96
|
+
return {
|
|
97
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
98
|
+
details: { operation: "gsd_exec", error: "invalid_params", detail: message },
|
|
99
|
+
isError: true,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function executeGsdExec(
|
|
104
|
+
params: ExecToolParams,
|
|
105
|
+
deps: ExecToolDeps,
|
|
106
|
+
): Promise<ToolExecutionResult> {
|
|
107
|
+
if (!isEnabled(deps.preferences)) return disabledResult();
|
|
108
|
+
|
|
109
|
+
const runtime = params.runtime;
|
|
110
|
+
if (runtime !== "bash" && runtime !== "node" && runtime !== "python") {
|
|
111
|
+
return paramError(`invalid runtime "${String(runtime)}" — must be bash | node | python`);
|
|
112
|
+
}
|
|
113
|
+
const script = typeof params.script === "string" ? params.script : "";
|
|
114
|
+
if (script.trim().length === 0) {
|
|
115
|
+
return paramError("script is required and must be a non-empty string");
|
|
116
|
+
}
|
|
117
|
+
if (Buffer.byteLength(script, "utf8") > 200_000) {
|
|
118
|
+
return paramError("script exceeds the 200 KB length limit");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const opts = buildExecOptions(
|
|
122
|
+
deps.baseDir,
|
|
123
|
+
deps.preferences?.context_mode,
|
|
124
|
+
{ now: deps.now, generateId: deps.generateId },
|
|
125
|
+
);
|
|
126
|
+
const run = deps.run ?? runExecSandbox;
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const result = await run(
|
|
130
|
+
{
|
|
131
|
+
runtime,
|
|
132
|
+
script,
|
|
133
|
+
...(typeof params.purpose === "string" ? { purpose: params.purpose } : {}),
|
|
134
|
+
...(typeof params.timeout_ms === "number" ? { timeout_ms: params.timeout_ms } : {}),
|
|
135
|
+
},
|
|
136
|
+
opts,
|
|
137
|
+
);
|
|
138
|
+
return formatResult(result);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
141
|
+
return {
|
|
142
|
+
content: [{ type: "text", text: `Error: gsd_exec failed — ${message}` }],
|
|
143
|
+
details: { operation: "gsd_exec", error: message },
|
|
144
|
+
isError: true,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function formatResult(result: ExecSandboxResult): ToolExecutionResult {
|
|
150
|
+
const headerLines = [
|
|
151
|
+
`gsd_exec[${result.id}] runtime=${result.runtime} exit=${formatExit(result)} duration=${result.duration_ms}ms`,
|
|
152
|
+
` stdout: ${result.stdout_bytes}B${result.stdout_truncated ? " (truncated)" : ""} → ${result.stdout_path}`,
|
|
153
|
+
` stderr: ${result.stderr_bytes}B${result.stderr_truncated ? " (truncated)" : ""} → ${result.stderr_path}`,
|
|
154
|
+
];
|
|
155
|
+
const summary = `${headerLines.join("\n")}\n--- digest ---\n${result.digest}`.trimEnd();
|
|
156
|
+
return {
|
|
157
|
+
content: [{ type: "text", text: summary }],
|
|
158
|
+
details: {
|
|
159
|
+
operation: "gsd_exec",
|
|
160
|
+
id: result.id,
|
|
161
|
+
runtime: result.runtime,
|
|
162
|
+
exit_code: result.exit_code,
|
|
163
|
+
signal: result.signal,
|
|
164
|
+
timed_out: result.timed_out,
|
|
165
|
+
duration_ms: result.duration_ms,
|
|
166
|
+
stdout_bytes: result.stdout_bytes,
|
|
167
|
+
stderr_bytes: result.stderr_bytes,
|
|
168
|
+
stdout_truncated: result.stdout_truncated,
|
|
169
|
+
stderr_truncated: result.stderr_truncated,
|
|
170
|
+
stdout_path: result.stdout_path,
|
|
171
|
+
stderr_path: result.stderr_path,
|
|
172
|
+
meta_path: result.meta_path,
|
|
173
|
+
},
|
|
174
|
+
isError: result.timed_out || result.signal !== null || result.exit_code !== 0,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function formatExit(result: ExecSandboxResult): string {
|
|
179
|
+
if (result.timed_out) return "timeout";
|
|
180
|
+
if (result.signal) return `signal:${result.signal}`;
|
|
181
|
+
if (result.exit_code === null) return "null";
|
|
182
|
+
return String(result.exit_code);
|
|
183
|
+
}
|
|
@@ -48,6 +48,14 @@ export interface MemoryCaptureParams {
|
|
|
48
48
|
confidence?: number;
|
|
49
49
|
tags?: string[];
|
|
50
50
|
scope?: string;
|
|
51
|
+
/**
|
|
52
|
+
* ADR-013 Step 2: optional structured payload preserved verbatim on the
|
|
53
|
+
* memories row. Used when capturing decisions that need to retain
|
|
54
|
+
* gsd_save_decision-style fields (scope, decision, choice, rationale,
|
|
55
|
+
* made_by, revisable) so the eventual cutover (Step 6) is lossless.
|
|
56
|
+
* Plain pattern/gotcha/convention captures may omit this entirely.
|
|
57
|
+
*/
|
|
58
|
+
structuredFields?: Record<string, unknown> | null;
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
const VALID_CATEGORIES = new Set([
|
|
@@ -87,7 +95,8 @@ export function executeMemoryCapture(params: MemoryCaptureParams): ToolExecution
|
|
|
87
95
|
const scope = normalizeScope(params.scope);
|
|
88
96
|
const tags = normalizeTags(params.tags);
|
|
89
97
|
|
|
90
|
-
const
|
|
98
|
+
const structuredFields = normalizeStructuredFields(params.structuredFields);
|
|
99
|
+
const id = createMemory({ category, content, confidence, scope, tags, structuredFields });
|
|
91
100
|
if (!id) {
|
|
92
101
|
return {
|
|
93
102
|
content: [{ type: "text", text: "Error: failed to create memory." }],
|
|
@@ -113,6 +122,17 @@ function normalizeTags(value: unknown): string[] {
|
|
|
113
122
|
return value.filter((t): t is string => typeof t === "string" && t.trim().length > 0).slice(0, 10);
|
|
114
123
|
}
|
|
115
124
|
|
|
125
|
+
function normalizeStructuredFields(value: unknown): Record<string, unknown> | null {
|
|
126
|
+
if (value == null) return null;
|
|
127
|
+
if (typeof value !== "object" || Array.isArray(value)) return null;
|
|
128
|
+
// Only accept plain objects (Object.prototype or null prototype). Class
|
|
129
|
+
// instances and exotic objects won't round-trip cleanly through JSON, so
|
|
130
|
+
// reject them here instead of producing a partially-serialized payload.
|
|
131
|
+
const proto = Object.getPrototypeOf(value);
|
|
132
|
+
if (proto !== null && proto !== Object.prototype) return null;
|
|
133
|
+
return value as Record<string, unknown>;
|
|
134
|
+
}
|
|
135
|
+
|
|
116
136
|
function clampConfidence(value: unknown): number {
|
|
117
137
|
if (typeof value !== "number" || !Number.isFinite(value)) return 0.8;
|
|
118
138
|
if (value < 0.1) return 0.1;
|
|
@@ -248,6 +268,15 @@ function includeSupersededMemories(rankedActive: Memory[]): Memory[] {
|
|
|
248
268
|
/* leave empty */
|
|
249
269
|
}
|
|
250
270
|
}
|
|
271
|
+
let structuredFields: Record<string, unknown> | null = null;
|
|
272
|
+
if (typeof row["structured_fields"] === "string" && (row["structured_fields"] as string).length > 0) {
|
|
273
|
+
try {
|
|
274
|
+
const parsed = JSON.parse(row["structured_fields"] as string);
|
|
275
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
276
|
+
structuredFields = parsed as Record<string, unknown>;
|
|
277
|
+
}
|
|
278
|
+
} catch { /* leave null */ }
|
|
279
|
+
}
|
|
251
280
|
return {
|
|
252
281
|
seq: row["seq"] as number,
|
|
253
282
|
id: row["id"] as string,
|
|
@@ -262,6 +291,7 @@ function includeSupersededMemories(rankedActive: Memory[]): Memory[] {
|
|
|
262
291
|
hit_count: row["hit_count"] as number,
|
|
263
292
|
scope: (row["scope"] as string) ?? "project",
|
|
264
293
|
tags,
|
|
294
|
+
structured_fields: structuredFields,
|
|
265
295
|
};
|
|
266
296
|
});
|
|
267
297
|
} catch {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// GSD Resume Tool — returns the contents of .gsd/last-snapshot.md so
|
|
2
|
+
// agents can re-orient after compaction or session resume without
|
|
3
|
+
// re-deriving project memory state.
|
|
4
|
+
|
|
5
|
+
import { readCompactionSnapshot } from "../compaction-snapshot.js";
|
|
6
|
+
|
|
7
|
+
export interface ResumeToolParams {
|
|
8
|
+
/** Ignored — reserved for future variant (e.g. dated snapshots). */
|
|
9
|
+
_variant?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ToolExecutionResult {
|
|
13
|
+
content: Array<{ type: "text"; text: string }>;
|
|
14
|
+
details: Record<string, unknown>;
|
|
15
|
+
isError?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function executeResume(
|
|
19
|
+
_params: ResumeToolParams,
|
|
20
|
+
opts: { baseDir: string },
|
|
21
|
+
): ToolExecutionResult {
|
|
22
|
+
const snapshot = readCompactionSnapshot(opts.baseDir);
|
|
23
|
+
if (snapshot == null) {
|
|
24
|
+
return {
|
|
25
|
+
content: [
|
|
26
|
+
{
|
|
27
|
+
type: "text",
|
|
28
|
+
text:
|
|
29
|
+
"No snapshot found at .gsd/last-snapshot.md. The snapshot is written automatically " +
|
|
30
|
+
"on session_before_compact (enabled by default; set context_mode.enabled=false to opt out).",
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
details: { operation: "gsd_resume", found: false },
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: snapshot }],
|
|
38
|
+
details: { operation: "gsd_resume", found: true, bytes: Buffer.byteLength(snapshot, "utf-8") },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -38,6 +38,29 @@ function hasFileContent(path: string | null): boolean {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
function getArtifactLookupBases(basePath: string): string[] {
|
|
42
|
+
const bases = [basePath];
|
|
43
|
+
const projectRoot = process.env.GSD_PROJECT_ROOT;
|
|
44
|
+
if (projectRoot && projectRoot.trim().length > 0 && projectRoot !== basePath) {
|
|
45
|
+
bases.push(projectRoot);
|
|
46
|
+
}
|
|
47
|
+
return bases;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function hasMilestoneFileContent(
|
|
51
|
+
basePath: string,
|
|
52
|
+
milestoneId: string,
|
|
53
|
+
suffix: string,
|
|
54
|
+
): boolean {
|
|
55
|
+
const bases = getArtifactLookupBases(basePath);
|
|
56
|
+
for (const candidateBase of bases) {
|
|
57
|
+
if (hasFileContent(resolveMilestoneFile(candidateBase, milestoneId, suffix))) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
41
64
|
function countSliceResearchArtifacts(basePath: string, milestoneId: string, slices: SliceRow[]): number {
|
|
42
65
|
let count = 0;
|
|
43
66
|
for (const slice of slices) {
|
|
@@ -60,9 +83,9 @@ export function compileUnitGraphFromState(basePath: string, state: GSDState): Pl
|
|
|
60
83
|
const slices = getMilestoneSlices(mid).sort((a, b) => Number(a.sequence ?? 0) - Number(b.sequence ?? 0));
|
|
61
84
|
const nodes: UokGraphNode[] = [];
|
|
62
85
|
const clarifyRoundLimit = PLAN_V2_CLARIFY_ROUND_LIMIT;
|
|
63
|
-
const draftContextIncluded =
|
|
64
|
-
const finalizedContextIncluded =
|
|
65
|
-
const researchSynthesized =
|
|
86
|
+
const draftContextIncluded = hasMilestoneFileContent(basePath, mid, "CONTEXT-DRAFT");
|
|
87
|
+
const finalizedContextIncluded = hasMilestoneFileContent(basePath, mid, "CONTEXT");
|
|
88
|
+
const researchSynthesized = hasMilestoneFileContent(basePath, mid, "RESEARCH")
|
|
66
89
|
|| countSliceResearchArtifacts(basePath, mid, slices) > 0;
|
|
67
90
|
|
|
68
91
|
if (isExecutionEntryPhase(state.phase) && !finalizedContextIncluded) {
|
|
@@ -56,7 +56,10 @@ export type LogComponent =
|
|
|
56
56
|
| "safety" // LLM safety harness
|
|
57
57
|
| "ecosystem" // GSD ecosystem extension loader and dispatch
|
|
58
58
|
| "memory-embeddings" // Memory layer embedding generation
|
|
59
|
-
| "memory-ingest"
|
|
59
|
+
| "memory-ingest" // Memory layer ingestion pipeline
|
|
60
|
+
| "memory-backfill" // ADR-013: decisions->memories backfill
|
|
61
|
+
| "context-mode" // Context-mode exec sandbox and compaction snapshot
|
|
62
|
+
| "preflight"; // Clean-root preflight gate at milestone completion
|
|
60
63
|
|
|
61
64
|
export interface LogEntry {
|
|
62
65
|
ts: string;
|
|
@@ -23,6 +23,9 @@ export interface WorkflowCapabilityOptions {
|
|
|
23
23
|
const MCP_WORKFLOW_TOOL_SURFACE = new Set([
|
|
24
24
|
"ask_user_questions",
|
|
25
25
|
"gsd_decision_save",
|
|
26
|
+
"gsd_exec",
|
|
27
|
+
"gsd_exec_search",
|
|
28
|
+
"gsd_resume",
|
|
26
29
|
"gsd_complete_milestone",
|
|
27
30
|
"gsd_complete_task",
|
|
28
31
|
"gsd_complete_slice",
|
|
@@ -66,5 +66,11 @@ Use for: technology evaluation, architecture decisions, "should we X?" questions
|
|
|
66
66
|
- Recommendation with rationale
|
|
67
67
|
- Next steps if the recommendation is accepted
|
|
68
68
|
4. **Present** the recommendation to the user for discussion
|
|
69
|
+
5. **Offer wrap-up:** If the findings are reusable on future work, offer to run
|
|
70
|
+
the `spike-wrap-up` skill to package them as a project-local skill at
|
|
71
|
+
`.claude/skills/<name>/SKILL.md`. That skill will auto-load on future
|
|
72
|
+
similar tasks via `skill-discovery.ts`. If the recommendation is
|
|
73
|
+
decision-only (no reusable guidance), suggest appending a one-liner to
|
|
74
|
+
`.gsd/DECISIONS.md` instead.
|
|
69
75
|
|
|
70
76
|
</process>
|
|
@@ -79,6 +79,35 @@ export interface NotifyCtx {
|
|
|
79
79
|
) => void;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
// ─── Path Helpers ──────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Worktree marker segment — present in any path produced by worktreePath().
|
|
86
|
+
* Used to strip the worktree suffix and recover the project root (#3729).
|
|
87
|
+
*/
|
|
88
|
+
const WORKTREE_MARKER = "/.gsd/worktrees/";
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Resolve the project root from session path state.
|
|
92
|
+
*
|
|
93
|
+
* Prefers `originalBasePath` (always the project root when set), but falls
|
|
94
|
+
* back to `basePath` when `originalBasePath` is falsy (e.g. fresh AutoSession
|
|
95
|
+
* with default empty string). If `basePath` itself is inside a worktree
|
|
96
|
+
* directory (contains `/.gsd/worktrees/`), strip that suffix to recover the
|
|
97
|
+
* actual project root — preventing double-nested worktree paths (#3729).
|
|
98
|
+
*/
|
|
99
|
+
export function resolveProjectRoot(
|
|
100
|
+
originalBasePath: string,
|
|
101
|
+
basePath: string,
|
|
102
|
+
): string {
|
|
103
|
+
let resolved = originalBasePath || basePath;
|
|
104
|
+
const markerIdx = resolved.indexOf(WORKTREE_MARKER);
|
|
105
|
+
if (markerIdx !== -1) {
|
|
106
|
+
resolved = resolved.slice(0, markerIdx);
|
|
107
|
+
}
|
|
108
|
+
return resolved;
|
|
109
|
+
}
|
|
110
|
+
|
|
82
111
|
// ─── WorktreeResolver ──────────────────────────────────────────────────────
|
|
83
112
|
|
|
84
113
|
export class WorktreeResolver {
|
|
@@ -99,12 +128,12 @@ export class WorktreeResolver {
|
|
|
99
128
|
|
|
100
129
|
/** Original project root — always the non-worktree path. */
|
|
101
130
|
get projectRoot(): string {
|
|
102
|
-
return this.s.originalBasePath
|
|
131
|
+
return resolveProjectRoot(this.s.originalBasePath, this.s.basePath);
|
|
103
132
|
}
|
|
104
133
|
|
|
105
134
|
/** Path for auto.lock file — same as the old lockBase(). */
|
|
106
135
|
get lockPath(): string {
|
|
107
|
-
return this.s.originalBasePath
|
|
136
|
+
return resolveProjectRoot(this.s.originalBasePath, this.s.basePath);
|
|
108
137
|
}
|
|
109
138
|
|
|
110
139
|
// ── Private Helpers ────────────────────────────────────────────────────
|
|
@@ -182,7 +211,10 @@ export class WorktreeResolver {
|
|
|
182
211
|
return;
|
|
183
212
|
}
|
|
184
213
|
|
|
185
|
-
|
|
214
|
+
// Resolve the project root for worktree operations via shared helper.
|
|
215
|
+
// Handles the case where originalBasePath is falsy and basePath is itself
|
|
216
|
+
// a worktree path — prevents double-nested worktree paths (#3729).
|
|
217
|
+
const basePath = resolveProjectRoot(this.s.originalBasePath, this.s.basePath);
|
|
186
218
|
debugLog("WorktreeResolver", {
|
|
187
219
|
action: "enterMilestone",
|
|
188
220
|
milestoneId,
|
|
@@ -569,11 +601,13 @@ export class WorktreeResolver {
|
|
|
569
601
|
}
|
|
570
602
|
}
|
|
571
603
|
|
|
572
|
-
//
|
|
573
|
-
//
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
604
|
+
// Restore state before re-throwing so callers always get a consistent
|
|
605
|
+
// session (#4380).
|
|
606
|
+
this.restoreToProjectRoot();
|
|
607
|
+
// Re-throw: MergeConflictError stops the auto loop (#2330); non-conflict
|
|
608
|
+
// errors (permission denied, filesystem failures) must also propagate so
|
|
609
|
+
// broken states are diagnosable (#4380).
|
|
610
|
+
throw err;
|
|
577
611
|
}
|
|
578
612
|
|
|
579
613
|
// Always restore basePath and rebuild — whether merge succeeded or failed
|
|
@@ -659,6 +693,8 @@ export class WorktreeResolver {
|
|
|
659
693
|
error: msg,
|
|
660
694
|
});
|
|
661
695
|
ctx.notify(`Milestone merge failed (branch mode): ${msg}`, "warning");
|
|
696
|
+
// Re-throw all errors so callers can apply their own recovery logic (#4380).
|
|
697
|
+
throw err;
|
|
662
698
|
}
|
|
663
699
|
}
|
|
664
700
|
|
|
@@ -681,7 +717,16 @@ export class WorktreeResolver {
|
|
|
681
717
|
currentMilestoneId,
|
|
682
718
|
nextMilestoneId,
|
|
683
719
|
});
|
|
684
|
-
|
|
720
|
+
try {
|
|
721
|
+
this.mergeAndExit(currentMilestoneId, ctx);
|
|
722
|
+
} catch (err) {
|
|
723
|
+
// mergeAndExit emits a warning and restores state when it fails during
|
|
724
|
+
// merge/cleanup. But if it throws before recovery runs (e.g., in
|
|
725
|
+
// validateMilestoneId or emitJournalEvent), basePath won't be restored
|
|
726
|
+
// to projectRoot — re-throw so we don't enter the next milestone with
|
|
727
|
+
// the current one unmerged.
|
|
728
|
+
if (this.s.basePath !== this.projectRoot) throw err;
|
|
729
|
+
}
|
|
685
730
|
this.enterMilestone(nextMilestoneId, ctx);
|
|
686
731
|
}
|
|
687
732
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* All provider logic lives in provider.ts (S01) — this is pure UI wiring.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { supportsNativeWebSearch } from './native-search.js'
|
|
12
12
|
import type { ExtensionAPI } from '@gsd/pi-coding-agent'
|
|
13
13
|
import type { AutocompleteItem } from '@gsd/pi-tui'
|
|
14
14
|
import {
|
|
@@ -91,9 +91,10 @@ export function registerSearchProviderCommand(pi: ExtensionAPI): void {
|
|
|
91
91
|
|
|
92
92
|
setSearchProviderPreference(chosen)
|
|
93
93
|
const effective = resolveSearchProvider()
|
|
94
|
-
// Gate on api
|
|
95
|
-
//
|
|
96
|
-
|
|
94
|
+
// Gate on api shape + provider allowlist: the info note must match the
|
|
95
|
+
// actual runtime behavior in native-search.ts. Claude served via copilot
|
|
96
|
+
// / minimax / kimi is anthropic-shaped but does NOT run native search.
|
|
97
|
+
const isAnthropic = supportsNativeWebSearch(ctx.model)
|
|
97
98
|
const nativeNote = isAnthropic ? '\nNote: Native Anthropic web search is also active (automatic, no API key needed).' : ''
|
|
98
99
|
ctx.ui.notify(
|
|
99
100
|
`Search provider set to ${chosen}. Effective provider: ${effective ?? 'none (no API keys)'}${nativeNote}`,
|