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,20 +1,89 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
import { ghIsAvailable, _resetGhCache } from "../cli.ts";
|
|
4
4
|
|
|
5
|
-
describe("cli", () => {
|
|
5
|
+
describe("github-sync/cli.ghIsAvailable", () => {
|
|
6
|
+
let originalPath: string | undefined;
|
|
7
|
+
|
|
6
8
|
beforeEach(() => {
|
|
7
9
|
_resetGhCache();
|
|
10
|
+
originalPath = process.env.PATH;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
if (originalPath !== undefined) {
|
|
15
|
+
process.env.PATH = originalPath;
|
|
16
|
+
} else {
|
|
17
|
+
delete process.env.PATH;
|
|
18
|
+
}
|
|
19
|
+
_resetGhCache();
|
|
8
20
|
});
|
|
9
21
|
|
|
10
|
-
it("
|
|
11
|
-
|
|
12
|
-
|
|
22
|
+
it("returns true when gh is on PATH, false otherwise", () => {
|
|
23
|
+
// Force gh to be unavailable by setting PATH to an empty-ish string
|
|
24
|
+
// that contains no gh. This is more robust than asserting a raw
|
|
25
|
+
// `typeof === 'boolean'` (which the previous test did — a tautology,
|
|
26
|
+
// since the function's TypeScript signature already guarantees it).
|
|
27
|
+
process.env.PATH = "/nonexistent-path-for-test";
|
|
28
|
+
assert.equal(
|
|
29
|
+
ghIsAvailable(),
|
|
30
|
+
false,
|
|
31
|
+
"with gh not on PATH, ghIsAvailable must return false",
|
|
32
|
+
);
|
|
13
33
|
});
|
|
14
34
|
|
|
15
|
-
it("
|
|
35
|
+
it("caches the availability result — PATH changes after first call are ignored", () => {
|
|
36
|
+
// With the original PATH, gh may or may not be present (depends on
|
|
37
|
+
// the dev machine / CI runner). Either way, capture the first
|
|
38
|
+
// result, then mutate PATH so a fresh subprocess spawn would yield
|
|
39
|
+
// a different result. If the function is genuinely caching, the
|
|
40
|
+
// second call returns the same value despite the PATH change.
|
|
41
|
+
|
|
42
|
+
// Prime the cache with whatever the current PATH says.
|
|
16
43
|
const first = ghIsAvailable();
|
|
44
|
+
|
|
45
|
+
// Change PATH so the `gh` binary is no longer findable — any
|
|
46
|
+
// subsequent subprocess spawn would yield false.
|
|
47
|
+
process.env.PATH = "/nonexistent-path-for-test";
|
|
48
|
+
|
|
17
49
|
const second = ghIsAvailable();
|
|
18
|
-
|
|
50
|
+
|
|
51
|
+
assert.equal(
|
|
52
|
+
second,
|
|
53
|
+
first,
|
|
54
|
+
"cached result must not change when PATH changes after the first call. " +
|
|
55
|
+
"Without caching, mutating PATH away from gh would flip the result.",
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("re-evaluates after _resetGhCache — cache is the thing being tested", () => {
|
|
60
|
+
// This locks in that `_resetGhCache` actually clears the cache:
|
|
61
|
+
// with it absent, the second assertion wouldn't observe the PATH change.
|
|
62
|
+
process.env.PATH = "/nonexistent-path-for-test";
|
|
63
|
+
const beforeReset = ghIsAvailable(); // false — gh not on PATH
|
|
64
|
+
assert.equal(beforeReset, false);
|
|
65
|
+
|
|
66
|
+
_resetGhCache();
|
|
67
|
+
// Restore PATH so that if a real gh is available, the cached
|
|
68
|
+
// "false" from before-reset must not persist.
|
|
69
|
+
if (originalPath !== undefined) {
|
|
70
|
+
process.env.PATH = originalPath;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// After reset, another call re-probes. We don't know whether the
|
|
74
|
+
// real machine has gh, but we know the re-probe happened because
|
|
75
|
+
// before-reset with an empty PATH was false AND if the machine
|
|
76
|
+
// has gh, the post-reset result would be true (i.e. different).
|
|
77
|
+
const afterReset = ghIsAvailable();
|
|
78
|
+
// Invariant: either the dev machine has gh (afterReset=true, differs
|
|
79
|
+
// from beforeReset) or it doesn't (afterReset=false, unchanged).
|
|
80
|
+
// Both are fine — what matters is that _resetGhCache cleared the
|
|
81
|
+
// memoized value so the re-probe ran. That's observable by the
|
|
82
|
+
// fact that with gh present, afterReset=true even though the
|
|
83
|
+
// cached pre-reset value was false.
|
|
84
|
+
assert.ok(
|
|
85
|
+
typeof afterReset === "boolean",
|
|
86
|
+
"re-probe must return a boolean",
|
|
87
|
+
);
|
|
19
88
|
});
|
|
20
89
|
});
|
|
@@ -105,9 +105,41 @@ describe("templates", () => {
|
|
|
105
105
|
assert.ok(comment.includes("duration:"));
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
-
it("handles empty data gracefully", () => {
|
|
108
|
+
it("handles empty data gracefully — no debug-artifact output", () => {
|
|
109
|
+
// Previous version only asserted `typeof === 'string'`, which the
|
|
110
|
+
// function signature already guarantees (tautology).
|
|
111
|
+
//
|
|
112
|
+
// The real invariant is: empty input must produce a string that
|
|
113
|
+
// is safe to post (or skip) without leaking a debug-stringified
|
|
114
|
+
// object. An empty string IS allowed here — callers are expected
|
|
115
|
+
// to gate on truthiness before posting ("skip if empty"). What
|
|
116
|
+
// must NOT happen is leaking 'undefined', '[object Object]',
|
|
117
|
+
// 'null', or a template-placeholder tell like '{{' / '}}'.
|
|
109
118
|
const comment = formatSummaryComment({});
|
|
110
119
|
assert.equal(typeof comment, "string");
|
|
120
|
+
assert.doesNotMatch(
|
|
121
|
+
comment,
|
|
122
|
+
/^undefined$|^\[object Object\]$|^null$/,
|
|
123
|
+
"empty-data comment must not be a debug-style stringified artifact",
|
|
124
|
+
);
|
|
125
|
+
assert.doesNotMatch(
|
|
126
|
+
comment,
|
|
127
|
+
/\{\{\s*\w+\s*\}\}/,
|
|
128
|
+
"empty-data comment must not leak unsubstituted {{placeholders}}",
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("empty input produces empty comment — callers gate on truthiness", () => {
|
|
133
|
+
// Sister to the previous test: this locks in the current behaviour
|
|
134
|
+
// that empty input returns empty string, so a regression that
|
|
135
|
+
// unexpectedly starts emitting a non-empty default (which would
|
|
136
|
+
// then post spam comments for every bare-data milestone) fails.
|
|
137
|
+
const comment = formatSummaryComment({});
|
|
138
|
+
assert.equal(
|
|
139
|
+
comment,
|
|
140
|
+
"",
|
|
141
|
+
"empty data must return exactly '' so callers can `if (comment)` gate",
|
|
142
|
+
);
|
|
111
143
|
});
|
|
112
144
|
});
|
|
113
145
|
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from "./phases.js";
|
|
30
30
|
import { debugLog } from "../debug-logger.js";
|
|
31
31
|
import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterMs, COOLDOWN_FALLBACK_WAIT_MS, MAX_COOLDOWN_RETRIES } from "./infra-errors.js";
|
|
32
|
+
import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
|
|
32
33
|
import { resolveEngine } from "../engine-resolver.js";
|
|
33
34
|
import { logWarning } from "../workflow-logger.js";
|
|
34
35
|
import { gsdRoot } from "../paths.js";
|
|
@@ -703,6 +704,52 @@ export async function autoLoop(
|
|
|
703
704
|
// runFinalize leave the journal incomplete, making diagnosis harder.
|
|
704
705
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration, error: msg } });
|
|
705
706
|
|
|
707
|
+
// ── Pre-send model-policy block: not a retryable error (#4959 / #4850) ──
|
|
708
|
+
// The model-policy gate runs before the prompt is sent. When every
|
|
709
|
+
// candidate model is denied (cross-provider disabled + flat-rate
|
|
710
|
+
// baseline + tool-policy denial), retrying the same unit produces the
|
|
711
|
+
// same denial — burning the consecutive-error budget toward a 3-strike
|
|
712
|
+
// hard stop and corrupting auto-mode state. Pause for user attention
|
|
713
|
+
// instead, with the per-model deny reasons surfaced from the typed
|
|
714
|
+
// error.
|
|
715
|
+
if (loopErr instanceof ModelPolicyDispatchBlockedError) {
|
|
716
|
+
debugLog("autoLoop", {
|
|
717
|
+
phase: "model-policy-blocked",
|
|
718
|
+
iteration,
|
|
719
|
+
unitType: loopErr.unitType,
|
|
720
|
+
unitId: loopErr.unitId,
|
|
721
|
+
reasons: loopErr.reasons,
|
|
722
|
+
});
|
|
723
|
+
ctx.ui.notify(
|
|
724
|
+
`Auto-mode paused: model-policy denied dispatch for ${loopErr.unitType}/${loopErr.unitId}. ${msg}`,
|
|
725
|
+
"error",
|
|
726
|
+
);
|
|
727
|
+
deps.emitJournalEvent({
|
|
728
|
+
ts: new Date().toISOString(),
|
|
729
|
+
flowId,
|
|
730
|
+
seq: nextSeq(),
|
|
731
|
+
eventType: "unit-end",
|
|
732
|
+
data: {
|
|
733
|
+
unitType: loopErr.unitType,
|
|
734
|
+
unitId: loopErr.unitId,
|
|
735
|
+
status: "blocked",
|
|
736
|
+
reason: "model-policy-dispatch-blocked",
|
|
737
|
+
reasons: loopErr.reasons,
|
|
738
|
+
},
|
|
739
|
+
});
|
|
740
|
+
// Carry the blocked unit identity into the turn-result observer:
|
|
741
|
+
// the throw originated inside dispatch, so observedUnitType/Id were
|
|
742
|
+
// not assigned by the success path at lines 453/631/647 — but the
|
|
743
|
+
// typed error already names the unit (#4959 / CodeRabbit).
|
|
744
|
+
observedUnitType = loopErr.unitType;
|
|
745
|
+
observedUnitId = loopErr.unitId;
|
|
746
|
+
await deps.pauseAuto(ctx, pi);
|
|
747
|
+
finishTurn("paused", "manual-attention", msg);
|
|
748
|
+
// Do NOT increment consecutiveErrors — the failure is configuration,
|
|
749
|
+
// not a transient runtime fault.
|
|
750
|
+
break;
|
|
751
|
+
}
|
|
752
|
+
|
|
706
753
|
// ── Infrastructure errors: immediate stop, no retry ──
|
|
707
754
|
// These are unrecoverable (disk full, OOM, etc.). Retrying just burns
|
|
708
755
|
// LLM budget on guaranteed failures.
|
|
@@ -26,12 +26,12 @@ import {
|
|
|
26
26
|
import { detectStuck } from "./detect-stuck.js";
|
|
27
27
|
import { runUnit } from "./run-unit.js";
|
|
28
28
|
import { debugLog } from "../debug-logger.js";
|
|
29
|
-
import { PROJECT_FILES } from "../detection.js";
|
|
29
|
+
import { PROJECT_FILES, hasProjectFileInAncestor } from "../detection.js";
|
|
30
30
|
import { MergeConflictError } from "../git-service.js";
|
|
31
31
|
import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
|
|
32
32
|
import { pauseAutoForProviderError } from "../provider-error-pause.js";
|
|
33
33
|
import { resumeAutoAfterProviderDelay } from "../bootstrap/provider-error-resume.js";
|
|
34
|
-
import { join, basename
|
|
34
|
+
import { join, basename } from "node:path";
|
|
35
35
|
import { existsSync, cpSync, readdirSync } from "node:fs";
|
|
36
36
|
import {
|
|
37
37
|
logWarning,
|
|
@@ -201,6 +201,7 @@ async function closeoutAndStop(
|
|
|
201
201
|
s.currentUnit.startedAt,
|
|
202
202
|
deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id),
|
|
203
203
|
);
|
|
204
|
+
s.currentUnit = null;
|
|
204
205
|
}
|
|
205
206
|
await deps.stopAuto(ctx, pi, reason);
|
|
206
207
|
}
|
|
@@ -961,10 +962,14 @@ export async function runDispatch(
|
|
|
961
962
|
// ── Sliding-window stuck detection with graduated recovery ──
|
|
962
963
|
const derivedKey = `${unitType}/${unitId}`;
|
|
963
964
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
965
|
+
// Always record this dispatch in the sliding window so detectStuck() has
|
|
966
|
+
// accurate history. Skipping the push when pendingVerificationRetry is set
|
|
967
|
+
// caused infinite artifact-retry loops to be invisible to stuck detection
|
|
968
|
+
// (#2007). Only the *response* to a stuck signal is suppressed during retries.
|
|
969
|
+
loopState.recentUnits.push({ key: derivedKey });
|
|
970
|
+
if (loopState.recentUnits.length > STUCK_WINDOW_SIZE) loopState.recentUnits.shift();
|
|
967
971
|
|
|
972
|
+
if (!s.pendingVerificationRetry) {
|
|
968
973
|
const stuckSignal = detectStuck(loopState.recentUnits);
|
|
969
974
|
if (stuckSignal) {
|
|
970
975
|
debugLog("autoLoop", {
|
|
@@ -1378,21 +1383,10 @@ export async function runUnitPhase(
|
|
|
1378
1383
|
// Monorepo support (#2347): if no project files in the worktree directory,
|
|
1379
1384
|
// walk parent directories up to the filesystem root. In monorepos,
|
|
1380
1385
|
// package.json / Cargo.toml etc. live in a parent directory.
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
while (checkDir !== root) {
|
|
1386
|
-
// Stop at git repository boundary — ancestors above the repo root
|
|
1387
|
-
// (e.g. ~ or /usr/local) may contain unrelated project files.
|
|
1388
|
-
if (deps.existsSync(join(checkDir, ".git"))) break;
|
|
1389
|
-
if (PROJECT_FILES.some((f) => deps.existsSync(join(checkDir, f)))) {
|
|
1390
|
-
hasProjectFileInParent = true;
|
|
1391
|
-
break;
|
|
1392
|
-
}
|
|
1393
|
-
checkDir = dirname(checkDir);
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1386
|
+
const hasProjectFileInParent =
|
|
1387
|
+
!hasProjectFile && !hasSrcDir && !hasXcodeBundle
|
|
1388
|
+
? hasProjectFileInAncestor(s.basePath, deps.existsSync)
|
|
1389
|
+
: false;
|
|
1396
1390
|
if (!hasProjectFile && !hasSrcDir && !hasXcodeBundle && !hasProjectFileInParent) {
|
|
1397
1391
|
// Greenfield projects won't have project files yet — the first task creates them.
|
|
1398
1392
|
// Log a warning but allow execution to proceed. The .git check above is sufficient
|
|
@@ -2112,6 +2106,8 @@ export async function runFinalize(
|
|
|
2112
2106
|
|
|
2113
2107
|
// Both pre and post verification completed without timeout — reset counter
|
|
2114
2108
|
loopState.consecutiveFinalizeTimeouts = 0;
|
|
2109
|
+
s.currentUnit = null;
|
|
2110
|
+
clearCurrentPhase();
|
|
2115
2111
|
|
|
2116
2112
|
// Surface accumulated workflow-logger issues for this unit to the user.
|
|
2117
2113
|
// Warnings/errors logged during the unit are buffered in the logger and
|
|
@@ -75,9 +75,7 @@ export interface PreExecFailure {
|
|
|
75
75
|
|
|
76
76
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
77
77
|
|
|
78
|
-
export const MAX_UNIT_DISPATCHES = 3;
|
|
79
78
|
export const STUB_RECOVERY_THRESHOLD = 2;
|
|
80
|
-
export const MAX_LIFETIME_DISPATCHES = 6;
|
|
81
79
|
export const NEW_SESSION_TIMEOUT_MS = 120_000;
|
|
82
80
|
|
|
83
81
|
// ─── AutoSession ─────────────────────────────────────────────────────────────
|
|
@@ -59,7 +59,10 @@ import {
|
|
|
59
59
|
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
60
60
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
61
61
|
import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
|
|
62
|
+
import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
|
|
62
63
|
import { EXECUTION_ENTRY_PHASES, hasFinalizedMilestoneContext } from "./uok/plan-v2.js";
|
|
64
|
+
import { isAutoActive } from "./auto.js";
|
|
65
|
+
import { markDepthVerified } from "./bootstrap/write-gate.js";
|
|
63
66
|
|
|
64
67
|
// ─── Types ────────────────────────────────────────────────────────────────
|
|
65
68
|
|
|
@@ -90,6 +93,18 @@ export interface DispatchContext {
|
|
|
90
93
|
modelRegistry?: MinimalModelRegistry;
|
|
91
94
|
}
|
|
92
95
|
|
|
96
|
+
type ReassessmentChecker = typeof checkNeedsReassessment;
|
|
97
|
+
|
|
98
|
+
let reassessmentChecker: ReassessmentChecker = checkNeedsReassessment;
|
|
99
|
+
|
|
100
|
+
export function setReassessmentCheckerForTest(checker: ReassessmentChecker): () => void {
|
|
101
|
+
const previous = reassessmentChecker;
|
|
102
|
+
reassessmentChecker = checker;
|
|
103
|
+
return () => {
|
|
104
|
+
reassessmentChecker = previous;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
93
108
|
export interface DispatchRule {
|
|
94
109
|
/** Human-readable name for debugging and test identification */
|
|
95
110
|
name: string;
|
|
@@ -97,6 +112,38 @@ export interface DispatchRule {
|
|
|
97
112
|
match: (ctx: DispatchContext) => Promise<DispatchAction | null>;
|
|
98
113
|
}
|
|
99
114
|
|
|
115
|
+
async function readUatGateVerdict(
|
|
116
|
+
basePath: string,
|
|
117
|
+
mid: string,
|
|
118
|
+
sliceId: string,
|
|
119
|
+
): Promise<{ verdict: string; uatType: UatType | undefined } | null> {
|
|
120
|
+
const uatFile = resolveSliceFile(basePath, mid, sliceId, "UAT");
|
|
121
|
+
const assessmentFile = resolveSliceFile(basePath, mid, sliceId, "ASSESSMENT");
|
|
122
|
+
|
|
123
|
+
const uatContent = uatFile ? await loadFile(uatFile) : null;
|
|
124
|
+
const uatType = uatContent ? extractUatType(uatContent) : undefined;
|
|
125
|
+
|
|
126
|
+
const assessmentContent = assessmentFile ? await loadFile(assessmentFile) : null;
|
|
127
|
+
if (assessmentContent) {
|
|
128
|
+
const assessmentVerdict = extractVerdict(assessmentContent);
|
|
129
|
+
if (assessmentVerdict) {
|
|
130
|
+
return {
|
|
131
|
+
verdict: assessmentVerdict,
|
|
132
|
+
uatType: uatType ?? extractUatType(assessmentContent),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (uatContent) {
|
|
138
|
+
const legacyUatVerdict = extractVerdict(uatContent);
|
|
139
|
+
if (legacyUatVerdict) {
|
|
140
|
+
return { verdict: legacyUatVerdict, uatType };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
100
147
|
function missingSliceStop(mid: string, phase: string): DispatchAction {
|
|
101
148
|
return {
|
|
102
149
|
action: "stop",
|
|
@@ -263,6 +310,16 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
263
310
|
// Align with the plan-v2 gate's lookup semantics: whitespace-only counts
|
|
264
311
|
// as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
|
|
265
312
|
if (hasFinalizedMilestoneContext(basePath, mid)) return null;
|
|
313
|
+
// H6 fix (#4973): In auto-mode there is no human to answer the
|
|
314
|
+
// depth-verification ask_user_questions, so the write-gate deadlocks.
|
|
315
|
+
// Pre-mark the milestone as depth-verified so gsd_summary_save({artifact_type:"CONTEXT"})
|
|
316
|
+
// is not blocked. Safe ordering: session_switch fires clearDiscussionFlowState()
|
|
317
|
+
// (register-hooks.ts:106) before before_agent_start, which fires before resolveDispatch
|
|
318
|
+
// reaches this match fn — so this call always happens after any session-switch reset.
|
|
319
|
+
// Interactive sessions (isAutoActive()===false) are unaffected.
|
|
320
|
+
if (isAutoActive()) {
|
|
321
|
+
markDepthVerified(mid, basePath);
|
|
322
|
+
}
|
|
266
323
|
return {
|
|
267
324
|
action: "dispatch",
|
|
268
325
|
unitType: "discuss-milestone",
|
|
@@ -336,27 +393,28 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
336
393
|
// Only applies when UAT dispatch is enabled
|
|
337
394
|
if (!prefs?.uat_dispatch) return null;
|
|
338
395
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
// DB-first: get completed slices from DB
|
|
342
|
-
let completedSliceIds: string[];
|
|
396
|
+
// DB-first: prefer closed slices from DB; fall back to ROADMAP on disk.
|
|
397
|
+
let closedSliceIds: string[];
|
|
343
398
|
if (isDbAvailable()) {
|
|
344
|
-
|
|
345
|
-
.filter(s => s.status
|
|
399
|
+
closedSliceIds = getMilestoneSlices(mid)
|
|
400
|
+
.filter(s => isClosedStatus(s.status))
|
|
346
401
|
.map(s => s.id);
|
|
347
402
|
} else {
|
|
348
|
-
|
|
403
|
+
// Filesystem fallback for degraded / unmigrated projects.
|
|
404
|
+
// `slice.done` in the parsed ROADMAP is the disk-level closed signal.
|
|
405
|
+
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
406
|
+
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
407
|
+
if (!roadmapContent) return null;
|
|
408
|
+
const roadmap = parseRoadmap(roadmapContent);
|
|
409
|
+
closedSliceIds = roadmap.slices.filter(s => s.done).map(s => s.id);
|
|
349
410
|
}
|
|
350
411
|
|
|
351
|
-
for (const sliceId of
|
|
352
|
-
const
|
|
353
|
-
if (!
|
|
354
|
-
const
|
|
355
|
-
if (!content) continue;
|
|
356
|
-
const verdict = extractVerdict(content);
|
|
357
|
-
const uatType = extractUatType(content);
|
|
412
|
+
for (const sliceId of closedSliceIds) {
|
|
413
|
+
const result = await readUatGateVerdict(basePath, mid, sliceId);
|
|
414
|
+
if (!result) continue;
|
|
415
|
+
const { verdict, uatType } = result;
|
|
358
416
|
|
|
359
|
-
if (
|
|
417
|
+
if (!isAcceptableUatVerdict(verdict, uatType)) {
|
|
360
418
|
return {
|
|
361
419
|
action: "stop" as const,
|
|
362
420
|
reason: `UAT verdict for ${sliceId} is "${verdict}" — blocking progression until resolved.\nReview the UAT result and update the verdict to PASS, or re-run /gsd auto after fixing.`,
|
|
@@ -371,11 +429,15 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
371
429
|
name: "reassess-roadmap (post-completion)",
|
|
372
430
|
match: async ({ state, mid, midTitle, basePath, prefs }) => {
|
|
373
431
|
if (prefs?.phases?.skip_reassess) return null;
|
|
374
|
-
// Default reassess_after_slice to
|
|
375
|
-
// is
|
|
376
|
-
|
|
432
|
+
// Default reassess_after_slice to false per ADR-003 §4 — most reassess
|
|
433
|
+
// units conclude "roadmap is fine" and burn a session for no change.
|
|
434
|
+
// The plan-slice prompt now carries a reassessment preamble so the
|
|
435
|
+
// next slice's planner does JIT roadmap verification at zero extra
|
|
436
|
+
// cost. Opt-in via explicit `reassess_after_slice: true` (e.g.
|
|
437
|
+
// burn-max profile) when you want the dedicated reassess session.
|
|
438
|
+
const reassessEnabled = prefs?.phases?.reassess_after_slice ?? false;
|
|
377
439
|
if (!reassessEnabled) return null;
|
|
378
|
-
const needsReassess = await
|
|
440
|
+
const needsReassess = await reassessmentChecker(basePath, mid, state);
|
|
379
441
|
if (!needsReassess) return null;
|
|
380
442
|
return {
|
|
381
443
|
action: "dispatch",
|
|
@@ -394,6 +456,12 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
394
456
|
name: "needs-discussion → discuss-milestone",
|
|
395
457
|
match: async ({ state, mid, midTitle, basePath, structuredQuestionsAvailable }) => {
|
|
396
458
|
if (state.phase !== "needs-discussion") return null;
|
|
459
|
+
// H6 fix (#4973): auto-mark depth-verified so the write-gate does not
|
|
460
|
+
// deadlock in non-interactive (auto-mode) runs. See ordering note at
|
|
461
|
+
// "execution-entry phase (no context) → discuss-milestone" above.
|
|
462
|
+
if (isAutoActive()) {
|
|
463
|
+
markDepthVerified(mid, basePath);
|
|
464
|
+
}
|
|
397
465
|
return {
|
|
398
466
|
action: "dispatch",
|
|
399
467
|
unitType: "discuss-milestone",
|
|
@@ -414,6 +482,12 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
414
482
|
const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT");
|
|
415
483
|
const hasContext = !!(contextFile && (await loadFile(contextFile)));
|
|
416
484
|
if (hasContext) return null; // fall through to next rule
|
|
485
|
+
// H6 fix (#4973): auto-mark depth-verified so the write-gate does not
|
|
486
|
+
// deadlock in non-interactive (auto-mode) runs. See ordering note at
|
|
487
|
+
// "execution-entry phase (no context) → discuss-milestone" above.
|
|
488
|
+
if (isAutoActive()) {
|
|
489
|
+
markDepthVerified(mid, basePath);
|
|
490
|
+
}
|
|
417
491
|
return {
|
|
418
492
|
action: "dispatch",
|
|
419
493
|
unitType: "discuss-milestone",
|
|
@@ -482,6 +556,11 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
482
556
|
match: async ({ state, mid, midTitle, basePath, prefs }) => {
|
|
483
557
|
if (state.phase !== "planning") return null;
|
|
484
558
|
if (prefs?.phases?.skip_research || prefs?.phases?.skip_slice_research) return null;
|
|
559
|
+
// #4781 phase 2: trivial-scope milestones skip dedicated slice research.
|
|
560
|
+
// plan-slice absorbs the lightweight discovery a trivial deliverable
|
|
561
|
+
// needs. Null result (DB unavailable / unknown) falls through to today's
|
|
562
|
+
// behavior.
|
|
563
|
+
if (await getMilestonePipelineVariant(mid) === "trivial") return null;
|
|
485
564
|
|
|
486
565
|
// Load roadmap to find all slices
|
|
487
566
|
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
@@ -538,6 +617,8 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
538
617
|
// Phase skip: skip research when preference or profile says so
|
|
539
618
|
if (prefs?.phases?.skip_research || prefs?.phases?.skip_slice_research)
|
|
540
619
|
return null;
|
|
620
|
+
// #4781 phase 2: trivial-scope milestones skip dedicated slice research.
|
|
621
|
+
if (await getMilestonePipelineVariant(mid) === "trivial") return null;
|
|
541
622
|
if (!state.activeSlice) return missingSliceStop(mid, state.phase);
|
|
542
623
|
const sid = state.activeSlice!.id;
|
|
543
624
|
const sTitle = state.activeSlice!.title;
|
|
@@ -890,8 +971,13 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
890
971
|
};
|
|
891
972
|
}
|
|
892
973
|
|
|
893
|
-
//
|
|
894
|
-
|
|
974
|
+
// #4781 phase 2: trivial-scope milestones skip the dedicated validate
|
|
975
|
+
// unit — complete-milestone's own verification steps (3/4/5 in the
|
|
976
|
+
// closer prompt) are sufficient proof for contained deliverables.
|
|
977
|
+
const trivialVariant = await getMilestonePipelineVariant(mid) === "trivial";
|
|
978
|
+
|
|
979
|
+
// Skip preference OR trivial scope: write a minimal pass-through VALIDATION file.
|
|
980
|
+
if (prefs?.phases?.skip_milestone_validation || trivialVariant) {
|
|
895
981
|
const mDir = resolveMilestonePath(basePath, mid);
|
|
896
982
|
if (mDir) {
|
|
897
983
|
if (!existsSync(mDir)) mkdirSync(mDir, { recursive: true });
|
|
@@ -899,15 +985,18 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
899
985
|
mDir,
|
|
900
986
|
buildMilestoneFileName(mid, "VALIDATION"),
|
|
901
987
|
);
|
|
988
|
+
const skipSource = trivialVariant
|
|
989
|
+
? "trivial-scope pipeline variant (#4781)"
|
|
990
|
+
: "`skip_milestone_validation` preference";
|
|
902
991
|
const content = [
|
|
903
992
|
"---",
|
|
904
993
|
"verdict: pass",
|
|
905
994
|
"remediation_round: 0",
|
|
906
995
|
"---",
|
|
907
996
|
"",
|
|
908
|
-
"# Milestone Validation (skipped
|
|
997
|
+
"# Milestone Validation (skipped)",
|
|
909
998
|
"",
|
|
910
|
-
|
|
999
|
+
`Milestone validation was skipped via ${skipSource}.`,
|
|
911
1000
|
].join("\n");
|
|
912
1001
|
writeFileSync(validationPath, content, "utf-8");
|
|
913
1002
|
}
|
|
@@ -978,7 +1067,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
978
1067
|
// Safety guard (#1703): verify the milestone produced implementation
|
|
979
1068
|
// artifacts (non-.gsd/ files). A milestone with only plan files and
|
|
980
1069
|
// zero implementation code should not be marked complete.
|
|
981
|
-
const artifactCheck = hasImplementationArtifacts(basePath);
|
|
1070
|
+
const artifactCheck = hasImplementationArtifacts(basePath, mid);
|
|
982
1071
|
if (artifactCheck === "absent") {
|
|
983
1072
|
return {
|
|
984
1073
|
action: "stop",
|