@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
|
@@ -137,7 +137,9 @@ export type ContextModePolicy =
|
|
|
137
137
|
* edits project markdown outside .gsd/.
|
|
138
138
|
* - "verification"
|
|
139
139
|
* — Read tools + Bash for verification commands, writes
|
|
140
|
-
* restricted to .gsd
|
|
140
|
+
* restricted to .gsd/**. Subagent dispatch is denied unless
|
|
141
|
+
* `allowedSubagents` opts a unit into controlled read-only
|
|
142
|
+
* specialist delegation.
|
|
141
143
|
*
|
|
142
144
|
* The allowlist for "docs" is declared per-manifest rather than hardcoded so
|
|
143
145
|
* projects with non-standard doc layouts can extend it without forking the
|
|
@@ -150,7 +152,7 @@ export type ToolsPolicy =
|
|
|
150
152
|
| { readonly mode: "planning" }
|
|
151
153
|
| { readonly mode: "planning-dispatch"; readonly allowedSubagents: readonly string[] }
|
|
152
154
|
| { readonly mode: "docs"; readonly allowedPathGlobs: readonly string[] }
|
|
153
|
-
| { readonly mode: "verification" };
|
|
155
|
+
| { readonly mode: "verification"; readonly allowedSubagents?: readonly string[] };
|
|
154
156
|
|
|
155
157
|
// ─── Computed-artifact registry (#4924 v2 contract) ───────────────────────
|
|
156
158
|
|
|
@@ -305,6 +307,10 @@ const COMMON_BUDGET_SMALL = 250_000; // ~65K tokens
|
|
|
305
307
|
const TOOLS_ALL: ToolsPolicy = { mode: "all" };
|
|
306
308
|
const TOOLS_PLANNING: ToolsPolicy = { mode: "planning" };
|
|
307
309
|
const TOOLS_VERIFICATION: ToolsPolicy = { mode: "verification" };
|
|
310
|
+
const TOOLS_VERIFICATION_DISPATCH_UAT: ToolsPolicy = {
|
|
311
|
+
mode: "verification",
|
|
312
|
+
allowedSubagents: ["mnemo", "scout", "reviewer", "tester"],
|
|
313
|
+
};
|
|
308
314
|
// Like TOOLS_PLANNING but permits dispatch to read-only recon/planning
|
|
309
315
|
// specialists. Runtime-enforced by write-gate.ts before the subagent tool runs.
|
|
310
316
|
const TOOLS_PLANNING_DISPATCH_RECON: ToolsPolicy = {
|
|
@@ -601,7 +607,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
601
607
|
codebaseMap: false,
|
|
602
608
|
preferences: "active-only",
|
|
603
609
|
contextMode: "verification",
|
|
604
|
-
tools:
|
|
610
|
+
tools: TOOLS_VERIFICATION_DISPATCH_UAT,
|
|
605
611
|
artifacts: {
|
|
606
612
|
inline: ["slice-uat"],
|
|
607
613
|
excerpt: ["slice-summary"],
|
|
@@ -792,9 +798,12 @@ export function compileSubagentPermissionContract(
|
|
|
792
798
|
if (policy.mode === "all") {
|
|
793
799
|
return { allowed: true, allowedSubagents: ["*"], toolsMode: policy.mode };
|
|
794
800
|
}
|
|
795
|
-
if (
|
|
801
|
+
if (
|
|
802
|
+
(policy.mode === "planning-dispatch" || policy.mode === "verification") &&
|
|
803
|
+
Array.isArray(policy.allowedSubagents)
|
|
804
|
+
) {
|
|
796
805
|
return {
|
|
797
|
-
allowed:
|
|
806
|
+
allowed: policy.allowedSubagents.length > 0,
|
|
798
807
|
allowedSubagents: [...policy.allowedSubagents],
|
|
799
808
|
toolsMode: policy.mode,
|
|
800
809
|
};
|
|
@@ -14,6 +14,8 @@ const VALIDATION_BLOCK_RE =
|
|
|
14
14
|
/milestone validation returned needs-(?:attention|remediation)|validation verdict is needs-(?:attention|remediation)/i;
|
|
15
15
|
|
|
16
16
|
const VALIDATION_SAFE_DISPATCH_COMMANDS = new Set([
|
|
17
|
+
"reassess",
|
|
18
|
+
"reassess-roadmap",
|
|
17
19
|
"validate",
|
|
18
20
|
"validate-milestone",
|
|
19
21
|
]);
|
|
@@ -7,9 +7,60 @@
|
|
|
7
7
|
|
|
8
8
|
import { extractUatType } from "./files.js";
|
|
9
9
|
import type { UatType } from "./files.js";
|
|
10
|
+
import { splitFrontmatter, parseFrontmatterMap } from "../shared/frontmatter.js";
|
|
11
|
+
import { parse as parseYaml } from "yaml";
|
|
12
|
+
|
|
13
|
+
function normalizeVerdict(value: unknown): string | undefined {
|
|
14
|
+
if (typeof value !== "string") return undefined;
|
|
15
|
+
let verdict = value.trim().toLowerCase();
|
|
16
|
+
if (!verdict) return undefined;
|
|
17
|
+
if (verdict === "passed") verdict = "pass";
|
|
18
|
+
return verdict;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getCaseInsensitive(obj: Record<string, unknown>, key: string): unknown {
|
|
22
|
+
const lowerKey = key.toLowerCase();
|
|
23
|
+
for (const [candidate, value] of Object.entries(obj)) {
|
|
24
|
+
if (candidate.toLowerCase() === lowerKey) return value;
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
10
28
|
|
|
11
29
|
// ── Verdict extraction ──────────────────────────────────────────────────
|
|
12
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Extract and normalize the frontmatter `verdict` value.
|
|
33
|
+
*
|
|
34
|
+
* Supports both top-level `verdict` and the hook outcome shape
|
|
35
|
+
* `outcome.verdict`. Returns `undefined` when frontmatter is absent or has no
|
|
36
|
+
* verdict field.
|
|
37
|
+
*/
|
|
38
|
+
export function extractFrontmatterVerdict(content: string): string | undefined {
|
|
39
|
+
const [frontmatterLines] = splitFrontmatter(content);
|
|
40
|
+
if (!frontmatterLines) return undefined;
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const parsed = parseYaml(frontmatterLines.join("\n")) as unknown;
|
|
44
|
+
if (parsed && typeof parsed === "object") {
|
|
45
|
+
const root = parsed as Record<string, unknown>;
|
|
46
|
+
const topLevel = normalizeVerdict(getCaseInsensitive(root, "verdict"));
|
|
47
|
+
if (topLevel) return topLevel;
|
|
48
|
+
const outcome = getCaseInsensitive(root, "outcome");
|
|
49
|
+
if (outcome && typeof outcome === "object") {
|
|
50
|
+
const nested = normalizeVerdict(getCaseInsensitive(outcome as Record<string, unknown>, "verdict"));
|
|
51
|
+
if (nested) return nested;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
// Fall through to the permissive parser used by legacy frontmatter paths.
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const frontmatter = parseFrontmatterMap(frontmatterLines);
|
|
59
|
+
const topLevel = normalizeVerdict(getCaseInsensitive(frontmatter, "verdict"));
|
|
60
|
+
if (topLevel) return topLevel;
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
13
64
|
/**
|
|
14
65
|
* Extract and normalize the `verdict` value from YAML frontmatter.
|
|
15
66
|
*
|
|
@@ -21,24 +72,14 @@ import type { UatType } from "./files.js";
|
|
|
21
72
|
*/
|
|
22
73
|
export function extractVerdict(content: string): string | undefined {
|
|
23
74
|
// Primary: YAML frontmatter verdict (canonical format)
|
|
24
|
-
const
|
|
25
|
-
if (
|
|
26
|
-
const verdictMatch = fmMatch[1].match(/verdict:\s*([\w-]+)/i);
|
|
27
|
-
if (verdictMatch) {
|
|
28
|
-
let v = verdictMatch[1].toLowerCase();
|
|
29
|
-
if (v === "passed") v = "pass";
|
|
30
|
-
return v;
|
|
31
|
-
}
|
|
32
|
-
return undefined;
|
|
33
|
-
}
|
|
75
|
+
const [frontmatterLines] = splitFrontmatter(content);
|
|
76
|
+
if (frontmatterLines) return extractFrontmatterVerdict(content);
|
|
34
77
|
|
|
35
78
|
// Fallback: detect verdict in markdown body (LLM manual writes, #2960).
|
|
36
79
|
// Matches patterns like: **Verdict:** PASS, **Verdict:** ✅ PASS, **Verdict** needs-remediation
|
|
37
80
|
const bodyMatch = content.match(/\*\*Verdict:?\*\*\s*(?:✅\s*)?(\w[\w-]*)/i);
|
|
38
81
|
if (bodyMatch) {
|
|
39
|
-
|
|
40
|
-
if (v === "passed") v = "pass";
|
|
41
|
-
return v;
|
|
82
|
+
return normalizeVerdict(bodyMatch[1]);
|
|
42
83
|
}
|
|
43
84
|
|
|
44
85
|
return undefined;
|
|
@@ -295,6 +295,90 @@ function hasUnsafeShellSyntax(cmd: string): boolean {
|
|
|
295
295
|
return false;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
function splitLeadingShellWords(cmd: string): string[] {
|
|
299
|
+
const words: string[] = [];
|
|
300
|
+
let current = "";
|
|
301
|
+
let inSingle = false;
|
|
302
|
+
let inDouble = false;
|
|
303
|
+
let escaped = false;
|
|
304
|
+
|
|
305
|
+
for (let i = 0; i < cmd.length; i += 1) {
|
|
306
|
+
const ch = cmd[i];
|
|
307
|
+
|
|
308
|
+
if (escaped) {
|
|
309
|
+
current += ch;
|
|
310
|
+
escaped = false;
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (ch === "\\" && !inSingle) {
|
|
315
|
+
escaped = true;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (ch === "'" && !inDouble) {
|
|
320
|
+
inSingle = !inSingle;
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (ch === "\"" && !inSingle) {
|
|
325
|
+
inDouble = !inDouble;
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (!inSingle && !inDouble) {
|
|
330
|
+
if (/\s/.test(ch)) {
|
|
331
|
+
if (current) {
|
|
332
|
+
words.push(current);
|
|
333
|
+
current = "";
|
|
334
|
+
}
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if ([";", "|", "&", "<", ">"].includes(ch)) {
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
current += ch;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (current) {
|
|
347
|
+
words.push(current);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return words;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function isCountFlag(token: string): boolean {
|
|
354
|
+
return (
|
|
355
|
+
token === "--count" ||
|
|
356
|
+
token.startsWith("--count=") ||
|
|
357
|
+
token === "--count-matches" ||
|
|
358
|
+
token.startsWith("--count-matches=") ||
|
|
359
|
+
/^-[A-Za-z]*c[A-Za-z]*$/.test(token)
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function countSearchWarning(command: string, exitCode: number): string | null {
|
|
364
|
+
if (exitCode !== 1) return null;
|
|
365
|
+
|
|
366
|
+
const trimmed = command.trim();
|
|
367
|
+
if (trimmed.startsWith("!")) return null;
|
|
368
|
+
|
|
369
|
+
const [tool, ...args] = splitLeadingShellWords(trimmed);
|
|
370
|
+
if (tool !== "grep" && tool !== "rg") return null;
|
|
371
|
+
if (!args.some(isCountFlag)) return null;
|
|
372
|
+
|
|
373
|
+
return `verification-gate: warning: '${tool} -c' returns exit 1 when count=0; for absence checks use '! ${tool} -q ...' instead.`;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function appendStderrWarning(stderr: string, warning: string | null): string {
|
|
377
|
+
if (!warning) return stderr;
|
|
378
|
+
const trimmed = stderr.trimEnd();
|
|
379
|
+
return trimmed ? `${trimmed}\n${warning}` : warning;
|
|
380
|
+
}
|
|
381
|
+
|
|
298
382
|
/**
|
|
299
383
|
* Known executable first-tokens that are safe to run.
|
|
300
384
|
* Lowercase commands, common build/test tools, and npm/yarn/pnpm invocations.
|
|
@@ -486,11 +570,13 @@ export function runVerificationGate(options: RunVerificationGateOptions): Verifi
|
|
|
486
570
|
stderr = truncate(result.stderr, MAX_OUTPUT_BYTES);
|
|
487
571
|
}
|
|
488
572
|
|
|
573
|
+
const warning = countSearchWarning(command, exitCode);
|
|
574
|
+
|
|
489
575
|
checks.push({
|
|
490
576
|
command,
|
|
491
577
|
exitCode,
|
|
492
578
|
stdout: truncate(result.stdout, MAX_OUTPUT_BYTES),
|
|
493
|
-
stderr,
|
|
579
|
+
stderr: truncate(appendStderrWarning(stderr, warning), MAX_OUTPUT_BYTES),
|
|
494
580
|
durationMs,
|
|
495
581
|
});
|
|
496
582
|
}
|
|
@@ -58,6 +58,7 @@ export function shouldAutoPrepareWorkflowMcp(ctx: WorkflowMcpAutoPrepContext): b
|
|
|
58
58
|
const authMode = getAuthModeSafe(ctx, provider);
|
|
59
59
|
|
|
60
60
|
if (provider !== "claude-code") return false;
|
|
61
|
+
if (authMode === undefined) return true;
|
|
61
62
|
return usesWorkflowMcpTransport(authMode as any, baseUrl) || authMode === "externalCli";
|
|
62
63
|
}
|
|
63
64
|
|
|
@@ -72,7 +73,7 @@ export function prepareWorkflowMcpForProject(
|
|
|
72
73
|
try {
|
|
73
74
|
const result = ensureProjectWorkflowMcpConfig(projectRoot);
|
|
74
75
|
if (result.status !== "unchanged") {
|
|
75
|
-
prepCtx.ui?.notify?.(`
|
|
76
|
+
prepCtx.ui?.notify?.(`GSD MCP Server Prepared at ${result.configPath}`, "info");
|
|
76
77
|
}
|
|
77
78
|
return result;
|
|
78
79
|
} catch (err) {
|
|
@@ -2,6 +2,7 @@ import { execSync } from "node:child_process";
|
|
|
2
2
|
import { existsSync, realpathSync } from "node:fs";
|
|
3
3
|
import { dirname, resolve, sep } from "node:path";
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import { RUN_UAT_WORKFLOW_TOOL_NAMES } from "./tool-presentation-plan.js";
|
|
5
6
|
|
|
6
7
|
type WorkflowExecutorsModule = typeof import("./tools/workflow-tool-executors.js");
|
|
7
8
|
|
|
@@ -100,6 +101,8 @@ const MCP_WORKFLOW_TOOL_SURFACE = new Set([
|
|
|
100
101
|
"gsd_task_complete",
|
|
101
102
|
"gsd_task_reopen",
|
|
102
103
|
"gsd_update_requirement",
|
|
104
|
+
"gsd_uat_exec",
|
|
105
|
+
"gsd_uat_result_save",
|
|
103
106
|
"gsd_validate_milestone",
|
|
104
107
|
]);
|
|
105
108
|
|
|
@@ -462,8 +465,9 @@ export function getRequiredWorkflowToolsForAutoUnit(unitType: string): string[]
|
|
|
462
465
|
];
|
|
463
466
|
case "research-milestone":
|
|
464
467
|
case "research-slice":
|
|
465
|
-
case "run-uat":
|
|
466
468
|
return ["gsd_summary_save"];
|
|
469
|
+
case "run-uat":
|
|
470
|
+
return [...RUN_UAT_WORKFLOW_TOOL_NAMES];
|
|
467
471
|
case "plan-milestone":
|
|
468
472
|
return ["gsd_plan_milestone"];
|
|
469
473
|
case "plan-slice":
|
|
@@ -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
|
+
}
|
|
File without changes
|
|
File without changes
|