gsd-pi 2.81.0 → 2.82.0-dev.725028083
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 +60 -30
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
- package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
- package/dist/resources/extensions/gsd/auto/loop.js +111 -8
- package/dist/resources/extensions/gsd/auto/phases.js +199 -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-prompts.js +11 -3
- 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 +13 -2
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +4 -8
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
- 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/commands-handlers.js +15 -2
- package/dist/resources/extensions/gsd/context-store.js +112 -0
- package/dist/resources/extensions/gsd/db-writer.js +150 -84
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
- 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/knowledge-backfill.js +144 -0
- package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
- package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
- package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +6 -96
- package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
- 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/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
- 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/templates/knowledge.md +2 -2
- 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 +15 -15
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- 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.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +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/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.d.ts +0 -7
- package/dist/welcome-screen.js +60 -69
- package/package.json +3 -2
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +2 -0
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -2
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -1
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/index.ts +7 -2
- package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +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/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
- 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/src/tests/system-prompt-file-safety.test.ts +22 -0
- 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/browser-tools/tools/screenshot.ts +1 -0
- package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
- 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 +158 -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-prompts.ts +11 -3
- 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 +12 -2
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
- 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/commands-handlers.ts +19 -2
- package/src/resources/extensions/gsd/context-store.ts +120 -1
- package/src/resources/extensions/gsd/db-writer.ts +167 -84
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
- package/src/resources/extensions/gsd/doctor-types.ts +2 -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/knowledge-backfill.ts +164 -0
- package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
- package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
- package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +10 -96
- package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
- 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/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
- 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/templates/knowledge.md +2 -2
- 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 +729 -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/browser-tools-compatibility-declarations.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
- 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/freeform-decisions.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
- 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/doctor-git.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
- 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/knowledge-backfill-projection.test.ts +323 -0
- package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
- package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
- 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/plan-milestone-sketch-render.test.ts +157 -0
- 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 +32 -1
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- 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-start-footer.test.ts +16 -4
- 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-logger.ts +4 -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/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → KDRTXR-22LPCsa80X9dey}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → KDRTXR-22LPCsa80X9dey}/_ssgManifest.js +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// GSD2 — Decisions -> memories backfill (ADR-013 step 5)
|
|
2
2
|
//
|
|
3
|
-
// Idempotent
|
|
4
|
-
// the memories table with
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// Idempotent migration that copies every decisions row (active and
|
|
4
|
+
// superseded — see Stage 2a note below) into the memories table with
|
|
5
|
+
// category="architecture" and a structured_fields payload preserving the
|
|
6
|
+
// original gsd_save_decision schema (when_context, scope, decision, choice,
|
|
7
|
+
// rationale, made_by, revisable, superseded_by, sourceDecisionId).
|
|
7
8
|
//
|
|
8
9
|
// The backfill exists so the cutover in ADR-013 step 6 can drop the
|
|
9
10
|
// decisions table without losing schema fidelity. Idempotency is enforced
|
|
@@ -14,11 +15,18 @@
|
|
|
14
15
|
// only ever fires once per project. Costs O(N) inserts on first run where
|
|
15
16
|
// N is the active-decisions count; subsequent runs are an O(N) lookup that
|
|
16
17
|
// finds existing markers and exits.
|
|
18
|
+
//
|
|
19
|
+
// ADR-013 Stage 2a (PR #5755): backfill now includes superseded rows so the
|
|
20
|
+
// DECISIONS.md projection regen can source from memories without losing
|
|
21
|
+
// historical entries. An auto-heal pass runs after the initial migration to
|
|
22
|
+
// pick up superseded_by changes that occurred after the source decision was
|
|
23
|
+
// already migrated (e.g. a fresh md-importer run that introduced a new
|
|
24
|
+
// supersedes-chain).
|
|
17
25
|
import { isDbAvailable, _getAdapter } from "./gsd-db.js";
|
|
18
26
|
import { createMemory } from "./memory-store.js";
|
|
19
27
|
import { logWarning } from "./workflow-logger.js";
|
|
20
28
|
/**
|
|
21
|
-
* Backfill
|
|
29
|
+
* Backfill decisions rows into the memories table.
|
|
22
30
|
*
|
|
23
31
|
* - Idempotent (per-row): every row written carries
|
|
24
32
|
* `structured_fields.sourceDecisionId = "<decisionId>"`. Each candidate
|
|
@@ -27,13 +35,18 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
27
35
|
* their own `sourceDecisionId` does NOT abort the backfill.
|
|
28
36
|
* - Best-effort: never throws. Logs and returns 0 on failure so a broken
|
|
29
37
|
* backfill cannot block agent startup.
|
|
30
|
-
* -
|
|
31
|
-
*
|
|
32
|
-
*
|
|
38
|
+
* - Full migration (ADR-013 Stage 2a): both active and superseded rows are
|
|
39
|
+
* migrated. `structured_fields.superseded_by` preserves the supersedes
|
|
40
|
+
* chain so the DECISIONS.md projection regen can source from memories
|
|
41
|
+
* without losing historical entries.
|
|
42
|
+
* - Drift auto-heal: after the initial insert pass, the function updates
|
|
43
|
+
* any pre-existing memory whose `structured_fields.superseded_by` drifted
|
|
44
|
+
* from the source decision (e.g. a fresh md-importer run introduced a
|
|
45
|
+
* new supersedes annotation after the initial migration).
|
|
33
46
|
*
|
|
34
47
|
* Returns the number of memories written (0 when already backfilled or
|
|
35
|
-
* when the DB has no decisions).
|
|
36
|
-
*
|
|
48
|
+
* when the DB has no decisions). Drift-heal updates are not counted in
|
|
49
|
+
* this return — they are logged separately.
|
|
37
50
|
*/
|
|
38
51
|
export function backfillDecisionsToMemories() {
|
|
39
52
|
if (!isDbAvailable())
|
|
@@ -43,7 +56,7 @@ export function backfillDecisionsToMemories() {
|
|
|
43
56
|
return 0;
|
|
44
57
|
try {
|
|
45
58
|
const decisions = adapter
|
|
46
|
-
.prepare("SELECT id, when_context, scope, decision, choice, rationale, made_by, revisable, superseded_by FROM decisions
|
|
59
|
+
.prepare("SELECT id, when_context, scope, decision, choice, rationale, made_by, revisable, superseded_by FROM decisions ORDER BY seq")
|
|
47
60
|
.all();
|
|
48
61
|
if (decisions.length === 0)
|
|
49
62
|
return 0;
|
|
@@ -52,8 +65,10 @@ export function backfillDecisionsToMemories() {
|
|
|
52
65
|
// per row by matching that exact id, NOT by a global sentinel — a global
|
|
53
66
|
// sentinel would silently abort the backfill if a user manually called
|
|
54
67
|
// capture_thought with their own structuredFields.sourceDecisionId.
|
|
55
|
-
const checkExisting = adapter.prepare("SELECT
|
|
68
|
+
const checkExisting = adapter.prepare("SELECT id, structured_fields FROM memories WHERE structured_fields LIKE :pattern LIMIT 1");
|
|
69
|
+
const updateStructuredFields = adapter.prepare("UPDATE memories SET structured_fields = :sf, updated_at = :ts WHERE id = :id");
|
|
56
70
|
let written = 0;
|
|
71
|
+
let healed = 0;
|
|
57
72
|
for (const raw of decisions) {
|
|
58
73
|
const row = {
|
|
59
74
|
id: String(raw["id"] ?? ""),
|
|
@@ -68,11 +83,40 @@ export function backfillDecisionsToMemories() {
|
|
|
68
83
|
};
|
|
69
84
|
if (!row.id)
|
|
70
85
|
continue;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (
|
|
86
|
+
const pattern = `%"sourceDecisionId":"${row.id}"%`;
|
|
87
|
+
const existing = checkExisting.get({ ":pattern": pattern });
|
|
88
|
+
if (existing) {
|
|
89
|
+
// Drift auto-heal: if the source decision's superseded_by has changed
|
|
90
|
+
// since the original migration, update the memory in place. Read-side
|
|
91
|
+
// queries reconstruct Decision.superseded_by from this field, so the
|
|
92
|
+
// DECISIONS.md projection stays accurate without us having to track
|
|
93
|
+
// supersedes events at the write site.
|
|
94
|
+
const parsedSf = existing.structured_fields
|
|
95
|
+
? safeParse(existing.structured_fields)
|
|
96
|
+
: {};
|
|
97
|
+
if (existing.structured_fields && !parsedSf) {
|
|
98
|
+
logWarning("memory-backfill", `decisions->memories drift heal skipped for ${row.id}: invalid structured_fields JSON`);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const currentSf = parsedSf ?? {};
|
|
102
|
+
const memorySuperseded = typeof currentSf["superseded_by"] === "string" || currentSf["superseded_by"] === null
|
|
103
|
+
? currentSf["superseded_by"]
|
|
104
|
+
: null;
|
|
105
|
+
if (memorySuperseded !== row.superseded_by) {
|
|
106
|
+
const merged = {
|
|
107
|
+
...currentSf,
|
|
108
|
+
superseded_by: row.superseded_by,
|
|
109
|
+
};
|
|
110
|
+
updateStructuredFields.run({
|
|
111
|
+
":id": existing.id,
|
|
112
|
+
":sf": JSON.stringify(merged),
|
|
113
|
+
":ts": new Date().toISOString(),
|
|
114
|
+
});
|
|
115
|
+
healed += 1;
|
|
116
|
+
}
|
|
74
117
|
continue;
|
|
75
|
-
|
|
118
|
+
}
|
|
119
|
+
const content = synthesizeDecisionMemoryContent(row);
|
|
76
120
|
const id = createMemory({
|
|
77
121
|
category: "architecture",
|
|
78
122
|
content,
|
|
@@ -87,11 +131,15 @@ export function backfillDecisionsToMemories() {
|
|
|
87
131
|
rationale: row.rationale,
|
|
88
132
|
made_by: row.made_by,
|
|
89
133
|
revisable: row.revisable,
|
|
134
|
+
superseded_by: row.superseded_by,
|
|
90
135
|
},
|
|
91
136
|
});
|
|
92
137
|
if (id)
|
|
93
138
|
written += 1;
|
|
94
139
|
}
|
|
140
|
+
if (healed > 0) {
|
|
141
|
+
logWarning("memory-backfill", `decisions->memories drift healed: ${healed} row${healed === 1 ? "" : "s"} updated superseded_by`);
|
|
142
|
+
}
|
|
95
143
|
return written;
|
|
96
144
|
}
|
|
97
145
|
catch (e) {
|
|
@@ -99,6 +147,14 @@ export function backfillDecisionsToMemories() {
|
|
|
99
147
|
return 0;
|
|
100
148
|
}
|
|
101
149
|
}
|
|
150
|
+
function safeParse(raw) {
|
|
151
|
+
try {
|
|
152
|
+
return JSON.parse(raw);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
102
158
|
/**
|
|
103
159
|
* Combine the decision's structured fields into a 1-3 sentence content
|
|
104
160
|
* string suitable for keyword retrieval and human review.
|
|
@@ -107,7 +163,7 @@ export function backfillDecisionsToMemories() {
|
|
|
107
163
|
* Truncates each field to keep the synthesized line under ~600 chars so
|
|
108
164
|
* memory_query rendering stays readable.
|
|
109
165
|
*/
|
|
110
|
-
function
|
|
166
|
+
export function synthesizeDecisionMemoryContent(row) {
|
|
111
167
|
const trim = (value, max) => {
|
|
112
168
|
const cleaned = value.replace(/\s+/g, " ").trim();
|
|
113
169
|
return cleaned.length > max ? cleaned.slice(0, max - 1) + "\u2026" : cleaned;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// GSD-2 — ADR-013 Phase 6 preflight scanner.
|
|
2
|
+
//
|
|
3
|
+
// Read-only detection of rows in the legacy knowledge surfaces (decisions
|
|
4
|
+
// table, `.gsd/KNOWLEDGE.md`) that lack a corresponding `memories` row.
|
|
5
|
+
// Runs on session start (and on demand via doctor); never mutates state.
|
|
6
|
+
//
|
|
7
|
+
// The scanner exists so the destructive Phase 6 cutover (#5755) can prove
|
|
8
|
+
// the migration is complete before any tables are dropped. Today's
|
|
9
|
+
// `backfillDecisionsToMemories` writes a `structured_fields.sourceDecisionId`
|
|
10
|
+
// marker on each migrated row; the scanner uses that marker for decisions
|
|
11
|
+
// detection. A `sourceKnowledgeId` marker is reserved for the parallel
|
|
12
|
+
// KNOWLEDGE.md backfill that Phase 6 will introduce — until that ships,
|
|
13
|
+
// every KNOWLEDGE.md row is reported as unmigrated, which is the honest
|
|
14
|
+
// state of the consolidation.
|
|
15
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
16
|
+
import { _getAdapter, isDbAvailable } from "./gsd-db.js";
|
|
17
|
+
import { appendNotification } from "./notification-store.js";
|
|
18
|
+
import { resolveGsdRootFile } from "./paths.js";
|
|
19
|
+
import { logWarning } from "./workflow-logger.js";
|
|
20
|
+
// ─── KNOWLEDGE.md parsing ────────────────────────────────────────────────────
|
|
21
|
+
const KNOWLEDGE_SECTIONS = [
|
|
22
|
+
{ table: "rules", heading: "## Rules", idPrefix: "K" },
|
|
23
|
+
{ table: "patterns", heading: "## Patterns", idPrefix: "P" },
|
|
24
|
+
{ table: "lessons", heading: "## Lessons Learned", idPrefix: "L" },
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Parse `.gsd/KNOWLEDGE.md` into rows, one per table entry. Skips the table
|
|
28
|
+
* header and separator lines; ignores rows from unrecognized sections.
|
|
29
|
+
*
|
|
30
|
+
* The format is locked in `files.ts:appendKnowledge` — three `## ` sections
|
|
31
|
+
* (Rules, Patterns, Lessons Learned), each a Markdown table. Row IDs are
|
|
32
|
+
* `K###` / `P###` / `L###`.
|
|
33
|
+
*/
|
|
34
|
+
export function parseKnowledgeRows(content) {
|
|
35
|
+
const rows = [];
|
|
36
|
+
if (!content.trim())
|
|
37
|
+
return rows;
|
|
38
|
+
// Slice the content into sections by heading. The leading text before the
|
|
39
|
+
// first ## heading is intro prose — ignored.
|
|
40
|
+
const lines = content.split("\n");
|
|
41
|
+
let activeSection;
|
|
42
|
+
for (const line of lines) {
|
|
43
|
+
const trimmed = line.trim();
|
|
44
|
+
if (trimmed.startsWith("## ")) {
|
|
45
|
+
activeSection = KNOWLEDGE_SECTIONS.find((s) => s.heading === trimmed);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (!activeSection)
|
|
49
|
+
continue;
|
|
50
|
+
if (!trimmed.startsWith("|"))
|
|
51
|
+
continue;
|
|
52
|
+
// Skip the table header rows: the column-titles line and the |---|---| separator.
|
|
53
|
+
// Real data rows start with `| <prefix>### |`.
|
|
54
|
+
const idMatch = new RegExp(`^\\|\\s*(${activeSection.idPrefix}\\d+)\\s*\\|`).exec(trimmed);
|
|
55
|
+
if (!idMatch)
|
|
56
|
+
continue;
|
|
57
|
+
rows.push({
|
|
58
|
+
table: activeSection.table,
|
|
59
|
+
id: idMatch[1] ?? "",
|
|
60
|
+
row: trimmed,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return rows;
|
|
64
|
+
}
|
|
65
|
+
function knowledgeMdContent(basePath) {
|
|
66
|
+
const path = resolveGsdRootFile(basePath, "KNOWLEDGE");
|
|
67
|
+
if (!existsSync(path))
|
|
68
|
+
return "";
|
|
69
|
+
try {
|
|
70
|
+
return readFileSync(path, "utf-8");
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function getActiveDecisions() {
|
|
77
|
+
if (!isDbAvailable())
|
|
78
|
+
return [];
|
|
79
|
+
const adapter = _getAdapter();
|
|
80
|
+
if (!adapter)
|
|
81
|
+
return [];
|
|
82
|
+
try {
|
|
83
|
+
const rows = adapter
|
|
84
|
+
.prepare("SELECT id, decision FROM decisions WHERE superseded_by IS NULL")
|
|
85
|
+
.all();
|
|
86
|
+
return rows
|
|
87
|
+
.map((row) => ({
|
|
88
|
+
id: String(row["id"] ?? ""),
|
|
89
|
+
decision: String(row["decision"] ?? ""),
|
|
90
|
+
}))
|
|
91
|
+
.filter((row) => row.id.length > 0);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* True when a memory row has a `structured_fields` JSON payload containing
|
|
99
|
+
* the given `markerKey: "value"` pair. Matches the LIKE pattern used by
|
|
100
|
+
* `backfillDecisionsToMemories` so the scanner is consistent with the
|
|
101
|
+
* backfill's idempotency check.
|
|
102
|
+
*/
|
|
103
|
+
function memoryHasSourceMarker(markerKey, value) {
|
|
104
|
+
if (!isDbAvailable())
|
|
105
|
+
return false;
|
|
106
|
+
const adapter = _getAdapter();
|
|
107
|
+
if (!adapter)
|
|
108
|
+
return false;
|
|
109
|
+
try {
|
|
110
|
+
const pattern = `%"${markerKey}":"${value}"%`;
|
|
111
|
+
const row = adapter
|
|
112
|
+
.prepare("SELECT 1 FROM memories WHERE structured_fields LIKE :pattern LIMIT 1")
|
|
113
|
+
.get({ ":pattern": pattern });
|
|
114
|
+
return row !== undefined;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
121
|
+
const SAMPLE_LIMIT = 5;
|
|
122
|
+
/**
|
|
123
|
+
* Scan the legacy knowledge surfaces and return a structured report of what's
|
|
124
|
+
* already in the `memories` table vs what's still unmigrated. Pure detection
|
|
125
|
+
* — no DB writes, no file writes, no notifications.
|
|
126
|
+
*/
|
|
127
|
+
export function scanConsolidationGaps(basePath) {
|
|
128
|
+
// ── Decisions ────────────────────────────────────────────────────────
|
|
129
|
+
const decisions = getActiveDecisions();
|
|
130
|
+
const decisionSamples = [];
|
|
131
|
+
let decisionMigrated = 0;
|
|
132
|
+
for (const decision of decisions) {
|
|
133
|
+
if (memoryHasSourceMarker("sourceDecisionId", decision.id)) {
|
|
134
|
+
decisionMigrated += 1;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (decisionSamples.length < SAMPLE_LIMIT) {
|
|
138
|
+
decisionSamples.push({
|
|
139
|
+
id: decision.id,
|
|
140
|
+
decision: decision.decision.length > 80 ? decision.decision.slice(0, 79) + "…" : decision.decision,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// ── KNOWLEDGE.md ─────────────────────────────────────────────────────
|
|
145
|
+
const knowledgeRows = parseKnowledgeRows(knowledgeMdContent(basePath));
|
|
146
|
+
const knowledgeByTable = { rules: 0, patterns: 0, lessons: 0 };
|
|
147
|
+
const knowledgeSamples = [];
|
|
148
|
+
let knowledgeMigrated = 0;
|
|
149
|
+
for (const row of knowledgeRows) {
|
|
150
|
+
knowledgeByTable[row.table] += 1;
|
|
151
|
+
// Phase 6 will introduce a `sourceKnowledgeId` marker as part of the
|
|
152
|
+
// KNOWLEDGE.md backfill. Until that path ships, this check returns
|
|
153
|
+
// false for every row, which is the honest state of the consolidation.
|
|
154
|
+
if (memoryHasSourceMarker("sourceKnowledgeId", row.id)) {
|
|
155
|
+
knowledgeMigrated += 1;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (knowledgeSamples.length < SAMPLE_LIMIT) {
|
|
159
|
+
knowledgeSamples.push({
|
|
160
|
+
table: row.table,
|
|
161
|
+
id: row.id,
|
|
162
|
+
row: row.row.length > 100 ? row.row.slice(0, 99) + "…" : row.row,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const decisionsReport = {
|
|
167
|
+
total: decisions.length,
|
|
168
|
+
migrated: decisionMigrated,
|
|
169
|
+
unmigrated: decisions.length - decisionMigrated,
|
|
170
|
+
samples: decisionSamples,
|
|
171
|
+
};
|
|
172
|
+
const knowledgeReport = {
|
|
173
|
+
total: knowledgeRows.length,
|
|
174
|
+
migrated: knowledgeMigrated,
|
|
175
|
+
unmigrated: knowledgeRows.length - knowledgeMigrated,
|
|
176
|
+
byTable: knowledgeByTable,
|
|
177
|
+
samples: knowledgeSamples,
|
|
178
|
+
};
|
|
179
|
+
const totalGaps = decisionsReport.unmigrated + knowledgeReport.unmigrated;
|
|
180
|
+
// Summary line is intentionally short so it fits in a single notification
|
|
181
|
+
// (notification-store truncates messages over 500 chars). Detail is
|
|
182
|
+
// accessible via getProviderSwitchStats-style callers, not embedded here.
|
|
183
|
+
const parts = [];
|
|
184
|
+
if (decisionsReport.unmigrated > 0) {
|
|
185
|
+
parts.push(`${decisionsReport.unmigrated} of ${decisionsReport.total} active decisions`);
|
|
186
|
+
}
|
|
187
|
+
if (knowledgeReport.unmigrated > 0) {
|
|
188
|
+
parts.push(`${knowledgeReport.unmigrated} of ${knowledgeReport.total} KNOWLEDGE.md rows`);
|
|
189
|
+
}
|
|
190
|
+
const summary = parts.length === 0
|
|
191
|
+
? "Memory consolidation: all decisions and KNOWLEDGE.md rows are in memories."
|
|
192
|
+
: `Memory consolidation: ${parts.join(" and ")} not yet in memories table. Run /doctor for details.`;
|
|
193
|
+
return { decisions: decisionsReport, knowledge: knowledgeReport, totalGaps, summary };
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Run the scanner and emit a persistent notification + workflow-logger
|
|
197
|
+
* warning when gaps exist. Best-effort: never throws; a broken scanner
|
|
198
|
+
* cannot block agent startup.
|
|
199
|
+
*
|
|
200
|
+
* Returns the full {@link ConsolidationGapReport} regardless of whether gaps
|
|
201
|
+
* exist (including when `totalGaps === 0`). Returns `null` only when
|
|
202
|
+
* `scanConsolidationGaps` itself throws. `appendNotification` and
|
|
203
|
+
* `logWarning` are called only when `report.totalGaps > 0`.
|
|
204
|
+
*
|
|
205
|
+
* Idempotent at the surface: the notification store applies its own
|
|
206
|
+
* 30-second dedup window keyed on (severity, source, message), so repeated
|
|
207
|
+
* boots with identical gaps produce one notification, not a flood.
|
|
208
|
+
*/
|
|
209
|
+
export function reportConsolidationGaps(basePath) {
|
|
210
|
+
try {
|
|
211
|
+
const report = scanConsolidationGaps(basePath);
|
|
212
|
+
if (report.totalGaps === 0)
|
|
213
|
+
return report;
|
|
214
|
+
appendNotification(report.summary, "warning", "workflow-logger");
|
|
215
|
+
logWarning("memory-consolidation", report.summary);
|
|
216
|
+
return report;
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
logWarning("memory-consolidation", `scanner failed: ${e.message}`);
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -551,21 +551,21 @@ export function nativeAddAll(basePath) {
|
|
|
551
551
|
export function nativeAddTracked(basePath) {
|
|
552
552
|
gitFileExec(basePath, ["add", "-u"]);
|
|
553
553
|
}
|
|
554
|
-
function
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
// exit 1 means this form is not ignored; try the next variant
|
|
566
|
-
}
|
|
554
|
+
export function nativeIsIgnored(basePath, path) {
|
|
555
|
+
try {
|
|
556
|
+
execFileSync("git", ["check-ignore", "-q", "--", path], {
|
|
557
|
+
cwd: basePath,
|
|
558
|
+
stdio: "pipe",
|
|
559
|
+
env: GIT_NO_PROMPT_ENV,
|
|
560
|
+
});
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
563
|
+
catch {
|
|
564
|
+
return false;
|
|
567
565
|
}
|
|
568
|
-
|
|
566
|
+
}
|
|
567
|
+
function isDotGsdIgnored(basePath) {
|
|
568
|
+
return [".gsd", ".gsd/"].some(path => nativeIsIgnored(basePath, path));
|
|
569
569
|
}
|
|
570
570
|
/**
|
|
571
571
|
* Determine whether the project opts out of GSD-managed `.gitignore` via
|
|
@@ -1,11 +1,25 @@
|
|
|
1
|
-
// GSD
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
import { truncateToWidth, visibleWidth, wrapTextWithAnsi, matchesKey, Key } from "@gsd/pi-tui";
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Notification history overlay with severity filtering and width-safe TUI rendering.
|
|
3
|
+
import { truncateToWidth, visibleWidth, matchesKey, Key } from "@gsd/pi-tui";
|
|
5
4
|
import { readNotifications, markAllRead, clearNotifications, onNotificationStoreChange, } from "./notification-store.js";
|
|
6
5
|
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
7
|
-
import {
|
|
8
|
-
const FILTER_CYCLE = ["all", "error", "warning", "info"];
|
|
6
|
+
import { padRightVisible, renderFrame, renderKeyHints, rightAlign, wrapVisibleText, } from "./tui/render-kit.js";
|
|
7
|
+
const FILTER_CYCLE = ["all", "error", "warning", "success", "info"];
|
|
8
|
+
const OVERLAY_WIDTH = "58%";
|
|
9
|
+
const OVERLAY_MIN_WIDTH = 68;
|
|
10
|
+
const OVERLAY_MAX_HEIGHT_PERCENT = 52;
|
|
11
|
+
const OVERLAY_MARGIN = { top: 2, right: 2, bottom: 6, left: 2 };
|
|
12
|
+
export function notificationOverlayOptions() {
|
|
13
|
+
return {
|
|
14
|
+
width: OVERLAY_WIDTH,
|
|
15
|
+
minWidth: OVERLAY_MIN_WIDTH,
|
|
16
|
+
maxHeight: `${OVERLAY_MAX_HEIGHT_PERCENT}%`,
|
|
17
|
+
anchor: "top-center",
|
|
18
|
+
row: "24%",
|
|
19
|
+
margin: OVERLAY_MARGIN,
|
|
20
|
+
backdrop: true,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
9
23
|
function severityIcon(severity) {
|
|
10
24
|
switch (severity) {
|
|
11
25
|
case "error": return "✗";
|
|
@@ -15,15 +29,6 @@ function severityIcon(severity) {
|
|
|
15
29
|
default: return "●";
|
|
16
30
|
}
|
|
17
31
|
}
|
|
18
|
-
/** Column-aware word wrap using pi-tui's native wrapper (handles unicode/ANSI). */
|
|
19
|
-
function wrapText(text, maxWidth) {
|
|
20
|
-
if (maxWidth <= 0)
|
|
21
|
-
return [text];
|
|
22
|
-
const lines = wrapTextWithAnsi(text, maxWidth);
|
|
23
|
-
// Safety clamp: if any line still exceeds maxWidth (e.g. unbreakable long token),
|
|
24
|
-
// truncate it with an ellipsis so it cannot bleed past the box border.
|
|
25
|
-
return lines.map((l) => visibleWidth(l) > maxWidth ? truncateToWidth(l, maxWidth, "…") : l);
|
|
26
|
-
}
|
|
27
32
|
function formatTimestamp(ts) {
|
|
28
33
|
try {
|
|
29
34
|
const d = new Date(ts);
|
|
@@ -155,12 +160,15 @@ export class GSDNotificationOverlay {
|
|
|
155
160
|
return this.cachedLines;
|
|
156
161
|
}
|
|
157
162
|
const content = this.buildContentLines(width);
|
|
158
|
-
const
|
|
163
|
+
const terminalRows = process.stdout.rows || 32;
|
|
164
|
+
const availableRows = Math.max(1, terminalRows - OVERLAY_MARGIN.top - OVERLAY_MARGIN.bottom);
|
|
165
|
+
const overlayRows = Math.min(availableRows, Math.max(1, Math.floor((terminalRows * OVERLAY_MAX_HEIGHT_PERCENT) / 100)));
|
|
166
|
+
const maxVisibleRows = Math.max(5, overlayRows - 2);
|
|
159
167
|
const visibleContentRows = Math.min(content.length, maxVisibleRows);
|
|
160
168
|
const maxScroll = Math.max(0, content.length - visibleContentRows);
|
|
161
169
|
this.scrollOffset = Math.min(this.scrollOffset, maxScroll);
|
|
162
170
|
const visibleContent = content.slice(this.scrollOffset, this.scrollOffset + visibleContentRows);
|
|
163
|
-
const lines = this.
|
|
171
|
+
const lines = renderFrame(this.theme, visibleContent, width);
|
|
164
172
|
this.cachedWidth = width;
|
|
165
173
|
this.cachedLines = lines;
|
|
166
174
|
return lines;
|
|
@@ -192,30 +200,14 @@ export class GSDNotificationOverlay {
|
|
|
192
200
|
this.tui.requestRender();
|
|
193
201
|
}
|
|
194
202
|
}
|
|
195
|
-
wrapInBox(inner, width) {
|
|
196
|
-
const th = this.theme;
|
|
197
|
-
const border = (s) => th.fg("borderAccent", s);
|
|
198
|
-
const innerWidth = width - 4;
|
|
199
|
-
const lines = [];
|
|
200
|
-
lines.push(border("╭" + "─".repeat(width - 2) + "╮"));
|
|
201
|
-
for (const line of inner) {
|
|
202
|
-
const truncated = truncateToWidth(line, innerWidth);
|
|
203
|
-
const padWidth = Math.max(0, innerWidth - visibleWidth(truncated));
|
|
204
|
-
lines.push(border("│") + " " + truncated + " ".repeat(padWidth) + " " + border("│"));
|
|
205
|
-
}
|
|
206
|
-
lines.push(border("╰" + "─".repeat(width - 2) + "╯"));
|
|
207
|
-
return lines;
|
|
208
|
-
}
|
|
209
203
|
buildContentLines(width) {
|
|
210
204
|
const th = this.theme;
|
|
211
|
-
const shellWidth = width - 4;
|
|
212
|
-
const contentWidth =
|
|
213
|
-
const sidePad = Math.max(0, Math.floor((shellWidth - contentWidth) / 2));
|
|
214
|
-
const leftMargin = " ".repeat(sidePad);
|
|
205
|
+
const shellWidth = Math.max(1, width - 4);
|
|
206
|
+
const contentWidth = shellWidth;
|
|
215
207
|
const lines = [];
|
|
216
208
|
const row = (content = "") => {
|
|
217
209
|
const truncated = truncateToWidth(content, contentWidth);
|
|
218
|
-
return
|
|
210
|
+
return padRightVisible(truncated, contentWidth);
|
|
219
211
|
};
|
|
220
212
|
const blank = () => row("");
|
|
221
213
|
const hr = () => row(th.fg("dim", "─".repeat(contentWidth)));
|
|
@@ -223,13 +215,16 @@ export class GSDNotificationOverlay {
|
|
|
223
215
|
const title = th.fg("accent", th.bold("Notifications"));
|
|
224
216
|
const filterLabel = this.filter === "all"
|
|
225
217
|
? th.fg("dim", "all")
|
|
226
|
-
: th.fg(this.filter === "error" ? "error"
|
|
218
|
+
: th.fg(this.filter === "error" ? "error"
|
|
219
|
+
: this.filter === "warning" ? "warning"
|
|
220
|
+
: this.filter === "success" ? "success"
|
|
221
|
+
: "dim", this.filter);
|
|
227
222
|
const count = `${this.filteredEntries.length} entries`;
|
|
228
|
-
lines.push(row(
|
|
223
|
+
lines.push(row(rightAlign(`${title} ${th.fg("dim", "filter:")} ${filterLabel}`, th.fg("dim", count), contentWidth)));
|
|
229
224
|
lines.push(hr());
|
|
230
225
|
// Controls
|
|
231
226
|
const closeShortcut = formattedShortcutPair("notifications");
|
|
232
|
-
lines.push(row(th
|
|
227
|
+
lines.push(row(renderKeyHints(th, ["↑/↓ scroll", "f filter", "c clear", `Esc/${closeShortcut} close`], contentWidth)));
|
|
233
228
|
lines.push(blank());
|
|
234
229
|
// Entries
|
|
235
230
|
const filtered = this.filteredEntries;
|
|
@@ -254,7 +249,7 @@ export class GSDNotificationOverlay {
|
|
|
254
249
|
const prefixWidth = visibleWidth(prefix);
|
|
255
250
|
const msgMaxWidth = Math.max(10, contentWidth - prefixWidth);
|
|
256
251
|
// Wrap long messages onto continuation lines indented to align with message start
|
|
257
|
-
const msgLines =
|
|
252
|
+
const msgLines = wrapVisibleText(entry.message, msgMaxWidth);
|
|
258
253
|
const indent = " ".repeat(prefixWidth);
|
|
259
254
|
for (let i = 0; i < msgLines.length; i++) {
|
|
260
255
|
if (i === 0) {
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
import { existsSync, readdirSync } from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { spawnSync } from "node:child_process";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { resolveGsdPathContract } from "./paths.js";
|
|
11
|
+
import { getAutoWorktreePath } from "./auto-worktree.js";
|
|
12
|
+
import { buildWorktreeLifecycleDeps } from "./auto.js";
|
|
13
|
+
import { mergeMilestoneStandalone, } from "./worktree-lifecycle.js";
|
|
13
14
|
import { MergeConflictError } from "./git-service.js";
|
|
14
15
|
import { removeSessionStatus } from "./session-status-io.js";
|
|
15
16
|
import { getErrorMessage } from "./error-utils.js";
|
|
@@ -105,37 +106,42 @@ export function determineMergeOrder(workers, order = "sequential", basePath) {
|
|
|
105
106
|
}
|
|
106
107
|
/**
|
|
107
108
|
* Attempt to merge a single milestone's worktree back to main.
|
|
108
|
-
*
|
|
109
|
+
*
|
|
110
|
+
* Routes through `WorktreeLifecycle.mergeMilestoneStandalone` so parallel
|
|
111
|
+
* callers get the same projection-finalize / roadmap-fallback / secondary-
|
|
112
|
+
* teardown invariants as the single-loop path. Closes the parallel-merge
|
|
113
|
+
* bypass that ADR-016 names (issue #5618).
|
|
109
114
|
*/
|
|
110
115
|
export async function mergeCompletedMilestone(basePath, milestoneId) {
|
|
116
|
+
// Resolve the worktree path explicitly; parallel-merge has no AutoSession
|
|
117
|
+
// to read it from. Only use the worktree path when git actually knows
|
|
118
|
+
// about it (`getAutoWorktreePath` returns non-null). When the directory
|
|
119
|
+
// exists on disk but isn't a registered git worktree (e.g. a stale
|
|
120
|
+
// session-status marker dir), fall back to the project root and let the
|
|
121
|
+
// standalone's mode detection pick branch-mode or skipped — using the
|
|
122
|
+
// un-registered dir as `worktreeBasePath` would cause `getCurrentBranch`
|
|
123
|
+
// to fail with a "Worktree HEAD diverged" error.
|
|
124
|
+
const registeredWtPath = getAutoWorktreePath(basePath, milestoneId);
|
|
125
|
+
const worktreeBasePath = registeredWtPath ?? basePath;
|
|
126
|
+
let result;
|
|
111
127
|
try {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return {
|
|
116
|
-
milestoneId,
|
|
117
|
-
success: false,
|
|
118
|
-
error: `No roadmap found for ${milestoneId}`,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
const roadmapContent = await loadFile(roadmapPath);
|
|
122
|
-
if (!roadmapContent) {
|
|
123
|
-
return {
|
|
124
|
-
milestoneId,
|
|
125
|
-
success: false,
|
|
126
|
-
error: `Could not read roadmap for ${milestoneId}`,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
// Attempt the merge
|
|
130
|
-
const result = mergeMilestoneToMain(basePath, milestoneId, roadmapContent);
|
|
131
|
-
// Clean up parallel session status
|
|
132
|
-
removeSessionStatus(basePath, milestoneId);
|
|
133
|
-
return {
|
|
128
|
+
result = mergeMilestoneStandalone(buildWorktreeLifecycleDeps(), {
|
|
129
|
+
originalBasePath: basePath,
|
|
130
|
+
worktreeBasePath,
|
|
134
131
|
milestoneId,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
132
|
+
// Parallel context never runs with degraded isolation — workers only
|
|
133
|
+
// exist when isolation succeeded. Pass `false` explicitly so the
|
|
134
|
+
// standalone's degraded-skip branch is not reached.
|
|
135
|
+
isolationDegraded: false,
|
|
136
|
+
notify: (msg, level) => {
|
|
137
|
+
// Surface user-visible messages from the standalone through the
|
|
138
|
+
// workflow logger so the parallel merge's progress is visible in
|
|
139
|
+
// the same channel as the rest of the parallel orchestration.
|
|
140
|
+
if (level === "error" || level === "warning") {
|
|
141
|
+
logWarning("parallel", `${milestoneId}: ${msg}`);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
});
|
|
139
145
|
}
|
|
140
146
|
catch (err) {
|
|
141
147
|
if (err instanceof MergeConflictError) {
|
|
@@ -152,6 +158,23 @@ export async function mergeCompletedMilestone(basePath, milestoneId) {
|
|
|
152
158
|
error: getErrorMessage(err),
|
|
153
159
|
};
|
|
154
160
|
}
|
|
161
|
+
if (!result.merged) {
|
|
162
|
+
return {
|
|
163
|
+
milestoneId,
|
|
164
|
+
success: false,
|
|
165
|
+
error: result.mode === "skipped"
|
|
166
|
+
? `Merge skipped for ${milestoneId} (mode=none or isolation degraded).`
|
|
167
|
+
: `No roadmap for ${milestoneId} — milestone branch preserved for manual merge.`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
// Clean up parallel session status — only on a real merge.
|
|
171
|
+
removeSessionStatus(basePath, milestoneId);
|
|
172
|
+
return {
|
|
173
|
+
milestoneId,
|
|
174
|
+
success: true,
|
|
175
|
+
commitMessage: result.commitMessage,
|
|
176
|
+
pushed: result.pushed,
|
|
177
|
+
};
|
|
155
178
|
}
|
|
156
179
|
/**
|
|
157
180
|
* Merge all completed milestones in sequence.
|