@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
|
@@ -4,7 +4,7 @@ import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
|
4
4
|
|
|
5
5
|
import { minimatch } from "minimatch";
|
|
6
6
|
|
|
7
|
-
import { shouldBlockAutoUnitToolCall } from "../auto-unit-tool-scope.js";
|
|
7
|
+
import { GSD_PHASE_SCOPE_DISPLAY_REASON, shouldBlockAutoUnitToolCall } from "../auto-unit-tool-scope.js";
|
|
8
8
|
import { getIsolationMode } from "../preferences.js";
|
|
9
9
|
import { compileSubagentPermissionContract, type ToolsPolicy } from "../unit-context-manifest.js";
|
|
10
10
|
import { logWarning } from "../workflow-logger.js";
|
|
@@ -679,6 +679,7 @@ const PLANNING_SUBAGENT_TOOLS = new Set(["subagent", "task"]);
|
|
|
679
679
|
* manifests still declare per-unit subsets via ToolsPolicy.allowedSubagents.
|
|
680
680
|
*/
|
|
681
681
|
const PLANNING_DISPATCH_AGENT_REGISTRY = {
|
|
682
|
+
mnemo: { readOnlySpecialist: true },
|
|
682
683
|
scout: { readOnlySpecialist: true },
|
|
683
684
|
planner: { readOnlySpecialist: true },
|
|
684
685
|
reviewer: { readOnlySpecialist: true },
|
|
@@ -692,7 +693,7 @@ export const ALLOWED_PLANNING_DISPATCH_AGENTS = new Set<string>(
|
|
|
692
693
|
.map(([agentId]) => agentId),
|
|
693
694
|
);
|
|
694
695
|
|
|
695
|
-
let
|
|
696
|
+
let warnedMissingControlledDispatchAgentClasses = false;
|
|
696
697
|
|
|
697
698
|
function isReadOnlySpecialist(agentId: string): boolean {
|
|
698
699
|
const metadata = PLANNING_DISPATCH_AGENT_REGISTRY[agentId as keyof typeof PLANNING_DISPATCH_AGENT_REGISTRY];
|
|
@@ -703,11 +704,20 @@ function allowedPlanningDispatchAgentsList(): string {
|
|
|
703
704
|
return [...ALLOWED_PLANNING_DISPATCH_AGENTS].join(", ");
|
|
704
705
|
}
|
|
705
706
|
|
|
706
|
-
function
|
|
707
|
-
|
|
708
|
-
|
|
707
|
+
function allowsControlledSubagentDispatch(
|
|
708
|
+
policy: ToolsPolicy,
|
|
709
|
+
): policy is ToolsPolicy & { readonly allowedSubagents: readonly string[] } {
|
|
710
|
+
return (
|
|
711
|
+
(policy.mode === "planning-dispatch" || policy.mode === "verification") &&
|
|
712
|
+
Array.isArray((policy as { readonly allowedSubagents?: unknown }).allowedSubagents)
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function warnMissingControlledDispatchAgentClasses(unitType: string, mode: string, toolName: string): void {
|
|
717
|
+
if (warnedMissingControlledDispatchAgentClasses) return;
|
|
718
|
+
warnedMissingControlledDispatchAgentClasses = true;
|
|
709
719
|
// TODO(#5060): Remove this migration shim once all subagent/task callers are verified to forward agent identities.
|
|
710
|
-
const message = `[write-gate]
|
|
720
|
+
const message = `[write-gate] controlled-dispatch: shouldBlockPlanningUnit called for tool "${toolName}" ` +
|
|
711
721
|
`on unit "${unitType}" without agentClasses - stale caller; blocking dispatch.`;
|
|
712
722
|
console.warn(message);
|
|
713
723
|
logWarning("intercept", message, {
|
|
@@ -762,6 +772,20 @@ function blockReason(unitType: string, mode: string, what: string): string {
|
|
|
762
772
|
].join(" ");
|
|
763
773
|
}
|
|
764
774
|
|
|
775
|
+
function planningBlock(unitType: string, mode: string, what: string): PlanningUnitBlockResult {
|
|
776
|
+
return {
|
|
777
|
+
block: true,
|
|
778
|
+
reason: blockReason(unitType, mode, what),
|
|
779
|
+
displayReason: GSD_PHASE_SCOPE_DISPLAY_REASON,
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
type PlanningUnitBlockResult = {
|
|
784
|
+
block: boolean;
|
|
785
|
+
reason?: string;
|
|
786
|
+
displayReason?: string;
|
|
787
|
+
};
|
|
788
|
+
|
|
765
789
|
/**
|
|
766
790
|
* Planning-unit tool-policy enforcement. Returns { block } per the policy
|
|
767
791
|
* resolved from the active unit's manifest:
|
|
@@ -777,8 +801,9 @@ function blockReason(unitType: string, mode: string, what: string): string {
|
|
|
777
801
|
* - "docs" → like "planning" but also allows writes to paths
|
|
778
802
|
* matching `allowedPathGlobs` relative to basePath.
|
|
779
803
|
* - "verification"
|
|
780
|
-
* → allows Bash for project verification commands,
|
|
781
|
-
* writes restricted to .gsd
|
|
804
|
+
* → allows Bash for project verification commands, keeps
|
|
805
|
+
* writes restricted to .gsd/, and permits subagent dispatch
|
|
806
|
+
* only when the manifest declares allowedSubagents.
|
|
782
807
|
*
|
|
783
808
|
* `pathOrCommand` is the file path for write/edit-shaped tools and the
|
|
784
809
|
* shell command for bash. Other tools ignore this argument.
|
|
@@ -801,7 +826,7 @@ export function shouldBlockPlanningUnit(
|
|
|
801
826
|
agentClasses?: readonly string[],
|
|
802
827
|
toolInput?: unknown,
|
|
803
828
|
unitId?: string,
|
|
804
|
-
):
|
|
829
|
+
): PlanningUnitBlockResult {
|
|
805
830
|
const tool = canonicalToolName(toolName);
|
|
806
831
|
const autoScopeGuard = shouldBlockAutoUnitToolCall(unitType, toolName, toolInput, unitId);
|
|
807
832
|
if (autoScopeGuard.block) return autoScopeGuard;
|
|
@@ -814,10 +839,10 @@ export function shouldBlockPlanningUnit(
|
|
|
814
839
|
if (PLANNING_SAFE_TOOLS.has(tool)) return { block: false };
|
|
815
840
|
if (tool.startsWith("gsd_")) return { block: false };
|
|
816
841
|
if (PLANNING_WRITE_TOOLS.has(tool) || tool === "bash" || PLANNING_SUBAGENT_TOOLS.has(tool)) {
|
|
817
|
-
return
|
|
842
|
+
return planningBlock(unitType, policy.mode, `${tool} is not permitted (read-only)`);
|
|
818
843
|
}
|
|
819
844
|
// Unknown tool in read-only mode — block by default.
|
|
820
|
-
return
|
|
845
|
+
return planningBlock(unitType, policy.mode, `tool "${tool}" is not on the read-only allowlist`);
|
|
821
846
|
}
|
|
822
847
|
|
|
823
848
|
// planning / planning-dispatch / docs / verification modes share the same surface for safe tools, bash, and subagent.
|
|
@@ -825,7 +850,7 @@ export function shouldBlockPlanningUnit(
|
|
|
825
850
|
if (tool.startsWith("gsd_")) return { block: false };
|
|
826
851
|
|
|
827
852
|
if (PLANNING_SUBAGENT_TOOLS.has(tool)) {
|
|
828
|
-
if (policy
|
|
853
|
+
if (allowsControlledSubagentDispatch(policy)) {
|
|
829
854
|
const requested = (agentClasses ?? []).map(a => a.trim()).filter(Boolean);
|
|
830
855
|
const dispatchContract = compileSubagentPermissionContract(policy);
|
|
831
856
|
const allowedSubagents = dispatchContract.allowedSubagents;
|
|
@@ -834,15 +859,12 @@ export function shouldBlockPlanningUnit(
|
|
|
834
859
|
// agent identities yet. Block and warn so stale callers surface in telemetry
|
|
835
860
|
// instead of silently bypassing the gate.
|
|
836
861
|
if (agentClasses === undefined) {
|
|
837
|
-
|
|
838
|
-
return
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
`subagent dispatch blocked: stale caller did not supply agent identities for "${tool}"; update extractSubagentAgentClasses to handle this input shape`,
|
|
844
|
-
),
|
|
845
|
-
};
|
|
862
|
+
warnMissingControlledDispatchAgentClasses(unitType, policy.mode, tool);
|
|
863
|
+
return planningBlock(
|
|
864
|
+
unitType,
|
|
865
|
+
policy.mode,
|
|
866
|
+
`subagent dispatch blocked: stale caller did not supply agent identities for "${tool}"; update extractSubagentAgentClasses to handle this input shape`,
|
|
867
|
+
);
|
|
846
868
|
}
|
|
847
869
|
// agentClasses was explicitly provided but resolved to an empty list (for
|
|
848
870
|
// example, a bare tool call with no agent field). Pass through; no agents
|
|
@@ -852,57 +874,45 @@ export function shouldBlockPlanningUnit(
|
|
|
852
874
|
}
|
|
853
875
|
const globallyDisallowed = requested.find(a => !isReadOnlySpecialist(a));
|
|
854
876
|
if (globallyDisallowed) {
|
|
855
|
-
return
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
`subagent dispatch of "${globallyDisallowed}" not permitted; only read-only specialists (${allowedPlanningDispatchAgentsList()}) may be dispatched from planning-dispatch units`,
|
|
861
|
-
),
|
|
862
|
-
};
|
|
877
|
+
return planningBlock(
|
|
878
|
+
unitType,
|
|
879
|
+
policy.mode,
|
|
880
|
+
`subagent dispatch of "${globallyDisallowed}" not permitted; only read-only specialists (${allowedPlanningDispatchAgentsList()}) may be dispatched from ${policy.mode} units`,
|
|
881
|
+
);
|
|
863
882
|
}
|
|
864
883
|
const disallowedByPolicy = requested.find(a => !allowed.has(a));
|
|
865
884
|
if (disallowedByPolicy) {
|
|
866
|
-
return
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
`subagent dispatch of "${disallowedByPolicy}" not permitted by ToolsPolicy.allowedSubagents; permitted agents for this unit: ${allowedSubagents.join(", ")}`,
|
|
872
|
-
),
|
|
873
|
-
};
|
|
885
|
+
return planningBlock(
|
|
886
|
+
unitType,
|
|
887
|
+
policy.mode,
|
|
888
|
+
`subagent dispatch of "${disallowedByPolicy}" not permitted by ToolsPolicy.allowedSubagents; permitted agents for this unit: ${allowedSubagents.join(", ")}`,
|
|
889
|
+
);
|
|
874
890
|
}
|
|
875
891
|
return { block: false };
|
|
876
892
|
}
|
|
877
|
-
return
|
|
893
|
+
return planningBlock(unitType, policy.mode, "subagent dispatch is not permitted in planning units");
|
|
878
894
|
}
|
|
879
895
|
|
|
880
896
|
if (tool === "bash") {
|
|
881
897
|
if (policy.mode === "verification") {
|
|
882
898
|
if (BASH_VERIFICATION_RE.test(pathOrCommand) || BASH_READ_ONLY_RE.test(pathOrCommand)) return { block: false };
|
|
883
|
-
return
|
|
884
|
-
block: true,
|
|
885
|
-
reason: blockReason(
|
|
886
|
-
unitType,
|
|
887
|
-
policy.mode,
|
|
888
|
-
`bash is restricted to build/test verification commands (npm run build, npm test, etc.); cannot run "${pathOrCommand.slice(0, 80)}${pathOrCommand.length > 80 ? "…" : ""}"`,
|
|
889
|
-
),
|
|
890
|
-
};
|
|
891
|
-
}
|
|
892
|
-
if (BASH_READ_ONLY_RE.test(pathOrCommand)) return { block: false };
|
|
893
|
-
return {
|
|
894
|
-
block: true,
|
|
895
|
-
reason: blockReason(
|
|
899
|
+
return planningBlock(
|
|
896
900
|
unitType,
|
|
897
901
|
policy.mode,
|
|
898
|
-
`bash is restricted to
|
|
899
|
-
)
|
|
900
|
-
}
|
|
902
|
+
`bash is restricted to build/test verification commands (npm run build, npm test, etc.); cannot run "${pathOrCommand.slice(0, 80)}${pathOrCommand.length > 80 ? "…" : ""}"`,
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
if (BASH_READ_ONLY_RE.test(pathOrCommand)) return { block: false };
|
|
906
|
+
return planningBlock(
|
|
907
|
+
unitType,
|
|
908
|
+
policy.mode,
|
|
909
|
+
`bash is restricted to read-only commands (cat/grep/git log/etc); cannot run "${pathOrCommand.slice(0, 80)}${pathOrCommand.length > 80 ? "…" : ""}"`,
|
|
910
|
+
);
|
|
901
911
|
}
|
|
902
912
|
|
|
903
913
|
if (PLANNING_WRITE_TOOLS.has(tool)) {
|
|
904
914
|
if (!pathOrCommand) {
|
|
905
|
-
return
|
|
915
|
+
return planningBlock(unitType, policy.mode, `${tool} called with empty path`);
|
|
906
916
|
}
|
|
907
917
|
const absPath = isAbsolute(pathOrCommand) ? pathOrCommand : resolve(basePath, pathOrCommand);
|
|
908
918
|
|
|
@@ -914,14 +924,11 @@ export function shouldBlockPlanningUnit(
|
|
|
914
924
|
return { block: false };
|
|
915
925
|
}
|
|
916
926
|
|
|
917
|
-
return
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
`cannot ${tool} "${pathOrCommand}" — writes are restricted to .gsd/${policy.mode === "docs" ? " and " + policy.allowedPathGlobs.join(", ") : ""}`,
|
|
923
|
-
),
|
|
924
|
-
};
|
|
927
|
+
return planningBlock(
|
|
928
|
+
unitType,
|
|
929
|
+
policy.mode,
|
|
930
|
+
`cannot ${tool} "${pathOrCommand}" — writes are restricted to .gsd/${policy.mode === "docs" ? " and " + policy.allowedPathGlobs.join(", ") : ""}`,
|
|
931
|
+
);
|
|
925
932
|
}
|
|
926
933
|
|
|
927
934
|
// Unknown tool name — pass through. Other layers (queue, pending-gate,
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Shared browser-observable UAT requirement and evidence detection.
|
|
3
3
|
|
|
4
|
-
export const BROWSER_REQUIREMENT_RE = /\b(?:
|
|
4
|
+
export const BROWSER_REQUIREMENT_RE = /\b(?:file:\/\/|localhost|playwright|chrome|screenshot|snapshot|browser_(?:assert|batch|find|verify|snapshot_refs))\b|\b(?:open|launch|navigate|load|visit|serve|start)\b.{0,80}\b(?:browser|page|localhost|file:\/\/)\b|\bbrowser\s+(?:check|session|test|uat|tool|automation|interaction|flow)\b/i;
|
|
5
5
|
export const NO_BROWSER_EVIDENCE_RE = /\b(?:no|without|not|wasn'?t|isn'?t)\s+(?:automated\s+)?(?:live\s+)?browser(?:\s+(?:session|test|uat))?|\bno\s+automated\s+browser\b|\bnot\s+conducted\b/i;
|
|
6
6
|
export const BROWSER_RUNTIME_RE = /\b(?:browser|playwright|chrome|camoufox|browser_(?:assert|batch|find|verify|snapshot_refs)|screenshot|snapshot|file:\/\/|localhost)\b/i;
|
|
7
7
|
export const BROWSER_ACTION_RE = /\b(?:open(?:ed)?|navigate(?:d)?|click(?:ed)?|type(?:d)?|reload(?:ed)?|capture(?:d)?|screenshot|snapshot)\b/i;
|
|
8
8
|
export const BROWSER_ASSERTION_RE = /\b(?:assert(?:ed|ion)?|observed|confirmed|verified|expected|visible|text|count|label|strikethrough|localstorage|screenshot|snapshot|passed)\b/i;
|
|
9
|
+
const NON_REQUIREMENT_BROWSER_HEADING_RE = /^(?:not\s+proven|not\s+covered|out\s+of\s+scope|deferred|follow-?ups?|known\s+limitations|notes\s+for\s+tester)\b/i;
|
|
10
|
+
const NON_REQUIREMENT_BROWSER_LINE_RE = /\b(?:deferred|not\s+proven|not\s+covered|out\s+of\s+scope|future\s+slice|follow-?up|no\s+(?:live\s+)?browser|without\s+(?:a\s+)?browser|not\s+(?:a\s+)?browser)\b/i;
|
|
9
11
|
|
|
10
12
|
export function compactTextParts(parts: Array<string | string[] | null | undefined>): string {
|
|
11
13
|
return parts.flatMap((part) => Array.isArray(part) ? part : [part])
|
|
@@ -14,7 +16,29 @@ export function compactTextParts(parts: Array<string | string[] | null | undefin
|
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export function hasBrowserRequiredText(text: string): boolean {
|
|
17
|
-
|
|
19
|
+
let inNonRequirementSection = false;
|
|
20
|
+
let nonRequirementDepth = 0;
|
|
21
|
+
for (const line of text.split(/\r?\n/)) {
|
|
22
|
+
const headingMatch = line.match(/^(#{1,6})\s+(.+?)\s*$/);
|
|
23
|
+
if (headingMatch) {
|
|
24
|
+
const depth = headingMatch[1]!.length;
|
|
25
|
+
const title = headingMatch[2] ?? "";
|
|
26
|
+
// Only update section context when at the same or higher level than the
|
|
27
|
+
// heading that opened the non-requirement zone. A sub-heading deeper than
|
|
28
|
+
// the opening heading must not escape or re-enter the zone on its own.
|
|
29
|
+
if (!inNonRequirementSection || depth <= nonRequirementDepth) {
|
|
30
|
+
inNonRequirementSection = NON_REQUIREMENT_BROWSER_HEADING_RE.test(title);
|
|
31
|
+
nonRequirementDepth = inNonRequirementSection ? depth : 0;
|
|
32
|
+
}
|
|
33
|
+
// Check the heading title itself — section state is already updated, so
|
|
34
|
+
// we correctly skip headings that opened a non-requirement zone.
|
|
35
|
+
if (!inNonRequirementSection && BROWSER_REQUIREMENT_RE.test(title)) return true;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (inNonRequirementSection || NON_REQUIREMENT_BROWSER_LINE_RE.test(line)) continue;
|
|
39
|
+
if (BROWSER_REQUIREMENT_RE.test(line)) return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
18
42
|
}
|
|
19
43
|
|
|
20
44
|
export function hasBrowserEvidenceText(text: string): boolean {
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Shared DB-backed guard for milestone closeout finalization.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
getDbPath,
|
|
6
|
+
getLatestAssessmentByScope,
|
|
7
|
+
getMilestone,
|
|
8
|
+
getMilestoneSlices,
|
|
9
|
+
getPendingGates,
|
|
10
|
+
getSliceTasks,
|
|
11
|
+
isDbAvailable,
|
|
12
|
+
refreshOpenDatabaseFromDisk,
|
|
13
|
+
} from "./gsd-db.js";
|
|
14
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
15
|
+
|
|
16
|
+
export const CLOSEOUT_CONSISTENCY_BLOCKED_REASON = "closeout-consistency-blocked";
|
|
17
|
+
|
|
18
|
+
export type CloseoutConsistencyFailureReason =
|
|
19
|
+
| "db-unavailable"
|
|
20
|
+
| "db-refresh-failed"
|
|
21
|
+
| "milestone-missing"
|
|
22
|
+
| "milestone-open"
|
|
23
|
+
| "validation-not-pass"
|
|
24
|
+
| "slice-missing"
|
|
25
|
+
| "slice-open"
|
|
26
|
+
| "task-open"
|
|
27
|
+
| "quality-gate-pending";
|
|
28
|
+
|
|
29
|
+
export type CloseoutConsistencyResult =
|
|
30
|
+
| { ok: true }
|
|
31
|
+
| {
|
|
32
|
+
ok: false;
|
|
33
|
+
reason: CloseoutConsistencyFailureReason;
|
|
34
|
+
recoveryReason: typeof CLOSEOUT_CONSISTENCY_BLOCKED_REASON;
|
|
35
|
+
message: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export interface CloseoutConsistencyOptions {
|
|
39
|
+
refreshFromDisk?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function blocked(reason: CloseoutConsistencyFailureReason, message: string): CloseoutConsistencyResult {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
reason,
|
|
46
|
+
recoveryReason: CLOSEOUT_CONSISTENCY_BLOCKED_REASON,
|
|
47
|
+
message,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isFileBackedDbPath(path: string | null): boolean {
|
|
52
|
+
return Boolean(path && path !== ":memory:");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function checkCloseoutConsistencyGate(
|
|
56
|
+
milestoneId: string,
|
|
57
|
+
options: CloseoutConsistencyOptions = {},
|
|
58
|
+
): CloseoutConsistencyResult {
|
|
59
|
+
if (!isDbAvailable()) {
|
|
60
|
+
return blocked(
|
|
61
|
+
"db-unavailable",
|
|
62
|
+
`Closeout consistency blocked for ${milestoneId}: canonical DB is unavailable.`,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (options.refreshFromDisk && isFileBackedDbPath(getDbPath()) && !refreshOpenDatabaseFromDisk()) {
|
|
67
|
+
return blocked(
|
|
68
|
+
"db-refresh-failed",
|
|
69
|
+
`Closeout consistency blocked for ${milestoneId}: canonical DB refresh failed.`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const milestone = getMilestone(milestoneId);
|
|
74
|
+
if (!milestone) {
|
|
75
|
+
return blocked(
|
|
76
|
+
"milestone-missing",
|
|
77
|
+
`Closeout consistency blocked for ${milestoneId}: milestone is missing from canonical DB.`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
if (!isClosedStatus(milestone.status)) {
|
|
81
|
+
return blocked(
|
|
82
|
+
"milestone-open",
|
|
83
|
+
`Closeout consistency blocked for ${milestoneId}: canonical DB milestone status is "${milestone.status}".`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (milestone.status !== "skipped") {
|
|
88
|
+
const validation = getLatestAssessmentByScope(milestoneId, "milestone-validation");
|
|
89
|
+
if (validation?.status !== "pass") {
|
|
90
|
+
return blocked(
|
|
91
|
+
"validation-not-pass",
|
|
92
|
+
`Closeout consistency blocked for ${milestoneId}: latest milestone validation is "${validation?.status ?? "absent"}".`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const slices = getMilestoneSlices(milestoneId);
|
|
98
|
+
if (slices.length === 0 && milestone.status !== "skipped") {
|
|
99
|
+
return blocked(
|
|
100
|
+
"slice-missing",
|
|
101
|
+
`Closeout consistency blocked for ${milestoneId}: no slices exist in canonical DB.`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
for (const slice of slices) {
|
|
106
|
+
if (!isClosedStatus(slice.status)) {
|
|
107
|
+
return blocked(
|
|
108
|
+
"slice-open",
|
|
109
|
+
`Closeout consistency blocked for ${milestoneId}: slice ${slice.id} status is "${slice.status}".`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (const task of getSliceTasks(milestoneId, slice.id)) {
|
|
114
|
+
if (!isClosedStatus(task.status)) {
|
|
115
|
+
return blocked(
|
|
116
|
+
"task-open",
|
|
117
|
+
`Closeout consistency blocked for ${milestoneId}: task ${slice.id}/${task.id} status is "${task.status}".`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const pendingGate = getPendingGates(milestoneId, slice.id)[0];
|
|
123
|
+
if (pendingGate) {
|
|
124
|
+
return blocked(
|
|
125
|
+
"quality-gate-pending",
|
|
126
|
+
`Closeout consistency blocked for ${milestoneId}: quality gate ${pendingGate.gate_id} is still pending for ${slice.id}.`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { ok: true };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function formatCloseoutConsistencyBlock(result: CloseoutConsistencyResult): string {
|
|
135
|
+
if (result.ok) return "";
|
|
136
|
+
return `${result.message} Recovery reason: ${result.recoveryReason}. Resolve the canonical DB state and run /gsd auto to retry.`;
|
|
137
|
+
}
|
|
@@ -14,7 +14,7 @@ export interface GsdCommandDefinition {
|
|
|
14
14
|
type CompletionMap = Record<string, readonly GsdCommandDefinition[]>;
|
|
15
15
|
|
|
16
16
|
export const GSD_COMMAND_DESCRIPTION =
|
|
17
|
-
"GSD — Git Ship Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|brief|report|queue|quick|discuss|capture|triage|dispatch|verdict|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|closeout|model|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|debug|logs|forensics|changelog|migrate|remote|steer|knowledge|memory|new-milestone|new-project|parallel|cmux|park|unpark|init|setup|onboarding|inspect|extensions|update|upgrade|fast|mcp|rethink|workflow|codebase|notifications|ship|do|usage|context|session-report|backlog|pr-branch|add-tests|scan|language|worktree|eval-review";
|
|
17
|
+
"GSD — Git Ship Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|brief|report|queue|quick|discuss|capture|triage|dispatch|verdict|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|closeout|rebuild|model|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|debug|logs|forensics|changelog|migrate|remote|steer|knowledge|memory|new-milestone|new-project|parallel|cmux|park|unpark|init|setup|onboarding|inspect|extensions|update|upgrade|fast|mcp|rethink|workflow|codebase|notifications|ship|do|usage|context|session-report|backlog|pr-branch|add-tests|scan|language|worktree|eval-review";
|
|
18
18
|
|
|
19
19
|
export const TOP_LEVEL_SUBCOMMANDS: readonly GsdCommandDefinition[] = [
|
|
20
20
|
{ cmd: "help", desc: "Categorized command reference with descriptions" },
|
|
@@ -44,6 +44,7 @@ export const TOP_LEVEL_SUBCOMMANDS: readonly GsdCommandDefinition[] = [
|
|
|
44
44
|
{ cmd: "export", desc: "Alias for /gsd report" },
|
|
45
45
|
{ cmd: "cleanup", desc: "Remove merged branches or snapshots" },
|
|
46
46
|
{ cmd: "closeout", desc: "Recover failed git closeout actions (status, retry, resolve)" },
|
|
47
|
+
{ cmd: "rebuild", desc: "Rebuild markdown projections from the canonical DB" },
|
|
47
48
|
{ cmd: "model", desc: "Switch the active session model or open a picker" },
|
|
48
49
|
{ cmd: "mode", desc: "Switch workflow mode (solo/team)" },
|
|
49
50
|
{ cmd: "prefs", desc: "Manage preferences (model selection, timeouts, etc.)" },
|
|
@@ -214,6 +215,10 @@ const NESTED_COMPLETIONS: CompletionMap = {
|
|
|
214
215
|
{ cmd: "retry", desc: "Retry the latest failed closeout git action" },
|
|
215
216
|
{ cmd: "resolve", desc: "Mark closeout resolved after the worktree is clean" },
|
|
216
217
|
],
|
|
218
|
+
rebuild: [
|
|
219
|
+
{ cmd: "markdown", desc: "Rebuild markdown projections from the canonical DB" },
|
|
220
|
+
{ cmd: "database", desc: "Reserved for DB-native rebuilds; does not import markdown" },
|
|
221
|
+
],
|
|
217
222
|
knowledge: [
|
|
218
223
|
{ cmd: "rule", desc: "Add a project rule (always/never do X)" },
|
|
219
224
|
{ cmd: "pattern", desc: "Add a code pattern to follow" },
|
|
@@ -56,6 +56,7 @@ export function showHelp(ctx: ExtensionCommandContext, args = ""): void {
|
|
|
56
56
|
" /gsd keys API key manager (LLM + tool keys)",
|
|
57
57
|
" /gsd doctor Diagnose and repair .gsd/ state",
|
|
58
58
|
" /gsd closeout Recover failed git closeout actions",
|
|
59
|
+
" /gsd rebuild Rebuild markdown projections from the DB [markdown]",
|
|
59
60
|
"",
|
|
60
61
|
"Use /gsd help full for the complete command reference.",
|
|
61
62
|
];
|
|
@@ -74,7 +75,7 @@ export function showHelp(ctx: ExtensionCommandContext, args = ""): void {
|
|
|
74
75
|
" /gsd new-milestone Create milestone from headless context (used by gsd headless)",
|
|
75
76
|
" /gsd new-project Bootstrap a new project (use --deep for staged project-level discovery)",
|
|
76
77
|
" /gsd quick Execute a quick task without full planning overhead",
|
|
77
|
-
" /gsd dispatch Dispatch a specific phase directly [research|plan|execute|complete|uat|replan]",
|
|
78
|
+
" /gsd dispatch Dispatch a specific phase directly [research|plan|execute|complete|validate|reassess|uat|replan]",
|
|
78
79
|
" /gsd verdict <v> Override milestone validation verdict [pass|needs-attention|needs-remediation] [--milestone Mxxx] [--rationale \"...\"]",
|
|
79
80
|
" /gsd parallel Parallel milestone orchestration [start|status|stop|pause|resume|merge|watch]",
|
|
80
81
|
" /gsd workflow Custom workflow lifecycle [new|run|list|validate|pause|resume]",
|
|
@@ -138,7 +139,7 @@ export function showHelp(ctx: ExtensionCommandContext, args = ""): void {
|
|
|
138
139
|
" /gsd skill-health Skill lifecycle dashboard",
|
|
139
140
|
" /gsd extensions Manage extensions [list|enable|disable|info]",
|
|
140
141
|
" /gsd fast Toggle OpenAI service tier [on|off|flex|status]",
|
|
141
|
-
" /gsd mcp MCP server management [status|check|test|enable|disable|import|delete|init]",
|
|
142
|
+
" /gsd mcp MCP server management [status|check|discover|test|enable|disable|import|delete|init]",
|
|
142
143
|
"",
|
|
143
144
|
"MAINTENANCE",
|
|
144
145
|
" /gsd doctor Diagnose and repair .gsd/ state [audit|fix|heal] [scope]",
|
|
@@ -147,6 +148,9 @@ export function showHelp(ctx: ExtensionCommandContext, args = ""): void {
|
|
|
147
148
|
" /gsd export Alias for /gsd report",
|
|
148
149
|
" /gsd cleanup Remove merged branches or snapshots [branches|snapshots]",
|
|
149
150
|
" /gsd closeout Recover failed git closeout actions [status|retry|resolve] [unit-id]",
|
|
151
|
+
" /gsd rebuild markdown Rebuild markdown projections from the canonical DB",
|
|
152
|
+
" /gsd rebuild database Reserved for DB-native rebuilds; does not import markdown",
|
|
153
|
+
" /gsd recover --confirm Import markdown into the DB after DB loss/corruption",
|
|
150
154
|
" /gsd worktree Manage worktrees from the TUI [list|merge|clean|remove]",
|
|
151
155
|
" /gsd migrate Migrate .planning/ (v1) to DB-backed .gsd/ with backup + audit",
|
|
152
156
|
" /gsd remote Control remote auto-mode [slack|discord|status|disconnect]",
|
|
@@ -9,7 +9,7 @@ import { handleDoctor, handleCapture, handleKnowledge, handleRunHook, handleSkil
|
|
|
9
9
|
import { handleInspect } from "../../commands-inspect.js";
|
|
10
10
|
import { handleLogs } from "../../commands-logs.js";
|
|
11
11
|
import { handleDebug } from "../../commands-debug.js";
|
|
12
|
-
import { handleCleanupBranches, handleCleanupSnapshots, handleSkip, handleCleanupProjects, handleCleanupWorktrees, handleRecover } from "../../commands-maintenance.js";
|
|
12
|
+
import { handleCleanupBranches, handleCleanupSnapshots, handleSkip, handleCleanupProjects, handleCleanupWorktrees, handleRecover, handleRebuild } from "../../commands-maintenance.js";
|
|
13
13
|
import { handleExport } from "../../export.js";
|
|
14
14
|
import { handleHistory } from "../../history.js";
|
|
15
15
|
import { handleUndo } from "../../undo.js";
|
|
@@ -146,8 +146,12 @@ export async function handleOpsCommand(trimmed: string, ctx: ExtensionCommandCon
|
|
|
146
146
|
await handleSkip(trimmed.replace(/^skip\s*/, "").trim(), ctx, projectRoot());
|
|
147
147
|
return true;
|
|
148
148
|
}
|
|
149
|
-
if (trimmed === "recover") {
|
|
150
|
-
await handleRecover(ctx, projectRoot());
|
|
149
|
+
if (trimmed === "recover" || trimmed.startsWith("recover ")) {
|
|
150
|
+
await handleRecover(ctx, projectRoot(), trimmed.replace(/^recover\s*/, "").trim());
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
if (trimmed === "rebuild" || trimmed.startsWith("rebuild ")) {
|
|
154
|
+
await handleRebuild(ctx, projectRoot(), trimmed.replace(/^rebuild\s*/, "").trim());
|
|
151
155
|
return true;
|
|
152
156
|
}
|
|
153
157
|
if (trimmed === "closeout" || trimmed.startsWith("closeout ")) {
|
|
@@ -278,8 +282,8 @@ Examples:
|
|
|
278
282
|
await handleInspect(ctx);
|
|
279
283
|
return true;
|
|
280
284
|
}
|
|
281
|
-
if (trimmed === "update" || trimmed === "upgrade") {
|
|
282
|
-
await handleUpdate(ctx);
|
|
285
|
+
if (trimmed === "update" || trimmed.startsWith("update ") || trimmed === "upgrade" || trimmed.startsWith("upgrade ")) {
|
|
286
|
+
await handleUpdate(ctx, trimmed.replace(/^(?:update|upgrade)\s*/, "").trim());
|
|
283
287
|
return true;
|
|
284
288
|
}
|
|
285
289
|
if (trimmed === "fast" || trimmed.startsWith("fast ")) {
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
9
9
|
import { existsSync, readFileSync, mkdirSync } from "node:fs";
|
|
10
|
+
import { execFileSync } from "node:child_process";
|
|
11
|
+
import { createRequire } from "node:module";
|
|
10
12
|
import { join, resolve as resolvePath, sep } from "node:path";
|
|
11
13
|
import { homedir } from "node:os";
|
|
12
14
|
import { deriveState } from "./state.js";
|
|
@@ -37,7 +39,10 @@ import {
|
|
|
37
39
|
scopeGsdWorkflowToolsForDispatch,
|
|
38
40
|
} from "./bootstrap/register-hooks.js";
|
|
39
41
|
|
|
42
|
+
const GSD_PI_PACKAGE = "@opengsd/gsd-pi";
|
|
43
|
+
const GSD_BROWSER_PACKAGE = "@opengsd/gsd-browser";
|
|
40
44
|
const UPDATE_REGISTRY_URL = "https://registry.npmjs.org/@opengsd%2fgsd-pi/latest";
|
|
45
|
+
const BROWSER_UPDATE_REGISTRY_URL = "https://registry.npmjs.org/@opengsd%2fgsd-browser/latest";
|
|
41
46
|
const UPDATE_FETCH_TIMEOUT_MS = 5000;
|
|
42
47
|
|
|
43
48
|
// Detects a bun-installed gsd via `process.argv[1]`. Mirrors isBunInstall in
|
|
@@ -62,12 +67,12 @@ function resolveInstallCommand(pkg: string): string {
|
|
|
62
67
|
return `npm install -g ${pkg}`;
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
async function fetchLatestVersionForCommand(): Promise<string | null> {
|
|
70
|
+
async function fetchLatestVersionForCommand(registryUrl: string = UPDATE_REGISTRY_URL): Promise<string | null> {
|
|
66
71
|
const controller = new AbortController();
|
|
67
72
|
const timeout = setTimeout(() => controller.abort(), UPDATE_FETCH_TIMEOUT_MS);
|
|
68
73
|
|
|
69
74
|
try {
|
|
70
|
-
const res = await fetch(
|
|
75
|
+
const res = await fetch(registryUrl, { signal: controller.signal });
|
|
71
76
|
if (!res.ok) return null;
|
|
72
77
|
const data = (await res.json()) as { version?: string };
|
|
73
78
|
const latest = typeof data.version === "string" ? data.version.trim().replace(/^v/, "") : "";
|
|
@@ -79,6 +84,19 @@ async function fetchLatestVersionForCommand(): Promise<string | null> {
|
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
|
|
87
|
+
function resolveInstalledPackageVersionForCommand(packageName: string): string | null {
|
|
88
|
+
try {
|
|
89
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
90
|
+
const packageJsonPath = requireFromHere.resolve(`${packageName}/package.json`);
|
|
91
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as { version?: unknown };
|
|
92
|
+
return typeof pkg.version === "string" && pkg.version.trim().length > 0
|
|
93
|
+
? pkg.version.trim().replace(/^v/, "")
|
|
94
|
+
: null;
|
|
95
|
+
} catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
82
100
|
export function dispatchDoctorHeal(pi: ExtensionAPI, scope: string | undefined, reportText: string, structuredIssues: string): void {
|
|
83
101
|
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(gsdHome(), "agent", "GSD-WORKFLOW.md");
|
|
84
102
|
const workflow = readFileSync(workflowPath, "utf-8");
|
|
@@ -473,34 +491,81 @@ function compareSemverLocal(a: string, b: string): number {
|
|
|
473
491
|
return 0
|
|
474
492
|
}
|
|
475
493
|
|
|
476
|
-
|
|
494
|
+
function formatCommandVersion(version: string | null): string {
|
|
495
|
+
return version ? `v${version}` : "unknown";
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
function pickHigherVersionForCommand(a: string | null, b: string | null): string | null {
|
|
499
|
+
if (!a) return b;
|
|
500
|
+
if (!b) return a;
|
|
501
|
+
return compareSemverLocal(a, b) >= 0 ? a : b;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Mirrors resolveGsdBrowserPathVersion in src/update-check.ts — duplicated because
|
|
505
|
+
// tsconfig.resources.json rootDir prevents importing from src/.
|
|
506
|
+
function resolveGsdBrowserPathVersionForCommand(env: NodeJS.ProcessEnv = process.env): string | null {
|
|
507
|
+
const explicit = env.GSD_BROWSER_PATH_VERSION?.trim();
|
|
508
|
+
if (explicit) return explicit.match(/\b(\d+\.\d+\.\d+)\b/)?.[1] ?? null;
|
|
509
|
+
try {
|
|
510
|
+
const out = execFileSync("gsd-browser", ["--version"], {
|
|
511
|
+
encoding: "utf-8",
|
|
512
|
+
env,
|
|
513
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
514
|
+
timeout: 2000,
|
|
515
|
+
});
|
|
516
|
+
return out.match(/\b(\d+\.\d+\.\d+)\b/)?.[1] ?? null;
|
|
517
|
+
} catch {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export async function handleUpdate(ctx: ExtensionCommandContext, args = ""): Promise<void> {
|
|
477
523
|
const { execSync } = await import("node:child_process");
|
|
478
524
|
|
|
479
|
-
const
|
|
480
|
-
const
|
|
525
|
+
const target = args.trim();
|
|
526
|
+
const browserUpdate = target === "browser" || target === "gsd-browser";
|
|
527
|
+
if (target && !browserUpdate) {
|
|
528
|
+
ctx.ui.notify("Usage: /gsd update [browser]", "warning");
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const NPM_PACKAGE = browserUpdate ? GSD_BROWSER_PACKAGE : GSD_PI_PACKAGE;
|
|
533
|
+
const registryUrl = browserUpdate ? BROWSER_UPDATE_REGISTRY_URL : UPDATE_REGISTRY_URL;
|
|
534
|
+
const bundledVersion = browserUpdate
|
|
535
|
+
? resolveInstalledPackageVersionForCommand(GSD_BROWSER_PACKAGE)
|
|
536
|
+
: null;
|
|
537
|
+
const current = browserUpdate
|
|
538
|
+
? pickHigherVersionForCommand(bundledVersion, resolveGsdBrowserPathVersionForCommand())
|
|
539
|
+
: process.env.GSD_VERSION || "0.0.0";
|
|
540
|
+
const label = browserUpdate ? "gsd-browser version" : "version";
|
|
481
541
|
|
|
482
|
-
ctx.ui.notify(`Current
|
|
542
|
+
ctx.ui.notify(`Current ${label}: ${formatCommandVersion(current)}\nChecking npm registry...`, "info");
|
|
483
543
|
|
|
484
|
-
const latest = await fetchLatestVersionForCommand();
|
|
544
|
+
const latest = await fetchLatestVersionForCommand(registryUrl);
|
|
485
545
|
if (!latest) {
|
|
486
546
|
ctx.ui.notify("Failed to reach npm registry. Check your network connection.", "error");
|
|
487
547
|
return;
|
|
488
548
|
}
|
|
489
549
|
|
|
490
|
-
if (compareSemverLocal(latest, current) <= 0) {
|
|
491
|
-
ctx.ui.notify(`Already up to date (
|
|
550
|
+
if (current && compareSemverLocal(latest, current) <= 0) {
|
|
551
|
+
ctx.ui.notify(`Already up to date (${formatCommandVersion(current)}).`, "info");
|
|
492
552
|
return;
|
|
493
553
|
}
|
|
494
554
|
|
|
495
|
-
ctx.ui.notify(`Updating:
|
|
555
|
+
ctx.ui.notify(`Updating: ${formatCommandVersion(current)} → v${latest}...`, "info");
|
|
496
556
|
|
|
497
557
|
const installCmd = resolveInstallCommand(`${NPM_PACKAGE}@latest`);
|
|
498
558
|
try {
|
|
499
559
|
execSync(installCmd, {
|
|
500
560
|
stdio: ["ignore", "pipe", "ignore"],
|
|
501
561
|
});
|
|
562
|
+
const newPathVersion = browserUpdate ? resolveGsdBrowserPathVersionForCommand() : null;
|
|
563
|
+
const pathReady = !browserUpdate || (!!newPathVersion && compareSemverLocal(newPathVersion, latest) >= 0);
|
|
502
564
|
ctx.ui.notify(
|
|
503
|
-
|
|
565
|
+
browserUpdate
|
|
566
|
+
? `Updated gsd-browser to v${latest}. Restart your GSD session to use the new browser automation version.` +
|
|
567
|
+
(pathReady ? "" : "\nNote: Ensure the npm global bin directory is on your PATH so MCP automation uses the updated binary.")
|
|
568
|
+
: `Updated to v${latest}. Restart your GSD session to use the new version.`,
|
|
504
569
|
"info",
|
|
505
570
|
);
|
|
506
571
|
} catch {
|