@opengsd/gsd-pi 1.2.0-dev.955e4da0 → 1.2.0-dev.d6c5343c
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/dist/cli-style.d.ts +17 -0
- package/dist/cli-style.js +28 -0
- package/dist/cli.js +1 -1
- package/dist/headless-events.d.ts +4 -2
- package/dist/headless-events.js +14 -34
- package/dist/models-resolver.d.ts +3 -13
- package/dist/models-resolver.js +3 -22
- package/dist/resource-loader.js +2 -14
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +5 -4
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
- package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
- package/dist/resources/extensions/async-jobs/index.js +65 -0
- package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
- package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
- package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
- package/dist/resources/extensions/bg-shell/overlay.js +9 -6
- package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
- package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
- package/dist/resources/extensions/bg-shell/utilities.js +3 -0
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
- package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
- package/dist/resources/extensions/browser-tools/index.js +69 -12
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +30 -4
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +61 -44
- package/dist/resources/extensions/gsd/auto/phases.js +2 -2
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +8 -32
- package/dist/resources/extensions/gsd/auto-dispatch.js +40 -57
- package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
- package/dist/resources/extensions/gsd/auto-post-unit.js +23 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
- package/dist/resources/extensions/gsd/auto-start.js +18 -15
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
- package/dist/resources/extensions/gsd/auto-verification.js +9 -28
- package/dist/resources/extensions/gsd/auto-worktree.js +30 -90
- package/dist/resources/extensions/gsd/auto.js +4 -13
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +212 -48
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +303 -77
- package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
- package/dist/resources/extensions/gsd/captures.js +4 -6
- package/dist/resources/extensions/gsd/consent-question.js +337 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- package/dist/resources/extensions/gsd/constants.js +0 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
- package/dist/resources/extensions/gsd/db/queries.js +26 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/doctor-environment.js +2 -6
- package/dist/resources/extensions/gsd/doctor-format.js +9 -6
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +13 -15
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- package/dist/resources/extensions/gsd/error-classifier.js +9 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
- package/dist/resources/extensions/gsd/files.js +33 -19
- package/dist/resources/extensions/gsd/guidance.js +158 -0
- package/dist/resources/extensions/gsd/guided-flow.js +17 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
- package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
- package/dist/resources/extensions/gsd/migrate/safety.js +4 -1
- package/dist/resources/extensions/gsd/milestone-closeout.js +13 -23
- package/dist/resources/extensions/gsd/notification-store.js +11 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +6 -4
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/paths.js +27 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
- package/dist/resources/extensions/gsd/preferences-models.js +14 -48
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +6 -4
- package/dist/resources/extensions/gsd/prompts/system.md +5 -2
- package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
- package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
- package/dist/resources/extensions/gsd/publication.js +87 -0
- package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/recovery-classification.js +37 -94
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/state.js +6 -20
- package/dist/resources/extensions/gsd/stop-notice.js +57 -0
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +20 -10
- package/dist/resources/extensions/gsd/tools/exec-tool.js +9 -7
- package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
- package/dist/resources/extensions/gsd/uat-policy.js +42 -16
- package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
- package/dist/resources/extensions/gsd/unit-registry.js +337 -0
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
- package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
- package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +15 -9
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
- package/dist/resources/extensions/gsd/worktree-root.js +11 -0
- package/dist/resources/extensions/gsd/worktree-session-state.js +4 -5
- package/dist/resources/extensions/search-the-web/native-search.js +5 -3
- package/dist/resources/extensions/shared/browser-contract.js +59 -0
- package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
- package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
- 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/react-loadable-manifest.json +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.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/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +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 +12 -12
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +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/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
- package/dist/web/standalone/package.json +1 -1
- package/dist/worktree-cli.js +3 -6
- package/dist/worktree-status-banner.js +7 -15
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +4 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +6 -3
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +17 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
- package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +3 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/README.md +1 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +35 -125
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +46 -120
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
- package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +5 -4
- package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
- package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
- package/src/resources/extensions/async-jobs/index.ts +79 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
- package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
- package/src/resources/extensions/bg-shell/overlay.ts +9 -5
- package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
- package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
- package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
- package/src/resources/extensions/bg-shell/utilities.ts +3 -0
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
- package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
- package/src/resources/extensions/browser-tools/index.ts +71 -13
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +34 -4
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +70 -46
- package/src/resources/extensions/gsd/auto/phases.ts +2 -2
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -32
- package/src/resources/extensions/gsd/auto-dispatch.ts +38 -52
- package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +25 -8
- package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
- package/src/resources/extensions/gsd/auto-start.ts +18 -17
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
- package/src/resources/extensions/gsd/auto-verification.ts +8 -26
- package/src/resources/extensions/gsd/auto-worktree.ts +30 -93
- package/src/resources/extensions/gsd/auto.ts +8 -15
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +251 -47
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +352 -84
- package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
- package/src/resources/extensions/gsd/captures.ts +4 -6
- package/src/resources/extensions/gsd/consent-question.ts +416 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- package/src/resources/extensions/gsd/constants.ts +0 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
- package/src/resources/extensions/gsd/db/queries.ts +37 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/doctor-environment.ts +2 -7
- package/src/resources/extensions/gsd/doctor-format.ts +12 -7
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +13 -15
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- package/src/resources/extensions/gsd/error-classifier.ts +11 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/files.ts +33 -12
- package/src/resources/extensions/gsd/guidance.ts +217 -0
- package/src/resources/extensions/gsd/guided-flow.ts +16 -2
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
- package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
- package/src/resources/extensions/gsd/migrate/safety.ts +4 -1
- package/src/resources/extensions/gsd/milestone-closeout.ts +13 -23
- package/src/resources/extensions/gsd/notification-store.ts +26 -3
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -4
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/paths.ts +33 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
- package/src/resources/extensions/gsd/preferences-models.ts +12 -47
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +6 -4
- package/src/resources/extensions/gsd/prompts/system.md +5 -2
- package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
- package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
- package/src/resources/extensions/gsd/publication.ts +122 -0
- package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/recovery-classification.ts +42 -96
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/state.ts +9 -21
- package/src/resources/extensions/gsd/stop-notice.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +101 -26
- package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
- package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +336 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +53 -11
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +73 -58
- package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
- package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +20 -10
- package/src/resources/extensions/gsd/tools/exec-tool.ts +8 -7
- package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
- package/src/resources/extensions/gsd/uat-policy.ts +62 -16
- package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
- package/src/resources/extensions/gsd/unit-registry.ts +412 -0
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
- package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
- package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +15 -9
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
- package/src/resources/extensions/gsd/worktree-root.ts +12 -0
- package/src/resources/extensions/gsd/worktree-session-state.ts +3 -5
- package/src/resources/extensions/search-the-web/native-search.ts +5 -3
- package/src/resources/extensions/shared/browser-contract.ts +66 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/references/executable-code.md +1 -1
- package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
- /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → jmTLg6xZmAuq_LIqKOxrH}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → jmTLg6xZmAuq_LIqKOxrH}/_ssgManifest.js +0 -0
|
@@ -42,21 +42,14 @@ import { isDbAvailable, getSlice, getTask, } from "../gsd-db.js";
|
|
|
42
42
|
import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
|
|
43
43
|
import { getErrorMessage } from "../error-utils.js";
|
|
44
44
|
import { logWarning } from "../workflow-logger.js";
|
|
45
|
+
import { normalizeRealPath } from "../paths.js";
|
|
46
|
+
import { buildDispatchKey, createDispatchHistory, STUCK_WINDOW_SIZE, } from "./dispatch-history.js";
|
|
45
47
|
import { existsSync, readFileSync } from "node:fs";
|
|
46
48
|
import { join } from "node:path";
|
|
47
49
|
import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
|
|
48
50
|
function now() {
|
|
49
51
|
return Date.now();
|
|
50
52
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Size of the dispatch-decision ring buffer used by the Auto Orchestration
|
|
53
|
-
* module's stuck-loop detector. When the same `${unitType}:${unitId}` key
|
|
54
|
-
* fills the window, advance() blocks with `action: "stop"`.
|
|
55
|
-
*
|
|
56
|
-
* Mirrors the legacy `STUCK_WINDOW_SIZE` in auto/phases.ts so behaviour is
|
|
57
|
-
* preserved across the eventual cutover (issue #5791).
|
|
58
|
-
*/
|
|
59
|
-
export const STUCK_WINDOW_SIZE = 6;
|
|
60
53
|
function noRemainingUnitsOutcome(stateSnapshot) {
|
|
61
54
|
if (stateSnapshot.phase === "complete") {
|
|
62
55
|
return {
|
|
@@ -244,7 +237,9 @@ export class AutoOrchestrator {
|
|
|
244
237
|
seq = 0;
|
|
245
238
|
lastAdvanceKey = null;
|
|
246
239
|
lastFinalizedUnitKey = null;
|
|
247
|
-
|
|
240
|
+
// Dispatch History module (#482): the dispatch-decision window with
|
|
241
|
+
// cross-session DB rehydration and full detect-stuck rules.
|
|
242
|
+
dispatchHistory;
|
|
248
243
|
// ADR-030 Phase Transition Invariant: the prior advance's reconciled Phase,
|
|
249
244
|
// the "from" endpoint of the edge check. In-memory; reset on start/resume/stop
|
|
250
245
|
// so the first advance of a session has no edge to assert.
|
|
@@ -260,6 +255,13 @@ export class AutoOrchestrator {
|
|
|
260
255
|
this.runtimeBasePath = context.runtimeBasePath;
|
|
261
256
|
this.s = context.session;
|
|
262
257
|
this.flowId = `auto-orchestrator-${Date.now()}`;
|
|
258
|
+
this.dispatchHistory = createDispatchHistory({
|
|
259
|
+
windowSize: STUCK_WINDOW_SIZE,
|
|
260
|
+
// Same stable scope the auto-loop uses for stuck-state persistence so
|
|
261
|
+
// rehydration reads the rows the dispatch ledger wrote for this project.
|
|
262
|
+
resolveScopeId: () => normalizeRealPath(this.s.scope?.workspace.projectRoot ??
|
|
263
|
+
(this.s.originalBasePath || this.s.basePath || this.runtimeBasePath)) || null,
|
|
264
|
+
});
|
|
263
265
|
}
|
|
264
266
|
// ── Live base-path resolution (was the wiring factory's getLiveDispatchBasePath) ──
|
|
265
267
|
getLiveDispatchBasePath() {
|
|
@@ -612,7 +614,7 @@ export class AutoOrchestrator {
|
|
|
612
614
|
* skipped result) instead of stopping.
|
|
613
615
|
*/
|
|
614
616
|
tryStuckArtifactRecovery(unitType, unitId) {
|
|
615
|
-
const key =
|
|
617
|
+
const key = buildDispatchKey(unitType, unitId);
|
|
616
618
|
if (this.lastStuckRecoveryKey === key)
|
|
617
619
|
return false; // already tried this episode
|
|
618
620
|
const basePath = this.getLiveDispatchBasePath();
|
|
@@ -627,7 +629,7 @@ export class AutoOrchestrator {
|
|
|
627
629
|
return false;
|
|
628
630
|
this.lastStuckRecoveryKey = key;
|
|
629
631
|
invalidateAllCaches();
|
|
630
|
-
this.
|
|
632
|
+
this.dispatchHistory.clearOnRecovery();
|
|
631
633
|
this.lastAdvanceKey = null;
|
|
632
634
|
this.lastFinalizedUnitKey = null;
|
|
633
635
|
return true;
|
|
@@ -653,7 +655,12 @@ export class AutoOrchestrator {
|
|
|
653
655
|
async start(_sessionContext) {
|
|
654
656
|
this.lastAdvanceKey = null;
|
|
655
657
|
this.lastFinalizedUnitKey = null;
|
|
656
|
-
|
|
658
|
+
// #482: the DB dispatch ledger is the source of truth across sessions.
|
|
659
|
+
// Discard any in-memory window and rebuild it from the ledger so a unit
|
|
660
|
+
// that was re-dispatched in previous sessions is detected as stuck here
|
|
661
|
+
// instead of silently re-dispatching forever.
|
|
662
|
+
this.dispatchHistory.clearOnRecovery();
|
|
663
|
+
this.dispatchHistory.rehydrate();
|
|
657
664
|
this.lastStuckRecoveryKey = null;
|
|
658
665
|
this.lastDerivedPhase = null;
|
|
659
666
|
this.status.phase = "running";
|
|
@@ -753,7 +760,7 @@ export class AutoOrchestrator {
|
|
|
753
760
|
this.status.phase = "paused";
|
|
754
761
|
this.status.activeUnit = undefined;
|
|
755
762
|
this.lastAdvanceKey = null;
|
|
756
|
-
this.
|
|
763
|
+
this.dispatchHistory.clearOnRecovery();
|
|
757
764
|
this.bumpTransition();
|
|
758
765
|
this.journalTransition({ name: "advance-blocked", reason: settlementBlock.reason });
|
|
759
766
|
this.postAdvanceRecord(settlementBlock);
|
|
@@ -769,7 +776,7 @@ export class AutoOrchestrator {
|
|
|
769
776
|
this.status.phase = "stopped";
|
|
770
777
|
this.status.activeUnit = undefined;
|
|
771
778
|
this.lastAdvanceKey = null;
|
|
772
|
-
this.
|
|
779
|
+
this.dispatchHistory.clearOnRecovery();
|
|
773
780
|
this.bumpTransition();
|
|
774
781
|
this.journalTransition({ name: "advance-stopped", reason: stopped.reason });
|
|
775
782
|
this.postAdvanceRecord(stopped);
|
|
@@ -817,16 +824,12 @@ export class AutoOrchestrator {
|
|
|
817
824
|
this.postAdvanceRecord(blocked);
|
|
818
825
|
return blocked;
|
|
819
826
|
}
|
|
820
|
-
|
|
821
|
-
// Record every dispatch decision in the ring buffer before pre-flight
|
|
827
|
+
// Record every dispatch decision in the history window before pre-flight
|
|
822
828
|
// checks so the stuck-loop detector observes the full decision history
|
|
823
829
|
// (including decisions that idempotency would otherwise short-circuit).
|
|
824
|
-
// The
|
|
825
|
-
this.
|
|
826
|
-
|
|
827
|
-
this.dispatchKeyWindow.shift();
|
|
828
|
-
}
|
|
829
|
-
const matchingCount = this.dispatchKeyWindow.filter((k) => k === nextKey).length;
|
|
830
|
+
// The window is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
|
|
831
|
+
const nextKey = this.dispatchHistory.recordDispatch(decision.unitType, decision.unitId);
|
|
832
|
+
const matchingCount = this.dispatchHistory.countMatching(nextKey);
|
|
830
833
|
if (this.lastFinalizedUnitKey === nextKey) {
|
|
831
834
|
// #442: the unit re-dispatched immediately after finalizing may have
|
|
832
835
|
// actually completed on disk with a stale DB. Verify + recover before
|
|
@@ -858,22 +861,30 @@ export class AutoOrchestrator {
|
|
|
858
861
|
// checks coexist: idempotency for the common immediate-repeat case,
|
|
859
862
|
// stuck-loop for the saturated-window case.
|
|
860
863
|
if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
|
|
864
|
+
// Unit already active — benign no-op. Return skipped so the loop re-polls
|
|
865
|
+
// without cancelling the in-flight unit (blocked+pause would force-cancel it).
|
|
861
866
|
this.clearPendingDispatch();
|
|
862
|
-
const
|
|
867
|
+
const skipped = { kind: "skipped", reason: "idempotent advance: unit already active" };
|
|
863
868
|
this.journalTransition({
|
|
864
|
-
name: "advance-
|
|
865
|
-
reason:
|
|
869
|
+
name: "advance-skipped",
|
|
870
|
+
reason: skipped.reason,
|
|
866
871
|
unitType: decision.unitType,
|
|
867
872
|
unitId: decision.unitId,
|
|
868
873
|
});
|
|
869
|
-
this.postAdvanceRecord(
|
|
870
|
-
return
|
|
874
|
+
this.postAdvanceRecord(skipped);
|
|
875
|
+
return skipped;
|
|
871
876
|
}
|
|
872
|
-
// Stuck-loop detection: when the
|
|
873
|
-
// `nextKey` (count >= STUCK_WINDOW_SIZE), the
|
|
874
|
-
//
|
|
875
|
-
//
|
|
876
|
-
|
|
877
|
+
// Stuck-loop detection: when the window is saturated with copies of
|
|
878
|
+
// `nextKey` (count >= STUCK_WINDOW_SIZE), consult the Dispatch History
|
|
879
|
+
// module's full detect-stuck rule set for the verdict instead of the old
|
|
880
|
+
// bare saturation count. This keeps the saturation threshold (the window
|
|
881
|
+
// deliberately records benign idempotent repeats, so earlier-firing
|
|
882
|
+
// rules would false-positive on pause/resume re-advances) while gaining
|
|
883
|
+
// retry-budget suppression and diagnosable rule reasons. A saturated
|
|
884
|
+
// window with no verdict means the dispatch ledger says we are inside
|
|
885
|
+
// the unit's retry-backoff budget — let the retry proceed.
|
|
886
|
+
const stuckVerdict = matchingCount >= STUCK_WINDOW_SIZE ? this.dispatchHistory.detectStuck() : null;
|
|
887
|
+
if (stuckVerdict) {
|
|
877
888
|
// #442: before declaring a stuck loop, verify the unit didn't actually
|
|
878
889
|
// complete on disk (stale DB) and recover if so — legacy graduated
|
|
879
890
|
// stuck-recovery parity. Otherwise hard-stop with a diagnosable reason.
|
|
@@ -884,7 +895,7 @@ export class AutoOrchestrator {
|
|
|
884
895
|
this.clearPendingDispatch();
|
|
885
896
|
const blocked = {
|
|
886
897
|
kind: "blocked",
|
|
887
|
-
reason: `stuck-loop: ${
|
|
898
|
+
reason: `stuck-loop: ${stuckVerdict.reason}`,
|
|
888
899
|
action: "stop",
|
|
889
900
|
};
|
|
890
901
|
this.journalTransition({
|
|
@@ -974,7 +985,7 @@ export class AutoOrchestrator {
|
|
|
974
985
|
if (result.kind === "stopped") {
|
|
975
986
|
this.lastAdvanceKey = null;
|
|
976
987
|
this.lastFinalizedUnitKey = null;
|
|
977
|
-
this.
|
|
988
|
+
this.dispatchHistory.clearOnRecovery();
|
|
978
989
|
this.status.activeUnit = undefined;
|
|
979
990
|
}
|
|
980
991
|
this.bumpTransition();
|
|
@@ -1003,8 +1014,14 @@ export class AutoOrchestrator {
|
|
|
1003
1014
|
async resume() {
|
|
1004
1015
|
this.lastAdvanceKey = null;
|
|
1005
1016
|
this.lastFinalizedUnitKey = null;
|
|
1006
|
-
// Preserve
|
|
1007
|
-
// accumulates across pause/resume cycles rather than
|
|
1017
|
+
// Preserve the dispatch-history window across an in-process resume so
|
|
1018
|
+
// stuck-loop detection accumulates across pause/resume cycles rather than
|
|
1019
|
+
// resetting each time (#572 regression). When the window is empty (fresh
|
|
1020
|
+
// orchestrator resuming a prior session), rehydrate it from the DB
|
|
1021
|
+
// dispatch ledger so cross-session re-dispatch loops are detected (#482).
|
|
1022
|
+
if (this.dispatchHistory.getRecentWindow().length === 0) {
|
|
1023
|
+
this.dispatchHistory.rehydrate();
|
|
1024
|
+
}
|
|
1008
1025
|
this.lastStuckRecoveryKey = null;
|
|
1009
1026
|
// ADR-030: drop the prior "from" — the first advance after resume has no
|
|
1010
1027
|
// edge to assert (avoids a false illegal-edge across the pause boundary).
|
|
@@ -1025,10 +1042,10 @@ export class AutoOrchestrator {
|
|
|
1025
1042
|
this.lastAdvanceKey = null;
|
|
1026
1043
|
this.lastFinalizedUnitKey = null;
|
|
1027
1044
|
this.lastDerivedPhase = null;
|
|
1028
|
-
// Preserve
|
|
1029
|
-
// across pause/resume cycles. Only clear on a hard stop.
|
|
1045
|
+
// Preserve the dispatch-history window on pause so stuck-loop detection
|
|
1046
|
+
// accumulates across pause/resume cycles. Only clear on a hard stop.
|
|
1030
1047
|
if (reason !== "pause") {
|
|
1031
|
-
this.
|
|
1048
|
+
this.dispatchHistory.clearOnRecovery();
|
|
1032
1049
|
}
|
|
1033
1050
|
this.lastStuckRecoveryKey = null;
|
|
1034
1051
|
this.bumpTransition();
|
|
@@ -1040,9 +1057,9 @@ export class AutoOrchestrator {
|
|
|
1040
1057
|
return { ...this.status, activeUnit: this.status.activeUnit ? { ...this.status.activeUnit } : undefined };
|
|
1041
1058
|
}
|
|
1042
1059
|
async completeActiveUnit(unit) {
|
|
1043
|
-
const unitKey =
|
|
1060
|
+
const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
|
|
1044
1061
|
const activeUnitKey = this.status.activeUnit
|
|
1045
|
-
?
|
|
1062
|
+
? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
|
|
1046
1063
|
: null;
|
|
1047
1064
|
if (activeUnitKey !== unitKey)
|
|
1048
1065
|
return;
|
|
@@ -1059,9 +1076,9 @@ export class AutoOrchestrator {
|
|
|
1059
1076
|
});
|
|
1060
1077
|
}
|
|
1061
1078
|
async retryActiveUnit(unit) {
|
|
1062
|
-
const unitKey =
|
|
1079
|
+
const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
|
|
1063
1080
|
const activeUnitKey = this.status.activeUnit
|
|
1064
|
-
?
|
|
1081
|
+
? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
|
|
1065
1082
|
: null;
|
|
1066
1083
|
if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey)
|
|
1067
1084
|
return;
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { importExtensionModule } from "@gsd/pi-coding-agent";
|
|
12
12
|
import { USER_DRIVEN_DEEP_UNITS, isAwaitingUserInput, } from "../auto-post-unit.js";
|
|
13
|
-
import { lastAssistantText } from "../
|
|
13
|
+
import { lastAssistantText } from "../consent-question.js";
|
|
14
14
|
import { resolveEffectiveUnitIsolationMode } from "../preferences.js";
|
|
15
15
|
import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from "./types.js";
|
|
16
16
|
import { detectStuck } from "./detect-stuck.js";
|
|
17
|
+
import { STUCK_WINDOW_SIZE } from "./dispatch-history.js";
|
|
17
18
|
import { runUnit } from "./run-unit.js";
|
|
18
19
|
import { debugLog } from "../debug-logger.js";
|
|
19
20
|
import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
|
|
@@ -60,7 +61,6 @@ import { buildPhaseHandoffOutcome, setAutoActiveStatus, setAutoOutcomeWidget } f
|
|
|
60
61
|
import { getConsecutiveDispatchBlocker } from "../dispatch-guard.js";
|
|
61
62
|
import { captureRootDirtySnapshot, detectRootWriteLeak, formatRootWriteLeakMessage, } from "../root-write-leak-guard.js";
|
|
62
63
|
import { classifyError, isTransient } from "../error-classifier.js";
|
|
63
|
-
export const STUCK_WINDOW_SIZE = 6;
|
|
64
64
|
const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
|
|
65
65
|
const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE = /^(?:api error(?::|$|\s*\()|provider error(?::|$|\s*\()|request failed\b|(?:http\s*)?(?:429|500|502|503)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|socket hang up\b|fetch failed\b|(?:network|connection|server) error(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|dns\b.*(?:fail|error|timeout)|unexpected eof\b|stream idle timeout\b|partial response received\b|stream_exhausted\b|terminated(?::|$)|(?:connection|stream|request)\b.{0,40}\bterminated\b|other side closed\b|rate.?limit(?:ed| exceeded| reached| error)|too many requests\b|you(?:'ve| have) (?:hit|reached) your (?:\w+ )?limit\b|.*\b(?:usage|session|weekly|daily|monthly|quota) limit\b|limit\b.{0,40}\bresets?\b|out of extra usage\b|service.?unavailable\b|internal(?: server)? error(?::|$)|internal(?:[_-]server)?[_-]error\b|server[_-]error\b|(?:provider|server|api|model|codex|claude|openai|anthropic|gemini)\b.{0,80}\boverloaded\b|overloaded\b.{0,80}\b(?:provider|server|api|model)\b|context (?:window|length) exceed|context window exceed)/i;
|
|
66
66
|
const ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE = /(?:\b(?:http|status(?: code)?|code|error:)\s*(?:429|500|502|503)\b|\b(?:api|provider) error\s*[:(]?\s*(?:429|500|502|503)\b|\b(?:typeerror|error):\s*(?:fetch failed\b|socket hang up\b|terminated(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|(?:network|connection|server) error(?::|$)|stream idle timeout\b|partial response received\b|unexpected eof\b)|\b(?:server_error|api_error|stream_exhausted(?:_without_result)?)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|context (?:window|length) exceed|context window exceed)/i;
|
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { deriveState } from "./state.js";
|
|
6
6
|
import { loadFile } from "./files.js";
|
|
7
|
-
import { isDbAvailable,
|
|
8
|
-
import {
|
|
9
|
-
import { resolveMilestoneFile, resolveSliceFile, relSliceFile, } from "./paths.js";
|
|
7
|
+
import { isDbAvailable, getClosedSliceIds } from "./gsd-db.js";
|
|
8
|
+
import { resolveSliceFile, relSliceFile, } from "./paths.js";
|
|
10
9
|
import { buildResearchSlicePrompt, buildResearchMilestonePrompt, buildPlanSlicePrompt, buildPlanMilestonePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReassessRoadmapPrompt, buildRunUatPrompt, buildReplanSlicePrompt, } from "./auto-prompts.js";
|
|
11
10
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
12
11
|
import { pauseAuto } from "./auto.js";
|
|
@@ -135,21 +134,9 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
135
134
|
}
|
|
136
135
|
case "reassess":
|
|
137
136
|
case "reassess-roadmap": {
|
|
138
|
-
// DB
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
completedSliceIds = getMilestoneSlices(mid).filter(s => s.status === "complete").map(s => s.id);
|
|
142
|
-
}
|
|
143
|
-
if (completedSliceIds.length === 0) {
|
|
144
|
-
// File-based fallback: parse roadmap checkboxes
|
|
145
|
-
const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
|
|
146
|
-
if (roadmapPath) {
|
|
147
|
-
const roadmapContent = await loadFile(roadmapPath);
|
|
148
|
-
if (roadmapContent) {
|
|
149
|
-
completedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
137
|
+
// DB-authoritative read (ADR-017) — markdown projections are never
|
|
138
|
+
// consulted for dispatch decisions. No DB rows means no completed slices.
|
|
139
|
+
const completedSliceIds = isDbAvailable() ? getClosedSliceIds(mid) : [];
|
|
153
140
|
if (completedSliceIds.length === 0) {
|
|
154
141
|
ctx.ui.notify("Cannot dispatch reassess-roadmap: no completed slices.", "warning");
|
|
155
142
|
return;
|
|
@@ -173,20 +160,9 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
173
160
|
// incomplete) slice. After slice completion, state.activeSlice advances
|
|
174
161
|
// to the next incomplete slice, so we find the last done slice from the
|
|
175
162
|
// roadmap instead (#1693).
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
if (uatCompletedSliceIds.length === 0) {
|
|
181
|
-
// File-based fallback: parse roadmap checkboxes
|
|
182
|
-
const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
|
|
183
|
-
if (roadmapPath) {
|
|
184
|
-
const roadmapContent = await loadFile(roadmapPath);
|
|
185
|
-
if (roadmapContent) {
|
|
186
|
-
uatCompletedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
163
|
+
// DB-authoritative read (ADR-017) — no markdown fallback for dispatch
|
|
164
|
+
// decisions.
|
|
165
|
+
const uatCompletedSliceIds = isDbAvailable() ? getClosedSliceIds(mid) : [];
|
|
190
166
|
if (uatCompletedSliceIds.length === 0) {
|
|
191
167
|
ctx.ui.notify("Cannot dispatch run-uat: no completed slices.", "warning");
|
|
192
168
|
return;
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// File Purpose: Declarative auto-mode dispatch rules and dispatch resolver.
|
|
3
3
|
import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
|
|
4
4
|
import { getUatBrowserToolSupportError } from "./uat-policy.js";
|
|
5
|
-
import { isDbAvailable, getMilestoneSlices, getPendingGatesForTurn, markPendingGatesOmittedForTurn, getMilestone, insertArtifact, insertAssessment, setSliceSketchFlag, transaction, getAssessment, } from "./gsd-db.js";
|
|
5
|
+
import { isDbAvailable, getMilestoneSlices, getMilestoneSliceSummaries, getClosedSliceIds, getPendingGatesForTurn, markPendingGatesOmittedForTurn, getMilestone, insertArtifact, insertAssessment, setSliceSketchFlag, transaction, getAssessment, } from "./gsd-db.js";
|
|
6
6
|
import { isClosedStatus } from "./status-guards.js";
|
|
7
7
|
import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
|
|
8
8
|
import { gsdRoot, resolveGsdPathContract, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveSlicePath, resolveTaskFile, relTaskFile, relSliceFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, gsdProjectionRoot, } from "./paths.js";
|
|
9
|
-
import { parseRoadmap } from "./parsers-legacy.js";
|
|
10
9
|
import { validateArtifact } from "./schemas/validate.js";
|
|
11
10
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync } from "node:fs";
|
|
12
11
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
@@ -19,10 +18,14 @@ import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
|
|
|
19
18
|
import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
|
|
20
19
|
import { EXECUTION_ENTRY_PHASES, hasFinalizedMilestoneContext } from "./uok/plan-v2.js";
|
|
21
20
|
import { isAutoActive } from "./auto.js";
|
|
22
|
-
|
|
21
|
+
// Host adapter explicitly: auto-dispatch runs in the extension host, and the
|
|
22
|
+
// ambient write-gate exports env-sniff the adapter per call (they are reserved
|
|
23
|
+
// for the workflow MCP child's dynamic-import surface).
|
|
24
|
+
import { hostWriteGateAdapter } from "./bootstrap/write-gate.js";
|
|
23
25
|
import { ensureWorkflowPreferencesCaptured } from "./planning-depth.js";
|
|
24
26
|
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
25
|
-
import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, } from "./workflow-mcp.js";
|
|
27
|
+
import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, resolveWorkflowMcpProjectRoot, } from "./workflow-mcp.js";
|
|
28
|
+
import { prepareBrowserDaemonForUat } from "./browser-daemon-auto-prep.js";
|
|
26
29
|
import { PROJECT_RESEARCH_INFLIGHT_MARKER, } from "./project-research-policy.js";
|
|
27
30
|
import { isWorkflowPrefsCaptured, resolveDeepProjectSetupState, } from "./deep-project-setup-policy.js";
|
|
28
31
|
import { annotateBackgroundable } from "./delegation-policy.js";
|
|
@@ -289,30 +292,13 @@ function persistSliceAssessmentBackfill(assessmentRelPath, mid, sliceId, content
|
|
|
289
292
|
});
|
|
290
293
|
}
|
|
291
294
|
function backfillMissingAssessmentsFromSummaries(basePath, mid) {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
302
|
-
if (!roadmapFile)
|
|
303
|
-
return;
|
|
304
|
-
try {
|
|
305
|
-
const roadmap = parseRoadmap(readFileSync(roadmapFile, "utf-8"));
|
|
306
|
-
for (const slice of roadmap.slices) {
|
|
307
|
-
if (slice.done)
|
|
308
|
-
completedSliceIds.add(slice.id);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
catch {
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
for (const sliceId of completedSliceIds) {
|
|
295
|
+
// DB-authoritative (ADR-017): no markdown fallback. Without DB rows there
|
|
296
|
+
// is nothing to backfill.
|
|
297
|
+
if (!isDbAvailable())
|
|
298
|
+
return;
|
|
299
|
+
// Canonical closed vocabulary (complete/done/skipped/closed) — a skipped or
|
|
300
|
+
// closed slice with a SUMMARY gets the same assessment backfill treatment.
|
|
301
|
+
for (const sliceId of getClosedSliceIds(mid)) {
|
|
316
302
|
const summaryPath = resolveSliceFile(basePath, mid, sliceId, "SUMMARY");
|
|
317
303
|
if (!summaryPath || !existsSync(summaryPath))
|
|
318
304
|
continue;
|
|
@@ -488,7 +474,7 @@ export const DISPATCH_RULES = [
|
|
|
488
474
|
// deadlock. Deep planning is still user-driven even inside auto-mode,
|
|
489
475
|
// so it must wait for explicit approval instead of taking this bypass.
|
|
490
476
|
if (shouldBypassMilestoneDepthGateInAuto(prefs)) {
|
|
491
|
-
markDepthVerified(mid, basePath);
|
|
477
|
+
hostWriteGateAdapter.markDepthVerified(mid, basePath);
|
|
492
478
|
}
|
|
493
479
|
return {
|
|
494
480
|
action: "dispatch",
|
|
@@ -540,6 +526,16 @@ export const DISPATCH_RULES = [
|
|
|
540
526
|
if (browserToolError) {
|
|
541
527
|
return { action: "stop", reason: browserToolError, level: "warning" };
|
|
542
528
|
}
|
|
529
|
+
const browserDaemonError = prepareBrowserDaemonForUat({
|
|
530
|
+
uatType,
|
|
531
|
+
sessionProvider,
|
|
532
|
+
sessionAuthMode,
|
|
533
|
+
sessionBaseUrl,
|
|
534
|
+
projectRoot: resolveWorkflowMcpProjectRoot(basePath),
|
|
535
|
+
});
|
|
536
|
+
if (browserDaemonError) {
|
|
537
|
+
return { action: "stop", reason: browserDaemonError, level: "warning" };
|
|
538
|
+
}
|
|
543
539
|
// Cap run-uat dispatch attempts to prevent infinite replay (#3624).
|
|
544
540
|
// Check before incrementing so an exhausted counter cannot create a
|
|
545
541
|
// no-progress skip loop that starves later dispatch rules.
|
|
@@ -569,24 +565,11 @@ export const DISPATCH_RULES = [
|
|
|
569
565
|
// Only applies when UAT dispatch is enabled
|
|
570
566
|
if (!prefs?.uat_dispatch)
|
|
571
567
|
return null;
|
|
572
|
-
// DB-
|
|
573
|
-
|
|
574
|
-
if (isDbAvailable())
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
.map(s => s.id);
|
|
578
|
-
}
|
|
579
|
-
else {
|
|
580
|
-
// Filesystem fallback for degraded / unmigrated projects.
|
|
581
|
-
// `slice.done` in the parsed ROADMAP is the disk-level closed signal.
|
|
582
|
-
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
583
|
-
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
584
|
-
if (!roadmapContent)
|
|
585
|
-
return null;
|
|
586
|
-
const roadmap = parseRoadmap(roadmapContent);
|
|
587
|
-
closedSliceIds = roadmap.slices.filter(s => s.done).map(s => s.id);
|
|
588
|
-
}
|
|
589
|
-
for (const sliceId of closedSliceIds) {
|
|
568
|
+
// DB-authoritative (ADR-017): closed slices come from the DB only; the
|
|
569
|
+
// ROADMAP projection is never parsed for gate decisions.
|
|
570
|
+
if (!isDbAvailable())
|
|
571
|
+
return null;
|
|
572
|
+
for (const sliceId of getClosedSliceIds(mid)) {
|
|
590
573
|
const result = await readUatGateVerdict(basePath, mid, sliceId);
|
|
591
574
|
if (!result)
|
|
592
575
|
continue;
|
|
@@ -641,7 +624,7 @@ export const DISPATCH_RULES = [
|
|
|
641
624
|
// H6 fix (#4973): keep the non-deep auto-mode bypass, but do not
|
|
642
625
|
// pre-verify deep planning's user-facing milestone approval gate.
|
|
643
626
|
if (shouldBypassMilestoneDepthGateInAuto(prefs)) {
|
|
644
|
-
markDepthVerified(mid, basePath);
|
|
627
|
+
hostWriteGateAdapter.markDepthVerified(mid, basePath);
|
|
645
628
|
}
|
|
646
629
|
return {
|
|
647
630
|
action: "dispatch",
|
|
@@ -823,7 +806,7 @@ export const DISPATCH_RULES = [
|
|
|
823
806
|
// H6 fix (#4973): keep the non-deep auto-mode bypass, but do not
|
|
824
807
|
// pre-verify deep planning's user-facing milestone approval gate.
|
|
825
808
|
if (shouldBypassMilestoneDepthGateInAuto(prefs)) {
|
|
826
|
-
markDepthVerified(mid, basePath);
|
|
809
|
+
hostWriteGateAdapter.markDepthVerified(mid, basePath);
|
|
827
810
|
}
|
|
828
811
|
return {
|
|
829
812
|
action: "dispatch",
|
|
@@ -905,18 +888,18 @@ export const DISPATCH_RULES = [
|
|
|
905
888
|
// behavior.
|
|
906
889
|
if (await getMilestonePipelineVariant(mid) === "trivial")
|
|
907
890
|
return null;
|
|
908
|
-
//
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
891
|
+
// DB-authoritative slice list (ADR-017): the ROADMAP projection is
|
|
892
|
+
// never parsed for dispatch decisions. No DB / no rows → skip this rule.
|
|
893
|
+
if (!isDbAvailable())
|
|
894
|
+
return null;
|
|
895
|
+
const dbSlices = getMilestoneSliceSummaries(mid);
|
|
896
|
+
if (dbSlices.length === 0)
|
|
913
897
|
return null;
|
|
914
|
-
const roadmap = parseRoadmap(roadmapContent);
|
|
915
898
|
// Find slices that need research (no RESEARCH file, dependencies done)
|
|
916
899
|
const milestoneResearchFile = resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
|
|
917
900
|
resolveMilestoneFile(basePath, mid, "RESEARCH");
|
|
918
901
|
const researchReadySlices = [];
|
|
919
|
-
for (const slice of
|
|
902
|
+
for (const slice of dbSlices) {
|
|
920
903
|
if (slice.done)
|
|
921
904
|
continue;
|
|
922
905
|
// Skip S01 when milestone research exists
|
|
@@ -926,7 +909,7 @@ export const DISPATCH_RULES = [
|
|
|
926
909
|
if (resolveExistingExpectedArtifact("research-slice", `${mid}/${slice.id}`, basePath))
|
|
927
910
|
continue;
|
|
928
911
|
// Skip if dependencies aren't done (check for SUMMARY files)
|
|
929
|
-
const depsComplete =
|
|
912
|
+
const depsComplete = slice.depends.every((depId) => !!resolveExistingExpectedArtifact("complete-slice", `${mid}/${depId}`, basePath));
|
|
930
913
|
if (!depsComplete)
|
|
931
914
|
continue;
|
|
932
915
|
researchReadySlices.push({ id: slice.id, title: slice.title });
|
|
@@ -839,15 +839,34 @@ export function resolveModelId(modelId, availableModels, currentProvider) {
|
|
|
839
839
|
if (providerMatch)
|
|
840
840
|
return providerMatch;
|
|
841
841
|
}
|
|
842
|
-
//
|
|
843
|
-
//
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
842
|
+
// Subscription/OAuth routes beat pay-per-token API when the same model ID
|
|
843
|
+
// exists on multiple providers. Order matters — first match wins.
|
|
844
|
+
for (const provider of BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE) {
|
|
845
|
+
const match = candidates.find(m => m.provider === provider);
|
|
846
|
+
if (match)
|
|
847
|
+
return match;
|
|
848
|
+
}
|
|
848
849
|
// Fall back to first non-extension candidate, or any candidate
|
|
849
850
|
return candidates.find(m => !EXTENSION_PROVIDERS.has(m.provider)) ?? candidates[0];
|
|
850
851
|
}
|
|
852
|
+
/**
|
|
853
|
+
* When a bare model ID exists on multiple providers, prefer subscription/OAuth
|
|
854
|
+
* routes over pay-per-token API keys. Matches PROVIDER_ROUTES in doctor-providers
|
|
855
|
+
* but applies when *both* sides are authenticated.
|
|
856
|
+
*
|
|
857
|
+
* Order rationale:
|
|
858
|
+
* - openai-codex before github-copilot: ChatGPT-native for shared GPT IDs
|
|
859
|
+
* - google-gemini-cli before github-copilot: first-party Gemini CLI
|
|
860
|
+
* - anthropic before github-copilot: first-party Claude API/OAuth over Copilot
|
|
861
|
+
* - github-copilot before openai/google: Copilot OAuth over platform API keys
|
|
862
|
+
*/
|
|
863
|
+
export const BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE = [
|
|
864
|
+
"openai-codex",
|
|
865
|
+
"google-gemini-cli",
|
|
866
|
+
"anthropic",
|
|
867
|
+
"github-copilot",
|
|
868
|
+
"google-antigravity",
|
|
869
|
+
];
|
|
851
870
|
/**
|
|
852
871
|
* Flat-rate providers charge the same per request regardless of model.
|
|
853
872
|
* Dynamic routing provides no cost benefit — it only degrades quality (#3453).
|
|
@@ -16,7 +16,7 @@ import { deriveState } from "./state.js";
|
|
|
16
16
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
17
17
|
import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
|
|
18
18
|
import { loadPrompt } from "./prompt-loader.js";
|
|
19
|
-
import { isAwaitingUserInput } from "./
|
|
19
|
+
import { isAwaitingUserInput } from "./consent-question.js";
|
|
20
20
|
import { resolveMilestonePath, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, } from "./paths.js";
|
|
21
21
|
import { invalidateAllCaches } from "./cache.js";
|
|
22
22
|
import { rebuildState } from "./doctor.js";
|
|
@@ -30,8 +30,7 @@ import { createWorkspace, scopeMilestone } from "./workspace.js";
|
|
|
30
30
|
import { normalizeWorktreePathForCompare } from "./worktree-root.js";
|
|
31
31
|
import { isDbAvailable, getTask, getSlice, getMilestone, getMilestoneSlices, updateTaskStatus, _getAdapter, getVerificationEvidence } from "./gsd-db.js";
|
|
32
32
|
import { getWorkflowDatabasePath, refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
|
|
33
|
-
import { renderPlanCheckboxes, renderRoadmapFromDb } from "./markdown-renderer.js";
|
|
34
|
-
import { parseRoadmap as parseLegacyRoadmap } from "./parsers-legacy.js";
|
|
33
|
+
import { renderPlanCheckboxes, renderRoadmapFromDb, roadmapRenderMarksSliceDone } from "./markdown-renderer.js";
|
|
35
34
|
import { consumeSignal } from "./session-status-io.js";
|
|
36
35
|
import { checkPostUnitHooks, consumeHookFailure, isRetryPending, consumeRetryTrigger, consumeGateBlock, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
|
|
37
36
|
import { hasPendingCaptures, loadPendingCaptures, revertExecutorResolvedCaptures } from "./captures.js";
|
|
@@ -55,11 +54,12 @@ import { writeTurnGitTransaction } from "./uok/gitops.js";
|
|
|
55
54
|
import { isClosedStatus } from "./status-guards.js";
|
|
56
55
|
import { detectAbandonMilestone } from "./abandon-detect.js";
|
|
57
56
|
import { getPendingGate } from "./bootstrap/write-gate.js";
|
|
58
|
-
import { isDeterministicPolicyError } from "./auto-tool-tracking.js";
|
|
57
|
+
import { isDeterministicPolicyError, isToolUnavailableError } from "./auto-tool-tracking.js";
|
|
59
58
|
import { formatConnectedStepStack, formatPostUnitStatusCard } from "./auto-status-message.js";
|
|
60
59
|
import { clearProjectResearchInflightMarker, finalizeProjectResearchTimeout, } from "./project-research-policy.js";
|
|
61
60
|
import { validateArtifact } from "./schemas/validate.js";
|
|
62
61
|
import { verificationRetryKey } from "./auto/verification-retry-policy.js";
|
|
62
|
+
import { saveCustomVerifyRetryCounts } from "./auto/custom-verify-retry-store.js";
|
|
63
63
|
import { getLedger } from "./metrics.js";
|
|
64
64
|
import { getUnitCostSpikeAction, resolveUnitCostSpikeMultiplier } from "./auto-budget.js";
|
|
65
65
|
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
@@ -722,7 +722,7 @@ export const USER_DRIVEN_DEEP_UNITS = new Set([
|
|
|
722
722
|
"discuss-milestone",
|
|
723
723
|
"research-decision",
|
|
724
724
|
]);
|
|
725
|
-
export { isAwaitingUserInput } from "./
|
|
725
|
+
export { isAwaitingUserInput } from "./consent-question.js";
|
|
726
726
|
function artifactValidationKind(unitType) {
|
|
727
727
|
if (unitType === "discuss-project")
|
|
728
728
|
return "project";
|
|
@@ -800,11 +800,13 @@ async function repairCompleteSliceRoadmapProjection(unitType, unitId, basePath)
|
|
|
800
800
|
if (!summaryPath || !existsSync(summaryPath) || !uatPath || !existsSync(uatPath)) {
|
|
801
801
|
return false;
|
|
802
802
|
}
|
|
803
|
+
// Stale-render detection (ADR-017): the DB already says the slice is closed;
|
|
804
|
+
// this only checks whether the rendered ROADMAP projection reflects it, to
|
|
805
|
+
// decide whether a repair re-render is needed.
|
|
803
806
|
const roadmapPath = resolveMilestoneFile(artifactBase, mid, "ROADMAP");
|
|
804
807
|
if (roadmapPath && existsSync(roadmapPath)) {
|
|
805
808
|
try {
|
|
806
|
-
|
|
807
|
-
if (roadmap.slices.find((roadmapSlice) => roadmapSlice.id === sid)?.done) {
|
|
809
|
+
if (roadmapRenderMarksSliceDone(readFileSync(roadmapPath, "utf-8"), sid)) {
|
|
808
810
|
return false;
|
|
809
811
|
}
|
|
810
812
|
}
|
|
@@ -1701,7 +1703,16 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1701
1703
|
ctx.ui.notify(`Artifact missing for ${s.currentUnit.type} ${s.currentUnit.id} — DB unavailable, skipping retry.${dbSkipDiag ? ` Expected: ${dbSkipDiag}` : ""}`, "error");
|
|
1702
1704
|
}
|
|
1703
1705
|
else if (!triggerArtifactVerified) {
|
|
1704
|
-
if (s.lastToolInvocationError) {
|
|
1706
|
+
if (s.lastToolInvocationError && isToolUnavailableError(s.lastToolInvocationError)) {
|
|
1707
|
+
// Tool-unavailable is the one transient invocation error: the
|
|
1708
|
+
// workflow MCP server registers its surface asynchronously, so a
|
|
1709
|
+
// Unit's first call can race the registration. Fall through to the
|
|
1710
|
+
// bounded verification retry instead of pausing.
|
|
1711
|
+
debugLog("postUnit", { phase: "tool-unavailable-retry", unitType: s.currentUnit.type, unitId: s.currentUnit.id, error: s.lastToolInvocationError });
|
|
1712
|
+
ctx.ui.notify(`Tool unavailable for ${s.currentUnit.type}: ${s.lastToolInvocationError}. The tool surface may still be registering — retrying.`, "warning");
|
|
1713
|
+
s.lastToolInvocationError = null;
|
|
1714
|
+
}
|
|
1715
|
+
else if (s.lastToolInvocationError) {
|
|
1705
1716
|
const isUserSkip = /queued user message/i.test(s.lastToolInvocationError);
|
|
1706
1717
|
const errMsg = isUserSkip
|
|
1707
1718
|
? `Tool skipped for ${s.currentUnit.type}: ${s.lastToolInvocationError}. Queued user message interrupted the turn — pausing auto-mode.`
|
|
@@ -1789,12 +1800,14 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1789
1800
|
}
|
|
1790
1801
|
}
|
|
1791
1802
|
s.exhaustedVerificationUnits.add(retryKey);
|
|
1803
|
+
saveCustomVerifyRetryCounts(s, { logFailure: err => debugLog("postUnit", { phase: "save-verify-retries-failed", error: err instanceof Error ? err.message : String(err) }) });
|
|
1792
1804
|
debugLog("postUnit", { phase: "artifact-verify-exhausted", unitType: s.currentUnit.type, unitId: s.currentUnit.id, attempt });
|
|
1793
1805
|
ctx.ui.notify(`${failureDetails} Pausing auto-mode after ${MAX_ARTIFACT_VERIFICATION_RETRIES} retries.`, "error");
|
|
1794
1806
|
await pauseAuto(ctx, pi);
|
|
1795
1807
|
return "dispatched";
|
|
1796
1808
|
}
|
|
1797
1809
|
s.verificationRetryCount.set(retryKey, attempt);
|
|
1810
|
+
saveCustomVerifyRetryCounts(s, { logFailure: err => debugLog("postUnit", { phase: "save-verify-retries-failed", error: err instanceof Error ? err.message : String(err) }) });
|
|
1798
1811
|
s.pendingVerificationRetry = {
|
|
1799
1812
|
unitId: s.currentUnit.id,
|
|
1800
1813
|
failureContext: `${failureDetails} (attempt ${attempt}/${MAX_ARTIFACT_VERIFICATION_RETRIES}).`,
|
|
@@ -1814,6 +1827,8 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1814
1827
|
}
|
|
1815
1828
|
s.verificationRetryCount.delete(retryKey);
|
|
1816
1829
|
s.verificationRetryFailureHashes.delete(retryKey);
|
|
1830
|
+
s.exhaustedVerificationUnits.delete(retryKey);
|
|
1831
|
+
saveCustomVerifyRetryCounts(s, { logFailure: err => debugLog("postUnit", { phase: "save-verify-retries-failed", error: err instanceof Error ? err.message : String(err) }) });
|
|
1817
1832
|
if (s.currentUnit.type === "complete-milestone") {
|
|
1818
1833
|
const { milestone: mid } = parseUnitId(s.currentUnit.id);
|
|
1819
1834
|
if (mid) {
|