@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
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { debugCount, debugLog, debugTime } from "../debug-logger.js";
|
|
13
13
|
import { reconcileBeforeDispatch } from "../state-reconciliation.js";
|
|
14
14
|
import { isLegalEdge, IllegalPhaseTransitionError } from "../state-transition-matrix.js";
|
|
15
|
-
import { resolveDispatch } from "../auto-dispatch.js";
|
|
15
|
+
import { hasPendingDeepStage, resolveDispatch } from "../auto-dispatch.js";
|
|
16
16
|
import { classifyFailure } from "../recovery-classification.js";
|
|
17
17
|
import { verifyExpectedArtifact, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
|
|
18
18
|
import { invalidateAllCaches } from "../cache.js";
|
|
@@ -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 {
|
|
@@ -118,14 +111,25 @@ function shouldAdoptActiveMilestone(state, activeSession, activeDispatchBasePath
|
|
|
118
111
|
export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, session, input) {
|
|
119
112
|
const state = input.stateSnapshot;
|
|
120
113
|
const active = state.activeMilestone;
|
|
121
|
-
if (!active)
|
|
122
|
-
return null;
|
|
123
114
|
const activeSession = input.session ?? session;
|
|
124
115
|
const activeDispatchBasePath = activeSession?.basePath || dispatchBasePath;
|
|
125
|
-
|
|
116
|
+
const prefs = loadEffectiveGSDPreferences(activeDispatchBasePath)?.preferences;
|
|
117
|
+
if (!active) {
|
|
118
|
+
if (state.phase !== "pre-planning")
|
|
119
|
+
return null;
|
|
120
|
+
if (!hasPendingDeepStage(prefs, activeDispatchBasePath)) {
|
|
121
|
+
return {
|
|
122
|
+
kind: "blocked",
|
|
123
|
+
reason: state.nextAction || "No active milestone. Run /gsd unpark <id> or create a new milestone.",
|
|
124
|
+
action: "stop",
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (active && activeSession && shouldAdoptActiveMilestone(state, activeSession, activeDispatchBasePath)) {
|
|
126
129
|
activeSession.currentMilestoneId = active.id;
|
|
127
130
|
}
|
|
128
|
-
const
|
|
131
|
+
const dispatchMid = active?.id ?? activeSession?.currentMilestoneId ?? "";
|
|
132
|
+
const dispatchMidTitle = active?.title ?? "";
|
|
129
133
|
// Derive session-derived dispatch inputs the same way phases.ts:runDispatch does
|
|
130
134
|
// (#5789). Prefer caller-supplied values when present so test harnesses and
|
|
131
135
|
// alternative wirings can inject deterministic snapshots; otherwise pull from
|
|
@@ -153,8 +157,15 @@ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, sess
|
|
|
153
157
|
})
|
|
154
158
|
? "true"
|
|
155
159
|
: "false");
|
|
160
|
+
// Only replay a milestone-scoped verification retry when a milestone is
|
|
161
|
+
// active. Pre-PR (#712 fix), `!active` returned null before reaching this
|
|
162
|
+
// block, so the retry was preserved for a future tick. The new
|
|
163
|
+
// pre-planning + deep-pending fall-through must keep that contract:
|
|
164
|
+
// otherwise a stale execute-task / complete-slice / complete-milestone
|
|
165
|
+
// retry whose target milestone has since been parked would preempt
|
|
166
|
+
// project-level deep rules like `discuss-project`.
|
|
156
167
|
const pendingRetry = session?.pendingVerificationRetryDispatch;
|
|
157
|
-
if (session && pendingRetry) {
|
|
168
|
+
if (session && pendingRetry && active) {
|
|
158
169
|
session.pendingVerificationRetryDispatch = null;
|
|
159
170
|
const alreadyClosedReason = getAlreadyClosedDispatchReason(pendingRetry.unitType, pendingRetry.unitId);
|
|
160
171
|
if (alreadyClosedReason) {
|
|
@@ -172,8 +183,8 @@ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, sess
|
|
|
172
183
|
}
|
|
173
184
|
const action = await resolveDispatch({
|
|
174
185
|
basePath: activeDispatchBasePath,
|
|
175
|
-
mid:
|
|
176
|
-
midTitle:
|
|
186
|
+
mid: dispatchMid,
|
|
187
|
+
midTitle: dispatchMidTitle,
|
|
177
188
|
state,
|
|
178
189
|
prefs,
|
|
179
190
|
session: activeSession,
|
|
@@ -218,8 +229,8 @@ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, sess
|
|
|
218
229
|
prompt: action.prompt,
|
|
219
230
|
pauseAfterUatDispatch: action.pauseAfterDispatch ?? false,
|
|
220
231
|
state,
|
|
221
|
-
mid:
|
|
222
|
-
midTitle:
|
|
232
|
+
mid: dispatchMid,
|
|
233
|
+
midTitle: dispatchMidTitle,
|
|
223
234
|
};
|
|
224
235
|
session.pendingOrchestrationDispatch = pending;
|
|
225
236
|
}
|
|
@@ -244,7 +255,9 @@ export class AutoOrchestrator {
|
|
|
244
255
|
seq = 0;
|
|
245
256
|
lastAdvanceKey = null;
|
|
246
257
|
lastFinalizedUnitKey = null;
|
|
247
|
-
|
|
258
|
+
// Dispatch History module (#482): the dispatch-decision window with
|
|
259
|
+
// cross-session DB rehydration and full detect-stuck rules.
|
|
260
|
+
dispatchHistory;
|
|
248
261
|
// ADR-030 Phase Transition Invariant: the prior advance's reconciled Phase,
|
|
249
262
|
// the "from" endpoint of the edge check. In-memory; reset on start/resume/stop
|
|
250
263
|
// so the first advance of a session has no edge to assert.
|
|
@@ -260,6 +273,13 @@ export class AutoOrchestrator {
|
|
|
260
273
|
this.runtimeBasePath = context.runtimeBasePath;
|
|
261
274
|
this.s = context.session;
|
|
262
275
|
this.flowId = `auto-orchestrator-${Date.now()}`;
|
|
276
|
+
this.dispatchHistory = createDispatchHistory({
|
|
277
|
+
windowSize: STUCK_WINDOW_SIZE,
|
|
278
|
+
// Same stable scope the auto-loop uses for stuck-state persistence so
|
|
279
|
+
// rehydration reads the rows the dispatch ledger wrote for this project.
|
|
280
|
+
resolveScopeId: () => normalizeRealPath(this.s.scope?.workspace.projectRoot ??
|
|
281
|
+
(this.s.originalBasePath || this.s.basePath || this.runtimeBasePath)) || null,
|
|
282
|
+
});
|
|
263
283
|
}
|
|
264
284
|
// ── Live base-path resolution (was the wiring factory's getLiveDispatchBasePath) ──
|
|
265
285
|
getLiveDispatchBasePath() {
|
|
@@ -612,7 +632,7 @@ export class AutoOrchestrator {
|
|
|
612
632
|
* skipped result) instead of stopping.
|
|
613
633
|
*/
|
|
614
634
|
tryStuckArtifactRecovery(unitType, unitId) {
|
|
615
|
-
const key =
|
|
635
|
+
const key = buildDispatchKey(unitType, unitId);
|
|
616
636
|
if (this.lastStuckRecoveryKey === key)
|
|
617
637
|
return false; // already tried this episode
|
|
618
638
|
const basePath = this.getLiveDispatchBasePath();
|
|
@@ -627,7 +647,7 @@ export class AutoOrchestrator {
|
|
|
627
647
|
return false;
|
|
628
648
|
this.lastStuckRecoveryKey = key;
|
|
629
649
|
invalidateAllCaches();
|
|
630
|
-
this.
|
|
650
|
+
this.dispatchHistory.clearOnRecovery();
|
|
631
651
|
this.lastAdvanceKey = null;
|
|
632
652
|
this.lastFinalizedUnitKey = null;
|
|
633
653
|
return true;
|
|
@@ -653,7 +673,12 @@ export class AutoOrchestrator {
|
|
|
653
673
|
async start(_sessionContext) {
|
|
654
674
|
this.lastAdvanceKey = null;
|
|
655
675
|
this.lastFinalizedUnitKey = null;
|
|
656
|
-
|
|
676
|
+
// #482: the DB dispatch ledger is the source of truth across sessions.
|
|
677
|
+
// Discard any in-memory window and rebuild it from the ledger so a unit
|
|
678
|
+
// that was re-dispatched in previous sessions is detected as stuck here
|
|
679
|
+
// instead of silently re-dispatching forever.
|
|
680
|
+
this.dispatchHistory.clearOnRecovery();
|
|
681
|
+
this.dispatchHistory.rehydrate();
|
|
657
682
|
this.lastStuckRecoveryKey = null;
|
|
658
683
|
this.lastDerivedPhase = null;
|
|
659
684
|
this.status.phase = "running";
|
|
@@ -753,7 +778,7 @@ export class AutoOrchestrator {
|
|
|
753
778
|
this.status.phase = "paused";
|
|
754
779
|
this.status.activeUnit = undefined;
|
|
755
780
|
this.lastAdvanceKey = null;
|
|
756
|
-
this.
|
|
781
|
+
this.dispatchHistory.clearOnRecovery();
|
|
757
782
|
this.bumpTransition();
|
|
758
783
|
this.journalTransition({ name: "advance-blocked", reason: settlementBlock.reason });
|
|
759
784
|
this.postAdvanceRecord(settlementBlock);
|
|
@@ -769,7 +794,7 @@ export class AutoOrchestrator {
|
|
|
769
794
|
this.status.phase = "stopped";
|
|
770
795
|
this.status.activeUnit = undefined;
|
|
771
796
|
this.lastAdvanceKey = null;
|
|
772
|
-
this.
|
|
797
|
+
this.dispatchHistory.clearOnRecovery();
|
|
773
798
|
this.bumpTransition();
|
|
774
799
|
this.journalTransition({ name: "advance-stopped", reason: stopped.reason });
|
|
775
800
|
this.postAdvanceRecord(stopped);
|
|
@@ -817,16 +842,12 @@ export class AutoOrchestrator {
|
|
|
817
842
|
this.postAdvanceRecord(blocked);
|
|
818
843
|
return blocked;
|
|
819
844
|
}
|
|
820
|
-
|
|
821
|
-
// Record every dispatch decision in the ring buffer before pre-flight
|
|
845
|
+
// Record every dispatch decision in the history window before pre-flight
|
|
822
846
|
// checks so the stuck-loop detector observes the full decision history
|
|
823
847
|
// (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;
|
|
848
|
+
// The window is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
|
|
849
|
+
const nextKey = this.dispatchHistory.recordDispatch(decision.unitType, decision.unitId);
|
|
850
|
+
const matchingCount = this.dispatchHistory.countMatching(nextKey);
|
|
830
851
|
if (this.lastFinalizedUnitKey === nextKey) {
|
|
831
852
|
// #442: the unit re-dispatched immediately after finalizing may have
|
|
832
853
|
// actually completed on disk with a stale DB. Verify + recover before
|
|
@@ -858,22 +879,30 @@ export class AutoOrchestrator {
|
|
|
858
879
|
// checks coexist: idempotency for the common immediate-repeat case,
|
|
859
880
|
// stuck-loop for the saturated-window case.
|
|
860
881
|
if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
|
|
882
|
+
// Unit already active — benign no-op. Return skipped so the loop re-polls
|
|
883
|
+
// without cancelling the in-flight unit (blocked+pause would force-cancel it).
|
|
861
884
|
this.clearPendingDispatch();
|
|
862
|
-
const
|
|
885
|
+
const skipped = { kind: "skipped", reason: "idempotent advance: unit already active" };
|
|
863
886
|
this.journalTransition({
|
|
864
|
-
name: "advance-
|
|
865
|
-
reason:
|
|
887
|
+
name: "advance-skipped",
|
|
888
|
+
reason: skipped.reason,
|
|
866
889
|
unitType: decision.unitType,
|
|
867
890
|
unitId: decision.unitId,
|
|
868
891
|
});
|
|
869
|
-
this.postAdvanceRecord(
|
|
870
|
-
return
|
|
892
|
+
this.postAdvanceRecord(skipped);
|
|
893
|
+
return skipped;
|
|
871
894
|
}
|
|
872
|
-
// Stuck-loop detection: when the
|
|
873
|
-
// `nextKey` (count >= STUCK_WINDOW_SIZE), the
|
|
874
|
-
//
|
|
875
|
-
//
|
|
876
|
-
|
|
895
|
+
// Stuck-loop detection: when the window is saturated with copies of
|
|
896
|
+
// `nextKey` (count >= STUCK_WINDOW_SIZE), consult the Dispatch History
|
|
897
|
+
// module's full detect-stuck rule set for the verdict instead of the old
|
|
898
|
+
// bare saturation count. This keeps the saturation threshold (the window
|
|
899
|
+
// deliberately records benign idempotent repeats, so earlier-firing
|
|
900
|
+
// rules would false-positive on pause/resume re-advances) while gaining
|
|
901
|
+
// retry-budget suppression and diagnosable rule reasons. A saturated
|
|
902
|
+
// window with no verdict means the dispatch ledger says we are inside
|
|
903
|
+
// the unit's retry-backoff budget — let the retry proceed.
|
|
904
|
+
const stuckVerdict = matchingCount >= STUCK_WINDOW_SIZE ? this.dispatchHistory.detectStuck() : null;
|
|
905
|
+
if (stuckVerdict) {
|
|
877
906
|
// #442: before declaring a stuck loop, verify the unit didn't actually
|
|
878
907
|
// complete on disk (stale DB) and recover if so — legacy graduated
|
|
879
908
|
// stuck-recovery parity. Otherwise hard-stop with a diagnosable reason.
|
|
@@ -884,7 +913,7 @@ export class AutoOrchestrator {
|
|
|
884
913
|
this.clearPendingDispatch();
|
|
885
914
|
const blocked = {
|
|
886
915
|
kind: "blocked",
|
|
887
|
-
reason: `stuck-loop: ${
|
|
916
|
+
reason: `stuck-loop: ${stuckVerdict.reason}`,
|
|
888
917
|
action: "stop",
|
|
889
918
|
};
|
|
890
919
|
this.journalTransition({
|
|
@@ -974,7 +1003,7 @@ export class AutoOrchestrator {
|
|
|
974
1003
|
if (result.kind === "stopped") {
|
|
975
1004
|
this.lastAdvanceKey = null;
|
|
976
1005
|
this.lastFinalizedUnitKey = null;
|
|
977
|
-
this.
|
|
1006
|
+
this.dispatchHistory.clearOnRecovery();
|
|
978
1007
|
this.status.activeUnit = undefined;
|
|
979
1008
|
}
|
|
980
1009
|
this.bumpTransition();
|
|
@@ -1003,8 +1032,14 @@ export class AutoOrchestrator {
|
|
|
1003
1032
|
async resume() {
|
|
1004
1033
|
this.lastAdvanceKey = null;
|
|
1005
1034
|
this.lastFinalizedUnitKey = null;
|
|
1006
|
-
// Preserve
|
|
1007
|
-
// accumulates across pause/resume cycles rather than
|
|
1035
|
+
// Preserve the dispatch-history window across an in-process resume so
|
|
1036
|
+
// stuck-loop detection accumulates across pause/resume cycles rather than
|
|
1037
|
+
// resetting each time (#572 regression). When the window is empty (fresh
|
|
1038
|
+
// orchestrator resuming a prior session), rehydrate it from the DB
|
|
1039
|
+
// dispatch ledger so cross-session re-dispatch loops are detected (#482).
|
|
1040
|
+
if (this.dispatchHistory.getRecentWindow().length === 0) {
|
|
1041
|
+
this.dispatchHistory.rehydrate();
|
|
1042
|
+
}
|
|
1008
1043
|
this.lastStuckRecoveryKey = null;
|
|
1009
1044
|
// ADR-030: drop the prior "from" — the first advance after resume has no
|
|
1010
1045
|
// edge to assert (avoids a false illegal-edge across the pause boundary).
|
|
@@ -1025,10 +1060,10 @@ export class AutoOrchestrator {
|
|
|
1025
1060
|
this.lastAdvanceKey = null;
|
|
1026
1061
|
this.lastFinalizedUnitKey = null;
|
|
1027
1062
|
this.lastDerivedPhase = null;
|
|
1028
|
-
// Preserve
|
|
1029
|
-
// across pause/resume cycles. Only clear on a hard stop.
|
|
1063
|
+
// Preserve the dispatch-history window on pause so stuck-loop detection
|
|
1064
|
+
// accumulates across pause/resume cycles. Only clear on a hard stop.
|
|
1030
1065
|
if (reason !== "pause") {
|
|
1031
|
-
this.
|
|
1066
|
+
this.dispatchHistory.clearOnRecovery();
|
|
1032
1067
|
}
|
|
1033
1068
|
this.lastStuckRecoveryKey = null;
|
|
1034
1069
|
this.bumpTransition();
|
|
@@ -1040,9 +1075,9 @@ export class AutoOrchestrator {
|
|
|
1040
1075
|
return { ...this.status, activeUnit: this.status.activeUnit ? { ...this.status.activeUnit } : undefined };
|
|
1041
1076
|
}
|
|
1042
1077
|
async completeActiveUnit(unit) {
|
|
1043
|
-
const unitKey =
|
|
1078
|
+
const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
|
|
1044
1079
|
const activeUnitKey = this.status.activeUnit
|
|
1045
|
-
?
|
|
1080
|
+
? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
|
|
1046
1081
|
: null;
|
|
1047
1082
|
if (activeUnitKey !== unitKey)
|
|
1048
1083
|
return;
|
|
@@ -1059,9 +1094,9 @@ export class AutoOrchestrator {
|
|
|
1059
1094
|
});
|
|
1060
1095
|
}
|
|
1061
1096
|
async retryActiveUnit(unit) {
|
|
1062
|
-
const unitKey =
|
|
1097
|
+
const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
|
|
1063
1098
|
const activeUnitKey = this.status.activeUnit
|
|
1064
|
-
?
|
|
1099
|
+
? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
|
|
1065
1100
|
: null;
|
|
1066
1101
|
if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey)
|
|
1067
1102
|
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 "../
|
|
14
|
-
import { resolveEffectiveUnitIsolationMode } from "../preferences.js";
|
|
13
|
+
import { lastAssistantText } from "../consent-question.js";
|
|
14
|
+
import { resolveEffectiveUnitIsolationMode, getIsolationMode } 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";
|
|
@@ -34,9 +35,10 @@ import { writeUnitRuntimeRecord } from "../unit-runtime.js";
|
|
|
34
35
|
import { withTimeout, FINALIZE_PRE_TIMEOUT_MS, FINALIZE_POST_TIMEOUT_MS } from "./finalize-timeout.js";
|
|
35
36
|
import { getEligibleSlices } from "../slice-parallel-eligibility.js";
|
|
36
37
|
import { isSliceParallelActive, startSliceParallel } from "../slice-parallel-orchestrator.js";
|
|
37
|
-
import { isDbAvailable, getMilestoneSlices, getSlice, getTask } from "../gsd-db.js";
|
|
38
|
+
import { isDbAvailable, getMilestone, getMilestoneSlices, getSlice, getTask } from "../gsd-db.js";
|
|
38
39
|
import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
|
|
39
40
|
import { isClosedStatus } from "../status-guards.js";
|
|
41
|
+
import { findUnmergedCompletedMilestones } from "../unmerged-milestone-guard.js";
|
|
40
42
|
import { setRuntimeKv } from "../db/runtime-kv.js";
|
|
41
43
|
import { getLatestForUnit } from "../db/unit-dispatches.js";
|
|
42
44
|
import { reconcileBeforeSpawn } from "../state-reconciliation.js";
|
|
@@ -49,7 +51,8 @@ import { parseUnitId } from "../unit-id.js";
|
|
|
49
51
|
import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
|
|
50
52
|
import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
|
|
51
53
|
import { getContextPauseAction } from "../auto-budget.js";
|
|
52
|
-
import {
|
|
54
|
+
import { supportsStructuredQuestions } from "../workflow-mcp.js";
|
|
55
|
+
import { getUnitWorkflowDispatchReadinessError } from "../tool-contract.js";
|
|
53
56
|
import { prepareWorkflowMcpForProject } from "../workflow-mcp-auto-prep.js";
|
|
54
57
|
import { applyThinkingLevelForModel, floorThinkingLevelForUnit, getRegisteredToolSnapshot, getToolBaselineSnapshot, } from "../auto-model-selection.js";
|
|
55
58
|
import { resolveManifest } from "../unit-context-manifest.js";
|
|
@@ -60,7 +63,6 @@ import { buildPhaseHandoffOutcome, setAutoActiveStatus, setAutoOutcomeWidget } f
|
|
|
60
63
|
import { getConsecutiveDispatchBlocker } from "../dispatch-guard.js";
|
|
61
64
|
import { captureRootDirtySnapshot, detectRootWriteLeak, formatRootWriteLeakMessage, } from "../root-write-leak-guard.js";
|
|
62
65
|
import { classifyError, isTransient } from "../error-classifier.js";
|
|
63
|
-
export const STUCK_WINDOW_SIZE = 6;
|
|
64
66
|
const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
|
|
65
67
|
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
68
|
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;
|
|
@@ -600,6 +602,36 @@ async function failClosedOnFinalizeTimeout(ic, iterData, loopState, stage, start
|
|
|
600
602
|
drainLogs();
|
|
601
603
|
return { action: "break", reason: progressKind };
|
|
602
604
|
}
|
|
605
|
+
export async function shouldSkipTerminalMilestoneCloseout(s, state, mid) {
|
|
606
|
+
const closeoutMilestoneId = mid ?? s.currentMilestoneId ?? state.lastCompletedMilestone?.id;
|
|
607
|
+
if (s.completionStopInProgress) {
|
|
608
|
+
return { skip: true, milestoneId: closeoutMilestoneId };
|
|
609
|
+
}
|
|
610
|
+
if (!closeoutMilestoneId) {
|
|
611
|
+
return { skip: false };
|
|
612
|
+
}
|
|
613
|
+
if (isDbAvailable())
|
|
614
|
+
refreshWorkflowDatabaseFromDisk();
|
|
615
|
+
const closeoutBasePath = s.originalBasePath || s.canonicalProjectRoot || s.basePath;
|
|
616
|
+
let closeoutMergePending = false;
|
|
617
|
+
if (getIsolationMode(closeoutBasePath) !== "none") {
|
|
618
|
+
try {
|
|
619
|
+
const blockers = await findUnmergedCompletedMilestones(closeoutBasePath);
|
|
620
|
+
closeoutMergePending = blockers.some((blocker) => blocker.milestoneId === closeoutMilestoneId);
|
|
621
|
+
}
|
|
622
|
+
catch {
|
|
623
|
+
// Fail open: without git/DB inspection we cannot safely treat closeout as done.
|
|
624
|
+
closeoutMergePending = true;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
const milestoneAlreadyClosedOut = isDbAvailable()
|
|
628
|
+
&& isClosedStatus(getMilestone(closeoutMilestoneId)?.status ?? "")
|
|
629
|
+
&& !closeoutMergePending;
|
|
630
|
+
if (milestoneAlreadyClosedOut) {
|
|
631
|
+
return { skip: true, milestoneId: closeoutMilestoneId };
|
|
632
|
+
}
|
|
633
|
+
return { skip: false, milestoneId: closeoutMilestoneId };
|
|
634
|
+
}
|
|
603
635
|
// ─── runPreDispatch ───────────────────────────────────────────────────────────
|
|
604
636
|
/**
|
|
605
637
|
* Phase 1: Pre-dispatch — resource guard, health gate, state derivation,
|
|
@@ -962,6 +994,13 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
962
994
|
deps.setActiveMilestoneId(s.basePath, mid);
|
|
963
995
|
}
|
|
964
996
|
// ── Terminal conditions ──────────────────────────────────────────────
|
|
997
|
+
if (state.phase === "complete") {
|
|
998
|
+
const closeoutSkip = await shouldSkipTerminalMilestoneCloseout(s, state, mid);
|
|
999
|
+
if (closeoutSkip.skip) {
|
|
1000
|
+
debugLog("autoLoop", { phase: "complete", reason: "milestone-already-closed", milestoneId: closeoutSkip.milestoneId });
|
|
1001
|
+
return { action: "break", reason: "milestone-complete" };
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
965
1004
|
if (!mid) {
|
|
966
1005
|
if (s.currentUnit) {
|
|
967
1006
|
await deps.closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
|
|
@@ -1769,7 +1808,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1769
1808
|
s.currentDispatchedModelId = s.currentUnitModel
|
|
1770
1809
|
? `${s.currentUnitModel.provider ?? ""}/${s.currentUnitModel.id ?? ""}`
|
|
1771
1810
|
: null;
|
|
1772
|
-
const compatibilityError =
|
|
1811
|
+
const compatibilityError = getUnitWorkflowDispatchReadinessError({
|
|
1812
|
+
provider: s.currentUnitModel?.provider ?? ctx.model?.provider,
|
|
1773
1813
|
projectRoot: s.basePath,
|
|
1774
1814
|
surface: "auto-mode",
|
|
1775
1815
|
unitType,
|
|
@@ -1848,6 +1888,9 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1848
1888
|
causedBy: "unit-start",
|
|
1849
1889
|
});
|
|
1850
1890
|
s.lastToolInvocationError = null; // #2883: clear stale error from previous unit
|
|
1891
|
+
if (nextDispatchCount <= 1) {
|
|
1892
|
+
s.toolUnavailableRetries = 0;
|
|
1893
|
+
}
|
|
1851
1894
|
const unitStartSeq = ic.nextSeq();
|
|
1852
1895
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
|
|
1853
1896
|
deps.captureAvailableSkills();
|
|
@@ -126,6 +126,8 @@ export class AutoSession {
|
|
|
126
126
|
/** Set when a GSD tool execution ends with isError due to malformed/truncated
|
|
127
127
|
* JSON arguments. Checked by postUnitPreVerification to break retry loops. */
|
|
128
128
|
lastToolInvocationError = null;
|
|
129
|
+
/** Consecutive tool-unavailable retries for the current unit (MCP startup race). */
|
|
130
|
+
toolUnavailableRetries = 0;
|
|
129
131
|
/** Agent-end messages from the just-finished unit, consumed during finalize. */
|
|
130
132
|
lastUnitAgentEndMessages = null;
|
|
131
133
|
/** Set when turn-level git action fails during closeout. */
|
|
@@ -306,6 +308,7 @@ export class AutoSession {
|
|
|
306
308
|
this.lastPreExecFailure = null;
|
|
307
309
|
this.preExecRetryCount.clear();
|
|
308
310
|
this.lastToolInvocationError = null;
|
|
311
|
+
this.toolUnavailableRetries = 0;
|
|
309
312
|
this.lastUnitAgentEndMessages = null;
|
|
310
313
|
this.lastGitActionFailure = null;
|
|
311
314
|
this.lastGitActionStatus = null;
|
|
@@ -4,14 +4,13 @@
|
|
|
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";
|
|
13
12
|
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
14
|
-
import {
|
|
13
|
+
import { getUnitWorkflowDispatchReadinessError } from "./tool-contract.js";
|
|
15
14
|
export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
16
15
|
const state = await deriveState(base);
|
|
17
16
|
const mid = state.activeMilestone?.id;
|
|
@@ -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;
|
|
@@ -225,7 +201,8 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
225
201
|
ctx.ui.notify(`Unknown phase "${phase}". Valid phases: research, plan, execute, complete, validate, reassess, uat, replan.`, "warning");
|
|
226
202
|
return;
|
|
227
203
|
}
|
|
228
|
-
const compatibilityError =
|
|
204
|
+
const compatibilityError = getUnitWorkflowDispatchReadinessError({
|
|
205
|
+
provider: ctx.model?.provider,
|
|
229
206
|
projectRoot,
|
|
230
207
|
surface: "direct phase dispatch",
|
|
231
208
|
unitType,
|