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
|
@@ -2,6 +2,7 @@ import test from "node:test";
|
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
5
6
|
|
|
6
7
|
const autoSrc = readFileSync(join(import.meta.dirname, "..", "auto.ts"), "utf-8");
|
|
7
8
|
const phasesSrc = readFileSync(join(import.meta.dirname, "..", "auto", "phases.ts"), "utf-8");
|
|
@@ -20,7 +21,7 @@ test("stopAuto restores original thinking level", () => {
|
|
|
20
21
|
test("runUnitPhase threads captured thinking level into selectAndApplyModel", () => {
|
|
21
22
|
const callIdx = phasesSrc.indexOf("deps.selectAndApplyModel(");
|
|
22
23
|
assert.ok(callIdx > -1, "phases.ts should call selectAndApplyModel");
|
|
23
|
-
const callBlock = phasesSrc.
|
|
24
|
+
const callBlock = extractSourceRegion(phasesSrc, "deps.selectAndApplyModel(");
|
|
24
25
|
assert.ok(
|
|
25
26
|
callBlock.includes("s.autoModeStartThinkingLevel"),
|
|
26
27
|
"runUnitPhase should pass autoModeStartThinkingLevel to selectAndApplyModel",
|
|
@@ -30,7 +31,7 @@ test("runUnitPhase threads captured thinking level into selectAndApplyModel", ()
|
|
|
30
31
|
test("hook model override preserves captured thinking level", () => {
|
|
31
32
|
const hookIdx = phasesSrc.indexOf("const hookModelOverride = sidecarItem?.model ?? iterData.hookModelOverride;");
|
|
32
33
|
assert.ok(hookIdx > -1, "phases.ts should include hook model override handling");
|
|
33
|
-
const hookBlock = phasesSrc
|
|
34
|
+
const hookBlock = extractSourceRegion(phasesSrc, "const hookModelOverride = sidecarItem?.model ?? iterData.hookModelOverride;");
|
|
34
35
|
assert.ok(
|
|
35
36
|
hookBlock.includes("pi.setThinkingLevel(s.autoModeStartThinkingLevel)"),
|
|
36
37
|
"hook model override should re-apply captured thinking level after setModel",
|
|
@@ -27,6 +27,7 @@ import { readFileSync } from "node:fs";
|
|
|
27
27
|
import { join } from "node:path";
|
|
28
28
|
|
|
29
29
|
import { buildFlatRateContext } from "../auto-model-selection.ts";
|
|
30
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
30
31
|
|
|
31
32
|
// ─── Bug 2: this-binding regression ─────────────────────────────────────
|
|
32
33
|
|
|
@@ -69,7 +70,7 @@ test("isSamePath short-circuits ENOENT before logging a warning", () => {
|
|
|
69
70
|
assert.ok(fnIdx !== -1, "isSamePath function exists");
|
|
70
71
|
|
|
71
72
|
// Grab the function body (enough to cover the catch block).
|
|
72
|
-
const fnBody = src
|
|
73
|
+
const fnBody = extractSourceRegion(src, "function isSamePath", { fromIdx: fnIdx });
|
|
73
74
|
|
|
74
75
|
const catchIdx = fnBody.indexOf("catch");
|
|
75
76
|
assert.ok(catchIdx !== -1, "isSamePath has a catch block");
|
|
@@ -103,7 +104,7 @@ test("checkAutoStartAfterDiscuss guards DISCUSSION-MANIFEST.json unlink with exi
|
|
|
103
104
|
|
|
104
105
|
// Everything from the comment to a short distance below should contain
|
|
105
106
|
// the existsSync guard before the unlinkSync call.
|
|
106
|
-
const block = src
|
|
107
|
+
const block = extractSourceRegion(src, "remove discussion manifest after auto-start", { fromIdx: cleanupIdx });
|
|
107
108
|
|
|
108
109
|
const existsIdx = block.indexOf("existsSync(manifestPath)");
|
|
109
110
|
const unlinkIdx = block.indexOf("unlinkSync(manifestPath)");
|
|
@@ -2,6 +2,7 @@ import { describe, test } from "node:test";
|
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
5
6
|
|
|
6
7
|
const systemContextSrc = readFileSync(
|
|
7
8
|
join(import.meta.dirname, "..", "bootstrap", "system-context.ts"),
|
|
@@ -29,7 +30,7 @@ describe("bootstrap deriveState DB guards (#3844)", () => {
|
|
|
29
30
|
test("register-hooks opens DB before deriveState in session_before_compact", () => {
|
|
30
31
|
const compactIdx = registerHooksSrc.indexOf('pi.on("session_before_compact"');
|
|
31
32
|
assert.ok(compactIdx > -1, "register-hooks should define session_before_compact");
|
|
32
|
-
const compactSection = registerHooksSrc.
|
|
33
|
+
const compactSection = extractSourceRegion(registerHooksSrc, 'pi.on("session_before_compact"');
|
|
33
34
|
const ensureIdx = compactSection.indexOf("ensureDbOpen()");
|
|
34
35
|
const deriveIdx = compactSection.indexOf("deriveState(basePath)");
|
|
35
36
|
assert.ok(ensureIdx > -1, "session_before_compact should call ensureDbOpen()");
|
|
@@ -69,11 +69,11 @@ describe("cache-staleness-regression", () => {
|
|
|
69
69
|
].join('\n');
|
|
70
70
|
writeMilestoneFile(base, 'M001', 'ROADMAP', roadmap);
|
|
71
71
|
|
|
72
|
-
// Step 3:
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
//
|
|
72
|
+
// Step 3: Explicit invalidation — this is the #1240 fix path. We
|
|
73
|
+
// do NOT rely on the 100ms TTL here; the production code calls
|
|
74
|
+
// invalidateAllCaches() / invalidateStateCache() immediately after
|
|
75
|
+
// writing planning files, so the next deriveState() must see the
|
|
76
|
+
// new roadmap without any wall-clock wait.
|
|
77
77
|
invalidateAllCaches();
|
|
78
78
|
invalidateStateCache();
|
|
79
79
|
const state2 = await deriveState(base);
|
|
@@ -100,10 +100,8 @@ describe("cache-staleness-regression", () => {
|
|
|
100
100
|
// Simulate: discussion completes, CONTEXT.md is written
|
|
101
101
|
writeMilestoneFile(base, 'M001', 'CONTEXT', '# M001: Test\n\nFull context after discussion.\n');
|
|
102
102
|
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// Without invalidation, we'd still see 'needs-discussion'
|
|
103
|
+
// Explicit invalidation is the production fix path for #1249 —
|
|
104
|
+
// no wall-clock wait needed.
|
|
107
105
|
invalidateAllCaches();
|
|
108
106
|
invalidateStateCache();
|
|
109
107
|
const state2 = await deriveState(base);
|
|
@@ -116,7 +114,7 @@ describe("cache-staleness-regression", () => {
|
|
|
116
114
|
}
|
|
117
115
|
});
|
|
118
116
|
|
|
119
|
-
test("state cache TTL:
|
|
117
|
+
test("state cache TTL: within window returns cached; past window re-derives", async () => {
|
|
120
118
|
const base = createBase();
|
|
121
119
|
try {
|
|
122
120
|
writeMilestoneFile(base, 'M001', 'CONTEXT', '# M001\n\nDesc.\n');
|
|
@@ -126,7 +124,7 @@ describe("cache-staleness-regression", () => {
|
|
|
126
124
|
const state1 = await deriveState(base);
|
|
127
125
|
assert.strictEqual(state1.phase, 'pre-planning', 'initial: pre-planning');
|
|
128
126
|
|
|
129
|
-
// Write roadmap immediately
|
|
127
|
+
// Write roadmap immediately — no invalidation
|
|
130
128
|
writeMilestoneFile(base, 'M001', 'ROADMAP', [
|
|
131
129
|
'# M001: Test',
|
|
132
130
|
'',
|
|
@@ -136,18 +134,19 @@ describe("cache-staleness-regression", () => {
|
|
|
136
134
|
'',
|
|
137
135
|
].join('\n'));
|
|
138
136
|
|
|
139
|
-
//
|
|
137
|
+
// Within the TTL window, deriveState() must return the cached
|
|
138
|
+
// pre-planning state — this is the "cached" half of the TTL
|
|
139
|
+
// contract and the reason invalidateStateCache() exists.
|
|
140
140
|
const state2 = await deriveState(base);
|
|
141
|
-
|
|
141
|
+
assert.strictEqual(state2.phase, 'pre-planning', 'within TTL: cached pre-planning is returned');
|
|
142
142
|
|
|
143
|
-
//
|
|
143
|
+
// Past the TTL + explicit parse-cache flush, the fresh derive must
|
|
144
|
+
// see the new roadmap. invalidateAllCaches() is required because
|
|
145
|
+
// the file-parse cache is independent of the state TTL.
|
|
144
146
|
await new Promise(r => setTimeout(r, 150));
|
|
145
|
-
|
|
146
|
-
// ALSO invalidate parse cache (not just state cache)
|
|
147
147
|
invalidateAllCaches();
|
|
148
|
-
invalidateStateCache();
|
|
149
148
|
const state3 = await deriveState(base);
|
|
150
|
-
assert.strictEqual(state3.phase, 'planning', '
|
|
149
|
+
assert.strictEqual(state3.phase, 'planning', 'past TTL: re-derive sees new roadmap');
|
|
151
150
|
} finally {
|
|
152
151
|
cleanup(base);
|
|
153
152
|
}
|
|
@@ -194,7 +193,6 @@ describe("cache-staleness-regression", () => {
|
|
|
194
193
|
'- [ ] **T02: Second Task** `est:1h`',
|
|
195
194
|
].join('\n'));
|
|
196
195
|
|
|
197
|
-
await new Promise(r => setTimeout(r, 150));
|
|
198
196
|
invalidateAllCaches();
|
|
199
197
|
invalidateStateCache();
|
|
200
198
|
const state2 = await deriveState(base);
|
|
@@ -242,7 +240,6 @@ describe("cache-staleness-regression", () => {
|
|
|
242
240
|
'- [x] **T01: Task** `est:1h`',
|
|
243
241
|
].join('\n'));
|
|
244
242
|
|
|
245
|
-
await new Promise(r => setTimeout(r, 150));
|
|
246
243
|
invalidateAllCaches();
|
|
247
244
|
invalidateStateCache();
|
|
248
245
|
const state2 = await deriveState(base);
|
|
@@ -282,7 +279,6 @@ describe("cache-staleness-regression", () => {
|
|
|
282
279
|
'',
|
|
283
280
|
].join('\n'));
|
|
284
281
|
|
|
285
|
-
await new Promise(r => setTimeout(r, 150));
|
|
286
282
|
invalidateAllCaches();
|
|
287
283
|
invalidateStateCache();
|
|
288
284
|
const state2 = await deriveState(base);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for resolveCanonicalMilestoneRoot — the worktree-aware reader
|
|
3
|
+
* that fixes #4761 (worktree work stranded when auto-loop exits without
|
|
4
|
+
* milestone completion).
|
|
5
|
+
*
|
|
6
|
+
* Contract: given (basePath, milestoneId), return the worktree path if a
|
|
7
|
+
* live git worktree exists for that milestone at .gsd/worktrees/<MID>/;
|
|
8
|
+
* otherwise return basePath unchanged. A live worktree has a .git file
|
|
9
|
+
* (not directory) — a bare directory without .git is a stale leftover.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import test from "node:test";
|
|
13
|
+
import assert from "node:assert/strict";
|
|
14
|
+
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { tmpdir } from "node:os";
|
|
17
|
+
import { randomUUID } from "node:crypto";
|
|
18
|
+
|
|
19
|
+
import { resolveCanonicalMilestoneRoot } from "../worktree-manager.ts";
|
|
20
|
+
|
|
21
|
+
function makeTmpBase(): string {
|
|
22
|
+
const base = join(tmpdir(), `gsd-canon-test-${randomUUID()}`);
|
|
23
|
+
mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
|
|
24
|
+
return base;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function cleanup(base: string): void {
|
|
28
|
+
try { rmSync(base, { recursive: true, force: true }); } catch { /* */ }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create a worktree directory shape that looks live: the .gsd/worktrees/<MID>/
|
|
33
|
+
* directory with a .git file containing a gitdir: pointer. We don't need a
|
|
34
|
+
* real git worktree — the resolver only checks for the .git file's presence.
|
|
35
|
+
*/
|
|
36
|
+
function makeLiveWorktree(base: string, mid: string): string {
|
|
37
|
+
const wtPath = join(base, ".gsd", "worktrees", mid);
|
|
38
|
+
mkdirSync(wtPath, { recursive: true });
|
|
39
|
+
writeFileSync(
|
|
40
|
+
join(wtPath, ".git"),
|
|
41
|
+
`gitdir: ${join(base, ".git", "worktrees", mid)}\n`,
|
|
42
|
+
);
|
|
43
|
+
return wtPath;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function makeStaleWorktree(base: string, mid: string): string {
|
|
47
|
+
const wtPath = join(base, ".gsd", "worktrees", mid);
|
|
48
|
+
mkdirSync(wtPath, { recursive: true });
|
|
49
|
+
// No .git file — this is the stale-leftover shape createWorktree() sees
|
|
50
|
+
// and cleans up.
|
|
51
|
+
return wtPath;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
test("returns worktree path when a live worktree exists for the milestone", () => {
|
|
55
|
+
const base = makeTmpBase();
|
|
56
|
+
try {
|
|
57
|
+
const wtPath = makeLiveWorktree(base, "M001");
|
|
58
|
+
const result = resolveCanonicalMilestoneRoot(base, "M001");
|
|
59
|
+
assert.equal(result, wtPath);
|
|
60
|
+
} finally {
|
|
61
|
+
cleanup(base);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("returns basePath when no worktree directory exists", () => {
|
|
66
|
+
const base = makeTmpBase();
|
|
67
|
+
try {
|
|
68
|
+
const result = resolveCanonicalMilestoneRoot(base, "M001");
|
|
69
|
+
assert.equal(result, base);
|
|
70
|
+
} finally {
|
|
71
|
+
cleanup(base);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("returns basePath when worktree directory exists but has no .git file (stale)", () => {
|
|
76
|
+
const base = makeTmpBase();
|
|
77
|
+
try {
|
|
78
|
+
makeStaleWorktree(base, "M001");
|
|
79
|
+
const result = resolveCanonicalMilestoneRoot(base, "M001");
|
|
80
|
+
assert.equal(result, base);
|
|
81
|
+
} finally {
|
|
82
|
+
cleanup(base);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("returns basePath for invalid milestoneId (path separators)", () => {
|
|
87
|
+
const base = makeTmpBase();
|
|
88
|
+
try {
|
|
89
|
+
// Even if a worktree coincidentally exists, the guard should reject.
|
|
90
|
+
assert.equal(resolveCanonicalMilestoneRoot(base, "../evil"), base);
|
|
91
|
+
assert.equal(resolveCanonicalMilestoneRoot(base, "M001/subdir"), base);
|
|
92
|
+
assert.equal(resolveCanonicalMilestoneRoot(base, "M001\\subdir"), base);
|
|
93
|
+
assert.equal(resolveCanonicalMilestoneRoot(base, ""), base);
|
|
94
|
+
} finally {
|
|
95
|
+
cleanup(base);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("only returns the worktree for the requested milestone, not siblings", () => {
|
|
100
|
+
const base = makeTmpBase();
|
|
101
|
+
try {
|
|
102
|
+
makeLiveWorktree(base, "M001");
|
|
103
|
+
const result = resolveCanonicalMilestoneRoot(base, "M002");
|
|
104
|
+
assert.equal(result, base, "M002 has no worktree → basePath");
|
|
105
|
+
} finally {
|
|
106
|
+
cleanup(base);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
// GSD-2 — #4780: slice-summary excerpts replace full inlining in
|
|
2
|
+
// buildCompleteMilestonePrompt. Verify (a) the excerpt helper emits
|
|
3
|
+
// frontmatter fields + section heads + on-demand path, (b) the closer
|
|
4
|
+
// prompt lists all slice SUMMARY paths under "On-demand Slice Summaries",
|
|
5
|
+
// (c) regression on prompt size.
|
|
6
|
+
|
|
7
|
+
import test from "node:test";
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
|
|
13
|
+
import { buildSliceSummaryExcerpt, buildCompleteMilestonePrompt } from "../auto-prompts.ts";
|
|
14
|
+
import { invalidateAllCaches } from "../cache.ts";
|
|
15
|
+
|
|
16
|
+
// ─── Fixture helpers ──────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
function createBase(): string {
|
|
19
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-cm-excerpt-"));
|
|
20
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
21
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S02", "tasks"), { recursive: true });
|
|
22
|
+
return base;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function cleanup(base: string): void {
|
|
26
|
+
rmSync(base, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function writeRoadmap(base: string, content: string): void {
|
|
30
|
+
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), content);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function writeSummary(base: string, sid: string, content: string): void {
|
|
34
|
+
writeFileSync(
|
|
35
|
+
join(base, ".gsd", "milestones", "M001", "slices", sid, `${sid}-SUMMARY.md`),
|
|
36
|
+
content,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// A summary with enough body narrative that full inlining would balloon the
|
|
41
|
+
// prompt. The excerpt should keep frontmatter + sections but drop the
|
|
42
|
+
// "What Happened" narrative.
|
|
43
|
+
function makeFatSummary(sid: string): string {
|
|
44
|
+
const narrativePara =
|
|
45
|
+
"The team discovered several subtle integration issues, traced them to the cache layer, and produced a patch set that threads the cache key through every call site. ".repeat(20);
|
|
46
|
+
return [
|
|
47
|
+
"---",
|
|
48
|
+
`id: ${sid}`,
|
|
49
|
+
"parent: M001",
|
|
50
|
+
"milestone: M001",
|
|
51
|
+
"provides:",
|
|
52
|
+
" - compact slice-summary excerpts",
|
|
53
|
+
" - on-demand read path registry",
|
|
54
|
+
"affects:",
|
|
55
|
+
" - complete-milestone prompt builder",
|
|
56
|
+
"key_decisions:",
|
|
57
|
+
" - use parseSummary for frontmatter extraction",
|
|
58
|
+
" - fall back to full inline when frontmatter fails",
|
|
59
|
+
"patterns_established:",
|
|
60
|
+
" - excerpt-first inlining for closer units",
|
|
61
|
+
"key_files:",
|
|
62
|
+
" - src/resources/extensions/gsd/auto-prompts.ts",
|
|
63
|
+
"duration: 1h",
|
|
64
|
+
"verification_result: passed",
|
|
65
|
+
"completed_at: 2026-04-24",
|
|
66
|
+
"blocker_discovered: false",
|
|
67
|
+
"---",
|
|
68
|
+
"",
|
|
69
|
+
`# ${sid}: Slice summary`,
|
|
70
|
+
"**Short one-liner for the slice**",
|
|
71
|
+
"",
|
|
72
|
+
"## What Happened",
|
|
73
|
+
"",
|
|
74
|
+
narrativePara,
|
|
75
|
+
"",
|
|
76
|
+
"## Deviations",
|
|
77
|
+
"",
|
|
78
|
+
"Extended the excerpt helper scope at review time.",
|
|
79
|
+
"",
|
|
80
|
+
"## Known Limitations",
|
|
81
|
+
"",
|
|
82
|
+
"Does not yet cover validate-milestone — follow-up.",
|
|
83
|
+
"",
|
|
84
|
+
"## Follow-ups",
|
|
85
|
+
"",
|
|
86
|
+
"- Wire the same excerpt into buildValidateMilestonePrompt",
|
|
87
|
+
].join("\n");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function makeRoadmap(): string {
|
|
91
|
+
return [
|
|
92
|
+
"# M001 Roadmap",
|
|
93
|
+
"## Slices",
|
|
94
|
+
"- [x] **S01: Excerpt helper** `risk:medium` `depends:[]`",
|
|
95
|
+
"- [x] **S02: Closer wiring** `risk:low` `depends:[S01]`",
|
|
96
|
+
].join("\n");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ─── buildSliceSummaryExcerpt unit tests ──────────────────────────────────
|
|
100
|
+
|
|
101
|
+
test("#4780 excerpt: emits compact block with frontmatter fields + section heads", async (t) => {
|
|
102
|
+
const base = createBase();
|
|
103
|
+
t.after(() => cleanup(base));
|
|
104
|
+
invalidateAllCaches();
|
|
105
|
+
|
|
106
|
+
const absPath = join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-SUMMARY.md");
|
|
107
|
+
const relPath = ".gsd/milestones/M001/slices/S01/S01-SUMMARY.md";
|
|
108
|
+
writeSummary(base, "S01", makeFatSummary("S01"));
|
|
109
|
+
|
|
110
|
+
const out = await buildSliceSummaryExcerpt(absPath, relPath, "S01");
|
|
111
|
+
|
|
112
|
+
// Compact header with source path for on-demand Read
|
|
113
|
+
assert.match(out, /### S01 Summary \(excerpt\)/);
|
|
114
|
+
assert.match(out, /Source: `\.gsd\/milestones\/M001\/slices\/S01\/S01-SUMMARY\.md`/);
|
|
115
|
+
|
|
116
|
+
// Frontmatter fields surfaced
|
|
117
|
+
assert.match(out, /\*\*Title:\*\* S01: Slice summary/);
|
|
118
|
+
assert.match(out, /\*\*One-liner:\*\*/);
|
|
119
|
+
assert.match(out, /\*\*Verification:\*\* `passed`/);
|
|
120
|
+
assert.match(out, /\*\*Blockers:\*\* none/);
|
|
121
|
+
assert.match(out, /\*\*Provides:\*\* compact slice-summary excerpts;/);
|
|
122
|
+
assert.match(out, /\*\*Key decisions:\*\* use parseSummary/);
|
|
123
|
+
assert.match(out, /\*\*Patterns established:\*\* excerpt-first inlining/);
|
|
124
|
+
|
|
125
|
+
// Section heads included (body-section markdown), not whole sections inlined
|
|
126
|
+
assert.match(out, /#### Deviations/);
|
|
127
|
+
assert.match(out, /#### Known limitations/);
|
|
128
|
+
assert.match(out, /#### Follow-ups/);
|
|
129
|
+
|
|
130
|
+
// On-demand instruction present
|
|
131
|
+
assert.match(out, /On-demand.*read.*for the full "What Happened"/);
|
|
132
|
+
|
|
133
|
+
// Bulk narrative is NOT inlined — excerpt is meaningfully shorter than full
|
|
134
|
+
// A 20x-repeated paragraph produces ~2.5KB; excerpt should come in well under.
|
|
135
|
+
const fullSize = makeFatSummary("S01").length;
|
|
136
|
+
assert.ok(
|
|
137
|
+
out.length < fullSize * 0.6,
|
|
138
|
+
`excerpt length ${out.length} should be < 60% of full summary length ${fullSize}`,
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("#4780 excerpt: blocker_discovered=true surfaces prominent marker", async (t) => {
|
|
143
|
+
const base = createBase();
|
|
144
|
+
t.after(() => cleanup(base));
|
|
145
|
+
invalidateAllCaches();
|
|
146
|
+
|
|
147
|
+
const content = [
|
|
148
|
+
"---",
|
|
149
|
+
"id: S01",
|
|
150
|
+
"parent: M001",
|
|
151
|
+
"milestone: M001",
|
|
152
|
+
"blocker_discovered: true",
|
|
153
|
+
"---",
|
|
154
|
+
"# S01",
|
|
155
|
+
"**One-liner**",
|
|
156
|
+
"",
|
|
157
|
+
"## What Happened",
|
|
158
|
+
"content",
|
|
159
|
+
].join("\n");
|
|
160
|
+
const absPath = join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-SUMMARY.md");
|
|
161
|
+
writeSummary(base, "S01", content);
|
|
162
|
+
|
|
163
|
+
const out = await buildSliceSummaryExcerpt(absPath, "rel", "S01");
|
|
164
|
+
assert.match(out, /Blockers:\*\* ⚠️ blocker recorded/);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("#4780 excerpt: fall back to full inline when frontmatter is unrecognizable", async (t) => {
|
|
168
|
+
const base = createBase();
|
|
169
|
+
t.after(() => cleanup(base));
|
|
170
|
+
invalidateAllCaches();
|
|
171
|
+
|
|
172
|
+
// No frontmatter, no id — parser returns empty id, triggering fallback
|
|
173
|
+
const garbage = "# S99\n\nJust a wall of text with no frontmatter at all.\n";
|
|
174
|
+
const absPath = join(base, ".gsd", "milestones", "M001", "slices", "S01", "S99-SUMMARY.md");
|
|
175
|
+
writeFileSync(absPath, garbage);
|
|
176
|
+
|
|
177
|
+
const out = await buildSliceSummaryExcerpt(absPath, "rel/path.md", "S99");
|
|
178
|
+
// Full content preserved (no excerpt wrapper), no data-loss
|
|
179
|
+
assert.match(out, /Just a wall of text/);
|
|
180
|
+
assert.match(out, /### S99 Summary/);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test("#4780 excerpt: missing file reports not-found fallback", async (t) => {
|
|
184
|
+
const base = createBase();
|
|
185
|
+
t.after(() => cleanup(base));
|
|
186
|
+
|
|
187
|
+
const out = await buildSliceSummaryExcerpt(null, "rel/missing.md", "S42");
|
|
188
|
+
assert.match(out, /### S42 Summary \(excerpt\)/);
|
|
189
|
+
assert.match(out, /not found — file does not exist yet/);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("#4780 excerpt: section bodies are capped (coderabbit review)", async (t) => {
|
|
193
|
+
const base = createBase();
|
|
194
|
+
t.after(() => cleanup(base));
|
|
195
|
+
invalidateAllCaches();
|
|
196
|
+
|
|
197
|
+
// Long Follow-ups section (~4.8KB) would balloon the excerpt without
|
|
198
|
+
// the cap — regression coverage for the coderabbit finding on #4908.
|
|
199
|
+
const longFollowUps = "A verbose follow-up bullet that keeps restating the same point. ".repeat(60);
|
|
200
|
+
const content = [
|
|
201
|
+
"---",
|
|
202
|
+
"id: S01",
|
|
203
|
+
"parent: M001",
|
|
204
|
+
"milestone: M001",
|
|
205
|
+
"---",
|
|
206
|
+
"# S01: Test",
|
|
207
|
+
"**One-liner**",
|
|
208
|
+
"",
|
|
209
|
+
"## Follow-ups",
|
|
210
|
+
longFollowUps,
|
|
211
|
+
].join("\n");
|
|
212
|
+
const absPath = join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-SUMMARY.md");
|
|
213
|
+
writeSummary(base, "S01", content);
|
|
214
|
+
|
|
215
|
+
const out = await buildSliceSummaryExcerpt(absPath, "rel/path.md", "S01");
|
|
216
|
+
|
|
217
|
+
assert.match(out, /\(truncated — see full `rel\/path\.md`\)/);
|
|
218
|
+
assert.ok(
|
|
219
|
+
out.length < 2000,
|
|
220
|
+
`excerpt length ${out.length} should be well under 2KB when one section hits the cap`,
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// ─── buildCompleteMilestonePrompt integration test ─────────────────────────
|
|
225
|
+
|
|
226
|
+
test("#4780 closer prompt: uses excerpts + lists on-demand slice SUMMARY paths", async (t) => {
|
|
227
|
+
const base = createBase();
|
|
228
|
+
t.after(() => cleanup(base));
|
|
229
|
+
invalidateAllCaches();
|
|
230
|
+
|
|
231
|
+
writeRoadmap(base, makeRoadmap());
|
|
232
|
+
writeSummary(base, "S01", makeFatSummary("S01"));
|
|
233
|
+
writeSummary(base, "S02", makeFatSummary("S02"));
|
|
234
|
+
|
|
235
|
+
const prompt = await buildCompleteMilestonePrompt("M001", "Test Milestone", base);
|
|
236
|
+
|
|
237
|
+
// Excerpt markers present for each slice
|
|
238
|
+
assert.match(prompt, /### S01 Summary \(excerpt\)/);
|
|
239
|
+
assert.match(prompt, /### S02 Summary \(excerpt\)/);
|
|
240
|
+
|
|
241
|
+
// On-demand path section exists with both slice paths
|
|
242
|
+
assert.match(prompt, /### On-demand Slice Summaries/);
|
|
243
|
+
assert.match(prompt, /S01-SUMMARY\.md/);
|
|
244
|
+
assert.match(prompt, /S02-SUMMARY\.md/);
|
|
245
|
+
|
|
246
|
+
// Fat narrative (the 20x-repeated paragraph) is NOT inlined
|
|
247
|
+
assert.ok(
|
|
248
|
+
!prompt.includes("threads the cache key through every call site."),
|
|
249
|
+
"closer prompt must not inline full 'What Happened' narrative after #4780",
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
// Prompt size is bounded — the two fat summaries' narratives alone would
|
|
253
|
+
// have exceeded ~4KB each. Post-fix closer prompt should be meaningfully
|
|
254
|
+
// smaller than their combined raw size.
|
|
255
|
+
const rawSize = makeFatSummary("S01").length + makeFatSummary("S02").length;
|
|
256
|
+
// Prompt includes roadmap, templates, and other inlines, so it may still
|
|
257
|
+
// be sizable — the guard is specifically that the fat narrative is gone.
|
|
258
|
+
// Use a soft bound: prompt - overhead should be less than 2x one summary.
|
|
259
|
+
assert.ok(
|
|
260
|
+
prompt.length < rawSize + 20_000,
|
|
261
|
+
`closer prompt length ${prompt.length} should be < raw summary size ${rawSize} + 20KB headroom`,
|
|
262
|
+
);
|
|
263
|
+
});
|
|
@@ -153,6 +153,31 @@ describe("complete-milestone", () => {
|
|
|
153
153
|
);
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
+
test("prompt does not hard-fail main self-diff as missing implementation (#4699)", () => {
|
|
157
|
+
const prompt = loadPromptFromWorktree("complete-milestone", {
|
|
158
|
+
workingDirectory: "/tmp/test-project",
|
|
159
|
+
milestoneId: "M001",
|
|
160
|
+
milestoneTitle: "Main Retry Test",
|
|
161
|
+
roadmapPath: ".gsd/milestones/M001/M001-ROADMAP.md",
|
|
162
|
+
inlinedContext: "context",
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
assert.ok(
|
|
166
|
+
!prompt.includes("git diff --stat HEAD $(git merge-base HEAD main) -- ':!.gsd/'"),
|
|
167
|
+
"prompt must not require the known self-diff command from #4699",
|
|
168
|
+
);
|
|
169
|
+
assert.match(
|
|
170
|
+
prompt,
|
|
171
|
+
/self-diff/i,
|
|
172
|
+
"prompt should explicitly guard retries where HEAD and the integration branch are the same commit",
|
|
173
|
+
);
|
|
174
|
+
assert.match(
|
|
175
|
+
prompt,
|
|
176
|
+
/GSD-(?:Task|Unit)/,
|
|
177
|
+
"prompt should direct main-branch retries toward milestone-scoped GSD commit evidence",
|
|
178
|
+
);
|
|
179
|
+
});
|
|
180
|
+
|
|
156
181
|
test("handleCompleteMilestone rejects when verificationPassed is false", async () => {
|
|
157
182
|
const { handleCompleteMilestone } = await import("../tools/complete-milestone.ts");
|
|
158
183
|
const base = createFixtureBase();
|