gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0
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/loader.js +0 -0
- 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/github-sync/templates.js +103 -0
- package/dist/resources/extensions/google-search/index.js +3 -2
- package/dist/resources/extensions/gsd/auto/loop.js +124 -2
- package/dist/resources/extensions/gsd/auto/phases.js +57 -39
- package/dist/resources/extensions/gsd/auto/session.js +6 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
- package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
- package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
- package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
- package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
- package/dist/resources/extensions/gsd/auto-start.js +107 -29
- 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 +76 -21
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -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/context-store.js +23 -7
- package/dist/resources/extensions/gsd/detection.js +49 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/forensics.js +106 -0
- 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 +39 -13
- 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/milestone-summary-classifier.js +37 -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/preferences-validation.js +23 -0
- package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- 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-cadence.js +238 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
- package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
- package/dist/resources/extensions/gsd/state.js +69 -58
- package/dist/resources/extensions/gsd/sync-lock.js +98 -42
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
- 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/dispatch-envelope.js +33 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
- package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
- package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
- package/dist/resources/extensions/gsd/uok/writer.js +82 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
- package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
- package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
- 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 +12 -12
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- 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/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- 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/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +2 -3
- package/packages/daemon/package.json +2 -2
- 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/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +15 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- 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 +85 -0
- package/packages/mcp-server/src/workflow-tools.ts +19 -6
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +2 -2
- 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/package.json +1 -1
- 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/package.json +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/__tests__/tool-execution.test.js +36 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.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/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.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/package.json +1 -1
- 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/__tests__/tool-execution.test.ts +49 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
- 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 +37 -11
- 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/package.json +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 +42 -11
- 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/package.json +1 -1
- package/packages/rpc-client/src/rpc-client.test.ts +109 -52
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +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/templates.ts +151 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
- package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
- package/src/resources/extensions/google-search/index.ts +3 -2
- package/src/resources/extensions/gsd/auto/loop.ts +142 -2
- package/src/resources/extensions/gsd/auto/phases.ts +62 -38
- package/src/resources/extensions/gsd/auto/session.ts +7 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
- package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
- package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
- package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
- package/src/resources/extensions/gsd/auto-start.ts +127 -9
- 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 +90 -23
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -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/context-store.ts +25 -8
- package/src/resources/extensions/gsd/detection.ts +58 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/forensics.ts +118 -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 +149 -2
- package/src/resources/extensions/gsd/gsd-db.ts +6 -3
- package/src/resources/extensions/gsd/guided-flow.ts +57 -14
- package/src/resources/extensions/gsd/journal.ts +11 -1
- 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/milestone-summary-classifier.ts +42 -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/preferences-validation.ts +21 -0
- package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- 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-cadence.ts +299 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
- package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
- package/src/resources/extensions/gsd/state.ts +76 -66
- 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/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
- 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 +133 -292
- 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-remediate-slice-status.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
- 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-slice-verification-gate.test.ts +2 -1
- 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/context-store.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
- 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 -4
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
- 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/google-search-stub.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
- 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 -56
- 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/interactive-routing-bypass.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
- 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 -55
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -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 -48
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
- 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/preferences-worktree-sync.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
- 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/queue-draft-detection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
- 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/restore-tools-after-discuss.test.ts +6 -3
- 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/sidecar-queue.test.ts +3 -2
- 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-cadence.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
- 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/sync-worktree-skip-current.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
- 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-contracts.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -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/uok-loop-adapter-writer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
- package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
- 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/worktree-telemetry.test.ts +210 -0
- 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/tools/validate-milestone.ts +8 -2
- 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/contracts.ts +65 -0
- package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
- package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
- package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
- package/src/resources/extensions/gsd/uok/writer.ts +113 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
- package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
- package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
- 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/dist/web/standalone/.next/static/chunks/app/page-5b113fd32bc2a1c3.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- 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 -143
- 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 -74
- package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
- 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 -125
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → C1zT2kEfoLhDdbWPWKrXd}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → C1zT2kEfoLhDdbWPWKrXd}/_ssgManifest.js +0 -0
|
@@ -12,13 +12,15 @@ import { _clearCurrentResolve } from "./resolve.js";
|
|
|
12
12
|
import { runPreDispatch, runDispatch, runGuards, runUnitPhase, runFinalize, } from "./phases.js";
|
|
13
13
|
import { debugLog } from "../debug-logger.js";
|
|
14
14
|
import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterMs, COOLDOWN_FALLBACK_WAIT_MS, MAX_COOLDOWN_RETRIES } from "./infra-errors.js";
|
|
15
|
+
import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
|
|
15
16
|
import { resolveEngine } from "../engine-resolver.js";
|
|
16
17
|
import { logWarning } from "../workflow-logger.js";
|
|
17
18
|
import { gsdRoot } from "../paths.js";
|
|
19
|
+
import { atomicWriteSync } from "../atomic-write.js";
|
|
18
20
|
import { resolveUokFlags } from "../uok/flags.js";
|
|
19
21
|
import { scheduleSidecarQueue } from "../uok/execution-graph.js";
|
|
20
22
|
import { ExecutionGraphScheduler } from "../uok/execution-graph.js";
|
|
21
|
-
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
23
|
+
import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
|
|
22
24
|
import { join } from "node:path";
|
|
23
25
|
// ── Stuck detection persistence (#3704) ──────────────────────────────────
|
|
24
26
|
// Persist stuck detection state to disk so it survives session restarts.
|
|
@@ -62,12 +64,64 @@ function saveStuckState(basePath, state) {
|
|
|
62
64
|
debugLog("autoLoop", { phase: "save-stuck-state-failed", error: err instanceof Error ? err.message : String(err) });
|
|
63
65
|
}
|
|
64
66
|
}
|
|
67
|
+
// ── Custom workflow verification retry persistence ───────────────────────
|
|
68
|
+
// Custom workflows can request verification retries after a step runs. The
|
|
69
|
+
// retry budget must survive an auto-mode restart or a failing verifier can
|
|
70
|
+
// consume a fresh retry budget every session.
|
|
71
|
+
function customVerifyRetryStateDir(s) {
|
|
72
|
+
return s.activeRunDir ? join(s.activeRunDir, "runtime") : join(gsdRoot(s.basePath), "runtime");
|
|
73
|
+
}
|
|
74
|
+
function customVerifyRetryStatePath(s) {
|
|
75
|
+
return join(customVerifyRetryStateDir(s), "custom-verify-retries.json");
|
|
76
|
+
}
|
|
77
|
+
function hydrateCustomVerifyRetryCounts(s) {
|
|
78
|
+
if (s.verificationRetryCount.size > 0) {
|
|
79
|
+
return s.verificationRetryCount;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const raw = JSON.parse(readFileSync(customVerifyRetryStatePath(s), "utf-8"));
|
|
83
|
+
const counts = raw && typeof raw === "object" && raw.counts && typeof raw.counts === "object"
|
|
84
|
+
? raw.counts
|
|
85
|
+
: {};
|
|
86
|
+
for (const [key, value] of Object.entries(counts)) {
|
|
87
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
88
|
+
s.verificationRetryCount.set(key, Math.floor(value));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
debugLog("autoLoop", { phase: "load-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
|
|
94
|
+
}
|
|
95
|
+
return s.verificationRetryCount;
|
|
96
|
+
}
|
|
97
|
+
function saveCustomVerifyRetryCounts(s) {
|
|
98
|
+
const retryCounts = s.verificationRetryCount;
|
|
99
|
+
const filePath = customVerifyRetryStatePath(s);
|
|
100
|
+
try {
|
|
101
|
+
if (!retryCounts || retryCounts.size === 0) {
|
|
102
|
+
unlinkSync(filePath);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
mkdirSync(customVerifyRetryStateDir(s), { recursive: true });
|
|
106
|
+
atomicWriteSync(filePath, JSON.stringify({
|
|
107
|
+
counts: Object.fromEntries(retryCounts),
|
|
108
|
+
updatedAt: new Date().toISOString(),
|
|
109
|
+
}) + "\n");
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
const code = err && typeof err === "object" && "code" in err ? err.code : undefined;
|
|
113
|
+
if (code !== "ENOENT") {
|
|
114
|
+
debugLog("autoLoop", { phase: "save-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
65
118
|
// ── Memory pressure monitoring (#3331) ──────────────────────────────────
|
|
66
119
|
// Check heap usage every N iterations and trigger graceful shutdown before
|
|
67
120
|
// the OS OOM killer sends SIGKILL. The threshold is 90% of the V8 heap
|
|
68
121
|
// limit (--max-old-space-size or default ~1.5-4GB depending on platform).
|
|
69
122
|
const MEMORY_CHECK_INTERVAL = 5; // check every 5 iterations
|
|
70
123
|
const MEMORY_PRESSURE_THRESHOLD = 0.85; // 85% of heap limit
|
|
124
|
+
const MAX_CUSTOM_ENGINE_VERIFY_RETRIES = 3;
|
|
71
125
|
function checkMemoryPressure() {
|
|
72
126
|
const mem = process.memoryUsage();
|
|
73
127
|
// v8.getHeapStatistics() gives heap_size_limit but requires import
|
|
@@ -360,15 +414,41 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
360
414
|
break;
|
|
361
415
|
}
|
|
362
416
|
if (verifyResult === "retry") {
|
|
363
|
-
|
|
417
|
+
const recoveryKey = `${iterData.unitType}/${iterData.unitId}`;
|
|
418
|
+
const retryCounts = hydrateCustomVerifyRetryCounts(s);
|
|
419
|
+
const attempts = (retryCounts.get(recoveryKey) ?? 0) + 1;
|
|
420
|
+
retryCounts.set(recoveryKey, attempts);
|
|
421
|
+
saveCustomVerifyRetryCounts(s);
|
|
422
|
+
debugLog("autoLoop", { phase: "custom-engine-verify-retry", iteration, unitId: iterData.unitId, attempts });
|
|
364
423
|
deps.uokObserver?.onPhaseResult("custom-engine", "retry", {
|
|
365
424
|
unitType: iterData.unitType,
|
|
366
425
|
unitId: iterData.unitId,
|
|
426
|
+
attempts,
|
|
367
427
|
});
|
|
428
|
+
if (attempts > MAX_CUSTOM_ENGINE_VERIFY_RETRIES) {
|
|
429
|
+
const recovery = await policy.recover(iterData.unitType, iterData.unitId, { basePath: s.basePath });
|
|
430
|
+
if (recovery.outcome === "pause") {
|
|
431
|
+
await deps.pauseAuto(ctx, pi);
|
|
432
|
+
finishTurn("paused", "manual-attention", recovery.reason ?? "custom-engine-verify-retry-exhausted");
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
if (recovery.outcome === "skip") {
|
|
436
|
+
await deps.stopAuto(ctx, pi, recovery.reason ??
|
|
437
|
+
`Custom workflow verification for ${iterData.unitId} requested skip after retry exhaustion, but the custom engine cannot reconcile skipped steps.`);
|
|
438
|
+
finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
const exhaustedReason = `Custom workflow verification for ${iterData.unitId} requested retry ${attempts} times without passing.`;
|
|
442
|
+
await deps.stopAuto(ctx, pi, recovery.outcome === "stop" && recovery.reason ? recovery.reason : exhaustedReason);
|
|
443
|
+
finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
|
|
444
|
+
break;
|
|
445
|
+
}
|
|
368
446
|
finishTurn("retry");
|
|
369
447
|
continue;
|
|
370
448
|
}
|
|
371
449
|
// Verification passed — mark step complete
|
|
450
|
+
s.verificationRetryCount?.delete(`${iterData.unitType}/${iterData.unitId}`);
|
|
451
|
+
saveCustomVerifyRetryCounts(s);
|
|
372
452
|
debugLog("autoLoop", { phase: "custom-engine-reconcile", iteration, unitId: iterData.unitId });
|
|
373
453
|
const reconcileResult = await engine.reconcile(engineState, {
|
|
374
454
|
unitType: iterData.unitType,
|
|
@@ -516,6 +596,48 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
516
596
|
// completion even on failure (#2344). Without this, errors in
|
|
517
597
|
// runFinalize leave the journal incomplete, making diagnosis harder.
|
|
518
598
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration, error: msg } });
|
|
599
|
+
// ── Pre-send model-policy block: not a retryable error (#4959 / #4850) ──
|
|
600
|
+
// The model-policy gate runs before the prompt is sent. When every
|
|
601
|
+
// candidate model is denied (cross-provider disabled + flat-rate
|
|
602
|
+
// baseline + tool-policy denial), retrying the same unit produces the
|
|
603
|
+
// same denial — burning the consecutive-error budget toward a 3-strike
|
|
604
|
+
// hard stop and corrupting auto-mode state. Pause for user attention
|
|
605
|
+
// instead, with the per-model deny reasons surfaced from the typed
|
|
606
|
+
// error.
|
|
607
|
+
if (loopErr instanceof ModelPolicyDispatchBlockedError) {
|
|
608
|
+
debugLog("autoLoop", {
|
|
609
|
+
phase: "model-policy-blocked",
|
|
610
|
+
iteration,
|
|
611
|
+
unitType: loopErr.unitType,
|
|
612
|
+
unitId: loopErr.unitId,
|
|
613
|
+
reasons: loopErr.reasons,
|
|
614
|
+
});
|
|
615
|
+
ctx.ui.notify(`Auto-mode paused: model-policy denied dispatch for ${loopErr.unitType}/${loopErr.unitId}. ${msg}`, "error");
|
|
616
|
+
deps.emitJournalEvent({
|
|
617
|
+
ts: new Date().toISOString(),
|
|
618
|
+
flowId,
|
|
619
|
+
seq: nextSeq(),
|
|
620
|
+
eventType: "unit-end",
|
|
621
|
+
data: {
|
|
622
|
+
unitType: loopErr.unitType,
|
|
623
|
+
unitId: loopErr.unitId,
|
|
624
|
+
status: "blocked",
|
|
625
|
+
reason: "model-policy-dispatch-blocked",
|
|
626
|
+
reasons: loopErr.reasons,
|
|
627
|
+
},
|
|
628
|
+
});
|
|
629
|
+
// Carry the blocked unit identity into the turn-result observer:
|
|
630
|
+
// the throw originated inside dispatch, so observedUnitType/Id were
|
|
631
|
+
// not assigned by the success path at lines 453/631/647 — but the
|
|
632
|
+
// typed error already names the unit (#4959 / CodeRabbit).
|
|
633
|
+
observedUnitType = loopErr.unitType;
|
|
634
|
+
observedUnitId = loopErr.unitId;
|
|
635
|
+
await deps.pauseAuto(ctx, pi);
|
|
636
|
+
finishTurn("paused", "manual-attention", msg);
|
|
637
|
+
// Do NOT increment consecutiveErrors — the failure is configuration,
|
|
638
|
+
// not a transient runtime fault.
|
|
639
|
+
break;
|
|
640
|
+
}
|
|
519
641
|
// ── Infrastructure errors: immediate stop, no retry ──
|
|
520
642
|
// These are unrecoverable (disk full, OOM, etc.). Retrying just burns
|
|
521
643
|
// LLM budget on guaranteed failures.
|
|
@@ -11,12 +11,12 @@ import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from ".
|
|
|
11
11
|
import { detectStuck } from "./detect-stuck.js";
|
|
12
12
|
import { runUnit } from "./run-unit.js";
|
|
13
13
|
import { debugLog } from "../debug-logger.js";
|
|
14
|
-
import { PROJECT_FILES } from "../detection.js";
|
|
14
|
+
import { PROJECT_FILES, hasProjectFileInAncestor } from "../detection.js";
|
|
15
15
|
import { MergeConflictError } from "../git-service.js";
|
|
16
16
|
import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
|
|
17
17
|
import { pauseAutoForProviderError } from "../provider-error-pause.js";
|
|
18
18
|
import { resumeAutoAfterProviderDelay } from "../bootstrap/provider-error-resume.js";
|
|
19
|
-
import { join, basename
|
|
19
|
+
import { join, basename } from "node:path";
|
|
20
20
|
import { existsSync, cpSync, readdirSync } from "node:fs";
|
|
21
21
|
import { logWarning, logError, _resetLogs, drainLogs, drainAndSummarize, formatForNotification, hasAnyIssues, } from "../workflow-logger.js";
|
|
22
22
|
import { gsdRoot } from "../paths.js";
|
|
@@ -27,7 +27,7 @@ import { withTimeout, FINALIZE_PRE_TIMEOUT_MS, FINALIZE_POST_TIMEOUT_MS } from "
|
|
|
27
27
|
import { getEligibleSlices } from "../slice-parallel-eligibility.js";
|
|
28
28
|
import { startSliceParallel } from "../slice-parallel-orchestrator.js";
|
|
29
29
|
import { isDbAvailable, getMilestoneSlices } from "../gsd-db.js";
|
|
30
|
-
import { ensurePlanV2Graph } from "../uok/plan-v2.js";
|
|
30
|
+
import { ensurePlanV2Graph, isMissingFinalizedContextResult } from "../uok/plan-v2.js";
|
|
31
31
|
import { resolveUokFlags } from "../uok/flags.js";
|
|
32
32
|
import { UokGateRunner } from "../uok/gate-runner.js";
|
|
33
33
|
import { resetEvidence, loadEvidenceFromDisk } from "../safety/evidence-collector.js";
|
|
@@ -127,6 +127,7 @@ async function generateMilestoneReport(s, ctx, milestoneId) {
|
|
|
127
127
|
async function closeoutAndStop(ctx, pi, s, deps, reason) {
|
|
128
128
|
if (s.currentUnit) {
|
|
129
129
|
await deps.closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
|
|
130
|
+
s.currentUnit = null;
|
|
130
131
|
}
|
|
131
132
|
await deps.stopAuto(ctx, pi, reason);
|
|
132
133
|
}
|
|
@@ -296,27 +297,42 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
296
297
|
const compiled = ensurePlanV2Graph(s.basePath, state);
|
|
297
298
|
if (!compiled.ok) {
|
|
298
299
|
const reason = compiled.reason ?? "Plan v2 compilation failed";
|
|
300
|
+
if (isMissingFinalizedContextResult(compiled)) {
|
|
301
|
+
await runPreDispatchGate({
|
|
302
|
+
gateId: "plan-v2-gate",
|
|
303
|
+
gateType: "policy",
|
|
304
|
+
outcome: "pass",
|
|
305
|
+
failureClass: "none",
|
|
306
|
+
rationale: "plan v2 missing context recovery deferred to dispatch",
|
|
307
|
+
findings: reason,
|
|
308
|
+
milestoneId: state.activeMilestone?.id ?? undefined,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
await runPreDispatchGate({
|
|
313
|
+
gateId: "plan-v2-gate",
|
|
314
|
+
gateType: "policy",
|
|
315
|
+
outcome: "manual-attention",
|
|
316
|
+
failureClass: "manual-attention",
|
|
317
|
+
rationale: "plan v2 compile gate failed",
|
|
318
|
+
findings: reason,
|
|
319
|
+
milestoneId: state.activeMilestone?.id ?? undefined,
|
|
320
|
+
});
|
|
321
|
+
ctx.ui.notify(`Plan gate failed-closed: ${reason}\n\nIf this keeps happening, try: /gsd doctor heal`, "error");
|
|
322
|
+
await deps.pauseAuto(ctx, pi);
|
|
323
|
+
return { action: "break", reason: "plan-v2-gate-failed" };
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (compiled.ok) {
|
|
299
327
|
await runPreDispatchGate({
|
|
300
328
|
gateId: "plan-v2-gate",
|
|
301
329
|
gateType: "policy",
|
|
302
|
-
outcome: "
|
|
303
|
-
failureClass: "
|
|
304
|
-
rationale: "plan v2 compile gate
|
|
305
|
-
findings: reason,
|
|
330
|
+
outcome: "pass",
|
|
331
|
+
failureClass: "none",
|
|
332
|
+
rationale: "plan v2 compile gate passed",
|
|
306
333
|
milestoneId: state.activeMilestone?.id ?? undefined,
|
|
307
334
|
});
|
|
308
|
-
ctx.ui.notify(`Plan gate failed-closed: ${reason}\n\nIf this keeps happening, try: /gsd doctor heal`, "error");
|
|
309
|
-
await deps.pauseAuto(ctx, pi);
|
|
310
|
-
return { action: "break", reason: "plan-v2-gate-failed" };
|
|
311
335
|
}
|
|
312
|
-
await runPreDispatchGate({
|
|
313
|
-
gateId: "plan-v2-gate",
|
|
314
|
-
gateType: "policy",
|
|
315
|
-
outcome: "pass",
|
|
316
|
-
failureClass: "none",
|
|
317
|
-
rationale: "plan v2 compile gate passed",
|
|
318
|
-
milestoneId: state.activeMilestone?.id ?? undefined,
|
|
319
|
-
});
|
|
320
336
|
}
|
|
321
337
|
deps.syncCmuxSidebar(prefs, state);
|
|
322
338
|
let mid = state.activeMilestone?.id;
|
|
@@ -667,10 +683,14 @@ export async function runDispatch(ic, preData, loopState) {
|
|
|
667
683
|
const pauseAfterUatDispatch = dispatchResult.pauseAfterDispatch ?? false;
|
|
668
684
|
// ── Sliding-window stuck detection with graduated recovery ──
|
|
669
685
|
const derivedKey = `${unitType}/${unitId}`;
|
|
686
|
+
// Always record this dispatch in the sliding window so detectStuck() has
|
|
687
|
+
// accurate history. Skipping the push when pendingVerificationRetry is set
|
|
688
|
+
// caused infinite artifact-retry loops to be invisible to stuck detection
|
|
689
|
+
// (#2007). Only the *response* to a stuck signal is suppressed during retries.
|
|
690
|
+
loopState.recentUnits.push({ key: derivedKey });
|
|
691
|
+
if (loopState.recentUnits.length > STUCK_WINDOW_SIZE)
|
|
692
|
+
loopState.recentUnits.shift();
|
|
670
693
|
if (!s.pendingVerificationRetry) {
|
|
671
|
-
loopState.recentUnits.push({ key: derivedKey });
|
|
672
|
-
if (loopState.recentUnits.length > STUCK_WINDOW_SIZE)
|
|
673
|
-
loopState.recentUnits.shift();
|
|
674
694
|
const stuckSignal = detectStuck(loopState.recentUnits);
|
|
675
695
|
if (stuckSignal) {
|
|
676
696
|
debugLog("autoLoop", {
|
|
@@ -996,22 +1016,9 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
996
1016
|
// Monorepo support (#2347): if no project files in the worktree directory,
|
|
997
1017
|
// walk parent directories up to the filesystem root. In monorepos,
|
|
998
1018
|
// package.json / Cargo.toml etc. live in a parent directory.
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
const { root } = parsePath(checkDir);
|
|
1003
|
-
while (checkDir !== root) {
|
|
1004
|
-
// Stop at git repository boundary — ancestors above the repo root
|
|
1005
|
-
// (e.g. ~ or /usr/local) may contain unrelated project files.
|
|
1006
|
-
if (deps.existsSync(join(checkDir, ".git")))
|
|
1007
|
-
break;
|
|
1008
|
-
if (PROJECT_FILES.some((f) => deps.existsSync(join(checkDir, f)))) {
|
|
1009
|
-
hasProjectFileInParent = true;
|
|
1010
|
-
break;
|
|
1011
|
-
}
|
|
1012
|
-
checkDir = dirname(checkDir);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1019
|
+
const hasProjectFileInParent = !hasProjectFile && !hasSrcDir && !hasXcodeBundle
|
|
1020
|
+
? hasProjectFileInAncestor(s.basePath, deps.existsSync)
|
|
1021
|
+
: false;
|
|
1015
1022
|
if (!hasProjectFile && !hasSrcDir && !hasXcodeBundle && !hasProjectFileInParent) {
|
|
1016
1023
|
// Greenfield projects won't have project files yet — the first task creates them.
|
|
1017
1024
|
// Log a warning but allow execution to proceed. The .git check above is sufficient
|
|
@@ -1241,9 +1248,18 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1241
1248
|
}
|
|
1242
1249
|
if (unitResult.status === "cancelled") {
|
|
1243
1250
|
const errorCategory = unitResult.errorContext?.category;
|
|
1244
|
-
// Provider-error pause:
|
|
1245
|
-
//
|
|
1251
|
+
// Provider-error pause: agent_end recovery normally pauses before this
|
|
1252
|
+
// branch. Provider readiness failures happen before dispatch, so pause here
|
|
1253
|
+
// if nothing upstream already did.
|
|
1246
1254
|
if (errorCategory === "provider") {
|
|
1255
|
+
if (!s.paused) {
|
|
1256
|
+
const detail = unitResult.errorContext?.message ?? `Provider unavailable for ${unitType} ${unitId}`;
|
|
1257
|
+
await pauseAutoForProviderError(ctx.ui, detail, () => deps.pauseAuto(ctx, pi), {
|
|
1258
|
+
isRateLimit: false,
|
|
1259
|
+
isTransient: Boolean(unitResult.errorContext?.isTransient),
|
|
1260
|
+
retryAfterMs: unitResult.errorContext?.retryAfterMs,
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1247
1263
|
await emitCancelledUnitEnd(ic, unitType, unitId, unitStartSeq, unitResult.errorContext);
|
|
1248
1264
|
debugLog("autoLoop", { phase: "exit", reason: "provider-pause", isTransient: unitResult.errorContext?.isTransient });
|
|
1249
1265
|
return { action: "break", reason: "provider-pause" };
|
|
@@ -1537,6 +1553,8 @@ export async function runFinalize(ic, iterData, loopState, sidecarItem) {
|
|
|
1537
1553
|
}
|
|
1538
1554
|
// Both pre and post verification completed without timeout — reset counter
|
|
1539
1555
|
loopState.consecutiveFinalizeTimeouts = 0;
|
|
1556
|
+
s.currentUnit = null;
|
|
1557
|
+
clearCurrentPhase();
|
|
1540
1558
|
// Surface accumulated workflow-logger issues for this unit to the user.
|
|
1541
1559
|
// Warnings/errors logged during the unit are buffered in the logger and
|
|
1542
1560
|
// drained here so the user sees a single consolidated post-unit alert.
|
|
@@ -16,9 +16,7 @@
|
|
|
16
16
|
* `let` or `var` declarations.
|
|
17
17
|
*/
|
|
18
18
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
19
|
-
export const MAX_UNIT_DISPATCHES = 3;
|
|
20
19
|
export const STUB_RECOVERY_THRESHOLD = 2;
|
|
21
|
-
export const MAX_LIFETIME_DISPATCHES = 6;
|
|
22
20
|
export const NEW_SESSION_TIMEOUT_MS = 120_000;
|
|
23
21
|
// ─── AutoSession ─────────────────────────────────────────────────────────────
|
|
24
22
|
export class AutoSession {
|
|
@@ -105,6 +103,11 @@ export class AutoSession {
|
|
|
105
103
|
/** Set to true after phases.ts successfully calls mergeAndExit, so that
|
|
106
104
|
* stopAuto does not attempt the same merge a second time (#2645). */
|
|
107
105
|
milestoneMergedInPhases = false;
|
|
106
|
+
// #4765 — slice-cadence collapse: main-branch SHAs at the moment each
|
|
107
|
+
// milestone's first slice merge began. Used by resquashMilestoneOnMain at
|
|
108
|
+
// milestone completion to collapse N slice commits into one. Cleared when
|
|
109
|
+
// the milestone finishes (or resquash runs).
|
|
110
|
+
milestoneStartShas = new Map();
|
|
108
111
|
// ── Dispatch circuit breakers ──────────────────────────────────────
|
|
109
112
|
rewriteAttemptCount = 0;
|
|
110
113
|
/** Tracks consecutive bootstrap attempts that found phase === "complete".
|
|
@@ -221,6 +224,7 @@ export class AutoSession {
|
|
|
221
224
|
this.lastGitActionStatus = null;
|
|
222
225
|
this.isolationDegraded = false;
|
|
223
226
|
this.milestoneMergedInPhases = false;
|
|
227
|
+
this.milestoneStartShas = new Map();
|
|
224
228
|
this.checkpointSha = null;
|
|
225
229
|
// Signal handler
|
|
226
230
|
this.sigtermHandler = null;
|
|
@@ -17,11 +17,47 @@ import { parseRoadmap } from "./parsers-legacy.js";
|
|
|
17
17
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
18
18
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
19
19
|
import { join } from "node:path";
|
|
20
|
-
import { hasImplementationArtifacts
|
|
20
|
+
import { hasImplementationArtifacts } from "./auto-recovery.js";
|
|
21
|
+
import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
|
|
21
22
|
import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildRefineSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, buildParallelResearchSlicesPrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
|
|
22
23
|
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
23
24
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
24
25
|
import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
|
|
26
|
+
import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
|
|
27
|
+
import { EXECUTION_ENTRY_PHASES, hasFinalizedMilestoneContext } from "./uok/plan-v2.js";
|
|
28
|
+
import { isAutoActive } from "./auto.js";
|
|
29
|
+
import { markDepthVerified } from "./bootstrap/write-gate.js";
|
|
30
|
+
let reassessmentChecker = checkNeedsReassessment;
|
|
31
|
+
export function setReassessmentCheckerForTest(checker) {
|
|
32
|
+
const previous = reassessmentChecker;
|
|
33
|
+
reassessmentChecker = checker;
|
|
34
|
+
return () => {
|
|
35
|
+
reassessmentChecker = previous;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function readUatGateVerdict(basePath, mid, sliceId) {
|
|
39
|
+
const uatFile = resolveSliceFile(basePath, mid, sliceId, "UAT");
|
|
40
|
+
const assessmentFile = resolveSliceFile(basePath, mid, sliceId, "ASSESSMENT");
|
|
41
|
+
const uatContent = uatFile ? await loadFile(uatFile) : null;
|
|
42
|
+
const uatType = uatContent ? extractUatType(uatContent) : undefined;
|
|
43
|
+
const assessmentContent = assessmentFile ? await loadFile(assessmentFile) : null;
|
|
44
|
+
if (assessmentContent) {
|
|
45
|
+
const assessmentVerdict = extractVerdict(assessmentContent);
|
|
46
|
+
if (assessmentVerdict) {
|
|
47
|
+
return {
|
|
48
|
+
verdict: assessmentVerdict,
|
|
49
|
+
uatType: uatType ?? extractUatType(assessmentContent),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (uatContent) {
|
|
54
|
+
const legacyUatVerdict = extractVerdict(uatContent);
|
|
55
|
+
if (legacyUatVerdict) {
|
|
56
|
+
return { verdict: legacyUatVerdict, uatType };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
25
61
|
function missingSliceStop(mid, phase) {
|
|
26
62
|
return {
|
|
27
63
|
action: "stop",
|
|
@@ -155,6 +191,45 @@ export const DISPATCH_RULES = [
|
|
|
155
191
|
};
|
|
156
192
|
},
|
|
157
193
|
},
|
|
194
|
+
{
|
|
195
|
+
// #4671 — Recovery path for execution-entry phases with missing CONTEXT.md.
|
|
196
|
+
//
|
|
197
|
+
// Once `deriveStateFromDb` returns an execution-entry phase (executing /
|
|
198
|
+
// summarizing / validating-milestone / completing-milestone), the
|
|
199
|
+
// pre-planning guard at `pre-planning (no context) → discuss-milestone`
|
|
200
|
+
// no longer fires. The plan-v2 gate correctly detects the missing context
|
|
201
|
+
// but can only block — it cannot redispatch. Without this rule the
|
|
202
|
+
// milestone is stuck until `/gsd doctor heal` repairs it (and heal
|
|
203
|
+
// historically missed this check too).
|
|
204
|
+
//
|
|
205
|
+
// Fire BEFORE the execution-entry phase rules so we redispatch to
|
|
206
|
+
// `discuss-milestone` instead of hitting the plan-v2 gate.
|
|
207
|
+
name: "execution-entry phase (no context) → discuss-milestone",
|
|
208
|
+
match: async ({ state, mid, midTitle, basePath, structuredQuestionsAvailable }) => {
|
|
209
|
+
if (!EXECUTION_ENTRY_PHASES.has(state.phase))
|
|
210
|
+
return null;
|
|
211
|
+
// Align with the plan-v2 gate's lookup semantics: whitespace-only counts
|
|
212
|
+
// as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
|
|
213
|
+
if (hasFinalizedMilestoneContext(basePath, mid))
|
|
214
|
+
return null;
|
|
215
|
+
// H6 fix (#4973): In auto-mode there is no human to answer the
|
|
216
|
+
// depth-verification ask_user_questions, so the write-gate deadlocks.
|
|
217
|
+
// Pre-mark the milestone as depth-verified so gsd_summary_save({artifact_type:"CONTEXT"})
|
|
218
|
+
// is not blocked. Safe ordering: session_switch fires clearDiscussionFlowState()
|
|
219
|
+
// (register-hooks.ts:106) before before_agent_start, which fires before resolveDispatch
|
|
220
|
+
// reaches this match fn — so this call always happens after any session-switch reset.
|
|
221
|
+
// Interactive sessions (isAutoActive()===false) are unaffected.
|
|
222
|
+
if (isAutoActive()) {
|
|
223
|
+
markDepthVerified(mid, basePath);
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
action: "dispatch",
|
|
227
|
+
unitType: "discuss-milestone",
|
|
228
|
+
unitId: mid,
|
|
229
|
+
prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable),
|
|
230
|
+
};
|
|
231
|
+
},
|
|
232
|
+
},
|
|
158
233
|
{
|
|
159
234
|
name: "summarizing → complete-slice",
|
|
160
235
|
match: async ({ state, mid, midTitle, basePath }) => {
|
|
@@ -205,27 +280,29 @@ export const DISPATCH_RULES = [
|
|
|
205
280
|
// Only applies when UAT dispatch is enabled
|
|
206
281
|
if (!prefs?.uat_dispatch)
|
|
207
282
|
return null;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
let completedSliceIds;
|
|
283
|
+
// DB-first: prefer closed slices from DB; fall back to ROADMAP on disk.
|
|
284
|
+
let closedSliceIds;
|
|
211
285
|
if (isDbAvailable()) {
|
|
212
|
-
|
|
213
|
-
.filter(s => s.status
|
|
286
|
+
closedSliceIds = getMilestoneSlices(mid)
|
|
287
|
+
.filter(s => isClosedStatus(s.status))
|
|
214
288
|
.map(s => s.id);
|
|
215
289
|
}
|
|
216
290
|
else {
|
|
217
|
-
|
|
291
|
+
// Filesystem fallback for degraded / unmigrated projects.
|
|
292
|
+
// `slice.done` in the parsed ROADMAP is the disk-level closed signal.
|
|
293
|
+
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
294
|
+
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
295
|
+
if (!roadmapContent)
|
|
296
|
+
return null;
|
|
297
|
+
const roadmap = parseRoadmap(roadmapContent);
|
|
298
|
+
closedSliceIds = roadmap.slices.filter(s => s.done).map(s => s.id);
|
|
218
299
|
}
|
|
219
|
-
for (const sliceId of
|
|
220
|
-
const
|
|
221
|
-
if (!
|
|
300
|
+
for (const sliceId of closedSliceIds) {
|
|
301
|
+
const result = await readUatGateVerdict(basePath, mid, sliceId);
|
|
302
|
+
if (!result)
|
|
222
303
|
continue;
|
|
223
|
-
const
|
|
224
|
-
if (!
|
|
225
|
-
continue;
|
|
226
|
-
const verdict = extractVerdict(content);
|
|
227
|
-
const uatType = extractUatType(content);
|
|
228
|
-
if (verdict && !isAcceptableUatVerdict(verdict, uatType)) {
|
|
304
|
+
const { verdict, uatType } = result;
|
|
305
|
+
if (!isAcceptableUatVerdict(verdict, uatType)) {
|
|
229
306
|
return {
|
|
230
307
|
action: "stop",
|
|
231
308
|
reason: `UAT verdict for ${sliceId} is "${verdict}" — blocking progression until resolved.\nReview the UAT result and update the verdict to PASS, or re-run /gsd auto after fixing.`,
|
|
@@ -241,12 +318,16 @@ export const DISPATCH_RULES = [
|
|
|
241
318
|
match: async ({ state, mid, midTitle, basePath, prefs }) => {
|
|
242
319
|
if (prefs?.phases?.skip_reassess)
|
|
243
320
|
return null;
|
|
244
|
-
// Default reassess_after_slice to
|
|
245
|
-
// is
|
|
246
|
-
|
|
321
|
+
// Default reassess_after_slice to false per ADR-003 §4 — most reassess
|
|
322
|
+
// units conclude "roadmap is fine" and burn a session for no change.
|
|
323
|
+
// The plan-slice prompt now carries a reassessment preamble so the
|
|
324
|
+
// next slice's planner does JIT roadmap verification at zero extra
|
|
325
|
+
// cost. Opt-in via explicit `reassess_after_slice: true` (e.g.
|
|
326
|
+
// burn-max profile) when you want the dedicated reassess session.
|
|
327
|
+
const reassessEnabled = prefs?.phases?.reassess_after_slice ?? false;
|
|
247
328
|
if (!reassessEnabled)
|
|
248
329
|
return null;
|
|
249
|
-
const needsReassess = await
|
|
330
|
+
const needsReassess = await reassessmentChecker(basePath, mid, state);
|
|
250
331
|
if (!needsReassess)
|
|
251
332
|
return null;
|
|
252
333
|
return {
|
|
@@ -262,6 +343,12 @@ export const DISPATCH_RULES = [
|
|
|
262
343
|
match: async ({ state, mid, midTitle, basePath, structuredQuestionsAvailable }) => {
|
|
263
344
|
if (state.phase !== "needs-discussion")
|
|
264
345
|
return null;
|
|
346
|
+
// H6 fix (#4973): auto-mark depth-verified so the write-gate does not
|
|
347
|
+
// deadlock in non-interactive (auto-mode) runs. See ordering note at
|
|
348
|
+
// "execution-entry phase (no context) → discuss-milestone" above.
|
|
349
|
+
if (isAutoActive()) {
|
|
350
|
+
markDepthVerified(mid, basePath);
|
|
351
|
+
}
|
|
265
352
|
return {
|
|
266
353
|
action: "dispatch",
|
|
267
354
|
unitType: "discuss-milestone",
|
|
@@ -279,6 +366,12 @@ export const DISPATCH_RULES = [
|
|
|
279
366
|
const hasContext = !!(contextFile && (await loadFile(contextFile)));
|
|
280
367
|
if (hasContext)
|
|
281
368
|
return null; // fall through to next rule
|
|
369
|
+
// H6 fix (#4973): auto-mark depth-verified so the write-gate does not
|
|
370
|
+
// deadlock in non-interactive (auto-mode) runs. See ordering note at
|
|
371
|
+
// "execution-entry phase (no context) → discuss-milestone" above.
|
|
372
|
+
if (isAutoActive()) {
|
|
373
|
+
markDepthVerified(mid, basePath);
|
|
374
|
+
}
|
|
282
375
|
return {
|
|
283
376
|
action: "dispatch",
|
|
284
377
|
unitType: "discuss-milestone",
|
|
@@ -352,6 +445,12 @@ export const DISPATCH_RULES = [
|
|
|
352
445
|
return null;
|
|
353
446
|
if (prefs?.phases?.skip_research || prefs?.phases?.skip_slice_research)
|
|
354
447
|
return null;
|
|
448
|
+
// #4781 phase 2: trivial-scope milestones skip dedicated slice research.
|
|
449
|
+
// plan-slice absorbs the lightweight discovery a trivial deliverable
|
|
450
|
+
// needs. Null result (DB unavailable / unknown) falls through to today's
|
|
451
|
+
// behavior.
|
|
452
|
+
if (await getMilestonePipelineVariant(mid) === "trivial")
|
|
453
|
+
return null;
|
|
355
454
|
// Load roadmap to find all slices
|
|
356
455
|
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
357
456
|
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
@@ -401,6 +500,9 @@ export const DISPATCH_RULES = [
|
|
|
401
500
|
// Phase skip: skip research when preference or profile says so
|
|
402
501
|
if (prefs?.phases?.skip_research || prefs?.phases?.skip_slice_research)
|
|
403
502
|
return null;
|
|
503
|
+
// #4781 phase 2: trivial-scope milestones skip dedicated slice research.
|
|
504
|
+
if (await getMilestonePipelineVariant(mid) === "trivial")
|
|
505
|
+
return null;
|
|
404
506
|
if (!state.activeSlice)
|
|
405
507
|
return missingSliceStop(mid, state.phase);
|
|
406
508
|
const sid = state.activeSlice.id;
|
|
@@ -682,22 +784,29 @@ export const DISPATCH_RULES = [
|
|
|
682
784
|
level: "error",
|
|
683
785
|
};
|
|
684
786
|
}
|
|
685
|
-
//
|
|
686
|
-
|
|
787
|
+
// #4781 phase 2: trivial-scope milestones skip the dedicated validate
|
|
788
|
+
// unit — complete-milestone's own verification steps (3/4/5 in the
|
|
789
|
+
// closer prompt) are sufficient proof for contained deliverables.
|
|
790
|
+
const trivialVariant = await getMilestonePipelineVariant(mid) === "trivial";
|
|
791
|
+
// Skip preference OR trivial scope: write a minimal pass-through VALIDATION file.
|
|
792
|
+
if (prefs?.phases?.skip_milestone_validation || trivialVariant) {
|
|
687
793
|
const mDir = resolveMilestonePath(basePath, mid);
|
|
688
794
|
if (mDir) {
|
|
689
795
|
if (!existsSync(mDir))
|
|
690
796
|
mkdirSync(mDir, { recursive: true });
|
|
691
797
|
const validationPath = join(mDir, buildMilestoneFileName(mid, "VALIDATION"));
|
|
798
|
+
const skipSource = trivialVariant
|
|
799
|
+
? "trivial-scope pipeline variant (#4781)"
|
|
800
|
+
: "`skip_milestone_validation` preference";
|
|
692
801
|
const content = [
|
|
693
802
|
"---",
|
|
694
803
|
"verdict: pass",
|
|
695
804
|
"remediation_round: 0",
|
|
696
805
|
"---",
|
|
697
806
|
"",
|
|
698
|
-
"# Milestone Validation (skipped
|
|
807
|
+
"# Milestone Validation (skipped)",
|
|
699
808
|
"",
|
|
700
|
-
|
|
809
|
+
`Milestone validation was skipped via ${skipSource}.`,
|
|
701
810
|
].join("\n");
|
|
702
811
|
writeFileSync(validationPath, content, "utf-8");
|
|
703
812
|
}
|
|
@@ -728,7 +837,7 @@ export const DISPATCH_RULES = [
|
|
|
728
837
|
}
|
|
729
838
|
const existingSummary = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
730
839
|
let summaryOutcome = "unknown";
|
|
731
|
-
if (existingSummary
|
|
840
|
+
if (existingSummary) {
|
|
732
841
|
const summaryContent = await loadFile(existingSummary);
|
|
733
842
|
if (summaryContent) {
|
|
734
843
|
summaryOutcome = classifyMilestoneSummaryContent(summaryContent);
|
|
@@ -764,7 +873,7 @@ export const DISPATCH_RULES = [
|
|
|
764
873
|
// Safety guard (#1703): verify the milestone produced implementation
|
|
765
874
|
// artifacts (non-.gsd/ files). A milestone with only plan files and
|
|
766
875
|
// zero implementation code should not be marked complete.
|
|
767
|
-
const artifactCheck = hasImplementationArtifacts(basePath);
|
|
876
|
+
const artifactCheck = hasImplementationArtifacts(basePath, mid);
|
|
768
877
|
if (artifactCheck === "absent") {
|
|
769
878
|
return {
|
|
770
879
|
action: "stop",
|
|
@@ -815,10 +924,14 @@ export const DISPATCH_RULES = [
|
|
|
815
924
|
// - success summary: reconcile DB and skip re-dispatch
|
|
816
925
|
// - failure summary: pause/fail-closed
|
|
817
926
|
// - unknown summary: pause/fail-closed
|
|
818
|
-
if (existingSummary
|
|
819
|
-
const milestone = getMilestone(mid);
|
|
820
|
-
const status = milestone?.status ?? "missing";
|
|
927
|
+
if (existingSummary) {
|
|
928
|
+
const milestone = isDbAvailable() ? getMilestone(mid) : null;
|
|
929
|
+
const status = milestone?.status ?? (isDbAvailable() ? "missing" : "unavailable");
|
|
821
930
|
if (summaryOutcome === "success") {
|
|
931
|
+
if (!isDbAvailable()) {
|
|
932
|
+
logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB is unavailable — skipping duplicate complete-milestone dispatch`);
|
|
933
|
+
return { action: "skip" };
|
|
934
|
+
}
|
|
822
935
|
try {
|
|
823
936
|
updateMilestoneStatus(mid, "complete", new Date().toISOString());
|
|
824
937
|
logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB status was "${status}" — reconciled DB to complete (#4658)`);
|