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
|
@@ -46,6 +46,7 @@ import { logWarning, logError } from './workflow-logger.js';
|
|
|
46
46
|
import { extractVerdict } from './verdict-parser.js';
|
|
47
47
|
import { loadEffectiveGSDPreferences } from './preferences.js';
|
|
48
48
|
import { detectPendingEscalation } from './escalation.js';
|
|
49
|
+
import { isTerminalMilestoneSummaryContent } from './milestone-summary-classifier.js';
|
|
49
50
|
|
|
50
51
|
import {
|
|
51
52
|
isDbAvailable,
|
|
@@ -139,6 +140,14 @@ export function isValidationTerminal(validationContent: string): boolean {
|
|
|
139
140
|
return extractVerdict(validationContent) != null;
|
|
140
141
|
}
|
|
141
142
|
|
|
143
|
+
async function isTerminalMilestoneSummaryFile(
|
|
144
|
+
path: string,
|
|
145
|
+
loader: (path: string) => Promise<string | null>,
|
|
146
|
+
): Promise<boolean> {
|
|
147
|
+
const content = await loader(path);
|
|
148
|
+
return content != null && isTerminalMilestoneSummaryContent(content);
|
|
149
|
+
}
|
|
150
|
+
|
|
142
151
|
// ─── State Derivation ──────────────────────────────────────────────────────
|
|
143
152
|
|
|
144
153
|
// ── deriveState memoization ─────────────────────────────────────────────────
|
|
@@ -211,15 +220,15 @@ export async function getActiveMilestoneId(basePath: string): Promise<string | n
|
|
|
211
220
|
const content = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
212
221
|
if (!content) {
|
|
213
222
|
const summaryFile = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
214
|
-
if (summaryFile) continue;
|
|
223
|
+
if (summaryFile && await isTerminalMilestoneSummaryFile(summaryFile, loadFile)) continue;
|
|
215
224
|
if (isGhostMilestone(basePath, mid)) continue;
|
|
216
225
|
return mid;
|
|
217
226
|
}
|
|
218
227
|
const roadmap = parseRoadmap(content);
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
const summaryFile = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
229
|
+
if (summaryFile && await isTerminalMilestoneSummaryFile(summaryFile, loadFile)) continue;
|
|
230
|
+
if (!isMilestoneComplete(roadmap)) return mid;
|
|
231
|
+
return mid;
|
|
223
232
|
}
|
|
224
233
|
return null;
|
|
225
234
|
}
|
|
@@ -258,7 +267,7 @@ export async function deriveState(basePath: string): Promise<GSDState> {
|
|
|
258
267
|
let synced = false;
|
|
259
268
|
for (const diskId of diskIds) {
|
|
260
269
|
if (!isGhostMilestone(basePath, diskId)) {
|
|
261
|
-
insertMilestone(
|
|
270
|
+
insertMilestone(diskMilestoneInsert(basePath, diskId));
|
|
262
271
|
synced = true;
|
|
263
272
|
}
|
|
264
273
|
}
|
|
@@ -318,6 +327,42 @@ function extractContextTitle(content: string | null, fallback: string): string {
|
|
|
318
327
|
// Alias kept for backward compatibility within this file.
|
|
319
328
|
const isStatusDone = isClosedStatus;
|
|
320
329
|
|
|
330
|
+
function loadSync(path: string | null): string | null {
|
|
331
|
+
if (!path) return null;
|
|
332
|
+
try {
|
|
333
|
+
return readFileSync(path, "utf-8");
|
|
334
|
+
} catch {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function diskMilestoneInsert(basePath: string, mid: string): {
|
|
340
|
+
id: string;
|
|
341
|
+
title?: string;
|
|
342
|
+
status: string;
|
|
343
|
+
depends_on: string[];
|
|
344
|
+
} {
|
|
345
|
+
const contextContent = loadSync(resolveMilestoneFile(basePath, mid, "CONTEXT"));
|
|
346
|
+
const draftContent = !contextContent ? loadSync(resolveMilestoneFile(basePath, mid, "CONTEXT-DRAFT")) : null;
|
|
347
|
+
const roadmapContent = loadSync(resolveMilestoneFile(basePath, mid, "ROADMAP"));
|
|
348
|
+
const summaryContent = loadSync(resolveMilestoneFile(basePath, mid, "SUMMARY"));
|
|
349
|
+
const roadmap = roadmapContent ? parseRoadmap(roadmapContent) : null;
|
|
350
|
+
const summary = summaryContent ? parseSummary(summaryContent) : null;
|
|
351
|
+
const summaryTerminal = summaryContent != null && isTerminalMilestoneSummaryContent(summaryContent);
|
|
352
|
+
const parked = resolveMilestoneFile(basePath, mid, "PARKED") !== null;
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
id: mid,
|
|
356
|
+
title: roadmap
|
|
357
|
+
? stripMilestonePrefix(roadmap.title)
|
|
358
|
+
: (contextContent || draftContent)
|
|
359
|
+
? extractContextTitle(contextContent || draftContent, mid)
|
|
360
|
+
: (summary?.title || mid),
|
|
361
|
+
status: parked ? "parked" : summaryTerminal ? "complete" : "active",
|
|
362
|
+
depends_on: parseContextDependsOn(contextContent ?? draftContent),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
321
366
|
/**
|
|
322
367
|
* Derive GSD state from the milestones/slices/tasks DB tables.
|
|
323
368
|
* Flag files (PARKED, VALIDATION, CONTINUE, REPLAN, REPLAN-TRIGGER, CONTEXT-DRAFT)
|
|
@@ -333,7 +378,7 @@ function reconcileDiskToDb(basePath: string): MilestoneRow[] {
|
|
|
333
378
|
let synced = false;
|
|
334
379
|
for (const diskId of diskIds) {
|
|
335
380
|
if (!dbIdSet.has(diskId) && !isGhostMilestone(basePath, diskId)) {
|
|
336
|
-
insertMilestone(
|
|
381
|
+
insertMilestone(diskMilestoneInsert(basePath, diskId));
|
|
337
382
|
synced = true;
|
|
338
383
|
}
|
|
339
384
|
}
|
|
@@ -668,37 +713,12 @@ function resolveSliceDependencies(activeMilestoneSlices: SliceRow[]): { activeSl
|
|
|
668
713
|
}
|
|
669
714
|
}
|
|
670
715
|
|
|
671
|
-
// First pass: find a slice with ALL dependencies satisfied (strict)
|
|
672
|
-
let bestFallback: SliceRow | null = null;
|
|
673
|
-
let bestFallbackSatisfied = -1;
|
|
674
|
-
|
|
675
716
|
for (const s of activeMilestoneSlices) {
|
|
676
717
|
if (isStatusDone(s.status)) continue;
|
|
677
718
|
if (isDeferredStatus(s.status)) continue;
|
|
678
719
|
if (s.depends.every(dep => doneSliceIds.has(dep))) {
|
|
679
720
|
return { activeSlice: { id: s.id, title: s.title }, activeSliceRow: s };
|
|
680
721
|
}
|
|
681
|
-
// Track the slice with the most satisfied dependencies as fallback
|
|
682
|
-
const satisfied = s.depends.filter(dep => doneSliceIds.has(dep)).length;
|
|
683
|
-
if (satisfied > bestFallbackSatisfied || (satisfied === bestFallbackSatisfied && !bestFallback)) {
|
|
684
|
-
bestFallback = s;
|
|
685
|
-
bestFallbackSatisfied = satisfied;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// Fallback: if no slice has all deps met but there ARE incomplete non-deferred
|
|
690
|
-
// slices, pick the one with the most deps satisfied. This prevents hard-blocking
|
|
691
|
-
// when dependency metadata is stale (e.g. after reassessment added/removed slices)
|
|
692
|
-
// or when deps reference slices from previous milestones.
|
|
693
|
-
if (bestFallback) {
|
|
694
|
-
const unmet = bestFallback.depends.filter(dep => !doneSliceIds.has(dep));
|
|
695
|
-
logWarning("state",
|
|
696
|
-
`No slice has all deps satisfied — falling back to ${bestFallback.id} ` +
|
|
697
|
-
`(${bestFallbackSatisfied}/${bestFallback.depends.length} deps met, ` +
|
|
698
|
-
`unmet: ${unmet.join(", ")})`,
|
|
699
|
-
{ mid: activeMilestoneSlices[0]?.milestone_id, sid: bestFallback.id },
|
|
700
|
-
);
|
|
701
|
-
return { activeSlice: { id: bestFallback.id, title: bestFallback.title }, activeSliceRow: bestFallback };
|
|
702
722
|
}
|
|
703
723
|
|
|
704
724
|
return { activeSlice: null, activeSliceRow: null };
|
|
@@ -712,14 +732,19 @@ async function reconcileSliceTasks(
|
|
|
712
732
|
): Promise<TaskRow[]> {
|
|
713
733
|
let tasks = getSliceTasks(milestoneId, sliceId);
|
|
714
734
|
|
|
715
|
-
|
|
735
|
+
// #3600/#4974: import missing plan-file tasks even when the DB already has
|
|
736
|
+
// a partial task set. Existing DB task statuses stay authoritative.
|
|
737
|
+
if (planFile) {
|
|
716
738
|
try {
|
|
717
739
|
const planContent = await loadFile(planFile);
|
|
718
740
|
if (planContent) {
|
|
719
741
|
const diskPlan = parsePlan(planContent);
|
|
720
742
|
if (diskPlan.tasks.length > 0) {
|
|
743
|
+
const dbTaskIds = new Set(tasks.map(t => t.id));
|
|
744
|
+
let inserted = 0;
|
|
721
745
|
for (let i = 0; i < diskPlan.tasks.length; i++) {
|
|
722
746
|
const t = diskPlan.tasks[i];
|
|
747
|
+
if (dbTaskIds.has(t.id)) continue;
|
|
723
748
|
try {
|
|
724
749
|
insertTask({
|
|
725
750
|
id: t.id,
|
|
@@ -729,12 +754,15 @@ async function reconcileSliceTasks(
|
|
|
729
754
|
status: t.done ? 'complete' : 'pending',
|
|
730
755
|
sequence: i + 1,
|
|
731
756
|
});
|
|
757
|
+
inserted++;
|
|
732
758
|
} catch (insertErr) {
|
|
733
759
|
logWarning("reconcile", `failed to insert task ${t.id} from plan file: ${insertErr instanceof Error ? insertErr.message : String(insertErr)}`);
|
|
734
760
|
}
|
|
735
761
|
}
|
|
736
|
-
|
|
737
|
-
|
|
762
|
+
if (inserted > 0) {
|
|
763
|
+
tasks = getSliceTasks(milestoneId, sliceId);
|
|
764
|
+
logWarning("reconcile", `imported ${inserted} missing task(s) from plan file for ${milestoneId}/${sliceId}`, { mid: milestoneId, sid: sliceId });
|
|
765
|
+
}
|
|
738
766
|
}
|
|
739
767
|
}
|
|
740
768
|
} catch (err) {
|
|
@@ -1160,7 +1188,7 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
1160
1188
|
const rc = rf ? await cachedLoadFile(rf) : null;
|
|
1161
1189
|
if (!rc) {
|
|
1162
1190
|
const sf = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
1163
|
-
if (sf) completeMilestoneIds.add(mid);
|
|
1191
|
+
if (sf && await isTerminalMilestoneSummaryFile(sf, cachedLoadFile)) completeMilestoneIds.add(mid);
|
|
1164
1192
|
continue;
|
|
1165
1193
|
}
|
|
1166
1194
|
const rmap = parseRoadmap(rc);
|
|
@@ -1169,11 +1197,11 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
1169
1197
|
// Summary is the terminal artifact — if it exists, the milestone is
|
|
1170
1198
|
// complete even when roadmap checkboxes weren't ticked (#864).
|
|
1171
1199
|
const sf = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
1172
|
-
if (sf) completeMilestoneIds.add(mid);
|
|
1200
|
+
if (sf && await isTerminalMilestoneSummaryFile(sf, cachedLoadFile)) completeMilestoneIds.add(mid);
|
|
1173
1201
|
continue;
|
|
1174
1202
|
}
|
|
1175
1203
|
const sf = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
1176
|
-
if (sf) completeMilestoneIds.add(mid);
|
|
1204
|
+
if (sf && await isTerminalMilestoneSummaryFile(sf, cachedLoadFile)) completeMilestoneIds.add(mid);
|
|
1177
1205
|
}
|
|
1178
1206
|
|
|
1179
1207
|
// Phase 2: Build registry using cached roadmaps (no re-parsing or re-reading)
|
|
@@ -1201,12 +1229,14 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
1201
1229
|
const summaryFile = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
1202
1230
|
if (summaryFile) {
|
|
1203
1231
|
const summaryContent = await cachedLoadFile(summaryFile);
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1232
|
+
if (summaryContent != null && isTerminalMilestoneSummaryContent(summaryContent)) {
|
|
1233
|
+
const summaryTitle = summaryContent
|
|
1234
|
+
? (parseSummary(summaryContent).title || mid)
|
|
1235
|
+
: mid;
|
|
1236
|
+
registry.push({ id: mid, title: summaryTitle, status: 'complete' });
|
|
1237
|
+
completeMilestoneIds.add(mid);
|
|
1238
|
+
continue;
|
|
1239
|
+
}
|
|
1210
1240
|
}
|
|
1211
1241
|
// Ghost milestone (only META.json, no CONTEXT/ROADMAP/SUMMARY) — skip entirely
|
|
1212
1242
|
if (isGhostMilestone(basePath, mid)) continue;
|
|
@@ -1262,7 +1292,7 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
1262
1292
|
// needs-remediation is terminal but requires re-validation (#3596)
|
|
1263
1293
|
const needsRevalidation = !validationTerminal || verdict === 'needs-remediation';
|
|
1264
1294
|
|
|
1265
|
-
if (summaryFile) {
|
|
1295
|
+
if (summaryFile && await isTerminalMilestoneSummaryFile(summaryFile, cachedLoadFile)) {
|
|
1266
1296
|
// Summary exists → milestone is complete regardless of validation state.
|
|
1267
1297
|
// The summary is the terminal artifact (#864).
|
|
1268
1298
|
registry.push({ id: mid, title, status: 'complete' });
|
|
@@ -1288,7 +1318,7 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
1288
1318
|
// Roadmap slices not all checked — but if a summary exists, the milestone
|
|
1289
1319
|
// is still complete. The summary is the terminal artifact (#864).
|
|
1290
1320
|
const summaryFile = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
1291
|
-
if (summaryFile) {
|
|
1321
|
+
if (summaryFile && await isTerminalMilestoneSummaryFile(summaryFile, cachedLoadFile)) {
|
|
1292
1322
|
registry.push({ id: mid, title, status: 'complete' });
|
|
1293
1323
|
} else if (!activeMilestoneFound) {
|
|
1294
1324
|
// Check milestone-level dependencies before promoting to active.
|
|
@@ -1563,32 +1593,12 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
1563
1593
|
};
|
|
1564
1594
|
}
|
|
1565
1595
|
} else {
|
|
1566
|
-
let bestFallbackLegacy: { id: string; title: string; depends: string[] } | null = null;
|
|
1567
|
-
let bestFallbackLegacySatisfied = -1;
|
|
1568
|
-
|
|
1569
1596
|
for (const s of activeRoadmap.slices) {
|
|
1570
1597
|
if (s.done) continue;
|
|
1571
1598
|
if (s.depends.every(dep => doneSliceIds.has(dep))) {
|
|
1572
1599
|
activeSlice = { id: s.id, title: s.title };
|
|
1573
1600
|
break;
|
|
1574
1601
|
}
|
|
1575
|
-
// Track best fallback
|
|
1576
|
-
const satisfied = s.depends.filter(dep => doneSliceIds.has(dep)).length;
|
|
1577
|
-
if (satisfied > bestFallbackLegacySatisfied) {
|
|
1578
|
-
bestFallbackLegacy = s;
|
|
1579
|
-
bestFallbackLegacySatisfied = satisfied;
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
// Fallback: if no slice has all deps met, pick the one with the most deps satisfied
|
|
1584
|
-
if (!activeSlice && bestFallbackLegacy) {
|
|
1585
|
-
const unmet = bestFallbackLegacy.depends.filter(dep => !doneSliceIds.has(dep));
|
|
1586
|
-
logWarning("state",
|
|
1587
|
-
`No slice has all deps satisfied — falling back to ${bestFallbackLegacy.id} ` +
|
|
1588
|
-
`(${bestFallbackLegacySatisfied}/${bestFallbackLegacy.depends.length} deps met, ` +
|
|
1589
|
-
`unmet: ${unmet.join(", ")})`,
|
|
1590
|
-
);
|
|
1591
|
-
activeSlice = { id: bestFallbackLegacy.id, title: bestFallbackLegacy.title };
|
|
1592
1602
|
}
|
|
1593
1603
|
}
|
|
1594
1604
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// GSD Extension — Advisory Sync Lock
|
|
2
2
|
// Prevents concurrent worktree syncs from colliding via a simple file lock.
|
|
3
|
-
// Stale locks (mtime > 60s) are
|
|
4
|
-
// to 5 seconds then skips non-fatally.
|
|
3
|
+
// Stale locks (mtime > 60s, owner PID confirmed dead) are overridden. Lock
|
|
4
|
+
// acquisition waits up to 5 seconds then skips non-fatally.
|
|
5
5
|
|
|
6
|
-
import { existsSync, statSync, unlinkSync } from "node:fs";
|
|
7
|
-
import { join } from "node:path";
|
|
8
|
-
import { atomicWriteSync } from "./atomic-write.js";
|
|
6
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
9
8
|
|
|
10
9
|
const STALE_THRESHOLD_MS = 60_000; // 60 seconds
|
|
11
10
|
const DEFAULT_TIMEOUT_MS = 5_000; // 5 seconds
|
|
@@ -23,13 +22,59 @@ function sleepSync(ms: number): void {
|
|
|
23
22
|
Atomics.wait(SLEEP_VIEW, 0, 0, ms);
|
|
24
23
|
}
|
|
25
24
|
|
|
25
|
+
/** True if the given PID is alive in the current process namespace. */
|
|
26
|
+
function isPidAlive(pid: number): boolean {
|
|
27
|
+
try {
|
|
28
|
+
process.kill(pid, 0);
|
|
29
|
+
return true;
|
|
30
|
+
} catch (err) {
|
|
31
|
+
if ((err as NodeJS.ErrnoException).code === "EPERM") return true;
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Atomically create the lock file with `O_EXCL` semantics. Returns true on
|
|
38
|
+
* exclusive create, false if the file already existed. Any other error
|
|
39
|
+
* propagates.
|
|
40
|
+
*/
|
|
41
|
+
function tryCreateLockFile(lp: string, payload: string): boolean {
|
|
42
|
+
// Ensure parent dir exists (`atomicWriteSync` previously did this implicitly).
|
|
43
|
+
try {
|
|
44
|
+
mkdirSync(dirname(lp), { recursive: true });
|
|
45
|
+
} catch {
|
|
46
|
+
/* best-effort */
|
|
47
|
+
}
|
|
48
|
+
let fd: number;
|
|
49
|
+
try {
|
|
50
|
+
// "wx" → O_WRONLY | O_CREAT | O_EXCL — atomic create-if-not-exists on POSIX.
|
|
51
|
+
fd = openSync(lp, "wx");
|
|
52
|
+
} catch (err) {
|
|
53
|
+
const code = (err as NodeJS.ErrnoException).code;
|
|
54
|
+
if (code === "EEXIST") return false;
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
writeSync(fd, payload);
|
|
59
|
+
} finally {
|
|
60
|
+
closeSync(fd);
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
26
65
|
/**
|
|
27
66
|
* Acquire an advisory sync lock for the given basePath.
|
|
28
67
|
* Returns { acquired: true } on success, { acquired: false } after timeout.
|
|
29
68
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
69
|
+
* Replaces a non-atomic `existsSync` + `atomicWriteSync` (write-temp+rename,
|
|
70
|
+
* which is not exclusive-create) sequence that allowed two callers to both
|
|
71
|
+
* believe they had acquired the lock, corrupting the event log.
|
|
72
|
+
* (Issue #4980 CRIT-4)
|
|
73
|
+
*
|
|
74
|
+
* Stale-lock override now also verifies the recorded owner PID is dead
|
|
75
|
+
* before stealing — prevents a slow event-loop pause (>60s under heavy I/O)
|
|
76
|
+
* from making a legitimately-held lock appear stale and get stolen.
|
|
77
|
+
* (Issue #4980 M-concurrency-3)
|
|
33
78
|
*/
|
|
34
79
|
export function acquireSyncLock(
|
|
35
80
|
basePath: string,
|
|
@@ -37,45 +82,58 @@ export function acquireSyncLock(
|
|
|
37
82
|
): { acquired: boolean } {
|
|
38
83
|
const lp = lockFilePath(basePath);
|
|
39
84
|
const deadline = Date.now() + timeoutMs;
|
|
85
|
+
const lockData = JSON.stringify(
|
|
86
|
+
{ pid: process.pid, acquired_at: new Date().toISOString() },
|
|
87
|
+
null,
|
|
88
|
+
2,
|
|
89
|
+
);
|
|
40
90
|
|
|
41
91
|
while (true) {
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const stat = statSync(lp);
|
|
47
|
-
const age = Date.now() - stat.mtimeMs;
|
|
48
|
-
if (age > STALE_THRESHOLD_MS) {
|
|
49
|
-
// Stale lock — override it
|
|
50
|
-
try { unlinkSync(lp); } catch { /* race: already removed */ }
|
|
51
|
-
} else {
|
|
52
|
-
// Lock is held and not stale — wait or give up
|
|
53
|
-
if (Date.now() >= deadline) {
|
|
54
|
-
return { acquired: false };
|
|
55
|
-
}
|
|
56
|
-
sleepSync(SPIN_INTERVAL_MS);
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
} catch {
|
|
60
|
-
// stat failed (file removed between exists check and stat) — try to acquire
|
|
92
|
+
// First try the fast path: atomic create. No check-then-write race.
|
|
93
|
+
try {
|
|
94
|
+
if (tryCreateLockFile(lp, lockData)) {
|
|
95
|
+
return { acquired: true };
|
|
61
96
|
}
|
|
97
|
+
} catch {
|
|
98
|
+
/* unexpected — fall through to retry */
|
|
62
99
|
}
|
|
63
100
|
|
|
64
|
-
//
|
|
101
|
+
// File exists. Decide whether to steal (stale + owner dead) or wait.
|
|
102
|
+
let canSteal = false;
|
|
65
103
|
try {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
104
|
+
const stat = statSync(lp);
|
|
105
|
+
const age = Date.now() - stat.mtimeMs;
|
|
106
|
+
if (age > STALE_THRESHOLD_MS) {
|
|
107
|
+
// Verify the recorded owner PID is dead before stealing.
|
|
108
|
+
let ownerAlive = false;
|
|
109
|
+
try {
|
|
110
|
+
const data = JSON.parse(readFileSync(lp, "utf-8")) as { pid?: number };
|
|
111
|
+
if (typeof data.pid === "number" && data.pid !== process.pid) {
|
|
112
|
+
ownerAlive = isPidAlive(data.pid);
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
// Lock contents unreadable — be conservative and steal only on age.
|
|
116
|
+
// A garbage lock file that we cannot parse is safer to remove than
|
|
117
|
+
// to leave wedging the lock indefinitely.
|
|
118
|
+
}
|
|
119
|
+
canSteal = !ownerAlive;
|
|
76
120
|
}
|
|
77
|
-
|
|
121
|
+
} catch {
|
|
122
|
+
// stat failed (file removed between exists and stat) — retry create.
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (canSteal) {
|
|
127
|
+
try { unlinkSync(lp); } catch { /* race: already removed */ }
|
|
128
|
+
// Loop back to retry create.
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Lock is held and not stale (or owner is alive) — wait or give up.
|
|
133
|
+
if (Date.now() >= deadline) {
|
|
134
|
+
return { acquired: false };
|
|
78
135
|
}
|
|
136
|
+
sleepSync(SPIN_INTERVAL_MS);
|
|
79
137
|
}
|
|
80
138
|
}
|
|
81
139
|
|