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
|
@@ -2,65 +2,237 @@
|
|
|
2
2
|
* merge-conflict-stops-loop.test.ts — #2330
|
|
3
3
|
*
|
|
4
4
|
* When a squash merge has real code conflicts (not just .gsd/ files),
|
|
5
|
-
* the merge
|
|
6
|
-
* silently in mergeAndExit
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* the merge used to retry forever because `MergeConflictError` was
|
|
6
|
+
* caught silently in `mergeAndExit`. The fix:
|
|
7
|
+
*
|
|
8
|
+
* 1. `WorktreeResolver.mergeAndExit` **re-throws** `MergeConflictError`
|
|
9
|
+
* (and other unexpected errors) so the caller sees the failure.
|
|
10
|
+
* 2. `auto/phases.ts` catches `MergeConflictError` from `mergeAndExit`
|
|
11
|
+
* and returns `{ action: "break", reason: "merge-conflict" }` +
|
|
12
|
+
* calls `stopAuto`, instead of looping.
|
|
13
|
+
*
|
|
14
|
+
* The previous version of this file was three source-grep assertions
|
|
15
|
+
* (`src.includes("MergeConflictError")` / `src.includes("throw err")` /
|
|
16
|
+
* `extractSourceRegion(..., "instanceof MergeConflictError").includes("stopAuto")`).
|
|
17
|
+
* Those all pass even if the bug reappears verbatim — the catch block
|
|
18
|
+
* could swallow the error silently as long as the identifier text
|
|
19
|
+
* remains somewhere in the file. Called out in #4784 / #4824 as the
|
|
20
|
+
* canonical source-grep false-coverage case.
|
|
21
|
+
*
|
|
22
|
+
* This rewrite tests the invariant at the `WorktreeResolver` layer
|
|
23
|
+
* (where the re-throw happens) with injected deps: we wire
|
|
24
|
+
* `mergeMilestoneToMain` to throw `MergeConflictError`, call
|
|
25
|
+
* `mergeAndExit`, and assert the error propagates. That is the ONLY
|
|
26
|
+
* assertion that fails if someone reverts the re-throw to a silent
|
|
27
|
+
* catch.
|
|
9
28
|
*/
|
|
10
29
|
|
|
11
|
-
import {
|
|
30
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
31
|
+
import assert from "node:assert/strict";
|
|
32
|
+
import { mkdtempSync, rmSync, mkdirSync } from "node:fs";
|
|
12
33
|
import { join } from "node:path";
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const methodBody = resolverSrc.slice(methodStart, methodStart + 6000);
|
|
31
|
-
const rethrowsConflict =
|
|
32
|
-
methodBody.includes("MergeConflictError") &&
|
|
33
|
-
methodBody.includes("throw err");
|
|
34
|
-
|
|
35
|
-
assertTrue(
|
|
36
|
-
rethrowsConflict,
|
|
37
|
-
"worktree-resolver._mergeWorktreeMode re-throws MergeConflictError (#2330)",
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
// ── Test 2: auto/phases.ts imports and uses MergeConflictError ──────────
|
|
41
|
-
|
|
42
|
-
assertTrue(
|
|
43
|
-
phasesSrc.includes("MergeConflictError") && phasesSrc.includes("mergeAndExit"),
|
|
44
|
-
"auto/phases.ts handles MergeConflictError from mergeAndExit (#2330)",
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
// ── Test 3: The handler stops the loop (doesn't just warn) ──────────────
|
|
48
|
-
|
|
49
|
-
// Find the instanceof MergeConflictError check (not the import line)
|
|
50
|
-
const instanceofIdx = phasesSrc.indexOf("instanceof MergeConflictError");
|
|
51
|
-
assertTrue(instanceofIdx > 0, "auto/phases.ts has instanceof MergeConflictError check");
|
|
34
|
+
import { tmpdir } from "node:os";
|
|
35
|
+
|
|
36
|
+
import { WorktreeResolver } from "../worktree-resolver.ts";
|
|
37
|
+
import { MergeConflictError } from "../git-service.ts";
|
|
38
|
+
import type { WorktreeResolverDeps } from "../worktree-resolver.ts";
|
|
39
|
+
import type { AutoSession } from "../auto/session.ts";
|
|
40
|
+
|
|
41
|
+
// ─── Test-only session double ───────────────────────────────────────────
|
|
42
|
+
// `AutoSession` is a large class but `WorktreeResolver` only reads a few
|
|
43
|
+
// fields from it (basePath, originalBasePath, currentMilestoneId).
|
|
44
|
+
function makeSession(basePath: string): AutoSession {
|
|
45
|
+
return {
|
|
46
|
+
basePath,
|
|
47
|
+
originalBasePath: basePath,
|
|
48
|
+
currentMilestoneId: "M001",
|
|
49
|
+
} as unknown as AutoSession;
|
|
50
|
+
}
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Build a deps object where every method is a no-op or a controlled
|
|
54
|
+
* value, except the ones the caller explicitly overrides. This is the
|
|
55
|
+
* boring-tech approach — no mocking library, just plain objects.
|
|
56
|
+
*/
|
|
57
|
+
function makeDeps(
|
|
58
|
+
overrides: Partial<WorktreeResolverDeps> = {},
|
|
59
|
+
): WorktreeResolverDeps {
|
|
60
|
+
return {
|
|
61
|
+
isInAutoWorktree: () => true,
|
|
62
|
+
shouldUseWorktreeIsolation: () => true,
|
|
63
|
+
getIsolationMode: () => "worktree",
|
|
64
|
+
mergeMilestoneToMain: () => ({ pushed: false, codeFilesChanged: true }),
|
|
65
|
+
syncWorktreeStateBack: () => ({ synced: [] }),
|
|
66
|
+
teardownAutoWorktree: () => undefined,
|
|
67
|
+
createAutoWorktree: () => "",
|
|
68
|
+
enterAutoWorktree: () => "",
|
|
69
|
+
enterBranchModeForMilestone: () => undefined,
|
|
70
|
+
getAutoWorktreePath: () => null,
|
|
71
|
+
autoCommitCurrentBranch: () => undefined,
|
|
72
|
+
getCurrentBranch: () => "worktree/M001",
|
|
73
|
+
autoWorktreeBranch: (mid: string) => `worktree/${mid}`,
|
|
74
|
+
resolveMilestoneFile: () => null, // no roadmap → early return path
|
|
75
|
+
readFileSync: () => "",
|
|
76
|
+
GitServiceImpl: class {
|
|
77
|
+
constructor(_basePath: string, _config: unknown) {}
|
|
78
|
+
} as never,
|
|
79
|
+
loadEffectiveGSDPreferences: () => ({ preferences: {} }),
|
|
80
|
+
invalidateAllCaches: () => undefined,
|
|
81
|
+
captureIntegrationBranch: () => undefined,
|
|
82
|
+
...overrides,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
59
85
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
86
|
+
function makeNotifyCtx(): {
|
|
87
|
+
notify: (msg: string, level?: "info" | "warning" | "error" | "success") => void;
|
|
88
|
+
calls: Array<{ msg: string; level?: string }>;
|
|
89
|
+
} {
|
|
90
|
+
const calls: Array<{ msg: string; level?: string }> = [];
|
|
91
|
+
return {
|
|
92
|
+
notify: (msg, level) => {
|
|
93
|
+
calls.push({ msg, level });
|
|
94
|
+
},
|
|
95
|
+
calls,
|
|
96
|
+
};
|
|
64
97
|
}
|
|
65
98
|
|
|
66
|
-
|
|
99
|
+
describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", () => {
|
|
100
|
+
let baseDir: string;
|
|
101
|
+
|
|
102
|
+
beforeEach(() => {
|
|
103
|
+
baseDir = mkdtempSync(join(tmpdir(), "merge-conflict-stops-loop-"));
|
|
104
|
+
// Fake out a milestone directory so mergeAndExit reaches mergeMilestoneToMain.
|
|
105
|
+
mkdirSync(join(baseDir, ".gsd", "milestones", "M001"), { recursive: true });
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
afterEach(() => {
|
|
109
|
+
try {
|
|
110
|
+
rmSync(baseDir, { recursive: true, force: true });
|
|
111
|
+
} catch {
|
|
112
|
+
// best-effort
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("propagates MergeConflictError with conflicted file list", () => {
|
|
117
|
+
const conflicted = ["src/feature.ts", "README.md"];
|
|
118
|
+
const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
|
|
119
|
+
const deps = makeDeps({
|
|
120
|
+
resolveMilestoneFile: (_base, _mid, type) =>
|
|
121
|
+
type === "ROADMAP" ? roadmapPath : null,
|
|
122
|
+
readFileSync: () => "# M001\n",
|
|
123
|
+
mergeMilestoneToMain: () => {
|
|
124
|
+
throw new MergeConflictError(conflicted, "squash", "worktree/M001", "main");
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const resolver = new WorktreeResolver(makeSession(baseDir), deps);
|
|
129
|
+
const ctx = makeNotifyCtx();
|
|
130
|
+
|
|
131
|
+
assert.throws(
|
|
132
|
+
() => resolver.mergeAndExit("M001", ctx),
|
|
133
|
+
(err: unknown) => {
|
|
134
|
+
assert.ok(
|
|
135
|
+
err instanceof MergeConflictError,
|
|
136
|
+
`expected MergeConflictError, got: ${err}`,
|
|
137
|
+
);
|
|
138
|
+
assert.deepEqual(err.conflictedFiles, conflicted);
|
|
139
|
+
assert.equal(err.strategy, "squash");
|
|
140
|
+
assert.equal(err.branch, "worktree/M001");
|
|
141
|
+
assert.equal(err.mainBranch, "main");
|
|
142
|
+
return true;
|
|
143
|
+
},
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("propagates non-conflict errors too (#4380 — never swallow silently)", () => {
|
|
148
|
+
const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
|
|
149
|
+
class FakePermError extends Error {}
|
|
150
|
+
const deps = makeDeps({
|
|
151
|
+
resolveMilestoneFile: (_base, _mid, type) =>
|
|
152
|
+
type === "ROADMAP" ? roadmapPath : null,
|
|
153
|
+
readFileSync: () => "# M001\n",
|
|
154
|
+
mergeMilestoneToMain: () => {
|
|
155
|
+
throw new FakePermError("EACCES: permission denied");
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const resolver = new WorktreeResolver(makeSession(baseDir), deps);
|
|
160
|
+
const ctx = makeNotifyCtx();
|
|
161
|
+
|
|
162
|
+
assert.throws(
|
|
163
|
+
() => resolver.mergeAndExit("M001", ctx),
|
|
164
|
+
(err: unknown) => {
|
|
165
|
+
assert.ok(
|
|
166
|
+
err instanceof FakePermError,
|
|
167
|
+
`expected FakePermError, got: ${err}`,
|
|
168
|
+
);
|
|
169
|
+
return true;
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("successful merge does not throw", () => {
|
|
175
|
+
const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
|
|
176
|
+
const deps = makeDeps({
|
|
177
|
+
resolveMilestoneFile: (_base, _mid, type) =>
|
|
178
|
+
type === "ROADMAP" ? roadmapPath : null,
|
|
179
|
+
readFileSync: () => "# M001\n",
|
|
180
|
+
mergeMilestoneToMain: () => ({ pushed: false, codeFilesChanged: true }),
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const resolver = new WorktreeResolver(makeSession(baseDir), deps);
|
|
184
|
+
const ctx = makeNotifyCtx();
|
|
185
|
+
|
|
186
|
+
// Should not throw — the success path.
|
|
187
|
+
assert.doesNotThrow(() => resolver.mergeAndExit("M001", ctx));
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// ─── phases.ts handler contract ──────────────────────────────────────────
|
|
192
|
+
//
|
|
193
|
+
// The inline handler at `auto/phases.ts:580-598 / 695-712 / 823-840`:
|
|
194
|
+
//
|
|
195
|
+
// if (mergeErr instanceof MergeConflictError) {
|
|
196
|
+
// ctx.ui.notify(`Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. ...`);
|
|
197
|
+
// await deps.stopAuto(...);
|
|
198
|
+
// return { action: "break", reason: "merge-conflict" };
|
|
199
|
+
// }
|
|
200
|
+
//
|
|
201
|
+
// Testing it end-to-end requires constructing a full `IterationContext`
|
|
202
|
+
// + `LoopState` + `deps` surface (hundreds of fields). Extracting the
|
|
203
|
+
// handler into a reusable helper is the right refactor and is tracked
|
|
204
|
+
// alongside this issue. In the meantime, defend the contract between
|
|
205
|
+
// the thrower and the handler: if the fields the handler formats drift,
|
|
206
|
+
// the handler silently regresses.
|
|
207
|
+
|
|
208
|
+
describe("Merge-conflict handler contract (#2330 — phases.ts inline pattern)", () => {
|
|
209
|
+
test("MergeConflictError exposes fields the phases.ts handler formats", () => {
|
|
210
|
+
const err = new MergeConflictError(
|
|
211
|
+
["a.ts", "b.ts"],
|
|
212
|
+
"squash",
|
|
213
|
+
"worktree/M001",
|
|
214
|
+
"main",
|
|
215
|
+
);
|
|
216
|
+
assert.deepEqual(err.conflictedFiles, ["a.ts", "b.ts"]);
|
|
217
|
+
assert.equal(err.strategy, "squash");
|
|
218
|
+
assert.equal(err.branch, "worktree/M001");
|
|
219
|
+
assert.equal(err.mainBranch, "main");
|
|
220
|
+
// instanceof is the type-discriminant the handler uses.
|
|
221
|
+
assert.ok(err instanceof MergeConflictError);
|
|
222
|
+
// The class extends Error so the non-conflict fallback message path
|
|
223
|
+
// (`String(mergeErr)` / `mergeErr.message`) still works.
|
|
224
|
+
assert.ok(err instanceof Error);
|
|
225
|
+
assert.match(err.message, /worktree\/M001/);
|
|
226
|
+
assert.match(err.message, /main/);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("MergeConflictError with empty conflicted list still serializes (edge)", () => {
|
|
230
|
+
// The handler's `conflictedFiles.join(", ")` must not crash on empty
|
|
231
|
+
// list. Defensive: some producers could legitimately emit a
|
|
232
|
+
// zero-length array.
|
|
233
|
+
const err = new MergeConflictError([], "merge", "feature/x", "main");
|
|
234
|
+
assert.deepEqual(err.conflictedFiles, []);
|
|
235
|
+
assert.equal(err.conflictedFiles.join(", "), "");
|
|
236
|
+
assert.ok(err instanceof MergeConflictError);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// GSD-2 — #4781: classifier behavior matrix. Pure-function tests, no I/O.
|
|
2
|
+
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
classifyMilestoneScope,
|
|
8
|
+
type MilestoneScopeInput,
|
|
9
|
+
} from "../milestone-scope-classifier.ts";
|
|
10
|
+
|
|
11
|
+
// ─── Classification matrix ────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
test("#4781 classifier: single static HTML to-do app → trivial (b23 forensic case)", () => {
|
|
14
|
+
const input: MilestoneScopeInput = {
|
|
15
|
+
title: "To-Do App",
|
|
16
|
+
vision: "A minimal, clean browser-based to-do app. Pure HTML/CSS/JS, no build step, no backend. Tasks persist in localStorage.",
|
|
17
|
+
successCriteria: [
|
|
18
|
+
"Open index.html in any browser without a server",
|
|
19
|
+
"Add tasks by typing and pressing Enter or clicking Add",
|
|
20
|
+
"Mark tasks complete (toggleable)",
|
|
21
|
+
"Delete individual tasks",
|
|
22
|
+
"Tasks survive a page reload via localStorage",
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
const r = classifyMilestoneScope(input);
|
|
26
|
+
assert.strictEqual(r.variant, "trivial", `expected trivial, got ${r.variant} — reasons: ${r.reasons.join("; ")}`);
|
|
27
|
+
assert.ok(r.reasons.some(s => s.includes("trivial keywords")), "should cite trivial keywords");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("#4781 classifier: readme typo fix → trivial", () => {
|
|
31
|
+
const r = classifyMilestoneScope({
|
|
32
|
+
title: "Fix README typo",
|
|
33
|
+
vision: "Correct spelling error in the installation section.",
|
|
34
|
+
successCriteria: ["Typo fixed", "README renders correctly"],
|
|
35
|
+
});
|
|
36
|
+
assert.strictEqual(r.variant, "trivial");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("#4781 classifier: auth flow single file → standard (override beats trivial)", () => {
|
|
40
|
+
const r = classifyMilestoneScope({
|
|
41
|
+
title: "Add login",
|
|
42
|
+
vision: "Implement authentication flow in a single file with OAuth credentials.",
|
|
43
|
+
successCriteria: ["User can log in"],
|
|
44
|
+
});
|
|
45
|
+
assert.strictEqual(r.variant, "standard", `override should beat single-file signal. reasons: ${r.reasons.join("; ")}`);
|
|
46
|
+
assert.ok(r.signals.triggeredOverride, "override signals should be flagged");
|
|
47
|
+
assert.ok(r.reasons.some(s => s.includes("override keywords")));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("#4781 classifier: security review scope → standard (even if small)", () => {
|
|
51
|
+
const r = classifyMilestoneScope({
|
|
52
|
+
title: "Harden session tokens",
|
|
53
|
+
vision: "Review and patch security vulnerability in one session token helper.",
|
|
54
|
+
successCriteria: ["No XSS via token"],
|
|
55
|
+
});
|
|
56
|
+
assert.strictEqual(r.variant, "standard");
|
|
57
|
+
assert.ok(r.signals.triggeredOverride);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("#4781 classifier: schema migration mentioned → standard (override-level signal)", () => {
|
|
61
|
+
const r = classifyMilestoneScope({
|
|
62
|
+
title: "User profile v2",
|
|
63
|
+
vision: "Perform schema migration to split user.name into first_name and last_name across the users table.",
|
|
64
|
+
successCriteria: ["Migration lands", "Existing rows backfilled", "Rollback path validated"],
|
|
65
|
+
});
|
|
66
|
+
// "migration" / "migrate" / "backfill" are OVERRIDE_KEYWORDS, not
|
|
67
|
+
// COMPLEX_KEYWORDS — migration is override-level (forces at least
|
|
68
|
+
// `standard`), not complex-level. Safe behavior: migrations need the
|
|
69
|
+
// full standard pipeline but not the extra ceremony of complex.
|
|
70
|
+
assert.strictEqual(r.variant, "standard", `reasons: ${r.reasons.join("; ")}`);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("#4781 classifier: architecture keyword → complex", () => {
|
|
74
|
+
const r = classifyMilestoneScope({
|
|
75
|
+
title: "Redesign plugin registry",
|
|
76
|
+
vision: "Refactor core architecture of the plugin registry to support versioned contracts.",
|
|
77
|
+
});
|
|
78
|
+
assert.strictEqual(r.variant, "complex");
|
|
79
|
+
assert.ok(r.reasons.some(s => s.includes("complex keywords")));
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("#4781 classifier: >=8 files hint → complex", () => {
|
|
83
|
+
const r = classifyMilestoneScope({
|
|
84
|
+
title: "Multi-file refactor",
|
|
85
|
+
vision: "Touch 12 files to extract shared helpers.",
|
|
86
|
+
});
|
|
87
|
+
assert.strictEqual(r.variant, "complex");
|
|
88
|
+
assert.strictEqual(r.signals.fileCountHint, 12);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("#4781 classifier: backend API mention → standard (not trivial)", () => {
|
|
92
|
+
const r = classifyMilestoneScope({
|
|
93
|
+
title: "Health endpoint",
|
|
94
|
+
vision: "Add a single-file API endpoint returning status.",
|
|
95
|
+
successCriteria: ["/health returns 200"],
|
|
96
|
+
});
|
|
97
|
+
// Single file + no override + but backend mentioned → not trivial
|
|
98
|
+
assert.strictEqual(r.variant, "standard");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("#4781 classifier: tests mentioned → standard (not trivial)", () => {
|
|
102
|
+
const r = classifyMilestoneScope({
|
|
103
|
+
title: "Landing page",
|
|
104
|
+
vision: "Ship a static one-page landing page with unit tests for the form validation.",
|
|
105
|
+
});
|
|
106
|
+
assert.strictEqual(r.variant, "standard", `reasons: ${r.reasons.join("; ")}`);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("#4781 classifier: ambiguous prose → standard (safe default)", () => {
|
|
110
|
+
const r = classifyMilestoneScope({
|
|
111
|
+
title: "Generic improvements",
|
|
112
|
+
vision: "Make the system better.",
|
|
113
|
+
successCriteria: ["It's better"],
|
|
114
|
+
});
|
|
115
|
+
assert.strictEqual(r.variant, "standard");
|
|
116
|
+
assert.ok(r.reasons.includes("no strong signals — default"));
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("#4781 classifier: empty input → standard (safe default)", () => {
|
|
120
|
+
const r = classifyMilestoneScope({});
|
|
121
|
+
assert.strictEqual(r.variant, "standard");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// ─── Override precedence over trivial ──────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
test("#4781 classifier: override + trivial keyword → standard (override wins)", () => {
|
|
127
|
+
const r = classifyMilestoneScope({
|
|
128
|
+
title: "Token rotation",
|
|
129
|
+
vision: "Single file change to rotate the oauth token expiry schedule.",
|
|
130
|
+
});
|
|
131
|
+
// "single file" is trivial signal; "oauth" is override signal. Override wins.
|
|
132
|
+
assert.strictEqual(r.variant, "standard");
|
|
133
|
+
assert.ok(r.signals.triggeredOverride);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("#4781 classifier: complex + override → complex (complex wins, flagged)", () => {
|
|
137
|
+
const r = classifyMilestoneScope({
|
|
138
|
+
title: "Auth service refactor",
|
|
139
|
+
vision: "Refactor core authentication architecture across services.",
|
|
140
|
+
});
|
|
141
|
+
// Complex (architecture, refactor core) wins over override (auth).
|
|
142
|
+
assert.strictEqual(r.variant, "complex");
|
|
143
|
+
// Override still recorded in signals for telemetry.
|
|
144
|
+
assert.ok(r.signals.triggeredOverride, "override hits should still be tracked in signals");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ─── File count hint extraction ───────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
test("#4781 classifier: 'a single file' hint parsed as 1", () => {
|
|
150
|
+
const r = classifyMilestoneScope({
|
|
151
|
+
title: "Tweak",
|
|
152
|
+
vision: "Update a single file to flip the copy.",
|
|
153
|
+
});
|
|
154
|
+
assert.strictEqual(r.signals.fileCountHint, 1);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("#4781 classifier: 'two files' hint parsed as 2", () => {
|
|
158
|
+
const r = classifyMilestoneScope({
|
|
159
|
+
title: "Minor",
|
|
160
|
+
vision: "Touch two files.",
|
|
161
|
+
});
|
|
162
|
+
assert.strictEqual(r.signals.fileCountHint, 2);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("#4781 classifier: '12 files' hint parsed as 12", () => {
|
|
166
|
+
const r = classifyMilestoneScope({
|
|
167
|
+
title: "Bulk",
|
|
168
|
+
vision: "Update 12 files.",
|
|
169
|
+
});
|
|
170
|
+
assert.strictEqual(r.signals.fileCountHint, 12);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// ─── Reasons surface useful debugging info ─────────────────────────────────
|
|
174
|
+
|
|
175
|
+
test("#4781 classifier: reasons array populated for every branch", () => {
|
|
176
|
+
const branches: Array<[string, MilestoneScopeInput]> = [
|
|
177
|
+
["trivial", { title: "Readme typo", vision: "Fix a single file typo." }],
|
|
178
|
+
["standard (override)", { title: "Auth", vision: "Touch auth helper." }],
|
|
179
|
+
["complex (keyword)", { title: "Arch", vision: "Refactor core system design." }],
|
|
180
|
+
["complex (file count)", { title: "Bulk", vision: "Update 9 files." }],
|
|
181
|
+
["standard (default)", { title: "Generic", vision: "General work." }],
|
|
182
|
+
];
|
|
183
|
+
for (const [label, input] of branches) {
|
|
184
|
+
const r = classifyMilestoneScope(input);
|
|
185
|
+
assert.ok(r.reasons.length > 0, `${label}: reasons must not be empty`);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import { classifyMilestoneSummaryContent } from "../milestone-summary-classifier.ts";
|
|
5
|
+
|
|
6
|
+
test("milestone SUMMARY classifier treats explicit failed status as failure", () => {
|
|
7
|
+
assert.equal(
|
|
8
|
+
classifyMilestoneSummaryContent([
|
|
9
|
+
"---",
|
|
10
|
+
"status: failed",
|
|
11
|
+
"---",
|
|
12
|
+
"",
|
|
13
|
+
"# M001 Summary",
|
|
14
|
+
"Recovery stopped.",
|
|
15
|
+
].join("\n")),
|
|
16
|
+
"failure",
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("milestone SUMMARY classifier does not treat historical not-complete prose as failure", () => {
|
|
21
|
+
assert.equal(
|
|
22
|
+
classifyMilestoneSummaryContent([
|
|
23
|
+
"# M001 Summary",
|
|
24
|
+
"",
|
|
25
|
+
"This milestone was previously not complete, now resolved.",
|
|
26
|
+
].join("\n")),
|
|
27
|
+
"unknown",
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
@@ -74,7 +74,7 @@ test("#2885: cost table includes openai-codex provider models", () => {
|
|
|
74
74
|
const ids = BUNDLED_COST_TABLE.map(e => e.id);
|
|
75
75
|
const codexModels = [
|
|
76
76
|
"gpt-5.1", "gpt-5.1-codex-max", "gpt-5.1-codex-mini",
|
|
77
|
-
"gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.3-codex-spark", "gpt-5.4", "gpt-5.4-mini",
|
|
77
|
+
"gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.3-codex-spark", "gpt-5.4", "gpt-5.4-mini", "gpt-5.5",
|
|
78
78
|
];
|
|
79
79
|
for (const model of codexModels) {
|
|
80
80
|
assert.ok(ids.includes(model), `cost table should include openai-codex model "${model}"`);
|
|
@@ -101,3 +101,11 @@ test("#2885: lookupModelCost returns costs for new models (not 999 fallback)", (
|
|
|
101
101
|
assert.ok(entry.inputPer1k < 999, `${model} should have a real cost, not the 999 fallback`);
|
|
102
102
|
}
|
|
103
103
|
});
|
|
104
|
+
|
|
105
|
+
test("gpt-5.5 uses official OpenAI list pricing", () => {
|
|
106
|
+
const entry = lookupModelCost("gpt-5.5");
|
|
107
|
+
assert.ok(entry, "lookupModelCost should find gpt-5.5");
|
|
108
|
+
assert.equal(entry.inputPer1k, 0.005);
|
|
109
|
+
assert.equal(entry.outputPer1k, 0.03);
|
|
110
|
+
assert.equal(entry.updatedAt, "2026-04-23");
|
|
111
|
+
});
|
|
@@ -382,7 +382,7 @@ test("#2885: openai-codex standard-tier models are recognized", () => {
|
|
|
382
382
|
|
|
383
383
|
test("#2885: openai-codex heavy-tier models are recognized", () => {
|
|
384
384
|
const config = { ...defaultRoutingConfig(), enabled: true };
|
|
385
|
-
const heavyModels = ["gpt-5", "gpt-5-pro", "gpt-5.1", "gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.4", "o4-mini", "o4-mini-deep-research"];
|
|
385
|
+
const heavyModels = ["gpt-5", "gpt-5-pro", "gpt-5.1", "gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.4", "gpt-5.5", "o4-mini", "o4-mini-deep-research"];
|
|
386
386
|
for (const model of heavyModels) {
|
|
387
387
|
const result = resolveModelForComplexity(
|
|
388
388
|
makeClassification("heavy"),
|
|
@@ -18,54 +18,12 @@ import { tmpdir } from "node:os";
|
|
|
18
18
|
import { execFileSync } from "node:child_process";
|
|
19
19
|
import { nativeIsRepo, nativeCommit, nativeResetHard } from "../native-git-bridge.js";
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
function extractFunctionBody(src: string, fnName: string): string {
|
|
29
|
-
const idx = src.indexOf(`export function ${fnName}`);
|
|
30
|
-
if (idx === -1) throw new Error(`${fnName} not found in source`);
|
|
31
|
-
return src.slice(idx, idx + 1500);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function hasRawExecSync(body: string): boolean {
|
|
35
|
-
const withoutFileSync = body.replace(/execFileSync\(/g, "__FILESYNC__");
|
|
36
|
-
return withoutFileSync.includes("execSync(");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
describe("native-git-bridge #4180: fallback paths use execFileSync not execSync", () => {
|
|
40
|
-
const src = readFileSync(SRC_PATH, "utf-8");
|
|
41
|
-
|
|
42
|
-
test("nativeIsRepo fallback does not use raw execSync", () => {
|
|
43
|
-
const body = extractFunctionBody(src, "nativeIsRepo");
|
|
44
|
-
assert.equal(
|
|
45
|
-
hasRawExecSync(body),
|
|
46
|
-
false,
|
|
47
|
-
"nativeIsRepo fallback must use execFileSync to avoid cmd.exe PATH failures on Windows",
|
|
48
|
-
);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test("nativeCommit fallback does not use raw execSync", () => {
|
|
52
|
-
const body = extractFunctionBody(src, "nativeCommit");
|
|
53
|
-
assert.equal(
|
|
54
|
-
hasRawExecSync(body),
|
|
55
|
-
false,
|
|
56
|
-
"nativeCommit fallback must use execFileSync to avoid cmd.exe PATH failures on Windows",
|
|
57
|
-
);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("nativeResetHard fallback does not use raw execSync", () => {
|
|
61
|
-
const body = extractFunctionBody(src, "nativeResetHard");
|
|
62
|
-
assert.equal(
|
|
63
|
-
hasRawExecSync(body),
|
|
64
|
-
false,
|
|
65
|
-
"nativeResetHard fallback must use execFileSync to avoid cmd.exe PATH failures on Windows",
|
|
66
|
-
);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
21
|
+
// Note: prior static-analysis tests that scanned native-git-bridge.ts for
|
|
22
|
+
// the raw shell-spawn pattern were removed under #4827 — the integration
|
|
23
|
+
// tests below already exercise the fallback path end-to-end with the native
|
|
24
|
+
// module disabled (GSD_ENABLE_NATIVE_GSD_GIT unset). Any cmd.exe PATH
|
|
25
|
+
// regression on Windows surfaces through a real fallback failure, not a
|
|
26
|
+
// grep miss in source text.
|
|
69
27
|
|
|
70
28
|
// ─── Integration tests ────────────────────────────────────────────────────
|
|
71
29
|
// Verify correct runtime behaviour through the fallback path (native module
|
|
@@ -16,9 +16,12 @@ test("buildNotificationWidgetLines shows unread count with shortcut pair", () =>
|
|
|
16
16
|
appendNotification("Need attention", "warning");
|
|
17
17
|
|
|
18
18
|
const lines = buildNotificationWidgetLines();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
assert.
|
|
19
|
+
// Widget must render at least one line; may add secondary lines later
|
|
20
|
+
// (e.g., "View with /gsd notif") without breaking this assertion.
|
|
21
|
+
assert.ok(lines.length >= 1, `expected at least 1 widget line, got ${lines.length}`);
|
|
22
|
+
const combined = lines.join("\n");
|
|
23
|
+
assert.match(combined, /🔔\s+1 unread/);
|
|
24
|
+
assert.match(combined, /\(.+\/.+\)/);
|
|
22
25
|
} finally {
|
|
23
26
|
_resetNotificationStore();
|
|
24
27
|
rmSync(tmp, { recursive: true, force: true });
|