gsd-pi 2.81.0 → 2.82.0-dev.ed17d078d
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/orchestrator.js +113 -6
- 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 +386 -106
- 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/md-importer.js +1 -1
- 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/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- 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 +6 -6
- 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 +6 -6
- 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/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.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/src/tui.ts +6 -0
- 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/contracts.ts +46 -11
- 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/orchestrator.ts +118 -6
- 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 +424 -106
- 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/md-importer.ts +1 -1
- 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/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- 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-orchestrator.test.ts +408 -4
- 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 +20 -5
- 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/migrate-command.test.ts +48 -3
- 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/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
- 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 → YEvjuT-fsFfYQhDSWtueS}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → YEvjuT-fsFfYQhDSWtueS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: ADR-017 roadmap-divergence drift handler. Detects mismatches
|
|
3
|
+
// between ROADMAP.md (parsed slice sequence + depends declarations) and the
|
|
4
|
+
// DB slice rows for that milestone, then reconciles via the markdown
|
|
5
|
+
// importer plus an explicit junction-table sync.
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { getMilestone, getMilestoneSlices, isDbAvailable, syncSliceDependencies, } from "../../gsd-db.js";
|
|
8
|
+
import { migrateHierarchyToDb } from "../../md-importer.js";
|
|
9
|
+
import { findMilestoneIds } from "../../milestone-ids.js";
|
|
10
|
+
import { parseRoadmap } from "../../parsers-legacy.js";
|
|
11
|
+
import { resolveMilestoneFile } from "../../paths.js";
|
|
12
|
+
function arraysEqual(a, b) {
|
|
13
|
+
if (a.length !== b.length)
|
|
14
|
+
return false;
|
|
15
|
+
for (let i = 0; i < a.length; i++)
|
|
16
|
+
if (a[i] !== b[i])
|
|
17
|
+
return false;
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
function milestoneHasDivergence(basePath, milestoneId) {
|
|
21
|
+
const roadmapPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
|
|
22
|
+
if (!roadmapPath || !existsSync(roadmapPath))
|
|
23
|
+
return false;
|
|
24
|
+
let roadmap;
|
|
25
|
+
try {
|
|
26
|
+
roadmap = parseRoadmap(readFileSync(roadmapPath, "utf-8"));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const dbSlices = getMilestoneSlices(milestoneId);
|
|
32
|
+
const dbSliceMap = new Map(dbSlices.map((s) => [s.id, s]));
|
|
33
|
+
for (let i = 0; i < roadmap.slices.length; i++) {
|
|
34
|
+
const roadmapSlice = roadmap.slices[i];
|
|
35
|
+
const expectedSequence = i + 1;
|
|
36
|
+
const dbSlice = dbSliceMap.get(roadmapSlice.id);
|
|
37
|
+
if (!dbSlice)
|
|
38
|
+
return true; // Roadmap has a slice the DB doesn't.
|
|
39
|
+
if (dbSlice.sequence !== expectedSequence)
|
|
40
|
+
return true;
|
|
41
|
+
if (!arraysEqual(dbSlice.depends, roadmapSlice.depends))
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
export function detectRoadmapDivergenceDrift(_state, ctx) {
|
|
47
|
+
if (!isDbAvailable())
|
|
48
|
+
return [];
|
|
49
|
+
const drifts = [];
|
|
50
|
+
for (const milestoneId of findMilestoneIds(ctx.basePath)) {
|
|
51
|
+
// Skip milestones that don't yet have a DB row — that's the
|
|
52
|
+
// unregistered-milestone drift handler's responsibility.
|
|
53
|
+
if (!getMilestone(milestoneId))
|
|
54
|
+
continue;
|
|
55
|
+
if (milestoneHasDivergence(ctx.basePath, milestoneId)) {
|
|
56
|
+
drifts.push({ kind: "roadmap-divergence", milestoneId });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return drifts;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Repair a milestone's roadmap divergence:
|
|
63
|
+
* 1. migrateHierarchyToDb upserts slice rows (sequence + depends JSON
|
|
64
|
+
* update via ON CONFLICT DO UPDATE).
|
|
65
|
+
* 2. syncSliceDependencies updates the junction table per slice — the
|
|
66
|
+
* importer only writes the JSON column, not the relational view.
|
|
67
|
+
*/
|
|
68
|
+
export function repairRoadmapDivergence(record, ctx) {
|
|
69
|
+
migrateHierarchyToDb(ctx.basePath);
|
|
70
|
+
const roadmapPath = resolveMilestoneFile(ctx.basePath, record.milestoneId, "ROADMAP");
|
|
71
|
+
if (!roadmapPath || !existsSync(roadmapPath))
|
|
72
|
+
return;
|
|
73
|
+
try {
|
|
74
|
+
const roadmap = parseRoadmap(readFileSync(roadmapPath, "utf-8"));
|
|
75
|
+
for (const slice of roadmap.slices) {
|
|
76
|
+
syncSliceDependencies(record.milestoneId, slice.id, slice.depends);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
/* parse failure: detector will fire again next pass */
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export const roadmapDivergenceHandler = {
|
|
84
|
+
kind: "roadmap-divergence",
|
|
85
|
+
detect: detectRoadmapDivergenceDrift,
|
|
86
|
+
repair: repairRoadmapDivergence,
|
|
87
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: ADR-017 stale-sketch-flag drift handler. Relocated from
|
|
3
|
+
// gsd-db.ts where autoHealSketchFlags previously lived with zero callers.
|
|
4
|
+
//
|
|
5
|
+
// Recovers from two scenarios (per ADR-011):
|
|
6
|
+
// 1. Crash between gsd_plan_slice's PLAN.md write and the sketch flag flip.
|
|
7
|
+
// 2. Flag-OFF downgrade: when progressive_planning is off, dispatch routes
|
|
8
|
+
// sketch slices to plan-slice, which writes PLAN.md but leaves
|
|
9
|
+
// is_sketch=1 — the next reconciliation pass clears it.
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
11
|
+
import { getSketchedSliceIds, isDbAvailable, setSliceSketchFlag, } from "../../gsd-db.js";
|
|
12
|
+
import { resolveSliceFile } from "../../paths.js";
|
|
13
|
+
export function detectStaleSketchFlags(state, ctx) {
|
|
14
|
+
if (!isDbAvailable())
|
|
15
|
+
return [];
|
|
16
|
+
const mid = state.activeMilestone?.id;
|
|
17
|
+
if (!mid)
|
|
18
|
+
return [];
|
|
19
|
+
const sliceIds = getSketchedSliceIds(mid);
|
|
20
|
+
return sliceIds
|
|
21
|
+
.filter((sid) => {
|
|
22
|
+
const planPath = resolveSliceFile(ctx.basePath, mid, sid, "PLAN");
|
|
23
|
+
return planPath !== null && existsSync(planPath);
|
|
24
|
+
})
|
|
25
|
+
.map((sid) => ({ kind: "stale-sketch-flag", mid, sid }));
|
|
26
|
+
}
|
|
27
|
+
export function repairStaleSketchFlag(record) {
|
|
28
|
+
setSliceSketchFlag(record.mid, record.sid, false);
|
|
29
|
+
}
|
|
30
|
+
export const sketchFlagHandler = {
|
|
31
|
+
kind: "stale-sketch-flag",
|
|
32
|
+
detect: detectStaleSketchFlags,
|
|
33
|
+
repair: (record) => {
|
|
34
|
+
repairStaleSketchFlag(record);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Legacy entry point preserved for callers that supply a custom hasPlanFile
|
|
39
|
+
* predicate. Prefer the drift handler (sketchFlagHandler) for new code.
|
|
40
|
+
*/
|
|
41
|
+
export function autoHealSketchFlags(milestoneId, hasPlanFile) {
|
|
42
|
+
if (!isDbAvailable())
|
|
43
|
+
return;
|
|
44
|
+
const sliceIds = getSketchedSliceIds(milestoneId);
|
|
45
|
+
for (const sid of sliceIds) {
|
|
46
|
+
if (hasPlanFile(sid)) {
|
|
47
|
+
setSliceSketchFlag(milestoneId, sid, false);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: ADR-017 stale-render drift handler. Relocated from
|
|
3
|
+
// markdown-renderer.ts as part of issue #5702. detectStaleRenders stays in
|
|
4
|
+
// markdown-renderer.ts (it's a useful diagnostic primitive on its own); only
|
|
5
|
+
// the detect+repair composition moves here. The previous repairStaleRenders
|
|
6
|
+
// had zero callers in production code — wiring it through
|
|
7
|
+
// reconcileBeforeDispatch closes that gap.
|
|
8
|
+
import { detectStaleRenders, renderPlanCheckboxes, renderRoadmapCheckboxes, renderSliceSummary, renderTaskSummary, } from "../../markdown-renderer.js";
|
|
9
|
+
import { logWarning } from "../../workflow-logger.js";
|
|
10
|
+
// ─── Core (basePath-only — usable by both drift API and legacy wrapper) ──────
|
|
11
|
+
function detectStaleRenderDriftFromBasePath(basePath) {
|
|
12
|
+
const entries = detectStaleRenders(basePath);
|
|
13
|
+
if (entries.length === 0)
|
|
14
|
+
return [];
|
|
15
|
+
// detectStaleRenders may emit multiple entries for the same path (one per
|
|
16
|
+
// mismatched checkbox). Dedupe by path; the repair re-renders the whole
|
|
17
|
+
// file in a single call. Prefer a reason the repair dispatcher can handle.
|
|
18
|
+
const seen = new Map();
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
const currentReason = seen.get(entry.path);
|
|
21
|
+
if (currentReason === undefined ||
|
|
22
|
+
(!isRepairableStaleRenderReason(currentReason) && isRepairableStaleRenderReason(entry.reason))) {
|
|
23
|
+
seen.set(entry.path, entry.reason);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return Array.from(seen.entries()).map(([renderPath, reason]) => ({
|
|
27
|
+
kind: "stale-render",
|
|
28
|
+
renderPath,
|
|
29
|
+
reason,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
function isRepairableStaleRenderReason(reason) {
|
|
33
|
+
return (reason.includes("in roadmap") ||
|
|
34
|
+
reason.includes("in plan") ||
|
|
35
|
+
(reason.includes("SUMMARY.md missing") && /^T\d+/.test(reason)) ||
|
|
36
|
+
(reason.includes("SUMMARY.md missing") && /^S\d+/.test(reason)) ||
|
|
37
|
+
reason.includes("UAT.md missing"));
|
|
38
|
+
}
|
|
39
|
+
async function repairStaleRenderFromBasePath(record, basePath) {
|
|
40
|
+
const normPath = record.renderPath.replace(/\\/g, "/");
|
|
41
|
+
const reason = record.reason;
|
|
42
|
+
if (reason.includes("in roadmap")) {
|
|
43
|
+
const milestoneMatch = normPath.match(/milestones\/([^/]+)\//);
|
|
44
|
+
if (!milestoneMatch) {
|
|
45
|
+
throw new Error(`stale-render drift: roadmap path missing milestone segment: ${record.renderPath}`);
|
|
46
|
+
}
|
|
47
|
+
await renderRoadmapCheckboxes(basePath, milestoneMatch[1]);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (reason.includes("in plan")) {
|
|
51
|
+
const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
|
|
52
|
+
if (!pathMatch) {
|
|
53
|
+
throw new Error(`stale-render drift: plan path missing milestone/slice segments: ${record.renderPath}`);
|
|
54
|
+
}
|
|
55
|
+
await renderPlanCheckboxes(basePath, pathMatch[1], pathMatch[2]);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (reason.includes("SUMMARY.md missing") && /^T\d+/.test(reason)) {
|
|
59
|
+
const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\/tasks\//);
|
|
60
|
+
const taskMatch = reason.match(/^(T\d+)/);
|
|
61
|
+
if (!pathMatch || !taskMatch) {
|
|
62
|
+
throw new Error(`stale-render drift: task summary path/reason malformed: ${record.renderPath} reason=${reason}`);
|
|
63
|
+
}
|
|
64
|
+
await renderTaskSummary(basePath, pathMatch[1], pathMatch[2], taskMatch[1]);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (reason.includes("SUMMARY.md missing") && /^S\d+/.test(reason)) {
|
|
68
|
+
const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
|
|
69
|
+
if (!pathMatch) {
|
|
70
|
+
throw new Error(`stale-render drift: slice summary path missing milestone/slice segments: ${record.renderPath}`);
|
|
71
|
+
}
|
|
72
|
+
await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (reason.includes("UAT.md missing")) {
|
|
76
|
+
const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
|
|
77
|
+
if (!pathMatch) {
|
|
78
|
+
throw new Error(`stale-render drift: UAT path missing milestone/slice segments: ${record.renderPath}`);
|
|
79
|
+
}
|
|
80
|
+
// renderSliceSummary handles both SUMMARY and UAT.
|
|
81
|
+
await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`stale-render drift: detector emitted unknown reason "${reason}" for ${record.renderPath}`);
|
|
85
|
+
}
|
|
86
|
+
// ─── Drift Handler API ───────────────────────────────────────────────────────
|
|
87
|
+
export function detectStaleRenderDrift(_state, ctx) {
|
|
88
|
+
return detectStaleRenderDriftFromBasePath(ctx.basePath);
|
|
89
|
+
}
|
|
90
|
+
export async function repairStaleRender(record, ctx) {
|
|
91
|
+
await repairStaleRenderFromBasePath(record, ctx.basePath);
|
|
92
|
+
}
|
|
93
|
+
export const staleRenderHandler = {
|
|
94
|
+
kind: "stale-render",
|
|
95
|
+
detect: detectStaleRenderDrift,
|
|
96
|
+
repair: repairStaleRender,
|
|
97
|
+
};
|
|
98
|
+
// ─── Legacy entry point ──────────────────────────────────────────────────────
|
|
99
|
+
/**
|
|
100
|
+
* Legacy bulk entry preserved for existing tests
|
|
101
|
+
* (tests/markdown-renderer.test.ts, tests/integration/integration-proof.test.ts).
|
|
102
|
+
* New code prefers the drift handler via `reconcileBeforeDispatch`. Matches the
|
|
103
|
+
* pre-ADR-017 behavior: silent per-entry error handling, returns the count of
|
|
104
|
+
* successful repairs.
|
|
105
|
+
*/
|
|
106
|
+
export async function repairStaleRenders(basePath) {
|
|
107
|
+
const drifts = detectStaleRenderDriftFromBasePath(basePath);
|
|
108
|
+
if (drifts.length === 0)
|
|
109
|
+
return 0;
|
|
110
|
+
let repaired = 0;
|
|
111
|
+
for (const drift of drifts) {
|
|
112
|
+
try {
|
|
113
|
+
await repairStaleRenderFromBasePath(drift, basePath);
|
|
114
|
+
repaired++;
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
logWarning("renderer", `repair failed for ${drift.renderPath}: ${err.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (repaired > 0) {
|
|
121
|
+
process.stderr.write(`markdown-renderer: repaired ${repaired} stale render(s)\n`);
|
|
122
|
+
}
|
|
123
|
+
return repaired;
|
|
124
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: ADR-017 stale-worker drift handler. Detects session-lock
|
|
3
|
+
// artifacts whose owning PID is no longer alive (typical after SIGKILL or
|
|
4
|
+
// laptop sleep where the heartbeat wasn't released cleanly), and clears them
|
|
5
|
+
// before the next dispatch attempts to acquire the lock.
|
|
6
|
+
import { effectiveLockFile, isSessionLockProcessAlive, readSessionLockData, removeStaleSessionLock, } from "../../session-lock.js";
|
|
7
|
+
export function detectStaleWorkerDrift(_state, ctx) {
|
|
8
|
+
const data = readSessionLockData(ctx.basePath);
|
|
9
|
+
if (!data)
|
|
10
|
+
return [];
|
|
11
|
+
if (typeof data.pid !== "number")
|
|
12
|
+
return [];
|
|
13
|
+
if (isSessionLockProcessAlive(data))
|
|
14
|
+
return [];
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
kind: "stale-worker",
|
|
18
|
+
lockPath: effectiveLockFile(),
|
|
19
|
+
pid: data.pid,
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
export function repairStaleWorker(_record, ctx) {
|
|
24
|
+
// removeStaleSessionLock is idempotent: it re-reads lock state and is a
|
|
25
|
+
// no-op when the lock is held by an alive process. Safe under cap=2 retry.
|
|
26
|
+
removeStaleSessionLock(ctx.basePath);
|
|
27
|
+
}
|
|
28
|
+
export const staleWorkerHandler = {
|
|
29
|
+
kind: "stale-worker",
|
|
30
|
+
detect: detectStaleWorkerDrift,
|
|
31
|
+
repair: repairStaleWorker,
|
|
32
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: ADR-017 typed reconciliation failure for Recovery Classification.
|
|
3
|
+
/**
|
|
4
|
+
* Thrown by reconcileBeforeDispatch when:
|
|
5
|
+
* - one or more repair functions throw within a pass (`failures` populated), or
|
|
6
|
+
* - drift persists after the cap=2 lifecycle (`persistentDrift` populated).
|
|
7
|
+
*
|
|
8
|
+
* Recovery Classification recognizes this error via instanceof and maps it to
|
|
9
|
+
* failureKind "reconciliation-drift" with action "escalate".
|
|
10
|
+
*/
|
|
11
|
+
export class ReconciliationFailedError extends Error {
|
|
12
|
+
failures;
|
|
13
|
+
detectionFailures;
|
|
14
|
+
persistentDrift;
|
|
15
|
+
pass;
|
|
16
|
+
constructor(opts) {
|
|
17
|
+
super(formatMessage(opts));
|
|
18
|
+
this.name = "ReconciliationFailedError";
|
|
19
|
+
this.failures = opts.failures ?? [];
|
|
20
|
+
this.detectionFailures = opts.detectionFailures ?? [];
|
|
21
|
+
this.persistentDrift = opts.persistentDrift ?? [];
|
|
22
|
+
this.pass = opts.pass;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function formatMessage(opts) {
|
|
26
|
+
if (opts.detectionFailures && opts.detectionFailures.length > 0) {
|
|
27
|
+
const kinds = opts.detectionFailures.map((f) => f.handlerKind).join(", ");
|
|
28
|
+
const passSuffix = opts.pass !== undefined ? ` in pass ${opts.pass}` : "";
|
|
29
|
+
return `Reconciliation detect failed${passSuffix} for handlers: ${kinds}`;
|
|
30
|
+
}
|
|
31
|
+
if (opts.failures && opts.failures.length > 0) {
|
|
32
|
+
const kinds = opts.failures.map((f) => f.drift.kind).join(", ");
|
|
33
|
+
const passSuffix = opts.pass !== undefined ? ` in pass ${opts.pass}` : "";
|
|
34
|
+
return `Reconciliation repair failed${passSuffix} for drift kinds: ${kinds}`;
|
|
35
|
+
}
|
|
36
|
+
if (opts.persistentDrift && opts.persistentDrift.length > 0) {
|
|
37
|
+
const kinds = opts.persistentDrift.map((d) => d.kind).join(", ");
|
|
38
|
+
return `Reconciliation drift persisted after cap=2 passes: ${kinds}`;
|
|
39
|
+
}
|
|
40
|
+
return "Reconciliation failed";
|
|
41
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: ADR-017 drift-driven State Reconciliation Module entry point.
|
|
3
|
+
// reconcileBeforeDispatch runs before every Dispatch decision and worker spawn.
|
|
4
|
+
import { deriveState as defaultDeriveState, invalidateStateCache as defaultInvalidate, } from "../state.js";
|
|
5
|
+
import { ReconciliationFailedError, } from "./errors.js";
|
|
6
|
+
import { DRIFT_REGISTRY } from "./registry.js";
|
|
7
|
+
export { ReconciliationFailedError } from "./errors.js";
|
|
8
|
+
export { DRIFT_REGISTRY } from "./registry.js";
|
|
9
|
+
const MAX_PASSES = 2;
|
|
10
|
+
const defaultDeps = {
|
|
11
|
+
invalidateStateCache: defaultInvalidate,
|
|
12
|
+
deriveState: defaultDeriveState,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Drift-driven pre-dispatch reconciliation per ADR-017.
|
|
16
|
+
*
|
|
17
|
+
* Lifecycle: derive → detect drift → apply repairs → re-derive. Capped at
|
|
18
|
+
* MAX_PASSES (=2) cycles. The loop runs only when the prior pass fully
|
|
19
|
+
* succeeded but re-derive surfaces NEW drift (cascading repairs — e.g.
|
|
20
|
+
* fixing milestone registration uncovers a downstream completion-timestamp
|
|
21
|
+
* drift).
|
|
22
|
+
*
|
|
23
|
+
* Returns ok=true with `repaired` and terminal `blockers` populated.
|
|
24
|
+
* Throws ReconciliationFailedError when:
|
|
25
|
+
* - any repair function throws within a pass, or
|
|
26
|
+
* - drift persists after the cap.
|
|
27
|
+
*/
|
|
28
|
+
export async function reconcileBeforeDispatch(basePath, deps = defaultDeps) {
|
|
29
|
+
const registry = deps.registry ?? DRIFT_REGISTRY;
|
|
30
|
+
const repaired = [];
|
|
31
|
+
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
32
|
+
deps.invalidateStateCache();
|
|
33
|
+
const stateSnapshot = await deps.deriveState(basePath, deps.deriveStateOptions);
|
|
34
|
+
const ctx = { basePath, state: stateSnapshot };
|
|
35
|
+
const drift = await detectAllDrift(stateSnapshot, ctx, registry, pass);
|
|
36
|
+
if (drift.length === 0) {
|
|
37
|
+
return {
|
|
38
|
+
ok: true,
|
|
39
|
+
stateSnapshot,
|
|
40
|
+
repaired,
|
|
41
|
+
blockers: stateSnapshot.blockers ?? [],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const failures = [];
|
|
45
|
+
for (const record of drift) {
|
|
46
|
+
const handler = registry.find((h) => h.kind === record.kind);
|
|
47
|
+
if (!handler) {
|
|
48
|
+
failures.push({
|
|
49
|
+
drift: record,
|
|
50
|
+
cause: new Error(`No drift handler registered for kind "${record.kind}"`),
|
|
51
|
+
});
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
await handler.repair(record, ctx);
|
|
56
|
+
repaired.push(record);
|
|
57
|
+
}
|
|
58
|
+
catch (cause) {
|
|
59
|
+
failures.push({ drift: record, cause });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (failures.length > 0) {
|
|
63
|
+
throw new ReconciliationFailedError({ failures, pass });
|
|
64
|
+
}
|
|
65
|
+
// Pass fully succeeded; loop runs again to detect cascading drift.
|
|
66
|
+
}
|
|
67
|
+
// After MAX_PASSES, one more derive+detect to verify nothing persists.
|
|
68
|
+
deps.invalidateStateCache();
|
|
69
|
+
const finalState = await deps.deriveState(basePath, deps.deriveStateOptions);
|
|
70
|
+
const finalCtx = { basePath, state: finalState };
|
|
71
|
+
const persistent = await detectAllDrift(finalState, finalCtx, registry);
|
|
72
|
+
if (persistent.length > 0) {
|
|
73
|
+
throw new ReconciliationFailedError({ persistentDrift: persistent });
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
ok: true,
|
|
77
|
+
stateSnapshot: finalState,
|
|
78
|
+
repaired,
|
|
79
|
+
blockers: finalState.blockers ?? [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function detectAllDrift(state, ctx,
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
registry, pass) {
|
|
85
|
+
const collected = [];
|
|
86
|
+
for (const handler of registry) {
|
|
87
|
+
try {
|
|
88
|
+
const detected = await handler.detect(state, ctx);
|
|
89
|
+
collected.push(...detected);
|
|
90
|
+
}
|
|
91
|
+
catch (cause) {
|
|
92
|
+
throw new ReconciliationFailedError({
|
|
93
|
+
failures: [{ drift: { kind: handler.kind }, cause }],
|
|
94
|
+
pass,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return collected;
|
|
99
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: ADR-017 drift handler registry. Single source of truth for
|
|
3
|
+
// the catalog. Tests can override per-call via ReconciliationDeps.registry.
|
|
4
|
+
import { completionTimestampHandler } from "./drift/completion.js";
|
|
5
|
+
import { mergeStateHandler } from "./drift/merge-state.js";
|
|
6
|
+
import { unregisteredMilestoneHandler } from "./drift/project-md.js";
|
|
7
|
+
import { roadmapDivergenceHandler } from "./drift/roadmap.js";
|
|
8
|
+
import { sketchFlagHandler } from "./drift/sketch-flag.js";
|
|
9
|
+
import { staleRenderHandler } from "./drift/stale-render.js";
|
|
10
|
+
import { staleWorkerHandler } from "./drift/stale-worker.js";
|
|
11
|
+
// Each handler is parameterized over its specific DriftRecord variant for
|
|
12
|
+
// internal type safety. The registry stores them under DriftHandler<any> so
|
|
13
|
+
// handlers with disjoint repair parameter types coexist; the lifecycle matches
|
|
14
|
+
// by kind before invoking repair, so this is sound at runtime.
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
export const DRIFT_REGISTRY = [
|
|
17
|
+
sketchFlagHandler,
|
|
18
|
+
mergeStateHandler,
|
|
19
|
+
staleRenderHandler,
|
|
20
|
+
staleWorkerHandler,
|
|
21
|
+
unregisteredMilestoneHandler,
|
|
22
|
+
roadmapDivergenceHandler,
|
|
23
|
+
completionTimestampHandler,
|
|
24
|
+
];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: ADR-017 #5707 caller-closure helper. Parent processes that
|
|
3
|
+
// spawn auto-loop workers must reconcile before spawn — otherwise each
|
|
4
|
+
// worker independently detects+repairs the same drift, racing on shared
|
|
5
|
+
// state. This helper centralises the reconcile+catch flow so the two
|
|
6
|
+
// production spawn sites (commands/handlers/parallel.ts and auto/phases.ts
|
|
7
|
+
// startSliceParallel) share one contract.
|
|
8
|
+
import { reconcileBeforeDispatch, ReconciliationFailedError, } from "./index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Run reconciliation before spawning workers. Returns ok=true when the run
|
|
11
|
+
* completed without throwing (blockers ride along but don't fail the gate —
|
|
12
|
+
* spawn callers can choose how to handle them). On
|
|
13
|
+
* ReconciliationFailedError, returns ok=false with the error message so the
|
|
14
|
+
* caller can surface it to the user without re-throwing.
|
|
15
|
+
*
|
|
16
|
+
* Other unexpected errors propagate; they are not part of the drift
|
|
17
|
+
* taxonomy.
|
|
18
|
+
*/
|
|
19
|
+
export async function reconcileBeforeSpawn(basePath, deps = {}) {
|
|
20
|
+
const reconcileFn = deps.reconcile ?? reconcileBeforeDispatch;
|
|
21
|
+
try {
|
|
22
|
+
const result = await reconcileFn(basePath, deps);
|
|
23
|
+
if (result.blockers.length > 0) {
|
|
24
|
+
return {
|
|
25
|
+
ok: false,
|
|
26
|
+
reason: `Reconciliation blocker: ${result.blockers[0]}`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const repairedKinds = result.repaired.map((d) => d.kind);
|
|
30
|
+
return {
|
|
31
|
+
ok: true,
|
|
32
|
+
reason: repairedKinds.length > 0
|
|
33
|
+
? `repaired before spawn: ${repairedKinds.join(", ")}`
|
|
34
|
+
: undefined,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (err instanceof ReconciliationFailedError) {
|
|
39
|
+
return { ok: false, reason: err.message };
|
|
40
|
+
}
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,27 +1,6 @@
|
|
|
1
1
|
// Project/App: GSD-2
|
|
2
|
-
// File Purpose: ADR-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
export async function reconcileBeforeDispatch(basePath, deps = defaultDeps, opts) {
|
|
9
|
-
deps.invalidateStateCache();
|
|
10
|
-
const stateSnapshot = await deps.deriveState(basePath, opts);
|
|
11
|
-
const blockers = stateSnapshot.blockers ?? [];
|
|
12
|
-
if (blockers.length > 0 || stateSnapshot.phase === "blocked") {
|
|
13
|
-
return {
|
|
14
|
-
ok: false,
|
|
15
|
-
reason: blockers[0] ?? `State reconciliation blocked in phase ${stateSnapshot.phase}`,
|
|
16
|
-
stateSnapshot,
|
|
17
|
-
repaired: ["derive-state-cache-invalidated"],
|
|
18
|
-
blockers,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
ok: true,
|
|
23
|
-
stateSnapshot,
|
|
24
|
-
repaired: ["derive-state-cache-invalidated"],
|
|
25
|
-
blockers,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
2
|
+
// File Purpose: ADR-017 State Reconciliation Module — public entry point.
|
|
3
|
+
// Re-exports the drift-driven implementation from the state-reconciliation/
|
|
4
|
+
// folder so existing import paths (./state-reconciliation.js) keep working.
|
|
5
|
+
export { reconcileBeforeDispatch, ReconciliationFailedError, DRIFT_REGISTRY, } from "./state-reconciliation/index.js";
|
|
6
|
+
export { reconcileBeforeSpawn } from "./state-reconciliation/spawn-gate.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Project Knowledge
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Project-specific rules plus projected patterns and lessons learned.
|
|
4
|
+
Rules are maintained in this file. Patterns and lessons are persisted to the memories table and rendered here on the next session-start projection.
|
|
5
5
|
|
|
6
6
|
## Rules
|
|
7
7
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Shared terminal rendering helpers for GSD extension TUI surfaces.
|
|
3
|
+
import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@gsd/pi-tui";
|
|
4
|
+
export function safeLine(text, width, ellipsis = "…") {
|
|
5
|
+
if (width <= 0)
|
|
6
|
+
return "";
|
|
7
|
+
return truncateToWidth(text, width, ellipsis);
|
|
8
|
+
}
|
|
9
|
+
export function padRightVisible(text, width) {
|
|
10
|
+
if (width <= 0)
|
|
11
|
+
return "";
|
|
12
|
+
const truncated = safeLine(text, width);
|
|
13
|
+
const pad = Math.max(0, width - visibleWidth(truncated));
|
|
14
|
+
return truncated + " ".repeat(pad);
|
|
15
|
+
}
|
|
16
|
+
export function rightAlign(left, right, width) {
|
|
17
|
+
if (width <= 0)
|
|
18
|
+
return "";
|
|
19
|
+
if (!right)
|
|
20
|
+
return safeLine(left, width);
|
|
21
|
+
if (!left)
|
|
22
|
+
return safeLine(" ".repeat(Math.max(0, width - visibleWidth(right))) + right, width);
|
|
23
|
+
const gap = Math.max(1, width - visibleWidth(left) - visibleWidth(right));
|
|
24
|
+
return safeLine(left + " ".repeat(gap) + right, width);
|
|
25
|
+
}
|
|
26
|
+
export function wrapVisibleText(text, width) {
|
|
27
|
+
if (width <= 0)
|
|
28
|
+
return [text];
|
|
29
|
+
return wrapTextWithAnsi(text, width).map((line) => visibleWidth(line) > width ? truncateToWidth(line, width, "…") : line);
|
|
30
|
+
}
|
|
31
|
+
export function renderBar(theme, width, color = "muted") {
|
|
32
|
+
return safeLine(theme.fg(color, "─".repeat(Math.max(0, width))), width, "");
|
|
33
|
+
}
|
|
34
|
+
export function renderKeyHints(theme, hints, width) {
|
|
35
|
+
return safeLine(theme.fg("dim", hints.filter(Boolean).join(" │ ")), width);
|
|
36
|
+
}
|
|
37
|
+
export function renderProgressBar(theme, done, total, width, options = {}) {
|
|
38
|
+
const barWidth = Math.max(0, width);
|
|
39
|
+
const pct = total > 0 ? Math.max(0, Math.min(1, done / total)) : 0;
|
|
40
|
+
const filled = Math.round(pct * barWidth);
|
|
41
|
+
const filledChar = options.filledChar ?? "█";
|
|
42
|
+
const emptyChar = options.emptyChar ?? "░";
|
|
43
|
+
return (theme.fg(options.filledColor ?? "success", filledChar.repeat(filled)) +
|
|
44
|
+
theme.fg(options.emptyColor ?? "dim", emptyChar.repeat(barWidth - filled)));
|
|
45
|
+
}
|
|
46
|
+
export function statusGlyph(theme, level) {
|
|
47
|
+
switch (level) {
|
|
48
|
+
case "active": return theme.fg("success", "●");
|
|
49
|
+
case "success": return theme.fg("success", "✓");
|
|
50
|
+
case "warning": return theme.fg("warning", "!");
|
|
51
|
+
case "error": return theme.fg("error", "x");
|
|
52
|
+
case "idle":
|
|
53
|
+
default: return theme.fg("dim", "○");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function renderFrame(theme, inner, width, options = {}) {
|
|
57
|
+
if (width < 4)
|
|
58
|
+
return inner.map((line) => safeLine(line, width));
|
|
59
|
+
const borderColor = options.borderColor ?? "borderAccent";
|
|
60
|
+
const paddingX = Math.max(0, options.paddingX ?? 1);
|
|
61
|
+
const contentWidth = Math.max(0, width - 2 - paddingX * 2);
|
|
62
|
+
const border = (text) => theme.fg(borderColor, text);
|
|
63
|
+
const pad = " ".repeat(paddingX);
|
|
64
|
+
const lines = [border("╭" + "─".repeat(width - 2) + "╮")];
|
|
65
|
+
for (const line of inner) {
|
|
66
|
+
lines.push(border("│") +
|
|
67
|
+
pad +
|
|
68
|
+
padRightVisible(line, contentWidth) +
|
|
69
|
+
pad +
|
|
70
|
+
border("│"));
|
|
71
|
+
}
|
|
72
|
+
lines.push(border("╰" + "─".repeat(width - 2) + "╯"));
|
|
73
|
+
return lines.map((line) => safeLine(line, width, ""));
|
|
74
|
+
}
|