@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.75048e7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -2
- package/dist/help-text.js +10 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
- package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
- package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/dist/resources/extensions/browser-tools/index.js +57 -9
- package/dist/resources/extensions/browser-tools/package.json +5 -1
- package/dist/resources/extensions/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 +55 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
- package/dist/resources/extensions/gsd/auto-prompts.js +72 -22
- package/dist/resources/extensions/gsd/auto-recovery.js +7 -8
- 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 +18 -65
- package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
- package/dist/resources/extensions/gsd/auto.js +31 -6
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -4
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +56 -20
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +33 -38
- package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
- package/dist/resources/extensions/gsd/commands/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 +119 -176
- 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/milestone-closeout.js +3 -1
- package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +33 -23
- 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/recovery-classification.js +20 -0
- 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-contract.js +5 -0
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +143 -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 +483 -6
- package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
- 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 -73
- 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 +5 -5
- 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 +5 -5
- 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/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +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 +42 -3
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
- package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +6 -1
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/api-registry.d.ts +2 -0
- package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
- package/packages/pi-ai/dist/api-registry.js +23 -0
- package/packages/pi-ai/dist/api-registry.js.map +1 -1
- package/packages/pi-ai/dist/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 +411 -39
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +504 -153
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/stream.js +6 -6
- package/packages/pi-ai/dist/stream.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/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/dist/core/tools/bash.js +2 -2
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
- package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/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 +67 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
- package/src/resources/extensions/gsd/auto-prompts.ts +106 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +7 -7
- 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 +43 -73
- package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
- package/src/resources/extensions/gsd/auto.ts +47 -5
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +96 -4
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +81 -25
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +70 -63
- package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
- package/src/resources/extensions/gsd/commands/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 +215 -217
- 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/milestone-closeout.ts +3 -1
- package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
- package/src/resources/extensions/gsd/preferences-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 +33 -23
- 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/recovery-classification.ts +20 -0
- package/src/resources/extensions/gsd/rule-registry.ts +558 -58
- package/src/resources/extensions/gsd/rule-types.ts +2 -0
- package/src/resources/extensions/gsd/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-recovery.test.ts +10 -2
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-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/auto-warning-noise-regression.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
- package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
- package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/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-complete-milestone-guard.test.ts +40 -1
- 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/gate-1b-orphan-discrimination.test.ts +31 -79
- 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-session-isolation.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +72 -10
- package/src/resources/extensions/gsd/tests/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/merge-closeout-consistency-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/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 +83 -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 +79 -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/run-uat-composer.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/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 +493 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +40 -0
- package/src/resources/extensions/gsd/tool-contract.ts +6 -0
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +223 -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 +589 -8
- 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/unit-tool-contracts.ts +186 -0
- 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 -73
- 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/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
- /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_ssgManifest.js +0 -0
|
@@ -49,6 +49,8 @@ import {
|
|
|
49
49
|
import { loadEffectiveGSDPreferences, getIsolationMode } from "./preferences.js";
|
|
50
50
|
import { invalidateAllCaches } from "./cache.js";
|
|
51
51
|
import { resolveMilestoneFile } from "./paths.js";
|
|
52
|
+
import { getMilestone, insertMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
|
|
53
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
52
54
|
import type { WorktreeStateProjection } from "./worktree-state-projection.js";
|
|
53
55
|
import { createWorkspace, scopeMilestone } from "./workspace.js";
|
|
54
56
|
// ADR-016 phase 2 / C1 (#5624): file-system + git-CLI leaf primitives
|
|
@@ -85,6 +87,28 @@ export function resetRecentWorktreeMergeFailuresForTest(): void {
|
|
|
85
87
|
recentWorktreeMergeFailures.clear();
|
|
86
88
|
}
|
|
87
89
|
|
|
90
|
+
function markMilestoneClosedAfterMerge(milestoneId: string, completedAt: string): void {
|
|
91
|
+
if (!isDbAvailable()) return;
|
|
92
|
+
try {
|
|
93
|
+
const existing = getMilestone(milestoneId);
|
|
94
|
+
if (!existing) {
|
|
95
|
+
insertMilestone({ id: milestoneId, title: milestoneId, status: "complete" });
|
|
96
|
+
updateMilestoneStatus(milestoneId, "complete", completedAt);
|
|
97
|
+
invalidateAllCaches();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!isClosedStatus(existing.status)) {
|
|
101
|
+
updateMilestoneStatus(milestoneId, "complete", completedAt);
|
|
102
|
+
invalidateAllCaches();
|
|
103
|
+
}
|
|
104
|
+
} catch (err) {
|
|
105
|
+
logWarning(
|
|
106
|
+
"worktree",
|
|
107
|
+
`Merged ${milestoneId} but failed to mark milestone complete in DB: ${err instanceof Error ? err.message : String(err)}`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
88
112
|
// ─── Types ───────────────────────────────────────────────────────────────
|
|
89
113
|
|
|
90
114
|
export interface NotifyCtx {
|
|
@@ -1716,6 +1740,8 @@ export class WorktreeLifecycle {
|
|
|
1716
1740
|
|
|
1717
1741
|
// #4764 — record merge completion. Only reaches here when an actual
|
|
1718
1742
|
// merge ran; failure paths throw out before this point.
|
|
1743
|
+
const mergeCompletedAt = new Date().toISOString();
|
|
1744
|
+
markMilestoneClosedAfterMerge(milestoneId, mergeCompletedAt);
|
|
1719
1745
|
try {
|
|
1720
1746
|
emitWorktreeMerged(
|
|
1721
1747
|
this.s.originalBasePath || this.s.basePath,
|
|
@@ -103,6 +103,8 @@ const CHILD_ENV_ALLOWLIST = new Set([
|
|
|
103
103
|
"XDG_CACHE_HOME",
|
|
104
104
|
]);
|
|
105
105
|
|
|
106
|
+
const MCP_STDERR_MAX_BYTES = 4096;
|
|
107
|
+
|
|
106
108
|
let cachedStatus: ManagedMcpStatus | null = null;
|
|
107
109
|
let cachedStatusKey = "";
|
|
108
110
|
|
|
@@ -231,6 +233,34 @@ export function resolveMcpString(value: string): string {
|
|
|
231
233
|
);
|
|
232
234
|
}
|
|
233
235
|
|
|
236
|
+
function captureTransportStderr(transport: StdioClientTransport): () => string {
|
|
237
|
+
const chunks: Buffer[] = [];
|
|
238
|
+
let totalBytes = 0;
|
|
239
|
+
const stderr = transport.stderr;
|
|
240
|
+
stderr?.on("data", (chunk: Buffer | string) => {
|
|
241
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
|
|
242
|
+
totalBytes += buffer.byteLength;
|
|
243
|
+
chunks.push(buffer);
|
|
244
|
+
while (chunks.reduce((sum, entry) => sum + entry.byteLength, 0) > MCP_STDERR_MAX_BYTES) {
|
|
245
|
+
chunks.shift();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return () => {
|
|
250
|
+
const captured = Buffer.concat(chunks).toString("utf-8").trim();
|
|
251
|
+
if (!captured) return "";
|
|
252
|
+
return totalBytes > MCP_STDERR_MAX_BYTES
|
|
253
|
+
? `[stderr truncated to last ${MCP_STDERR_MAX_BYTES} bytes]\n${captured}`
|
|
254
|
+
: captured;
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function formatConnectionError(error: unknown, stderr: string): string {
|
|
259
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
260
|
+
if (!stderr) return message;
|
|
261
|
+
return `${message}\nStderr:\n${stderr}`;
|
|
262
|
+
}
|
|
263
|
+
|
|
234
264
|
export function upsertProjectLocalMcpServer(
|
|
235
265
|
input: ManagedMcpServerInput,
|
|
236
266
|
options: { projectDir?: string; previousName?: string } = {},
|
|
@@ -348,6 +378,7 @@ export async function testMcpServerConnection(
|
|
|
348
378
|
|
|
349
379
|
const client = new Client({ name: "gsd", version: "1.0.0" });
|
|
350
380
|
let transport: StdioClientTransport | StreamableHTTPClientTransport | undefined;
|
|
381
|
+
let readCapturedStderr: (() => string) | undefined;
|
|
351
382
|
const timeout = options.timeoutMs ?? 30_000;
|
|
352
383
|
try {
|
|
353
384
|
if (config.transport === "stdio") {
|
|
@@ -358,6 +389,7 @@ export async function testMcpServerConnection(
|
|
|
358
389
|
cwd: config.cwd,
|
|
359
390
|
stderr: "pipe",
|
|
360
391
|
});
|
|
392
|
+
readCapturedStderr = captureTransportStderr(transport);
|
|
361
393
|
} else {
|
|
362
394
|
const resolvedUrl = resolveMcpString(config.url ?? "");
|
|
363
395
|
transport = new StreamableHTTPClientTransport(
|
|
@@ -385,7 +417,7 @@ export async function testMcpServerConnection(
|
|
|
385
417
|
toolCount: 0,
|
|
386
418
|
tools: [],
|
|
387
419
|
warnings: config.envWarnings,
|
|
388
|
-
error: error
|
|
420
|
+
error: formatConnectionError(error, readCapturedStderr?.() ?? ""),
|
|
389
421
|
};
|
|
390
422
|
} finally {
|
|
391
423
|
if (transport) {
|
|
@@ -163,3 +163,38 @@ test("MCP connection test performs handshake and tools/list without invoking too
|
|
|
163
163
|
cleanup();
|
|
164
164
|
}
|
|
165
165
|
});
|
|
166
|
+
|
|
167
|
+
test("MCP connection test includes stdio stderr when discovery fails", async () => {
|
|
168
|
+
const { projectDir, cleanup } = makeProject();
|
|
169
|
+
try {
|
|
170
|
+
const serverPath = join(projectDir, "crashing-mcp-server.mjs");
|
|
171
|
+
writeFileSync(
|
|
172
|
+
serverPath,
|
|
173
|
+
[
|
|
174
|
+
'console.error("fatal browser bootstrap failed");',
|
|
175
|
+
'console.error("missing browser profile");',
|
|
176
|
+
"process.exit(1);",
|
|
177
|
+
].join("\n"),
|
|
178
|
+
"utf-8",
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const result = await testMcpServerConnection({
|
|
182
|
+
name: "crashing",
|
|
183
|
+
transport: "stdio",
|
|
184
|
+
sourcePath: join(projectDir, ".gsd", "mcp.json"),
|
|
185
|
+
sourceKind: "project-local",
|
|
186
|
+
disabled: false,
|
|
187
|
+
command: process.execPath,
|
|
188
|
+
args: [serverPath],
|
|
189
|
+
envWarnings: [],
|
|
190
|
+
} satisfies ManagedMcpServerConfig, { projectDir, timeoutMs: 10_000 });
|
|
191
|
+
|
|
192
|
+
assert.equal(result.ok, false);
|
|
193
|
+
assert.match(result.error ?? "", /Connection closed|closed|exit/i);
|
|
194
|
+
assert.match(result.error ?? "", /Stderr:/);
|
|
195
|
+
assert.match(result.error ?? "", /fatal browser bootstrap failed/);
|
|
196
|
+
assert.match(result.error ?? "", /missing browser profile/);
|
|
197
|
+
} finally {
|
|
198
|
+
cleanup();
|
|
199
|
+
}
|
|
200
|
+
});
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { basename, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
export const GSD_BROWSER_MCP_SERVER_NAME = "gsd-browser";
|
|
9
|
+
|
|
10
|
+
export interface GsdBrowserMcpLaunchConfig {
|
|
11
|
+
serverName: string;
|
|
12
|
+
command: string;
|
|
13
|
+
args: string[];
|
|
14
|
+
cwd: string;
|
|
15
|
+
env?: Record<string, string>;
|
|
16
|
+
projectRoot: string;
|
|
17
|
+
sessionName: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface GsdBrowserMcpLaunchOptions {
|
|
21
|
+
sessionName?: string;
|
|
22
|
+
sessionSuffix?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseJsonEnv<T>(env: NodeJS.ProcessEnv, name: string): T | undefined {
|
|
26
|
+
const raw = env[name];
|
|
27
|
+
if (!raw) return undefined;
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(raw) as T;
|
|
30
|
+
} catch {
|
|
31
|
+
throw new Error(`Invalid JSON in ${name}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function sanitizeSessionSegment(value: string): string {
|
|
36
|
+
return value
|
|
37
|
+
.replace(/[^a-zA-Z0-9._-]+/g, "-")
|
|
38
|
+
.replace(/^-+|-+$/g, "")
|
|
39
|
+
.slice(0, 40);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function compareSemverLocal(a: string, b: string): number {
|
|
43
|
+
const left = a.split(".").map(Number);
|
|
44
|
+
const right = b.split(".").map(Number);
|
|
45
|
+
for (let index = 0; index < Math.max(left.length, right.length); index++) {
|
|
46
|
+
const leftValue = left[index] || 0;
|
|
47
|
+
const rightValue = right[index] || 0;
|
|
48
|
+
if (leftValue > rightValue) return 1;
|
|
49
|
+
if (leftValue < rightValue) return -1;
|
|
50
|
+
}
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseGsdBrowserVersion(output: string): string | null {
|
|
55
|
+
return output.match(/\b(\d+\.\d+\.\d+)\b/)?.[1] ?? null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveBundledGsdBrowserPackageVersion(): string | null {
|
|
59
|
+
try {
|
|
60
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
61
|
+
const packageJsonPath = requireFromHere.resolve("@opengsd/gsd-browser/package.json");
|
|
62
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as { version?: unknown };
|
|
63
|
+
return typeof pkg.version === "string" ? parseGsdBrowserVersion(pkg.version) : null;
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function resolvePathGsdBrowserVersion(env: NodeJS.ProcessEnv): string | null {
|
|
70
|
+
const explicit = env.GSD_BROWSER_PATH_VERSION?.trim();
|
|
71
|
+
if (explicit) return parseGsdBrowserVersion(explicit);
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
return parseGsdBrowserVersion(execFileSync("gsd-browser", ["--version"], {
|
|
75
|
+
encoding: "utf-8",
|
|
76
|
+
env,
|
|
77
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
78
|
+
timeout: 2000,
|
|
79
|
+
}));
|
|
80
|
+
} catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function shouldPreferPathGsdBrowser(env: NodeJS.ProcessEnv): boolean {
|
|
86
|
+
const pathVersion = resolvePathGsdBrowserVersion(env);
|
|
87
|
+
if (!pathVersion) return false;
|
|
88
|
+
|
|
89
|
+
const bundledVersion = resolveBundledGsdBrowserPackageVersion();
|
|
90
|
+
return !bundledVersion || compareSemverLocal(pathVersion, bundledVersion) > 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function resolveBundledGsdBrowserCliPath(env: NodeJS.ProcessEnv = process.env): string | null {
|
|
94
|
+
const explicit = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
|
|
95
|
+
if (explicit) return explicit;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
99
|
+
const packageJsonPath = requireFromHere.resolve("@opengsd/gsd-browser/package.json");
|
|
100
|
+
const candidate = resolve(packageJsonPath, "..", "bin", "gsd-browser");
|
|
101
|
+
if (existsSync(candidate)) return candidate;
|
|
102
|
+
} catch {
|
|
103
|
+
// Fall through to path candidates for source/dist layouts.
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const candidates = [
|
|
107
|
+
resolve(fileURLToPath(new URL("../../../../node_modules/@opengsd/gsd-browser/bin/gsd-browser", import.meta.url))),
|
|
108
|
+
resolve(fileURLToPath(new URL("../../../../node_modules/.bin/gsd-browser", import.meta.url))),
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
for (const candidate of candidates) {
|
|
112
|
+
if (existsSync(candidate)) return candidate;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function buildGsdBrowserSessionName(projectRoot: string, suffix?: string): string {
|
|
119
|
+
const resolvedProjectRoot = resolve(projectRoot);
|
|
120
|
+
const base = sanitizeSessionSegment(basename(resolvedProjectRoot)) || "project";
|
|
121
|
+
const hash = createHash("sha1").update(resolvedProjectRoot).digest("hex").slice(0, 8);
|
|
122
|
+
const cleanSuffix = suffix ? sanitizeSessionSegment(suffix) : "";
|
|
123
|
+
return cleanSuffix ? `gsd-${base}-${hash}-${cleanSuffix}` : `gsd-${base}-${hash}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function resolveGsdBrowserMcpLaunchConfig(
|
|
127
|
+
projectRoot: string,
|
|
128
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
129
|
+
options: GsdBrowserMcpLaunchOptions = {},
|
|
130
|
+
): GsdBrowserMcpLaunchConfig {
|
|
131
|
+
const resolvedProjectRoot = resolve(projectRoot);
|
|
132
|
+
const serverName = env.GSD_BROWSER_MCP_NAME?.trim() || GSD_BROWSER_MCP_SERVER_NAME;
|
|
133
|
+
const explicitArgs = parseJsonEnv<unknown>(env, "GSD_BROWSER_MCP_ARGS");
|
|
134
|
+
const explicitEnv = parseJsonEnv<Record<string, string>>(env, "GSD_BROWSER_MCP_ENV");
|
|
135
|
+
const explicitCommand = env.GSD_BROWSER_MCP_COMMAND?.trim();
|
|
136
|
+
const explicitCliPath = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
|
|
137
|
+
const preferPathCli = !explicitCommand && !explicitCliPath && shouldPreferPathGsdBrowser(env);
|
|
138
|
+
const bundledCliPath = !explicitCommand && !explicitCliPath && !preferPathCli
|
|
139
|
+
? resolveBundledGsdBrowserCliPath(env)
|
|
140
|
+
: null;
|
|
141
|
+
const sessionName =
|
|
142
|
+
options.sessionName?.trim() || buildGsdBrowserSessionName(resolvedProjectRoot, options.sessionSuffix);
|
|
143
|
+
const command =
|
|
144
|
+
explicitCommand
|
|
145
|
+
|| explicitCliPath
|
|
146
|
+
|| (preferPathCli ? "gsd-browser" : undefined)
|
|
147
|
+
|| (bundledCliPath ? process.execPath : undefined)
|
|
148
|
+
|| "gsd-browser";
|
|
149
|
+
const args = Array.isArray(explicitArgs) && explicitArgs.length > 0
|
|
150
|
+
? explicitArgs.map(String)
|
|
151
|
+
: [
|
|
152
|
+
...(bundledCliPath ? [bundledCliPath] : []),
|
|
153
|
+
"mcp",
|
|
154
|
+
"--session",
|
|
155
|
+
sessionName,
|
|
156
|
+
"--identity-scope",
|
|
157
|
+
"project",
|
|
158
|
+
"--identity-project",
|
|
159
|
+
resolvedProjectRoot,
|
|
160
|
+
];
|
|
161
|
+
const cwd = env.GSD_BROWSER_MCP_CWD?.trim() || resolvedProjectRoot;
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
serverName,
|
|
165
|
+
command,
|
|
166
|
+
args,
|
|
167
|
+
cwd,
|
|
168
|
+
...(explicitEnv ? { env: explicitEnv } : {}),
|
|
169
|
+
projectRoot: resolvedProjectRoot,
|
|
170
|
+
sessionName,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
// gsd-pi + Gate 1b recovery bound corrections — regression tests for the two bugs
|
|
2
|
-
// found in peer review of the H1 fix (commit f0e1d42a2):
|
|
3
|
-
// 1. Escalation message must describe /gsd (counter reset) AND /gsd-debug (diagnose).
|
|
4
|
-
// 2. planBlockedRecoveryCount must NOT increment when pi.sendMessage throws.
|
|
5
|
-
|
|
6
|
-
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
7
|
-
import assert from "node:assert/strict";
|
|
8
|
-
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
9
|
-
import { join } from "node:path";
|
|
10
|
-
import { tmpdir } from "node:os";
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
checkAutoStartAfterDiscuss,
|
|
14
|
-
setPendingAutoStart,
|
|
15
|
-
clearPendingAutoStart,
|
|
16
|
-
_getPendingAutoStart,
|
|
17
|
-
} from "../guided-flow.ts";
|
|
18
|
-
import { drainLogs } from "../workflow-logger.ts";
|
|
19
|
-
import {
|
|
20
|
-
openDatabase,
|
|
21
|
-
closeDatabase,
|
|
22
|
-
insertMilestone,
|
|
23
|
-
} from "../gsd-db.ts";
|
|
24
|
-
|
|
25
|
-
// ─── Harness ───────────────────────────────────────────────────────────────
|
|
26
|
-
|
|
27
|
-
interface MockCapture {
|
|
28
|
-
notifies: Array<{ msg: string; level: string }>;
|
|
29
|
-
messages: Array<{ payload: any; options: any }>;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function mkCapture(): MockCapture {
|
|
33
|
-
return { notifies: [], messages: [] };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function mkCtx(cap: MockCapture): any {
|
|
37
|
-
return {
|
|
38
|
-
ui: {
|
|
39
|
-
notify: (msg: string, level: string) => {
|
|
40
|
-
cap.notifies.push({ msg, level });
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Returns a pi stub whose sendMessage throws on the first call, succeeds after. */
|
|
47
|
-
function mkPiThrowOnce(cap: MockCapture): any {
|
|
48
|
-
let callCount = 0;
|
|
49
|
-
return {
|
|
50
|
-
sendMessage: (payload: any, options: any) => {
|
|
51
|
-
callCount += 1;
|
|
52
|
-
if (callCount === 1) {
|
|
53
|
-
throw new Error("transient network error");
|
|
54
|
-
}
|
|
55
|
-
cap.messages.push({ payload, options });
|
|
56
|
-
},
|
|
57
|
-
setActiveTools: () => undefined,
|
|
58
|
-
getActiveTools: () => [],
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function mkPi(cap: MockCapture): any {
|
|
63
|
-
return {
|
|
64
|
-
sendMessage: (payload: any, options: any) => {
|
|
65
|
-
cap.messages.push({ payload, options });
|
|
66
|
-
},
|
|
67
|
-
setActiveTools: () => undefined,
|
|
68
|
-
getActiveTools: () => [],
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function mkBase(): string {
|
|
73
|
-
const base = mkdtempSync(join(tmpdir(), "gsd-gate1b-corrections-"));
|
|
74
|
-
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
75
|
-
writeFileSync(
|
|
76
|
-
join(base, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
|
|
77
|
-
"# M001: Corrections Test\n\nContext written by discuss phase.\n",
|
|
78
|
-
);
|
|
79
|
-
return base;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// ─── Tests ─────────────────────────────────────────────────────────────────
|
|
83
|
-
|
|
84
|
-
describe("Gate 1b recovery bound corrections", () => {
|
|
85
|
-
let base: string;
|
|
86
|
-
let cap: MockCapture;
|
|
87
|
-
|
|
88
|
-
beforeEach(() => {
|
|
89
|
-
clearPendingAutoStart();
|
|
90
|
-
drainLogs();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
afterEach(() => {
|
|
94
|
-
closeDatabase();
|
|
95
|
-
clearPendingAutoStart();
|
|
96
|
-
if (base) {
|
|
97
|
-
rmSync(base, { recursive: true, force: true });
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// ── Fix 1: escalation message ──────────────────────────────────────────
|
|
102
|
-
|
|
103
|
-
test("escalation message describes /gsd for reset AND /gsd-debug for diagnosis", () => {
|
|
104
|
-
base = mkBase();
|
|
105
|
-
openDatabase(":memory:");
|
|
106
|
-
insertMilestone({ id: "M001", title: "Corrections Test", status: "queued" });
|
|
107
|
-
|
|
108
|
-
cap = mkCapture();
|
|
109
|
-
setPendingAutoStart(base, {
|
|
110
|
-
basePath: base,
|
|
111
|
-
milestoneId: "M001",
|
|
112
|
-
ctx: mkCtx(cap),
|
|
113
|
-
pi: mkPi(cap),
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Exhaust the recovery budget (MAX = 3)
|
|
117
|
-
checkAutoStartAfterDiscuss(); // count → 1
|
|
118
|
-
checkAutoStartAfterDiscuss(); // count → 2
|
|
119
|
-
checkAutoStartAfterDiscuss(); // count → 3
|
|
120
|
-
|
|
121
|
-
cap.notifies = [];
|
|
122
|
-
drainLogs();
|
|
123
|
-
|
|
124
|
-
// This call hits the cap and must escalate
|
|
125
|
-
const result = checkAutoStartAfterDiscuss();
|
|
126
|
-
assert.equal(result, false, "escalation call must return false");
|
|
127
|
-
|
|
128
|
-
const errorNotify = cap.notifies.find((n) => n.level === "error");
|
|
129
|
-
assert.ok(errorNotify, "escalation must emit a notify with level 'error'");
|
|
130
|
-
|
|
131
|
-
// Must mention /gsd with reset semantics
|
|
132
|
-
assert.match(
|
|
133
|
-
errorNotify.msg,
|
|
134
|
-
/\/gsd\b/,
|
|
135
|
-
"escalation message must reference /gsd (the command that resets the counter)",
|
|
136
|
-
);
|
|
137
|
-
assert.match(
|
|
138
|
-
errorNotify.msg,
|
|
139
|
-
/reset/i,
|
|
140
|
-
"escalation message must use the word 'reset' so users know /gsd resets the counter",
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
// Must also mention /gsd-debug
|
|
144
|
-
assert.match(
|
|
145
|
-
errorNotify.msg,
|
|
146
|
-
/\/gsd-debug/i,
|
|
147
|
-
"escalation message must also reference /gsd-debug for diagnosis",
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
// Must NOT suggest /gsd-debug alone as the sole remediation
|
|
151
|
-
assert.doesNotMatch(
|
|
152
|
-
errorNotify.msg,
|
|
153
|
-
/^[^/]*\/gsd-debug[^/]*$/,
|
|
154
|
-
"escalation message must not mention /gsd-debug as the only option",
|
|
155
|
-
);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// ── Fix 2: counter ordering ────────────────────────────────────────────
|
|
159
|
-
|
|
160
|
-
test("counter stays at 0 when sendMessage throws on the first call", () => {
|
|
161
|
-
base = mkBase();
|
|
162
|
-
openDatabase(":memory:");
|
|
163
|
-
insertMilestone({ id: "M001", title: "Corrections Test", status: "queued" });
|
|
164
|
-
|
|
165
|
-
cap = mkCapture();
|
|
166
|
-
setPendingAutoStart(base, {
|
|
167
|
-
basePath: base,
|
|
168
|
-
milestoneId: "M001",
|
|
169
|
-
ctx: mkCtx(cap),
|
|
170
|
-
pi: mkPiThrowOnce(cap),
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
// First call: sendMessage throws — counter must NOT increment
|
|
174
|
-
const result = checkAutoStartAfterDiscuss();
|
|
175
|
-
assert.equal(result, false, "must return false even when sendMessage throws");
|
|
176
|
-
|
|
177
|
-
const entry = _getPendingAutoStart(base);
|
|
178
|
-
assert.ok(entry, "entry must still exist after a failed sendMessage");
|
|
179
|
-
assert.equal(
|
|
180
|
-
entry.planBlockedRecoveryCount,
|
|
181
|
-
0,
|
|
182
|
-
"counter must remain 0 when sendMessage throws — no budget burned by transient failure",
|
|
183
|
-
);
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
test("counter increments to 1 on the second call when first sendMessage threw", () => {
|
|
187
|
-
base = mkBase();
|
|
188
|
-
openDatabase(":memory:");
|
|
189
|
-
insertMilestone({ id: "M001", title: "Corrections Test", status: "queued" });
|
|
190
|
-
|
|
191
|
-
cap = mkCapture();
|
|
192
|
-
setPendingAutoStart(base, {
|
|
193
|
-
basePath: base,
|
|
194
|
-
milestoneId: "M001",
|
|
195
|
-
ctx: mkCtx(cap),
|
|
196
|
-
pi: mkPiThrowOnce(cap),
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
checkAutoStartAfterDiscuss(); // sendMessage throws → count stays 0
|
|
200
|
-
|
|
201
|
-
const entryAfterThrow = _getPendingAutoStart(base);
|
|
202
|
-
assert.equal(entryAfterThrow!.planBlockedRecoveryCount, 0, "count is 0 after throw");
|
|
203
|
-
|
|
204
|
-
checkAutoStartAfterDiscuss(); // sendMessage succeeds → count becomes 1
|
|
205
|
-
assert.equal(cap.messages.length, 1, "second call must produce one successful sendMessage");
|
|
206
|
-
|
|
207
|
-
const entryAfterSuccess = _getPendingAutoStart(base);
|
|
208
|
-
assert.equal(
|
|
209
|
-
entryAfterSuccess!.planBlockedRecoveryCount,
|
|
210
|
-
1,
|
|
211
|
-
"counter must be 1 after first successful dispatch",
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
test("3 successful sendMessage calls exhaust the budget; 4th emits escalation notify", () => {
|
|
216
|
-
base = mkBase();
|
|
217
|
-
openDatabase(":memory:");
|
|
218
|
-
insertMilestone({ id: "M001", title: "Corrections Test", status: "queued" });
|
|
219
|
-
|
|
220
|
-
cap = mkCapture();
|
|
221
|
-
setPendingAutoStart(base, {
|
|
222
|
-
basePath: base,
|
|
223
|
-
milestoneId: "M001",
|
|
224
|
-
ctx: mkCtx(cap),
|
|
225
|
-
pi: mkPi(cap),
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
// Three successful recoveries
|
|
229
|
-
checkAutoStartAfterDiscuss(); // count → 1
|
|
230
|
-
checkAutoStartAfterDiscuss(); // count → 2
|
|
231
|
-
checkAutoStartAfterDiscuss(); // count → 3
|
|
232
|
-
|
|
233
|
-
const entry = _getPendingAutoStart(base);
|
|
234
|
-
assert.equal(entry!.planBlockedRecoveryCount, 3, "counter must be 3 after three successes");
|
|
235
|
-
assert.equal(cap.messages.length, 3, "three sendMessage calls must have occurred");
|
|
236
|
-
|
|
237
|
-
// Fourth call hits the cap
|
|
238
|
-
cap.notifies = [];
|
|
239
|
-
cap.messages = [];
|
|
240
|
-
const resultAtCap = checkAutoStartAfterDiscuss();
|
|
241
|
-
assert.equal(resultAtCap, false, "4th call must return false");
|
|
242
|
-
assert.equal(cap.messages.length, 0, "4th call must NOT call sendMessage");
|
|
243
|
-
const errorNotify = cap.notifies.find((n) => n.level === "error");
|
|
244
|
-
assert.ok(errorNotify, "4th call must emit escalation notify with level 'error'");
|
|
245
|
-
});
|
|
246
|
-
});
|