@opengsd/gsd-pi 1.2.0-dev.84c56d87 → 1.2.0-dev.9ad8ae33
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/headless-events.js +7 -5
- package/dist/mcp-server.js +2 -1
- package/dist/resource-loader.d.ts +10 -5
- package/dist/resource-loader.js +121 -6
- 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/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 +89 -54
- package/dist/resources/extensions/gsd/auto/phases.js +49 -6
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
- package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
- package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
- package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
- package/dist/resources/extensions/gsd/auto-prompts.js +78 -19
- package/dist/resources/extensions/gsd/auto-start.js +35 -15
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
- package/dist/resources/extensions/gsd/auto-verification.js +23 -30
- package/dist/resources/extensions/gsd/auto-worktree.js +14 -1
- package/dist/resources/extensions/gsd/auto.js +37 -1
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +145 -50
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
- package/dist/resources/extensions/gsd/consent-question.js +353 -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 +8 -3
- package/dist/resources/extensions/gsd/db/queries.js +26 -0
- package/dist/resources/extensions/gsd/db-writer.js +8 -17
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
- package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -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/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +2 -1
- package/dist/resources/extensions/gsd/guidance.js +60 -0
- package/dist/resources/extensions/gsd/guided-flow.js +6 -3
- package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
- package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/preferences-models.js +2 -2
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.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/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/dist/resources/extensions/gsd/prompts/system.md +5 -2
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/state.js +5 -0
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
- package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
- package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
- package/dist/resources/extensions/gsd/uat-policy.js +40 -15
- package/dist/resources/extensions/gsd/unit-context-composer.js +65 -0
- package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
- package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
- package/dist/resources/extensions/gsd/workflow-events.js +6 -18
- package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
- package/dist/resources/extensions/gsd/worktree.js +8 -1
- package/dist/resources/extensions/shared/gsd-browser-cli.js +45 -3
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -1
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/SKILL.md +3 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +20 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- 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 +6 -6
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- 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/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
- package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
- package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
- package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
- package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
- package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
- package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
- package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
- package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/package.json +2 -2
- 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/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 +10 -5
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +4 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +99 -38
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- 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/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +419 -221
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +460 -261
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.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/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/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
- 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 +98 -56
- package/src/resources/extensions/gsd/auto/phases.ts +65 -26
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
- package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
- package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +115 -35
- package/src/resources/extensions/gsd/auto-start.ts +36 -18
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
- package/src/resources/extensions/gsd/auto-verification.ts +26 -28
- package/src/resources/extensions/gsd/auto-worktree.ts +14 -1
- package/src/resources/extensions/gsd/auto.ts +44 -1
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +163 -55
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
- package/src/resources/extensions/gsd/consent-question.ts +431 -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 +10 -2
- package/src/resources/extensions/gsd/db/queries.ts +37 -0
- package/src/resources/extensions/gsd/db-writer.ts +11 -19
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -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/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +4 -3
- package/src/resources/extensions/gsd/guidance.ts +78 -0
- package/src/resources/extensions/gsd/guided-flow.ts +21 -26
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
- package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/preferences-models.ts +2 -1
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.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/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/src/resources/extensions/gsd/prompts/system.md +5 -2
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/state.ts +5 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
- 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/discuss-routing-fixes.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- 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/gsd-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
- 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/milestone-closeout.test.ts +95 -4
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- 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 +138 -0
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
- 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-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
- package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
- package/src/resources/extensions/gsd/uat-policy.ts +60 -15
- package/src/resources/extensions/gsd/unit-context-composer.ts +99 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
- package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
- package/src/resources/extensions/gsd/workflow-events.ts +12 -20
- package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
- package/src/resources/extensions/gsd/worktree.ts +7 -1
- package/src/resources/extensions/shared/gsd-browser-cli.ts +54 -3
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -1
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/SKILL.md +3 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
- package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
- 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/src/resources/skills/gsd-browser/SKILL.md +0 -41
- /package/dist/web/standalone/.next/static/{AOpDeK_gJHU8OZjRo31gQ → FBNo5cT_chy7YNoAQsU3o}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{AOpDeK_gJHU8OZjRo31gQ → FBNo5cT_chy7YNoAQsU3o}/_ssgManifest.js +0 -0
|
@@ -22,7 +22,7 @@ type BlockedAdvanceResult = Extract<AutoAdvanceResult, { kind: "blocked" }>;
|
|
|
22
22
|
import { debugCount, debugLog, debugTime } from "../debug-logger.js";
|
|
23
23
|
import { reconcileBeforeDispatch } from "../state-reconciliation.js";
|
|
24
24
|
import { isLegalEdge, IllegalPhaseTransitionError } from "../state-transition-matrix.js";
|
|
25
|
-
import { resolveDispatch } from "../auto-dispatch.js";
|
|
25
|
+
import { hasPendingDeepStage, resolveDispatch } from "../auto-dispatch.js";
|
|
26
26
|
import { classifyFailure } from "../recovery-classification.js";
|
|
27
27
|
import { verifyExpectedArtifact, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
|
|
28
28
|
import { invalidateAllCaches } from "../cache.js";
|
|
@@ -64,6 +64,13 @@ import {
|
|
|
64
64
|
import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
|
|
65
65
|
import { getErrorMessage } from "../error-utils.js";
|
|
66
66
|
import { logWarning } from "../workflow-logger.js";
|
|
67
|
+
import { normalizeRealPath } from "../paths.js";
|
|
68
|
+
import {
|
|
69
|
+
buildDispatchKey,
|
|
70
|
+
createDispatchHistory,
|
|
71
|
+
STUCK_WINDOW_SIZE,
|
|
72
|
+
type DispatchHistory,
|
|
73
|
+
} from "./dispatch-history.js";
|
|
67
74
|
import { existsSync, readFileSync } from "node:fs";
|
|
68
75
|
import { join } from "node:path";
|
|
69
76
|
import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
|
|
@@ -72,16 +79,6 @@ function now(): number {
|
|
|
72
79
|
return Date.now();
|
|
73
80
|
}
|
|
74
81
|
|
|
75
|
-
/**
|
|
76
|
-
* Size of the dispatch-decision ring buffer used by the Auto Orchestration
|
|
77
|
-
* module's stuck-loop detector. When the same `${unitType}:${unitId}` key
|
|
78
|
-
* fills the window, advance() blocks with `action: "stop"`.
|
|
79
|
-
*
|
|
80
|
-
* Mirrors the legacy `STUCK_WINDOW_SIZE` in auto/phases.ts so behaviour is
|
|
81
|
-
* preserved across the eventual cutover (issue #5791).
|
|
82
|
-
*/
|
|
83
|
-
export const STUCK_WINDOW_SIZE = 6;
|
|
84
|
-
|
|
85
82
|
function noRemainingUnitsOutcome(stateSnapshot: GSDState): AutoTerminalOutcome {
|
|
86
83
|
if (stateSnapshot.phase === "complete") {
|
|
87
84
|
return {
|
|
@@ -196,14 +193,25 @@ export async function decideOrchestratorDispatch(
|
|
|
196
193
|
): Promise<DispatchDecision> {
|
|
197
194
|
const state = input.stateSnapshot;
|
|
198
195
|
const active = state.activeMilestone;
|
|
199
|
-
if (!active) return null;
|
|
200
|
-
|
|
201
196
|
const activeSession = input.session ?? session;
|
|
202
197
|
const activeDispatchBasePath = activeSession?.basePath || dispatchBasePath;
|
|
203
|
-
|
|
198
|
+
const prefs = loadEffectiveGSDPreferences(activeDispatchBasePath)?.preferences;
|
|
199
|
+
if (!active) {
|
|
200
|
+
if (state.phase !== "pre-planning") return null;
|
|
201
|
+
if (!hasPendingDeepStage(prefs, activeDispatchBasePath)) {
|
|
202
|
+
return {
|
|
203
|
+
kind: "blocked",
|
|
204
|
+
reason: state.nextAction || "No active milestone. Run /gsd unpark <id> or create a new milestone.",
|
|
205
|
+
action: "stop",
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (active && activeSession && shouldAdoptActiveMilestone(state, activeSession, activeDispatchBasePath)) {
|
|
204
211
|
activeSession.currentMilestoneId = active.id;
|
|
205
212
|
}
|
|
206
|
-
const
|
|
213
|
+
const dispatchMid = active?.id ?? activeSession?.currentMilestoneId ?? "";
|
|
214
|
+
const dispatchMidTitle = active?.title ?? "";
|
|
207
215
|
|
|
208
216
|
// Derive session-derived dispatch inputs the same way phases.ts:runDispatch does
|
|
209
217
|
// (#5789). Prefer caller-supplied values when present so test harnesses and
|
|
@@ -235,8 +243,15 @@ export async function decideOrchestratorDispatch(
|
|
|
235
243
|
? "true"
|
|
236
244
|
: "false");
|
|
237
245
|
|
|
246
|
+
// Only replay a milestone-scoped verification retry when a milestone is
|
|
247
|
+
// active. Pre-PR (#712 fix), `!active` returned null before reaching this
|
|
248
|
+
// block, so the retry was preserved for a future tick. The new
|
|
249
|
+
// pre-planning + deep-pending fall-through must keep that contract:
|
|
250
|
+
// otherwise a stale execute-task / complete-slice / complete-milestone
|
|
251
|
+
// retry whose target milestone has since been parked would preempt
|
|
252
|
+
// project-level deep rules like `discuss-project`.
|
|
238
253
|
const pendingRetry = session?.pendingVerificationRetryDispatch;
|
|
239
|
-
if (session && pendingRetry) {
|
|
254
|
+
if (session && pendingRetry && active) {
|
|
240
255
|
session.pendingVerificationRetryDispatch = null;
|
|
241
256
|
const alreadyClosedReason = getAlreadyClosedDispatchReason(
|
|
242
257
|
pendingRetry.unitType,
|
|
@@ -258,8 +273,8 @@ export async function decideOrchestratorDispatch(
|
|
|
258
273
|
|
|
259
274
|
const action = await resolveDispatch({
|
|
260
275
|
basePath: activeDispatchBasePath,
|
|
261
|
-
mid:
|
|
262
|
-
midTitle:
|
|
276
|
+
mid: dispatchMid,
|
|
277
|
+
midTitle: dispatchMidTitle,
|
|
263
278
|
state,
|
|
264
279
|
prefs,
|
|
265
280
|
session: activeSession,
|
|
@@ -303,8 +318,8 @@ export async function decideOrchestratorDispatch(
|
|
|
303
318
|
prompt: action.prompt,
|
|
304
319
|
pauseAfterUatDispatch: action.pauseAfterDispatch ?? false,
|
|
305
320
|
state,
|
|
306
|
-
mid:
|
|
307
|
-
midTitle:
|
|
321
|
+
mid: dispatchMid,
|
|
322
|
+
midTitle: dispatchMidTitle,
|
|
308
323
|
};
|
|
309
324
|
session.pendingOrchestrationDispatch = pending;
|
|
310
325
|
}
|
|
@@ -330,7 +345,9 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
330
345
|
private seq = 0;
|
|
331
346
|
private lastAdvanceKey: string | null = null;
|
|
332
347
|
private lastFinalizedUnitKey: string | null = null;
|
|
333
|
-
|
|
348
|
+
// Dispatch History module (#482): the dispatch-decision window with
|
|
349
|
+
// cross-session DB rehydration and full detect-stuck rules.
|
|
350
|
+
private readonly dispatchHistory: DispatchHistory;
|
|
334
351
|
// ADR-030 Phase Transition Invariant: the prior advance's reconciled Phase,
|
|
335
352
|
// the "from" endpoint of the edge check. In-memory; reset on start/resume/stop
|
|
336
353
|
// so the first advance of a session has no edge to assert.
|
|
@@ -347,6 +364,16 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
347
364
|
this.runtimeBasePath = context.runtimeBasePath;
|
|
348
365
|
this.s = context.session;
|
|
349
366
|
this.flowId = `auto-orchestrator-${Date.now()}`;
|
|
367
|
+
this.dispatchHistory = createDispatchHistory({
|
|
368
|
+
windowSize: STUCK_WINDOW_SIZE,
|
|
369
|
+
// Same stable scope the auto-loop uses for stuck-state persistence so
|
|
370
|
+
// rehydration reads the rows the dispatch ledger wrote for this project.
|
|
371
|
+
resolveScopeId: () =>
|
|
372
|
+
normalizeRealPath(
|
|
373
|
+
this.s.scope?.workspace.projectRoot ??
|
|
374
|
+
(this.s.originalBasePath || this.s.basePath || this.runtimeBasePath),
|
|
375
|
+
) || null,
|
|
376
|
+
});
|
|
350
377
|
}
|
|
351
378
|
|
|
352
379
|
// ── Live base-path resolution (was the wiring factory's getLiveDispatchBasePath) ──
|
|
@@ -765,7 +792,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
765
792
|
* skipped result) instead of stopping.
|
|
766
793
|
*/
|
|
767
794
|
private tryStuckArtifactRecovery(unitType: string, unitId: string): boolean {
|
|
768
|
-
const key =
|
|
795
|
+
const key = buildDispatchKey(unitType, unitId);
|
|
769
796
|
if (this.lastStuckRecoveryKey === key) return false; // already tried this episode
|
|
770
797
|
const basePath = this.getLiveDispatchBasePath();
|
|
771
798
|
if (!verifyExpectedArtifact(unitType, unitId, basePath)) return false;
|
|
@@ -777,7 +804,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
777
804
|
if (!refreshed.ok && refreshed.fatal) return false;
|
|
778
805
|
this.lastStuckRecoveryKey = key;
|
|
779
806
|
invalidateAllCaches();
|
|
780
|
-
this.
|
|
807
|
+
this.dispatchHistory.clearOnRecovery();
|
|
781
808
|
this.lastAdvanceKey = null;
|
|
782
809
|
this.lastFinalizedUnitKey = null;
|
|
783
810
|
return true;
|
|
@@ -808,7 +835,12 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
808
835
|
public async start(_sessionContext: AutoSessionContext): Promise<AutoAdvanceResult> {
|
|
809
836
|
this.lastAdvanceKey = null;
|
|
810
837
|
this.lastFinalizedUnitKey = null;
|
|
811
|
-
|
|
838
|
+
// #482: the DB dispatch ledger is the source of truth across sessions.
|
|
839
|
+
// Discard any in-memory window and rebuild it from the ledger so a unit
|
|
840
|
+
// that was re-dispatched in previous sessions is detected as stuck here
|
|
841
|
+
// instead of silently re-dispatching forever.
|
|
842
|
+
this.dispatchHistory.clearOnRecovery();
|
|
843
|
+
this.dispatchHistory.rehydrate();
|
|
812
844
|
this.lastStuckRecoveryKey = null;
|
|
813
845
|
this.lastDerivedPhase = null;
|
|
814
846
|
this.status.phase = "running";
|
|
@@ -913,7 +945,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
913
945
|
this.status.phase = "paused";
|
|
914
946
|
this.status.activeUnit = undefined;
|
|
915
947
|
this.lastAdvanceKey = null;
|
|
916
|
-
this.
|
|
948
|
+
this.dispatchHistory.clearOnRecovery();
|
|
917
949
|
this.bumpTransition();
|
|
918
950
|
this.journalTransition({ name: "advance-blocked", reason: settlementBlock.reason });
|
|
919
951
|
this.postAdvanceRecord(settlementBlock);
|
|
@@ -929,7 +961,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
929
961
|
this.status.phase = "stopped";
|
|
930
962
|
this.status.activeUnit = undefined;
|
|
931
963
|
this.lastAdvanceKey = null;
|
|
932
|
-
this.
|
|
964
|
+
this.dispatchHistory.clearOnRecovery();
|
|
933
965
|
this.bumpTransition();
|
|
934
966
|
this.journalTransition({ name: "advance-stopped", reason: stopped.reason });
|
|
935
967
|
this.postAdvanceRecord(stopped);
|
|
@@ -979,18 +1011,13 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
979
1011
|
return blocked;
|
|
980
1012
|
}
|
|
981
1013
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
// Record every dispatch decision in the ring buffer before pre-flight
|
|
1014
|
+
// Record every dispatch decision in the history window before pre-flight
|
|
985
1015
|
// checks so the stuck-loop detector observes the full decision history
|
|
986
1016
|
// (including decisions that idempotency would otherwise short-circuit).
|
|
987
|
-
// The
|
|
988
|
-
this.
|
|
989
|
-
if (this.dispatchKeyWindow.length > STUCK_WINDOW_SIZE) {
|
|
990
|
-
this.dispatchKeyWindow.shift();
|
|
991
|
-
}
|
|
1017
|
+
// The window is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
|
|
1018
|
+
const nextKey = this.dispatchHistory.recordDispatch(decision.unitType, decision.unitId);
|
|
992
1019
|
|
|
993
|
-
const matchingCount = this.
|
|
1020
|
+
const matchingCount = this.dispatchHistory.countMatching(nextKey);
|
|
994
1021
|
if (this.lastFinalizedUnitKey === nextKey) {
|
|
995
1022
|
// #442: the unit re-dispatched immediately after finalizing may have
|
|
996
1023
|
// actually completed on disk with a stale DB. Verify + recover before
|
|
@@ -1023,23 +1050,32 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
1023
1050
|
// checks coexist: idempotency for the common immediate-repeat case,
|
|
1024
1051
|
// stuck-loop for the saturated-window case.
|
|
1025
1052
|
if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
|
|
1053
|
+
// Unit already active — benign no-op. Return skipped so the loop re-polls
|
|
1054
|
+
// without cancelling the in-flight unit (blocked+pause would force-cancel it).
|
|
1026
1055
|
this.clearPendingDispatch();
|
|
1027
|
-
const
|
|
1056
|
+
const skipped: AutoAdvanceResult = { kind: "skipped", reason: "idempotent advance: unit already active" };
|
|
1028
1057
|
this.journalTransition({
|
|
1029
|
-
name: "advance-
|
|
1030
|
-
reason:
|
|
1058
|
+
name: "advance-skipped",
|
|
1059
|
+
reason: skipped.reason,
|
|
1031
1060
|
unitType: decision.unitType,
|
|
1032
1061
|
unitId: decision.unitId,
|
|
1033
1062
|
});
|
|
1034
|
-
this.postAdvanceRecord(
|
|
1035
|
-
return
|
|
1063
|
+
this.postAdvanceRecord(skipped);
|
|
1064
|
+
return skipped;
|
|
1036
1065
|
}
|
|
1037
1066
|
|
|
1038
|
-
// Stuck-loop detection: when the
|
|
1039
|
-
// `nextKey` (count >= STUCK_WINDOW_SIZE), the
|
|
1040
|
-
//
|
|
1041
|
-
//
|
|
1042
|
-
|
|
1067
|
+
// Stuck-loop detection: when the window is saturated with copies of
|
|
1068
|
+
// `nextKey` (count >= STUCK_WINDOW_SIZE), consult the Dispatch History
|
|
1069
|
+
// module's full detect-stuck rule set for the verdict instead of the old
|
|
1070
|
+
// bare saturation count. This keeps the saturation threshold (the window
|
|
1071
|
+
// deliberately records benign idempotent repeats, so earlier-firing
|
|
1072
|
+
// rules would false-positive on pause/resume re-advances) while gaining
|
|
1073
|
+
// retry-budget suppression and diagnosable rule reasons. A saturated
|
|
1074
|
+
// window with no verdict means the dispatch ledger says we are inside
|
|
1075
|
+
// the unit's retry-backoff budget — let the retry proceed.
|
|
1076
|
+
const stuckVerdict =
|
|
1077
|
+
matchingCount >= STUCK_WINDOW_SIZE ? this.dispatchHistory.detectStuck() : null;
|
|
1078
|
+
if (stuckVerdict) {
|
|
1043
1079
|
// #442: before declaring a stuck loop, verify the unit didn't actually
|
|
1044
1080
|
// complete on disk (stale DB) and recover if so — legacy graduated
|
|
1045
1081
|
// stuck-recovery parity. Otherwise hard-stop with a diagnosable reason.
|
|
@@ -1050,7 +1086,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
1050
1086
|
this.clearPendingDispatch();
|
|
1051
1087
|
const blocked: AutoAdvanceResult = {
|
|
1052
1088
|
kind: "blocked",
|
|
1053
|
-
reason: `stuck-loop: ${
|
|
1089
|
+
reason: `stuck-loop: ${stuckVerdict.reason}`,
|
|
1054
1090
|
action: "stop",
|
|
1055
1091
|
};
|
|
1056
1092
|
this.journalTransition({
|
|
@@ -1144,7 +1180,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
1144
1180
|
if (result.kind === "stopped") {
|
|
1145
1181
|
this.lastAdvanceKey = null;
|
|
1146
1182
|
this.lastFinalizedUnitKey = null;
|
|
1147
|
-
this.
|
|
1183
|
+
this.dispatchHistory.clearOnRecovery();
|
|
1148
1184
|
this.status.activeUnit = undefined;
|
|
1149
1185
|
}
|
|
1150
1186
|
this.bumpTransition();
|
|
@@ -1173,8 +1209,14 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
1173
1209
|
public async resume(): Promise<AutoAdvanceResult> {
|
|
1174
1210
|
this.lastAdvanceKey = null;
|
|
1175
1211
|
this.lastFinalizedUnitKey = null;
|
|
1176
|
-
// Preserve
|
|
1177
|
-
// accumulates across pause/resume cycles rather than
|
|
1212
|
+
// Preserve the dispatch-history window across an in-process resume so
|
|
1213
|
+
// stuck-loop detection accumulates across pause/resume cycles rather than
|
|
1214
|
+
// resetting each time (#572 regression). When the window is empty (fresh
|
|
1215
|
+
// orchestrator resuming a prior session), rehydrate it from the DB
|
|
1216
|
+
// dispatch ledger so cross-session re-dispatch loops are detected (#482).
|
|
1217
|
+
if (this.dispatchHistory.getRecentWindow().length === 0) {
|
|
1218
|
+
this.dispatchHistory.rehydrate();
|
|
1219
|
+
}
|
|
1178
1220
|
this.lastStuckRecoveryKey = null;
|
|
1179
1221
|
// ADR-030: drop the prior "from" — the first advance after resume has no
|
|
1180
1222
|
// edge to assert (avoids a false illegal-edge across the pause boundary).
|
|
@@ -1196,10 +1238,10 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
1196
1238
|
this.lastAdvanceKey = null;
|
|
1197
1239
|
this.lastFinalizedUnitKey = null;
|
|
1198
1240
|
this.lastDerivedPhase = null;
|
|
1199
|
-
// Preserve
|
|
1200
|
-
// across pause/resume cycles. Only clear on a hard stop.
|
|
1241
|
+
// Preserve the dispatch-history window on pause so stuck-loop detection
|
|
1242
|
+
// accumulates across pause/resume cycles. Only clear on a hard stop.
|
|
1201
1243
|
if (reason !== "pause") {
|
|
1202
|
-
this.
|
|
1244
|
+
this.dispatchHistory.clearOnRecovery();
|
|
1203
1245
|
}
|
|
1204
1246
|
this.lastStuckRecoveryKey = null;
|
|
1205
1247
|
this.bumpTransition();
|
|
@@ -1213,9 +1255,9 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
1213
1255
|
}
|
|
1214
1256
|
|
|
1215
1257
|
public async completeActiveUnit(unit: { unitType: string; unitId: string }): Promise<void> {
|
|
1216
|
-
const unitKey =
|
|
1258
|
+
const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
|
|
1217
1259
|
const activeUnitKey = this.status.activeUnit
|
|
1218
|
-
?
|
|
1260
|
+
? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
|
|
1219
1261
|
: null;
|
|
1220
1262
|
if (activeUnitKey !== unitKey) return;
|
|
1221
1263
|
|
|
@@ -1233,9 +1275,9 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
1233
1275
|
}
|
|
1234
1276
|
|
|
1235
1277
|
public async retryActiveUnit(unit: { unitType: string; unitId: string }): Promise<void> {
|
|
1236
|
-
const unitKey =
|
|
1278
|
+
const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
|
|
1237
1279
|
const activeUnitKey = this.status.activeUnit
|
|
1238
|
-
?
|
|
1280
|
+
? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
|
|
1239
1281
|
: null;
|
|
1240
1282
|
if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey) return;
|
|
1241
1283
|
|
|
@@ -19,9 +19,9 @@ import {
|
|
|
19
19
|
type PostUnitContext,
|
|
20
20
|
type PreVerificationOpts,
|
|
21
21
|
} from "../auto-post-unit.js";
|
|
22
|
-
import { lastAssistantText } from "../
|
|
23
|
-
import { resolveEffectiveUnitIsolationMode } from "../preferences.js";
|
|
24
|
-
import type { Phase } from "../types.js";
|
|
22
|
+
import { lastAssistantText } from "../consent-question.js";
|
|
23
|
+
import { resolveEffectiveUnitIsolationMode, getIsolationMode } from "../preferences.js";
|
|
24
|
+
import type { GSDState, Phase } from "../types.js";
|
|
25
25
|
import {
|
|
26
26
|
MAX_RECOVERY_CHARS,
|
|
27
27
|
BUDGET_THRESHOLDS,
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
type IterationData,
|
|
34
34
|
} from "./types.js";
|
|
35
35
|
import { detectStuck } from "./detect-stuck.js";
|
|
36
|
+
import { STUCK_WINDOW_SIZE } from "./dispatch-history.js";
|
|
36
37
|
import { runUnit } from "./run-unit.js";
|
|
37
38
|
import { debugLog } from "../debug-logger.js";
|
|
38
39
|
import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
|
|
@@ -61,9 +62,10 @@ import { writeUnitRuntimeRecord } from "../unit-runtime.js";
|
|
|
61
62
|
import { withTimeout, FINALIZE_PRE_TIMEOUT_MS, FINALIZE_POST_TIMEOUT_MS } from "./finalize-timeout.js";
|
|
62
63
|
import { getEligibleSlices } from "../slice-parallel-eligibility.js";
|
|
63
64
|
import { isSliceParallelActive, startSliceParallel } from "../slice-parallel-orchestrator.js";
|
|
64
|
-
import { isDbAvailable, getMilestoneSlices, getSlice, getTask } from "../gsd-db.js";
|
|
65
|
+
import { isDbAvailable, getMilestone, getMilestoneSlices, getSlice, getTask } from "../gsd-db.js";
|
|
65
66
|
import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
|
|
66
67
|
import { isClosedStatus } from "../status-guards.js";
|
|
68
|
+
import { findUnmergedCompletedMilestones } from "../unmerged-milestone-guard.js";
|
|
67
69
|
import { setRuntimeKv } from "../db/runtime-kv.js";
|
|
68
70
|
import { getLatestForUnit } from "../db/unit-dispatches.js";
|
|
69
71
|
import { reconcileBeforeSpawn } from "../state-reconciliation.js";
|
|
@@ -81,11 +83,8 @@ import { parseUnitId } from "../unit-id.js";
|
|
|
81
83
|
import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
|
|
82
84
|
import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
|
|
83
85
|
import { getContextPauseAction } from "../auto-budget.js";
|
|
84
|
-
import {
|
|
85
|
-
|
|
86
|
-
getRequiredWorkflowToolsForAutoUnit,
|
|
87
|
-
supportsStructuredQuestions,
|
|
88
|
-
} from "../workflow-mcp.js";
|
|
86
|
+
import { supportsStructuredQuestions } from "../workflow-mcp.js";
|
|
87
|
+
import { getUnitWorkflowDispatchReadinessError } from "../tool-contract.js";
|
|
89
88
|
import { prepareWorkflowMcpForProject } from "../workflow-mcp-auto-prep.js";
|
|
90
89
|
import {
|
|
91
90
|
applyThinkingLevelForModel,
|
|
@@ -107,7 +106,6 @@ import {
|
|
|
107
106
|
} from "../root-write-leak-guard.js";
|
|
108
107
|
import { classifyError, isTransient } from "../error-classifier.js";
|
|
109
108
|
|
|
110
|
-
export const STUCK_WINDOW_SIZE = 6;
|
|
111
109
|
const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
|
|
112
110
|
const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE =
|
|
113
111
|
/^(?: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;
|
|
@@ -838,6 +836,39 @@ async function failClosedOnFinalizeTimeout(
|
|
|
838
836
|
return { action: "break", reason: progressKind };
|
|
839
837
|
}
|
|
840
838
|
|
|
839
|
+
export async function shouldSkipTerminalMilestoneCloseout(
|
|
840
|
+
s: AutoSession,
|
|
841
|
+
state: Pick<GSDState, "phase" | "lastCompletedMilestone" | "activeMilestone">,
|
|
842
|
+
mid?: string | null,
|
|
843
|
+
): Promise<{ skip: boolean; milestoneId?: string }> {
|
|
844
|
+
const closeoutMilestoneId = mid ?? s.currentMilestoneId ?? state.lastCompletedMilestone?.id;
|
|
845
|
+
if (s.completionStopInProgress) {
|
|
846
|
+
return { skip: true, milestoneId: closeoutMilestoneId };
|
|
847
|
+
}
|
|
848
|
+
if (!closeoutMilestoneId) {
|
|
849
|
+
return { skip: false };
|
|
850
|
+
}
|
|
851
|
+
if (isDbAvailable()) refreshWorkflowDatabaseFromDisk();
|
|
852
|
+
const closeoutBasePath = s.originalBasePath || s.canonicalProjectRoot || s.basePath;
|
|
853
|
+
let closeoutMergePending = false;
|
|
854
|
+
if (getIsolationMode(closeoutBasePath) !== "none") {
|
|
855
|
+
try {
|
|
856
|
+
const blockers = await findUnmergedCompletedMilestones(closeoutBasePath);
|
|
857
|
+
closeoutMergePending = blockers.some((blocker) => blocker.milestoneId === closeoutMilestoneId);
|
|
858
|
+
} catch {
|
|
859
|
+
// Fail open: without git/DB inspection we cannot safely treat closeout as done.
|
|
860
|
+
closeoutMergePending = true;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
const milestoneAlreadyClosedOut = isDbAvailable()
|
|
864
|
+
&& isClosedStatus(getMilestone(closeoutMilestoneId)?.status ?? "")
|
|
865
|
+
&& !closeoutMergePending;
|
|
866
|
+
if (milestoneAlreadyClosedOut) {
|
|
867
|
+
return { skip: true, milestoneId: closeoutMilestoneId };
|
|
868
|
+
}
|
|
869
|
+
return { skip: false, milestoneId: closeoutMilestoneId };
|
|
870
|
+
}
|
|
871
|
+
|
|
841
872
|
// ─── runPreDispatch ───────────────────────────────────────────────────────────
|
|
842
873
|
|
|
843
874
|
/**
|
|
@@ -1279,6 +1310,14 @@ export async function runPreDispatch(
|
|
|
1279
1310
|
|
|
1280
1311
|
// ── Terminal conditions ──────────────────────────────────────────────
|
|
1281
1312
|
|
|
1313
|
+
if (state.phase === "complete") {
|
|
1314
|
+
const closeoutSkip = await shouldSkipTerminalMilestoneCloseout(s, state, mid);
|
|
1315
|
+
if (closeoutSkip.skip) {
|
|
1316
|
+
debugLog("autoLoop", { phase: "complete", reason: "milestone-already-closed", milestoneId: closeoutSkip.milestoneId });
|
|
1317
|
+
return { action: "break", reason: "milestone-complete" };
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1282
1321
|
if (!mid) {
|
|
1283
1322
|
if (s.currentUnit) {
|
|
1284
1323
|
await deps.closeoutUnit(
|
|
@@ -2324,22 +2363,19 @@ export async function runUnitPhase(
|
|
|
2324
2363
|
? `${(s.currentUnitModel as any).provider ?? ""}/${(s.currentUnitModel as any).id ?? ""}`
|
|
2325
2364
|
: null;
|
|
2326
2365
|
|
|
2327
|
-
const compatibilityError =
|
|
2328
|
-
s.currentUnitModel?.provider ?? ctx.model?.provider,
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
? ctx.modelRegistry.getProviderAuthMode(
|
|
2336
|
-
:
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
activeTools: typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [],
|
|
2341
|
-
},
|
|
2342
|
-
);
|
|
2366
|
+
const compatibilityError = getUnitWorkflowDispatchReadinessError({
|
|
2367
|
+
provider: s.currentUnitModel?.provider ?? ctx.model?.provider,
|
|
2368
|
+
projectRoot: s.basePath,
|
|
2369
|
+
surface: "auto-mode",
|
|
2370
|
+
unitType,
|
|
2371
|
+
authMode: s.currentUnitModel?.provider
|
|
2372
|
+
? ctx.modelRegistry.getProviderAuthMode(s.currentUnitModel.provider)
|
|
2373
|
+
: ctx.model?.provider
|
|
2374
|
+
? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider)
|
|
2375
|
+
: undefined,
|
|
2376
|
+
baseUrl: (s.currentUnitModel as any)?.baseUrl ?? ctx.model?.baseUrl,
|
|
2377
|
+
activeTools: typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [],
|
|
2378
|
+
});
|
|
2343
2379
|
const workflowMcpPrepModel = s.currentUnitModel;
|
|
2344
2380
|
if (compatibilityError) {
|
|
2345
2381
|
s.currentUnitRouting = prevUnitRouting;
|
|
@@ -2409,6 +2445,9 @@ export async function runUnitPhase(
|
|
|
2409
2445
|
causedBy: "unit-start",
|
|
2410
2446
|
});
|
|
2411
2447
|
s.lastToolInvocationError = null; // #2883: clear stale error from previous unit
|
|
2448
|
+
if (nextDispatchCount <= 1) {
|
|
2449
|
+
s.toolUnavailableRetries = 0;
|
|
2450
|
+
}
|
|
2412
2451
|
const unitStartSeq = ic.nextSeq();
|
|
2413
2452
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
|
|
2414
2453
|
deps.captureAvailableSkills();
|
|
@@ -212,6 +212,8 @@ export class AutoSession {
|
|
|
212
212
|
/** Set when a GSD tool execution ends with isError due to malformed/truncated
|
|
213
213
|
* JSON arguments. Checked by postUnitPreVerification to break retry loops. */
|
|
214
214
|
lastToolInvocationError: string | null = null;
|
|
215
|
+
/** Consecutive tool-unavailable retries for the current unit (MCP startup race). */
|
|
216
|
+
toolUnavailableRetries = 0;
|
|
215
217
|
/** Agent-end messages from the just-finished unit, consumed during finalize. */
|
|
216
218
|
lastUnitAgentEndMessages: unknown[] | null = null;
|
|
217
219
|
/** Set when turn-level git action fails during closeout. */
|
|
@@ -406,6 +408,7 @@ export class AutoSession {
|
|
|
406
408
|
this.lastPreExecFailure = null;
|
|
407
409
|
this.preExecRetryCount.clear();
|
|
408
410
|
this.lastToolInvocationError = null;
|
|
411
|
+
this.toolUnavailableRetries = 0;
|
|
409
412
|
this.lastUnitAgentEndMessages = null;
|
|
410
413
|
this.lastGitActionFailure = null;
|
|
411
414
|
this.lastGitActionStatus = null;
|
|
@@ -10,10 +10,9 @@ import type {
|
|
|
10
10
|
|
|
11
11
|
import { deriveState } from "./state.js";
|
|
12
12
|
import { loadFile } from "./files.js";
|
|
13
|
-
import { isDbAvailable,
|
|
14
|
-
import { parseRoadmap } from "./parsers-legacy.js";
|
|
13
|
+
import { isDbAvailable, getClosedSliceIds } from "./gsd-db.js";
|
|
15
14
|
import {
|
|
16
|
-
|
|
15
|
+
resolveSliceFile, relSliceFile,
|
|
17
16
|
} from "./paths.js";
|
|
18
17
|
import {
|
|
19
18
|
buildResearchSlicePrompt,
|
|
@@ -32,10 +31,7 @@ import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
|
32
31
|
import type { MinimalModelRegistry } from "./context-budget.js";
|
|
33
32
|
import { pauseAuto } from "./auto.js";
|
|
34
33
|
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
35
|
-
import {
|
|
36
|
-
getWorkflowTransportSupportError,
|
|
37
|
-
getRequiredWorkflowToolsForAutoUnit,
|
|
38
|
-
} from "./workflow-mcp.js";
|
|
34
|
+
import { getUnitWorkflowDispatchReadinessError } from "./tool-contract.js";
|
|
39
35
|
|
|
40
36
|
export async function dispatchDirectPhase(
|
|
41
37
|
ctx: ExtensionCommandContext,
|
|
@@ -182,21 +178,9 @@ export async function dispatchDirectPhase(
|
|
|
182
178
|
|
|
183
179
|
case "reassess":
|
|
184
180
|
case "reassess-roadmap": {
|
|
185
|
-
// DB
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
completedSliceIds = getMilestoneSlices(mid).filter(s => s.status === "complete").map(s => s.id);
|
|
189
|
-
}
|
|
190
|
-
if (completedSliceIds.length === 0) {
|
|
191
|
-
// File-based fallback: parse roadmap checkboxes
|
|
192
|
-
const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
|
|
193
|
-
if (roadmapPath) {
|
|
194
|
-
const roadmapContent = await loadFile(roadmapPath);
|
|
195
|
-
if (roadmapContent) {
|
|
196
|
-
completedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
181
|
+
// DB-authoritative read (ADR-017) — markdown projections are never
|
|
182
|
+
// consulted for dispatch decisions. No DB rows means no completed slices.
|
|
183
|
+
const completedSliceIds = isDbAvailable() ? getClosedSliceIds(mid) : [];
|
|
200
184
|
if (completedSliceIds.length === 0) {
|
|
201
185
|
ctx.ui.notify("Cannot dispatch reassess-roadmap: no completed slices.", "warning");
|
|
202
186
|
return;
|
|
@@ -222,20 +206,9 @@ export async function dispatchDirectPhase(
|
|
|
222
206
|
// incomplete) slice. After slice completion, state.activeSlice advances
|
|
223
207
|
// to the next incomplete slice, so we find the last done slice from the
|
|
224
208
|
// roadmap instead (#1693).
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
if (uatCompletedSliceIds.length === 0) {
|
|
230
|
-
// File-based fallback: parse roadmap checkboxes
|
|
231
|
-
const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
|
|
232
|
-
if (roadmapPath) {
|
|
233
|
-
const roadmapContent = await loadFile(roadmapPath);
|
|
234
|
-
if (roadmapContent) {
|
|
235
|
-
uatCompletedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
209
|
+
// DB-authoritative read (ADR-017) — no markdown fallback for dispatch
|
|
210
|
+
// decisions.
|
|
211
|
+
const uatCompletedSliceIds = isDbAvailable() ? getClosedSliceIds(mid) : [];
|
|
239
212
|
if (uatCompletedSliceIds.length === 0) {
|
|
240
213
|
ctx.ui.notify("Cannot dispatch run-uat: no completed slices.", "warning");
|
|
241
214
|
return;
|
|
@@ -280,18 +253,15 @@ export async function dispatchDirectPhase(
|
|
|
280
253
|
return;
|
|
281
254
|
}
|
|
282
255
|
|
|
283
|
-
const compatibilityError =
|
|
284
|
-
ctx.model?.provider,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
activeTools: typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [],
|
|
293
|
-
},
|
|
294
|
-
);
|
|
256
|
+
const compatibilityError = getUnitWorkflowDispatchReadinessError({
|
|
257
|
+
provider: ctx.model?.provider,
|
|
258
|
+
projectRoot,
|
|
259
|
+
surface: "direct phase dispatch",
|
|
260
|
+
unitType,
|
|
261
|
+
authMode: ctx.model?.provider ? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider) : undefined,
|
|
262
|
+
baseUrl: ctx.model?.baseUrl,
|
|
263
|
+
activeTools: typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [],
|
|
264
|
+
});
|
|
295
265
|
if (compatibilityError) {
|
|
296
266
|
ctx.ui.notify(compatibilityError, "error");
|
|
297
267
|
return;
|