@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
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Verifies /gsd forensics scopes issue-filing tools for its queued turn.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
applyForensicsToolScope,
|
|
9
|
+
buildForensicsToolingSection,
|
|
10
|
+
createForensicsToolScope,
|
|
11
|
+
restoreForensicsToolScope,
|
|
12
|
+
} from "../forensics.ts";
|
|
13
|
+
|
|
14
|
+
function tool(name: string): { name: string } {
|
|
15
|
+
return { name };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
test("forensics adds registered filing tools for the queued turn and restores the prior tools", () => {
|
|
19
|
+
const originalTools = ["read"];
|
|
20
|
+
let activeTools = [...originalTools];
|
|
21
|
+
const pi = {
|
|
22
|
+
getActiveTools: () => [...activeTools],
|
|
23
|
+
getAllTools: () => ["read", "bash", "write"].map(tool),
|
|
24
|
+
setActiveTools: (tools: string[]) => {
|
|
25
|
+
activeTools = [...tools];
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const scope = createForensicsToolScope(pi as any);
|
|
30
|
+
|
|
31
|
+
assert.deepEqual(scope.savedTools, originalTools);
|
|
32
|
+
assert.deepEqual(scope.activeToolsForTurn, ["read", "bash", "write"]);
|
|
33
|
+
assert.deepEqual(scope.availableFilingTools, ["bash", "write"]);
|
|
34
|
+
assert.deepEqual(scope.missingFilingTools, []);
|
|
35
|
+
assert.equal(scope.toolsChanged, true);
|
|
36
|
+
assert.deepEqual(activeTools, originalTools, "scope creation must not mutate active tools");
|
|
37
|
+
|
|
38
|
+
applyForensicsToolScope(pi as any, scope);
|
|
39
|
+
assert.deepEqual(activeTools, ["read", "bash", "write"]);
|
|
40
|
+
|
|
41
|
+
const toolingSection = buildForensicsToolingSection(scope);
|
|
42
|
+
assert.match(toolingSection, /`bash`: available/);
|
|
43
|
+
assert.match(toolingSection, /`write`: available/);
|
|
44
|
+
assert.match(toolingSection, /GitHub duplicate-check and issue-creation protocols/);
|
|
45
|
+
|
|
46
|
+
restoreForensicsToolScope(pi as any, scope);
|
|
47
|
+
assert.deepEqual(activeTools, originalTools);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("forensics tooling guidance falls back when bash is not registered", () => {
|
|
51
|
+
let activeTools = ["read"];
|
|
52
|
+
const pi = {
|
|
53
|
+
getActiveTools: () => [...activeTools],
|
|
54
|
+
getAllTools: () => ["read", "write"].map(tool),
|
|
55
|
+
setActiveTools: (tools: string[]) => {
|
|
56
|
+
activeTools = [...tools];
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const scope = createForensicsToolScope(pi as any);
|
|
61
|
+
|
|
62
|
+
assert.deepEqual(scope.availableFilingTools, ["write"]);
|
|
63
|
+
assert.deepEqual(scope.missingFilingTools, ["bash"]);
|
|
64
|
+
assert.deepEqual(scope.activeToolsForTurn, ["read", "write"]);
|
|
65
|
+
|
|
66
|
+
const toolingSection = buildForensicsToolingSection(scope);
|
|
67
|
+
assert.match(toolingSection, /`bash`: unavailable/);
|
|
68
|
+
assert.match(toolingSection, /paste-once shell script fallback/);
|
|
69
|
+
});
|
package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
import test from "node:test";
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
6
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { VISION_ASK_VARIANTS } from "../vision-ask.ts";
|
|
10
|
+
import { buildDiscussMilestonePrompt } from "../auto-prompts.ts";
|
|
10
11
|
|
|
11
12
|
test("guided milestone prompt renders compact interview and context guidance", async (t) => {
|
|
12
13
|
const previousGsdHome = process.env.GSD_HOME;
|
|
@@ -47,3 +48,41 @@ test("guided milestone prompt renders compact interview and context guidance", a
|
|
|
47
48
|
assert.match(prompt, /milestone_id: M001/);
|
|
48
49
|
assert.doesNotMatch(prompt, /\{\{[a-zA-Z][a-zA-Z0-9_]*\}\}/);
|
|
49
50
|
});
|
|
51
|
+
|
|
52
|
+
test("guided milestone prompt builder preloads milestone planning context", async () => {
|
|
53
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-guided-milestone-context-"));
|
|
54
|
+
try {
|
|
55
|
+
const milestonesRoot = join(base, ".gsd", "milestones");
|
|
56
|
+
const priorDir = join(milestonesRoot, "M001");
|
|
57
|
+
const currentDir = join(milestonesRoot, "M002");
|
|
58
|
+
const futureDir = join(milestonesRoot, "M003");
|
|
59
|
+
mkdirSync(priorDir, { recursive: true });
|
|
60
|
+
mkdirSync(currentDir, { recursive: true });
|
|
61
|
+
mkdirSync(futureDir, { recursive: true });
|
|
62
|
+
|
|
63
|
+
writeFileSync(join(base, ".gsd", "DECISIONS.md"), "# Decisions\n\nDECISION-SIGNAL", "utf-8");
|
|
64
|
+
writeFileSync(join(priorDir, "M001-SUMMARY.md"), "# M001 Summary\n\nPRIOR-SUMMARY-SIGNAL", "utf-8");
|
|
65
|
+
writeFileSync(join(currentDir, "M002-ROADMAP.md"), "# M002 Roadmap\n\nROADMAP-SIGNAL", "utf-8");
|
|
66
|
+
writeFileSync(join(currentDir, "M002-CONTEXT.md"), "# M002 Context\n\nCONTEXT-SIGNAL", "utf-8");
|
|
67
|
+
writeFileSync(join(currentDir, "M002-RESEARCH.md"), "# M002 Research\n\nRESEARCH-SIGNAL", "utf-8");
|
|
68
|
+
writeFileSync(join(futureDir, "M003-SUMMARY.md"), "# M003 Summary\n\nFUTURE-SUMMARY-SIGNAL", "utf-8");
|
|
69
|
+
|
|
70
|
+
const prompt = await buildDiscussMilestonePrompt("M002", "Checkout Polish", base, "true");
|
|
71
|
+
|
|
72
|
+
assert.match(prompt, /## Inlined Context \(preloaded — do not re-read these files\)/);
|
|
73
|
+
assert.match(prompt, /### Milestone Roadmap/);
|
|
74
|
+
assert.match(prompt, /ROADMAP-SIGNAL/);
|
|
75
|
+
assert.match(prompt, /### Milestone Context/);
|
|
76
|
+
assert.match(prompt, /CONTEXT-SIGNAL/);
|
|
77
|
+
assert.match(prompt, /### Milestone Research/);
|
|
78
|
+
assert.match(prompt, /RESEARCH-SIGNAL/);
|
|
79
|
+
assert.match(prompt, /### Decisions Register/);
|
|
80
|
+
assert.match(prompt, /DECISION-SIGNAL/);
|
|
81
|
+
assert.match(prompt, /### M001 Prior Milestone Summary/);
|
|
82
|
+
assert.match(prompt, /PRIOR-SUMMARY-SIGNAL/);
|
|
83
|
+
assert.doesNotMatch(prompt, /FUTURE-SUMMARY-SIGNAL/);
|
|
84
|
+
assert.match(prompt, /### Output Template: Context/);
|
|
85
|
+
} finally {
|
|
86
|
+
rmSync(base, { recursive: true, force: true });
|
|
87
|
+
}
|
|
88
|
+
});
|
|
@@ -104,3 +104,89 @@ test("guided dispatch passes the explicit project root through model and compati
|
|
|
104
104
|
rmSync(otherRoot, { recursive: true, force: true });
|
|
105
105
|
}
|
|
106
106
|
});
|
|
107
|
+
|
|
108
|
+
test("guided dispatch accepts workflow MCP tools absent from parent active tool surface", async () => {
|
|
109
|
+
const explicitRoot = mkdtempSync(join(tmpdir(), "gsd-guided-mcp-surface-"));
|
|
110
|
+
const workflowPath = join(explicitRoot, "GSD-WORKFLOW.md");
|
|
111
|
+
const originalWorkflowPath = process.env.GSD_WORKFLOW_PATH;
|
|
112
|
+
const originalMcpCommand = process.env.GSD_WORKFLOW_MCP_COMMAND;
|
|
113
|
+
const notifications: string[] = [];
|
|
114
|
+
let sent = false;
|
|
115
|
+
|
|
116
|
+
const ctx = {
|
|
117
|
+
model: { provider: "claude-code", baseUrl: "local://claude-code" },
|
|
118
|
+
modelRegistry: {
|
|
119
|
+
getProviderAuthMode: () => "externalCli",
|
|
120
|
+
},
|
|
121
|
+
ui: {
|
|
122
|
+
notify: (message: string) => {
|
|
123
|
+
notifications.push(message);
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
let activeTools = [
|
|
129
|
+
"ScheduleWakeup",
|
|
130
|
+
"ToolSearch",
|
|
131
|
+
"ask_user_questions",
|
|
132
|
+
"bash",
|
|
133
|
+
"read",
|
|
134
|
+
"write",
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
const pi = {
|
|
138
|
+
getActiveTools: () => [...activeTools],
|
|
139
|
+
setActiveTools: (tools: string[]) => {
|
|
140
|
+
activeTools = [...tools];
|
|
141
|
+
},
|
|
142
|
+
sendMessage: () => {
|
|
143
|
+
sent = true;
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
writeFileSync(workflowPath, "# Workflow\n", "utf-8");
|
|
149
|
+
process.env.GSD_WORKFLOW_PATH = workflowPath;
|
|
150
|
+
process.env.GSD_WORKFLOW_MCP_COMMAND = "node";
|
|
151
|
+
|
|
152
|
+
await _dispatchWorkflowForTest(
|
|
153
|
+
pi as any,
|
|
154
|
+
"Discuss the milestone.",
|
|
155
|
+
"gsd-discuss",
|
|
156
|
+
ctx as any,
|
|
157
|
+
"discuss-milestone",
|
|
158
|
+
{
|
|
159
|
+
basePath: explicitRoot,
|
|
160
|
+
deps: {
|
|
161
|
+
loadPreferences: () => ({ preferences: {} }) as any,
|
|
162
|
+
selectModel: (async () => ({
|
|
163
|
+
routing: null,
|
|
164
|
+
appliedModel: {
|
|
165
|
+
provider: "claude-code",
|
|
166
|
+
id: "claude-opus-4-8",
|
|
167
|
+
baseUrl: "local://claude-code",
|
|
168
|
+
},
|
|
169
|
+
})) as any,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
assert.equal(sent, true);
|
|
175
|
+
assert.equal(
|
|
176
|
+
notifications.some((message) => message.includes("cannot run guided flow")),
|
|
177
|
+
false,
|
|
178
|
+
);
|
|
179
|
+
} finally {
|
|
180
|
+
if (originalWorkflowPath === undefined) {
|
|
181
|
+
delete process.env.GSD_WORKFLOW_PATH;
|
|
182
|
+
} else {
|
|
183
|
+
process.env.GSD_WORKFLOW_PATH = originalWorkflowPath;
|
|
184
|
+
}
|
|
185
|
+
if (originalMcpCommand === undefined) {
|
|
186
|
+
delete process.env.GSD_WORKFLOW_MCP_COMMAND;
|
|
187
|
+
} else {
|
|
188
|
+
process.env.GSD_WORKFLOW_MCP_COMMAND = originalMcpCommand;
|
|
189
|
+
}
|
|
190
|
+
rmSync(explicitRoot, { recursive: true, force: true });
|
|
191
|
+
}
|
|
192
|
+
});
|
|
@@ -8,14 +8,17 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
8
8
|
|
|
9
9
|
test("guided milestone discussion callsites pass workingDirectory to loadPrompt", () => {
|
|
10
10
|
const source = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
|
|
11
|
-
const calls = [...source.matchAll(/loadPrompt\("guided-discuss-milestone",\s*\{([\s\S]*?)\}\)/g)];
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
// All guided-discuss-milestone dispatches now go through buildDiscussMilestonePrompt,
|
|
13
|
+
// which centralises the loadPrompt call and always passes workingDirectory.
|
|
14
|
+
// Verify no callsite bypasses the builder by calling loadPrompt directly.
|
|
15
|
+
const directCalls = [...source.matchAll(/loadPrompt\("guided-discuss-milestone"/g)];
|
|
16
|
+
assert.equal(
|
|
17
|
+
directCalls.length,
|
|
18
|
+
0,
|
|
19
|
+
'guided-flow.ts must not call loadPrompt("guided-discuss-milestone") directly — use buildDiscussMilestonePrompt',
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const calls = [...source.matchAll(/\bawait buildDiscussMilestonePrompt\(/g)];
|
|
23
|
+
assert.equal(calls.length, 9, "all guided-flow guided-discuss-milestone callsites should be covered");
|
|
21
24
|
});
|
|
@@ -119,8 +119,8 @@ test("resolveExpectedArtifactPath returns correct path for all slice-level types
|
|
|
119
119
|
// ─── run-uat artifact path contract (#2873) ──────────────────────────────
|
|
120
120
|
|
|
121
121
|
test("resolveExpectedArtifactPath for run-uat returns ASSESSMENT path, not UAT (#2873)", (t) => {
|
|
122
|
-
// The run-uat prompt instructs the agent to call
|
|
123
|
-
//
|
|
122
|
+
// The run-uat prompt instructs the agent to call gsd_uat_result_save, which
|
|
123
|
+
// writes S##-ASSESSMENT.md through the workflow persistence path. The artifact
|
|
124
124
|
// verification path must match — otherwise verification fails and auto-mode
|
|
125
125
|
// retries the unit in an infinite loop.
|
|
126
126
|
const base = makeTmpBase();
|
|
@@ -147,12 +147,12 @@ test("diagnoseExpectedArtifact for run-uat references ASSESSMENT (#2873)", (t) =
|
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
test("verifyExpectedArtifact passes for run-uat when ASSESSMENT file exists (#2873)", (t) => {
|
|
150
|
-
// Regression test: run-uat writes S##-ASSESSMENT.md via
|
|
150
|
+
// Regression test: run-uat writes S##-ASSESSMENT.md via gsd_uat_result_save,
|
|
151
151
|
// but verification looked for S##-UAT.md, causing false stuck retries.
|
|
152
152
|
const base = makeTmpBase();
|
|
153
153
|
t.after(() => cleanup(base));
|
|
154
154
|
|
|
155
|
-
// Write the ASSESSMENT file (what
|
|
155
|
+
// Write the ASSESSMENT file (what gsd_uat_result_save actually produces)
|
|
156
156
|
const assessPath = join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-ASSESSMENT.md");
|
|
157
157
|
writeFileSync(assessPath, "---\nverdict: PASS\n---\n# UAT Assessment\n");
|
|
158
158
|
|
|
@@ -72,6 +72,38 @@ function makeBrowserObservableUatContent(mode = 'artifact-driven'): string {
|
|
|
72
72
|
].join('\n');
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
function makeDeferredBrowserUatContent(): string {
|
|
76
|
+
return [
|
|
77
|
+
'# UAT File',
|
|
78
|
+
'',
|
|
79
|
+
'## UAT Type',
|
|
80
|
+
'',
|
|
81
|
+
'- UAT mode: artifact-driven',
|
|
82
|
+
'- Why this mode is sufficient: Node interaction tests exercise the real app.js render/event/localStorage loop through a DOM harness. Live browser, keyboard, responsive, and visual-polish UAT remain intentionally deferred to S02.',
|
|
83
|
+
'',
|
|
84
|
+
'## Smoke Test',
|
|
85
|
+
'',
|
|
86
|
+
'Run `node --test tests/s01-static-interactions.test.js` and confirm all tests pass.',
|
|
87
|
+
'',
|
|
88
|
+
'## Test Cases',
|
|
89
|
+
'',
|
|
90
|
+
'1. Click the todo row edit control in the DOM harness.',
|
|
91
|
+
'2. Save changed text and reload/recreate the app from persisted localStorage.',
|
|
92
|
+
'3. Expected: the stored record shape remains unchanged.',
|
|
93
|
+
'',
|
|
94
|
+
'## Not Proven By This UAT',
|
|
95
|
+
'',
|
|
96
|
+
'- Final visual polish of edit controls.',
|
|
97
|
+
'- Keyboard usability through a real browser.',
|
|
98
|
+
'- Browser console and local network cleanliness.',
|
|
99
|
+
'',
|
|
100
|
+
'## Notes for Tester',
|
|
101
|
+
'',
|
|
102
|
+
'S02 should capture browser evidence for the full loop rather than changing this persisted model.',
|
|
103
|
+
'',
|
|
104
|
+
].join('\n');
|
|
105
|
+
}
|
|
106
|
+
|
|
75
107
|
describe('run-uat', () => {
|
|
76
108
|
test('(a) artifact-driven', () => {
|
|
77
109
|
assert.deepStrictEqual(
|
|
@@ -232,8 +264,8 @@ test('(k) run-uat prompt template', () => {
|
|
|
232
264
|
`prompt contains detected dynamic uatType value "${uatType}" after substitution`,
|
|
233
265
|
);
|
|
234
266
|
assert.ok(
|
|
235
|
-
promptResult?.includes(`uatType: ${uatType}`) ?? false,
|
|
236
|
-
`prompt contains dynamic uatType
|
|
267
|
+
promptResult?.includes(`uatType: "${uatType}"`) ?? false,
|
|
268
|
+
`prompt contains dynamic uatType field "${uatType}" after substitution`,
|
|
237
269
|
);
|
|
238
270
|
assert.ok(
|
|
239
271
|
!/\{\{[^}]+\}\}/.test(promptResult ?? ''),
|
|
@@ -249,7 +281,7 @@ test('(k) run-uat prompt template', () => {
|
|
|
249
281
|
);
|
|
250
282
|
});
|
|
251
283
|
|
|
252
|
-
test('(k2) run-uat prompt references
|
|
284
|
+
test('(k2) run-uat prompt references gsd_uat_result_save, not direct write', () => {
|
|
253
285
|
const promptResult = loadPromptFromWorktree('run-uat', {
|
|
254
286
|
workingDirectory: '/tmp/test-project',
|
|
255
287
|
milestoneId: 'M001',
|
|
@@ -261,17 +293,25 @@ test('(k2) run-uat prompt references gsd_summary_save, not direct write', () =>
|
|
|
261
293
|
});
|
|
262
294
|
|
|
263
295
|
assert.ok(
|
|
264
|
-
promptResult.includes('
|
|
265
|
-
'run-uat prompt should reference
|
|
296
|
+
promptResult.includes('gsd_uat_result_save'),
|
|
297
|
+
'run-uat prompt should reference gsd_uat_result_save tool',
|
|
298
|
+
);
|
|
299
|
+
assert.ok(
|
|
300
|
+
promptResult.includes('presentedTools') && promptResult.includes('blockedTools'),
|
|
301
|
+
'run-uat prompt should specify the tool presentation contract',
|
|
266
302
|
);
|
|
267
303
|
assert.ok(
|
|
268
|
-
promptResult.includes('
|
|
269
|
-
'run-uat prompt should
|
|
304
|
+
!promptResult.includes('Call `gsd_summary_save`'),
|
|
305
|
+
'run-uat prompt should not instruct direct summary-save UAT persistence',
|
|
270
306
|
);
|
|
271
307
|
assert.ok(
|
|
272
308
|
!promptResult.includes('MUST write'),
|
|
273
309
|
'run-uat prompt should not instruct direct file write in footer',
|
|
274
310
|
);
|
|
311
|
+
assert.ok(
|
|
312
|
+
!promptResult.includes('Call `gsd_summary_save` with `artifact_type: "ASSESSMENT"`'),
|
|
313
|
+
'run-uat prompt should not instruct the legacy summary-save UAT path',
|
|
314
|
+
);
|
|
275
315
|
});
|
|
276
316
|
|
|
277
317
|
test('(l) dispatch preconditions via resolveSliceFile', () => {
|
|
@@ -482,8 +522,8 @@ test('(n) stale replay guard', async () => {
|
|
|
482
522
|
});
|
|
483
523
|
|
|
484
524
|
test('(q) verdict in ASSESSMENT file skips UAT dispatch (file-based path)', async () => {
|
|
485
|
-
// Regression test for #2644: run-uat
|
|
486
|
-
// S{sid}-ASSESSMENT.md
|
|
525
|
+
// Regression test for #2644: run-uat writes the verdict to
|
|
526
|
+
// S{sid}-ASSESSMENT.md through the structured UAT save path,
|
|
487
527
|
// but checkNeedsRunUat only checked S{sid}-UAT.md — causing a stuck loop.
|
|
488
528
|
const base = createFixtureBase();
|
|
489
529
|
try {
|
|
@@ -679,11 +719,27 @@ test('(u) run-uat prompt promotes artifact-driven browser specs to browser-execu
|
|
|
679
719
|
const prompt = await buildRunUatPrompt('M001', 'S01', uatRel, uatContent, base);
|
|
680
720
|
|
|
681
721
|
assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`browser-executable`/);
|
|
682
|
-
assert.match(prompt, /uatType: browser-executable/);
|
|
722
|
+
assert.match(prompt, /uatType: "browser-executable"/);
|
|
683
723
|
assert.match(prompt, /use gsd-browser tools/i);
|
|
684
724
|
} finally {
|
|
685
725
|
cleanup(base);
|
|
686
726
|
}
|
|
687
727
|
});
|
|
688
728
|
|
|
729
|
+
test('(v) run-uat prompt keeps deferred browser work artifact-driven', async () => {
|
|
730
|
+
const base = createFixtureBase();
|
|
731
|
+
try {
|
|
732
|
+
const uatRel = '.gsd/milestones/M001/slices/S01/S01-UAT.md';
|
|
733
|
+
const uatContent = makeDeferredBrowserUatContent();
|
|
734
|
+
writeSliceFile(base, 'M001', 'S01', 'UAT', uatContent);
|
|
735
|
+
|
|
736
|
+
const prompt = await buildRunUatPrompt('M001', 'S01', uatRel, uatContent, base);
|
|
737
|
+
|
|
738
|
+
assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`artifact-driven`/);
|
|
739
|
+
assert.match(prompt, /uatType: "artifact-driven"/);
|
|
740
|
+
assert.doesNotMatch(prompt, /uatType: "browser-executable"/);
|
|
741
|
+
} finally {
|
|
742
|
+
cleanup(base);
|
|
743
|
+
}
|
|
744
|
+
});
|
|
689
745
|
});
|
|
@@ -11,6 +11,16 @@ import {
|
|
|
11
11
|
import { createMemoryRelation, listRelationsFor } from '../memory-relations.ts';
|
|
12
12
|
import { saveEmbedding, getEmbeddingForMemory } from '../memory-embeddings.ts';
|
|
13
13
|
|
|
14
|
+
function markProcessedUnits(count = 21): void {
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
for (let i = 0; i < count; i++) {
|
|
17
|
+
markUnitProcessed(`unit/${i}`, `file-${i}`);
|
|
18
|
+
_getAdapter()!
|
|
19
|
+
.prepare('UPDATE memory_processed_units SET processed_at = :ts WHERE unit_key = :key')
|
|
20
|
+
.run({ ':ts': new Date(now + i * 1000).toISOString(), ':key': `unit/${i}` });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
15
25
|
// enforceMemoryCap — cascade cleanup of embeddings and relations
|
|
16
26
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -71,14 +81,7 @@ test('memory-decay: returns decayed memory IDs', () => {
|
|
|
71
81
|
openDatabase(':memory:');
|
|
72
82
|
|
|
73
83
|
// Insert processed units — decayStaleMemories needs at least N rows.
|
|
74
|
-
|
|
75
|
-
for (let i = 0; i < 21; i++) {
|
|
76
|
-
markUnitProcessed(`unit/${i}`, `file-${i}`);
|
|
77
|
-
// small spacing to create deterministic ordering
|
|
78
|
-
const row = _getAdapter()!
|
|
79
|
-
.prepare('UPDATE memory_processed_units SET processed_at = :ts WHERE unit_key = :key');
|
|
80
|
-
row.run({ ':ts': new Date(now + i * 1000).toISOString(), ':key': `unit/${i}` });
|
|
81
|
-
}
|
|
84
|
+
markProcessedUnits();
|
|
82
85
|
|
|
83
86
|
// Create memory with updated_at in the distant past
|
|
84
87
|
createMemory({ category: 'pattern', content: 'stale entry', confidence: 0.9 });
|
|
@@ -98,6 +101,34 @@ test('memory-decay: returns decayed memory IDs', () => {
|
|
|
98
101
|
closeDatabase();
|
|
99
102
|
});
|
|
100
103
|
|
|
104
|
+
test('memory-decay: skips stale decision-sourced memories', () => {
|
|
105
|
+
openDatabase(':memory:');
|
|
106
|
+
markProcessedUnits();
|
|
107
|
+
|
|
108
|
+
createMemory({ category: 'pattern', content: 'stale working note', confidence: 0.9 });
|
|
109
|
+
createMemory({
|
|
110
|
+
category: 'architecture',
|
|
111
|
+
content: 'decision-backed architecture memory',
|
|
112
|
+
confidence: 0.85,
|
|
113
|
+
structuredFields: { sourceDecisionId: 'D001' },
|
|
114
|
+
});
|
|
115
|
+
_getAdapter()!
|
|
116
|
+
.prepare("UPDATE memories SET updated_at = '2000-01-01T00:00:00Z' WHERE id IN ('MEM001', 'MEM002')")
|
|
117
|
+
.run({});
|
|
118
|
+
|
|
119
|
+
const decayed = decayStaleMemories(20);
|
|
120
|
+
assert.ok(decayed.includes('MEM001'));
|
|
121
|
+
assert.ok(!decayed.includes('MEM002'));
|
|
122
|
+
|
|
123
|
+
const rows = _getAdapter()!
|
|
124
|
+
.prepare("SELECT id, confidence FROM memories WHERE id IN ('MEM001', 'MEM002') ORDER BY id")
|
|
125
|
+
.all() as Array<{ id: string; confidence: number }>;
|
|
126
|
+
assert.ok(rows.find((row) => row.id === 'MEM001')!.confidence < 0.9);
|
|
127
|
+
assert.equal(rows.find((row) => row.id === 'MEM002')!.confidence, 0.85);
|
|
128
|
+
|
|
129
|
+
closeDatabase();
|
|
130
|
+
});
|
|
131
|
+
|
|
101
132
|
test('memory-decay: returns empty when there are fewer processed units than the threshold', () => {
|
|
102
133
|
openDatabase(':memory:');
|
|
103
134
|
createMemory({ category: 'pattern', content: 'fresh' });
|
|
@@ -13,10 +13,10 @@ test("dispatchNewMilestoneDiscuss uses discuss.md only on greenfield projects",
|
|
|
13
13
|
|
|
14
14
|
assert.match(fnBody, /findMilestoneIds\(basePath\)\.length === 0/);
|
|
15
15
|
assert.match(fnBody, /prepareAndBuildDiscussPrompt/);
|
|
16
|
-
assert.match(fnBody, /
|
|
16
|
+
assert.match(fnBody, /buildDiscussMilestonePrompt/);
|
|
17
17
|
assert.match(
|
|
18
18
|
fnBody,
|
|
19
|
-
/if \(isGreenfield\)[\s\S]*prepareAndBuildDiscussPrompt[\s\S]*
|
|
19
|
+
/if \(isGreenfield\)[\s\S]*prepareAndBuildDiscussPrompt[\s\S]*buildDiscussMilestonePrompt/,
|
|
20
20
|
"greenfield branch must precede guided-discuss-milestone branch",
|
|
21
21
|
);
|
|
22
22
|
});
|
|
@@ -24,7 +24,7 @@ test("dispatchNewMilestoneDiscuss uses discuss.md only on greenfield projects",
|
|
|
24
24
|
test("dispatchNewMilestoneDiscuss uses milestone-specific preparation guidance", () => {
|
|
25
25
|
const source = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
|
|
26
26
|
const fnBody = extractSourceRegion(source, "async function dispatchNewMilestoneDiscuss(");
|
|
27
|
-
assert.match(fnBody, /buildDiscussPreparationContext\(ctx, basePath, "milestone"\)/);
|
|
27
|
+
assert.match(fnBody, /buildDiscussPreparationContext\(ctx, basePath, "milestone", true\)/);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
test("launchNextMilestoneDiscuss routes through dispatchNewMilestoneDiscuss for normal path", () => {
|
|
@@ -22,23 +22,31 @@ import { tmpdir } from "node:os";
|
|
|
22
22
|
|
|
23
23
|
import { loadSkills } from "@gsd/pi-coding-agent";
|
|
24
24
|
import {
|
|
25
|
-
|
|
25
|
+
buildCompleteSlicePrompt,
|
|
26
26
|
buildParallelResearchSlicesPrompt,
|
|
27
|
+
buildResearchSlicePrompt,
|
|
27
28
|
} from "../auto-prompts.ts";
|
|
28
29
|
|
|
29
30
|
const SKILL_NAME = "testskill";
|
|
31
|
+
const COMPLETE_SLICE_SKILL_NAME = "complete-slice-policies";
|
|
30
32
|
const SKILL_ACTIVATION_SUBSTRING = `Call Skill({ skill: '${SKILL_NAME}' })`;
|
|
33
|
+
const COMPLETE_SLICE_SKILL_ACTIVATION_SUBSTRING = `Call Skill({ skill: '${COMPLETE_SLICE_SKILL_NAME}' })`;
|
|
31
34
|
|
|
32
35
|
const tmpDirs: string[] = [];
|
|
33
36
|
let savedCwd: string | undefined;
|
|
34
37
|
|
|
35
|
-
function setupProjectWithSkill(
|
|
38
|
+
function setupProjectWithSkill(options: {
|
|
39
|
+
skillName?: string;
|
|
40
|
+
preferencesLines?: string[];
|
|
41
|
+
} = {}): string {
|
|
42
|
+
const skillName = options.skillName ?? SKILL_NAME;
|
|
36
43
|
const base = mkdtempSync(join(tmpdir(), "gsd-worker-skill-int-"));
|
|
37
44
|
tmpDirs.push(base);
|
|
38
45
|
|
|
39
46
|
// Milestone roadmap — buildResearchSlicePrompt inlines the roadmap excerpt.
|
|
40
47
|
const milestoneDir = join(base, ".gsd", "milestones", "M001");
|
|
41
|
-
|
|
48
|
+
const sliceOneDir = join(milestoneDir, "slices", "S01");
|
|
49
|
+
mkdirSync(join(sliceOneDir, "tasks"), { recursive: true });
|
|
42
50
|
mkdirSync(join(milestoneDir, "slices", "S02"), { recursive: true });
|
|
43
51
|
writeFileSync(
|
|
44
52
|
join(milestoneDir, "M001-ROADMAP.md"),
|
|
@@ -55,27 +63,41 @@ function setupProjectWithSkill(): string {
|
|
|
55
63
|
].join("\n"),
|
|
56
64
|
"utf-8",
|
|
57
65
|
);
|
|
66
|
+
writeFileSync(
|
|
67
|
+
join(sliceOneDir, "S01-PLAN.md"),
|
|
68
|
+
[
|
|
69
|
+
"# S01: Alpha",
|
|
70
|
+
"",
|
|
71
|
+
"**Goal:** Verify worker x skill prompt plumbing.",
|
|
72
|
+
"**Demo:** Rendered prompts include the skill activation block.",
|
|
73
|
+
"",
|
|
74
|
+
"## Tasks",
|
|
75
|
+
"- [x] **T01: Task** `est:10m`",
|
|
76
|
+
"",
|
|
77
|
+
].join("\n"),
|
|
78
|
+
"utf-8",
|
|
79
|
+
);
|
|
58
80
|
|
|
59
81
|
// Project preferences — buildSkillActivationBlock picks these up via
|
|
60
82
|
// loadEffectiveGSDPreferences(), which reads from `${cwd}/.gsd/PREFERENCES.md`.
|
|
61
83
|
writeFileSync(
|
|
62
84
|
join(base, ".gsd", "PREFERENCES.md"),
|
|
63
|
-
["---", `always_use_skills:`, ` - ${
|
|
85
|
+
["---", ...(options.preferencesLines ?? [`always_use_skills:`, ` - ${skillName}`]), "---", ""].join("\n"),
|
|
64
86
|
"utf-8",
|
|
65
87
|
);
|
|
66
88
|
|
|
67
89
|
// Project-scoped skill — resolveSkillReference scans `${cwd}/.agents/skills/`.
|
|
68
|
-
const skillDir = join(base, ".agents", "skills",
|
|
90
|
+
const skillDir = join(base, ".agents", "skills", skillName);
|
|
69
91
|
mkdirSync(skillDir, { recursive: true });
|
|
70
92
|
writeFileSync(
|
|
71
93
|
join(skillDir, "SKILL.md"),
|
|
72
94
|
[
|
|
73
95
|
"---",
|
|
74
|
-
`name: ${
|
|
96
|
+
`name: ${skillName}`,
|
|
75
97
|
`description: Integration-test skill for worker × skill prompt plumbing.`,
|
|
76
98
|
"---",
|
|
77
99
|
"",
|
|
78
|
-
`# ${
|
|
100
|
+
`# ${skillName}`,
|
|
79
101
|
"",
|
|
80
102
|
"Test skill body.",
|
|
81
103
|
].join("\n"),
|
|
@@ -122,6 +144,31 @@ test("worker prompt (buildResearchSlicePrompt) includes <skill_activation> from
|
|
|
122
144
|
);
|
|
123
145
|
});
|
|
124
146
|
|
|
147
|
+
test("complete-slice prompt includes <skill_activation> from unit-specific skill_rules", async () => {
|
|
148
|
+
const base = setupProjectWithSkill({
|
|
149
|
+
skillName: COMPLETE_SLICE_SKILL_NAME,
|
|
150
|
+
preferencesLines: [
|
|
151
|
+
"skill_rules:",
|
|
152
|
+
" - when: complete-slice",
|
|
153
|
+
" use:",
|
|
154
|
+
` - ${COMPLETE_SLICE_SKILL_NAME}`,
|
|
155
|
+
],
|
|
156
|
+
});
|
|
157
|
+
savedCwd = process.cwd();
|
|
158
|
+
process.chdir(base);
|
|
159
|
+
|
|
160
|
+
const prompt = await buildCompleteSlicePrompt("M001", "Test Milestone", "S01", "Alpha", base, "minimal");
|
|
161
|
+
|
|
162
|
+
assert.ok(
|
|
163
|
+
prompt.includes("<skill_activation>"),
|
|
164
|
+
"complete-slice prompt should contain a <skill_activation> block",
|
|
165
|
+
);
|
|
166
|
+
assert.ok(
|
|
167
|
+
prompt.includes(COMPLETE_SLICE_SKILL_ACTIVATION_SUBSTRING),
|
|
168
|
+
`complete-slice prompt should reference the skill-rule skill '${COMPLETE_SLICE_SKILL_NAME}'`,
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
|
|
125
172
|
test("subagent dispatch prompt (buildParallelResearchSlicesPrompt) carries <skill_activation> into each embedded per-slice section", async () => {
|
|
126
173
|
const base = setupProjectWithSkill();
|
|
127
174
|
savedCwd = process.cwd();
|
|
@@ -83,6 +83,15 @@ test("plan-slice prompt: compact planning gates survive template substitution",
|
|
|
83
83
|
assert.ok(!result.includes("{{"));
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
+
test("plan-slice prompt: absence checks use negated quiet searches", () => {
|
|
87
|
+
const result = loadPrompt("plan-slice", { ...BASE_VARS, commitInstruction: "Do not commit." });
|
|
88
|
+
assert.ok(result.includes("For absence checks"));
|
|
89
|
+
assert.ok(result.includes("`! grep -q 'pattern' file`"));
|
|
90
|
+
assert.ok(result.includes("`! rg -q 'pattern' file`"));
|
|
91
|
+
assert.ok(result.includes("do not use `grep -c` or `rg -c`"));
|
|
92
|
+
assert.ok(result.includes("count commands exit 1 when they find zero matches"));
|
|
93
|
+
});
|
|
94
|
+
|
|
86
95
|
test("plan-slice prompt: footer references gsd_plan_slice tool, not direct write", () => {
|
|
87
96
|
const result = loadPrompt("plan-slice", { ...BASE_VARS, commitInstruction: "Do not commit." });
|
|
88
97
|
assert.ok(
|