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
|
@@ -238,14 +238,6 @@ function clearProjectRootStateFiles(basePath: string, milestoneId: string): void
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
function isProjectGsdSymlink(basePath: string): boolean {
|
|
242
|
-
try {
|
|
243
|
-
return lstatSyncFn(join(basePath, ".gsd")).isSymbolicLink();
|
|
244
|
-
} catch {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
241
|
// ─── Build Artifact Auto-Resolve ─────────────────────────────────────────────
|
|
250
242
|
|
|
251
243
|
/** Patterns for machine-generated build artifacts that can be safely
|
|
@@ -1664,54 +1656,15 @@ export function mergeMilestoneToMain(
|
|
|
1664
1656
|
}
|
|
1665
1657
|
}
|
|
1666
1658
|
|
|
1667
|
-
// 7.
|
|
1668
|
-
// blocked by unrelated local changes (#2151). clearProjectRootStateFiles
|
|
1669
|
-
// only removes untracked .gsd/ files; tracked dirty files elsewhere (e.g.
|
|
1670
|
-
// .planning/work-state.json with stash conflict markers) are invisible to
|
|
1671
|
-
// that cleanup but will cause `git merge --squash` to reject.
|
|
1672
|
-
let stashed = false;
|
|
1673
|
-
try {
|
|
1674
|
-
const status = execFileSync("git", ["status", "--porcelain"], {
|
|
1675
|
-
cwd: originalBasePath_,
|
|
1676
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
1677
|
-
encoding: "utf-8",
|
|
1678
|
-
}).trim();
|
|
1679
|
-
if (status) {
|
|
1680
|
-
// Use --include-untracked to stash untracked files that would block
|
|
1681
|
-
// the squash merge, but EXCLUDE .gsd/milestones/ (#2505).
|
|
1682
|
-
// --include-untracked without exclusion sweeps queued milestone
|
|
1683
|
-
// CONTEXT files into the stash. If stash pop later fails, those files
|
|
1684
|
-
// are permanently trapped in the stash entry and lost on the next
|
|
1685
|
-
// stash push or drop.
|
|
1686
|
-
//
|
|
1687
|
-
// When `.gsd` itself is a symlink, Git rejects pathspecs below it
|
|
1688
|
-
// ("beyond a symbolic link"). In that layout, exclude the whole symlink
|
|
1689
|
-
// and keep stashing real project files that could block the merge.
|
|
1690
|
-
const stashPathspecs = isProjectGsdSymlink(originalBasePath_)
|
|
1691
|
-
? [".", ":(exclude).gsd"]
|
|
1692
|
-
: [":(exclude).gsd/milestones"];
|
|
1693
|
-
execFileSync(
|
|
1694
|
-
"git",
|
|
1695
|
-
[
|
|
1696
|
-
"stash", "push", "--include-untracked",
|
|
1697
|
-
"-m", `gsd: pre-merge stash for ${milestoneId}`,
|
|
1698
|
-
"--", ...stashPathspecs,
|
|
1699
|
-
],
|
|
1700
|
-
{ cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" },
|
|
1701
|
-
);
|
|
1702
|
-
stashed = true;
|
|
1703
|
-
}
|
|
1704
|
-
} catch (err) {
|
|
1705
|
-
// Stash failure is non-fatal — proceed without stash and let the merge
|
|
1706
|
-
// report the dirty tree if it fails.
|
|
1707
|
-
logWarning("worktree", `git stash failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
// 7a. Shelter queued milestone directories before the squash merge (#2505).
|
|
1659
|
+
// 7. Shelter queued milestone directories before the squash merge (#2505).
|
|
1711
1660
|
// The milestone branch may contain copies of queued milestone dirs (via
|
|
1712
1661
|
// copyPlanningArtifacts), so `git merge --squash` rejects when those same
|
|
1713
1662
|
// files exist as untracked in the working tree. Temporarily move them to
|
|
1714
1663
|
// a backup location, then restore after the merge+commit.
|
|
1664
|
+
//
|
|
1665
|
+
// MUST run BEFORE the pre-merge stash (step 7a) so `--include-untracked`
|
|
1666
|
+
// does not sweep queued CONTEXT files into the stash. If stash pop later
|
|
1667
|
+
// fails, files trapped inside the stash are permanently lost (#2505).
|
|
1715
1668
|
const milestonesDir = join(gsdRoot(originalBasePath_), "milestones");
|
|
1716
1669
|
const shelterDir = join(gsdRoot(originalBasePath_), ".milestone-shelter");
|
|
1717
1670
|
const shelteredDirs: string[] = [];
|
|
@@ -1759,6 +1712,35 @@ export function mergeMilestoneToMain(
|
|
|
1759
1712
|
logWarning("worktree", `milestone shelter operation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1760
1713
|
}
|
|
1761
1714
|
|
|
1715
|
+
// 7a. Stash pre-existing dirty files so the squash merge is not blocked by
|
|
1716
|
+
// unrelated local changes (#2151). Includes untracked files to handle
|
|
1717
|
+
// locally-added files that conflict with tracked files on the milestone
|
|
1718
|
+
// branch. Passing NO pathspec lets git skip gitignored paths silently;
|
|
1719
|
+
// adding an explicit pathspec trips a `git add`-style fatal on ignored
|
|
1720
|
+
// entries (e.g. a gitignored `.gsd` symlink under ADR-002) (#4573).
|
|
1721
|
+
// Queued CONTEXT files under `.gsd/milestones/*` are already sheltered
|
|
1722
|
+
// in step 7 above, so they won't be swept into the stash.
|
|
1723
|
+
let stashed = false;
|
|
1724
|
+
try {
|
|
1725
|
+
const status = execFileSync("git", ["status", "--porcelain"], {
|
|
1726
|
+
cwd: originalBasePath_,
|
|
1727
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1728
|
+
encoding: "utf-8",
|
|
1729
|
+
}).trim();
|
|
1730
|
+
if (status) {
|
|
1731
|
+
execFileSync(
|
|
1732
|
+
"git",
|
|
1733
|
+
["stash", "push", "--include-untracked", "-m", `gsd: pre-merge stash for ${milestoneId}`],
|
|
1734
|
+
{ cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" },
|
|
1735
|
+
);
|
|
1736
|
+
stashed = true;
|
|
1737
|
+
}
|
|
1738
|
+
} catch (err) {
|
|
1739
|
+
// Stash failure is non-fatal — proceed without stash and let the merge
|
|
1740
|
+
// report the dirty tree if it fails.
|
|
1741
|
+
logWarning("worktree", `git stash failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1762
1744
|
// 7b. Clean up stale merge state before attempting squash merge (#2912).
|
|
1763
1745
|
// A leftover MERGE_HEAD (from a previous failed merge, libgit2 native path,
|
|
1764
1746
|
// or interrupted operation) causes `git merge --squash` to refuse with
|
|
@@ -2012,21 +1994,38 @@ export function mergeMilestoneToMain(
|
|
|
2012
1994
|
// When a milestone only produced .gsd/ metadata (summaries, roadmaps) but no
|
|
2013
1995
|
// real code, the user sees "milestone complete" but nothing changed in their
|
|
2014
1996
|
// codebase. Surface this so the caller can warn the user.
|
|
1997
|
+
//
|
|
1998
|
+
// Bug #4385 fix: use `git diff-tree --root` instead of `git diff HEAD~1 HEAD`.
|
|
1999
|
+
// `HEAD~1` does not exist on initial commits and is unreliable on shallow clones
|
|
2000
|
+
// and merge commits. `diff-tree --root` handles all three cases correctly.
|
|
2001
|
+
// The empty-tree hash (4b825dc…) is the universal fallback for refs that don't exist.
|
|
2002
|
+
const GIT_EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
2015
2003
|
let codeFilesChanged = false;
|
|
2016
2004
|
if (!nothingToCommit) {
|
|
2017
2005
|
try {
|
|
2018
|
-
const
|
|
2019
|
-
|
|
2020
|
-
"HEAD
|
|
2021
|
-
"
|
|
2022
|
-
);
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
);
|
|
2006
|
+
const diffTreeOutput = execFileSync(
|
|
2007
|
+
"git",
|
|
2008
|
+
["diff-tree", "--root", "--no-commit-id", "-r", "--name-only", "HEAD"],
|
|
2009
|
+
{ cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" },
|
|
2010
|
+
).trim();
|
|
2011
|
+
const mergedFiles = diffTreeOutput ? diffTreeOutput.split("\n").filter(Boolean) : [];
|
|
2012
|
+
codeFilesChanged = mergedFiles.some((f) => !f.startsWith(".gsd/"));
|
|
2026
2013
|
} catch (e) {
|
|
2027
|
-
//
|
|
2028
|
-
|
|
2029
|
-
|
|
2014
|
+
// diff-tree failed (e.g. unborn HEAD in a brand-new repo) — fall back to
|
|
2015
|
+
// comparing against the empty tree so initial-commit repos still report changes.
|
|
2016
|
+
try {
|
|
2017
|
+
const fallbackOutput = execFileSync(
|
|
2018
|
+
"git",
|
|
2019
|
+
["diff", "--name-only", GIT_EMPTY_TREE, "HEAD"],
|
|
2020
|
+
{ cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" },
|
|
2021
|
+
).trim();
|
|
2022
|
+
const fallbackFiles = fallbackOutput ? fallbackOutput.split("\n").filter(Boolean) : [];
|
|
2023
|
+
codeFilesChanged = fallbackFiles.some((f) => !f.startsWith(".gsd/"));
|
|
2024
|
+
} catch {
|
|
2025
|
+
// Truly unable to determine — assume code was changed to avoid silent data loss
|
|
2026
|
+
logWarning("worktree", `diff-tree and empty-tree fallback both failed (assuming code changed): ${(e as Error).message}`);
|
|
2027
|
+
codeFilesChanged = true;
|
|
2028
|
+
}
|
|
2030
2029
|
}
|
|
2031
2030
|
}
|
|
2032
2031
|
|
|
@@ -126,8 +126,9 @@ import {
|
|
|
126
126
|
formatTokenCount,
|
|
127
127
|
} from "./metrics.js";
|
|
128
128
|
import { setLogBasePath, logWarning, logError } from "./workflow-logger.js";
|
|
129
|
+
import { preflightCleanRoot, postflightPopStash } from "./clean-root-preflight.js";
|
|
129
130
|
import { homedir } from "node:os";
|
|
130
|
-
import { join } from "node:path";
|
|
131
|
+
import { isAbsolute, join } from "node:path";
|
|
131
132
|
import { pathToFileURL } from "node:url";
|
|
132
133
|
import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs";
|
|
133
134
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
@@ -182,7 +183,6 @@ import {
|
|
|
182
183
|
unitVerb,
|
|
183
184
|
formatAutoElapsed as _formatAutoElapsed,
|
|
184
185
|
formatWidgetTokens,
|
|
185
|
-
hideFooter,
|
|
186
186
|
type WidgetStateAccessors,
|
|
187
187
|
} from "./auto-dashboard.js";
|
|
188
188
|
import {
|
|
@@ -310,6 +310,21 @@ function restoreMilestoneLockEnv(): void {
|
|
|
310
310
|
s.milestoneLockEnvCaptured = false;
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
+
function normalizeSessionFilePath(raw: unknown): string | null {
|
|
314
|
+
if (typeof raw !== "string") return null;
|
|
315
|
+
const trimmed = raw.trim();
|
|
316
|
+
if (!trimmed) return null;
|
|
317
|
+
const firstLine = trimmed.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
318
|
+
if (!firstLine) return null;
|
|
319
|
+
|
|
320
|
+
// Guard against accidental message concatenation by trimming to .jsonl.
|
|
321
|
+
const jsonlIndex = firstLine.toLowerCase().indexOf(".jsonl");
|
|
322
|
+
const candidate = jsonlIndex >= 0 ? firstLine.slice(0, jsonlIndex + ".jsonl".length) : firstLine;
|
|
323
|
+
if (!isAbsolute(candidate)) return null;
|
|
324
|
+
if (!candidate.toLowerCase().endsWith(".jsonl")) return null;
|
|
325
|
+
return candidate;
|
|
326
|
+
}
|
|
327
|
+
|
|
313
328
|
export function startAutoDetached(
|
|
314
329
|
ctx: ExtensionCommandContext,
|
|
315
330
|
pi: ExtensionAPI,
|
|
@@ -330,8 +345,8 @@ export function startAutoDetached(
|
|
|
330
345
|
}
|
|
331
346
|
|
|
332
347
|
/** Returns true if the project is configured for `isolation:worktree` mode. */
|
|
333
|
-
export function shouldUseWorktreeIsolation(): boolean {
|
|
334
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
348
|
+
export function shouldUseWorktreeIsolation(basePath?: string): boolean {
|
|
349
|
+
const prefs = loadEffectiveGSDPreferences(basePath)?.preferences?.git;
|
|
335
350
|
if (prefs?.isolation === "worktree") return true;
|
|
336
351
|
// Default is false — worktree isolation requires explicit opt-in
|
|
337
352
|
return false;
|
|
@@ -424,7 +439,7 @@ export function getAutoDashboardData(): AutoDashboardData {
|
|
|
424
439
|
const rtkSavings = sessionId && s.basePath
|
|
425
440
|
? getRtkSessionSavings(s.basePath, sessionId)
|
|
426
441
|
: null;
|
|
427
|
-
const rtkEnabled = loadEffectiveGSDPreferences()?.preferences.experimental?.rtk === true;
|
|
442
|
+
const rtkEnabled = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences.experimental?.rtk === true;
|
|
428
443
|
// Pending capture count — lazy check, non-fatal
|
|
429
444
|
let pendingCaptureCount = 0;
|
|
430
445
|
try {
|
|
@@ -648,7 +663,7 @@ function buildSnapshotOpts(
|
|
|
648
663
|
gitStatus?: "ok" | "failed";
|
|
649
664
|
gitError?: string;
|
|
650
665
|
} & Record<string, unknown> {
|
|
651
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
666
|
+
const prefs = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
|
|
652
667
|
const uokFlags = resolveUokFlags(prefs);
|
|
653
668
|
return {
|
|
654
669
|
...(s.autoStartTime > 0 ? { autoSessionKey: String(s.autoStartTime) } : {}),
|
|
@@ -686,7 +701,7 @@ function handleLostSessionLock(
|
|
|
686
701
|
restoreProjectRootEnv();
|
|
687
702
|
restoreMilestoneLockEnv();
|
|
688
703
|
deregisterSigtermHandler();
|
|
689
|
-
clearCmuxSidebar(loadEffectiveGSDPreferences()?.preferences);
|
|
704
|
+
clearCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences);
|
|
690
705
|
const base = lockBase();
|
|
691
706
|
const lockFilePath = base ? join(gsdRoot(base), "auto.lock") : "unknown";
|
|
692
707
|
const recoverySuggestion = "\nTo recover, run: gsd doctor --fix";
|
|
@@ -706,7 +721,6 @@ function handleLostSessionLock(
|
|
|
706
721
|
);
|
|
707
722
|
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
708
723
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
709
|
-
ctx?.ui.setFooter(undefined);
|
|
710
724
|
if (ctx) initHealthWidget(ctx);
|
|
711
725
|
}
|
|
712
726
|
|
|
@@ -742,7 +756,6 @@ function cleanupAfterLoopExit(ctx: ExtensionContext): void {
|
|
|
742
756
|
if (!s.paused) {
|
|
743
757
|
ctx.ui.setStatus("gsd-auto", undefined);
|
|
744
758
|
ctx.ui.setWidget("gsd-progress", undefined);
|
|
745
|
-
ctx.ui.setFooter(undefined);
|
|
746
759
|
initHealthWidget(ctx);
|
|
747
760
|
}
|
|
748
761
|
|
|
@@ -764,7 +777,7 @@ export async function stopAuto(
|
|
|
764
777
|
reason?: string,
|
|
765
778
|
): Promise<void> {
|
|
766
779
|
if (!s.active && !s.paused) return;
|
|
767
|
-
const loadedPreferences = loadEffectiveGSDPreferences()?.preferences;
|
|
780
|
+
const loadedPreferences = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
|
|
768
781
|
const reasonSuffix = reason ? ` — ${reason}` : "";
|
|
769
782
|
|
|
770
783
|
try {
|
|
@@ -969,7 +982,7 @@ export async function stopAuto(
|
|
|
969
982
|
logWarning("engine", `file unlink failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
970
983
|
}
|
|
971
984
|
|
|
972
|
-
// ── Step 13: Restore original model (before reset clears IDs) ──
|
|
985
|
+
// ── Step 13: Restore original model + thinking (before reset clears IDs) ──
|
|
973
986
|
try {
|
|
974
987
|
if (pi && ctx && s.originalModelId && s.originalModelProvider) {
|
|
975
988
|
const original = ctx.modelRegistry.find(
|
|
@@ -978,6 +991,9 @@ export async function stopAuto(
|
|
|
978
991
|
);
|
|
979
992
|
if (original) await pi.setModel(original);
|
|
980
993
|
}
|
|
994
|
+
if (pi && s.originalThinkingLevel) {
|
|
995
|
+
pi.setThinkingLevel(s.originalThinkingLevel);
|
|
996
|
+
}
|
|
981
997
|
} catch (e) {
|
|
982
998
|
debugLog("stop-cleanup-model", { error: e instanceof Error ? e.message : String(e) });
|
|
983
999
|
}
|
|
@@ -1015,7 +1031,6 @@ export async function stopAuto(
|
|
|
1015
1031
|
// UI cleanup
|
|
1016
1032
|
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
1017
1033
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
1018
|
-
ctx?.ui.setFooter(undefined);
|
|
1019
1034
|
if (ctx) initHealthWidget(ctx);
|
|
1020
1035
|
restoreProjectRootEnv();
|
|
1021
1036
|
restoreMilestoneLockEnv();
|
|
@@ -1056,7 +1071,7 @@ export async function pauseAuto(
|
|
|
1056
1071
|
// from provider-error pause and avoid hard-stopping (#2762).
|
|
1057
1072
|
resolveAgentEndCancelled(_errorContext);
|
|
1058
1073
|
|
|
1059
|
-
s.pausedSessionFile = ctx?.sessionManager?.getSessionFile() ?? null;
|
|
1074
|
+
s.pausedSessionFile = normalizeSessionFilePath(ctx?.sessionManager?.getSessionFile() ?? null);
|
|
1060
1075
|
|
|
1061
1076
|
// Persist paused-session metadata so resume survives /exit (#1383).
|
|
1062
1077
|
// The fresh-start bootstrap checks for this file and restores worktree context.
|
|
@@ -1118,7 +1133,6 @@ export async function pauseAuto(
|
|
|
1118
1133
|
s.verificationRetryCount.clear();
|
|
1119
1134
|
ctx?.ui.setStatus("gsd-auto", "paused");
|
|
1120
1135
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
1121
|
-
ctx?.ui.setFooter(undefined);
|
|
1122
1136
|
if (ctx) initHealthWidget(ctx);
|
|
1123
1137
|
const resumeCmd = s.stepMode ? "/gsd next" : "/gsd auto";
|
|
1124
1138
|
ctx?.ui.notify(
|
|
@@ -1289,6 +1303,10 @@ function buildLoopDeps(): LoopDeps {
|
|
|
1289
1303
|
|
|
1290
1304
|
// Journal
|
|
1291
1305
|
emitJournalEvent: (entry: JournalEntry) => _emitJournalEvent(s.basePath, entry),
|
|
1306
|
+
|
|
1307
|
+
// Clean-root preflight gate (#2909)
|
|
1308
|
+
preflightCleanRoot,
|
|
1309
|
+
postflightPopStash,
|
|
1292
1310
|
} as unknown as LoopDeps;
|
|
1293
1311
|
}
|
|
1294
1312
|
|
|
@@ -1361,7 +1379,11 @@ export async function startAuto(
|
|
|
1361
1379
|
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
1362
1380
|
s.sessionMilestoneLock = meta.milestoneLock ?? null;
|
|
1363
1381
|
s.paused = true;
|
|
1364
|
-
try { unlinkSync(pausedPath); } catch (e) {
|
|
1382
|
+
try { unlinkSync(pausedPath); } catch (e) {
|
|
1383
|
+
if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1384
|
+
logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1365
1387
|
ctx.ui.notify(
|
|
1366
1388
|
`Resuming paused custom workflow${meta.activeRunDir ? ` (${meta.activeRunDir})` : ""}.`,
|
|
1367
1389
|
"info",
|
|
@@ -1380,7 +1402,9 @@ export async function startAuto(
|
|
|
1380
1402
|
const summaryFile = resolveMilestoneFile(base, meta.milestoneId, "SUMMARY");
|
|
1381
1403
|
if (!mDir || summaryFile) {
|
|
1382
1404
|
try { unlinkSync(pausedPath); } catch (err) {
|
|
1383
|
-
|
|
1405
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1406
|
+
logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1407
|
+
}
|
|
1384
1408
|
}
|
|
1385
1409
|
ctx.ui.notify(
|
|
1386
1410
|
`Paused milestone ${meta.milestoneId} is ${!mDir ? "missing" : "already complete"}. Starting fresh.`,
|
|
@@ -1390,20 +1414,28 @@ export async function startAuto(
|
|
|
1390
1414
|
s.currentMilestoneId = meta.milestoneId;
|
|
1391
1415
|
s.originalBasePath = meta.originalBasePath || base;
|
|
1392
1416
|
s.stepMode = meta.stepMode ?? requestedStepMode;
|
|
1393
|
-
s.pausedSessionFile = meta.sessionFile ?? null;
|
|
1417
|
+
s.pausedSessionFile = normalizeSessionFilePath(meta.sessionFile ?? null);
|
|
1394
1418
|
s.pausedUnitType = meta.unitType ?? null;
|
|
1395
1419
|
s.pausedUnitId = meta.unitId ?? null;
|
|
1396
1420
|
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
1397
1421
|
s.sessionMilestoneLock = meta.milestoneLock ?? null;
|
|
1398
1422
|
s.paused = true;
|
|
1399
|
-
try { unlinkSync(pausedPath); } catch (e) {
|
|
1423
|
+
try { unlinkSync(pausedPath); } catch (e) {
|
|
1424
|
+
if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1425
|
+
logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1400
1428
|
ctx.ui.notify(
|
|
1401
1429
|
`Resuming paused session for ${meta.milestoneId}${meta.worktreePath && existsSync(meta.worktreePath) ? ` (worktree)` : ""}.`,
|
|
1402
1430
|
"info",
|
|
1403
1431
|
);
|
|
1404
1432
|
}
|
|
1405
1433
|
} else if (existsSync(pausedPath)) {
|
|
1406
|
-
try { unlinkSync(pausedPath); } catch (e) {
|
|
1434
|
+
try { unlinkSync(pausedPath); } catch (e) {
|
|
1435
|
+
if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1436
|
+
logWarning("session", `stale pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1407
1439
|
}
|
|
1408
1440
|
}
|
|
1409
1441
|
} catch (err) {
|
|
@@ -1462,7 +1494,9 @@ export async function startAuto(
|
|
|
1462
1494
|
// Lock acquired — now safe to delete the pause file
|
|
1463
1495
|
if (s.pausedSessionFile) {
|
|
1464
1496
|
try { unlinkSync(s.pausedSessionFile); } catch (err) {
|
|
1465
|
-
|
|
1497
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1498
|
+
logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1499
|
+
}
|
|
1466
1500
|
}
|
|
1467
1501
|
s.pausedSessionFile = null;
|
|
1468
1502
|
}
|
|
@@ -1473,6 +1507,17 @@ export async function startAuto(
|
|
|
1473
1507
|
s.stepMode = requestedStepMode;
|
|
1474
1508
|
s.cmdCtx = ctx;
|
|
1475
1509
|
s.basePath = base;
|
|
1510
|
+
// ── Resume worktree: if the paused session was inside a milestone worktree,
|
|
1511
|
+
// apply that path as the dispatch basePath immediately (#3723).
|
|
1512
|
+
// This ensures the dispatch loop runs from the worktree directory even when
|
|
1513
|
+
// enterMilestone guard conditions differ between the original and resumed
|
|
1514
|
+
// session (e.g. isolation mode changed, detectWorktreeName differs across
|
|
1515
|
+
// process restarts). We guard with existsSync so a stale or deleted
|
|
1516
|
+
// worktree directory safely falls back to the project root.
|
|
1517
|
+
const resumeWorktreePath = freshStartAssessment.pausedSession?.worktreePath;
|
|
1518
|
+
if (resumeWorktreePath && existsSync(resumeWorktreePath)) {
|
|
1519
|
+
s.basePath = resumeWorktreePath;
|
|
1520
|
+
}
|
|
1476
1521
|
// Ensure the workflow-logger audit log is pinned to the project root
|
|
1477
1522
|
// even when auto-mode is entered via a path that bypasses the
|
|
1478
1523
|
// bootstrap/dynamic-tools ensureDbOpen() → setLogBasePath() chain
|
|
@@ -1492,7 +1537,7 @@ export async function startAuto(
|
|
|
1492
1537
|
// ── Auto-worktree / branch-mode: re-enter on resume ──
|
|
1493
1538
|
if (
|
|
1494
1539
|
s.currentMilestoneId &&
|
|
1495
|
-
getIsolationMode() !== "none" &&
|
|
1540
|
+
getIsolationMode(s.originalBasePath || s.basePath) !== "none" &&
|
|
1496
1541
|
s.originalBasePath &&
|
|
1497
1542
|
!isInAutoWorktree(s.basePath) &&
|
|
1498
1543
|
!detectWorktreeName(s.basePath) &&
|
|
@@ -1506,7 +1551,7 @@ export async function startAuto(
|
|
|
1506
1551
|
registerSigtermHandler(lockBase());
|
|
1507
1552
|
|
|
1508
1553
|
ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
|
|
1509
|
-
ctx.ui.
|
|
1554
|
+
ctx.ui.setWidget("gsd-health", undefined);
|
|
1510
1555
|
ctx.ui.notify(
|
|
1511
1556
|
s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.",
|
|
1512
1557
|
"info",
|
|
@@ -1531,7 +1576,7 @@ export async function startAuto(
|
|
|
1531
1576
|
await openProjectDbIfPresent(s.basePath);
|
|
1532
1577
|
try {
|
|
1533
1578
|
await rebuildState(s.basePath);
|
|
1534
|
-
syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
|
|
1579
|
+
syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
|
|
1535
1580
|
} catch (e) {
|
|
1536
1581
|
debugLog("resume-rebuild-state-failed", {
|
|
1537
1582
|
error: e instanceof Error ? e.message : String(e),
|
|
@@ -1581,7 +1626,7 @@ export async function startAuto(
|
|
|
1581
1626
|
"resuming",
|
|
1582
1627
|
s.currentMilestoneId ?? "unknown",
|
|
1583
1628
|
);
|
|
1584
|
-
logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
|
|
1629
|
+
logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
|
|
1585
1630
|
|
|
1586
1631
|
captureProjectRootEnv(s.originalBasePath || s.basePath);
|
|
1587
1632
|
startAutoCommandPolling(s.basePath);
|
|
@@ -1619,12 +1664,12 @@ export async function startAuto(
|
|
|
1619
1664
|
|
|
1620
1665
|
captureProjectRootEnv(s.originalBasePath || s.basePath);
|
|
1621
1666
|
try {
|
|
1622
|
-
syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
|
|
1667
|
+
syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
|
|
1623
1668
|
} catch (err) {
|
|
1624
1669
|
// Best-effort only — sidebar sync must never block auto-mode startup
|
|
1625
1670
|
logWarning("engine", `cmux sync failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1626
1671
|
}
|
|
1627
|
-
logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
|
|
1672
|
+
logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
|
|
1628
1673
|
|
|
1629
1674
|
startAutoCommandPolling(s.basePath);
|
|
1630
1675
|
|
|
@@ -1773,12 +1818,12 @@ export async function dispatchHookUnit(
|
|
|
1773
1818
|
}
|
|
1774
1819
|
}
|
|
1775
1820
|
|
|
1776
|
-
const sessionFile = ctx.sessionManager.getSessionFile();
|
|
1821
|
+
const sessionFile = normalizeSessionFilePath(ctx.sessionManager.getSessionFile());
|
|
1777
1822
|
writeLock(
|
|
1778
1823
|
lockBase(),
|
|
1779
1824
|
hookUnitType,
|
|
1780
1825
|
triggerUnitId,
|
|
1781
|
-
sessionFile,
|
|
1826
|
+
sessionFile ?? undefined,
|
|
1782
1827
|
);
|
|
1783
1828
|
|
|
1784
1829
|
clearUnitTimeout();
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
2
2
|
|
|
3
3
|
import { logWarning } from "../workflow-logger.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
checkAutoStartAfterDiscuss,
|
|
6
|
+
maybeHandleReadyPhraseWithoutFiles,
|
|
7
|
+
maybeHandleEmptyIntentTurn,
|
|
8
|
+
resetEmptyTurnCounter,
|
|
9
|
+
} from "../guided-flow.js";
|
|
5
10
|
import { getAutoDashboardData, getAutoModeStartModel, isAutoActive, pauseAuto, setCurrentDispatchedModelId } from "../auto.js";
|
|
6
11
|
import { getNextFallbackModel, resolveModelWithFallbacksForUnit } from "../preferences.js";
|
|
7
12
|
import { pauseAutoForProviderError } from "../provider-error-pause.js";
|
|
@@ -75,6 +80,20 @@ export async function handleAgentEnd(
|
|
|
75
80
|
clearDiscussionFlowState();
|
|
76
81
|
return;
|
|
77
82
|
}
|
|
83
|
+
|
|
84
|
+
// #4573 — When the LLM emits "Milestone X ready." but the required files
|
|
85
|
+
// are missing, `checkAutoStartAfterDiscuss` returns false silently. Surface
|
|
86
|
+
// that and nudge the LLM to complete the writes before the user hits the
|
|
87
|
+
// downstream "All milestones complete" warning loop.
|
|
88
|
+
if (maybeHandleReadyPhraseWithoutFiles(event)) return;
|
|
89
|
+
|
|
90
|
+
// #4573 — Empty-turn recovery: if the LLM announced intent in prose but
|
|
91
|
+
// emitted no tool calls, nudge it to execute. Fires only when auto-mode is
|
|
92
|
+
// active or a discussion autostart is pending (non-auto interactive discuss
|
|
93
|
+
// is user-driven). Runs before `isAutoActive` early return so pending
|
|
94
|
+
// discussions (where isAutoActive may be false) still get recovered.
|
|
95
|
+
if (maybeHandleEmptyIntentTurn(event, isAutoActive())) return;
|
|
96
|
+
|
|
78
97
|
if (!isAutoActive()) return;
|
|
79
98
|
if (isSessionSwitchInFlight()) return;
|
|
80
99
|
|
|
@@ -336,6 +355,9 @@ export async function handleAgentEnd(
|
|
|
336
355
|
// ── Success path ─────────────────────────────────────────────────────────
|
|
337
356
|
try {
|
|
338
357
|
resetRetryState(retryState);
|
|
358
|
+
// #4573 — Reset the empty-turn counter on any successful agent turn so
|
|
359
|
+
// transient stalls don't accumulate across independent units.
|
|
360
|
+
resetEmptyTurnCounter();
|
|
339
361
|
resolveAgentEnd(event);
|
|
340
362
|
} catch (err) {
|
|
341
363
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -35,6 +35,19 @@ function registerAlias(pi: ExtensionAPI, toolDef: any, aliasName: string, canoni
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Read a tool result's structured payload, accommodating MCP's `details` →
|
|
40
|
+
* `structuredContent` rename (#4472, #4477). In-process executions still
|
|
41
|
+
* deliver the payload on `result.details`; MCP-routed executions deliver it
|
|
42
|
+
* on `result.structuredContent` (post `adaptExecutorResult` transform). All
|
|
43
|
+
* `renderResult` callbacks in this file route through this helper so a future
|
|
44
|
+
* field rename only needs to be applied in one place.
|
|
45
|
+
*/
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- result shape varies by tool
|
|
47
|
+
function readDetails(result: any): any {
|
|
48
|
+
return result?.details ?? result?.structuredContent;
|
|
49
|
+
}
|
|
50
|
+
|
|
38
51
|
export function registerDbTools(pi: ExtensionAPI): void {
|
|
39
52
|
// ─── gsd_decision_save (formerly gsd_save_decision) ─────────────────────
|
|
40
53
|
|
|
@@ -110,7 +123,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
110
123
|
return new Text(text, 0, 0);
|
|
111
124
|
},
|
|
112
125
|
renderResult(result: any, _options: any, theme: any) {
|
|
113
|
-
const d = result
|
|
126
|
+
const d = readDetails(result);
|
|
114
127
|
if (result.isError || d?.error) {
|
|
115
128
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
116
129
|
}
|
|
@@ -188,7 +201,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
188
201
|
return new Text(text, 0, 0);
|
|
189
202
|
},
|
|
190
203
|
renderResult(result: any, _options: any, theme: any) {
|
|
191
|
-
const d = result
|
|
204
|
+
const d = readDetails(result);
|
|
192
205
|
if (result.isError || d?.error) {
|
|
193
206
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
194
207
|
}
|
|
@@ -273,7 +286,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
273
286
|
return new Text(text, 0, 0);
|
|
274
287
|
},
|
|
275
288
|
renderResult(result: any, _options: any, theme: any) {
|
|
276
|
-
const d = result
|
|
289
|
+
const d = readDetails(result);
|
|
277
290
|
if (result.isError || d?.error) {
|
|
278
291
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
279
292
|
}
|
|
@@ -322,7 +335,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
322
335
|
return new Text(text, 0, 0);
|
|
323
336
|
},
|
|
324
337
|
renderResult(result: any, _options: any, theme: any) {
|
|
325
|
-
const d = result
|
|
338
|
+
const d = readDetails(result);
|
|
326
339
|
if (result.isError || d?.error) {
|
|
327
340
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
328
341
|
}
|
|
@@ -406,7 +419,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
406
419
|
return new Text(theme.fg("toolTitle", theme.bold("milestone_generate_id")), 0, 0);
|
|
407
420
|
},
|
|
408
421
|
renderResult(result: any, _options: any, theme: any) {
|
|
409
|
-
const d = result
|
|
422
|
+
const d = readDetails(result);
|
|
410
423
|
if (result.isError || d?.error) {
|
|
411
424
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
412
425
|
}
|
|
@@ -1074,13 +1087,31 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1074
1087
|
text += theme.fg("dim", ` → ${args.verdict ?? ""}`);
|
|
1075
1088
|
return new Text(text, 0, 0);
|
|
1076
1089
|
},
|
|
1090
|
+
/**
|
|
1091
|
+
* Render the save_gate_result tool output for the TUI.
|
|
1092
|
+
*
|
|
1093
|
+
* Prefers structured fields, but falls back to `content[0].text` when the
|
|
1094
|
+
* structured payload is empty. Defensive: the structural fix on this
|
|
1095
|
+
* branch plumbs `details` through MCP via `structuredContent`, but older
|
|
1096
|
+
* hosts, a future handler that forgets `structuredContent`, or any drop
|
|
1097
|
+
* of non-standard return fields would otherwise render as
|
|
1098
|
+
* "undefined: undefined". Same fallback applies to error rendering, and
|
|
1099
|
+
* we strip a leading `Error:` from the fallback text to avoid producing
|
|
1100
|
+
* `Error: Error: ...`.
|
|
1101
|
+
*/
|
|
1077
1102
|
renderResult(result: any, _options: any, theme: any) {
|
|
1078
|
-
const d = result
|
|
1103
|
+
const d = readDetails(result);
|
|
1079
1104
|
if (result.isError || d?.error) {
|
|
1080
|
-
|
|
1105
|
+
const rawMsg = d?.error ?? result.content?.[0]?.text ?? "unknown";
|
|
1106
|
+
const msg = rawMsg.replace(/^\s*Error:\s*/i, "");
|
|
1107
|
+
return new Text(theme.fg("error", `Error: ${msg}`), 0, 0);
|
|
1108
|
+
}
|
|
1109
|
+
if (!d?.gateId || !d?.verdict) {
|
|
1110
|
+
const text = result.content?.[0]?.text ?? "Gate result saved";
|
|
1111
|
+
return new Text(theme.fg("success", text), 0, 0);
|
|
1081
1112
|
}
|
|
1082
|
-
const color = d
|
|
1083
|
-
return new Text(theme.fg(color, `${d
|
|
1113
|
+
const color = d.verdict === "flag" ? "warning" : "success";
|
|
1114
|
+
return new Text(theme.fg(color, `${d.gateId}: ${d.verdict}`), 0, 0);
|
|
1084
1115
|
},
|
|
1085
1116
|
};
|
|
1086
1117
|
|