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
|
@@ -98,6 +98,66 @@ const ROOT_STATE_FILES = [
|
|
|
98
98
|
// because the project root is authoritative for preferences (#2684).
|
|
99
99
|
] as const;
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Pop a stash entry by tracking the unique marker embedded in its message so
|
|
103
|
+
* concurrent stash operations against the same project root cannot cause us to
|
|
104
|
+
* pop the wrong entry.
|
|
105
|
+
*
|
|
106
|
+
* If `stashMarker` is null or no longer present in the stash list (e.g. a
|
|
107
|
+
* concurrent process popped/dropped it), leaves the stash list untouched and
|
|
108
|
+
* returns null.
|
|
109
|
+
*
|
|
110
|
+
* Throws on pop failure so callers can handle conflict cases the same way
|
|
111
|
+
* they would with the prior `git stash pop` form. When throwing after a
|
|
112
|
+
* targeted pop attempt, the error is annotated with the targeted stash ref.
|
|
113
|
+
*
|
|
114
|
+
* (Issue #4980 HIGH-6)
|
|
115
|
+
*/
|
|
116
|
+
function popStashByRef(basePath: string, stashMarker: string | null): string | null {
|
|
117
|
+
let popArg: string | null = null;
|
|
118
|
+
if (stashMarker) {
|
|
119
|
+
try {
|
|
120
|
+
const list = execFileSync("git", ["stash", "list", "--format=%gd%x00%s"], {
|
|
121
|
+
cwd: basePath,
|
|
122
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
123
|
+
encoding: "utf-8",
|
|
124
|
+
}).trim().split("\n").filter(Boolean);
|
|
125
|
+
for (const entry of list) {
|
|
126
|
+
const [ref, subject] = entry.split("\0");
|
|
127
|
+
if (ref && subject?.includes(stashMarker)) {
|
|
128
|
+
popArg = ref;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} catch (err) {
|
|
133
|
+
logWarning("worktree", `stash list lookup failed; leaving stash untouched: ${err instanceof Error ? err.message : String(err)}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (!popArg) {
|
|
137
|
+
logWarning("worktree", "recorded stash entry could not be resolved; skipping automatic pop");
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
execFileSync("git", ["stash", "pop", popArg], {
|
|
142
|
+
cwd: basePath,
|
|
143
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
144
|
+
encoding: "utf-8",
|
|
145
|
+
});
|
|
146
|
+
} catch (err) {
|
|
147
|
+
if (err && typeof err === "object") {
|
|
148
|
+
(err as { stashRef?: string }).stashRef = popArg;
|
|
149
|
+
}
|
|
150
|
+
throw err;
|
|
151
|
+
}
|
|
152
|
+
return popArg;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function stashRefFromError(err: unknown): string | null {
|
|
156
|
+
if (!err || typeof err !== "object") return null;
|
|
157
|
+
const stashRef = (err as { stashRef?: unknown }).stashRef;
|
|
158
|
+
return typeof stashRef === "string" && stashRef.length > 0 ? stashRef : null;
|
|
159
|
+
}
|
|
160
|
+
|
|
101
161
|
/**
|
|
102
162
|
* Check if two filesystem paths resolve to the same real location.
|
|
103
163
|
* Returns false if either path cannot be resolved (e.g. doesn't exist).
|
|
@@ -971,6 +1031,32 @@ export function enterBranchModeForMilestone(
|
|
|
971
1031
|
validatedPrefBranch ??
|
|
972
1032
|
nativeDetectMainBranch(basePath);
|
|
973
1033
|
|
|
1034
|
+
// TOCTOU ancestry guard (Issue #4980 HIGH-3).
|
|
1035
|
+
//
|
|
1036
|
+
// The outer `branchExists` check at line 1012 is racy: a concurrent
|
|
1037
|
+
// process (parallel-orchestrator worker, side-by-side `gsd` instance,
|
|
1038
|
+
// or manual `git branch` invocation) may have created the branch with
|
|
1039
|
+
// real commits between that check and this point. `nativeBranchForceReset`
|
|
1040
|
+
// does `git branch -f`, which silently overwrites the branch ref —
|
|
1041
|
+
// orphaning any commits not reachable from `startPoint`. Re-check
|
|
1042
|
+
// immediately before the destructive call and refuse if the branch
|
|
1043
|
+
// suddenly exists with non-ancestor commits.
|
|
1044
|
+
//
|
|
1045
|
+
// Note: under single-threaded execution this is rarely reached, but it
|
|
1046
|
+
// is NOT dead code — it is the only barrier against a TOCTOU-induced
|
|
1047
|
+
// commit loss in this code path.
|
|
1048
|
+
const concurrentlyCreated = nativeBranchExists(basePath, branch);
|
|
1049
|
+
if (
|
|
1050
|
+
concurrentlyCreated &&
|
|
1051
|
+
!nativeIsAncestor(basePath, branch, startPoint)
|
|
1052
|
+
) {
|
|
1053
|
+
throw new GSDError(
|
|
1054
|
+
GSD_GIT_ERROR,
|
|
1055
|
+
`Branch "${branch}" was created concurrently with commits not reachable from "${startPoint}". ` +
|
|
1056
|
+
`Refusing to force-reset — would orphan prior work. ` +
|
|
1057
|
+
`Resume the existing milestone or run \`git branch -D ${branch}\` to discard.`,
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
974
1060
|
// nativeBranchForceReset creates (or resets) branch at startPoint,
|
|
975
1061
|
// then checkout switches HEAD to it.
|
|
976
1062
|
nativeBranchForceReset(basePath, branch, startPoint);
|
|
@@ -1576,7 +1662,20 @@ export function mergeMilestoneToMain(
|
|
|
1576
1662
|
|
|
1577
1663
|
// 5. Checkout integration branch (skip if already current — avoids git error
|
|
1578
1664
|
// when main is already checked out in the project-root worktree, #757)
|
|
1665
|
+
//
|
|
1666
|
+
// Refuse to proceed if the project root is in detached HEAD state. Silently
|
|
1667
|
+
// running `nativeCheckoutBranch(mainBranch)` on a detached HEAD would
|
|
1668
|
+
// abandon the user's deliberately-checked-out commit (mid-bisect, reviewing
|
|
1669
|
+
// a tag, CI checkout-sha) without warning. (Issue #4980 HIGH-10)
|
|
1579
1670
|
const currentBranchAtBase = nativeGetCurrentBranch(originalBasePath_);
|
|
1671
|
+
if (!currentBranchAtBase || currentBranchAtBase.length === 0) {
|
|
1672
|
+
process.chdir(previousCwd);
|
|
1673
|
+
throw new GSDError(
|
|
1674
|
+
GSD_GIT_ERROR,
|
|
1675
|
+
`Project root is in detached HEAD state — cannot perform milestone merge. ` +
|
|
1676
|
+
`Checkout an integration branch (e.g. \`git checkout ${mainBranch}\`) before resuming.`,
|
|
1677
|
+
);
|
|
1678
|
+
}
|
|
1580
1679
|
if (currentBranchAtBase !== mainBranch) {
|
|
1581
1680
|
nativeCheckoutBranch(originalBasePath_, mainBranch);
|
|
1582
1681
|
}
|
|
@@ -1768,6 +1867,11 @@ export function mergeMilestoneToMain(
|
|
|
1768
1867
|
}
|
|
1769
1868
|
|
|
1770
1869
|
let stashed = false;
|
|
1870
|
+
// Embed a unique marker in the stash message so subsequent pop/drop targets
|
|
1871
|
+
// the entry we created, not whatever happens to be at stash@{0} (concurrent
|
|
1872
|
+
// milestone merges share the project-root stash list and can shift positions).
|
|
1873
|
+
// (Issue #4980 HIGH-6)
|
|
1874
|
+
let stashMarker: string | null = null;
|
|
1771
1875
|
try {
|
|
1772
1876
|
const status = execFileSync("git", ["status", "--porcelain"], {
|
|
1773
1877
|
cwd: originalBasePath_,
|
|
@@ -1775,9 +1879,10 @@ export function mergeMilestoneToMain(
|
|
|
1775
1879
|
encoding: "utf-8",
|
|
1776
1880
|
}).trim();
|
|
1777
1881
|
if (status) {
|
|
1882
|
+
stashMarker = `gsd-pre-merge:${milestoneId}:${process.pid}:${Date.now()}:${process.hrtime.bigint().toString(36)}`;
|
|
1778
1883
|
execFileSync(
|
|
1779
1884
|
"git",
|
|
1780
|
-
["stash", "push", "--include-untracked", "-m", `gsd: pre-merge stash for ${milestoneId}`],
|
|
1885
|
+
["stash", "push", "--include-untracked", "-m", `gsd: pre-merge stash for ${milestoneId} [${stashMarker}]`],
|
|
1781
1886
|
{ cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" },
|
|
1782
1887
|
);
|
|
1783
1888
|
stashed = true;
|
|
@@ -1834,11 +1939,7 @@ export function mergeMilestoneToMain(
|
|
|
1834
1939
|
// Pop stash before throwing so local work is not lost.
|
|
1835
1940
|
if (stashed) {
|
|
1836
1941
|
try {
|
|
1837
|
-
|
|
1838
|
-
cwd: originalBasePath_,
|
|
1839
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
1840
|
-
encoding: "utf-8",
|
|
1841
|
-
});
|
|
1942
|
+
popStashByRef(originalBasePath_, stashMarker);
|
|
1842
1943
|
} catch (err) { /* stash pop conflict is non-fatal */
|
|
1843
1944
|
logWarning("worktree", `git stash pop failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1844
1945
|
}
|
|
@@ -1910,11 +2011,7 @@ export function mergeMilestoneToMain(
|
|
|
1910
2011
|
// Pop stash before throwing so local work is not lost (#2151).
|
|
1911
2012
|
if (stashed) {
|
|
1912
2013
|
try {
|
|
1913
|
-
|
|
1914
|
-
cwd: originalBasePath_,
|
|
1915
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
1916
|
-
encoding: "utf-8",
|
|
1917
|
-
});
|
|
2014
|
+
popStashByRef(originalBasePath_, stashMarker);
|
|
1918
2015
|
} catch (err) { /* stash pop conflict is non-fatal */
|
|
1919
2016
|
logWarning("worktree", `git stash pop failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1920
2017
|
}
|
|
@@ -1962,13 +2059,11 @@ export function mergeMilestoneToMain(
|
|
|
1962
2059
|
// or the commit content. Conflict on pop is non-fatal — the stash entry is
|
|
1963
2060
|
// preserved and the user can resolve manually with `git stash pop`.
|
|
1964
2061
|
if (stashed) {
|
|
2062
|
+
let stashRefForDrop: string | null = null;
|
|
1965
2063
|
try {
|
|
1966
|
-
|
|
1967
|
-
cwd: originalBasePath_,
|
|
1968
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
1969
|
-
encoding: "utf-8",
|
|
1970
|
-
});
|
|
2064
|
+
stashRefForDrop = popStashByRef(originalBasePath_, stashMarker);
|
|
1971
2065
|
} catch (e) {
|
|
2066
|
+
stashRefForDrop = stashRefFromError(e);
|
|
1972
2067
|
logWarning("worktree", `git stash pop failed, attempting conflict resolution: ${(e as Error).message}`);
|
|
1973
2068
|
// Stash pop after squash merge can conflict on .gsd/ state files that
|
|
1974
2069
|
// diverged between branches. Left unresolved, these UU entries block
|
|
@@ -1997,22 +2092,31 @@ export function mergeMilestoneToMain(
|
|
|
1997
2092
|
}
|
|
1998
2093
|
}
|
|
1999
2094
|
|
|
2000
|
-
if (nonGsdUU.length === 0) {
|
|
2095
|
+
if (gsdUU.length > 0 && nonGsdUU.length === 0) {
|
|
2001
2096
|
// All conflicts were .gsd/ files — safe to drop the stash
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2097
|
+
if (stashRefForDrop) {
|
|
2098
|
+
try {
|
|
2099
|
+
execFileSync("git", ["stash", "drop", stashRefForDrop], {
|
|
2100
|
+
cwd: originalBasePath_,
|
|
2101
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2102
|
+
encoding: "utf-8",
|
|
2103
|
+
});
|
|
2104
|
+
} catch (err) { /* stash may already be consumed */
|
|
2105
|
+
logWarning("worktree", `git stash drop failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
2106
|
+
}
|
|
2107
|
+
} else {
|
|
2108
|
+
logWarning("worktree", "recorded stash entry could not be resolved; skipping automatic drop");
|
|
2010
2109
|
}
|
|
2011
|
-
} else {
|
|
2110
|
+
} else if (nonGsdUU.length > 0) {
|
|
2012
2111
|
// Non-.gsd conflicts remain — leave stash for manual resolution
|
|
2013
2112
|
logWarning("reconcile", "Stash pop conflict on non-.gsd files after merge", {
|
|
2014
2113
|
files: nonGsdUU.join(", "),
|
|
2015
2114
|
});
|
|
2115
|
+
} else {
|
|
2116
|
+
logWarning(
|
|
2117
|
+
"worktree",
|
|
2118
|
+
"git stash pop failed without resolvable conflict files; leaving stash for manual recovery",
|
|
2119
|
+
);
|
|
2016
2120
|
}
|
|
2017
2121
|
}
|
|
2018
2122
|
}
|
|
@@ -84,10 +84,11 @@ import {
|
|
|
84
84
|
clearInFlightTools,
|
|
85
85
|
isToolInvocationError,
|
|
86
86
|
isQueuedUserMessageSkip,
|
|
87
|
+
isDeterministicPolicyError,
|
|
87
88
|
} from "./auto-tool-tracking.js";
|
|
88
89
|
import { closeoutUnit } from "./auto-unit-closeout.js";
|
|
89
90
|
import { recoverTimedOutUnit } from "./auto-timeout-recovery.js";
|
|
90
|
-
import { selectAndApplyModel, resolveModelId } from "./auto-model-selection.js";
|
|
91
|
+
import { selectAndApplyModel, resolveModelId, clearToolBaseline } from "./auto-model-selection.js";
|
|
91
92
|
import { resetRoutingHistory, recordOutcome } from "./routing-history.js";
|
|
92
93
|
import {
|
|
93
94
|
checkPostUnitHooks,
|
|
@@ -232,9 +233,7 @@ import { reorderForCaching } from "./prompt-ordering.js";
|
|
|
232
233
|
|
|
233
234
|
import {
|
|
234
235
|
AutoSession,
|
|
235
|
-
MAX_UNIT_DISPATCHES,
|
|
236
236
|
STUB_RECOVERY_THRESHOLD,
|
|
237
|
-
MAX_LIFETIME_DISPATCHES,
|
|
238
237
|
NEW_SESSION_TIMEOUT_MS,
|
|
239
238
|
} from "./auto/session.js";
|
|
240
239
|
import type {
|
|
@@ -243,9 +242,7 @@ import type {
|
|
|
243
242
|
StartModel,
|
|
244
243
|
} from "./auto/session.js";
|
|
245
244
|
export {
|
|
246
|
-
MAX_UNIT_DISPATCHES,
|
|
247
245
|
STUB_RECOVERY_THRESHOLD,
|
|
248
|
-
MAX_LIFETIME_DISPATCHES,
|
|
249
246
|
NEW_SESSION_TIMEOUT_MS,
|
|
250
247
|
} from "./auto/session.js";
|
|
251
248
|
export type {
|
|
@@ -337,6 +334,25 @@ function normalizeSessionFilePath(raw: unknown): string | null {
|
|
|
337
334
|
return candidate;
|
|
338
335
|
}
|
|
339
336
|
|
|
337
|
+
function synthesizePausedSessionRecovery(
|
|
338
|
+
basePath: string,
|
|
339
|
+
unitType: string,
|
|
340
|
+
unitId: string,
|
|
341
|
+
sessionFile: string,
|
|
342
|
+
): ReturnType<typeof synthesizeCrashRecovery> {
|
|
343
|
+
const activityDir = join(gsdRoot(basePath), "activity");
|
|
344
|
+
return synthesizeCrashRecovery(basePath, unitType, unitId, sessionFile, activityDir);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function _synthesizePausedSessionRecoveryForTest(
|
|
348
|
+
basePath: string,
|
|
349
|
+
unitType: string,
|
|
350
|
+
unitId: string,
|
|
351
|
+
sessionFile: string,
|
|
352
|
+
): ReturnType<typeof synthesizeCrashRecovery> {
|
|
353
|
+
return synthesizePausedSessionRecovery(basePath, unitType, unitId, sessionFile);
|
|
354
|
+
}
|
|
355
|
+
|
|
340
356
|
export function startAutoDetached(
|
|
341
357
|
ctx: ExtensionCommandContext,
|
|
342
358
|
pi: ExtensionAPI,
|
|
@@ -544,12 +560,14 @@ export function markToolEnd(toolCallId: string): void {
|
|
|
544
560
|
/**
|
|
545
561
|
* Record a tool invocation error on the current session (#2883).
|
|
546
562
|
* Called from tool_execution_end when a GSD tool fails with isError.
|
|
547
|
-
*
|
|
548
|
-
* (malformed/truncated JSON)
|
|
563
|
+
* Stores the error if it matches:
|
|
564
|
+
* - tool-invocation-error pattern (malformed/truncated JSON)
|
|
565
|
+
* - queued-user-message skip pattern
|
|
566
|
+
* - deterministic policy rejection (#4973, e.g. context_write_blocked)
|
|
549
567
|
*/
|
|
550
568
|
export function recordToolInvocationError(toolName: string, errorMsg: string): void {
|
|
551
569
|
if (!s.active) return;
|
|
552
|
-
if (isToolInvocationError(errorMsg) || isQueuedUserMessageSkip(errorMsg)) {
|
|
570
|
+
if (isToolInvocationError(errorMsg) || isQueuedUserMessageSkip(errorMsg) || isDeterministicPolicyError(errorMsg)) {
|
|
553
571
|
s.lastToolInvocationError = `${toolName}: ${errorMsg}`;
|
|
554
572
|
}
|
|
555
573
|
}
|
|
@@ -1088,6 +1106,12 @@ export async function stopAuto(
|
|
|
1088
1106
|
restoreProjectRootEnv();
|
|
1089
1107
|
restoreMilestoneLockEnv();
|
|
1090
1108
|
|
|
1109
|
+
// Drop the active-tool baseline so a subsequent /gsd auto run on the
|
|
1110
|
+
// same `pi` instance recaptures from the live tool set rather than
|
|
1111
|
+
// restoring this session's snapshot and silently undoing any tool
|
|
1112
|
+
// changes the user made between sessions (#4959 / CodeRabbit).
|
|
1113
|
+
if (pi) clearToolBaseline(pi);
|
|
1114
|
+
|
|
1091
1115
|
// Reset all session state in one call
|
|
1092
1116
|
s.reset();
|
|
1093
1117
|
}
|
|
@@ -1388,6 +1412,15 @@ export async function startAuto(
|
|
|
1388
1412
|
return;
|
|
1389
1413
|
}
|
|
1390
1414
|
|
|
1415
|
+
// On a *fresh* start, drop any stale active-tool baseline left by a prior
|
|
1416
|
+
// auto session that didn't run stopAuto cleanly. Skip on resume: pauseAuto
|
|
1417
|
+
// leaves the last provider-trimmed active tools in place, so clearing here
|
|
1418
|
+
// would let the next selectAndApplyModel recapture that already-narrowed
|
|
1419
|
+
// set as the new baseline — exactly the cross-unit poisoning this PR is
|
|
1420
|
+
// fixing (#4959 / CodeRabbit Major). The pre-pause baseline survives in
|
|
1421
|
+
// the WeakMap keyed by `pi`.
|
|
1422
|
+
if (!s.paused) clearToolBaseline(pi);
|
|
1423
|
+
|
|
1391
1424
|
const requestedStepMode = options?.step ?? false;
|
|
1392
1425
|
const interruptedAssessment = options?.interrupted ?? null;
|
|
1393
1426
|
if (options?.milestoneLock !== undefined) {
|
|
@@ -1556,16 +1589,6 @@ export async function startAuto(
|
|
|
1556
1589
|
return;
|
|
1557
1590
|
}
|
|
1558
1591
|
|
|
1559
|
-
// Lock acquired — now safe to delete the pause file
|
|
1560
|
-
if (s.pausedSessionFile) {
|
|
1561
|
-
try { unlinkSync(s.pausedSessionFile); } catch (err) {
|
|
1562
|
-
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1563
|
-
logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1564
|
-
}
|
|
1565
|
-
}
|
|
1566
|
-
s.pausedSessionFile = null;
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
1592
|
s.paused = false;
|
|
1570
1593
|
s.active = true;
|
|
1571
1594
|
s.verbose = verboseMode;
|
|
@@ -1663,13 +1686,11 @@ export async function startAuto(
|
|
|
1663
1686
|
invalidateAllCaches();
|
|
1664
1687
|
|
|
1665
1688
|
if (s.pausedSessionFile) {
|
|
1666
|
-
const
|
|
1667
|
-
const recovery = synthesizeCrashRecovery(
|
|
1689
|
+
const recovery = synthesizePausedSessionRecovery(
|
|
1668
1690
|
s.basePath,
|
|
1669
1691
|
s.currentUnit?.type ?? s.pausedUnitType ?? "unknown",
|
|
1670
1692
|
s.currentUnit?.id ?? s.pausedUnitId ?? "unknown",
|
|
1671
|
-
s.pausedSessionFile
|
|
1672
|
-
activityDir,
|
|
1693
|
+
s.pausedSessionFile,
|
|
1673
1694
|
);
|
|
1674
1695
|
if (recovery && recovery.trace.toolCallCount > 0) {
|
|
1675
1696
|
s.pendingCrashRecovery = recovery.prompt;
|
|
@@ -26,7 +26,15 @@ import { blockModel, isModelBlocked } from "../blocked-models.js";
|
|
|
26
26
|
|
|
27
27
|
const retryState = createRetryState();
|
|
28
28
|
const MAX_NETWORK_RETRIES = 2;
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Cap on auto-resume attempts for sustained transient-provider errors.
|
|
31
|
+
*
|
|
32
|
+
* Exported so tests assert against the shared constant instead of
|
|
33
|
+
* regex-scraping the source literal (see #4837). Raising this value to
|
|
34
|
+
* handle longer provider overloads should update the single constant; the
|
|
35
|
+
* test in provider-errors.test.ts consumes it directly.
|
|
36
|
+
*/
|
|
37
|
+
export const MAX_TRANSIENT_AUTO_RESUMES = 8;
|
|
30
38
|
|
|
31
39
|
/**
|
|
32
40
|
* Reset the module-level retry state so a resumed auto-session starts fresh.
|
|
@@ -491,6 +491,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
491
491
|
definitionOfDone: Type.Optional(Type.Array(Type.String(), { description: "Definition of done bullets" })),
|
|
492
492
|
requirementCoverage: Type.Optional(Type.String({ description: "Requirement coverage text" })),
|
|
493
493
|
boundaryMapMarkdown: Type.Optional(Type.String({ description: "Boundary map markdown block" })),
|
|
494
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
495
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
496
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'plan-phase complete')" })),
|
|
494
497
|
}),
|
|
495
498
|
execute: planMilestoneExecute,
|
|
496
499
|
};
|
|
@@ -537,6 +540,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
537
540
|
proofLevel: Type.Optional(Type.String({ description: "Slice proof level" })),
|
|
538
541
|
integrationClosure: Type.Optional(Type.String({ description: "Slice integration closure" })),
|
|
539
542
|
observabilityImpact: Type.Optional(Type.String({ description: "Slice observability impact" })),
|
|
543
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
544
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
545
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'plan-phase complete')" })),
|
|
540
546
|
}),
|
|
541
547
|
execute: planSliceExecute,
|
|
542
548
|
};
|
|
@@ -607,6 +613,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
607
613
|
inputs: Type.Array(Type.String(), { description: "Input files or references" }),
|
|
608
614
|
expectedOutput: Type.Array(Type.String(), { description: "Expected output files or artifacts" }),
|
|
609
615
|
observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
|
|
616
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
617
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
618
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'plan-phase complete')" })),
|
|
610
619
|
}),
|
|
611
620
|
execute: planTaskExecute,
|
|
612
621
|
};
|
|
@@ -674,6 +683,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
674
683
|
]),
|
|
675
684
|
{ description: "Array of verification evidence entries" },
|
|
676
685
|
)),
|
|
686
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
687
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
688
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'task verified after retry')" })),
|
|
677
689
|
}),
|
|
678
690
|
execute: taskCompleteExecute,
|
|
679
691
|
};
|
|
@@ -771,6 +783,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
771
783
|
]),
|
|
772
784
|
{ description: "Upstream slice dependencies consumed" },
|
|
773
785
|
)),
|
|
786
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
787
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
788
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'all tasks verified')" })),
|
|
774
789
|
}),
|
|
775
790
|
execute: sliceCompleteExecute,
|
|
776
791
|
};
|
|
@@ -905,6 +920,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
905
920
|
lessonsLearned: Type.Optional(Type.Array(Type.String(), { description: "Lessons learned during the milestone" })),
|
|
906
921
|
followUps: Type.Optional(Type.String({ description: "Follow-up items for future milestones" })),
|
|
907
922
|
deviations: Type.Optional(Type.String({ description: "Deviations from the original plan" })),
|
|
923
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
924
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
925
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'milestone validation passed')" })),
|
|
908
926
|
}),
|
|
909
927
|
execute: milestoneCompleteExecute,
|
|
910
928
|
};
|
|
@@ -989,6 +1007,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
989
1007
|
{ description: "Tasks to upsert (update existing or insert new)" },
|
|
990
1008
|
),
|
|
991
1009
|
removedTaskIds: Type.Array(Type.String(), { description: "Task IDs to remove from the slice" }),
|
|
1010
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
1011
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
1012
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'blocker discovered during execution')" })),
|
|
992
1013
|
}),
|
|
993
1014
|
execute: replanSliceExecute,
|
|
994
1015
|
};
|
|
@@ -1044,6 +1065,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1044
1065
|
),
|
|
1045
1066
|
removed: Type.Array(Type.String(), { description: "Slice IDs to remove" }),
|
|
1046
1067
|
}, { description: "Slice changes to apply" }),
|
|
1068
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
1069
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
1070
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'slice S01 completed, reassessing remaining roadmap')" })),
|
|
1047
1071
|
}),
|
|
1048
1072
|
execute: reassessRoadmapExecute,
|
|
1049
1073
|
};
|
|
@@ -1051,6 +1075,203 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1051
1075
|
pi.registerTool(reassessRoadmapTool);
|
|
1052
1076
|
registerAlias(pi, reassessRoadmapTool, "gsd_roadmap_reassess", "gsd_reassess_roadmap");
|
|
1053
1077
|
|
|
1078
|
+
// ─── gsd_task_reopen (gsd_reopen_task alias) ───────────────────────────
|
|
1079
|
+
// Single-writer v3, Stream 3: reversibility tools for closed units.
|
|
1080
|
+
|
|
1081
|
+
const reopenTaskExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1082
|
+
const dbAvailable = await ensureDbOpen();
|
|
1083
|
+
if (!dbAvailable) {
|
|
1084
|
+
return {
|
|
1085
|
+
content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot reopen task." }],
|
|
1086
|
+
details: { operation: "reopen_task", error: "db_unavailable" } as any,
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
try {
|
|
1090
|
+
const { handleReopenTask } = await import("../tools/reopen-task.js");
|
|
1091
|
+
const result = await handleReopenTask(params, process.cwd());
|
|
1092
|
+
if ("error" in result) {
|
|
1093
|
+
return {
|
|
1094
|
+
content: [{ type: "text" as const, text: `Error reopening task: ${result.error}` }],
|
|
1095
|
+
details: { operation: "reopen_task", error: result.error } as any,
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
return {
|
|
1099
|
+
content: [{ type: "text" as const, text: `Reopened task ${result.taskId} (${result.sliceId}/${result.milestoneId})` }],
|
|
1100
|
+
details: {
|
|
1101
|
+
operation: "reopen_task",
|
|
1102
|
+
milestoneId: result.milestoneId,
|
|
1103
|
+
sliceId: result.sliceId,
|
|
1104
|
+
taskId: result.taskId,
|
|
1105
|
+
} as any,
|
|
1106
|
+
};
|
|
1107
|
+
} catch (err) {
|
|
1108
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1109
|
+
logError("tool", `reopen_task tool failed: ${msg}`, { tool: "gsd_task_reopen", error: String(err) });
|
|
1110
|
+
return {
|
|
1111
|
+
content: [{ type: "text" as const, text: `Error reopening task: ${msg}` }],
|
|
1112
|
+
details: { operation: "reopen_task", error: msg } as any,
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
const reopenTaskTool = {
|
|
1118
|
+
name: "gsd_task_reopen",
|
|
1119
|
+
label: "Reopen Task",
|
|
1120
|
+
description:
|
|
1121
|
+
"Reset a completed task back to 'pending' so it can be re-done. Cleans up SUMMARY.md so the DB-filesystem reconciler does not auto-correct the task back to complete. " +
|
|
1122
|
+
"Both the parent slice and milestone must still be open — use gsd_slice_reopen first if the slice has been closed.",
|
|
1123
|
+
promptSnippet: "Reopen a completed GSD task (resets status to pending, removes SUMMARY.md)",
|
|
1124
|
+
promptGuidelines: [
|
|
1125
|
+
"Use gsd_task_reopen when a completed task needs to be re-done (e.g. verification missed a regression, requirements changed).",
|
|
1126
|
+
"Will fail if the parent slice or milestone is already closed — reopen those first.",
|
|
1127
|
+
"Will fail if the task is not currently 'complete' — there is nothing to reopen.",
|
|
1128
|
+
"Use the canonical name gsd_task_reopen; gsd_reopen_task is only an alias.",
|
|
1129
|
+
],
|
|
1130
|
+
parameters: Type.Object({
|
|
1131
|
+
milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
|
|
1132
|
+
sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
|
|
1133
|
+
taskId: Type.String({ description: "Task ID (e.g. T01)" }),
|
|
1134
|
+
reason: Type.Optional(Type.String({ description: "Why the task is being reopened (recorded in the audit trail)" })),
|
|
1135
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
1136
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
1137
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'regression discovered post-completion')" })),
|
|
1138
|
+
}),
|
|
1139
|
+
execute: reopenTaskExecute,
|
|
1140
|
+
};
|
|
1141
|
+
|
|
1142
|
+
pi.registerTool(reopenTaskTool);
|
|
1143
|
+
registerAlias(pi, reopenTaskTool, "gsd_reopen_task", "gsd_task_reopen");
|
|
1144
|
+
|
|
1145
|
+
// ─── gsd_slice_reopen (gsd_reopen_slice alias) ─────────────────────────
|
|
1146
|
+
|
|
1147
|
+
const reopenSliceExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1148
|
+
const dbAvailable = await ensureDbOpen();
|
|
1149
|
+
if (!dbAvailable) {
|
|
1150
|
+
return {
|
|
1151
|
+
content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot reopen slice." }],
|
|
1152
|
+
details: { operation: "reopen_slice", error: "db_unavailable" } as any,
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
try {
|
|
1156
|
+
const { handleReopenSlice } = await import("../tools/reopen-slice.js");
|
|
1157
|
+
const result = await handleReopenSlice(params, process.cwd());
|
|
1158
|
+
if ("error" in result) {
|
|
1159
|
+
return {
|
|
1160
|
+
content: [{ type: "text" as const, text: `Error reopening slice: ${result.error}` }],
|
|
1161
|
+
details: { operation: "reopen_slice", error: result.error } as any,
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
return {
|
|
1165
|
+
content: [{ type: "text" as const, text: `Reopened slice ${result.sliceId} (${result.milestoneId}); reset ${result.tasksReset} task(s) to pending.` }],
|
|
1166
|
+
details: {
|
|
1167
|
+
operation: "reopen_slice",
|
|
1168
|
+
milestoneId: result.milestoneId,
|
|
1169
|
+
sliceId: result.sliceId,
|
|
1170
|
+
tasksReset: result.tasksReset,
|
|
1171
|
+
} as any,
|
|
1172
|
+
};
|
|
1173
|
+
} catch (err) {
|
|
1174
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1175
|
+
logError("tool", `reopen_slice tool failed: ${msg}`, { tool: "gsd_slice_reopen", error: String(err) });
|
|
1176
|
+
return {
|
|
1177
|
+
content: [{ type: "text" as const, text: `Error reopening slice: ${msg}` }],
|
|
1178
|
+
details: { operation: "reopen_slice", error: msg } as any,
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
const reopenSliceTool = {
|
|
1184
|
+
name: "gsd_slice_reopen",
|
|
1185
|
+
label: "Reopen Slice",
|
|
1186
|
+
description:
|
|
1187
|
+
"Reset a completed slice back to 'in_progress' and reset ALL of its tasks back to 'pending'. Cleans up SUMMARY.md / UAT.md and per-task summaries. " +
|
|
1188
|
+
"Reopening a slice means re-doing the work — partial resets create ambiguous state, so all tasks are reset.",
|
|
1189
|
+
promptSnippet: "Reopen a completed GSD slice (resets all tasks to pending, removes summaries)",
|
|
1190
|
+
promptGuidelines: [
|
|
1191
|
+
"Use gsd_slice_reopen when a completed slice needs to be re-done (e.g. integration issue surfaced, requirements changed).",
|
|
1192
|
+
"All tasks within the slice are reset to 'pending' — there is no partial-reopen.",
|
|
1193
|
+
"Will fail if the parent milestone is already closed — reopen the milestone first.",
|
|
1194
|
+
"Will fail if the slice is not currently 'complete' — there is nothing to reopen.",
|
|
1195
|
+
"Use the canonical name gsd_slice_reopen; gsd_reopen_slice is only an alias.",
|
|
1196
|
+
],
|
|
1197
|
+
parameters: Type.Object({
|
|
1198
|
+
milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
|
|
1199
|
+
sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
|
|
1200
|
+
reason: Type.Optional(Type.String({ description: "Why the slice is being reopened (recorded in the audit trail)" })),
|
|
1201
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
1202
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
1203
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'cross-slice regression discovered')" })),
|
|
1204
|
+
}),
|
|
1205
|
+
execute: reopenSliceExecute,
|
|
1206
|
+
};
|
|
1207
|
+
|
|
1208
|
+
pi.registerTool(reopenSliceTool);
|
|
1209
|
+
registerAlias(pi, reopenSliceTool, "gsd_reopen_slice", "gsd_slice_reopen");
|
|
1210
|
+
|
|
1211
|
+
// ─── gsd_milestone_reopen (gsd_reopen_milestone alias) ─────────────────
|
|
1212
|
+
|
|
1213
|
+
const reopenMilestoneExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1214
|
+
const dbAvailable = await ensureDbOpen();
|
|
1215
|
+
if (!dbAvailable) {
|
|
1216
|
+
return {
|
|
1217
|
+
content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot reopen milestone." }],
|
|
1218
|
+
details: { operation: "reopen_milestone", error: "db_unavailable" } as any,
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
try {
|
|
1222
|
+
const { handleReopenMilestone } = await import("../tools/reopen-milestone.js");
|
|
1223
|
+
const result = await handleReopenMilestone(params, process.cwd());
|
|
1224
|
+
if ("error" in result) {
|
|
1225
|
+
return {
|
|
1226
|
+
content: [{ type: "text" as const, text: `Error reopening milestone: ${result.error}` }],
|
|
1227
|
+
details: { operation: "reopen_milestone", error: result.error } as any,
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1230
|
+
return {
|
|
1231
|
+
content: [{ type: "text" as const, text: `Reopened milestone ${result.milestoneId}; reset ${result.slicesReset} slice(s) and ${result.tasksReset} task(s).` }],
|
|
1232
|
+
details: {
|
|
1233
|
+
operation: "reopen_milestone",
|
|
1234
|
+
milestoneId: result.milestoneId,
|
|
1235
|
+
slicesReset: result.slicesReset,
|
|
1236
|
+
tasksReset: result.tasksReset,
|
|
1237
|
+
} as any,
|
|
1238
|
+
};
|
|
1239
|
+
} catch (err) {
|
|
1240
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1241
|
+
logError("tool", `reopen_milestone tool failed: ${msg}`, { tool: "gsd_milestone_reopen", error: String(err) });
|
|
1242
|
+
return {
|
|
1243
|
+
content: [{ type: "text" as const, text: `Error reopening milestone: ${msg}` }],
|
|
1244
|
+
details: { operation: "reopen_milestone", error: msg } as any,
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
};
|
|
1248
|
+
|
|
1249
|
+
const reopenMilestoneTool = {
|
|
1250
|
+
name: "gsd_milestone_reopen",
|
|
1251
|
+
label: "Reopen Milestone",
|
|
1252
|
+
description:
|
|
1253
|
+
"Reset a closed milestone back to 'active', all of its slices to 'in_progress', and all tasks to 'pending'. " +
|
|
1254
|
+
"Cleans up MILESTONE-SUMMARY.md, slice summaries, and task summaries so the DB-filesystem reconciler does not auto-correct status back to complete.",
|
|
1255
|
+
promptSnippet: "Reopen a closed GSD milestone (resets slices and tasks, removes summaries)",
|
|
1256
|
+
promptGuidelines: [
|
|
1257
|
+
"Use gsd_milestone_reopen when a closed milestone needs to be re-done (e.g. validation failure surfaced after closure).",
|
|
1258
|
+
"All slices reset to 'in_progress' and all tasks reset to 'pending' — no partial reopen.",
|
|
1259
|
+
"Will fail if the milestone is not currently closed — there is nothing to reopen.",
|
|
1260
|
+
"Use the canonical name gsd_milestone_reopen; gsd_reopen_milestone is only an alias.",
|
|
1261
|
+
],
|
|
1262
|
+
parameters: Type.Object({
|
|
1263
|
+
milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
|
|
1264
|
+
reason: Type.Optional(Type.String({ description: "Why the milestone is being reopened (recorded in the audit trail)" })),
|
|
1265
|
+
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
1266
|
+
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
1267
|
+
triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'post-closure validation failure')" })),
|
|
1268
|
+
}),
|
|
1269
|
+
execute: reopenMilestoneExecute,
|
|
1270
|
+
};
|
|
1271
|
+
|
|
1272
|
+
pi.registerTool(reopenMilestoneTool);
|
|
1273
|
+
registerAlias(pi, reopenMilestoneTool, "gsd_reopen_milestone", "gsd_milestone_reopen");
|
|
1274
|
+
|
|
1054
1275
|
// ─── gsd_save_gate_result ──────────────────────────────────────────────
|
|
1055
1276
|
|
|
1056
1277
|
const saveGateResultExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|