@opengsd/gsd-pi 1.1.1-dev.74e8dd1 → 1.1.1-dev.a5a2de8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -2
- package/dist/help-text.js +10 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
- package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
- package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/dist/resources/extensions/browser-tools/index.js +57 -9
- package/dist/resources/extensions/browser-tools/package.json +5 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
- package/dist/resources/extensions/gsd/auto-dashboard.js +77 -13
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +21 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +63 -22
- package/dist/resources/extensions/gsd/auto-recovery.js +3 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +18 -66
- package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
- package/dist/resources/extensions/gsd/auto.js +9 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +20 -14
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +28 -13
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +18 -29
- package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
- package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
- package/dist/resources/extensions/gsd/escalation.js +4 -4
- package/dist/resources/extensions/gsd/forensics.js +74 -2
- package/dist/resources/extensions/gsd/gsd-db.js +5 -2
- package/dist/resources/extensions/gsd/guided-flow.js +118 -175
- package/dist/resources/extensions/gsd/mcp-project-config.js +9 -76
- package/dist/resources/extensions/gsd/memory-store.js +4 -1
- package/dist/resources/extensions/gsd/milestone-closeout.js +3 -1
- package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +25 -21
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/dist/resources/extensions/gsd/recovery-classification.js +20 -0
- package/dist/resources/extensions/gsd/rule-registry.js +428 -52
- package/dist/resources/extensions/gsd/state.js +2 -2
- package/dist/resources/extensions/gsd/templates/plan.md +3 -1
- package/dist/resources/extensions/gsd/tool-contract.js +5 -0
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +17 -7
- package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +132 -18
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
- package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
- package/dist/resources/extensions/gsd/verification-gate.js +72 -1
- package/dist/resources/extensions/gsd/workflow-mcp.js +3 -75
- package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
- package/dist/rtk.d.ts +7 -1
- package/dist/rtk.js +27 -11
- package/dist/update-check.d.ts +15 -1
- package/dist/update-check.js +87 -12
- package/dist/update-cmd.d.ts +1 -0
- package/dist/update-cmd.js +53 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +4 -2
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +32 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/index.d.ts +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +1 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
- package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
- package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
- package/packages/gsd-agent-core/package.json +6 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +20 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
- package/packages/mcp-server/dist/remote-questions.js +23 -9
- package/packages/mcp-server/dist/remote-questions.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +2 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +42 -3
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +6 -1
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/api-registry.d.ts +2 -0
- package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
- package/packages/pi-ai/dist/api-registry.js +23 -0
- package/packages/pi-ai/dist/api-registry.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +74 -6
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +78 -10
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/stream.js +6 -6
- package/packages/pi-ai/dist/stream.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
- package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
- package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
- package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/src/resources/extensions/browser-tools/index.ts +60 -9
- package/src/resources/extensions/browser-tools/package.json +5 -1
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
- package/src/resources/extensions/gsd/auto-dashboard.ts +82 -14
- package/src/resources/extensions/gsd/auto-dispatch.ts +19 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +28 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +97 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +3 -3
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -74
- package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
- package/src/resources/extensions/gsd/auto.ts +12 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +20 -14
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +32 -13
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +50 -54
- package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
- package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
- package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
- package/src/resources/extensions/gsd/escalation.ts +4 -4
- package/src/resources/extensions/gsd/forensics.ts +99 -5
- package/src/resources/extensions/gsd/gsd-db.ts +5 -2
- package/src/resources/extensions/gsd/guided-flow.ts +214 -216
- package/src/resources/extensions/gsd/mcp-project-config.ts +13 -78
- package/src/resources/extensions/gsd/memory-store.ts +4 -1
- package/src/resources/extensions/gsd/milestone-closeout.ts +3 -1
- package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +25 -21
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/src/resources/extensions/gsd/recovery-classification.ts +20 -0
- package/src/resources/extensions/gsd/rule-registry.ts +558 -58
- package/src/resources/extensions/gsd/rule-types.ts +2 -0
- package/src/resources/extensions/gsd/state.ts +2 -2
- package/src/resources/extensions/gsd/templates/plan.md +3 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +105 -4
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +10 -2
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
- package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
- package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
- package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +31 -79
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +69 -10
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -0
- package/src/resources/extensions/gsd/tool-contract.ts +6 -0
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +38 -8
- package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +163 -20
- package/src/resources/extensions/gsd/types.ts +69 -5
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +186 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
- package/src/resources/extensions/gsd/verification-gate.ts +87 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -75
- package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
- /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → 9y3LeeR2uGr2yRj9RjY3D}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → 9y3LeeR2uGr2yRj9RjY3D}/_ssgManifest.js +0 -0
|
@@ -298,6 +298,106 @@ test("session_start installs the welcome screen as the TUI header", async (t) =>
|
|
|
298
298
|
assert.deepEqual(header.render(123), ["welcome 9.9.9-test none 123"]);
|
|
299
299
|
});
|
|
300
300
|
|
|
301
|
+
test("session hooks preserve closeout-boundary UI during completion reroot", async (t) => {
|
|
302
|
+
const dir = join(
|
|
303
|
+
tmpdir(),
|
|
304
|
+
`gsd-closeout-session-hooks-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
305
|
+
);
|
|
306
|
+
mkdirSync(join(dir, ".gsd"), { recursive: true });
|
|
307
|
+
mkdirSync(join(dir, "dist"), { recursive: true });
|
|
308
|
+
const tempGsdHome = join(dir, "home");
|
|
309
|
+
mkdirSync(tempGsdHome, { recursive: true });
|
|
310
|
+
writeFileSync(
|
|
311
|
+
join(dir, "dist", "welcome-screen.js"),
|
|
312
|
+
"export function buildWelcomeScreenLines() { return ['welcome header']; }\n",
|
|
313
|
+
"utf-8",
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
const originalCwd = process.cwd();
|
|
317
|
+
const originalGsdHome = process.env.GSD_HOME;
|
|
318
|
+
const originalGsdPkgRoot = process.env.GSD_PKG_ROOT;
|
|
319
|
+
process.chdir(dir);
|
|
320
|
+
process.env.GSD_HOME = tempGsdHome;
|
|
321
|
+
process.env.GSD_PKG_ROOT = dir;
|
|
322
|
+
autoSession.reset();
|
|
323
|
+
autoSession.completionStopInProgress = true;
|
|
324
|
+
t.after(() => {
|
|
325
|
+
autoSession.reset();
|
|
326
|
+
process.chdir(originalCwd);
|
|
327
|
+
if (originalGsdHome === undefined) delete process.env.GSD_HOME;
|
|
328
|
+
else process.env.GSD_HOME = originalGsdHome;
|
|
329
|
+
if (originalGsdPkgRoot === undefined) delete process.env.GSD_PKG_ROOT;
|
|
330
|
+
else process.env.GSD_PKG_ROOT = originalGsdPkgRoot;
|
|
331
|
+
try { rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ }
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
|
|
335
|
+
const pi = {
|
|
336
|
+
on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
|
|
337
|
+
handlers.set(event, handler);
|
|
338
|
+
},
|
|
339
|
+
} as any;
|
|
340
|
+
|
|
341
|
+
registerHooks(pi, []);
|
|
342
|
+
|
|
343
|
+
const sessionStart = handlers.get("session_start");
|
|
344
|
+
const sessionSwitch = handlers.get("session_switch");
|
|
345
|
+
assert.ok(sessionStart, "session_start handler must be registered");
|
|
346
|
+
assert.ok(sessionSwitch, "session_switch handler must be registered");
|
|
347
|
+
|
|
348
|
+
const widgetCalls: Array<{ key: string; value: unknown }> = [];
|
|
349
|
+
let headerInstallCount = 0;
|
|
350
|
+
const ctx = {
|
|
351
|
+
hasUI: true,
|
|
352
|
+
ui: {
|
|
353
|
+
notify: () => {},
|
|
354
|
+
setStatus: () => {},
|
|
355
|
+
setFooter: () => {},
|
|
356
|
+
setHeader: () => {
|
|
357
|
+
headerInstallCount++;
|
|
358
|
+
},
|
|
359
|
+
setWorkingMessage: () => {},
|
|
360
|
+
onTerminalInput: () => () => {},
|
|
361
|
+
setWidget: (key: string, value: unknown) => {
|
|
362
|
+
widgetCalls.push({ key, value });
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
sessionManager: { getSessionId: () => null },
|
|
366
|
+
model: null,
|
|
367
|
+
setCompactionThresholdOverride: () => {},
|
|
368
|
+
modelRegistry: {
|
|
369
|
+
setDisabledModelProviders: () => {},
|
|
370
|
+
getProviderAuthMode: () => undefined,
|
|
371
|
+
isProviderRequestReady: () => false,
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
await sessionStart!({}, ctx);
|
|
376
|
+
assert.equal(
|
|
377
|
+
headerInstallCount,
|
|
378
|
+
0,
|
|
379
|
+
"completion reroot session_start must not reinstall the welcome/project-console header",
|
|
380
|
+
);
|
|
381
|
+
assert.ok(
|
|
382
|
+
widgetCalls.some((call) => call.key === "gsd-health" && call.value === undefined),
|
|
383
|
+
"completion reroot session_start should hide the ambient health widget",
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
widgetCalls.length = 0;
|
|
387
|
+
await sessionSwitch!({ reason: "reroot" }, ctx);
|
|
388
|
+
assert.deepEqual(
|
|
389
|
+
widgetCalls
|
|
390
|
+
.filter((call) => call.key === "gsd-progress" || call.key === "gsd-outcome")
|
|
391
|
+
.map((call) => [call.key, call.value]),
|
|
392
|
+
[],
|
|
393
|
+
"completion reroot session_switch must not clear the preserved closeout surface",
|
|
394
|
+
);
|
|
395
|
+
assert.ok(
|
|
396
|
+
widgetCalls.some((call) => call.key === "gsd-health" && call.value === undefined),
|
|
397
|
+
"completion reroot session_switch should keep the ambient health widget hidden",
|
|
398
|
+
);
|
|
399
|
+
});
|
|
400
|
+
|
|
301
401
|
test("session_start and session_switch apply disabled model provider policy from current preferences", async (t) => {
|
|
302
402
|
const dir = join(
|
|
303
403
|
tmpdir(),
|
|
@@ -1352,6 +1352,145 @@ test("ADR-017: orphan task completion artifact fails closed", async (t) => {
|
|
|
1352
1352
|
assert.match(result.blockers.join("\n"), /Artifact\/DB status drift/);
|
|
1353
1353
|
});
|
|
1354
1354
|
|
|
1355
|
+
test("ADR-017 (#414): failure-path summary artifact blocker matches auto.ts filter phrase", async (t) => {
|
|
1356
|
+
// When gsd_summary_save writes a SUMMARY artifact row for a task that never
|
|
1357
|
+
// called gsd_task_complete, the task stays pending and the artifact DB row
|
|
1358
|
+
// produces an artifact-db-status-divergence blocker. The auto.ts dispatch
|
|
1359
|
+
// wrapper must be able to filter this class of blocker to allow re-dispatch.
|
|
1360
|
+
// If this test fails, update the filter strings in auto.ts to match.
|
|
1361
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-failure-path-summary-drift-"));
|
|
1362
|
+
t.after(() => cleanup(base));
|
|
1363
|
+
|
|
1364
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S04"), { recursive: true });
|
|
1365
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1366
|
+
insertMilestone({ id: "M001", title: "Milestone", status: "active" });
|
|
1367
|
+
insertSlice({ id: "S04", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
1368
|
+
insertTask({ id: "T01", sliceId: "S04", milestoneId: "M001", title: "Task", status: "pending" });
|
|
1369
|
+
insertArtifact({
|
|
1370
|
+
path: join(base, ".gsd", "milestones", "M001", "slices", "S04", "tasks", "T01", "T01-SUMMARY.md"),
|
|
1371
|
+
artifact_type: "SUMMARY",
|
|
1372
|
+
milestone_id: "M001",
|
|
1373
|
+
slice_id: "S04",
|
|
1374
|
+
task_id: "T01",
|
|
1375
|
+
full_content: "# T01 Failure Summary\n",
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
const result = await reconcileBeforeDispatch(base, {
|
|
1379
|
+
invalidateStateCache: () => {},
|
|
1380
|
+
deriveState: async () => makeState({ activeMilestone: { id: "M001", title: "Milestone" } }),
|
|
1381
|
+
});
|
|
1382
|
+
|
|
1383
|
+
assert.equal(result.ok, true);
|
|
1384
|
+
assert.ok(result.blockers.length > 0, "blocker must be produced for pending-task SUMMARY drift");
|
|
1385
|
+
const blocker = result.blockers.join("\n");
|
|
1386
|
+
assert.match(
|
|
1387
|
+
blocker,
|
|
1388
|
+
/has SUMMARY artifact while DB status is/,
|
|
1389
|
+
"blocker phrase must match the filter in auto.ts reconcileBeforeDispatch wrapper",
|
|
1390
|
+
);
|
|
1391
|
+
});
|
|
1392
|
+
|
|
1393
|
+
test("ADR-017 (#414): no-db-tasks summary artifact blocker matches auto.ts filter phrase", async (t) => {
|
|
1394
|
+
// When a slice has SUMMARY artifacts in the DB but no DB tasks, the auto.ts
|
|
1395
|
+
// filter must be able to recognise this as a failure-path case and skip it.
|
|
1396
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-no-db-tasks-summary-drift-"));
|
|
1397
|
+
t.after(() => cleanup(base));
|
|
1398
|
+
|
|
1399
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S04"), { recursive: true });
|
|
1400
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1401
|
+
insertMilestone({ id: "M001", title: "Milestone", status: "active" });
|
|
1402
|
+
insertSlice({ id: "S04", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
1403
|
+
// No tasks inserted — slice has SUMMARY artifacts for a task that no longer exists.
|
|
1404
|
+
insertArtifact({
|
|
1405
|
+
path: join(base, ".gsd", "milestones", "M001", "slices", "S04", "tasks", "T01", "T01-SUMMARY.md"),
|
|
1406
|
+
artifact_type: "SUMMARY",
|
|
1407
|
+
milestone_id: "M001",
|
|
1408
|
+
slice_id: "S04",
|
|
1409
|
+
task_id: "T01",
|
|
1410
|
+
full_content: "# T01 Failure Summary\n",
|
|
1411
|
+
});
|
|
1412
|
+
|
|
1413
|
+
const result = await reconcileBeforeDispatch(base, {
|
|
1414
|
+
invalidateStateCache: () => {},
|
|
1415
|
+
deriveState: async () => makeState({ activeMilestone: { id: "M001", title: "Milestone" } }),
|
|
1416
|
+
});
|
|
1417
|
+
|
|
1418
|
+
assert.equal(result.ok, true);
|
|
1419
|
+
assert.ok(result.blockers.length > 0, "blocker must be produced for no-db-tasks SUMMARY drift");
|
|
1420
|
+
const blocker = result.blockers.join("\n");
|
|
1421
|
+
assert.match(
|
|
1422
|
+
blocker,
|
|
1423
|
+
/has task SUMMARY artifacts but no DB tasks/,
|
|
1424
|
+
"blocker phrase must match the filter in auto.ts reconcileBeforeDispatch wrapper",
|
|
1425
|
+
);
|
|
1426
|
+
});
|
|
1427
|
+
|
|
1428
|
+
test("ADR-017 (#414): task-level on-disk summary blocker matches auto.ts filter phrase", async (t) => {
|
|
1429
|
+
// When gsd_summary_save writes a SUMMARY file to disk for a task that never
|
|
1430
|
+
// called gsd_task_complete, but the artifact DB row was not yet written (or
|
|
1431
|
+
// the process crashed before insertion), reconciliation emits
|
|
1432
|
+
// "has SUMMARY on disk while DB status is". The auto.ts filter must match
|
|
1433
|
+
// this phrase so re-dispatch is not blocked.
|
|
1434
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-task-disk-summary-drift-"));
|
|
1435
|
+
t.after(() => cleanup(base));
|
|
1436
|
+
|
|
1437
|
+
const tasksDir = join(base, ".gsd", "milestones", "M001", "slices", "S04", "tasks");
|
|
1438
|
+
mkdirSync(tasksDir, { recursive: true });
|
|
1439
|
+
writeFileSync(join(tasksDir, "T01-SUMMARY.md"), "# T01 Failure Summary\n");
|
|
1440
|
+
|
|
1441
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1442
|
+
insertMilestone({ id: "M001", title: "Milestone", status: "active" });
|
|
1443
|
+
insertSlice({ id: "S04", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
1444
|
+
insertTask({ id: "T01", sliceId: "S04", milestoneId: "M001", title: "Task", status: "pending" });
|
|
1445
|
+
// No artifact row inserted — SUMMARY exists only on disk.
|
|
1446
|
+
|
|
1447
|
+
const result = await reconcileBeforeDispatch(base, {
|
|
1448
|
+
invalidateStateCache: () => {},
|
|
1449
|
+
deriveState: async () => makeState({ activeMilestone: { id: "M001", title: "Milestone" } }),
|
|
1450
|
+
});
|
|
1451
|
+
|
|
1452
|
+
assert.equal(result.ok, true);
|
|
1453
|
+
assert.ok(result.blockers.length > 0, "blocker must be produced for on-disk task SUMMARY drift");
|
|
1454
|
+
const blocker = result.blockers.join("\n");
|
|
1455
|
+
assert.match(
|
|
1456
|
+
blocker,
|
|
1457
|
+
/has SUMMARY on disk while DB status is/,
|
|
1458
|
+
"blocker phrase must match the filter in auto.ts reconcileBeforeDispatch wrapper",
|
|
1459
|
+
);
|
|
1460
|
+
});
|
|
1461
|
+
|
|
1462
|
+
test("ADR-017 (#414): slice-level on-disk summary blocker matches auto.ts filter phrase", async (t) => {
|
|
1463
|
+
// When a SUMMARY file exists on disk for a slice that is still pending
|
|
1464
|
+
// (no gsd_task_complete for the slice), reconciliation emits
|
|
1465
|
+
// "has SUMMARY on disk while DB status is". The auto.ts filter must match
|
|
1466
|
+
// this phrase so re-dispatch is not blocked.
|
|
1467
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-slice-disk-summary-drift-"));
|
|
1468
|
+
t.after(() => cleanup(base));
|
|
1469
|
+
|
|
1470
|
+
const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S04");
|
|
1471
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
1472
|
+
writeFileSync(join(sliceDir, "S04-SUMMARY.md"), "# S04 Failure Summary\n");
|
|
1473
|
+
|
|
1474
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1475
|
+
insertMilestone({ id: "M001", title: "Milestone", status: "active" });
|
|
1476
|
+
insertSlice({ id: "S04", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
1477
|
+
// No artifact row inserted — SUMMARY exists only on disk.
|
|
1478
|
+
|
|
1479
|
+
const result = await reconcileBeforeDispatch(base, {
|
|
1480
|
+
invalidateStateCache: () => {},
|
|
1481
|
+
deriveState: async () => makeState({ activeMilestone: { id: "M001", title: "Milestone" } }),
|
|
1482
|
+
});
|
|
1483
|
+
|
|
1484
|
+
assert.equal(result.ok, true);
|
|
1485
|
+
assert.ok(result.blockers.length > 0, "blocker must be produced for on-disk slice SUMMARY drift");
|
|
1486
|
+
const blocker = result.blockers.join("\n");
|
|
1487
|
+
assert.match(
|
|
1488
|
+
blocker,
|
|
1489
|
+
/has SUMMARY on disk while DB status is/,
|
|
1490
|
+
"blocker phrase must match the filter in auto.ts reconcileBeforeDispatch wrapper",
|
|
1491
|
+
);
|
|
1492
|
+
});
|
|
1493
|
+
|
|
1355
1494
|
test("ADR-017: completed milestone dispatch history blocks accidental re-planning", async (t) => {
|
|
1356
1495
|
const base = mkdtempSync(join(tmpdir(), "gsd-completed-reopened-drift-"));
|
|
1357
1496
|
t.after(() => cleanup(base));
|
|
@@ -101,7 +101,7 @@ test("buildMinimalAutoGsdToolSet keeps unit-specific completion tools without al
|
|
|
101
101
|
assert.ok(!result.includes("gsd_complete_slice"));
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
test("buildMinimalAutoGsdToolSet scopes run-uat to UAT-specific tools", () => {
|
|
104
|
+
test("buildMinimalAutoGsdToolSet scopes run-uat to UAT-specific and read-only tools", () => {
|
|
105
105
|
const active = ["ask_user_questions", "bash", "read", "edit", "write", "gsd_summary_save"];
|
|
106
106
|
const registered = [
|
|
107
107
|
...active,
|
|
@@ -123,11 +123,11 @@ test("buildMinimalAutoGsdToolSet scopes run-uat to UAT-specific tools", () => {
|
|
|
123
123
|
assert.ok(result.includes("gsd_resume"));
|
|
124
124
|
assert.ok(result.includes("gsd_milestone_status"));
|
|
125
125
|
assert.ok(result.includes("gsd_journal_query"));
|
|
126
|
+
assert.ok(result.includes("read"));
|
|
126
127
|
assert.ok(result.includes("browser_navigate"), "run-uat needs browser_navigate");
|
|
127
128
|
assert.ok(result.includes("browser_click"), "run-uat needs browser_click");
|
|
128
129
|
assert.ok(!result.includes("ToolSearch"));
|
|
129
130
|
assert.ok(!result.includes("bash"));
|
|
130
|
-
assert.ok(!result.includes("read"));
|
|
131
131
|
assert.ok(!result.includes("edit"));
|
|
132
132
|
assert.ok(!result.includes("write"));
|
|
133
133
|
assert.ok(!result.includes("gsd_exec"));
|
|
@@ -230,9 +230,9 @@ test("buildMinimalAutoGsdToolSet preserves compatible browser add-ons for run-ua
|
|
|
230
230
|
assert.ok(result.includes("gsd_uat_exec"));
|
|
231
231
|
assert.ok(result.includes("gsd_uat_result_save"));
|
|
232
232
|
assert.ok(result.includes("subagent"));
|
|
233
|
+
assert.ok(result.includes("read"));
|
|
233
234
|
assert.ok(!result.includes("ToolSearch"));
|
|
234
235
|
assert.ok(!result.includes("bash"));
|
|
235
|
-
assert.ok(!result.includes("read"));
|
|
236
236
|
assert.ok(!result.includes("edit"));
|
|
237
237
|
assert.ok(!result.includes("write"));
|
|
238
238
|
assert.ok(!result.includes("gsd_exec"));
|
|
@@ -281,12 +281,12 @@ test("buildMinimalAutoGsdToolSet honors provider-compatible registered tools for
|
|
|
281
281
|
|
|
282
282
|
assert.ok(result.includes("gsd_uat_exec"));
|
|
283
283
|
assert.ok(result.includes("gsd_uat_result_save"));
|
|
284
|
+
assert.ok(result.includes("read"));
|
|
284
285
|
assert.ok(result.includes("browser_navigate"));
|
|
285
286
|
assert.ok(result.includes("browser_click"));
|
|
286
287
|
assert.ok(!result.includes("browser_screenshot"), "provider-filtered screenshot tool must stay filtered");
|
|
287
288
|
assert.ok(!result.includes("ToolSearch"));
|
|
288
289
|
assert.ok(!result.includes("bash"));
|
|
289
|
-
assert.ok(!result.includes("read"));
|
|
290
290
|
assert.ok(!result.includes("gsd_exec"));
|
|
291
291
|
assert.ok(!result.includes("gsd_summary_save"));
|
|
292
292
|
assert.ok(!result.includes("gsd_save_gate_result"));
|
|
@@ -102,6 +102,25 @@ describe("#2883: isToolInvocationError classification", () => {
|
|
|
102
102
|
);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
+
test("detects MCP -32602 Input validation error (wire format)", () => {
|
|
106
|
+
assert.equal(
|
|
107
|
+
isToolInvocationError("MCP error -32602: Input validation error: Invalid arguments for tool gsd_slice_complete [path: verification, expected string, invalid_type]"),
|
|
108
|
+
true,
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("detects standalone 'Input validation error' prefix", () => {
|
|
113
|
+
assert.equal(isToolInvocationError("Input validation error: expected string"), true);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("detects 'Invalid arguments for tool' prefix", () => {
|
|
117
|
+
assert.equal(isToolInvocationError("Invalid arguments for tool gsd_slice_complete"), true);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("detects 'No such tool available' error", () => {
|
|
121
|
+
assert.equal(isToolInvocationError("No such tool available: mcp__gsd-workflow__memory_query"), true);
|
|
122
|
+
});
|
|
123
|
+
|
|
105
124
|
test("detects ESM export-link errors", () => {
|
|
106
125
|
assert.equal(
|
|
107
126
|
isToolInvocationError("The requested module '../paths.js' does not provide an export named 'gsdProjectionRoot'"),
|
|
@@ -101,13 +101,19 @@ test("gsd_slice_complete — enrichment arrays are optional", () => {
|
|
|
101
101
|
"sliceTitle",
|
|
102
102
|
"oneLiner",
|
|
103
103
|
"narrative",
|
|
104
|
-
"verification",
|
|
105
104
|
"uatContent",
|
|
106
105
|
];
|
|
107
106
|
for (const field of coreRequired) {
|
|
108
107
|
assert.ok(required.has(field), `core field "${field}" must be required`);
|
|
109
108
|
}
|
|
110
109
|
|
|
110
|
+
// verification is intentionally optional — models that omit it avoid -32602;
|
|
111
|
+
// the summary records verification as passed without detail in that case.
|
|
112
|
+
assert.ok(
|
|
113
|
+
!required.has("verification"),
|
|
114
|
+
"verification must be optional — omitting it avoids -32602; summary records verification as passed without detail",
|
|
115
|
+
);
|
|
116
|
+
|
|
111
117
|
// Enrichment/metadata arrays MUST be optional
|
|
112
118
|
const enrichmentFields = [
|
|
113
119
|
"keyFiles",
|
package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts
CHANGED
|
@@ -11,11 +11,14 @@ const prompt = readFileSync(promptPath, "utf-8");
|
|
|
11
11
|
|
|
12
12
|
test("validate-milestone reviewer C requires canonical verification class names", () => {
|
|
13
13
|
assert.match(prompt, /\*\*Reviewer C[\s\S]*Verification Classes/i);
|
|
14
|
-
assert.match(prompt, /
|
|
14
|
+
assert.match(prompt, /must be exactly `Contract`, `Integration`, `Operational`, or `UAT`/i);
|
|
15
|
+
assert.match(prompt, /Preserve every planned non-empty class row/i);
|
|
16
|
+
assert.match(prompt, /first cell of each row must be exactly `Contract`, `Integration`, `Operational`, or `UAT`/i);
|
|
15
17
|
assert.match(prompt, /If no verification classes were planned, say that explicitly/i);
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
test("validate-milestone prompt routes verification class analysis into verificationClasses", () => {
|
|
19
|
-
assert.match(prompt, /pass
|
|
20
|
-
assert.match(prompt, /
|
|
21
|
+
assert.match(prompt, /pass a complete canonical table in `verificationClasses`/i);
|
|
22
|
+
assert.match(prompt, /If Reviewer C omitted a planned class, reconstruct the missing row/i);
|
|
23
|
+
assert.match(prompt, /Do not call `gsd_validate_milestone` with a partial `verificationClasses` table/i);
|
|
21
24
|
});
|
|
@@ -180,6 +180,35 @@ describe("handleValidateMilestone write ordering (#2725)", () => {
|
|
|
180
180
|
assert.equal(row, undefined, "assessment row should not be written when verification classes are invalid");
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
+
it("reports all missing planned verification class rows at once", async () => {
|
|
184
|
+
base = makeTmpBase();
|
|
185
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
186
|
+
openDatabase(dbPath);
|
|
187
|
+
insertMilestone({
|
|
188
|
+
id: "M001",
|
|
189
|
+
planning: {
|
|
190
|
+
verificationContract: "Contract command exits 0",
|
|
191
|
+
verificationOperational: "Process lifecycle proof",
|
|
192
|
+
verificationUat: "Browser-observable UAT proof",
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
insertSlice({ id: "S01", milestoneId: "M001" });
|
|
196
|
+
|
|
197
|
+
const result = await handleValidateMilestone(
|
|
198
|
+
{ ...VALID_PARAMS, verificationClasses: "| Check | Result |\n| --- | --- |\n| Generic verification | PASS |" },
|
|
199
|
+
base,
|
|
200
|
+
);
|
|
201
|
+
assert.ok("error" in result, "expected validation to fail");
|
|
202
|
+
assert.match(result.error, /canonical rows "Contract", "Operational", "UAT"/);
|
|
203
|
+
assert.match(result.error, /planned contract, operational, uat verification/);
|
|
204
|
+
|
|
205
|
+
const adapter = _getAdapter()!;
|
|
206
|
+
const row = adapter.prepare(
|
|
207
|
+
`SELECT status FROM assessments WHERE milestone_id = 'M001' AND scope = 'milestone-validation'`,
|
|
208
|
+
).get() as { status: string } | undefined;
|
|
209
|
+
assert.equal(row, undefined, "assessment row should not be written when verification classes are invalid");
|
|
210
|
+
});
|
|
211
|
+
|
|
183
212
|
it("accepts verificationClasses when planned Operational class is present", async () => {
|
|
184
213
|
base = makeTmpBase();
|
|
185
214
|
const dbPath = join(base, ".gsd", "gsd.db");
|
|
@@ -406,6 +435,110 @@ describe("handleValidateMilestone write ordering (#2725)", () => {
|
|
|
406
435
|
assert.equal(result.verdict, "pass");
|
|
407
436
|
});
|
|
408
437
|
|
|
438
|
+
it("keeps pass when browser-like criteria are verified by runtime-executable UAT", async () => {
|
|
439
|
+
base = makeTmpBase();
|
|
440
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
441
|
+
openDatabase(dbPath);
|
|
442
|
+
insertMilestone({
|
|
443
|
+
id: "M001",
|
|
444
|
+
planning: {
|
|
445
|
+
successCriteria: [
|
|
446
|
+
"Clicking Mark All Complete sets all todos completed",
|
|
447
|
+
"Reload keeps completed state",
|
|
448
|
+
],
|
|
449
|
+
verificationUat: "Run the Node.js DOM-state script against the static app source.",
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
insertSlice({
|
|
453
|
+
id: "S01",
|
|
454
|
+
milestoneId: "M001",
|
|
455
|
+
// Uses localhost so hasBrowserRequiredText returns true and the gate is
|
|
456
|
+
// actually triggered before the runtime evidence bypasses it.
|
|
457
|
+
demo: "Visit localhost:3000 to verify DOM state after clicking Mark All Complete.",
|
|
458
|
+
});
|
|
459
|
+
const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
460
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
461
|
+
writeFileSync(
|
|
462
|
+
join(sliceDir, "S01-ASSESSMENT.md"),
|
|
463
|
+
[
|
|
464
|
+
"---",
|
|
465
|
+
"sliceId: S01",
|
|
466
|
+
"uatType: runtime-executable",
|
|
467
|
+
"verdict: PASS",
|
|
468
|
+
"attempt: 1",
|
|
469
|
+
"---",
|
|
470
|
+
"# UAT Result - S01",
|
|
471
|
+
"",
|
|
472
|
+
"## Checks",
|
|
473
|
+
"",
|
|
474
|
+
"| Check | Mode | Result | Evidence | Notes |",
|
|
475
|
+
"|-------|------|--------|----------|-------|",
|
|
476
|
+
"| DOM-state script | runtime | PASS | gsd_uat_exec:.gsd/evidence/uat/M001/S01/dom-state.json | Runtime assertion verified completed state and reload persistence. |",
|
|
477
|
+
"",
|
|
478
|
+
].join("\n"),
|
|
479
|
+
"utf-8",
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
const result = await handleValidateMilestone(
|
|
483
|
+
{
|
|
484
|
+
...VALID_PARAMS,
|
|
485
|
+
verificationClasses:
|
|
486
|
+
`${VALID_PARAMS.verificationClasses}\n| UAT | Runtime executable UAT verified static-app behavior. |`,
|
|
487
|
+
},
|
|
488
|
+
base,
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
assert.ok(!("error" in result), `unexpected error: ${"error" in result ? result.error : ""}`);
|
|
492
|
+
assert.equal(result.verdict, "pass");
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
it("downgrades to needs-attention when only one of two browser-requiring slices has runtime evidence", async () => {
|
|
496
|
+
base = makeTmpBase();
|
|
497
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
498
|
+
openDatabase(dbPath);
|
|
499
|
+
insertMilestone({ id: "M001" });
|
|
500
|
+
insertSlice({
|
|
501
|
+
id: "S01",
|
|
502
|
+
milestoneId: "M001",
|
|
503
|
+
demo: "Visit localhost:3000 to verify DOM state.",
|
|
504
|
+
});
|
|
505
|
+
insertSlice({
|
|
506
|
+
id: "S02",
|
|
507
|
+
milestoneId: "M001",
|
|
508
|
+
demo: "Visit localhost:3000 to confirm persistence after reload.",
|
|
509
|
+
});
|
|
510
|
+
// S01 has runtime-executable evidence; S02 has none.
|
|
511
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01"), { recursive: true });
|
|
512
|
+
writeFileSync(
|
|
513
|
+
join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-ASSESSMENT.md"),
|
|
514
|
+
[
|
|
515
|
+
"---",
|
|
516
|
+
"sliceId: S01",
|
|
517
|
+
"uatType: runtime-executable",
|
|
518
|
+
"verdict: PASS",
|
|
519
|
+
"---",
|
|
520
|
+
"| DOM check | runtime | PASS | gsd_uat_exec:.gsd/evidence/uat/M001/S01/dom.json | Verified. |",
|
|
521
|
+
"",
|
|
522
|
+
].join("\n"),
|
|
523
|
+
"utf-8",
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
const result = await handleValidateMilestone(
|
|
527
|
+
{
|
|
528
|
+
...VALID_PARAMS,
|
|
529
|
+
verificationClasses: `${VALID_PARAMS.verificationClasses}\n| UAT | S01 runtime verified; S02 still needs evidence. |`,
|
|
530
|
+
},
|
|
531
|
+
base,
|
|
532
|
+
);
|
|
533
|
+
|
|
534
|
+
assert.ok(!("error" in result), `unexpected error: ${"error" in result ? result.error : ""}`);
|
|
535
|
+
assert.equal(
|
|
536
|
+
result.verdict,
|
|
537
|
+
"needs-attention",
|
|
538
|
+
"S01 runtime evidence must not bypass the gate for S02 which has browser requirements but no evidence",
|
|
539
|
+
);
|
|
540
|
+
});
|
|
541
|
+
|
|
409
542
|
it("ignores slice full_uat_md planning text for browser requirement detection", async () => {
|
|
410
543
|
base = makeTmpBase();
|
|
411
544
|
const dbPath = join(base, ".gsd", "gsd.db");
|
|
@@ -35,6 +35,20 @@ function makeTempDir(prefix: string): string {
|
|
|
35
35
|
return dir;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function withRtkDisabled<T>(callback: () => T): T {
|
|
39
|
+
const previous = process.env.GSD_RTK_DISABLED;
|
|
40
|
+
process.env.GSD_RTK_DISABLED = "1";
|
|
41
|
+
try {
|
|
42
|
+
return callback();
|
|
43
|
+
} finally {
|
|
44
|
+
if (previous === undefined) {
|
|
45
|
+
delete process.env.GSD_RTK_DISABLED;
|
|
46
|
+
} else {
|
|
47
|
+
process.env.GSD_RTK_DISABLED = previous;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
38
52
|
// ─── Discovery Tests ─────────────────────────────────────────────────────────
|
|
39
53
|
|
|
40
54
|
describe("verification-gate: discovery", () => {
|
|
@@ -430,6 +444,38 @@ describe("verification-gate: execution", () => {
|
|
|
430
444
|
assert.ok(result.checks[1].stderr.includes("err"));
|
|
431
445
|
});
|
|
432
446
|
|
|
447
|
+
test("grep -c zero-match failure includes absence-check warning", () => {
|
|
448
|
+
writeFileSync(join(tmp, "sample.txt"), "present\n");
|
|
449
|
+
|
|
450
|
+
const result = withRtkDisabled(() => runVerificationGate({
|
|
451
|
+
cwd: tmp,
|
|
452
|
+
preferenceCommands: ["grep -c missing sample.txt"],
|
|
453
|
+
}));
|
|
454
|
+
|
|
455
|
+
assert.equal(result.passed, false);
|
|
456
|
+
assert.equal(result.checks.length, 1);
|
|
457
|
+
assert.equal(result.checks[0].exitCode, 1);
|
|
458
|
+
assert.equal(result.checks[0].stdout.trim(), "0");
|
|
459
|
+
assert.match(result.checks[0].stderr, /grep -c/);
|
|
460
|
+
assert.match(result.checks[0].stderr, /count=0/);
|
|
461
|
+
assert.match(result.checks[0].stderr, /! grep -q/);
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
test("grep -c matching count does not warn", () => {
|
|
465
|
+
writeFileSync(join(tmp, "sample.txt"), "present\n");
|
|
466
|
+
|
|
467
|
+
const result = withRtkDisabled(() => runVerificationGate({
|
|
468
|
+
cwd: tmp,
|
|
469
|
+
preferenceCommands: ["grep -c present sample.txt"],
|
|
470
|
+
}));
|
|
471
|
+
|
|
472
|
+
assert.equal(result.passed, true);
|
|
473
|
+
assert.equal(result.checks.length, 1);
|
|
474
|
+
assert.equal(result.checks[0].exitCode, 0);
|
|
475
|
+
assert.equal(result.checks[0].stdout.trim(), "1");
|
|
476
|
+
assert.equal(result.checks[0].stderr, "");
|
|
477
|
+
});
|
|
478
|
+
|
|
433
479
|
test("no commands discovered → gate passes with 0 checks", () => {
|
|
434
480
|
const result = runVerificationGate({
|
|
435
481
|
cwd: tmp,
|
|
@@ -686,6 +732,11 @@ test("isLikelyCommand: bash negation with known command is accepted", () => {
|
|
|
686
732
|
assert.equal(isLikelyCommand("! grep needle file.txt"), true);
|
|
687
733
|
});
|
|
688
734
|
|
|
735
|
+
test("validateVerificationCommand accepts negated quiet absence checks", () => {
|
|
736
|
+
assert.equal(validateVerificationCommand("! grep -q needle file.txt").ok, true);
|
|
737
|
+
assert.equal(validateVerificationCommand("! rg -q needle file.txt").ok, true);
|
|
738
|
+
});
|
|
739
|
+
|
|
689
740
|
test("validateVerificationCommand allows shell pipelines", () => {
|
|
690
741
|
assert.deepEqual(validateVerificationCommand("python3 -m pytest tests/ -q --tb=short").ok, true);
|
|
691
742
|
const result = validateVerificationCommand("python3 -m pytest tests/ -q --tb=short | tail -5");
|