@opengsd/gsd-pi 1.1.1-dev.3ea310e → 1.1.1-dev.595401e
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/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
- package/dist/resources/extensions/gsd/auto/phases.js +4 -3
- package/dist/resources/extensions/gsd/auto-dashboard.js +92 -17
- package/dist/resources/extensions/gsd/auto-dispatch.js +5 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +132 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +68 -22
- package/dist/resources/extensions/gsd/auto-start.js +41 -12
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +2 -1
- package/dist/resources/extensions/gsd/auto.js +12 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +82 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +30 -9
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -10
- package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
- package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
- package/dist/resources/extensions/gsd/config-overlay.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/error-classifier.js +2 -1
- package/dist/resources/extensions/gsd/escalation.js +4 -4
- package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
- 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 +29 -68
- package/dist/resources/extensions/gsd/memory-store.js +4 -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 +48 -24
- package/dist/resources/extensions/gsd/prompts/system.md +3 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/dist/resources/extensions/gsd/rule-registry.js +428 -52
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
- package/dist/resources/extensions/gsd/skill-activation.js +20 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
- package/dist/resources/extensions/gsd/state.js +3 -3
- package/dist/resources/extensions/gsd/templates/plan.md +3 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
- package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +403 -3
- package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -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-auto-prep.js +1 -1
- package/dist/resources/extensions/gsd/workflow-mcp.js +5 -1
- package/dist/rtk.d.ts +7 -1
- package/dist/rtk.js +27 -11
- 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/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 +3 -2
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +14 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/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/settings-selector.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
- 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 +89 -31
- 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/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.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.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +84 -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 +38 -0
- 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/types.d.ts +3 -0
- 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/image-models.generated.d.ts +15 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.js +15 -0
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +86 -18
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +108 -40
- 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/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/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/terminal.d.ts +1 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +8 -4
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- 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/gsd/auto/orchestrator.ts +0 -1
- package/src/resources/extensions/gsd/auto/phases.ts +5 -3
- package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
- package/src/resources/extensions/gsd/auto-dispatch.ts +5 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +164 -7
- package/src/resources/extensions/gsd/auto-prompts.ts +102 -15
- package/src/resources/extensions/gsd/auto-start.ts +54 -14
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +2 -1
- package/src/resources/extensions/gsd/auto.ts +15 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +89 -3
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +51 -14
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +21 -10
- package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
- package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
- package/src/resources/extensions/gsd/config-overlay.ts +3 -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/error-classifier.ts +2 -1
- package/src/resources/extensions/gsd/escalation.ts +4 -4
- package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
- 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 +90 -82
- package/src/resources/extensions/gsd/memory-store.ts +4 -1
- package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
- package/src/resources/extensions/gsd/preferences-types.ts +1 -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 +48 -24
- package/src/resources/extensions/gsd/prompts/system.md +3 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- 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/safety/destructive-guard.ts +3 -0
- package/src/resources/extensions/gsd/skill-activation.ts +20 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
- package/src/resources/extensions/gsd/state.ts +3 -3
- package/src/resources/extensions/gsd/templates/plan.md +3 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +16 -3
- package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -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/derive-state-db.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
- 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/exec-sandbox.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
- 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/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.test.ts +12 -9
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +66 -10
- package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
- package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
- 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 +53 -1
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
- 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/validation-block-guard.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +213 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +25 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +489 -3
- package/src/resources/extensions/gsd/types.ts +67 -4
- package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -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-auto-prep.ts +1 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +5 -1
- /package/dist/web/standalone/.next/static/{xACmObbrDjwLriepRgaa9 → IDKjyRHLIaumjgonPcYiX}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{xACmObbrDjwLriepRgaa9 → IDKjyRHLIaumjgonPcYiX}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
e81bc72bf9d51027
|
|
@@ -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",
|
|
@@ -51,13 +51,13 @@ import { resolveManifest } from "../unit-context-manifest.js";
|
|
|
51
51
|
import { createWorktreeSafetyModule } from "../worktree-safety.js";
|
|
52
52
|
import { isSuspiciousGhostCompletion } from "../auto-unit-closeout.js";
|
|
53
53
|
import { decideVerificationRetry, verificationRetryKey } from "./verification-retry-policy.js";
|
|
54
|
-
import { buildPhaseHandoffOutcome, setAutoOutcomeWidget } from "../auto-dashboard.js";
|
|
54
|
+
import { buildPhaseHandoffOutcome, setAutoActiveStatus, setAutoOutcomeWidget } from "../auto-dashboard.js";
|
|
55
55
|
import { getConsecutiveDispatchBlocker } from "../dispatch-guard.js";
|
|
56
56
|
import { captureRootDirtySnapshot, detectRootWriteLeak, formatRootWriteLeakMessage, } from "../root-write-leak-guard.js";
|
|
57
57
|
import { classifyError, isTransient } from "../error-classifier.js";
|
|
58
58
|
export const STUCK_WINDOW_SIZE = 6;
|
|
59
59
|
const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
|
|
60
|
-
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 your limit\b|
|
|
60
|
+
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;
|
|
61
61
|
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;
|
|
62
62
|
function classifyZeroToolProviderMessage(message) {
|
|
63
63
|
const firstLine = message.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
@@ -67,6 +67,7 @@ function classifyZeroToolProviderMessage(message) {
|
|
|
67
67
|
return null;
|
|
68
68
|
return classifyError(firstLine);
|
|
69
69
|
}
|
|
70
|
+
export const _classifyZeroToolProviderMessageForTest = classifyZeroToolProviderMessage;
|
|
70
71
|
export function resolveDispatchRecoveryAttempts(unitRecoveryCount, unitType, unitId) {
|
|
71
72
|
return (unitRecoveryCount.get(`${unitType}/${unitId}`) ?? 0) > 0
|
|
72
73
|
? 0
|
|
@@ -1582,7 +1583,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1582
1583
|
const dispatchKey = `${unitType}/${unitId}`;
|
|
1583
1584
|
const nextDispatchCount = (s.unitDispatchCount.get(dispatchKey) ?? 0) + 1;
|
|
1584
1585
|
// Status bar (widget + preconditions deferred until after model selection — see #2899)
|
|
1585
|
-
ctx
|
|
1586
|
+
setAutoActiveStatus(ctx, s.stepMode ? "next" : "auto");
|
|
1586
1587
|
if (mid)
|
|
1587
1588
|
deps.updateSliceProgressCache(s.basePath, mid, state.activeSlice?.id);
|
|
1588
1589
|
// ── Safety harness: reset evidence + create checkpoint ──
|
|
@@ -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.
|
|
@@ -369,8 +402,9 @@ export const hideFooter = (_tui, theme, footerData) => ({
|
|
|
369
402
|
invalidate() { },
|
|
370
403
|
dispose() { },
|
|
371
404
|
});
|
|
405
|
+
export const DEFAULT_WIDGET_MODE = "small";
|
|
372
406
|
const WIDGET_MODES = ["full", "small", "min", "off"];
|
|
373
|
-
let widgetMode =
|
|
407
|
+
let widgetMode = DEFAULT_WIDGET_MODE;
|
|
374
408
|
let widgetModeInitialized = false;
|
|
375
409
|
let widgetModePreferencePath = null;
|
|
376
410
|
function safeReadTextFile(path) {
|
|
@@ -473,10 +507,19 @@ export function getWidgetMode(projectPath, globalPath) {
|
|
|
473
507
|
}
|
|
474
508
|
/** Test-only reset for widget mode caching. */
|
|
475
509
|
export function _resetWidgetModeForTests() {
|
|
476
|
-
widgetMode =
|
|
510
|
+
widgetMode = DEFAULT_WIDGET_MODE;
|
|
477
511
|
widgetModeInitialized = false;
|
|
478
512
|
widgetModePreferencePath = null;
|
|
479
513
|
}
|
|
514
|
+
function clearAutoOutcomeWidget(ctx) {
|
|
515
|
+
if (!ctx.hasUI)
|
|
516
|
+
return;
|
|
517
|
+
ctx.ui.setWidget("gsd-outcome", undefined);
|
|
518
|
+
}
|
|
519
|
+
export function setAutoActiveStatus(ctx, status) {
|
|
520
|
+
ctx.ui.setStatus("gsd-auto", status);
|
|
521
|
+
clearAutoOutcomeWidget(ctx);
|
|
522
|
+
}
|
|
480
523
|
export function updateProgressWidget(ctx, unitType, unitId, state, accessors, tierBadge) {
|
|
481
524
|
if (!ctx.hasUI)
|
|
482
525
|
return;
|
|
@@ -495,7 +538,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
495
538
|
ctx.ui.setStatus("gsd-step", undefined);
|
|
496
539
|
}
|
|
497
540
|
if (!accessors.isSessionSwitching()) {
|
|
498
|
-
ctx
|
|
541
|
+
clearAutoOutcomeWidget(ctx);
|
|
499
542
|
}
|
|
500
543
|
const verb = unitVerb(unitType);
|
|
501
544
|
const phaseLabel = unitPhaseLabel(unitType);
|
|
@@ -548,6 +591,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
548
591
|
logWarning("dashboard", `DB status update failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
549
592
|
}
|
|
550
593
|
}, 15_000);
|
|
594
|
+
progressRefreshTimer.unref?.();
|
|
551
595
|
return {
|
|
552
596
|
render(width) {
|
|
553
597
|
if (cachedLines && cachedWidth === width)
|
|
@@ -631,26 +675,57 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
631
675
|
cachedWidth = width;
|
|
632
676
|
return lines;
|
|
633
677
|
}
|
|
634
|
-
// ── Mode: small —
|
|
678
|
+
// ── Mode: small — dense horizontal grid ───────────────────────
|
|
635
679
|
if (widgetMode === "small") {
|
|
636
|
-
lines.
|
|
637
|
-
|
|
638
|
-
const target = task ? `${task.id}: ${task.title}` : unitId;
|
|
639
|
-
const actionLeft = `${pad}${theme.fg("accent", "▸")} ${theme.fg("accent", verb)} ${theme.fg("text", target)}`;
|
|
640
|
-
lines.push(rightAlign(actionLeft, theme.fg("dim", phaseLabel), width));
|
|
641
|
-
// Progress bar
|
|
680
|
+
lines.length = 0;
|
|
681
|
+
lines.push(...ui.bar());
|
|
642
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 ?? "--";
|
|
643
709
|
if (shouldRenderRoadmapProgress(roadmapSlices)) {
|
|
644
710
|
const { done, total, activeSliceTasks } = roadmapSlices;
|
|
645
|
-
const barWidth = Math.max(
|
|
711
|
+
const barWidth = Math.max(4, Math.min(14, Math.floor(width * 0.12)));
|
|
646
712
|
const bar = renderProgressBar(theme, done, total, barWidth);
|
|
647
|
-
|
|
713
|
+
sliceValue = `${bar} ${theme.fg("text", `${done}/${total}`)}`;
|
|
648
714
|
if (activeSliceTasks && activeSliceTasks.total > 0) {
|
|
649
|
-
const
|
|
650
|
-
|
|
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}`)}`;
|
|
651
719
|
}
|
|
652
|
-
lines.push(`${pad}${bar} ${meta}`);
|
|
653
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);
|
|
654
729
|
lines.push(...ui.bar());
|
|
655
730
|
cachedLines = lines;
|
|
656
731
|
cachedWidth = width;
|
|
@@ -789,7 +864,7 @@ export function setCompletionProgressWidget(ctx, snapshot) {
|
|
|
789
864
|
if (!ctx.hasUI)
|
|
790
865
|
return;
|
|
791
866
|
const widgetKey = "gsd-progress";
|
|
792
|
-
ctx
|
|
867
|
+
clearAutoOutcomeWidget(ctx);
|
|
793
868
|
if (typeof ctx.ui?.setHeader === "function") {
|
|
794
869
|
ctx.ui.setHeader(() => ({
|
|
795
870
|
render() { return []; },
|
|
@@ -443,6 +443,7 @@ export const DISPATCH_RULES = [
|
|
|
443
443
|
unitType: "discuss-milestone",
|
|
444
444
|
unitId: mid,
|
|
445
445
|
prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
|
|
446
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
446
447
|
};
|
|
447
448
|
},
|
|
448
449
|
},
|
|
@@ -578,6 +579,7 @@ export const DISPATCH_RULES = [
|
|
|
578
579
|
unitType: "discuss-milestone",
|
|
579
580
|
unitId: mid,
|
|
580
581
|
prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
|
|
582
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
581
583
|
};
|
|
582
584
|
},
|
|
583
585
|
},
|
|
@@ -617,6 +619,7 @@ export const DISPATCH_RULES = [
|
|
|
617
619
|
unitType: "discuss-project",
|
|
618
620
|
unitId: "PROJECT",
|
|
619
621
|
prompt: await buildDiscussProjectPrompt(basePath, structuredQuestionsAvailable),
|
|
622
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
620
623
|
};
|
|
621
624
|
},
|
|
622
625
|
},
|
|
@@ -642,6 +645,7 @@ export const DISPATCH_RULES = [
|
|
|
642
645
|
unitType: "discuss-requirements",
|
|
643
646
|
unitId: "REQUIREMENTS",
|
|
644
647
|
prompt: await buildDiscussRequirementsPrompt(basePath, structuredQuestionsAvailable),
|
|
648
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
645
649
|
};
|
|
646
650
|
},
|
|
647
651
|
},
|
|
@@ -757,6 +761,7 @@ export const DISPATCH_RULES = [
|
|
|
757
761
|
unitType: "discuss-milestone",
|
|
758
762
|
unitId: mid,
|
|
759
763
|
prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
|
|
764
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS,
|
|
760
765
|
};
|
|
761
766
|
},
|
|
762
767
|
},
|
|
@@ -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";
|
|
@@ -323,6 +323,41 @@ function stripKnownIdPrefix(value, id) {
|
|
|
323
323
|
return raw.slice(id.length + 1).trim() || undefined;
|
|
324
324
|
return raw;
|
|
325
325
|
}
|
|
326
|
+
function parseReactiveBatchTaskIds(unitId) {
|
|
327
|
+
const { task: batchPart } = parseUnitId(unitId);
|
|
328
|
+
if (!batchPart?.startsWith("reactive+"))
|
|
329
|
+
return [];
|
|
330
|
+
const rawIds = batchPart
|
|
331
|
+
.slice("reactive+".length)
|
|
332
|
+
.split(",")
|
|
333
|
+
.map((taskId) => taskId.trim().toUpperCase())
|
|
334
|
+
.filter(Boolean);
|
|
335
|
+
const unique = new Set();
|
|
336
|
+
for (const taskId of rawIds) {
|
|
337
|
+
unique.add(taskId);
|
|
338
|
+
}
|
|
339
|
+
return [...unique];
|
|
340
|
+
}
|
|
341
|
+
function dedupePaths(values) {
|
|
342
|
+
const seen = new Set();
|
|
343
|
+
const result = [];
|
|
344
|
+
for (const value of values) {
|
|
345
|
+
if (!seen.has(value)) {
|
|
346
|
+
seen.add(value);
|
|
347
|
+
result.push(value);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return result;
|
|
351
|
+
}
|
|
352
|
+
function getPlannedKeyFiles(tasks) {
|
|
353
|
+
return dedupePaths(tasks.flatMap((taskRow) => [
|
|
354
|
+
...(taskRow.expected_output ?? []),
|
|
355
|
+
...(taskRow.files ?? []),
|
|
356
|
+
...(taskRow.key_files ?? []),
|
|
357
|
+
]));
|
|
358
|
+
}
|
|
359
|
+
export const _parseReactiveBatchTaskIdsForTest = parseReactiveBatchTaskIds;
|
|
360
|
+
export const _getPlannedKeyFilesForTest = getPlannedKeyFiles;
|
|
326
361
|
function resolveVerificationFailureMarkerPath(unitType, unitId, basePath) {
|
|
327
362
|
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
328
363
|
switch (unitType) {
|
|
@@ -402,6 +437,34 @@ async function buildTaskCommitContextForUnit(basePath, unitId) {
|
|
|
402
437
|
issueNumber: ghIssueNumber,
|
|
403
438
|
};
|
|
404
439
|
}
|
|
440
|
+
async function buildReactiveTaskCommitContext(_basePath, unitId) {
|
|
441
|
+
const { milestone: mid, slice: sid } = parseUnitId(unitId);
|
|
442
|
+
if (!mid || !sid || !isDbAvailable())
|
|
443
|
+
return undefined;
|
|
444
|
+
const batchTaskIds = parseReactiveBatchTaskIds(unitId);
|
|
445
|
+
if (batchTaskIds.length === 0)
|
|
446
|
+
return undefined;
|
|
447
|
+
const milestone = getMilestone(mid);
|
|
448
|
+
const slice = getSlice(mid, sid);
|
|
449
|
+
const taskRows = batchTaskIds
|
|
450
|
+
.map((tid) => getTask(mid, sid, tid))
|
|
451
|
+
.filter((taskRow) => taskRow !== null);
|
|
452
|
+
const keyFiles = getPlannedKeyFiles(taskRows);
|
|
453
|
+
if (taskRows.length === 0 || keyFiles.length === 0)
|
|
454
|
+
return undefined;
|
|
455
|
+
const taskLabel = taskRows.map((row) => row.id).join(",");
|
|
456
|
+
return {
|
|
457
|
+
taskId: `${sid}/${taskLabel}`,
|
|
458
|
+
taskDisplayId: "reactive-batch",
|
|
459
|
+
taskTitle: `Reactive batch: ${taskLabel}`,
|
|
460
|
+
milestoneId: mid,
|
|
461
|
+
milestoneTitle: stripKnownIdPrefix(milestone?.title, mid),
|
|
462
|
+
sliceId: sid,
|
|
463
|
+
sliceTitle: stripKnownIdPrefix(slice?.title, sid),
|
|
464
|
+
oneLiner: `Reactive execute for ${taskLabel}`,
|
|
465
|
+
keyFiles,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
405
468
|
async function runPostUnitGitHubSyncIfNeeded(basePath, unit) {
|
|
406
469
|
if (unit.type === "complete-milestone")
|
|
407
470
|
return;
|
|
@@ -761,6 +824,9 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
|
|
|
761
824
|
if (unitType === "execute-task") {
|
|
762
825
|
taskContext = await buildTaskCommitContextForUnit(basePath, unitId);
|
|
763
826
|
}
|
|
827
|
+
else if (unitType === "reactive-execute") {
|
|
828
|
+
taskContext = await buildReactiveTaskCommitContext(basePath, unitId);
|
|
829
|
+
}
|
|
764
830
|
_resetHasChangesCache();
|
|
765
831
|
if (LIFECYCLE_ONLY_UNITS.has(unitType)) {
|
|
766
832
|
return null;
|
|
@@ -812,6 +878,22 @@ async function runCloseoutGitAction(pctx, unit, opts) {
|
|
|
812
878
|
targetRepositories = getTask(mid, sid, tid)?.target_repositories;
|
|
813
879
|
}
|
|
814
880
|
}
|
|
881
|
+
else if (turnAction === "commit" && unit.type === "reactive-execute") {
|
|
882
|
+
taskContext = await buildReactiveTaskCommitContext(s.basePath, unit.id);
|
|
883
|
+
const { milestone: mid, slice: sid } = parseUnitId(unit.id);
|
|
884
|
+
if (mid && sid && isDbAvailable()) {
|
|
885
|
+
const repositories = new Set();
|
|
886
|
+
for (const tid of parseReactiveBatchTaskIds(unit.id)) {
|
|
887
|
+
const taskRow = getTask(mid, sid, tid);
|
|
888
|
+
for (const repoId of taskRow?.target_repositories ?? []) {
|
|
889
|
+
repositories.add(repoId);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
if (repositories.size > 0) {
|
|
893
|
+
targetRepositories = [...repositories];
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
815
897
|
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
816
898
|
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
817
899
|
// `false` result causes autoCommit to skip staging entirely.
|
|
@@ -1206,12 +1288,19 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1206
1288
|
if (safetyConfig.enabled) {
|
|
1207
1289
|
const { milestone: sMid, slice: sSid, task: sTid } = parseUnitId(s.currentUnit.id);
|
|
1208
1290
|
// File change validation (execute-task only, after unit execution)
|
|
1209
|
-
if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid
|
|
1291
|
+
if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid) {
|
|
1210
1292
|
try {
|
|
1211
|
-
const
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1293
|
+
const sliceTaskRows = isDbAvailable()
|
|
1294
|
+
? getSliceTasks(sMid, sSid).filter((t) => isClosedStatus(t.status) || t.id === sTid)
|
|
1295
|
+
: [];
|
|
1296
|
+
if (sliceTaskRows.length > 0) {
|
|
1297
|
+
const expectedOutput = getPlannedKeyFiles(sliceTaskRows.map((taskRow) => ({
|
|
1298
|
+
expected_output: taskRow.expected_output,
|
|
1299
|
+
files: taskRow.files,
|
|
1300
|
+
})));
|
|
1301
|
+
const plannedFiles = getPlannedKeyFiles(sliceTaskRows.map((taskRow) => ({
|
|
1302
|
+
files: taskRow.files,
|
|
1303
|
+
})));
|
|
1215
1304
|
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, safetyConfig.file_change_allowlist);
|
|
1216
1305
|
if (audit && audit.violations.length > 0) {
|
|
1217
1306
|
const warnings = audit.violations.filter(v => v.severity === "warning");
|
|
@@ -1223,6 +1312,23 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1223
1312
|
}
|
|
1224
1313
|
}
|
|
1225
1314
|
}
|
|
1315
|
+
else {
|
|
1316
|
+
const taskRow = getTask(sMid, sSid, sTid);
|
|
1317
|
+
if (taskRow) {
|
|
1318
|
+
const expectedOutput = taskRow.expected_output ?? [];
|
|
1319
|
+
const plannedFiles = taskRow.files ?? [];
|
|
1320
|
+
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, safetyConfig.file_change_allowlist);
|
|
1321
|
+
if (audit && audit.violations.length > 0) {
|
|
1322
|
+
const warnings = audit.violations.filter(v => v.severity === "warning");
|
|
1323
|
+
for (const v of warnings) {
|
|
1324
|
+
logWarning("safety", `file-change: ${v.file} — ${v.reason}`);
|
|
1325
|
+
}
|
|
1326
|
+
if (warnings.length > 0) {
|
|
1327
|
+
ctx.ui.notify(`Safety: ${warnings.length} unexpected file change(s) outside task plan`, "warning");
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1226
1332
|
}
|
|
1227
1333
|
catch (e) {
|
|
1228
1334
|
debugLog("postUnit", { phase: "safety-file-change", error: String(e) });
|
|
@@ -1754,18 +1860,25 @@ export async function postUnitPostVerification(pctx) {
|
|
|
1754
1860
|
// ── Post-unit hooks ──
|
|
1755
1861
|
if (s.currentUnit && !s.stepMode) {
|
|
1756
1862
|
const hookUnit = checkPostUnitHooks(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
1863
|
+
persistHookState(s.basePath);
|
|
1757
1864
|
if (hookUnit) {
|
|
1758
1865
|
if (s.currentUnit) {
|
|
1759
1866
|
await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
|
|
1760
1867
|
}
|
|
1761
|
-
persistHookState(s.basePath);
|
|
1762
1868
|
return enqueueSidecar(s, ctx, { kind: "hook", unitType: hookUnit.unitType, unitId: hookUnit.unitId, prompt: hookUnit.prompt, model: hookUnit.model }, { hookName: hookUnit.hookName });
|
|
1763
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
|
+
}
|
|
1764
1876
|
// Check if a hook requested a retry of the trigger unit
|
|
1765
1877
|
if (isRetryPending()) {
|
|
1766
1878
|
const trigger = consumeRetryTrigger();
|
|
1767
1879
|
if (trigger) {
|
|
1768
|
-
|
|
1880
|
+
persistHookState(s.basePath);
|
|
1881
|
+
ctx.ui.notify(`Hook requested retry of ${trigger.unitType} ${trigger.unitId} — resetting trigger unit state.`, "info");
|
|
1769
1882
|
await s.orchestration?.retryActiveUnit({
|
|
1770
1883
|
unitType: trigger.unitType,
|
|
1771
1884
|
unitId: trigger.unitId,
|
|
@@ -1812,6 +1925,17 @@ export async function postUnitPostVerification(pctx) {
|
|
|
1812
1925
|
// Fall through to normal dispatch — deriveState will re-derive the unit
|
|
1813
1926
|
}
|
|
1814
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
|
+
}
|
|
1815
1939
|
}
|
|
1816
1940
|
// ── Fast-path stop detection (#3487) ──
|
|
1817
1941
|
// Before waiting for triage, check if any PENDING captures contain explicit
|
|
@@ -30,6 +30,7 @@ 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";
|
|
33
34
|
export { buildSkillActivationBlock, buildSkillDiscoveryVars };
|
|
34
35
|
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
35
36
|
/**
|
|
@@ -1270,7 +1271,7 @@ export async function checkNeedsRunUat(base, mid, state, prefs) {
|
|
|
1270
1271
|
if (hasVerdict(uatContent))
|
|
1271
1272
|
continue;
|
|
1272
1273
|
// Also check the ASSESSMENT file — the run-uat prompt writes the verdict
|
|
1273
|
-
// there (via
|
|
1274
|
+
// there (via gsd_uat_result_save), not into the
|
|
1274
1275
|
// UAT spec file. Without this check the unit re-dispatches indefinitely.
|
|
1275
1276
|
const assessmentFile = resolveSliceFile(base, mid, sid, "ASSESSMENT");
|
|
1276
1277
|
if (assessmentFile) {
|
|
@@ -1325,21 +1326,44 @@ export async function checkNeedsRunUat(base, mid, state, prefs) {
|
|
|
1325
1326
|
}
|
|
1326
1327
|
return null;
|
|
1327
1328
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
const
|
|
1329
|
+
export async function buildDiscussMilestoneInlinedContext(mid, base) {
|
|
1330
|
+
const inlined = [];
|
|
1331
|
+
const roadmapInline = await inlineFileOptional(resolveMilestoneFile(base, mid, "ROADMAP"), relMilestoneFile(base, mid, "ROADMAP"), "Milestone Roadmap");
|
|
1332
|
+
if (roadmapInline)
|
|
1333
|
+
inlined.push(roadmapInline);
|
|
1334
|
+
const contextInline = await inlineFileOptional(resolveMilestoneFile(base, mid, "CONTEXT"), relMilestoneFile(base, mid, "CONTEXT"), "Milestone Context");
|
|
1335
|
+
if (contextInline)
|
|
1336
|
+
inlined.push(contextInline);
|
|
1337
|
+
const researchInline = await inlineFileOptional(resolveMilestoneFile(base, mid, "RESEARCH"), relMilestoneFile(base, mid, "RESEARCH"), "Milestone Research");
|
|
1338
|
+
if (researchInline)
|
|
1339
|
+
inlined.push(researchInline);
|
|
1340
|
+
const decisionsPath = resolveGsdRootFile(base, "DECISIONS");
|
|
1341
|
+
if (existsSync(decisionsPath)) {
|
|
1342
|
+
const decisionsContent = await loadFile(decisionsPath);
|
|
1343
|
+
if (decisionsContent) {
|
|
1344
|
+
inlined.push(`### Decisions Register\nSource: \`${relGsdRootFile("DECISIONS")}\`\n\n${decisionsContent.trim()}`);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
const milestoneIds = findMilestoneIds(base);
|
|
1348
|
+
const currentIndex = milestoneIds.indexOf(mid);
|
|
1349
|
+
const priorMilestoneIds = currentIndex >= 0 ? milestoneIds.slice(0, currentIndex) : milestoneIds;
|
|
1350
|
+
for (const priorMid of priorMilestoneIds) {
|
|
1351
|
+
const summaryInline = await inlineFileOptional(resolveMilestoneFile(base, priorMid, "SUMMARY"), relMilestoneFile(base, priorMid, "SUMMARY"), `${priorMid} Prior Milestone Summary`);
|
|
1352
|
+
if (summaryInline)
|
|
1353
|
+
inlined.push(summaryInline);
|
|
1354
|
+
}
|
|
1355
|
+
return inlined.length > 0
|
|
1356
|
+
? `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`
|
|
1357
|
+
: "## Inlined Context\n\n_(no milestone context files found yet — go in blind and ask broad questions)_";
|
|
1358
|
+
}
|
|
1359
|
+
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, } = {}) {
|
|
1360
|
+
const contextTemplate = inlineTemplate("context", "Context");
|
|
1337
1361
|
if (headless) {
|
|
1338
1362
|
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
1339
1363
|
const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
|
|
1340
1364
|
return loadPrompt("discuss-headless", {
|
|
1341
1365
|
seedContext: roadmapContent ?? "",
|
|
1342
|
-
inlinedTemplates:
|
|
1366
|
+
inlinedTemplates: contextTemplate,
|
|
1343
1367
|
workingDirectory: base,
|
|
1344
1368
|
milestoneId: mid,
|
|
1345
1369
|
contextPath: relMilestoneFile(base, mid, "CONTEXT"),
|
|
@@ -1347,24 +1371,28 @@ export async function buildDiscussMilestonePrompt(mid, midTitle, base, structure
|
|
|
1347
1371
|
multiMilestoneCommitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1348
1372
|
});
|
|
1349
1373
|
}
|
|
1350
|
-
const
|
|
1374
|
+
const rawInlinedContext = await buildDiscussMilestoneInlinedContext(mid, base);
|
|
1375
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
1376
|
+
const discussTemplates = [cappedInlinedContext, contextTemplate].join("\n\n---\n\n");
|
|
1351
1377
|
const basePrompt = loadPrompt("guided-discuss-milestone", {
|
|
1352
1378
|
workingDirectory: base,
|
|
1353
1379
|
milestoneId: mid,
|
|
1354
1380
|
milestoneTitle: midTitle,
|
|
1355
1381
|
inlinedTemplates: discussTemplates,
|
|
1356
1382
|
structuredQuestionsAvailable,
|
|
1357
|
-
commitInstruction
|
|
1358
|
-
fastPathInstruction
|
|
1383
|
+
commitInstruction,
|
|
1384
|
+
fastPathInstruction,
|
|
1359
1385
|
});
|
|
1360
|
-
const promptWithContextMode =
|
|
1386
|
+
const promptWithContextMode = includeContextMode
|
|
1387
|
+
? prependContextModeToBlock("discuss-milestone", base, basePrompt)
|
|
1388
|
+
: basePrompt;
|
|
1361
1389
|
// If a CONTEXT-DRAFT.md exists, append it as seed material
|
|
1362
1390
|
const draftPath = resolveMilestoneFile(base, mid, "CONTEXT-DRAFT");
|
|
1363
1391
|
const draftContent = draftPath ? await loadFile(draftPath) : null;
|
|
1364
|
-
if (draftContent) {
|
|
1392
|
+
if (includeDraftSeed && draftContent) {
|
|
1365
1393
|
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
1394
|
}
|
|
1367
|
-
return
|
|
1395
|
+
return promptWithContextMode;
|
|
1368
1396
|
}
|
|
1369
1397
|
/**
|
|
1370
1398
|
* Build a prompt for the workflow-preferences unit type (deep mode).
|
|
@@ -2351,6 +2379,15 @@ export async function buildCompleteSlicePrompt(mid, midTitle, sid, sTitle, base,
|
|
|
2351
2379
|
sliceSummaryPath,
|
|
2352
2380
|
sliceUatPath,
|
|
2353
2381
|
gatesToClose,
|
|
2382
|
+
skillActivation: buildSkillActivationBlock({
|
|
2383
|
+
base,
|
|
2384
|
+
milestoneId: mid,
|
|
2385
|
+
milestoneTitle: midTitle,
|
|
2386
|
+
sliceId: sid,
|
|
2387
|
+
sliceTitle: sTitle,
|
|
2388
|
+
extraContext: [inlinedContext],
|
|
2389
|
+
unitType: "complete-slice",
|
|
2390
|
+
}),
|
|
2354
2391
|
});
|
|
2355
2392
|
}
|
|
2356
2393
|
export async function buildCompleteMilestonePrompt(mid, midTitle, base, level) {
|
|
@@ -2531,17 +2568,26 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
|
|
|
2531
2568
|
if (isDbAvailable()) {
|
|
2532
2569
|
const milestone = getMilestone(mid);
|
|
2533
2570
|
if (milestone) {
|
|
2571
|
+
const escapeCell = (value) => value.replace(/[\\|]/g, (char) => `\\${char}`).replace(/\r?\n/g, " ");
|
|
2534
2572
|
const classes = [];
|
|
2535
2573
|
if (milestone.verification_contract)
|
|
2536
|
-
classes.push(
|
|
2574
|
+
classes.push(`| Contract | ${escapeCell(milestone.verification_contract)} |`);
|
|
2537
2575
|
if (milestone.verification_integration)
|
|
2538
|
-
classes.push(
|
|
2576
|
+
classes.push(`| Integration | ${escapeCell(milestone.verification_integration)} |`);
|
|
2539
2577
|
if (milestone.verification_operational)
|
|
2540
|
-
classes.push(
|
|
2578
|
+
classes.push(`| Operational | ${escapeCell(milestone.verification_operational)} |`);
|
|
2541
2579
|
if (milestone.verification_uat)
|
|
2542
|
-
classes.push(
|
|
2580
|
+
classes.push(`| UAT | ${escapeCell(milestone.verification_uat)} |`);
|
|
2543
2581
|
if (classes.length > 0) {
|
|
2544
|
-
const verificationClasses =
|
|
2582
|
+
const verificationClasses = [
|
|
2583
|
+
"### Verification Classes (from planning)",
|
|
2584
|
+
"",
|
|
2585
|
+
"These verification tiers were defined during milestone planning. Every row in this table must appear in `verificationClasses` with the same canonical class name.",
|
|
2586
|
+
"",
|
|
2587
|
+
"| Class | Planned Check |",
|
|
2588
|
+
"| --- | --- |",
|
|
2589
|
+
...classes,
|
|
2590
|
+
].join("\n");
|
|
2545
2591
|
inlined.push(verificationClasses);
|
|
2546
2592
|
trackPromptContext(contextTelemetry, "verification-classes", "inline", verificationClasses);
|
|
2547
2593
|
}
|