@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.9bb7453
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -2
- package/dist/help-text.js +10 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
- package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
- package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/dist/resources/extensions/browser-tools/index.js +57 -9
- package/dist/resources/extensions/browser-tools/package.json +5 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +167 -16
- package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
- package/dist/resources/extensions/gsd/auto/phases.js +4 -3
- package/dist/resources/extensions/gsd/auto-dashboard.js +92 -17
- package/dist/resources/extensions/gsd/auto-dispatch.js +44 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
- package/dist/resources/extensions/gsd/auto-prompts.js +68 -22
- package/dist/resources/extensions/gsd/auto-recovery.js +4 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +94 -15
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +2 -1
- package/dist/resources/extensions/gsd/auto.js +31 -6
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +83 -4
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +39 -14
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -10
- package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +9 -5
- package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
- package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
- package/dist/resources/extensions/gsd/commands-mcp-status.js +109 -60
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
- package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
- package/dist/resources/extensions/gsd/config-overlay.js +2 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
- package/dist/resources/extensions/gsd/error-classifier.js +2 -1
- package/dist/resources/extensions/gsd/escalation.js +4 -4
- package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
- package/dist/resources/extensions/gsd/forensics.js +74 -2
- package/dist/resources/extensions/gsd/gsd-db.js +42 -6
- package/dist/resources/extensions/gsd/guided-flow.js +30 -69
- package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
- package/dist/resources/extensions/gsd/mcp-project-config.js +76 -84
- package/dist/resources/extensions/gsd/memory-store.js +4 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
- package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +48 -24
- package/dist/resources/extensions/gsd/prompts/system.md +3 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/dist/resources/extensions/gsd/rule-registry.js +428 -52
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
- package/dist/resources/extensions/gsd/skill-activation.js +20 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +4 -2
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
- package/dist/resources/extensions/gsd/state.js +17 -14
- package/dist/resources/extensions/gsd/templates/plan.md +3 -1
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +120 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
- package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +403 -3
- package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
- package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
- package/dist/resources/extensions/gsd/verification-gate.js +72 -1
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -1
- package/dist/resources/extensions/gsd/workflow-mcp.js +5 -1
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
- package/dist/resources/extensions/mcp-client/manager.js +31 -1
- package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
- package/dist/rtk.d.ts +7 -1
- package/dist/rtk.js +27 -11
- package/dist/update-check.d.ts +15 -1
- package/dist/update-check.js +87 -12
- package/dist/update-cmd.d.ts +1 -0
- package/dist/update-cmd.js +53 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +5 -3
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +14 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +32 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/index.d.ts +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +1 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
- package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
- package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
- package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
- package/packages/gsd-agent-core/package.json +6 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +92 -31
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
- package/packages/mcp-server/dist/remote-questions.js +23 -9
- package/packages/mcp-server/dist/remote-questions.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +84 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +38 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +3 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/api-registry.d.ts +2 -0
- package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
- package/packages/pi-ai/dist/api-registry.js +23 -0
- package/packages/pi-ai/dist/api-registry.js.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.js +15 -0
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +406 -17
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +484 -116
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/stream.js +6 -6
- package/packages/pi-ai/dist/stream.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/terminal.d.ts +1 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +8 -4
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
- package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
- package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
- package/src/resources/extensions/browser-tools/index.ts +60 -9
- package/src/resources/extensions/browser-tools/package.json +5 -1
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
- package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
- package/src/resources/extensions/gsd/auto/phases.ts +5 -3
- package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
- package/src/resources/extensions/gsd/auto-dispatch.ts +53 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
- package/src/resources/extensions/gsd/auto-prompts.ts +102 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +4 -4
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
- package/src/resources/extensions/gsd/auto-start.ts +112 -17
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +2 -1
- package/src/resources/extensions/gsd/auto.ts +47 -5
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +90 -4
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +60 -19
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +21 -10
- package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +9 -5
- package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
- package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
- package/src/resources/extensions/gsd/commands-mcp-status.ts +136 -58
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
- package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
- package/src/resources/extensions/gsd/config-overlay.ts +3 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
- package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
- package/src/resources/extensions/gsd/error-classifier.ts +2 -1
- package/src/resources/extensions/gsd/escalation.ts +4 -4
- package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
- package/src/resources/extensions/gsd/forensics.ts +99 -5
- package/src/resources/extensions/gsd/gsd-db.ts +46 -8
- package/src/resources/extensions/gsd/guided-flow.ts +91 -83
- package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
- package/src/resources/extensions/gsd/mcp-project-config.ts +105 -88
- package/src/resources/extensions/gsd/memory-store.ts +4 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
- package/src/resources/extensions/gsd/preferences-types.ts +1 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +48 -24
- package/src/resources/extensions/gsd/prompts/system.md +3 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
- package/src/resources/extensions/gsd/rule-registry.ts +558 -58
- package/src/resources/extensions/gsd/rule-types.ts +2 -0
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
- package/src/resources/extensions/gsd/skill-activation.ts +20 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +4 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
- package/src/resources/extensions/gsd/state.ts +18 -14
- package/src/resources/extensions/gsd/templates/plan.md +3 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
- package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
- package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
- package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/gsd-rebuild.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +66 -10
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +13 -6
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +39 -1
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +53 -1
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +17 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +213 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +25 -0
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +167 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +489 -3
- package/src/resources/extensions/gsd/types.ts +69 -5
- package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
- package/src/resources/extensions/gsd/verification-gate.ts +87 -1
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +5 -1
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
- package/src/resources/extensions/mcp-client/manager.ts +33 -1
- package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
- /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → jBtwT9v1u2lUA3UEOy_ZH}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → jBtwT9v1u2lUA3UEOy_ZH}/_ssgManifest.js +0 -0
|
@@ -72,6 +72,38 @@ function makeBrowserObservableUatContent(mode = 'artifact-driven'): string {
|
|
|
72
72
|
].join('\n');
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
function makeDeferredBrowserUatContent(): string {
|
|
76
|
+
return [
|
|
77
|
+
'# UAT File',
|
|
78
|
+
'',
|
|
79
|
+
'## UAT Type',
|
|
80
|
+
'',
|
|
81
|
+
'- UAT mode: artifact-driven',
|
|
82
|
+
'- 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.',
|
|
83
|
+
'',
|
|
84
|
+
'## Smoke Test',
|
|
85
|
+
'',
|
|
86
|
+
'Run `node --test tests/s01-static-interactions.test.js` and confirm all tests pass.',
|
|
87
|
+
'',
|
|
88
|
+
'## Test Cases',
|
|
89
|
+
'',
|
|
90
|
+
'1. Click the todo row edit control in the DOM harness.',
|
|
91
|
+
'2. Save changed text and reload/recreate the app from persisted localStorage.',
|
|
92
|
+
'3. Expected: the stored record shape remains unchanged.',
|
|
93
|
+
'',
|
|
94
|
+
'## Not Proven By This UAT',
|
|
95
|
+
'',
|
|
96
|
+
'- Final visual polish of edit controls.',
|
|
97
|
+
'- Keyboard usability through a real browser.',
|
|
98
|
+
'- Browser console and local network cleanliness.',
|
|
99
|
+
'',
|
|
100
|
+
'## Notes for Tester',
|
|
101
|
+
'',
|
|
102
|
+
'S02 should capture browser evidence for the full loop rather than changing this persisted model.',
|
|
103
|
+
'',
|
|
104
|
+
].join('\n');
|
|
105
|
+
}
|
|
106
|
+
|
|
75
107
|
describe('run-uat', () => {
|
|
76
108
|
test('(a) artifact-driven', () => {
|
|
77
109
|
assert.deepStrictEqual(
|
|
@@ -232,8 +264,8 @@ test('(k) run-uat prompt template', () => {
|
|
|
232
264
|
`prompt contains detected dynamic uatType value "${uatType}" after substitution`,
|
|
233
265
|
);
|
|
234
266
|
assert.ok(
|
|
235
|
-
promptResult?.includes(`uatType: ${uatType}`) ?? false,
|
|
236
|
-
`prompt contains dynamic uatType
|
|
267
|
+
promptResult?.includes(`uatType: "${uatType}"`) ?? false,
|
|
268
|
+
`prompt contains dynamic uatType field "${uatType}" after substitution`,
|
|
237
269
|
);
|
|
238
270
|
assert.ok(
|
|
239
271
|
!/\{\{[^}]+\}\}/.test(promptResult ?? ''),
|
|
@@ -249,7 +281,7 @@ test('(k) run-uat prompt template', () => {
|
|
|
249
281
|
);
|
|
250
282
|
});
|
|
251
283
|
|
|
252
|
-
test('(k2) run-uat prompt references
|
|
284
|
+
test('(k2) run-uat prompt references gsd_uat_result_save, not direct write', () => {
|
|
253
285
|
const promptResult = loadPromptFromWorktree('run-uat', {
|
|
254
286
|
workingDirectory: '/tmp/test-project',
|
|
255
287
|
milestoneId: 'M001',
|
|
@@ -261,17 +293,25 @@ test('(k2) run-uat prompt references gsd_summary_save, not direct write', () =>
|
|
|
261
293
|
});
|
|
262
294
|
|
|
263
295
|
assert.ok(
|
|
264
|
-
promptResult.includes('
|
|
265
|
-
'run-uat prompt should reference
|
|
296
|
+
promptResult.includes('gsd_uat_result_save'),
|
|
297
|
+
'run-uat prompt should reference gsd_uat_result_save tool',
|
|
298
|
+
);
|
|
299
|
+
assert.ok(
|
|
300
|
+
promptResult.includes('presentedTools') && promptResult.includes('blockedTools'),
|
|
301
|
+
'run-uat prompt should specify the tool presentation contract',
|
|
266
302
|
);
|
|
267
303
|
assert.ok(
|
|
268
|
-
promptResult.includes('
|
|
269
|
-
'run-uat prompt should
|
|
304
|
+
!promptResult.includes('Call `gsd_summary_save`'),
|
|
305
|
+
'run-uat prompt should not instruct direct summary-save UAT persistence',
|
|
270
306
|
);
|
|
271
307
|
assert.ok(
|
|
272
308
|
!promptResult.includes('MUST write'),
|
|
273
309
|
'run-uat prompt should not instruct direct file write in footer',
|
|
274
310
|
);
|
|
311
|
+
assert.ok(
|
|
312
|
+
!promptResult.includes('Call `gsd_summary_save` with `artifact_type: "ASSESSMENT"`'),
|
|
313
|
+
'run-uat prompt should not instruct the legacy summary-save UAT path',
|
|
314
|
+
);
|
|
275
315
|
});
|
|
276
316
|
|
|
277
317
|
test('(l) dispatch preconditions via resolveSliceFile', () => {
|
|
@@ -482,8 +522,8 @@ test('(n) stale replay guard', async () => {
|
|
|
482
522
|
});
|
|
483
523
|
|
|
484
524
|
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
|
|
525
|
+
// Regression test for #2644: run-uat writes the verdict to
|
|
526
|
+
// S{sid}-ASSESSMENT.md through the structured UAT save path,
|
|
487
527
|
// but checkNeedsRunUat only checked S{sid}-UAT.md — causing a stuck loop.
|
|
488
528
|
const base = createFixtureBase();
|
|
489
529
|
try {
|
|
@@ -679,11 +719,27 @@ test('(u) run-uat prompt promotes artifact-driven browser specs to browser-execu
|
|
|
679
719
|
const prompt = await buildRunUatPrompt('M001', 'S01', uatRel, uatContent, base);
|
|
680
720
|
|
|
681
721
|
assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`browser-executable`/);
|
|
682
|
-
assert.match(prompt, /uatType: browser-executable/);
|
|
722
|
+
assert.match(prompt, /uatType: "browser-executable"/);
|
|
683
723
|
assert.match(prompt, /use gsd-browser tools/i);
|
|
684
724
|
} finally {
|
|
685
725
|
cleanup(base);
|
|
686
726
|
}
|
|
687
727
|
});
|
|
688
728
|
|
|
729
|
+
test('(v) run-uat prompt keeps deferred browser work artifact-driven', async () => {
|
|
730
|
+
const base = createFixtureBase();
|
|
731
|
+
try {
|
|
732
|
+
const uatRel = '.gsd/milestones/M001/slices/S01/S01-UAT.md';
|
|
733
|
+
const uatContent = makeDeferredBrowserUatContent();
|
|
734
|
+
writeSliceFile(base, 'M001', 'S01', 'UAT', uatContent);
|
|
735
|
+
|
|
736
|
+
const prompt = await buildRunUatPrompt('M001', 'S01', uatRel, uatContent, base);
|
|
737
|
+
|
|
738
|
+
assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`artifact-driven`/);
|
|
739
|
+
assert.match(prompt, /uatType: "artifact-driven"/);
|
|
740
|
+
assert.doesNotMatch(prompt, /uatType: "browser-executable"/);
|
|
741
|
+
} finally {
|
|
742
|
+
cleanup(base);
|
|
743
|
+
}
|
|
744
|
+
});
|
|
689
745
|
});
|
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' });
|
|
@@ -102,8 +102,8 @@ test("migration auto-check preserves empty DB and reports explicit recovery", as
|
|
|
102
102
|
assert.equal(result.action, "recovery-required");
|
|
103
103
|
assert.equal(result.reason, "db-empty");
|
|
104
104
|
assert.deepEqual(result.afterDb, { milestones: 0, slices: 0, tasks: 0 });
|
|
105
|
-
assert.equal(result.recoveryCommand, "/gsd recover");
|
|
106
|
-
assert.match(result.message ?? "", /run `\/gsd recover`/);
|
|
105
|
+
assert.equal(result.recoveryCommand, "/gsd recover --confirm");
|
|
106
|
+
assert.match(result.message ?? "", /run `\/gsd recover --confirm`/);
|
|
107
107
|
assert.equal(getAllMilestones().length, 0);
|
|
108
108
|
assert.equal(getSliceTasks("M001", "S01").length, 0);
|
|
109
109
|
} finally {
|
|
@@ -125,7 +125,7 @@ test("migration auto-check preserves DB on hierarchy count mismatch", async () =
|
|
|
125
125
|
assert.equal(result.reason, "count-mismatch");
|
|
126
126
|
assert.deepEqual(result.beforeDb, { milestones: 1, slices: 1, tasks: 0 });
|
|
127
127
|
assert.deepEqual(result.afterDb, { milestones: 1, slices: 1, tasks: 0 });
|
|
128
|
-
assert.equal(result.recoveryCommand, "/gsd recover");
|
|
128
|
+
assert.equal(result.recoveryCommand, "/gsd recover --confirm");
|
|
129
129
|
assert.equal(getSliceTasks("M001", "S01").length, 0);
|
|
130
130
|
} finally {
|
|
131
131
|
cleanup(base);
|
|
@@ -13,10 +13,10 @@ test("dispatchNewMilestoneDiscuss uses discuss.md only on greenfield projects",
|
|
|
13
13
|
|
|
14
14
|
assert.match(fnBody, /findMilestoneIds\(basePath\)\.length === 0/);
|
|
15
15
|
assert.match(fnBody, /prepareAndBuildDiscussPrompt/);
|
|
16
|
-
assert.match(fnBody, /
|
|
16
|
+
assert.match(fnBody, /buildDiscussMilestonePrompt/);
|
|
17
17
|
assert.match(
|
|
18
18
|
fnBody,
|
|
19
|
-
/if \(isGreenfield\)[\s\S]*prepareAndBuildDiscussPrompt[\s\S]*
|
|
19
|
+
/if \(isGreenfield\)[\s\S]*prepareAndBuildDiscussPrompt[\s\S]*buildDiscussMilestonePrompt/,
|
|
20
20
|
"greenfield branch must precede guided-discuss-milestone branch",
|
|
21
21
|
);
|
|
22
22
|
});
|
|
@@ -24,7 +24,7 @@ test("dispatchNewMilestoneDiscuss uses discuss.md only on greenfield projects",
|
|
|
24
24
|
test("dispatchNewMilestoneDiscuss uses milestone-specific preparation guidance", () => {
|
|
25
25
|
const source = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
|
|
26
26
|
const fnBody = extractSourceRegion(source, "async function dispatchNewMilestoneDiscuss(");
|
|
27
|
-
assert.match(fnBody, /buildDiscussPreparationContext\(ctx, basePath, "milestone"\)/);
|
|
27
|
+
assert.match(fnBody, /buildDiscussPreparationContext\(ctx, basePath, "milestone", true\)/);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
test("launchNextMilestoneDiscuss routes through dispatchNewMilestoneDiscuss for normal path", () => {
|