@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.9bb7453
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -2
- package/dist/help-text.js +10 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
- package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
- package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/dist/resources/extensions/browser-tools/index.js +57 -9
- package/dist/resources/extensions/browser-tools/package.json +5 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +167 -16
- 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 +44 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
- package/dist/resources/extensions/gsd/auto-prompts.js +68 -22
- package/dist/resources/extensions/gsd/auto-recovery.js +4 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +94 -15
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +2 -1
- package/dist/resources/extensions/gsd/auto.js +31 -6
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +83 -4
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +39 -14
- 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/catalog.js +6 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +9 -5
- package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
- package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
- package/dist/resources/extensions/gsd/commands-mcp-status.js +109 -60
- 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 +42 -6
- package/dist/resources/extensions/gsd/guided-flow.js +30 -69
- package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
- package/dist/resources/extensions/gsd/mcp-project-config.js +76 -84
- package/dist/resources/extensions/gsd/memory-store.js +4 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
- 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/artifact-db.js +4 -2
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
- 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 +17 -14
- package/dist/resources/extensions/gsd/templates/plan.md +3 -1
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +120 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
- package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- 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 +3 -1
- package/dist/resources/extensions/gsd/workflow-mcp.js +5 -1
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
- package/dist/resources/extensions/mcp-client/manager.js +31 -1
- package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
- package/dist/rtk.d.ts +7 -1
- package/dist/rtk.js +27 -11
- package/dist/update-check.d.ts +15 -1
- package/dist/update-check.js +87 -12
- package/dist/update-cmd.d.ts +1 -0
- package/dist/update-cmd.js +53 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
- 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 +5 -3
- 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 +92 -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-extension-dialogs.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.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 +406 -17
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +484 -116
- 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/browser-tools/engine/managed-gsd-browser.ts +579 -0
- package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
- package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/src/resources/extensions/browser-tools/index.ts +60 -9
- package/src/resources/extensions/browser-tools/package.json +5 -1
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
- 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 +53 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
- package/src/resources/extensions/gsd/auto-prompts.ts +102 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +4 -4
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
- package/src/resources/extensions/gsd/auto-start.ts +112 -17
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +2 -1
- package/src/resources/extensions/gsd/auto.ts +47 -5
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +90 -4
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +60 -19
- 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/catalog.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +9 -5
- package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
- package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
- package/src/resources/extensions/gsd/commands-mcp-status.ts +136 -58
- 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 +46 -8
- package/src/resources/extensions/gsd/guided-flow.ts +91 -83
- package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
- package/src/resources/extensions/gsd/mcp-project-config.ts +105 -88
- package/src/resources/extensions/gsd/memory-store.ts +4 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
- 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/artifact-db.ts +4 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
- 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 +18 -14
- 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 +123 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
- package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
- 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/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
- package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -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/gsd-rebuild.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -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/integration/state-machine-live-validation.test.ts +13 -6
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
- 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/plan-slice.test.ts +39 -1
- 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/session-start-footer.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
- 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-invocation-error-loop-break.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
- 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 +17 -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/tool-presentation-plan.ts +167 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- 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 +69 -5
- 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 +2 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +5 -1
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
- package/src/resources/extensions/mcp-client/manager.ts +33 -1
- package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
- /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → jBtwT9v1u2lUA3UEOy_ZH}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → jBtwT9v1u2lUA3UEOy_ZH}/_ssgManifest.js +0 -0
|
@@ -229,6 +229,24 @@ function makeIsolatedBaseWithCleanup(t: TestContext): string {
|
|
|
229
229
|
return base;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
function setGsdHeadless(t: TestContext): void {
|
|
233
|
+
const previous = process.env.GSD_HEADLESS;
|
|
234
|
+
process.env.GSD_HEADLESS = "1";
|
|
235
|
+
t.after(() => {
|
|
236
|
+
if (previous === undefined) delete process.env.GSD_HEADLESS;
|
|
237
|
+
else process.env.GSD_HEADLESS = previous;
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function unsetGsdHeadless(t: TestContext): void {
|
|
242
|
+
const previous = process.env.GSD_HEADLESS;
|
|
243
|
+
delete process.env.GSD_HEADLESS;
|
|
244
|
+
t.after(() => {
|
|
245
|
+
if (previous === undefined) delete process.env.GSD_HEADLESS;
|
|
246
|
+
else process.env.GSD_HEADLESS = previous;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
232
250
|
function writeValidProject(base: string): void {
|
|
233
251
|
writeFileSync(join(base, ".gsd", "PROJECT.md"), VALID_PROJECT_MD);
|
|
234
252
|
}
|
|
@@ -364,16 +382,33 @@ test("Deep mode: discuss-project does NOT dispatch when planning_depth is 'light
|
|
|
364
382
|
test("Deep mode: discuss-project DOES dispatch when planning_depth is 'deep' and PROJECT.md missing", async (t) => {
|
|
365
383
|
const base = makeIsolatedBaseWithCleanup(t);
|
|
366
384
|
|
|
385
|
+
unsetGsdHeadless(t);
|
|
386
|
+
|
|
367
387
|
const prefs = { planning_depth: "deep" } as GSDPreferences;
|
|
368
388
|
const result = await rule(PROJECT_RULE_NAME).match(makeCtx(base, prefs));
|
|
369
389
|
assert.ok(result && result.action === "dispatch", "deep mode + missing PROJECT.md must dispatch");
|
|
370
390
|
if (result.action === "dispatch") {
|
|
371
391
|
assert.strictEqual(result.unitType, "discuss-project");
|
|
372
392
|
assert.strictEqual(result.unitId, "PROJECT");
|
|
393
|
+
assert.strictEqual(result.pauseAfterDispatch, true);
|
|
373
394
|
assert.ok(result.prompt.length > 0, "prompt must be non-empty");
|
|
374
395
|
}
|
|
375
396
|
});
|
|
376
397
|
|
|
398
|
+
test("Deep mode: discuss-project does not pause when GSD_HEADLESS is set", async (t) => {
|
|
399
|
+
const base = makeIsolatedBaseWithCleanup(t);
|
|
400
|
+
|
|
401
|
+
setGsdHeadless(t);
|
|
402
|
+
|
|
403
|
+
const prefs = { planning_depth: "deep" } as GSDPreferences;
|
|
404
|
+
const result = await rule(PROJECT_RULE_NAME).match(makeCtx(base, prefs));
|
|
405
|
+
assert.ok(result && result.action === "dispatch", "deep mode + missing PROJECT.md must dispatch");
|
|
406
|
+
if (result.action === "dispatch") {
|
|
407
|
+
assert.strictEqual(result.unitType, "discuss-project");
|
|
408
|
+
assert.strictEqual(result.pauseAfterDispatch, false);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
|
|
377
412
|
test("Deep mode: discuss-project does NOT dispatch when PROJECT.md already exists and is valid", async (t) => {
|
|
378
413
|
const base = makeIsolatedBaseWithCleanup(t);
|
|
379
414
|
|
|
@@ -432,6 +467,8 @@ test("Deep mode: discuss-requirements does NOT dispatch when PROJECT.md missing
|
|
|
432
467
|
test("Deep mode: discuss-requirements DOES dispatch when PROJECT.md exists and REQUIREMENTS.md missing", async (t) => {
|
|
433
468
|
const base = makeIsolatedBaseWithCleanup(t);
|
|
434
469
|
|
|
470
|
+
unsetGsdHeadless(t);
|
|
471
|
+
|
|
435
472
|
writeValidProject(base);
|
|
436
473
|
const prefs = { planning_depth: "deep" } as GSDPreferences;
|
|
437
474
|
const result = await rule(REQUIREMENTS_RULE_NAME).match(makeCtx(base, prefs));
|
|
@@ -439,6 +476,22 @@ test("Deep mode: discuss-requirements DOES dispatch when PROJECT.md exists and R
|
|
|
439
476
|
if (result.action === "dispatch") {
|
|
440
477
|
assert.strictEqual(result.unitType, "discuss-requirements");
|
|
441
478
|
assert.strictEqual(result.unitId, "REQUIREMENTS");
|
|
479
|
+
assert.strictEqual(result.pauseAfterDispatch, true);
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
test("Deep mode: discuss-requirements does not pause when GSD_HEADLESS is set", async (t) => {
|
|
484
|
+
const base = makeIsolatedBaseWithCleanup(t);
|
|
485
|
+
|
|
486
|
+
setGsdHeadless(t);
|
|
487
|
+
|
|
488
|
+
writeValidProject(base);
|
|
489
|
+
const prefs = { planning_depth: "deep" } as GSDPreferences;
|
|
490
|
+
const result = await rule(REQUIREMENTS_RULE_NAME).match(makeCtx(base, prefs));
|
|
491
|
+
assert.ok(result && result.action === "dispatch", "deep mode + PROJECT.md present + REQUIREMENTS.md missing must dispatch");
|
|
492
|
+
if (result.action === "dispatch") {
|
|
493
|
+
assert.strictEqual(result.unitType, "discuss-requirements");
|
|
494
|
+
assert.strictEqual(result.pauseAfterDispatch, false);
|
|
442
495
|
}
|
|
443
496
|
});
|
|
444
497
|
|
|
@@ -868,6 +868,14 @@ describe('derive-state-db', async () => {
|
|
|
868
868
|
dbState.blockers.some(b => b.includes('needs-remediation') && b.includes('M001')),
|
|
869
869
|
'remediation-stuck-db: blocker message mentions milestone and verdict',
|
|
870
870
|
);
|
|
871
|
+
assert.ok(
|
|
872
|
+
dbState.blockers.some(b => b.includes('/gsd dispatch reassess')),
|
|
873
|
+
'remediation-stuck-db: blocker message points users to the reassess command',
|
|
874
|
+
);
|
|
875
|
+
assert.ok(
|
|
876
|
+
dbState.blockers.every(b => !b.includes('gsd_reassess_roadmap')),
|
|
877
|
+
'remediation-stuck-db: blocker message does not expose the internal tool name',
|
|
878
|
+
);
|
|
871
879
|
|
|
872
880
|
closeDatabase();
|
|
873
881
|
} finally {
|
|
@@ -473,13 +473,13 @@ describe('derive-state-helpers', () => {
|
|
|
473
473
|
}
|
|
474
474
|
});
|
|
475
475
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
476
|
+
test('getActiveMilestoneId: DB lock path ignores PARKED flag projection', async () => {
|
|
477
|
+
const base = createFixtureBase();
|
|
478
|
+
const previousLock = process.env.GSD_MILESTONE_LOCK;
|
|
479
|
+
const previousWorker = process.env.GSD_PARALLEL_WORKER;
|
|
480
|
+
try {
|
|
481
|
+
process.env.GSD_MILESTONE_LOCK = 'M001';
|
|
482
|
+
process.env.GSD_PARALLEL_WORKER = '1';
|
|
483
483
|
writeFile(base, 'milestones/M001/M001-PARKED.md', '# Parked on disk');
|
|
484
484
|
|
|
485
485
|
openDatabase(':memory:');
|
|
@@ -487,12 +487,41 @@ describe('derive-state-helpers', () => {
|
|
|
487
487
|
|
|
488
488
|
const id = await getActiveMilestoneId(base);
|
|
489
489
|
assert.equal(id, 'M001', 'DB status remains authoritative despite PARKED projection');
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
490
|
+
} finally {
|
|
491
|
+
if (previousLock === undefined) delete process.env.GSD_MILESTONE_LOCK;
|
|
492
|
+
else process.env.GSD_MILESTONE_LOCK = previousLock;
|
|
493
|
+
if (previousWorker === undefined) delete process.env.GSD_PARALLEL_WORKER;
|
|
494
|
+
else process.env.GSD_PARALLEL_WORKER = previousWorker;
|
|
495
|
+
closeDatabase();
|
|
496
|
+
cleanup(base);
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
test('deriveStateFromDb: solo milestone lock scopes state to the requested milestone', async () => {
|
|
501
|
+
const base = createFixtureBase();
|
|
502
|
+
const previousLock = process.env.GSD_MILESTONE_LOCK;
|
|
503
|
+
const previousWorker = process.env.GSD_PARALLEL_WORKER;
|
|
504
|
+
try {
|
|
505
|
+
delete process.env.GSD_PARALLEL_WORKER;
|
|
506
|
+
process.env.GSD_MILESTONE_LOCK = 'M002';
|
|
507
|
+
|
|
508
|
+
openDatabase(':memory:');
|
|
509
|
+
insertMilestone({ id: 'M001', title: 'Earlier', status: 'active' });
|
|
510
|
+
insertMilestone({ id: 'M002', title: 'Requested', status: 'active' });
|
|
511
|
+
|
|
512
|
+
invalidateStateCache();
|
|
513
|
+
const state = await deriveStateFromDb(base);
|
|
514
|
+
const id = await getActiveMilestoneId(base);
|
|
515
|
+
|
|
516
|
+
assert.equal(state.activeMilestone?.id, 'M002', 'explicit lock chooses requested milestone');
|
|
517
|
+
assert.deepEqual(state.registry.map((entry) => entry.id), ['M002'], 'registry is scoped to requested milestone');
|
|
518
|
+
assert.equal(id, 'M002', 'active milestone helper honors solo lock');
|
|
519
|
+
} finally {
|
|
520
|
+
if (previousLock === undefined) delete process.env.GSD_MILESTONE_LOCK;
|
|
521
|
+
else process.env.GSD_MILESTONE_LOCK = previousLock;
|
|
522
|
+
if (previousWorker === undefined) delete process.env.GSD_PARALLEL_WORKER;
|
|
523
|
+
else process.env.GSD_PARALLEL_WORKER = previousWorker;
|
|
524
|
+
closeDatabase();
|
|
496
525
|
cleanup(base);
|
|
497
526
|
}
|
|
498
527
|
});
|
|
@@ -526,6 +555,14 @@ describe('derive-state-helpers', () => {
|
|
|
526
555
|
state.blockers.some(b => b.includes('needs-remediation') && b.includes('M001')),
|
|
527
556
|
'remediation-stuck: blocker message mentions milestone and verdict',
|
|
528
557
|
);
|
|
558
|
+
assert.ok(
|
|
559
|
+
state.blockers.some(b => b.includes('/gsd dispatch reassess')),
|
|
560
|
+
'remediation-stuck: blocker message points users to the reassess command',
|
|
561
|
+
);
|
|
562
|
+
assert.ok(
|
|
563
|
+
state.blockers.every(b => !b.includes('gsd_reassess_roadmap')),
|
|
564
|
+
'remediation-stuck: blocker message does not expose the internal tool name',
|
|
565
|
+
);
|
|
529
566
|
} finally {
|
|
530
567
|
closeDatabase();
|
|
531
568
|
cleanup(base);
|
|
@@ -44,14 +44,26 @@ function setGsdHeadless(t: { after: (fn: () => void) => void }): void {
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
function unsetGsdHeadless(t: { after: (fn: () => void) => void }): void {
|
|
48
|
+
const previous = process.env.GSD_HEADLESS;
|
|
49
|
+
delete process.env.GSD_HEADLESS;
|
|
50
|
+
t.after(() => {
|
|
51
|
+
if (previous === undefined) delete process.env.GSD_HEADLESS;
|
|
52
|
+
else process.env.GSD_HEADLESS = previous;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
test("auto-dispatch passes structuredQuestionsAvailable=true into discuss-milestone prompt", async (t) => {
|
|
48
57
|
const tmp = mkdtempSync(join(tmpdir(), "gsd-discuss-milestone-structured-"));
|
|
49
58
|
t.after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
50
59
|
|
|
60
|
+
unsetGsdHeadless(t);
|
|
61
|
+
|
|
51
62
|
const result = await resolveDispatch(makeContext(tmp, "needs-discussion", "true"));
|
|
52
63
|
|
|
53
64
|
assert.equal(result.action, "dispatch");
|
|
54
65
|
assert.equal(result.unitType, "discuss-milestone");
|
|
66
|
+
assert.equal(result.pauseAfterDispatch, true);
|
|
55
67
|
assert.match(
|
|
56
68
|
result.prompt,
|
|
57
69
|
/\*\*Structured questions available: true\*\*/,
|
|
@@ -62,10 +74,13 @@ test("auto-dispatch preserves structuredQuestionsAvailable=false for discuss-mil
|
|
|
62
74
|
const tmp = mkdtempSync(join(tmpdir(), "gsd-discuss-milestone-plain-"));
|
|
63
75
|
t.after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
64
76
|
|
|
77
|
+
unsetGsdHeadless(t);
|
|
78
|
+
|
|
65
79
|
const result = await resolveDispatch(makeContext(tmp, "pre-planning", "false"));
|
|
66
80
|
|
|
67
81
|
assert.equal(result.action, "dispatch");
|
|
68
82
|
assert.equal(result.unitType, "discuss-milestone");
|
|
83
|
+
assert.equal(result.pauseAfterDispatch, true);
|
|
69
84
|
assert.match(
|
|
70
85
|
result.prompt,
|
|
71
86
|
/\*\*Structured questions available: false\*\*/,
|
|
@@ -82,6 +97,7 @@ test("auto-dispatch uses discuss-headless prompt when GSD_HEADLESS is set", asyn
|
|
|
82
97
|
|
|
83
98
|
assert.equal(result.action, "dispatch");
|
|
84
99
|
assert.equal(result.unitType, "discuss-milestone");
|
|
100
|
+
assert.equal(result.pauseAfterDispatch, false);
|
|
85
101
|
assert.match(result.prompt, /This is a \*\*headless\*\* flow/);
|
|
86
102
|
assert.doesNotMatch(result.prompt, /\*\*Structured questions available: true\*\*/);
|
|
87
103
|
});
|
|
@@ -96,10 +112,24 @@ test("auto-dispatch uses discuss-headless prompt for needs-discussion when GSD_H
|
|
|
96
112
|
|
|
97
113
|
assert.equal(result.action, "dispatch");
|
|
98
114
|
assert.equal(result.unitType, "discuss-milestone");
|
|
115
|
+
assert.equal(result.pauseAfterDispatch, false);
|
|
99
116
|
assert.match(result.prompt, /This is a \*\*headless\*\* flow/);
|
|
100
117
|
assert.doesNotMatch(result.prompt, /\*\*Structured questions available: true\*\*/);
|
|
101
118
|
});
|
|
102
119
|
|
|
120
|
+
test("auto-dispatch pauses after execution-entry discuss-milestone recovery", async (t) => {
|
|
121
|
+
const tmp = mkdtempSync(join(tmpdir(), "gsd-discuss-milestone-executing-"));
|
|
122
|
+
t.after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
123
|
+
|
|
124
|
+
unsetGsdHeadless(t);
|
|
125
|
+
|
|
126
|
+
const result = await resolveDispatch(makeContext(tmp, "executing", "true"));
|
|
127
|
+
|
|
128
|
+
assert.equal(result.action, "dispatch");
|
|
129
|
+
assert.equal(result.unitType, "discuss-milestone");
|
|
130
|
+
assert.equal(result.pauseAfterDispatch, true);
|
|
131
|
+
});
|
|
132
|
+
|
|
103
133
|
test("auto-dispatch uses discuss-headless prompt for executing when GSD_HEADLESS is set", async (t) => {
|
|
104
134
|
const tmp = mkdtempSync(join(tmpdir(), "gsd-discuss-milestone-headless-"));
|
|
105
135
|
t.after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
@@ -110,6 +140,7 @@ test("auto-dispatch uses discuss-headless prompt for executing when GSD_HEADLESS
|
|
|
110
140
|
|
|
111
141
|
assert.equal(result.action, "dispatch");
|
|
112
142
|
assert.equal(result.unitType, "discuss-milestone");
|
|
143
|
+
assert.equal(result.pauseAfterDispatch, false);
|
|
113
144
|
assert.match(result.prompt, /This is a \*\*headless\*\* flow/);
|
|
114
145
|
assert.doesNotMatch(result.prompt, /\*\*Structured questions available: true\*\*/);
|
|
115
146
|
});
|
|
@@ -19,6 +19,7 @@ import type { DispatchContext } from "../auto-dispatch.ts";
|
|
|
19
19
|
import type { AutoSession } from "../auto/session.ts";
|
|
20
20
|
import type { GSDState } from "../types.ts";
|
|
21
21
|
import { enableDebug, disableDebug, getDebugLogPath } from "../debug-logger.ts";
|
|
22
|
+
import { closeDatabase, insertMilestone, isDbAvailable, openDatabase } from "../gsd-db.ts";
|
|
22
23
|
|
|
23
24
|
function makeState(overrides: Partial<GSDState> = {}): GSDState {
|
|
24
25
|
return {
|
|
@@ -123,6 +124,29 @@ test("dispatch: missing task plan triggers plan-slice (not stop) — issue #909"
|
|
|
123
124
|
`unitId should be M002/S03, got: ${result.action === "dispatch" ? result.unitId : "(stop)"}`);
|
|
124
125
|
});
|
|
125
126
|
|
|
127
|
+
test("dispatch: closed milestone is not implicitly recovered or reopened", async (t) => {
|
|
128
|
+
const tmp = mkdtempSync(join(tmpdir(), "gsd-closed-dispatch-"));
|
|
129
|
+
t.after(() => {
|
|
130
|
+
if (isDbAvailable()) closeDatabase();
|
|
131
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
if (isDbAvailable()) closeDatabase();
|
|
135
|
+
mkdirSync(join(tmp, ".gsd"), { recursive: true });
|
|
136
|
+
openDatabase(join(tmp, ".gsd", "gsd.db"));
|
|
137
|
+
insertMilestone({ id: "M002", title: "Closed Milestone", status: "complete" });
|
|
138
|
+
scaffoldMilestoneContext(tmp, "M002");
|
|
139
|
+
scaffoldSlicePlan(tmp, "M002", "S03");
|
|
140
|
+
|
|
141
|
+
const result = await resolveDispatch(makeContext(tmp));
|
|
142
|
+
|
|
143
|
+
assert.equal(result.action, "stop");
|
|
144
|
+
assert.ok(result.action === "stop");
|
|
145
|
+
assert.equal(result.level, "warning");
|
|
146
|
+
assert.match(result.reason, /Milestone M002 is closed/);
|
|
147
|
+
assert.match(result.reason, /will not reopen or recover it implicitly/);
|
|
148
|
+
});
|
|
149
|
+
|
|
126
150
|
test("dispatch: present task plan proceeds to execute-task normally", async (t) => {
|
|
127
151
|
const tmp = mkdtempSync(join(tmpdir(), "gsd-909-ok-"));
|
|
128
152
|
t.after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
@@ -141,6 +165,42 @@ test("dispatch: present task plan proceeds to execute-task normally", async (t)
|
|
|
141
165
|
`unitId should be M002/S03/T01, got: ${result.action === "dispatch" ? result.unitId : "(stop)"}`);
|
|
142
166
|
});
|
|
143
167
|
|
|
168
|
+
test("dispatch: session milestone mismatch stops before missing-task-plan recovery", async (t) => {
|
|
169
|
+
const tmp = mkdtempSync(join(tmpdir(), "gsd-session-milestone-mismatch-"));
|
|
170
|
+
t.after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
171
|
+
|
|
172
|
+
const worktreeRoot = join(tmp, ".gsd", "worktrees", "M002");
|
|
173
|
+
mkdirSync(worktreeRoot, { recursive: true });
|
|
174
|
+
|
|
175
|
+
const ctx = makeContextFor(tmp, "M001", "S01", "T01", {
|
|
176
|
+
basePath: worktreeRoot,
|
|
177
|
+
originalBasePath: tmp,
|
|
178
|
+
currentMilestoneId: "M002",
|
|
179
|
+
});
|
|
180
|
+
const result = await resolveDispatch(ctx);
|
|
181
|
+
|
|
182
|
+
assert.equal(result.action, "stop");
|
|
183
|
+
assert.ok(result.action === "stop");
|
|
184
|
+
assert.equal(result.level, "warning");
|
|
185
|
+
assert.match(result.reason, /context mid "M001" does not match session\.currentMilestoneId "M002"/);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("dispatch: worktree path mismatch stops before planning a different milestone", async (t) => {
|
|
189
|
+
const tmp = mkdtempSync(join(tmpdir(), "gsd-worktree-path-milestone-mismatch-"));
|
|
190
|
+
t.after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
191
|
+
|
|
192
|
+
const worktreeRoot = join(tmp, ".gsd", "worktrees", "M002");
|
|
193
|
+
mkdirSync(worktreeRoot, { recursive: true });
|
|
194
|
+
|
|
195
|
+
const ctx = makeContextFor(worktreeRoot, "M001", "S01", "T01");
|
|
196
|
+
const result = await resolveDispatch(ctx);
|
|
197
|
+
|
|
198
|
+
assert.equal(result.action, "stop");
|
|
199
|
+
assert.ok(result.action === "stop");
|
|
200
|
+
assert.equal(result.level, "warning");
|
|
201
|
+
assert.match(result.reason, /context mid "M001" does not match basePath worktree "M002"/);
|
|
202
|
+
});
|
|
203
|
+
|
|
144
204
|
test("dispatch: executing recovery checks active milestone worktree task plans before re-dispatching plan-slice", async (t) => {
|
|
145
205
|
const tmp = mkdtempSync(join(tmpdir(), "gsd-6192-"));
|
|
146
206
|
t.after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
@@ -45,3 +45,30 @@ test("doctor fix respects git.manage_gitignore false (#4161)", async (t) => {
|
|
|
45
45
|
assert.equal(readFileSync(join(dir, ".gitignore"), "utf-8"), "node_modules/\n");
|
|
46
46
|
assert.equal(existsSync(join(dir, ".gsd", "PREFERENCES.md")), true);
|
|
47
47
|
});
|
|
48
|
+
|
|
49
|
+
test("doctor fix resets run-uat counters at the dispatch cap", async (t) => {
|
|
50
|
+
const dir = createGitProject();
|
|
51
|
+
t.after(() => rmSync(dir, { recursive: true, force: true }));
|
|
52
|
+
|
|
53
|
+
const runtimeDir = join(dir, ".gsd", "runtime");
|
|
54
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
55
|
+
const counterPath = join(runtimeDir, "uat-count-M002-S01.json");
|
|
56
|
+
writeFileSync(
|
|
57
|
+
counterPath,
|
|
58
|
+
JSON.stringify({ count: 3, updatedAt: "2026-06-02T19:40:23.289Z" }) + "\n",
|
|
59
|
+
"utf-8",
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const detect = await runGSDDoctor(dir);
|
|
63
|
+
const issue = detect.issues.find((candidate) => candidate.code === "uat_retry_exhausted");
|
|
64
|
+
assert.ok(issue, "doctor reports the exhausted UAT retry counter at the dispatch cap");
|
|
65
|
+
assert.equal(issue.unitId, "M002/S01");
|
|
66
|
+
assert.match(issue.message, /3 attempt\(s\)/);
|
|
67
|
+
|
|
68
|
+
const fixed = await runGSDDoctor(dir, { fix: true, scope: "M002/S02" });
|
|
69
|
+
assert.ok(
|
|
70
|
+
fixed.fixesApplied.some((fix) => fix.includes("reset exhausted run-uat retry counter for M002/S01")),
|
|
71
|
+
"doctor --fix resets the blocked counter even when the current displayed scope has advanced",
|
|
72
|
+
);
|
|
73
|
+
assert.equal(existsSync(counterPath), false);
|
|
74
|
+
});
|
|
@@ -106,7 +106,7 @@ test("ADR-011 P2: writeEscalationArtifact persists canonical JSON at tasks/T##-E
|
|
|
106
106
|
assert.equal(row?.escalation_artifact_path, path);
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
-
test("ADR-011 P2: continueWithDefault=true sets awaiting_review (NOT pending)
|
|
109
|
+
test("ADR-011 P2: continueWithDefault=true sets awaiting_review (NOT pending)", (t) => {
|
|
110
110
|
const base = makeBase();
|
|
111
111
|
t.after(() => cleanup(base));
|
|
112
112
|
seedCompletedTask(base, "T04");
|
|
@@ -126,7 +126,7 @@ test("ADR-011 P2: continueWithDefault=true sets awaiting_review (NOT pending)
|
|
|
126
126
|
assert.equal(row?.escalation_awaiting_review, 1);
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
test("ADR-011 P2: detectPendingEscalation
|
|
129
|
+
test("ADR-011 P2: detectPendingEscalation pauses on unresolved awaiting_review escalations", (t) => {
|
|
130
130
|
const base = makeBase();
|
|
131
131
|
t.after(() => cleanup(base));
|
|
132
132
|
seedCompletedTask(base, "T01");
|
|
@@ -147,7 +147,7 @@ test("ADR-011 P2: detectPendingEscalation returns only pause-scoped escalations"
|
|
|
147
147
|
|
|
148
148
|
const tasks = [getTask("M001", "S01", "T01")!, getTask("M001", "S01", "T02")!];
|
|
149
149
|
const id = detectPendingEscalation(tasks, base);
|
|
150
|
-
assert.equal(id, "
|
|
150
|
+
assert.equal(id, "T01", "unresolved awaiting_review escalations must pause before later tasks");
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
test("ADR-011 P2: resolveEscalation(accept) marks artifact + clears flags", (t) => {
|
|
@@ -677,26 +677,19 @@ test("ADR-011 P3 #23: concurrent escalations across parallel slices — only the
|
|
|
677
677
|
assert.equal(detectPendingEscalation([getTask("M001", "S02", "T70")!], base), null);
|
|
678
678
|
});
|
|
679
679
|
|
|
680
|
-
test("ADR-011 P3 #24: continueWithDefault
|
|
681
|
-
// Timeline this test pins
|
|
682
|
-
// elapsed wall-clock where the loop keeps running after T80's
|
|
683
|
-
// continueWithDefault=true write):
|
|
680
|
+
test("ADR-011 P3 #24: continueWithDefault requires explicit response before override injection", (t) => {
|
|
681
|
+
// Timeline this test pins:
|
|
684
682
|
//
|
|
685
|
-
// 1. T80 writes continueWithDefault=true → awaiting_review=1
|
|
686
|
-
//
|
|
687
|
-
//
|
|
688
|
-
//
|
|
689
|
-
// 3. The very next prompt build (for T83) claims the override exactly
|
|
690
|
-
// once. T81/T82 are in the past — they must not retroactively
|
|
691
|
-
// receive the injection even though they ran during the window.
|
|
683
|
+
// 1. T80 writes continueWithDefault=true → awaiting_review=1.
|
|
684
|
+
// 2. Scheduler detection pauses on T80 instead of treating silence as
|
|
685
|
+
// consent. Prompt injection still waits until the user responds.
|
|
686
|
+
// 3. After the response, the next prompt build claims the override once.
|
|
692
687
|
const base = makeBase();
|
|
693
688
|
t.after(() => cleanup(base));
|
|
694
689
|
seedCompletedTask(base, "T80");
|
|
695
|
-
seedCompletedTask(base, "T81");
|
|
696
|
-
seedCompletedTask(base, "T82");
|
|
697
690
|
seedCompletedTask(base, "T83");
|
|
698
691
|
|
|
699
|
-
// Phase 1 — T80 escalates with continueWithDefault=true
|
|
692
|
+
// Phase 1 — T80 escalates with continueWithDefault=true.
|
|
700
693
|
writeEscalationArtifact(base, buildEscalationArtifact({
|
|
701
694
|
taskId: "T80", sliceId: "S01", milestoneId: "M001",
|
|
702
695
|
question: "Which cache strategy?", options: sampleOptions,
|
|
@@ -704,21 +697,17 @@ test("ADR-011 P3 #24: continueWithDefault timeout — late user response injects
|
|
|
704
697
|
continueWithDefault: true,
|
|
705
698
|
}));
|
|
706
699
|
|
|
707
|
-
// T80 is awaiting_review (not pending)
|
|
700
|
+
// T80 is awaiting_review (not pending), but scheduler detection still
|
|
701
|
+
// pauses until the user explicitly responds.
|
|
708
702
|
assert.equal(getTask("M001", "S01", "T80")?.escalation_awaiting_review, 1);
|
|
709
703
|
assert.equal(getTask("M001", "S01", "T80")?.escalation_pending, 0);
|
|
710
|
-
assert.equal(detectPendingEscalation([getTask("M001", "S01", "T80")!], base),
|
|
704
|
+
assert.equal(detectPendingEscalation([getTask("M001", "S01", "T80")!], base), "T80");
|
|
711
705
|
|
|
712
|
-
//
|
|
706
|
+
// Prompt injection must still wait for a response.
|
|
713
707
|
assert.equal(
|
|
714
708
|
claimOverrideForInjection(base, "M001", "S01"),
|
|
715
709
|
null,
|
|
716
|
-
"
|
|
717
|
-
);
|
|
718
|
-
assert.equal(
|
|
719
|
-
claimOverrideForInjection(base, "M001", "S01"),
|
|
720
|
-
null,
|
|
721
|
-
"T82's prompt build must also not claim the unresolved awaiting_review",
|
|
710
|
+
"unresolved awaiting_review must not be claimed as a default response",
|
|
722
711
|
);
|
|
723
712
|
|
|
724
713
|
// The response window remains open across N tasks — still no override applied.
|
|
@@ -728,7 +717,7 @@ test("ADR-011 P3 #24: continueWithDefault timeout — late user response injects
|
|
|
728
717
|
"applied_at must stay null throughout the response window",
|
|
729
718
|
);
|
|
730
719
|
|
|
731
|
-
// Phase 2 — user responds
|
|
720
|
+
// Phase 2 — user responds with a different option than the recommendation.
|
|
732
721
|
const resolveResult = resolveEscalation(
|
|
733
722
|
base, "M001", "S01", "T80", "B", "after reviewing, B is the call",
|
|
734
723
|
);
|
|
@@ -53,6 +53,24 @@ test('runExecSandbox: captures stdout, persists artifacts, returns digest', asyn
|
|
|
53
53
|
}
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
+
test('runExecSandbox: persists optional request metadata', async () => {
|
|
57
|
+
const base = freshBase();
|
|
58
|
+
try {
|
|
59
|
+
const result = await runExecSandbox(
|
|
60
|
+
{
|
|
61
|
+
runtime: 'bash',
|
|
62
|
+
script: 'echo metadata-ok',
|
|
63
|
+
metadata: { kind: 'uat_exec', intent: 'uat-artifact-check' },
|
|
64
|
+
},
|
|
65
|
+
baseOpts(base),
|
|
66
|
+
);
|
|
67
|
+
const meta = JSON.parse(readFileSync(result.meta_path, 'utf-8')) as Record<string, unknown>;
|
|
68
|
+
assert.deepEqual(meta.metadata, { kind: 'uat_exec', intent: 'uat-artifact-check' });
|
|
69
|
+
} finally {
|
|
70
|
+
cleanup(base);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
56
74
|
test('runExecSandbox: enforces stdout cap and marks truncation', async () => {
|
|
57
75
|
const base = freshBase();
|
|
58
76
|
try {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import { registerExecTools } from "../bootstrap/exec-tools.ts";
|
|
5
|
+
import { executeUatExec } from "../tools/exec-tool.ts";
|
|
6
|
+
import type { ExecSandboxRequest, ExecSandboxResult } from "../exec-sandbox.ts";
|
|
7
|
+
|
|
8
|
+
function makeExecResult(request: ExecSandboxRequest): ExecSandboxResult {
|
|
9
|
+
return {
|
|
10
|
+
id: "exec-1",
|
|
11
|
+
runtime: request.runtime,
|
|
12
|
+
exit_code: 0,
|
|
13
|
+
signal: null,
|
|
14
|
+
timed_out: false,
|
|
15
|
+
duration_ms: 1,
|
|
16
|
+
stdout_bytes: 12,
|
|
17
|
+
stderr_bytes: 0,
|
|
18
|
+
stdout_truncated: false,
|
|
19
|
+
stderr_truncated: false,
|
|
20
|
+
stdout_path: ".gsd/exec/exec-1.stdout",
|
|
21
|
+
stderr_path: ".gsd/exec/exec-1.stderr",
|
|
22
|
+
meta_path: ".gsd/exec/exec-1.meta.json",
|
|
23
|
+
digest: "check passed",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
test("executeUatExec accepts evidence-mode aliases for intent", async () => {
|
|
28
|
+
const requests: ExecSandboxRequest[] = [];
|
|
29
|
+
const result = await executeUatExec(
|
|
30
|
+
{
|
|
31
|
+
milestoneId: "M001",
|
|
32
|
+
sliceId: "S01",
|
|
33
|
+
checkId: "UAT-PRE",
|
|
34
|
+
intent: "artifact",
|
|
35
|
+
runtime: "bash",
|
|
36
|
+
script: "printf ok",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
baseDir: "/tmp/gsd-uat-exec-test",
|
|
40
|
+
preferences: null,
|
|
41
|
+
run: async (request) => {
|
|
42
|
+
requests.push(request);
|
|
43
|
+
return makeExecResult(request);
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
assert.equal(result.isError, false);
|
|
49
|
+
assert.equal(result.details?.operation, "gsd_uat_exec");
|
|
50
|
+
assert.equal(result.details?.intent, "uat-artifact-check");
|
|
51
|
+
assert.equal(requests[0]?.metadata?.intent, "uat-artifact-check");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("registerExecTools exposes gsd_uat_exec intent as recoverable string schema", () => {
|
|
55
|
+
const tools: Array<{ name: string; parameters: any }> = [];
|
|
56
|
+
registerExecTools({
|
|
57
|
+
registerTool: (tool: { name: string; parameters: any }) => {
|
|
58
|
+
tools.push(tool);
|
|
59
|
+
},
|
|
60
|
+
} as any);
|
|
61
|
+
|
|
62
|
+
const tool = tools.find((registeredTool) => registeredTool.name === "gsd_uat_exec");
|
|
63
|
+
assert.ok(tool, "gsd_uat_exec should be registered");
|
|
64
|
+
const intentSchema = tool.parameters.properties.intent;
|
|
65
|
+
assert.equal(intentSchema.type, "string");
|
|
66
|
+
assert.equal("anyOf" in intentSchema, false);
|
|
67
|
+
assert.match(intentSchema.description, /uat-artifact-check/);
|
|
68
|
+
assert.match(intentSchema.description, /artifact/);
|
|
69
|
+
});
|
|
@@ -41,3 +41,23 @@ test("forensics prompt routes issue creation through bash tool, not github_issue
|
|
|
41
41
|
"Prompt must instruct use of the bash tool for issue creation",
|
|
42
42
|
);
|
|
43
43
|
});
|
|
44
|
+
|
|
45
|
+
test("forensics prompt provides paste-once fallback when bash is unavailable", () => {
|
|
46
|
+
const prompt = readPrompt("forensics");
|
|
47
|
+
|
|
48
|
+
assert.match(
|
|
49
|
+
prompt,
|
|
50
|
+
/If `bash` is unavailable/i,
|
|
51
|
+
"Prompt must branch when bash cannot be activated",
|
|
52
|
+
);
|
|
53
|
+
assert.match(
|
|
54
|
+
prompt,
|
|
55
|
+
/paste-once shell script/i,
|
|
56
|
+
"Prompt must provide a user-runnable fallback instead of an impossible tool call",
|
|
57
|
+
);
|
|
58
|
+
assert.match(
|
|
59
|
+
prompt,
|
|
60
|
+
/Searching closed issues for possible duplicates/i,
|
|
61
|
+
"Fallback script must preserve the duplicate-search step for the user",
|
|
62
|
+
);
|
|
63
|
+
});
|
|
@@ -24,13 +24,16 @@ test("forensics prompt renders compact investigation and issue routing guidance"
|
|
|
24
24
|
forensicData: "stuck-detected event for execute-task/M001/S01/T01",
|
|
25
25
|
gsdSourceDir: process.env.GSD_TEST_WORKSPACE_ROOT ?? process.cwd(),
|
|
26
26
|
dedupSection: "No duplicate issue found.",
|
|
27
|
+
toolingSection: "## Filing Tool Availability\n\n- `bash`: available\n- `write`: available",
|
|
27
28
|
});
|
|
28
29
|
|
|
29
30
|
assert.match(prompt, /Investigation Protocol/);
|
|
31
|
+
assert.match(prompt, /Filing Tool Availability/);
|
|
30
32
|
assert.match(prompt, /gsd_milestone_status/);
|
|
31
33
|
assert.match(prompt, /sqlite3 .gsd\/gsd.db/);
|
|
32
34
|
assert.match(prompt, /gh issue create --repo open-gsd\/gsd-pi/);
|
|
33
35
|
assert.match(prompt, /Do NOT use the `github_issues` tool/);
|
|
36
|
+
assert.match(prompt, /paste-once shell script/);
|
|
34
37
|
assert.match(prompt, /Redaction Rules/);
|
|
35
38
|
assert.doesNotMatch(prompt, /\{\{[a-zA-Z][a-zA-Z0-9_]*\}\}/);
|
|
36
39
|
});
|