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
|
@@ -26,14 +26,6 @@ import { MAX_FINALIZE_TIMEOUTS } from "../auto/types.ts";
|
|
|
26
26
|
|
|
27
27
|
const { assertTrue, assertEq, report } = createTestContext();
|
|
28
28
|
|
|
29
|
-
function getRunFinalizeBody(phasesSource: string): string {
|
|
30
|
-
const fnIdx = phasesSource.indexOf("export async function runFinalize(");
|
|
31
|
-
assertTrue(fnIdx > 0, "runFinalize function should exist in phases.ts");
|
|
32
|
-
|
|
33
|
-
const nextExportIdx = phasesSource.indexOf("\nexport ", fnIdx + 1);
|
|
34
|
-
return phasesSource.slice(fnIdx, nextExportIdx > fnIdx ? nextExportIdx : undefined);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
29
|
// ═══ Test: withTimeout resolves when inner promise resolves promptly ══════════
|
|
38
30
|
|
|
39
31
|
{
|
|
@@ -142,45 +134,6 @@ function getRunFinalizeBody(phasesSource: string): string {
|
|
|
142
134
|
assertEq(result.timedOut, false, "should not time out");
|
|
143
135
|
}
|
|
144
136
|
|
|
145
|
-
// ═══ Test: runFinalize wraps BOTH pre and post verification with withTimeout ═
|
|
146
|
-
|
|
147
|
-
{
|
|
148
|
-
console.log("\n=== #3757: runFinalize wraps preVerification with timeout guard ===");
|
|
149
|
-
|
|
150
|
-
const { readFileSync } = await import("node:fs");
|
|
151
|
-
const phasesSource = readFileSync(
|
|
152
|
-
new URL("../auto/phases.ts", import.meta.url),
|
|
153
|
-
"utf-8",
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const fnBody = getRunFinalizeBody(phasesSource);
|
|
157
|
-
|
|
158
|
-
// postUnitPreVerification must be wrapped in withTimeout
|
|
159
|
-
const preTimeoutIdx = fnBody.indexOf("withTimeout(");
|
|
160
|
-
assertTrue(preTimeoutIdx > 0, "withTimeout should appear in runFinalize");
|
|
161
|
-
|
|
162
|
-
const preVerIdx = fnBody.indexOf("postUnitPreVerification");
|
|
163
|
-
assertTrue(preVerIdx > 0, "postUnitPreVerification should appear in runFinalize");
|
|
164
|
-
|
|
165
|
-
// The first withTimeout should wrap postUnitPreVerification (not postUnitPostVerification)
|
|
166
|
-
const firstWithTimeout = fnBody.slice(preTimeoutIdx, preTimeoutIdx + 200);
|
|
167
|
-
assertTrue(
|
|
168
|
-
firstWithTimeout.includes("postUnitPreVerification"),
|
|
169
|
-
"first withTimeout in runFinalize should wrap postUnitPreVerification",
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
// postUnitPostVerification must also be wrapped
|
|
173
|
-
const postVerIdx = fnBody.indexOf("postUnitPostVerification");
|
|
174
|
-
assertTrue(postVerIdx > 0, "postUnitPostVerification should appear in runFinalize");
|
|
175
|
-
|
|
176
|
-
// Count withTimeout occurrences — should be at least 2 (pre + post)
|
|
177
|
-
const timeoutCount = (fnBody.match(/withTimeout\(/g) || []).length;
|
|
178
|
-
assertTrue(
|
|
179
|
-
timeoutCount >= 2,
|
|
180
|
-
`runFinalize should have at least 2 withTimeout guards (found ${timeoutCount})`,
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
137
|
// ═══ Test: MAX_FINALIZE_TIMEOUTS is defined and reasonable ═══════════════════
|
|
185
138
|
|
|
186
139
|
{
|
|
@@ -200,62 +153,13 @@ function getRunFinalizeBody(phasesSource: string): string {
|
|
|
200
153
|
);
|
|
201
154
|
}
|
|
202
155
|
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
"utf-8",
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
const fnBody = getRunFinalizeBody(phasesSource);
|
|
215
|
-
|
|
216
|
-
const helperCallCount = (fnBody.match(/failClosedOnFinalizeTimeout\(/g) || []).length;
|
|
217
|
-
assertTrue(
|
|
218
|
-
helperCallCount >= 2,
|
|
219
|
-
`runFinalize should route both timeout branches through failClosedOnFinalizeTimeout (found ${helperCallCount})`,
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
const helperStart = phasesSource.indexOf("async function failClosedOnFinalizeTimeout");
|
|
223
|
-
assertTrue(helperStart > 0, "failClosedOnFinalizeTimeout helper should exist");
|
|
224
|
-
const helperEnd = phasesSource.indexOf("// ─── runPreDispatch", helperStart);
|
|
225
|
-
const helperBody = phasesSource.slice(helperStart, helperEnd > helperStart ? helperEnd : undefined);
|
|
226
|
-
|
|
227
|
-
const incrementCount = (helperBody.match(/consecutiveFinalizeTimeouts\+\+/g) || []).length;
|
|
228
|
-
assertTrue(
|
|
229
|
-
incrementCount >= 1,
|
|
230
|
-
`timeout helper should increment consecutiveFinalizeTimeouts (found ${incrementCount})`,
|
|
231
|
-
);
|
|
232
|
-
|
|
233
|
-
const detachCount = (helperBody.match(/s\.currentUnit\s*=\s*null/g) || []).length;
|
|
234
|
-
assertTrue(
|
|
235
|
-
detachCount >= 1,
|
|
236
|
-
`timeout helper should detach s.currentUnit (found ${detachCount})`,
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
const pauseCount = (helperBody.match(/pauseAuto\(/g) || []).length;
|
|
240
|
-
assertTrue(
|
|
241
|
-
pauseCount >= 1,
|
|
242
|
-
`timeout helper should pause auto-mode (found ${pauseCount})`,
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
assertTrue(
|
|
246
|
-
helperBody.includes('eventType: "unit-end"'),
|
|
247
|
-
"timeout helper should emit a terminal unit-end event",
|
|
248
|
-
);
|
|
249
|
-
assertTrue(
|
|
250
|
-
helperBody.includes('phase: "finalize-timeout"'),
|
|
251
|
-
"timeout helper should persist finalize-timeout runtime state",
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
// Successful finalize should reset the counter
|
|
255
|
-
assertTrue(
|
|
256
|
-
fnBody.includes("consecutiveFinalizeTimeouts = 0"),
|
|
257
|
-
"should reset consecutiveFinalizeTimeouts on successful finalize",
|
|
258
|
-
);
|
|
259
|
-
}
|
|
156
|
+
// Note: the two previous source-grep blocks that scanned phases.ts for
|
|
157
|
+
// `withTimeout(` / `failClosedOnFinalizeTimeout(` occurrences were removed
|
|
158
|
+
// under #4825 — they encoded implementation shape (Goodhart) and broke on
|
|
159
|
+
// any helper/loop refactor without catching a real regression. The intended
|
|
160
|
+
// behavioural invariant (pre+post verification hangs → pauseAuto called,
|
|
161
|
+
// unit-end emitted, escalation counter incremented) should be covered by a
|
|
162
|
+
// runFinalize integration test with mocked hanging verification — tracked
|
|
163
|
+
// separately. Refs #4825.
|
|
260
164
|
|
|
261
165
|
report();
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// GSD Gate State Canonicalization Tests
|
|
2
|
+
// Regression tests for #4950: canonical omitted state and GateVerdict type narrowing.
|
|
3
|
+
|
|
4
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
openDatabase,
|
|
12
|
+
closeDatabase,
|
|
13
|
+
insertGateRow,
|
|
14
|
+
markAllGatesOmitted,
|
|
15
|
+
getGateResults,
|
|
16
|
+
getPendingGates,
|
|
17
|
+
insertMilestone,
|
|
18
|
+
insertSlice,
|
|
19
|
+
} from "../gsd-db.ts";
|
|
20
|
+
import type { GateVerdict } from "../types.ts";
|
|
21
|
+
|
|
22
|
+
describe("gate-state canonicalization (#4950)", () => {
|
|
23
|
+
let tmpDir: string;
|
|
24
|
+
let dbPath: string;
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
tmpDir = mkdtempSync(join(tmpdir(), "gate-canon-test-"));
|
|
28
|
+
dbPath = join(tmpDir, "gsd.db");
|
|
29
|
+
openDatabase(dbPath);
|
|
30
|
+
insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
|
|
31
|
+
insertSlice({
|
|
32
|
+
milestoneId: "M001",
|
|
33
|
+
id: "S01",
|
|
34
|
+
title: "Test Slice",
|
|
35
|
+
status: "pending",
|
|
36
|
+
risk: "medium",
|
|
37
|
+
depends: [],
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
closeDatabase();
|
|
43
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("markAllGatesOmitted produces status=complete, verdict=omitted (not status=omitted)", () => {
|
|
47
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
48
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
|
|
49
|
+
|
|
50
|
+
markAllGatesOmitted("M001", "S01");
|
|
51
|
+
|
|
52
|
+
const all = getGateResults("M001", "S01");
|
|
53
|
+
assert.equal(all.length, 2);
|
|
54
|
+
for (const g of all) {
|
|
55
|
+
assert.equal(g.status, "complete", `expected status=complete for gate ${g.gate_id}`);
|
|
56
|
+
assert.equal(g.verdict, "omitted", `expected verdict=omitted for gate ${g.gate_id}`);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("markAllGatesOmitted leaves no pending gates", () => {
|
|
61
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
62
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
|
|
63
|
+
|
|
64
|
+
markAllGatesOmitted("M001", "S01");
|
|
65
|
+
|
|
66
|
+
const pending = getPendingGates("M001", "S01");
|
|
67
|
+
assert.equal(pending.length, 0);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("pending gate verdict is null, not empty string", () => {
|
|
71
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
72
|
+
|
|
73
|
+
const pending = getPendingGates("M001", "S01");
|
|
74
|
+
assert.equal(pending.length, 1);
|
|
75
|
+
assert.equal(pending[0].verdict, null, "pending gate verdict must be null, not empty string");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("complete gate verdict round-trips as a valid GateVerdict (pass/flag/omitted only)", () => {
|
|
79
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
|
|
80
|
+
markAllGatesOmitted("M001", "S01");
|
|
81
|
+
|
|
82
|
+
const results = getGateResults("M001", "S01");
|
|
83
|
+
const q4 = results.find((g) => g.gate_id === "Q4");
|
|
84
|
+
assert.ok(q4, "Q4 gate must exist");
|
|
85
|
+
|
|
86
|
+
const validVerdicts: GateVerdict[] = ["pass", "flag", "omitted"];
|
|
87
|
+
assert.ok(
|
|
88
|
+
q4.verdict !== null && validVerdicts.includes(q4.verdict),
|
|
89
|
+
`verdict "${q4.verdict}" must be one of: ${validVerdicts.join(", ")}`,
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("empty-string verdict is not reachable after round-trip through DB", () => {
|
|
94
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
95
|
+
markAllGatesOmitted("M001", "S01");
|
|
96
|
+
|
|
97
|
+
const results = getGateResults("M001", "S01");
|
|
98
|
+
for (const g of results) {
|
|
99
|
+
assert.notEqual(g.verdict, "", `gate ${g.gate_id} verdict must not be empty string`);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -109,7 +109,7 @@ describe("quality_gates CRUD", () => {
|
|
|
109
109
|
const all = getGateResults("M001", "S01");
|
|
110
110
|
assert.equal(all.length, 3);
|
|
111
111
|
for (const g of all) {
|
|
112
|
-
assert.equal(g.status, "
|
|
112
|
+
assert.equal(g.status, "complete");
|
|
113
113
|
assert.equal(g.verdict, "omitted");
|
|
114
114
|
}
|
|
115
115
|
});
|
|
@@ -85,8 +85,10 @@ test("google-search stub: session_start warning contains package name", async (_
|
|
|
85
85
|
);
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
-
test("google-search stub: session_start warning
|
|
89
|
-
// STUB-01:
|
|
88
|
+
test("google-search stub: session_start warning explains package is not yet published", async (_t) => {
|
|
89
|
+
// STUB-01: stub must NOT advise `gsd extensions install` — the replacement
|
|
90
|
+
// package is not yet on npm, so that command would 404. The message must
|
|
91
|
+
// explain the extraction is in progress and no user action is required.
|
|
90
92
|
const mod = await import("../../google-search/index.ts");
|
|
91
93
|
const stubFn = mod.default;
|
|
92
94
|
|
|
@@ -115,7 +117,15 @@ test("google-search stub: session_start warning contains install command", async
|
|
|
115
117
|
await capturedHandler!({}, mockCtx);
|
|
116
118
|
|
|
117
119
|
assert.ok(
|
|
118
|
-
capturedMessage?.includes("gsd extensions install"),
|
|
119
|
-
`Expected message to include
|
|
120
|
+
!capturedMessage?.includes("gsd extensions install"),
|
|
121
|
+
`Expected message NOT to include unpublished install command, got: "${capturedMessage}"`,
|
|
122
|
+
);
|
|
123
|
+
assert.ok(
|
|
124
|
+
capturedMessage?.includes("not yet published"),
|
|
125
|
+
`Expected message to include "not yet published", got: "${capturedMessage}"`,
|
|
126
|
+
);
|
|
127
|
+
assert.ok(
|
|
128
|
+
capturedMessage?.includes("No action needed"),
|
|
129
|
+
`Expected message to include "No action needed", got: "${capturedMessage}"`,
|
|
120
130
|
);
|
|
121
131
|
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression tests for the headless vs interactive milestone-bootstrap divergence.
|
|
3
|
+
*
|
|
4
|
+
* Two defects were covered here:
|
|
5
|
+
* 1. `showHeadlessMilestoneCreation` dispatched with `unitType: "plan-milestone"`
|
|
6
|
+
* instead of `"discuss-milestone"`. The `discuss-` prefix drives tool
|
|
7
|
+
* scoping (`guided-flow.ts:583`) and enables the `checkAutoStartAfterDiscuss`
|
|
8
|
+
* guardrails — routing through `plan-milestone` bypassed them even
|
|
9
|
+
* though headless is semantically a discuss flow.
|
|
10
|
+
* 2. The `discuss-headless.md` ready-phrase pre-condition was a prose
|
|
11
|
+
* sentence, so models that treated it as advisory could skip ahead to
|
|
12
|
+
* the ready phrase without actually writing the artifacts. The checkbox
|
|
13
|
+
* format from `discuss.md` has lower abstraction cost and is harder to
|
|
14
|
+
* rationalize past.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { test, describe } from "node:test";
|
|
18
|
+
import assert from "node:assert/strict";
|
|
19
|
+
import { readFileSync } from "node:fs";
|
|
20
|
+
import { dirname, join } from "node:path";
|
|
21
|
+
import { fileURLToPath } from "node:url";
|
|
22
|
+
|
|
23
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
|
|
25
|
+
const GUIDED_FLOW_PATH = join(__dirname, "..", "guided-flow.ts");
|
|
26
|
+
const DISCUSS_HEADLESS_PATH = join(__dirname, "..", "prompts", "discuss-headless.md");
|
|
27
|
+
|
|
28
|
+
function getGuidedFlowSource(): string {
|
|
29
|
+
return readFileSync(GUIDED_FLOW_PATH, "utf-8");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getHeadlessPromptSource(): string {
|
|
33
|
+
return readFileSync(DISCUSS_HEADLESS_PATH, "utf-8");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe("headless milestone bootstrap — parity with interactive flow", () => {
|
|
37
|
+
test("showHeadlessMilestoneCreation dispatches as discuss-milestone, not plan-milestone", () => {
|
|
38
|
+
const source = getGuidedFlowSource();
|
|
39
|
+
const fnStart = source.indexOf("export async function showHeadlessMilestoneCreation");
|
|
40
|
+
assert.ok(fnStart > -1, "showHeadlessMilestoneCreation must exist");
|
|
41
|
+
|
|
42
|
+
// Scope: from the function start to the next top-level export (or EOF).
|
|
43
|
+
const nextExport = source.indexOf("\nexport ", fnStart + 1);
|
|
44
|
+
const fnBody = source.slice(fnStart, nextExport === -1 ? source.length : nextExport);
|
|
45
|
+
|
|
46
|
+
// Match only the actual dispatchWorkflow call — comments in the body
|
|
47
|
+
// may mention "plan-milestone" as part of the fix rationale.
|
|
48
|
+
const dispatchMatches = [...fnBody.matchAll(/dispatchWorkflow\([^)]*,\s*"([^"]+)"\s*\)/g)];
|
|
49
|
+
assert.strictEqual(
|
|
50
|
+
dispatchMatches.length,
|
|
51
|
+
1,
|
|
52
|
+
`expected exactly one dispatchWorkflow call, found ${dispatchMatches.length}`,
|
|
53
|
+
);
|
|
54
|
+
assert.strictEqual(
|
|
55
|
+
dispatchMatches[0][1],
|
|
56
|
+
"discuss-milestone",
|
|
57
|
+
`showHeadlessMilestoneCreation must dispatch as "discuss-milestone" so tool scoping and discuss-flow guardrails apply; got "${dispatchMatches[0][1]}"`,
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("discuss-headless single-milestone pre-condition uses the non-bypassable checkbox format", () => {
|
|
62
|
+
const source = getHeadlessPromptSource();
|
|
63
|
+
const section = source.split("### Multi-Milestone")[0];
|
|
64
|
+
assert.ok(
|
|
65
|
+
/### Ready-phrase pre-condition \(NON-BYPASSABLE\)/.test(section),
|
|
66
|
+
"single-milestone ready-phrase section must be present",
|
|
67
|
+
);
|
|
68
|
+
// All four required artifacts must appear as checkboxes, not a prose list.
|
|
69
|
+
for (const artifact of [
|
|
70
|
+
"`.gsd/PROJECT.md`",
|
|
71
|
+
"`.gsd/REQUIREMENTS.md`",
|
|
72
|
+
"`{{contextPath}}`",
|
|
73
|
+
"`gsd_plan_milestone`",
|
|
74
|
+
]) {
|
|
75
|
+
assert.ok(
|
|
76
|
+
new RegExp(`- \\[ \\] [A-Za-z]+ ${artifact.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`).test(section),
|
|
77
|
+
`single-milestone pre-condition must include a checkbox for ${artifact}`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
assert.ok(
|
|
81
|
+
/If ANY box is unchecked, \*\*STOP\*\*/.test(section),
|
|
82
|
+
"single-milestone pre-condition must include the 'If ANY box is unchecked, STOP' sentinel",
|
|
83
|
+
);
|
|
84
|
+
assert.ok(
|
|
85
|
+
/Do not announce the ready phrase as something you are "about to" do/.test(section),
|
|
86
|
+
"single-milestone pre-condition must include the 'do not announce intent' guard",
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("discuss-headless multi-milestone pre-condition uses the non-bypassable checkbox format", () => {
|
|
91
|
+
const source = getHeadlessPromptSource();
|
|
92
|
+
const multiIdx = source.indexOf("### Multi-Milestone");
|
|
93
|
+
assert.ok(multiIdx > -1, "multi-milestone section must be present");
|
|
94
|
+
const multiSection = source.slice(multiIdx);
|
|
95
|
+
|
|
96
|
+
assert.ok(
|
|
97
|
+
/### Ready-phrase pre-condition \(NON-BYPASSABLE\)/.test(multiSection),
|
|
98
|
+
"multi-milestone ready-phrase section must be present",
|
|
99
|
+
);
|
|
100
|
+
for (const artifact of [
|
|
101
|
+
"`.gsd/PROJECT.md`",
|
|
102
|
+
"`.gsd/REQUIREMENTS.md`",
|
|
103
|
+
"`gsd_plan_milestone`",
|
|
104
|
+
"`.gsd/DISCUSSION-MANIFEST.json`",
|
|
105
|
+
]) {
|
|
106
|
+
const escaped = artifact.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
107
|
+
assert.ok(
|
|
108
|
+
new RegExp(`- \\[ \\] [\\s\\S]*?${escaped}`).test(multiSection),
|
|
109
|
+
`multi-milestone pre-condition must include a checkbox referencing ${artifact}`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
assert.ok(
|
|
113
|
+
/gates_completed === total/.test(multiSection),
|
|
114
|
+
"multi-milestone pre-condition must still enforce gates_completed === total",
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { join, dirname } from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
|
|
7
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const gsdDir = join(__dirname, "..");
|
|
9
3
|
|
|
10
4
|
/**
|
|
11
5
|
* Regression tests for #2826: hook/* completed-unit keys were parsed
|
|
@@ -15,17 +9,13 @@ const gsdDir = join(__dirname, "..");
|
|
|
15
9
|
* The root cause: `key.indexOf("/")` splits "hook/telegram-progress/M007/S01"
|
|
16
10
|
* into unitType="hook" + unitId="telegram-progress/M007/S01" instead of
|
|
17
11
|
* unitType="hook/telegram-progress" + unitId="M007/S01".
|
|
12
|
+
*
|
|
13
|
+
* These tests exercise the real `splitCompletedKey` helper — the previous
|
|
14
|
+
* source-grep "does not use indexOf" blocks were dropped under #4825 as
|
|
15
|
+
* they over-specified implementation shape.
|
|
18
16
|
*/
|
|
19
17
|
|
|
20
18
|
describe("splitCompletedKey (#2826)", () => {
|
|
21
|
-
it("is exported from forensics.ts", () => {
|
|
22
|
-
const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
|
|
23
|
-
assert.ok(
|
|
24
|
-
source.includes("export function splitCompletedKey"),
|
|
25
|
-
"forensics.ts must export splitCompletedKey helper",
|
|
26
|
-
);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
19
|
it("splits simple unit types correctly", async () => {
|
|
30
20
|
const { splitCompletedKey } = await import("../forensics.ts");
|
|
31
21
|
const result = splitCompletedKey("execute-task/M007/S01/T01");
|
|
@@ -64,44 +54,3 @@ describe("splitCompletedKey (#2826)", () => {
|
|
|
64
54
|
assert.strictEqual(splitCompletedKey("hook/someName"), null);
|
|
65
55
|
});
|
|
66
56
|
});
|
|
67
|
-
|
|
68
|
-
describe("forensics detectMissingArtifacts uses splitCompletedKey (#2826)", () => {
|
|
69
|
-
it("does not use indexOf for key splitting", () => {
|
|
70
|
-
const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
|
|
71
|
-
// Extract only the detectMissingArtifacts function body
|
|
72
|
-
const fnStart = source.indexOf("function detectMissingArtifacts");
|
|
73
|
-
assert.ok(fnStart !== -1, "detectMissingArtifacts must exist");
|
|
74
|
-
const fnBody = source.slice(fnStart, source.indexOf("\n}\n", fnStart) + 3);
|
|
75
|
-
|
|
76
|
-
assert.ok(
|
|
77
|
-
!fnBody.includes('key.indexOf("/")'),
|
|
78
|
-
"detectMissingArtifacts must not use key.indexOf('/') — use splitCompletedKey instead",
|
|
79
|
-
);
|
|
80
|
-
assert.ok(
|
|
81
|
-
fnBody.includes("splitCompletedKey"),
|
|
82
|
-
"detectMissingArtifacts must use splitCompletedKey helper",
|
|
83
|
-
);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe("doctor-runtime-checks uses splitCompletedKey (#2826)", () => {
|
|
88
|
-
it("does not use indexOf for key splitting in orphaned-key check", () => {
|
|
89
|
-
const source = readFileSync(
|
|
90
|
-
join(gsdDir, "doctor-runtime-checks.ts"),
|
|
91
|
-
"utf-8",
|
|
92
|
-
);
|
|
93
|
-
// Find the orphaned completed-units section
|
|
94
|
-
const sectionStart = source.indexOf("Orphaned completed-units");
|
|
95
|
-
assert.ok(sectionStart !== -1, "orphaned completed-units section must exist");
|
|
96
|
-
const sectionBody = source.slice(sectionStart, source.indexOf("} catch", sectionStart));
|
|
97
|
-
|
|
98
|
-
assert.ok(
|
|
99
|
-
!sectionBody.includes('key.indexOf("/")'),
|
|
100
|
-
"doctor orphaned-key check must not use key.indexOf('/') — use splitCompletedKey instead",
|
|
101
|
-
);
|
|
102
|
-
assert.ok(
|
|
103
|
-
sectionBody.includes("splitCompletedKey"),
|
|
104
|
-
"doctor orphaned-key check must use splitCompletedKey helper",
|
|
105
|
-
);
|
|
106
|
-
});
|
|
107
|
-
});
|
package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts
CHANGED
|
@@ -21,10 +21,9 @@ import {
|
|
|
21
21
|
realpathSync,
|
|
22
22
|
readFileSync,
|
|
23
23
|
} from "node:fs";
|
|
24
|
-
import { join
|
|
24
|
+
import { join } from "node:path";
|
|
25
25
|
import { tmpdir } from "node:os";
|
|
26
26
|
import { execSync } from "node:child_process";
|
|
27
|
-
import { fileURLToPath } from "node:url";
|
|
28
27
|
|
|
29
28
|
import {
|
|
30
29
|
createAutoWorktree,
|
|
@@ -33,8 +32,6 @@ import {
|
|
|
33
32
|
mergeMilestoneToMain,
|
|
34
33
|
} from "../../auto-worktree.ts";
|
|
35
34
|
|
|
36
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
37
|
-
|
|
38
35
|
function run(command: string, cwd: string): string {
|
|
39
36
|
return execSync(command, {
|
|
40
37
|
cwd,
|
|
@@ -75,58 +72,12 @@ function createMilestoneArtifacts(dir: string, mid: string): void {
|
|
|
75
72
|
writeFileSync(join(msDir, `${mid}-ROADMAP.md`), roadmap);
|
|
76
73
|
}
|
|
77
74
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"utf-8",
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
// Find the "incomplete.length === 0" block
|
|
88
|
-
const incompleteIdx = loopSrc.indexOf("incomplete.length === 0");
|
|
89
|
-
assert.ok(
|
|
90
|
-
incompleteIdx > -1,
|
|
91
|
-
"auto/phases.ts should have 'incomplete.length === 0' check",
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
// The merge call must appear BETWEEN the incomplete check and the stopAuto call.
|
|
95
|
-
const blockAfterIncomplete = loopSrc.slice(
|
|
96
|
-
incompleteIdx,
|
|
97
|
-
incompleteIdx + 3000,
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
assert.ok(
|
|
101
|
-
blockAfterIncomplete.includes("deps.resolver.mergeAndExit"),
|
|
102
|
-
"auto/phases.ts should call resolver.mergeAndExit in the 'all milestones complete' path",
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
// The merge should come before stopAuto in this block
|
|
106
|
-
const mergePos = blockAfterIncomplete.indexOf("deps.resolver.mergeAndExit");
|
|
107
|
-
const stopPos = blockAfterIncomplete.indexOf("stopAuto");
|
|
108
|
-
assert.ok(
|
|
109
|
-
mergePos < stopPos,
|
|
110
|
-
"resolver.mergeAndExit should be called before stopAuto in the 'all complete' path",
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
const helperIdx = resolverSrc.indexOf("mergeAndExit(milestoneId");
|
|
114
|
-
assert.ok(
|
|
115
|
-
helperIdx > -1,
|
|
116
|
-
"WorktreeResolver.mergeAndExit helper should exist",
|
|
117
|
-
);
|
|
118
|
-
const helperBlock = resolverSrc.slice(helperIdx, helperIdx + 2600);
|
|
119
|
-
assert.ok(
|
|
120
|
-
helperBlock.includes('mode === "worktree"') ||
|
|
121
|
-
helperBlock.includes('mode: "worktree"'),
|
|
122
|
-
"WorktreeResolver.mergeAndExit should handle worktree mode",
|
|
123
|
-
);
|
|
124
|
-
assert.ok(
|
|
125
|
-
helperBlock.includes('mode === "branch"') ||
|
|
126
|
-
helperBlock.includes('mode: "branch"'),
|
|
127
|
-
"WorktreeResolver.mergeAndExit should handle branch mode",
|
|
128
|
-
);
|
|
129
|
-
});
|
|
75
|
+
// Note: the prior phases.ts / worktree-resolver.ts source-grep block was
|
|
76
|
+
// removed under #4825 — it asserted `deps.resolver.mergeAndExit` appears
|
|
77
|
+
// before `stopAuto` via indexOf positions in the source text, which broke
|
|
78
|
+
// on any helper refactor without catching a real regression. The two
|
|
79
|
+
// integration tests below exercise the merge-before-stop behaviour end
|
|
80
|
+
// to end through real git worktrees.
|
|
130
81
|
|
|
131
82
|
// ─── Integration: single milestone completes → merged to main ────────────────
|
|
132
83
|
|
|
@@ -717,6 +717,26 @@ test("hasImplementationArtifacts returns 'present' when implementation files com
|
|
|
717
717
|
assert.equal(result, "present", "should return 'present' when implementation files are present");
|
|
718
718
|
});
|
|
719
719
|
|
|
720
|
+
test("hasImplementationArtifacts finds production execute-task commits after retry resumes on main (#4699)", (t) => {
|
|
721
|
+
const base = makeGitBase();
|
|
722
|
+
t.after(() => cleanup(base));
|
|
723
|
+
|
|
724
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
725
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), "# Roadmap");
|
|
726
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
727
|
+
execFileSync("git", ["commit", "-m", "chore: auto-commit after plan-milestone\n\nGSD-Unit: M001"], { cwd: base, stdio: "ignore" });
|
|
728
|
+
|
|
729
|
+
mkdirSync(join(base, "src"), { recursive: true });
|
|
730
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
731
|
+
writeFileSync(join(base, "src", "feature.ts"), "export function feature() {}");
|
|
732
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-SUMMARY.md"), "# Summary");
|
|
733
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
734
|
+
execFileSync("git", ["commit", "-m", "feat: add milestone feature\n\nGSD-Task: S01/T01"], { cwd: base, stdio: "ignore" });
|
|
735
|
+
|
|
736
|
+
const result = hasImplementationArtifacts(base, "M001");
|
|
737
|
+
assert.equal(result, "present", "main self-diff retry should find production execute-task commits");
|
|
738
|
+
});
|
|
739
|
+
|
|
720
740
|
test("hasImplementationArtifacts returns 'unknown' on non-git directory (fail-open)", (t) => {
|
|
721
741
|
const base = join(tmpdir(), `gsd-test-nogit-${randomUUID()}`);
|
|
722
742
|
mkdirSync(base, { recursive: true });
|
|
@@ -161,11 +161,27 @@ describe('doctor-proactive', async () => {
|
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
test('escalation: no double escalation', () => {
|
|
164
|
-
//
|
|
164
|
+
// Self-contained: drive the escalated state from scratch in this test.
|
|
165
|
+
// Previously this relied on module-singleton state left over from the
|
|
166
|
+
// preceding 'escalation: at threshold' test, which silently broke under
|
|
167
|
+
// filtered/parallel/reordered runs (the fallback `shouldEscalate: false`
|
|
168
|
+
// path was satisfied by the wrong reason — see #4828).
|
|
169
|
+
resetProactiveHealing();
|
|
170
|
+
for (let i = 0; i < 5; i++) {
|
|
171
|
+
recordHealthSnapshot(0, 0, 0); // older clean snapshots
|
|
172
|
+
}
|
|
173
|
+
for (let i = 0; i < 5; i++) {
|
|
174
|
+
recordHealthSnapshot(2, 1, 0); // recent error snapshots → degrading trend
|
|
175
|
+
}
|
|
176
|
+
// First check: trigger escalation.
|
|
177
|
+
const first = checkHealEscalation(2, [{ code: "test", message: "test error", unitId: "M001/S01" }]);
|
|
178
|
+
assert.deepStrictEqual(first.shouldEscalate, true, "precondition: first call escalates");
|
|
179
|
+
|
|
180
|
+
// Second check: same session, must NOT double-escalate.
|
|
165
181
|
recordHealthSnapshot(2, 0, 0);
|
|
166
182
|
const result = checkHealEscalation(2, [{ code: "test", message: "test error", unitId: "M001/S01" }]);
|
|
167
183
|
assert.deepStrictEqual(result.shouldEscalate, false, "no double escalation in same session");
|
|
168
|
-
assert.ok(result.reason.includes("already escalated"),
|
|
184
|
+
assert.ok(result.reason.includes("already escalated"), `reason must explain no-re-escalation (got: ${result.reason})`);
|
|
169
185
|
});
|
|
170
186
|
|
|
171
187
|
test('escalation: deferred when improving', () => {
|
package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts
CHANGED
|
@@ -140,12 +140,18 @@ for (let i = 1; i <= COMPLETED_COUNT; i++) {
|
|
|
140
140
|
|
|
141
141
|
// ─── Test: the overall context should be reasonable in size ──────────────
|
|
142
142
|
|
|
143
|
-
//
|
|
144
|
-
//
|
|
143
|
+
// Invariant (not absolute budget): the per-completed-milestone line
|
|
144
|
+
// contribution should stay small and CONSTANT (not proportional to the
|
|
145
|
+
// size of its CONTEXT.md / SUMMARY.md). With 50 lines of fixture text
|
|
146
|
+
// per completed CONTEXT.md, a naive loader would produce >=50 lines per
|
|
147
|
+
// completed milestone (>1250 lines for 25 milestones). The fix emits a
|
|
148
|
+
// short summary section plus separator per completed milestone, which
|
|
149
|
+
// stays well under 10 lines/milestone regardless of CONTEXT.md size.
|
|
145
150
|
const contextLines = context.split("\n").length;
|
|
151
|
+
const avgLinesPerCompletedMilestone = contextLines / COMPLETED_COUNT;
|
|
146
152
|
assertTrue(
|
|
147
|
-
|
|
148
|
-
`
|
|
153
|
+
avgLinesPerCompletedMilestone < 10,
|
|
154
|
+
`Completed milestones should not inflate the context: got ${contextLines} lines across ${COMPLETED_COUNT} completed milestones (~${avgLinesPerCompletedMilestone.toFixed(1)}/milestone)`,
|
|
149
155
|
);
|
|
150
156
|
|
|
151
157
|
// ─── Cleanup ──────────────────────────────────────────────────────────────
|