@opengsd/gsd-pi 1.1.1-dev.3ea310e → 1.1.1-dev.595401e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
- package/dist/resources/extensions/gsd/auto/phases.js +4 -3
- package/dist/resources/extensions/gsd/auto-dashboard.js +92 -17
- package/dist/resources/extensions/gsd/auto-dispatch.js +5 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +132 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +68 -22
- package/dist/resources/extensions/gsd/auto-start.js +41 -12
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +2 -1
- package/dist/resources/extensions/gsd/auto.js +12 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +82 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +30 -9
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -10
- package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
- package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
- package/dist/resources/extensions/gsd/config-overlay.js +2 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
- package/dist/resources/extensions/gsd/error-classifier.js +2 -1
- package/dist/resources/extensions/gsd/escalation.js +4 -4
- package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
- package/dist/resources/extensions/gsd/forensics.js +74 -2
- package/dist/resources/extensions/gsd/gsd-db.js +5 -2
- package/dist/resources/extensions/gsd/guided-flow.js +29 -68
- package/dist/resources/extensions/gsd/memory-store.js +4 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +48 -24
- package/dist/resources/extensions/gsd/prompts/system.md +3 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/dist/resources/extensions/gsd/rule-registry.js +428 -52
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
- package/dist/resources/extensions/gsd/skill-activation.js +20 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
- package/dist/resources/extensions/gsd/state.js +3 -3
- package/dist/resources/extensions/gsd/templates/plan.md +3 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
- package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +403 -3
- package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
- package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
- package/dist/resources/extensions/gsd/verification-gate.js +72 -1
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +1 -1
- package/dist/resources/extensions/gsd/workflow-mcp.js +5 -1
- package/dist/rtk.d.ts +7 -1
- package/dist/rtk.js +27 -11
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +3 -2
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +14 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +32 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/index.d.ts +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +1 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
- package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
- package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
- package/packages/gsd-agent-core/package.json +6 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +89 -31
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
- package/packages/mcp-server/dist/remote-questions.js +23 -9
- package/packages/mcp-server/dist/remote-questions.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +84 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +38 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +3 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/api-registry.d.ts +2 -0
- package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
- package/packages/pi-ai/dist/api-registry.js +23 -0
- package/packages/pi-ai/dist/api-registry.js.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.js +15 -0
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +86 -18
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +108 -40
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/stream.js +6 -6
- package/packages/pi-ai/dist/stream.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/terminal.d.ts +1 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +8 -4
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
- package/src/resources/extensions/gsd/auto/phases.ts +5 -3
- package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
- package/src/resources/extensions/gsd/auto-dispatch.ts +5 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +164 -7
- package/src/resources/extensions/gsd/auto-prompts.ts +102 -15
- package/src/resources/extensions/gsd/auto-start.ts +54 -14
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +2 -1
- package/src/resources/extensions/gsd/auto.ts +15 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +89 -3
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +51 -14
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +21 -10
- package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
- package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
- package/src/resources/extensions/gsd/config-overlay.ts +3 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
- package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
- package/src/resources/extensions/gsd/error-classifier.ts +2 -1
- package/src/resources/extensions/gsd/escalation.ts +4 -4
- package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
- package/src/resources/extensions/gsd/forensics.ts +99 -5
- package/src/resources/extensions/gsd/gsd-db.ts +5 -2
- package/src/resources/extensions/gsd/guided-flow.ts +90 -82
- package/src/resources/extensions/gsd/memory-store.ts +4 -1
- package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
- package/src/resources/extensions/gsd/preferences-types.ts +1 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +48 -24
- package/src/resources/extensions/gsd/prompts/system.md +3 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/src/resources/extensions/gsd/rule-registry.ts +558 -58
- package/src/resources/extensions/gsd/rule-types.ts +2 -0
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
- package/src/resources/extensions/gsd/skill-activation.ts +20 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
- package/src/resources/extensions/gsd/state.ts +3 -3
- package/src/resources/extensions/gsd/templates/plan.md +3 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +16 -3
- package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +66 -10
- package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
- package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +53 -1
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +213 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +25 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +489 -3
- package/src/resources/extensions/gsd/types.ts +67 -4
- package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
- package/src/resources/extensions/gsd/verification-gate.ts +87 -1
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +1 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +5 -1
- /package/dist/web/standalone/.next/static/{xACmObbrDjwLriepRgaa9 → IDKjyRHLIaumjgonPcYiX}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{xACmObbrDjwLriepRgaa9 → IDKjyRHLIaumjgonPcYiX}/_ssgManifest.js +0 -0
|
@@ -51,7 +51,7 @@ test("discuss workflow scopes tools for the queued turn and restores the full to
|
|
|
51
51
|
// discuss allowlist: gsd_summary_save and gsd_plan_milestone (the latter
|
|
52
52
|
// is needed for the discuss.md output phase — see DISCUSS_TOOLS_ALLOWLIST).
|
|
53
53
|
// gsd_task_complete and the broad shell_exec tool are scoped out.
|
|
54
|
-
assert.deepEqual(sentTools, ["
|
|
54
|
+
assert.deepEqual(sentTools, ["gsd_plan_milestone", "gsd_summary_save", "ToolSearch"]);
|
|
55
55
|
assert.deepEqual(activeTools, originalTools);
|
|
56
56
|
assert.equal(triggerTurn, true);
|
|
57
57
|
} finally {
|
|
@@ -8,6 +8,7 @@ import { test, describe, beforeEach } from "node:test";
|
|
|
8
8
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
import { join } from "node:path";
|
|
11
|
+
import { emitJournalEvent } from "../journal.ts";
|
|
11
12
|
import {
|
|
12
13
|
RuleRegistry,
|
|
13
14
|
getRegistry,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
resetRegistry,
|
|
17
18
|
convertDispatchRules,
|
|
18
19
|
getOrCreateRegistry,
|
|
20
|
+
resolveHookArtifactPath,
|
|
19
21
|
} from "../rule-registry.ts";
|
|
20
22
|
import type { UnifiedRule } from "../rule-types.ts";
|
|
21
23
|
import type { DispatchAction, DispatchContext } from "../auto-dispatch.ts";
|
|
@@ -443,6 +445,79 @@ describe("RuleRegistry", () => {
|
|
|
443
445
|
}
|
|
444
446
|
});
|
|
445
447
|
|
|
448
|
+
test("failed hook completion with an artifact does not dequeue the next hook", () => {
|
|
449
|
+
const originalGsdHome = process.env.GSD_HOME;
|
|
450
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-hook-failed-"));
|
|
451
|
+
const tempGsdHome = mkdtempSync(join(tmpdir(), "gsd-hook-home-"));
|
|
452
|
+
const unitId = "M001/S01/T01";
|
|
453
|
+
|
|
454
|
+
try {
|
|
455
|
+
mkdirSync(join(projectRoot, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
456
|
+
writeFileSync(
|
|
457
|
+
join(projectRoot, ".gsd", "PREFERENCES.md"),
|
|
458
|
+
[
|
|
459
|
+
"---",
|
|
460
|
+
"version: 1",
|
|
461
|
+
"post_unit_hooks:",
|
|
462
|
+
" - name: review-arbiter",
|
|
463
|
+
" after: [execute-task]",
|
|
464
|
+
" prompt: Review {taskId}",
|
|
465
|
+
" artifact: REVIEW.md",
|
|
466
|
+
" max_cycles: 1",
|
|
467
|
+
" - name: follow-up-review",
|
|
468
|
+
" after: [execute-task]",
|
|
469
|
+
" prompt: Follow-up review {taskId}",
|
|
470
|
+
"---",
|
|
471
|
+
].join("\n"),
|
|
472
|
+
"utf-8",
|
|
473
|
+
);
|
|
474
|
+
process.env.GSD_HOME = tempGsdHome;
|
|
475
|
+
|
|
476
|
+
const registry = new RuleRegistry([]);
|
|
477
|
+
const firstHook = registry.evaluatePostUnit("execute-task", unitId, projectRoot);
|
|
478
|
+
assert.equal(firstHook?.hookName, "review-arbiter");
|
|
479
|
+
|
|
480
|
+
writeFileSync(
|
|
481
|
+
resolveHookArtifactPath(projectRoot, unitId, "REVIEW.md"),
|
|
482
|
+
"partial review output",
|
|
483
|
+
"utf-8",
|
|
484
|
+
);
|
|
485
|
+
emitJournalEvent(projectRoot, {
|
|
486
|
+
ts: "2026-06-03T12:00:00.000Z",
|
|
487
|
+
flowId: "flow-hook-failed",
|
|
488
|
+
seq: 3,
|
|
489
|
+
eventType: "unit-end",
|
|
490
|
+
data: {
|
|
491
|
+
unitType: "hook/review-arbiter",
|
|
492
|
+
unitId,
|
|
493
|
+
status: "cancelled",
|
|
494
|
+
artifactVerified: false,
|
|
495
|
+
errorContext: {
|
|
496
|
+
message: "Provider error: Stream ended without finish_reason",
|
|
497
|
+
category: "provider",
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
const nextHook = registry.evaluatePostUnit("hook/review-arbiter", unitId, projectRoot);
|
|
503
|
+
assert.equal(nextHook, null, "failed hook must not allow follow-up hook dispatch");
|
|
504
|
+
const failure = registry.consumeHookFailure();
|
|
505
|
+
assert.equal(failure?.hookName, "review-arbiter");
|
|
506
|
+
assert.match(failure?.reason ?? "", /status cancelled/);
|
|
507
|
+
|
|
508
|
+
const resumedRegistry = new RuleRegistry([]);
|
|
509
|
+
resumedRegistry.restoreState(projectRoot);
|
|
510
|
+
const resumedHook = resumedRegistry.evaluatePostUnit("execute-task", unitId, projectRoot);
|
|
511
|
+
assert.equal(resumedHook, null, "resumed hook evaluation must not skip failed hook artifact");
|
|
512
|
+
assert.equal(resumedRegistry.consumeHookFailure()?.hookName, "review-arbiter");
|
|
513
|
+
} finally {
|
|
514
|
+
if (originalGsdHome === undefined) delete process.env.GSD_HOME;
|
|
515
|
+
else process.env.GSD_HOME = originalGsdHome;
|
|
516
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
517
|
+
rmSync(tempGsdHome, { recursive: true, force: true });
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
|
|
446
521
|
// ── matchedRule provenance (S02 journal support) ───────────────────
|
|
447
522
|
|
|
448
523
|
test("evaluateDispatch result includes matchedRule on dispatch match", async () => {
|
|
@@ -5,6 +5,7 @@ import { join } from "node:path";
|
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { loadSkills } from "@gsd/pi-coding-agent";
|
|
7
7
|
import {
|
|
8
|
+
buildCompleteSlicePrompt,
|
|
8
9
|
buildPlanMilestonePrompt,
|
|
9
10
|
buildResearchMilestonePrompt,
|
|
10
11
|
buildSkillActivationBlock,
|
|
@@ -143,6 +144,29 @@ test("buildSkillActivationBlock includes skill_rules matches and task-plan skill
|
|
|
143
144
|
}
|
|
144
145
|
});
|
|
145
146
|
|
|
147
|
+
test("buildSkillActivationBlock matches skill_rules against exact unit type context", () => {
|
|
148
|
+
const base = makeTempBase();
|
|
149
|
+
try {
|
|
150
|
+
writeSkill(base, "complete-slice-policies", "Use for complete-slice closeout policy checks.");
|
|
151
|
+
writeSkill(base, "slice-broad", "Use for broad slice work.");
|
|
152
|
+
loadOnlyTestSkills(base);
|
|
153
|
+
|
|
154
|
+
const result = buildBlock(base, {
|
|
155
|
+
unitType: "complete-slice",
|
|
156
|
+
}, {
|
|
157
|
+
skill_rules: [
|
|
158
|
+
{ when: "complete-slice", use: ["complete-slice-policies"] },
|
|
159
|
+
{ when: "slice", use: ["slice-broad"] },
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
assert.match(result, /Call Skill\(\{ skill: 'complete-slice-policies' \}\)/);
|
|
164
|
+
assert.doesNotMatch(result, /slice-broad/);
|
|
165
|
+
} finally {
|
|
166
|
+
cleanup(base);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
146
170
|
test("buildSkillActivationBlock honors avoid_skills against always_use_skills", () => {
|
|
147
171
|
const base = makeTempBase();
|
|
148
172
|
try {
|
|
@@ -328,6 +352,37 @@ test("milestone prompt builders propagate always_use_skills through buildSkillAc
|
|
|
328
352
|
}
|
|
329
353
|
});
|
|
330
354
|
|
|
355
|
+
test("complete-slice prompt propagates always_use_skills through buildSkillActivationBlock", async () => {
|
|
356
|
+
const base = makeTempBase();
|
|
357
|
+
try {
|
|
358
|
+
writeSkill(base, "write-docs", "Use when writing docs or RFCs.");
|
|
359
|
+
writeProjectPreferences(base, "always_use_skills:\n - write-docs\n");
|
|
360
|
+
loadOnlyTestSkills(base);
|
|
361
|
+
|
|
362
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M001");
|
|
363
|
+
const sliceDir = join(milestoneDir, "slices", "S01");
|
|
364
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
365
|
+
writeFileSync(
|
|
366
|
+
join(milestoneDir, "M001-ROADMAP.md"),
|
|
367
|
+
[
|
|
368
|
+
"# M001: Test",
|
|
369
|
+
"",
|
|
370
|
+
"## Slices",
|
|
371
|
+
"",
|
|
372
|
+
"- [ ] **S01: Slice** `risk:low` `depends:[]`",
|
|
373
|
+
"",
|
|
374
|
+
].join("\n"),
|
|
375
|
+
);
|
|
376
|
+
writeFileSync(join(sliceDir, "S01-PLAN.md"), "# S01: Slice\n\n## Tasks\n\n- [x] **T01: Done**\n");
|
|
377
|
+
|
|
378
|
+
const prompt = await buildCompleteSlicePrompt("M001", "Test", "S01", "Slice", base);
|
|
379
|
+
|
|
380
|
+
assert.match(prompt, /Call Skill\(\{ skill: 'write-docs' \}\)/);
|
|
381
|
+
} finally {
|
|
382
|
+
cleanup(base);
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
|
|
331
386
|
test("skill manifest strict warnings require GSD_SKILL_MANIFEST_STRICT=1", (t) => {
|
|
332
387
|
const previousStrict = process.env.GSD_SKILL_MANIFEST_STRICT;
|
|
333
388
|
const previousStderr = setStderrLoggingEnabled(false);
|
|
@@ -906,6 +906,51 @@ test("ADR-017 (#5704): registered milestone (DB row present) → no drift", asyn
|
|
|
906
906
|
|
|
907
907
|
// ─── #5705: roadmap-divergence drift ─────────────────────────────────────────
|
|
908
908
|
|
|
909
|
+
test("ADR-017 (#391): roadmap-divergence skips slices before task planning completes", async (t) => {
|
|
910
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-adr017-roadmap-unplanned-"));
|
|
911
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M001");
|
|
912
|
+
const roadmapPath = join(milestoneDir, "M001-ROADMAP.md");
|
|
913
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
914
|
+
const originalRoadmap = [
|
|
915
|
+
"# M001: Test",
|
|
916
|
+
"",
|
|
917
|
+
"**Vision:** Verify transient milestone planning state",
|
|
918
|
+
"",
|
|
919
|
+
"## Slices",
|
|
920
|
+
"",
|
|
921
|
+
"- [ ] **S01: Foundation** `risk:medium` `depends:[]`",
|
|
922
|
+
"- [ ] **S02: Feature** `risk:medium` `depends:[S01]`",
|
|
923
|
+
"",
|
|
924
|
+
].join("\n");
|
|
925
|
+
writeFileSync(roadmapPath, originalRoadmap);
|
|
926
|
+
t.after(() => {
|
|
927
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
928
|
+
rmSync(base, { recursive: true, force: true });
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
932
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
933
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
|
|
934
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Feature", status: "pending", risk: "medium", depends: [], demo: "", sequence: 2 });
|
|
935
|
+
|
|
936
|
+
assert.equal(getSliceTasks("M001", "S01").length, 0, "pre: S01 has not been planned");
|
|
937
|
+
assert.equal(getSliceTasks("M001", "S02").length, 0, "pre: S02 has not been planned");
|
|
938
|
+
|
|
939
|
+
const result = await reconcileBeforeDispatch(base, {
|
|
940
|
+
invalidateStateCache: () => {},
|
|
941
|
+
deriveState: async () => makeState(),
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
assert.equal(result.ok, true);
|
|
945
|
+
assert.equal(
|
|
946
|
+
result.repaired.some((d) => d.kind === "roadmap-divergence"),
|
|
947
|
+
false,
|
|
948
|
+
"unplanned slices should not trigger roadmap-divergence repair",
|
|
949
|
+
);
|
|
950
|
+
assert.equal(readFileSync(roadmapPath, "utf-8"), originalRoadmap);
|
|
951
|
+
assert.deepEqual(getSlice("M001", "S02")?.depends, [], "DB remains unchanged");
|
|
952
|
+
});
|
|
953
|
+
|
|
909
954
|
test("ADR-017 (#5705): roadmap-divergence re-renders projection without syncing depends into DB", async (t) => {
|
|
910
955
|
const base = mkdtempSync(join(tmpdir(), "gsd-adr017-roadmap-"));
|
|
911
956
|
const milestoneDir = join(base, ".gsd", "milestones", "M001");
|
|
@@ -936,6 +981,8 @@ test("ADR-017 (#5705): roadmap-divergence re-renders projection without syncing
|
|
|
936
981
|
// Seed DB with S02 depending on [] — diverges from ROADMAP.md
|
|
937
982
|
insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
|
|
938
983
|
insertSlice({ id: "S02", milestoneId: "M001", title: "Feature", status: "pending", risk: "medium", depends: [], demo: "", sequence: 2 });
|
|
984
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
|
|
985
|
+
insertTask({ id: "T01", sliceId: "S02", milestoneId: "M001", title: "Plan S02", status: "pending" });
|
|
939
986
|
|
|
940
987
|
assert.deepEqual(getSlice("M001", "S02")?.depends, [], "pre: DB has S02.depends = []");
|
|
941
988
|
|
|
@@ -987,6 +1034,7 @@ test("ADR-017 (#5705): ROADMAP-only slice is removed from projection and not ins
|
|
|
987
1034
|
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
988
1035
|
// Only insert S01 — S02 is intentionally absent from the DB.
|
|
989
1036
|
insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
|
|
1037
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
|
|
990
1038
|
|
|
991
1039
|
assert.equal(getSlice("M001", "S02"), null, "pre: S02 has no DB row");
|
|
992
1040
|
|
|
@@ -1035,6 +1083,8 @@ test("ADR-017 (#5705): ROADMAP sequence drift re-renders from DB order without m
|
|
|
1035
1083
|
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
1036
1084
|
insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
|
|
1037
1085
|
insertSlice({ id: "S02", milestoneId: "M001", title: "Feature", status: "pending", risk: "medium", depends: [], demo: "", sequence: 2 });
|
|
1086
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
|
|
1087
|
+
insertTask({ id: "T01", sliceId: "S02", milestoneId: "M001", title: "Plan S02", status: "pending" });
|
|
1038
1088
|
|
|
1039
1089
|
const result = await reconcileBeforeDispatch(base, {
|
|
1040
1090
|
invalidateStateCache: () => {},
|
|
@@ -1078,6 +1128,7 @@ test("ADR-017 (#5705): ROADMAP checkbox drift re-renders from DB status without
|
|
|
1078
1128
|
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1079
1129
|
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
1080
1130
|
insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
|
|
1131
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
|
|
1081
1132
|
|
|
1082
1133
|
const result = await reconcileBeforeDispatch(base, {
|
|
1083
1134
|
invalidateStateCache: () => {},
|
|
@@ -1119,6 +1170,7 @@ test("ADR-017 (#5705): in-sync ROADMAP and DB → no roadmap-divergence drift",
|
|
|
1119
1170
|
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1120
1171
|
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
1121
1172
|
insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "low", depends: [], demo: "", sequence: 1 });
|
|
1173
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
|
|
1122
1174
|
|
|
1123
1175
|
const result = await reconcileBeforeDispatch(base, {
|
|
1124
1176
|
invalidateStateCache: () => {},
|
|
@@ -1300,6 +1352,145 @@ test("ADR-017: orphan task completion artifact fails closed", async (t) => {
|
|
|
1300
1352
|
assert.match(result.blockers.join("\n"), /Artifact\/DB status drift/);
|
|
1301
1353
|
});
|
|
1302
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
|
+
|
|
1303
1494
|
test("ADR-017: completed milestone dispatch history blocks accidental re-planning", async (t) => {
|
|
1304
1495
|
const base = mkdtempSync(join(tmpdir(), "gsd-completed-reopened-drift-"));
|
|
1305
1496
|
t.after(() => cleanup(base));
|
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
import assert from "node:assert/strict";
|
|
5
5
|
import test from "node:test";
|
|
6
6
|
|
|
7
|
+
import { registerToolCompatibility } from "@gsd/pi-coding-agent";
|
|
8
|
+
|
|
7
9
|
import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
|
|
8
10
|
import { buildMinimalAutoGsdToolSet, buildMinimalGsdToolSet, buildMinimalGsdWorkflowToolSet, buildRequestScopedGsdToolSet, MINIMAL_AUTO_BASE_TOOL_NAMES, MINIMAL_GSD_TOOL_NAMES, requestHasGsdCustomType, restoreGsdWorkflowTools, scopeGsdWorkflowToolsForDispatch } from "../bootstrap/register-hooks.ts";
|
|
11
|
+
import { filterToolsForProvider } from "../model-router.ts";
|
|
9
12
|
import { applyUnitSkillVisibility } from "../skill-scope.ts";
|
|
10
13
|
|
|
11
14
|
test("buildMinimalGsdToolSet preserves non-GSD tools and replaces broad GSD surface", () => {
|
|
@@ -31,7 +34,7 @@ test("buildMinimalGsdToolSet preserves non-GSD tools and replaces broad GSD surf
|
|
|
31
34
|
for (const toolName of MINIMAL_GSD_TOOL_NAMES) {
|
|
32
35
|
assert.ok(result.includes(toolName), `expected ${toolName}`);
|
|
33
36
|
}
|
|
34
|
-
assert.ok(
|
|
37
|
+
assert.ok(result.includes("gsd_plan_milestone"));
|
|
35
38
|
assert.ok(!result.includes("gsd_task_complete"));
|
|
36
39
|
assert.ok(!result.includes("gsd_graph"));
|
|
37
40
|
});
|
|
@@ -98,22 +101,39 @@ test("buildMinimalAutoGsdToolSet keeps unit-specific completion tools without al
|
|
|
98
101
|
assert.ok(!result.includes("gsd_complete_slice"));
|
|
99
102
|
});
|
|
100
103
|
|
|
101
|
-
test("buildMinimalAutoGsdToolSet
|
|
102
|
-
|
|
103
|
-
// tools stay registered. run-uat must still get them: resolution reads the
|
|
104
|
-
// full registry, not just the (browser-stripped) active set.
|
|
105
|
-
const active = ["ask_user_questions", "bash", "read", "gsd_summary_save"];
|
|
104
|
+
test("buildMinimalAutoGsdToolSet scopes run-uat to UAT-specific tools", () => {
|
|
105
|
+
const active = ["ask_user_questions", "bash", "read", "edit", "write", "gsd_summary_save"];
|
|
106
106
|
const registered = [
|
|
107
107
|
...active,
|
|
108
|
+
"gsd_uat_exec",
|
|
109
|
+
"gsd_uat_result_save",
|
|
110
|
+
"gsd_resume",
|
|
111
|
+
"gsd_milestone_status",
|
|
112
|
+
"gsd_journal_query",
|
|
113
|
+
"gsd_exec",
|
|
114
|
+
"gsd_save_gate_result",
|
|
115
|
+
"search-the-web",
|
|
108
116
|
"browser_navigate",
|
|
109
117
|
"browser_click",
|
|
110
118
|
"browser_snapshot_refs",
|
|
111
|
-
"gsd_exec",
|
|
112
119
|
];
|
|
113
120
|
const result = buildMinimalAutoGsdToolSet(active, "run-uat", registered);
|
|
121
|
+
assert.ok(result.includes("gsd_uat_exec"));
|
|
122
|
+
assert.ok(result.includes("gsd_uat_result_save"));
|
|
123
|
+
assert.ok(result.includes("gsd_resume"));
|
|
124
|
+
assert.ok(result.includes("gsd_milestone_status"));
|
|
125
|
+
assert.ok(result.includes("gsd_journal_query"));
|
|
114
126
|
assert.ok(result.includes("browser_navigate"), "run-uat needs browser_navigate");
|
|
115
127
|
assert.ok(result.includes("browser_click"), "run-uat needs browser_click");
|
|
116
|
-
assert.ok(result.includes("
|
|
128
|
+
assert.ok(!result.includes("ToolSearch"));
|
|
129
|
+
assert.ok(!result.includes("bash"));
|
|
130
|
+
assert.ok(!result.includes("read"));
|
|
131
|
+
assert.ok(!result.includes("edit"));
|
|
132
|
+
assert.ok(!result.includes("write"));
|
|
133
|
+
assert.ok(!result.includes("gsd_exec"));
|
|
134
|
+
assert.ok(!result.includes("gsd_summary_save"));
|
|
135
|
+
assert.ok(!result.includes("gsd_save_gate_result"));
|
|
136
|
+
assert.ok(!result.includes("search-the-web"));
|
|
117
137
|
});
|
|
118
138
|
|
|
119
139
|
test("buildMinimalAutoGsdToolSet keeps only the auto base non-GSD tools", () => {
|
|
@@ -175,17 +195,27 @@ test("buildMinimalAutoGsdToolSet re-injects registered base tools filtered from
|
|
|
175
195
|
assert.ok(result.includes("search-the-web"));
|
|
176
196
|
});
|
|
177
197
|
|
|
178
|
-
test("buildMinimalAutoGsdToolSet preserves browser
|
|
198
|
+
test("buildMinimalAutoGsdToolSet preserves compatible browser add-ons for run-uat", () => {
|
|
179
199
|
const result = buildMinimalAutoGsdToolSet([
|
|
180
200
|
"bash",
|
|
181
201
|
"read",
|
|
202
|
+
"edit",
|
|
203
|
+
"write",
|
|
182
204
|
"browser_navigate",
|
|
183
205
|
"browser_click",
|
|
184
206
|
"browser_type",
|
|
185
207
|
"browser_assert",
|
|
186
208
|
"browser_screenshot",
|
|
187
209
|
"browser_wait_for",
|
|
210
|
+
"gsd_uat_exec",
|
|
211
|
+
"gsd_uat_result_save",
|
|
212
|
+
"gsd_resume",
|
|
213
|
+
"gsd_milestone_status",
|
|
214
|
+
"gsd_journal_query",
|
|
215
|
+
"subagent",
|
|
188
216
|
"gsd_summary_save",
|
|
217
|
+
"gsd_exec",
|
|
218
|
+
"gsd_save_gate_result",
|
|
189
219
|
"gsd_task_complete",
|
|
190
220
|
"memory_query",
|
|
191
221
|
"capture_thought",
|
|
@@ -197,7 +227,17 @@ test("buildMinimalAutoGsdToolSet preserves browser tools for run-uat", () => {
|
|
|
197
227
|
assert.ok(result.includes("browser_assert"));
|
|
198
228
|
assert.ok(result.includes("browser_screenshot"));
|
|
199
229
|
assert.ok(result.includes("browser_wait_for"));
|
|
200
|
-
assert.ok(result.includes("
|
|
230
|
+
assert.ok(result.includes("gsd_uat_exec"));
|
|
231
|
+
assert.ok(result.includes("gsd_uat_result_save"));
|
|
232
|
+
assert.ok(result.includes("subagent"));
|
|
233
|
+
assert.ok(!result.includes("ToolSearch"));
|
|
234
|
+
assert.ok(!result.includes("bash"));
|
|
235
|
+
assert.ok(!result.includes("read"));
|
|
236
|
+
assert.ok(!result.includes("edit"));
|
|
237
|
+
assert.ok(!result.includes("write"));
|
|
238
|
+
assert.ok(!result.includes("gsd_exec"));
|
|
239
|
+
assert.ok(!result.includes("gsd_summary_save"));
|
|
240
|
+
assert.ok(!result.includes("gsd_save_gate_result"));
|
|
201
241
|
assert.ok(!result.includes("gsd_task_complete"));
|
|
202
242
|
});
|
|
203
243
|
|
|
@@ -218,6 +258,40 @@ test("buildMinimalAutoGsdToolSet prefers MCP browser tools for run-uat when avai
|
|
|
218
258
|
assert.ok(!result.includes("browser_click"));
|
|
219
259
|
});
|
|
220
260
|
|
|
261
|
+
test("buildMinimalAutoGsdToolSet honors provider-compatible registered tools for run-uat", () => {
|
|
262
|
+
registerToolCompatibility("browser_screenshot", { producesImages: true });
|
|
263
|
+
const registered = [
|
|
264
|
+
"bash",
|
|
265
|
+
"read",
|
|
266
|
+
"ToolSearch",
|
|
267
|
+
"browser_navigate",
|
|
268
|
+
"browser_click",
|
|
269
|
+
"browser_screenshot",
|
|
270
|
+
"gsd_uat_exec",
|
|
271
|
+
"gsd_uat_result_save",
|
|
272
|
+
"gsd_resume",
|
|
273
|
+
"gsd_milestone_status",
|
|
274
|
+
"gsd_journal_query",
|
|
275
|
+
"gsd_exec",
|
|
276
|
+
"gsd_summary_save",
|
|
277
|
+
"gsd_save_gate_result",
|
|
278
|
+
];
|
|
279
|
+
const providerCompatible = filterToolsForProvider(registered, "openai-responses").compatible;
|
|
280
|
+
const result = buildMinimalAutoGsdToolSet(["gsd_uat_exec"], "run-uat", providerCompatible);
|
|
281
|
+
|
|
282
|
+
assert.ok(result.includes("gsd_uat_exec"));
|
|
283
|
+
assert.ok(result.includes("gsd_uat_result_save"));
|
|
284
|
+
assert.ok(result.includes("browser_navigate"));
|
|
285
|
+
assert.ok(result.includes("browser_click"));
|
|
286
|
+
assert.ok(!result.includes("browser_screenshot"), "provider-filtered screenshot tool must stay filtered");
|
|
287
|
+
assert.ok(!result.includes("ToolSearch"));
|
|
288
|
+
assert.ok(!result.includes("bash"));
|
|
289
|
+
assert.ok(!result.includes("read"));
|
|
290
|
+
assert.ok(!result.includes("gsd_exec"));
|
|
291
|
+
assert.ok(!result.includes("gsd_summary_save"));
|
|
292
|
+
assert.ok(!result.includes("gsd_save_gate_result"));
|
|
293
|
+
});
|
|
294
|
+
|
|
221
295
|
test("buildMinimalAutoGsdToolSet includes discuss-slice persistence tools", () => {
|
|
222
296
|
const result = buildMinimalAutoGsdToolSet([
|
|
223
297
|
"bash",
|
|
@@ -39,6 +39,12 @@ const RENAME_MAP: Array<{ canonical: string; alias: string }> = [
|
|
|
39
39
|
{ canonical: "gsd_milestone_reopen", alias: "gsd_reopen_milestone" },
|
|
40
40
|
];
|
|
41
41
|
|
|
42
|
+
const STANDALONE_TOOLS = [
|
|
43
|
+
"gsd_save_gate_result",
|
|
44
|
+
"gsd_skip_slice",
|
|
45
|
+
"gsd_uat_result_save",
|
|
46
|
+
];
|
|
47
|
+
|
|
42
48
|
// ─── Registration count ──────────────────────────────────────────────────────
|
|
43
49
|
|
|
44
50
|
console.log('\n── Tool naming: registration count ──');
|
|
@@ -48,10 +54,14 @@ registerDbTools(pi);
|
|
|
48
54
|
|
|
49
55
|
assert.deepStrictEqual(
|
|
50
56
|
pi.tools.length,
|
|
51
|
-
RENAME_MAP.length * 2 +
|
|
52
|
-
'Should register canonical/alias tool pairs plus
|
|
57
|
+
RENAME_MAP.length * 2 + STANDALONE_TOOLS.length,
|
|
58
|
+
'Should register canonical/alias tool pairs plus standalone DB tools',
|
|
53
59
|
);
|
|
54
60
|
|
|
61
|
+
for (const name of STANDALONE_TOOLS) {
|
|
62
|
+
assert.ok(pi.tools.some((t: any) => t.name === name), `Standalone tool "${name}" should be registered`);
|
|
63
|
+
}
|
|
64
|
+
|
|
55
65
|
// ─── Both names exist for each pair ──────────────────────────────────────────
|
|
56
66
|
|
|
57
67
|
console.log('\n── Tool naming: canonical and alias names exist ──');
|