@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
|
@@ -75,6 +75,11 @@ test("closeout executors reject phase escalation from the wrong active auto unit
|
|
|
75
75
|
const milestone = await executeCompleteMilestone({} as Parameters<typeof executeCompleteMilestone>[0], "/tmp/project");
|
|
76
76
|
assert.equal(milestone.isError, true);
|
|
77
77
|
assert.match(String(milestone.details.error), /complete_milestone may only run from complete-milestone/);
|
|
78
|
+
|
|
79
|
+
const uat = await executeUatResultSave({} as Parameters<typeof executeUatResultSave>[0], "/tmp/project");
|
|
80
|
+
assert.equal(uat.isError, true);
|
|
81
|
+
assert.match(String(uat.details.error), /save_uat_result may only run from run-uat/);
|
|
82
|
+
assert.match(String(uat.details.error), /Tool Contract failure/);
|
|
78
83
|
} finally {
|
|
79
84
|
autoSession.reset();
|
|
80
85
|
}
|
|
@@ -235,6 +240,62 @@ test("executeTaskComplete derives missing verification from evidence", async ()
|
|
|
235
240
|
}
|
|
236
241
|
});
|
|
237
242
|
|
|
243
|
+
test("executeTaskComplete surfaces escalation questions and metadata", async () => {
|
|
244
|
+
const base = makeTmpBase();
|
|
245
|
+
try {
|
|
246
|
+
openTestDb(base);
|
|
247
|
+
writeFileSync(join(base, ".gsd", "PREFERENCES.md"), [
|
|
248
|
+
"---",
|
|
249
|
+
"version: 1",
|
|
250
|
+
"phases:",
|
|
251
|
+
" mid_execution_escalation: true",
|
|
252
|
+
"---",
|
|
253
|
+
].join("\n"));
|
|
254
|
+
const planDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
255
|
+
mkdirSync(planDir, { recursive: true });
|
|
256
|
+
writeFileSync(join(planDir, "S01-PLAN.md"), "# S01\n\n- [ ] **T01: Demo** `est:5m`\n");
|
|
257
|
+
|
|
258
|
+
const result = await inProjectDir(base, () => executeTaskComplete({
|
|
259
|
+
milestoneId: "M001",
|
|
260
|
+
sliceId: "S01",
|
|
261
|
+
taskId: "T01",
|
|
262
|
+
oneLiner: "Completed task",
|
|
263
|
+
narrative: "Did the work but found an ambiguity.",
|
|
264
|
+
verification: "npm test",
|
|
265
|
+
escalation: {
|
|
266
|
+
question: "Should the cache use write-through or write-back?",
|
|
267
|
+
options: [
|
|
268
|
+
{ id: "A", label: "Write-through", tradeoffs: "Simpler reads; slower writes." },
|
|
269
|
+
{ id: "B", label: "Write-back", tradeoffs: "Faster writes; more flush complexity." },
|
|
270
|
+
],
|
|
271
|
+
recommendation: "A",
|
|
272
|
+
recommendationRationale: "Current usage favors correctness over write latency.",
|
|
273
|
+
continueWithDefault: true,
|
|
274
|
+
},
|
|
275
|
+
}, base));
|
|
276
|
+
|
|
277
|
+
assert.equal(result.details.operation, "complete_task");
|
|
278
|
+
assert.match(
|
|
279
|
+
String(result.content[0]?.text),
|
|
280
|
+
/Task completed with escalation decision required: Should the cache use write-through or write-back\?/,
|
|
281
|
+
);
|
|
282
|
+
assert.match(String(result.content[0]?.text), /Resolve with: \/gsd escalate resolve T01/);
|
|
283
|
+
assert.equal((result.details.escalation as { question?: string }).question, "Should the cache use write-through or write-back?");
|
|
284
|
+
|
|
285
|
+
const db = _getAdapter();
|
|
286
|
+
assert.ok(db, "DB should be open");
|
|
287
|
+
const row = db!.prepare(
|
|
288
|
+
"SELECT escalation_pending, escalation_awaiting_review, escalation_artifact_path FROM tasks WHERE milestone_id = ? AND slice_id = ? AND id = ?",
|
|
289
|
+
).get("M001", "S01", "T01") as Record<string, unknown> | undefined;
|
|
290
|
+
assert.equal(row?.escalation_pending, 0);
|
|
291
|
+
assert.equal(row?.escalation_awaiting_review, 1);
|
|
292
|
+
assert.ok(String(row?.escalation_artifact_path ?? "").endsWith("T01-ESCALATION.json"));
|
|
293
|
+
} finally {
|
|
294
|
+
closeDatabase();
|
|
295
|
+
cleanup(base);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
|
|
238
299
|
test("executeTaskComplete returns a tool error when verification cannot be derived", async () => {
|
|
239
300
|
const base = makeTmpBase();
|
|
240
301
|
try {
|
|
@@ -587,6 +648,343 @@ test("executeUatResultSave accepts gsd_uat_exec evidence written in a milestone
|
|
|
587
648
|
}
|
|
588
649
|
});
|
|
589
650
|
|
|
651
|
+
test("executeUatResultSave supplies canonical presentation and normalizes verdict casing", async () => {
|
|
652
|
+
const base = makeTmpBase();
|
|
653
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
654
|
+
const worktreeExecDir = join(worktree, ".gsd", "exec");
|
|
655
|
+
const evidenceId = "uat-lowercase-verdict";
|
|
656
|
+
try {
|
|
657
|
+
openTestDb(base);
|
|
658
|
+
seedMilestone("M001", "Milestone One");
|
|
659
|
+
seedSlice("M001", "S03", "complete");
|
|
660
|
+
mkdirSync(worktreeExecDir, { recursive: true });
|
|
661
|
+
writeFileSync(
|
|
662
|
+
join(worktreeExecDir, `${evidenceId}.meta.json`),
|
|
663
|
+
JSON.stringify({
|
|
664
|
+
id: evidenceId,
|
|
665
|
+
metadata: {
|
|
666
|
+
kind: "uat_exec",
|
|
667
|
+
milestoneId: "M001",
|
|
668
|
+
sliceId: "S03",
|
|
669
|
+
checkId: "UAT-01",
|
|
670
|
+
intent: "uat-artifact-check",
|
|
671
|
+
},
|
|
672
|
+
}),
|
|
673
|
+
"utf-8",
|
|
674
|
+
);
|
|
675
|
+
|
|
676
|
+
const result = await inProjectDir(worktree, () => executeUatResultSave({
|
|
677
|
+
milestoneId: "M001",
|
|
678
|
+
sliceId: "S03",
|
|
679
|
+
uatType: "artifact-driven",
|
|
680
|
+
verdict: "pass",
|
|
681
|
+
checks: [{
|
|
682
|
+
id: "UAT-01",
|
|
683
|
+
description: "Static artifact contract passes",
|
|
684
|
+
mode: "artifact",
|
|
685
|
+
result: "PASS",
|
|
686
|
+
evidence: [{ kind: "gsd_uat_exec", ref: evidenceId }],
|
|
687
|
+
notes: "Artifact check passed.",
|
|
688
|
+
}],
|
|
689
|
+
notes: "UAT passed with canonical presentation supplied by the executor.",
|
|
690
|
+
} as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
|
|
691
|
+
|
|
692
|
+
assert.equal(result.isError, undefined);
|
|
693
|
+
assert.equal(result.details.verdict, "PASS");
|
|
694
|
+
|
|
695
|
+
const attempt = JSON.parse(readFileSync(
|
|
696
|
+
join(base, ".gsd", "uat", "M001", "S03", "attempt-1.json"),
|
|
697
|
+
"utf-8",
|
|
698
|
+
)) as { presentation?: { toolPresentationPlanId?: string; presentedTools?: string[] } };
|
|
699
|
+
assert.equal(attempt.presentation?.toolPresentationPlanId, "run-uat/default-v1");
|
|
700
|
+
assert.ok(attempt.presentation?.presentedTools?.includes("gsd_uat_result_save"));
|
|
701
|
+
assert.ok(attempt.presentation?.presentedTools?.includes("read"));
|
|
702
|
+
} finally {
|
|
703
|
+
closeDatabase();
|
|
704
|
+
cleanup(base);
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
test("executeUatResultSave supplies direct browser tools for browser-executable UAT", async () => {
|
|
709
|
+
const base = makeTmpBase();
|
|
710
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
711
|
+
const worktreeExecDir = join(worktree, ".gsd", "exec");
|
|
712
|
+
const evidenceId = "uat-direct-browser-evidence";
|
|
713
|
+
try {
|
|
714
|
+
openTestDb(base);
|
|
715
|
+
seedMilestone("M001", "Milestone One");
|
|
716
|
+
seedSlice("M001", "S06", "complete");
|
|
717
|
+
mkdirSync(worktreeExecDir, { recursive: true });
|
|
718
|
+
writeFileSync(
|
|
719
|
+
join(worktreeExecDir, `${evidenceId}.meta.json`),
|
|
720
|
+
JSON.stringify({
|
|
721
|
+
id: evidenceId,
|
|
722
|
+
metadata: {
|
|
723
|
+
kind: "uat_exec",
|
|
724
|
+
milestoneId: "M001",
|
|
725
|
+
sliceId: "S06",
|
|
726
|
+
checkId: "UAT-01",
|
|
727
|
+
intent: "uat-browser-check",
|
|
728
|
+
},
|
|
729
|
+
}),
|
|
730
|
+
"utf-8",
|
|
731
|
+
);
|
|
732
|
+
|
|
733
|
+
const result = await inProjectDir(worktree, () => executeUatResultSave({
|
|
734
|
+
milestoneId: "M001",
|
|
735
|
+
sliceId: "S06",
|
|
736
|
+
uatType: "browser-executable",
|
|
737
|
+
verdict: "PASS",
|
|
738
|
+
checks: [{
|
|
739
|
+
id: "UAT-01",
|
|
740
|
+
description: "Browser flow used managed gsd-browser tools",
|
|
741
|
+
mode: "browser",
|
|
742
|
+
result: "PASS",
|
|
743
|
+
evidence: [{ kind: "gsd_uat_exec", ref: evidenceId }],
|
|
744
|
+
notes: "Browser check passed.",
|
|
745
|
+
}],
|
|
746
|
+
notes: "UAT passed with managed browser evidence.",
|
|
747
|
+
} as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
|
|
748
|
+
|
|
749
|
+
assert.equal(result.isError, undefined);
|
|
750
|
+
const attempt = JSON.parse(readFileSync(
|
|
751
|
+
join(base, ".gsd", "uat", "M001", "S06", "attempt-1.json"),
|
|
752
|
+
"utf-8",
|
|
753
|
+
)) as { presentation?: { presentedTools?: string[] } };
|
|
754
|
+
|
|
755
|
+
assert.ok(attempt.presentation?.presentedTools?.includes("browser_navigate"));
|
|
756
|
+
assert.ok(attempt.presentation?.presentedTools?.includes("browser_assert"));
|
|
757
|
+
assert.equal(
|
|
758
|
+
attempt.presentation?.presentedTools?.some((toolName) => toolName.startsWith("mcp__gsd-browser__")),
|
|
759
|
+
false,
|
|
760
|
+
);
|
|
761
|
+
} finally {
|
|
762
|
+
closeDatabase();
|
|
763
|
+
cleanup(base);
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
test("executeUatResultSave merges canonical plan ID and read-only tools when presentation lacks plan ID", async () => {
|
|
768
|
+
const base = makeTmpBase();
|
|
769
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
770
|
+
const worktreeExecDir = join(worktree, ".gsd", "exec");
|
|
771
|
+
const evidenceId = "uat-no-plan-id-evidence";
|
|
772
|
+
try {
|
|
773
|
+
openTestDb(base);
|
|
774
|
+
seedMilestone("M001", "Milestone One");
|
|
775
|
+
seedSlice("M001", "S05", "complete");
|
|
776
|
+
mkdirSync(worktreeExecDir, { recursive: true });
|
|
777
|
+
writeFileSync(
|
|
778
|
+
join(worktreeExecDir, `${evidenceId}.meta.json`),
|
|
779
|
+
JSON.stringify({
|
|
780
|
+
id: evidenceId,
|
|
781
|
+
metadata: {
|
|
782
|
+
kind: "uat_exec",
|
|
783
|
+
milestoneId: "M001",
|
|
784
|
+
sliceId: "S05",
|
|
785
|
+
checkId: "UAT-01",
|
|
786
|
+
intent: "uat-artifact-check",
|
|
787
|
+
},
|
|
788
|
+
}),
|
|
789
|
+
"utf-8",
|
|
790
|
+
);
|
|
791
|
+
|
|
792
|
+
const result = await inProjectDir(worktree, () => executeUatResultSave({
|
|
793
|
+
milestoneId: "M001",
|
|
794
|
+
sliceId: "S05",
|
|
795
|
+
uatType: "artifact-driven",
|
|
796
|
+
verdict: "PASS",
|
|
797
|
+
checks: [{
|
|
798
|
+
id: "UAT-01",
|
|
799
|
+
description: "Presentation plan ID absent from provider call",
|
|
800
|
+
mode: "artifact",
|
|
801
|
+
result: "PASS",
|
|
802
|
+
evidence: [{ kind: "gsd_uat_exec", ref: evidenceId }],
|
|
803
|
+
notes: "Canonical merge should apply even when toolPresentationPlanId is absent.",
|
|
804
|
+
}],
|
|
805
|
+
presentation: {
|
|
806
|
+
surface: "mcp",
|
|
807
|
+
presentedTools: [
|
|
808
|
+
"gsd_uat_exec",
|
|
809
|
+
"gsd_uat_result_save",
|
|
810
|
+
"gsd_resume",
|
|
811
|
+
"gsd_milestone_status",
|
|
812
|
+
"gsd_journal_query",
|
|
813
|
+
],
|
|
814
|
+
blockedTools: [
|
|
815
|
+
{ name: "gsd_exec", reason: "forbidden during run-uat" },
|
|
816
|
+
{ name: "gsd_summary_save", reason: "forbidden during run-uat" },
|
|
817
|
+
{ name: "gsd_save_gate_result", reason: "forbidden during run-uat" },
|
|
818
|
+
],
|
|
819
|
+
},
|
|
820
|
+
notes: "Provider omitted toolPresentationPlanId; executor must canonicalize.",
|
|
821
|
+
} as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
|
|
822
|
+
|
|
823
|
+
assert.equal(result.isError, undefined);
|
|
824
|
+
assert.equal(result.details.verdict, "PASS");
|
|
825
|
+
|
|
826
|
+
const attempt = JSON.parse(readFileSync(
|
|
827
|
+
join(base, ".gsd", "uat", "M001", "S05", "attempt-1.json"),
|
|
828
|
+
"utf-8",
|
|
829
|
+
)) as { presentation?: { toolPresentationPlanId?: string; presentedTools?: string[] } };
|
|
830
|
+
assert.equal(attempt.presentation?.toolPresentationPlanId, "run-uat/default-v1");
|
|
831
|
+
assert.ok(attempt.presentation?.presentedTools?.includes("read"), "read-only tool must be merged in");
|
|
832
|
+
assert.ok(attempt.presentation?.presentedTools?.includes("gsd_uat_result_save"));
|
|
833
|
+
} finally {
|
|
834
|
+
closeDatabase();
|
|
835
|
+
cleanup(base);
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
test("executeUatResultSave rejects saved UAT without fresh UAT-owned evidence", async () => {
|
|
840
|
+
const base = makeTmpBase();
|
|
841
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
842
|
+
const worktreeExecDir = join(worktree, ".gsd", "exec");
|
|
843
|
+
const evidenceId = "generic-exec-evidence";
|
|
844
|
+
try {
|
|
845
|
+
openTestDb(base);
|
|
846
|
+
seedMilestone("M001", "Milestone One");
|
|
847
|
+
seedSlice("M001", "S04", "complete");
|
|
848
|
+
mkdirSync(worktreeExecDir, { recursive: true });
|
|
849
|
+
writeFileSync(
|
|
850
|
+
join(worktreeExecDir, `${evidenceId}.meta.json`),
|
|
851
|
+
JSON.stringify({
|
|
852
|
+
id: evidenceId,
|
|
853
|
+
metadata: { kind: "exec" },
|
|
854
|
+
}),
|
|
855
|
+
"utf-8",
|
|
856
|
+
);
|
|
857
|
+
|
|
858
|
+
const result = await inProjectDir(worktree, () => executeUatResultSave({
|
|
859
|
+
milestoneId: "M001",
|
|
860
|
+
sliceId: "S04",
|
|
861
|
+
uatType: "artifact-driven",
|
|
862
|
+
verdict: "PASS",
|
|
863
|
+
checks: [{
|
|
864
|
+
id: "UAT-01",
|
|
865
|
+
description: "Static artifact contract passes",
|
|
866
|
+
mode: "artifact",
|
|
867
|
+
result: "PASS",
|
|
868
|
+
evidence: [{ kind: "gsd_exec", ref: evidenceId }],
|
|
869
|
+
notes: "Generic evidence should not satisfy fresh UAT evidence.",
|
|
870
|
+
}],
|
|
871
|
+
notes: "UAT should not pass without fresh UAT-owned evidence.",
|
|
872
|
+
} as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
|
|
873
|
+
|
|
874
|
+
assert.equal(result.isError, true);
|
|
875
|
+
assert.match(String(result.content[0]?.text), /fresh gsd_uat_exec evidence/);
|
|
876
|
+
} finally {
|
|
877
|
+
closeDatabase();
|
|
878
|
+
cleanup(base);
|
|
879
|
+
}
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
test("executeUatResultSave rejects an unrecognized uatType", async () => {
|
|
883
|
+
const base = makeTmpBase();
|
|
884
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
885
|
+
try {
|
|
886
|
+
openTestDb(base);
|
|
887
|
+
mkdirSync(worktree, { recursive: true });
|
|
888
|
+
seedMilestone("M001", "Milestone One");
|
|
889
|
+
seedSlice("M001", "S06", "complete");
|
|
890
|
+
|
|
891
|
+
const result = await inProjectDir(worktree, () => executeUatResultSave({
|
|
892
|
+
milestoneId: "M001",
|
|
893
|
+
sliceId: "S06",
|
|
894
|
+
uatType: "hallucinated-mode",
|
|
895
|
+
verdict: "PASS",
|
|
896
|
+
checks: [{
|
|
897
|
+
id: "UAT-01",
|
|
898
|
+
description: "Static artifact contract passes",
|
|
899
|
+
mode: "artifact",
|
|
900
|
+
result: "PASS",
|
|
901
|
+
evidence: [{ kind: "gsd_uat_exec", ref: "some-ref" }],
|
|
902
|
+
}],
|
|
903
|
+
notes: "Should fail before evidence validation.",
|
|
904
|
+
} as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
|
|
905
|
+
|
|
906
|
+
assert.equal(result.isError, true);
|
|
907
|
+
assert.match(String(result.content[0]?.text), /uatType must be one of/);
|
|
908
|
+
} finally {
|
|
909
|
+
closeDatabase();
|
|
910
|
+
cleanup(base);
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
test("executeUatResultSave rejects artifact-driven PASS with human follow-up checks", async () => {
|
|
915
|
+
const base = makeTmpBase();
|
|
916
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
917
|
+
const evidenceId = "uat-artifact-nonautomatable";
|
|
918
|
+
const worktreeExecDir = join(worktree, ".gsd", "exec");
|
|
919
|
+
try {
|
|
920
|
+
openTestDb(base);
|
|
921
|
+
seedMilestone("M001", "Milestone One");
|
|
922
|
+
seedSlice("M001", "S01", "complete");
|
|
923
|
+
mkdirSync(worktreeExecDir, { recursive: true });
|
|
924
|
+
writeFileSync(
|
|
925
|
+
join(worktreeExecDir, `${evidenceId}.meta.json`),
|
|
926
|
+
JSON.stringify({
|
|
927
|
+
id: evidenceId,
|
|
928
|
+
metadata: {
|
|
929
|
+
kind: "uat_exec",
|
|
930
|
+
milestoneId: "M001",
|
|
931
|
+
sliceId: "S01",
|
|
932
|
+
checkId: "UAT-01",
|
|
933
|
+
intent: "uat-artifact-check",
|
|
934
|
+
},
|
|
935
|
+
}),
|
|
936
|
+
"utf-8",
|
|
937
|
+
);
|
|
938
|
+
|
|
939
|
+
const result = await inProjectDir(worktree, () => executeUatResultSave({
|
|
940
|
+
milestoneId: "M001",
|
|
941
|
+
sliceId: "S01",
|
|
942
|
+
uatType: "artifact-driven",
|
|
943
|
+
verdict: "PASS",
|
|
944
|
+
checks: [
|
|
945
|
+
{
|
|
946
|
+
id: "UAT-01",
|
|
947
|
+
description: "Static contract passes",
|
|
948
|
+
mode: "artifact",
|
|
949
|
+
result: "PASS",
|
|
950
|
+
evidence: [{ kind: "gsd_uat_exec", ref: evidenceId }],
|
|
951
|
+
notes: "Artifact check passed.",
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
id: "UAT-02",
|
|
955
|
+
description: "Browser polish is deferred to the next slice",
|
|
956
|
+
mode: "human-follow-up",
|
|
957
|
+
result: "NEEDS-HUMAN",
|
|
958
|
+
notes: "Out of scope for this artifact-driven UAT.",
|
|
959
|
+
nonAutomatable: true,
|
|
960
|
+
},
|
|
961
|
+
],
|
|
962
|
+
presentation: {
|
|
963
|
+
surface: "mcp",
|
|
964
|
+
presentedTools: [
|
|
965
|
+
"gsd_uat_exec",
|
|
966
|
+
"gsd_uat_result_save",
|
|
967
|
+
"gsd_resume",
|
|
968
|
+
"gsd_milestone_status",
|
|
969
|
+
"gsd_journal_query",
|
|
970
|
+
],
|
|
971
|
+
blockedTools: [
|
|
972
|
+
{ name: "gsd_exec", reason: "forbidden during run-uat" },
|
|
973
|
+
{ name: "gsd_summary_save", reason: "forbidden during run-uat" },
|
|
974
|
+
{ name: "gsd_save_gate_result", reason: "forbidden during run-uat" },
|
|
975
|
+
],
|
|
976
|
+
},
|
|
977
|
+
notes: "UAT passed; non-automatable browser polish is deferred.",
|
|
978
|
+
}, worktree));
|
|
979
|
+
|
|
980
|
+
assert.equal(result.isError, true);
|
|
981
|
+
assert.match(String(result.content[0]?.text), /artifact-driven UAT cannot PASS with human-only checks/);
|
|
982
|
+
} finally {
|
|
983
|
+
closeDatabase();
|
|
984
|
+
cleanup(base);
|
|
985
|
+
}
|
|
986
|
+
});
|
|
987
|
+
|
|
590
988
|
test("executeSliceComplete coerces string enrichment entries and writes summary/UAT artifacts", async () => {
|
|
591
989
|
const base = makeTmpBase();
|
|
592
990
|
try {
|
|
@@ -1279,6 +1677,10 @@ test("executeSummarySave blocks final root artifacts while approval gate is pend
|
|
|
1279
1677
|
|
|
1280
1678
|
assert.equal(result.isError, true);
|
|
1281
1679
|
assert.equal(result.details.error, "root_artifact_write_blocked");
|
|
1680
|
+
assert.equal(
|
|
1681
|
+
result.details.displayReason,
|
|
1682
|
+
"Approval confirmation required before saving final project setup artifacts.",
|
|
1683
|
+
);
|
|
1282
1684
|
assert.match(result.content[0].text, /has not been confirmed/);
|
|
1283
1685
|
assert.equal(existsSync(join(base, ".gsd", "REQUIREMENTS.md")), false);
|
|
1284
1686
|
|
|
@@ -1321,6 +1723,10 @@ test("executeSummarySave requires verified root approval in deep mode", async ()
|
|
|
1321
1723
|
|
|
1322
1724
|
assert.equal(blocked.isError, true);
|
|
1323
1725
|
assert.equal(blocked.details.error, "root_artifact_write_blocked");
|
|
1726
|
+
assert.equal(
|
|
1727
|
+
blocked.details.displayReason,
|
|
1728
|
+
"Approval confirmation required before saving final project setup artifacts.",
|
|
1729
|
+
);
|
|
1324
1730
|
assert.match(blocked.content[0].text, /fail-closed/);
|
|
1325
1731
|
assert.equal(existsSync(join(base, ".gsd", "PROJECT.md")), false);
|
|
1326
1732
|
|
|
@@ -1537,6 +1943,10 @@ test("executeSummarySave CONTEXT HARD BLOCK clears after write-gate state file i
|
|
|
1537
1943
|
content: "# Context\n\ncontent",
|
|
1538
1944
|
}, base));
|
|
1539
1945
|
assert.equal(blocked.isError, true, "should be blocked without depth verification");
|
|
1946
|
+
assert.equal(
|
|
1947
|
+
blocked.details.displayReason,
|
|
1948
|
+
"Depth check required before writing milestone context.",
|
|
1949
|
+
);
|
|
1540
1950
|
assert.match(
|
|
1541
1951
|
blocked.content[0].text,
|
|
1542
1952
|
/HARD BLOCK/,
|
|
@@ -9,6 +9,7 @@ import test from 'node:test';
|
|
|
9
9
|
import assert from 'node:assert/strict';
|
|
10
10
|
import { join, sep } from 'node:path';
|
|
11
11
|
|
|
12
|
+
import { GSD_PHASE_SCOPE_DISPLAY_REASON } from '../auto-unit-tool-scope.ts';
|
|
12
13
|
import { ALLOWED_PLANNING_DISPATCH_AGENTS, shouldBlockPlanningUnit } from '../bootstrap/write-gate.ts';
|
|
13
14
|
import { extractSubagentAgentClasses } from '../bootstrap/subagent-input.ts';
|
|
14
15
|
import { isDeterministicPolicyError } from '../auto-tool-tracking.ts';
|
|
@@ -65,6 +66,19 @@ test('planning-unit: deterministic block reason is suitable for retry short-circ
|
|
|
65
66
|
assert.strictEqual(isDeterministicPolicyError(r.reason!), true);
|
|
66
67
|
});
|
|
67
68
|
|
|
69
|
+
test('planning-unit: blocked tool-policy calls include UI-safe display reason', () => {
|
|
70
|
+
const r = shouldBlockPlanningUnit(
|
|
71
|
+
'edit',
|
|
72
|
+
'src/main.ts',
|
|
73
|
+
BASE,
|
|
74
|
+
'discuss-milestone',
|
|
75
|
+
PLANNING,
|
|
76
|
+
);
|
|
77
|
+
assert.strictEqual(r.block, true);
|
|
78
|
+
assert.match(r.reason!, /HARD BLOCK/);
|
|
79
|
+
assert.strictEqual(r.displayReason, GSD_PHASE_SCOPE_DISPLAY_REASON);
|
|
80
|
+
});
|
|
81
|
+
|
|
68
82
|
test('planning-unit: blocks write to user source via relative path', () => {
|
|
69
83
|
const r = shouldBlockPlanningUnit('write', 'src/main.ts', BASE, 'plan-milestone', PLANNING);
|
|
70
84
|
assert.strictEqual(r.block, true);
|
|
@@ -367,6 +381,7 @@ test('auto-unit scope: execute-task allows only its task completion lifecycle to
|
|
|
367
381
|
assert.strictEqual(blocked.block, true);
|
|
368
382
|
assert.match(blocked.reason!, /HARD BLOCK/);
|
|
369
383
|
assert.match(blocked.reason!, /gsd_save_gate_result/);
|
|
384
|
+
assert.strictEqual(blocked.displayReason, GSD_PHASE_SCOPE_DISPLAY_REASON);
|
|
370
385
|
assert.strictEqual(isDeterministicPolicyError(blocked.reason!), true);
|
|
371
386
|
});
|
|
372
387
|
|
|
@@ -8,12 +8,14 @@ import {
|
|
|
8
8
|
type ToolsPolicy,
|
|
9
9
|
} from "./unit-context-manifest.js";
|
|
10
10
|
import { getRequiredWorkflowToolsForAutoUnit } from "./workflow-mcp.js";
|
|
11
|
+
import { getUnitToolSurfaceContract } from "./unit-tool-contracts.js";
|
|
11
12
|
|
|
12
13
|
export interface UnitToolContract {
|
|
13
14
|
unitType: string;
|
|
14
15
|
contextMode: ContextModePolicy;
|
|
15
16
|
toolsPolicy: ToolsPolicy;
|
|
16
17
|
requiredWorkflowTools: readonly string[];
|
|
18
|
+
forbiddenWorkflowTools: readonly { name: string; reason: string }[];
|
|
17
19
|
promptObligations: readonly string[];
|
|
18
20
|
validationRules: readonly string[];
|
|
19
21
|
closeoutTools: readonly string[];
|
|
@@ -30,6 +32,7 @@ export type ToolContractResult =
|
|
|
30
32
|
|
|
31
33
|
export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
32
34
|
const manifest = resolveManifest(unitType);
|
|
35
|
+
const surfaceContract = getUnitToolSurfaceContract(unitType);
|
|
33
36
|
if (!manifest) {
|
|
34
37
|
return {
|
|
35
38
|
ok: false,
|
|
@@ -39,6 +42,8 @@ export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
const requiredWorkflowTools = getRequiredWorkflowToolsForAutoUnit(unitType);
|
|
45
|
+
const forbiddenWorkflowTools = Object.entries(surfaceContract?.forbiddenGsdTools ?? {})
|
|
46
|
+
.map(([name, reason]) => ({ name, reason }));
|
|
42
47
|
const closeoutTools = requiredWorkflowTools.filter((tool) =>
|
|
43
48
|
/^gsd_(?:task|slice|milestone|complete|validate|save|summary)/.test(tool),
|
|
44
49
|
);
|
|
@@ -58,6 +63,7 @@ export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
|
58
63
|
contextMode: manifest.contextMode,
|
|
59
64
|
toolsPolicy: manifest.tools,
|
|
60
65
|
requiredWorkflowTools,
|
|
66
|
+
forbiddenWorkflowTools,
|
|
61
67
|
promptObligations: [
|
|
62
68
|
`context-mode:${manifest.contextMode}`,
|
|
63
69
|
`tools-policy:${manifest.tools.mode}`,
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Resolve phase-aware tool surfaces for GSD model presentations.
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
RUN_UAT_BROWSER_TOOL_NAMES,
|
|
6
|
+
RUN_UAT_READ_ONLY_TOOL_NAMES,
|
|
7
|
+
RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
|
|
8
|
+
RUN_UAT_WORKFLOW_TOOL_NAMES,
|
|
9
|
+
} from "./unit-tool-contracts.js";
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
RUN_UAT_BROWSER_TOOL_NAMES,
|
|
13
|
+
RUN_UAT_READ_ONLY_TOOL_NAMES,
|
|
14
|
+
RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
|
|
15
|
+
RUN_UAT_WORKFLOW_TOOL_NAMES,
|
|
16
|
+
} from "./unit-tool-contracts.js";
|
|
17
|
+
|
|
4
18
|
export type ToolPresentationSurface = "provider-tools" | "claude-code-sdk" | "mcp" | "hybrid";
|
|
5
19
|
|
|
6
20
|
export interface ToolPresentationModel {
|
|
@@ -20,13 +34,12 @@ export interface ToolPresentationPlan {
|
|
|
20
34
|
diagnostics: string[];
|
|
21
35
|
}
|
|
22
36
|
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
] as const;
|
|
37
|
+
export interface RunUatResultPresentation {
|
|
38
|
+
surface: ToolPresentationSurface;
|
|
39
|
+
presentedTools: string[];
|
|
40
|
+
blockedTools: Array<{ name: string; reason: string }>;
|
|
41
|
+
toolPresentationPlanId: string;
|
|
42
|
+
}
|
|
30
43
|
|
|
31
44
|
export const RUN_UAT_FORBIDDEN_TOOL_NAMES = [
|
|
32
45
|
"edit",
|
|
@@ -105,10 +118,53 @@ function addBlockedTool(
|
|
|
105
118
|
export function buildRunUatCanonicalToolNames(options: { includeBrowserTools?: readonly string[] } = {}): string[] {
|
|
106
119
|
return dedupe([
|
|
107
120
|
...RUN_UAT_WORKFLOW_TOOL_NAMES,
|
|
121
|
+
...RUN_UAT_READ_ONLY_TOOL_NAMES,
|
|
108
122
|
...(options.includeBrowserTools ?? []),
|
|
109
123
|
]);
|
|
110
124
|
}
|
|
111
125
|
|
|
126
|
+
export function runUatBrowserToolsForType(uatType: string | undefined): readonly string[] {
|
|
127
|
+
return uatType === "browser-executable" ? RUN_UAT_BROWSER_TOOL_NAMES : [];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function runUatPresentationSurfaceForType(uatType: string | undefined): ToolPresentationSurface {
|
|
131
|
+
return uatType === "browser-executable" ? "hybrid" : "mcp";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function buildRunUatPresentationForType(
|
|
135
|
+
uatType: string | undefined,
|
|
136
|
+
options: {
|
|
137
|
+
surface?: ToolPresentationSurface;
|
|
138
|
+
presentedTools?: readonly string[];
|
|
139
|
+
} = {},
|
|
140
|
+
): RunUatResultPresentation {
|
|
141
|
+
return buildRunUatResultPresentation({
|
|
142
|
+
...options,
|
|
143
|
+
surface: options.surface ?? runUatPresentationSurfaceForType(uatType),
|
|
144
|
+
includeBrowserTools: runUatBrowserToolsForType(uatType),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function buildRunUatResultPresentation(options: {
|
|
149
|
+
surface?: ToolPresentationSurface;
|
|
150
|
+
includeBrowserTools?: readonly string[];
|
|
151
|
+
presentedTools?: readonly string[];
|
|
152
|
+
} = {}): RunUatResultPresentation {
|
|
153
|
+
const presentedTools = options.presentedTools
|
|
154
|
+
? dedupe(options.presentedTools)
|
|
155
|
+
: buildRunUatCanonicalToolNames({ includeBrowserTools: options.includeBrowserTools });
|
|
156
|
+
const blockedTools = RUN_UAT_FORBIDDEN_TOOL_NAMES
|
|
157
|
+
.filter((toolName) => !toolName.includes("*"))
|
|
158
|
+
.map((name) => ({ name, reason: "forbidden during run-uat" }));
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
surface: options.surface ?? "mcp",
|
|
162
|
+
presentedTools,
|
|
163
|
+
blockedTools,
|
|
164
|
+
toolPresentationPlanId: RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
112
168
|
export function resolveToolPresentationPlan(options: {
|
|
113
169
|
phase: string;
|
|
114
170
|
surface: ToolPresentationSurface;
|
|
@@ -217,7 +217,7 @@ ${params.narrative}
|
|
|
217
217
|
|
|
218
218
|
## Verification
|
|
219
219
|
|
|
220
|
-
${params.verification}
|
|
220
|
+
${params.verification ?? ""}
|
|
221
221
|
|
|
222
222
|
## Requirements Advanced
|
|
223
223
|
|
|
@@ -440,6 +440,19 @@ export async function handleCompleteSlice(
|
|
|
440
440
|
const parsed = parseRequirementSection(existingSummaryMd, "Requirements Invalidated or Re-scoped", "what");
|
|
441
441
|
if (parsed.length > 0) effectiveParams.requirementsInvalidated = parsed as Array<{ id: string; what: string }>;
|
|
442
442
|
}
|
|
443
|
+
if (effectiveParams.verification === undefined) {
|
|
444
|
+
const headingLine = "## Verification\n\n";
|
|
445
|
+
const start = existingSummaryMd.indexOf(headingLine);
|
|
446
|
+
if (start !== -1) {
|
|
447
|
+
const contentStart = start + headingLine.length;
|
|
448
|
+
const nextHeading = existingSummaryMd.indexOf("\n\n## ", contentStart);
|
|
449
|
+
const prior = nextHeading === -1
|
|
450
|
+
? existingSummaryMd.slice(contentStart)
|
|
451
|
+
: existingSummaryMd.slice(contentStart, nextHeading);
|
|
452
|
+
const trimmed = prior.trim();
|
|
453
|
+
if (trimmed) effectiveParams.verification = trimmed;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
443
456
|
}
|
|
444
457
|
|
|
445
458
|
// Render summary markdown
|