gsd-pi 2.76.0-dev.4100bd590 → 2.76.0-dev.479ad0e78
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/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/extensions/claude-code-cli/readiness.js +4 -3
- 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 +58 -5
- 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 +14 -3
- 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-worktree.js +51 -53
- package/dist/resources/extensions/gsd/auto.js +70 -28
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -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/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +52 -6
- 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-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/error-classifier.js +10 -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 +149 -31
- 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/init-wizard.js +15 -1
- package/dist/resources/extensions/gsd/key-manager.js +28 -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/discuss-headless.md +8 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- 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/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/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/worktree-resolver.js +50 -10
- package/dist/resources/skills/verify-before-complete/SKILL.md +2 -1
- package/dist/resources/skills/write-docs/SKILL.md +2 -1
- 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 +17 -17
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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 +17 -17
- 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 +5 -5
- 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/.next/server/server-reference-manifest.json +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/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.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +64 -25
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -1
- 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 +84 -43
- package/packages/mcp-server/tsconfig.test.json +19 -0
- package/packages/mcp-server/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-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 +8 -3
- 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/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-shared.ts +26 -5
- package/packages/pi-ai/src/providers/anthropic.ts +9 -3
- 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/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 +7 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
- 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/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-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/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/src/core/agent-session-abort-order.test.ts +3 -2
- package/packages/pi-coding-agent/src/core/agent-session.ts +11 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +2 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -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-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/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/scripts/link-workspace-packages.cjs +1 -0
- package/src/resources/extensions/claude-code-cli/readiness.ts +4 -3
- 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 +82 -4
- 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 +17 -2
- 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-worktree.ts +62 -63
- package/src/resources/extensions/gsd/auto.ts +73 -28
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +23 -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/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +54 -6
- 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-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/error-classifier.ts +10 -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 +157 -33
- 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/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/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/discuss-headless.md +8 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- 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/tests/auto-loop.test.ts +188 -2
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +12 -0
- 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/clean-root-preflight.test.ts +186 -0
- 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/doctor-providers.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +1 -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/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/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/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 +2 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +9 -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 +48 -0
- 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/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/resume-tool.ts +40 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +26 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
- package/src/resources/skills/verify-before-complete/SKILL.md +2 -1
- package/src/resources/skills/write-docs/SKILL.md +2 -1
- /package/dist/web/standalone/.next/static/{YnUwu2WWaT0_hyTLUF4nq → JgU2F-5N9mTyB7kUSSk9A}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{YnUwu2WWaT0_hyTLUF4nq → JgU2F-5N9mTyB7kUSSk9A}/_ssgManifest.js +0 -0
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import type { Api, Model } from "@gsd/pi-ai";
|
|
20
|
-
import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
20
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
21
21
|
import type { GitServiceImpl } from "../git-service.js";
|
|
22
22
|
import type { CaptureEntry } from "../captures.js";
|
|
23
23
|
import type { BudgetAlertLevel } from "../auto-budget.js";
|
|
@@ -40,6 +40,8 @@ export interface StartModel {
|
|
|
40
40
|
id: string;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export type ThinkingLevelSnapshot = ReturnType<ExtensionAPI["getThinkingLevel"]>;
|
|
44
|
+
|
|
43
45
|
export interface PendingVerificationRetry {
|
|
44
46
|
unitId: string;
|
|
45
47
|
failureContext: string;
|
|
@@ -62,6 +64,15 @@ export interface SidecarItem {
|
|
|
62
64
|
captureId?: string;
|
|
63
65
|
}
|
|
64
66
|
|
|
67
|
+
export interface PreExecFailure {
|
|
68
|
+
/** Milestone/slice that failed (e.g. "M001/S02"). */
|
|
69
|
+
unitId: string;
|
|
70
|
+
/** Verbatim blocking check strings from the failed gate run. */
|
|
71
|
+
blockingFindings: string[];
|
|
72
|
+
/** Condensed gate verdict excerpt for context (status + rationale). */
|
|
73
|
+
verdictExcerpt: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
65
76
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
66
77
|
|
|
67
78
|
export const MAX_UNIT_DISPATCHES = 3;
|
|
@@ -120,6 +131,8 @@ export class AutoSession {
|
|
|
120
131
|
currentDispatchedModelId: string | null = null;
|
|
121
132
|
originalModelId: string | null = null;
|
|
122
133
|
originalModelProvider: string | null = null;
|
|
134
|
+
autoModeStartThinkingLevel: ThinkingLevelSnapshot | null = null;
|
|
135
|
+
originalThinkingLevel: ThinkingLevelSnapshot | null = null;
|
|
123
136
|
lastBudgetAlertLevel: BudgetAlertLevel = 0;
|
|
124
137
|
|
|
125
138
|
// ── Recovery ─────────────────────────────────────────────────────────────
|
|
@@ -135,6 +148,18 @@ export class AutoSession {
|
|
|
135
148
|
// ── Sidecar queue ─────────────────────────────────────────────────────
|
|
136
149
|
sidecarQueue: SidecarItem[] = [];
|
|
137
150
|
|
|
151
|
+
// ── Pre-exec gate failure context (#4551) ───────────────────────────
|
|
152
|
+
/**
|
|
153
|
+
* Persisted when a pre-execution gate fails on a plan-slice or refine-slice
|
|
154
|
+
* unit. The planning → plan-slice dispatch rule reads this field and injects
|
|
155
|
+
* the failure details into the next re-dispatch prompt so the LLM can fix the
|
|
156
|
+
* specific issues instead of producing an identical plan.
|
|
157
|
+
*
|
|
158
|
+
* Cleared after it has been consumed (injected into the prompt) to avoid
|
|
159
|
+
* stale context bleeding into unrelated slices.
|
|
160
|
+
*/
|
|
161
|
+
lastPreExecFailure: PreExecFailure | null = null;
|
|
162
|
+
|
|
138
163
|
// ── Tool invocation errors (#2883) ──────────────────────────────────
|
|
139
164
|
/** Set when a GSD tool execution ends with isError due to malformed/truncated
|
|
140
165
|
* JSON arguments. Checked by postUnitPreVerification to break retry loops. */
|
|
@@ -195,7 +220,12 @@ export class AutoSession {
|
|
|
195
220
|
}
|
|
196
221
|
|
|
197
222
|
get lockBasePath(): string {
|
|
198
|
-
|
|
223
|
+
// Prefer originalBasePath (project root); fall back to basePath.
|
|
224
|
+
// Strip /.gsd/worktrees/ suffix if basePath is itself a worktree path
|
|
225
|
+
// to avoid reading/writing the lock inside the worktree (#3729).
|
|
226
|
+
const resolved = this.originalBasePath || this.basePath;
|
|
227
|
+
const markerIdx = resolved.indexOf("/.gsd/worktrees/");
|
|
228
|
+
return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
|
|
199
229
|
}
|
|
200
230
|
|
|
201
231
|
reset(): void {
|
|
@@ -241,6 +271,8 @@ export class AutoSession {
|
|
|
241
271
|
this.currentDispatchedModelId = null;
|
|
242
272
|
this.originalModelId = null;
|
|
243
273
|
this.originalModelProvider = null;
|
|
274
|
+
this.autoModeStartThinkingLevel = null;
|
|
275
|
+
this.originalThinkingLevel = null;
|
|
244
276
|
this.lastBudgetAlertLevel = 0;
|
|
245
277
|
|
|
246
278
|
// Recovery
|
|
@@ -261,6 +293,7 @@ export class AutoSession {
|
|
|
261
293
|
this.sidecarQueue = [];
|
|
262
294
|
this.rewriteAttemptCount = 0;
|
|
263
295
|
this.consecutiveCompleteBootstraps = 0;
|
|
296
|
+
this.lastPreExecFailure = null;
|
|
264
297
|
this.lastToolInvocationError = null;
|
|
265
298
|
this.lastGitActionFailure = null;
|
|
266
299
|
this.lastGitActionStatus = null;
|
|
@@ -568,15 +568,28 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
568
568
|
},
|
|
569
569
|
{
|
|
570
570
|
name: "planning → plan-slice",
|
|
571
|
-
match: async ({ state, mid, midTitle, basePath, sessionContextWindow, modelRegistry }) => {
|
|
571
|
+
match: async ({ state, mid, midTitle, basePath, sessionContextWindow, modelRegistry, session }) => {
|
|
572
572
|
if (state.phase !== "planning") return null;
|
|
573
573
|
if (!state.activeSlice) return missingSliceStop(mid, state.phase);
|
|
574
574
|
const sid = state.activeSlice!.id;
|
|
575
575
|
const sTitle = state.activeSlice!.title;
|
|
576
|
+
// #4551: Consume any persisted pre-exec failure for this slice so the
|
|
577
|
+
// re-dispatched prompt includes the exact blocked references. Clear the
|
|
578
|
+
// field immediately after reading to prevent stale context leaking into
|
|
579
|
+
// a later, unrelated plan-slice run.
|
|
580
|
+
const unitId = `${mid}/${sid}`;
|
|
581
|
+
let priorPreExecFailure: { blockingFindings: string[]; verdictExcerpt: string } | undefined;
|
|
582
|
+
if (session?.lastPreExecFailure?.unitId === unitId) {
|
|
583
|
+
priorPreExecFailure = {
|
|
584
|
+
blockingFindings: session.lastPreExecFailure.blockingFindings,
|
|
585
|
+
verdictExcerpt: session.lastPreExecFailure.verdictExcerpt,
|
|
586
|
+
};
|
|
587
|
+
session.lastPreExecFailure = null;
|
|
588
|
+
}
|
|
576
589
|
return {
|
|
577
590
|
action: "dispatch",
|
|
578
591
|
unitType: "plan-slice",
|
|
579
|
-
unitId
|
|
592
|
+
unitId,
|
|
580
593
|
prompt: await buildPlanSlicePrompt(
|
|
581
594
|
mid,
|
|
582
595
|
midTitle,
|
|
@@ -584,7 +597,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
584
597
|
sTitle,
|
|
585
598
|
basePath,
|
|
586
599
|
undefined,
|
|
587
|
-
{ sessionContextWindow, modelRegistry },
|
|
600
|
+
{ sessionContextWindow, modelRegistry, priorPreExecFailure },
|
|
588
601
|
),
|
|
589
602
|
};
|
|
590
603
|
},
|
|
@@ -33,6 +33,14 @@ export interface PreferredModelConfig {
|
|
|
33
33
|
source: "explicit" | "synthesized";
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
function reapplyThinkingLevel(
|
|
37
|
+
pi: ExtensionAPI,
|
|
38
|
+
level: ReturnType<ExtensionAPI["getThinkingLevel"]> | null | undefined,
|
|
39
|
+
): void {
|
|
40
|
+
if (!level) return;
|
|
41
|
+
pi.setThinkingLevel(level);
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
export function resolvePreferredModelConfig(
|
|
37
45
|
unitType: string,
|
|
38
46
|
autoModeStartModel: { provider: string; id: string; flatRateCtx?: FlatRateContext } | null,
|
|
@@ -97,6 +105,8 @@ export async function selectAndApplyModel(
|
|
|
97
105
|
isAutoMode = true,
|
|
98
106
|
/** Explicit /gsd model pin captured at bootstrap for long-running auto loops. */
|
|
99
107
|
sessionModelOverride?: { provider: string; id: string } | null,
|
|
108
|
+
/** Thinking level captured at auto-mode start and re-applied after model swaps. */
|
|
109
|
+
autoModeStartThinkingLevel?: ReturnType<ExtensionAPI["getThinkingLevel"]> | null,
|
|
100
110
|
): Promise<ModelSelectionResult> {
|
|
101
111
|
const uokFlags = resolveUokFlags(prefs);
|
|
102
112
|
const effectiveSessionModelOverride = sessionModelOverride === undefined
|
|
@@ -380,11 +390,12 @@ export async function selectAndApplyModel(
|
|
|
380
390
|
const ok = await pi.setModel(model, { persist: false });
|
|
381
391
|
if (ok) {
|
|
382
392
|
appliedModel = model;
|
|
393
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
383
394
|
|
|
384
395
|
// ADR-005: Adjust active tool set for the selected model's provider capabilities.
|
|
385
396
|
// Hard-filter incompatible tools, then let extensions override via adjust_tool_set hook.
|
|
386
397
|
const activeToolNames = pi.getActiveTools();
|
|
387
|
-
const { toolNames: compatibleTools, removedTools } = adjustToolSet(activeToolNames, model.api);
|
|
398
|
+
const { toolNames: compatibleTools, removedTools } = adjustToolSet(activeToolNames, model.api, model.provider);
|
|
388
399
|
let finalToolNames = compatibleTools;
|
|
389
400
|
|
|
390
401
|
// Fire adjust_tool_set hook — extensions can override the filtered tool set
|
|
@@ -456,10 +467,14 @@ export async function selectAndApplyModel(
|
|
|
456
467
|
);
|
|
457
468
|
if (byId) {
|
|
458
469
|
const fallbackOk = await pi.setModel(byId, { persist: false });
|
|
459
|
-
if (fallbackOk)
|
|
470
|
+
if (fallbackOk) {
|
|
471
|
+
appliedModel = byId;
|
|
472
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
473
|
+
}
|
|
460
474
|
}
|
|
461
475
|
} else {
|
|
462
476
|
appliedModel = startModel;
|
|
477
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
463
478
|
}
|
|
464
479
|
}
|
|
465
480
|
}
|
|
@@ -55,7 +55,7 @@ import { hasPendingCaptures, loadPendingCaptures, revertExecutorResolvedCaptures
|
|
|
55
55
|
import { debugLog } from "./debug-logger.js";
|
|
56
56
|
import { runSafely } from "./auto-utils.js";
|
|
57
57
|
import type { AutoSession, SidecarItem } from "./auto/session.js";
|
|
58
|
-
import { getEvidence } from "./safety/evidence-collector.js";
|
|
58
|
+
import { getEvidence, clearEvidenceFromDisk } from "./safety/evidence-collector.js";
|
|
59
59
|
import { validateFileChanges } from "./safety/file-change-validator.js";
|
|
60
60
|
// crossReferenceEvidence available for future use when verification_evidence is stored in DB
|
|
61
61
|
// import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
|
|
@@ -107,7 +107,6 @@ import {
|
|
|
107
107
|
updateProgressWidget as _updateProgressWidget,
|
|
108
108
|
updateSliceProgressCache,
|
|
109
109
|
unitVerb,
|
|
110
|
-
hideFooter,
|
|
111
110
|
describeNextUnit,
|
|
112
111
|
} from "./auto-dashboard.js";
|
|
113
112
|
import { existsSync, unlinkSync } from "node:fs";
|
|
@@ -654,7 +653,7 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
654
653
|
if (taskRow) {
|
|
655
654
|
const expectedOutput = taskRow.expected_output ?? [];
|
|
656
655
|
const plannedFiles = taskRow.files ?? [];
|
|
657
|
-
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles);
|
|
656
|
+
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, safetyConfig.file_change_allowlist);
|
|
658
657
|
if (audit && audit.violations.length > 0) {
|
|
659
658
|
const warnings = audit.violations.filter(v => v.severity === "warning");
|
|
660
659
|
for (const v of warnings) {
|
|
@@ -712,6 +711,16 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
712
711
|
debugLog("postUnit", { phase: "safety-content-validation", error: String(e) });
|
|
713
712
|
}
|
|
714
713
|
}
|
|
714
|
+
|
|
715
|
+
// Clear persisted evidence file now that post-unit processing is complete
|
|
716
|
+
// (Bug #4385 — prevents stale evidence from affecting retries of same unit ID).
|
|
717
|
+
if (safetyConfig.evidence_collection && s.currentUnit.type === "execute-task" && sMid && sSid && sTid) {
|
|
718
|
+
try {
|
|
719
|
+
clearEvidenceFromDisk(s.basePath, sMid, sSid, sTid);
|
|
720
|
+
} catch (e) {
|
|
721
|
+
debugLog("postUnit", { phase: "safety-evidence-clear", error: String(e) });
|
|
722
|
+
}
|
|
723
|
+
}
|
|
715
724
|
}
|
|
716
725
|
} catch (e) {
|
|
717
726
|
debugLog("postUnit", { phase: "safety-harness", error: String(e) });
|
|
@@ -1134,6 +1143,15 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
1134
1143
|
`Pre-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found\n${details}${suffix}${evidenceNote}`,
|
|
1135
1144
|
"error",
|
|
1136
1145
|
);
|
|
1146
|
+
// Persist failure context so the next plan-slice re-dispatch can inject
|
|
1147
|
+
// it into the prompt and break the infinite loop (#4551).
|
|
1148
|
+
s.lastPreExecFailure = {
|
|
1149
|
+
unitId: currentUnit.id,
|
|
1150
|
+
blockingFindings: blockingChecks.map(
|
|
1151
|
+
c => `[${c.category}] ${c.target}: ${c.message}`,
|
|
1152
|
+
),
|
|
1153
|
+
verdictExcerpt: `status=${result.status}; ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} detected`,
|
|
1154
|
+
};
|
|
1137
1155
|
preExecPauseNeeded = true;
|
|
1138
1156
|
} else if (result.status === "warn") {
|
|
1139
1157
|
ctx.ui.notify(
|
|
@@ -1142,6 +1160,14 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
1142
1160
|
);
|
|
1143
1161
|
// Strict mode: treat warnings as blocking
|
|
1144
1162
|
if (prefs?.enhanced_verification_strict === true) {
|
|
1163
|
+
const warnChecks = result.checks.filter(c => !c.passed);
|
|
1164
|
+
s.lastPreExecFailure = {
|
|
1165
|
+
unitId: currentUnit.id,
|
|
1166
|
+
blockingFindings: warnChecks.map(
|
|
1167
|
+
c => `[${c.category}] ${c.target}: ${c.message}`,
|
|
1168
|
+
),
|
|
1169
|
+
verdictExcerpt: `status=${result.status} (strict mode); ${warnChecks.length} warning${warnChecks.length === 1 ? "" : "s"} treated as blocking`,
|
|
1170
|
+
};
|
|
1145
1171
|
preExecPauseNeeded = true;
|
|
1146
1172
|
}
|
|
1147
1173
|
}
|
|
@@ -1380,7 +1380,18 @@ async function renderSlicePrompt(options: {
|
|
|
1380
1380
|
|
|
1381
1381
|
export async function buildPlanSlicePrompt(
|
|
1382
1382
|
mid: string, _midTitle: string, sid: string, sTitle: string, base: string, level?: InlineLevel,
|
|
1383
|
-
options?: {
|
|
1383
|
+
options?: {
|
|
1384
|
+
softScopeHint?: string;
|
|
1385
|
+
sessionContextWindow?: number;
|
|
1386
|
+
modelRegistry?: MinimalModelRegistry;
|
|
1387
|
+
/** Failure context from a prior pre-exec gate run (#4551). When present, a
|
|
1388
|
+
* "Fix these specific issues" section is appended so the LLM addresses the
|
|
1389
|
+
* exact problems instead of producing an identical plan that fails again. */
|
|
1390
|
+
priorPreExecFailure?: {
|
|
1391
|
+
blockingFindings: string[];
|
|
1392
|
+
verdictExcerpt: string;
|
|
1393
|
+
};
|
|
1394
|
+
},
|
|
1384
1395
|
): Promise<string> {
|
|
1385
1396
|
const prependBlocks: string[] = [];
|
|
1386
1397
|
// ADR-011: when the refining-phase dispatch rule gracefully downgrades to
|
|
@@ -1393,6 +1404,22 @@ export async function buildPlanSlicePrompt(
|
|
|
1393
1404
|
`This scope was captured during an earlier progressive-planning pass that was later disabled. Treat it as context only — you may plan beyond it if the work genuinely requires more scope. Do NOT treat this as a hard boundary.`,
|
|
1394
1405
|
);
|
|
1395
1406
|
}
|
|
1407
|
+
// #4551: inject pre-exec failure context so the re-dispatched plan-slice
|
|
1408
|
+
// addresses the exact blocked references rather than reproducing the same plan.
|
|
1409
|
+
if (options?.priorPreExecFailure) {
|
|
1410
|
+
const { blockingFindings, verdictExcerpt } = options.priorPreExecFailure;
|
|
1411
|
+
const findingsList = blockingFindings.length > 0
|
|
1412
|
+
? blockingFindings.map(f => `- ${f}`).join("\n")
|
|
1413
|
+
: "- (no specific findings recorded)";
|
|
1414
|
+
prependBlocks.push(
|
|
1415
|
+
`## Fix these specific issues from the prior pre-exec check\n\n` +
|
|
1416
|
+
`The previous plan-slice attempt was blocked by pre-execution validation.\n` +
|
|
1417
|
+
`Gate verdict: ${verdictExcerpt}\n\n` +
|
|
1418
|
+
`Blocked references that must be resolved in this plan:\n${findingsList}\n\n` +
|
|
1419
|
+
`Revise the plan so that every reference listed above is satisfied before execution begins. ` +
|
|
1420
|
+
`Do not reproduce the same file paths, package names, or task ordering that caused these failures.`,
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1396
1423
|
return renderSlicePrompt({
|
|
1397
1424
|
mid, sid, sTitle, base,
|
|
1398
1425
|
level: level ?? resolveInlineLevel(),
|
|
@@ -13,7 +13,7 @@ import { appendEvent } from "./workflow-events.js";
|
|
|
13
13
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
14
14
|
import { clearParseCache } from "./files.js";
|
|
15
15
|
import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
|
|
16
|
-
import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGates, updateTaskStatus, updateSliceStatus } from "./gsd-db.js";
|
|
16
|
+
import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGates, updateTaskStatus, updateSliceStatus, insertSlice } from "./gsd-db.js";
|
|
17
17
|
import { isValidationTerminal } from "./state.js";
|
|
18
18
|
import { getErrorMessage } from "./error-utils.js";
|
|
19
19
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
@@ -268,11 +268,26 @@ export function verifyExpectedArtifact(
|
|
|
268
268
|
// RESEARCH file. Without this, resolveExpectedArtifactPath returns null and
|
|
269
269
|
// the retry/escalation machinery silently re-dispatches forever.
|
|
270
270
|
//
|
|
271
|
+
// #4068: Also treat a PARALLEL-BLOCKER placeholder as a terminal completion
|
|
272
|
+
// so that timeout-recovery can write the blocker, have verifyExpectedArtifact
|
|
273
|
+
// return true, and let the dispatch loop advance past this unit. Without
|
|
274
|
+
// this, the blocker is written but verification still returns false, the unit
|
|
275
|
+
// is never cleared from unitDispatchCount, and on the next iteration the
|
|
276
|
+
// dispatch rule (which correctly skips parallel-research when PARALLEL-BLOCKER
|
|
277
|
+
// exists) returns null — leaving the loop stuck re-deriving indefinitely.
|
|
278
|
+
//
|
|
271
279
|
// NOTE: this predicate mirrors the dispatch rule at
|
|
272
280
|
// auto-dispatch.ts parallel-research-slices — keep the two in sync.
|
|
273
281
|
if (unitType === "research-slice" && unitId.endsWith("/parallel-research")) {
|
|
274
282
|
const { milestone: mid } = parseUnitId(unitId);
|
|
275
283
|
if (!mid) return false;
|
|
284
|
+
|
|
285
|
+
// #4068: PARALLEL-BLOCKER written by timeout-recovery is a terminal state.
|
|
286
|
+
const blockerPath = resolveExpectedArtifactPath(unitType, unitId, base);
|
|
287
|
+
if (blockerPath && existsSync(blockerPath)) {
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
|
|
276
291
|
const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
277
292
|
if (!roadmapFile || !existsSync(roadmapFile)) {
|
|
278
293
|
logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap missing`);
|
|
@@ -532,6 +547,16 @@ export function writeBlockerPlaceholder(
|
|
|
532
547
|
try { updateSliceStatus(mid, sid, "complete", ts); } catch (e) { logWarning("recovery", `updateSliceStatus failed during context exhaustion: ${e instanceof Error ? e.message : String(e)}`); }
|
|
533
548
|
try { appendEvent(base, { cmd: "complete-slice", params: { milestoneId: mid, sliceId: sid }, ts, actor: "system", trigger_reason: "blocker-placeholder-recovery" }); } catch (e) { logWarning("recovery", `appendEvent failed for slice recovery: ${e instanceof Error ? e.message : String(e)}`); }
|
|
534
549
|
}
|
|
550
|
+
// Insert a placeholder complete slice so deriveState sees activeMilestoneSlices.length > 0
|
|
551
|
+
// and exits the pre-planning phase. Without this, activeMilestoneSlices stays empty
|
|
552
|
+
// after the blocker ROADMAP.md is written, causing deriveState to return phase:'pre-planning'
|
|
553
|
+
// indefinitely and re-dispatching plan-milestone in an infinite loop (#4378).
|
|
554
|
+
if (unitType === "plan-milestone" && mid) {
|
|
555
|
+
try {
|
|
556
|
+
insertSlice({ id: "S00-blocker", milestoneId: mid, title: "Blocker placeholder — planning failed", status: "complete", sequence: 0 });
|
|
557
|
+
} catch (e) { logWarning("recovery", `insertSlice placeholder failed for plan-milestone recovery: ${e instanceof Error ? e.message : String(e)}`); }
|
|
558
|
+
try { appendEvent(base, { cmd: "plan-milestone", params: { milestoneId: mid }, ts, actor: "system", trigger_reason: "blocker-placeholder-recovery" }); } catch (e) { logWarning("recovery", `appendEvent failed for plan-milestone recovery: ${e instanceof Error ? e.message : String(e)}`); }
|
|
559
|
+
}
|
|
535
560
|
}
|
|
536
561
|
|
|
537
562
|
return diagnoseExpectedArtifact(unitType, unitId, base);
|
|
@@ -60,8 +60,8 @@ import { initRoutingHistory } from "./routing-history.js";
|
|
|
60
60
|
import { restoreHookState, resetHookState } from "./post-unit-hooks.js";
|
|
61
61
|
import { resetProactiveHealing, setLevelChangeCallback } from "./doctor-proactive.js";
|
|
62
62
|
import { snapshotSkills } from "./skill-discovery.js";
|
|
63
|
-
import { isDbAvailable, getMilestone, openDatabase } from "./gsd-db.js";
|
|
64
|
-
|
|
63
|
+
import { isDbAvailable, getMilestone, openDatabase, getDbStatus } from "./gsd-db.js";
|
|
64
|
+
|
|
65
65
|
import {
|
|
66
66
|
debugLog,
|
|
67
67
|
enableDebug,
|
|
@@ -92,7 +92,7 @@ import type { WorktreeResolver } from "./worktree-resolver.js";
|
|
|
92
92
|
import { getSessionModelOverride } from "./session-model-override.js";
|
|
93
93
|
|
|
94
94
|
export interface BootstrapDeps {
|
|
95
|
-
shouldUseWorktreeIsolation: () => boolean;
|
|
95
|
+
shouldUseWorktreeIsolation: (basePath?: string) => boolean;
|
|
96
96
|
registerSigtermHandler: (basePath: string) => void;
|
|
97
97
|
lockBase: () => string;
|
|
98
98
|
buildResolver: () => WorktreeResolver;
|
|
@@ -273,8 +273,8 @@ export async function bootstrapAutoSession(
|
|
|
273
273
|
//
|
|
274
274
|
// Precedence:
|
|
275
275
|
// 1) Explicit session override via /gsd model (this session)
|
|
276
|
-
// 2)
|
|
277
|
-
// 3)
|
|
276
|
+
// 2) Current session model from settings/session restore (if provider ready)
|
|
277
|
+
// 3) GSD model preferences from PREFERENCES.md (validated against live auth)
|
|
278
278
|
//
|
|
279
279
|
// This preserves #3517 defaults while honoring explicit runtime model
|
|
280
280
|
// selection for subsequent /gsd runs in the same session.
|
|
@@ -314,11 +314,14 @@ export async function bootstrapAutoSession(
|
|
|
314
314
|
}
|
|
315
315
|
const sessionModelReady =
|
|
316
316
|
ctx.model && ctx.modelRegistry.isProviderRequestReady(ctx.model.provider);
|
|
317
|
+
const currentSessionModel = (sessionModelReady && ctx.model)
|
|
318
|
+
? { provider: ctx.model.provider, id: ctx.model.id }
|
|
319
|
+
: null;
|
|
320
|
+
const startThinkingSnapshot = pi.getThinkingLevel();
|
|
317
321
|
const startModelSnapshot = manualSessionOverride
|
|
322
|
+
?? currentSessionModel
|
|
318
323
|
?? validatedPreferredModel
|
|
319
|
-
??
|
|
320
|
-
? { provider: ctx.model.provider, id: ctx.model.id }
|
|
321
|
-
: null);
|
|
324
|
+
?? null;
|
|
322
325
|
|
|
323
326
|
try {
|
|
324
327
|
// Validate GSD_PROJECT_ID early so the user gets immediate feedback
|
|
@@ -340,7 +343,7 @@ export async function bootstrapAutoSession(
|
|
|
340
343
|
const hasLocalGit = existsSync(join(base, ".git"));
|
|
341
344
|
if (!hasLocalGit || isInheritedRepo(base)) {
|
|
342
345
|
const mainBranch =
|
|
343
|
-
loadEffectiveGSDPreferences()?.preferences?.git?.main_branch || "main";
|
|
346
|
+
loadEffectiveGSDPreferences(base)?.preferences?.git?.main_branch || "main";
|
|
344
347
|
nativeInit(base, mainBranch);
|
|
345
348
|
}
|
|
346
349
|
|
|
@@ -358,7 +361,7 @@ export async function bootstrapAutoSession(
|
|
|
358
361
|
// Ensure .gitignore has baseline patterns.
|
|
359
362
|
// ensureGitignore checks for git-tracked .gsd/ files and skips the
|
|
360
363
|
// ".gsd" pattern if the project intentionally tracks .gsd/ in git.
|
|
361
|
-
const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
364
|
+
const gitPrefs = loadEffectiveGSDPreferences(base)?.preferences?.git;
|
|
362
365
|
const manageGitignore = gitPrefs?.manage_gitignore;
|
|
363
366
|
ensureGitignore(base, { manageGitignore });
|
|
364
367
|
if (manageGitignore !== false) untrackRuntimeFiles(base);
|
|
@@ -387,7 +390,7 @@ export async function bootstrapAutoSession(
|
|
|
387
390
|
// Initialize GitServiceImpl
|
|
388
391
|
s.gitService = new GitServiceImpl(
|
|
389
392
|
s.basePath,
|
|
390
|
-
loadEffectiveGSDPreferences()?.preferences?.git ?? {},
|
|
393
|
+
loadEffectiveGSDPreferences(base)?.preferences?.git ?? {},
|
|
391
394
|
);
|
|
392
395
|
|
|
393
396
|
// ── Debug mode ──
|
|
@@ -431,7 +434,7 @@ export async function bootstrapAutoSession(
|
|
|
431
434
|
// was lost due to session ending between completion and teardown.
|
|
432
435
|
// Must run after DB open and before worktree entry.
|
|
433
436
|
try {
|
|
434
|
-
const auditResult = auditOrphanedMilestoneBranches(base, getIsolationMode());
|
|
437
|
+
const auditResult = auditOrphanedMilestoneBranches(base, getIsolationMode(base));
|
|
435
438
|
for (const msg of auditResult.recovered) {
|
|
436
439
|
ctx.ui.notify(`Orphan audit: ${msg}`, "info");
|
|
437
440
|
}
|
|
@@ -451,7 +454,7 @@ export async function bootstrapAutoSession(
|
|
|
451
454
|
// Stale worktree state recovery (#654)
|
|
452
455
|
if (
|
|
453
456
|
state.activeMilestone &&
|
|
454
|
-
shouldUseWorktreeIsolation() &&
|
|
457
|
+
shouldUseWorktreeIsolation(base) &&
|
|
455
458
|
!detectWorktreeName(base)
|
|
456
459
|
) {
|
|
457
460
|
const wtPath = getAutoWorktreePath(base, state.activeMilestone.id);
|
|
@@ -469,7 +472,7 @@ export async function bootstrapAutoSession(
|
|
|
469
472
|
if (
|
|
470
473
|
state.activeMilestone &&
|
|
471
474
|
(state.phase === "pre-planning" || state.phase === "complete") &&
|
|
472
|
-
getIsolationMode() !== "none" &&
|
|
475
|
+
getIsolationMode(base) !== "none" &&
|
|
473
476
|
!detectWorktreeName(base) &&
|
|
474
477
|
!base.includes(`${pathSep}.gsd${pathSep}worktrees${pathSep}`)
|
|
475
478
|
) {
|
|
@@ -550,37 +553,15 @@ export async function bootstrapAutoSession(
|
|
|
550
553
|
const { showSmartEntry } = await import("./guided-flow.js");
|
|
551
554
|
await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
|
|
552
555
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
} else if (
|
|
563
|
-
postState.activeMilestone &&
|
|
564
|
-
postState.phase === "pre-planning"
|
|
565
|
-
) {
|
|
566
|
-
const contextFile = resolveMilestoneFile(
|
|
567
|
-
base,
|
|
568
|
-
postState.activeMilestone.id,
|
|
569
|
-
"CONTEXT",
|
|
570
|
-
);
|
|
571
|
-
const hasContext = !!(contextFile && (await loadFile(contextFile)));
|
|
572
|
-
if (hasContext) {
|
|
573
|
-
state = postState;
|
|
574
|
-
} else {
|
|
575
|
-
ctx.ui.notify(
|
|
576
|
-
"Discussion completed but no milestone context was written. Run /gsd to try the discussion again, or /gsd auto after creating the milestone manually.",
|
|
577
|
-
"warning",
|
|
578
|
-
);
|
|
579
|
-
return releaseLockAndReturn();
|
|
580
|
-
}
|
|
581
|
-
} else {
|
|
582
|
-
return releaseLockAndReturn();
|
|
583
|
-
}
|
|
556
|
+
// showSmartEntry dispatches via pi.sendMessage() which is fire-and-forget:
|
|
557
|
+
// it queues the message and returns immediately, before the LLM turn runs.
|
|
558
|
+
// Checking postState here would always see the pre-dispatch state, causing
|
|
559
|
+
// the premature "Discussion completed but..." warning (#3420).
|
|
560
|
+
//
|
|
561
|
+
// checkAutoStartAfterDiscuss (in guided-flow.ts) already handles re-entering
|
|
562
|
+
// auto-mode by calling startAutoDetached after the discussion completes.
|
|
563
|
+
// Release the lock and let the async dispatch proceed.
|
|
564
|
+
return releaseLockAndReturn();
|
|
584
565
|
}
|
|
585
566
|
|
|
586
567
|
// Active milestone exists but has no roadmap
|
|
@@ -592,17 +573,16 @@ export async function bootstrapAutoSession(
|
|
|
592
573
|
const { showSmartEntry } = await import("./guided-flow.js");
|
|
593
574
|
await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
|
|
594
575
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
}
|
|
576
|
+
// showSmartEntry dispatches via pi.sendMessage() which is fire-and-forget:
|
|
577
|
+
// it queues the message and returns immediately, before the LLM turn runs.
|
|
578
|
+
// Checking postState here fires before the LLM has had a turn, so the
|
|
579
|
+
// pre-planning phase would still appear unchanged and a premature warning
|
|
580
|
+
// would be emitted (#3420).
|
|
581
|
+
//
|
|
582
|
+
// checkAutoStartAfterDiscuss (in guided-flow.ts) already handles re-entering
|
|
583
|
+
// auto-mode by calling startAutoDetached after the discussion completes.
|
|
584
|
+
// Release the lock and let the async dispatch proceed.
|
|
585
|
+
return releaseLockAndReturn();
|
|
606
586
|
}
|
|
607
587
|
}
|
|
608
588
|
|
|
@@ -664,15 +644,16 @@ export async function bootstrapAutoSession(
|
|
|
664
644
|
s.pendingQuickTasks = [];
|
|
665
645
|
s.currentUnit = null;
|
|
666
646
|
s.currentMilestoneId = state.activeMilestone?.id ?? null;
|
|
667
|
-
s.originalModelId = ctx.model?.id ?? null;
|
|
668
|
-
s.originalModelProvider = ctx.model?.provider ?? null;
|
|
647
|
+
s.originalModelId = startModelSnapshot?.id ?? ctx.model?.id ?? null;
|
|
648
|
+
s.originalModelProvider = startModelSnapshot?.provider ?? ctx.model?.provider ?? null;
|
|
649
|
+
s.originalThinkingLevel = startThinkingSnapshot ?? null;
|
|
669
650
|
|
|
670
651
|
// Register SIGTERM handler
|
|
671
652
|
registerSigtermHandler(base);
|
|
672
653
|
|
|
673
654
|
// Capture integration branch
|
|
674
655
|
if (s.currentMilestoneId) {
|
|
675
|
-
if (getIsolationMode() !== "none") {
|
|
656
|
+
if (getIsolationMode(base) !== "none") {
|
|
676
657
|
captureIntegrationBranch(base, s.currentMilestoneId);
|
|
677
658
|
}
|
|
678
659
|
setActiveMilestoneId(base, s.currentMilestoneId);
|
|
@@ -681,7 +662,7 @@ export async function bootstrapAutoSession(
|
|
|
681
662
|
// Guard against stale milestone branch when isolation:none (#3613).
|
|
682
663
|
// A prior session with isolation:branch/worktree may have left HEAD on
|
|
683
664
|
// milestone/<MID>. Auto-checkout back to the integration branch.
|
|
684
|
-
if (getIsolationMode() === "none" && nativeIsRepo(base)) {
|
|
665
|
+
if (getIsolationMode(base) === "none" && nativeIsRepo(base)) {
|
|
685
666
|
try {
|
|
686
667
|
const currentBranch = nativeGetCurrentBranch(base);
|
|
687
668
|
if (currentBranch.startsWith("milestone/")) {
|
|
@@ -712,7 +693,7 @@ export async function bootstrapAutoSession(
|
|
|
712
693
|
|
|
713
694
|
if (
|
|
714
695
|
s.currentMilestoneId &&
|
|
715
|
-
getIsolationMode() !== "none" &&
|
|
696
|
+
getIsolationMode(base) !== "none" &&
|
|
716
697
|
!detectWorktreeName(base) &&
|
|
717
698
|
!isUnderGsdWorktrees(base)
|
|
718
699
|
) {
|
|
@@ -758,9 +739,22 @@ export async function bootstrapAutoSession(
|
|
|
758
739
|
// call returns "db_unavailable", triggering artifact-retry which
|
|
759
740
|
// re-dispatches the same task — producing an infinite loop (#2419).
|
|
760
741
|
if (existsSync(gsdDbPath) && !isDbAvailable()) {
|
|
742
|
+
const dbStatus = getDbStatus();
|
|
743
|
+
const phaseHint = dbStatus.lastPhase === "open"
|
|
744
|
+
? "The database file could not be opened"
|
|
745
|
+
: dbStatus.lastPhase === "initSchema"
|
|
746
|
+
? "The database schema could not be initialized"
|
|
747
|
+
: dbStatus.lastPhase === "vacuum-recovery"
|
|
748
|
+
? "Corruption recovery (VACUUM) failed"
|
|
749
|
+
: dbStatus.attempted
|
|
750
|
+
? "The database could not be opened (phase unknown)"
|
|
751
|
+
: "The database provider could not be loaded";
|
|
752
|
+
const errorDetail = dbStatus.lastError ? ` (${dbStatus.lastError.message})` : "";
|
|
753
|
+
const providerHint = dbStatus.provider
|
|
754
|
+
? ` Provider: ${dbStatus.provider}.`
|
|
755
|
+
: " No SQLite provider available — check Node >= 22 or install better-sqlite3.";
|
|
761
756
|
ctx.ui.notify(
|
|
762
|
-
|
|
763
|
-
"Check for corrupt gsd.db or missing native SQLite bindings.",
|
|
757
|
+
`SQLite database exists but failed to open: ${gsdDbPath}. ${phaseHint}${errorDetail}.${providerHint}`,
|
|
764
758
|
"error",
|
|
765
759
|
);
|
|
766
760
|
return releaseLockAndReturn();
|
|
@@ -779,6 +773,7 @@ export async function bootstrapAutoSession(
|
|
|
779
773
|
id: startModelSnapshot.id,
|
|
780
774
|
};
|
|
781
775
|
}
|
|
776
|
+
s.autoModeStartThinkingLevel = startThinkingSnapshot ?? null;
|
|
782
777
|
s.manualSessionModelOverride = manualSessionOverride ?? null;
|
|
783
778
|
|
|
784
779
|
// Apply worker model override from parallel orchestrator (#worker-model).
|
|
@@ -801,14 +796,11 @@ export async function bootstrapAutoSession(
|
|
|
801
796
|
}
|
|
802
797
|
|
|
803
798
|
// Snapshot installed skills
|
|
804
|
-
if (resolveSkillDiscoveryMode() !== "off") {
|
|
799
|
+
if (resolveSkillDiscoveryMode(base) !== "off") {
|
|
805
800
|
snapshotSkills();
|
|
806
801
|
}
|
|
807
802
|
|
|
808
803
|
ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
|
|
809
|
-
ctx.ui.setFooter(hideFooter);
|
|
810
|
-
// Hide gsd-health during AUTO — gsd-progress is the single source of truth
|
|
811
|
-
// for last-commit / cost / health signal while auto is running.
|
|
812
804
|
ctx.ui.setWidget("gsd-health", undefined);
|
|
813
805
|
const modeLabel = s.stepMode ? "Step-mode" : "Auto-mode";
|
|
814
806
|
const pendingCount = (state.registry ?? []).filter(
|
|
@@ -835,7 +827,7 @@ export async function bootstrapAutoSession(
|
|
|
835
827
|
// FlatRateContext used by selectAndApplyModel so user-declared
|
|
836
828
|
// flat-rate providers and externalCli auto-detection are respected.
|
|
837
829
|
const { isFlatRateProvider, buildFlatRateContext } = await import("./auto-model-selection.js");
|
|
838
|
-
const bannerPrefs = loadEffectiveGSDPreferences()?.preferences;
|
|
830
|
+
const bannerPrefs = loadEffectiveGSDPreferences(base)?.preferences;
|
|
839
831
|
const effectiveProvider = s.autoModeStartModel?.provider ?? ctx.model?.provider;
|
|
840
832
|
const effectivelyEnabled = routingConfig.enabled
|
|
841
833
|
&& (routingConfig.allow_flat_rate_providers
|