@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
|
@@ -305,10 +305,18 @@ This config sets a parent workspace with two child repositories. The implicit `p
|
|
|
305
305
|
- `max_cycles`: number — max times this hook fires per trigger (default: 1, max: 10).
|
|
306
306
|
- `model`: string — optional model override.
|
|
307
307
|
- `artifact`: string — expected output file name (relative to task/slice dir). Hook is skipped if file already exists (idempotent).
|
|
308
|
+
- `criticality`: `"advisory"` or `"blocking"` — advisory preserves current best-effort behavior; blocking requires clean hook completion plus a valid outcome verdict before auto-mode advances. Default: `"advisory"`.
|
|
308
309
|
- `retry_on`: string — if this file is produced instead of the artifact, re-run the trigger unit then re-run hooks.
|
|
310
|
+
- `on_block`: object — optional routing for blocking findings:
|
|
311
|
+
- `action`: `"retry-unit"`, `"retry-task"`, `"queue-task"`, `"queue-slice"`, or `"pause"`.
|
|
312
|
+
- `artifact`: string — optional compatibility artifact for retry routing.
|
|
309
313
|
- `agent`: string — agent definition file to use for hook execution.
|
|
310
314
|
- `enabled`: boolean — toggle without removing (default: `true`).
|
|
311
315
|
|
|
316
|
+
Blocking hook artifacts must begin with YAML frontmatter containing either `verdict` or `outcome.verdict`.
|
|
317
|
+
Supported verdicts are `pass`, `advisory`, `needs-rework`, `needs-remediation`, and `needs-attention`.
|
|
318
|
+
`pass` and `advisory` continue; `needs-rework` retries the trigger unit when routed with `retry-unit`/`retry-task`; `needs-remediation` and `needs-attention` pause with recovery guidance.
|
|
319
|
+
|
|
312
320
|
- `pre_dispatch_hooks`: array — hooks that fire before a unit is dispatched. Each entry has:
|
|
313
321
|
- `name`: string — unique hook identifier.
|
|
314
322
|
- `before`: string[] — unit types to intercept.
|
|
@@ -269,14 +269,14 @@ export async function checkRuntimeHealth(
|
|
|
269
269
|
} catch {
|
|
270
270
|
count = MAX_UAT_ATTEMPTS + 1;
|
|
271
271
|
}
|
|
272
|
-
if (count
|
|
272
|
+
if (count < MAX_UAT_ATTEMPTS) continue;
|
|
273
273
|
|
|
274
274
|
issues.push({
|
|
275
275
|
severity: "warning",
|
|
276
276
|
code: "uat_retry_exhausted",
|
|
277
277
|
scope: "slice",
|
|
278
278
|
unitId: `${mid}/${sid}`,
|
|
279
|
-
message: `run-uat for ${mid}/${sid} exhausted ${count
|
|
279
|
+
message: `run-uat for ${mid}/${sid} exhausted ${count} attempt(s) without an ASSESSMENT verdict. Reset the retry counter after fixing the underlying UAT/tool issue, then rerun /gsd auto.`,
|
|
280
280
|
file: `.gsd/runtime/${fileName}`,
|
|
281
281
|
fixable: true,
|
|
282
282
|
});
|
|
@@ -47,9 +47,10 @@ export function resetRetryState(state: RetryState): void {
|
|
|
47
47
|
const PERMANENT_RE = /auth|unauthorized|forbidden|invalid.*key|invalid.*api|billing|quota exceeded|account/i;
|
|
48
48
|
// Include provider-specific quota-window phrasing like:
|
|
49
49
|
// - "You've hit your limit"
|
|
50
|
+
// - "You've reached your limit"
|
|
50
51
|
// - "usage limit" / "quota reached"
|
|
51
52
|
// - "out of extra usage"
|
|
52
|
-
const RATE_LIMIT_RE = /rate.?limit|too many requests|429|hit your limit|usage limit|out of extra usage|quota (?:reached|hit)|limit.*resets?/i;
|
|
53
|
+
const RATE_LIMIT_RE = /rate.?limit|too many requests|429|(?:hit|reached) your (?:\w+ )?limit|(?:usage|session|weekly|daily|monthly|quota) limit|out of extra usage|quota (?:reached|hit)|limit.*resets?/i;
|
|
53
54
|
// OpenRouter affordability-style quota errors should be treated as transient
|
|
54
55
|
// so core retry logic can lower maxTokens and continue in-session.
|
|
55
56
|
const AFFORDABILITY_RE = /requires more credits|can only afford|insufficient credits|not enough credits|fewer max_tokens/i;
|
|
@@ -159,13 +159,13 @@ export function readEscalationArtifact(path: string): EscalationArtifact | null
|
|
|
159
159
|
// ─── Detection ────────────────────────────────────────────────────────────
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
|
-
* Returns the task id of the first task with an
|
|
163
|
-
*
|
|
164
|
-
*
|
|
162
|
+
* Returns the task id of the first task with an unresolved escalation.
|
|
163
|
+
* `continueWithDefault=true` artifacts keep the awaiting_review flag for
|
|
164
|
+
* compatibility, but still pause dispatch until the user explicitly responds.
|
|
165
165
|
*/
|
|
166
166
|
export function detectPendingEscalation(tasks: TaskRow[], basePath: string): string | null {
|
|
167
167
|
for (const t of tasks) {
|
|
168
|
-
if (t.escalation_pending !== 1) continue;
|
|
168
|
+
if (t.escalation_pending !== 1 && t.escalation_awaiting_review !== 1) continue;
|
|
169
169
|
if (!t.escalation_artifact_path) continue;
|
|
170
170
|
const art = readEscalationArtifact(t.escalation_artifact_path);
|
|
171
171
|
if (art && !art.respondedAt) return t.id;
|
|
@@ -20,6 +20,8 @@ export interface ExecSandboxRequest {
|
|
|
20
20
|
script: string;
|
|
21
21
|
/** Optional purpose/label recorded in meta.json. */
|
|
22
22
|
purpose?: string;
|
|
23
|
+
/** Optional structured metadata recorded in meta.json. */
|
|
24
|
+
metadata?: Record<string, unknown>;
|
|
23
25
|
/** Per-invocation timeout in ms. Clamped to `clamp_timeout_ms`. */
|
|
24
26
|
timeout_ms?: number;
|
|
25
27
|
}
|
|
@@ -315,6 +317,7 @@ function writeMeta(
|
|
|
315
317
|
id: result.id,
|
|
316
318
|
runtime: result.runtime,
|
|
317
319
|
purpose: request.purpose ?? null,
|
|
320
|
+
...(request.metadata ? { metadata: request.metadata } : {}),
|
|
318
321
|
script_chars: request.script.length,
|
|
319
322
|
started_at: now.toISOString(),
|
|
320
323
|
finished_at: new Date(now.getTime() + result.duration_ms).toISOString(),
|
|
@@ -328,6 +331,7 @@ function writeMeta(
|
|
|
328
331
|
stderr_truncated: result.stderr_truncated,
|
|
329
332
|
stdout_path: result.stdout_path,
|
|
330
333
|
stderr_path: result.stderr_path,
|
|
334
|
+
...(request.metadata ? { metadata: request.metadata } : {}),
|
|
331
335
|
};
|
|
332
336
|
writeFileSync(path, `${JSON.stringify(meta, null, 2)}\n`);
|
|
333
337
|
}
|
|
@@ -123,6 +123,91 @@ interface ForensicReport {
|
|
|
123
123
|
worktreeTelemetry: WorktreeTelemetrySummary | null;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
// ─── Filing Tool Scope ───────────────────────────────────────────────────────
|
|
127
|
+
|
|
128
|
+
const FORENSICS_FILING_TOOLS = ["bash", "write"] as const;
|
|
129
|
+
|
|
130
|
+
type ForensicsFilingTool = typeof FORENSICS_FILING_TOOLS[number];
|
|
131
|
+
|
|
132
|
+
export interface ForensicsToolScope {
|
|
133
|
+
savedTools: string[];
|
|
134
|
+
activeToolsForTurn: string[];
|
|
135
|
+
availableFilingTools: ForensicsFilingTool[];
|
|
136
|
+
missingFilingTools: ForensicsFilingTool[];
|
|
137
|
+
toolsChanged: boolean;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function uniqueAppend(base: readonly string[], additions: readonly string[]): string[] {
|
|
141
|
+
const seen = new Set(base);
|
|
142
|
+
const next = [...base];
|
|
143
|
+
for (const name of additions) {
|
|
144
|
+
if (seen.has(name)) continue;
|
|
145
|
+
seen.add(name);
|
|
146
|
+
next.push(name);
|
|
147
|
+
}
|
|
148
|
+
return next;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function sameOrderedTools(a: readonly string[], b: readonly string[]): boolean {
|
|
152
|
+
return a.length === b.length && a.every((name, index) => name === b[index]);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function getRegisteredToolNames(
|
|
156
|
+
pi: Pick<ExtensionAPI, "getActiveTools"> & Partial<Pick<ExtensionAPI, "getAllTools">>,
|
|
157
|
+
fallback: readonly string[],
|
|
158
|
+
): string[] {
|
|
159
|
+
if (typeof pi.getAllTools === "function") {
|
|
160
|
+
return pi.getAllTools().map((tool) => tool.name);
|
|
161
|
+
}
|
|
162
|
+
return [...fallback];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function createForensicsToolScope(
|
|
166
|
+
pi: Pick<ExtensionAPI, "getActiveTools"> & Partial<Pick<ExtensionAPI, "getAllTools">>,
|
|
167
|
+
): ForensicsToolScope {
|
|
168
|
+
const savedTools = [...pi.getActiveTools()];
|
|
169
|
+
const registeredTools = new Set([...getRegisteredToolNames(pi, savedTools), ...savedTools]);
|
|
170
|
+
const availableFilingTools = FORENSICS_FILING_TOOLS.filter((name) => registeredTools.has(name));
|
|
171
|
+
const missingFilingTools = FORENSICS_FILING_TOOLS.filter((name) => !registeredTools.has(name));
|
|
172
|
+
const activeToolsForTurn = uniqueAppend(savedTools, availableFilingTools);
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
savedTools,
|
|
176
|
+
activeToolsForTurn,
|
|
177
|
+
availableFilingTools,
|
|
178
|
+
missingFilingTools,
|
|
179
|
+
toolsChanged: !sameOrderedTools(savedTools, activeToolsForTurn),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function applyForensicsToolScope(pi: Pick<ExtensionAPI, "setActiveTools">, scope: ForensicsToolScope): void {
|
|
184
|
+
if (scope.toolsChanged) pi.setActiveTools(scope.activeToolsForTurn);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function restoreForensicsToolScope(pi: Pick<ExtensionAPI, "setActiveTools">, scope: ForensicsToolScope): void {
|
|
188
|
+
if (scope.toolsChanged) pi.setActiveTools(scope.savedTools);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function buildForensicsToolingSection(scope: ForensicsToolScope): string {
|
|
192
|
+
const available = new Set(scope.availableFilingTools);
|
|
193
|
+
const requested = scope.availableFilingTools.length
|
|
194
|
+
? scope.availableFilingTools.map((name) => `\`${name}\``).join(", ")
|
|
195
|
+
: "none";
|
|
196
|
+
const statusFor = (name: ForensicsFilingTool) => available.has(name)
|
|
197
|
+
? `- \`${name}\`: available for this queued forensics turn`
|
|
198
|
+
: `- \`${name}\`: unavailable in this host session`;
|
|
199
|
+
|
|
200
|
+
return `
|
|
201
|
+
## Filing Tool Availability
|
|
202
|
+
|
|
203
|
+
For this queued forensic turn, the extension requested the registered filing tools: ${requested}.
|
|
204
|
+
|
|
205
|
+
${FORENSICS_FILING_TOOLS.map(statusFor).join("\n")}
|
|
206
|
+
|
|
207
|
+
If \`bash\` is available, use the GitHub duplicate-check and issue-creation protocols below. If \`bash\` is unavailable, do not attempt duplicate-check or issue-creation tool calls with another tool; provide the paste-once shell script fallback instead.
|
|
208
|
+
`;
|
|
209
|
+
}
|
|
210
|
+
|
|
126
211
|
// ─── Duplicate Detection ──────────────────────────────────────────────────────
|
|
127
212
|
|
|
128
213
|
const DEDUP_PROMPT_SECTION = `
|
|
@@ -134,6 +219,8 @@ Before reading GSD source code or performing deep analysis, you MUST search for
|
|
|
134
219
|
|
|
135
220
|
Use keywords from the user's problem description and the anomaly summaries in the forensic report above.
|
|
136
221
|
|
|
222
|
+
If \`bash\` is unavailable in the Filing Tool Availability section, do not attempt live duplicate-search tool calls. Say the live duplicate search must be run by the user, continue the source investigation, and include the duplicate-search commands in the paste-once fallback when issue filing is accepted.
|
|
223
|
+
|
|
137
224
|
1. **Search closed issues** for similar keywords:
|
|
138
225
|
\`\`\`
|
|
139
226
|
gh issue list --repo open-gsd/gsd-pi --state closed --search "<keywords from root cause>" --limit 20
|
|
@@ -265,21 +352,28 @@ export async function handleForensics(
|
|
|
265
352
|
}
|
|
266
353
|
|
|
267
354
|
const forensicData = formatReportForPrompt(report);
|
|
355
|
+
const toolScope = createForensicsToolScope(pi);
|
|
268
356
|
const content = loadPrompt("forensics", {
|
|
269
357
|
problemDescription,
|
|
270
358
|
forensicData,
|
|
271
359
|
gsdSourceDir,
|
|
272
360
|
dedupSection,
|
|
361
|
+
toolingSection: buildForensicsToolingSection(toolScope),
|
|
273
362
|
});
|
|
274
363
|
|
|
275
364
|
ctx.ui.notify(`Forensic report saved: ${relative(basePath, savedPath)}`, "info");
|
|
276
365
|
ctx.ui.setStatus("gsd-forensics", "running");
|
|
277
366
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
367
|
+
try {
|
|
368
|
+
applyForensicsToolScope(pi, toolScope);
|
|
369
|
+
await pi.sendMessage(
|
|
370
|
+
{ customType: "gsd-forensics", content, display: false },
|
|
371
|
+
{ triggerTurn: true },
|
|
372
|
+
);
|
|
373
|
+
} finally {
|
|
374
|
+
restoreForensicsToolScope(pi, toolScope);
|
|
375
|
+
ctx.ui.setStatus("gsd-forensics", undefined);
|
|
376
|
+
}
|
|
283
377
|
|
|
284
378
|
// Persist forensics context so follow-up turns can re-inject it (#2941)
|
|
285
379
|
writeForensicsMarker(basePath, savedPath, content);
|
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
import { rowToGate } from "./db-gate-rows.js";
|
|
56
56
|
import { rowToArtifact, rowToMilestone, type ArtifactRow, type MilestoneRow } from "./db-milestone-artifact-rows.js";
|
|
57
57
|
import { backupDatabaseBeforeMigration } from "./db-migration-backup.js";
|
|
58
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
58
59
|
import {
|
|
59
60
|
applyMigrationV2Artifacts,
|
|
60
61
|
applyMigrationV3Memories,
|
|
@@ -1487,7 +1488,7 @@ export function setTaskEscalationPending(
|
|
|
1487
1488
|
).run({ ":path": artifactPath, ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
|
|
1488
1489
|
}
|
|
1489
1490
|
|
|
1490
|
-
/** Set awaiting-review state (artifact exists
|
|
1491
|
+
/** Set awaiting-review state (artifact exists and requires explicit user review). Mutually exclusive with pending. */
|
|
1491
1492
|
export function setTaskEscalationAwaitingReview(
|
|
1492
1493
|
milestoneId: string, sliceId: string, taskId: string,
|
|
1493
1494
|
artifactPath: string,
|
|
@@ -1665,16 +1666,50 @@ export function setMilestoneQueueOrder(order: string[]): void {
|
|
|
1665
1666
|
}
|
|
1666
1667
|
}
|
|
1667
1668
|
|
|
1669
|
+
function getMilestoneStatusForUpdate(milestoneId: string): string | null {
|
|
1670
|
+
if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1671
|
+
const row = currentDb.prepare("SELECT status FROM milestones WHERE id = :id").get({ ":id": milestoneId });
|
|
1672
|
+
return typeof row?.["status"] === "string" ? row["status"] : null;
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
function writeMilestoneStatus(milestoneId: string, status: string, completedAt?: string | null): void {
|
|
1676
|
+
if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1677
|
+
currentDb.prepare(
|
|
1678
|
+
`UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`,
|
|
1679
|
+
).run({ ":status": status, ":completed_at": completedAt ?? null, ":id": milestoneId });
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1668
1682
|
/**
|
|
1669
1683
|
* Update a milestone's status in the database.
|
|
1670
|
-
*
|
|
1671
|
-
*
|
|
1684
|
+
*
|
|
1685
|
+
* Generic status updates may close milestones, park/unpark open milestones, or
|
|
1686
|
+
* advance planned milestones. They may not reopen a closed milestone; callers
|
|
1687
|
+
* must use reopenMilestoneStatus(), which is reserved for gsd_milestone_reopen.
|
|
1672
1688
|
*/
|
|
1673
1689
|
export function updateMilestoneStatus(milestoneId: string, status: string, completedAt?: string | null): void {
|
|
1674
1690
|
if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1691
|
+
const currentStatus = getMilestoneStatusForUpdate(milestoneId);
|
|
1692
|
+
if (currentStatus && isClosedStatus(currentStatus) && !isClosedStatus(status)) {
|
|
1693
|
+
throw new Error(
|
|
1694
|
+
`Cannot update closed milestone ${milestoneId} from ${currentStatus} to ${status}; use gsd_milestone_reopen for an explicit reopen.`,
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
writeMilestoneStatus(milestoneId, status, completedAt);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
/**
|
|
1701
|
+
* Explicit closed -> active transition for gsd_milestone_reopen only.
|
|
1702
|
+
*/
|
|
1703
|
+
export function reopenMilestoneStatus(milestoneId: string): void {
|
|
1704
|
+
if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1705
|
+
const currentStatus = getMilestoneStatusForUpdate(milestoneId);
|
|
1706
|
+
if (!currentStatus) {
|
|
1707
|
+
throw new Error(`Cannot reopen missing milestone ${milestoneId}`);
|
|
1708
|
+
}
|
|
1709
|
+
if (!isClosedStatus(currentStatus)) {
|
|
1710
|
+
throw new Error(`Cannot reopen milestone ${milestoneId} from status ${currentStatus}; milestone is not closed.`);
|
|
1711
|
+
}
|
|
1712
|
+
writeMilestoneStatus(milestoneId, "active", null);
|
|
1678
1713
|
}
|
|
1679
1714
|
|
|
1680
1715
|
export function getActiveMilestoneFromDb(): MilestoneRow | null {
|
|
@@ -2708,7 +2743,7 @@ export function deleteArtifactByPath(path: string): void {
|
|
|
2708
2743
|
|
|
2709
2744
|
/**
|
|
2710
2745
|
* Drop hierarchy rows in dependency order inside a transaction. Used by
|
|
2711
|
-
* `gsd recover` to rebuild engine state from markdown.
|
|
2746
|
+
* `gsd recover --confirm` to rebuild engine state from markdown.
|
|
2712
2747
|
*/
|
|
2713
2748
|
export function clearEngineHierarchy(): void {
|
|
2714
2749
|
if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
@@ -3198,7 +3233,10 @@ export function decayMemoriesBefore(cutoffTs: string, now: string): void {
|
|
|
3198
3233
|
currentDb.prepare(
|
|
3199
3234
|
`UPDATE memories
|
|
3200
3235
|
SET confidence = MAX(0.1, confidence - 0.1), updated_at = :now
|
|
3201
|
-
WHERE superseded_by IS NULL
|
|
3236
|
+
WHERE superseded_by IS NULL
|
|
3237
|
+
AND updated_at < :cutoff
|
|
3238
|
+
AND confidence > 0.1
|
|
3239
|
+
AND (structured_fields IS NULL OR structured_fields NOT LIKE '%"sourceDecisionId"%')`,
|
|
3202
3240
|
).run({ ":now": now, ":cutoff": cutoffTs });
|
|
3203
3241
|
}
|
|
3204
3242
|
|
|
@@ -227,21 +227,22 @@ async function dispatchDiscussForNextMilestoneWithBacklog(
|
|
|
227
227
|
nextId: string,
|
|
228
228
|
): Promise<void> {
|
|
229
229
|
const backlogContext = buildRequirementsBacklogDiscussContext(nextId);
|
|
230
|
-
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
231
230
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
232
|
-
const basePrompt =
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
inlinedTemplates: discussMilestoneTemplates,
|
|
231
|
+
const basePrompt = await buildDiscussMilestonePrompt(
|
|
232
|
+
nextId,
|
|
233
|
+
`New milestone ${nextId}`,
|
|
234
|
+
basePath,
|
|
237
235
|
structuredQuestionsAvailable,
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
236
|
+
{
|
|
237
|
+
commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
|
|
238
|
+
includeContextMode: false,
|
|
239
|
+
fastPathInstruction: [
|
|
240
|
+
"> **Requirements backlog active.**",
|
|
241
|
+
"> Map unmapped active requirements to this milestone before finalizing context.",
|
|
242
|
+
"> Confirm ownership with the user when scope is ambiguous.",
|
|
243
|
+
].join("\n"),
|
|
244
|
+
},
|
|
245
|
+
);
|
|
245
246
|
const prompt = backlogContext ? `${basePrompt}\n\n${backlogContext}` : basePrompt;
|
|
246
247
|
await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
247
248
|
}
|
|
@@ -1371,6 +1372,7 @@ async function buildDiscussPreparationContext(
|
|
|
1371
1372
|
ctx: ExtensionCommandContext,
|
|
1372
1373
|
basePath: string,
|
|
1373
1374
|
mode: "greenfield" | "milestone" = "greenfield",
|
|
1375
|
+
skipPriorContext = false,
|
|
1374
1376
|
): Promise<string> {
|
|
1375
1377
|
const prefs = loadEffectiveGSDPreferences()?.preferences ?? {};
|
|
1376
1378
|
if (prefs.discuss_preparation === false) return "";
|
|
@@ -1388,7 +1390,7 @@ async function buildDiscussPreparationContext(
|
|
|
1388
1390
|
const priorContextBrief = prepResult.priorContextBrief || formatPriorContextBrief(prepResult.priorContext);
|
|
1389
1391
|
const parts: string[] = [];
|
|
1390
1392
|
if (codebaseBrief) parts.push(`### Codebase Brief\n\n${codebaseBrief}`);
|
|
1391
|
-
if (priorContextBrief) parts.push(`### Prior Context Brief\n\n${priorContextBrief}`);
|
|
1393
|
+
if (priorContextBrief && !skipPriorContext) parts.push(`### Prior Context Brief\n\n${priorContextBrief}`);
|
|
1392
1394
|
if (parts.length === 0) return "";
|
|
1393
1395
|
|
|
1394
1396
|
const guidance = mode === "milestone"
|
|
@@ -1441,18 +1443,18 @@ async function dispatchNewMilestoneDiscuss(
|
|
|
1441
1443
|
return;
|
|
1442
1444
|
}
|
|
1443
1445
|
|
|
1444
|
-
const preparationContext = await buildDiscussPreparationContext(ctx, basePath, "milestone");
|
|
1445
|
-
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
1446
|
+
const preparationContext = await buildDiscussPreparationContext(ctx, basePath, "milestone", true);
|
|
1446
1447
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
1447
|
-
let prompt =
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
inlinedTemplates: discussMilestoneTemplates,
|
|
1448
|
+
let prompt = await buildDiscussMilestonePrompt(
|
|
1449
|
+
nextId,
|
|
1450
|
+
`New milestone ${nextId}`,
|
|
1451
|
+
basePath,
|
|
1452
1452
|
structuredQuestionsAvailable,
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1453
|
+
{
|
|
1454
|
+
commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
|
|
1455
|
+
includeContextMode: false,
|
|
1456
|
+
},
|
|
1457
|
+
);
|
|
1456
1458
|
if (preparationContext) prompt += preparationContext;
|
|
1457
1459
|
await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
1458
1460
|
}
|
|
@@ -1759,9 +1761,6 @@ export async function showDiscuss(
|
|
|
1759
1761
|
// Special case: milestone is in needs-discussion phase (has CONTEXT-DRAFT.md but no roadmap yet).
|
|
1760
1762
|
// Route to the draft discussion flow instead of erroring — the discussion IS how the roadmap gets created.
|
|
1761
1763
|
if (state.phase === "needs-discussion") {
|
|
1762
|
-
const draftFile = resolveMilestoneFile(basePath, mid, "CONTEXT-DRAFT");
|
|
1763
|
-
const draftContent = draftFile ? await loadFile(draftFile) : null;
|
|
1764
|
-
|
|
1765
1764
|
const choice = await showNextAction(ctx, {
|
|
1766
1765
|
title: `GSD — ${mid}: ${milestoneTitle}`,
|
|
1767
1766
|
summary: ["This milestone has a draft context from a prior discussion.", "It needs a dedicated discussion before auto-planning can begin."],
|
|
@@ -1787,29 +1786,34 @@ export async function showDiscuss(
|
|
|
1787
1786
|
});
|
|
1788
1787
|
|
|
1789
1788
|
if (choice === "discuss_draft") {
|
|
1790
|
-
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
1791
1789
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
1792
|
-
const
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1790
|
+
const seed = await buildDiscussMilestonePrompt(
|
|
1791
|
+
mid,
|
|
1792
|
+
milestoneTitle,
|
|
1793
|
+
basePath,
|
|
1794
|
+
structuredQuestionsAvailable,
|
|
1795
|
+
{
|
|
1796
|
+
commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
|
|
1797
|
+
includeContextMode: false,
|
|
1798
|
+
},
|
|
1799
|
+
);
|
|
1801
1800
|
setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: mid, step: true });
|
|
1802
1801
|
await dispatchWorkflow(pi, seed, "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
1803
1802
|
} else if (choice === "discuss_fresh") {
|
|
1804
|
-
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
1805
1803
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
1804
|
+
const prompt = await buildDiscussMilestonePrompt(
|
|
1805
|
+
mid,
|
|
1806
|
+
milestoneTitle,
|
|
1807
|
+
basePath,
|
|
1808
|
+
structuredQuestionsAvailable,
|
|
1809
|
+
{
|
|
1810
|
+
commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
|
|
1811
|
+
includeContextMode: false,
|
|
1812
|
+
includeDraftSeed: false,
|
|
1813
|
+
},
|
|
1814
|
+
);
|
|
1806
1815
|
setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: mid, step: true });
|
|
1807
|
-
await dispatchWorkflow(pi,
|
|
1808
|
-
workingDirectory: basePath,
|
|
1809
|
-
milestoneId: mid, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
1810
|
-
commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
|
|
1811
|
-
fastPathInstruction: "",
|
|
1812
|
-
}), "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
1816
|
+
await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
1813
1817
|
} else if (choice === "skip_milestone") {
|
|
1814
1818
|
const { ensureDbOpen } = await import("./bootstrap/dynamic-tools.js");
|
|
1815
1819
|
await ensureDbOpen(basePath);
|
|
@@ -2068,20 +2072,18 @@ async function dispatchDiscussForMilestone(
|
|
|
2068
2072
|
"> Ask only questions where the answer would materially change scope.",
|
|
2069
2073
|
].join("\n")
|
|
2070
2074
|
: "";
|
|
2071
|
-
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
2072
2075
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
2073
|
-
const
|
|
2074
|
-
|
|
2075
|
-
milestoneId: mid,
|
|
2076
|
+
const prompt = await buildDiscussMilestonePrompt(
|
|
2077
|
+
mid,
|
|
2076
2078
|
milestoneTitle,
|
|
2077
|
-
|
|
2079
|
+
basePath,
|
|
2078
2080
|
structuredQuestionsAvailable,
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2081
|
+
{
|
|
2082
|
+
commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
|
|
2083
|
+
includeContextMode: false,
|
|
2084
|
+
fastPathInstruction,
|
|
2085
|
+
},
|
|
2086
|
+
);
|
|
2085
2087
|
await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
2086
2088
|
}
|
|
2087
2089
|
|
|
@@ -2374,7 +2376,7 @@ export async function showSmartEntry(
|
|
|
2374
2376
|
if (result.action === "recovery-required") {
|
|
2375
2377
|
ctx.ui.notify(
|
|
2376
2378
|
result.message ??
|
|
2377
|
-
`Markdown planning artifacts do not match the authoritative DB. Run \`${result.recoveryCommand ?? "/gsd recover"}\` to import markdown explicitly.`,
|
|
2379
|
+
`Markdown planning artifacts do not match the authoritative DB. Run \`${result.recoveryCommand ?? "/gsd recover --confirm"}\` to import markdown explicitly.`,
|
|
2378
2380
|
"warning",
|
|
2379
2381
|
);
|
|
2380
2382
|
}
|
|
@@ -2612,9 +2614,6 @@ export async function showSmartEntry(
|
|
|
2612
2614
|
|
|
2613
2615
|
// ── Draft milestone — needs discussion before planning ────────────────
|
|
2614
2616
|
if (state.phase === "needs-discussion") {
|
|
2615
|
-
const draftFile = resolveMilestoneFile(basePath, milestoneId, "CONTEXT-DRAFT");
|
|
2616
|
-
const draftContent = draftFile ? await loadFile(draftFile) : null;
|
|
2617
|
-
|
|
2618
2617
|
const choice = await showNextAction(ctx, {
|
|
2619
2618
|
title: `GSD — ${milestoneId}: ${milestoneTitle}`,
|
|
2620
2619
|
summary: ["This milestone has a draft context from a prior discussion.", "It needs a dedicated discussion before auto-planning can begin."],
|
|
@@ -2640,29 +2639,34 @@ export async function showSmartEntry(
|
|
|
2640
2639
|
});
|
|
2641
2640
|
|
|
2642
2641
|
if (choice === "discuss_draft") {
|
|
2643
|
-
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
2644
2642
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
2645
|
-
const
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2643
|
+
const seed = await buildDiscussMilestonePrompt(
|
|
2644
|
+
milestoneId,
|
|
2645
|
+
milestoneTitle,
|
|
2646
|
+
basePath,
|
|
2647
|
+
structuredQuestionsAvailable,
|
|
2648
|
+
{
|
|
2649
|
+
commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
|
|
2650
|
+
includeContextMode: false,
|
|
2651
|
+
},
|
|
2652
|
+
);
|
|
2654
2653
|
setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId, step: stepMode });
|
|
2655
2654
|
await dispatchWorkflow(pi, seed, "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
2656
2655
|
} else if (choice === "discuss_fresh") {
|
|
2657
|
-
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
2658
2656
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
2657
|
+
const prompt = await buildDiscussMilestonePrompt(
|
|
2658
|
+
milestoneId,
|
|
2659
|
+
milestoneTitle,
|
|
2660
|
+
basePath,
|
|
2661
|
+
structuredQuestionsAvailable,
|
|
2662
|
+
{
|
|
2663
|
+
commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
|
|
2664
|
+
includeContextMode: false,
|
|
2665
|
+
includeDraftSeed: false,
|
|
2666
|
+
},
|
|
2667
|
+
);
|
|
2659
2668
|
setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId, step: stepMode });
|
|
2660
|
-
await dispatchWorkflow(pi,
|
|
2661
|
-
workingDirectory: basePath,
|
|
2662
|
-
milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
2663
|
-
commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
|
|
2664
|
-
fastPathInstruction: "",
|
|
2665
|
-
}), "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
2669
|
+
await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
|
|
2666
2670
|
} else if (choice === "skip_milestone") {
|
|
2667
2671
|
const milestoneIds = findMilestoneIds(basePath);
|
|
2668
2672
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
@@ -2783,14 +2787,18 @@ export async function showSmartEntry(
|
|
|
2783
2787
|
{ basePath },
|
|
2784
2788
|
);
|
|
2785
2789
|
} else if (choice === "discuss") {
|
|
2786
|
-
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
2787
2790
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
2788
|
-
await
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2791
|
+
const prompt = await buildDiscussMilestonePrompt(
|
|
2792
|
+
milestoneId,
|
|
2793
|
+
milestoneTitle,
|
|
2794
|
+
basePath,
|
|
2795
|
+
structuredQuestionsAvailable,
|
|
2796
|
+
{
|
|
2797
|
+
commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
|
|
2798
|
+
includeContextMode: false,
|
|
2799
|
+
},
|
|
2800
|
+
);
|
|
2801
|
+
await dispatchWorkflow(pi, prompt, "gsd-run", ctx, "discuss-milestone", { basePath });
|
|
2794
2802
|
} else if (choice === "skip_milestone") {
|
|
2795
2803
|
const milestoneIds = findMilestoneIds(basePath);
|
|
2796
2804
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
@@ -40,9 +40,11 @@ function collectServerEntries(servers: unknown): DiscoveredMcpServer[] {
|
|
|
40
40
|
export function discoverMcpServers(projectDir: string): DiscoveredMcpServer[] {
|
|
41
41
|
const mcpJsonPath = resolve(projectDir, ".mcp.json");
|
|
42
42
|
const settingsPath = resolve(projectDir, ".claude", "settings.json");
|
|
43
|
+
const localSettingsPath = resolve(projectDir, ".claude", "settings.local.json");
|
|
43
44
|
|
|
44
45
|
const mcpJson = readJsonFile(mcpJsonPath) as McpJsonFile | undefined;
|
|
45
46
|
const settings = readJsonFile(settingsPath, true) as ClaudeSettingsFile | undefined;
|
|
47
|
+
const localSettings = readJsonFile(localSettingsPath, true) as ClaudeSettingsFile | undefined;
|
|
46
48
|
|
|
47
49
|
const seen = new Set<string>();
|
|
48
50
|
const discovered: DiscoveredMcpServer[] = [];
|
|
@@ -50,6 +52,7 @@ export function discoverMcpServers(projectDir: string): DiscoveredMcpServer[] {
|
|
|
50
52
|
...collectServerEntries(mcpJson?.mcpServers),
|
|
51
53
|
...collectServerEntries(mcpJson?.servers),
|
|
52
54
|
...collectServerEntries(settings?.mcpServers),
|
|
55
|
+
...collectServerEntries(localSettings?.mcpServers),
|
|
53
56
|
]) {
|
|
54
57
|
if (seen.has(entry.name)) continue;
|
|
55
58
|
seen.add(entry.name);
|