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
|
@@ -19,6 +19,38 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
19
19
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
20
20
|
import { applyModelPolicyFilter } from "./uok/model-policy.js";
|
|
21
21
|
import { isModelBlocked } from "./blocked-models.js";
|
|
22
|
+
import { getRequiredWorkflowToolsForAutoUnit } from "./workflow-mcp.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Thrown when the model-policy gate rejects every candidate model for a unit
|
|
26
|
+
* dispatch (#4959 / #4681 / #4850). The auto-loop catches this specifically
|
|
27
|
+
* to classify the unit as `blocked` rather than counting it as a retryable
|
|
28
|
+
* iteration error — pre-send policy denial is a configuration problem, not a
|
|
29
|
+
* transient runtime failure, so retrying just burns the consecutive-error
|
|
30
|
+
* budget toward a hard stop.
|
|
31
|
+
*/
|
|
32
|
+
export class ModelPolicyDispatchBlockedError extends Error {
|
|
33
|
+
readonly unitType: string;
|
|
34
|
+
readonly unitId: string;
|
|
35
|
+
readonly reasons: ReadonlyArray<{ provider: string; modelId: string; reason: string }>;
|
|
36
|
+
constructor(
|
|
37
|
+
unitType: string,
|
|
38
|
+
unitId: string,
|
|
39
|
+
reasons: ReadonlyArray<{ provider: string; modelId: string; reason: string }>,
|
|
40
|
+
) {
|
|
41
|
+
const summary = reasons.length === 0
|
|
42
|
+
? "no candidate models"
|
|
43
|
+
: reasons
|
|
44
|
+
.slice(0, 4)
|
|
45
|
+
.map((r) => `${r.provider}/${r.modelId} (${r.reason})`)
|
|
46
|
+
.join("; ");
|
|
47
|
+
super(`Model policy denied dispatch for ${unitType}/${unitId} before prompt send. Rejected: ${summary}`);
|
|
48
|
+
this.name = "ModelPolicyDispatchBlockedError";
|
|
49
|
+
this.unitType = unitType;
|
|
50
|
+
this.unitId = unitId;
|
|
51
|
+
this.reasons = reasons;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
22
54
|
|
|
23
55
|
export interface ModelSelectionResult {
|
|
24
56
|
/** Routing metadata for metrics recording */
|
|
@@ -33,6 +65,51 @@ export interface PreferredModelConfig {
|
|
|
33
65
|
source: "explicit" | "synthesized";
|
|
34
66
|
}
|
|
35
67
|
|
|
68
|
+
// Baseline active-tool set per-`pi` instance, captured the first time
|
|
69
|
+
// `selectAndApplyModel` runs against that instance during an auto session
|
|
70
|
+
// and re-applied before each subsequent dispatch. WeakMap so that test
|
|
71
|
+
// fakes / disposed sessions are garbage-collected normally. See
|
|
72
|
+
// #4959 / #4681 cross-unit poisoning notes at the call site below.
|
|
73
|
+
//
|
|
74
|
+
// LIFECYCLE: the baseline is tied to a single auto session, NOT to the
|
|
75
|
+
// lifetime of the `pi` instance (which can outlive many auto runs and have
|
|
76
|
+
// the user mutate tools between them). `clearToolBaseline` MUST be called
|
|
77
|
+
// at auto start AND auto stop so that a second `/gsd auto` run on the same
|
|
78
|
+
// `pi` does not silently restore a stale snapshot from the prior run and
|
|
79
|
+
// undo any tool changes the user made between sessions.
|
|
80
|
+
const TOOL_BASELINE = new WeakMap<object, string[]>();
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Drop the captured tool baseline for `pi` so the next `selectAndApplyModel`
|
|
84
|
+
* call re-captures from the live active set. Wired into `startAuto` and
|
|
85
|
+
* `stopAuto` in `auto.ts` to bound the baseline to a single auto session.
|
|
86
|
+
*
|
|
87
|
+
* Safe to call when no baseline is recorded (no-op).
|
|
88
|
+
*/
|
|
89
|
+
export function clearToolBaseline(pi: ExtensionAPI | object): void {
|
|
90
|
+
TOOL_BASELINE.delete(pi as unknown as object);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function restoreToolBaseline(pi: ExtensionAPI): void {
|
|
94
|
+
const key = pi as unknown as object;
|
|
95
|
+
const baseline = TOOL_BASELINE.get(key);
|
|
96
|
+
if (baseline === undefined) {
|
|
97
|
+
// First call: capture the canonical pre-dispatch tool set. At auto-mode
|
|
98
|
+
// start the active set has not yet been narrowed for any provider.
|
|
99
|
+
// Guarded against test fakes that omit getActiveTools — record an empty
|
|
100
|
+
// baseline so subsequent calls don't keep re-probing.
|
|
101
|
+
const initial = typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [];
|
|
102
|
+
TOOL_BASELINE.set(key, [...initial]);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Restore baseline before the next unit reads getActiveTools / applies
|
|
106
|
+
// post-selection adjustToolSet. Older fakes that omit setActiveTools are
|
|
107
|
+
// tolerated — the test asserts call order on real fakes.
|
|
108
|
+
if (typeof pi.setActiveTools === "function") {
|
|
109
|
+
pi.setActiveTools([...baseline]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
36
113
|
function reapplyThinkingLevel(
|
|
37
114
|
pi: ExtensionAPI,
|
|
38
115
|
level: ReturnType<ExtensionAPI["getThinkingLevel"]> | null | undefined,
|
|
@@ -129,6 +206,29 @@ export async function selectAndApplyModel(
|
|
|
129
206
|
let routing: { tier: string; modelDowngraded: boolean } | null = null;
|
|
130
207
|
let appliedModel: Model<Api> | null = null;
|
|
131
208
|
|
|
209
|
+
// ── Restore active-tool baseline before policy evaluation (#4959, #4681, #4850) ──
|
|
210
|
+
// Per-unit narrowing at the bottom of this function (line ~417) calls
|
|
211
|
+
// `pi.setActiveTools(finalToolNames)` and monotonically narrows the active
|
|
212
|
+
// set across units. Without restoration, a previously-dispatched unit on a
|
|
213
|
+
// narrow-API provider (e.g. openai-completions) leaves the active set
|
|
214
|
+
// missing tools that the next unit's selected model fully supports, but
|
|
215
|
+
// `pi.getActiveTools()` snapshot-as-hard-gate (the old behaviour) blocked
|
|
216
|
+
// dispatch with "tool policy denied" anyway.
|
|
217
|
+
//
|
|
218
|
+
// The baseline is captured once per `pi` instance via a WeakMap and
|
|
219
|
+
// re-applied here so each unit starts from a clean slate. Soft adaptation
|
|
220
|
+
// (adjustToolSet at the bottom of this function) still trims for the
|
|
221
|
+
// selected model.
|
|
222
|
+
//
|
|
223
|
+
// Auto-mode only (#4965): `guided-flow.ts:dispatchWorkflow` also calls
|
|
224
|
+
// `selectAndApplyModel` with `isAutoMode=false`. Guided-flow has its own
|
|
225
|
+
// narrow/restore via discuss-tool-scoping (guided-flow.ts:587-622) and no
|
|
226
|
+
// baseline-clear hook of its own, so an unconditional restore here would
|
|
227
|
+
// resurrect an auto-era baseline on guided-flow dispatches — silently
|
|
228
|
+
// overwriting any tool changes made interactively between auto sessions.
|
|
229
|
+
// The baseline is structurally an auto-mode concept; gate it accordingly.
|
|
230
|
+
if (isAutoMode) restoreToolBaseline(pi);
|
|
231
|
+
|
|
132
232
|
if (modelConfig) {
|
|
133
233
|
const availableModels = ctx.modelRegistry.getAvailable();
|
|
134
234
|
const modelPolicyTraceId = `model:${ctx.sessionManager.getSessionId()}:${Date.now()}`;
|
|
@@ -160,7 +260,16 @@ export async function selectAndApplyModel(
|
|
|
160
260
|
? extractTaskMetadata(unitId, basePath)
|
|
161
261
|
: undefined;
|
|
162
262
|
|
|
263
|
+
let policyDenyReasons: Array<{ provider: string; modelId: string; reason: string }> = [];
|
|
163
264
|
if (uokFlags.modelPolicy) {
|
|
265
|
+
// Use the workflow-spec required-tool subset for the unit type rather
|
|
266
|
+
// than the live `pi.getActiveTools()` snapshot (#4959). The active set
|
|
267
|
+
// is poisoned by per-unit narrowing for narrow-API providers — using it
|
|
268
|
+
// as a hard gate promotes soft adaptation (adjustToolSet at line ~417)
|
|
269
|
+
// into a layering violation that throws before dispatch. The smaller
|
|
270
|
+
// workflow-required subset reflects what the unit actually needs; soft
|
|
271
|
+
// adaptation post-selection still trims provider-incompatible tools.
|
|
272
|
+
const requiredTools = getRequiredWorkflowToolsForAutoUnit(unitType);
|
|
164
273
|
const policy = applyModelPolicyFilter(
|
|
165
274
|
availableModels,
|
|
166
275
|
{
|
|
@@ -171,15 +280,18 @@ export async function selectAndApplyModel(
|
|
|
171
280
|
taskMetadata: taskMetadataForPolicy,
|
|
172
281
|
currentProvider: ctx.model?.provider,
|
|
173
282
|
allowCrossProvider: routingConfig.cross_provider !== false,
|
|
174
|
-
requiredTools
|
|
283
|
+
requiredTools,
|
|
175
284
|
},
|
|
176
285
|
);
|
|
177
286
|
routingEligibleModels = policy.eligible;
|
|
178
287
|
policyAllowedModelKeys = new Set(
|
|
179
288
|
policy.eligible.map((m) => `${m.provider.toLowerCase()}/${m.id.toLowerCase()}`),
|
|
180
289
|
);
|
|
290
|
+
policyDenyReasons = policy.decisions
|
|
291
|
+
.filter((d) => !d.allowed)
|
|
292
|
+
.map((d) => ({ provider: d.provider, modelId: d.modelId, reason: d.reason }));
|
|
181
293
|
if (routingEligibleModels.length === 0) {
|
|
182
|
-
throw new
|
|
294
|
+
throw new ModelPolicyDispatchBlockedError(unitType, unitId, policyDenyReasons);
|
|
183
295
|
}
|
|
184
296
|
}
|
|
185
297
|
|
|
@@ -235,7 +347,11 @@ export async function selectAndApplyModel(
|
|
|
235
347
|
);
|
|
236
348
|
const availableModelIds = routingEligibleModels.map(m => `${m.provider}/${m.id}`);
|
|
237
349
|
|
|
238
|
-
// Escalate tier on retry when escalate_on_failure is enabled (default: true)
|
|
350
|
+
// Escalate tier on retry when escalate_on_failure is enabled (default: true).
|
|
351
|
+
// #4973: Deterministic policy errors are short-circuited at the postUnit
|
|
352
|
+
// level (auto-post-unit.ts writes a placeholder and returns "continue"),
|
|
353
|
+
// so this code path only runs for legitimate model-quality retries where
|
|
354
|
+
// tier escalation is the right response.
|
|
239
355
|
if (
|
|
240
356
|
retryContext?.isRetry &&
|
|
241
357
|
retryContext.previousTier &&
|
|
@@ -249,6 +365,17 @@ export async function selectAndApplyModel(
|
|
|
249
365
|
`Tier escalation: ${retryContext.previousTier} → ${escalated} (retry after failure)`,
|
|
250
366
|
"info",
|
|
251
367
|
);
|
|
368
|
+
} else {
|
|
369
|
+
// #4973: Already at max tier — keep previousTier rather than letting
|
|
370
|
+
// fresh classification silently downgrade the model back to a lower tier.
|
|
371
|
+
// Without this, a light-start unit on retry 3 would revert to the light
|
|
372
|
+
// model after escalating to heavy on retries 1 and 2.
|
|
373
|
+
const tierOrder: Record<string, number> = { light: 0, standard: 1, heavy: 2 };
|
|
374
|
+
const prevOrder = tierOrder[retryContext.previousTier] ?? 0;
|
|
375
|
+
const freshOrder = tierOrder[classification.tier] ?? 0;
|
|
376
|
+
if (prevOrder > freshOrder) {
|
|
377
|
+
classification = { ...classification, tier: retryContext.previousTier as ComplexityTier, reason: "retained escalated tier from retry" };
|
|
378
|
+
}
|
|
252
379
|
}
|
|
253
380
|
}
|
|
254
381
|
|
|
@@ -443,7 +570,7 @@ export async function selectAndApplyModel(
|
|
|
443
570
|
}
|
|
444
571
|
|
|
445
572
|
if (uokFlags.modelPolicy && policyAllowedModelKeys && !attemptedPolicyEligible) {
|
|
446
|
-
throw new
|
|
573
|
+
throw new ModelPolicyDispatchBlockedError(unitType, unitId, policyDenyReasons);
|
|
447
574
|
}
|
|
448
575
|
} else if (autoModeStartModel) {
|
|
449
576
|
// No model preference for this unit type — re-apply the model captured
|
|
@@ -65,16 +65,28 @@ import { resolveExpectedArtifactPath as resolveArtifactForContent } from "./auto
|
|
|
65
65
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
66
66
|
import { getSliceTasks } from "./gsd-db.js";
|
|
67
67
|
import { runPreExecutionChecks, type PreExecutionResult } from "./pre-execution-checks.js";
|
|
68
|
-
import { writePreExecutionEvidence } from "./verification-evidence.js";
|
|
68
|
+
import { writePreExecutionEvidence, type PreExecutionCheckJSON } from "./verification-evidence.js";
|
|
69
69
|
import { ensureCodebaseMapFresh } from "./codebase-generator.js";
|
|
70
70
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
71
71
|
import { UokGateRunner } from "./uok/gate-runner.js";
|
|
72
72
|
import { writeTurnGitTransaction } from "./uok/gitops.js";
|
|
73
73
|
import { isClosedStatus } from "./status-guards.js";
|
|
74
74
|
import { detectAbandonMilestone } from "./abandon-detect.js";
|
|
75
|
+
import { isDeterministicPolicyError } from "./auto-tool-tracking.js";
|
|
75
76
|
|
|
76
77
|
/** Maximum verification retry attempts before escalating to blocker placeholder (#2653). */
|
|
77
78
|
const MAX_VERIFICATION_RETRIES = 3;
|
|
79
|
+
/** Keep failure toasts short while still showing concrete examples. */
|
|
80
|
+
const MAX_NOTIFICATION_DETAILS = 3;
|
|
81
|
+
const NOTIFICATION_BULLET = "•";
|
|
82
|
+
|
|
83
|
+
function formatPreExecutionCheckDetail(check: PreExecutionCheckJSON): string {
|
|
84
|
+
const category = check.category?.trim() || "unknown category";
|
|
85
|
+
const target = check.target?.trim() || "unknown target";
|
|
86
|
+
const message = check.message.split(/\r?\n/, 1)[0]?.trim() || "No details provided";
|
|
87
|
+
return ` ${NOTIFICATION_BULLET} [${category}] ${target}: ${message}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
78
90
|
const COMPLETE_MILESTONE_DB_SETTLE_MS = 1500;
|
|
79
91
|
const COMPLETE_MILESTONE_DB_SETTLE_POLL_MS = 100;
|
|
80
92
|
|
|
@@ -125,7 +137,7 @@ import {
|
|
|
125
137
|
describeNextUnit,
|
|
126
138
|
} from "./auto-dashboard.js";
|
|
127
139
|
import { existsSync, unlinkSync } from "node:fs";
|
|
128
|
-
import { join } from "node:path";
|
|
140
|
+
import { join, relative } from "node:path";
|
|
129
141
|
import { _resetHasChangesCache } from "./native-git-bridge.js";
|
|
130
142
|
import { autoCommitCurrentBranch } from "./worktree.js";
|
|
131
143
|
|
|
@@ -253,6 +265,14 @@ export function detectRogueFileWrites(
|
|
|
253
265
|
return rogues;
|
|
254
266
|
}
|
|
255
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Maximum number of times to retry a unit whose expected artifact is missing
|
|
270
|
+
* after execution. Matches the bounded pattern used by runPostUnitVerification
|
|
271
|
+
* in auto-verification.ts. Exceeding this limit pauses auto-mode instead of
|
|
272
|
+
* looping indefinitely (#2007).
|
|
273
|
+
*/
|
|
274
|
+
const MAX_ARTIFACT_VERIFICATION_RETRIES = 3;
|
|
275
|
+
|
|
256
276
|
export const STEP_COMPLETE_FALLBACK_MESSAGE =
|
|
257
277
|
"Step complete. Run /clear, then /gsd to continue (or /gsd auto to run continuously).";
|
|
258
278
|
|
|
@@ -905,16 +925,35 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
905
925
|
// When artifact verification fails for a unit type that has a known expected
|
|
906
926
|
// artifact, return "retry" so the caller re-dispatches with failure context
|
|
907
927
|
// instead of blindly re-dispatching the same unit (#1571).
|
|
908
|
-
//
|
|
909
|
-
//
|
|
928
|
+
// Retries are capped at MAX_ARTIFACT_VERIFICATION_RETRIES to prevent
|
|
929
|
+
// unbounded loops (#2007).
|
|
930
|
+
//
|
|
931
|
+
// Pre-checks short-circuit retry for known-unrecoverable failures:
|
|
932
|
+
// - Deterministic policy rejection (#4973): structural write-gate failure
|
|
933
|
+
// that will recur on every retry, so write a blocker placeholder.
|
|
934
|
+
// - DB infra failure (#2517): completion tool returned db_unavailable, so
|
|
935
|
+
// the artifact was never written. Retrying can never succeed.
|
|
936
|
+
// - Tool invocation error (#2883/#3595): malformed JSON args or queued
|
|
937
|
+
// user message — retry will produce the same failure.
|
|
910
938
|
//
|
|
911
|
-
//
|
|
912
|
-
//
|
|
913
|
-
//
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
939
|
+
// #4973: Deterministic policy rejections (e.g. context_write_blocked from the
|
|
940
|
+
// write-gate) are checked FIRST — before the DB-availability check — because
|
|
941
|
+
// they are structural gates that will fire on every retry regardless of DB or
|
|
942
|
+
// model tier. Short-circuit immediately by writing a blocker placeholder.
|
|
943
|
+
if (!triggerArtifactVerified && s.lastToolInvocationError && isDeterministicPolicyError(s.lastToolInvocationError)) {
|
|
944
|
+
const retryKey = `${s.currentUnit.type}:${s.currentUnit.id}`;
|
|
945
|
+
debugLog("postUnit", { phase: "deterministic-policy-error-placeholder", unitType: s.currentUnit.type, unitId: s.currentUnit.id, error: s.lastToolInvocationError });
|
|
946
|
+
const reason = `Deterministic policy rejection for ${s.currentUnit.type} "${s.currentUnit.id}": ${s.lastToolInvocationError}. Retrying cannot resolve this gate — writing blocker placeholder to advance pipeline.`;
|
|
947
|
+
s.lastToolInvocationError = null;
|
|
948
|
+
s.pendingVerificationRetry = null;
|
|
949
|
+
s.verificationRetryCount.delete(retryKey);
|
|
950
|
+
writeBlockerPlaceholder(s.currentUnit.type, s.currentUnit.id, s.basePath, reason);
|
|
951
|
+
ctx.ui.notify(
|
|
952
|
+
`${s.currentUnit.type} ${s.currentUnit.id} — deterministic policy rejection, wrote blocker placeholder (no retries) (#4973)`,
|
|
953
|
+
"warning",
|
|
954
|
+
);
|
|
955
|
+
// Fall through to "continue" — do NOT enter the retry or db-unavailable paths.
|
|
956
|
+
} else if (!triggerArtifactVerified && !isDbAvailable()) {
|
|
918
957
|
debugLog("postUnit", { phase: "artifact-verify-skip-db-unavailable", unitType: s.currentUnit.type, unitId: s.currentUnit.id });
|
|
919
958
|
const dbSkipDiag = diagnoseExpectedArtifact(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
920
959
|
ctx.ui.notify(
|
|
@@ -922,9 +961,6 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
922
961
|
"error",
|
|
923
962
|
);
|
|
924
963
|
} else if (!triggerArtifactVerified) {
|
|
925
|
-
// #2883/#3595: If the artifact is missing because the tool invocation
|
|
926
|
-
// failed (malformed JSON) or was skipped (queued user message), retrying
|
|
927
|
-
// will produce the same failure. Pause auto-mode instead of looping.
|
|
928
964
|
if (s.lastToolInvocationError) {
|
|
929
965
|
const isUserSkip = /queued user message/i.test(s.lastToolInvocationError);
|
|
930
966
|
const errMsg = isUserSkip
|
|
@@ -941,68 +977,36 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
941
977
|
if (hasExpectedArtifact) {
|
|
942
978
|
const retryKey = `${s.currentUnit.type}:${s.currentUnit.id}`;
|
|
943
979
|
const attempt = (s.verificationRetryCount.get(retryKey) ?? 0) + 1;
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
if (attempt > MAX_VERIFICATION_RETRIES) {
|
|
947
|
-
// #4175: For complete-milestone, a blocker placeholder is harmful —
|
|
948
|
-
// the stub SUMMARY has no recovery value (milestone is terminal),
|
|
949
|
-
// it does not update DB status (so deriveState never advances),
|
|
950
|
-
// and it fools stopAuto's presence check into merging a milestone
|
|
951
|
-
// that was never legitimately completed. Pause auto-mode with a
|
|
952
|
-
// clear single failure signal and preserve the worktree branch.
|
|
953
|
-
if (s.currentUnit.type === "complete-milestone") {
|
|
954
|
-
debugLog("postUnit", {
|
|
955
|
-
phase: "artifact-verify-pause-complete-milestone",
|
|
956
|
-
unitType: s.currentUnit.type,
|
|
957
|
-
unitId: s.currentUnit.id,
|
|
958
|
-
attempt,
|
|
959
|
-
maxRetries: MAX_VERIFICATION_RETRIES,
|
|
960
|
-
});
|
|
961
|
-
s.verificationRetryCount.delete(retryKey);
|
|
962
|
-
s.pendingVerificationRetry = null;
|
|
963
|
-
ctx.ui.notify(
|
|
964
|
-
`Milestone ${s.currentUnit.id} verification failed after ${MAX_VERIFICATION_RETRIES} retries — worktree branch preserved. Re-run /gsd auto once blockers are resolved.`,
|
|
965
|
-
"error",
|
|
966
|
-
);
|
|
967
|
-
await pauseAuto(ctx, pi);
|
|
968
|
-
return "dispatched";
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
// Retries exhausted — write a blocker placeholder so the pipeline
|
|
972
|
-
// can advance past this stuck unit (#2653).
|
|
973
|
-
debugLog("postUnit", {
|
|
974
|
-
phase: "artifact-verify-escalate",
|
|
975
|
-
unitType: s.currentUnit.type,
|
|
976
|
-
unitId: s.currentUnit.id,
|
|
977
|
-
attempt,
|
|
978
|
-
maxRetries: MAX_VERIFICATION_RETRIES,
|
|
979
|
-
});
|
|
980
|
-
const reason = `Artifact verification failed after ${MAX_VERIFICATION_RETRIES} retries for ${s.currentUnit.type} "${s.currentUnit.id}".`;
|
|
981
|
-
writeBlockerPlaceholder(s.currentUnit.type, s.currentUnit.id, s.basePath, reason);
|
|
982
|
-
ctx.ui.notify(
|
|
983
|
-
`${s.currentUnit.type} ${s.currentUnit.id} — verification retries exhausted (${MAX_VERIFICATION_RETRIES}), wrote blocker placeholder to advance pipeline`,
|
|
984
|
-
"warning",
|
|
985
|
-
);
|
|
986
|
-
// Reset retry count and fall through to "continue" so the loop
|
|
987
|
-
// re-derives state with the placeholder in place.
|
|
980
|
+
if (attempt > MAX_ARTIFACT_VERIFICATION_RETRIES) {
|
|
988
981
|
s.verificationRetryCount.delete(retryKey);
|
|
989
|
-
s.
|
|
990
|
-
// Do NOT return "retry" — fall through to "continue" below.
|
|
991
|
-
} else {
|
|
992
|
-
s.pendingVerificationRetry = {
|
|
993
|
-
unitId: s.currentUnit.id,
|
|
994
|
-
failureContext: `Artifact verification failed: expected artifact for ${s.currentUnit.type} "${s.currentUnit.id}" was not found on disk after unit execution (attempt ${attempt}).`,
|
|
995
|
-
attempt,
|
|
996
|
-
};
|
|
997
|
-
debugLog("postUnit", { phase: "artifact-verify-retry", unitType: s.currentUnit.type, unitId: s.currentUnit.id, attempt });
|
|
982
|
+
debugLog("postUnit", { phase: "artifact-verify-exhausted", unitType: s.currentUnit.type, unitId: s.currentUnit.id, attempt });
|
|
998
983
|
ctx.ui.notify(
|
|
999
|
-
`Artifact missing for ${s.currentUnit.type} ${s.currentUnit.id}
|
|
1000
|
-
"
|
|
984
|
+
`Artifact still missing for ${s.currentUnit.type} ${s.currentUnit.id} after ${MAX_ARTIFACT_VERIFICATION_RETRIES} retries — pausing auto-mode`,
|
|
985
|
+
"error",
|
|
1001
986
|
);
|
|
1002
|
-
|
|
987
|
+
await pauseAuto(ctx, pi);
|
|
988
|
+
return "dispatched";
|
|
1003
989
|
}
|
|
990
|
+
s.verificationRetryCount.set(retryKey, attempt);
|
|
991
|
+
s.pendingVerificationRetry = {
|
|
992
|
+
unitId: s.currentUnit.id,
|
|
993
|
+
failureContext: `Artifact verification failed: expected artifact for ${s.currentUnit.type} "${s.currentUnit.id}" was not found on disk after unit execution (attempt ${attempt}/${MAX_ARTIFACT_VERIFICATION_RETRIES}).`,
|
|
994
|
+
attempt,
|
|
995
|
+
};
|
|
996
|
+
debugLog("postUnit", { phase: "artifact-verify-retry", unitType: s.currentUnit.type, unitId: s.currentUnit.id, attempt });
|
|
997
|
+
ctx.ui.notify(
|
|
998
|
+
`Artifact missing for ${s.currentUnit.type} ${s.currentUnit.id} — retrying (attempt ${attempt}/${MAX_ARTIFACT_VERIFICATION_RETRIES})`,
|
|
999
|
+
"warning",
|
|
1000
|
+
);
|
|
1001
|
+
return "retry";
|
|
1004
1002
|
}
|
|
1005
1003
|
}
|
|
1004
|
+
|
|
1005
|
+
// Verification succeeded — clear the retry counter so a future failure
|
|
1006
|
+
// of the same unit gets a full retry budget instead of the stale count.
|
|
1007
|
+
if (triggerArtifactVerified) {
|
|
1008
|
+
s.verificationRetryCount.delete(`${s.currentUnit.type}:${s.currentUnit.id}`);
|
|
1009
|
+
}
|
|
1006
1010
|
} else {
|
|
1007
1011
|
// Hook unit completed — no additional processing needed
|
|
1008
1012
|
}
|
|
@@ -1242,8 +1246,11 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
1242
1246
|
|
|
1243
1247
|
// Write evidence JSON to slice artifacts directory
|
|
1244
1248
|
const slicePath = resolveSlicePath(s.basePath, mid, sid);
|
|
1249
|
+
const evidenceFileName = `${sid}-PRE-EXEC-VERIFY.json`;
|
|
1250
|
+
let evidencePath = join(".gsd", "milestones", mid, "slices", sid, evidenceFileName);
|
|
1245
1251
|
if (slicePath) {
|
|
1246
1252
|
writePreExecutionEvidence(result, slicePath, mid, sid);
|
|
1253
|
+
evidencePath = relative(s.basePath, join(slicePath, evidenceFileName)) || evidenceFileName;
|
|
1247
1254
|
}
|
|
1248
1255
|
|
|
1249
1256
|
if (uokFlags.gates) {
|
|
@@ -1280,9 +1287,11 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
1280
1287
|
if (result.status === "fail") {
|
|
1281
1288
|
const blockingChecks = result.checks.filter(c => !c.passed && c.blocking);
|
|
1282
1289
|
const blockingCount = blockingChecks.length;
|
|
1283
|
-
const details = blockingChecks.slice(0,
|
|
1284
|
-
const suffix = blockingChecks.length >
|
|
1285
|
-
|
|
1290
|
+
const details = blockingChecks.slice(0, MAX_NOTIFICATION_DETAILS).map(formatPreExecutionCheckDetail).join("\n");
|
|
1291
|
+
const suffix = blockingChecks.length > MAX_NOTIFICATION_DETAILS
|
|
1292
|
+
? `\n ${NOTIFICATION_BULLET} ...and ${blockingChecks.length - MAX_NOTIFICATION_DETAILS} more`
|
|
1293
|
+
: "";
|
|
1294
|
+
const evidenceNote = `\nSee ${evidencePath} for full details.`;
|
|
1286
1295
|
ctx.ui.notify(
|
|
1287
1296
|
`Pre-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found\n${details}${suffix}${evidenceNote}`,
|
|
1288
1297
|
"error",
|