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
|
@@ -7,9 +7,10 @@ Rules:
|
|
|
7
7
|
2. Read before edit.
|
|
8
8
|
3. Prefer fixing authoritative artifacts over masking warnings.
|
|
9
9
|
4. For missing summaries or UAT files, generate the real artifact from existing slice/task context when possible — do not leave placeholders if you can reconstruct the real content.
|
|
10
|
-
5.
|
|
11
|
-
6.
|
|
12
|
-
7.
|
|
10
|
+
5. For a missing milestone `CONTEXT.md` when the milestone is already past `pre-planning` (phase is `executing`, `summarizing`, `validating-milestone`, or `completing-milestone`): the artifact was skipped during bootstrap and must be reconstructed before execution can resume. Read `PROJECT.md`, `REQUIREMENTS.md`, the milestone's `ROADMAP.md`, and any slice-level context on disk, then write `.gsd/milestones/<milestone-id>/<milestone-id>-CONTEXT.md` with the real context for the scoped milestone. Do not leave a stub — the plan gate will reject it on the next cycle.
|
|
11
|
+
6. After each repair cluster, verify the relevant invariant directly from disk.
|
|
12
|
+
7. When done, rerun `/gsd doctor {{doctorCommandSuffix}}` mentally by ensuring the remaining issue set for this scope is reduced or cleared.
|
|
13
|
+
8. Do NOT query `.gsd/gsd.db` directly via `sqlite3` or `node -e require('better-sqlite3')` — use `gsd_milestone_status` to inspect DB state. Direct access bypasses the WAL connection owned by the engine and can corrupt in-flight writes.
|
|
13
14
|
|
|
14
15
|
## Doctor Summary
|
|
15
16
|
|
|
@@ -27,4 +28,4 @@ Then:
|
|
|
27
28
|
- Repair the unresolved issues in scope
|
|
28
29
|
- Keep changes minimal and targeted
|
|
29
30
|
- If unresolved issues remain outside scope, leave them untouched and mention them briefly
|
|
30
|
-
- End with: "GSD doctor heal complete."
|
|
31
|
+
- End with: "GSD doctor heal complete."
|
|
@@ -20,9 +20,22 @@ Pay particular attention to **Forward Intelligence** sections — they contain h
|
|
|
20
20
|
|
|
21
21
|
You have full tool access. Before decomposing, explore the relevant code to ground your plan in reality.
|
|
22
22
|
|
|
23
|
-
### Verify Roadmap Assumptions
|
|
23
|
+
### Verify Roadmap Assumptions (JIT Reassessment — ADR-003 §4)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Before planning this slice, verify that the roadmap's assumptions still hold given prior slice summaries. Check inlined dependency summaries (below) for discovered constraints, changed approaches, or flagged fragility.
|
|
26
|
+
|
|
27
|
+
**If the remaining roadmap needs adjustment, modify it before proceeding:**
|
|
28
|
+
|
|
29
|
+
- If a downstream slice's title/demo/dependencies are now wrong, call `gsd_reassess_roadmap` with the corrected `sliceChanges.modified` entry.
|
|
30
|
+
- If new work surfaced that deserves its own slice, add it via `sliceChanges.added`.
|
|
31
|
+
- If a downstream slice is now redundant or out of scope, remove it via `sliceChanges.removed`.
|
|
32
|
+
- **Bias strongly toward "roadmap is fine."** Most slice completions produce no structural change. Only adjust when there is concrete evidence a downstream slice is wrong — not speculative concern. Over-reassessment is costlier than a later mid-slice replan.
|
|
33
|
+
|
|
34
|
+
Completed slices are immutable: never modify or remove a slice whose status is complete.
|
|
35
|
+
|
|
36
|
+
Then proceed with planning this slice against the (possibly updated) roadmap.
|
|
37
|
+
|
|
38
|
+
The roadmap description may be stale — verify it against the current codebase state.
|
|
26
39
|
|
|
27
40
|
### Explore Slice Scope
|
|
28
41
|
|
|
@@ -72,6 +72,21 @@ export function rollbackToCheckpoint(
|
|
|
72
72
|
return false;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
// Preserve any staged or untracked user work before the hard reset.
|
|
76
|
+
// The user may have a partial fix staged that they wanted to inspect;
|
|
77
|
+
// reset --hard wipes both staged and unstaged changes (reflog only
|
|
78
|
+
// covers committed state). Push a labeled stash first so recovery
|
|
79
|
+
// is possible. (Issue #4980 HIGH-4)
|
|
80
|
+
try {
|
|
81
|
+
execFileSync(
|
|
82
|
+
"git",
|
|
83
|
+
["stash", "push", "--include-untracked", "-m", `gsd: pre-rollback-stash ${unitId} ${new Date().toISOString()}`],
|
|
84
|
+
{ cwd: basePath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" },
|
|
85
|
+
);
|
|
86
|
+
} catch {
|
|
87
|
+
/* nothing to stash, or stash refused — proceed with reset */
|
|
88
|
+
}
|
|
89
|
+
|
|
75
90
|
// Reset branch pointer and working tree to checkpoint SHA in one step.
|
|
76
91
|
// Using `git reset --hard <sha>` works on the currently checked-out branch
|
|
77
92
|
// (unlike `git branch -f` which is rejected for checked-out branches).
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Service Tier — gating, status formatting, icon resolution, and
|
|
3
3
|
* the /gsd fast command handler.
|
|
4
4
|
*
|
|
5
|
-
* Service tiers (priority/flex) are an OpenAI feature that only
|
|
6
|
-
* to gpt-5.4 variants. This module centralizes the model-gating logic
|
|
5
|
+
* Service tiers (priority/flex) are an OpenAI feature that currently only
|
|
6
|
+
* applies to gpt-5.4 variants in GSD. This module centralizes the model-gating logic
|
|
7
7
|
* so that icons, preferences, and the before_provider_request hook all
|
|
8
8
|
* use a single source of truth.
|
|
9
9
|
*/
|
|
@@ -35,6 +35,9 @@ const SERVICE_TIER_SCOPE_NOTE = "Only affects gpt-5.4 models, regardless of prov
|
|
|
35
35
|
* (set via CAPABILITY_PATCHES in packages/pi-ai/src/models.ts). When callers
|
|
36
36
|
* have access to the full Model object, prefer reading capabilities directly.
|
|
37
37
|
*
|
|
38
|
+
* GPT-5.5 is intentionally excluded until we verify its provider payload
|
|
39
|
+
* contract instead of assuming `service_tier` support.
|
|
40
|
+
*
|
|
38
41
|
* See: https://github.com/gsd-build/gsd-2/issues/2546
|
|
39
42
|
*/
|
|
40
43
|
const SERVICE_TIER_MODEL_PREFIXES = ["gpt-5.4"] as const;
|
|
@@ -188,13 +188,14 @@ function ensureExitHandler(_gsdDir: string): void {
|
|
|
188
188
|
// Lock files accumulate across main project .gsd/, worktree .gsd/,
|
|
189
189
|
// and projects registry paths — cleanup must cover all of them.
|
|
190
190
|
for (const dir of _lockDirRegistry) {
|
|
191
|
+
const lockFile = join(dir, LOCK_FILE);
|
|
192
|
+
const ownsRegisteredLock = isLockFileOwnedByCurrentProcess(lockFile);
|
|
191
193
|
try {
|
|
192
|
-
|
|
193
|
-
if (existsSync(lockFile)) unlinkSync(lockFile);
|
|
194
|
+
if (ownsRegisteredLock && existsSync(lockFile)) unlinkSync(lockFile);
|
|
194
195
|
} catch { /* best-effort */ }
|
|
195
196
|
try {
|
|
196
197
|
const lockDir = join(dir + ".lock");
|
|
197
|
-
if (existsSync(lockDir)) rmSync(lockDir, { recursive: true, force: true });
|
|
198
|
+
if (ownsRegisteredLock && existsSync(lockDir)) rmSync(lockDir, { recursive: true, force: true });
|
|
198
199
|
} catch { /* best-effort */ }
|
|
199
200
|
}
|
|
200
201
|
});
|
|
@@ -526,10 +527,13 @@ export function releaseSessionLock(basePath: string): void {
|
|
|
526
527
|
_releaseFunction = null;
|
|
527
528
|
}
|
|
528
529
|
|
|
529
|
-
// Remove the lock file at the current path
|
|
530
|
+
// Remove the lock file at the current path only if it still belongs to us.
|
|
531
|
+
// Lost-lock cleanup can run after another process has taken ownership; in
|
|
532
|
+
// that case deleting auto.lock would erase the newer owner's evidence.
|
|
530
533
|
const lp = lockPath(basePath);
|
|
534
|
+
const ownsPrimaryLock = isLockFileOwnedByCurrentProcess(lp);
|
|
531
535
|
try {
|
|
532
|
-
if (existsSync(lp)) unlinkSync(lp);
|
|
536
|
+
if (ownsPrimaryLock && existsSync(lp)) unlinkSync(lp);
|
|
533
537
|
} catch {
|
|
534
538
|
// Non-fatal
|
|
535
539
|
}
|
|
@@ -540,12 +544,12 @@ export function releaseSessionLock(basePath: string): void {
|
|
|
540
544
|
const lockTarget = effectiveLockTarget(gsdDir);
|
|
541
545
|
try {
|
|
542
546
|
const lockDir = join(lockTarget + ".lock");
|
|
543
|
-
if (existsSync(lockDir)) rmSync(lockDir, { recursive: true, force: true });
|
|
547
|
+
if (ownsPrimaryLock && existsSync(lockDir)) rmSync(lockDir, { recursive: true, force: true });
|
|
544
548
|
} catch {
|
|
545
549
|
// Non-fatal
|
|
546
550
|
}
|
|
547
551
|
// Also clean the per-milestone parallel directory itself if it exists
|
|
548
|
-
if (lockTarget !== gsdDir) {
|
|
552
|
+
if (ownsPrimaryLock && lockTarget !== gsdDir) {
|
|
549
553
|
try {
|
|
550
554
|
if (existsSync(lockTarget)) rmSync(lockTarget, { recursive: true, force: true });
|
|
551
555
|
} catch {
|
|
@@ -556,13 +560,14 @@ export function releaseSessionLock(basePath: string): void {
|
|
|
556
560
|
// Clean ALL registered lock paths (#1578) — lock files accumulate across
|
|
557
561
|
// main project .gsd/, worktree .gsd/, and projects registry paths.
|
|
558
562
|
for (const dir of _lockDirRegistry) {
|
|
563
|
+
const lockFile = join(dir, LOCK_FILE);
|
|
564
|
+
const ownsRegisteredLock = isLockFileOwnedByCurrentProcess(lockFile);
|
|
559
565
|
try {
|
|
560
|
-
|
|
561
|
-
if (existsSync(lockFile)) unlinkSync(lockFile);
|
|
566
|
+
if (ownsRegisteredLock && existsSync(lockFile)) unlinkSync(lockFile);
|
|
562
567
|
} catch { /* best-effort */ }
|
|
563
568
|
try {
|
|
564
569
|
const lockDir = join(dir + ".lock");
|
|
565
|
-
if (existsSync(lockDir)) rmSync(lockDir, { recursive: true, force: true });
|
|
570
|
+
if (ownsRegisteredLock && existsSync(lockDir)) rmSync(lockDir, { recursive: true, force: true });
|
|
566
571
|
} catch { /* best-effort */ }
|
|
567
572
|
}
|
|
568
573
|
_lockDirRegistry.clear();
|
|
@@ -619,6 +624,11 @@ function readExistingLockData(lp: string): SessionLockData | null {
|
|
|
619
624
|
}
|
|
620
625
|
}
|
|
621
626
|
|
|
627
|
+
function isLockFileOwnedByCurrentProcess(lp: string): boolean {
|
|
628
|
+
const existing = readExistingLockData(lp);
|
|
629
|
+
return existing?.pid === process.pid;
|
|
630
|
+
}
|
|
631
|
+
|
|
622
632
|
/**
|
|
623
633
|
* Retry-tolerant variant of readExistingLockData for use in onCompromised and
|
|
624
634
|
* other paths where a transient filesystem hiccup (NFS/CIFS latency, macOS APFS
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// GSD2 + skill-manifest — per-unit-type skill allowlist resolver (RFC #4779)
|
|
2
|
+
//
|
|
3
|
+
// Each auto-mode unit type can declare which skills are relevant to it. This
|
|
4
|
+
// trims the set of skills considered for activation in the per-unit prompt,
|
|
5
|
+
// reducing prompt token bloat and sharpening model focus.
|
|
6
|
+
//
|
|
7
|
+
// Contract:
|
|
8
|
+
// - Unknown unit types fall through to "all skills" (current behavior).
|
|
9
|
+
// - A manifest entry referencing a skill that is not installed is a silent
|
|
10
|
+
// no-op at filter time — the filter passes through installed skills only.
|
|
11
|
+
// - The allowlist is an inclusion list: only skills whose normalized name
|
|
12
|
+
// appears in the allowlist are retained. Order is not preserved.
|
|
13
|
+
//
|
|
14
|
+
// Phase 1 scope: seed manifests for a small number of unit types as proof.
|
|
15
|
+
// Additional unit types can be added incrementally; each addition is a pure
|
|
16
|
+
// data change with no wiring cost.
|
|
17
|
+
|
|
18
|
+
import { logWarning } from "./workflow-logger.js";
|
|
19
|
+
|
|
20
|
+
/** Normalize a skill reference the same way callers do (lowercase, trim). */
|
|
21
|
+
function normalize(name: string): string {
|
|
22
|
+
return name.trim().toLowerCase();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Allowlist per unit type. Keys match unit type identifiers used by auto-mode
|
|
27
|
+
* dispatch. Values are normalized skill names.
|
|
28
|
+
*
|
|
29
|
+
* Wildcard semantics: a unit type absent from this map resolves to `null`
|
|
30
|
+
* (wildcard) — meaning "all installed skills are eligible". Prefer absence
|
|
31
|
+
* over an exhaustive list when uncertain.
|
|
32
|
+
*/
|
|
33
|
+
const UNIT_TYPE_SKILL_MANIFEST: Record<string, string[]> = {
|
|
34
|
+
// Milestone-level planning / meta flows — predictable skill sets.
|
|
35
|
+
"research-milestone": [
|
|
36
|
+
"write-docs",
|
|
37
|
+
"write-milestone-brief",
|
|
38
|
+
"decompose-into-slices",
|
|
39
|
+
"grill-me",
|
|
40
|
+
"design-an-interface",
|
|
41
|
+
"api-design",
|
|
42
|
+
"observability",
|
|
43
|
+
],
|
|
44
|
+
"plan-milestone": [
|
|
45
|
+
"write-milestone-brief",
|
|
46
|
+
"decompose-into-slices",
|
|
47
|
+
"design-an-interface",
|
|
48
|
+
"grill-me",
|
|
49
|
+
"write-docs",
|
|
50
|
+
"api-design",
|
|
51
|
+
"tdd",
|
|
52
|
+
"verify-before-complete",
|
|
53
|
+
],
|
|
54
|
+
"complete-milestone": [
|
|
55
|
+
"verify-before-complete",
|
|
56
|
+
"write-docs",
|
|
57
|
+
"handoff",
|
|
58
|
+
"forensics",
|
|
59
|
+
"observability",
|
|
60
|
+
"security-review",
|
|
61
|
+
],
|
|
62
|
+
"validate-milestone": [
|
|
63
|
+
"verify-before-complete",
|
|
64
|
+
"review",
|
|
65
|
+
"test",
|
|
66
|
+
"lint",
|
|
67
|
+
"security-review",
|
|
68
|
+
"accessibility",
|
|
69
|
+
"forensics",
|
|
70
|
+
"observability",
|
|
71
|
+
],
|
|
72
|
+
"reassess-roadmap": [
|
|
73
|
+
"decompose-into-slices",
|
|
74
|
+
"grill-me",
|
|
75
|
+
"write-milestone-brief",
|
|
76
|
+
"write-docs",
|
|
77
|
+
"forensics",
|
|
78
|
+
],
|
|
79
|
+
// Slice-level research / planning.
|
|
80
|
+
"research-slice": [
|
|
81
|
+
"write-docs",
|
|
82
|
+
"decompose-into-slices",
|
|
83
|
+
"design-an-interface",
|
|
84
|
+
"grill-me",
|
|
85
|
+
"api-design",
|
|
86
|
+
"observability",
|
|
87
|
+
],
|
|
88
|
+
"plan-slice": [
|
|
89
|
+
"decompose-into-slices",
|
|
90
|
+
"design-an-interface",
|
|
91
|
+
"grill-me",
|
|
92
|
+
"write-docs",
|
|
93
|
+
"api-design",
|
|
94
|
+
"tdd",
|
|
95
|
+
"verify-before-complete",
|
|
96
|
+
],
|
|
97
|
+
"refine-slice": [
|
|
98
|
+
"decompose-into-slices",
|
|
99
|
+
"design-an-interface",
|
|
100
|
+
"grill-me",
|
|
101
|
+
"write-docs",
|
|
102
|
+
"api-design",
|
|
103
|
+
"tdd",
|
|
104
|
+
"verify-before-complete",
|
|
105
|
+
],
|
|
106
|
+
"replan-slice": [
|
|
107
|
+
"decompose-into-slices",
|
|
108
|
+
"grill-me",
|
|
109
|
+
"design-an-interface",
|
|
110
|
+
"write-docs",
|
|
111
|
+
"api-design",
|
|
112
|
+
],
|
|
113
|
+
"run-uat": [
|
|
114
|
+
"verify-before-complete",
|
|
115
|
+
"test",
|
|
116
|
+
"review",
|
|
117
|
+
"accessibility",
|
|
118
|
+
],
|
|
119
|
+
// `execute-task` intentionally omitted — implementation hot path covers a
|
|
120
|
+
// wide surface of technologies; wildcard fallback preserves today's
|
|
121
|
+
// behavior until per-task skill hints can be derived from task-plan
|
|
122
|
+
// frontmatter. See RFC #4779.
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Resolve the skill allowlist for a unit type.
|
|
127
|
+
*
|
|
128
|
+
* @returns Array of normalized skill names when an entry exists, or `null`
|
|
129
|
+
* when the unit type is unknown (wildcard — caller should not filter).
|
|
130
|
+
*/
|
|
131
|
+
export function resolveSkillManifest(unitType: string | undefined): string[] | null {
|
|
132
|
+
if (!unitType) return null;
|
|
133
|
+
const entry = UNIT_TYPE_SKILL_MANIFEST[unitType];
|
|
134
|
+
if (!entry) return null;
|
|
135
|
+
return entry.map(normalize);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Filter a skill list by the manifest for `unitType`. Pass-through when the
|
|
140
|
+
* manifest is wildcard (unknown unit type) or `unitType` is undefined.
|
|
141
|
+
*/
|
|
142
|
+
export function filterSkillsByManifest<T extends { name: string }>(
|
|
143
|
+
skills: T[],
|
|
144
|
+
unitType: string | undefined,
|
|
145
|
+
): T[] {
|
|
146
|
+
const allowlist = resolveSkillManifest(unitType);
|
|
147
|
+
if (allowlist === null) return skills;
|
|
148
|
+
const allowed = new Set(allowlist);
|
|
149
|
+
return skills.filter(skill => allowed.has(normalize(skill.name)));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Dev-mode guard: warn once per process if a manifest entry references a name
|
|
154
|
+
* that is not currently installed. Silent in production.
|
|
155
|
+
*/
|
|
156
|
+
const warnedMissing = new Set<string>();
|
|
157
|
+
|
|
158
|
+
export function warnIfManifestHasMissingSkills(
|
|
159
|
+
unitType: string | undefined,
|
|
160
|
+
installedNames: Set<string>,
|
|
161
|
+
): void {
|
|
162
|
+
// Strict mode is intentionally opt-in via exactly "1"; values like "0" or
|
|
163
|
+
// "false" must preserve the normal silent manifest behavior.
|
|
164
|
+
if (process.env.GSD_SKILL_MANIFEST_STRICT !== "1") return;
|
|
165
|
+
const allowlist = resolveSkillManifest(unitType);
|
|
166
|
+
if (!allowlist) return;
|
|
167
|
+
for (const name of allowlist) {
|
|
168
|
+
const key = `${unitType}:${name}`;
|
|
169
|
+
if (warnedMissing.has(key)) continue;
|
|
170
|
+
if (!installedNames.has(name)) {
|
|
171
|
+
warnedMissing.add(key);
|
|
172
|
+
logWarning("prompt", `skill-manifest: references uninstalled skill '${name}' for unit '${unitType}'`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slice-cadence collapse — #4765.
|
|
3
|
+
*
|
|
4
|
+
* When `git.collapse_cadence: "slice"` is set, each slice's commits are
|
|
5
|
+
* squash-merged from the milestone branch to main as soon as the slice
|
|
6
|
+
* passes validation. Shrinks the orphan window (#4761) from milestone-size
|
|
7
|
+
* to slice-size and surfaces merge conflicts per-slice rather than all at
|
|
8
|
+
* once at milestone end.
|
|
9
|
+
*
|
|
10
|
+
* This module is deliberately focused and narrower than mergeMilestoneToMain:
|
|
11
|
+
* - No worktree teardown (worktree is reused for the next slice)
|
|
12
|
+
* - No DB reconciliation (modern worktrees share the main DB via path resolver)
|
|
13
|
+
* - No roadmap/summary/gate handling (that's still the milestone's job)
|
|
14
|
+
* - Fails loudly on dirty main — caller is responsible for cleanliness
|
|
15
|
+
*
|
|
16
|
+
* Kernighan: the v1 surface handles the happy path + conflict. Edge cases
|
|
17
|
+
* that mergeMilestoneToMain covers (concurrent merges, shared DB paths,
|
|
18
|
+
* submodules) are explicit non-goals; users opt in via preference and early-
|
|
19
|
+
* adopter scenarios are scoped narrow.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
23
|
+
import { join } from "node:path";
|
|
24
|
+
import { execFileSync } from "node:child_process";
|
|
25
|
+
|
|
26
|
+
import { GSDError, GSD_GIT_ERROR } from "./errors.js";
|
|
27
|
+
import { MergeConflictError } from "./git-service.js";
|
|
28
|
+
import {
|
|
29
|
+
nativeBranchForceReset,
|
|
30
|
+
nativeCheckoutBranch,
|
|
31
|
+
nativeCommit,
|
|
32
|
+
nativeCommitCountBetween,
|
|
33
|
+
nativeConflictFiles,
|
|
34
|
+
nativeDetectMainBranch,
|
|
35
|
+
nativeMergeSquash,
|
|
36
|
+
} from "./native-git-bridge.js";
|
|
37
|
+
import { resolveGitDir } from "./worktree-manager.js";
|
|
38
|
+
import { logWarning } from "./workflow-logger.js";
|
|
39
|
+
import { emitSliceMerged, emitMilestoneResquash } from "./worktree-telemetry.js";
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Auto-worktree milestone branch name. Must match autoWorktreeBranch() in
|
|
43
|
+
* auto-worktree.ts; duplicated here to avoid a cyclic import.
|
|
44
|
+
*/
|
|
45
|
+
function milestoneBranchName(milestoneId: string): string {
|
|
46
|
+
return `milestone/${milestoneId}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function cleanupMergeArtifacts(projectRoot: string): void {
|
|
50
|
+
try {
|
|
51
|
+
const gitDir = resolveGitDir(projectRoot);
|
|
52
|
+
for (const f of ["SQUASH_MSG", "MERGE_MSG", "MERGE_HEAD"]) {
|
|
53
|
+
const p = join(gitDir, f);
|
|
54
|
+
if (existsSync(p)) unlinkSync(p);
|
|
55
|
+
}
|
|
56
|
+
} catch (err) {
|
|
57
|
+
logWarning("worktree", `merge artifact cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface SliceMergeResult {
|
|
62
|
+
commitSha: string | null;
|
|
63
|
+
mainBranch: string;
|
|
64
|
+
milestoneBranch: string;
|
|
65
|
+
durationMs: number;
|
|
66
|
+
skipped: boolean;
|
|
67
|
+
skippedReason?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Squash-merge one slice's commits from the milestone branch to main.
|
|
72
|
+
*
|
|
73
|
+
* Preconditions:
|
|
74
|
+
* - Caller is on the milestone branch inside the worktree
|
|
75
|
+
* - `projectRoot` points at the real project root (not the worktree)
|
|
76
|
+
*
|
|
77
|
+
* Post-conditions on success:
|
|
78
|
+
* - Slice's commits are a single squash commit on main
|
|
79
|
+
* - `milestone/<MID>` is fast-forwarded to main (so next slice's work
|
|
80
|
+
* starts from a clean base)
|
|
81
|
+
* - caller's process.cwd is restored
|
|
82
|
+
*
|
|
83
|
+
* Throws MergeConflictError on conflicts; caller should surface and stop.
|
|
84
|
+
* Throws GSDError on dirty main / detection failures.
|
|
85
|
+
*/
|
|
86
|
+
export function mergeSliceToMain(
|
|
87
|
+
projectRoot: string,
|
|
88
|
+
milestoneId: string,
|
|
89
|
+
sliceId: string,
|
|
90
|
+
): SliceMergeResult {
|
|
91
|
+
const started = Date.now();
|
|
92
|
+
const worktreeCwd = process.cwd();
|
|
93
|
+
const milestoneBranch = milestoneBranchName(milestoneId);
|
|
94
|
+
const mainBranch = nativeDetectMainBranch(projectRoot);
|
|
95
|
+
|
|
96
|
+
// Fast path: if the milestone branch has no commits ahead of main, there
|
|
97
|
+
// is nothing to merge. Return a skip result instead of no-op'ing silently
|
|
98
|
+
// so the caller's telemetry shows the decision.
|
|
99
|
+
let commitsAhead = 0;
|
|
100
|
+
try {
|
|
101
|
+
commitsAhead = nativeCommitCountBetween(projectRoot, mainBranch, milestoneBranch);
|
|
102
|
+
} catch {
|
|
103
|
+
// If we can't count, assume there's work and let the merge proceed —
|
|
104
|
+
// a failing merge is more informative than a silent skip.
|
|
105
|
+
commitsAhead = 1;
|
|
106
|
+
}
|
|
107
|
+
if (commitsAhead === 0) {
|
|
108
|
+
// Do NOT emit slice-merged here — this is a no-op, not a merge. Emitting
|
|
109
|
+
// would inflate slicesMerged in telemetry/forensics and distort the
|
|
110
|
+
// conflict rate denominator.
|
|
111
|
+
return {
|
|
112
|
+
commitSha: null,
|
|
113
|
+
mainBranch,
|
|
114
|
+
milestoneBranch,
|
|
115
|
+
durationMs: Date.now() - started,
|
|
116
|
+
skipped: true,
|
|
117
|
+
skippedReason: "no-commits-ahead",
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
process.chdir(projectRoot);
|
|
122
|
+
try {
|
|
123
|
+
// Dirty-main check — v1 fails loudly rather than auto-stashing. Users
|
|
124
|
+
// running slice-cadence opt in knowing main stays clean between merges.
|
|
125
|
+
const status = execFileSync("git", ["status", "--porcelain"], {
|
|
126
|
+
cwd: projectRoot,
|
|
127
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
128
|
+
encoding: "utf-8",
|
|
129
|
+
}).trim();
|
|
130
|
+
if (status) {
|
|
131
|
+
throw new GSDError(
|
|
132
|
+
GSD_GIT_ERROR,
|
|
133
|
+
`slice-cadence merge requires a clean project root; uncommitted changes detected. ` +
|
|
134
|
+
`Commit or stash at ${projectRoot} before retrying. Status:\n${status}`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
nativeCheckoutBranch(projectRoot, mainBranch);
|
|
139
|
+
|
|
140
|
+
// Clean any stale merge artifacts before attempting the squash (#2912 pattern)
|
|
141
|
+
cleanupMergeArtifacts(projectRoot);
|
|
142
|
+
|
|
143
|
+
const mergeResult = nativeMergeSquash(projectRoot, milestoneBranch);
|
|
144
|
+
if (!mergeResult.success) {
|
|
145
|
+
const conflictedFiles = mergeResult.conflicts.length > 0
|
|
146
|
+
? mergeResult.conflicts
|
|
147
|
+
: nativeConflictFiles(projectRoot);
|
|
148
|
+
cleanupMergeArtifacts(projectRoot);
|
|
149
|
+
try {
|
|
150
|
+
emitSliceMerged(projectRoot, milestoneId, sliceId, {
|
|
151
|
+
durationMs: Date.now() - started,
|
|
152
|
+
conflict: true,
|
|
153
|
+
});
|
|
154
|
+
} catch { /* silent */ }
|
|
155
|
+
throw new MergeConflictError(
|
|
156
|
+
conflictedFiles,
|
|
157
|
+
"squash",
|
|
158
|
+
milestoneBranch,
|
|
159
|
+
mainBranch,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Commit the squash with a slice-scoped message
|
|
164
|
+
const commitSha = nativeCommit(
|
|
165
|
+
projectRoot,
|
|
166
|
+
`gsd: merge ${sliceId} of ${milestoneId} (slice-cadence)`,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Advance the milestone branch to main so the next slice's commits start
|
|
170
|
+
// from a clean base. Force-reset is safe because we just merged this
|
|
171
|
+
// branch's entire delta.
|
|
172
|
+
nativeBranchForceReset(projectRoot, milestoneBranch, mainBranch);
|
|
173
|
+
|
|
174
|
+
const durationMs = Date.now() - started;
|
|
175
|
+
try {
|
|
176
|
+
emitSliceMerged(projectRoot, milestoneId, sliceId, {
|
|
177
|
+
durationMs,
|
|
178
|
+
conflict: false,
|
|
179
|
+
commitSha: commitSha ?? undefined,
|
|
180
|
+
});
|
|
181
|
+
} catch { /* silent */ }
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
commitSha,
|
|
185
|
+
mainBranch,
|
|
186
|
+
milestoneBranch,
|
|
187
|
+
durationMs,
|
|
188
|
+
skipped: false,
|
|
189
|
+
};
|
|
190
|
+
} finally {
|
|
191
|
+
// Always restore cwd even if anything above threw.
|
|
192
|
+
try { process.chdir(worktreeCwd); } catch { /* best-effort */ }
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Re-squash per-slice commits on main into a single milestone commit.
|
|
198
|
+
*
|
|
199
|
+
* Runs at milestone completion when `collapse_cadence: "slice"` AND
|
|
200
|
+
* `milestone_resquash: true`. The `startSha` is the SHA of main immediately
|
|
201
|
+
* before the milestone's first slice merge — the caller is responsible for
|
|
202
|
+
* recording this (AutoSession field, git ref, or DB row).
|
|
203
|
+
*
|
|
204
|
+
* Strategy: soft-reset main to startSha, then commit the net diff. The
|
|
205
|
+
* N slice commits between startSha and HEAD are collapsed into one.
|
|
206
|
+
*
|
|
207
|
+
* No-op (returns false) if startSha equals HEAD (nothing to re-squash).
|
|
208
|
+
*/
|
|
209
|
+
export function resquashMilestoneOnMain(
|
|
210
|
+
projectRoot: string,
|
|
211
|
+
milestoneId: string,
|
|
212
|
+
startSha: string,
|
|
213
|
+
): { resquashed: boolean; newSha: string | null } {
|
|
214
|
+
const mainBranch = nativeDetectMainBranch(projectRoot);
|
|
215
|
+
const worktreeCwd = process.cwd();
|
|
216
|
+
|
|
217
|
+
process.chdir(projectRoot);
|
|
218
|
+
try {
|
|
219
|
+
nativeCheckoutBranch(projectRoot, mainBranch);
|
|
220
|
+
|
|
221
|
+
// Verify the startSha..HEAD range contains ONLY this milestone's slice-
|
|
222
|
+
// cadence commits. If any unrelated commits landed on main since the
|
|
223
|
+
// milestone started (e.g. concurrent work, cherry-picks, hotfixes), a
|
|
224
|
+
// blind `git reset --soft` would fold them into the re-squash and rewrite
|
|
225
|
+
// their attribution. Fail closed — the user can resolve manually.
|
|
226
|
+
const expectedSuffix = `(slice-cadence)`;
|
|
227
|
+
const expectedMilestoneToken = ` of ${milestoneId} `;
|
|
228
|
+
let subjectsRaw = "";
|
|
229
|
+
try {
|
|
230
|
+
subjectsRaw = execFileSync(
|
|
231
|
+
"git",
|
|
232
|
+
["log", "--format=%s", `${startSha}..HEAD`],
|
|
233
|
+
{ cwd: projectRoot, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" },
|
|
234
|
+
);
|
|
235
|
+
} catch {
|
|
236
|
+
return { resquashed: false, newSha: null };
|
|
237
|
+
}
|
|
238
|
+
const subjects = subjectsRaw.split("\n").filter((s) => s.length > 0);
|
|
239
|
+
const sliceCount = subjects.length;
|
|
240
|
+
if (sliceCount === 0) {
|
|
241
|
+
return { resquashed: false, newSha: null };
|
|
242
|
+
}
|
|
243
|
+
const foreign = subjects.filter(
|
|
244
|
+
(s) => !(s.endsWith(expectedSuffix) && s.includes(expectedMilestoneToken)),
|
|
245
|
+
);
|
|
246
|
+
if (foreign.length > 0) {
|
|
247
|
+
logWarning(
|
|
248
|
+
"worktree",
|
|
249
|
+
`slice-cadence: skipping milestone resquash for ${milestoneId} — ` +
|
|
250
|
+
`${foreign.length} non-slice-cadence commit(s) in ${startSha}..HEAD ` +
|
|
251
|
+
`would be folded in. First: "${foreign[0]}". Resolve history manually.`,
|
|
252
|
+
);
|
|
253
|
+
return { resquashed: false, newSha: null };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Safe to collapse: all commits in the range are this milestone's slices.
|
|
257
|
+
execFileSync("git", ["reset", "--soft", startSha], {
|
|
258
|
+
cwd: projectRoot,
|
|
259
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
260
|
+
encoding: "utf-8",
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const newSha = nativeCommit(
|
|
264
|
+
projectRoot,
|
|
265
|
+
`gsd: complete milestone ${milestoneId} (${sliceCount} slices re-squashed)`,
|
|
266
|
+
{ allowEmpty: true },
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
emitMilestoneResquash(projectRoot, milestoneId, {
|
|
271
|
+
sliceCount,
|
|
272
|
+
startSha,
|
|
273
|
+
endSha: newSha ?? undefined,
|
|
274
|
+
});
|
|
275
|
+
} catch { /* silent */ }
|
|
276
|
+
|
|
277
|
+
return { resquashed: true, newSha };
|
|
278
|
+
} finally {
|
|
279
|
+
try { process.chdir(worktreeCwd); } catch { /* best-effort */ }
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Read the effective collapse cadence from validated preferences. Accepts
|
|
285
|
+
* a raw preferences object (the shape loadEffectiveGSDPreferences returns).
|
|
286
|
+
*/
|
|
287
|
+
export function getCollapseCadence(
|
|
288
|
+
prefs: { git?: { collapse_cadence?: "milestone" | "slice" } } | undefined | null,
|
|
289
|
+
): "milestone" | "slice" {
|
|
290
|
+
return prefs?.git?.collapse_cadence ?? "milestone";
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function getMilestoneResquash(
|
|
294
|
+
prefs: { git?: { milestone_resquash?: boolean } } | undefined | null,
|
|
295
|
+
): boolean {
|
|
296
|
+
// Default true when cadence is slice — resquash preserves the milestone-
|
|
297
|
+
// level history shape users expect.
|
|
298
|
+
return prefs?.git?.milestone_resquash !== false;
|
|
299
|
+
}
|