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
|
@@ -65,6 +65,8 @@ export class AutoSession {
|
|
|
65
65
|
currentDispatchedModelId = null;
|
|
66
66
|
originalModelId = null;
|
|
67
67
|
originalModelProvider = null;
|
|
68
|
+
autoModeStartThinkingLevel = null;
|
|
69
|
+
originalThinkingLevel = null;
|
|
68
70
|
lastBudgetAlertLevel = 0;
|
|
69
71
|
// ── Recovery ─────────────────────────────────────────────────────────────
|
|
70
72
|
pendingCrashRecovery = null;
|
|
@@ -77,6 +79,17 @@ export class AutoSession {
|
|
|
77
79
|
lastStateRebuildAt = 0;
|
|
78
80
|
// ── Sidecar queue ─────────────────────────────────────────────────────
|
|
79
81
|
sidecarQueue = [];
|
|
82
|
+
// ── Pre-exec gate failure context (#4551) ───────────────────────────
|
|
83
|
+
/**
|
|
84
|
+
* Persisted when a pre-execution gate fails on a plan-slice or refine-slice
|
|
85
|
+
* unit. The planning → plan-slice dispatch rule reads this field and injects
|
|
86
|
+
* the failure details into the next re-dispatch prompt so the LLM can fix the
|
|
87
|
+
* specific issues instead of producing an identical plan.
|
|
88
|
+
*
|
|
89
|
+
* Cleared after it has been consumed (injected into the prompt) to avoid
|
|
90
|
+
* stale context bleeding into unrelated slices.
|
|
91
|
+
*/
|
|
92
|
+
lastPreExecFailure = null;
|
|
80
93
|
// ── Tool invocation errors (#2883) ──────────────────────────────────
|
|
81
94
|
/** Set when a GSD tool execution ends with isError due to malformed/truncated
|
|
82
95
|
* JSON arguments. Checked by postUnitPreVerification to break retry loops. */
|
|
@@ -137,7 +150,12 @@ export class AutoSession {
|
|
|
137
150
|
this.unitLifetimeDispatches.clear();
|
|
138
151
|
}
|
|
139
152
|
get lockBasePath() {
|
|
140
|
-
|
|
153
|
+
// Prefer originalBasePath (project root); fall back to basePath.
|
|
154
|
+
// Strip /.gsd/worktrees/ suffix if basePath is itself a worktree path
|
|
155
|
+
// to avoid reading/writing the lock inside the worktree (#3729).
|
|
156
|
+
const resolved = this.originalBasePath || this.basePath;
|
|
157
|
+
const markerIdx = resolved.indexOf("/.gsd/worktrees/");
|
|
158
|
+
return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
|
|
141
159
|
}
|
|
142
160
|
reset() {
|
|
143
161
|
this.clearTimers();
|
|
@@ -177,6 +195,8 @@ export class AutoSession {
|
|
|
177
195
|
this.currentDispatchedModelId = null;
|
|
178
196
|
this.originalModelId = null;
|
|
179
197
|
this.originalModelProvider = null;
|
|
198
|
+
this.autoModeStartThinkingLevel = null;
|
|
199
|
+
this.originalThinkingLevel = null;
|
|
180
200
|
this.lastBudgetAlertLevel = 0;
|
|
181
201
|
// Recovery
|
|
182
202
|
this.pendingCrashRecovery = null;
|
|
@@ -195,6 +215,7 @@ export class AutoSession {
|
|
|
195
215
|
this.sidecarQueue = [];
|
|
196
216
|
this.rewriteAttemptCount = 0;
|
|
197
217
|
this.consecutiveCompleteBootstraps = 0;
|
|
218
|
+
this.lastPreExecFailure = null;
|
|
198
219
|
this.lastToolInvocationError = null;
|
|
199
220
|
this.lastGitActionFailure = null;
|
|
200
221
|
this.lastGitActionStatus = null;
|
|
@@ -451,18 +451,31 @@ export const DISPATCH_RULES = [
|
|
|
451
451
|
},
|
|
452
452
|
{
|
|
453
453
|
name: "planning → plan-slice",
|
|
454
|
-
match: async ({ state, mid, midTitle, basePath, sessionContextWindow, modelRegistry }) => {
|
|
454
|
+
match: async ({ state, mid, midTitle, basePath, sessionContextWindow, modelRegistry, session }) => {
|
|
455
455
|
if (state.phase !== "planning")
|
|
456
456
|
return null;
|
|
457
457
|
if (!state.activeSlice)
|
|
458
458
|
return missingSliceStop(mid, state.phase);
|
|
459
459
|
const sid = state.activeSlice.id;
|
|
460
460
|
const sTitle = state.activeSlice.title;
|
|
461
|
+
// #4551: Consume any persisted pre-exec failure for this slice so the
|
|
462
|
+
// re-dispatched prompt includes the exact blocked references. Clear the
|
|
463
|
+
// field immediately after reading to prevent stale context leaking into
|
|
464
|
+
// a later, unrelated plan-slice run.
|
|
465
|
+
const unitId = `${mid}/${sid}`;
|
|
466
|
+
let priorPreExecFailure;
|
|
467
|
+
if (session?.lastPreExecFailure?.unitId === unitId) {
|
|
468
|
+
priorPreExecFailure = {
|
|
469
|
+
blockingFindings: session.lastPreExecFailure.blockingFindings,
|
|
470
|
+
verdictExcerpt: session.lastPreExecFailure.verdictExcerpt,
|
|
471
|
+
};
|
|
472
|
+
session.lastPreExecFailure = null;
|
|
473
|
+
}
|
|
461
474
|
return {
|
|
462
475
|
action: "dispatch",
|
|
463
476
|
unitType: "plan-slice",
|
|
464
|
-
unitId
|
|
465
|
-
prompt: await buildPlanSlicePrompt(mid, midTitle, sid, sTitle, basePath, undefined, { sessionContextWindow, modelRegistry }),
|
|
477
|
+
unitId,
|
|
478
|
+
prompt: await buildPlanSlicePrompt(mid, midTitle, sid, sTitle, basePath, undefined, { sessionContextWindow, modelRegistry, priorPreExecFailure }),
|
|
466
479
|
};
|
|
467
480
|
},
|
|
468
481
|
},
|
|
@@ -13,6 +13,11 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
13
13
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
14
14
|
import { applyModelPolicyFilter } from "./uok/model-policy.js";
|
|
15
15
|
import { isModelBlocked } from "./blocked-models.js";
|
|
16
|
+
function reapplyThinkingLevel(pi, level) {
|
|
17
|
+
if (!level)
|
|
18
|
+
return;
|
|
19
|
+
pi.setThinkingLevel(level);
|
|
20
|
+
}
|
|
16
21
|
export function resolvePreferredModelConfig(unitType, autoModeStartModel, isAutoMode = true) {
|
|
17
22
|
const explicitConfig = resolveModelWithFallbacksForUnit(unitType);
|
|
18
23
|
if (explicitConfig) {
|
|
@@ -58,7 +63,9 @@ export async function selectAndApplyModel(ctx, pi, unitType, unitId, basePath, p
|
|
|
58
63
|
* Dynamic routing only applies in auto-mode where cost optimization is expected. (#3962) */
|
|
59
64
|
isAutoMode = true,
|
|
60
65
|
/** Explicit /gsd model pin captured at bootstrap for long-running auto loops. */
|
|
61
|
-
sessionModelOverride
|
|
66
|
+
sessionModelOverride,
|
|
67
|
+
/** Thinking level captured at auto-mode start and re-applied after model swaps. */
|
|
68
|
+
autoModeStartThinkingLevel) {
|
|
62
69
|
const uokFlags = resolveUokFlags(prefs);
|
|
63
70
|
const effectiveSessionModelOverride = sessionModelOverride === undefined
|
|
64
71
|
? getSessionModelOverride(ctx.sessionManager.getSessionId())
|
|
@@ -280,10 +287,11 @@ sessionModelOverride) {
|
|
|
280
287
|
const ok = await pi.setModel(model, { persist: false });
|
|
281
288
|
if (ok) {
|
|
282
289
|
appliedModel = model;
|
|
290
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
283
291
|
// ADR-005: Adjust active tool set for the selected model's provider capabilities.
|
|
284
292
|
// Hard-filter incompatible tools, then let extensions override via adjust_tool_set hook.
|
|
285
293
|
const activeToolNames = pi.getActiveTools();
|
|
286
|
-
const { toolNames: compatibleTools, removedTools } = adjustToolSet(activeToolNames, model.api);
|
|
294
|
+
const { toolNames: compatibleTools, removedTools } = adjustToolSet(activeToolNames, model.api, model.provider);
|
|
287
295
|
let finalToolNames = compatibleTools;
|
|
288
296
|
// Fire adjust_tool_set hook — extensions can override the filtered tool set
|
|
289
297
|
if (routingConfig.hooks !== false) {
|
|
@@ -346,12 +354,15 @@ sessionModelOverride) {
|
|
|
346
354
|
const byId = availableModels.find(m => m.id === autoModeStartModel.id && !isModelBlocked(basePath, m.provider, m.id));
|
|
347
355
|
if (byId) {
|
|
348
356
|
const fallbackOk = await pi.setModel(byId, { persist: false });
|
|
349
|
-
if (fallbackOk)
|
|
357
|
+
if (fallbackOk) {
|
|
350
358
|
appliedModel = byId;
|
|
359
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
360
|
+
}
|
|
351
361
|
}
|
|
352
362
|
}
|
|
353
363
|
else {
|
|
354
364
|
appliedModel = startModel;
|
|
365
|
+
reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
|
|
355
366
|
}
|
|
356
367
|
}
|
|
357
368
|
}
|
|
@@ -30,7 +30,7 @@ import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookSta
|
|
|
30
30
|
import { hasPendingCaptures, loadPendingCaptures, revertExecutorResolvedCaptures } from "./captures.js";
|
|
31
31
|
import { debugLog } from "./debug-logger.js";
|
|
32
32
|
import { runSafely } from "./auto-utils.js";
|
|
33
|
-
import { getEvidence } from "./safety/evidence-collector.js";
|
|
33
|
+
import { getEvidence, clearEvidenceFromDisk } from "./safety/evidence-collector.js";
|
|
34
34
|
import { validateFileChanges } from "./safety/file-change-validator.js";
|
|
35
35
|
// crossReferenceEvidence available for future use when verification_evidence is stored in DB
|
|
36
36
|
// import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
|
|
@@ -535,7 +535,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
535
535
|
if (taskRow) {
|
|
536
536
|
const expectedOutput = taskRow.expected_output ?? [];
|
|
537
537
|
const plannedFiles = taskRow.files ?? [];
|
|
538
|
-
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles);
|
|
538
|
+
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, safetyConfig.file_change_allowlist);
|
|
539
539
|
if (audit && audit.violations.length > 0) {
|
|
540
540
|
const warnings = audit.violations.filter(v => v.severity === "warning");
|
|
541
541
|
for (const v of warnings) {
|
|
@@ -588,6 +588,16 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
588
588
|
debugLog("postUnit", { phase: "safety-content-validation", error: String(e) });
|
|
589
589
|
}
|
|
590
590
|
}
|
|
591
|
+
// Clear persisted evidence file now that post-unit processing is complete
|
|
592
|
+
// (Bug #4385 — prevents stale evidence from affecting retries of same unit ID).
|
|
593
|
+
if (safetyConfig.evidence_collection && s.currentUnit.type === "execute-task" && sMid && sSid && sTid) {
|
|
594
|
+
try {
|
|
595
|
+
clearEvidenceFromDisk(s.basePath, sMid, sSid, sTid);
|
|
596
|
+
}
|
|
597
|
+
catch (e) {
|
|
598
|
+
debugLog("postUnit", { phase: "safety-evidence-clear", error: String(e) });
|
|
599
|
+
}
|
|
600
|
+
}
|
|
591
601
|
}
|
|
592
602
|
}
|
|
593
603
|
catch (e) {
|
|
@@ -950,12 +960,25 @@ export async function postUnitPostVerification(pctx) {
|
|
|
950
960
|
const suffix = blockingChecks.length > 3 ? `\n \u2022 ...and ${blockingChecks.length - 3} more` : "";
|
|
951
961
|
const evidenceNote = `\nSee ${sid}-PRE-EXEC-VERIFY.json for full details.`;
|
|
952
962
|
ctx.ui.notify(`Pre-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found\n${details}${suffix}${evidenceNote}`, "error");
|
|
963
|
+
// Persist failure context so the next plan-slice re-dispatch can inject
|
|
964
|
+
// it into the prompt and break the infinite loop (#4551).
|
|
965
|
+
s.lastPreExecFailure = {
|
|
966
|
+
unitId: currentUnit.id,
|
|
967
|
+
blockingFindings: blockingChecks.map(c => `[${c.category}] ${c.target}: ${c.message}`),
|
|
968
|
+
verdictExcerpt: `status=${result.status}; ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} detected`,
|
|
969
|
+
};
|
|
953
970
|
preExecPauseNeeded = true;
|
|
954
971
|
}
|
|
955
972
|
else if (result.status === "warn") {
|
|
956
973
|
ctx.ui.notify(`Pre-execution checks passed with warnings`, "warning");
|
|
957
974
|
// Strict mode: treat warnings as blocking
|
|
958
975
|
if (prefs?.enhanced_verification_strict === true) {
|
|
976
|
+
const warnChecks = result.checks.filter(c => !c.passed);
|
|
977
|
+
s.lastPreExecFailure = {
|
|
978
|
+
unitId: currentUnit.id,
|
|
979
|
+
blockingFindings: warnChecks.map(c => `[${c.category}] ${c.target}: ${c.message}`),
|
|
980
|
+
verdictExcerpt: `status=${result.status} (strict mode); ${warnChecks.length} warning${warnChecks.length === 1 ? "" : "s"} treated as blocking`,
|
|
981
|
+
};
|
|
959
982
|
preExecPauseNeeded = true;
|
|
960
983
|
}
|
|
961
984
|
}
|
|
@@ -1223,6 +1223,20 @@ export async function buildPlanSlicePrompt(mid, _midTitle, sid, sTitle, base, le
|
|
|
1223
1223
|
prependBlocks.push(`## Prior Sketch Scope (soft hint — non-binding)\n\n${options.softScopeHint.trim()}\n\n` +
|
|
1224
1224
|
`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.`);
|
|
1225
1225
|
}
|
|
1226
|
+
// #4551: inject pre-exec failure context so the re-dispatched plan-slice
|
|
1227
|
+
// addresses the exact blocked references rather than reproducing the same plan.
|
|
1228
|
+
if (options?.priorPreExecFailure) {
|
|
1229
|
+
const { blockingFindings, verdictExcerpt } = options.priorPreExecFailure;
|
|
1230
|
+
const findingsList = blockingFindings.length > 0
|
|
1231
|
+
? blockingFindings.map(f => `- ${f}`).join("\n")
|
|
1232
|
+
: "- (no specific findings recorded)";
|
|
1233
|
+
prependBlocks.push(`## Fix these specific issues from the prior pre-exec check\n\n` +
|
|
1234
|
+
`The previous plan-slice attempt was blocked by pre-execution validation.\n` +
|
|
1235
|
+
`Gate verdict: ${verdictExcerpt}\n\n` +
|
|
1236
|
+
`Blocked references that must be resolved in this plan:\n${findingsList}\n\n` +
|
|
1237
|
+
`Revise the plan so that every reference listed above is satisfied before execution begins. ` +
|
|
1238
|
+
`Do not reproduce the same file paths, package names, or task ordering that caused these failures.`);
|
|
1239
|
+
}
|
|
1226
1240
|
return renderSlicePrompt({
|
|
1227
1241
|
mid, sid, sTitle, base,
|
|
1228
1242
|
level: level ?? resolveInlineLevel(),
|
|
@@ -11,7 +11,7 @@ import { appendEvent } from "./workflow-events.js";
|
|
|
11
11
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
12
12
|
import { clearParseCache } from "./files.js";
|
|
13
13
|
import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
|
|
14
|
-
import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGates, updateTaskStatus, updateSliceStatus } from "./gsd-db.js";
|
|
14
|
+
import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGates, updateTaskStatus, updateSliceStatus, insertSlice } from "./gsd-db.js";
|
|
15
15
|
import { isValidationTerminal } from "./state.js";
|
|
16
16
|
import { getErrorMessage } from "./error-utils.js";
|
|
17
17
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
@@ -220,12 +220,25 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
220
220
|
// RESEARCH file. Without this, resolveExpectedArtifactPath returns null and
|
|
221
221
|
// the retry/escalation machinery silently re-dispatches forever.
|
|
222
222
|
//
|
|
223
|
+
// #4068: Also treat a PARALLEL-BLOCKER placeholder as a terminal completion
|
|
224
|
+
// so that timeout-recovery can write the blocker, have verifyExpectedArtifact
|
|
225
|
+
// return true, and let the dispatch loop advance past this unit. Without
|
|
226
|
+
// this, the blocker is written but verification still returns false, the unit
|
|
227
|
+
// is never cleared from unitDispatchCount, and on the next iteration the
|
|
228
|
+
// dispatch rule (which correctly skips parallel-research when PARALLEL-BLOCKER
|
|
229
|
+
// exists) returns null — leaving the loop stuck re-deriving indefinitely.
|
|
230
|
+
//
|
|
223
231
|
// NOTE: this predicate mirrors the dispatch rule at
|
|
224
232
|
// auto-dispatch.ts parallel-research-slices — keep the two in sync.
|
|
225
233
|
if (unitType === "research-slice" && unitId.endsWith("/parallel-research")) {
|
|
226
234
|
const { milestone: mid } = parseUnitId(unitId);
|
|
227
235
|
if (!mid)
|
|
228
236
|
return false;
|
|
237
|
+
// #4068: PARALLEL-BLOCKER written by timeout-recovery is a terminal state.
|
|
238
|
+
const blockerPath = resolveExpectedArtifactPath(unitType, unitId, base);
|
|
239
|
+
if (blockerPath && existsSync(blockerPath)) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
229
242
|
const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
230
243
|
if (!roadmapFile || !existsSync(roadmapFile)) {
|
|
231
244
|
logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap missing`);
|
|
@@ -497,6 +510,24 @@ export function writeBlockerPlaceholder(unitType, unitId, base, reason) {
|
|
|
497
510
|
logWarning("recovery", `appendEvent failed for slice recovery: ${e instanceof Error ? e.message : String(e)}`);
|
|
498
511
|
}
|
|
499
512
|
}
|
|
513
|
+
// Insert a placeholder complete slice so deriveState sees activeMilestoneSlices.length > 0
|
|
514
|
+
// and exits the pre-planning phase. Without this, activeMilestoneSlices stays empty
|
|
515
|
+
// after the blocker ROADMAP.md is written, causing deriveState to return phase:'pre-planning'
|
|
516
|
+
// indefinitely and re-dispatching plan-milestone in an infinite loop (#4378).
|
|
517
|
+
if (unitType === "plan-milestone" && mid) {
|
|
518
|
+
try {
|
|
519
|
+
insertSlice({ id: "S00-blocker", milestoneId: mid, title: "Blocker placeholder — planning failed", status: "complete", sequence: 0 });
|
|
520
|
+
}
|
|
521
|
+
catch (e) {
|
|
522
|
+
logWarning("recovery", `insertSlice placeholder failed for plan-milestone recovery: ${e instanceof Error ? e.message : String(e)}`);
|
|
523
|
+
}
|
|
524
|
+
try {
|
|
525
|
+
appendEvent(base, { cmd: "plan-milestone", params: { milestoneId: mid }, ts, actor: "system", trigger_reason: "blocker-placeholder-recovery" });
|
|
526
|
+
}
|
|
527
|
+
catch (e) {
|
|
528
|
+
logWarning("recovery", `appendEvent failed for plan-milestone recovery: ${e instanceof Error ? e.message : String(e)}`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
500
531
|
}
|
|
501
532
|
return diagnoseExpectedArtifact(unitType, unitId, base);
|
|
502
533
|
}
|
|
@@ -30,8 +30,7 @@ import { initRoutingHistory } from "./routing-history.js";
|
|
|
30
30
|
import { restoreHookState, resetHookState } from "./post-unit-hooks.js";
|
|
31
31
|
import { resetProactiveHealing, setLevelChangeCallback } from "./doctor-proactive.js";
|
|
32
32
|
import { snapshotSkills } from "./skill-discovery.js";
|
|
33
|
-
import { isDbAvailable, getMilestone, openDatabase } from "./gsd-db.js";
|
|
34
|
-
import { hideFooter } from "./auto-dashboard.js";
|
|
33
|
+
import { isDbAvailable, getMilestone, openDatabase, getDbStatus } from "./gsd-db.js";
|
|
35
34
|
import { debugLog, enableDebug, isDebugEnabled, getDebugLogPath, } from "./debug-logger.js";
|
|
36
35
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
37
36
|
import { existsSync, mkdirSync, readdirSync, rmSync, statSync, unlinkSync, } from "node:fs";
|
|
@@ -190,8 +189,8 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
190
189
|
//
|
|
191
190
|
// Precedence:
|
|
192
191
|
// 1) Explicit session override via /gsd model (this session)
|
|
193
|
-
// 2)
|
|
194
|
-
// 3)
|
|
192
|
+
// 2) Current session model from settings/session restore (if provider ready)
|
|
193
|
+
// 3) GSD model preferences from PREFERENCES.md (validated against live auth)
|
|
195
194
|
//
|
|
196
195
|
// This preserves #3517 defaults while honoring explicit runtime model
|
|
197
196
|
// selection for subsequent /gsd runs in the same session.
|
|
@@ -224,11 +223,14 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
224
223
|
}
|
|
225
224
|
}
|
|
226
225
|
const sessionModelReady = ctx.model && ctx.modelRegistry.isProviderRequestReady(ctx.model.provider);
|
|
226
|
+
const currentSessionModel = (sessionModelReady && ctx.model)
|
|
227
|
+
? { provider: ctx.model.provider, id: ctx.model.id }
|
|
228
|
+
: null;
|
|
229
|
+
const startThinkingSnapshot = pi.getThinkingLevel();
|
|
227
230
|
const startModelSnapshot = manualSessionOverride
|
|
231
|
+
?? currentSessionModel
|
|
228
232
|
?? validatedPreferredModel
|
|
229
|
-
??
|
|
230
|
-
? { provider: ctx.model.provider, id: ctx.model.id }
|
|
231
|
-
: null);
|
|
233
|
+
?? null;
|
|
232
234
|
try {
|
|
233
235
|
// Validate GSD_PROJECT_ID early so the user gets immediate feedback
|
|
234
236
|
const customProjectId = process.env.GSD_PROJECT_ID;
|
|
@@ -244,7 +246,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
244
246
|
// the parent git root). See #2393 and related issue.
|
|
245
247
|
const hasLocalGit = existsSync(join(base, ".git"));
|
|
246
248
|
if (!hasLocalGit || isInheritedRepo(base)) {
|
|
247
|
-
const mainBranch = loadEffectiveGSDPreferences()?.preferences?.git?.main_branch || "main";
|
|
249
|
+
const mainBranch = loadEffectiveGSDPreferences(base)?.preferences?.git?.main_branch || "main";
|
|
248
250
|
nativeInit(base, mainBranch);
|
|
249
251
|
}
|
|
250
252
|
// Migrate legacy in-project .gsd/ to external state directory.
|
|
@@ -260,7 +262,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
260
262
|
// Ensure .gitignore has baseline patterns.
|
|
261
263
|
// ensureGitignore checks for git-tracked .gsd/ files and skips the
|
|
262
264
|
// ".gsd" pattern if the project intentionally tracks .gsd/ in git.
|
|
263
|
-
const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
265
|
+
const gitPrefs = loadEffectiveGSDPreferences(base)?.preferences?.git;
|
|
264
266
|
const manageGitignore = gitPrefs?.manage_gitignore;
|
|
265
267
|
ensureGitignore(base, { manageGitignore });
|
|
266
268
|
if (manageGitignore !== false)
|
|
@@ -286,7 +288,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
286
288
|
prepareWorkflowMcpForProject(ctx, base);
|
|
287
289
|
}
|
|
288
290
|
// Initialize GitServiceImpl
|
|
289
|
-
s.gitService = new GitServiceImpl(s.basePath, loadEffectiveGSDPreferences()?.preferences?.git ?? {});
|
|
291
|
+
s.gitService = new GitServiceImpl(s.basePath, loadEffectiveGSDPreferences(base)?.preferences?.git ?? {});
|
|
290
292
|
// ── Debug mode ──
|
|
291
293
|
if (!isDebugEnabled() && process.env.GSD_DEBUG === "1") {
|
|
292
294
|
enableDebug(base);
|
|
@@ -319,7 +321,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
319
321
|
// was lost due to session ending between completion and teardown.
|
|
320
322
|
// Must run after DB open and before worktree entry.
|
|
321
323
|
try {
|
|
322
|
-
const auditResult = auditOrphanedMilestoneBranches(base, getIsolationMode());
|
|
324
|
+
const auditResult = auditOrphanedMilestoneBranches(base, getIsolationMode(base));
|
|
323
325
|
for (const msg of auditResult.recovered) {
|
|
324
326
|
ctx.ui.notify(`Orphan audit: ${msg}`, "info");
|
|
325
327
|
}
|
|
@@ -337,7 +339,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
337
339
|
let state = await deriveState(base);
|
|
338
340
|
// Stale worktree state recovery (#654)
|
|
339
341
|
if (state.activeMilestone &&
|
|
340
|
-
shouldUseWorktreeIsolation() &&
|
|
342
|
+
shouldUseWorktreeIsolation(base) &&
|
|
341
343
|
!detectWorktreeName(base)) {
|
|
342
344
|
const wtPath = getAutoWorktreePath(base, state.activeMilestone.id);
|
|
343
345
|
if (wtPath) {
|
|
@@ -352,7 +354,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
352
354
|
let hasSurvivorBranch = false;
|
|
353
355
|
if (state.activeMilestone &&
|
|
354
356
|
(state.phase === "pre-planning" || state.phase === "complete") &&
|
|
355
|
-
getIsolationMode() !== "none" &&
|
|
357
|
+
getIsolationMode(base) !== "none" &&
|
|
356
358
|
!detectWorktreeName(base) &&
|
|
357
359
|
!base.includes(`${pathSep}.gsd${pathSep}worktrees${pathSep}`)) {
|
|
358
360
|
const milestoneBranch = `milestone/${state.activeMilestone.id}`;
|
|
@@ -413,29 +415,15 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
413
415
|
}
|
|
414
416
|
const { showSmartEntry } = await import("./guided-flow.js");
|
|
415
417
|
await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
postState.phase === "pre-planning") {
|
|
426
|
-
const contextFile = resolveMilestoneFile(base, postState.activeMilestone.id, "CONTEXT");
|
|
427
|
-
const hasContext = !!(contextFile && (await loadFile(contextFile)));
|
|
428
|
-
if (hasContext) {
|
|
429
|
-
state = postState;
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
432
|
-
ctx.ui.notify("Discussion completed but no milestone context was written. Run /gsd to try the discussion again, or /gsd auto after creating the milestone manually.", "warning");
|
|
433
|
-
return releaseLockAndReturn();
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
else {
|
|
437
|
-
return releaseLockAndReturn();
|
|
438
|
-
}
|
|
418
|
+
// showSmartEntry dispatches via pi.sendMessage() which is fire-and-forget:
|
|
419
|
+
// it queues the message and returns immediately, before the LLM turn runs.
|
|
420
|
+
// Checking postState here would always see the pre-dispatch state, causing
|
|
421
|
+
// the premature "Discussion completed but..." warning (#3420).
|
|
422
|
+
//
|
|
423
|
+
// checkAutoStartAfterDiscuss (in guided-flow.ts) already handles re-entering
|
|
424
|
+
// auto-mode by calling startAutoDetached after the discussion completes.
|
|
425
|
+
// Release the lock and let the async dispatch proceed.
|
|
426
|
+
return releaseLockAndReturn();
|
|
439
427
|
}
|
|
440
428
|
// Active milestone exists but has no roadmap
|
|
441
429
|
if (state.phase === "pre-planning") {
|
|
@@ -445,15 +433,16 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
445
433
|
if (!hasContext) {
|
|
446
434
|
const { showSmartEntry } = await import("./guided-flow.js");
|
|
447
435
|
await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
436
|
+
// showSmartEntry dispatches via pi.sendMessage() which is fire-and-forget:
|
|
437
|
+
// it queues the message and returns immediately, before the LLM turn runs.
|
|
438
|
+
// Checking postState here fires before the LLM has had a turn, so the
|
|
439
|
+
// pre-planning phase would still appear unchanged and a premature warning
|
|
440
|
+
// would be emitted (#3420).
|
|
441
|
+
//
|
|
442
|
+
// checkAutoStartAfterDiscuss (in guided-flow.ts) already handles re-entering
|
|
443
|
+
// auto-mode by calling startAutoDetached after the discussion completes.
|
|
444
|
+
// Release the lock and let the async dispatch proceed.
|
|
445
|
+
return releaseLockAndReturn();
|
|
457
446
|
}
|
|
458
447
|
}
|
|
459
448
|
// Active milestone has CONTEXT-DRAFT but no full context — needs discussion
|
|
@@ -506,13 +495,14 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
506
495
|
s.pendingQuickTasks = [];
|
|
507
496
|
s.currentUnit = null;
|
|
508
497
|
s.currentMilestoneId = state.activeMilestone?.id ?? null;
|
|
509
|
-
s.originalModelId = ctx.model?.id ?? null;
|
|
510
|
-
s.originalModelProvider = ctx.model?.provider ?? null;
|
|
498
|
+
s.originalModelId = startModelSnapshot?.id ?? ctx.model?.id ?? null;
|
|
499
|
+
s.originalModelProvider = startModelSnapshot?.provider ?? ctx.model?.provider ?? null;
|
|
500
|
+
s.originalThinkingLevel = startThinkingSnapshot ?? null;
|
|
511
501
|
// Register SIGTERM handler
|
|
512
502
|
registerSigtermHandler(base);
|
|
513
503
|
// Capture integration branch
|
|
514
504
|
if (s.currentMilestoneId) {
|
|
515
|
-
if (getIsolationMode() !== "none") {
|
|
505
|
+
if (getIsolationMode(base) !== "none") {
|
|
516
506
|
captureIntegrationBranch(base, s.currentMilestoneId);
|
|
517
507
|
}
|
|
518
508
|
setActiveMilestoneId(base, s.currentMilestoneId);
|
|
@@ -520,7 +510,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
520
510
|
// Guard against stale milestone branch when isolation:none (#3613).
|
|
521
511
|
// A prior session with isolation:branch/worktree may have left HEAD on
|
|
522
512
|
// milestone/<MID>. Auto-checkout back to the integration branch.
|
|
523
|
-
if (getIsolationMode() === "none" && nativeIsRepo(base)) {
|
|
513
|
+
if (getIsolationMode(base) === "none" && nativeIsRepo(base)) {
|
|
524
514
|
try {
|
|
525
515
|
const currentBranch = nativeGetCurrentBranch(base);
|
|
526
516
|
if (currentBranch.startsWith("milestone/")) {
|
|
@@ -548,7 +538,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
548
538
|
return symlinkRe.test(p);
|
|
549
539
|
};
|
|
550
540
|
if (s.currentMilestoneId &&
|
|
551
|
-
getIsolationMode() !== "none" &&
|
|
541
|
+
getIsolationMode(base) !== "none" &&
|
|
552
542
|
!detectWorktreeName(base) &&
|
|
553
543
|
!isUnderGsdWorktrees(base)) {
|
|
554
544
|
buildResolver().enterMilestone(s.currentMilestoneId, {
|
|
@@ -593,8 +583,21 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
593
583
|
// call returns "db_unavailable", triggering artifact-retry which
|
|
594
584
|
// re-dispatches the same task — producing an infinite loop (#2419).
|
|
595
585
|
if (existsSync(gsdDbPath) && !isDbAvailable()) {
|
|
596
|
-
|
|
597
|
-
|
|
586
|
+
const dbStatus = getDbStatus();
|
|
587
|
+
const phaseHint = dbStatus.lastPhase === "open"
|
|
588
|
+
? "The database file could not be opened"
|
|
589
|
+
: dbStatus.lastPhase === "initSchema"
|
|
590
|
+
? "The database schema could not be initialized"
|
|
591
|
+
: dbStatus.lastPhase === "vacuum-recovery"
|
|
592
|
+
? "Corruption recovery (VACUUM) failed"
|
|
593
|
+
: dbStatus.attempted
|
|
594
|
+
? "The database could not be opened (phase unknown)"
|
|
595
|
+
: "The database provider could not be loaded";
|
|
596
|
+
const errorDetail = dbStatus.lastError ? ` (${dbStatus.lastError.message})` : "";
|
|
597
|
+
const providerHint = dbStatus.provider
|
|
598
|
+
? ` Provider: ${dbStatus.provider}.`
|
|
599
|
+
: " No SQLite provider available — check Node >= 22 or install better-sqlite3.";
|
|
600
|
+
ctx.ui.notify(`SQLite database exists but failed to open: ${gsdDbPath}. ${phaseHint}${errorDetail}.${providerHint}`, "error");
|
|
598
601
|
return releaseLockAndReturn();
|
|
599
602
|
}
|
|
600
603
|
// Initialize metrics
|
|
@@ -608,6 +611,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
608
611
|
id: startModelSnapshot.id,
|
|
609
612
|
};
|
|
610
613
|
}
|
|
614
|
+
s.autoModeStartThinkingLevel = startThinkingSnapshot ?? null;
|
|
611
615
|
s.manualSessionModelOverride = manualSessionOverride ?? null;
|
|
612
616
|
// Apply worker model override from parallel orchestrator (#worker-model).
|
|
613
617
|
// GSD_WORKER_MODEL is injected by the coordinator when parallel.worker_model
|
|
@@ -628,13 +632,10 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
628
632
|
}
|
|
629
633
|
}
|
|
630
634
|
// Snapshot installed skills
|
|
631
|
-
if (resolveSkillDiscoveryMode() !== "off") {
|
|
635
|
+
if (resolveSkillDiscoveryMode(base) !== "off") {
|
|
632
636
|
snapshotSkills();
|
|
633
637
|
}
|
|
634
638
|
ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
|
|
635
|
-
ctx.ui.setFooter(hideFooter);
|
|
636
|
-
// Hide gsd-health during AUTO — gsd-progress is the single source of truth
|
|
637
|
-
// for last-commit / cost / health signal while auto is running.
|
|
638
639
|
ctx.ui.setWidget("gsd-health", undefined);
|
|
639
640
|
const modeLabel = s.stepMode ? "Step-mode" : "Auto-mode";
|
|
640
641
|
const pendingCount = (state.registry ?? []).filter((m) => m.status !== "complete" && m.status !== "parked").length;
|
|
@@ -656,7 +657,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
656
657
|
// FlatRateContext used by selectAndApplyModel so user-declared
|
|
657
658
|
// flat-rate providers and externalCli auto-detection are respected.
|
|
658
659
|
const { isFlatRateProvider, buildFlatRateContext } = await import("./auto-model-selection.js");
|
|
659
|
-
const bannerPrefs = loadEffectiveGSDPreferences()?.preferences;
|
|
660
|
+
const bannerPrefs = loadEffectiveGSDPreferences(base)?.preferences;
|
|
660
661
|
const effectiveProvider = s.autoModeStartModel?.provider ?? ctx.model?.provider;
|
|
661
662
|
const effectivelyEnabled = routingConfig.enabled
|
|
662
663
|
&& (routingConfig.allow_flat_rate_providers
|