@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
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GSD Maintenance — cleanup, skip, dry-run, and recover handlers.
|
|
3
3
|
*
|
|
4
|
-
* Contains: handleCleanupBranches, handleCleanupSnapshots, handleCleanupWorktrees, handleSkip, handleDryRun, handleRecover
|
|
4
|
+
* Contains: handleCleanupBranches, handleCleanupSnapshots, handleCleanupWorktrees, handleSkip, handleDryRun, handleRecover, handleRebuild
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
8
|
+
import { existsSync, mkdirSync, renameSync } from "node:fs";
|
|
9
|
+
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
8
10
|
import { deriveState } from "./state.js";
|
|
11
|
+
import { gsdProjectionRoot, gsdRoot } from "./paths.js";
|
|
9
12
|
import { nativeBranchList, nativeDetectMainBranch, nativeBranchListMerged, nativeBranchDelete, nativeForEachRef, nativeUpdateRef } from "./native-git-bridge.js";
|
|
10
13
|
import { logWarning } from "./workflow-logger.js";
|
|
11
14
|
|
|
@@ -478,6 +481,39 @@ export async function handleCleanupProjects(args: string, ctx: ExtensionCommandC
|
|
|
478
481
|
ctx.ui.notify(lines.join("\n"), "info");
|
|
479
482
|
}
|
|
480
483
|
|
|
484
|
+
function recoverConfirmed(args: string): boolean {
|
|
485
|
+
return args
|
|
486
|
+
.split(/\s+/)
|
|
487
|
+
.map((part) => part.trim().toLowerCase())
|
|
488
|
+
.some((part) => part === "--confirm" || part === "--yes" || part === "confirm");
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
async function confirmRecover(ctx: ExtensionCommandContext, args: string): Promise<boolean> {
|
|
492
|
+
if (recoverConfirmed(args)) return true;
|
|
493
|
+
|
|
494
|
+
const warning = [
|
|
495
|
+
"gsd recover imports markdown into the database.",
|
|
496
|
+
"It clears and reconstructs milestone, slice, and task hierarchy rows from rendered markdown.",
|
|
497
|
+
"Use /gsd rebuild markdown for normal DB-to-markdown realignment.",
|
|
498
|
+
].join("\n");
|
|
499
|
+
|
|
500
|
+
if (typeof ctx.ui.confirm === "function") {
|
|
501
|
+
const confirmed = await ctx.ui.confirm(
|
|
502
|
+
"Import markdown into the DB?",
|
|
503
|
+
`${warning}\n\nContinue only if the DB is lost or corrupt and markdown is the source you intend to import.`,
|
|
504
|
+
);
|
|
505
|
+
if (confirmed) return true;
|
|
506
|
+
ctx.ui.notify("gsd recover cancelled. No database changes made.", "info");
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
ctx.ui.notify(
|
|
511
|
+
`${warning}\n\nNo database changes made. Re-run /gsd recover --confirm to proceed.`,
|
|
512
|
+
"warning",
|
|
513
|
+
);
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
|
|
481
517
|
/**
|
|
482
518
|
* `gsd recover` — Reconstruct DB hierarchy state from rendered markdown on disk.
|
|
483
519
|
*
|
|
@@ -487,7 +523,7 @@ export async function handleCleanupProjects(args: string, ctx: ExtensionCommandC
|
|
|
487
523
|
*
|
|
488
524
|
* Prints counts of recovered items and the resulting project phase.
|
|
489
525
|
*/
|
|
490
|
-
export async function handleRecover(ctx: ExtensionCommandContext, basePath: string): Promise<void> {
|
|
526
|
+
export async function handleRecover(ctx: ExtensionCommandContext, basePath: string, args = ""): Promise<void> {
|
|
491
527
|
const { isDbAvailable: dbAvailable, clearEngineHierarchy, transaction: dbTransaction } = await import("./gsd-db.js");
|
|
492
528
|
const { migrateHierarchyToDb } = await import("./md-importer.js");
|
|
493
529
|
const { invalidateStateCache } = await import("./state.js");
|
|
@@ -497,6 +533,8 @@ export async function handleRecover(ctx: ExtensionCommandContext, basePath: stri
|
|
|
497
533
|
return;
|
|
498
534
|
}
|
|
499
535
|
|
|
536
|
+
if (!(await confirmRecover(ctx, args))) return;
|
|
537
|
+
|
|
500
538
|
try {
|
|
501
539
|
// 1. Delete + re-populate inside a single transaction for atomicity.
|
|
502
540
|
// clearEngineHierarchy() uses transaction() internally but transaction()
|
|
@@ -542,3 +580,160 @@ export async function handleRecover(ctx: ExtensionCommandContext, basePath: stri
|
|
|
542
580
|
ctx.ui.notify(`gsd recover failed: ${msg}`, "error");
|
|
543
581
|
}
|
|
544
582
|
}
|
|
583
|
+
|
|
584
|
+
function normalizeArtifactPath(value: string): string {
|
|
585
|
+
return value.replace(/\\/g, "/");
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
function pathWithin(root: string, candidate: string): boolean {
|
|
589
|
+
const rel = relative(root, candidate);
|
|
590
|
+
return rel.length === 0 || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
function artifactPathForDb(basePath: string, absPath: string): string {
|
|
594
|
+
const projectionRoot = gsdProjectionRoot(basePath);
|
|
595
|
+
const root = pathWithin(projectionRoot, absPath) ? projectionRoot : gsdRoot(basePath);
|
|
596
|
+
return normalizeArtifactPath(relative(root, absPath));
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function quarantineRelativePath(basePath: string, absPath: string): string {
|
|
600
|
+
for (const root of [gsdProjectionRoot(basePath), gsdRoot(basePath)]) {
|
|
601
|
+
if (pathWithin(root, absPath)) {
|
|
602
|
+
return normalizeArtifactPath(relative(root, absPath));
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
return normalizeArtifactPath(absPath.replace(/^[/\\]+/, ""));
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function uniquePath(path: string): string {
|
|
609
|
+
if (!existsSync(path)) return path;
|
|
610
|
+
let idx = 2;
|
|
611
|
+
while (existsSync(`${path}.${idx}`)) idx++;
|
|
612
|
+
return `${path}.${idx}`;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function resolveDiskArtifactPath(basePath: string, artifactPath: string): string {
|
|
616
|
+
if (isAbsolute(artifactPath)) return artifactPath;
|
|
617
|
+
const candidates = [
|
|
618
|
+
join(gsdProjectionRoot(basePath), artifactPath),
|
|
619
|
+
join(gsdRoot(basePath), artifactPath),
|
|
620
|
+
];
|
|
621
|
+
return candidates.find((candidate) => existsSync(candidate)) ?? candidates[0]!;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function quarantineProjectionFile(basePath: string, absPath: string, stamp: string): string {
|
|
625
|
+
const rel = quarantineRelativePath(basePath, absPath);
|
|
626
|
+
const target = uniquePath(join(gsdProjectionRoot(basePath), "quarantine", "projections", stamp, rel));
|
|
627
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
628
|
+
renameSync(absPath, target);
|
|
629
|
+
return target;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
type RebuildTarget = "markdown" | "database" | "usage";
|
|
633
|
+
|
|
634
|
+
function parseRebuildTarget(args: string): RebuildTarget {
|
|
635
|
+
const trimmed = args.trim().toLowerCase();
|
|
636
|
+
if (!trimmed || trimmed === "markdown") return "markdown";
|
|
637
|
+
if (trimmed === "database" || trimmed === "db") return "database";
|
|
638
|
+
return "usage";
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* `gsd rebuild markdown` — Re-render markdown projections from the authoritative DB.
|
|
643
|
+
*
|
|
644
|
+
* This is the DB-first realignment command. It does not import markdown into
|
|
645
|
+
* the DB. Completion SUMMARY files that contradict open DB rows are preserved
|
|
646
|
+
* under `.gsd/quarantine/projections/` before DB projections are rendered.
|
|
647
|
+
*/
|
|
648
|
+
export async function handleRebuild(ctx: ExtensionCommandContext, basePath: string, args = ""): Promise<void> {
|
|
649
|
+
const { isDbAvailable: dbAvailable, deleteArtifactByPath } = await import("./gsd-db.js");
|
|
650
|
+
const { detectArtifactDbDrift } = await import("./state-reconciliation/drift/artifact-db.js");
|
|
651
|
+
const { renderAllFromDb } = await import("./markdown-renderer.js");
|
|
652
|
+
const { invalidateStateCache } = await import("./state.js");
|
|
653
|
+
|
|
654
|
+
const target = parseRebuildTarget(args);
|
|
655
|
+
if (target === "usage") {
|
|
656
|
+
ctx.ui.notify(
|
|
657
|
+
[
|
|
658
|
+
"Usage:",
|
|
659
|
+
" /gsd rebuild markdown Rebuild markdown projections from the canonical DB",
|
|
660
|
+
" /gsd rebuild database Reserved for DB-native rebuilds; does not import markdown",
|
|
661
|
+
].join("\n"),
|
|
662
|
+
"warning",
|
|
663
|
+
);
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
if (target === "database") {
|
|
668
|
+
ctx.ui.notify(
|
|
669
|
+
[
|
|
670
|
+
"gsd rebuild database is reserved for DB-native rebuilds.",
|
|
671
|
+
"It will not import markdown projections into the DB.",
|
|
672
|
+
"For normal realignment, run /gsd rebuild markdown.",
|
|
673
|
+
"If the DB is lost or corrupt and markdown is the source to import, run /gsd recover --confirm.",
|
|
674
|
+
].join("\n"),
|
|
675
|
+
"warning",
|
|
676
|
+
);
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (!dbAvailable()) {
|
|
681
|
+
ctx.ui.notify("gsd rebuild markdown: No database open. Run a GSD command first to initialize the DB.", "error");
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
try {
|
|
686
|
+
invalidateStateCache();
|
|
687
|
+
const state = await deriveState(basePath);
|
|
688
|
+
const drifts = detectArtifactDbDrift(state, { basePath, state });
|
|
689
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
690
|
+
const quarantined: string[] = [];
|
|
691
|
+
const seen = new Set<string>();
|
|
692
|
+
|
|
693
|
+
for (const drift of drifts) {
|
|
694
|
+
if (drift.kind !== "artifact-db-status-divergence") continue;
|
|
695
|
+
if (drift.artifactType !== "SUMMARY" || !drift.artifactPath) continue;
|
|
696
|
+
const absPath = resolveDiskArtifactPath(basePath, drift.artifactPath);
|
|
697
|
+
if (seen.has(absPath) || !existsSync(absPath)) continue;
|
|
698
|
+
seen.add(absPath);
|
|
699
|
+
const artifactDbPath = artifactPathForDb(basePath, absPath);
|
|
700
|
+
const target = quarantineProjectionFile(basePath, absPath, stamp);
|
|
701
|
+
deleteArtifactByPath(artifactDbPath);
|
|
702
|
+
quarantined.push(target);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const rendered = await renderAllFromDb(basePath);
|
|
706
|
+
invalidateStateCache();
|
|
707
|
+
|
|
708
|
+
const lines = [
|
|
709
|
+
"gsd rebuild markdown: rebuilt markdown projections from the canonical DB",
|
|
710
|
+
` Rendered: ${rendered.rendered}`,
|
|
711
|
+
` Skipped: ${rendered.skipped}`,
|
|
712
|
+
` Quarantined: ${quarantined.length}`,
|
|
713
|
+
];
|
|
714
|
+
if (rendered.errors.length > 0) {
|
|
715
|
+
lines.push(` Errors: ${rendered.errors.length}`);
|
|
716
|
+
for (const err of rendered.errors.slice(0, 5)) {
|
|
717
|
+
lines.push(` - ${err}`);
|
|
718
|
+
}
|
|
719
|
+
if (rendered.errors.length > 5) {
|
|
720
|
+
lines.push(` - ${rendered.errors.length - 5} more`);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
if (quarantined.length > 0) {
|
|
724
|
+
lines.push("", " Quarantine:");
|
|
725
|
+
for (const target of quarantined.slice(0, 5)) {
|
|
726
|
+
lines.push(` - ${target}`);
|
|
727
|
+
}
|
|
728
|
+
if (quarantined.length > 5) {
|
|
729
|
+
lines.push(` - ${quarantined.length - 5} more`);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
ctx.ui.notify(lines.join("\n"), rendered.errors.length > 0 ? "warning" : "success");
|
|
734
|
+
} catch (err) {
|
|
735
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
736
|
+
logWarning("command", `rebuild failed: ${msg}`);
|
|
737
|
+
ctx.ui.notify(`gsd rebuild failed: ${msg}`, "error");
|
|
738
|
+
}
|
|
739
|
+
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* /gsd mcp — Overview of all servers (alias: /gsd mcp status)
|
|
8
8
|
* /gsd mcp status — Same as bare /gsd mcp
|
|
9
9
|
* /gsd mcp check <srv> — Detailed status for a specific server
|
|
10
|
+
* /gsd mcp discover [srv] — Connect and list tools for a server
|
|
10
11
|
* /gsd mcp test <srv> — Test handshake + tools/list for a server
|
|
11
12
|
* /gsd mcp enable <srv> / disable <srv> — Toggle local server exposure
|
|
12
13
|
* /gsd mcp import <srv> [as <name>] — Copy a discovered server into local config
|
|
@@ -34,6 +35,7 @@ export interface McpServerStatus {
|
|
|
34
35
|
name: string;
|
|
35
36
|
transport: ManagedMcpTransport;
|
|
36
37
|
connected: boolean;
|
|
38
|
+
available?: boolean;
|
|
37
39
|
toolCount: number;
|
|
38
40
|
error: string | undefined;
|
|
39
41
|
disabled?: boolean;
|
|
@@ -45,6 +47,8 @@ export interface McpServerDetail extends McpServerStatus {
|
|
|
45
47
|
tools: string[];
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
const MCP_STATUS_PROBE_TIMEOUT_MS = 10_000;
|
|
51
|
+
|
|
48
52
|
export function hasHostMcpTool(systemPrompt: string, serverName: string): boolean {
|
|
49
53
|
const marker = `mcp__${serverName}__`;
|
|
50
54
|
return systemPrompt.includes(marker);
|
|
@@ -68,7 +72,8 @@ export function formatMcpInitResult(
|
|
|
68
72
|
`Project: ${targetPath}`,
|
|
69
73
|
`Config: ${configPath}`,
|
|
70
74
|
"",
|
|
71
|
-
"MCP-capable clients can now load the GSD workflow MCP
|
|
75
|
+
"MCP-capable clients can now load the GSD workflow and gsd-browser MCP servers from this folder.",
|
|
76
|
+
"Pi Providers use the managed gsd-browser engine directly; this project config is for External MCP Clients.",
|
|
72
77
|
"Restart or reconnect any client that already has this project open.",
|
|
73
78
|
].join("\n");
|
|
74
79
|
}
|
|
@@ -89,13 +94,15 @@ export function formatMcpStatusReport(servers: McpServerStatus[]): string {
|
|
|
89
94
|
const lines: string[] = [`MCP Server Status — ${servers.length} server(s)\n`];
|
|
90
95
|
|
|
91
96
|
for (const s of servers) {
|
|
92
|
-
const icon = s.disabled ? "⊘" : s.error ? "✗" : s.connected ? "✓" : "○";
|
|
97
|
+
const icon = s.disabled ? "⊘" : s.error ? "✗" : s.connected || s.available ? "✓" : "○";
|
|
93
98
|
const status = s.disabled
|
|
94
99
|
? "disabled"
|
|
95
100
|
: s.error
|
|
96
101
|
? `error: ${s.error}`
|
|
97
102
|
: s.connected
|
|
98
103
|
? `connected — ${s.toolCount} tools`
|
|
104
|
+
: s.available
|
|
105
|
+
? `available — ${s.toolCount} tools`
|
|
99
106
|
: "disconnected";
|
|
100
107
|
const warningText = s.envWarnings?.length ? ` — ${s.envWarnings.length} warning(s)` : "";
|
|
101
108
|
lines.push(` ${icon} ${s.name} (${s.transport}) — ${status}${warningText}`);
|
|
@@ -103,8 +110,8 @@ export function formatMcpStatusReport(servers: McpServerStatus[]): string {
|
|
|
103
110
|
|
|
104
111
|
lines.push("");
|
|
105
112
|
lines.push("Use /gsd mcp check <server> for details on a specific server.");
|
|
113
|
+
lines.push("Use /gsd mcp discover <server> to connect and list tools.");
|
|
106
114
|
lines.push("Use /gsd mcp test <server> to verify handshake and tool discovery.");
|
|
107
|
-
lines.push("Use mcp_discover to connect and list tools for a server.");
|
|
108
115
|
|
|
109
116
|
return lines.join("\n");
|
|
110
117
|
}
|
|
@@ -120,8 +127,8 @@ export function formatMcpServerDetail(server: McpServerDetail): string {
|
|
|
120
127
|
} else if (server.error) {
|
|
121
128
|
lines.push(` Status: error`);
|
|
122
129
|
lines.push(` Error: ${server.error}`);
|
|
123
|
-
} else if (server.connected) {
|
|
124
|
-
lines.push(` Status: connected`);
|
|
130
|
+
} else if (server.connected || server.available) {
|
|
131
|
+
lines.push(` Status: ${server.connected ? "connected" : "available"}`);
|
|
125
132
|
lines.push(` Tools: ${server.toolCount}`);
|
|
126
133
|
if (server.tools.length > 0) {
|
|
127
134
|
lines.push("");
|
|
@@ -133,7 +140,7 @@ export function formatMcpServerDetail(server: McpServerDetail): string {
|
|
|
133
140
|
} else {
|
|
134
141
|
lines.push(` Status: disconnected`);
|
|
135
142
|
lines.push("");
|
|
136
|
-
lines.push(` Run
|
|
143
|
+
lines.push(` Run /gsd mcp discover ${server.name} to connect and list tools.`);
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
if (server.envWarnings?.length) {
|
|
@@ -167,10 +174,93 @@ export function formatMcpConnectionTestResult(result: ManagedMcpConnectionTestRe
|
|
|
167
174
|
].join("\n");
|
|
168
175
|
}
|
|
169
176
|
|
|
177
|
+
export function formatMcpDiscoveryResult(result: ManagedMcpConnectionTestResult): string {
|
|
178
|
+
if (result.ok) {
|
|
179
|
+
return [
|
|
180
|
+
`MCP discovery completed for ${result.server}.`,
|
|
181
|
+
"",
|
|
182
|
+
`Transport: ${result.transport}`,
|
|
183
|
+
`Tools: ${result.toolCount}`,
|
|
184
|
+
...(result.tools.length > 0 ? ["", "Discovered tools:", ...result.tools.map((tool) => ` - ${tool}`)] : []),
|
|
185
|
+
"",
|
|
186
|
+
`Call with: mcp_call(server="${result.server}", tool="<tool_name>", args={...})`,
|
|
187
|
+
].join("\n");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return [
|
|
191
|
+
`MCP discovery failed for ${result.server}.`,
|
|
192
|
+
"",
|
|
193
|
+
`Transport: ${result.transport}`,
|
|
194
|
+
`Error: ${result.error ?? "Unknown error"}`,
|
|
195
|
+
...(result.warnings.length > 0 ? ["", "Warnings:", ...result.warnings.map((warning) => ` - ${warning}`)] : []),
|
|
196
|
+
].join("\n");
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function readLiveConnectionStatus(serverName: string): Promise<{
|
|
200
|
+
connected: boolean;
|
|
201
|
+
tools: string[];
|
|
202
|
+
error?: string;
|
|
203
|
+
}> {
|
|
204
|
+
try {
|
|
205
|
+
const mcpClient = await import("../mcp-client/index.js");
|
|
206
|
+
const mod = mcpClient as Record<string, unknown>;
|
|
207
|
+
if (typeof mod.getConnectionStatus === "function") {
|
|
208
|
+
return (mod.getConnectionStatus as (name: string) => { connected: boolean; tools: string[]; error?: string })(serverName);
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
// mcp-client may not expose status helpers in some hosts.
|
|
212
|
+
}
|
|
213
|
+
return { connected: false, tools: [] };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function shouldProbeConfiguredServer(config: { disabled?: boolean; transport: ManagedMcpTransport; envWarnings?: string[] }): boolean {
|
|
217
|
+
return !config.disabled && config.transport === "stdio" && (config.envWarnings?.length ?? 0) === 0;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async function resolveMcpRuntimeStatus(
|
|
221
|
+
config: {
|
|
222
|
+
name: string;
|
|
223
|
+
transport: ManagedMcpTransport;
|
|
224
|
+
disabled?: boolean;
|
|
225
|
+
envWarnings?: string[];
|
|
226
|
+
},
|
|
227
|
+
systemPrompt: string,
|
|
228
|
+
): Promise<{
|
|
229
|
+
connected: boolean;
|
|
230
|
+
available: boolean;
|
|
231
|
+
tools: string[];
|
|
232
|
+
error?: string;
|
|
233
|
+
}> {
|
|
234
|
+
const live = await readLiveConnectionStatus(config.name);
|
|
235
|
+
let connected = live.connected;
|
|
236
|
+
let tools = live.tools;
|
|
237
|
+
let error = live.error;
|
|
238
|
+
|
|
239
|
+
if (!connected && !error && hasHostMcpTool(systemPrompt, config.name)) connected = true;
|
|
240
|
+
|
|
241
|
+
if (!connected && !error && shouldProbeConfiguredServer(config)) {
|
|
242
|
+
const probed = await testMcpServerConnection(config.name, { timeoutMs: MCP_STATUS_PROBE_TIMEOUT_MS });
|
|
243
|
+
if (probed.ok) {
|
|
244
|
+
return {
|
|
245
|
+
connected: false,
|
|
246
|
+
available: true,
|
|
247
|
+
tools: probed.tools,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
error = probed.error;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
connected,
|
|
255
|
+
available: false,
|
|
256
|
+
tools,
|
|
257
|
+
error,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
170
260
|
// ─── Command handler ────────────────────────────────────────────────────────
|
|
171
261
|
|
|
172
262
|
/**
|
|
173
|
-
* Handle `/gsd mcp [status|check <server
|
|
263
|
+
* Handle `/gsd mcp [status|check <server>|discover [server]|...]`.
|
|
174
264
|
*/
|
|
175
265
|
export async function handleMcpStatus(
|
|
176
266
|
args: string,
|
|
@@ -200,6 +290,28 @@ export async function handleMcpStatus(
|
|
|
200
290
|
return;
|
|
201
291
|
}
|
|
202
292
|
|
|
293
|
+
// /gsd mcp discover [server]
|
|
294
|
+
if (lowered === "discover" || lowered.startsWith("discover ")) {
|
|
295
|
+
const requestedServerName = trimmed.slice("discover".length).trim();
|
|
296
|
+
let serverName = requestedServerName;
|
|
297
|
+
if (!serverName) {
|
|
298
|
+
if (configs.length === 1) {
|
|
299
|
+
serverName = configs[0]!.name;
|
|
300
|
+
} else {
|
|
301
|
+
const available = configs.map((config) => config.name).join(", ") || "(none)";
|
|
302
|
+
ctx.ui.notify(
|
|
303
|
+
`Usage: /gsd mcp discover <server>\n\nAvailable: ${available}`,
|
|
304
|
+
"warning",
|
|
305
|
+
);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const result = await testMcpServerConnection(serverName);
|
|
311
|
+
ctx.ui.notify(formatMcpDiscoveryResult(result), result.ok ? "info" : "warning");
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
203
315
|
// /gsd mcp test <server>
|
|
204
316
|
if (lowered.startsWith("test ")) {
|
|
205
317
|
const serverName = trimmed.slice("test ".length).trim();
|
|
@@ -304,33 +416,17 @@ export async function handleMcpStatus(
|
|
|
304
416
|
return;
|
|
305
417
|
}
|
|
306
418
|
|
|
307
|
-
|
|
308
|
-
let connected = false;
|
|
309
|
-
let toolNames: string[] = [];
|
|
310
|
-
let error: string | undefined;
|
|
311
|
-
try {
|
|
312
|
-
const mcpClient = await import("../mcp-client/index.js");
|
|
313
|
-
// Access the module's connection state if exported; fall back gracefully
|
|
314
|
-
const mod = mcpClient as Record<string, unknown>;
|
|
315
|
-
if (typeof mod.getConnectionStatus === "function") {
|
|
316
|
-
const status = (mod.getConnectionStatus as (name: string) => { connected: boolean; tools: string[]; error?: string })(serverName);
|
|
317
|
-
connected = status.connected;
|
|
318
|
-
toolNames = status.tools;
|
|
319
|
-
error = status.error;
|
|
320
|
-
}
|
|
321
|
-
} catch {
|
|
322
|
-
// mcp-client may not expose status helpers — that's fine
|
|
323
|
-
}
|
|
324
|
-
if (!connected && !error && hasHostMcpTool(systemPrompt, serverName)) connected = true;
|
|
419
|
+
const runtime = await resolveMcpRuntimeStatus(config, systemPrompt);
|
|
325
420
|
|
|
326
421
|
ctx.ui.notify(
|
|
327
422
|
formatMcpServerDetail({
|
|
328
423
|
name: config.name,
|
|
329
424
|
transport: config.transport,
|
|
330
|
-
connected,
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
425
|
+
connected: runtime.connected,
|
|
426
|
+
available: runtime.available,
|
|
427
|
+
toolCount: runtime.tools.length,
|
|
428
|
+
tools: runtime.tools,
|
|
429
|
+
error: runtime.error,
|
|
334
430
|
disabled: config.disabled,
|
|
335
431
|
sourcePath: config.sourcePath,
|
|
336
432
|
envWarnings: config.envWarnings,
|
|
@@ -342,39 +438,20 @@ export async function handleMcpStatus(
|
|
|
342
438
|
|
|
343
439
|
// /gsd mcp or /gsd mcp status
|
|
344
440
|
if (!lowered || lowered === "status") {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
for (const config of configs) {
|
|
349
|
-
let connected = false;
|
|
350
|
-
let toolCount = 0;
|
|
351
|
-
let error: string | undefined;
|
|
352
|
-
|
|
353
|
-
try {
|
|
354
|
-
const mcpClient = await import("../mcp-client/index.js");
|
|
355
|
-
const mod = mcpClient as Record<string, unknown>;
|
|
356
|
-
if (typeof mod.getConnectionStatus === "function") {
|
|
357
|
-
const status = (mod.getConnectionStatus as (name: string) => { connected: boolean; tools: string[]; error?: string })(config.name);
|
|
358
|
-
connected = status.connected;
|
|
359
|
-
toolCount = status.tools.length;
|
|
360
|
-
error = status.error;
|
|
361
|
-
}
|
|
362
|
-
} catch {
|
|
363
|
-
// Fall back to unknown state
|
|
364
|
-
}
|
|
365
|
-
if (!connected && !error && hasHostMcpTool(systemPrompt, config.name)) connected = true;
|
|
366
|
-
|
|
367
|
-
statuses.push({
|
|
441
|
+
const statuses: McpServerStatus[] = await Promise.all(configs.map(async (config) => {
|
|
442
|
+
const runtime = await resolveMcpRuntimeStatus(config, systemPrompt);
|
|
443
|
+
return {
|
|
368
444
|
name: config.name,
|
|
369
445
|
transport: config.transport,
|
|
370
|
-
connected,
|
|
371
|
-
|
|
372
|
-
|
|
446
|
+
connected: runtime.connected,
|
|
447
|
+
available: runtime.available,
|
|
448
|
+
toolCount: runtime.tools.length,
|
|
449
|
+
error: runtime.error,
|
|
373
450
|
disabled: config.disabled,
|
|
374
451
|
sourcePath: config.sourcePath,
|
|
375
452
|
envWarnings: config.envWarnings,
|
|
376
|
-
}
|
|
377
|
-
}
|
|
453
|
+
};
|
|
454
|
+
}));
|
|
378
455
|
|
|
379
456
|
const warningLines = [
|
|
380
457
|
...management.warnings,
|
|
@@ -389,9 +466,10 @@ export async function handleMcpStatus(
|
|
|
389
466
|
|
|
390
467
|
// Unknown subcommand
|
|
391
468
|
ctx.ui.notify(
|
|
392
|
-
"Usage: /gsd mcp [status|check <server>|test <server>|enable <server>|disable <server>|delete <server> --confirm|import <server> [as <name>]|init [dir]]\n\n" +
|
|
469
|
+
"Usage: /gsd mcp [status|check <server>|discover [server]|test <server>|enable <server>|disable <server>|delete <server> --confirm|import <server> [as <name>]|init [dir]]\n\n" +
|
|
393
470
|
" status Show all MCP server statuses (default)\n" +
|
|
394
471
|
" check <server> Detailed status for a specific server\n" +
|
|
472
|
+
" discover [server] Connect and list tools for a server\n" +
|
|
395
473
|
" test <server> Verify MCP handshake and tools/list\n" +
|
|
396
474
|
" enable <server> Enable a local GSD-managed server\n" +
|
|
397
475
|
" disable <server> Disable a local GSD-managed server\n" +
|
|
@@ -23,6 +23,9 @@ import {
|
|
|
23
23
|
import { loadFile, saveFile, splitFrontmatter, parseFrontmatterMap } from "./files.js";
|
|
24
24
|
import { runClaudeImportFlow } from "./claude-import.js";
|
|
25
25
|
|
|
26
|
+
const DEFAULT_WIDGET_MODE = "small";
|
|
27
|
+
const WIDGET_MODE_OPTIONS = [DEFAULT_WIDGET_MODE, "full", "min", "off"] as const;
|
|
28
|
+
|
|
26
29
|
/** Extract body content after frontmatter closing delimiter, or null if none. */
|
|
27
30
|
function extractBodyAfterFrontmatter(content: string): string | null {
|
|
28
31
|
const closingIdx = content.indexOf("\n---", content.indexOf("---"));
|
|
@@ -1558,7 +1561,7 @@ async function configureAdvanced(ctx: ExtensionCommandContext, prefs: Record<str
|
|
|
1558
1561
|
prefs.min_request_interval_ms = minRequestInterval;
|
|
1559
1562
|
}
|
|
1560
1563
|
|
|
1561
|
-
const widget = await promptEnum(ctx, "Auto-mode widget display", prefs.widget_mode,
|
|
1564
|
+
const widget = await promptEnum(ctx, "Auto-mode widget display", prefs.widget_mode, WIDGET_MODE_OPTIONS, DEFAULT_WIDGET_MODE);
|
|
1562
1565
|
if (widget !== undefined) prefs.widget_mode = widget;
|
|
1563
1566
|
|
|
1564
1567
|
const experimental = (prefs.experimental as Record<string, unknown> | undefined) ?? {};
|
|
@@ -238,7 +238,7 @@ export async function handleVerdict(
|
|
|
238
238
|
|
|
239
239
|
if (effectiveVerdict === "needs-remediation") {
|
|
240
240
|
ctx.ui.notify(
|
|
241
|
-
"Follow up with
|
|
241
|
+
"Follow up with /gsd dispatch reassess to add remediation slices, then re-run /gsd auto.",
|
|
242
242
|
"info",
|
|
243
243
|
);
|
|
244
244
|
}
|
|
@@ -23,6 +23,8 @@ import {
|
|
|
23
23
|
resolveAutoSupervisorConfig,
|
|
24
24
|
} from "./preferences.js";
|
|
25
25
|
|
|
26
|
+
const DEFAULT_WIDGET_MODE = "small";
|
|
27
|
+
|
|
26
28
|
// ─── Data Collection ──────────────────────────────────────────────────────
|
|
27
29
|
|
|
28
30
|
interface ConfigSection {
|
|
@@ -160,7 +162,7 @@ function collectConfigSections(): ConfigSection[] {
|
|
|
160
162
|
if (prefs?.service_tier) toggleRows.push({ label: "service_tier", value: prefs.service_tier });
|
|
161
163
|
if (prefs?.search_provider && prefs.search_provider !== "auto") toggleRows.push({ label: "search_provider", value: prefs.search_provider });
|
|
162
164
|
if (prefs?.context_selection) toggleRows.push({ label: "context_selection", value: prefs.context_selection });
|
|
163
|
-
if (prefs?.widget_mode && prefs.widget_mode !==
|
|
165
|
+
if (prefs?.widget_mode && prefs.widget_mode !== DEFAULT_WIDGET_MODE) toggleRows.push({ label: "widget_mode", value: prefs.widget_mode });
|
|
164
166
|
if (prefs?.experimental?.rtk) toggleRows.push({ label: "experimental.rtk", value: "on" });
|
|
165
167
|
if (toggleRows.length > 0) sections.push({ title: "Toggles", rows: toggleRows });
|
|
166
168
|
|
|
@@ -71,6 +71,14 @@ export class GSDDashboardOverlay {
|
|
|
71
71
|
private refreshInFlight: Promise<void> | null = null;
|
|
72
72
|
private disposed = false;
|
|
73
73
|
private resizeHandler: (() => void) | null = null;
|
|
74
|
+
private cachedMetrics: {
|
|
75
|
+
totals: ReturnType<typeof getProjectTotals>;
|
|
76
|
+
promptStats: ReturnType<typeof getPromptSizeStats>;
|
|
77
|
+
phases: ReturnType<typeof aggregateByPhase>;
|
|
78
|
+
slices: ReturnType<typeof aggregateBySlice>;
|
|
79
|
+
models: ReturnType<typeof aggregateByModel>;
|
|
80
|
+
} | null = null;
|
|
81
|
+
private lastSeenUnitCount = -1;
|
|
74
82
|
|
|
75
83
|
constructor(
|
|
76
84
|
tui: { requestRender: () => void },
|
|
@@ -123,7 +131,8 @@ export class GSDDashboardOverlay {
|
|
|
123
131
|
this.dashData = getAutoDashboardData();
|
|
124
132
|
const nextIdentity = this.computeDashboardIdentity(this.dashData);
|
|
125
133
|
|
|
126
|
-
|
|
134
|
+
const identityChanged = initial || nextIdentity !== this.loadedDashboardIdentity;
|
|
135
|
+
if (identityChanged) {
|
|
127
136
|
const loaded = await this.loadData();
|
|
128
137
|
if (this.disposed) return;
|
|
129
138
|
if (loaded) {
|
|
@@ -135,7 +144,9 @@ export class GSDDashboardOverlay {
|
|
|
135
144
|
this.loading = false;
|
|
136
145
|
}
|
|
137
146
|
|
|
138
|
-
|
|
147
|
+
if (identityChanged) {
|
|
148
|
+
this.invalidate();
|
|
149
|
+
}
|
|
139
150
|
this.tui.requestRender();
|
|
140
151
|
}
|
|
141
152
|
|
|
@@ -459,7 +470,7 @@ export class GSDDashboardOverlay {
|
|
|
459
470
|
|
|
460
471
|
const ledger = getLedger();
|
|
461
472
|
if (ledger && ledger.units.length > 0) {
|
|
462
|
-
const totals =
|
|
473
|
+
const { totals, promptStats, phases, slices, models } = this.ensureMetricsCache(ledger.units);
|
|
463
474
|
|
|
464
475
|
lines.push(blank());
|
|
465
476
|
lines.push(hr());
|
|
@@ -496,7 +507,6 @@ export class GSDDashboardOverlay {
|
|
|
496
507
|
lines.push(row(budgetParts.join(` ${th.fg("dim", "·")} `)));
|
|
497
508
|
}
|
|
498
509
|
|
|
499
|
-
const promptStats = getPromptSizeStats(ledger.units);
|
|
500
510
|
if (promptStats) {
|
|
501
511
|
const promptParts = [
|
|
502
512
|
`${th.fg("dim", "avg prompt:")} ${th.fg("text", formatCharCount(promptStats.averagePromptChars))}`,
|
|
@@ -508,7 +518,6 @@ export class GSDDashboardOverlay {
|
|
|
508
518
|
lines.push(row(promptParts.join(` ${th.fg("dim", "·")} `)));
|
|
509
519
|
}
|
|
510
520
|
|
|
511
|
-
const phases = aggregateByPhase(ledger.units);
|
|
512
521
|
if (phases.length > 0) {
|
|
513
522
|
lines.push(blank());
|
|
514
523
|
lines.push(row(th.fg("dim", "By Phase")));
|
|
@@ -520,7 +529,6 @@ export class GSDDashboardOverlay {
|
|
|
520
529
|
}
|
|
521
530
|
}
|
|
522
531
|
|
|
523
|
-
const slices = aggregateBySlice(ledger.units);
|
|
524
532
|
if (slices.length > 0) {
|
|
525
533
|
lines.push(blank());
|
|
526
534
|
lines.push(row(th.fg("dim", "By Slice")));
|
|
@@ -551,7 +559,6 @@ export class GSDDashboardOverlay {
|
|
|
551
559
|
}
|
|
552
560
|
}
|
|
553
561
|
|
|
554
|
-
const models = aggregateByModel(ledger.units);
|
|
555
562
|
if (models.length >= 1) {
|
|
556
563
|
lines.push(blank());
|
|
557
564
|
lines.push(row(th.fg("dim", "By Model")));
|
|
@@ -625,6 +632,20 @@ export class GSDDashboardOverlay {
|
|
|
625
632
|
return `${th.fg("dim", labelText)}${" ".repeat(gap)}${bar}${" ".repeat(gap)}${th.fg("dim", rightText)}`;
|
|
626
633
|
}
|
|
627
634
|
|
|
635
|
+
private ensureMetricsCache(units: UnitMetrics[]) {
|
|
636
|
+
if (!this.cachedMetrics || units.length !== this.lastSeenUnitCount) {
|
|
637
|
+
this.cachedMetrics = {
|
|
638
|
+
totals: getProjectTotals(units),
|
|
639
|
+
promptStats: getPromptSizeStats(units),
|
|
640
|
+
phases: aggregateByPhase(units),
|
|
641
|
+
slices: aggregateBySlice(units),
|
|
642
|
+
models: aggregateByModel(units),
|
|
643
|
+
};
|
|
644
|
+
this.lastSeenUnitCount = units.length;
|
|
645
|
+
}
|
|
646
|
+
return this.cachedMetrics!;
|
|
647
|
+
}
|
|
648
|
+
|
|
628
649
|
invalidate(): void {
|
|
629
650
|
this.cachedWidth = undefined;
|
|
630
651
|
this.cachedLines = undefined;
|