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,65 +1,244 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* worktree-submodule-safety.test.ts — #2337
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The bug (#2337): `git worktree remove --force` destroys uncommitted
|
|
5
|
+
* changes in submodule directories. The fix (in
|
|
6
|
+
* `worktree-manager.removeWorktree`) detects submodules with
|
|
7
|
+
* uncommitted state via `git submodule status`, auto-stashes the
|
|
8
|
+
* worktree before teardown, and attempts non-force removal first —
|
|
9
|
+
* falling back to force only after a stash was taken.
|
|
10
|
+
*
|
|
11
|
+
* This test was previously four `src.includes(...)` source-grep checks
|
|
12
|
+
* that asserted the strings "submodule" / "force" / "--force" appeared
|
|
13
|
+
* in the function body. Test 4 was tautological — it passed whenever
|
|
14
|
+
* both "submodule" and "force" were mentioned anywhere in `removeWorktree`
|
|
15
|
+
* regardless of whether the guard was wired correctly. See #4823 and
|
|
16
|
+
* parent issue #4784.
|
|
17
|
+
*
|
|
18
|
+
* This rewrite builds a real git parent repo + local submodule, creates
|
|
19
|
+
* a worktree, dirties a tracked file inside the submodule, then invokes
|
|
20
|
+
* `removeWorktree` and asserts observable behaviour on stderr (where
|
|
21
|
+
* `logWarning` writes) and on the filesystem (the worktree is gone).
|
|
7
22
|
*/
|
|
8
23
|
|
|
9
|
-
import {
|
|
24
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
25
|
+
import assert from "node:assert/strict";
|
|
26
|
+
import { execFileSync } from "node:child_process";
|
|
27
|
+
import {
|
|
28
|
+
mkdtempSync,
|
|
29
|
+
renameSync,
|
|
30
|
+
rmSync,
|
|
31
|
+
writeFileSync,
|
|
32
|
+
existsSync,
|
|
33
|
+
} from "node:fs";
|
|
10
34
|
import { join } from "node:path";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
35
|
+
import { tmpdir } from "node:os";
|
|
36
|
+
|
|
37
|
+
import { createWorktree, removeWorktree } from "../worktree-manager.ts";
|
|
38
|
+
|
|
39
|
+
interface Harness {
|
|
40
|
+
parent: string;
|
|
41
|
+
subSrc: string;
|
|
42
|
+
cleanup: () => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function runGit(cwd: string, args: string[]): string {
|
|
46
|
+
return execFileSync("git", args, {
|
|
47
|
+
cwd,
|
|
48
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
49
|
+
encoding: "utf-8",
|
|
50
|
+
env: {
|
|
51
|
+
...process.env,
|
|
52
|
+
// Disable user config from polluting the test environment.
|
|
53
|
+
GIT_CONFIG_GLOBAL: "/dev/null",
|
|
54
|
+
GIT_CONFIG_SYSTEM: "/dev/null",
|
|
55
|
+
GIT_AUTHOR_NAME: "gsd-test",
|
|
56
|
+
GIT_AUTHOR_EMAIL: "gsd-test@example.com",
|
|
57
|
+
GIT_COMMITTER_NAME: "gsd-test",
|
|
58
|
+
GIT_COMMITTER_EMAIL: "gsd-test@example.com",
|
|
59
|
+
// Allow local-path submodule URLs. Git 2.38.1+ blocks the `file` transport
|
|
60
|
+
// in `submodule add` by default (CVE-2022-39253). The config also has to
|
|
61
|
+
// propagate to git subprocess env for submodule cloning.
|
|
62
|
+
GIT_ALLOW_PROTOCOL: "file",
|
|
63
|
+
},
|
|
64
|
+
}).trim();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function makeHarness(): Harness {
|
|
68
|
+
// Two real git repos: the parent that we will create worktrees of, and
|
|
69
|
+
// the `subSrc` repo that we will add as a submodule.
|
|
70
|
+
const parent = mkdtempSync(join(tmpdir(), "worktree-submodule-parent-"));
|
|
71
|
+
const subSrc = mkdtempSync(join(tmpdir(), "worktree-submodule-source-"));
|
|
72
|
+
|
|
73
|
+
// Bootstrap the submodule source with one committed file.
|
|
74
|
+
runGit(subSrc, ["init", "-b", "main"]);
|
|
75
|
+
writeFileSync(join(subSrc, "tracked.txt"), "initial\n", "utf-8");
|
|
76
|
+
runGit(subSrc, ["add", "."]);
|
|
77
|
+
runGit(subSrc, ["commit", "-m", "initial"]);
|
|
78
|
+
|
|
79
|
+
// Bootstrap the parent with one commit so it has a HEAD for worktrees.
|
|
80
|
+
runGit(parent, ["init", "-b", "main"]);
|
|
81
|
+
// Allow local file:// URLs for submodule add (git 2.38+ blocks by default).
|
|
82
|
+
runGit(parent, ["config", "protocol.file.allow", "always"]);
|
|
83
|
+
writeFileSync(join(parent, "README.md"), "parent\n", "utf-8");
|
|
84
|
+
runGit(parent, ["add", "."]);
|
|
85
|
+
runGit(parent, ["commit", "-m", "initial"]);
|
|
86
|
+
|
|
87
|
+
// Register the subSrc as a submodule named "sub" inside the parent.
|
|
88
|
+
// Use `file://` URL so `protocol.file.allow` governs access; plain path
|
|
89
|
+
// would be blocked by git's local-filesystem safety checks regardless.
|
|
90
|
+
runGit(parent, [
|
|
91
|
+
"-c",
|
|
92
|
+
"protocol.file.allow=always",
|
|
93
|
+
"submodule",
|
|
94
|
+
"add",
|
|
95
|
+
`file://${subSrc}`,
|
|
96
|
+
"sub",
|
|
97
|
+
]);
|
|
98
|
+
runGit(parent, ["commit", "-m", "add submodule"]);
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
parent,
|
|
102
|
+
subSrc,
|
|
103
|
+
cleanup: () => {
|
|
104
|
+
for (const dir of [parent, subSrc]) {
|
|
105
|
+
try {
|
|
106
|
+
rmSync(dir, { recursive: true, force: true });
|
|
107
|
+
} catch {
|
|
108
|
+
// Best-effort cleanup.
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Capture stderr writes during `fn`. `logWarning` writes to stderr, so
|
|
116
|
+
* this reveals warnings emitted by the worktree-manager. */
|
|
117
|
+
function captureStderr(fn: () => void): string {
|
|
118
|
+
const streamAny = process.stderr as unknown as {
|
|
119
|
+
write: (chunk: string | Uint8Array, ...rest: unknown[]) => boolean;
|
|
120
|
+
};
|
|
121
|
+
const original = streamAny.write.bind(streamAny);
|
|
122
|
+
const chunks: string[] = [];
|
|
123
|
+
streamAny.write = (chunk: string | Uint8Array): boolean => {
|
|
124
|
+
chunks.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf-8"));
|
|
125
|
+
return true;
|
|
126
|
+
};
|
|
127
|
+
try {
|
|
128
|
+
fn();
|
|
129
|
+
} finally {
|
|
130
|
+
streamAny.write = original;
|
|
131
|
+
}
|
|
132
|
+
return chunks.join("");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
describe("removeWorktree preserves submodule uncommitted state (#2337)", () => {
|
|
136
|
+
let h: Harness;
|
|
137
|
+
|
|
138
|
+
beforeEach(() => {
|
|
139
|
+
h = makeHarness();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
afterEach(() => {
|
|
143
|
+
h.cleanup();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("clean submodules: worktree removes without stashing or submodule warnings", () => {
|
|
147
|
+
const wt = createWorktree(h.parent, "cleanwt");
|
|
148
|
+
runGit(wt.path, ["submodule", "update", "--init", "--recursive"]);
|
|
149
|
+
|
|
150
|
+
const stderr = captureStderr(() => {
|
|
151
|
+
removeWorktree(h.parent, "cleanwt");
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
assert.ok(!existsSync(wt.path), "worktree directory should be gone");
|
|
155
|
+
assert.doesNotMatch(
|
|
156
|
+
stderr,
|
|
157
|
+
/Saved uncommitted submodule changes to rescue branch/,
|
|
158
|
+
"clean submodule must not trigger rescue-branch creation",
|
|
159
|
+
);
|
|
160
|
+
assert.doesNotMatch(
|
|
161
|
+
stderr,
|
|
162
|
+
/Submodule rescue branch creation failed/,
|
|
163
|
+
"clean submodule must not trigger rescue-branch failure warning",
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("diverged submodule HEAD: removeWorktree detects and warns before tearing down", () => {
|
|
168
|
+
// The code's detection key is `git submodule status` output lines
|
|
169
|
+
// starting with `+` (HEAD diverged from parent's recorded SHA) or
|
|
170
|
+
// `-` (not initialised). Note this is NARROWER than #2337's
|
|
171
|
+
// description ("uncommitted changes") — a plain working-tree edit
|
|
172
|
+
// inside the submodule does NOT trigger the detection. That gap is
|
|
173
|
+
// tracked separately; this test exercises the code path that the
|
|
174
|
+
// current implementation actually guards.
|
|
175
|
+
const wt = createWorktree(h.parent, "dirtywt");
|
|
176
|
+
runGit(wt.path, ["submodule", "update", "--init", "--recursive"]);
|
|
177
|
+
|
|
178
|
+
// Write a new file, commit it inside the submodule — this moves the
|
|
179
|
+
// submodule's HEAD ahead of the parent's recorded SHA, yielding a
|
|
180
|
+
// `+` prefix in `git submodule status`.
|
|
181
|
+
const subPath = join(wt.path, "sub");
|
|
182
|
+
writeFileSync(join(subPath, "new-file.txt"), "divergence\n", "utf-8");
|
|
183
|
+
runGit(subPath, ["add", "."]);
|
|
184
|
+
runGit(subPath, ["commit", "-m", "divergence commit"]);
|
|
185
|
+
|
|
186
|
+
// Sanity: submodule status in the parent worktree must now show `+`.
|
|
187
|
+
const subStatus = runGit(wt.path, ["submodule", "status"]);
|
|
188
|
+
assert.match(
|
|
189
|
+
subStatus,
|
|
190
|
+
/^\+/,
|
|
191
|
+
`precondition: submodule must be diverged, got: "${subStatus}"`,
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const stderr = captureStderr(() => {
|
|
195
|
+
removeWorktree(h.parent, "dirtywt");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Worktree is gone: force fallback succeeded.
|
|
199
|
+
assert.ok(!existsSync(wt.path), "worktree directory should be removed");
|
|
200
|
+
|
|
201
|
+
// The code path that fires on dirty submodules emits one of these
|
|
202
|
+
// two warnings. Either indicates the detection ran — the ONLY
|
|
203
|
+
// observable that would fail if someone removed the
|
|
204
|
+
// `if (hasSubmoduleChanges)` branch and went straight to force
|
|
205
|
+
// removal. This is the assertion that #4823 demanded in place of
|
|
206
|
+
// the tautological `src.includes("submodule") && src.includes("force")`.
|
|
207
|
+
assert.match(
|
|
208
|
+
stderr,
|
|
209
|
+
/Saved uncommitted submodule changes to rescue branch|Submodule rescue branch creation failed|Submodule changes detected/,
|
|
210
|
+
"dirty submodule must trigger detection-and-warning path",
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("missing .gitmodules: detection short-circuits even when submodule content is dirty", () => {
|
|
215
|
+
// Prove the detection is file-based, not identifier-based. If the
|
|
216
|
+
// .gitmodules file is absent, the detection branch must NOT fire
|
|
217
|
+
// regardless of whether "submodule" appears elsewhere in the source.
|
|
218
|
+
const wt = createWorktree(h.parent, "no-gitmodules");
|
|
219
|
+
runGit(wt.path, ["submodule", "update", "--init", "--recursive"]);
|
|
220
|
+
|
|
221
|
+
writeFileSync(
|
|
222
|
+
join(wt.path, "sub", "tracked.txt"),
|
|
223
|
+
"modified\n",
|
|
224
|
+
"utf-8",
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
// Hide .gitmodules so existsSync(gitmodulesPath) returns false.
|
|
228
|
+
const modPath = join(wt.path, ".gitmodules");
|
|
229
|
+
const hiddenPath = join(wt.path, ".gitmodules.hidden");
|
|
230
|
+
if (existsSync(modPath)) {
|
|
231
|
+
renameSync(modPath, hiddenPath);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const stderr = captureStderr(() => {
|
|
235
|
+
removeWorktree(h.parent, "no-gitmodules");
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
assert.doesNotMatch(
|
|
239
|
+
stderr,
|
|
240
|
+
/Saved uncommitted submodule changes to rescue branch/,
|
|
241
|
+
"missing .gitmodules should skip submodule detection entirely",
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
@@ -10,14 +10,10 @@
|
|
|
10
10
|
*
|
|
11
11
|
* 2. completed-units.json is not forward-synced from project root to
|
|
12
12
|
* worktree, so the worktree never learns about already-completed units.
|
|
13
|
-
*
|
|
14
|
-
* Covers:
|
|
15
|
-
* - syncProjectRootToWorktree does NOT overwrite existing worktree files
|
|
16
|
-
* - syncProjectRootToWorktree copies files missing from the worktree
|
|
17
|
-
* - completed-units.json is forward-synced from project root to worktree
|
|
18
|
-
* - completed-units.json sync uses force:true (project root is authoritative)
|
|
19
13
|
*/
|
|
20
14
|
|
|
15
|
+
import { test } from "node:test";
|
|
16
|
+
import assert from "node:assert/strict";
|
|
21
17
|
import {
|
|
22
18
|
mkdtempSync,
|
|
23
19
|
mkdirSync,
|
|
@@ -30,9 +26,6 @@ import { join } from "node:path";
|
|
|
30
26
|
import { tmpdir } from "node:os";
|
|
31
27
|
|
|
32
28
|
import { syncProjectRootToWorktree } from "../auto-worktree.ts";
|
|
33
|
-
import { createTestContext } from "./test-helpers.ts";
|
|
34
|
-
|
|
35
|
-
const { assertTrue, assertEq, report } = createTestContext();
|
|
36
29
|
|
|
37
30
|
function createBase(name: string): string {
|
|
38
31
|
const base = mkdtempSync(join(tmpdir(), `gsd-wt-1886-${name}-`));
|
|
@@ -40,165 +33,124 @@ function createBase(name: string): string {
|
|
|
40
33
|
return base;
|
|
41
34
|
}
|
|
42
35
|
|
|
43
|
-
function
|
|
44
|
-
|
|
36
|
+
function registerBases(
|
|
37
|
+
t: { after: (fn: () => void) => void },
|
|
38
|
+
...dirs: string[]
|
|
39
|
+
): void {
|
|
40
|
+
t.after(() => {
|
|
41
|
+
for (const d of dirs) {
|
|
42
|
+
rmSync(d, { recursive: true, force: true });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
test("#1886: worktree VALIDATION.md is not overwritten by project root sync", (t) => {
|
|
48
|
+
const mainBase = createBase("main");
|
|
49
|
+
const wtBase = createBase("wt");
|
|
50
|
+
registerBases(t, mainBase, wtBase);
|
|
51
|
+
|
|
52
|
+
// Project root has an older CONTEXT but no VALIDATION
|
|
53
|
+
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
54
|
+
mkdirSync(prM004, { recursive: true });
|
|
55
|
+
writeFileSync(join(prM004, "M004-CONTEXT.md"), "# old context");
|
|
56
|
+
|
|
57
|
+
// Worktree has CONTEXT + VALIDATION (written by validate-milestone)
|
|
58
|
+
const wtM004 = join(wtBase, ".gsd", "milestones", "M004");
|
|
59
|
+
mkdirSync(wtM004, { recursive: true });
|
|
60
|
+
writeFileSync(join(wtM004, "M004-CONTEXT.md"), "# worktree context");
|
|
61
|
+
writeFileSync(
|
|
62
|
+
join(wtM004, "M004-VALIDATION.md"),
|
|
63
|
+
"verdict: pass\nremediation_round: 1",
|
|
51
64
|
);
|
|
52
|
-
{
|
|
53
|
-
const mainBase = createBase("main");
|
|
54
|
-
const wtBase = createBase("wt");
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
// Project root has an older CONTEXT but no VALIDATION
|
|
58
|
-
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
59
|
-
mkdirSync(prM004, { recursive: true });
|
|
60
|
-
writeFileSync(join(prM004, "M004-CONTEXT.md"), "# old context");
|
|
61
|
-
|
|
62
|
-
// Worktree has CONTEXT + VALIDATION (written by validate-milestone)
|
|
63
|
-
const wtM004 = join(wtBase, ".gsd", "milestones", "M004");
|
|
64
|
-
mkdirSync(wtM004, { recursive: true });
|
|
65
|
-
writeFileSync(join(wtM004, "M004-CONTEXT.md"), "# worktree context");
|
|
66
|
-
writeFileSync(
|
|
67
|
-
join(wtM004, "M004-VALIDATION.md"),
|
|
68
|
-
"verdict: pass\nremediation_round: 1",
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
72
|
-
|
|
73
|
-
// VALIDATION.md must still exist in worktree
|
|
74
|
-
assertTrue(
|
|
75
|
-
existsSync(join(wtM004, "M004-VALIDATION.md")),
|
|
76
|
-
"#1886: VALIDATION.md still exists after sync",
|
|
77
|
-
);
|
|
78
|
-
assertEq(
|
|
79
|
-
readFileSync(join(wtM004, "M004-VALIDATION.md"), "utf-8"),
|
|
80
|
-
"verdict: pass\nremediation_round: 1",
|
|
81
|
-
"#1886: VALIDATION.md content preserved",
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
// CONTEXT.md should NOT be overwritten — worktree version is authoritative
|
|
85
|
-
assertEq(
|
|
86
|
-
readFileSync(join(wtM004, "M004-CONTEXT.md"), "utf-8"),
|
|
87
|
-
"# worktree context",
|
|
88
|
-
"#1886: existing worktree CONTEXT.md not overwritten",
|
|
89
|
-
);
|
|
90
|
-
} finally {
|
|
91
|
-
cleanup(mainBase);
|
|
92
|
-
cleanup(wtBase);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// ─── 2. Missing files ARE still copied from project root ────────────────
|
|
97
|
-
console.log("\n=== 2. #1886: missing worktree files still copied ===");
|
|
98
|
-
{
|
|
99
|
-
const mainBase = createBase("main");
|
|
100
|
-
const wtBase = createBase("wt");
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
104
|
-
mkdirSync(prM004, { recursive: true });
|
|
105
|
-
writeFileSync(join(prM004, "M004-CONTEXT.md"), "# from project root");
|
|
106
|
-
writeFileSync(join(prM004, "M004-ROADMAP.md"), "# roadmap");
|
|
107
|
-
|
|
108
|
-
// Worktree has no M004 directory at all
|
|
109
|
-
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
110
|
-
|
|
111
|
-
assertTrue(
|
|
112
|
-
existsSync(join(wtBase, ".gsd", "milestones", "M004", "M004-CONTEXT.md")),
|
|
113
|
-
"#1886: missing CONTEXT.md copied from project root",
|
|
114
|
-
);
|
|
115
|
-
assertTrue(
|
|
116
|
-
existsSync(join(wtBase, ".gsd", "milestones", "M004", "M004-ROADMAP.md")),
|
|
117
|
-
"#1886: missing ROADMAP.md copied from project root",
|
|
118
|
-
);
|
|
119
|
-
} finally {
|
|
120
|
-
cleanup(mainBase);
|
|
121
|
-
cleanup(wtBase);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
65
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
66
|
+
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
67
|
+
|
|
68
|
+
assert.ok(
|
|
69
|
+
existsSync(join(wtM004, "M004-VALIDATION.md")),
|
|
70
|
+
"VALIDATION.md still exists after sync",
|
|
128
71
|
);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
);
|
|
151
|
-
assertEq(
|
|
152
|
-
wtCompleted,
|
|
153
|
-
["validate-milestone/M004"],
|
|
154
|
-
"#1886: completed-units.json synced from project root (force:true)",
|
|
155
|
-
);
|
|
156
|
-
} finally {
|
|
157
|
-
cleanup(mainBase);
|
|
158
|
-
cleanup(wtBase);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
72
|
+
assert.equal(
|
|
73
|
+
readFileSync(join(wtM004, "M004-VALIDATION.md"), "utf-8"),
|
|
74
|
+
"verdict: pass\nremediation_round: 1",
|
|
75
|
+
"VALIDATION.md content preserved",
|
|
76
|
+
);
|
|
77
|
+
assert.equal(
|
|
78
|
+
readFileSync(join(wtM004, "M004-CONTEXT.md"), "utf-8"),
|
|
79
|
+
"# worktree context",
|
|
80
|
+
"existing worktree CONTEXT.md not overwritten",
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("#1886: missing worktree files are still copied from project root", (t) => {
|
|
85
|
+
const mainBase = createBase("main");
|
|
86
|
+
const wtBase = createBase("wt");
|
|
87
|
+
registerBases(t, mainBase, wtBase);
|
|
88
|
+
|
|
89
|
+
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
90
|
+
mkdirSync(prM004, { recursive: true });
|
|
91
|
+
writeFileSync(join(prM004, "M004-CONTEXT.md"), "# from project root");
|
|
92
|
+
writeFileSync(join(prM004, "M004-ROADMAP.md"), "# roadmap");
|
|
161
93
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
94
|
+
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
95
|
+
|
|
96
|
+
assert.ok(
|
|
97
|
+
existsSync(join(wtBase, ".gsd", "milestones", "M004", "M004-CONTEXT.md")),
|
|
98
|
+
"missing CONTEXT.md copied from project root",
|
|
165
99
|
);
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// Project root milestone dir must exist for sync to run
|
|
172
|
-
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
173
|
-
mkdirSync(prM004, { recursive: true });
|
|
174
|
-
|
|
175
|
-
// No completed-units.json in project root
|
|
176
|
-
// Worktree has its own
|
|
177
|
-
writeFileSync(
|
|
178
|
-
join(wtBase, ".gsd", "completed-units.json"),
|
|
179
|
-
JSON.stringify(["some-unit/M001"]),
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
183
|
-
|
|
184
|
-
const wtCompleted = JSON.parse(
|
|
185
|
-
readFileSync(join(wtBase, ".gsd", "completed-units.json"), "utf-8"),
|
|
186
|
-
);
|
|
187
|
-
assertEq(
|
|
188
|
-
wtCompleted,
|
|
189
|
-
["some-unit/M001"],
|
|
190
|
-
"#1886: worktree completed-units.json untouched when project root has none",
|
|
191
|
-
);
|
|
192
|
-
} finally {
|
|
193
|
-
cleanup(mainBase);
|
|
194
|
-
cleanup(wtBase);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
100
|
+
assert.ok(
|
|
101
|
+
existsSync(join(wtBase, ".gsd", "milestones", "M004", "M004-ROADMAP.md")),
|
|
102
|
+
"missing ROADMAP.md copied from project root",
|
|
103
|
+
);
|
|
104
|
+
});
|
|
197
105
|
|
|
198
|
-
|
|
199
|
-
|
|
106
|
+
test("#1886: completed-units.json is forward-synced to worktree", (t) => {
|
|
107
|
+
const mainBase = createBase("main");
|
|
108
|
+
const wtBase = createBase("wt");
|
|
109
|
+
registerBases(t, mainBase, wtBase);
|
|
110
|
+
|
|
111
|
+
writeFileSync(
|
|
112
|
+
join(mainBase, ".gsd", "completed-units.json"),
|
|
113
|
+
JSON.stringify(["validate-milestone/M004"]),
|
|
114
|
+
);
|
|
115
|
+
writeFileSync(
|
|
116
|
+
join(wtBase, ".gsd", "completed-units.json"),
|
|
117
|
+
JSON.stringify([]),
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
121
|
+
|
|
122
|
+
const wtCompleted = JSON.parse(
|
|
123
|
+
readFileSync(join(wtBase, ".gsd", "completed-units.json"), "utf-8"),
|
|
124
|
+
);
|
|
125
|
+
assert.deepEqual(
|
|
126
|
+
wtCompleted,
|
|
127
|
+
["validate-milestone/M004"],
|
|
128
|
+
"completed-units.json synced from project root (force:true)",
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("#1886: worktree completed-units.json untouched when project root has none", (t) => {
|
|
133
|
+
const mainBase = createBase("main");
|
|
134
|
+
const wtBase = createBase("wt");
|
|
135
|
+
registerBases(t, mainBase, wtBase);
|
|
136
|
+
|
|
137
|
+
// Project root milestone dir must exist for sync to run
|
|
138
|
+
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
139
|
+
mkdirSync(prM004, { recursive: true });
|
|
140
|
+
|
|
141
|
+
writeFileSync(
|
|
142
|
+
join(wtBase, ".gsd", "completed-units.json"),
|
|
143
|
+
JSON.stringify(["some-unit/M001"]),
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
200
147
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
148
|
+
const wtCompleted = JSON.parse(
|
|
149
|
+
readFileSync(join(wtBase, ".gsd", "completed-units.json"), "utf-8"),
|
|
150
|
+
);
|
|
151
|
+
assert.deepEqual(
|
|
152
|
+
wtCompleted,
|
|
153
|
+
["some-unit/M001"],
|
|
154
|
+
"worktree completed-units.json untouched when project root has none",
|
|
155
|
+
);
|
|
204
156
|
});
|