@opengsd/gsd-pi 1.2.0-dev.5457a158 → 1.2.0-dev.822c9439
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/headless-events.js +7 -5
- package/dist/mcp-server.js +2 -1
- package/dist/resource-loader.d.ts +9 -5
- package/dist/resource-loader.js +114 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +5 -4
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
- package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
- package/dist/resources/extensions/async-jobs/index.js +65 -0
- package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
- package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
- package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
- package/dist/resources/extensions/bg-shell/overlay.js +9 -6
- package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
- package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
- package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
- package/dist/resources/extensions/browser-tools/index.js +69 -12
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +3 -2
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +89 -54
- package/dist/resources/extensions/gsd/auto/phases.js +49 -6
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
- package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
- package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
- package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
- package/dist/resources/extensions/gsd/auto-prompts.js +78 -19
- package/dist/resources/extensions/gsd/auto-start.js +12 -12
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
- package/dist/resources/extensions/gsd/auto-verification.js +23 -30
- package/dist/resources/extensions/gsd/auto-worktree.js +14 -1
- package/dist/resources/extensions/gsd/auto.js +37 -1
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +172 -59
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
- package/dist/resources/extensions/gsd/consent-question.js +353 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- package/dist/resources/extensions/gsd/constants.js +0 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
- package/dist/resources/extensions/gsd/db/queries.js +26 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
- package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
- package/dist/resources/extensions/gsd/files.js +33 -19
- package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +2 -1
- package/dist/resources/extensions/gsd/guidance.js +60 -0
- package/dist/resources/extensions/gsd/guided-flow.js +6 -3
- package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
- package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/preferences-models.js +2 -2
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/dist/resources/extensions/gsd/prompts/system.md +5 -2
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/state.js +5 -0
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
- package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
- package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
- package/dist/resources/extensions/gsd/uat-policy.js +42 -16
- package/dist/resources/extensions/gsd/unit-context-composer.js +65 -0
- package/dist/resources/extensions/gsd/unit-registry.js +7 -20
- package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
- package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
- package/dist/resources/extensions/gsd/workflow-events.js +6 -18
- package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
- package/dist/resources/extensions/gsd/worktree.js +8 -1
- package/dist/resources/extensions/search-the-web/native-search.js +5 -3
- package/dist/resources/extensions/shared/browser-contract.js +59 -0
- package/dist/resources/extensions/shared/gsd-browser-cli.js +116 -6
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -1
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/SKILL.md +3 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
- package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +20 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- 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/api/update/route.js.nft.json +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 +11 -11
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-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/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/package.json +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- 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.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
- 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 +8 -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-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +10 -5
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +4 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +99 -38
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
- package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +3 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/README.md +1 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +239 -153
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +256 -145
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
- package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +5 -4
- package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
- package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
- package/src/resources/extensions/async-jobs/index.ts +79 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
- package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
- package/src/resources/extensions/bg-shell/overlay.ts +9 -5
- package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
- package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
- package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
- package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
- package/src/resources/extensions/browser-tools/index.ts +71 -13
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +3 -2
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +98 -56
- package/src/resources/extensions/gsd/auto/phases.ts +65 -26
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
- package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
- package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +115 -35
- package/src/resources/extensions/gsd/auto-start.ts +12 -14
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
- package/src/resources/extensions/gsd/auto-verification.ts +26 -28
- package/src/resources/extensions/gsd/auto-worktree.ts +14 -1
- package/src/resources/extensions/gsd/auto.ts +44 -1
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +211 -59
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
- package/src/resources/extensions/gsd/consent-question.ts +431 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- package/src/resources/extensions/gsd/constants.ts +0 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
- package/src/resources/extensions/gsd/db/queries.ts +37 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/files.ts +33 -12
- package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +4 -3
- package/src/resources/extensions/gsd/guidance.ts +78 -0
- package/src/resources/extensions/gsd/guided-flow.ts +21 -26
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
- package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/preferences-models.ts +2 -1
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/src/resources/extensions/gsd/prompts/system.md +5 -2
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/state.ts +5 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
- package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
- package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +7 -11
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +20 -58
- package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
- package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
- package/src/resources/extensions/gsd/uat-policy.ts +62 -16
- package/src/resources/extensions/gsd/unit-context-composer.ts +99 -0
- package/src/resources/extensions/gsd/unit-registry.ts +7 -20
- package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
- package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
- package/src/resources/extensions/gsd/workflow-events.ts +12 -20
- package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
- package/src/resources/extensions/gsd/worktree.ts +7 -1
- package/src/resources/extensions/search-the-web/native-search.ts +5 -3
- package/src/resources/extensions/shared/browser-contract.ts +66 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +141 -6
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -1
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/SKILL.md +3 -0
- package/src/resources/skills/create-skill/references/executable-code.md +1 -1
- package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
- package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
- package/src/resources/skills/gsd-browser/SKILL.md +0 -41
- /package/dist/web/standalone/.next/static/{2p9Rv9pQflAxCBbGVI2vb → yWwBo-w09Y_W-nmeeWFRp}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{2p9Rv9pQflAxCBbGVI2vb → yWwBo-w09Y_W-nmeeWFRp}/_ssgManifest.js +0 -0
|
@@ -731,6 +731,75 @@ test('(u) run-uat prompt promotes artifact-driven browser specs to browser-execu
|
|
|
731
731
|
}
|
|
732
732
|
});
|
|
733
733
|
|
|
734
|
+
test('(w) run-uat prompt promotes browser-executable harness specs to runtime-executable (M006/S01)', async () => {
|
|
735
|
+
const base = createFixtureBase();
|
|
736
|
+
try {
|
|
737
|
+
const uatRel = '.gsd/milestones/M006/slices/S01/S01-UAT.md';
|
|
738
|
+
const uatContent = [
|
|
739
|
+
'# S01 UAT',
|
|
740
|
+
'',
|
|
741
|
+
'## UAT Type',
|
|
742
|
+
'- UAT mode: browser-executable',
|
|
743
|
+
'',
|
|
744
|
+
'## Preconditions',
|
|
745
|
+
'- Start the local app server with `npm run start`.',
|
|
746
|
+
'- Open the app at `http://127.0.0.1:4173`.',
|
|
747
|
+
'',
|
|
748
|
+
'## Evidence',
|
|
749
|
+
'- Fresh closeout verification command: `npm run test:uat`',
|
|
750
|
+
].join('\n');
|
|
751
|
+
writeSliceFile(base, 'M006', 'S01', 'UAT', uatContent);
|
|
752
|
+
|
|
753
|
+
const prompt = await buildRunUatPrompt('M006', 'S01', uatRel, uatContent, base);
|
|
754
|
+
|
|
755
|
+
assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`runtime-executable`/);
|
|
756
|
+
assert.match(prompt, /uatType: "runtime-executable"/);
|
|
757
|
+
assert.match(prompt, /Runtime harness override/i);
|
|
758
|
+
assert.match(prompt, /Do \*\*not\*\* call `uat-service-start`/);
|
|
759
|
+
assert.doesNotMatch(prompt, /uatType: "browser-executable"/);
|
|
760
|
+
} finally {
|
|
761
|
+
cleanup(base);
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
test('(w2) run-uat prompt promotes harness from slice context when UAT only names test:server (M007/S01)', async () => {
|
|
766
|
+
const base = createFixtureBase();
|
|
767
|
+
try {
|
|
768
|
+
const uatRel = '.gsd/milestones/M007/slices/S01/S01-UAT.md';
|
|
769
|
+
const uatContent = [
|
|
770
|
+
'# S01 UAT',
|
|
771
|
+
'',
|
|
772
|
+
'## UAT Type',
|
|
773
|
+
'- UAT mode: browser-executable',
|
|
774
|
+
'',
|
|
775
|
+
'## Preconditions',
|
|
776
|
+
'- Start the dev/local verification server with `npm run test:server`.',
|
|
777
|
+
'- Open the app at the localhost URL printed by the server.',
|
|
778
|
+
].join('\n');
|
|
779
|
+
writeSliceFile(base, 'M007', 'S01', 'UAT', uatContent);
|
|
780
|
+
writeSliceFile(
|
|
781
|
+
base,
|
|
782
|
+
'M007',
|
|
783
|
+
'S01',
|
|
784
|
+
'SUMMARY',
|
|
785
|
+
[
|
|
786
|
+
'# S01 Summary',
|
|
787
|
+
'',
|
|
788
|
+
'Verification: `npm run test:uat` passed with clean browser diagnostics.',
|
|
789
|
+
].join('\n'),
|
|
790
|
+
);
|
|
791
|
+
|
|
792
|
+
const prompt = await buildRunUatPrompt('M007', 'S01', uatRel, uatContent, base);
|
|
793
|
+
|
|
794
|
+
assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`runtime-executable`/);
|
|
795
|
+
assert.match(prompt, /Runtime harness override/i);
|
|
796
|
+
assert.match(prompt, /npm run test:server/);
|
|
797
|
+
assert.match(prompt, /uatType: "runtime-executable"/);
|
|
798
|
+
} finally {
|
|
799
|
+
cleanup(base);
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
|
|
734
803
|
test('(v) run-uat prompt keeps deferred browser work artifact-driven', async () => {
|
|
735
804
|
const base = createFixtureBase();
|
|
736
805
|
try {
|
|
@@ -748,4 +817,134 @@ test('(v) run-uat prompt keeps deferred browser work artifact-driven', async ()
|
|
|
748
817
|
cleanup(base);
|
|
749
818
|
}
|
|
750
819
|
});
|
|
820
|
+
|
|
821
|
+
test('(x) checkNeedsRunUat returns runtime-executable when slice SUMMARY names a self-contained harness (M007/S01)', async () => {
|
|
822
|
+
// Regression: the dispatch gate must surface the same effective UAT mode
|
|
823
|
+
// that buildRunUatPrompt emits. When the UAT file alone declares
|
|
824
|
+
// `browser-executable` but the slice SUMMARY references `npm run test:uat`,
|
|
825
|
+
// the prompt promotes to `runtime-executable` — and so must the gate, or
|
|
826
|
+
// the auto-dispatch path requires browser tools / warms up the browser
|
|
827
|
+
// daemon (and may stop dispatch entirely) for a UAT that never touches
|
|
828
|
+
// the browser. See cursor[bot] review on PR #696.
|
|
829
|
+
const base = createFixtureBase();
|
|
830
|
+
try {
|
|
831
|
+
const roadmapDir = join(base, '.gsd', 'milestones', 'M007');
|
|
832
|
+
mkdirSync(roadmapDir, { recursive: true });
|
|
833
|
+
writeFileSync(
|
|
834
|
+
join(roadmapDir, 'M007-ROADMAP.md'),
|
|
835
|
+
[
|
|
836
|
+
'# M007: Test roadmap',
|
|
837
|
+
'',
|
|
838
|
+
'## Slices',
|
|
839
|
+
'',
|
|
840
|
+
'- [x] **S01: Only slice** `risk:low` `depends:[]`',
|
|
841
|
+
'',
|
|
842
|
+
'## Boundary Map',
|
|
843
|
+
'',
|
|
844
|
+
].join('\n'),
|
|
845
|
+
);
|
|
846
|
+
writeSliceFile(
|
|
847
|
+
base,
|
|
848
|
+
'M007',
|
|
849
|
+
'S01',
|
|
850
|
+
'UAT',
|
|
851
|
+
[
|
|
852
|
+
'# S01 UAT',
|
|
853
|
+
'',
|
|
854
|
+
'## UAT Type',
|
|
855
|
+
'- UAT mode: browser-executable',
|
|
856
|
+
'',
|
|
857
|
+
'## Preconditions',
|
|
858
|
+
'- Start the dev/local verification server with `npm run test:server`.',
|
|
859
|
+
].join('\n'),
|
|
860
|
+
);
|
|
861
|
+
writeSliceFile(
|
|
862
|
+
base,
|
|
863
|
+
'M007',
|
|
864
|
+
'S01',
|
|
865
|
+
'SUMMARY',
|
|
866
|
+
[
|
|
867
|
+
'# S01 Summary',
|
|
868
|
+
'',
|
|
869
|
+
'Verification: `npm run test:uat` passed with clean browser diagnostics.',
|
|
870
|
+
].join('\n'),
|
|
871
|
+
);
|
|
872
|
+
|
|
873
|
+
const state = {
|
|
874
|
+
activeMilestone: { id: 'M007', title: 'Test roadmap' },
|
|
875
|
+
activeSlice: null,
|
|
876
|
+
activeTask: null,
|
|
877
|
+
phase: 'validating-milestone',
|
|
878
|
+
recentDecisions: [],
|
|
879
|
+
blockers: [],
|
|
880
|
+
nextAction: 'Validate M007',
|
|
881
|
+
registry: [],
|
|
882
|
+
} as const;
|
|
883
|
+
|
|
884
|
+
const result = await checkNeedsRunUat(base, 'M007', state as any, { uat_dispatch: true } as any);
|
|
885
|
+
assert.deepStrictEqual(
|
|
886
|
+
result,
|
|
887
|
+
{ sliceId: 'S01', uatType: 'runtime-executable' },
|
|
888
|
+
'dispatch gate must mirror the prompt`s runtime-executable promotion so it does not require browser tools',
|
|
889
|
+
);
|
|
890
|
+
} finally {
|
|
891
|
+
cleanup(base);
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
test('(x2) checkNeedsRunUat leaves true browser-executable UAT unpromoted when no harness is referenced', async () => {
|
|
896
|
+
// Counter-test for (x): when the slice SUMMARY does NOT name a
|
|
897
|
+
// self-contained harness, the dispatch gate must still require browser
|
|
898
|
+
// tools for a genuinely browser-executable UAT.
|
|
899
|
+
const base = createFixtureBase();
|
|
900
|
+
try {
|
|
901
|
+
const roadmapDir = join(base, '.gsd', 'milestones', 'M008');
|
|
902
|
+
mkdirSync(roadmapDir, { recursive: true });
|
|
903
|
+
writeFileSync(
|
|
904
|
+
join(roadmapDir, 'M008-ROADMAP.md'),
|
|
905
|
+
[
|
|
906
|
+
'# M008: Test roadmap',
|
|
907
|
+
'',
|
|
908
|
+
'## Slices',
|
|
909
|
+
'',
|
|
910
|
+
'- [x] **S01: Only slice** `risk:low` `depends:[]`',
|
|
911
|
+
'',
|
|
912
|
+
'## Boundary Map',
|
|
913
|
+
'',
|
|
914
|
+
].join('\n'),
|
|
915
|
+
);
|
|
916
|
+
writeSliceFile(base, 'M008', 'S01', 'UAT', makeBrowserObservableUatContent('browser-executable'));
|
|
917
|
+
writeSliceFile(
|
|
918
|
+
base,
|
|
919
|
+
'M008',
|
|
920
|
+
'S01',
|
|
921
|
+
'SUMMARY',
|
|
922
|
+
[
|
|
923
|
+
'# S01 Summary',
|
|
924
|
+
'',
|
|
925
|
+
'Verification: clicked through the UI and confirmed the search box filters todos.',
|
|
926
|
+
].join('\n'),
|
|
927
|
+
);
|
|
928
|
+
|
|
929
|
+
const state = {
|
|
930
|
+
activeMilestone: { id: 'M008', title: 'Test roadmap' },
|
|
931
|
+
activeSlice: null,
|
|
932
|
+
activeTask: null,
|
|
933
|
+
phase: 'validating-milestone',
|
|
934
|
+
recentDecisions: [],
|
|
935
|
+
blockers: [],
|
|
936
|
+
nextAction: 'Validate M008',
|
|
937
|
+
registry: [],
|
|
938
|
+
} as const;
|
|
939
|
+
|
|
940
|
+
const result = await checkNeedsRunUat(base, 'M008', state as any, { uat_dispatch: true } as any);
|
|
941
|
+
assert.deepStrictEqual(
|
|
942
|
+
result,
|
|
943
|
+
{ sliceId: 'S01', uatType: 'browser-executable' },
|
|
944
|
+
'a true browser-executable UAT without a harness reference must keep its browser-executable mode',
|
|
945
|
+
);
|
|
946
|
+
} finally {
|
|
947
|
+
cleanup(base);
|
|
948
|
+
}
|
|
949
|
+
});
|
|
751
950
|
});
|
|
@@ -60,7 +60,9 @@ test("ensureProjectWorkflowMcpConfig creates .mcp.json with workflow and browser
|
|
|
60
60
|
assert.equal(typeof browserArgs[mcpArgIndex + 6], "string");
|
|
61
61
|
assert.ok((browserArgs[mcpArgIndex + 6] ?? "").length > 0, "identity-key must be non-empty");
|
|
62
62
|
assert.equal(browserArgs[mcpArgIndex + 7], "--identity-project");
|
|
63
|
-
assert.equal(browserArgs[mcpArgIndex + 8],
|
|
63
|
+
assert.equal(typeof browserArgs[mcpArgIndex + 8], "string");
|
|
64
|
+
assert.ok((browserArgs[mcpArgIndex + 8] ?? "").length > 0, "identity-project must be non-empty");
|
|
65
|
+
assert.doesNotMatch(browserArgs[mcpArgIndex + 8] ?? "", /[\\/]/, "identity-project must not be a filesystem path");
|
|
64
66
|
assert.equal((browserServer as { cwd?: string })?.cwd, projectRoot);
|
|
65
67
|
|
|
66
68
|
const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
|
|
@@ -3,22 +3,24 @@
|
|
|
3
3
|
|
|
4
4
|
import test from "node:test";
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
|
-
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
6
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, readFileSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { openDatabase, insertAssessment, insertMilestone, insertSlice, closeDatabase } from "../gsd-db.js";
|
|
10
10
|
import {
|
|
11
11
|
isMilestoneCloseoutSettled,
|
|
12
12
|
evaluateCompleteMilestoneDispatch,
|
|
13
|
+
isCompletedMilestoneTerminal,
|
|
14
|
+
repairMissingMilestoneSummaryProjection,
|
|
13
15
|
} from "../milestone-closeout.js";
|
|
14
16
|
import type { DispatchContext } from "../auto-dispatch.js";
|
|
15
17
|
|
|
16
18
|
/** Build a minimal DispatchContext for the dispatch-policy branches under test. */
|
|
17
|
-
function makeDispatchCtx(base: string, phase: string): DispatchContext {
|
|
19
|
+
function makeDispatchCtx(base: string, phase: string, mid = "M001"): DispatchContext {
|
|
18
20
|
return {
|
|
19
21
|
basePath: base,
|
|
20
|
-
mid
|
|
21
|
-
midTitle:
|
|
22
|
+
mid,
|
|
23
|
+
midTitle: `${mid}: Test`,
|
|
22
24
|
state: { phase } as DispatchContext["state"],
|
|
23
25
|
prefs: undefined,
|
|
24
26
|
} as DispatchContext;
|
|
@@ -119,3 +121,92 @@ test("evaluateCompleteMilestoneDispatch skips when milestone is already closed",
|
|
|
119
121
|
assert.ok(action, "an already-closed milestone in completing-milestone should yield an action");
|
|
120
122
|
assert.equal(action!.action, "skip", "already-closed milestone should resolve to skip (idempotent)");
|
|
121
123
|
});
|
|
124
|
+
|
|
125
|
+
test("isCompletedMilestoneTerminal accepts DB complete without SUMMARY artifact", async () => {
|
|
126
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-terminal-db-complete-"));
|
|
127
|
+
tmpDirs.push(base);
|
|
128
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
129
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
130
|
+
insertMilestone({ id: "M008", title: "Done", status: "complete" });
|
|
131
|
+
insertSlice({ id: "S01", milestoneId: "M008", title: "Slice", status: "complete" });
|
|
132
|
+
|
|
133
|
+
assert.equal(await isCompletedMilestoneTerminal(base, "M008"), true);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("isCompletedMilestoneTerminal accepts validation-pass with all slices closed", async () => {
|
|
137
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-terminal-validation-pass-"));
|
|
138
|
+
tmpDirs.push(base);
|
|
139
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
140
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
141
|
+
insertMilestone({ id: "M008", title: "Active", status: "active" });
|
|
142
|
+
insertSlice({ id: "S01", milestoneId: "M008", title: "Slice", status: "complete" });
|
|
143
|
+
insertAssessment({
|
|
144
|
+
path: "milestones/M008/M008-VALIDATION.md",
|
|
145
|
+
milestoneId: "M008",
|
|
146
|
+
status: "pass",
|
|
147
|
+
scope: "milestone-validation",
|
|
148
|
+
fullContent: "verdict: pass",
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
assert.equal(await isCompletedMilestoneTerminal(base, "M008"), true);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test("evaluateCompleteMilestoneDispatch repairs missing SUMMARY when DB is closed", async () => {
|
|
155
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-dispatch-repair-summary-"));
|
|
156
|
+
tmpDirs.push(base);
|
|
157
|
+
mkdirSync(join(base, ".gsd", "milestones", "M008"), { recursive: true });
|
|
158
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
159
|
+
insertMilestone({ id: "M008", title: "Live Text Search", status: "complete" });
|
|
160
|
+
insertSlice({ id: "S01", milestoneId: "M008", title: "Slice", status: "complete" });
|
|
161
|
+
insertAssessment({
|
|
162
|
+
path: "milestones/M008/M008-VALIDATION.md",
|
|
163
|
+
milestoneId: "M008",
|
|
164
|
+
status: "pass",
|
|
165
|
+
scope: "milestone-validation",
|
|
166
|
+
fullContent: "verdict: pass",
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const action = await evaluateCompleteMilestoneDispatch(
|
|
170
|
+
makeDispatchCtx(base, "completing-milestone", "M008"),
|
|
171
|
+
);
|
|
172
|
+
assert.equal(action?.action, "skip");
|
|
173
|
+
assert.ok(
|
|
174
|
+
existsSync(join(base, ".gsd", "milestones", "M008", "M008-SUMMARY.md")),
|
|
175
|
+
"repair should write the missing milestone SUMMARY projection",
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("repairMissingMilestoneSummaryProjection succeeds when milestone dir does not exist yet", async () => {
|
|
180
|
+
// Regression: resolveExpectedArtifactPath returns null before the milestone
|
|
181
|
+
// directory exists. The post-write success check must use the handler's
|
|
182
|
+
// returned summaryPath (the absolute path it just created), not the
|
|
183
|
+
// pre-write resolver result, otherwise repair always reports failure and
|
|
184
|
+
// dispatch falls back to re-dispatching complete-milestone.
|
|
185
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-repair-summary-new-dir-"));
|
|
186
|
+
tmpDirs.push(base);
|
|
187
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
188
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
189
|
+
insertMilestone({ id: "M042", title: "Done", status: "complete" });
|
|
190
|
+
|
|
191
|
+
const repair = await repairMissingMilestoneSummaryProjection(base, "M042");
|
|
192
|
+
assert.equal(repair.ok, true, "repair should report success when handler creates the SUMMARY");
|
|
193
|
+
assert.ok(
|
|
194
|
+
existsSync(join(base, ".gsd", "milestones", "M042", "M042-SUMMARY.md")),
|
|
195
|
+
"repair should write the SUMMARY artifact to the canonical projection path",
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("repairMissingMilestoneSummaryProjection is idempotent when SUMMARY exists", async () => {
|
|
200
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-repair-summary-idempotent-"));
|
|
201
|
+
tmpDirs.push(base);
|
|
202
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M001");
|
|
203
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
204
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
205
|
+
insertMilestone({ id: "M001", title: "Done", status: "complete" });
|
|
206
|
+
const summaryPath = join(milestoneDir, "M001-SUMMARY.md");
|
|
207
|
+
writeFileSync(summaryPath, "# Existing summary\n");
|
|
208
|
+
|
|
209
|
+
const repair = await repairMissingMilestoneSummaryProjection(base, "M001");
|
|
210
|
+
assert.equal(repair.ok, true);
|
|
211
|
+
assert.equal(readFileSync(summaryPath, "utf-8"), "# Existing summary\n");
|
|
212
|
+
});
|
|
@@ -14,7 +14,7 @@ import { tmpdir } from "node:os";
|
|
|
14
14
|
import { resolveExpectedArtifactPath } from "../auto-artifact-paths.ts";
|
|
15
15
|
import { unitPhaseLabel, unitVerb } from "../auto-dashboard.ts";
|
|
16
16
|
import { classifyUnitPhase } from "../metrics.ts";
|
|
17
|
-
import { resolveModelWithFallbacksForUnit } from "../preferences-models.ts";
|
|
17
|
+
import { resolveDefaultSessionModel, resolveModelWithFallbacksForUnit } from "../preferences-models.ts";
|
|
18
18
|
import { KNOWN_UNIT_LABELS } from "../preferences-types.ts";
|
|
19
19
|
|
|
20
20
|
function withModelPreferences<T>(fn: () => T): T {
|
|
@@ -92,6 +92,37 @@ test("run-uat falls back to completion when uat bucket is not configured", () =>
|
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
+
test("default session model resolves from the explicit project base path", () => {
|
|
96
|
+
const oldHome = process.env.GSD_HOME;
|
|
97
|
+
const originalCwd = process.cwd();
|
|
98
|
+
const home = mkdtempSync(join(tmpdir(), "gsd-model-map-home-"));
|
|
99
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-model-map-project-"));
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
process.env.GSD_HOME = home;
|
|
103
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
104
|
+
writeFileSync(join(base, ".gsd", "PREFERENCES.md"), [
|
|
105
|
+
"---",
|
|
106
|
+
"models:",
|
|
107
|
+
" execution: gpt-5.5",
|
|
108
|
+
"---",
|
|
109
|
+
"",
|
|
110
|
+
].join("\n"));
|
|
111
|
+
process.chdir(home);
|
|
112
|
+
|
|
113
|
+
assert.deepEqual(resolveDefaultSessionModel("openai-codex", base), {
|
|
114
|
+
provider: "openai-codex",
|
|
115
|
+
id: "gpt-5.5",
|
|
116
|
+
});
|
|
117
|
+
} finally {
|
|
118
|
+
process.chdir(originalCwd);
|
|
119
|
+
if (oldHome === undefined) delete process.env.GSD_HOME;
|
|
120
|
+
else process.env.GSD_HOME = oldHome;
|
|
121
|
+
rmSync(home, { recursive: true, force: true });
|
|
122
|
+
rmSync(base, { recursive: true, force: true });
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
95
126
|
test("every known unit label with a dispatch phase resolves when all model buckets are configured", () => {
|
|
96
127
|
withModelPreferences(() => {
|
|
97
128
|
const missing = KNOWN_UNIT_LABELS.filter((unitType) => !resolveModelWithFallbacksForUnit(unitType));
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth/subscription vs pay-per-token API routing for bare model IDs.
|
|
3
|
+
*
|
|
4
|
+
* When the same model ID (e.g. gpt-5.5) exists on multiple providers, resolveModelId
|
|
5
|
+
* must prefer subscription/OAuth routes over platform API keys.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { MODELS } from "../../../../../packages/pi-ai/dist/models.generated.js";
|
|
11
|
+
import {
|
|
12
|
+
BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE,
|
|
13
|
+
resolveModelId,
|
|
14
|
+
} from "../auto-model-selection.js";
|
|
15
|
+
|
|
16
|
+
type ModelRef = { id: string; provider: string };
|
|
17
|
+
|
|
18
|
+
function modelsForProviders(modelId: string, providers: string[]): ModelRef[] {
|
|
19
|
+
return providers.map((provider) => ({ id: modelId, provider }));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Table-driven precedence cases — one row per conflict shape, not per model ID. */
|
|
23
|
+
const PRECEDENCE_CASES: Array<{
|
|
24
|
+
label: string;
|
|
25
|
+
modelId: string;
|
|
26
|
+
providers: string[];
|
|
27
|
+
expected: string;
|
|
28
|
+
currentProvider?: string;
|
|
29
|
+
}> = [
|
|
30
|
+
{
|
|
31
|
+
label: "ChatGPT OAuth beats OpenAI API (gpt-5.5)",
|
|
32
|
+
modelId: "gpt-5.5",
|
|
33
|
+
providers: ["openai", "openai-codex"],
|
|
34
|
+
expected: "openai-codex",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
label: "Codex beats Copilot beats OpenAI API (gpt-5.5 triple)",
|
|
38
|
+
modelId: "gpt-5.5",
|
|
39
|
+
providers: ["openai", "github-copilot", "openai-codex"],
|
|
40
|
+
expected: "openai-codex",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: "Copilot OAuth beats OpenAI API when no Codex (gpt-5.5)",
|
|
44
|
+
modelId: "gpt-5.5",
|
|
45
|
+
providers: ["openai", "github-copilot"],
|
|
46
|
+
expected: "github-copilot",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: "Copilot OAuth beats OpenAI API (gpt-5-mini)",
|
|
50
|
+
modelId: "gpt-5-mini",
|
|
51
|
+
providers: ["openai", "github-copilot"],
|
|
52
|
+
expected: "github-copilot",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: "Anthropic beats Copilot for Claude (claude-sonnet-4-6)",
|
|
56
|
+
modelId: "claude-sonnet-4-6",
|
|
57
|
+
providers: ["anthropic", "github-copilot"],
|
|
58
|
+
expected: "anthropic",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: "Copilot beats Google API for Gemini (gemini-2.5-pro)",
|
|
62
|
+
modelId: "gemini-2.5-pro",
|
|
63
|
+
providers: ["google", "github-copilot"],
|
|
64
|
+
expected: "github-copilot",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
label: "Gemini CLI beats Google API (gemini-2.5-pro)",
|
|
68
|
+
modelId: "gemini-2.5-pro",
|
|
69
|
+
providers: ["google", "google-gemini-cli"],
|
|
70
|
+
expected: "google-gemini-cli",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
label: "Gemini CLI beats Copilot beats Google API",
|
|
74
|
+
modelId: "gemini-2.5-pro",
|
|
75
|
+
providers: ["google", "github-copilot", "google-gemini-cli"],
|
|
76
|
+
expected: "google-gemini-cli",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: "Session provider still wins (openai-codex explicit)",
|
|
80
|
+
modelId: "gpt-5.5",
|
|
81
|
+
providers: ["openai", "openai-codex", "github-copilot"],
|
|
82
|
+
expected: "github-copilot",
|
|
83
|
+
currentProvider: "github-copilot",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
label: "claude-code session beats anthropic (#3772)",
|
|
87
|
+
modelId: "claude-sonnet-4-6",
|
|
88
|
+
providers: ["anthropic", "claude-code"],
|
|
89
|
+
expected: "claude-code",
|
|
90
|
+
currentProvider: "claude-code",
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
for (const row of PRECEDENCE_CASES) {
|
|
95
|
+
test(`resolveModelId precedence: ${row.label}`, () => {
|
|
96
|
+
const available = modelsForProviders(row.modelId, row.providers);
|
|
97
|
+
const result = resolveModelId(row.modelId, available, row.currentProvider);
|
|
98
|
+
assert.ok(result, `expected a match for ${row.modelId}`);
|
|
99
|
+
assert.equal(result.provider, row.expected);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
test("BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE covers known OAuth/subscription providers", () => {
|
|
104
|
+
const expected = [
|
|
105
|
+
"openai-codex",
|
|
106
|
+
"google-gemini-cli",
|
|
107
|
+
"anthropic",
|
|
108
|
+
"github-copilot",
|
|
109
|
+
"google-antigravity",
|
|
110
|
+
];
|
|
111
|
+
assert.deepEqual([...BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE], expected);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("every catalog overlap with OAuth/subscription + API resolves to subscription route", () => {
|
|
115
|
+
const oauthProviders = new Set(["anthropic", "github-copilot", "openai-codex"]);
|
|
116
|
+
const subscriptionCli = new Set(["google-gemini-cli", "google-antigravity", "claude-code"]);
|
|
117
|
+
const apiPayPerToken = new Set(["openai", "google", "azure-openai-responses"]);
|
|
118
|
+
|
|
119
|
+
const byId = new Map<string, Set<string>>();
|
|
120
|
+
for (const [provider, models] of Object.entries(MODELS)) {
|
|
121
|
+
for (const id of Object.keys(models)) {
|
|
122
|
+
if (!byId.has(id)) byId.set(id, new Set());
|
|
123
|
+
byId.get(id)!.add(provider);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const failures: string[] = [];
|
|
128
|
+
|
|
129
|
+
for (const [modelId, providers] of byId) {
|
|
130
|
+
if (providers.size < 2) continue;
|
|
131
|
+
|
|
132
|
+
const hasApi = [...providers].some((p) => apiPayPerToken.has(p));
|
|
133
|
+
const subscriptionCandidates = [...providers].filter(
|
|
134
|
+
(p) => oauthProviders.has(p) || subscriptionCli.has(p),
|
|
135
|
+
);
|
|
136
|
+
if (!hasApi || subscriptionCandidates.length === 0) continue;
|
|
137
|
+
|
|
138
|
+
const testProviders = new Set<string>(subscriptionCandidates);
|
|
139
|
+
for (const p of providers) {
|
|
140
|
+
if (apiPayPerToken.has(p)) testProviders.add(p);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const available = modelsForProviders(modelId, [...testProviders]);
|
|
144
|
+
const result = resolveModelId(modelId, available, undefined);
|
|
145
|
+
if (!result) {
|
|
146
|
+
failures.push(`${modelId}: no resolution among ${[...testProviders].join(", ")}`);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const winnerIsSubscription =
|
|
151
|
+
oauthProviders.has(result.provider) ||
|
|
152
|
+
subscriptionCli.has(result.provider) ||
|
|
153
|
+
result.provider === "anthropic";
|
|
154
|
+
|
|
155
|
+
if (!winnerIsSubscription) {
|
|
156
|
+
failures.push(
|
|
157
|
+
`${modelId}: got ${result.provider}, expected subscription route among ${[...testProviders].join(", ")}`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
assert.equal(
|
|
163
|
+
failures.length,
|
|
164
|
+
0,
|
|
165
|
+
`catalog overlap routing failures:\n${failures.join("\n")}`,
|
|
166
|
+
);
|
|
167
|
+
});
|
|
@@ -41,6 +41,7 @@ after(() => {
|
|
|
41
41
|
|
|
42
42
|
const { resolveDispatch } = await import("../auto-dispatch.ts");
|
|
43
43
|
const { buildParallelResearchSlicesPrompt } = await import("../auto-prompts.ts");
|
|
44
|
+
const { openDatabase, closeDatabase, insertMilestone, insertSlice } = await import("../gsd-db.ts");
|
|
44
45
|
|
|
45
46
|
type DispatchState = Parameters<typeof resolveDispatch>[0]["state"];
|
|
46
47
|
|
|
@@ -51,6 +52,20 @@ function writeRoadmap(
|
|
|
51
52
|
): void {
|
|
52
53
|
const milestoneDir = join(base, ".gsd", "milestones", mid);
|
|
53
54
|
mkdirSync(milestoneDir, { recursive: true });
|
|
55
|
+
// The dispatch rule reads slices from the DB (ADR-017), not the ROADMAP
|
|
56
|
+
// projection — seed both so disk-based artifact checks still resolve.
|
|
57
|
+
insertMilestone({ id: mid, title: "Parallel Research Milestone" });
|
|
58
|
+
let sequence = 1;
|
|
59
|
+
for (const s of slices) {
|
|
60
|
+
insertSlice({
|
|
61
|
+
id: s.id,
|
|
62
|
+
milestoneId: mid,
|
|
63
|
+
title: s.title,
|
|
64
|
+
status: s.done ? "complete" : "pending",
|
|
65
|
+
depends: s.depends ?? [],
|
|
66
|
+
sequence: sequence++,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
54
69
|
const lines = [
|
|
55
70
|
`# ${mid}: Parallel Research Milestone`,
|
|
56
71
|
"",
|
|
@@ -100,9 +115,12 @@ describe("parallel-research-slices dispatch rule", () => {
|
|
|
100
115
|
|
|
101
116
|
beforeEach(() => {
|
|
102
117
|
base = mkdtempSync(join(tmpdir(), "parallel-research-"));
|
|
118
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
119
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
103
120
|
});
|
|
104
121
|
|
|
105
122
|
afterEach(() => {
|
|
123
|
+
closeDatabase();
|
|
106
124
|
rmSync(base, { recursive: true, force: true });
|
|
107
125
|
});
|
|
108
126
|
|