@opengsd/gsd-pi 1.1.1-dev.74e8dd1 → 1.1.1-dev.75048e7
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 +30 -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 +8 -8
- 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 +8 -8
- 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 -23
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +82 -31
- 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 +72 -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 +73 -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 +410 -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 +63 -7
- 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 → h4TGni4xJzlZjGkxaT6uU}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → h4TGni4xJzlZjGkxaT6uU}/_ssgManifest.js +0 -0
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Resolve phase-aware tool surfaces for GSD model presentations.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
"gsd_uat_result_save",
|
|
6
|
-
"gsd_resume",
|
|
7
|
-
"gsd_milestone_status",
|
|
8
|
-
"gsd_journal_query",
|
|
9
|
-
];
|
|
3
|
+
import { RUN_UAT_BROWSER_TOOL_NAMES, RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_TOOL_PRESENTATION_PLAN_ID, RUN_UAT_WORKFLOW_TOOL_NAMES, } from "./unit-tool-contracts.js";
|
|
4
|
+
export { RUN_UAT_BROWSER_TOOL_NAMES, RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_TOOL_PRESENTATION_PLAN_ID, RUN_UAT_WORKFLOW_TOOL_NAMES, } from "./unit-tool-contracts.js";
|
|
10
5
|
export const RUN_UAT_FORBIDDEN_TOOL_NAMES = [
|
|
11
6
|
"edit",
|
|
12
7
|
"write",
|
|
@@ -74,9 +69,37 @@ function addBlockedTool(blocked, name, reason) {
|
|
|
74
69
|
export function buildRunUatCanonicalToolNames(options = {}) {
|
|
75
70
|
return dedupe([
|
|
76
71
|
...RUN_UAT_WORKFLOW_TOOL_NAMES,
|
|
72
|
+
...RUN_UAT_READ_ONLY_TOOL_NAMES,
|
|
77
73
|
...(options.includeBrowserTools ?? []),
|
|
78
74
|
]);
|
|
79
75
|
}
|
|
76
|
+
export function runUatBrowserToolsForType(uatType) {
|
|
77
|
+
return uatType === "browser-executable" ? RUN_UAT_BROWSER_TOOL_NAMES : [];
|
|
78
|
+
}
|
|
79
|
+
export function runUatPresentationSurfaceForType(uatType) {
|
|
80
|
+
return uatType === "browser-executable" ? "hybrid" : "mcp";
|
|
81
|
+
}
|
|
82
|
+
export function buildRunUatPresentationForType(uatType, options = {}) {
|
|
83
|
+
return buildRunUatResultPresentation({
|
|
84
|
+
...options,
|
|
85
|
+
surface: options.surface ?? runUatPresentationSurfaceForType(uatType),
|
|
86
|
+
includeBrowserTools: runUatBrowserToolsForType(uatType),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
export function buildRunUatResultPresentation(options = {}) {
|
|
90
|
+
const presentedTools = options.presentedTools
|
|
91
|
+
? dedupe(options.presentedTools)
|
|
92
|
+
: buildRunUatCanonicalToolNames({ includeBrowserTools: options.includeBrowserTools });
|
|
93
|
+
const blockedTools = RUN_UAT_FORBIDDEN_TOOL_NAMES
|
|
94
|
+
.filter((toolName) => !toolName.includes("*"))
|
|
95
|
+
.map((name) => ({ name, reason: "forbidden during run-uat" }));
|
|
96
|
+
return {
|
|
97
|
+
surface: options.surface ?? "mcp",
|
|
98
|
+
presentedTools,
|
|
99
|
+
blockedTools,
|
|
100
|
+
toolPresentationPlanId: RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
80
103
|
export function resolveToolPresentationPlan(options) {
|
|
81
104
|
const requested = options.requestedToolNames ?? (options.phase === "run-uat"
|
|
82
105
|
? buildRunUatCanonicalToolNames({ includeBrowserTools: options.includeBrowserTools })
|
|
@@ -158,7 +158,7 @@ ${params.narrative}
|
|
|
158
158
|
|
|
159
159
|
## Verification
|
|
160
160
|
|
|
161
|
-
${params.verification}
|
|
161
|
+
${params.verification ?? ""}
|
|
162
162
|
|
|
163
163
|
## Requirements Advanced
|
|
164
164
|
|
|
@@ -351,6 +351,20 @@ export async function handleCompleteSlice(params, basePath) {
|
|
|
351
351
|
if (parsed.length > 0)
|
|
352
352
|
effectiveParams.requirementsInvalidated = parsed;
|
|
353
353
|
}
|
|
354
|
+
if (effectiveParams.verification === undefined) {
|
|
355
|
+
const headingLine = "## Verification\n\n";
|
|
356
|
+
const start = existingSummaryMd.indexOf(headingLine);
|
|
357
|
+
if (start !== -1) {
|
|
358
|
+
const contentStart = start + headingLine.length;
|
|
359
|
+
const nextHeading = existingSummaryMd.indexOf("\n\n## ", contentStart);
|
|
360
|
+
const prior = nextHeading === -1
|
|
361
|
+
? existingSummaryMd.slice(contentStart)
|
|
362
|
+
: existingSummaryMd.slice(contentStart, nextHeading);
|
|
363
|
+
const trimmed = prior.trim();
|
|
364
|
+
if (trimmed)
|
|
365
|
+
effectiveParams.verification = trimmed;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
354
368
|
}
|
|
355
369
|
// Render summary markdown
|
|
356
370
|
const summaryMd = renderSliceSummaryMarkdown(effectiveParams);
|
|
@@ -314,9 +314,18 @@ export async function handleCompleteTask(params, basePath) {
|
|
|
314
314
|
// overwrite it; gate rows are UPSERT-keyed per task and will also be
|
|
315
315
|
// overwritten. This restores the invariant that deriveState() sees a
|
|
316
316
|
// consistent "task not done" view so the loop re-dispatches the task.
|
|
317
|
+
let escalationMetadata;
|
|
317
318
|
if (validatedEscalationArtifact) {
|
|
318
319
|
try {
|
|
319
|
-
writeEscalationArtifact(artifactBasePath, validatedEscalationArtifact);
|
|
320
|
+
const escalationPath = writeEscalationArtifact(artifactBasePath, validatedEscalationArtifact);
|
|
321
|
+
escalationMetadata = {
|
|
322
|
+
artifactPath: escalationPath,
|
|
323
|
+
question: validatedEscalationArtifact.question,
|
|
324
|
+
options: validatedEscalationArtifact.options,
|
|
325
|
+
recommendation: validatedEscalationArtifact.recommendation,
|
|
326
|
+
recommendationRationale: validatedEscalationArtifact.recommendationRationale,
|
|
327
|
+
continueWithDefault: validatedEscalationArtifact.continueWithDefault,
|
|
328
|
+
};
|
|
320
329
|
}
|
|
321
330
|
catch (escalationErr) {
|
|
322
331
|
const msg = `complete-task escalation write failed for ${params.milestoneId}/${params.sliceId}/${params.taskId}: ${escalationErr.message}`;
|
|
@@ -378,6 +387,7 @@ export async function handleCompleteTask(params, basePath) {
|
|
|
378
387
|
sliceId: params.sliceId,
|
|
379
388
|
milestoneId: params.milestoneId,
|
|
380
389
|
summaryPath,
|
|
390
|
+
...(escalationMetadata ? { escalation: escalationMetadata } : {}),
|
|
381
391
|
...(projectionStale ? { stale: true } : {}),
|
|
382
392
|
};
|
|
383
393
|
}
|
|
@@ -44,19 +44,12 @@ function getRequiredVerificationClasses(milestoneId) {
|
|
|
44
44
|
required.push("UAT");
|
|
45
45
|
return required;
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
chunks.push(artifact.full_content);
|
|
54
|
-
const assessmentPath = resolveSliceFile(basePath, milestoneId, slice.id, "ASSESSMENT");
|
|
55
|
-
const assessmentContent = assessmentPath ? await loadFile(assessmentPath) : null;
|
|
56
|
-
if (assessmentContent)
|
|
57
|
-
chunks.push(assessmentContent);
|
|
58
|
-
}
|
|
59
|
-
return chunks.join("\n\n");
|
|
47
|
+
function hasRuntimeExecutableUatEvidenceText(text) {
|
|
48
|
+
if (!/\buatType:\s*runtime-executable\b/i.test(text))
|
|
49
|
+
return false;
|
|
50
|
+
if (!/\bverdict:\s*PASS\b/i.test(text))
|
|
51
|
+
return false;
|
|
52
|
+
return /^\|\s*[^|\n]+\s*\|\s*runtime\s*\|\s*PASS\s*\|[^|\n]*\bgsd_uat_exec\b/mi.test(text);
|
|
60
53
|
}
|
|
61
54
|
async function browserEvidenceGateRequiresAttention(params, basePath) {
|
|
62
55
|
if (params.verdict !== "pass")
|
|
@@ -77,7 +70,36 @@ async function browserEvidenceGateRequiresAttention(params, basePath) {
|
|
|
77
70
|
]);
|
|
78
71
|
if (!hasBrowserRequiredText(requirementText))
|
|
79
72
|
return false;
|
|
80
|
-
|
|
73
|
+
// Collect per-slice evidence so the runtime bypass is checked independently
|
|
74
|
+
// for each slice. Concatenating all slices before checking would allow runtime
|
|
75
|
+
// evidence from one slice to cover another slice's browser requirements.
|
|
76
|
+
const sliceEvidencePairs = [];
|
|
77
|
+
for (const slice of slices) {
|
|
78
|
+
const chunks = [];
|
|
79
|
+
const artifactPath = `milestones/${params.milestoneId}/slices/${slice.id}/${slice.id}-ASSESSMENT.md`;
|
|
80
|
+
const artifact = getArtifact(artifactPath);
|
|
81
|
+
if (artifact?.full_content)
|
|
82
|
+
chunks.push(artifact.full_content);
|
|
83
|
+
const assessmentPath = resolveSliceFile(basePath, params.milestoneId, slice.id, "ASSESSMENT");
|
|
84
|
+
const assessmentContent = assessmentPath ? await loadFile(assessmentPath) : null;
|
|
85
|
+
if (assessmentContent)
|
|
86
|
+
chunks.push(assessmentContent);
|
|
87
|
+
sliceEvidencePairs.push({
|
|
88
|
+
sliceRequirementText: compactTextParts([slice.demo, slice.goal, slice.success_criteria]),
|
|
89
|
+
evidenceText: chunks.join("\n\n"),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const persistedEvidence = sliceEvidencePairs.map((s) => s.evidenceText).join("\n\n");
|
|
93
|
+
// Runtime bypass: each slice whose own requirement text has browser-observable
|
|
94
|
+
// criteria must have its own runtime-executable UAT evidence. When no individual
|
|
95
|
+
// slice has slice-level browser requirements (e.g., they come from milestone-level
|
|
96
|
+
// fields only), fall back to checking whether any slice has runtime evidence.
|
|
97
|
+
const browserRequiringSlices = sliceEvidencePairs.filter((s) => hasBrowserRequiredText(s.sliceRequirementText));
|
|
98
|
+
const runtimeBypasses = browserRequiringSlices.length > 0
|
|
99
|
+
? browserRequiringSlices.every((s) => hasRuntimeExecutableUatEvidenceText(s.evidenceText))
|
|
100
|
+
: sliceEvidencePairs.some((s) => hasRuntimeExecutableUatEvidenceText(s.evidenceText));
|
|
101
|
+
if (runtimeBypasses)
|
|
102
|
+
return false;
|
|
81
103
|
const validationEvidence = compactTextParts([
|
|
82
104
|
params.successCriteriaChecklist,
|
|
83
105
|
params.verificationClasses,
|
|
@@ -138,12 +160,20 @@ export async function handleValidateMilestone(params, basePath, opts) {
|
|
|
138
160
|
const requiredClasses = getRequiredVerificationClasses(params.milestoneId);
|
|
139
161
|
if (requiredClasses.length > 0) {
|
|
140
162
|
const verificationClasses = params.verificationClasses ?? "";
|
|
141
|
-
const
|
|
142
|
-
if (
|
|
163
|
+
const missingClasses = requiredClasses.filter((className) => !new RegExp(`\\b${className}\\b`, "i").test(verificationClasses));
|
|
164
|
+
if (missingClasses.length === 1) {
|
|
165
|
+
const missingClass = missingClasses[0];
|
|
143
166
|
return {
|
|
144
167
|
error: `verificationClasses must include canonical row "${missingClass}" because this milestone planned ${missingClass.toLowerCase()} verification`,
|
|
145
168
|
};
|
|
146
169
|
}
|
|
170
|
+
if (missingClasses.length > 1) {
|
|
171
|
+
const quotedClasses = missingClasses.map((className) => `"${className}"`).join(", ");
|
|
172
|
+
const plannedClasses = missingClasses.map((className) => className.toLowerCase()).join(", ");
|
|
173
|
+
return {
|
|
174
|
+
error: `verificationClasses must include canonical rows ${quotedClasses} because this milestone planned ${plannedClasses} verification`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
147
177
|
}
|
|
148
178
|
const artifactBasePath = resolveCanonicalMilestoneRoot(basePath, params.milestoneId);
|
|
149
179
|
const shouldApplyBrowserEvidenceGate = !opts?.skipBrowserEvidenceGate &&
|
|
@@ -26,7 +26,7 @@ import { invalidateStateCache } from "../state.js";
|
|
|
26
26
|
import { loadEffectiveGSDPreferences } from "../preferences.js";
|
|
27
27
|
import { parseProject } from "../schemas/parsers.js";
|
|
28
28
|
import { getAutoRuntimeSnapshot } from "../auto-runtime-state.js";
|
|
29
|
-
import { canonicalWorkflowToolName, parseMcpToolName, RUN_UAT_FORBIDDEN_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES, } from "../tool-presentation-plan.js";
|
|
29
|
+
import { buildRunUatPresentationForType, canonicalWorkflowToolName, parseMcpToolName, RUN_UAT_FORBIDDEN_TOOL_NAMES, RUN_UAT_TOOL_PRESENTATION_PLAN_ID, RUN_UAT_WORKFLOW_TOOL_NAMES, } from "../tool-presentation-plan.js";
|
|
30
30
|
export const SUPPORTED_SUMMARY_ARTIFACT_TYPES = [
|
|
31
31
|
"SUMMARY",
|
|
32
32
|
"RESEARCH",
|
|
@@ -53,7 +53,7 @@ function blockIfWrongAutoUnit(requiredUnitType, operation) {
|
|
|
53
53
|
return null;
|
|
54
54
|
if (snapshot.currentUnit.type === requiredUnitType)
|
|
55
55
|
return null;
|
|
56
|
-
const error = `HARD BLOCK: ${operation} may only run from ${requiredUnitType}; active unit is ${snapshot.currentUnit.type}. The orchestrator owns phase transitions.`;
|
|
56
|
+
const error = `HARD BLOCK: Tool Contract failure: ${operation} may only run from ${requiredUnitType}; active unit is ${snapshot.currentUnit.type}. Fix unit-tool-contracts.ts or the active Unit prompt. The orchestrator owns phase transitions.`;
|
|
57
57
|
return {
|
|
58
58
|
content: [{ type: "text", text: error }],
|
|
59
59
|
details: { operation, error },
|
|
@@ -121,7 +121,11 @@ export async function executeSummarySave(params, basePath = process.cwd()) {
|
|
|
121
121
|
if (rootArtifactGuard.block) {
|
|
122
122
|
return {
|
|
123
123
|
content: [{ type: "text", text: `Error saving artifact: ${rootArtifactGuard.reason ?? "root artifact write blocked"}` }],
|
|
124
|
-
details: {
|
|
124
|
+
details: {
|
|
125
|
+
operation: "save_summary",
|
|
126
|
+
error: "root_artifact_write_blocked",
|
|
127
|
+
displayReason: "Approval confirmation required before saving final project setup artifacts.",
|
|
128
|
+
},
|
|
125
129
|
isError: true,
|
|
126
130
|
};
|
|
127
131
|
}
|
|
@@ -129,7 +133,11 @@ export async function executeSummarySave(params, basePath = process.cwd()) {
|
|
|
129
133
|
if (contextGuard.block) {
|
|
130
134
|
return {
|
|
131
135
|
content: [{ type: "text", text: `Error saving artifact: ${contextGuard.reason ?? "context write blocked"}` }],
|
|
132
|
-
details: {
|
|
136
|
+
details: {
|
|
137
|
+
operation: "save_summary",
|
|
138
|
+
error: "context_write_blocked",
|
|
139
|
+
displayReason: "Depth check required before writing milestone context.",
|
|
140
|
+
},
|
|
133
141
|
isError: true,
|
|
134
142
|
};
|
|
135
143
|
}
|
|
@@ -334,6 +342,28 @@ export async function executeTaskComplete(params, basePath = process.cwd()) {
|
|
|
334
342
|
isError: true,
|
|
335
343
|
};
|
|
336
344
|
}
|
|
345
|
+
if (result.escalation) {
|
|
346
|
+
const recommended = result.escalation.options.find((option) => option.id === result.escalation?.recommendation);
|
|
347
|
+
const optionIds = result.escalation.options.map((option) => option.id).join("|");
|
|
348
|
+
return {
|
|
349
|
+
content: [{
|
|
350
|
+
type: "text",
|
|
351
|
+
text: [
|
|
352
|
+
`Task completed with escalation decision required: ${result.escalation.question}`,
|
|
353
|
+
`Recommendation: ${result.escalation.recommendation}${recommended ? ` (${recommended.label})` : ""} — ${result.escalation.recommendationRationale}`,
|
|
354
|
+
`Resolve with: /gsd escalate resolve ${result.taskId} <${optionIds}|accept|reject-blocker> [rationale...]`,
|
|
355
|
+
].join("\n"),
|
|
356
|
+
}],
|
|
357
|
+
details: {
|
|
358
|
+
operation: "complete_task",
|
|
359
|
+
taskId: result.taskId,
|
|
360
|
+
sliceId: result.sliceId,
|
|
361
|
+
milestoneId: result.milestoneId,
|
|
362
|
+
summaryPath: result.summaryPath,
|
|
363
|
+
escalation: result.escalation,
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
}
|
|
337
367
|
return {
|
|
338
368
|
content: [{ type: "text", text: `Completed task ${result.taskId} (${result.sliceId}/${result.milestoneId})` }],
|
|
339
369
|
details: {
|
|
@@ -786,6 +816,52 @@ function errorResult(operation, message, error) {
|
|
|
786
816
|
function isNonEmptyString(value) {
|
|
787
817
|
return typeof value === "string" && value.trim().length > 0;
|
|
788
818
|
}
|
|
819
|
+
function mergeBlockedTools(current, canonical) {
|
|
820
|
+
const merged = new Map();
|
|
821
|
+
for (const entry of [...(current ?? []), ...canonical]) {
|
|
822
|
+
merged.set(canonicalWorkflowToolName(parseMcpToolName(entry.name)?.tool ?? entry.name), entry);
|
|
823
|
+
}
|
|
824
|
+
return [...merged.values()];
|
|
825
|
+
}
|
|
826
|
+
function mergePresentedTools(current, canonical) {
|
|
827
|
+
return [...new Set([...(current ?? []), ...canonical])];
|
|
828
|
+
}
|
|
829
|
+
function normalizeUatVerdict(params) {
|
|
830
|
+
const raw = params;
|
|
831
|
+
if (typeof raw.verdict === "string") {
|
|
832
|
+
return { ...params, verdict: raw.verdict.toUpperCase() };
|
|
833
|
+
}
|
|
834
|
+
return params;
|
|
835
|
+
}
|
|
836
|
+
function supplyDefaultPresentation(params) {
|
|
837
|
+
const raw = params;
|
|
838
|
+
if (!raw.presentation) {
|
|
839
|
+
return { ...params, presentation: buildRunUatPresentationForType(params.uatType) };
|
|
840
|
+
}
|
|
841
|
+
return params;
|
|
842
|
+
}
|
|
843
|
+
function mergeCanonicalPresentation(params) {
|
|
844
|
+
const canonicalPresentation = buildRunUatPresentationForType(params.uatType);
|
|
845
|
+
const providedPresentation = params.presentation;
|
|
846
|
+
return {
|
|
847
|
+
...params,
|
|
848
|
+
presentation: {
|
|
849
|
+
...providedPresentation,
|
|
850
|
+
surface: providedPresentation.surface ?? canonicalPresentation.surface,
|
|
851
|
+
presentedTools: mergePresentedTools(providedPresentation.presentedTools, canonicalPresentation.presentedTools),
|
|
852
|
+
blockedTools: mergeBlockedTools(providedPresentation.blockedTools, canonicalPresentation.blockedTools),
|
|
853
|
+
toolPresentationPlanId: RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
|
|
854
|
+
},
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
const VALID_UAT_TYPES = [
|
|
858
|
+
"artifact-driven",
|
|
859
|
+
"browser-executable",
|
|
860
|
+
"runtime-executable",
|
|
861
|
+
"live-runtime",
|
|
862
|
+
"mixed",
|
|
863
|
+
"human-experience",
|
|
864
|
+
];
|
|
789
865
|
function ensureUatRequiredFields(params) {
|
|
790
866
|
if (!isNonEmptyString(params.milestoneId))
|
|
791
867
|
return "milestoneId is required";
|
|
@@ -793,6 +869,9 @@ function ensureUatRequiredFields(params) {
|
|
|
793
869
|
return "sliceId is required";
|
|
794
870
|
if (!isNonEmptyString(params.uatType))
|
|
795
871
|
return "uatType is required";
|
|
872
|
+
if (!VALID_UAT_TYPES.includes(params.uatType)) {
|
|
873
|
+
return `uatType must be one of: ${VALID_UAT_TYPES.join(", ")}`;
|
|
874
|
+
}
|
|
796
875
|
if (!["PASS", "FAIL", "PARTIAL"].includes(params.verdict))
|
|
797
876
|
return "verdict must be PASS, FAIL, or PARTIAL";
|
|
798
877
|
if (!Array.isArray(params.checks) || params.checks.length === 0)
|
|
@@ -929,9 +1008,18 @@ function validateUatChecks(basePath, params) {
|
|
|
929
1008
|
}
|
|
930
1009
|
return null;
|
|
931
1010
|
}
|
|
1011
|
+
function validateFreshUatOwnedEvidence(params) {
|
|
1012
|
+
const hasFreshUatEvidence = params.checks.some((check) => (check.evidence ?? []).some((evidence) => evidence.kind === "gsd_uat_exec"));
|
|
1013
|
+
return hasFreshUatEvidence
|
|
1014
|
+
? null
|
|
1015
|
+
: "UAT Assessment requires at least one fresh gsd_uat_exec evidence reference from run-uat";
|
|
1016
|
+
}
|
|
932
1017
|
function validateUatMode(params) {
|
|
933
1018
|
const modes = new Set(params.checks.map((check) => check.mode));
|
|
934
1019
|
const hasHuman = params.checks.some((check) => check.result === "NEEDS-HUMAN");
|
|
1020
|
+
if (params.uatType === "artifact-driven" && hasHuman && params.verdict === "PASS") {
|
|
1021
|
+
return "artifact-driven UAT cannot PASS with human-only checks";
|
|
1022
|
+
}
|
|
935
1023
|
if (hasHuman &&
|
|
936
1024
|
params.verdict === "PASS" &&
|
|
937
1025
|
!["human-experience", "mixed", "live-runtime"].includes(params.uatType) &&
|
|
@@ -947,11 +1035,11 @@ function validateUatMode(params) {
|
|
|
947
1035
|
if (params.uatType === "live-runtime" && !modes.has("runtime") && !modes.has("browser")) {
|
|
948
1036
|
return "live-runtime UAT requires runtime or browser evidence";
|
|
949
1037
|
}
|
|
950
|
-
if (params.uatType === "artifact-driven" && hasHuman && params.verdict === "PASS") {
|
|
951
|
-
return "artifact-driven UAT cannot PASS with human-only checks";
|
|
952
|
-
}
|
|
953
1038
|
return null;
|
|
954
1039
|
}
|
|
1040
|
+
function quoteToolNames(toolNames) {
|
|
1041
|
+
return toolNames.map((toolName) => `"${toolName}"`).join(", ");
|
|
1042
|
+
}
|
|
955
1043
|
function validateCanonicalPresentation(params) {
|
|
956
1044
|
const aliasHints = {
|
|
957
1045
|
gsd_save_summary: "gsd_summary_save",
|
|
@@ -959,34 +1047,46 @@ function validateCanonicalPresentation(params) {
|
|
|
959
1047
|
gsd_complete_slice: "gsd_slice_complete",
|
|
960
1048
|
gsd_milestone_complete: "gsd_complete_milestone",
|
|
961
1049
|
};
|
|
1050
|
+
const errors = [];
|
|
962
1051
|
for (const toolName of params.presentation.presentedTools) {
|
|
963
1052
|
const baseName = parseMcpToolName(toolName)?.tool ?? toolName;
|
|
964
1053
|
const canonical = aliasHints[baseName];
|
|
965
1054
|
if (canonical)
|
|
966
|
-
|
|
1055
|
+
errors.push(`presentation tool "${toolName}" uses an alias; use canonical "${canonical}"`);
|
|
967
1056
|
}
|
|
968
1057
|
const presentedCanonical = new Set(params.presentation.presentedTools.map((toolName) => canonicalWorkflowToolName(parseMcpToolName(toolName)?.tool ?? toolName)));
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1058
|
+
const missingRequiredTools = RUN_UAT_WORKFLOW_TOOL_NAMES.filter((requiredTool) => !presentedCanonical.has(requiredTool));
|
|
1059
|
+
if (missingRequiredTools.length === 1) {
|
|
1060
|
+
errors.push(`presentation is missing required UAT tool "${missingRequiredTools[0]}"`);
|
|
1061
|
+
}
|
|
1062
|
+
else if (missingRequiredTools.length > 1) {
|
|
1063
|
+
errors.push(`presentation is missing required UAT tools ${quoteToolNames(missingRequiredTools)}`);
|
|
973
1064
|
}
|
|
974
1065
|
const forbiddenCanonical = new Set(RUN_UAT_FORBIDDEN_TOOL_NAMES
|
|
975
1066
|
.filter((toolName) => !toolName.includes("*"))
|
|
976
1067
|
.map((toolName) => canonicalWorkflowToolName(parseMcpToolName(toolName)?.tool ?? toolName)));
|
|
1068
|
+
const forbiddenPresentedTools = [];
|
|
977
1069
|
for (const toolName of params.presentation.presentedTools) {
|
|
978
1070
|
const canonical = canonicalWorkflowToolName(parseMcpToolName(toolName)?.tool ?? toolName);
|
|
979
1071
|
if (toolName === "mcp__gsd-workflow__*" || forbiddenCanonical.has(canonical)) {
|
|
980
|
-
|
|
1072
|
+
forbiddenPresentedTools.push(toolName);
|
|
981
1073
|
}
|
|
982
1074
|
}
|
|
1075
|
+
if (forbiddenPresentedTools.length === 1) {
|
|
1076
|
+
errors.push(`presentation includes forbidden run-uat tool "${forbiddenPresentedTools[0]}"`);
|
|
1077
|
+
}
|
|
1078
|
+
else if (forbiddenPresentedTools.length > 1) {
|
|
1079
|
+
errors.push(`presentation includes forbidden run-uat tools ${quoteToolNames(forbiddenPresentedTools)}`);
|
|
1080
|
+
}
|
|
983
1081
|
const blockedCanonical = new Set(params.presentation.blockedTools.map((entry) => canonicalWorkflowToolName(parseMcpToolName(entry.name)?.tool ?? entry.name)));
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
}
|
|
1082
|
+
const missingBlockedTools = ["gsd_exec", "gsd_summary_save", "gsd_save_gate_result"].filter((blockedTool) => !blockedCanonical.has(blockedTool));
|
|
1083
|
+
if (missingBlockedTools.length === 1) {
|
|
1084
|
+
errors.push(`presentation must record "${missingBlockedTools[0]}" as blocked during run-uat`);
|
|
988
1085
|
}
|
|
989
|
-
|
|
1086
|
+
else if (missingBlockedTools.length > 1) {
|
|
1087
|
+
errors.push(`presentation must record ${quoteToolNames(missingBlockedTools)} as blocked during run-uat`);
|
|
1088
|
+
}
|
|
1089
|
+
return errors.length > 0 ? errors.join("; ") : null;
|
|
990
1090
|
}
|
|
991
1091
|
function nextUatAttempt(basePath, milestoneId, sliceId) {
|
|
992
1092
|
const contract = resolveGsdPathContract(basePath);
|
|
@@ -1050,18 +1150,32 @@ async function saveUatAttemptArtifact(basePath, params, attempt) {
|
|
|
1050
1150
|
return relativePath;
|
|
1051
1151
|
}
|
|
1052
1152
|
export async function executeUatResultSave(params, basePath = process.cwd()) {
|
|
1153
|
+
const unitGuard = blockIfWrongAutoUnit("run-uat", "save_uat_result");
|
|
1154
|
+
if (unitGuard)
|
|
1155
|
+
return unitGuard;
|
|
1156
|
+
// Phase 1: normalize verdict and supply the canonical presentation when none was provided.
|
|
1157
|
+
params = normalizeUatVerdict(params);
|
|
1158
|
+
params = supplyDefaultPresentation(params);
|
|
1053
1159
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
1054
1160
|
if (!dbAvailable)
|
|
1055
1161
|
return errorResult("save_uat_result", "GSD database is not available.", "db_unavailable");
|
|
1162
|
+
// Phase 2: validate the submitted presentation before the canonical merge so that
|
|
1163
|
+
// presentations missing required workflow tools are rejected rather than silently patched.
|
|
1056
1164
|
const requiredError = ensureUatRequiredFields(params);
|
|
1057
1165
|
if (requiredError)
|
|
1058
1166
|
return errorResult("save_uat_result", requiredError, "invalid_params");
|
|
1059
1167
|
const presentationError = validateCanonicalPresentation(params);
|
|
1060
1168
|
if (presentationError)
|
|
1061
1169
|
return errorResult("save_uat_result", presentationError, "alias_tool_name");
|
|
1170
|
+
// Phase 3: merge in the canonical plan ID and read-only audit tools so the persisted
|
|
1171
|
+
// artifact always carries the full audit surface even when the provider omitted them.
|
|
1172
|
+
params = mergeCanonicalPresentation(params);
|
|
1062
1173
|
const checkError = validateUatChecks(basePath, params);
|
|
1063
1174
|
if (checkError)
|
|
1064
1175
|
return errorResult("save_uat_result", checkError, "invalid_evidence");
|
|
1176
|
+
const freshEvidenceError = validateFreshUatOwnedEvidence(params);
|
|
1177
|
+
if (freshEvidenceError)
|
|
1178
|
+
return errorResult("save_uat_result", freshEvidenceError, "missing_fresh_uat_evidence");
|
|
1065
1179
|
const modeError = validateUatMode(params);
|
|
1066
1180
|
if (modeError)
|
|
1067
1181
|
return errorResult("save_uat_result", modeError, "uat_mode_mismatch");
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Central Unit-to-tool contracts for phase-aware GSD tool surfaces.
|
|
3
|
+
export const RUN_UAT_WORKFLOW_TOOL_NAMES = [
|
|
4
|
+
"gsd_uat_exec",
|
|
5
|
+
"gsd_uat_result_save",
|
|
6
|
+
"gsd_resume",
|
|
7
|
+
"gsd_milestone_status",
|
|
8
|
+
"gsd_journal_query",
|
|
9
|
+
];
|
|
10
|
+
export const RUN_UAT_READ_ONLY_TOOL_NAMES = [
|
|
11
|
+
"find",
|
|
12
|
+
"glob",
|
|
13
|
+
"grep",
|
|
14
|
+
"ls",
|
|
15
|
+
"read",
|
|
16
|
+
];
|
|
17
|
+
export const RUN_UAT_BROWSER_TOOL_NAMES = [
|
|
18
|
+
"browser_navigate",
|
|
19
|
+
"browser_click",
|
|
20
|
+
"browser_type",
|
|
21
|
+
"browser_fill_form",
|
|
22
|
+
"browser_click_ref",
|
|
23
|
+
"browser_fill_ref",
|
|
24
|
+
"browser_wait_for",
|
|
25
|
+
"browser_assert",
|
|
26
|
+
"browser_verify",
|
|
27
|
+
"browser_screenshot",
|
|
28
|
+
"browser_snapshot_refs",
|
|
29
|
+
"browser_find",
|
|
30
|
+
"browser_get_console_logs",
|
|
31
|
+
"browser_get_network_logs",
|
|
32
|
+
"browser_evaluate",
|
|
33
|
+
"browser_reload",
|
|
34
|
+
"browser_batch",
|
|
35
|
+
"browser_act",
|
|
36
|
+
];
|
|
37
|
+
export const RUN_UAT_TOOL_PRESENTATION_PLAN_ID = "run-uat/default-v1";
|
|
38
|
+
export const UNIT_TOOL_CONTRACTS = {
|
|
39
|
+
"research-milestone": {
|
|
40
|
+
allowedGsdTools: ["gsd_summary_save", "gsd_decision_save"],
|
|
41
|
+
requiredWorkflowTools: ["gsd_summary_save"],
|
|
42
|
+
},
|
|
43
|
+
"plan-milestone": {
|
|
44
|
+
allowedGsdTools: ["gsd_plan_milestone", "gsd_decision_save", "gsd_requirement_update"],
|
|
45
|
+
requiredWorkflowTools: ["gsd_plan_milestone"],
|
|
46
|
+
},
|
|
47
|
+
"discuss-milestone": {
|
|
48
|
+
allowedGsdTools: [
|
|
49
|
+
"gsd_summary_save",
|
|
50
|
+
"gsd_decision_save",
|
|
51
|
+
"gsd_requirement_save",
|
|
52
|
+
"gsd_requirement_update",
|
|
53
|
+
"gsd_plan_milestone",
|
|
54
|
+
"gsd_milestone_generate_id",
|
|
55
|
+
],
|
|
56
|
+
requiredWorkflowTools: [
|
|
57
|
+
"gsd_summary_save",
|
|
58
|
+
"gsd_requirement_save",
|
|
59
|
+
"gsd_requirement_update",
|
|
60
|
+
"gsd_plan_milestone",
|
|
61
|
+
"gsd_milestone_generate_id",
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
"discuss-slice": {
|
|
65
|
+
allowedGsdTools: ["gsd_summary_save", "gsd_decision_save"],
|
|
66
|
+
requiredWorkflowTools: ["gsd_summary_save"],
|
|
67
|
+
},
|
|
68
|
+
"validate-milestone": {
|
|
69
|
+
allowedGsdTools: ["gsd_validate_milestone", "gsd_reassess_roadmap", "subagent"],
|
|
70
|
+
requiredWorkflowTools: ["gsd_milestone_status", "gsd_validate_milestone", "gsd_reassess_roadmap"],
|
|
71
|
+
},
|
|
72
|
+
"complete-milestone": {
|
|
73
|
+
allowedGsdTools: ["gsd_complete_milestone", "subagent"],
|
|
74
|
+
requiredWorkflowTools: ["gsd_milestone_status", "gsd_complete_milestone"],
|
|
75
|
+
},
|
|
76
|
+
"research-slice": {
|
|
77
|
+
allowedGsdTools: ["gsd_summary_save", "gsd_decision_save"],
|
|
78
|
+
requiredWorkflowTools: ["gsd_summary_save"],
|
|
79
|
+
},
|
|
80
|
+
"plan-slice": {
|
|
81
|
+
allowedGsdTools: ["gsd_plan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
82
|
+
requiredWorkflowTools: ["gsd_plan_slice"],
|
|
83
|
+
},
|
|
84
|
+
"refine-slice": {
|
|
85
|
+
allowedGsdTools: ["gsd_plan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
86
|
+
requiredWorkflowTools: [],
|
|
87
|
+
},
|
|
88
|
+
"replan-slice": {
|
|
89
|
+
allowedGsdTools: ["gsd_replan_slice", "gsd_plan_task", "gsd_decision_save"],
|
|
90
|
+
requiredWorkflowTools: ["gsd_replan_slice"],
|
|
91
|
+
},
|
|
92
|
+
"complete-slice": {
|
|
93
|
+
allowedGsdTools: [
|
|
94
|
+
"gsd_slice_complete",
|
|
95
|
+
"gsd_task_reopen",
|
|
96
|
+
"gsd_replan_slice",
|
|
97
|
+
"gsd_decision_save",
|
|
98
|
+
"gsd_requirement_update",
|
|
99
|
+
"subagent",
|
|
100
|
+
],
|
|
101
|
+
requiredWorkflowTools: ["gsd_slice_complete", "gsd_task_reopen", "gsd_replan_slice"],
|
|
102
|
+
forbiddenGsdTools: {
|
|
103
|
+
gsd_uat_result_save: "Run UAT owns persisted UAT Assessment.",
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
"reassess-roadmap": {
|
|
107
|
+
allowedGsdTools: ["gsd_reassess_roadmap"],
|
|
108
|
+
requiredWorkflowTools: ["gsd_milestone_status", "gsd_reassess_roadmap"],
|
|
109
|
+
},
|
|
110
|
+
"execute-task": {
|
|
111
|
+
allowedGsdTools: ["gsd_task_complete", "gsd_decision_save"],
|
|
112
|
+
requiredWorkflowTools: ["gsd_task_complete"],
|
|
113
|
+
},
|
|
114
|
+
"execute-task-simple": {
|
|
115
|
+
allowedGsdTools: ["gsd_task_complete", "gsd_decision_save"],
|
|
116
|
+
requiredWorkflowTools: ["gsd_task_complete"],
|
|
117
|
+
},
|
|
118
|
+
"reactive-execute": {
|
|
119
|
+
allowedGsdTools: ["gsd_task_complete", "gsd_decision_save"],
|
|
120
|
+
requiredWorkflowTools: ["gsd_task_complete"],
|
|
121
|
+
},
|
|
122
|
+
"run-uat": {
|
|
123
|
+
allowedGsdTools: [...RUN_UAT_WORKFLOW_TOOL_NAMES, "subagent"],
|
|
124
|
+
requiredWorkflowTools: [...RUN_UAT_WORKFLOW_TOOL_NAMES],
|
|
125
|
+
forbiddenGsdTools: {
|
|
126
|
+
gsd_exec: "Use gsd_uat_exec so acceptance evidence is typed as UAT-owned.",
|
|
127
|
+
gsd_save_gate_result: "gsd_uat_result_save owns the aggregate UAT gate.",
|
|
128
|
+
gsd_summary_save: "gsd_uat_result_save owns persisted UAT Assessment writes.",
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
"gate-evaluate": {
|
|
132
|
+
allowedGsdTools: ["gsd_save_gate_result"],
|
|
133
|
+
requiredWorkflowTools: ["gsd_save_gate_result"],
|
|
134
|
+
},
|
|
135
|
+
"rewrite-docs": {
|
|
136
|
+
allowedGsdTools: ["gsd_summary_save", "gsd_decision_save"],
|
|
137
|
+
requiredWorkflowTools: [],
|
|
138
|
+
},
|
|
139
|
+
"workflow-preferences": {
|
|
140
|
+
allowedGsdTools: ["gsd_summary_save"],
|
|
141
|
+
requiredWorkflowTools: [],
|
|
142
|
+
},
|
|
143
|
+
"discuss-project": {
|
|
144
|
+
allowedGsdTools: ["gsd_summary_save", "gsd_decision_save", "gsd_requirement_save"],
|
|
145
|
+
requiredWorkflowTools: ["ask_user_questions", "gsd_summary_save"],
|
|
146
|
+
},
|
|
147
|
+
"discuss-requirements": {
|
|
148
|
+
allowedGsdTools: ["gsd_requirement_save", "gsd_summary_save"],
|
|
149
|
+
requiredWorkflowTools: ["ask_user_questions", "gsd_requirement_save", "gsd_summary_save"],
|
|
150
|
+
},
|
|
151
|
+
"research-decision": {
|
|
152
|
+
allowedGsdTools: ["gsd_summary_save"],
|
|
153
|
+
requiredWorkflowTools: ["ask_user_questions"],
|
|
154
|
+
},
|
|
155
|
+
"research-project": {
|
|
156
|
+
allowedGsdTools: ["gsd_summary_save", "gsd_decision_save"],
|
|
157
|
+
requiredWorkflowTools: [],
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
export const AUTO_UNIT_SCOPED_TOOLS = Object.fromEntries(Object.entries(UNIT_TOOL_CONTRACTS).map(([unitType, contract]) => [unitType, contract.allowedGsdTools]));
|
|
161
|
+
export function getUnitToolSurfaceContract(unitType) {
|
|
162
|
+
return UNIT_TOOL_CONTRACTS[unitType];
|
|
163
|
+
}
|
|
164
|
+
export function getRequiredWorkflowToolsForUnit(unitType) {
|
|
165
|
+
return [...(UNIT_TOOL_CONTRACTS[unitType]?.requiredWorkflowTools ?? [])];
|
|
166
|
+
}
|
|
167
|
+
export function getForbiddenGsdToolReason(unitType, toolName) {
|
|
168
|
+
return UNIT_TOOL_CONTRACTS[unitType]?.forbiddenGsdTools?.[toolName];
|
|
169
|
+
}
|