@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
|
@@ -11,6 +11,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
11
11
|
import { extractUatType } from '../../files.ts';
|
|
12
12
|
import { resolveSliceFile } from '../../paths.ts';
|
|
13
13
|
import { buildRunUatPrompt, checkNeedsRunUat } from '../../auto-prompts.ts';
|
|
14
|
+
import { buildRunUatResultPresentation, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from '../../tool-presentation-plan.ts';
|
|
14
15
|
|
|
15
16
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
17
|
const worktreePromptsDir = join(__dirname, '../..', 'prompts');
|
|
@@ -20,6 +21,8 @@ function loadPromptFromWorktree(name: string, vars: Record<string, string> = {})
|
|
|
20
21
|
let content = readFileSync(path, 'utf-8');
|
|
21
22
|
const effectiveVars = {
|
|
22
23
|
skillActivation: 'If no installed skill clearly matches this unit, skip explicit skill activation and continue with the required workflow.',
|
|
24
|
+
canonicalPresentation: JSON.stringify(buildRunUatResultPresentation(), null, 2),
|
|
25
|
+
toolPresentationPlanId: RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
|
|
23
26
|
...vars,
|
|
24
27
|
};
|
|
25
28
|
for (const [key, value] of Object.entries(effectiveVars)) {
|
|
@@ -72,6 +75,38 @@ function makeBrowserObservableUatContent(mode = 'artifact-driven'): string {
|
|
|
72
75
|
].join('\n');
|
|
73
76
|
}
|
|
74
77
|
|
|
78
|
+
function makeDeferredBrowserUatContent(): string {
|
|
79
|
+
return [
|
|
80
|
+
'# UAT File',
|
|
81
|
+
'',
|
|
82
|
+
'## UAT Type',
|
|
83
|
+
'',
|
|
84
|
+
'- UAT mode: artifact-driven',
|
|
85
|
+
'- Why this mode is sufficient: Node interaction tests exercise the real app.js render/event/localStorage loop through a DOM harness. Live browser, keyboard, responsive, and visual-polish UAT remain intentionally deferred to S02.',
|
|
86
|
+
'',
|
|
87
|
+
'## Smoke Test',
|
|
88
|
+
'',
|
|
89
|
+
'Run `node --test tests/s01-static-interactions.test.js` and confirm all tests pass.',
|
|
90
|
+
'',
|
|
91
|
+
'## Test Cases',
|
|
92
|
+
'',
|
|
93
|
+
'1. Click the todo row edit control in the DOM harness.',
|
|
94
|
+
'2. Save changed text and reload/recreate the app from persisted localStorage.',
|
|
95
|
+
'3. Expected: the stored record shape remains unchanged.',
|
|
96
|
+
'',
|
|
97
|
+
'## Not Proven By This UAT',
|
|
98
|
+
'',
|
|
99
|
+
'- Final visual polish of edit controls.',
|
|
100
|
+
'- Keyboard usability through a real browser.',
|
|
101
|
+
'- Browser console and local network cleanliness.',
|
|
102
|
+
'',
|
|
103
|
+
'## Notes for Tester',
|
|
104
|
+
'',
|
|
105
|
+
'S02 should capture browser evidence for the full loop rather than changing this persisted model.',
|
|
106
|
+
'',
|
|
107
|
+
].join('\n');
|
|
108
|
+
}
|
|
109
|
+
|
|
75
110
|
describe('run-uat', () => {
|
|
76
111
|
test('(a) artifact-driven', () => {
|
|
77
112
|
assert.deepStrictEqual(
|
|
@@ -232,8 +267,8 @@ test('(k) run-uat prompt template', () => {
|
|
|
232
267
|
`prompt contains detected dynamic uatType value "${uatType}" after substitution`,
|
|
233
268
|
);
|
|
234
269
|
assert.ok(
|
|
235
|
-
promptResult?.includes(`uatType: ${uatType}`) ?? false,
|
|
236
|
-
`prompt contains dynamic uatType
|
|
270
|
+
promptResult?.includes(`uatType: "${uatType}"`) ?? false,
|
|
271
|
+
`prompt contains dynamic uatType field "${uatType}" after substitution`,
|
|
237
272
|
);
|
|
238
273
|
assert.ok(
|
|
239
274
|
!/\{\{[^}]+\}\}/.test(promptResult ?? ''),
|
|
@@ -249,7 +284,7 @@ test('(k) run-uat prompt template', () => {
|
|
|
249
284
|
);
|
|
250
285
|
});
|
|
251
286
|
|
|
252
|
-
test('(k2) run-uat prompt references
|
|
287
|
+
test('(k2) run-uat prompt references gsd_uat_result_save, not direct write', () => {
|
|
253
288
|
const promptResult = loadPromptFromWorktree('run-uat', {
|
|
254
289
|
workingDirectory: '/tmp/test-project',
|
|
255
290
|
milestoneId: 'M001',
|
|
@@ -261,17 +296,25 @@ test('(k2) run-uat prompt references gsd_summary_save, not direct write', () =>
|
|
|
261
296
|
});
|
|
262
297
|
|
|
263
298
|
assert.ok(
|
|
264
|
-
promptResult.includes('
|
|
265
|
-
'run-uat prompt should reference
|
|
299
|
+
promptResult.includes('gsd_uat_result_save'),
|
|
300
|
+
'run-uat prompt should reference gsd_uat_result_save tool',
|
|
301
|
+
);
|
|
302
|
+
assert.ok(
|
|
303
|
+
promptResult.includes('presentedTools') && promptResult.includes('blockedTools'),
|
|
304
|
+
'run-uat prompt should specify the tool presentation contract',
|
|
266
305
|
);
|
|
267
306
|
assert.ok(
|
|
268
|
-
promptResult.includes('
|
|
269
|
-
'run-uat prompt should
|
|
307
|
+
!promptResult.includes('Call `gsd_summary_save`'),
|
|
308
|
+
'run-uat prompt should not instruct direct summary-save UAT persistence',
|
|
270
309
|
);
|
|
271
310
|
assert.ok(
|
|
272
311
|
!promptResult.includes('MUST write'),
|
|
273
312
|
'run-uat prompt should not instruct direct file write in footer',
|
|
274
313
|
);
|
|
314
|
+
assert.ok(
|
|
315
|
+
!promptResult.includes('Call `gsd_summary_save` with `artifact_type: "ASSESSMENT"`'),
|
|
316
|
+
'run-uat prompt should not instruct the legacy summary-save UAT path',
|
|
317
|
+
);
|
|
275
318
|
});
|
|
276
319
|
|
|
277
320
|
test('(l) dispatch preconditions via resolveSliceFile', () => {
|
|
@@ -482,8 +525,8 @@ test('(n) stale replay guard', async () => {
|
|
|
482
525
|
});
|
|
483
526
|
|
|
484
527
|
test('(q) verdict in ASSESSMENT file skips UAT dispatch (file-based path)', async () => {
|
|
485
|
-
// Regression test for #2644: run-uat
|
|
486
|
-
// S{sid}-ASSESSMENT.md
|
|
528
|
+
// Regression test for #2644: run-uat writes the verdict to
|
|
529
|
+
// S{sid}-ASSESSMENT.md through the structured UAT save path,
|
|
487
530
|
// but checkNeedsRunUat only checked S{sid}-UAT.md — causing a stuck loop.
|
|
488
531
|
const base = createFixtureBase();
|
|
489
532
|
try {
|
|
@@ -679,11 +722,30 @@ test('(u) run-uat prompt promotes artifact-driven browser specs to browser-execu
|
|
|
679
722
|
const prompt = await buildRunUatPrompt('M001', 'S01', uatRel, uatContent, base);
|
|
680
723
|
|
|
681
724
|
assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`browser-executable`/);
|
|
682
|
-
assert.match(prompt, /uatType: browser-executable/);
|
|
725
|
+
assert.match(prompt, /uatType: "browser-executable"/);
|
|
683
726
|
assert.match(prompt, /use gsd-browser tools/i);
|
|
727
|
+
assert.match(prompt, /"browser_navigate"/);
|
|
728
|
+
assert.match(prompt, /"browser_assert"/);
|
|
684
729
|
} finally {
|
|
685
730
|
cleanup(base);
|
|
686
731
|
}
|
|
687
732
|
});
|
|
688
733
|
|
|
734
|
+
test('(v) run-uat prompt keeps deferred browser work artifact-driven', async () => {
|
|
735
|
+
const base = createFixtureBase();
|
|
736
|
+
try {
|
|
737
|
+
const uatRel = '.gsd/milestones/M001/slices/S01/S01-UAT.md';
|
|
738
|
+
const uatContent = makeDeferredBrowserUatContent();
|
|
739
|
+
writeSliceFile(base, 'M001', 'S01', 'UAT', uatContent);
|
|
740
|
+
|
|
741
|
+
const prompt = await buildRunUatPrompt('M001', 'S01', uatRel, uatContent, base);
|
|
742
|
+
|
|
743
|
+
assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`artifact-driven`/);
|
|
744
|
+
assert.match(prompt, /uatType: "artifact-driven"/);
|
|
745
|
+
assert.doesNotMatch(prompt, /uatType: "browser-executable"/);
|
|
746
|
+
assert.doesNotMatch(prompt, /"browser_navigate"/);
|
|
747
|
+
} finally {
|
|
748
|
+
cleanup(base);
|
|
749
|
+
}
|
|
750
|
+
});
|
|
689
751
|
});
|
package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts
CHANGED
|
@@ -50,6 +50,7 @@ import { handleCompleteSlice } from "../../tools/complete-slice.ts";
|
|
|
50
50
|
import { handleCompleteMilestone } from "../../tools/complete-milestone.ts";
|
|
51
51
|
import { handleReopenTask } from "../../tools/reopen-task.ts";
|
|
52
52
|
import { handleReopenSlice } from "../../tools/reopen-slice.ts";
|
|
53
|
+
import { handleReopenMilestone } from "../../tools/reopen-milestone.ts";
|
|
53
54
|
|
|
54
55
|
// ── State derivation ──────────────────────────────────────────────────────
|
|
55
56
|
import {
|
|
@@ -700,9 +701,7 @@ describe("state-machine-live-validation", () => {
|
|
|
700
701
|
assert.match((result as any).error, /closed milestone/);
|
|
701
702
|
});
|
|
702
703
|
|
|
703
|
-
test("
|
|
704
|
-
// This test documents the H5 finding: there is no handleReopenMilestone function.
|
|
705
|
-
// A completed milestone can only be undone via direct DB manipulation.
|
|
704
|
+
test("closed milestone cannot be reopened by generic DB update", async () => {
|
|
706
705
|
base = createFullFixture();
|
|
707
706
|
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
708
707
|
insertMilestone({ id: "M001", title: "Done", status: "complete" });
|
|
@@ -710,10 +709,18 @@ describe("state-machine-live-validation", () => {
|
|
|
710
709
|
const milestone = getMilestone("M001");
|
|
711
710
|
assert.ok(isClosedStatus(milestone!.status), "milestone is closed");
|
|
712
711
|
|
|
713
|
-
|
|
714
|
-
|
|
712
|
+
assert.throws(
|
|
713
|
+
() => updateMilestoneStatus("M001", "active", null),
|
|
714
|
+
/use gsd_milestone_reopen for an explicit reopen/,
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
const result = await handleReopenMilestone(
|
|
718
|
+
{ milestoneId: "M001", reason: "regression surfaced after closure" },
|
|
719
|
+
base,
|
|
720
|
+
);
|
|
721
|
+
assert.ok(!("error" in result), `unexpected reopen error: ${"error" in result ? result.error : ""}`);
|
|
715
722
|
const reopened = getMilestone("M001");
|
|
716
|
-
assert.equal(reopened!.status, "active", "
|
|
723
|
+
assert.equal(reopened!.status, "active", "explicit reopen handler reopens the milestone");
|
|
717
724
|
});
|
|
718
725
|
});
|
|
719
726
|
|
|
@@ -48,6 +48,21 @@ describe("discoverMcpServerNames", () => {
|
|
|
48
48
|
assert.deepEqual(result.sort(), ["server-a", "server-b", "shared"]);
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
+
it("reads from .claude/settings.local.json for Claude Code project-local servers", () => {
|
|
52
|
+
const dir = mkdtempSync(join(tmpdir(), "mcp-filter-test-"));
|
|
53
|
+
mkdirSync(join(dir, ".claude"), { recursive: true });
|
|
54
|
+
writeFileSync(
|
|
55
|
+
join(dir, ".claude", "settings.local.json"),
|
|
56
|
+
JSON.stringify({ mcpServers: { "local-server": {}, "shared": {} } }),
|
|
57
|
+
);
|
|
58
|
+
writeFileSync(
|
|
59
|
+
join(dir, ".claude", "settings.json"),
|
|
60
|
+
JSON.stringify({ mcpServers: { "project-server": {}, "shared": {} } }),
|
|
61
|
+
);
|
|
62
|
+
const result = discoverMcpServerNames(dir);
|
|
63
|
+
assert.deepEqual(result.sort(), ["local-server", "project-server", "shared"]);
|
|
64
|
+
});
|
|
65
|
+
|
|
51
66
|
it("handles .claude/settings.json missing gracefully", () => {
|
|
52
67
|
const dir = mkdtempSync(join(tmpdir(), "mcp-filter-test-"));
|
|
53
68
|
writeFileSync(
|
|
@@ -5,6 +5,8 @@ import { join } from "node:path";
|
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
buildProjectBrowserMcpServerConfig,
|
|
9
|
+
ensureClaudeCodeMcpJsonServerEnabled,
|
|
8
10
|
ensureProjectWorkflowMcpConfig,
|
|
9
11
|
GSD_BROWSER_MCP_SERVER_NAME,
|
|
10
12
|
GSD_WORKFLOW_MCP_SERVER_NAME,
|
|
@@ -54,6 +56,14 @@ test("ensureProjectWorkflowMcpConfig creates .mcp.json with workflow and browser
|
|
|
54
56
|
]);
|
|
55
57
|
assert.equal(browserArgs[mcpArgIndex + 6], projectRoot);
|
|
56
58
|
assert.equal((browserServer as { cwd?: string })?.cwd, projectRoot);
|
|
59
|
+
|
|
60
|
+
const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
|
|
61
|
+
enabledMcpjsonServers?: string[];
|
|
62
|
+
};
|
|
63
|
+
assert.deepEqual(settings.enabledMcpjsonServers, [
|
|
64
|
+
GSD_WORKFLOW_MCP_SERVER_NAME,
|
|
65
|
+
GSD_BROWSER_MCP_SERVER_NAME,
|
|
66
|
+
]);
|
|
57
67
|
} finally {
|
|
58
68
|
rmSync(projectRoot, { recursive: true, force: true });
|
|
59
69
|
}
|
|
@@ -115,6 +125,11 @@ test("ensureProjectWorkflowMcpConfig uses custom workflow server name from env",
|
|
|
115
125
|
assert.ok(parsed.mcpServers?.["custom-workflow"]);
|
|
116
126
|
assert.ok(parsed.mcpServers?.[GSD_BROWSER_MCP_SERVER_NAME]);
|
|
117
127
|
assert.equal(parsed.mcpServers?.[GSD_WORKFLOW_MCP_SERVER_NAME], undefined);
|
|
128
|
+
|
|
129
|
+
const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
|
|
130
|
+
enabledMcpjsonServers?: string[];
|
|
131
|
+
};
|
|
132
|
+
assert.deepEqual(settings.enabledMcpjsonServers, ["custom-workflow", GSD_BROWSER_MCP_SERVER_NAME]);
|
|
118
133
|
} finally {
|
|
119
134
|
rmSync(projectRoot, { recursive: true, force: true });
|
|
120
135
|
}
|
|
@@ -136,6 +151,42 @@ test("ensureProjectWorkflowMcpConfig can disable the default browser MCP server"
|
|
|
136
151
|
};
|
|
137
152
|
assert.ok(parsed.mcpServers?.[GSD_WORKFLOW_MCP_SERVER_NAME]);
|
|
138
153
|
assert.equal(parsed.mcpServers?.[GSD_BROWSER_MCP_SERVER_NAME], undefined);
|
|
154
|
+
|
|
155
|
+
const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
|
|
156
|
+
enabledMcpjsonServers?: string[];
|
|
157
|
+
};
|
|
158
|
+
assert.deepEqual(settings.enabledMcpjsonServers, [GSD_WORKFLOW_MCP_SERVER_NAME]);
|
|
159
|
+
} finally {
|
|
160
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("buildProjectBrowserMcpServerConfig prefers newer gsd-browser on PATH", () => {
|
|
165
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-browser-"));
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const config = buildProjectBrowserMcpServerConfig(projectRoot, {
|
|
169
|
+
GSD_BROWSER_PATH_VERSION: "99.0.0",
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
assert.equal(config?.command, "gsd-browser");
|
|
173
|
+
assert.equal(config?.args?.[0], "mcp");
|
|
174
|
+
} finally {
|
|
175
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("buildProjectBrowserMcpServerConfig keeps bundled browser when PATH version is older", () => {
|
|
180
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-browser-"));
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const config = buildProjectBrowserMcpServerConfig(projectRoot, {
|
|
184
|
+
GSD_BROWSER_PATH_VERSION: "0.0.1",
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
assert.equal(config?.command, process.execPath);
|
|
188
|
+
assert.match(config?.args?.[0] ?? "", /@opengsd[\/\\]gsd-browser[\/\\]bin[\/\\]gsd-browser/);
|
|
189
|
+
assert.equal(config?.args?.[1], "mcp");
|
|
139
190
|
} finally {
|
|
140
191
|
rmSync(projectRoot, { recursive: true, force: true });
|
|
141
192
|
}
|
|
@@ -156,3 +207,52 @@ test("ensureProjectWorkflowMcpConfig is idempotent when config is already curren
|
|
|
156
207
|
rmSync(projectRoot, { recursive: true, force: true });
|
|
157
208
|
}
|
|
158
209
|
});
|
|
210
|
+
|
|
211
|
+
test("ensureProjectWorkflowMcpConfig updates stale Claude Code MCP approval state", () => {
|
|
212
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-init-"));
|
|
213
|
+
mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
|
|
214
|
+
const settingsPath = join(projectRoot, ".claude", "settings.local.json");
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
const first = ensureProjectWorkflowMcpConfig(projectRoot);
|
|
218
|
+
assert.equal(first.status, "created");
|
|
219
|
+
|
|
220
|
+
writeFileSync(
|
|
221
|
+
settingsPath,
|
|
222
|
+
`${JSON.stringify({
|
|
223
|
+
permissions: { allow: ["Bash(gh issue *)"] },
|
|
224
|
+
enabledMcpjsonServers: [],
|
|
225
|
+
disabledMcpjsonServers: [GSD_WORKFLOW_MCP_SERVER_NAME, GSD_BROWSER_MCP_SERVER_NAME],
|
|
226
|
+
}, null, 2)}\n`,
|
|
227
|
+
"utf-8",
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const second = ensureProjectWorkflowMcpConfig(projectRoot);
|
|
231
|
+
assert.equal(second.status, "updated");
|
|
232
|
+
|
|
233
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8")) as {
|
|
234
|
+
permissions?: { allow?: string[] };
|
|
235
|
+
enabledMcpjsonServers?: string[];
|
|
236
|
+
disabledMcpjsonServers?: string[];
|
|
237
|
+
};
|
|
238
|
+
assert.deepEqual(settings.permissions?.allow, ["Bash(gh issue *)"]);
|
|
239
|
+
assert.deepEqual(settings.enabledMcpjsonServers, [
|
|
240
|
+
GSD_WORKFLOW_MCP_SERVER_NAME,
|
|
241
|
+
GSD_BROWSER_MCP_SERVER_NAME,
|
|
242
|
+
]);
|
|
243
|
+
assert.deepEqual(settings.disabledMcpjsonServers, []);
|
|
244
|
+
} finally {
|
|
245
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test("ensureClaudeCodeMcpJsonServerEnabled is idempotent", () => {
|
|
250
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-init-"));
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
assert.equal(ensureClaudeCodeMcpJsonServerEnabled(projectRoot, "gsd-workflow"), true);
|
|
254
|
+
assert.equal(ensureClaudeCodeMcpJsonServerEnabled(projectRoot, "gsd-workflow"), false);
|
|
255
|
+
} finally {
|
|
256
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
257
|
+
}
|
|
258
|
+
});
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import test, { describe } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
8
|
+
import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
3
9
|
|
|
4
10
|
import {
|
|
11
|
+
formatMcpDiscoveryResult,
|
|
5
12
|
formatMcpInitResult,
|
|
6
13
|
formatMcpConnectionTestResult,
|
|
7
14
|
formatMcpStatusReport,
|
|
8
15
|
formatMcpServerDetail,
|
|
9
16
|
hasHostMcpTool,
|
|
17
|
+
handleMcpStatus,
|
|
10
18
|
type McpServerStatus,
|
|
11
19
|
} from "../commands-mcp-status.ts";
|
|
20
|
+
import { clearMcpConfigCache } from "../../mcp-client/manager.ts";
|
|
12
21
|
|
|
13
22
|
// ─── formatMcpStatusReport ──────────────────────────────────────────────────
|
|
14
23
|
|
|
@@ -49,6 +58,16 @@ describe("formatMcpStatusReport", () => {
|
|
|
49
58
|
assert.match(result, /disabled/i);
|
|
50
59
|
});
|
|
51
60
|
|
|
61
|
+
test("shows available state for servers that pass a status probe", () => {
|
|
62
|
+
const servers: McpServerStatus[] = [
|
|
63
|
+
{ name: "gsd-workflow", transport: "stdio", connected: false, available: true, toolCount: 62, error: undefined },
|
|
64
|
+
];
|
|
65
|
+
const result = formatMcpStatusReport(servers);
|
|
66
|
+
assert.match(result, /gsd-workflow/);
|
|
67
|
+
assert.match(result, /available — 62 tools/);
|
|
68
|
+
assert.doesNotMatch(result, /disconnected/);
|
|
69
|
+
});
|
|
70
|
+
|
|
52
71
|
test("includes server count in header", () => {
|
|
53
72
|
const servers: McpServerStatus[] = [
|
|
54
73
|
{ name: "a", transport: "stdio", connected: true, toolCount: 3, error: undefined },
|
|
@@ -113,6 +132,20 @@ describe("formatMcpServerDetail", () => {
|
|
|
113
132
|
assert.match(result, /disconnected/i);
|
|
114
133
|
});
|
|
115
134
|
|
|
135
|
+
test("shows available status with tool names", () => {
|
|
136
|
+
const result = formatMcpServerDetail({
|
|
137
|
+
name: "gsd-workflow",
|
|
138
|
+
transport: "stdio",
|
|
139
|
+
connected: false,
|
|
140
|
+
available: true,
|
|
141
|
+
toolCount: 1,
|
|
142
|
+
tools: ["gsd_milestone_status"],
|
|
143
|
+
error: undefined,
|
|
144
|
+
});
|
|
145
|
+
assert.match(result, /available/i);
|
|
146
|
+
assert.match(result, /gsd_milestone_status/);
|
|
147
|
+
});
|
|
148
|
+
|
|
116
149
|
test("shows env warnings for server detail", () => {
|
|
117
150
|
const result = formatMcpServerDetail({
|
|
118
151
|
name: "warned",
|
|
@@ -128,6 +161,150 @@ describe("formatMcpServerDetail", () => {
|
|
|
128
161
|
});
|
|
129
162
|
});
|
|
130
163
|
|
|
164
|
+
describe("handleMcpStatus", () => {
|
|
165
|
+
test("probes configured stdio servers before reporting disconnected", async () => {
|
|
166
|
+
const previousGsdHome = process.env.GSD_HOME;
|
|
167
|
+
const originalCwd = process.cwd();
|
|
168
|
+
const projectDir = mkdtempSync(join(tmpdir(), "gsd-mcp-status-project-"));
|
|
169
|
+
const gsdHomeDir = mkdtempSync(join(tmpdir(), "gsd-mcp-status-home-"));
|
|
170
|
+
try {
|
|
171
|
+
process.env.GSD_HOME = gsdHomeDir;
|
|
172
|
+
process.chdir(projectDir);
|
|
173
|
+
mkdirSync(join(projectDir, ".gsd"), { recursive: true });
|
|
174
|
+
|
|
175
|
+
const require = createRequire(import.meta.url);
|
|
176
|
+
const mcpModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/mcp.js")).href;
|
|
177
|
+
const stdioModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/stdio.js")).href;
|
|
178
|
+
const serverPath = join(projectDir, "fake-mcp-server.mjs");
|
|
179
|
+
writeFileSync(
|
|
180
|
+
serverPath,
|
|
181
|
+
[
|
|
182
|
+
`const { McpServer } = await import(${JSON.stringify(mcpModuleUrl)});`,
|
|
183
|
+
`const { StdioServerTransport } = await import(${JSON.stringify(stdioModuleUrl)});`,
|
|
184
|
+
'const server = new McpServer({ name: "fake", version: "1.0.0" }, { capabilities: { tools: {} } });',
|
|
185
|
+
'server.tool("fake_tool", "Probe-visible tool", {}, async () => ({ content: [{ type: "text", text: "ok" }] }));',
|
|
186
|
+
'await server.connect(new StdioServerTransport());',
|
|
187
|
+
].join("\n"),
|
|
188
|
+
"utf-8",
|
|
189
|
+
);
|
|
190
|
+
writeFileSync(
|
|
191
|
+
join(projectDir, ".mcp.json"),
|
|
192
|
+
JSON.stringify({ mcpServers: { "gsd-workflow": { command: process.execPath, args: [serverPath] } } }),
|
|
193
|
+
"utf-8",
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
let message = "";
|
|
197
|
+
const ctx = {
|
|
198
|
+
getSystemPrompt: () => "",
|
|
199
|
+
ui: {
|
|
200
|
+
notify: (text: string) => {
|
|
201
|
+
message = text;
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
await handleMcpStatus("status", ctx as unknown as ExtensionCommandContext);
|
|
207
|
+
|
|
208
|
+
assert.match(message, /gsd-workflow/);
|
|
209
|
+
assert.match(message, /available — 1 tools/);
|
|
210
|
+
assert.doesNotMatch(message, /disconnected/);
|
|
211
|
+
} finally {
|
|
212
|
+
process.chdir(originalCwd);
|
|
213
|
+
if (previousGsdHome === undefined) delete process.env.GSD_HOME;
|
|
214
|
+
else process.env.GSD_HOME = previousGsdHome;
|
|
215
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
216
|
+
rmSync(gsdHomeDir, { recursive: true, force: true });
|
|
217
|
+
clearMcpConfigCache();
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test("discovers the only configured server when no server name is provided", async () => {
|
|
222
|
+
const previousGsdHome = process.env.GSD_HOME;
|
|
223
|
+
const originalCwd = process.cwd();
|
|
224
|
+
const projectDir = mkdtempSync(join(tmpdir(), "gsd-mcp-discover-project-"));
|
|
225
|
+
const gsdHomeDir = mkdtempSync(join(tmpdir(), "gsd-mcp-discover-home-"));
|
|
226
|
+
try {
|
|
227
|
+
process.env.GSD_HOME = gsdHomeDir;
|
|
228
|
+
process.chdir(projectDir);
|
|
229
|
+
|
|
230
|
+
const require = createRequire(import.meta.url);
|
|
231
|
+
const mcpModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/mcp.js")).href;
|
|
232
|
+
const stdioModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/stdio.js")).href;
|
|
233
|
+
const serverPath = join(projectDir, "discover-mcp-server.mjs");
|
|
234
|
+
writeFileSync(
|
|
235
|
+
serverPath,
|
|
236
|
+
[
|
|
237
|
+
`const { McpServer } = await import(${JSON.stringify(mcpModuleUrl)});`,
|
|
238
|
+
`const { StdioServerTransport } = await import(${JSON.stringify(stdioModuleUrl)});`,
|
|
239
|
+
'const server = new McpServer({ name: "fake", version: "1.0.0" }, { capabilities: { tools: {} } });',
|
|
240
|
+
'server.tool("discover_tool", "Discover-visible tool", {}, async () => ({ content: [{ type: "text", text: "ok" }] }));',
|
|
241
|
+
'await server.connect(new StdioServerTransport());',
|
|
242
|
+
].join("\n"),
|
|
243
|
+
"utf-8",
|
|
244
|
+
);
|
|
245
|
+
writeFileSync(
|
|
246
|
+
join(projectDir, ".mcp.json"),
|
|
247
|
+
JSON.stringify({ mcpServers: { "gsd-workflow": { command: process.execPath, args: [serverPath] } } }),
|
|
248
|
+
"utf-8",
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
let message = "";
|
|
252
|
+
const ctx = {
|
|
253
|
+
getSystemPrompt: () => "",
|
|
254
|
+
ui: {
|
|
255
|
+
notify: (text: string) => {
|
|
256
|
+
message = text;
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
await handleMcpStatus("discover", ctx as unknown as ExtensionCommandContext);
|
|
262
|
+
|
|
263
|
+
assert.match(message, /MCP discovery completed for gsd-workflow/);
|
|
264
|
+
assert.match(message, /discover_tool/);
|
|
265
|
+
assert.doesNotMatch(message, /Usage: \/gsd mcp/);
|
|
266
|
+
} finally {
|
|
267
|
+
process.chdir(originalCwd);
|
|
268
|
+
if (previousGsdHome === undefined) delete process.env.GSD_HOME;
|
|
269
|
+
else process.env.GSD_HOME = previousGsdHome;
|
|
270
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
271
|
+
rmSync(gsdHomeDir, { recursive: true, force: true });
|
|
272
|
+
clearMcpConfigCache();
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe("formatMcpDiscoveryResult", () => {
|
|
278
|
+
test("summarizes discovered tools", () => {
|
|
279
|
+
const result = formatMcpDiscoveryResult({
|
|
280
|
+
ok: true,
|
|
281
|
+
server: "demo",
|
|
282
|
+
transport: "stdio",
|
|
283
|
+
toolCount: 1,
|
|
284
|
+
tools: ["ping"],
|
|
285
|
+
warnings: [],
|
|
286
|
+
});
|
|
287
|
+
assert.match(result, /discovery completed/i);
|
|
288
|
+
assert.match(result, /ping/);
|
|
289
|
+
assert.match(result, /mcp_call/);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("summarizes discovery failures", () => {
|
|
293
|
+
const result = formatMcpDiscoveryResult({
|
|
294
|
+
ok: false,
|
|
295
|
+
server: "demo",
|
|
296
|
+
transport: "http",
|
|
297
|
+
toolCount: 0,
|
|
298
|
+
tools: [],
|
|
299
|
+
warnings: ["url references unset environment variable TOKEN."],
|
|
300
|
+
error: "bad config",
|
|
301
|
+
});
|
|
302
|
+
assert.match(result, /discovery failed/i);
|
|
303
|
+
assert.match(result, /bad config/);
|
|
304
|
+
assert.match(result, /TOKEN/);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
131
308
|
describe("formatMcpConnectionTestResult", () => {
|
|
132
309
|
test("summarizes successful tools/list", () => {
|
|
133
310
|
const result = formatMcpConnectionTestResult({
|
|
@@ -164,6 +341,8 @@ describe("formatMcpInitResult", () => {
|
|
|
164
341
|
assert.match(result, /created project mcp config/i);
|
|
165
342
|
assert.match(result, /\/tmp\/project\/\.mcp\.json/);
|
|
166
343
|
assert.match(result, /mcp-capable clients/i);
|
|
344
|
+
assert.match(result, /workflow and gsd-browser MCP servers/i);
|
|
345
|
+
assert.match(result, /Pi Providers use the managed gsd-browser engine/i);
|
|
167
346
|
assert.doesNotMatch(result, /claude code/i);
|
|
168
347
|
});
|
|
169
348
|
|
|
@@ -11,6 +11,16 @@ import {
|
|
|
11
11
|
import { createMemoryRelation, listRelationsFor } from '../memory-relations.ts';
|
|
12
12
|
import { saveEmbedding, getEmbeddingForMemory } from '../memory-embeddings.ts';
|
|
13
13
|
|
|
14
|
+
function markProcessedUnits(count = 21): void {
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
for (let i = 0; i < count; i++) {
|
|
17
|
+
markUnitProcessed(`unit/${i}`, `file-${i}`);
|
|
18
|
+
_getAdapter()!
|
|
19
|
+
.prepare('UPDATE memory_processed_units SET processed_at = :ts WHERE unit_key = :key')
|
|
20
|
+
.run({ ':ts': new Date(now + i * 1000).toISOString(), ':key': `unit/${i}` });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
15
25
|
// enforceMemoryCap — cascade cleanup of embeddings and relations
|
|
16
26
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -71,14 +81,7 @@ test('memory-decay: returns decayed memory IDs', () => {
|
|
|
71
81
|
openDatabase(':memory:');
|
|
72
82
|
|
|
73
83
|
// Insert processed units — decayStaleMemories needs at least N rows.
|
|
74
|
-
|
|
75
|
-
for (let i = 0; i < 21; i++) {
|
|
76
|
-
markUnitProcessed(`unit/${i}`, `file-${i}`);
|
|
77
|
-
// small spacing to create deterministic ordering
|
|
78
|
-
const row = _getAdapter()!
|
|
79
|
-
.prepare('UPDATE memory_processed_units SET processed_at = :ts WHERE unit_key = :key');
|
|
80
|
-
row.run({ ':ts': new Date(now + i * 1000).toISOString(), ':key': `unit/${i}` });
|
|
81
|
-
}
|
|
84
|
+
markProcessedUnits();
|
|
82
85
|
|
|
83
86
|
// Create memory with updated_at in the distant past
|
|
84
87
|
createMemory({ category: 'pattern', content: 'stale entry', confidence: 0.9 });
|
|
@@ -98,6 +101,34 @@ test('memory-decay: returns decayed memory IDs', () => {
|
|
|
98
101
|
closeDatabase();
|
|
99
102
|
});
|
|
100
103
|
|
|
104
|
+
test('memory-decay: skips stale decision-sourced memories', () => {
|
|
105
|
+
openDatabase(':memory:');
|
|
106
|
+
markProcessedUnits();
|
|
107
|
+
|
|
108
|
+
createMemory({ category: 'pattern', content: 'stale working note', confidence: 0.9 });
|
|
109
|
+
createMemory({
|
|
110
|
+
category: 'architecture',
|
|
111
|
+
content: 'decision-backed architecture memory',
|
|
112
|
+
confidence: 0.85,
|
|
113
|
+
structuredFields: { sourceDecisionId: 'D001' },
|
|
114
|
+
});
|
|
115
|
+
_getAdapter()!
|
|
116
|
+
.prepare("UPDATE memories SET updated_at = '2000-01-01T00:00:00Z' WHERE id IN ('MEM001', 'MEM002')")
|
|
117
|
+
.run({});
|
|
118
|
+
|
|
119
|
+
const decayed = decayStaleMemories(20);
|
|
120
|
+
assert.ok(decayed.includes('MEM001'));
|
|
121
|
+
assert.ok(!decayed.includes('MEM002'));
|
|
122
|
+
|
|
123
|
+
const rows = _getAdapter()!
|
|
124
|
+
.prepare("SELECT id, confidence FROM memories WHERE id IN ('MEM001', 'MEM002') ORDER BY id")
|
|
125
|
+
.all() as Array<{ id: string; confidence: number }>;
|
|
126
|
+
assert.ok(rows.find((row) => row.id === 'MEM001')!.confidence < 0.9);
|
|
127
|
+
assert.equal(rows.find((row) => row.id === 'MEM002')!.confidence, 0.85);
|
|
128
|
+
|
|
129
|
+
closeDatabase();
|
|
130
|
+
});
|
|
131
|
+
|
|
101
132
|
test('memory-decay: returns empty when there are fewer processed units than the threshold', () => {
|
|
102
133
|
openDatabase(':memory:');
|
|
103
134
|
createMemory({ category: 'pattern', content: 'fresh' });
|