gsd-pi 2.81.0 → 2.82.0
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 +36 -24
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/loop.js +111 -8
- package/dist/resources/extensions/gsd/auto/phases.js +190 -97
- package/dist/resources/extensions/gsd/auto/run-unit.js +66 -3
- package/dist/resources/extensions/gsd/auto/session.js +9 -0
- package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +43 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +182 -178
- package/dist/resources/extensions/gsd/auto-dispatch.js +14 -11
- package/dist/resources/extensions/gsd/auto-post-unit.js +7 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +6 -181
- package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -0
- package/dist/resources/extensions/gsd/auto-start.js +20 -23
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +33 -5
- package/dist/resources/extensions/gsd/auto-verification.js +12 -6
- package/dist/resources/extensions/gsd/auto-worktree.js +8 -0
- package/dist/resources/extensions/gsd/auto.js +265 -76
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +13 -6
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +8 -2
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +4 -8
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +4 -10
- package/dist/resources/extensions/gsd/commands/handlers/parallel.js +9 -0
- package/dist/resources/extensions/gsd/git-service.js +2 -1
- package/dist/resources/extensions/gsd/gsd-db.js +7 -23
- package/dist/resources/extensions/gsd/health-widget-core.js +1 -1
- package/dist/resources/extensions/gsd/health-widget.js +4 -10
- package/dist/resources/extensions/gsd/markdown-renderer.js +0 -95
- package/dist/resources/extensions/gsd/native-git-bridge.js +14 -14
- package/dist/resources/extensions/gsd/notification-overlay.js +35 -40
- package/dist/resources/extensions/gsd/parallel-merge.js +53 -30
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +25 -33
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +14 -12
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
- package/dist/resources/extensions/gsd/prompts/discuss.md +20 -2
- package/dist/resources/extensions/gsd/recovery-classification.js +15 -1
- package/dist/resources/extensions/gsd/session-lock.js +40 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +131 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +247 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +50 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +87 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +50 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +124 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +32 -0
- package/dist/resources/extensions/gsd/state-reconciliation/errors.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +99 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +24 -0
- package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +43 -0
- package/dist/resources/extensions/gsd/state-reconciliation/types.js +3 -0
- package/dist/resources/extensions/gsd/state-reconciliation.js +5 -26
- package/dist/resources/extensions/gsd/tui/render-kit.js +74 -0
- package/dist/resources/extensions/gsd/watch/header-renderer.js +92 -69
- package/dist/resources/extensions/gsd/watch/splash-palette.js +10 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +722 -316
- package/dist/resources/extensions/gsd/worktree-telemetry.js +3 -1
- 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 +9 -9
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- 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/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 +9 -9
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/welcome-screen.d.ts +0 -7
- package/dist/welcome-screen.js +60 -69
- package/package.json +1 -1
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/package.json +2 -2
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js +47 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +76 -9
- 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/__tests__/user-message-design.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +30 -29
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +10 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +13 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +58 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +2 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +12 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -41
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +0 -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 +86 -82
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts +35 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js +152 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts +16 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js +73 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +12 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +105 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +27 -26
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +9 -6
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +56 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +113 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +48 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +10 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +43 -42
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +14 -14
- package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +64 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +13 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +15 -42
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -104
- package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +196 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tui-style-kit.ts +94 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +14 -9
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +106 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +27 -26
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +9 -6
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +14 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.js +9 -6
- package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +20 -1
- package/packages/pi-tui/src/overlay-layout.ts +10 -7
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +105 -1
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +27 -26
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +9 -5
- package/src/resources/extensions/gsd/auto/loop.ts +113 -9
- package/src/resources/extensions/gsd/auto/phases.ts +144 -19
- package/src/resources/extensions/gsd/auto/run-unit.ts +69 -4
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +230 -183
- package/src/resources/extensions/gsd/auto-dispatch.ts +15 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +7 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +7 -209
- package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
- package/src/resources/extensions/gsd/auto-start.ts +22 -22
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +51 -0
- package/src/resources/extensions/gsd/auto-verification.ts +12 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +8 -0
- package/src/resources/extensions/gsd/auto.ts +295 -75
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -6
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +6 -2
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +4 -10
- package/src/resources/extensions/gsd/commands/handlers/parallel.ts +12 -0
- package/src/resources/extensions/gsd/git-service.ts +2 -0
- package/src/resources/extensions/gsd/gsd-db.ts +7 -23
- package/src/resources/extensions/gsd/health-widget-core.ts +1 -1
- package/src/resources/extensions/gsd/health-widget.ts +6 -10
- package/src/resources/extensions/gsd/journal.ts +2 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +4 -95
- package/src/resources/extensions/gsd/native-git-bridge.ts +14 -13
- package/src/resources/extensions/gsd/notification-overlay.ts +50 -46
- package/src/resources/extensions/gsd/parallel-merge.ts +61 -34
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +33 -35
- package/src/resources/extensions/gsd/prompts/complete-slice.md +14 -12
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +20 -2
- package/src/resources/extensions/gsd/recovery-classification.ts +18 -1
- package/src/resources/extensions/gsd/session-lock.ts +41 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +337 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +69 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +109 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
- package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
- package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +60 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
- package/src/resources/extensions/gsd/state-reconciliation.ts +21 -53
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +654 -176
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +291 -4
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +20 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +116 -24
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +46 -11
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +78 -41
- package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +12 -217
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +38 -6
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +65 -58
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +952 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +158 -58
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +572 -118
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +18 -0
- package/src/resources/extensions/gsd/tui/render-kit.ts +109 -0
- package/src/resources/extensions/gsd/watch/header-renderer.ts +121 -79
- package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +1151 -524
- package/src/resources/extensions/gsd/worktree-telemetry.ts +7 -2
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → S44UQTFCUdA44dkjfYt6S}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → S44UQTFCUdA44dkjfYt6S}/_ssgManifest.js +0 -0
|
@@ -8,9 +8,13 @@
|
|
|
8
8
|
import { existsSync, readdirSync } from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { spawnSync } from "node:child_process";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
11
|
+
import { resolveGsdPathContract } from "./paths.js";
|
|
12
|
+
import { getAutoWorktreePath } from "./auto-worktree.js";
|
|
13
|
+
import { buildWorktreeLifecycleDeps } from "./auto.js";
|
|
14
|
+
import {
|
|
15
|
+
mergeMilestoneStandalone,
|
|
16
|
+
type MergeStandaloneResult,
|
|
17
|
+
} from "./worktree-lifecycle.js";
|
|
14
18
|
import { MergeConflictError } from "./git-service.js";
|
|
15
19
|
import { removeSessionStatus } from "./session-status-io.js";
|
|
16
20
|
import type { WorkerInfo } from "./parallel-orchestrator.js";
|
|
@@ -136,44 +140,46 @@ export function determineMergeOrder(
|
|
|
136
140
|
|
|
137
141
|
/**
|
|
138
142
|
* Attempt to merge a single milestone's worktree back to main.
|
|
139
|
-
*
|
|
143
|
+
*
|
|
144
|
+
* Routes through `WorktreeLifecycle.mergeMilestoneStandalone` so parallel
|
|
145
|
+
* callers get the same projection-finalize / roadmap-fallback / secondary-
|
|
146
|
+
* teardown invariants as the single-loop path. Closes the parallel-merge
|
|
147
|
+
* bypass that ADR-016 names (issue #5618).
|
|
140
148
|
*/
|
|
141
149
|
export async function mergeCompletedMilestone(
|
|
142
150
|
basePath: string,
|
|
143
151
|
milestoneId: string,
|
|
144
152
|
): Promise<MergeResult> {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const roadmapContent = await loadFile(roadmapPath);
|
|
157
|
-
if (!roadmapContent) {
|
|
158
|
-
return {
|
|
159
|
-
milestoneId,
|
|
160
|
-
success: false,
|
|
161
|
-
error: `Could not read roadmap for ${milestoneId}`,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
153
|
+
// Resolve the worktree path explicitly; parallel-merge has no AutoSession
|
|
154
|
+
// to read it from. Only use the worktree path when git actually knows
|
|
155
|
+
// about it (`getAutoWorktreePath` returns non-null). When the directory
|
|
156
|
+
// exists on disk but isn't a registered git worktree (e.g. a stale
|
|
157
|
+
// session-status marker dir), fall back to the project root and let the
|
|
158
|
+
// standalone's mode detection pick branch-mode or skipped — using the
|
|
159
|
+
// un-registered dir as `worktreeBasePath` would cause `getCurrentBranch`
|
|
160
|
+
// to fail with a "Worktree HEAD diverged" error.
|
|
161
|
+
const registeredWtPath = getAutoWorktreePath(basePath, milestoneId);
|
|
162
|
+
const worktreeBasePath = registeredWtPath ?? basePath;
|
|
164
163
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return {
|
|
164
|
+
let result: MergeStandaloneResult;
|
|
165
|
+
try {
|
|
166
|
+
result = mergeMilestoneStandalone(buildWorktreeLifecycleDeps(), {
|
|
167
|
+
originalBasePath: basePath,
|
|
168
|
+
worktreeBasePath,
|
|
172
169
|
milestoneId,
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
// Parallel context never runs with degraded isolation — workers only
|
|
171
|
+
// exist when isolation succeeded. Pass `false` explicitly so the
|
|
172
|
+
// standalone's degraded-skip branch is not reached.
|
|
173
|
+
isolationDegraded: false,
|
|
174
|
+
notify: (msg, level) => {
|
|
175
|
+
// Surface user-visible messages from the standalone through the
|
|
176
|
+
// workflow logger so the parallel merge's progress is visible in
|
|
177
|
+
// the same channel as the rest of the parallel orchestration.
|
|
178
|
+
if (level === "error" || level === "warning") {
|
|
179
|
+
logWarning("parallel", `${milestoneId}: ${msg}`);
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
});
|
|
177
183
|
} catch (err) {
|
|
178
184
|
if (err instanceof MergeConflictError) {
|
|
179
185
|
return {
|
|
@@ -189,6 +195,27 @@ export async function mergeCompletedMilestone(
|
|
|
189
195
|
error: getErrorMessage(err),
|
|
190
196
|
};
|
|
191
197
|
}
|
|
198
|
+
|
|
199
|
+
if (!result.merged) {
|
|
200
|
+
return {
|
|
201
|
+
milestoneId,
|
|
202
|
+
success: false,
|
|
203
|
+
error:
|
|
204
|
+
result.mode === "skipped"
|
|
205
|
+
? `Merge skipped for ${milestoneId} (mode=none or isolation degraded).`
|
|
206
|
+
: `No roadmap for ${milestoneId} — milestone branch preserved for manual merge.`,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Clean up parallel session status — only on a real merge.
|
|
211
|
+
removeSessionStatus(basePath, milestoneId);
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
milestoneId,
|
|
215
|
+
success: true,
|
|
216
|
+
commitMessage: result.commitMessage,
|
|
217
|
+
pushed: result.pushed,
|
|
218
|
+
};
|
|
192
219
|
}
|
|
193
220
|
|
|
194
221
|
/**
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Full-screen TUI overlay showing real-time parallel worker progress.
|
|
5
|
-
* Opened via `/gsd parallel watch`, Ctrl+Alt+P (⌃⌥P on macOS),
|
|
6
|
-
* or Ctrl+Shift+P fallback.
|
|
7
|
-
* Reads the same data sources as `scripts/parallel-monitor.mjs` but
|
|
8
|
-
* renders as a native pi-tui overlay with theme integration.
|
|
9
|
-
*/
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Parallel worker monitor overlay with width-safe operations-console rendering.
|
|
10
3
|
|
|
11
4
|
import { existsSync, statSync, readFileSync, openSync, readSync, closeSync, readdirSync } from "node:fs";
|
|
12
5
|
import { join } from "node:path";
|
|
13
6
|
import { spawnSync } from "node:child_process";
|
|
14
7
|
|
|
15
8
|
import type { Theme } from "@gsd/pi-coding-agent";
|
|
16
|
-
import {
|
|
9
|
+
import { matchesKey, Key } from "@gsd/pi-tui";
|
|
17
10
|
|
|
18
|
-
import { formatDuration
|
|
11
|
+
import { formatDuration } from "../shared/mod.js";
|
|
19
12
|
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
20
13
|
import { resolveGsdPathContract } from "./paths.js";
|
|
14
|
+
import {
|
|
15
|
+
renderBar,
|
|
16
|
+
renderKeyHints,
|
|
17
|
+
renderProgressBar,
|
|
18
|
+
safeLine,
|
|
19
|
+
statusGlyph,
|
|
20
|
+
} from "./tui/render-kit.js";
|
|
21
21
|
|
|
22
22
|
// ─── Types ────────────────────────────────────────────────────────────────
|
|
23
23
|
|
|
@@ -277,17 +277,6 @@ function unitTypeLabel(unitType: string | null): string {
|
|
|
277
277
|
return labels[unitType || ""] || (unitType || "---").toUpperCase().slice(0, 5);
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
function progressBar(done: number, total: number, width: number): string {
|
|
281
|
-
if (total === 0) return "░".repeat(width);
|
|
282
|
-
const filled = Math.round((done / total) * width);
|
|
283
|
-
return "█".repeat(filled) + "░".repeat(width - filled);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function healthGlyph(alive: boolean, heartbeatAge: number): string {
|
|
287
|
-
if (!alive) return "○";
|
|
288
|
-
return "●";
|
|
289
|
-
}
|
|
290
|
-
|
|
291
280
|
// ─── Overlay Class ────────────────────────────────────────────────────────
|
|
292
281
|
|
|
293
282
|
export class ParallelMonitorOverlay {
|
|
@@ -299,6 +288,7 @@ export class ParallelMonitorOverlay {
|
|
|
299
288
|
private workers: WorkerView[] = [];
|
|
300
289
|
private events: string[] = [];
|
|
301
290
|
private cachedLines?: string[];
|
|
291
|
+
private cachedWidth?: number;
|
|
302
292
|
private scrollOffset = 0;
|
|
303
293
|
private disposed = false;
|
|
304
294
|
private resizeHandler: (() => void) | null = null;
|
|
@@ -339,6 +329,7 @@ export class ParallelMonitorOverlay {
|
|
|
339
329
|
this.events = this.events.slice(-10);
|
|
340
330
|
|
|
341
331
|
this.cachedLines = undefined;
|
|
332
|
+
this.cachedWidth = undefined;
|
|
342
333
|
this.tui.requestRender();
|
|
343
334
|
}
|
|
344
335
|
|
|
@@ -378,14 +369,15 @@ export class ParallelMonitorOverlay {
|
|
|
378
369
|
|
|
379
370
|
invalidate(): void {
|
|
380
371
|
this.cachedLines = undefined;
|
|
372
|
+
this.cachedWidth = undefined;
|
|
381
373
|
}
|
|
382
374
|
|
|
383
375
|
render(width: number): string[] {
|
|
384
|
-
if (this.cachedLines) return this.cachedLines;
|
|
376
|
+
if (this.cachedLines && this.cachedWidth === width) return this.cachedLines;
|
|
385
377
|
|
|
386
378
|
const t = this.theme;
|
|
387
379
|
const lines: string[] = [];
|
|
388
|
-
const w = Math.max(
|
|
380
|
+
const w = Math.max(1, width);
|
|
389
381
|
|
|
390
382
|
// Header
|
|
391
383
|
const totalCost = this.workers.reduce((s, wk) => s + wk.cost, 0);
|
|
@@ -398,7 +390,7 @@ export class ParallelMonitorOverlay {
|
|
|
398
390
|
t.bold(`$${totalCost.toFixed(2)}`) +
|
|
399
391
|
t.fg("muted", " │ 5s refresh"),
|
|
400
392
|
);
|
|
401
|
-
lines.push(t
|
|
393
|
+
lines.push(renderBar(t, w));
|
|
402
394
|
|
|
403
395
|
if (this.workers.length === 0) {
|
|
404
396
|
lines.push("");
|
|
@@ -410,7 +402,7 @@ export class ParallelMonitorOverlay {
|
|
|
410
402
|
|
|
411
403
|
// Health + ID + state
|
|
412
404
|
const healthColor = wk.alive ? "success" : "error";
|
|
413
|
-
const glyph =
|
|
405
|
+
const glyph = statusGlyph(t, wk.alive ? "active" : "idle");
|
|
414
406
|
const stateText = wk.alive
|
|
415
407
|
? t.fg("success", "RUNNING")
|
|
416
408
|
: t.fg("error", t.bold("DEAD"));
|
|
@@ -452,25 +444,29 @@ export class ParallelMonitorOverlay {
|
|
|
452
444
|
lines.push(` ${t.fg("muted", "slices")} ${chips.join(" ")}`);
|
|
453
445
|
|
|
454
446
|
// Task progress bar
|
|
455
|
-
const
|
|
447
|
+
const barWidth = Math.max(6, Math.min(25, w - 32));
|
|
448
|
+
const bar = renderProgressBar(t, wk.doneTasks, wk.totalTasks, barWidth, {
|
|
449
|
+
filledChar: "█",
|
|
450
|
+
emptyChar: "░",
|
|
451
|
+
emptyColor: "dim",
|
|
452
|
+
});
|
|
456
453
|
const pct = wk.totalTasks > 0 ? Math.round((wk.doneTasks / wk.totalTasks) * 100) : 0;
|
|
457
454
|
lines.push(
|
|
458
|
-
` ${t.fg("muted", "tasks")} ${
|
|
455
|
+
` ${t.fg("muted", "tasks")} ${bar} ${wk.doneTasks}/${wk.totalTasks} ` +
|
|
459
456
|
t.fg("muted", `(${pct}%) │ slices done ${wk.doneSlices}/${wk.totalSlices}`),
|
|
460
457
|
);
|
|
461
458
|
}
|
|
462
459
|
|
|
463
460
|
// Errors
|
|
464
461
|
for (const err of wk.errors.slice(-2)) {
|
|
465
|
-
|
|
466
|
-
lines.push(` ${t.fg("error", "⚠ " + truncated)}`);
|
|
462
|
+
lines.push(` ${t.fg("error", "! " + err)}`);
|
|
467
463
|
}
|
|
468
464
|
}
|
|
469
465
|
}
|
|
470
466
|
|
|
471
467
|
// Event feed
|
|
472
468
|
lines.push("");
|
|
473
|
-
lines.push(t
|
|
469
|
+
lines.push(renderBar(t, w));
|
|
474
470
|
lines.push(` ${t.bold("Recent Events")}`);
|
|
475
471
|
|
|
476
472
|
if (this.events.length === 0) {
|
|
@@ -478,8 +474,7 @@ export class ParallelMonitorOverlay {
|
|
|
478
474
|
} else {
|
|
479
475
|
for (const evt of this.events.slice(-8)) {
|
|
480
476
|
const mid = evt.match(/^✓ (M\d+)\//)?.[1] || "";
|
|
481
|
-
|
|
482
|
-
lines.push(` ${t.fg("muted", "│")} ${t.fg("accent", mid)} ${truncated.replace(/^✓ M\d+\//, "")}`);
|
|
477
|
+
lines.push(` ${t.fg("muted", "│")} ${t.fg("accent", mid)} ${evt.replace(/^✓ M\d+\//, "")}`);
|
|
483
478
|
}
|
|
484
479
|
}
|
|
485
480
|
|
|
@@ -496,14 +491,17 @@ export class ParallelMonitorOverlay {
|
|
|
496
491
|
}
|
|
497
492
|
lines.push(` ${t.bold("Total: $" + this.workers.reduce((s, wk) => s + wk.cost, 0).toFixed(2))}`);
|
|
498
493
|
}
|
|
499
|
-
lines.push(t
|
|
494
|
+
lines.push(renderKeyHints(t, [`ESC/q/${formattedShortcutPair("parallel")} close`, "↑↓ scroll"], w));
|
|
500
495
|
|
|
501
496
|
// Apply scroll — use terminal rows as height estimate
|
|
502
497
|
const termHeight = process.stdout.rows || 40;
|
|
503
498
|
const maxScroll = Math.max(0, lines.length - termHeight);
|
|
504
499
|
this.scrollOffset = Math.min(Math.max(this.scrollOffset, 0), maxScroll);
|
|
505
|
-
const visible = lines
|
|
500
|
+
const visible = lines
|
|
501
|
+
.slice(this.scrollOffset, this.scrollOffset + termHeight)
|
|
502
|
+
.map((line) => safeLine(line, w));
|
|
506
503
|
this.cachedLines = visible;
|
|
504
|
+
this.cachedWidth = width;
|
|
507
505
|
return visible;
|
|
508
506
|
}
|
|
509
507
|
}
|
|
@@ -22,22 +22,24 @@ Use `subagent` only for fresh-context review when useful: reviewer for cross-cut
|
|
|
22
22
|
|
|
23
23
|
1. Use the inlined Slice Summary and UAT templates.
|
|
24
24
|
2. {{skillActivation}}
|
|
25
|
-
3. Run all slice-level verification checks from the slice plan
|
|
26
|
-
4.
|
|
27
|
-
5.
|
|
28
|
-
6.
|
|
29
|
-
7. If
|
|
30
|
-
8.
|
|
31
|
-
9.
|
|
32
|
-
10.
|
|
33
|
-
11.
|
|
34
|
-
12.
|
|
35
|
-
13.
|
|
25
|
+
3. Run all slice-level verification checks from the slice plan through the closeout-safe verification surface (`gsd_exec` / Context Mode verification evidence); refresh current state if needed. Do not use direct `bash` for verification commands.
|
|
26
|
+
4. Complete the slice only when every required verification check passes. If verification fails or the fix requires source changes, do **not** edit source files in this unit and do **not** call `gsd_slice_complete`.
|
|
27
|
+
5. For task-specific failures, call `gsd_task_reopen` with the failing completed task and a concrete reason so execution can redo the work. For plan-invalidating failures, call `gsd_replan_slice` with the blocker and updated execution tasks. Then stop with: "Slice {{sliceId}} needs execution follow-up."
|
|
28
|
+
6. Task summaries use a flat file layout under `tasks/` such as `T01-SUMMARY.md`, not inside per-task subdirectories like `tasks/T01/SUMMARY.md`. Never use `tasks/*/SUMMARY.md`.
|
|
29
|
+
7. If observability/diagnostics were planned, verify them unless the slice is simple.
|
|
30
|
+
8. Address every gate in Gates to Close. Q8 maps to **Operational Readiness**: health signal, failure signal, recovery procedure, monitoring gaps. Empty sections are recorded as omitted.
|
|
31
|
+
9. If requirement status changed, call `gsd_requirement_update`; do not write `.gsd/REQUIREMENTS.md` directly.
|
|
32
|
+
10. Prepare `gsd_slice_complete` content with camelCase fields `milestoneId`, `sliceId`, `sliceTitle`, `oneLiner`, `narrative`, `verification`, and `uatContent`.
|
|
33
|
+
11. Draft concrete UAT with preconditions, numbered steps, expected outcomes, edge cases, UAT Type, and Not Proven By This UAT.
|
|
34
|
+
12. Review the inlined task-summary excerpts for DECISIONS.md and KNOWLEDGE.md-worthy decisions, patterns, and gotchas. Read full `*-SUMMARY.md` files only when an excerpt is absent, truncated, or lacks the specific evidence needed for the slice narrative. Capture significant items with `capture_thought`; do not append knowledge files directly.
|
|
35
|
+
13. When verification passes, call `gsd_slice_complete`. The DB-backed tool is the canonical write path. Do **not** manually write `{{sliceSummaryPath}}`. Do **not** manually write `{{sliceUatPath}}`. Do not edit roadmap checkboxes; the tool renders files and updates projections.
|
|
36
|
+
14. Do not run git commands.
|
|
37
|
+
15. Update `.gsd/PROJECT.md` with a full `write` only if the current project state needs refresh.
|
|
36
38
|
|
|
37
39
|
**Autonomous execution:** no human is available. Do not call `ask_user_questions` or `secure_env_collect`; make reasonable assumptions and document them.
|
|
38
40
|
|
|
39
41
|
**File system safety:** if re-reading task summaries, use `find .gsd/milestones/{{milestoneId}}/slices/{{sliceId}}/tasks -name "*-SUMMARY.md"` or `ls .gsd/milestones/{{milestoneId}}/slices/{{sliceId}}/tasks/*-SUMMARY.md`. Never pass `{{slicePath}}` or any directory path directly to the `read` tool.
|
|
40
42
|
|
|
41
|
-
**You MUST call `gsd_slice_complete` with summary and UAT content before finishing.**
|
|
43
|
+
**You MUST call `gsd_slice_complete` with summary and UAT content before finishing only after verification passes.**
|
|
42
44
|
|
|
43
45
|
When done, say: "Slice {{sliceId}} complete."
|
|
@@ -129,7 +129,16 @@ If ANY box is unchecked, **STOP**. Do NOT emit the ready phrase. Emit the missin
|
|
|
129
129
|
|
|
130
130
|
Do not announce the ready phrase as something you are "about to" do. The ready phrase is a post-write signal, not an intent signal.
|
|
131
131
|
|
|
132
|
-
After completing steps 1–7 above,
|
|
132
|
+
After completing steps 1–7 above, end with this concise user-facing handoff:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
Milestone {{milestoneId}} ready.
|
|
136
|
+
|
|
137
|
+
Next steps:
|
|
138
|
+
- Run `/gsd auto` to start execution if it does not begin automatically.
|
|
139
|
+
- Use `/gsd status` or `/gsd visualize` to inspect the roadmap.
|
|
140
|
+
- Use `/gsd notifications` to review or configure delivery alerts.
|
|
141
|
+
```
|
|
133
142
|
|
|
134
143
|
### Multi-Milestone
|
|
135
144
|
|
|
@@ -215,7 +224,16 @@ If ANY box is unchecked, **STOP**. Do NOT emit the ready phrase. Emit the missin
|
|
|
215
224
|
|
|
216
225
|
Do not announce the ready phrase as something you are "about to" do. The ready phrase is a post-write signal, not an intent signal.
|
|
217
226
|
|
|
218
|
-
After completing every step above,
|
|
227
|
+
After completing every step above, end with this concise user-facing handoff:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
Milestone {{milestoneId}} ready.
|
|
231
|
+
|
|
232
|
+
Next steps:
|
|
233
|
+
- Run `/gsd auto` to start execution if it does not begin automatically.
|
|
234
|
+
- Use `/gsd status` or `/gsd visualize` to inspect the roadmap.
|
|
235
|
+
- Use `/gsd notifications` to review or configure delivery alerts.
|
|
236
|
+
```
|
|
219
237
|
|
|
220
238
|
## Critical Rules
|
|
221
239
|
|
|
@@ -252,7 +252,16 @@ If ANY box is unchecked, **STOP**. Do NOT emit the ready phrase. Emit the missin
|
|
|
252
252
|
|
|
253
253
|
Do not announce the ready phrase as something you are "about to" do. It is a post-write signal, not intent.
|
|
254
254
|
|
|
255
|
-
After completing steps 1–7 above,
|
|
255
|
+
After completing steps 1–7 above, end with this concise user-facing handoff:
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
Milestone {{milestoneId}} ready.
|
|
259
|
+
|
|
260
|
+
Next steps:
|
|
261
|
+
- Run `/gsd auto` to start execution if it does not begin automatically.
|
|
262
|
+
- Use `/gsd status` or `/gsd visualize` to inspect the roadmap.
|
|
263
|
+
- Use `/gsd notifications` to review or configure delivery alerts.
|
|
264
|
+
```
|
|
256
265
|
|
|
257
266
|
### Multi-Milestone
|
|
258
267
|
|
|
@@ -345,6 +354,15 @@ If ANY box is unchecked, **STOP**. Do NOT emit the ready phrase. Emit the missin
|
|
|
345
354
|
|
|
346
355
|
Do not announce the ready phrase as something you are "about to" do. It is a post-write signal, not intent.
|
|
347
356
|
|
|
348
|
-
After completing all phases above,
|
|
357
|
+
After completing all phases above, end with this concise user-facing handoff:
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
Milestone M001 ready.
|
|
361
|
+
|
|
362
|
+
Next steps:
|
|
363
|
+
- Run `/gsd auto` to start execution if it does not begin automatically.
|
|
364
|
+
- Use `/gsd status` or `/gsd visualize` to inspect the roadmap.
|
|
365
|
+
- Use `/gsd notifications` to review or configure delivery alerts.
|
|
366
|
+
```
|
|
349
367
|
|
|
350
368
|
{{inlinedTemplates}}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// File Purpose: ADR-015 Recovery Classification module for runtime failure taxonomy.
|
|
3
3
|
|
|
4
4
|
import { classifyError, isTransient, type ErrorClass } from "./error-classifier.js";
|
|
5
|
+
import { ReconciliationFailedError } from "./state-reconciliation.js";
|
|
5
6
|
|
|
6
7
|
export type RecoveryFailureKind =
|
|
7
8
|
| "tool-schema"
|
|
@@ -9,6 +10,7 @@ export type RecoveryFailureKind =
|
|
|
9
10
|
| "stale-worker"
|
|
10
11
|
| "worktree-invalid"
|
|
11
12
|
| "verification-drift"
|
|
13
|
+
| "reconciliation-drift"
|
|
12
14
|
| "provider"
|
|
13
15
|
| "runtime-unknown";
|
|
14
16
|
|
|
@@ -33,7 +35,13 @@ export interface RecoveryClassification {
|
|
|
33
35
|
|
|
34
36
|
export function classifyFailure(input: RecoveryClassificationInput): RecoveryClassification {
|
|
35
37
|
const message = errorMessage(input.error);
|
|
36
|
-
|
|
38
|
+
// ADR-017: ReconciliationFailedError is a typed throw from the State
|
|
39
|
+
// Reconciliation Module. Recognize it by class regardless of caller-supplied
|
|
40
|
+
// failureKind so the taxonomy stays consistent.
|
|
41
|
+
const failureKind =
|
|
42
|
+
input.error instanceof ReconciliationFailedError
|
|
43
|
+
? "reconciliation-drift"
|
|
44
|
+
: input.failureKind ?? inferFailureKind(message);
|
|
37
45
|
|
|
38
46
|
switch (failureKind) {
|
|
39
47
|
case "tool-schema":
|
|
@@ -76,6 +84,15 @@ export function classifyFailure(input: RecoveryClassificationInput): RecoveryCla
|
|
|
76
84
|
exitReason: "verification-drift",
|
|
77
85
|
remediation: "Inspect the verification artifact and reconcile the state snapshot before resuming.",
|
|
78
86
|
};
|
|
87
|
+
case "reconciliation-drift":
|
|
88
|
+
return {
|
|
89
|
+
failureKind,
|
|
90
|
+
action: "escalate",
|
|
91
|
+
reason: `Reconciliation drift${unitSuffix(input)}: ${message}`,
|
|
92
|
+
exitReason: "reconciliation-drift",
|
|
93
|
+
remediation:
|
|
94
|
+
"Inspect the persistent or repair-failed drift kinds reported by the State Reconciliation Module before resuming.",
|
|
95
|
+
};
|
|
79
96
|
case "provider": {
|
|
80
97
|
const providerClass = classifyError(message, input.retryAfterMs);
|
|
81
98
|
return {
|
|
@@ -597,6 +597,47 @@ export function isSessionLockProcessAlive(data: SessionLockData): boolean {
|
|
|
597
597
|
return isPidAlive(data.pid);
|
|
598
598
|
}
|
|
599
599
|
|
|
600
|
+
/**
|
|
601
|
+
* ADR-017 raw primitive: remove orphaned lock artifacts (lock dir + lock file)
|
|
602
|
+
* when the recorded PID is dead or no metadata is present. Mirrors the
|
|
603
|
+
* pre-flight cleanup logic in acquireSessionLock so the stale-worker drift
|
|
604
|
+
* handler can clear the orphan proactively without going through the full
|
|
605
|
+
* acquire path. No-op when the lock is held by an alive process.
|
|
606
|
+
*
|
|
607
|
+
* Returns true when artifacts were removed (drift was present).
|
|
608
|
+
*/
|
|
609
|
+
export function removeStaleSessionLock(basePath: string): boolean {
|
|
610
|
+
const lp = lockPath(basePath);
|
|
611
|
+
const gsdDir = gsdRoot(basePath);
|
|
612
|
+
const lockTarget = effectiveLockTarget(gsdDir);
|
|
613
|
+
const lockDir = lockTarget + ".lock";
|
|
614
|
+
|
|
615
|
+
const existingData = readExistingLockData(lp);
|
|
616
|
+
const isOrphan =
|
|
617
|
+
!existingData ||
|
|
618
|
+
(typeof existingData.pid === "number" && !isPidAlive(existingData.pid));
|
|
619
|
+
if (!isOrphan) return false;
|
|
620
|
+
|
|
621
|
+
let removed = false;
|
|
622
|
+
if (existsSync(lockDir)) {
|
|
623
|
+
try {
|
|
624
|
+
rmSync(lockDir, { recursive: true, force: true });
|
|
625
|
+
removed = true;
|
|
626
|
+
} catch {
|
|
627
|
+
/* best-effort */
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
if (existsSync(lp)) {
|
|
631
|
+
try {
|
|
632
|
+
unlinkSync(lp);
|
|
633
|
+
removed = true;
|
|
634
|
+
} catch {
|
|
635
|
+
/* best-effort */
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return removed;
|
|
639
|
+
}
|
|
640
|
+
|
|
600
641
|
/**
|
|
601
642
|
* Returns true if we currently hold a session lock for the given path.
|
|
602
643
|
*/
|