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,11 +1,10 @@
|
|
|
1
1
|
// GSD Extension — Advisory Sync Lock
|
|
2
2
|
// Prevents concurrent worktree syncs from colliding via a simple file lock.
|
|
3
|
-
// Stale locks (mtime > 60s) are
|
|
4
|
-
// to 5 seconds then skips non-fatally.
|
|
3
|
+
// Stale locks (mtime > 60s, owner PID confirmed dead) are overridden. Lock
|
|
4
|
+
// acquisition waits up to 5 seconds then skips non-fatally.
|
|
5
5
|
|
|
6
|
-
import { existsSync, statSync, unlinkSync } from "node:fs";
|
|
7
|
-
import { join } from "node:path";
|
|
8
|
-
import { atomicWriteSync } from "./atomic-write.js";
|
|
6
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
9
8
|
|
|
10
9
|
const STALE_THRESHOLD_MS = 60_000; // 60 seconds
|
|
11
10
|
const DEFAULT_TIMEOUT_MS = 5_000; // 5 seconds
|
|
@@ -23,13 +22,59 @@ function sleepSync(ms: number): void {
|
|
|
23
22
|
Atomics.wait(SLEEP_VIEW, 0, 0, ms);
|
|
24
23
|
}
|
|
25
24
|
|
|
25
|
+
/** True if the given PID is alive in the current process namespace. */
|
|
26
|
+
function isPidAlive(pid: number): boolean {
|
|
27
|
+
try {
|
|
28
|
+
process.kill(pid, 0);
|
|
29
|
+
return true;
|
|
30
|
+
} catch (err) {
|
|
31
|
+
if ((err as NodeJS.ErrnoException).code === "EPERM") return true;
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Atomically create the lock file with `O_EXCL` semantics. Returns true on
|
|
38
|
+
* exclusive create, false if the file already existed. Any other error
|
|
39
|
+
* propagates.
|
|
40
|
+
*/
|
|
41
|
+
function tryCreateLockFile(lp: string, payload: string): boolean {
|
|
42
|
+
// Ensure parent dir exists (`atomicWriteSync` previously did this implicitly).
|
|
43
|
+
try {
|
|
44
|
+
mkdirSync(dirname(lp), { recursive: true });
|
|
45
|
+
} catch {
|
|
46
|
+
/* best-effort */
|
|
47
|
+
}
|
|
48
|
+
let fd: number;
|
|
49
|
+
try {
|
|
50
|
+
// "wx" → O_WRONLY | O_CREAT | O_EXCL — atomic create-if-not-exists on POSIX.
|
|
51
|
+
fd = openSync(lp, "wx");
|
|
52
|
+
} catch (err) {
|
|
53
|
+
const code = (err as NodeJS.ErrnoException).code;
|
|
54
|
+
if (code === "EEXIST") return false;
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
writeSync(fd, payload);
|
|
59
|
+
} finally {
|
|
60
|
+
closeSync(fd);
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
26
65
|
/**
|
|
27
66
|
* Acquire an advisory sync lock for the given basePath.
|
|
28
67
|
* Returns { acquired: true } on success, { acquired: false } after timeout.
|
|
29
68
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
69
|
+
* Replaces a non-atomic `existsSync` + `atomicWriteSync` (write-temp+rename,
|
|
70
|
+
* which is not exclusive-create) sequence that allowed two callers to both
|
|
71
|
+
* believe they had acquired the lock, corrupting the event log.
|
|
72
|
+
* (Issue #4980 CRIT-4)
|
|
73
|
+
*
|
|
74
|
+
* Stale-lock override now also verifies the recorded owner PID is dead
|
|
75
|
+
* before stealing — prevents a slow event-loop pause (>60s under heavy I/O)
|
|
76
|
+
* from making a legitimately-held lock appear stale and get stolen.
|
|
77
|
+
* (Issue #4980 M-concurrency-3)
|
|
33
78
|
*/
|
|
34
79
|
export function acquireSyncLock(
|
|
35
80
|
basePath: string,
|
|
@@ -37,45 +82,58 @@ export function acquireSyncLock(
|
|
|
37
82
|
): { acquired: boolean } {
|
|
38
83
|
const lp = lockFilePath(basePath);
|
|
39
84
|
const deadline = Date.now() + timeoutMs;
|
|
85
|
+
const lockData = JSON.stringify(
|
|
86
|
+
{ pid: process.pid, acquired_at: new Date().toISOString() },
|
|
87
|
+
null,
|
|
88
|
+
2,
|
|
89
|
+
);
|
|
40
90
|
|
|
41
91
|
while (true) {
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const stat = statSync(lp);
|
|
47
|
-
const age = Date.now() - stat.mtimeMs;
|
|
48
|
-
if (age > STALE_THRESHOLD_MS) {
|
|
49
|
-
// Stale lock — override it
|
|
50
|
-
try { unlinkSync(lp); } catch { /* race: already removed */ }
|
|
51
|
-
} else {
|
|
52
|
-
// Lock is held and not stale — wait or give up
|
|
53
|
-
if (Date.now() >= deadline) {
|
|
54
|
-
return { acquired: false };
|
|
55
|
-
}
|
|
56
|
-
sleepSync(SPIN_INTERVAL_MS);
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
} catch {
|
|
60
|
-
// stat failed (file removed between exists check and stat) — try to acquire
|
|
92
|
+
// First try the fast path: atomic create. No check-then-write race.
|
|
93
|
+
try {
|
|
94
|
+
if (tryCreateLockFile(lp, lockData)) {
|
|
95
|
+
return { acquired: true };
|
|
61
96
|
}
|
|
97
|
+
} catch {
|
|
98
|
+
/* unexpected — fall through to retry */
|
|
62
99
|
}
|
|
63
100
|
|
|
64
|
-
//
|
|
101
|
+
// File exists. Decide whether to steal (stale + owner dead) or wait.
|
|
102
|
+
let canSteal = false;
|
|
65
103
|
try {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
104
|
+
const stat = statSync(lp);
|
|
105
|
+
const age = Date.now() - stat.mtimeMs;
|
|
106
|
+
if (age > STALE_THRESHOLD_MS) {
|
|
107
|
+
// Verify the recorded owner PID is dead before stealing.
|
|
108
|
+
let ownerAlive = false;
|
|
109
|
+
try {
|
|
110
|
+
const data = JSON.parse(readFileSync(lp, "utf-8")) as { pid?: number };
|
|
111
|
+
if (typeof data.pid === "number" && data.pid !== process.pid) {
|
|
112
|
+
ownerAlive = isPidAlive(data.pid);
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
// Lock contents unreadable — be conservative and steal only on age.
|
|
116
|
+
// A garbage lock file that we cannot parse is safer to remove than
|
|
117
|
+
// to leave wedging the lock indefinitely.
|
|
118
|
+
}
|
|
119
|
+
canSteal = !ownerAlive;
|
|
76
120
|
}
|
|
77
|
-
|
|
121
|
+
} catch {
|
|
122
|
+
// stat failed (file removed between exists and stat) — retry create.
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (canSteal) {
|
|
127
|
+
try { unlinkSync(lp); } catch { /* race: already removed */ }
|
|
128
|
+
// Loop back to retry create.
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Lock is held and not stale (or owner is alive) — wait or give up.
|
|
133
|
+
if (Date.now() >= deadline) {
|
|
134
|
+
return { acquired: false };
|
|
78
135
|
}
|
|
136
|
+
sleepSync(SPIN_INTERVAL_MS);
|
|
79
137
|
}
|
|
80
138
|
}
|
|
81
139
|
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* artifact-retry-cap.test.ts — Regression tests for #2007.
|
|
3
|
+
*
|
|
4
|
+
* Three interacting bugs caused unbounded artifact-verification retry loops
|
|
5
|
+
* that burned unlimited budget (202 dispatches observed in production):
|
|
6
|
+
*
|
|
7
|
+
* Bug 1: postUnitPreVerification in auto-post-unit.ts had no MAX check before
|
|
8
|
+
* returning "retry" when an expected artifact was missing. The attempt
|
|
9
|
+
* counter incremented forever.
|
|
10
|
+
*
|
|
11
|
+
* Bug 2: runDispatch in auto/phases.ts only pushed to loopState.recentUnits
|
|
12
|
+
* when pendingVerificationRetry was falsy, so the sliding-window stuck
|
|
13
|
+
* detector never saw artifact-retry dispatches and could not fire.
|
|
14
|
+
*
|
|
15
|
+
* Bug 3: MAX_UNIT_DISPATCHES and MAX_LIFETIME_DISPATCHES were exported from
|
|
16
|
+
* auto/session.ts but never compared against unitDispatchCount anywhere
|
|
17
|
+
* in the codebase — dead constants that provided false confidence.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import test from "node:test";
|
|
21
|
+
import assert from "node:assert/strict";
|
|
22
|
+
import { readFileSync } from "node:fs";
|
|
23
|
+
import { join } from "node:path";
|
|
24
|
+
import ts from "typescript";
|
|
25
|
+
|
|
26
|
+
const dir = join(import.meta.dirname, "..");
|
|
27
|
+
|
|
28
|
+
const postUnitSrc = readFileSync(join(dir, "auto-post-unit.ts"), "utf-8");
|
|
29
|
+
const phasesSrc = readFileSync(join(dir, "auto", "phases.ts"), "utf-8");
|
|
30
|
+
const sessionSrc = readFileSync(join(dir, "auto", "session.ts"), "utf-8");
|
|
31
|
+
const autoSrc = readFileSync(join(dir, "auto.ts"), "utf-8");
|
|
32
|
+
|
|
33
|
+
function extractFunctionBody(source: string, functionName: string): string {
|
|
34
|
+
const sourceFile = ts.createSourceFile(
|
|
35
|
+
"auto-post-unit.ts",
|
|
36
|
+
source,
|
|
37
|
+
ts.ScriptTarget.Latest,
|
|
38
|
+
true,
|
|
39
|
+
ts.ScriptKind.TS,
|
|
40
|
+
);
|
|
41
|
+
let body: ts.Block | undefined;
|
|
42
|
+
|
|
43
|
+
function visit(node: ts.Node): void {
|
|
44
|
+
if (
|
|
45
|
+
ts.isFunctionDeclaration(node) &&
|
|
46
|
+
node.name?.text === functionName
|
|
47
|
+
) {
|
|
48
|
+
body = node.body;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
ts.forEachChild(node, visit);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
visit(sourceFile);
|
|
55
|
+
|
|
56
|
+
assert.ok(body, `${functionName} must have a function body`);
|
|
57
|
+
return source.slice(body.getStart(sourceFile) + 1, body.end - 1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function extractStuckDetectionSection(source: string): string {
|
|
61
|
+
const stuckSectionIdx = source.indexOf("Sliding-window stuck detection");
|
|
62
|
+
assert.ok(stuckSectionIdx !== -1, "stuck-detection section must exist");
|
|
63
|
+
|
|
64
|
+
const preDispatchIdx = source.indexOf("// Pre-dispatch hooks", stuckSectionIdx);
|
|
65
|
+
assert.ok(preDispatchIdx !== -1, "pre-dispatch hooks section must follow stuck detection");
|
|
66
|
+
|
|
67
|
+
return source.slice(stuckSectionIdx, preDispatchIdx);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const postUnitPreVerificationBody = extractFunctionBody(
|
|
71
|
+
postUnitSrc,
|
|
72
|
+
"postUnitPreVerification",
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// ─── Bug 1: artifact retry must be bounded ───────────────────────────────────
|
|
76
|
+
|
|
77
|
+
test("#2007 bug 1: MAX_ARTIFACT_VERIFICATION_RETRIES constant is defined", () => {
|
|
78
|
+
assert.ok(
|
|
79
|
+
postUnitSrc.includes("MAX_ARTIFACT_VERIFICATION_RETRIES"),
|
|
80
|
+
"auto-post-unit.ts must define MAX_ARTIFACT_VERIFICATION_RETRIES",
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("#2007 bug 1: attempt is compared against MAX_ARTIFACT_VERIFICATION_RETRIES before returning retry", () => {
|
|
85
|
+
const retryBlockIdx = postUnitPreVerificationBody.indexOf("const retryKey =");
|
|
86
|
+
assert.ok(retryBlockIdx !== -1, "retry block must exist in postUnitPreVerification");
|
|
87
|
+
|
|
88
|
+
const retryIdx = postUnitPreVerificationBody.indexOf("return \"retry\"", retryBlockIdx);
|
|
89
|
+
assert.ok(retryIdx !== -1, "return \"retry\" must exist in postUnitPreVerification");
|
|
90
|
+
|
|
91
|
+
const maxIdx = postUnitPreVerificationBody.indexOf(
|
|
92
|
+
"if (attempt > MAX_ARTIFACT_VERIFICATION_RETRIES)",
|
|
93
|
+
retryBlockIdx,
|
|
94
|
+
);
|
|
95
|
+
assert.ok(maxIdx !== -1, "retry block must compare attempt against MAX");
|
|
96
|
+
assert.ok(
|
|
97
|
+
maxIdx < retryIdx,
|
|
98
|
+
"MAX_ARTIFACT_VERIFICATION_RETRIES check must appear before return \"retry\"",
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("#2007 bug 1: exhaustion path pauses auto-mode instead of silently continuing", () => {
|
|
103
|
+
const exhaustionIdx = postUnitPreVerificationBody.indexOf("phase: \"artifact-verify-exhausted\"");
|
|
104
|
+
assert.ok(exhaustionIdx !== -1, "exhaustion branch must log artifact-verify-exhausted");
|
|
105
|
+
|
|
106
|
+
const pauseIdx = postUnitPreVerificationBody.indexOf("await pauseAuto", exhaustionIdx);
|
|
107
|
+
const dispatchedIdx = postUnitPreVerificationBody.indexOf("return \"dispatched\"", exhaustionIdx);
|
|
108
|
+
|
|
109
|
+
assert.ok(
|
|
110
|
+
pauseIdx !== -1 && dispatchedIdx !== -1 && pauseIdx < dispatchedIdx,
|
|
111
|
+
"exhaustion branch must pause auto-mode before returning \"dispatched\"",
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("#2007 bug 1: failure context message includes attempt count and max", () => {
|
|
116
|
+
const failureContextIdx = postUnitPreVerificationBody.indexOf("failureContext:");
|
|
117
|
+
assert.ok(failureContextIdx !== -1, "failureContext assignment must exist");
|
|
118
|
+
assert.ok(
|
|
119
|
+
postUnitPreVerificationBody.includes(
|
|
120
|
+
"attempt ${attempt}/${MAX_ARTIFACT_VERIFICATION_RETRIES}",
|
|
121
|
+
failureContextIdx,
|
|
122
|
+
),
|
|
123
|
+
"failure context should include attempt progress (attempt/current-max)",
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// ─── Bug 2: stuck detection must see all dispatches ──────────────────────────
|
|
128
|
+
|
|
129
|
+
test("#2007 bug 2: recentUnits.push is unconditional — not gated on pendingVerificationRetry", () => {
|
|
130
|
+
const stuckSection = extractStuckDetectionSection(phasesSrc);
|
|
131
|
+
const pushIdx = stuckSection.indexOf("recentUnits.push");
|
|
132
|
+
assert.ok(pushIdx !== -1, "recentUnits.push must exist in phases.ts");
|
|
133
|
+
|
|
134
|
+
const pendingCheckIdx = stuckSection.indexOf("!s.pendingVerificationRetry");
|
|
135
|
+
assert.ok(pendingCheckIdx !== -1, "pendingVerificationRetry guard must exist");
|
|
136
|
+
|
|
137
|
+
// The push must come BEFORE the pendingVerificationRetry guard
|
|
138
|
+
assert.ok(
|
|
139
|
+
pushIdx < pendingCheckIdx,
|
|
140
|
+
"recentUnits.push must be unconditional — it must appear before the !pendingVerificationRetry check",
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("#2007 bug 2: detectStuck is still inside the pendingVerificationRetry guard", () => {
|
|
145
|
+
// detectStuck should only run when NOT in a retry — to avoid false positives
|
|
146
|
+
// during legitimate retries, but now the window is always populated.
|
|
147
|
+
const stuckSection = extractStuckDetectionSection(phasesSrc);
|
|
148
|
+
const pendingCheckIdx = stuckSection.indexOf("!s.pendingVerificationRetry");
|
|
149
|
+
assert.ok(
|
|
150
|
+
pendingCheckIdx !== -1,
|
|
151
|
+
"pendingVerificationRetry guard must exist in the stuck-detection section",
|
|
152
|
+
);
|
|
153
|
+
const detectStuckIdx = stuckSection.indexOf("detectStuck(", pendingCheckIdx);
|
|
154
|
+
|
|
155
|
+
assert.ok(
|
|
156
|
+
detectStuckIdx !== -1 && detectStuckIdx > pendingCheckIdx,
|
|
157
|
+
"detectStuck call must remain inside the !pendingVerificationRetry block",
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ─── Bug 3: dead dispatch-limit constants removed ────────────────────────────
|
|
162
|
+
|
|
163
|
+
test("#2007 bug 3: MAX_UNIT_DISPATCHES is removed from session.ts", () => {
|
|
164
|
+
assert.ok(
|
|
165
|
+
!sessionSrc.includes("MAX_UNIT_DISPATCHES"),
|
|
166
|
+
"MAX_UNIT_DISPATCHES was never enforced and must be removed to prevent false confidence",
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("#2007 bug 3: MAX_LIFETIME_DISPATCHES is removed from session.ts", () => {
|
|
171
|
+
assert.ok(
|
|
172
|
+
!sessionSrc.includes("MAX_LIFETIME_DISPATCHES"),
|
|
173
|
+
"MAX_LIFETIME_DISPATCHES was never enforced and must be removed to prevent false confidence",
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test("#2007 bug 3: dead constants are not re-exported from auto.ts", () => {
|
|
178
|
+
assert.ok(
|
|
179
|
+
!autoSrc.includes("MAX_UNIT_DISPATCHES"),
|
|
180
|
+
"MAX_UNIT_DISPATCHES must not be re-exported from auto.ts",
|
|
181
|
+
);
|
|
182
|
+
assert.ok(
|
|
183
|
+
!autoSrc.includes("MAX_LIFETIME_DISPATCHES"),
|
|
184
|
+
"MAX_LIFETIME_DISPATCHES must not be re-exported from auto.ts",
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// ─── No stray dead constants left behind by the fix ──────────────────────────
|
|
189
|
+
|
|
190
|
+
test("#2007 fix does not introduce a new dead constant (STATE_REBUILD_MIN_INTERVAL_MS)", () => {
|
|
191
|
+
// Bug 3 was about removing dead constants. A draft of this PR added
|
|
192
|
+
// STATE_REBUILD_MIN_INTERVAL_MS without referencing it — the same anti-pattern
|
|
193
|
+
// it set out to remove. Lock that down so it cannot regress.
|
|
194
|
+
assert.ok(
|
|
195
|
+
!postUnitSrc.includes("STATE_REBUILD_MIN_INTERVAL_MS"),
|
|
196
|
+
"STATE_REBUILD_MIN_INTERVAL_MS was added but never referenced — must be removed",
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// ─── Behavioral: retry counter is cleared on success ─────────────────────────
|
|
201
|
+
|
|
202
|
+
test("#2007 verificationRetryCount is cleared on artifact verification success", () => {
|
|
203
|
+
// Find the success-clear we just added: when triggerArtifactVerified is
|
|
204
|
+
// true, the retry counter for the current unit must be deleted so a future
|
|
205
|
+
// failure of the same unit type+id gets the full retry budget instead of
|
|
206
|
+
// a stale leftover count.
|
|
207
|
+
//
|
|
208
|
+
// We assert on the structural shape because a behavioral test would need
|
|
209
|
+
// to mock 30+ imports of postUnitPreVerification. The AutoSession-level
|
|
210
|
+
// test below covers the Map contract.
|
|
211
|
+
const successClearIdx = postUnitPreVerificationBody.indexOf(
|
|
212
|
+
"if (triggerArtifactVerified)",
|
|
213
|
+
);
|
|
214
|
+
assert.ok(
|
|
215
|
+
successClearIdx !== -1,
|
|
216
|
+
"Must guard the retry-count clear behind a triggerArtifactVerified check",
|
|
217
|
+
);
|
|
218
|
+
const deleteIdx = postUnitPreVerificationBody.indexOf(
|
|
219
|
+
"verificationRetryCount.delete",
|
|
220
|
+
successClearIdx,
|
|
221
|
+
);
|
|
222
|
+
assert.ok(
|
|
223
|
+
deleteIdx !== -1,
|
|
224
|
+
"verificationRetryCount.delete must be called on the verification-success path",
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// ─── AutoSession.verificationRetryCount Map behavior ─────────────────────────
|
|
229
|
+
|
|
230
|
+
import { AutoSession } from "../auto/session.ts";
|
|
231
|
+
|
|
232
|
+
test("AutoSession.verificationRetryCount tracks attempts per retry key", () => {
|
|
233
|
+
const s = new AutoSession();
|
|
234
|
+
const key = "execute-task:M01/S01/T01";
|
|
235
|
+
|
|
236
|
+
assert.equal(s.verificationRetryCount.get(key), undefined);
|
|
237
|
+
|
|
238
|
+
s.verificationRetryCount.set(key, 1);
|
|
239
|
+
assert.equal(s.verificationRetryCount.get(key), 1);
|
|
240
|
+
|
|
241
|
+
s.verificationRetryCount.set(key, 2);
|
|
242
|
+
assert.equal(s.verificationRetryCount.get(key), 2);
|
|
243
|
+
|
|
244
|
+
// Simulate the success-clear path
|
|
245
|
+
s.verificationRetryCount.delete(key);
|
|
246
|
+
assert.equal(s.verificationRetryCount.get(key), undefined);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test("AutoSession.verificationRetryCount is cleared on session reset", () => {
|
|
250
|
+
const s = new AutoSession();
|
|
251
|
+
s.verificationRetryCount.set("execute-task:M01/S01/T01", 2);
|
|
252
|
+
s.verificationRetryCount.set("plan-slice:M01/S02", 1);
|
|
253
|
+
|
|
254
|
+
s.reset();
|
|
255
|
+
|
|
256
|
+
assert.equal(s.verificationRetryCount.size, 0);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test("AutoSession.verificationRetryCount independence across retry keys", () => {
|
|
260
|
+
// Critical: if retries for unit A fail twice and unit A then succeeds, the
|
|
261
|
+
// counter for A should be cleared but B's counter must remain untouched.
|
|
262
|
+
const s = new AutoSession();
|
|
263
|
+
s.verificationRetryCount.set("execute-task:M01/S01/T01", 2);
|
|
264
|
+
s.verificationRetryCount.set("execute-task:M01/S01/T02", 1);
|
|
265
|
+
|
|
266
|
+
s.verificationRetryCount.delete("execute-task:M01/S01/T01");
|
|
267
|
+
|
|
268
|
+
assert.equal(s.verificationRetryCount.get("execute-task:M01/S01/T01"), undefined);
|
|
269
|
+
assert.equal(s.verificationRetryCount.get("execute-task:M01/S01/T02"), 1);
|
|
270
|
+
});
|