gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0-dev.aeeb2ca00
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/README.md +53 -17
- package/dist/claude-cli-check.js +46 -10
- package/dist/headless.js +49 -4
- package/dist/resource-loader.d.ts +40 -0
- package/dist/resource-loader.js +32 -13
- package/dist/resources/extensions/browser-tools/capture.js +9 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
- package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +72 -16
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
- package/dist/resources/extensions/github-sync/templates.js +103 -0
- package/dist/resources/extensions/google-search/index.js +3 -2
- package/dist/resources/extensions/gsd/auto/loop.js +124 -2
- package/dist/resources/extensions/gsd/auto/phases.js +57 -39
- package/dist/resources/extensions/gsd/auto/session.js +6 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
- package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
- package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
- package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
- package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
- package/dist/resources/extensions/gsd/auto-start.js +107 -29
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
- package/dist/resources/extensions/gsd/auto.js +76 -21
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
- package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
- package/dist/resources/extensions/gsd/component-loader.js +447 -0
- package/dist/resources/extensions/gsd/component-types.js +69 -0
- package/dist/resources/extensions/gsd/context-store.js +23 -7
- package/dist/resources/extensions/gsd/detection.js +49 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/forensics.js +106 -0
- package/dist/resources/extensions/gsd/gate-registry.js +2 -2
- package/dist/resources/extensions/gsd/git-constants.js +28 -1
- package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
- package/dist/resources/extensions/gsd/git-service.js +126 -2
- package/dist/resources/extensions/gsd/gsd-db.js +6 -3
- package/dist/resources/extensions/gsd/guided-flow.js +39 -13
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
- package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
- package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
- package/dist/resources/extensions/gsd/model-router.js +6 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
- package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
- package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
- package/dist/resources/extensions/gsd/service-tier.js +5 -2
- package/dist/resources/extensions/gsd/session-lock.js +19 -10
- package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
- package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
- package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
- package/dist/resources/extensions/gsd/state.js +69 -58
- package/dist/resources/extensions/gsd/sync-lock.js +98 -42
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
- package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
- package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
- package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
- package/dist/resources/extensions/gsd/uok/writer.js +82 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
- package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
- package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
- package/dist/resources/extensions/mcp-client/index.js +3 -1
- package/dist/resources/extensions/ollama/index.js +5 -1
- package/dist/resources/extensions/remote-questions/manager.js +11 -5
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- 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 +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/git/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 +11 -11
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- 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 +2 -3
- package/packages/daemon/package.json +2 -2
- package/packages/daemon/src/logger.ts +4 -3
- package/packages/mcp-server/dist/server.d.ts +24 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +88 -87
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +15 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/mcp-server.test.ts +25 -3
- package/packages/mcp-server/src/readers/graph.test.ts +87 -15
- package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
- package/packages/mcp-server/src/server.ts +131 -105
- package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
- package/packages/mcp-server/src/workflow-tools.ts +19 -6
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +2 -2
- package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
- package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
- package/packages/native/src/__tests__/ps.test.mjs +14 -8
- package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
- package/packages/native/src/__tests__/truncate.test.mjs +17 -2
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
- package/packages/pi-agent-core/src/agent.test.ts +96 -102
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/capability-patches.js +9 -2
- package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
- package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +43 -70
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +36 -11
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +44 -0
- package/packages/pi-ai/src/models/capability-patches.ts +10 -2
- package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
- package/packages/pi-ai/src/models/generated/openai.ts +17 -0
- package/packages/pi-ai/src/models.generated.test.ts +46 -73
- package/packages/pi-ai/src/models.test.ts +48 -11
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
- package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
- package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
- package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
- package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
- package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
- package/packages/pi-tui/dist/components/editor.d.ts +14 -0
- package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/editor.js +19 -0
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.js +6 -5
- package/packages/pi-tui/dist/components/image.test.js.map +1 -1
- package/packages/pi-tui/dist/editor-component.d.ts +2 -0
- package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
- package/packages/pi-tui/dist/editor-component.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
- package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
- package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
- package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
- package/packages/pi-tui/src/components/editor.ts +22 -0
- package/packages/pi-tui/src/components/image.test.ts +10 -5
- package/packages/pi-tui/src/editor-component.ts +3 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/dist/rpc-client.test.js +101 -51
- package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/src/rpc-client.test.ts +109 -52
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/scripts/install.js +15 -1
- package/src/resources/extensions/browser-tools/capture.ts +12 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
- package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +75 -16
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
- package/src/resources/extensions/github-sync/templates.ts +151 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
- package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
- package/src/resources/extensions/google-search/index.ts +3 -2
- package/src/resources/extensions/gsd/auto/loop.ts +142 -2
- package/src/resources/extensions/gsd/auto/phases.ts +62 -38
- package/src/resources/extensions/gsd/auto/session.ts +7 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
- package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
- package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
- package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
- package/src/resources/extensions/gsd/auto-start.ts +127 -9
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
- package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
- package/src/resources/extensions/gsd/auto.ts +90 -23
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
- package/src/resources/extensions/gsd/component-loader.ts +598 -0
- package/src/resources/extensions/gsd/component-types.ts +362 -0
- package/src/resources/extensions/gsd/context-store.ts +25 -8
- package/src/resources/extensions/gsd/detection.ts +58 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/forensics.ts +118 -1
- package/src/resources/extensions/gsd/gate-registry.ts +2 -2
- package/src/resources/extensions/gsd/git-constants.ts +30 -1
- package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
- package/src/resources/extensions/gsd/git-service.ts +149 -2
- package/src/resources/extensions/gsd/gsd-db.ts +6 -3
- package/src/resources/extensions/gsd/guided-flow.ts +57 -14
- package/src/resources/extensions/gsd/journal.ts +11 -1
- package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
- package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
- package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
- package/src/resources/extensions/gsd/model-router.ts +6 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
- package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
- package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
- package/src/resources/extensions/gsd/service-tier.ts +5 -2
- package/src/resources/extensions/gsd/session-lock.ts +20 -10
- package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
- package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
- package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
- package/src/resources/extensions/gsd/state.ts +76 -66
- package/src/resources/extensions/gsd/sync-lock.ts +97 -39
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
- package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
- package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
- package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
- package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
- package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
- package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
- package/src/resources/extensions/gsd/types.ts +3 -3
- package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
- package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
- package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
- package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
- package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
- package/src/resources/extensions/gsd/uok/writer.ts +113 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
- package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
- package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
- package/src/resources/extensions/mcp-client/index.ts +3 -1
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
- package/src/resources/extensions/ollama/index.ts +5 -1
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
- package/src/resources/extensions/remote-questions/manager.ts +36 -4
- package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
- package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
- package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
- package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
- package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_ssgManifest.js +0 -0
|
@@ -1,281 +1,161 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
/**
|
|
2
|
+
* regex-hardening.test.ts — verifies production regexes accept both the
|
|
3
|
+
* legacy (M001) and unique (M001-abc123) milestone ID formats.
|
|
4
|
+
*
|
|
5
|
+
* The previous version of this file advertised 12 parser sites but
|
|
6
|
+
* only 3 tested imports (SLICE_BRANCH_RE, MILESTONE_ID_RE helpers).
|
|
7
|
+
* The remaining 9 sections (a, b, d, e, f) declared local `const
|
|
8
|
+
* *_RE = ...` copies of production regexes and asserted against the
|
|
9
|
+
* copies — a bug in the real regex would not fail those tests. See
|
|
10
|
+
* #4835.
|
|
11
|
+
*
|
|
12
|
+
* This rewrite imports every production pattern it exercises. Four
|
|
13
|
+
* call sites whose regexes are inline at the use site (state.ts:313
|
|
14
|
+
* title-strip, workspace-index.ts:80 title extraction, worktree-
|
|
15
|
+
* command.ts hasExistingMilestones, and the prompt dispatch regexes
|
|
16
|
+
* in index.ts) are intentionally NOT reimplemented here — they should
|
|
17
|
+
* be covered by behaviour tests of their parent functions, not by
|
|
18
|
+
* regex-copy assertions. A follow-up issue tracks extracting those
|
|
19
|
+
* regexes to a shared patterns module so they can be tested directly.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import test from "node:test";
|
|
23
|
+
import assert from "node:assert/strict";
|
|
15
24
|
|
|
16
25
|
import {
|
|
17
26
|
MILESTONE_ID_RE,
|
|
18
27
|
extractMilestoneSeq,
|
|
19
28
|
milestoneIdSort,
|
|
20
|
-
} from
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
import { createTestContext } from './test-helpers.ts';
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
27
|
-
// ─── Tests ─────────────────────────────────────────────────────────────────
|
|
28
|
-
|
|
29
|
-
async function main(): Promise<void> {
|
|
30
|
-
console.log('regex-hardening tests');
|
|
31
|
-
|
|
32
|
-
// (a) Directory scanning regex — used in state.ts, workspace-index.ts, files.ts
|
|
33
|
-
// Pattern: /^(M\d+(?:-[a-z0-9]{6})?)/
|
|
34
|
-
{
|
|
35
|
-
console.log(' (a) Directory scanning regex');
|
|
36
|
-
const DIR_SCAN_RE = /^(M\d+(?:-[a-z0-9]{6})?)/;
|
|
37
|
-
|
|
38
|
-
// Classic format matches
|
|
39
|
-
assertTrue(DIR_SCAN_RE.test('M001'), 'dir scan matches M001');
|
|
40
|
-
assertTrue(DIR_SCAN_RE.test('M042'), 'dir scan matches M042');
|
|
41
|
-
assertTrue(DIR_SCAN_RE.test('M999'), 'dir scan matches M999');
|
|
42
|
-
assertEq(('M001' as string).match(DIR_SCAN_RE)?.[1], 'M001', 'captures M001');
|
|
43
|
-
|
|
44
|
-
// Unique format matches
|
|
45
|
-
assertTrue(DIR_SCAN_RE.test('M001-abc123'), 'dir scan matches M001-abc123');
|
|
46
|
-
assertTrue(DIR_SCAN_RE.test('M042-z9a8b7'), 'dir scan matches M042-z9a8b7');
|
|
47
|
-
assertEq(('M001-abc123' as string).match(DIR_SCAN_RE)?.[1], 'M001-abc123', 'captures M001-abc123 from dir name');
|
|
48
|
-
|
|
49
|
-
// Rejects
|
|
50
|
-
assertTrue(!DIR_SCAN_RE.test('S01'), 'dir scan rejects S01');
|
|
51
|
-
assertTrue(!DIR_SCAN_RE.test('X001'), 'dir scan rejects X001');
|
|
52
|
-
assertTrue(!DIR_SCAN_RE.test('.DS_Store'), 'dir scan rejects .DS_Store');
|
|
53
|
-
assertTrue(!DIR_SCAN_RE.test('notes'), 'dir scan rejects notes');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// (b) Title-strip regex — used in state.ts, workspace-index.ts
|
|
57
|
-
// Pattern: /^M\d+(?:-[a-z0-9]{6})?[^:]*:\s*/
|
|
58
|
-
{
|
|
59
|
-
console.log(' (b) Title-strip regex');
|
|
60
|
-
const TITLE_STRIP_RE = /^M\d+(?:-[a-z0-9]{6})?[^:]*:\s*/;
|
|
61
|
-
|
|
62
|
-
// Classic format strip
|
|
63
|
-
assertEq('M001: Title'.replace(TITLE_STRIP_RE, ''), 'Title', 'strips M001: Title → Title');
|
|
64
|
-
assertEq('M042: Payment Integration'.replace(TITLE_STRIP_RE, ''), 'Payment Integration', 'strips M042: Payment Integration');
|
|
29
|
+
} from "../guided-flow.ts";
|
|
30
|
+
import { SLICE_BRANCH_RE } from "../worktree.ts";
|
|
31
|
+
import { MILESTONE_CONTEXT_RE } from "../bootstrap/write-gate.ts";
|
|
65
32
|
|
|
66
|
-
|
|
67
|
-
assertEq('M001-abc123: Title'.replace(TITLE_STRIP_RE, ''), 'Title', 'strips M001-abc123: Title → Title');
|
|
68
|
-
assertEq('M042-z9a8b7: Dashboard'.replace(TITLE_STRIP_RE, ''), 'Dashboard', 'strips M042-z9a8b7: Dashboard');
|
|
33
|
+
// ─── MILESTONE_ID_RE ──────────────────────────────────────────────────────
|
|
69
34
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
);
|
|
76
|
-
assertEq(
|
|
77
|
-
'M001-abc123: Foundation — Build Core'.replace(TITLE_STRIP_RE, ''),
|
|
78
|
-
'Foundation — Build Core',
|
|
79
|
-
'strips M001-abc123: prefix and preserves em dash in title body (unique format)',
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
// Edge case: dash-style separator (M001 — Title: Subtitle preserves colon in body)
|
|
83
|
-
assertEq(
|
|
84
|
-
'M001 — Unique Milestone IDs: Foo'.replace(TITLE_STRIP_RE, ''),
|
|
85
|
-
'Foo',
|
|
86
|
-
'strips M001 — Unique Milestone IDs: Foo → Foo (first colon consumed)',
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
// Edge case: colon inside title body preserved
|
|
90
|
-
assertEq(
|
|
91
|
-
'M001: Note: important'.replace(TITLE_STRIP_RE, ''),
|
|
92
|
-
'Note: important',
|
|
93
|
-
'preserves colons in title body',
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// No match — leaves non-milestone strings alone
|
|
97
|
-
assertEq('S01: Slice Title'.replace(TITLE_STRIP_RE, ''), 'S01: Slice Title', 'does not strip S01 prefix');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// (c) SLICE_BRANCH_RE — from worktree.ts
|
|
101
|
-
// Pattern: /^gsd\/(?:([a-zA-Z0-9_-]+)\/)?(M\d+(?:-[a-z0-9]{6})?)\/(S\d+)$/
|
|
102
|
-
{
|
|
103
|
-
console.log(' (c) SLICE_BRANCH_RE');
|
|
104
|
-
|
|
105
|
-
// Classic format — no worktree prefix
|
|
106
|
-
{
|
|
107
|
-
const m = 'gsd/M001/S01'.match(SLICE_BRANCH_RE);
|
|
108
|
-
assertTrue(m !== null, 'matches gsd/M001/S01');
|
|
109
|
-
assertEq(m?.[1], undefined, 'no worktree prefix for gsd/M001/S01');
|
|
110
|
-
assertEq(m?.[2], 'M001', 'captures M001');
|
|
111
|
-
assertEq(m?.[3], 'S01', 'captures S01');
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Unique format — no worktree prefix
|
|
115
|
-
{
|
|
116
|
-
const m = 'gsd/M001-abc123/S01'.match(SLICE_BRANCH_RE);
|
|
117
|
-
assertTrue(m !== null, 'matches gsd/M001-abc123/S01');
|
|
118
|
-
assertEq(m?.[1], undefined, 'no worktree prefix for unique format');
|
|
119
|
-
assertEq(m?.[2], 'M001-abc123', 'captures M001-abc123');
|
|
120
|
-
assertEq(m?.[3], 'S01', 'captures S01');
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Classic format — with worktree prefix
|
|
124
|
-
{
|
|
125
|
-
const m = 'gsd/worktree/M001/S01'.match(SLICE_BRANCH_RE);
|
|
126
|
-
assertTrue(m !== null, 'matches gsd/worktree/M001/S01');
|
|
127
|
-
assertEq(m?.[1], 'worktree', 'captures worktree prefix');
|
|
128
|
-
assertEq(m?.[2], 'M001', 'captures M001 with worktree');
|
|
129
|
-
assertEq(m?.[3], 'S01', 'captures S01 with worktree');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Unique format — with worktree prefix
|
|
133
|
-
{
|
|
134
|
-
const m = 'gsd/worktree/M001-abc123/S01'.match(SLICE_BRANCH_RE);
|
|
135
|
-
assertTrue(m !== null, 'matches gsd/worktree/M001-abc123/S01');
|
|
136
|
-
assertEq(m?.[1], 'worktree', 'captures worktree prefix with unique format');
|
|
137
|
-
assertEq(m?.[2], 'M001-abc123', 'captures M001-abc123 with worktree');
|
|
138
|
-
assertEq(m?.[3], 'S01', 'captures S01 with worktree and unique format');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Rejects
|
|
142
|
-
assertTrue(!SLICE_BRANCH_RE.test('gsd/S01'), 'rejects gsd/S01 (no milestone)');
|
|
143
|
-
assertTrue(!SLICE_BRANCH_RE.test('main'), 'rejects main');
|
|
144
|
-
assertTrue(!SLICE_BRANCH_RE.test('gsd/M001'), 'rejects gsd/M001 (no slice)');
|
|
145
|
-
assertTrue(!SLICE_BRANCH_RE.test('feature/M001/S01'), 'rejects feature/ prefix');
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// (d) Milestone detection regex — used in worktree-command.ts (hasExistingMilestones)
|
|
149
|
-
// Pattern: /^M\d+(?:-[a-z0-9]{6})?/
|
|
150
|
-
{
|
|
151
|
-
console.log(' (d) Milestone detection regex');
|
|
152
|
-
const MILESTONE_DETECT_RE = /^M\d+(?:-[a-z0-9]{6})?/;
|
|
35
|
+
test("MILESTONE_ID_RE accepts classic M001 format", () => {
|
|
36
|
+
assert.ok(MILESTONE_ID_RE.test("M001"));
|
|
37
|
+
assert.ok(MILESTONE_ID_RE.test("M042"));
|
|
38
|
+
assert.ok(MILESTONE_ID_RE.test("M999"));
|
|
39
|
+
});
|
|
153
40
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
41
|
+
test("MILESTONE_ID_RE accepts unique M001-abc123 format", () => {
|
|
42
|
+
assert.ok(MILESTONE_ID_RE.test("M001-abc123"));
|
|
43
|
+
assert.ok(MILESTONE_ID_RE.test("M042-z9a8b7"));
|
|
44
|
+
});
|
|
157
45
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
46
|
+
test("MILESTONE_ID_RE rejects non-milestone strings", () => {
|
|
47
|
+
assert.ok(!MILESTONE_ID_RE.test("S01"));
|
|
48
|
+
assert.ok(!MILESTONE_ID_RE.test("X001"));
|
|
49
|
+
assert.ok(!MILESTONE_ID_RE.test("notes"));
|
|
50
|
+
assert.ok(!MILESTONE_ID_RE.test(".DS_Store"));
|
|
51
|
+
assert.ok(!MILESTONE_ID_RE.test(""));
|
|
52
|
+
// Must be a bare id — not a prefix match.
|
|
53
|
+
assert.ok(!MILESTONE_ID_RE.test("M001-ABCDEF"), "uppercase suffix rejected");
|
|
54
|
+
assert.ok(!MILESTONE_ID_RE.test("M001 "), "trailing space rejected");
|
|
55
|
+
});
|
|
161
56
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
57
|
+
// ─── SLICE_BRANCH_RE ──────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
test("SLICE_BRANCH_RE captures milestone + slice without worktree prefix", () => {
|
|
60
|
+
for (const { input, expectMid } of [
|
|
61
|
+
{ input: "gsd/M001/S01", expectMid: "M001" },
|
|
62
|
+
{ input: "gsd/M001-abc123/S01", expectMid: "M001-abc123" },
|
|
63
|
+
]) {
|
|
64
|
+
const m = input.match(SLICE_BRANCH_RE);
|
|
65
|
+
assert.ok(m, `should match ${input}`);
|
|
66
|
+
assert.equal(m?.[1], undefined, "no worktree prefix");
|
|
67
|
+
assert.equal(m?.[2], expectMid);
|
|
68
|
+
assert.equal(m?.[3], "S01");
|
|
166
69
|
}
|
|
70
|
+
});
|
|
167
71
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// Unique format matches
|
|
179
|
-
assertTrue(CONTEXT_RE.test('M001-abc123-CONTEXT.md'), 'context matches M001-abc123-CONTEXT.md');
|
|
180
|
-
assertTrue(CONTEXT_RE.test('.gsd/milestones/M001-abc123/M001-abc123-CONTEXT.md'), 'context matches full path unique format');
|
|
181
|
-
|
|
182
|
-
// Rejects
|
|
183
|
-
assertTrue(!CONTEXT_RE.test('M001-ROADMAP.md'), 'context rejects M001-ROADMAP.md');
|
|
184
|
-
assertTrue(!CONTEXT_RE.test('M001-SUMMARY.md'), 'context rejects M001-SUMMARY.md');
|
|
185
|
-
assertTrue(!CONTEXT_RE.test('CONTEXT.md'), 'context rejects bare CONTEXT.md');
|
|
72
|
+
test("SLICE_BRANCH_RE captures worktree prefix when present", () => {
|
|
73
|
+
for (const { input, expectMid } of [
|
|
74
|
+
{ input: "gsd/worktree/M001/S01", expectMid: "M001" },
|
|
75
|
+
{ input: "gsd/worktree/M001-abc123/S01", expectMid: "M001-abc123" },
|
|
76
|
+
]) {
|
|
77
|
+
const m = input.match(SLICE_BRANCH_RE);
|
|
78
|
+
assert.ok(m, `should match ${input}`);
|
|
79
|
+
assert.equal(m?.[1], "worktree");
|
|
80
|
+
assert.equal(m?.[2], expectMid);
|
|
81
|
+
assert.equal(m?.[3], "S01");
|
|
186
82
|
}
|
|
83
|
+
});
|
|
187
84
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// Execute — classic format
|
|
195
|
-
{
|
|
196
|
-
const prompt = 'Execute the next task: T01 ("Write tests") in slice S01 of milestone M001';
|
|
197
|
-
const m = prompt.match(EXECUTE_RE);
|
|
198
|
-
assertTrue(m !== null, 'execute matches classic format');
|
|
199
|
-
assertEq(m?.[1], 'T01', 'execute captures T01');
|
|
200
|
-
assertEq(m?.[3], 'S01', 'execute captures S01');
|
|
201
|
-
assertEq(m?.[4], 'M001', 'execute captures M001');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Execute — unique format
|
|
205
|
-
{
|
|
206
|
-
const prompt = 'Execute the next task: T02 ("Build feature") in slice S03 of milestone M001-abc123';
|
|
207
|
-
const m = prompt.match(EXECUTE_RE);
|
|
208
|
-
assertTrue(m !== null, 'execute matches unique format');
|
|
209
|
-
assertEq(m?.[1], 'T02', 'execute captures T02 (unique format)');
|
|
210
|
-
assertEq(m?.[3], 'S03', 'execute captures S03 (unique format)');
|
|
211
|
-
assertEq(m?.[4], 'M001-abc123', 'execute captures M001-abc123');
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Resume — classic format
|
|
215
|
-
{
|
|
216
|
-
const prompt = 'Resume interrupted work.\nContinuing slice S02 of milestone M001';
|
|
217
|
-
const m = prompt.match(RESUME_RE);
|
|
218
|
-
assertTrue(m !== null, 'resume matches classic format');
|
|
219
|
-
assertEq(m?.[1], 'S02', 'resume captures S02');
|
|
220
|
-
assertEq(m?.[2], 'M001', 'resume captures M001');
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Resume — unique format
|
|
224
|
-
{
|
|
225
|
-
const prompt = 'Resume interrupted work.\nContinuing slice S01 of milestone M042-z9a8b7';
|
|
226
|
-
const m = prompt.match(RESUME_RE);
|
|
227
|
-
assertTrue(m !== null, 'resume matches unique format');
|
|
228
|
-
assertEq(m?.[1], 'S01', 'resume captures S01 (unique format)');
|
|
229
|
-
assertEq(m?.[2], 'M042-z9a8b7', 'resume captures M042-z9a8b7');
|
|
230
|
-
}
|
|
231
|
-
}
|
|
85
|
+
test("SLICE_BRANCH_RE rejects malformed inputs", () => {
|
|
86
|
+
assert.ok(!SLICE_BRANCH_RE.test("gsd/S01"), "no milestone");
|
|
87
|
+
assert.ok(!SLICE_BRANCH_RE.test("main"), "non-gsd branch");
|
|
88
|
+
assert.ok(!SLICE_BRANCH_RE.test("gsd/M001"), "no slice");
|
|
89
|
+
assert.ok(!SLICE_BRANCH_RE.test("feature/M001/S01"), "wrong prefix");
|
|
90
|
+
});
|
|
232
91
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
92
|
+
// ─── MILESTONE_CONTEXT_RE ────────────────────────────────────────────────
|
|
93
|
+
|
|
94
|
+
test("MILESTONE_CONTEXT_RE matches legacy and unique CONTEXT.md names", () => {
|
|
95
|
+
assert.ok(MILESTONE_CONTEXT_RE.test("M001-CONTEXT.md"));
|
|
96
|
+
assert.ok(MILESTONE_CONTEXT_RE.test("M001-abc123-CONTEXT.md"));
|
|
97
|
+
assert.ok(
|
|
98
|
+
MILESTONE_CONTEXT_RE.test(".gsd/milestones/M001/M001-CONTEXT.md"),
|
|
99
|
+
"full path legacy format",
|
|
100
|
+
);
|
|
101
|
+
assert.ok(
|
|
102
|
+
MILESTONE_CONTEXT_RE.test(".gsd/milestones/M001-abc123/M001-abc123-CONTEXT.md"),
|
|
103
|
+
"full path unique format",
|
|
104
|
+
);
|
|
105
|
+
});
|
|
239
106
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
107
|
+
test("MILESTONE_CONTEXT_RE rejects non-CONTEXT artifact names", () => {
|
|
108
|
+
assert.ok(!MILESTONE_CONTEXT_RE.test("M001-ROADMAP.md"));
|
|
109
|
+
assert.ok(!MILESTONE_CONTEXT_RE.test("M001-SUMMARY.md"));
|
|
110
|
+
assert.ok(!MILESTONE_CONTEXT_RE.test("CONTEXT.md"), "bare name without milestone prefix");
|
|
111
|
+
});
|
|
244
112
|
|
|
245
|
-
|
|
246
|
-
const oldOnly = ['M003', 'M001', 'M002'];
|
|
247
|
-
assertEq([...oldOnly].sort(milestoneIdSort), ['M001', 'M002', 'M003'], 'sorts classic-format IDs');
|
|
113
|
+
// ─── extractMilestoneSeq ──────────────────────────────────────────────────
|
|
248
114
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
115
|
+
test("extractMilestoneSeq returns numeric sequence for both formats", () => {
|
|
116
|
+
assert.equal(extractMilestoneSeq("M001"), 1);
|
|
117
|
+
assert.equal(extractMilestoneSeq("M042"), 42);
|
|
118
|
+
assert.equal(extractMilestoneSeq("M999"), 999);
|
|
119
|
+
assert.equal(extractMilestoneSeq("M001-abc123"), 1);
|
|
120
|
+
assert.equal(extractMilestoneSeq("M042-z9a8b7"), 42);
|
|
121
|
+
assert.equal(extractMilestoneSeq("M100-xyz789"), 100);
|
|
122
|
+
});
|
|
253
123
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
124
|
+
test("extractMilestoneSeq returns 0 (not NaN) for invalid inputs", () => {
|
|
125
|
+
assert.equal(extractMilestoneSeq(""), 0);
|
|
126
|
+
assert.equal(extractMilestoneSeq("notes"), 0);
|
|
127
|
+
assert.equal(extractMilestoneSeq("S01"), 0);
|
|
128
|
+
// Specific regression: the parseInt(slice(1)) implementation returned
|
|
129
|
+
// NaN on inputs like "M001-abc123" because parseInt stopped at the
|
|
130
|
+
// dash but then the rest of the logic treated the result as a number.
|
|
131
|
+
// Current impl returns a real number.
|
|
132
|
+
assert.ok(!Number.isNaN(extractMilestoneSeq("M001-abc123")));
|
|
133
|
+
});
|
|
257
134
|
|
|
258
|
-
|
|
259
|
-
assertEq(extractMilestoneSeq('M001'), 1, 'M001 → 1');
|
|
260
|
-
assertEq(extractMilestoneSeq('M042'), 42, 'M042 → 42');
|
|
261
|
-
assertEq(extractMilestoneSeq('M999'), 999, 'M999 → 999');
|
|
135
|
+
// ─── milestoneIdSort ──────────────────────────────────────────────────────
|
|
262
136
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
137
|
+
test("milestoneIdSort orders by numeric sequence across both formats", () => {
|
|
138
|
+
const mixed = ["M002-abc123", "M001", "M001-xyz789"];
|
|
139
|
+
assert.deepEqual(
|
|
140
|
+
[...mixed].sort(milestoneIdSort),
|
|
141
|
+
["M001", "M001-xyz789", "M002-abc123"],
|
|
142
|
+
"mixed formats sort by seq number",
|
|
143
|
+
);
|
|
267
144
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
assertEq(extractMilestoneSeq('notes'), 0, 'notes → 0');
|
|
271
|
-
assertEq(extractMilestoneSeq('S01'), 0, 'S01 → 0');
|
|
272
|
-
assertTrue(!Number.isNaN(extractMilestoneSeq('M001-abc123')), 'unique format does not return NaN');
|
|
273
|
-
assertTrue(!Number.isNaN(extractMilestoneSeq('M001-ABCDEF')), 'invalid format does not return NaN');
|
|
274
|
-
}
|
|
145
|
+
const legacy = ["M003", "M001", "M002"];
|
|
146
|
+
assert.deepEqual([...legacy].sort(milestoneIdSort), ["M001", "M002", "M003"]);
|
|
275
147
|
|
|
276
|
-
|
|
277
|
-
|
|
148
|
+
const unique = ["M003-abc123", "M001-def456", "M002-ghi789"];
|
|
149
|
+
assert.deepEqual(
|
|
150
|
+
[...unique].sort(milestoneIdSort),
|
|
151
|
+
["M001-def456", "M002-ghi789", "M003-abc123"],
|
|
152
|
+
);
|
|
153
|
+
});
|
|
278
154
|
|
|
279
|
-
test(
|
|
280
|
-
|
|
155
|
+
test("milestoneIdSort preserves input order for same-sequence ids", () => {
|
|
156
|
+
// sort is stable per ECMAScript 2019+ when the comparator returns 0.
|
|
157
|
+
const sameSeq = ["M001-abc123", "M001"];
|
|
158
|
+
const sorted = [...sameSeq].sort(milestoneIdSort);
|
|
159
|
+
assert.equal(sorted[0], "M001-abc123");
|
|
160
|
+
assert.equal(sorted[1], "M001");
|
|
281
161
|
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// GSD-2 — #4782 phase 3 batch 2: research-milestone migrated through composer.
|
|
2
|
+
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
|
|
9
|
+
import { buildResearchMilestonePrompt } from "../auto-prompts.ts";
|
|
10
|
+
import { invalidateAllCaches } from "../cache.ts";
|
|
11
|
+
import {
|
|
12
|
+
openDatabase,
|
|
13
|
+
closeDatabase,
|
|
14
|
+
insertMilestone,
|
|
15
|
+
upsertMilestonePlanning,
|
|
16
|
+
insertArtifact,
|
|
17
|
+
} from "../gsd-db.ts";
|
|
18
|
+
|
|
19
|
+
function makeBase(): string {
|
|
20
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-research-ms-composer-"));
|
|
21
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
22
|
+
return base;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function cleanup(base: string): void {
|
|
26
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
27
|
+
invalidateAllCaches();
|
|
28
|
+
rmSync(base, { recursive: true, force: true });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function seed(base: string, mid: string): void {
|
|
32
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
33
|
+
insertMilestone({ id: mid, title: "Research Test", status: "active", depends_on: [] });
|
|
34
|
+
upsertMilestonePlanning(mid, {
|
|
35
|
+
title: "Research Test",
|
|
36
|
+
status: "active",
|
|
37
|
+
vision: "Research composer migration",
|
|
38
|
+
successCriteria: ["Prompt compiles"],
|
|
39
|
+
keyRisks: [],
|
|
40
|
+
proofStrategy: [],
|
|
41
|
+
verificationContract: "",
|
|
42
|
+
verificationIntegration: "",
|
|
43
|
+
verificationOperational: "",
|
|
44
|
+
verificationUat: "",
|
|
45
|
+
definitionOfDone: [],
|
|
46
|
+
requirementCoverage: "",
|
|
47
|
+
boundaryMapMarkdown: "",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
test("#4782 phase 3: buildResearchMilestonePrompt emits milestone-context then research template via composer", async (t) => {
|
|
52
|
+
const base = makeBase();
|
|
53
|
+
t.after(() => cleanup(base));
|
|
54
|
+
invalidateAllCaches();
|
|
55
|
+
|
|
56
|
+
seed(base, "M001");
|
|
57
|
+
|
|
58
|
+
writeFileSync(
|
|
59
|
+
join(base, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
|
|
60
|
+
"# M001 Context\n\nA research test milestone.\n",
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const prompt = await buildResearchMilestonePrompt("M001", "Research Test", base);
|
|
64
|
+
|
|
65
|
+
// Context wrapper present
|
|
66
|
+
assert.match(prompt, /## Inlined Context \(preloaded — do not re-read these files\)/);
|
|
67
|
+
|
|
68
|
+
// Milestone context inlined first (manifest order)
|
|
69
|
+
assert.match(prompt, /### Milestone Context/);
|
|
70
|
+
assert.match(prompt, /A research test milestone/);
|
|
71
|
+
|
|
72
|
+
// Research template inlined as the templates artifact
|
|
73
|
+
assert.match(prompt, /### Output Template: Research/);
|
|
74
|
+
|
|
75
|
+
// Ordering: milestone-context precedes the research template
|
|
76
|
+
const contextIdx = prompt.indexOf("### Milestone Context");
|
|
77
|
+
const researchIdx = prompt.indexOf("### Output Template: Research");
|
|
78
|
+
assert.ok(contextIdx > -1 && researchIdx > contextIdx,
|
|
79
|
+
`milestone-context (${contextIdx}) must precede research template (${researchIdx})`);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("#4782 phase 3: buildResearchMilestonePrompt preserves manifest order across optional artifacts (#4925 review)", async (t) => {
|
|
83
|
+
const base = makeBase();
|
|
84
|
+
t.after(() => cleanup(base));
|
|
85
|
+
invalidateAllCaches();
|
|
86
|
+
|
|
87
|
+
seed(base, "M001");
|
|
88
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-CONTEXT.md"), "# M001 Context\n");
|
|
89
|
+
// Seed PROJECT.md into the artifacts table so inlineProjectFromDb resolves
|
|
90
|
+
// to a non-null body. Lets us verify the project block sits between
|
|
91
|
+
// milestone-context and the templates block per manifest order.
|
|
92
|
+
insertArtifact({
|
|
93
|
+
path: "PROJECT.md",
|
|
94
|
+
artifact_type: "project",
|
|
95
|
+
milestone_id: null,
|
|
96
|
+
slice_id: null,
|
|
97
|
+
task_id: null,
|
|
98
|
+
full_content: "# Project\n\nResearch composer fixture project.\n",
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const prompt = await buildResearchMilestonePrompt("M001", "Research Test", base);
|
|
102
|
+
|
|
103
|
+
// Manifest-declared order: milestone-context, project, requirements, decisions, templates.
|
|
104
|
+
const contextIdx = prompt.indexOf("### Milestone Context");
|
|
105
|
+
const projectIdx = prompt.indexOf("### Project");
|
|
106
|
+
const researchIdx = prompt.indexOf("### Output Template: Research");
|
|
107
|
+
assert.ok(contextIdx > -1, "milestone-context block missing");
|
|
108
|
+
assert.ok(projectIdx > -1, "project block missing — seed should have populated it");
|
|
109
|
+
assert.ok(researchIdx > -1, "research template block missing");
|
|
110
|
+
assert.ok(
|
|
111
|
+
contextIdx < projectIdx && projectIdx < researchIdx,
|
|
112
|
+
`manifest order violated: milestone-context (${contextIdx}) < project (${projectIdx}) < research-template (${researchIdx})`,
|
|
113
|
+
);
|
|
114
|
+
});
|
|
@@ -13,6 +13,7 @@ import { describe, it } from 'node:test'
|
|
|
13
13
|
import assert from 'node:assert/strict'
|
|
14
14
|
import { readFileSync } from 'node:fs'
|
|
15
15
|
import { resolve } from 'node:path'
|
|
16
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
16
17
|
|
|
17
18
|
const src = readFileSync(
|
|
18
19
|
resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'guided-flow.ts'),
|
|
@@ -37,7 +38,7 @@ describe('restore tools after discuss flow scoping (#3628)', () => {
|
|
|
37
38
|
assert.ok(discussCheck !== -1)
|
|
38
39
|
|
|
39
40
|
// Look for savedTools assignment within the discuss block
|
|
40
|
-
const blockAfter = src
|
|
41
|
+
const blockAfter = extractSourceRegion(src, 'if (unitType?.startsWith("discuss-"))')
|
|
41
42
|
assert.ok(
|
|
42
43
|
blockAfter.includes('savedTools = currentTools'),
|
|
43
44
|
'savedTools must be assigned from currentTools inside the discuss block',
|
|
@@ -55,8 +56,10 @@ describe('restore tools after discuss flow scoping (#3628)', () => {
|
|
|
55
56
|
const sendMsg = src.indexOf('triggerTurn: true', savedToolsAssign)
|
|
56
57
|
assert.ok(sendMsg !== -1, 'discuss-flow sendMessage with triggerTurn must exist after savedTools capture')
|
|
57
58
|
|
|
58
|
-
// After sendMessage, savedTools should be restored via setActiveTools
|
|
59
|
-
|
|
59
|
+
// After sendMessage, savedTools should be restored via setActiveTools.
|
|
60
|
+
// Use fromIdx to anchor at the discuss-flow sendMessage, not the first
|
|
61
|
+
// triggerTurn: true occurrence in the file.
|
|
62
|
+
const afterSend = extractSourceRegion(src, 'triggerTurn: true', { fromIdx: savedToolsAssign })
|
|
60
63
|
assert.ok(
|
|
61
64
|
afterSend.includes('if (savedTools)'),
|
|
62
65
|
'savedTools restoration guard must exist after sendMessage',
|