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
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Verify that state.ts contains the disk-to-DB task reconciliation logic
|
|
5
5
|
* that prevents the dispatcher from getting stuck in an infinite planning
|
|
6
6
|
* loop when the planner writes a PLAN.md but never calls the persistence
|
|
7
|
-
* tool, leaving the DB with zero task rows.
|
|
7
|
+
* tool, leaving the DB with zero or partial task rows.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { describe, test } from "node:test";
|
|
@@ -24,7 +24,8 @@ describe("dispatcher stuck-planning reconciliation (#3656)", () => {
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
test("contains plan-file task reconciliation block", () => {
|
|
27
|
-
assert.match(source, /
|
|
27
|
+
assert.match(source, /if\s*\(\s*planFile\s*\)/);
|
|
28
|
+
assert.match(source, /dbTaskIds\.has\(t\.id\)/);
|
|
28
29
|
});
|
|
29
30
|
|
|
30
31
|
test("calls insertTask for each disk plan task", () => {
|
|
@@ -4,6 +4,7 @@ import { readFileSync } from "node:fs";
|
|
|
4
4
|
import { join, dirname } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { AutoSession } from "../auto/session.ts";
|
|
7
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
7
8
|
|
|
8
9
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
|
|
@@ -20,7 +21,7 @@ describe("double mergeAndExit guard (#2645)", () => {
|
|
|
20
21
|
const completeIdx = phasesSrc.indexOf('state.phase === "complete"');
|
|
21
22
|
assert.ok(completeIdx > 0, "phases.ts should have a 'complete' phase check");
|
|
22
23
|
|
|
23
|
-
const afterComplete = phasesSrc
|
|
24
|
+
const afterComplete = extractSourceRegion(phasesSrc, 'state.phase === "complete"');
|
|
24
25
|
const mergeIdx = afterComplete.indexOf("deps.resolver.mergeAndExit");
|
|
25
26
|
const flagIdx = afterComplete.indexOf("s.milestoneMergedInPhases = true");
|
|
26
27
|
|
|
@@ -42,7 +43,7 @@ describe("double mergeAndExit guard (#2645)", () => {
|
|
|
42
43
|
const allCompleteIdx = phasesSrc.indexOf("incomplete.length === 0");
|
|
43
44
|
assert.ok(allCompleteIdx > 0, "phases.ts should have an all-milestones-complete check");
|
|
44
45
|
|
|
45
|
-
const afterAllComplete = phasesSrc
|
|
46
|
+
const afterAllComplete = extractSourceRegion(phasesSrc, "incomplete.length === 0");
|
|
46
47
|
const mergeIdx = afterAllComplete.indexOf("deps.resolver.mergeAndExit");
|
|
47
48
|
const flagIdx = afterAllComplete.indexOf("s.milestoneMergedInPhases = true");
|
|
48
49
|
|
|
@@ -64,7 +65,7 @@ describe("double mergeAndExit guard (#2645)", () => {
|
|
|
64
65
|
const step4Idx = autoSrc.indexOf("Step 4: Auto-worktree exit");
|
|
65
66
|
assert.ok(step4Idx > 0, "auto.ts should have Step 4 worktree exit");
|
|
66
67
|
|
|
67
|
-
const step4Block = autoSrc
|
|
68
|
+
const step4Block = extractSourceRegion(autoSrc, "Step 4: Auto-worktree exit");
|
|
68
69
|
assert.ok(
|
|
69
70
|
step4Block.includes("milestoneMergedInPhases"),
|
|
70
71
|
"stopAuto Step 4 must check milestoneMergedInPhases before merging",
|
|
@@ -13,6 +13,7 @@ import assert from "node:assert/strict";
|
|
|
13
13
|
import { readFileSync } from "node:fs";
|
|
14
14
|
import { join, dirname } from "node:path";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
16
17
|
|
|
17
18
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
19
|
const RECOVERY_PATH = join(__dirname, "..", "bootstrap", "agent-end-recovery.ts");
|
|
@@ -30,7 +31,7 @@ test("agent-end-recovery.ts does not pause on aborted messages with empty conten
|
|
|
30
31
|
assert.ok(abortIdx > -1, "abort handler must exist in agent-end-recovery.ts");
|
|
31
32
|
|
|
32
33
|
// Extract the region around the abort handler (enough to see the guard logic)
|
|
33
|
-
const abortRegion = source
|
|
34
|
+
const abortRegion = extractSourceRegion(source, 'stopReason === "aborted"', { fromIdx: abortIdx });
|
|
34
35
|
|
|
35
36
|
// Must check for empty content before pausing
|
|
36
37
|
assert.ok(
|
|
@@ -48,7 +49,7 @@ test("agent-end-recovery.ts routes empty-content aborted messages to resolveAgen
|
|
|
48
49
|
assert.ok(abortIdx > -1, "abort handler must exist");
|
|
49
50
|
|
|
50
51
|
// Get the full abort handling block (from the if to the next stopReason check or success path)
|
|
51
|
-
const afterAbort = source
|
|
52
|
+
const afterAbort = extractSourceRegion(source, 'stopReason === "aborted"');
|
|
52
53
|
|
|
53
54
|
// The abort block must have a code path that calls resolveAgentEnd (for empty-content case)
|
|
54
55
|
assert.ok(
|
|
@@ -63,7 +64,7 @@ test("agent-end-recovery.ts checks for errorMessage presence in abort handler (#
|
|
|
63
64
|
const abortIdx = source.indexOf('stopReason === "aborted"');
|
|
64
65
|
assert.ok(abortIdx > -1, "abort handler must exist");
|
|
65
66
|
|
|
66
|
-
const abortRegion = source
|
|
67
|
+
const abortRegion = extractSourceRegion(source, 'stopReason === "aborted"');
|
|
67
68
|
|
|
68
69
|
// Fatal aborts should have error context (errorMessage field).
|
|
69
70
|
// The handler should check for this to distinguish fatal from non-fatal aborts.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression tests for #4671 — execution-entry phase + missing CONTEXT.md.
|
|
3
|
+
*
|
|
4
|
+
* When a milestone advances to an execution-entry phase (executing /
|
|
5
|
+
* summarizing / validating-milestone / completing-milestone) without
|
|
6
|
+
* `CONTEXT.md` on disk, the `pre-planning (no context) → discuss-milestone`
|
|
7
|
+
* rule no longer fires and the plan-v2 gate only blocks. This rule provides
|
|
8
|
+
* the recovery by redispatching to discuss-milestone.
|
|
9
|
+
*
|
|
10
|
+
* Exercises the dispatch rule from DISPATCH_RULES directly with a
|
|
11
|
+
* DispatchContext built against a real temp directory.
|
|
12
|
+
*/
|
|
13
|
+
import { test, describe } from "node:test";
|
|
14
|
+
import assert from "node:assert/strict";
|
|
15
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { tmpdir } from "node:os";
|
|
18
|
+
import { DISPATCH_RULES, type DispatchContext } from "../auto-dispatch.ts";
|
|
19
|
+
import type { GSDState, Phase } from "../types.ts";
|
|
20
|
+
|
|
21
|
+
const RULE_NAME_TOKEN = "execution-entry phase (no context)";
|
|
22
|
+
|
|
23
|
+
function findRule() {
|
|
24
|
+
const matches = DISPATCH_RULES.filter((r) => r.name.includes(RULE_NAME_TOKEN));
|
|
25
|
+
if (matches.length !== 1) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`expected exactly one dispatch rule containing "${RULE_NAME_TOKEN}", found ${matches.length}`,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return matches[0];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function buildState(phase: Phase): GSDState {
|
|
34
|
+
return {
|
|
35
|
+
activeMilestone: { id: "M001", title: "Test milestone" },
|
|
36
|
+
activeSlice: null,
|
|
37
|
+
activeTask: null,
|
|
38
|
+
phase,
|
|
39
|
+
recentDecisions: [],
|
|
40
|
+
blockers: [],
|
|
41
|
+
nextAction: "",
|
|
42
|
+
registry: [],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function makeBasePath(prefix: string): string {
|
|
47
|
+
const dir = mkdtempSync(join(tmpdir(), `gsd-4671-${prefix}-`));
|
|
48
|
+
mkdirSync(join(dir, ".gsd", "milestones", "M001"), { recursive: true });
|
|
49
|
+
return dir;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function buildCtx(basePath: string, state: GSDState): DispatchContext {
|
|
53
|
+
return {
|
|
54
|
+
basePath,
|
|
55
|
+
mid: "M001",
|
|
56
|
+
midTitle: "Test milestone",
|
|
57
|
+
state,
|
|
58
|
+
prefs: undefined,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
describe("#4671 execution-entry phase missing-context recovery", () => {
|
|
63
|
+
const executionEntryPhases: Phase[] = [
|
|
64
|
+
"executing",
|
|
65
|
+
"summarizing",
|
|
66
|
+
"validating-milestone",
|
|
67
|
+
"completing-milestone",
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
for (const phase of executionEntryPhases) {
|
|
71
|
+
test(`phase=${phase} with missing CONTEXT.md → dispatches discuss-milestone`, async () => {
|
|
72
|
+
const basePath = makeBasePath(`missing-${phase}`);
|
|
73
|
+
try {
|
|
74
|
+
const action = await findRule().match(buildCtx(basePath, buildState(phase)));
|
|
75
|
+
assert.ok(action, "rule must return an action when CONTEXT.md is missing");
|
|
76
|
+
assert.strictEqual(action!.action, "dispatch");
|
|
77
|
+
if (action!.action === "dispatch") {
|
|
78
|
+
assert.strictEqual(action!.unitType, "discuss-milestone");
|
|
79
|
+
assert.strictEqual(action!.unitId, "M001");
|
|
80
|
+
assert.ok(typeof action!.prompt === "string" && action!.prompt.length > 0);
|
|
81
|
+
}
|
|
82
|
+
} finally {
|
|
83
|
+
rmSync(basePath, { recursive: true, force: true });
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
test("phase=executing with CONTEXT.md present → falls through", async () => {
|
|
89
|
+
const basePath = makeBasePath("has-context");
|
|
90
|
+
try {
|
|
91
|
+
writeFileSync(
|
|
92
|
+
join(basePath, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
|
|
93
|
+
"# M001 Context\n\nSome real context.\n",
|
|
94
|
+
);
|
|
95
|
+
const action = await findRule().match(buildCtx(basePath, buildState("executing")));
|
|
96
|
+
assert.strictEqual(action, null, "rule must fall through when CONTEXT.md exists");
|
|
97
|
+
} finally {
|
|
98
|
+
rmSync(basePath, { recursive: true, force: true });
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("phase=executing accepts finalized CONTEXT.md from GSD_PROJECT_ROOT fallback", async () => {
|
|
103
|
+
const projectRoot = makeBasePath("project-root-context");
|
|
104
|
+
const worktreeBase = makeBasePath("worktree-context");
|
|
105
|
+
const prevProjectRoot = process.env.GSD_PROJECT_ROOT;
|
|
106
|
+
try {
|
|
107
|
+
writeFileSync(
|
|
108
|
+
join(projectRoot, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
|
|
109
|
+
"# M001 Context\n\nFinalized context at project root.\n",
|
|
110
|
+
);
|
|
111
|
+
process.env.GSD_PROJECT_ROOT = projectRoot;
|
|
112
|
+
|
|
113
|
+
const action = await findRule().match(buildCtx(worktreeBase, buildState("executing")));
|
|
114
|
+
assert.strictEqual(
|
|
115
|
+
action,
|
|
116
|
+
null,
|
|
117
|
+
"rule must align with plan-v2 project-root fallback before redispatching",
|
|
118
|
+
);
|
|
119
|
+
} finally {
|
|
120
|
+
if (prevProjectRoot === undefined) {
|
|
121
|
+
delete process.env.GSD_PROJECT_ROOT;
|
|
122
|
+
} else {
|
|
123
|
+
process.env.GSD_PROJECT_ROOT = prevProjectRoot;
|
|
124
|
+
}
|
|
125
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
126
|
+
rmSync(worktreeBase, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("phase=pre-planning does not trigger this rule (handled by upstream rule)", async () => {
|
|
131
|
+
const basePath = makeBasePath("pre-planning");
|
|
132
|
+
try {
|
|
133
|
+
const action = await findRule().match(buildCtx(basePath, buildState("pre-planning")));
|
|
134
|
+
assert.strictEqual(
|
|
135
|
+
action,
|
|
136
|
+
null,
|
|
137
|
+
"rule must only target execution-entry phases; pre-planning is handled elsewhere",
|
|
138
|
+
);
|
|
139
|
+
} finally {
|
|
140
|
+
rmSync(basePath, { recursive: true, force: true });
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("empty CONTEXT.md (whitespace only) → rule still fires", async () => {
|
|
145
|
+
const basePath = makeBasePath("empty-context");
|
|
146
|
+
try {
|
|
147
|
+
writeFileSync(
|
|
148
|
+
join(basePath, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
|
|
149
|
+
" \n\t\n",
|
|
150
|
+
);
|
|
151
|
+
const action = await findRule().match(buildCtx(basePath, buildState("summarizing")));
|
|
152
|
+
assert.ok(action, "rule must fire when CONTEXT.md is empty/whitespace-only");
|
|
153
|
+
if (action?.action === "dispatch") {
|
|
154
|
+
assert.strictEqual(action.unitType, "discuss-milestone");
|
|
155
|
+
}
|
|
156
|
+
} finally {
|
|
157
|
+
rmSync(basePath, { recursive: true, force: true });
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("rule ordering: fires BEFORE execution-entry phase handlers", () => {
|
|
162
|
+
const recoveryIdx = DISPATCH_RULES.findIndex((r) => r.name.includes(RULE_NAME_TOKEN));
|
|
163
|
+
const summarizingIdx = DISPATCH_RULES.findIndex((r) =>
|
|
164
|
+
r.name.startsWith("summarizing → complete-slice"),
|
|
165
|
+
);
|
|
166
|
+
assert.ok(recoveryIdx > -1, "recovery rule must exist");
|
|
167
|
+
assert.ok(summarizingIdx > -1, "summarizing rule must exist");
|
|
168
|
+
assert.ok(
|
|
169
|
+
recoveryIdx < summarizingIdx,
|
|
170
|
+
`recovery rule (idx ${recoveryIdx}) must come before summarizing rule (idx ${summarizingIdx}) so it can redispatch before the plan-v2 gate blocks`,
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
@@ -1,154 +1,164 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Behavioural contract for GSD extension bootstrap isolation (#4168, #4172).
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
// (
|
|
5
|
-
// Windows-specific
|
|
6
|
-
// prevented /gsd from being registered at all
|
|
3
|
+
// Guarantee: the `/gsd` slash command must be registered on pi even if the
|
|
4
|
+
// full bootstrap (shortcuts, tools, hooks, ecosystem) throws during import or
|
|
5
|
+
// execution. Prior regressions: a Windows-specific failure in register-
|
|
6
|
+
// shortcuts.ts silently prevented /gsd from being registered at all because
|
|
7
|
+
// registerGSDCommand was called inside the same try that loaded shortcuts.
|
|
8
|
+
//
|
|
9
|
+
// These tests exercise the real default export of index.ts (which calls
|
|
10
|
+
// registerGSDCommand via dynamic import, then attempts the full bootstrap)
|
|
11
|
+
// with a minimal mock ExtensionAPI and verify the observable behaviour
|
|
12
|
+
// directly: /gsd is registered in both the happy path and the degraded path.
|
|
13
|
+
//
|
|
14
|
+
// Anti-regression proof (documented in commit):
|
|
15
|
+
// neuter index.ts to register /gsd inside the same try{} as
|
|
16
|
+
// register-extension → the degraded-path test fails (no /gsd command
|
|
17
|
+
// registered when register-extension throws). Restore → passes.
|
|
7
18
|
|
|
8
19
|
import { describe, test } from "node:test";
|
|
9
20
|
import assert from "node:assert/strict";
|
|
10
|
-
import { readFileSync } from "node:fs";
|
|
11
|
-
import { join, dirname } from "node:path";
|
|
12
|
-
import { fileURLToPath } from "node:url";
|
|
13
|
-
|
|
14
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
const indexSrc = readFileSync(join(__dirname, "../index.ts"), "utf-8");
|
|
16
|
-
const registerExtSrc = readFileSync(
|
|
17
|
-
join(__dirname, "../bootstrap/register-extension.ts"),
|
|
18
|
-
"utf-8",
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
// ─── index.ts: core /gsd command must be registered before full bootstrap ─────
|
|
22
|
-
|
|
23
|
-
describe("index.ts bootstrap isolation", () => {
|
|
24
|
-
test("imports registerGSDCommand from commands/index.js separately", () => {
|
|
25
|
-
assert.ok(
|
|
26
|
-
indexSrc.includes('./commands/index.js"') || indexSrc.includes("./commands/index.js'"),
|
|
27
|
-
"index.ts must import registerGSDCommand from ./commands/index.js",
|
|
28
|
-
);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("calls registerGSDCommand before importing register-extension.js", () => {
|
|
32
|
-
const gsdCommandCallPos = indexSrc.indexOf("registerGSDCommand(pi)");
|
|
33
|
-
const bootstrapImportPos = indexSrc.indexOf(
|
|
34
|
-
'./bootstrap/register-extension.js"',
|
|
35
|
-
);
|
|
36
21
|
|
|
37
|
-
|
|
38
|
-
|
|
22
|
+
import registerExtension from "../index.ts";
|
|
23
|
+
|
|
24
|
+
type RegisterFn = (name: string, def: unknown) => void;
|
|
25
|
+
|
|
26
|
+
function makePi(overrides: Partial<Record<string, unknown>> = {}) {
|
|
27
|
+
const registered: Array<[string, unknown]> = [];
|
|
28
|
+
const registerCommand: RegisterFn = (name, def) => {
|
|
29
|
+
registered.push([name, def]);
|
|
30
|
+
};
|
|
31
|
+
const events = {
|
|
32
|
+
on: () => {},
|
|
33
|
+
off: () => {},
|
|
34
|
+
emit: () => {},
|
|
35
|
+
};
|
|
36
|
+
const pi = {
|
|
37
|
+
registerCommand,
|
|
38
|
+
registerTool: () => {},
|
|
39
|
+
registerHook: () => {},
|
|
40
|
+
registerShortcut: () => {},
|
|
41
|
+
events,
|
|
42
|
+
...overrides,
|
|
43
|
+
};
|
|
44
|
+
return { pi, registered };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe("extension bootstrap isolation (#4168, #4172)", () => {
|
|
48
|
+
test("happy path: /gsd command is registered", async () => {
|
|
49
|
+
const { pi, registered } = makePi();
|
|
50
|
+
await registerExtension(pi as any);
|
|
51
|
+
const names = registered.map(([n]) => n);
|
|
39
52
|
assert.ok(
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
names.includes("gsd"),
|
|
54
|
+
`expected 'gsd' in registered commands, got ${JSON.stringify(names)}`,
|
|
42
55
|
);
|
|
43
56
|
});
|
|
44
57
|
|
|
45
|
-
test("
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
test("degraded path: /gsd still registered when registerCommand throws for non-core commands", async () => {
|
|
59
|
+
// Simulate the Windows-style failure: pi.registerCommand throws for a
|
|
60
|
+
// specific non-core command ('kill' is a simple target registered by
|
|
61
|
+
// the full bootstrap) — the full bootstrap must fail but /gsd must
|
|
62
|
+
// already be registered before the failure occurs.
|
|
63
|
+
const registered: Array<[string, unknown]> = [];
|
|
64
|
+
const pi = {
|
|
65
|
+
registerCommand: (name: string, def: unknown) => {
|
|
66
|
+
if (name !== "gsd" && name !== "worktree" && name !== "exit") {
|
|
67
|
+
// Let /gsd, /worktree, /exit succeed (they precede the non-core
|
|
68
|
+
// loop); throw when the first non-core registration fires.
|
|
69
|
+
}
|
|
70
|
+
if (name === "kill") throw new Error("simulated windows failure");
|
|
71
|
+
registered.push([name, def]);
|
|
72
|
+
},
|
|
73
|
+
registerTool: () => {},
|
|
74
|
+
registerHook: () => {},
|
|
75
|
+
registerShortcut: () => {},
|
|
76
|
+
events: { on: () => {}, off: () => {}, emit: () => {} },
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// registerExtension must not throw — the outer try/catch in index.ts
|
|
80
|
+
// swallows bootstrap failures after /gsd is already registered.
|
|
81
|
+
await registerExtension(pi as any);
|
|
82
|
+
|
|
83
|
+
const names = registered.map(([n]) => n);
|
|
55
84
|
assert.ok(
|
|
56
|
-
|
|
57
|
-
"
|
|
85
|
+
names.includes("gsd"),
|
|
86
|
+
"expected 'gsd' to be registered even when a later command registration throws",
|
|
58
87
|
);
|
|
59
88
|
});
|
|
60
89
|
|
|
61
|
-
test("
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
90
|
+
test("degraded path: /gsd registered BEFORE any non-core command", async () => {
|
|
91
|
+
// Ordering guard: the first registerCommand call must be for 'gsd',
|
|
92
|
+
// because index.ts awaits registerGSDCommand(pi) before importing
|
|
93
|
+
// register-extension. Regression scenario: if a future refactor moves
|
|
94
|
+
// registerGSDCommand into the try block or after other registrations,
|
|
95
|
+
// a failure in those earlier registrations would take /gsd down too.
|
|
96
|
+
const calls: string[] = [];
|
|
97
|
+
const pi = {
|
|
98
|
+
registerCommand: (name: string) => {
|
|
99
|
+
calls.push(name);
|
|
100
|
+
},
|
|
101
|
+
registerTool: () => {},
|
|
102
|
+
registerHook: () => {},
|
|
103
|
+
registerShortcut: () => {},
|
|
104
|
+
events: { on: () => {}, off: () => {}, emit: () => {} },
|
|
105
|
+
};
|
|
106
|
+
await registerExtension(pi as any);
|
|
107
|
+
assert.ok(calls.length > 0, "expected at least one registerCommand call");
|
|
108
|
+
assert.equal(
|
|
109
|
+
calls[0],
|
|
110
|
+
"gsd",
|
|
111
|
+
`expected 'gsd' to be the first command registered, got ${JSON.stringify(calls)}`,
|
|
69
112
|
);
|
|
70
113
|
});
|
|
71
114
|
});
|
|
72
115
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
98
|
-
const funcBody = registerExtSrc.slice(funcBodyStart);
|
|
99
|
-
|
|
100
|
-
assert.ok(
|
|
101
|
-
funcBody.includes("registerWorktreeCommand(pi)"),
|
|
102
|
-
"must register worktree command",
|
|
103
|
-
);
|
|
104
|
-
assert.ok(
|
|
105
|
-
funcBody.includes("registerExitCommand(pi)"),
|
|
106
|
-
"must register exit command",
|
|
107
|
-
);
|
|
108
|
-
assert.ok(
|
|
109
|
-
funcBody.includes('"kill"'),
|
|
110
|
-
"must register kill command",
|
|
111
|
-
);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test("wraps non-critical registrations in individual try-catch blocks", () => {
|
|
115
|
-
const funcBodyStart = registerExtSrc.indexOf(
|
|
116
|
-
"export function registerGsdExtension",
|
|
117
|
-
);
|
|
118
|
-
const funcBody = registerExtSrc.slice(funcBodyStart);
|
|
119
|
-
|
|
120
|
-
// Each non-critical registration should be wrapped with error handling
|
|
121
|
-
const registrationNames = [
|
|
122
|
-
"dynamic-tools",
|
|
123
|
-
"db-tools",
|
|
124
|
-
"journal-tools",
|
|
125
|
-
"query-tools",
|
|
126
|
-
"shortcuts",
|
|
127
|
-
"hooks",
|
|
128
|
-
];
|
|
129
|
-
|
|
130
|
-
for (const name of registrationNames) {
|
|
131
|
-
assert.ok(
|
|
132
|
-
funcBody.includes(`"${name}"`),
|
|
133
|
-
`non-critical registration "${name}" must be present`,
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Must have try-catch inside the registration loop
|
|
116
|
+
// Behavioural contract for registerGsdExtension itself: each non-core
|
|
117
|
+
// registration is wrapped in its own try/catch so one failure does not
|
|
118
|
+
// prevent siblings from loading.
|
|
119
|
+
|
|
120
|
+
import { registerGsdExtension } from "../bootstrap/register-extension.ts";
|
|
121
|
+
|
|
122
|
+
describe("registerGsdExtension defensive registration", () => {
|
|
123
|
+
test("a failing shortcut registration does not prevent kill command registration", async () => {
|
|
124
|
+
// `shortcuts` is registered via a non-critical slot that is wrapped in
|
|
125
|
+
// its own try/catch. `kill` is registered before the non-critical loop
|
|
126
|
+
// as a critical command. Simulate: registerShortcut throws. Expect:
|
|
127
|
+
// 'kill' is still registered, registerGsdExtension does not throw.
|
|
128
|
+
const registered: string[] = [];
|
|
129
|
+
const pi = {
|
|
130
|
+
registerCommand: (name: string) => {
|
|
131
|
+
registered.push(name);
|
|
132
|
+
},
|
|
133
|
+
registerTool: () => {},
|
|
134
|
+
registerHook: () => {},
|
|
135
|
+
registerShortcut: () => {
|
|
136
|
+
throw new Error("simulated platform-specific shortcut failure");
|
|
137
|
+
},
|
|
138
|
+
events: { on: () => {}, off: () => {}, emit: () => {} },
|
|
139
|
+
};
|
|
140
|
+
assert.doesNotThrow(() => registerGsdExtension(pi as any));
|
|
138
141
|
assert.ok(
|
|
139
|
-
|
|
140
|
-
|
|
142
|
+
registered.includes("kill"),
|
|
143
|
+
`expected 'kill' to be registered despite shortcut failure, got ${JSON.stringify(registered)}`,
|
|
141
144
|
);
|
|
142
145
|
});
|
|
143
146
|
|
|
144
|
-
test("
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
test("does NOT register /gsd (caller's responsibility, avoids double-registration)", () => {
|
|
148
|
+
const registered: string[] = [];
|
|
149
|
+
const pi = {
|
|
150
|
+
registerCommand: (name: string) => {
|
|
151
|
+
registered.push(name);
|
|
152
|
+
},
|
|
153
|
+
registerTool: () => {},
|
|
154
|
+
registerHook: () => {},
|
|
155
|
+
registerShortcut: () => {},
|
|
156
|
+
events: { on: () => {}, off: () => {}, emit: () => {} },
|
|
157
|
+
};
|
|
158
|
+
registerGsdExtension(pi as any);
|
|
149
159
|
assert.ok(
|
|
150
|
-
|
|
151
|
-
|
|
160
|
+
!registered.includes("gsd"),
|
|
161
|
+
`registerGsdExtension must NOT register 'gsd' (it is registered separately by index.ts), got ${JSON.stringify(registered)}`,
|
|
152
162
|
);
|
|
153
163
|
});
|
|
154
164
|
});
|