gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0-dev.aeeb2ca00
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -17
- package/dist/claude-cli-check.js +46 -10
- package/dist/headless.js +49 -4
- package/dist/resource-loader.d.ts +40 -0
- package/dist/resource-loader.js +32 -13
- package/dist/resources/extensions/browser-tools/capture.js +9 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
- package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +72 -16
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
- package/dist/resources/extensions/github-sync/templates.js +103 -0
- package/dist/resources/extensions/google-search/index.js +3 -2
- package/dist/resources/extensions/gsd/auto/loop.js +124 -2
- package/dist/resources/extensions/gsd/auto/phases.js +57 -39
- package/dist/resources/extensions/gsd/auto/session.js +6 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
- package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
- package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
- package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
- package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
- package/dist/resources/extensions/gsd/auto-start.js +107 -29
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
- package/dist/resources/extensions/gsd/auto.js +76 -21
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
- package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
- package/dist/resources/extensions/gsd/component-loader.js +447 -0
- package/dist/resources/extensions/gsd/component-types.js +69 -0
- package/dist/resources/extensions/gsd/context-store.js +23 -7
- package/dist/resources/extensions/gsd/detection.js +49 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/forensics.js +106 -0
- package/dist/resources/extensions/gsd/gate-registry.js +2 -2
- package/dist/resources/extensions/gsd/git-constants.js +28 -1
- package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
- package/dist/resources/extensions/gsd/git-service.js +126 -2
- package/dist/resources/extensions/gsd/gsd-db.js +6 -3
- package/dist/resources/extensions/gsd/guided-flow.js +39 -13
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
- package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
- package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
- package/dist/resources/extensions/gsd/model-router.js +6 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
- package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
- package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
- package/dist/resources/extensions/gsd/service-tier.js +5 -2
- package/dist/resources/extensions/gsd/session-lock.js +19 -10
- package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
- package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
- package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
- package/dist/resources/extensions/gsd/state.js +69 -58
- package/dist/resources/extensions/gsd/sync-lock.js +98 -42
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
- package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
- package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
- package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
- package/dist/resources/extensions/gsd/uok/writer.js +82 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
- package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
- package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
- package/dist/resources/extensions/mcp-client/index.js +3 -1
- package/dist/resources/extensions/ollama/index.js +5 -1
- package/dist/resources/extensions/remote-questions/manager.js +11 -5
- 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 +11 -11
- 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/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/api/git/route.js +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 +11 -11
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- 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/package.json +2 -3
- package/packages/daemon/package.json +2 -2
- package/packages/daemon/src/logger.ts +4 -3
- package/packages/mcp-server/dist/server.d.ts +24 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +88 -87
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +15 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/mcp-server.test.ts +25 -3
- package/packages/mcp-server/src/readers/graph.test.ts +87 -15
- package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
- package/packages/mcp-server/src/server.ts +131 -105
- package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
- package/packages/mcp-server/src/workflow-tools.ts +19 -6
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +2 -2
- package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
- package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
- package/packages/native/src/__tests__/ps.test.mjs +14 -8
- package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
- package/packages/native/src/__tests__/truncate.test.mjs +17 -2
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
- package/packages/pi-agent-core/src/agent.test.ts +96 -102
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/capability-patches.js +9 -2
- package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
- package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +43 -70
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +36 -11
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +44 -0
- package/packages/pi-ai/src/models/capability-patches.ts +10 -2
- package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
- package/packages/pi-ai/src/models/generated/openai.ts +17 -0
- package/packages/pi-ai/src/models.generated.test.ts +46 -73
- package/packages/pi-ai/src/models.test.ts +48 -11
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
- 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-model-switch.test.js +75 -12
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
- 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 +105 -13
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
- package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
- package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
- package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
- package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
- package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
- package/packages/pi-tui/dist/components/editor.d.ts +14 -0
- package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/editor.js +19 -0
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.js +6 -5
- package/packages/pi-tui/dist/components/image.test.js.map +1 -1
- package/packages/pi-tui/dist/editor-component.d.ts +2 -0
- package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
- package/packages/pi-tui/dist/editor-component.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
- package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
- package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
- package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
- package/packages/pi-tui/src/components/editor.ts +22 -0
- package/packages/pi-tui/src/components/image.test.ts +10 -5
- package/packages/pi-tui/src/editor-component.ts +3 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/dist/rpc-client.test.js +101 -51
- package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/src/rpc-client.test.ts +109 -52
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/scripts/install.js +15 -1
- package/src/resources/extensions/browser-tools/capture.ts +12 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
- package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +75 -16
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
- package/src/resources/extensions/github-sync/templates.ts +151 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
- package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
- package/src/resources/extensions/google-search/index.ts +3 -2
- package/src/resources/extensions/gsd/auto/loop.ts +142 -2
- package/src/resources/extensions/gsd/auto/phases.ts +62 -38
- package/src/resources/extensions/gsd/auto/session.ts +7 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
- package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
- package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
- package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
- package/src/resources/extensions/gsd/auto-start.ts +127 -9
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
- package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
- package/src/resources/extensions/gsd/auto.ts +90 -23
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
- package/src/resources/extensions/gsd/component-loader.ts +598 -0
- package/src/resources/extensions/gsd/component-types.ts +362 -0
- package/src/resources/extensions/gsd/context-store.ts +25 -8
- package/src/resources/extensions/gsd/detection.ts +58 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/forensics.ts +118 -1
- package/src/resources/extensions/gsd/gate-registry.ts +2 -2
- package/src/resources/extensions/gsd/git-constants.ts +30 -1
- package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
- package/src/resources/extensions/gsd/git-service.ts +149 -2
- package/src/resources/extensions/gsd/gsd-db.ts +6 -3
- package/src/resources/extensions/gsd/guided-flow.ts +57 -14
- package/src/resources/extensions/gsd/journal.ts +11 -1
- package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
- package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
- package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
- package/src/resources/extensions/gsd/model-router.ts +6 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
- package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
- package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
- package/src/resources/extensions/gsd/service-tier.ts +5 -2
- package/src/resources/extensions/gsd/session-lock.ts +20 -10
- package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
- package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
- package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
- package/src/resources/extensions/gsd/state.ts +76 -66
- package/src/resources/extensions/gsd/sync-lock.ts +97 -39
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
- package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
- package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
- package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
- package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
- package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
- package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
- package/src/resources/extensions/gsd/types.ts +3 -3
- package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
- package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
- package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
- package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
- package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
- package/src/resources/extensions/gsd/uok/writer.ts +113 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
- package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
- package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
- package/src/resources/extensions/mcp-client/index.ts +3 -1
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
- package/src/resources/extensions/ollama/index.ts +5 -1
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
- package/src/resources/extensions/remote-questions/manager.ts +36 -4
- package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
- package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
- package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
- package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
- package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_ssgManifest.js +0 -0
|
@@ -223,6 +223,84 @@ test("selectAndApplyModel honors explicit phase models without downgrading (#361
|
|
|
223
223
|
}
|
|
224
224
|
});
|
|
225
225
|
|
|
226
|
+
test("selectAndApplyModel escalates dynamic routing tier when retry metadata is provided", async (t) => {
|
|
227
|
+
const originalCwd = process.cwd();
|
|
228
|
+
const originalGsdHome = process.env.GSD_HOME;
|
|
229
|
+
const tempProject = makeTempDir("gsd-routing-retry-project-");
|
|
230
|
+
const tempGsdHome = makeTempDir("gsd-routing-retry-home-");
|
|
231
|
+
const setModelCalls: string[] = [];
|
|
232
|
+
const notifications: Array<{ message: string; level: string }> = [];
|
|
233
|
+
|
|
234
|
+
t.after(() => {
|
|
235
|
+
process.chdir(originalCwd);
|
|
236
|
+
if (originalGsdHome === undefined) delete process.env.GSD_HOME;
|
|
237
|
+
else process.env.GSD_HOME = originalGsdHome;
|
|
238
|
+
rmSync(tempProject, { recursive: true, force: true });
|
|
239
|
+
rmSync(tempGsdHome, { recursive: true, force: true });
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
mkdirSync(join(tempProject, ".gsd"), { recursive: true });
|
|
243
|
+
writeFileSync(
|
|
244
|
+
join(tempProject, ".gsd", "PREFERENCES.md"),
|
|
245
|
+
[
|
|
246
|
+
"---",
|
|
247
|
+
"dynamic_routing:",
|
|
248
|
+
" enabled: true",
|
|
249
|
+
" hooks: false",
|
|
250
|
+
" budget_pressure: false",
|
|
251
|
+
" tier_models:",
|
|
252
|
+
" light: claude-haiku-4-5",
|
|
253
|
+
" standard: claude-sonnet-4-6",
|
|
254
|
+
" heavy: claude-opus-4-6",
|
|
255
|
+
"---",
|
|
256
|
+
].join("\n"),
|
|
257
|
+
"utf-8",
|
|
258
|
+
);
|
|
259
|
+
process.env.GSD_HOME = tempGsdHome;
|
|
260
|
+
process.chdir(tempProject);
|
|
261
|
+
|
|
262
|
+
const availableModels = [
|
|
263
|
+
{ id: "claude-haiku-4-5", provider: "anthropic", api: "anthropic-messages" },
|
|
264
|
+
{ id: "claude-sonnet-4-6", provider: "anthropic", api: "anthropic-messages" },
|
|
265
|
+
{ id: "claude-opus-4-6", provider: "anthropic", api: "anthropic-messages" },
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
const result = await selectAndApplyModel(
|
|
269
|
+
{
|
|
270
|
+
modelRegistry: { getAvailable: () => availableModels },
|
|
271
|
+
sessionManager: { getSessionId: () => "test-session" },
|
|
272
|
+
ui: { notify: (message: string, level: string) => notifications.push({ message, level }) },
|
|
273
|
+
model: { provider: "anthropic", id: "claude-opus-4-6", api: "anthropic-messages" },
|
|
274
|
+
} as any,
|
|
275
|
+
{
|
|
276
|
+
setModel: async (model: { provider: string; id: string }) => {
|
|
277
|
+
setModelCalls.push(`${model.provider}/${model.id}`);
|
|
278
|
+
return true;
|
|
279
|
+
},
|
|
280
|
+
emitBeforeModelSelect: async () => undefined,
|
|
281
|
+
getActiveTools: () => [],
|
|
282
|
+
emitAdjustToolSet: async () => undefined,
|
|
283
|
+
setActiveTools: () => {},
|
|
284
|
+
} as any,
|
|
285
|
+
"execute-task",
|
|
286
|
+
"M001/S01/T01",
|
|
287
|
+
tempProject,
|
|
288
|
+
undefined,
|
|
289
|
+
false,
|
|
290
|
+
{ provider: "anthropic", id: "claude-opus-4-6" },
|
|
291
|
+
{ isRetry: true, previousTier: "light" },
|
|
292
|
+
true,
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
assert.deepEqual(setModelCalls, ["anthropic/claude-sonnet-4-6"]);
|
|
296
|
+
assert.deepEqual(result.routing, { tier: "standard", modelDowngraded: true });
|
|
297
|
+
assert.equal(result.appliedModel?.id, "claude-sonnet-4-6");
|
|
298
|
+
assert.ok(
|
|
299
|
+
notifications.some(n => n.message.includes("Tier escalation: light") && n.message.includes("standard")),
|
|
300
|
+
"retry metadata should produce a visible tier escalation notification",
|
|
301
|
+
);
|
|
302
|
+
});
|
|
303
|
+
|
|
226
304
|
// ─── resolveModelId tests ─────────────────────────────────────────────────
|
|
227
305
|
|
|
228
306
|
test("resolveModelId: bare ID resolves to claude-code when session is claude-code (#3772)", () => {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import { runFinalize } from "../auto/phases.ts";
|
|
5
|
+
import { AutoSession } from "../auto/session.ts";
|
|
6
|
+
|
|
7
|
+
test("runFinalize clears currentUnit after successful finalize", async () => {
|
|
8
|
+
const s = new AutoSession();
|
|
9
|
+
s.basePath = "/tmp/gsd-finalize-current-unit";
|
|
10
|
+
s.currentUnit = {
|
|
11
|
+
type: "execute-task",
|
|
12
|
+
id: "M001/S01/T01",
|
|
13
|
+
startedAt: Date.now(),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const deps = {
|
|
17
|
+
clearUnitTimeout() {},
|
|
18
|
+
buildSnapshotOpts() {
|
|
19
|
+
return {};
|
|
20
|
+
},
|
|
21
|
+
stopAuto: async () => {},
|
|
22
|
+
pauseAuto: async () => {},
|
|
23
|
+
updateProgressWidget() {},
|
|
24
|
+
postUnitPreVerification: async () => "continue",
|
|
25
|
+
runPostUnitVerification: async () => "continue",
|
|
26
|
+
postUnitPostVerification: async () => "continue",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const result = await runFinalize(
|
|
30
|
+
{
|
|
31
|
+
ctx: { ui: { notify() {} } },
|
|
32
|
+
pi: {},
|
|
33
|
+
s,
|
|
34
|
+
deps,
|
|
35
|
+
prefs: undefined,
|
|
36
|
+
iteration: 1,
|
|
37
|
+
flowId: "flow-1",
|
|
38
|
+
nextSeq: () => 1,
|
|
39
|
+
} as any,
|
|
40
|
+
{
|
|
41
|
+
unitType: "execute-task",
|
|
42
|
+
unitId: "M001/S01/T01",
|
|
43
|
+
prompt: "",
|
|
44
|
+
finalPrompt: "",
|
|
45
|
+
pauseAfterUatDispatch: false,
|
|
46
|
+
state: {} as any,
|
|
47
|
+
mid: "M001",
|
|
48
|
+
midTitle: "Milestone",
|
|
49
|
+
isRetry: false,
|
|
50
|
+
previousTier: undefined,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
recentUnits: [],
|
|
54
|
+
stuckRecoveryAttempts: 0,
|
|
55
|
+
consecutiveFinalizeTimeouts: 0,
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
assert.equal(result.action, "next");
|
|
60
|
+
assert.equal(s.currentUnit, null);
|
|
61
|
+
});
|
|
@@ -657,6 +657,80 @@ test("hasImplementationArtifacts returns true when implementation files committe
|
|
|
657
657
|
}
|
|
658
658
|
});
|
|
659
659
|
|
|
660
|
+
test("hasImplementationArtifacts finds milestone implementation commits after retry resumes on main (#4699)", () => {
|
|
661
|
+
const base = makeGitBase();
|
|
662
|
+
try {
|
|
663
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
664
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), "# Roadmap");
|
|
665
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
666
|
+
execFileSync("git", ["commit", "-m", "chore: auto-commit after plan-milestone\n\nGSD-Unit: M001"], { cwd: base, stdio: "ignore" });
|
|
667
|
+
|
|
668
|
+
mkdirSync(join(base, "src"), { recursive: true });
|
|
669
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
670
|
+
writeFileSync(join(base, "src", "feature.ts"), "export function feature() {}");
|
|
671
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-SUMMARY.md"), "# Summary");
|
|
672
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
673
|
+
execFileSync("git", ["commit", "-m", "feat: add milestone feature\n\nGSD-Task: S01/T01"], { cwd: base, stdio: "ignore" });
|
|
674
|
+
|
|
675
|
+
const result = hasImplementationArtifacts(base, "M001");
|
|
676
|
+
assert.equal(result, "present", "main self-diff retry should find production execute-task commits");
|
|
677
|
+
} finally {
|
|
678
|
+
cleanup(base);
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
test("hasImplementationArtifacts rejects milestone-scoped main history with only .gsd commits (#4699)", () => {
|
|
683
|
+
const base = makeGitBase();
|
|
684
|
+
try {
|
|
685
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
686
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), "# Roadmap");
|
|
687
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-SUMMARY.md"), "# Summary");
|
|
688
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
689
|
+
execFileSync("git", ["commit", "-m", "chore: auto-commit after complete-milestone\n\nGSD-Unit: M001"], { cwd: base, stdio: "ignore" });
|
|
690
|
+
|
|
691
|
+
const result = hasImplementationArtifacts(base, "M001");
|
|
692
|
+
assert.equal(result, "absent", "milestone-scoped fallback must not treat .gsd-only commits as implementation");
|
|
693
|
+
} finally {
|
|
694
|
+
cleanup(base);
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
test("hasImplementationArtifacts treats empty non-integration branch diff as absent (#4699)", () => {
|
|
699
|
+
const base = makeGitBase();
|
|
700
|
+
try {
|
|
701
|
+
execFileSync("git", ["checkout", "-b", "feat/empty-milestone"], { cwd: base, stdio: "ignore" });
|
|
702
|
+
|
|
703
|
+
const result = hasImplementationArtifacts(base, "M001");
|
|
704
|
+
assert.equal(result, "absent", "empty milestone branch diffs should not use main retry fallback");
|
|
705
|
+
} finally {
|
|
706
|
+
cleanup(base);
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
test("hasImplementationArtifacts uses milestone path history instead of rolling depth (#4699)", () => {
|
|
711
|
+
const base = makeGitBase();
|
|
712
|
+
try {
|
|
713
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
714
|
+
mkdirSync(join(base, "src"), { recursive: true });
|
|
715
|
+
writeFileSync(join(base, "src", "feature.ts"), "export function feature() {}");
|
|
716
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-SUMMARY.md"), "# Summary");
|
|
717
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
718
|
+
execFileSync("git", ["commit", "-m", "feat: old milestone implementation\n\nGSD-Task: S01/T01"], { cwd: base, stdio: "ignore" });
|
|
719
|
+
|
|
720
|
+
mkdirSync(join(base, "docs"), { recursive: true });
|
|
721
|
+
for (let i = 0; i < 205; i++) {
|
|
722
|
+
writeFileSync(join(base, "docs", `note-${i}.md`), `# Note ${i}\n`);
|
|
723
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
724
|
+
execFileSync("git", ["commit", "-m", `docs: filler ${i}`], { cwd: base, stdio: "ignore" });
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const result = hasImplementationArtifacts(base, "M001");
|
|
728
|
+
assert.equal(result, "present", "milestone evidence should not age out after 200 unrelated commits");
|
|
729
|
+
} finally {
|
|
730
|
+
cleanup(base);
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
|
|
660
734
|
test("hasImplementationArtifacts returns true on non-git directory (fail-open)", () => {
|
|
661
735
|
const base = join(tmpdir(), `gsd-test-nogit-${randomUUID()}`);
|
|
662
736
|
mkdirSync(base, { recursive: true });
|
|
@@ -706,6 +780,25 @@ test("verifyExpectedArtifact complete-milestone passes with impl files (#1703)",
|
|
|
706
780
|
}
|
|
707
781
|
});
|
|
708
782
|
|
|
783
|
+
test("verifyExpectedArtifact complete-milestone passes on main retry with milestone implementation commits (#4699)", () => {
|
|
784
|
+
const base = makeGitBase();
|
|
785
|
+
try {
|
|
786
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
787
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-SUMMARY.md"), "# Milestone Summary\nDone.");
|
|
788
|
+
mkdirSync(join(base, "src"), { recursive: true });
|
|
789
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
790
|
+
writeFileSync(join(base, "src", "app.ts"), "console.log('hello');");
|
|
791
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-SUMMARY.md"), "# Summary");
|
|
792
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
793
|
+
execFileSync("git", ["commit", "-m", "feat: implementation already on main\n\nGSD-Task: S01/T01"], { cwd: base, stdio: "ignore" });
|
|
794
|
+
|
|
795
|
+
const result = verifyExpectedArtifact("complete-milestone", "M001", base);
|
|
796
|
+
assert.equal(result, true, "complete-milestone should not fail solely because HEAD vs main is a self-diff");
|
|
797
|
+
} finally {
|
|
798
|
+
cleanup(base);
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
|
|
709
802
|
test("verifyExpectedArtifact complete-milestone fails when DB milestone is not complete (#4658)", () => {
|
|
710
803
|
const base = makeGitBase();
|
|
711
804
|
try {
|
|
@@ -15,6 +15,7 @@ import assert from 'node:assert/strict';
|
|
|
15
15
|
import { readFileSync } from 'node:fs';
|
|
16
16
|
import { fileURLToPath } from 'node:url';
|
|
17
17
|
import { dirname, join } from 'node:path';
|
|
18
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
18
19
|
|
|
19
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
20
21
|
const __dirname = dirname(__filename);
|
|
@@ -43,7 +44,9 @@ describe('auto-remediate stale slice status (#3673)', () => {
|
|
|
43
44
|
assert.match(before, /try\s*\{/,
|
|
44
45
|
'updateSliceStatus should be inside a try block');
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
// Bound the region to stop before the rogue fallback so /catch/ only
|
|
48
|
+
// matches this try block's catch, not an unrelated later one.
|
|
49
|
+
const after = extractSourceRegion(source, 'updateSliceStatus(mid, sid', 'rogues.push({');
|
|
47
50
|
assert.match(after, /catch/,
|
|
48
51
|
'try block should have a catch for fallback');
|
|
49
52
|
});
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Regression tests for PR #4288 — auto-retry bug, .mcp.json churn, and MCP
|
|
3
|
-
* worktree routing fixes.
|
|
3
|
+
* worktree routing fixes (behaviour subset).
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* The remaining 13 structural assertions (source-grep against register-hooks,
|
|
6
|
+
* auto-recovery, workflow-tools) were removed in favour of follow-up issues
|
|
7
|
+
* tracking a pure-helper extraction per the #4832/PR #4859 precedent. This
|
|
8
|
+
* file retains only the real behaviour tests against the public API of
|
|
9
|
+
* evidence-collector.
|
|
10
|
+
*
|
|
11
|
+
* Follow-ups filed for the removed coverage — see PR body.
|
|
10
12
|
*
|
|
11
13
|
* Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
import { describe, it, beforeEach } from "node:test";
|
|
15
17
|
import assert from "node:assert/strict";
|
|
16
|
-
import { readFileSync } from "node:fs";
|
|
17
|
-
import { resolve } from "node:path";
|
|
18
18
|
|
|
19
19
|
import {
|
|
20
20
|
resetEvidence,
|
|
@@ -24,8 +24,6 @@ import {
|
|
|
24
24
|
type BashEvidence,
|
|
25
25
|
} from "../safety/evidence-collector.js";
|
|
26
26
|
|
|
27
|
-
// ─── 1. evidence-collector: functional ─────────────────────────────────────
|
|
28
|
-
|
|
29
27
|
describe("evidence-collector: toolCallId-based matching (A-3)", () => {
|
|
30
28
|
beforeEach(() => {
|
|
31
29
|
resetEvidence();
|
|
@@ -42,14 +40,9 @@ describe("evidence-collector: toolCallId-based matching (A-3)", () => {
|
|
|
42
40
|
});
|
|
43
41
|
|
|
44
42
|
it("matches results to the correct entry by toolCallId, not insertion order", () => {
|
|
45
|
-
// Simulate two parallel bash calls dispatched in order tc-1, tc-2.
|
|
46
43
|
recordToolCall("tc-1", "bash", { command: "slow-thing" });
|
|
47
44
|
recordToolCall("tc-2", "bash", { command: "fast-thing" });
|
|
48
45
|
|
|
49
|
-
// Results arrive out of order: tc-2 first (fast), then tc-1 (slow).
|
|
50
|
-
// With the old empty-string-matching strategy, tc-2's result would be
|
|
51
|
-
// stapled to tc-1's entry because findLastUnresolved scanned backwards
|
|
52
|
-
// for empty ids. Now we match by id directly.
|
|
53
46
|
recordToolResult("tc-2", "bash", "Command exited with code 0\nfast-output", false);
|
|
54
47
|
recordToolResult("tc-1", "bash", "Command exited with code 1\nslow-failure", true);
|
|
55
48
|
|
|
@@ -59,9 +52,6 @@ describe("evidence-collector: toolCallId-based matching (A-3)", () => {
|
|
|
59
52
|
|
|
60
53
|
assert.ok(tc1, "tc-1 entry must exist");
|
|
61
54
|
assert.ok(tc2, "tc-2 entry must exist");
|
|
62
|
-
|
|
63
|
-
// The original command stays attached to the entry it was recorded with,
|
|
64
|
-
// and the result matches the id it was reported for.
|
|
65
55
|
assert.equal(tc1.command, "slow-thing");
|
|
66
56
|
assert.equal(tc1.exitCode, 1);
|
|
67
57
|
assert.ok(tc1.outputSnippet.includes("slow-failure"));
|
|
@@ -78,7 +68,6 @@ describe("evidence-collector: toolCallId-based matching (A-3)", () => {
|
|
|
78
68
|
const entries = getEvidence() as readonly BashEvidence[];
|
|
79
69
|
assert.equal(entries.length, 1);
|
|
80
70
|
assert.equal(entries[0].toolCallId, "tc-1");
|
|
81
|
-
// tc-1 must be untouched — no result was reported for it.
|
|
82
71
|
assert.equal(entries[0].exitCode, -1);
|
|
83
72
|
assert.equal(entries[0].outputSnippet, "");
|
|
84
73
|
});
|
|
@@ -95,178 +84,3 @@ describe("evidence-collector: toolCallId-based matching (A-3)", () => {
|
|
|
95
84
|
assert.equal(entries[1].toolCallId, "tc-edit");
|
|
96
85
|
});
|
|
97
86
|
});
|
|
98
|
-
|
|
99
|
-
// ─── 2. register-hooks: MCP auto-prep gated inside auto-worktrees (A-1) ────
|
|
100
|
-
|
|
101
|
-
describe("register-hooks: skip prepareWorkflowMcpForProject inside auto-worktrees (A-1)", () => {
|
|
102
|
-
const src = readFileSync(
|
|
103
|
-
resolve(process.cwd(), "src", "resources", "extensions", "gsd", "bootstrap", "register-hooks.ts"),
|
|
104
|
-
"utf-8",
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
it("session_start hook is gated on isInAutoWorktree", () => {
|
|
108
|
-
const idx = src.indexOf('pi.on("session_start"');
|
|
109
|
-
assert.ok(idx !== -1, "session_start handler must exist");
|
|
110
|
-
const block = src.slice(idx, idx + 2500);
|
|
111
|
-
assert.ok(
|
|
112
|
-
block.includes("isInAutoWorktree"),
|
|
113
|
-
"session_start must consult isInAutoWorktree before preparing MCP",
|
|
114
|
-
);
|
|
115
|
-
assert.ok(
|
|
116
|
-
block.includes("prepareWorkflowMcpForProject"),
|
|
117
|
-
"session_start still prepares MCP for non-worktree paths",
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it("session_switch hook is gated on isInAutoWorktree", () => {
|
|
122
|
-
const idx = src.indexOf('pi.on("session_switch"');
|
|
123
|
-
assert.ok(idx !== -1, "session_switch handler must exist");
|
|
124
|
-
const block = src.slice(idx, idx + 2500);
|
|
125
|
-
assert.ok(
|
|
126
|
-
block.includes("isInAutoWorktree"),
|
|
127
|
-
"session_switch must consult isInAutoWorktree before preparing MCP",
|
|
128
|
-
);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it("tool_call hook forwards event.toolCallId into safetyRecordToolCall (A-3)", () => {
|
|
132
|
-
// Find the call site (skip the import line by looking for the opening paren).
|
|
133
|
-
const idx = src.indexOf("safetyRecordToolCall(");
|
|
134
|
-
assert.ok(idx !== -1, "safetyRecordToolCall call must exist");
|
|
135
|
-
const line = src.slice(idx, src.indexOf("\n", idx));
|
|
136
|
-
assert.ok(
|
|
137
|
-
line.includes("event.toolCallId"),
|
|
138
|
-
"safetyRecordToolCall must receive event.toolCallId as the first argument",
|
|
139
|
-
);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// ─── 3. auto-recovery: verify-fail instrumentation ─────────────────────────
|
|
144
|
-
|
|
145
|
-
describe("verifyExpectedArtifact: verify-fail exit-point logging (Phase B diag)", () => {
|
|
146
|
-
const src = readFileSync(
|
|
147
|
-
resolve(process.cwd(), "src", "resources", "extensions", "gsd", "auto-recovery.ts"),
|
|
148
|
-
"utf-8",
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
it("logs a verify-fail warning on the null-absPath exit", () => {
|
|
152
|
-
assert.ok(
|
|
153
|
-
src.includes('verify-fail ${unitType} ${unitId}: resolveExpectedArtifactPath returned null'),
|
|
154
|
-
"null-absPath branch must emit a diagnostic line",
|
|
155
|
-
);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it("logs a verify-fail warning on the existsSync-false exit", () => {
|
|
159
|
-
assert.ok(
|
|
160
|
-
src.includes("verify-fail ${unitType} ${unitId}: existsSync false"),
|
|
161
|
-
"existsSync-false branch must emit a diagnostic line",
|
|
162
|
-
);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it("logs a verify-fail warning on the plan-slice no-task-entry exit", () => {
|
|
166
|
-
assert.ok(
|
|
167
|
-
src.includes("verify-fail ${unitType} ${unitId}: plan has no task checkbox/heading"),
|
|
168
|
-
"plan-slice no-task branch must emit a diagnostic line",
|
|
169
|
-
);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("plan-slice task-plan-files check fails fast on missing tasks dir (hardening)", () => {
|
|
173
|
-
// The original check silently passed when resolveTasksDir returned null.
|
|
174
|
-
// The new check returns false with a diagnostic, which is correct — if
|
|
175
|
-
// the tool successfully planned tasks, the tasks/ dir must exist.
|
|
176
|
-
const idx = src.indexOf('verify-fail ${unitType} ${unitId}: resolveTasksDir returned null');
|
|
177
|
-
assert.ok(
|
|
178
|
-
idx !== -1,
|
|
179
|
-
"resolveTasksDir-null branch must emit a diagnostic and return false",
|
|
180
|
-
);
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// ─── 4. workflow-tools (mcp-server): guard + optional projectDir + routing ─
|
|
185
|
-
|
|
186
|
-
describe("mcp-server workflow-tools: projectDir routing (Phase B root cause)", () => {
|
|
187
|
-
const src = readFileSync(
|
|
188
|
-
resolve(process.cwd(), "packages", "mcp-server", "src", "workflow-tools.ts"),
|
|
189
|
-
"utf-8",
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
it("projectDirParam is optional and documents the default", () => {
|
|
193
|
-
const idx = src.indexOf("const projectDirParam");
|
|
194
|
-
assert.ok(idx !== -1, "projectDirParam definition must exist");
|
|
195
|
-
const block = src.slice(idx, idx + 600);
|
|
196
|
-
assert.ok(
|
|
197
|
-
block.includes(".optional()"),
|
|
198
|
-
"projectDirParam must be optional so the agent stops deliberating",
|
|
199
|
-
);
|
|
200
|
-
assert.ok(
|
|
201
|
-
/Omit this field/i.test(block),
|
|
202
|
-
"description must tell the agent to omit the field",
|
|
203
|
-
);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it("parseWorkflowArgs defaults projectDir to process.cwd() when omitted", () => {
|
|
207
|
-
const idx = src.indexOf("function parseWorkflowArgs");
|
|
208
|
-
assert.ok(idx !== -1, "parseWorkflowArgs must exist");
|
|
209
|
-
const block = src.slice(idx, idx + 1500);
|
|
210
|
-
assert.ok(
|
|
211
|
-
block.includes("parsed.projectDir ?? process.cwd()"),
|
|
212
|
-
"parseWorkflowArgs must fall back to process.cwd() when projectDir is omitted",
|
|
213
|
-
);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it("validateProjectDir accepts external-state worktree paths via .gsd symlink target", () => {
|
|
217
|
-
const idx = src.indexOf("function validateProjectDir");
|
|
218
|
-
assert.ok(idx !== -1, "validateProjectDir must exist");
|
|
219
|
-
const block = src.slice(idx, idx + 2500);
|
|
220
|
-
assert.ok(
|
|
221
|
-
block.includes("resolveExternalStateRoot"),
|
|
222
|
-
"validateProjectDir must consult resolveExternalStateRoot for external-state layouts",
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
const helperIdx = src.indexOf("function resolveExternalStateRoot");
|
|
226
|
-
assert.ok(helperIdx !== -1, "resolveExternalStateRoot helper must exist");
|
|
227
|
-
const helperBlock = src.slice(helperIdx, helperIdx + 600);
|
|
228
|
-
assert.ok(
|
|
229
|
-
helperBlock.includes("realpathSync"),
|
|
230
|
-
"resolveExternalStateRoot must use realpathSync to follow the symlink",
|
|
231
|
-
);
|
|
232
|
-
assert.ok(
|
|
233
|
-
/join\([^)]*\.gsd/.test(helperBlock),
|
|
234
|
-
"resolveExternalStateRoot must resolve <allowedRoot>/.gsd",
|
|
235
|
-
);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it("parseWorkflowArgs routes tool writes to the active worktree when one exists", () => {
|
|
239
|
-
// This is the Phase B root-cause fix: when the tool call is scoped to a
|
|
240
|
-
// milestone that has an auto-worktree at <projectRoot>/.gsd/worktrees/<MID>/,
|
|
241
|
-
// tool writes must go to the worktree .gsd rather than the shared project .gsd.
|
|
242
|
-
const parseIdx = src.indexOf("function parseWorkflowArgs");
|
|
243
|
-
const parseBlock = src.slice(parseIdx, parseIdx + 2500);
|
|
244
|
-
assert.ok(
|
|
245
|
-
parseBlock.includes("resolveActiveWorktreeBasePath"),
|
|
246
|
-
"parseWorkflowArgs must consult resolveActiveWorktreeBasePath",
|
|
247
|
-
);
|
|
248
|
-
assert.ok(
|
|
249
|
-
parseBlock.includes("extractMilestoneId"),
|
|
250
|
-
"parseWorkflowArgs must extract the milestoneId to locate the worktree",
|
|
251
|
-
);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
it("resolveActiveWorktreeBasePath checks .git presence to avoid hijacking stray directories", () => {
|
|
255
|
-
const idx = src.indexOf("function resolveActiveWorktreeBasePath");
|
|
256
|
-
assert.ok(idx !== -1, "resolveActiveWorktreeBasePath helper must exist");
|
|
257
|
-
const block = src.slice(idx, idx + 1200);
|
|
258
|
-
assert.ok(
|
|
259
|
-
block.includes('existsSync(join(wtPath, ".git"))'),
|
|
260
|
-
"resolveActiveWorktreeBasePath must verify a .git file exists in the worktree",
|
|
261
|
-
);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("extractMilestoneId handles camelCase, snake_case, and short aliases", () => {
|
|
265
|
-
const idx = src.indexOf("function extractMilestoneId");
|
|
266
|
-
assert.ok(idx !== -1, "extractMilestoneId helper must exist");
|
|
267
|
-
const block = src.slice(idx, idx + 600);
|
|
268
|
-
assert.ok(block.includes("milestoneId"), "must check milestoneId");
|
|
269
|
-
assert.ok(block.includes("milestone_id"), "must check milestone_id");
|
|
270
|
-
assert.ok(block.includes("mid"), "must check mid");
|
|
271
|
-
});
|
|
272
|
-
});
|
|
@@ -10,6 +10,7 @@ import assert from "node:assert/strict";
|
|
|
10
10
|
import { readFileSync } from "node:fs";
|
|
11
11
|
import { join, dirname } from "node:path";
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
13
14
|
|
|
14
15
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
16
|
const sourceFile = join(__dirname, "..", "auto-start.ts");
|
|
@@ -37,7 +38,7 @@ describe("auto-start cleanStaleRuntimeUnits DB gating (#4663)", () => {
|
|
|
37
38
|
test("cleanStaleRuntimeUnits predicate consults DB status when available", () => {
|
|
38
39
|
const cleanIdx = source.indexOf("cleanStaleRuntimeUnits(");
|
|
39
40
|
assert.ok(cleanIdx > -1);
|
|
40
|
-
const snippet = source
|
|
41
|
+
const snippet = extractSourceRegion(source, "cleanStaleRuntimeUnits(");
|
|
41
42
|
assert.match(
|
|
42
43
|
snippet,
|
|
43
44
|
/isDbAvailable\(\)/,
|
|
@@ -53,7 +54,7 @@ describe("auto-start cleanStaleRuntimeUnits DB gating (#4663)", () => {
|
|
|
53
54
|
test("cleanStaleRuntimeUnits predicate still falls back to SUMMARY-file when DB unavailable", () => {
|
|
54
55
|
const cleanIdx = source.indexOf("cleanStaleRuntimeUnits(");
|
|
55
56
|
assert.ok(cleanIdx > -1);
|
|
56
|
-
const snippet = source
|
|
57
|
+
const snippet = extractSourceRegion(source, "cleanStaleRuntimeUnits(");
|
|
57
58
|
assert.match(
|
|
58
59
|
snippet,
|
|
59
60
|
/resolveMilestoneFile\(base,\s*mid,\s*["']SUMMARY["']\)/,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {createTestContext, extractSourceRegion } from "./test-helpers.ts";
|
|
5
5
|
|
|
6
6
|
const { assertTrue, report } = createTestContext();
|
|
7
7
|
|
|
@@ -13,7 +13,7 @@ console.log("\n=== #2841: cold DB opened before initial deriveState ===");
|
|
|
13
13
|
const helperIdx = src.indexOf("async function openProjectDbIfPresent");
|
|
14
14
|
assertTrue(helperIdx >= 0, "auto-start.ts defines a helper for pre-derive DB open (#2841)");
|
|
15
15
|
|
|
16
|
-
const helperRegion = helperIdx >= 0 ? src
|
|
16
|
+
const helperRegion = helperIdx >= 0 ? extractSourceRegion(src, "async function openProjectDbIfPresent") : "";
|
|
17
17
|
assertTrue(
|
|
18
18
|
helperRegion.includes("resolveProjectRootDbPath(basePath)"),
|
|
19
19
|
"pre-derive DB helper resolves the project-root DB path (#2841)",
|
|
@@ -157,62 +157,19 @@ describe("auto-start-needs-discussion (#1726)", () => {
|
|
|
157
157
|
}
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
// Verify needs-discussion IS handled inside the !hasSurvivorBranch block
|
|
177
|
-
const notSurvivorBlock = source.match(
|
|
178
|
-
/if\s*\(!hasSurvivorBranch\)\s*\{([\s\S]*?)\/\/ Unreachable safety check/,
|
|
179
|
-
);
|
|
180
|
-
assert.ok(!!notSurvivorBlock,
|
|
181
|
-
"found !hasSurvivorBranch block in auto-start.ts");
|
|
182
|
-
if (notSurvivorBlock) {
|
|
183
|
-
assert.ok(
|
|
184
|
-
notSurvivorBlock[1].includes('"needs-discussion"'),
|
|
185
|
-
"!hasSurvivorBranch block must handle needs-discussion phase",
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
test("7. Survivor branch + needs-discussion routes to showSmartEntry", () => {
|
|
191
|
-
const source = readAutoStartSource();
|
|
192
|
-
|
|
193
|
-
// When hasSurvivorBranch is true AND phase is needs-discussion, the code
|
|
194
|
-
// must route to showSmartEntry instead of falling through to auto-mode.
|
|
195
|
-
const survivorNeedsDiscussion = source.match(
|
|
196
|
-
/if\s*\(hasSurvivorBranch\s*&&\s*state\.phase\s*===\s*"needs-discussion"\)\s*\{[^}]*showSmartEntry/s,
|
|
197
|
-
);
|
|
198
|
-
assert.ok(!!survivorNeedsDiscussion,
|
|
199
|
-
"hasSurvivorBranch && needs-discussion must route to showSmartEntry");
|
|
200
|
-
|
|
201
|
-
// Verify the handler checks if the discussion succeeded
|
|
202
|
-
const handlerBlock = source.match(
|
|
203
|
-
/if\s*\(hasSurvivorBranch\s*&&\s*state\.phase\s*===\s*"needs-discussion"\)\s*\{([\s\S]*?)\n \}/,
|
|
204
|
-
);
|
|
205
|
-
assert.ok(!!handlerBlock,
|
|
206
|
-
"found survivor + needs-discussion handler block");
|
|
207
|
-
if (handlerBlock) {
|
|
208
|
-
assert.ok(
|
|
209
|
-
handlerBlock[1].includes('postState.phase !== "needs-discussion"'),
|
|
210
|
-
"handler must check if phase advanced after discussion",
|
|
211
|
-
);
|
|
212
|
-
assert.ok(
|
|
213
|
-
handlerBlock[1].includes("releaseLockAndReturn"),
|
|
214
|
-
"handler must abort if discussion didn't promote draft",
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
160
|
+
// Tests 6 and 7 removed in the #4832 follow-up.
|
|
161
|
+
//
|
|
162
|
+
// They source-grepped `auto-start.ts` for specific regex patterns like
|
|
163
|
+
// `if (hasSurvivorBranch && state.phase === "needs-discussion")` —
|
|
164
|
+
// which broke (correctly so) when the three-way survivor decision was
|
|
165
|
+
// extracted into the `decideSurvivorAction` pure helper. The
|
|
166
|
+
// behavioural invariants they were trying to uphold are now covered
|
|
167
|
+
// directly in `survivor-branch-complete.test.ts`:
|
|
168
|
+
// - (hasSurvivor=true, phase="needs-discussion") → "discuss"
|
|
169
|
+
// - (hasSurvivor=false, phase="needs-discussion") → "none"
|
|
170
|
+
// - (hasSurvivor=true, phase=other) → "none"
|
|
171
|
+
// Those tests fail on real decision regressions without the
|
|
172
|
+
// source-grep brittleness. Tests 1–5 above remain — they hit
|
|
173
|
+
// `deriveState` on real fixtures and defend the #1726 infinite-loop
|
|
174
|
+
// fix end-to-end.
|
|
218
175
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {createTestContext, extractSourceRegion } from "./test-helpers.ts";
|
|
5
5
|
|
|
6
6
|
const { assertTrue, report } = createTestContext();
|
|
7
7
|
|
|
@@ -13,7 +13,7 @@ console.log("\n=== #3822: worktree bootstrap uses project DB path ===");
|
|
|
13
13
|
const dbLifecycleIdx = src.indexOf("// ── DB lifecycle ──");
|
|
14
14
|
assertTrue(dbLifecycleIdx > 0, "auto-start.ts has a DB lifecycle section");
|
|
15
15
|
|
|
16
|
-
const dbLifecycleRegion = dbLifecycleIdx > 0 ? src
|
|
16
|
+
const dbLifecycleRegion = dbLifecycleIdx > 0 ? extractSourceRegion(src, "// ── DB lifecycle ──") : "";
|
|
17
17
|
|
|
18
18
|
assertTrue(
|
|
19
19
|
dbLifecycleRegion.includes("const gsdDbPath = resolveProjectRootDbPath(s.basePath);"),
|