gsd-pi 2.77.0-dev.58d3d4d6c → 2.77.0-dev.cfd69e714
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 +1 -1
- package/dist/claude-cli-check.js +5 -1
- 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 +5 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
- package/dist/resources/extensions/gsd/auto/loop.js +43 -0
- package/dist/resources/extensions/gsd/auto/phases.js +15 -21
- package/dist/resources/extensions/gsd/auto/session.js +0 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +102 -24
- package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
- package/dist/resources/extensions/gsd/auto-post-unit.js +71 -64
- package/dist/resources/extensions/gsd/auto-prompts.js +329 -102
- package/dist/resources/extensions/gsd/auto-recovery.js +195 -23
- package/dist/resources/extensions/gsd/auto-start.js +34 -24
- 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 +31 -20
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +9 -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/detection.js +49 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- 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 +17 -5
- 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/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/prompts/complete-milestone.md +6 -2
- 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-parallel-orchestrator.js +278 -8
- package/dist/resources/extensions/gsd/state.js +44 -33
- package/dist/resources/extensions/gsd/sync-lock.js +98 -42
- 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/gate-runner.js +53 -5
- package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +34 -8
- 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 +5 -5
- 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 +5 -5
- 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/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/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 +80 -39
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- 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/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/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/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/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/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/dynamic-border.test.ts +26 -20
- 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 +36 -12
- 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/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 +41 -12
- 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/src/rpc-client.test.ts +109 -52
- package/packages/rpc-client/tsconfig.tsbuildinfo +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 +5 -1
- 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/tests/cli.test.ts +76 -7
- package/src/resources/extensions/github-sync/tests/templates.test.ts +33 -1
- package/src/resources/extensions/gsd/auto/loop.ts +47 -0
- package/src/resources/extensions/gsd/auto/phases.ts +16 -20
- package/src/resources/extensions/gsd/auto/session.ts +0 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +113 -24
- package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +82 -73
- package/src/resources/extensions/gsd/auto-prompts.ts +330 -90
- package/src/resources/extensions/gsd/auto-recovery.ts +225 -24
- package/src/resources/extensions/gsd/auto-start.ts +54 -6
- 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 +43 -22
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +9 -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/detection.ts +58 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -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 +133 -2
- package/src/resources/extensions/gsd/gsd-db.ts +6 -3
- package/src/resources/extensions/gsd/guided-flow.ts +20 -5
- 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/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/prompts/complete-milestone.md +6 -2
- 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-parallel-orchestrator.ts +309 -8
- package/src/resources/extensions/gsd/state.ts +49 -44
- 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/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 +94 -289
- 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-retry-mcp-churn-fixes.test.ts +8 -197
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
- 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-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/crash-recovery.test.ts +50 -1
- 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 -3
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +9 -105
- 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/hook-key-parsing.test.ts +4 -55
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -57
- 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/interrupted-session-ui.test.ts +6 -9
- 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 -62
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -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 -49
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -133
- 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/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/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/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/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-parallel-orchestrator.test.ts +164 -1
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +5 -5
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
- 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/test-helpers.test.ts +12 -61
- package/src/resources/extensions/gsd/tests/test-helpers.ts +21 -8
- 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-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/validate-milestone.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -81
- 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/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/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/gate-runner.ts +65 -5
- package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +55 -7
- 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 -144
- 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 -75
- package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
- package/src/resources/extensions/gsd/tests/forensics-worktree-telemetry.test.ts +0 -145
- 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 -130
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -43
- /package/dist/web/standalone/.next/static/{Cev5xrAYA3ZGTRLyjR2fX → SvCJDZPQW104bR1KnBQg1}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Cev5xrAYA3ZGTRLyjR2fX → SvCJDZPQW104bR1KnBQg1}/_ssgManifest.js +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { test } from
|
|
2
|
-
import assert from
|
|
3
|
-
import * as fs from
|
|
4
|
-
import * as path from
|
|
5
|
-
import * as os from
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import * as os from "node:os";
|
|
6
6
|
import {
|
|
7
7
|
openDatabase,
|
|
8
8
|
closeDatabase,
|
|
@@ -17,197 +17,181 @@ import {
|
|
|
17
17
|
_getAdapter,
|
|
18
18
|
copyWorktreeDb,
|
|
19
19
|
reconcileWorktreeDb,
|
|
20
|
-
} from
|
|
20
|
+
} from "../gsd-db.ts";
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
24
|
-
// Helpers
|
|
25
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
22
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
26
23
|
|
|
27
24
|
function tempDir(): string {
|
|
28
|
-
return fs.mkdtempSync(path.join(os.tmpdir(),
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function cleanup(...dirs: string[]): void {
|
|
32
|
-
closeDatabase();
|
|
33
|
-
for (const dir of dirs) {
|
|
34
|
-
try {
|
|
35
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
36
|
-
} catch {
|
|
37
|
-
// best effort
|
|
38
|
-
}
|
|
39
|
-
}
|
|
25
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), "gsd-wt-test-"));
|
|
40
26
|
}
|
|
41
27
|
|
|
42
28
|
function seedMainDb(dbPath: string): void {
|
|
43
29
|
openDatabase(dbPath);
|
|
44
30
|
insertDecision({
|
|
45
|
-
id:
|
|
46
|
-
when_context:
|
|
47
|
-
scope:
|
|
48
|
-
decision:
|
|
49
|
-
choice:
|
|
50
|
-
rationale:
|
|
51
|
-
revisable:
|
|
52
|
-
made_by:
|
|
31
|
+
id: "D001",
|
|
32
|
+
when_context: "2025-01-01",
|
|
33
|
+
scope: "M001/S01",
|
|
34
|
+
decision: "Use SQLite",
|
|
35
|
+
choice: "node:sqlite",
|
|
36
|
+
rationale: "Built-in",
|
|
37
|
+
revisable: "yes",
|
|
38
|
+
made_by: "agent",
|
|
53
39
|
superseded_by: null,
|
|
54
40
|
});
|
|
55
41
|
insertRequirement({
|
|
56
|
-
id:
|
|
57
|
-
class:
|
|
58
|
-
status:
|
|
59
|
-
description:
|
|
60
|
-
why:
|
|
61
|
-
source:
|
|
62
|
-
primary_owner:
|
|
63
|
-
supporting_slices:
|
|
64
|
-
validation:
|
|
65
|
-
notes:
|
|
66
|
-
full_content:
|
|
42
|
+
id: "R001",
|
|
43
|
+
class: "functional",
|
|
44
|
+
status: "active",
|
|
45
|
+
description: "Must store decisions",
|
|
46
|
+
why: "Core feature",
|
|
47
|
+
source: "design",
|
|
48
|
+
primary_owner: "S01",
|
|
49
|
+
supporting_slices: "",
|
|
50
|
+
validation: "test",
|
|
51
|
+
notes: "",
|
|
52
|
+
full_content: "Full requirement text",
|
|
67
53
|
superseded_by: null,
|
|
68
54
|
});
|
|
69
55
|
insertArtifact({
|
|
70
|
-
path:
|
|
71
|
-
artifact_type:
|
|
72
|
-
milestone_id:
|
|
56
|
+
path: "docs/arch.md",
|
|
57
|
+
artifact_type: "plan",
|
|
58
|
+
milestone_id: "M001",
|
|
73
59
|
slice_id: null,
|
|
74
60
|
task_id: null,
|
|
75
|
-
full_content:
|
|
61
|
+
full_content: "Architecture document",
|
|
76
62
|
});
|
|
77
63
|
}
|
|
78
64
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
65
|
+
function registerCleanup(t: { after: (fn: () => void) => void }, ...dirs: string[]) {
|
|
66
|
+
t.after(() => {
|
|
67
|
+
closeDatabase();
|
|
68
|
+
for (const dir of dirs) {
|
|
69
|
+
try {
|
|
70
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
71
|
+
} catch {
|
|
72
|
+
// best effort
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
82
77
|
|
|
83
|
-
|
|
78
|
+
// ─── copyWorktreeDb ───────────────────────────────────────────────────────
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
{
|
|
80
|
+
test("copyWorktreeDb copies DB file and data is queryable", (t) => {
|
|
87
81
|
const srcDir = tempDir();
|
|
88
82
|
const destDir = tempDir();
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
registerCleanup(t, srcDir, destDir);
|
|
84
|
+
|
|
85
|
+
const srcDb = path.join(srcDir, "gsd.db");
|
|
86
|
+
const destDb = path.join(destDir, "nested", "gsd.db");
|
|
91
87
|
|
|
92
88
|
seedMainDb(srcDb);
|
|
93
89
|
closeDatabase();
|
|
94
90
|
|
|
95
91
|
const result = copyWorktreeDb(srcDb, destDb);
|
|
96
|
-
assert.
|
|
97
|
-
assert.ok(fs.existsSync(destDb),
|
|
92
|
+
assert.equal(result, true, "copyWorktreeDb returns true on success");
|
|
93
|
+
assert.ok(fs.existsSync(destDb), "dest DB file exists after copy");
|
|
98
94
|
|
|
99
|
-
// Open the copy and verify data is queryable
|
|
100
95
|
openDatabase(destDb);
|
|
101
|
-
const d = getDecisionById(
|
|
102
|
-
assert.ok(d !== null,
|
|
103
|
-
assert.
|
|
96
|
+
const d = getDecisionById("D001");
|
|
97
|
+
assert.ok(d !== null, "decision queryable in copied DB");
|
|
98
|
+
assert.equal(d?.choice, "node:sqlite", "decision data preserved in copy");
|
|
104
99
|
|
|
105
|
-
const r = getRequirementById(
|
|
106
|
-
assert.ok(r !== null,
|
|
107
|
-
assert.
|
|
100
|
+
const r = getRequirementById("R001");
|
|
101
|
+
assert.ok(r !== null, "requirement queryable in copied DB");
|
|
102
|
+
assert.equal(r?.description, "Must store decisions", "requirement data preserved in copy");
|
|
103
|
+
});
|
|
108
104
|
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Test: skips -wal and -shm files
|
|
113
|
-
{
|
|
105
|
+
test("copyWorktreeDb skips -wal and -shm files", (t) => {
|
|
114
106
|
const srcDir = tempDir();
|
|
115
107
|
const destDir = tempDir();
|
|
116
|
-
|
|
117
|
-
|
|
108
|
+
registerCleanup(t, srcDir, destDir);
|
|
109
|
+
|
|
110
|
+
const srcDb = path.join(srcDir, "gsd.db");
|
|
111
|
+
const destDb = path.join(destDir, "gsd.db");
|
|
118
112
|
|
|
119
113
|
seedMainDb(srcDb);
|
|
120
114
|
closeDatabase();
|
|
121
115
|
|
|
122
|
-
|
|
123
|
-
fs.writeFileSync(srcDb +
|
|
124
|
-
fs.writeFileSync(srcDb + '-shm', 'fake shm data');
|
|
116
|
+
fs.writeFileSync(srcDb + "-wal", "fake wal data");
|
|
117
|
+
fs.writeFileSync(srcDb + "-shm", "fake shm data");
|
|
125
118
|
|
|
126
119
|
copyWorktreeDb(srcDb, destDb);
|
|
127
120
|
|
|
128
|
-
assert.ok(fs.existsSync(destDb),
|
|
129
|
-
assert.ok(!fs.existsSync(destDb +
|
|
130
|
-
assert.ok(!fs.existsSync(destDb +
|
|
121
|
+
assert.ok(fs.existsSync(destDb), "DB file copied");
|
|
122
|
+
assert.ok(!fs.existsSync(destDb + "-wal"), "WAL file NOT copied");
|
|
123
|
+
assert.ok(!fs.existsSync(destDb + "-shm"), "SHM file NOT copied");
|
|
124
|
+
});
|
|
131
125
|
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Test: returns false when source doesn't exist (no throw)
|
|
136
|
-
{
|
|
126
|
+
test("copyWorktreeDb returns false when source doesn't exist", (t) => {
|
|
137
127
|
const destDir = tempDir();
|
|
138
|
-
|
|
139
|
-
assert.deepStrictEqual(result, false, 'returns false for missing source');
|
|
140
|
-
cleanup(destDir);
|
|
141
|
-
}
|
|
128
|
+
registerCleanup(t, destDir);
|
|
142
129
|
|
|
143
|
-
|
|
144
|
-
|
|
130
|
+
const missingSrc = path.join(destDir, "missing", "gsd.db");
|
|
131
|
+
const result = copyWorktreeDb(missingSrc, path.join(destDir, "gsd.db"));
|
|
132
|
+
assert.equal(result, false, "returns false for missing source");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("copyWorktreeDb creates deeply nested dest directories", (t) => {
|
|
145
136
|
const srcDir = tempDir();
|
|
146
137
|
const destDir = tempDir();
|
|
147
|
-
|
|
148
|
-
|
|
138
|
+
registerCleanup(t, srcDir, destDir);
|
|
139
|
+
|
|
140
|
+
const srcDb = path.join(srcDir, "gsd.db");
|
|
141
|
+
const deepDest = path.join(destDir, "a", "b", "c", "gsd.db");
|
|
149
142
|
|
|
150
143
|
seedMainDb(srcDb);
|
|
151
144
|
closeDatabase();
|
|
152
145
|
|
|
153
146
|
const result = copyWorktreeDb(srcDb, deepDest);
|
|
154
|
-
assert.
|
|
155
|
-
assert.ok(fs.existsSync(deepDest),
|
|
156
|
-
|
|
157
|
-
cleanup(srcDir, destDir);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
161
|
-
// reconcileWorktreeDb tests
|
|
162
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
147
|
+
assert.equal(result, true, "copyWorktreeDb succeeds with nested dest");
|
|
148
|
+
assert.ok(fs.existsSync(deepDest), "DB file created at deeply nested path");
|
|
149
|
+
});
|
|
163
150
|
|
|
164
|
-
|
|
151
|
+
// ─── reconcileWorktreeDb ──────────────────────────────────────────────────
|
|
165
152
|
|
|
166
|
-
|
|
167
|
-
{
|
|
153
|
+
test("reconcileWorktreeDb merges new decisions from worktree into main", (t) => {
|
|
168
154
|
const mainDir = tempDir();
|
|
169
155
|
const wtDir = tempDir();
|
|
170
|
-
|
|
171
|
-
|
|
156
|
+
registerCleanup(t, mainDir, wtDir);
|
|
157
|
+
|
|
158
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
159
|
+
const wtDb = path.join(wtDir, "gsd.db");
|
|
172
160
|
|
|
173
|
-
// Seed main with D001
|
|
174
161
|
seedMainDb(mainDb);
|
|
175
162
|
closeDatabase();
|
|
176
163
|
|
|
177
|
-
// Copy to worktree, add D002 in worktree
|
|
178
164
|
copyWorktreeDb(mainDb, wtDb);
|
|
179
165
|
openDatabase(wtDb);
|
|
180
166
|
insertDecision({
|
|
181
|
-
id:
|
|
182
|
-
when_context:
|
|
183
|
-
scope:
|
|
184
|
-
decision:
|
|
185
|
-
choice:
|
|
186
|
-
rationale:
|
|
187
|
-
revisable:
|
|
188
|
-
made_by:
|
|
167
|
+
id: "D002",
|
|
168
|
+
when_context: "2025-02-01",
|
|
169
|
+
scope: "M001/S02",
|
|
170
|
+
decision: "Use WAL mode",
|
|
171
|
+
choice: "WAL",
|
|
172
|
+
rationale: "Performance",
|
|
173
|
+
revisable: "yes",
|
|
174
|
+
made_by: "agent",
|
|
189
175
|
superseded_by: null,
|
|
190
176
|
});
|
|
191
177
|
closeDatabase();
|
|
192
178
|
|
|
193
|
-
// Re-open main and reconcile
|
|
194
179
|
openDatabase(mainDb);
|
|
195
180
|
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
196
181
|
|
|
197
|
-
assert.ok(result.decisions > 0,
|
|
198
|
-
const d2 = getDecisionById(
|
|
199
|
-
assert.ok(d2 !== null,
|
|
200
|
-
assert.
|
|
182
|
+
assert.ok(result.decisions > 0, "decisions merged count > 0");
|
|
183
|
+
const d2 = getDecisionById("D002");
|
|
184
|
+
assert.ok(d2 !== null, "D002 from worktree now in main");
|
|
185
|
+
assert.equal(d2?.choice, "WAL", "D002 data correct after merge");
|
|
186
|
+
});
|
|
201
187
|
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Test: merges new requirements from worktree into main
|
|
206
|
-
{
|
|
188
|
+
test("reconcileWorktreeDb merges new requirements from worktree into main", (t) => {
|
|
207
189
|
const mainDir = tempDir();
|
|
208
190
|
const wtDir = tempDir();
|
|
209
|
-
|
|
210
|
-
|
|
191
|
+
registerCleanup(t, mainDir, wtDir);
|
|
192
|
+
|
|
193
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
194
|
+
const wtDb = path.join(wtDir, "gsd.db");
|
|
211
195
|
|
|
212
196
|
seedMainDb(mainDb);
|
|
213
197
|
closeDatabase();
|
|
@@ -215,17 +199,17 @@ console.log('\n=== worktree-db: reconcileWorktreeDb ===');
|
|
|
215
199
|
|
|
216
200
|
openDatabase(wtDb);
|
|
217
201
|
insertRequirement({
|
|
218
|
-
id:
|
|
219
|
-
class:
|
|
220
|
-
status:
|
|
221
|
-
description:
|
|
222
|
-
why:
|
|
223
|
-
source:
|
|
224
|
-
primary_owner:
|
|
225
|
-
supporting_slices:
|
|
226
|
-
validation:
|
|
227
|
-
notes:
|
|
228
|
-
full_content:
|
|
202
|
+
id: "R002",
|
|
203
|
+
class: "non-functional",
|
|
204
|
+
status: "active",
|
|
205
|
+
description: "Must be fast",
|
|
206
|
+
why: "UX",
|
|
207
|
+
source: "design",
|
|
208
|
+
primary_owner: "S02",
|
|
209
|
+
supporting_slices: "",
|
|
210
|
+
validation: "benchmark",
|
|
211
|
+
notes: "",
|
|
212
|
+
full_content: "Performance requirement",
|
|
229
213
|
superseded_by: null,
|
|
230
214
|
});
|
|
231
215
|
closeDatabase();
|
|
@@ -233,20 +217,19 @@ console.log('\n=== worktree-db: reconcileWorktreeDb ===');
|
|
|
233
217
|
openDatabase(mainDb);
|
|
234
218
|
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
235
219
|
|
|
236
|
-
assert.ok(result.requirements > 0,
|
|
237
|
-
const r2 = getRequirementById(
|
|
238
|
-
assert.ok(r2 !== null,
|
|
239
|
-
assert.
|
|
220
|
+
assert.ok(result.requirements > 0, "requirements merged count > 0");
|
|
221
|
+
const r2 = getRequirementById("R002");
|
|
222
|
+
assert.ok(r2 !== null, "R002 from worktree now in main");
|
|
223
|
+
assert.equal(r2?.description, "Must be fast", "R002 data correct after merge");
|
|
224
|
+
});
|
|
240
225
|
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Test: merges new artifacts from worktree into main
|
|
245
|
-
{
|
|
226
|
+
test("reconcileWorktreeDb merges new artifacts from worktree into main", (t) => {
|
|
246
227
|
const mainDir = tempDir();
|
|
247
228
|
const wtDir = tempDir();
|
|
248
|
-
|
|
249
|
-
|
|
229
|
+
registerCleanup(t, mainDir, wtDir);
|
|
230
|
+
|
|
231
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
232
|
+
const wtDb = path.join(wtDir, "gsd.db");
|
|
250
233
|
|
|
251
234
|
seedMainDb(mainDb);
|
|
252
235
|
closeDatabase();
|
|
@@ -254,133 +237,124 @@ console.log('\n=== worktree-db: reconcileWorktreeDb ===');
|
|
|
254
237
|
|
|
255
238
|
openDatabase(wtDb);
|
|
256
239
|
insertArtifact({
|
|
257
|
-
path:
|
|
258
|
-
artifact_type:
|
|
259
|
-
milestone_id:
|
|
260
|
-
slice_id:
|
|
261
|
-
task_id:
|
|
262
|
-
full_content:
|
|
240
|
+
path: "docs/api.md",
|
|
241
|
+
artifact_type: "reference",
|
|
242
|
+
milestone_id: "M001",
|
|
243
|
+
slice_id: "S01",
|
|
244
|
+
task_id: "T01",
|
|
245
|
+
full_content: "API documentation",
|
|
263
246
|
});
|
|
264
247
|
closeDatabase();
|
|
265
248
|
|
|
266
249
|
openDatabase(mainDb);
|
|
267
250
|
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
268
251
|
|
|
269
|
-
assert.ok(result.artifacts > 0,
|
|
252
|
+
assert.ok(result.artifacts > 0, "artifacts merged count > 0");
|
|
270
253
|
const adapter = _getAdapter()!;
|
|
271
|
-
const row = adapter.prepare(
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
{
|
|
254
|
+
const row = adapter.prepare("SELECT * FROM artifacts WHERE path = ?").get("docs/api.md");
|
|
255
|
+
// Statement#get returns undefined (not null) when no row matches, so use
|
|
256
|
+
// loose inequality to catch both — strict `!== null` would silently let a
|
|
257
|
+
// missing artifact row pass this assertion.
|
|
258
|
+
assert.ok(row != null, "artifact from worktree now in main");
|
|
259
|
+
assert.equal((row as any)["artifact_type"], "reference", "artifact data correct after merge");
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test("reconcileWorktreeDb detects conflicts and applies worktree-wins policy", (t) => {
|
|
280
263
|
const mainDir = tempDir();
|
|
281
264
|
const wtDir = tempDir();
|
|
282
|
-
|
|
283
|
-
|
|
265
|
+
registerCleanup(t, mainDir, wtDir);
|
|
266
|
+
|
|
267
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
268
|
+
const wtDb = path.join(wtDir, "gsd.db");
|
|
284
269
|
|
|
285
|
-
// Seed main with D001
|
|
286
270
|
seedMainDb(mainDb);
|
|
287
271
|
closeDatabase();
|
|
288
272
|
copyWorktreeDb(mainDb, wtDb);
|
|
289
273
|
|
|
290
|
-
// Modify D001 in main
|
|
291
274
|
openDatabase(mainDb);
|
|
292
|
-
|
|
293
|
-
mainAdapter.prepare(
|
|
275
|
+
_getAdapter()!.prepare(
|
|
294
276
|
`UPDATE decisions SET choice = 'better-sqlite3' WHERE id = 'D001'`,
|
|
295
277
|
).run();
|
|
296
278
|
closeDatabase();
|
|
297
279
|
|
|
298
|
-
// Modify D001 in worktree differently
|
|
299
280
|
openDatabase(wtDb);
|
|
300
|
-
|
|
301
|
-
wtAdapter.prepare(
|
|
281
|
+
_getAdapter()!.prepare(
|
|
302
282
|
`UPDATE decisions SET choice = 'sql.js' WHERE id = 'D001'`,
|
|
303
283
|
).run();
|
|
304
284
|
closeDatabase();
|
|
305
285
|
|
|
306
|
-
// Reconcile
|
|
307
286
|
openDatabase(mainDb);
|
|
308
287
|
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
309
288
|
|
|
310
|
-
assert.ok(result.conflicts.length > 0,
|
|
289
|
+
assert.ok(result.conflicts.length > 0, "conflicts detected");
|
|
311
290
|
assert.ok(
|
|
312
|
-
result.conflicts.some(c => c.includes(
|
|
313
|
-
|
|
291
|
+
result.conflicts.some((c) => c.includes("D001")),
|
|
292
|
+
"conflict mentions D001",
|
|
314
293
|
);
|
|
315
294
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
cleanup(mainDir, wtDir);
|
|
321
|
-
}
|
|
295
|
+
const d1 = getDecisionById("D001");
|
|
296
|
+
assert.equal(d1?.choice, "sql.js", "worktree wins on conflict (INSERT OR REPLACE)");
|
|
297
|
+
});
|
|
322
298
|
|
|
323
|
-
|
|
324
|
-
{
|
|
299
|
+
test("reconcileWorktreeDb handles missing worktree DB gracefully", (t) => {
|
|
325
300
|
const mainDir = tempDir();
|
|
326
|
-
|
|
301
|
+
registerCleanup(t, mainDir);
|
|
327
302
|
|
|
303
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
328
304
|
seedMainDb(mainDb);
|
|
329
305
|
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
assert.
|
|
333
|
-
assert.
|
|
334
|
-
assert.
|
|
306
|
+
const missingWt = path.join(mainDir, "missing-worktree.db");
|
|
307
|
+
const result = reconcileWorktreeDb(mainDb, missingWt);
|
|
308
|
+
assert.equal(result.decisions, 0, "no decisions merged for missing worktree DB");
|
|
309
|
+
assert.equal(result.requirements, 0, "no requirements merged for missing worktree DB");
|
|
310
|
+
assert.equal(result.artifacts, 0, "no artifacts merged for missing worktree DB");
|
|
311
|
+
assert.equal(result.conflicts.length, 0, "no conflicts for missing worktree DB");
|
|
312
|
+
});
|
|
335
313
|
|
|
336
|
-
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// Test: path with spaces works
|
|
340
|
-
{
|
|
314
|
+
test("reconcileWorktreeDb handles paths containing spaces", (t) => {
|
|
341
315
|
const baseDir = tempDir();
|
|
342
|
-
|
|
343
|
-
|
|
316
|
+
registerCleanup(t, baseDir);
|
|
317
|
+
|
|
318
|
+
const mainDir = path.join(baseDir, "main dir");
|
|
319
|
+
const wtDir = path.join(baseDir, "worktree dir");
|
|
344
320
|
fs.mkdirSync(mainDir, { recursive: true });
|
|
345
321
|
fs.mkdirSync(wtDir, { recursive: true });
|
|
346
322
|
|
|
347
|
-
const mainDb = path.join(mainDir,
|
|
348
|
-
const wtDb = path.join(wtDir,
|
|
323
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
324
|
+
const wtDb = path.join(wtDir, "gsd.db");
|
|
349
325
|
|
|
350
326
|
seedMainDb(mainDb);
|
|
351
327
|
closeDatabase();
|
|
352
328
|
copyWorktreeDb(mainDb, wtDb);
|
|
353
329
|
|
|
354
|
-
// Add a decision in worktree
|
|
355
330
|
openDatabase(wtDb);
|
|
356
331
|
insertDecision({
|
|
357
|
-
id:
|
|
358
|
-
when_context:
|
|
359
|
-
scope:
|
|
360
|
-
decision:
|
|
361
|
-
choice:
|
|
362
|
-
rationale:
|
|
363
|
-
revisable:
|
|
364
|
-
made_by:
|
|
332
|
+
id: "D003",
|
|
333
|
+
when_context: "2025-03-01",
|
|
334
|
+
scope: "M001/S03",
|
|
335
|
+
decision: "Path spaces test",
|
|
336
|
+
choice: "yes",
|
|
337
|
+
rationale: "Robustness",
|
|
338
|
+
revisable: "no",
|
|
339
|
+
made_by: "agent",
|
|
365
340
|
superseded_by: null,
|
|
366
341
|
});
|
|
367
342
|
closeDatabase();
|
|
368
343
|
|
|
369
344
|
openDatabase(mainDb);
|
|
370
345
|
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
371
|
-
assert.ok(result.decisions > 0,
|
|
372
|
-
const d3 = getDecisionById(
|
|
373
|
-
assert.ok(d3 !== null,
|
|
346
|
+
assert.ok(result.decisions > 0, "reconciliation works with spaces in path");
|
|
347
|
+
const d3 = getDecisionById("D003");
|
|
348
|
+
assert.ok(d3 !== null, "D003 merged from worktree with spaces in path");
|
|
349
|
+
});
|
|
374
350
|
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Test: main DB is usable after reconciliation (DETACH cleanup verified)
|
|
379
|
-
{
|
|
351
|
+
test("reconcileWorktreeDb leaves main DB usable after DETACH", (t) => {
|
|
380
352
|
const mainDir = tempDir();
|
|
381
353
|
const wtDir = tempDir();
|
|
382
|
-
|
|
383
|
-
|
|
354
|
+
registerCleanup(t, mainDir, wtDir);
|
|
355
|
+
|
|
356
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
357
|
+
const wtDb = path.join(wtDir, "gsd.db");
|
|
384
358
|
|
|
385
359
|
seedMainDb(mainDb);
|
|
386
360
|
closeDatabase();
|
|
@@ -389,92 +363,78 @@ console.log('\n=== worktree-db: reconcileWorktreeDb ===');
|
|
|
389
363
|
openDatabase(mainDb);
|
|
390
364
|
reconcileWorktreeDb(mainDb, wtDb);
|
|
391
365
|
|
|
392
|
-
|
|
393
|
-
assert.ok(isDbAvailable(), 'DB still available after reconciliation');
|
|
366
|
+
assert.ok(isDbAvailable(), "DB still available after reconciliation");
|
|
394
367
|
|
|
395
368
|
insertDecision({
|
|
396
|
-
id:
|
|
397
|
-
when_context:
|
|
398
|
-
scope:
|
|
399
|
-
decision:
|
|
400
|
-
choice:
|
|
401
|
-
rationale:
|
|
402
|
-
revisable:
|
|
403
|
-
made_by:
|
|
369
|
+
id: "D099",
|
|
370
|
+
when_context: "2025-12-01",
|
|
371
|
+
scope: "test",
|
|
372
|
+
decision: "Post-reconcile insert",
|
|
373
|
+
choice: "works",
|
|
374
|
+
rationale: "Verify DETACH cleanup",
|
|
375
|
+
revisable: "no",
|
|
376
|
+
made_by: "agent",
|
|
404
377
|
superseded_by: null,
|
|
405
378
|
});
|
|
406
379
|
|
|
407
|
-
const d99 = getDecisionById(
|
|
408
|
-
assert.ok(d99 !== null,
|
|
409
|
-
assert.
|
|
380
|
+
const d99 = getDecisionById("D099");
|
|
381
|
+
assert.ok(d99 !== null, "can insert and query after reconciliation");
|
|
382
|
+
assert.equal(d99?.choice, "works", "post-reconcile data correct");
|
|
410
383
|
|
|
411
|
-
// Verify
|
|
384
|
+
// Verify wt database is detached
|
|
412
385
|
const adapter = _getAdapter()!;
|
|
413
386
|
let wtAccessible = false;
|
|
414
387
|
try {
|
|
415
|
-
adapter.prepare(
|
|
388
|
+
adapter.prepare("SELECT count(*) FROM wt.decisions").get();
|
|
416
389
|
wtAccessible = true;
|
|
417
390
|
} catch {
|
|
418
391
|
// Expected — wt should be detached
|
|
419
392
|
}
|
|
420
|
-
assert.ok(!wtAccessible,
|
|
393
|
+
assert.ok(!wtAccessible, "wt database is detached after reconciliation");
|
|
394
|
+
});
|
|
421
395
|
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Test: reconcile with empty worktree DB (no new rows, no conflicts)
|
|
426
|
-
{
|
|
396
|
+
test("reconcileWorktreeDb is a no-op when DBs are identical", (t) => {
|
|
427
397
|
const mainDir = tempDir();
|
|
428
398
|
const wtDir = tempDir();
|
|
429
|
-
|
|
430
|
-
|
|
399
|
+
registerCleanup(t, mainDir, wtDir);
|
|
400
|
+
|
|
401
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
402
|
+
const wtDb = path.join(wtDir, "gsd.db");
|
|
431
403
|
|
|
432
404
|
seedMainDb(mainDb);
|
|
433
405
|
closeDatabase();
|
|
434
406
|
copyWorktreeDb(mainDb, wtDb);
|
|
435
407
|
|
|
436
|
-
// Don't modify the worktree DB at all — reconcile the identical copy
|
|
437
408
|
openDatabase(mainDb);
|
|
438
409
|
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
439
410
|
|
|
440
|
-
|
|
441
|
-
assert.ok(
|
|
442
|
-
|
|
411
|
+
assert.equal(result.conflicts.length, 0, "no conflicts when DBs are identical");
|
|
412
|
+
assert.ok(isDbAvailable(), "DB usable after no-change reconciliation");
|
|
413
|
+
});
|
|
443
414
|
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Test: reconcileWorktreeDb must NOT downgrade milestone status complete→active (#4372)
|
|
448
|
-
{
|
|
415
|
+
test("reconcileWorktreeDb does not downgrade milestone status complete→active (#4372)", (t) => {
|
|
449
416
|
const mainDir = tempDir();
|
|
450
417
|
const wtDir = tempDir();
|
|
451
|
-
|
|
452
|
-
|
|
418
|
+
registerCleanup(t, mainDir, wtDir);
|
|
419
|
+
|
|
420
|
+
const mainDb = path.join(mainDir, "gsd.db");
|
|
421
|
+
const wtDb = path.join(wtDir, "gsd.db");
|
|
453
422
|
|
|
454
|
-
// Seed main with a milestone already marked complete
|
|
455
423
|
seedMainDb(mainDb);
|
|
456
424
|
const mainAdapter = _getAdapter()!;
|
|
457
|
-
insertMilestone({ id:
|
|
458
|
-
// Manually mark completed_at so it's a realistic complete record
|
|
425
|
+
insertMilestone({ id: "M-COMP", title: "Completed Milestone", status: "complete" });
|
|
459
426
|
mainAdapter.prepare(`UPDATE milestones SET completed_at = '2025-06-01T00:00:00.000Z' WHERE id = 'M-COMP'`).run();
|
|
460
427
|
closeDatabase();
|
|
461
428
|
|
|
462
|
-
// Copy to worktree — the worktree has the milestone as 'active' (stale / older snapshot)
|
|
463
429
|
copyWorktreeDb(mainDb, wtDb);
|
|
464
430
|
openDatabase(wtDb);
|
|
465
|
-
|
|
466
|
-
wtAdapter.prepare(`UPDATE milestones SET status = 'active', completed_at = NULL WHERE id = 'M-COMP'`).run();
|
|
431
|
+
_getAdapter()!.prepare(`UPDATE milestones SET status = 'active', completed_at = NULL WHERE id = 'M-COMP'`).run();
|
|
467
432
|
closeDatabase();
|
|
468
433
|
|
|
469
|
-
// Reconcile: main should win and keep 'complete'
|
|
470
434
|
openDatabase(mainDb);
|
|
471
435
|
reconcileWorktreeDb(mainDb, wtDb);
|
|
472
436
|
|
|
473
|
-
const m = getMilestone(
|
|
474
|
-
assert.ok(m !== null,
|
|
475
|
-
assert.
|
|
476
|
-
|
|
477
|
-
cleanup(mainDir, wtDir);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// ─── Final Report ──────────────────────────────────────────────────────────
|
|
437
|
+
const m = getMilestone("M-COMP");
|
|
438
|
+
assert.ok(m !== null, "milestone M-COMP still exists after reconcile");
|
|
439
|
+
assert.equal(m!.status, "complete", "complete milestone must not be downgraded to active by stale worktree");
|
|
440
|
+
});
|