@opengsd/gsd-pi 1.1.1-dev.74e8dd1 → 1.1.1-dev.a5a2de8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -2
- package/dist/help-text.js +10 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
- package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
- package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/dist/resources/extensions/browser-tools/index.js +57 -9
- package/dist/resources/extensions/browser-tools/package.json +5 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
- package/dist/resources/extensions/gsd/auto-dashboard.js +77 -13
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +21 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +63 -22
- package/dist/resources/extensions/gsd/auto-recovery.js +3 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +18 -66
- package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
- package/dist/resources/extensions/gsd/auto.js +9 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +20 -14
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +28 -13
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +18 -29
- package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
- package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
- package/dist/resources/extensions/gsd/escalation.js +4 -4
- package/dist/resources/extensions/gsd/forensics.js +74 -2
- package/dist/resources/extensions/gsd/gsd-db.js +5 -2
- package/dist/resources/extensions/gsd/guided-flow.js +118 -175
- package/dist/resources/extensions/gsd/mcp-project-config.js +9 -76
- package/dist/resources/extensions/gsd/memory-store.js +4 -1
- package/dist/resources/extensions/gsd/milestone-closeout.js +3 -1
- package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +25 -21
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/dist/resources/extensions/gsd/recovery-classification.js +20 -0
- package/dist/resources/extensions/gsd/rule-registry.js +428 -52
- package/dist/resources/extensions/gsd/state.js +2 -2
- package/dist/resources/extensions/gsd/templates/plan.md +3 -1
- package/dist/resources/extensions/gsd/tool-contract.js +5 -0
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +17 -7
- package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +132 -18
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
- package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
- package/dist/resources/extensions/gsd/verification-gate.js +72 -1
- package/dist/resources/extensions/gsd/workflow-mcp.js +3 -75
- package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
- package/dist/rtk.d.ts +7 -1
- package/dist/rtk.js +27 -11
- package/dist/update-check.d.ts +15 -1
- package/dist/update-check.js +87 -12
- package/dist/update-cmd.d.ts +1 -0
- package/dist/update-cmd.js +53 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +4 -2
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +32 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/index.d.ts +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +1 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
- package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
- package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
- package/packages/gsd-agent-core/package.json +6 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -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 +20 -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 +7 -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-command-handlers.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
- package/packages/mcp-server/dist/remote-questions.js +23 -9
- package/packages/mcp-server/dist/remote-questions.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +2 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +42 -3
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +6 -1
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/api-registry.d.ts +2 -0
- package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
- package/packages/pi-ai/dist/api-registry.js +23 -0
- package/packages/pi-ai/dist/api-registry.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +74 -6
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +78 -10
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/stream.js +6 -6
- package/packages/pi-ai/dist/stream.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
- package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
- package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
- package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/src/resources/extensions/browser-tools/index.ts +60 -9
- package/src/resources/extensions/browser-tools/package.json +5 -1
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
- package/src/resources/extensions/gsd/auto-dashboard.ts +82 -14
- package/src/resources/extensions/gsd/auto-dispatch.ts +19 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +28 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +97 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +3 -3
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -74
- package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
- package/src/resources/extensions/gsd/auto.ts +12 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +20 -14
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +32 -13
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +50 -54
- package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
- package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
- package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
- package/src/resources/extensions/gsd/escalation.ts +4 -4
- package/src/resources/extensions/gsd/forensics.ts +99 -5
- package/src/resources/extensions/gsd/gsd-db.ts +5 -2
- package/src/resources/extensions/gsd/guided-flow.ts +214 -216
- package/src/resources/extensions/gsd/mcp-project-config.ts +13 -78
- package/src/resources/extensions/gsd/memory-store.ts +4 -1
- package/src/resources/extensions/gsd/milestone-closeout.ts +3 -1
- package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +25 -21
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/src/resources/extensions/gsd/recovery-classification.ts +20 -0
- package/src/resources/extensions/gsd/rule-registry.ts +558 -58
- package/src/resources/extensions/gsd/rule-types.ts +2 -0
- package/src/resources/extensions/gsd/state.ts +2 -2
- package/src/resources/extensions/gsd/templates/plan.md +3 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +105 -4
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +10 -2
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
- package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
- package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
- package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +31 -79
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +69 -10
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -0
- package/src/resources/extensions/gsd/tool-contract.ts +6 -0
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +38 -8
- package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +163 -20
- package/src/resources/extensions/gsd/types.ts +69 -5
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +186 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
- package/src/resources/extensions/gsd/verification-gate.ts +87 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -75
- package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
- /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → 9y3LeeR2uGr2yRj9RjY3D}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → 9y3LeeR2uGr2yRj9RjY3D}/_ssgManifest.js +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "node --test tests/*.test.mjs"
|
|
7
|
+
"test": "node --import ../gsd/tests/resolve-ts.mjs --experimental-strip-types --test tests/*.test.mjs"
|
|
8
8
|
},
|
|
9
9
|
"pi": {
|
|
10
10
|
"extensions": [
|
|
@@ -12,10 +12,14 @@
|
|
|
12
12
|
]
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
+
"@opengsd/gsd-browser": ">=0.1.27",
|
|
15
16
|
"playwright": ">=1.40.0",
|
|
16
17
|
"sharp": ">=0.33.0"
|
|
17
18
|
},
|
|
18
19
|
"peerDependenciesMeta": {
|
|
20
|
+
"@opengsd/gsd-browser": {
|
|
21
|
+
"optional": true
|
|
22
|
+
},
|
|
19
23
|
"playwright": {
|
|
20
24
|
"optional": true
|
|
21
25
|
},
|
|
@@ -256,7 +256,6 @@ export class AutoOrchestrator {
|
|
|
256
256
|
this.status.activeUnit = { unitType: decision.unitType, unitId: decision.unitId };
|
|
257
257
|
this.status.phase = "running";
|
|
258
258
|
this.lastAdvanceKey = nextKey;
|
|
259
|
-
this.lastFinalizedUnitKey = null;
|
|
260
259
|
this.bumpTransition();
|
|
261
260
|
await this.deps.runtime.journalTransition({
|
|
262
261
|
name: "advance",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// gsd-pi + src/resources/extensions/gsd/auto-dashboard.ts - Auto-mode progress widget rendering and dashboard helpers.
|
|
2
2
|
import { getActiveHook } from "./post-unit-hooks.js";
|
|
3
|
-
import { getLedger } from "./metrics.js";
|
|
3
|
+
import { getLedger, getProjectTotals } from "./metrics.js";
|
|
4
4
|
import { getErrorMessage } from "./error-utils.js";
|
|
5
5
|
import { nativeIsRepo } from "./native-git-bridge.js";
|
|
6
6
|
import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
|
|
@@ -196,6 +196,39 @@ export function formatRuntimeHealthSignal(record, now = Date.now()) {
|
|
|
196
196
|
export function shouldRenderRoadmapProgress(progress) {
|
|
197
197
|
return !!progress && progress.total > 0;
|
|
198
198
|
}
|
|
199
|
+
function widgetGridLabel(theme, text, color = "borderAccent") {
|
|
200
|
+
return theme.fg(color, theme.bold(text.toUpperCase()));
|
|
201
|
+
}
|
|
202
|
+
function widgetGridColumn(content, width) {
|
|
203
|
+
return padRightVisible(truncateToWidth(content, width, "…"), width);
|
|
204
|
+
}
|
|
205
|
+
function widgetGridColumns(theme, width, parts) {
|
|
206
|
+
if (parts.length === 0)
|
|
207
|
+
return "";
|
|
208
|
+
const gap = theme.fg("dim", " │ ");
|
|
209
|
+
const gapWidth = visibleWidth(gap) * (parts.length - 1);
|
|
210
|
+
const available = Math.max(parts.length * 8, width - gapWidth);
|
|
211
|
+
const base = Math.floor(available / parts.length);
|
|
212
|
+
let remaining = available - base * parts.length;
|
|
213
|
+
const columns = parts.map((part) => {
|
|
214
|
+
const columnWidth = base + (remaining > 0 ? 1 : 0);
|
|
215
|
+
remaining--;
|
|
216
|
+
return widgetGridColumn(part, columnWidth);
|
|
217
|
+
});
|
|
218
|
+
return truncateToWidth(columns.join(gap), width, "…");
|
|
219
|
+
}
|
|
220
|
+
function formatSmallWidgetSpend() {
|
|
221
|
+
const ledger = getLedger();
|
|
222
|
+
if (!ledger || ledger.units.length === 0)
|
|
223
|
+
return "--";
|
|
224
|
+
const totals = getProjectTotals(ledger.units);
|
|
225
|
+
const parts = [];
|
|
226
|
+
if (totals.tokens.total > 0)
|
|
227
|
+
parts.push(formatWidgetTokens(totals.tokens.total));
|
|
228
|
+
if (totals.cost > 0)
|
|
229
|
+
parts.push(`$${totals.cost.toFixed(2)}`);
|
|
230
|
+
return parts.length > 0 ? parts.join(" · ") : "--";
|
|
231
|
+
}
|
|
199
232
|
// ─── ETA Estimation ──────────────────────────────────────────────────────────
|
|
200
233
|
/**
|
|
201
234
|
* Estimate remaining time based on average unit duration from the metrics ledger.
|
|
@@ -642,26 +675,57 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
642
675
|
cachedWidth = width;
|
|
643
676
|
return lines;
|
|
644
677
|
}
|
|
645
|
-
// ── Mode: small —
|
|
678
|
+
// ── Mode: small — dense horizontal grid ───────────────────────
|
|
646
679
|
if (widgetMode === "small") {
|
|
647
|
-
lines.
|
|
648
|
-
|
|
649
|
-
const target = task ? `${task.id}: ${task.title}` : unitId;
|
|
650
|
-
const actionLeft = `${pad}${theme.fg("accent", "▸")} ${theme.fg("accent", verb)} ${theme.fg("text", target)}`;
|
|
651
|
-
lines.push(rightAlign(actionLeft, theme.fg("dim", phaseLabel), width));
|
|
652
|
-
// Progress bar
|
|
680
|
+
lines.length = 0;
|
|
681
|
+
lines.push(...ui.bar());
|
|
653
682
|
const roadmapSlices = mid ? getRoadmapSlicesSync() : null;
|
|
683
|
+
const unitLabel = unitId || [mid?.id, slice?.id, task?.id].filter(Boolean).join("/");
|
|
684
|
+
const statusParts = [
|
|
685
|
+
spinner,
|
|
686
|
+
theme.fg("success", modeTag),
|
|
687
|
+
theme.fg(stateColor, activeState),
|
|
688
|
+
];
|
|
689
|
+
if (runtimeSignal?.summary) {
|
|
690
|
+
statusParts.push(theme.fg(healthColor, healthSummary));
|
|
691
|
+
}
|
|
692
|
+
else if (healthLevel !== "green") {
|
|
693
|
+
statusParts.push(`${theme.fg(healthColor, healthIcon)} ${theme.fg(healthColor, healthSummary)}`);
|
|
694
|
+
}
|
|
695
|
+
const timeValue = [elapsed, etaShort].filter(Boolean).join(" · ") || "--";
|
|
696
|
+
const rowOne = widgetGridColumns(theme, width, [
|
|
697
|
+
`${widgetGridLabel(theme, "status", "border")} ${statusParts.join(" ")}`,
|
|
698
|
+
`${widgetGridLabel(theme, "unit")} ${theme.fg("text", unitLabel || "--")}`,
|
|
699
|
+
`${widgetGridLabel(theme, "spend", "border")} ${theme.fg("dim", formatSmallWidgetSpend())}`,
|
|
700
|
+
`${widgetGridLabel(theme, "time")} ${theme.fg("dim", timeValue)}`,
|
|
701
|
+
]);
|
|
702
|
+
const target = task
|
|
703
|
+
? `${task.id}: ${task.title}`
|
|
704
|
+
: slice
|
|
705
|
+
? `${slice.id}: ${slice.title}`
|
|
706
|
+
: unitId;
|
|
707
|
+
let taskValue = task?.id ?? "--";
|
|
708
|
+
let sliceValue = slice?.id ?? "--";
|
|
654
709
|
if (shouldRenderRoadmapProgress(roadmapSlices)) {
|
|
655
710
|
const { done, total, activeSliceTasks } = roadmapSlices;
|
|
656
|
-
const barWidth = Math.max(
|
|
711
|
+
const barWidth = Math.max(4, Math.min(14, Math.floor(width * 0.12)));
|
|
657
712
|
const bar = renderProgressBar(theme, done, total, barWidth);
|
|
658
|
-
|
|
713
|
+
sliceValue = `${bar} ${theme.fg("text", `${done}/${total}`)}`;
|
|
659
714
|
if (activeSliceTasks && activeSliceTasks.total > 0) {
|
|
660
|
-
const
|
|
661
|
-
|
|
715
|
+
const taskNum = isHook
|
|
716
|
+
? Math.max(activeSliceTasks.done, 1)
|
|
717
|
+
: Math.min(activeSliceTasks.done + 1, activeSliceTasks.total);
|
|
718
|
+
taskValue = `${theme.fg("accent", `${taskNum}`)}${theme.fg("dim", `/${activeSliceTasks.total}`)}`;
|
|
662
719
|
}
|
|
663
|
-
lines.push(`${pad}${bar} ${meta}`);
|
|
664
720
|
}
|
|
721
|
+
const rowTwo = widgetGridColumns(theme, width, [
|
|
722
|
+
`${widgetGridLabel(theme, "phase", "border")} ${theme.fg("dim", unitType)}`,
|
|
723
|
+
`${widgetGridLabel(theme, "work")} ${theme.fg("text", target || "--")}`,
|
|
724
|
+
`${widgetGridLabel(theme, "task", "border")} ${taskValue}`,
|
|
725
|
+
`${widgetGridLabel(theme, "slice")} ${sliceValue}`,
|
|
726
|
+
]);
|
|
727
|
+
lines.push(rowOne);
|
|
728
|
+
lines.push(rowTwo);
|
|
665
729
|
lines.push(...ui.bar());
|
|
666
730
|
cachedLines = lines;
|
|
667
731
|
cachedWidth = width;
|
|
@@ -35,6 +35,7 @@ import { probeGitConflictState } from "./git-conflict-state.js";
|
|
|
35
35
|
import { runTurnGitAction } from "./git-service.js";
|
|
36
36
|
import { parseUnitId } from "./unit-id.js";
|
|
37
37
|
import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
|
|
38
|
+
import { checkCloseoutConsistencyGate, formatCloseoutConsistencyBlock, } from "./closeout-consistency-gate.js";
|
|
38
39
|
function resolveExistingExpectedArtifact(unitType, unitId, basePath) {
|
|
39
40
|
const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
|
|
40
41
|
return artifactPath && existsSync(artifactPath) ? artifactPath : null;
|
|
@@ -443,6 +444,7 @@ export const DISPATCH_RULES = [
|
|
|
443
444
|
unitType: "discuss-milestone",
|
|
444
445
|
unitId: mid,
|
|
445
446
|
prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
|
|
447
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
446
448
|
};
|
|
447
449
|
},
|
|
448
450
|
},
|
|
@@ -578,6 +580,7 @@ export const DISPATCH_RULES = [
|
|
|
578
580
|
unitType: "discuss-milestone",
|
|
579
581
|
unitId: mid,
|
|
580
582
|
prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
|
|
583
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
581
584
|
};
|
|
582
585
|
},
|
|
583
586
|
},
|
|
@@ -617,6 +620,7 @@ export const DISPATCH_RULES = [
|
|
|
617
620
|
unitType: "discuss-project",
|
|
618
621
|
unitId: "PROJECT",
|
|
619
622
|
prompt: await buildDiscussProjectPrompt(basePath, structuredQuestionsAvailable),
|
|
623
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
620
624
|
};
|
|
621
625
|
},
|
|
622
626
|
},
|
|
@@ -642,6 +646,7 @@ export const DISPATCH_RULES = [
|
|
|
642
646
|
unitType: "discuss-requirements",
|
|
643
647
|
unitId: "REQUIREMENTS",
|
|
644
648
|
prompt: await buildDiscussRequirementsPrompt(basePath, structuredQuestionsAvailable),
|
|
649
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
645
650
|
};
|
|
646
651
|
},
|
|
647
652
|
},
|
|
@@ -757,6 +762,7 @@ export const DISPATCH_RULES = [
|
|
|
757
762
|
unitType: "discuss-milestone",
|
|
758
763
|
unitId: mid,
|
|
759
764
|
prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
|
|
765
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
760
766
|
};
|
|
761
767
|
},
|
|
762
768
|
},
|
|
@@ -1350,6 +1356,16 @@ export const DISPATCH_RULES = [
|
|
|
1350
1356
|
prompt: await buildCompleteMilestonePrompt(mid, midTitle, basePath),
|
|
1351
1357
|
};
|
|
1352
1358
|
}
|
|
1359
|
+
if (milestone) {
|
|
1360
|
+
const closeoutGate = checkCloseoutConsistencyGate(mid, { refreshFromDisk: true });
|
|
1361
|
+
if (!closeoutGate.ok) {
|
|
1362
|
+
return {
|
|
1363
|
+
action: "stop",
|
|
1364
|
+
reason: formatCloseoutConsistencyBlock(closeoutGate),
|
|
1365
|
+
level: "warning",
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1353
1369
|
}
|
|
1354
1370
|
return {
|
|
1355
1371
|
action: "stop",
|
|
@@ -32,7 +32,7 @@ import { isDbAvailable, getDbPath, refreshOpenDatabaseFromDisk, getTask, getSlic
|
|
|
32
32
|
import { renderPlanCheckboxes, renderRoadmapFromDb } from "./markdown-renderer.js";
|
|
33
33
|
import { parseRoadmap as parseLegacyRoadmap } from "./parsers-legacy.js";
|
|
34
34
|
import { consumeSignal } from "./session-status-io.js";
|
|
35
|
-
import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
|
|
35
|
+
import { checkPostUnitHooks, consumeHookFailure, isRetryPending, consumeRetryTrigger, consumeGateBlock, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
|
|
36
36
|
import { hasPendingCaptures, loadPendingCaptures, revertExecutorResolvedCaptures } from "./captures.js";
|
|
37
37
|
import { debugLog } from "./debug-logger.js";
|
|
38
38
|
import { runSafely } from "./auto-utils.js";
|
|
@@ -1860,18 +1860,25 @@ export async function postUnitPostVerification(pctx) {
|
|
|
1860
1860
|
// ── Post-unit hooks ──
|
|
1861
1861
|
if (s.currentUnit && !s.stepMode) {
|
|
1862
1862
|
const hookUnit = checkPostUnitHooks(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
1863
|
+
persistHookState(s.basePath);
|
|
1863
1864
|
if (hookUnit) {
|
|
1864
1865
|
if (s.currentUnit) {
|
|
1865
1866
|
await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
|
|
1866
1867
|
}
|
|
1867
|
-
persistHookState(s.basePath);
|
|
1868
1868
|
return enqueueSidecar(s, ctx, { kind: "hook", unitType: hookUnit.unitType, unitId: hookUnit.unitId, prompt: hookUnit.prompt, model: hookUnit.model }, { hookName: hookUnit.hookName });
|
|
1869
1869
|
}
|
|
1870
|
+
const hookFailure = consumeHookFailure();
|
|
1871
|
+
if (hookFailure) {
|
|
1872
|
+
ctx.ui.notify(`Post-unit hook ${hookFailure.hookName} failed for ${hookFailure.unitId}: ${hookFailure.reason}. Pausing auto-mode.`, "warning");
|
|
1873
|
+
await pauseAuto(ctx, pi);
|
|
1874
|
+
return "stopped";
|
|
1875
|
+
}
|
|
1870
1876
|
// Check if a hook requested a retry of the trigger unit
|
|
1871
1877
|
if (isRetryPending()) {
|
|
1872
1878
|
const trigger = consumeRetryTrigger();
|
|
1873
1879
|
if (trigger) {
|
|
1874
|
-
|
|
1880
|
+
persistHookState(s.basePath);
|
|
1881
|
+
ctx.ui.notify(`Hook requested retry of ${trigger.unitType} ${trigger.unitId} — resetting trigger unit state.`, "info");
|
|
1875
1882
|
await s.orchestration?.retryActiveUnit({
|
|
1876
1883
|
unitType: trigger.unitType,
|
|
1877
1884
|
unitId: trigger.unitId,
|
|
@@ -1918,6 +1925,17 @@ export async function postUnitPostVerification(pctx) {
|
|
|
1918
1925
|
// Fall through to normal dispatch — deriveState will re-derive the unit
|
|
1919
1926
|
}
|
|
1920
1927
|
}
|
|
1928
|
+
const gateBlock = consumeGateBlock();
|
|
1929
|
+
if (gateBlock) {
|
|
1930
|
+
persistHookState(s.basePath);
|
|
1931
|
+
const verdict = gateBlock.verdict ? ` verdict=${gateBlock.verdict};` : "";
|
|
1932
|
+
const artifact = gateBlock.artifact ? ` artifact=${gateBlock.artifact};` : "";
|
|
1933
|
+
const message = `Post-unit gate "${gateBlock.hookName}" blocked ${gateBlock.triggerUnitType} ${gateBlock.triggerUnitId}:` +
|
|
1934
|
+
`${verdict}${artifact} ${gateBlock.reason}. Run /gsd status to inspect, then /gsd auto after recovery.`;
|
|
1935
|
+
ctx.ui.notify(message, "warning");
|
|
1936
|
+
await pauseAuto(ctx, pi);
|
|
1937
|
+
return "stopped";
|
|
1938
|
+
}
|
|
1921
1939
|
}
|
|
1922
1940
|
// ── Fast-path stop detection (#3487) ──
|
|
1923
1941
|
// Before waiting for triage, check if any PENDING captures contain explicit
|
|
@@ -30,6 +30,8 @@ import { classifyProject } from "./detection.js";
|
|
|
30
30
|
import { hasBrowserRequiredText } from "./browser-evidence.js";
|
|
31
31
|
import { debugLog } from "./debug-logger.js";
|
|
32
32
|
import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-activation.js";
|
|
33
|
+
import { findMilestoneIds } from "./milestone-ids.js";
|
|
34
|
+
import { buildRunUatResultPresentation, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from "./tool-presentation-plan.js";
|
|
33
35
|
export { buildSkillActivationBlock, buildSkillDiscoveryVars };
|
|
34
36
|
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
35
37
|
/**
|
|
@@ -1270,7 +1272,7 @@ export async function checkNeedsRunUat(base, mid, state, prefs) {
|
|
|
1270
1272
|
if (hasVerdict(uatContent))
|
|
1271
1273
|
continue;
|
|
1272
1274
|
// Also check the ASSESSMENT file — the run-uat prompt writes the verdict
|
|
1273
|
-
// there (via
|
|
1275
|
+
// there (via gsd_uat_result_save), not into the
|
|
1274
1276
|
// UAT spec file. Without this check the unit re-dispatches indefinitely.
|
|
1275
1277
|
const assessmentFile = resolveSliceFile(base, mid, sid, "ASSESSMENT");
|
|
1276
1278
|
if (assessmentFile) {
|
|
@@ -1325,21 +1327,44 @@ export async function checkNeedsRunUat(base, mid, state, prefs) {
|
|
|
1325
1327
|
}
|
|
1326
1328
|
return null;
|
|
1327
1329
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
const
|
|
1330
|
+
export async function buildDiscussMilestoneInlinedContext(mid, base) {
|
|
1331
|
+
const inlined = [];
|
|
1332
|
+
const roadmapInline = await inlineFileOptional(resolveMilestoneFile(base, mid, "ROADMAP"), relMilestoneFile(base, mid, "ROADMAP"), "Milestone Roadmap");
|
|
1333
|
+
if (roadmapInline)
|
|
1334
|
+
inlined.push(roadmapInline);
|
|
1335
|
+
const contextInline = await inlineFileOptional(resolveMilestoneFile(base, mid, "CONTEXT"), relMilestoneFile(base, mid, "CONTEXT"), "Milestone Context");
|
|
1336
|
+
if (contextInline)
|
|
1337
|
+
inlined.push(contextInline);
|
|
1338
|
+
const researchInline = await inlineFileOptional(resolveMilestoneFile(base, mid, "RESEARCH"), relMilestoneFile(base, mid, "RESEARCH"), "Milestone Research");
|
|
1339
|
+
if (researchInline)
|
|
1340
|
+
inlined.push(researchInline);
|
|
1341
|
+
const decisionsPath = resolveGsdRootFile(base, "DECISIONS");
|
|
1342
|
+
if (existsSync(decisionsPath)) {
|
|
1343
|
+
const decisionsContent = await loadFile(decisionsPath);
|
|
1344
|
+
if (decisionsContent) {
|
|
1345
|
+
inlined.push(`### Decisions Register\nSource: \`${relGsdRootFile("DECISIONS")}\`\n\n${decisionsContent.trim()}`);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
const milestoneIds = findMilestoneIds(base);
|
|
1349
|
+
const currentIndex = milestoneIds.indexOf(mid);
|
|
1350
|
+
const priorMilestoneIds = currentIndex >= 0 ? milestoneIds.slice(0, currentIndex) : milestoneIds;
|
|
1351
|
+
for (const priorMid of priorMilestoneIds) {
|
|
1352
|
+
const summaryInline = await inlineFileOptional(resolveMilestoneFile(base, priorMid, "SUMMARY"), relMilestoneFile(base, priorMid, "SUMMARY"), `${priorMid} Prior Milestone Summary`);
|
|
1353
|
+
if (summaryInline)
|
|
1354
|
+
inlined.push(summaryInline);
|
|
1355
|
+
}
|
|
1356
|
+
return inlined.length > 0
|
|
1357
|
+
? `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`
|
|
1358
|
+
: "## Inlined Context\n\n_(no milestone context files found yet — go in blind and ask broad questions)_";
|
|
1359
|
+
}
|
|
1360
|
+
export async function buildDiscussMilestonePrompt(mid, midTitle, base, structuredQuestionsAvailable = "false", { headless = false, commitInstruction = "Do not commit planning artifacts — .gsd/ is managed externally.", fastPathInstruction = "", includeDraftSeed = true, includeContextMode = true, } = {}) {
|
|
1361
|
+
const contextTemplate = inlineTemplate("context", "Context");
|
|
1337
1362
|
if (headless) {
|
|
1338
1363
|
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
1339
1364
|
const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
|
|
1340
1365
|
return loadPrompt("discuss-headless", {
|
|
1341
1366
|
seedContext: roadmapContent ?? "",
|
|
1342
|
-
inlinedTemplates:
|
|
1367
|
+
inlinedTemplates: contextTemplate,
|
|
1343
1368
|
workingDirectory: base,
|
|
1344
1369
|
milestoneId: mid,
|
|
1345
1370
|
contextPath: relMilestoneFile(base, mid, "CONTEXT"),
|
|
@@ -1347,24 +1372,28 @@ export async function buildDiscussMilestonePrompt(mid, midTitle, base, structure
|
|
|
1347
1372
|
multiMilestoneCommitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1348
1373
|
});
|
|
1349
1374
|
}
|
|
1350
|
-
const
|
|
1375
|
+
const rawInlinedContext = await buildDiscussMilestoneInlinedContext(mid, base);
|
|
1376
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
1377
|
+
const discussTemplates = [cappedInlinedContext, contextTemplate].join("\n\n---\n\n");
|
|
1351
1378
|
const basePrompt = loadPrompt("guided-discuss-milestone", {
|
|
1352
1379
|
workingDirectory: base,
|
|
1353
1380
|
milestoneId: mid,
|
|
1354
1381
|
milestoneTitle: midTitle,
|
|
1355
1382
|
inlinedTemplates: discussTemplates,
|
|
1356
1383
|
structuredQuestionsAvailable,
|
|
1357
|
-
commitInstruction
|
|
1358
|
-
fastPathInstruction
|
|
1384
|
+
commitInstruction,
|
|
1385
|
+
fastPathInstruction,
|
|
1359
1386
|
});
|
|
1360
|
-
const promptWithContextMode =
|
|
1387
|
+
const promptWithContextMode = includeContextMode
|
|
1388
|
+
? prependContextModeToBlock("discuss-milestone", base, basePrompt)
|
|
1389
|
+
: basePrompt;
|
|
1361
1390
|
// If a CONTEXT-DRAFT.md exists, append it as seed material
|
|
1362
1391
|
const draftPath = resolveMilestoneFile(base, mid, "CONTEXT-DRAFT");
|
|
1363
1392
|
const draftContent = draftPath ? await loadFile(draftPath) : null;
|
|
1364
|
-
if (draftContent) {
|
|
1393
|
+
if (includeDraftSeed && draftContent) {
|
|
1365
1394
|
return `${promptWithContextMode}\n\n## Prior Discussion (Draft Seed)\n\nThe following draft was captured from a prior multi-milestone discussion. Use it as seed material — the user has already provided this context. Start with a brief reflection on what the draft covers, then probe for any gaps or open questions before writing the full CONTEXT.md.\n\n${draftContent}`;
|
|
1366
1395
|
}
|
|
1367
|
-
return
|
|
1396
|
+
return promptWithContextMode;
|
|
1368
1397
|
}
|
|
1369
1398
|
/**
|
|
1370
1399
|
* Build a prompt for the workflow-preferences unit type (deep mode).
|
|
@@ -2540,17 +2569,26 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
|
|
|
2540
2569
|
if (isDbAvailable()) {
|
|
2541
2570
|
const milestone = getMilestone(mid);
|
|
2542
2571
|
if (milestone) {
|
|
2572
|
+
const escapeCell = (value) => value.replace(/[\\|]/g, (char) => `\\${char}`).replace(/\r?\n/g, " ");
|
|
2543
2573
|
const classes = [];
|
|
2544
2574
|
if (milestone.verification_contract)
|
|
2545
|
-
classes.push(
|
|
2575
|
+
classes.push(`| Contract | ${escapeCell(milestone.verification_contract)} |`);
|
|
2546
2576
|
if (milestone.verification_integration)
|
|
2547
|
-
classes.push(
|
|
2577
|
+
classes.push(`| Integration | ${escapeCell(milestone.verification_integration)} |`);
|
|
2548
2578
|
if (milestone.verification_operational)
|
|
2549
|
-
classes.push(
|
|
2579
|
+
classes.push(`| Operational | ${escapeCell(milestone.verification_operational)} |`);
|
|
2550
2580
|
if (milestone.verification_uat)
|
|
2551
|
-
classes.push(
|
|
2581
|
+
classes.push(`| UAT | ${escapeCell(milestone.verification_uat)} |`);
|
|
2552
2582
|
if (classes.length > 0) {
|
|
2553
|
-
const verificationClasses =
|
|
2583
|
+
const verificationClasses = [
|
|
2584
|
+
"### Verification Classes (from planning)",
|
|
2585
|
+
"",
|
|
2586
|
+
"These verification tiers were defined during milestone planning. Every row in this table must appear in `verificationClasses` with the same canonical class name.",
|
|
2587
|
+
"",
|
|
2588
|
+
"| Class | Planned Check |",
|
|
2589
|
+
"| --- | --- |",
|
|
2590
|
+
...classes,
|
|
2591
|
+
].join("\n");
|
|
2554
2592
|
inlined.push(verificationClasses);
|
|
2555
2593
|
trackPromptContext(contextTelemetry, "verification-classes", "inline", verificationClasses);
|
|
2556
2594
|
}
|
|
@@ -2902,6 +2940,7 @@ export async function buildRunUatPrompt(mid, sliceId, uatPath, uatContent, base)
|
|
|
2902
2940
|
emitPromptContextTelemetry("run-uat", contextTelemetry, inlinedContext);
|
|
2903
2941
|
const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "ASSESSMENT"));
|
|
2904
2942
|
const uatType = resolveEffectiveUatType(uatContent);
|
|
2943
|
+
const canonicalPresentation = JSON.stringify(buildRunUatResultPresentation(), null, 2);
|
|
2905
2944
|
return loadPrompt("run-uat", {
|
|
2906
2945
|
workingDirectory: base,
|
|
2907
2946
|
milestoneId: mid,
|
|
@@ -2909,6 +2948,8 @@ export async function buildRunUatPrompt(mid, sliceId, uatPath, uatContent, base)
|
|
|
2909
2948
|
uatPath,
|
|
2910
2949
|
uatResultPath,
|
|
2911
2950
|
uatType,
|
|
2951
|
+
toolPresentationPlanId: RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
|
|
2952
|
+
canonicalPresentation,
|
|
2912
2953
|
inlinedContext,
|
|
2913
2954
|
skillActivation: buildSkillActivationBlock({
|
|
2914
2955
|
base,
|
|
@@ -32,6 +32,7 @@ import { isGsdWorktreePath } from "./worktree-root.js";
|
|
|
32
32
|
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
33
33
|
import { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
|
|
34
34
|
import { loadAllCaptures, loadPendingCaptures } from "./captures.js";
|
|
35
|
+
import { checkCloseoutConsistencyGate } from "./closeout-consistency-gate.js";
|
|
35
36
|
// Re-export so existing consumers of auto-recovery.ts keep working.
|
|
36
37
|
export { resolveExpectedArtifactPath, diagnoseExpectedArtifact };
|
|
37
38
|
export { classifyMilestoneSummaryContent, } from "./milestone-summary-classifier.js";
|
|
@@ -571,10 +572,8 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
571
572
|
return false;
|
|
572
573
|
const { milestone: mid } = parseUnitId(unitId);
|
|
573
574
|
if (mid && isDbAvailable()) {
|
|
574
|
-
const
|
|
575
|
-
if (!
|
|
576
|
-
return false;
|
|
577
|
-
if (!isClosedStatus(dbMilestone.status) && summaryOutcome !== "success")
|
|
575
|
+
const closeoutGate = checkCloseoutConsistencyGate(mid, { refreshFromDisk: true });
|
|
576
|
+
if (!closeoutGate.ok)
|
|
578
577
|
return false;
|
|
579
578
|
}
|
|
580
579
|
if (hasImplementationArtifacts(base, mid) === "absent")
|
|
@@ -20,6 +20,9 @@ export function isAutoActive() {
|
|
|
20
20
|
export function isAutoPaused() {
|
|
21
21
|
return autoSession.paused;
|
|
22
22
|
}
|
|
23
|
+
export function isAutoCompletionStopInProgress() {
|
|
24
|
+
return autoSession.completionStopInProgress;
|
|
25
|
+
}
|
|
23
26
|
export function markToolStart(toolCallId, toolName) {
|
|
24
27
|
markTrackedToolStart(toolCallId, autoSession.active, toolName);
|
|
25
28
|
}
|
|
@@ -83,7 +83,7 @@ export function clearInFlightTools() {
|
|
|
83
83
|
* from the tool handler. When these errors occur, retrying the same unit will
|
|
84
84
|
* produce the same failure, so the retry loop must be broken.
|
|
85
85
|
*/
|
|
86
|
-
const TOOL_INVOCATION_ERROR_RE = /Validation failed for tool|Expected ',' or '\}'(?: after property value)?(?: in JSON)?|Unexpected end of JSON|Unexpected token.*in JSON|does not provide an export named|Named export .* not found|Cannot find module|ERR_MODULE_NOT_FOUND|ERR_MODULE_NOT_EXPORTED|ERR_PACKAGE_PATH_NOT_EXPORTED/i;
|
|
86
|
+
const TOOL_INVOCATION_ERROR_RE = /Validation failed for tool|Input validation error|Invalid arguments for tool|MCP error -32602|No such tool available|Expected ',' or '\}'(?: after property value)?(?: in JSON)?|Unexpected end of JSON|Unexpected token.*in JSON|does not provide an export named|Named export .* not found|Cannot find module|ERR_MODULE_NOT_FOUND|ERR_MODULE_NOT_EXPORTED|ERR_PACKAGE_PATH_NOT_EXPORTED/i;
|
|
87
87
|
const DETERMINISTIC_POLICY_ERROR_RE = /(?:^|\b)(?:HARD BLOCK:|Blocked: \/gsd queue is a planning tool|Direct writes to \.gsd\/STATE\.md and \.gsd\/gsd\.db are blocked|This is a mechanical gate)/i;
|
|
88
88
|
/**
|
|
89
89
|
* Returns true if the error message indicates a deterministic invocation or
|
|
@@ -1,57 +1,6 @@
|
|
|
1
1
|
import { parseUnitId } from "./unit-id.js";
|
|
2
|
-
import {
|
|
3
|
-
export
|
|
4
|
-
"browser_navigate",
|
|
5
|
-
"browser_click",
|
|
6
|
-
"browser_type",
|
|
7
|
-
"browser_fill_form",
|
|
8
|
-
"browser_click_ref",
|
|
9
|
-
"browser_fill_ref",
|
|
10
|
-
"browser_wait_for",
|
|
11
|
-
"browser_assert",
|
|
12
|
-
"browser_verify",
|
|
13
|
-
"browser_screenshot",
|
|
14
|
-
"browser_snapshot_refs",
|
|
15
|
-
"browser_find",
|
|
16
|
-
"browser_get_console_logs",
|
|
17
|
-
"browser_get_network_logs",
|
|
18
|
-
"browser_evaluate",
|
|
19
|
-
"browser_reload",
|
|
20
|
-
"browser_batch",
|
|
21
|
-
"browser_act",
|
|
22
|
-
];
|
|
23
|
-
export const AUTO_UNIT_SCOPED_TOOLS = {
|
|
24
|
-
"research-milestone": ["gsd_summary_save", "gsd_decision_save"],
|
|
25
|
-
"plan-milestone": ["gsd_plan_milestone", "gsd_decision_save", "gsd_requirement_update"],
|
|
26
|
-
"discuss-milestone": [
|
|
27
|
-
"gsd_summary_save",
|
|
28
|
-
"gsd_decision_save",
|
|
29
|
-
"gsd_requirement_save",
|
|
30
|
-
"gsd_requirement_update",
|
|
31
|
-
"gsd_plan_milestone",
|
|
32
|
-
"gsd_milestone_generate_id",
|
|
33
|
-
],
|
|
34
|
-
"discuss-slice": ["gsd_summary_save", "gsd_decision_save"],
|
|
35
|
-
"validate-milestone": ["gsd_validate_milestone", "gsd_reassess_roadmap", "subagent"],
|
|
36
|
-
"complete-milestone": ["gsd_complete_milestone", "subagent"],
|
|
37
|
-
"research-slice": ["gsd_summary_save", "gsd_decision_save"],
|
|
38
|
-
"plan-slice": ["gsd_plan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
39
|
-
"refine-slice": ["gsd_plan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
40
|
-
"replan-slice": ["gsd_replan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
41
|
-
"complete-slice": ["gsd_slice_complete", "gsd_task_reopen", "gsd_replan_slice", "gsd_decision_save", "gsd_requirement_update", "subagent"],
|
|
42
|
-
"reassess-roadmap": ["gsd_reassess_roadmap"],
|
|
43
|
-
"execute-task": ["gsd_task_complete", "gsd_decision_save"],
|
|
44
|
-
"execute-task-simple": ["gsd_task_complete", "gsd_decision_save"],
|
|
45
|
-
"reactive-execute": ["gsd_task_complete", "gsd_decision_save"],
|
|
46
|
-
"run-uat": [...RUN_UAT_WORKFLOW_TOOL_NAMES, "subagent", ...RUN_UAT_BROWSER_TOOL_NAMES],
|
|
47
|
-
"gate-evaluate": ["gsd_save_gate_result"],
|
|
48
|
-
"rewrite-docs": ["gsd_summary_save", "gsd_decision_save"],
|
|
49
|
-
"workflow-preferences": ["gsd_summary_save"],
|
|
50
|
-
"discuss-project": ["gsd_summary_save", "gsd_decision_save", "gsd_requirement_save"],
|
|
51
|
-
"discuss-requirements": ["gsd_requirement_save", "gsd_summary_save"],
|
|
52
|
-
"research-decision": ["gsd_summary_save"],
|
|
53
|
-
"research-project": ["gsd_summary_save", "gsd_decision_save"],
|
|
54
|
-
};
|
|
2
|
+
import { AUTO_UNIT_SCOPED_TOOLS, getForbiddenGsdToolReason, } from "./unit-tool-contracts.js";
|
|
3
|
+
export { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, } from "./unit-tool-contracts.js";
|
|
55
4
|
const WORKFLOW_TOOL_ALIASES = {
|
|
56
5
|
gsd_save_decision: "gsd_decision_save",
|
|
57
6
|
gsd_update_requirement: "gsd_requirement_update",
|
|
@@ -88,6 +37,7 @@ const SCOPED_GSD_LIFECYCLE_TOOLS = new Set([
|
|
|
88
37
|
]
|
|
89
38
|
.filter((tool) => tool.startsWith("gsd_"))
|
|
90
39
|
.map(canonicalWorkflowToolName));
|
|
40
|
+
export const GSD_PHASE_SCOPE_DISPLAY_REASON = "This GSD phase only allows its scoped workflow tools.";
|
|
91
41
|
function stripMcpToolPrefix(toolName) {
|
|
92
42
|
if (!toolName.startsWith("mcp__"))
|
|
93
43
|
return toolName;
|
|
@@ -103,11 +53,18 @@ export function isWorkflowAliasTool(toolName) {
|
|
|
103
53
|
}
|
|
104
54
|
function hardBlockReason(unitType, what) {
|
|
105
55
|
return [
|
|
106
|
-
`HARD BLOCK: unit "${unitType}"
|
|
56
|
+
`HARD BLOCK: Tool Contract failure for unit "${unitType}" — ${what}.`,
|
|
107
57
|
"This is a mechanical phase-boundary gate. You MUST NOT proceed, retry the same call,",
|
|
108
58
|
"or route around this block; the orchestrator owns phase transitions.",
|
|
109
59
|
].join(" ");
|
|
110
60
|
}
|
|
61
|
+
function hardBlock(unitType, what) {
|
|
62
|
+
return {
|
|
63
|
+
block: true,
|
|
64
|
+
reason: hardBlockReason(unitType, what),
|
|
65
|
+
displayReason: GSD_PHASE_SCOPE_DISPLAY_REASON,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
111
68
|
function allowedGsdToolsForUnit(unitType) {
|
|
112
69
|
return [...new Set((AUTO_UNIT_SCOPED_TOOLS[unitType] ?? [])
|
|
113
70
|
.filter((tool) => tool.startsWith("gsd_"))
|
|
@@ -143,20 +100,14 @@ function shouldBlockTaskCompletionScope(unitType, unitId, toolName, input) {
|
|
|
143
100
|
actualTask === expected.task) {
|
|
144
101
|
return { block: false };
|
|
145
102
|
}
|
|
146
|
-
return {
|
|
147
|
-
block: true,
|
|
148
|
-
reason: hardBlockReason(unitType, `gsd_task_complete may only complete the active task ${expected.milestone}/${expected.slice}/${expected.task}; requested ${actualMilestone}/${actualSlice}/${actualTask}`),
|
|
149
|
-
};
|
|
103
|
+
return hardBlock(unitType, `gsd_task_complete may only complete the active task ${expected.milestone}/${expected.slice}/${expected.task}; requested ${actualMilestone}/${actualSlice}/${actualTask}`);
|
|
150
104
|
}
|
|
151
105
|
export function shouldBlockAutoUnitToolCall(unitType, toolName, input, unitId) {
|
|
152
106
|
const scopedTools = AUTO_UNIT_SCOPED_TOOLS[unitType];
|
|
153
107
|
if (!scopedTools)
|
|
154
108
|
return { block: false };
|
|
155
109
|
if (isNativeWorkflowTool(toolName)) {
|
|
156
|
-
return
|
|
157
|
-
block: true,
|
|
158
|
-
reason: hardBlockReason(unitType, "native Workflow is not permitted inside a dispatched GSD auto-mode unit"),
|
|
159
|
-
};
|
|
110
|
+
return hardBlock(unitType, "native Workflow is not permitted inside a dispatched GSD auto-mode unit");
|
|
160
111
|
}
|
|
161
112
|
const taskScope = shouldBlockTaskCompletionScope(unitType, unitId, toolName, input);
|
|
162
113
|
if (taskScope.block)
|
|
@@ -167,8 +118,9 @@ export function shouldBlockAutoUnitToolCall(unitType, toolName, input, unitId) {
|
|
|
167
118
|
const allowedTools = allowedGsdToolsForUnit(unitType);
|
|
168
119
|
if (allowedTools.includes(canonicalTool))
|
|
169
120
|
return { block: false };
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
121
|
+
const forbiddenReason = getForbiddenGsdToolReason(unitType, canonicalTool);
|
|
122
|
+
if (forbiddenReason) {
|
|
123
|
+
return hardBlock(unitType, `GSD lifecycle tool "${canonicalTool}" is not permitted; ${forbiddenReason} Fix unit-tool-contracts.ts or the ${unitType} prompt.`);
|
|
124
|
+
}
|
|
125
|
+
return hardBlock(unitType, `GSD lifecycle tool "${canonicalTool}" is not permitted; allowed GSD tools: ${allowedTools.length > 0 ? allowedTools.join(", ") : "(none)"}`);
|
|
174
126
|
}
|
|
@@ -26,6 +26,7 @@ import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
|
26
26
|
import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
|
|
27
27
|
import { classifyProject } from "./detection.js";
|
|
28
28
|
import { nativeGetCurrentBranch, nativeDetectMainBranch, nativeWorkingTreeStatus, nativeAddAllWithExclusions, nativeCommit, nativeCheckoutBranch, nativeMergeSquash, nativeConflictFiles, nativeAddPaths, nativeRmForce, nativeBranchDelete, nativeBranchForceReset, nativeBranchExists, nativeDiffNumstat, nativeUpdateRef, nativeIsAncestor, nativeMergeAbort, nativeWorktreeList, nativeLsFiles, } from "./native-git-bridge.js";
|
|
29
|
+
import { CLOSEOUT_CONSISTENCY_BLOCKED_REASON, checkCloseoutConsistencyGate, formatCloseoutConsistencyBlock, } from "./closeout-consistency-gate.js";
|
|
29
30
|
import { gsdHome } from "./gsd-home.js";
|
|
30
31
|
import { createWorkspace } from "./workspace.js";
|
|
31
32
|
import { _finalizeProjectionForMergeImpl, _projectRootToWorktreeImpl, _projectWorktreeToRootImpl, } from "./worktree-state-projection.js";
|
|
@@ -1513,17 +1514,29 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
|
|
|
1513
1514
|
// symlink layout) — ATTACHing a WAL-mode file to itself corrupts the
|
|
1514
1515
|
// database (#2823).
|
|
1515
1516
|
if (isDbAvailable()) {
|
|
1517
|
+
const contract = resolveGsdPathContract(worktreeCwd, originalBasePath_);
|
|
1518
|
+
const worktreeDbPath = join(contract.worktreeGsd ?? join(worktreeCwd, ".gsd"), "gsd.db");
|
|
1519
|
+
const mainDbPath = contract.projectDb;
|
|
1516
1520
|
try {
|
|
1517
|
-
const
|
|
1518
|
-
|
|
1519
|
-
|
|
1521
|
+
const activeDbPath = getDbPath();
|
|
1522
|
+
if (activeDbPath && _shouldReconcileWorktreeDb(activeDbPath, mainDbPath)) {
|
|
1523
|
+
closeDatabase();
|
|
1524
|
+
if (!openDatabase(mainDbPath)) {
|
|
1525
|
+
throw new Error(`cannot open project DB at ${mainDbPath}`);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1520
1528
|
if (_shouldReconcileWorktreeDb(worktreeDbPath, mainDbPath)) {
|
|
1521
1529
|
reconcileWorktreeDb(mainDbPath, worktreeDbPath);
|
|
1522
1530
|
}
|
|
1523
1531
|
}
|
|
1524
1532
|
catch (err) {
|
|
1525
|
-
|
|
1526
|
-
logError("worktree",
|
|
1533
|
+
const message = `DB reconciliation failed before milestone ${milestoneId} merge: ${err instanceof Error ? err.message : String(err)}`;
|
|
1534
|
+
logError("worktree", message);
|
|
1535
|
+
throw new GSDError(GSD_GIT_ERROR, `${message}. Recovery reason: ${CLOSEOUT_CONSISTENCY_BLOCKED_REASON}.`);
|
|
1536
|
+
}
|
|
1537
|
+
const closeoutGate = checkCloseoutConsistencyGate(milestoneId);
|
|
1538
|
+
if (!closeoutGate.ok) {
|
|
1539
|
+
throw new GSDError(GSD_GIT_ERROR, formatCloseoutConsistencyBlock(closeoutGate));
|
|
1527
1540
|
}
|
|
1528
1541
|
}
|
|
1529
1542
|
// 2. Get completed slices for commit message
|