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
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
// GSD-2 — #4781 phase 2: dispatch-rule gates read pipeline variant from DB.
|
|
2
|
+
// Behavior tests (not source-grep) — construct a real tmpdir DB, insert a
|
|
3
|
+
// milestone whose planning fields classify to the target variant, exercise
|
|
4
|
+
// DISPATCH_RULES.match(), assert the gate result.
|
|
5
|
+
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { mkdtempSync, mkdirSync, rmSync, existsSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
|
|
12
|
+
import { DISPATCH_RULES, type DispatchContext } from "../auto-dispatch.ts";
|
|
13
|
+
import {
|
|
14
|
+
openDatabase,
|
|
15
|
+
closeDatabase,
|
|
16
|
+
insertMilestone,
|
|
17
|
+
upsertMilestonePlanning,
|
|
18
|
+
insertSlice,
|
|
19
|
+
} from "../gsd-db.ts";
|
|
20
|
+
import { invalidateAllCaches } from "../cache.ts";
|
|
21
|
+
import type { GSDState } from "../types.ts";
|
|
22
|
+
|
|
23
|
+
const PARALLEL_RESEARCH_RULE = "planning (multiple slices need research) → parallel-research-slices";
|
|
24
|
+
const SINGLE_RESEARCH_RULE = "planning (no research, not S01) → research-slice";
|
|
25
|
+
const VALIDATE_RULE = "validating-milestone → validate-milestone";
|
|
26
|
+
|
|
27
|
+
// ─── Fixture helpers ──────────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
function makeBase(): string {
|
|
30
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-pipeline-variant-"));
|
|
31
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
32
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S02", "tasks"), { recursive: true });
|
|
33
|
+
return base;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function cleanup(base: string): void {
|
|
37
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
38
|
+
invalidateAllCaches();
|
|
39
|
+
rmSync(base, { recursive: true, force: true });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface SeedOpts {
|
|
43
|
+
title: string;
|
|
44
|
+
vision: string;
|
|
45
|
+
successCriteria: string[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function seedMilestone(base: string, mid: string, opts: SeedOpts): void {
|
|
49
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
50
|
+
insertMilestone({
|
|
51
|
+
id: mid,
|
|
52
|
+
title: opts.title,
|
|
53
|
+
status: "active",
|
|
54
|
+
depends_on: [],
|
|
55
|
+
});
|
|
56
|
+
upsertMilestonePlanning(mid, {
|
|
57
|
+
title: opts.title,
|
|
58
|
+
status: "active",
|
|
59
|
+
vision: opts.vision,
|
|
60
|
+
successCriteria: opts.successCriteria,
|
|
61
|
+
keyRisks: [],
|
|
62
|
+
proofStrategy: [],
|
|
63
|
+
verificationContract: "",
|
|
64
|
+
verificationIntegration: "",
|
|
65
|
+
verificationOperational: "",
|
|
66
|
+
verificationUat: "",
|
|
67
|
+
definitionOfDone: [],
|
|
68
|
+
requirementCoverage: "",
|
|
69
|
+
boundaryMapMarkdown: "",
|
|
70
|
+
});
|
|
71
|
+
insertSlice({
|
|
72
|
+
id: "S01",
|
|
73
|
+
milestoneId: mid,
|
|
74
|
+
title: "First",
|
|
75
|
+
status: "pending",
|
|
76
|
+
risk: "low",
|
|
77
|
+
depends: [],
|
|
78
|
+
demo: "",
|
|
79
|
+
sequence: 1,
|
|
80
|
+
});
|
|
81
|
+
insertSlice({
|
|
82
|
+
id: "S02",
|
|
83
|
+
milestoneId: mid,
|
|
84
|
+
title: "Second",
|
|
85
|
+
status: "pending",
|
|
86
|
+
risk: "low",
|
|
87
|
+
depends: ["S01"],
|
|
88
|
+
demo: "",
|
|
89
|
+
sequence: 2,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function findRule(name: string) {
|
|
94
|
+
const rule = DISPATCH_RULES.find(r => r.name === name);
|
|
95
|
+
assert.ok(rule, `rule "${name}" must exist`);
|
|
96
|
+
return rule!;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function makeCtx(params: {
|
|
100
|
+
base: string;
|
|
101
|
+
mid: string;
|
|
102
|
+
phase: GSDState["phase"];
|
|
103
|
+
activeSlice?: { id: string; title: string };
|
|
104
|
+
}): DispatchContext {
|
|
105
|
+
const state: GSDState = {
|
|
106
|
+
phase: params.phase,
|
|
107
|
+
activeMilestone: { id: params.mid, title: "Test" },
|
|
108
|
+
activeSlice: params.activeSlice ?? null,
|
|
109
|
+
activeTask: null,
|
|
110
|
+
recentDecisions: [],
|
|
111
|
+
blockers: [],
|
|
112
|
+
nextAction: "",
|
|
113
|
+
registry: [{ id: params.mid, title: "Test", status: "active" }],
|
|
114
|
+
};
|
|
115
|
+
return {
|
|
116
|
+
basePath: params.base,
|
|
117
|
+
mid: params.mid,
|
|
118
|
+
midTitle: "Test",
|
|
119
|
+
state,
|
|
120
|
+
prefs: undefined,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Inputs that consistently classify.
|
|
125
|
+
const TRIVIAL_INPUT: SeedOpts = {
|
|
126
|
+
title: "Static To-Do App",
|
|
127
|
+
vision: "A minimal, clean browser-based to-do app. Pure HTML/CSS/JS, no build step, no backend. Tasks persist in localStorage.",
|
|
128
|
+
successCriteria: [
|
|
129
|
+
"Open index.html in any browser without a server",
|
|
130
|
+
"Tasks survive a page reload via localStorage",
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const STANDARD_INPUT: SeedOpts = {
|
|
135
|
+
title: "Billing API extension",
|
|
136
|
+
vision: "Extend the billing API to charge usage-tier overages. Touch the invoice service, the entitlements cache, and the webhook handler.",
|
|
137
|
+
successCriteria: [
|
|
138
|
+
"Overage charges generate correct invoices",
|
|
139
|
+
"Integration tests cover tier rollovers",
|
|
140
|
+
"API endpoint returns structured error on webhook failure",
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// ─── Research-slice gate (single) ─────────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
test("#4781 phase 2: single research-slice rule skips dispatch for trivial variant", async (t) => {
|
|
147
|
+
const base = makeBase();
|
|
148
|
+
t.after(() => cleanup(base));
|
|
149
|
+
|
|
150
|
+
seedMilestone(base, "M001", TRIVIAL_INPUT);
|
|
151
|
+
const ctx = makeCtx({
|
|
152
|
+
base,
|
|
153
|
+
mid: "M001",
|
|
154
|
+
phase: "planning",
|
|
155
|
+
activeSlice: { id: "S02", title: "Second" },
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const result = await findRule(SINGLE_RESEARCH_RULE).match(ctx);
|
|
159
|
+
assert.strictEqual(result, null, "trivial variant must skip research-slice dispatch");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("#4781 phase 2: single research-slice rule proceeds normally for standard variant", async (t) => {
|
|
163
|
+
const base = makeBase();
|
|
164
|
+
t.after(() => cleanup(base));
|
|
165
|
+
|
|
166
|
+
seedMilestone(base, "M001", STANDARD_INPUT);
|
|
167
|
+
const ctx = makeCtx({
|
|
168
|
+
base,
|
|
169
|
+
mid: "M001",
|
|
170
|
+
phase: "planning",
|
|
171
|
+
activeSlice: { id: "S02", title: "Second" },
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// No RESEARCH file exists → rule should reach the dispatch branch.
|
|
175
|
+
// We don't assert "dispatch" because the prompt builder may error with
|
|
176
|
+
// minimal fixture data; we assert "not null AND not a trivial-skip
|
|
177
|
+
// shortcut" by checking that if null was returned, it's for a known
|
|
178
|
+
// reason (research file exists). For this fixture none exists, so the
|
|
179
|
+
// result should be an action object.
|
|
180
|
+
const result = await findRule(SINGLE_RESEARCH_RULE).match(ctx);
|
|
181
|
+
assert.notStrictEqual(result, null, "standard variant must not short-circuit the research-slice gate");
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// ─── Parallel research-slice gate ─────────────────────────────────────────
|
|
185
|
+
|
|
186
|
+
test("#4781 phase 2: parallel-research-slices rule skips dispatch for trivial variant", async (t) => {
|
|
187
|
+
const base = makeBase();
|
|
188
|
+
t.after(() => cleanup(base));
|
|
189
|
+
|
|
190
|
+
seedMilestone(base, "M001", TRIVIAL_INPUT);
|
|
191
|
+
// Roadmap needs to be readable for the parallel rule to enter its slice
|
|
192
|
+
// analysis. Write a minimal one.
|
|
193
|
+
const { writeFileSync } = await import("node:fs");
|
|
194
|
+
writeFileSync(
|
|
195
|
+
join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
|
|
196
|
+
[
|
|
197
|
+
"# M001",
|
|
198
|
+
"## Slices",
|
|
199
|
+
"- [ ] **S01: First** `risk:low` `depends:[]`",
|
|
200
|
+
"- [ ] **S02: Second** `risk:low` `depends:[]`",
|
|
201
|
+
].join("\n"),
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const ctx = makeCtx({ base, mid: "M001", phase: "planning" });
|
|
205
|
+
const result = await findRule(PARALLEL_RESEARCH_RULE).match(ctx);
|
|
206
|
+
assert.strictEqual(result, null, "trivial variant must skip parallel-research dispatch");
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// ─── Validate-milestone gate ──────────────────────────────────────────────
|
|
210
|
+
|
|
211
|
+
test("#4781 phase 2: validate-milestone rule writes pass-through VALIDATION for trivial variant", async (t) => {
|
|
212
|
+
const base = makeBase();
|
|
213
|
+
t.after(() => cleanup(base));
|
|
214
|
+
|
|
215
|
+
seedMilestone(base, "M001", TRIVIAL_INPUT);
|
|
216
|
+
// findMissingSummaries checks slice SUMMARY files — write empty ones so
|
|
217
|
+
// the safety guard doesn't stop first.
|
|
218
|
+
const { writeFileSync } = await import("node:fs");
|
|
219
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-SUMMARY.md"), "# S01\n");
|
|
220
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S02", "S02-SUMMARY.md"), "# S02\n");
|
|
221
|
+
// Write a roadmap so findMissingSummaries can enumerate slice IDs.
|
|
222
|
+
writeFileSync(
|
|
223
|
+
join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
|
|
224
|
+
[
|
|
225
|
+
"# M001",
|
|
226
|
+
"## Slices",
|
|
227
|
+
"- [x] **S01: First** `risk:low` `depends:[]`",
|
|
228
|
+
"- [x] **S02: Second** `risk:low` `depends:[]`",
|
|
229
|
+
].join("\n"),
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const ctx = makeCtx({ base, mid: "M001", phase: "validating-milestone" });
|
|
233
|
+
const result = await findRule(VALIDATE_RULE).match(ctx);
|
|
234
|
+
|
|
235
|
+
assert.ok(result, "rule must return a result, not null");
|
|
236
|
+
assert.strictEqual(result!.action, "skip", "trivial variant must return skip action");
|
|
237
|
+
|
|
238
|
+
const validationPath = join(base, ".gsd", "milestones", "M001", "M001-VALIDATION.md");
|
|
239
|
+
assert.ok(existsSync(validationPath), "pass-through VALIDATION.md must be written");
|
|
240
|
+
|
|
241
|
+
const { readFileSync } = await import("node:fs");
|
|
242
|
+
const content = readFileSync(validationPath, "utf-8");
|
|
243
|
+
assert.match(content, /verdict: pass/);
|
|
244
|
+
assert.match(content, /trivial-scope pipeline variant \(#4781\)/);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("#4781 phase 2: validate-milestone rule dispatches normally for standard variant", async (t) => {
|
|
248
|
+
const base = makeBase();
|
|
249
|
+
t.after(() => cleanup(base));
|
|
250
|
+
|
|
251
|
+
seedMilestone(base, "M001", STANDARD_INPUT);
|
|
252
|
+
const { writeFileSync } = await import("node:fs");
|
|
253
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-SUMMARY.md"), "# S01\n");
|
|
254
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S02", "S02-SUMMARY.md"), "# S02\n");
|
|
255
|
+
writeFileSync(
|
|
256
|
+
join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
|
|
257
|
+
[
|
|
258
|
+
"# M001",
|
|
259
|
+
"## Slices",
|
|
260
|
+
"- [x] **S01: First** `risk:low` `depends:[]`",
|
|
261
|
+
"- [x] **S02: Second** `risk:low` `depends:[]`",
|
|
262
|
+
].join("\n"),
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
const ctx = makeCtx({ base, mid: "M001", phase: "validating-milestone" });
|
|
266
|
+
const result = await findRule(VALIDATE_RULE).match(ctx);
|
|
267
|
+
|
|
268
|
+
assert.ok(result, "standard variant must produce a result");
|
|
269
|
+
assert.strictEqual(result!.action, "dispatch", "standard variant must dispatch validate-milestone");
|
|
270
|
+
if (result!.action === "dispatch") {
|
|
271
|
+
assert.strictEqual(result!.unitType, "validate-milestone");
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// ─── Fallback safety: no DB, missing milestone ────────────────────────────
|
|
276
|
+
|
|
277
|
+
test("#4781 phase 2: null variant (no milestone row) does NOT gate dispatch — safe fallback", async (t) => {
|
|
278
|
+
const base = makeBase();
|
|
279
|
+
t.after(() => cleanup(base));
|
|
280
|
+
|
|
281
|
+
// Open DB but do NOT seed any milestone — getMilestone returns null,
|
|
282
|
+
// which makes getMilestonePipelineVariant return null. Rules must NOT
|
|
283
|
+
// short-circuit on null (silent downshift is the hazard we're guarding
|
|
284
|
+
// against).
|
|
285
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
286
|
+
|
|
287
|
+
const ctx = makeCtx({
|
|
288
|
+
base,
|
|
289
|
+
mid: "M999",
|
|
290
|
+
phase: "planning",
|
|
291
|
+
activeSlice: { id: "S02", title: "Second" },
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Rule should NOT return null from the variant gate. It may still return
|
|
295
|
+
// null for other reasons (e.g. missing active slice), but our assertion
|
|
296
|
+
// is specifically about the variant-gate not short-circuiting.
|
|
297
|
+
const result = await findRule(SINGLE_RESEARCH_RULE).match(ctx);
|
|
298
|
+
// Rule reaches its normal logic; with an active slice and no RESEARCH file,
|
|
299
|
+
// it should produce a dispatch action, not null from the variant gate.
|
|
300
|
+
assert.notStrictEqual(result, null, "null variant must not cause the research-slice gate to short-circuit");
|
|
301
|
+
});
|
|
@@ -191,7 +191,12 @@ function createFailingTasks(): void {
|
|
|
191
191
|
estimate: "1h",
|
|
192
192
|
files: [],
|
|
193
193
|
verify: "npm test",
|
|
194
|
-
inputs: [
|
|
194
|
+
inputs: [
|
|
195
|
+
"nonexistent-file-that-does-not-exist.ts",
|
|
196
|
+
"missing-second-file.ts",
|
|
197
|
+
"missing-third-file.ts",
|
|
198
|
+
"missing-fourth-file.ts",
|
|
199
|
+
],
|
|
195
200
|
expectedOutput: [],
|
|
196
201
|
observabilityImpact: "",
|
|
197
202
|
},
|
|
@@ -308,6 +313,32 @@ describe("Pre-execution checks → pauseAuto wiring", () => {
|
|
|
308
313
|
String(call.arguments[0]).includes("Pre-execution checks failed")
|
|
309
314
|
);
|
|
310
315
|
assert.ok(errorNotify, "Should show error notification about pre-execution check failure");
|
|
316
|
+
const errorMessage = String(errorNotify.arguments[0]);
|
|
317
|
+
assert.match(
|
|
318
|
+
errorMessage,
|
|
319
|
+
/Pre-execution checks failed: \d+ blocking issue/,
|
|
320
|
+
"failure notification should include the blocking issue count",
|
|
321
|
+
);
|
|
322
|
+
assert.ok(
|
|
323
|
+
errorMessage.includes("[file] nonexistent-file-that-does-not-exist.ts: Task T01 references"),
|
|
324
|
+
"failure notification should include category, target, and message details",
|
|
325
|
+
);
|
|
326
|
+
assert.ok(
|
|
327
|
+
errorMessage.includes("[file] missing-third-file.ts: Task T01 references"),
|
|
328
|
+
"failure notification should include up to three actionable check details",
|
|
329
|
+
);
|
|
330
|
+
assert.ok(
|
|
331
|
+
!errorMessage.includes("missing-fourth-file.ts"),
|
|
332
|
+
"failure notification should truncate details beyond the display limit",
|
|
333
|
+
);
|
|
334
|
+
assert.ok(
|
|
335
|
+
errorMessage.includes("...and 1 more"),
|
|
336
|
+
"failure notification should summarize truncated blocking checks",
|
|
337
|
+
);
|
|
338
|
+
assert.ok(
|
|
339
|
+
errorMessage.includes(join(".gsd", "milestones", "M001", "slices", "S01", "S01-PRE-EXEC-VERIFY.json")),
|
|
340
|
+
"failure notification should point to the relative pre-exec evidence file path",
|
|
341
|
+
);
|
|
311
342
|
});
|
|
312
343
|
|
|
313
344
|
test("pauseAuto is called when enhanced_verification_strict: true and pre-execution returns warn", async () => {
|
|
@@ -12,6 +12,7 @@ import assert from "node:assert/strict";
|
|
|
12
12
|
import { readFileSync, mkdtempSync, mkdirSync, writeFileSync, existsSync, readdirSync, rmSync } from "node:fs";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import { tmpdir } from "node:os";
|
|
15
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
15
16
|
|
|
16
17
|
test("#2684: preferences files are NOT in ROOT_STATE_FILES (forward-only sync)", () => {
|
|
17
18
|
const srcPath = join(import.meta.dirname, "..", "auto-worktree.ts");
|
|
@@ -49,7 +50,7 @@ test("copyPlanningArtifacts prefers canonical PREFERENCES.md with lowercase fall
|
|
|
49
50
|
assert.ok(fnIdx !== -1, "copyPlanningArtifacts function exists");
|
|
50
51
|
|
|
51
52
|
// Extract function body (up to the next top-level function)
|
|
52
|
-
const fnBody = src
|
|
53
|
+
const fnBody = extractSourceRegion(src, "function copyPlanningArtifacts");
|
|
53
54
|
|
|
54
55
|
assert.ok(
|
|
55
56
|
fnBody.includes("PROJECT_PREFERENCES_FILE") && fnBody.includes("LEGACY_PROJECT_PREFERENCES_FILE"),
|
|
@@ -64,6 +64,18 @@ describe("prompt-cache-optimizer: classifySection", () => {
|
|
|
64
64
|
assert.equal(classifySection("overrides"), "semi-static");
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
+
// Regression: issue #4719 — KNOWLEDGE falls through to dynamic default.
|
|
68
|
+
// Knowledge content is reused across all tasks within a milestone, so it
|
|
69
|
+
// must be classified as semi-static to qualify for prefix caching when the
|
|
70
|
+
// cache optimizer is wired into the prompt path.
|
|
71
|
+
it("classifies knowledge as semi-static (issue #4719)", () => {
|
|
72
|
+
assert.equal(classifySection("knowledge"), "semi-static");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("classifies project-knowledge as semi-static (issue #4719)", () => {
|
|
76
|
+
assert.equal(classifySection("project-knowledge"), "semi-static");
|
|
77
|
+
});
|
|
78
|
+
|
|
67
79
|
it("classifies task-plan as dynamic", () => {
|
|
68
80
|
assert.equal(classifySection("task-plan"), "dynamic");
|
|
69
81
|
});
|
|
@@ -13,6 +13,7 @@ import assert from 'node:assert/strict';
|
|
|
13
13
|
import { readFileSync } from 'node:fs';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { dirname, join } from 'node:path';
|
|
16
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
16
17
|
|
|
17
18
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
19
|
const __dirname = dirname(__filename);
|
|
@@ -69,11 +70,21 @@ describe('register-extension _gsdEpipeGuard (#3696)', () => {
|
|
|
69
70
|
|
|
70
71
|
describe('register-hooks session_before_compact (#3696)', () => {
|
|
71
72
|
test('session_before_compact only checks isAutoActive', () => {
|
|
72
|
-
//
|
|
73
|
-
|
|
73
|
+
// Anchor on the full registration token rather than the bare event name —
|
|
74
|
+
// prevents matching unrelated substring occurrences.
|
|
75
|
+
const compactIdx = registerHooksSrc.indexOf('pi.on("session_before_compact"');
|
|
74
76
|
assert.ok(compactIdx > -1, 'session_before_compact hook should exist');
|
|
75
|
-
// The first check in the handler should be isAutoActive(), not isAutoPaused()
|
|
76
|
-
|
|
77
|
+
// The first check in the handler should be isAutoActive(), not isAutoPaused().
|
|
78
|
+
// Bound the region to this single handler — register-hooks.ts contains
|
|
79
|
+
// multiple pi.on("session_before_compact") handlers and a later handler
|
|
80
|
+
// legitimately references isAutoPaused.
|
|
81
|
+
const afterCompact = extractSourceRegion(
|
|
82
|
+
registerHooksSrc,
|
|
83
|
+
'pi.on("session_before_compact"',
|
|
84
|
+
'pi.on("',
|
|
85
|
+
// NB: endAnchor search starts AFTER the startAnchor, so the next
|
|
86
|
+
// pi.on("... matches the subsequent handler rather than this one.
|
|
87
|
+
);
|
|
77
88
|
assert.match(afterCompact, /isAutoActive\(\)/,
|
|
78
89
|
'session_before_compact should check isAutoActive()');
|
|
79
90
|
// Should NOT block compaction when paused
|
|
@@ -13,7 +13,12 @@ import { fileURLToPath } from "node:url";
|
|
|
13
13
|
import { classifyError, isTransient, isTransientNetworkError } from "../error-classifier.ts";
|
|
14
14
|
import { pauseAutoForProviderError } from "../provider-error-pause.ts";
|
|
15
15
|
import { resumeAutoAfterProviderDelay } from "../bootstrap/provider-error-resume.ts";
|
|
16
|
+
import { MAX_TRANSIENT_AUTO_RESUMES } from "../bootstrap/agent-end-recovery.ts";
|
|
16
17
|
import { getNextFallbackModel } from "../preferences.ts";
|
|
18
|
+
// Zero-import module — imported by path rather than through the package
|
|
19
|
+
// barrel to avoid pulling the full AgentSession / @gsd/pi-ai dep graph into
|
|
20
|
+
// this unit test (see #4837).
|
|
21
|
+
import { RETRYABLE_ERROR_RE } from "../../../../../packages/pi-coding-agent/src/core/retryable-error-regex.ts";
|
|
17
22
|
|
|
18
23
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
24
|
|
|
@@ -405,7 +410,6 @@ test("resumeAutoAfterProviderDelay restarts paused auto-mode from the recorded b
|
|
|
405
410
|
basePath: "/tmp/project",
|
|
406
411
|
}),
|
|
407
412
|
resetTransientRetryState: () => {},
|
|
408
|
-
resetSessionTimeoutState: () => {},
|
|
409
413
|
startAuto: async (_ctx, _pi, base, verboseMode, options) => {
|
|
410
414
|
startCalls.push({ base, verboseMode, step: options?.step });
|
|
411
415
|
},
|
|
@@ -431,7 +435,6 @@ test("resumeAutoAfterProviderDelay does not double-start when auto-mode is alrea
|
|
|
431
435
|
basePath: "/tmp/project",
|
|
432
436
|
}),
|
|
433
437
|
resetTransientRetryState: () => {},
|
|
434
|
-
resetSessionTimeoutState: () => {},
|
|
435
438
|
startAuto: async () => {
|
|
436
439
|
startCalls += 1;
|
|
437
440
|
},
|
|
@@ -463,7 +466,6 @@ test("resumeAutoAfterProviderDelay leaves auto paused when no base path is avail
|
|
|
463
466
|
basePath: "",
|
|
464
467
|
}),
|
|
465
468
|
resetTransientRetryState: () => {},
|
|
466
|
-
resetSessionTimeoutState: () => {},
|
|
467
469
|
startAuto: async () => {
|
|
468
470
|
startCalls += 1;
|
|
469
471
|
},
|
|
@@ -480,7 +482,7 @@ test("resumeAutoAfterProviderDelay leaves auto paused when no base path is avail
|
|
|
480
482
|
]);
|
|
481
483
|
});
|
|
482
484
|
|
|
483
|
-
test("resumeAutoAfterProviderDelay resets provider retry state
|
|
485
|
+
test("resumeAutoAfterProviderDelay resets provider retry state without clearing session-timeout attempts", async () => {
|
|
484
486
|
const calls: string[] = [];
|
|
485
487
|
|
|
486
488
|
const result = await resumeAutoAfterProviderDelay(
|
|
@@ -496,9 +498,6 @@ test("resumeAutoAfterProviderDelay resets provider retry state before restarting
|
|
|
496
498
|
resetTransientRetryState: () => {
|
|
497
499
|
calls.push("reset-transient");
|
|
498
500
|
},
|
|
499
|
-
resetSessionTimeoutState: () => {
|
|
500
|
-
calls.push("reset-session-timeout");
|
|
501
|
-
},
|
|
502
501
|
startAuto: async () => {
|
|
503
502
|
calls.push("start-auto");
|
|
504
503
|
},
|
|
@@ -508,7 +507,6 @@ test("resumeAutoAfterProviderDelay resets provider retry state before restarting
|
|
|
508
507
|
assert.equal(result, "resumed");
|
|
509
508
|
assert.deepEqual(calls, [
|
|
510
509
|
"reset-transient",
|
|
511
|
-
"reset-session-timeout",
|
|
512
510
|
"start-auto",
|
|
513
511
|
]);
|
|
514
512
|
});
|
|
@@ -684,13 +682,12 @@ test("phases.ts resets session timeout counter on successful unit completion", (
|
|
|
684
682
|
// ── Fix 3: MAX_TRANSIENT_AUTO_RESUMES raised to 8 ───────────────────────────
|
|
685
683
|
|
|
686
684
|
test("MAX_TRANSIENT_AUTO_RESUMES is at least 8 for sustained overload resilience", () => {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
const value = Number(match![1]);
|
|
685
|
+
// Import the real constant rather than regex-scraping the source literal —
|
|
686
|
+
// this way the assertion cannot silently drift if the symbol is renamed or
|
|
687
|
+
// the value is moved. See #4837.
|
|
691
688
|
assert.ok(
|
|
692
|
-
|
|
693
|
-
`MAX_TRANSIENT_AUTO_RESUMES must be >= 8 for sustained overload resilience, got ${
|
|
689
|
+
MAX_TRANSIENT_AUTO_RESUMES >= 8,
|
|
690
|
+
`MAX_TRANSIENT_AUTO_RESUMES must be >= 8 for sustained overload resilience, got ${MAX_TRANSIENT_AUTO_RESUMES}`,
|
|
694
691
|
);
|
|
695
692
|
});
|
|
696
693
|
|
|
@@ -738,20 +735,22 @@ test("classifyError: 'context window' with 'exceed' is transient server", () =>
|
|
|
738
735
|
// ── agent-session retryable regex handles server_error (#1166) ──────────────
|
|
739
736
|
|
|
740
737
|
test("agent-session retryable error regex matches server_error (underscore)", () => {
|
|
741
|
-
//
|
|
742
|
-
//
|
|
743
|
-
//
|
|
744
|
-
//
|
|
745
|
-
|
|
738
|
+
// Import the real regex from the retry-handler so this test can never
|
|
739
|
+
// silently drift from runtime behaviour. The regex must match both
|
|
740
|
+
// "server error" (space) and "server_error" (underscore) to properly
|
|
741
|
+
// classify Codex streaming errors as retryable.
|
|
742
|
+
// "temporarily backed off" is intentionally excluded — see #3429 / #4837.
|
|
746
743
|
|
|
747
744
|
// server_error (with underscore — Codex streaming error format)
|
|
748
|
-
assert.ok(
|
|
745
|
+
assert.ok(RETRYABLE_ERROR_RE.test("Codex server_error: An error occurred"));
|
|
749
746
|
// server error (with space — traditional HTTP error format)
|
|
750
|
-
assert.ok(
|
|
747
|
+
assert.ok(RETRYABLE_ERROR_RE.test("server error occurred"));
|
|
751
748
|
// internal_error (with underscore)
|
|
752
|
-
assert.ok(
|
|
749
|
+
assert.ok(RETRYABLE_ERROR_RE.test("internal_error: something went wrong"));
|
|
753
750
|
// internal error (with space)
|
|
754
|
-
assert.ok(
|
|
751
|
+
assert.ok(RETRYABLE_ERROR_RE.test("internal error"));
|
|
755
752
|
// non-retryable errors must not match
|
|
756
|
-
assert.ok(!
|
|
753
|
+
assert.ok(!RETRYABLE_ERROR_RE.test("model not found"));
|
|
754
|
+
// "temporarily backed off" must NOT be matched (intentional exclusion #3429)
|
|
755
|
+
assert.ok(!RETRYABLE_ERROR_RE.test("temporarily backed off"));
|
|
757
756
|
});
|
|
@@ -178,4 +178,36 @@ describe("Windows pre-merge DB release (#4704)", () => {
|
|
|
178
178
|
"openDatabase() called after the pre-merge stash",
|
|
179
179
|
);
|
|
180
180
|
});
|
|
181
|
+
|
|
182
|
+
it("pre-merge stash targets entries by marker instead of refs/stash or stash@{0}", () => {
|
|
183
|
+
const src = readFileSync(
|
|
184
|
+
join(import.meta.dirname, "..", "auto-worktree.ts"),
|
|
185
|
+
"utf-8",
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
assert.ok(src.includes("stashMarker"), "stash marker is tracked");
|
|
189
|
+
assert.ok(
|
|
190
|
+
src.includes('"stash", "list", "--format=%gd%x00%s"'),
|
|
191
|
+
"stash lookup reads ref and message together",
|
|
192
|
+
);
|
|
193
|
+
assert.ok(!src.includes('"rev-parse", "refs/stash"'), "refs/stash is not used for identity");
|
|
194
|
+
assert.ok(!src.includes('["stash", "pop"]'), "stash pop is never unqualified");
|
|
195
|
+
assert.ok(!src.includes('["stash", "drop"]'), "stash drop is never unqualified");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("stash drop after pop failure requires auto-resolved .gsd conflicts", () => {
|
|
199
|
+
const src = readFileSync(
|
|
200
|
+
join(import.meta.dirname, "..", "auto-worktree.ts"),
|
|
201
|
+
"utf-8",
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
assert.ok(
|
|
205
|
+
src.includes("gsdUU.length > 0 && nonGsdUU.length === 0"),
|
|
206
|
+
"stash drop must only run after detected .gsd conflicts were auto-resolved",
|
|
207
|
+
);
|
|
208
|
+
assert.ok(
|
|
209
|
+
src.includes("git stash pop failed without resolvable conflict files; leaving stash for manual recovery"),
|
|
210
|
+
"non-conflict stash pop failures must leave the stash for manual recovery",
|
|
211
|
+
);
|
|
212
|
+
});
|
|
181
213
|
});
|
|
@@ -6,6 +6,7 @@ import { tmpdir } from "node:os";
|
|
|
6
6
|
|
|
7
7
|
import { deriveState } from "../state.js";
|
|
8
8
|
import { buildExistingMilestonesContext } from "../guided-flow.js";
|
|
9
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
9
10
|
|
|
10
11
|
describe('queue-draft-detection', () => {
|
|
11
12
|
test('draft and context milestone detection', async () => {
|
|
@@ -68,7 +69,7 @@ describe('queue-draft-detection', () => {
|
|
|
68
69
|
|
|
69
70
|
// both files: CONTEXT.md wins, no draft label
|
|
70
71
|
const m003Idx = context.indexOf("M003:");
|
|
71
|
-
const m003Section = context
|
|
72
|
+
const m003Section = extractSourceRegion(context, "M003:");
|
|
72
73
|
assert.ok(
|
|
73
74
|
m003Section.includes("**Context:**"),
|
|
74
75
|
"M003 (both files) should use 'Context:' label (CONTEXT.md wins)",
|
|
@@ -84,7 +85,7 @@ describe('queue-draft-detection', () => {
|
|
|
84
85
|
|
|
85
86
|
// neither file: no context section
|
|
86
87
|
const m004Idx = context.indexOf("M004:");
|
|
87
|
-
const m004Section = context
|
|
88
|
+
const m004Section = extractSourceRegion(context, "M004:");
|
|
88
89
|
assert.ok(
|
|
89
90
|
!m004Section.includes("**Context:**"),
|
|
90
91
|
"M004 (neither file) should not have Context: label",
|
|
@@ -3,6 +3,7 @@ import assert from "node:assert/strict";
|
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join, dirname } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
6
7
|
|
|
7
8
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
9
|
|
|
@@ -28,7 +29,7 @@ describe("queued-discuss-fast-path", () => {
|
|
|
28
29
|
const fnStart = source.indexOf("async function dispatchDiscussForMilestone(");
|
|
29
30
|
assert.ok(fnStart > 0, "dispatchDiscussForMilestone must exist");
|
|
30
31
|
const fnEnd = source.indexOf("\nasync function ", fnStart + 1);
|
|
31
|
-
const fnBody =
|
|
32
|
+
const fnBody = extractSourceRegion(source, "async function dispatchDiscussForMilestone(");
|
|
32
33
|
assert.ok(
|
|
33
34
|
fnBody.includes("fastPathInstruction"),
|
|
34
35
|
"dispatchDiscussForMilestone must compute fastPathInstruction",
|
|
@@ -61,8 +62,7 @@ describe("queued-discuss-fast-path", () => {
|
|
|
61
62
|
const source = guidedFlowSrc();
|
|
62
63
|
const fnStart = source.indexOf("async function showDiscussQueuedMilestone(");
|
|
63
64
|
assert.ok(fnStart > 0, "showDiscussQueuedMilestone must exist");
|
|
64
|
-
const
|
|
65
|
-
const fnBody = fnEnd > 0 ? source.slice(fnStart, fnEnd) : source.slice(fnStart, fnStart + 3000);
|
|
65
|
+
const fnBody = extractSourceRegion(source, "async function showDiscussQueuedMilestone(", "\nasync function ");
|
|
66
66
|
assert.ok(
|
|
67
67
|
fnBody.includes("hasDraft"),
|
|
68
68
|
"showDiscussQueuedMilestone must check hasDraft",
|
|
@@ -81,8 +81,7 @@ describe("queued-discuss-fast-path", () => {
|
|
|
81
81
|
const source = guidedFlowSrc();
|
|
82
82
|
const fnStart = source.indexOf("async function showDiscussQueuedMilestone(");
|
|
83
83
|
assert.ok(fnStart > 0, "showDiscussQueuedMilestone must exist");
|
|
84
|
-
const
|
|
85
|
-
const fnBody = fnEnd > 0 ? source.slice(fnStart, fnEnd) : source.slice(fnStart, fnStart + 3000);
|
|
84
|
+
const fnBody = extractSourceRegion(source, "async function showDiscussQueuedMilestone(", "\nasync function ");
|
|
86
85
|
assert.ok(
|
|
87
86
|
fnBody.includes("let fastPath = hasDraft"),
|
|
88
87
|
"showDiscussQueuedMilestone must set fastPath = hasDraft so draft presence auto-enables fast path",
|