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,209 @@
|
|
|
1
|
+
// ADR-013 follow-up — loadKnowledgeBlock injects only Rules from project
|
|
2
|
+
// KNOWLEDGE.md to avoid duplicating Patterns + Lessons content already
|
|
3
|
+
// injected via loadMemoryBlock (Stage 2b cutover).
|
|
4
|
+
//
|
|
5
|
+
// Global KNOWLEDGE.md (~/.gsd/agent/KNOWLEDGE.md) is NOT memory-projected
|
|
6
|
+
// and still passes through with all three sections intact.
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
|
|
14
|
+
import { loadKnowledgeBlock } from "../bootstrap/system-context.ts";
|
|
15
|
+
import { extractIntroAndRules } from "../knowledge-parser.ts";
|
|
16
|
+
|
|
17
|
+
function makeTmpProject(): string {
|
|
18
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-knowledge-rules-only-"));
|
|
19
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
20
|
+
return base;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function makeTmpHome(): string {
|
|
24
|
+
const home = mkdtempSync(join(tmpdir(), "gsd-knowledge-home-"));
|
|
25
|
+
mkdirSync(join(home, "agent"), { recursive: true });
|
|
26
|
+
return home;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function cleanup(...dirs: string[]): void {
|
|
30
|
+
for (const dir of dirs) {
|
|
31
|
+
try {
|
|
32
|
+
rmSync(dir, { recursive: true, force: true });
|
|
33
|
+
} catch {
|
|
34
|
+
/* noop */
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const FULL_KNOWLEDGE = `# Project Knowledge
|
|
40
|
+
|
|
41
|
+
Append-only register of project-specific rules, patterns, and lessons learned.
|
|
42
|
+
|
|
43
|
+
## Rules
|
|
44
|
+
|
|
45
|
+
| # | Scope | Rule | Why | Added |
|
|
46
|
+
|---|-------|------|-----|-------|
|
|
47
|
+
| K001 | project | All timestamps in UTC | clarity | 2026-01-01 |
|
|
48
|
+
| K002 | M001 | Never trust user input | safety | 2026-01-02 |
|
|
49
|
+
|
|
50
|
+
## Patterns
|
|
51
|
+
|
|
52
|
+
| # | Pattern | Where | Notes |
|
|
53
|
+
|---|---------|-------|-------|
|
|
54
|
+
| P001 | Repository pattern | services/ | guards |
|
|
55
|
+
|
|
56
|
+
## Lessons Learned
|
|
57
|
+
|
|
58
|
+
| # | What Happened | Root Cause | Fix | Scope |
|
|
59
|
+
|---|--------------|------------|-----|-------|
|
|
60
|
+
| L001 | Cache poisoning | reused key | versioned key | project |
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
// ─── extractIntroAndRules unit tests ───────────────────────────────────────
|
|
64
|
+
|
|
65
|
+
test("extractIntroAndRules keeps intro + Rules, drops Patterns + Lessons", () => {
|
|
66
|
+
const out = extractIntroAndRules(FULL_KNOWLEDGE);
|
|
67
|
+
assert.match(out, /# Project Knowledge/);
|
|
68
|
+
assert.match(out, /## Rules/);
|
|
69
|
+
assert.match(out, /\| K001 \| project \| All timestamps in UTC/);
|
|
70
|
+
assert.match(out, /\| K002 \| M001 \| Never trust user input/);
|
|
71
|
+
|
|
72
|
+
assert.equal(out.includes("## Patterns"), false, "Patterns heading must be dropped");
|
|
73
|
+
assert.equal(out.includes("P001"), false, "Pattern rows must be dropped");
|
|
74
|
+
assert.equal(out.includes("## Lessons Learned"), false, "Lessons heading must be dropped");
|
|
75
|
+
assert.equal(out.includes("L001"), false, "Lesson rows must be dropped");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("extractIntroAndRules returns content unchanged when no `## Rules` heading", () => {
|
|
79
|
+
const content = "# Notes\n\nfreeform content without standard sections\n";
|
|
80
|
+
assert.equal(extractIntroAndRules(content), content);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("extractIntroAndRules returns empty for empty input", () => {
|
|
84
|
+
assert.equal(extractIntroAndRules(""), "");
|
|
85
|
+
assert.equal(extractIntroAndRules(" \n\n"), "");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("extractIntroAndRules handles Rules as the only section (no Patterns/Lessons to drop)", () => {
|
|
89
|
+
const content = `# Project Knowledge
|
|
90
|
+
|
|
91
|
+
## Rules
|
|
92
|
+
|
|
93
|
+
| # | Scope | Rule | Why | Added |
|
|
94
|
+
|---|-------|------|-----|-------|
|
|
95
|
+
| K001 | project | only rule | reason | 2026-01-01 |
|
|
96
|
+
`;
|
|
97
|
+
const out = extractIntroAndRules(content);
|
|
98
|
+
assert.match(out, /K001/);
|
|
99
|
+
assert.match(out, /## Rules/);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// ─── loadKnowledgeBlock integration ────────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
test("loadKnowledgeBlock trims project KNOWLEDGE.md to intro + Rules", () => {
|
|
105
|
+
const base = makeTmpProject();
|
|
106
|
+
const home = makeTmpHome();
|
|
107
|
+
try {
|
|
108
|
+
writeFileSync(join(base, ".gsd", "KNOWLEDGE.md"), FULL_KNOWLEDGE, "utf-8");
|
|
109
|
+
const { block } = loadKnowledgeBlock(home, base);
|
|
110
|
+
|
|
111
|
+
assert.match(block, /## Project Knowledge/);
|
|
112
|
+
assert.match(block, /K001/);
|
|
113
|
+
assert.match(block, /K002/);
|
|
114
|
+
assert.equal(block.includes("P001"), false, "project Patterns must not appear in the block");
|
|
115
|
+
assert.equal(block.includes("L001"), false, "project Lessons must not appear in the block");
|
|
116
|
+
assert.equal(block.includes("## Patterns"), false);
|
|
117
|
+
assert.equal(block.includes("## Lessons Learned"), false);
|
|
118
|
+
} finally {
|
|
119
|
+
cleanup(base, home);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("loadKnowledgeBlock leaves global KNOWLEDGE.md intact (no memory projection there)", () => {
|
|
124
|
+
const base = makeTmpProject();
|
|
125
|
+
const home = makeTmpHome();
|
|
126
|
+
try {
|
|
127
|
+
writeFileSync(join(home, "agent", "KNOWLEDGE.md"), FULL_KNOWLEDGE, "utf-8");
|
|
128
|
+
const { block, globalSizeKb } = loadKnowledgeBlock(home, base);
|
|
129
|
+
|
|
130
|
+
assert.match(block, /## Global Knowledge/);
|
|
131
|
+
// Global is full-fidelity: all three sections intact.
|
|
132
|
+
assert.match(block, /K001/);
|
|
133
|
+
assert.match(block, /P001/);
|
|
134
|
+
assert.match(block, /L001/);
|
|
135
|
+
assert.match(block, /## Patterns/);
|
|
136
|
+
assert.match(block, /## Lessons Learned/);
|
|
137
|
+
assert.ok(globalSizeKb > 0, "globalSizeKb should report the global file size");
|
|
138
|
+
} finally {
|
|
139
|
+
cleanup(base, home);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("loadKnowledgeBlock with both global and project: global keeps full content, project trimmed", () => {
|
|
144
|
+
const base = makeTmpProject();
|
|
145
|
+
const home = makeTmpHome();
|
|
146
|
+
try {
|
|
147
|
+
writeFileSync(join(home, "agent", "KNOWLEDGE.md"), FULL_KNOWLEDGE, "utf-8");
|
|
148
|
+
writeFileSync(join(base, ".gsd", "KNOWLEDGE.md"), FULL_KNOWLEDGE, "utf-8");
|
|
149
|
+
const { block } = loadKnowledgeBlock(home, base);
|
|
150
|
+
|
|
151
|
+
// Both sections present.
|
|
152
|
+
assert.match(block, /## Global Knowledge/);
|
|
153
|
+
assert.match(block, /## Project Knowledge/);
|
|
154
|
+
|
|
155
|
+
// Project's Patterns/Lessons headings must be gone. But global keeps
|
|
156
|
+
// them, so a substring count of e.g. "## Patterns" should equal 1.
|
|
157
|
+
const patternsCount = (block.match(/## Patterns/g) ?? []).length;
|
|
158
|
+
const lessonsCount = (block.match(/## Lessons Learned/g) ?? []).length;
|
|
159
|
+
assert.equal(patternsCount, 1, "Patterns heading appears exactly once (in global)");
|
|
160
|
+
assert.equal(lessonsCount, 1, "Lessons heading appears exactly once (in global)");
|
|
161
|
+
|
|
162
|
+
// K/P/L rows: K appears twice (global + project), P/L appear once (global).
|
|
163
|
+
const k001Count = (block.match(/K001/g) ?? []).length;
|
|
164
|
+
const p001Count = (block.match(/P001/g) ?? []).length;
|
|
165
|
+
const l001Count = (block.match(/L001/g) ?? []).length;
|
|
166
|
+
assert.equal(k001Count, 2, "K001 in both global and project");
|
|
167
|
+
assert.equal(p001Count, 1, "P001 only in global");
|
|
168
|
+
assert.equal(l001Count, 1, "L001 only in global");
|
|
169
|
+
} finally {
|
|
170
|
+
cleanup(base, home);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("loadKnowledgeBlock returns empty block when neither file exists", () => {
|
|
175
|
+
const base = makeTmpProject();
|
|
176
|
+
const home = makeTmpHome();
|
|
177
|
+
try {
|
|
178
|
+
const result = loadKnowledgeBlock(home, base);
|
|
179
|
+
assert.equal(result.block, "");
|
|
180
|
+
assert.equal(result.globalSizeKb, 0);
|
|
181
|
+
} finally {
|
|
182
|
+
cleanup(base, home);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("loadKnowledgeBlock injects only Rules when project KNOWLEDGE.md has no Patterns/Lessons", () => {
|
|
187
|
+
const base = makeTmpProject();
|
|
188
|
+
const home = makeTmpHome();
|
|
189
|
+
try {
|
|
190
|
+
writeFileSync(
|
|
191
|
+
join(base, ".gsd", "KNOWLEDGE.md"),
|
|
192
|
+
`# Project Knowledge
|
|
193
|
+
|
|
194
|
+
## Rules
|
|
195
|
+
|
|
196
|
+
| # | Scope | Rule | Why | Added |
|
|
197
|
+
|---|-------|------|-----|-------|
|
|
198
|
+
| K001 | project | rule one | reason | 2026-01-01 |
|
|
199
|
+
`,
|
|
200
|
+
"utf-8",
|
|
201
|
+
);
|
|
202
|
+
const { block } = loadKnowledgeBlock(home, base);
|
|
203
|
+
assert.match(block, /K001/);
|
|
204
|
+
// Block heading reflects the new contract.
|
|
205
|
+
assert.match(block, /Rules from KNOWLEDGE\.md/);
|
|
206
|
+
} finally {
|
|
207
|
+
cleanup(base, home);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
@@ -24,8 +24,8 @@ import {
|
|
|
24
24
|
renderPlanFromDb,
|
|
25
25
|
renderTaskPlanFromDb,
|
|
26
26
|
detectStaleRenders,
|
|
27
|
-
repairStaleRenders,
|
|
28
27
|
} from '../markdown-renderer.ts';
|
|
28
|
+
import { repairStaleRenders } from '../state-reconciliation/drift/stale-render.ts';
|
|
29
29
|
import {
|
|
30
30
|
parseRoadmap,
|
|
31
31
|
parsePlan,
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
// GSD-2 — ADR-013 Phase 6 preflight scanner tests.
|
|
2
|
+
//
|
|
3
|
+
// Locks in the four states the scanner must distinguish:
|
|
4
|
+
// 1. Clean — no gaps, no warning emitted.
|
|
5
|
+
// 2. Decisions gap — active decisions without a migrated memory.
|
|
6
|
+
// 3. KNOWLEDGE.md gap — rows in the legacy markdown without migration.
|
|
7
|
+
// 4. Both gaps — combined summary message.
|
|
8
|
+
|
|
9
|
+
import test from "node:test";
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { tmpdir } from "node:os";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
openDatabase,
|
|
17
|
+
closeDatabase,
|
|
18
|
+
insertDecision,
|
|
19
|
+
} from "../gsd-db.ts";
|
|
20
|
+
import { createMemory } from "../memory-store.ts";
|
|
21
|
+
import {
|
|
22
|
+
_resetNotificationStore,
|
|
23
|
+
initNotificationStore,
|
|
24
|
+
readNotifications,
|
|
25
|
+
} from "../notification-store.ts";
|
|
26
|
+
import {
|
|
27
|
+
parseKnowledgeRows,
|
|
28
|
+
reportConsolidationGaps,
|
|
29
|
+
scanConsolidationGaps,
|
|
30
|
+
} from "../memory-consolidation-scanner.ts";
|
|
31
|
+
|
|
32
|
+
function makeTmpBase(): string {
|
|
33
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-consolidation-scan-"));
|
|
34
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
35
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
36
|
+
initNotificationStore(base);
|
|
37
|
+
return base;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function cleanup(base: string): void {
|
|
41
|
+
try {
|
|
42
|
+
closeDatabase();
|
|
43
|
+
} catch {
|
|
44
|
+
/* noop */
|
|
45
|
+
}
|
|
46
|
+
_resetNotificationStore();
|
|
47
|
+
try {
|
|
48
|
+
rmSync(base, { recursive: true, force: true });
|
|
49
|
+
} catch {
|
|
50
|
+
/* noop */
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function writeKnowledgeMd(base: string, body: string): void {
|
|
55
|
+
writeFileSync(join(base, ".gsd", "KNOWLEDGE.md"), body, "utf-8");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ─── parseKnowledgeRows ─────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
test("parseKnowledgeRows extracts entries from the three legacy tables", () => {
|
|
61
|
+
const content = `# Project Knowledge
|
|
62
|
+
|
|
63
|
+
Append-only register.
|
|
64
|
+
|
|
65
|
+
## Rules
|
|
66
|
+
|
|
67
|
+
| # | Scope | Rule | Why | Added |
|
|
68
|
+
|---|-------|------|-----|-------|
|
|
69
|
+
| K001 | project | Always pin SQLite version | corruption | 2026-01-01 |
|
|
70
|
+
| K002 | M001 | Use UTC | clarity | 2026-01-02 |
|
|
71
|
+
|
|
72
|
+
## Patterns
|
|
73
|
+
|
|
74
|
+
| # | Pattern | Where | Notes |
|
|
75
|
+
|---|---------|-------|-------|
|
|
76
|
+
| P001 | Repository pattern | services/ | guards |
|
|
77
|
+
|
|
78
|
+
## Lessons Learned
|
|
79
|
+
|
|
80
|
+
| # | What Happened | Root Cause | Fix | Scope |
|
|
81
|
+
|---|--------------|------------|-----|-------|
|
|
82
|
+
| L001 | Cache poisoning | reused key | versioned key | project |
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
const rows = parseKnowledgeRows(content);
|
|
86
|
+
assert.equal(rows.length, 4, "should extract 2 rules + 1 pattern + 1 lesson");
|
|
87
|
+
assert.deepEqual(
|
|
88
|
+
rows.map((r) => ({ table: r.table, id: r.id })),
|
|
89
|
+
[
|
|
90
|
+
{ table: "rules", id: "K001" },
|
|
91
|
+
{ table: "rules", id: "K002" },
|
|
92
|
+
{ table: "patterns", id: "P001" },
|
|
93
|
+
{ table: "lessons", id: "L001" },
|
|
94
|
+
],
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("parseKnowledgeRows skips header/separator rows and unrecognized sections", () => {
|
|
99
|
+
const content = `## Rules
|
|
100
|
+
|
|
101
|
+
| # | Scope | Rule | Why | Added |
|
|
102
|
+
|---|-------|------|-----|-------|
|
|
103
|
+
|
|
104
|
+
## Other Section
|
|
105
|
+
|
|
106
|
+
| # | Foo |
|
|
107
|
+
|---|-----|
|
|
108
|
+
| X999 | bar |
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
// Empty Rules table → 0 rows. Unrecognized "Other Section" is ignored.
|
|
112
|
+
assert.equal(parseKnowledgeRows(content).length, 0);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("parseKnowledgeRows returns empty for empty input", () => {
|
|
116
|
+
assert.deepEqual(parseKnowledgeRows(""), []);
|
|
117
|
+
assert.deepEqual(parseKnowledgeRows(" \n\n"), []);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// ─── scanConsolidationGaps ─────────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
test("scanConsolidationGaps reports zero gaps when both surfaces are empty", () => {
|
|
123
|
+
const base = makeTmpBase();
|
|
124
|
+
try {
|
|
125
|
+
const report = scanConsolidationGaps(base);
|
|
126
|
+
assert.equal(report.decisions.total, 0);
|
|
127
|
+
assert.equal(report.knowledge.total, 0);
|
|
128
|
+
assert.equal(report.totalGaps, 0);
|
|
129
|
+
assert.match(report.summary, /all decisions and KNOWLEDGE\.md rows are in memories/);
|
|
130
|
+
} finally {
|
|
131
|
+
cleanup(base);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("scanConsolidationGaps detects unmigrated decisions and ignores migrated ones", () => {
|
|
136
|
+
const base = makeTmpBase();
|
|
137
|
+
try {
|
|
138
|
+
insertDecision({
|
|
139
|
+
id: "D001",
|
|
140
|
+
when_context: "2026-01-01",
|
|
141
|
+
scope: "M001",
|
|
142
|
+
decision: "Decision needing migration",
|
|
143
|
+
choice: "A",
|
|
144
|
+
rationale: "because",
|
|
145
|
+
revisable: "yes",
|
|
146
|
+
made_by: "agent",
|
|
147
|
+
superseded_by: null,
|
|
148
|
+
});
|
|
149
|
+
insertDecision({
|
|
150
|
+
id: "D002",
|
|
151
|
+
when_context: "2026-01-02",
|
|
152
|
+
scope: "M001",
|
|
153
|
+
decision: "Already migrated decision",
|
|
154
|
+
choice: "B",
|
|
155
|
+
rationale: "covered",
|
|
156
|
+
revisable: "yes",
|
|
157
|
+
made_by: "agent",
|
|
158
|
+
superseded_by: null,
|
|
159
|
+
});
|
|
160
|
+
// D002 has a corresponding migrated memory; D001 doesn't.
|
|
161
|
+
createMemory({
|
|
162
|
+
category: "architecture",
|
|
163
|
+
content: "Already migrated decision Chose: B. Rationale: covered.",
|
|
164
|
+
scope: "M001",
|
|
165
|
+
structuredFields: { sourceDecisionId: "D002" },
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const report = scanConsolidationGaps(base);
|
|
169
|
+
assert.equal(report.decisions.total, 2);
|
|
170
|
+
assert.equal(report.decisions.migrated, 1);
|
|
171
|
+
assert.equal(report.decisions.unmigrated, 1);
|
|
172
|
+
assert.equal(report.decisions.samples.length, 1);
|
|
173
|
+
assert.equal(report.decisions.samples[0]?.id, "D001");
|
|
174
|
+
assert.equal(report.totalGaps, 1);
|
|
175
|
+
assert.match(report.summary, /1 of 2 active decisions/);
|
|
176
|
+
} finally {
|
|
177
|
+
cleanup(base);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("scanConsolidationGaps skips superseded decisions (historical record only)", () => {
|
|
182
|
+
const base = makeTmpBase();
|
|
183
|
+
try {
|
|
184
|
+
insertDecision({
|
|
185
|
+
id: "D001",
|
|
186
|
+
when_context: "2026-01-01",
|
|
187
|
+
scope: "M001",
|
|
188
|
+
decision: "Superseded — does not need migration",
|
|
189
|
+
choice: "A",
|
|
190
|
+
rationale: "old",
|
|
191
|
+
revisable: "yes",
|
|
192
|
+
made_by: "agent",
|
|
193
|
+
superseded_by: "D002",
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const report = scanConsolidationGaps(base);
|
|
197
|
+
assert.equal(report.decisions.total, 0, "superseded decisions excluded from active count");
|
|
198
|
+
assert.equal(report.totalGaps, 0);
|
|
199
|
+
} finally {
|
|
200
|
+
cleanup(base);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test("scanConsolidationGaps detects unmigrated KNOWLEDGE.md rows by table", () => {
|
|
205
|
+
const base = makeTmpBase();
|
|
206
|
+
try {
|
|
207
|
+
writeKnowledgeMd(
|
|
208
|
+
base,
|
|
209
|
+
`## Rules
|
|
210
|
+
|
|
211
|
+
| # | Scope | Rule | Why | Added |
|
|
212
|
+
|---|-------|------|-----|-------|
|
|
213
|
+
| K001 | project | Pin SQLite | corruption | 2026-01-01 |
|
|
214
|
+
| K002 | M001 | UTC only | clarity | 2026-01-02 |
|
|
215
|
+
|
|
216
|
+
## Patterns
|
|
217
|
+
|
|
218
|
+
| # | Pattern | Where | Notes |
|
|
219
|
+
|---|---------|-------|-------|
|
|
220
|
+
| P001 | Repository | services/ | guards |
|
|
221
|
+
|
|
222
|
+
## Lessons Learned
|
|
223
|
+
|
|
224
|
+
| # | What Happened | Root Cause | Fix | Scope |
|
|
225
|
+
|---|--------------|------------|-----|-------|
|
|
226
|
+
`,
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
const report = scanConsolidationGaps(base);
|
|
230
|
+
assert.equal(report.knowledge.total, 3);
|
|
231
|
+
assert.equal(report.knowledge.unmigrated, 3, "no sourceKnowledgeId markers exist yet");
|
|
232
|
+
assert.deepEqual(report.knowledge.byTable, { rules: 2, patterns: 1, lessons: 0 });
|
|
233
|
+
assert.equal(report.knowledge.samples.length, 3);
|
|
234
|
+
assert.equal(report.totalGaps, 3);
|
|
235
|
+
assert.match(report.summary, /3 of 3 KNOWLEDGE\.md rows/);
|
|
236
|
+
} finally {
|
|
237
|
+
cleanup(base);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("scanConsolidationGaps combines decisions and KNOWLEDGE.md gaps in summary", () => {
|
|
242
|
+
const base = makeTmpBase();
|
|
243
|
+
try {
|
|
244
|
+
insertDecision({
|
|
245
|
+
id: "D001",
|
|
246
|
+
when_context: "2026-01-01",
|
|
247
|
+
scope: "M001",
|
|
248
|
+
decision: "Unmigrated decision",
|
|
249
|
+
choice: "A",
|
|
250
|
+
rationale: "x",
|
|
251
|
+
revisable: "yes",
|
|
252
|
+
made_by: "agent",
|
|
253
|
+
superseded_by: null,
|
|
254
|
+
});
|
|
255
|
+
writeKnowledgeMd(
|
|
256
|
+
base,
|
|
257
|
+
`## Rules
|
|
258
|
+
|
|
259
|
+
| # | Scope | Rule | Why | Added |
|
|
260
|
+
|---|-------|------|-----|-------|
|
|
261
|
+
| K001 | project | Some rule | reason | 2026-01-01 |
|
|
262
|
+
`,
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
const report = scanConsolidationGaps(base);
|
|
266
|
+
assert.equal(report.totalGaps, 2);
|
|
267
|
+
assert.match(report.summary, /1 of 1 active decisions/);
|
|
268
|
+
assert.match(report.summary, /1 of 1 KNOWLEDGE\.md rows/);
|
|
269
|
+
} finally {
|
|
270
|
+
cleanup(base);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// ─── reportConsolidationGaps ───────────────────────────────────────────────
|
|
275
|
+
|
|
276
|
+
test("reportConsolidationGaps emits a notification + warning when gaps exist", () => {
|
|
277
|
+
const base = makeTmpBase();
|
|
278
|
+
try {
|
|
279
|
+
insertDecision({
|
|
280
|
+
id: "D001",
|
|
281
|
+
when_context: "2026-01-01",
|
|
282
|
+
scope: "M001",
|
|
283
|
+
decision: "Unmigrated",
|
|
284
|
+
choice: "A",
|
|
285
|
+
rationale: "x",
|
|
286
|
+
revisable: "yes",
|
|
287
|
+
made_by: "agent",
|
|
288
|
+
superseded_by: null,
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const report = reportConsolidationGaps(base);
|
|
292
|
+
assert.ok(report);
|
|
293
|
+
assert.equal(report.totalGaps, 1);
|
|
294
|
+
|
|
295
|
+
const notifications = readNotifications(base);
|
|
296
|
+
const gapNotifs = notifications.filter((n) => n.message.includes("Memory consolidation"));
|
|
297
|
+
assert.ok(gapNotifs.length >= 1, "a consolidation notification should be persisted");
|
|
298
|
+
assert.equal(gapNotifs[0]?.severity, "warning");
|
|
299
|
+
} finally {
|
|
300
|
+
cleanup(base);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
test("reportConsolidationGaps stays silent when there are no gaps", () => {
|
|
305
|
+
const base = makeTmpBase();
|
|
306
|
+
try {
|
|
307
|
+
const report = reportConsolidationGaps(base);
|
|
308
|
+
assert.ok(report);
|
|
309
|
+
assert.equal(report.totalGaps, 0);
|
|
310
|
+
const notifications = readNotifications(base);
|
|
311
|
+
const gapNotifs = notifications.filter((n) => n.message.includes("not yet in memories"));
|
|
312
|
+
assert.equal(gapNotifs.length, 0, "no warning notification when clean");
|
|
313
|
+
} finally {
|
|
314
|
+
cleanup(base);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
@@ -29,20 +29,25 @@
|
|
|
29
29
|
|
|
30
30
|
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
31
31
|
import assert from "node:assert/strict";
|
|
32
|
-
import { mkdtempSync, rmSync, mkdirSync } from "node:fs";
|
|
32
|
+
import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from "node:fs";
|
|
33
33
|
import { join } from "node:path";
|
|
34
34
|
import { tmpdir } from "node:os";
|
|
35
35
|
|
|
36
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
WorktreeLifecycle,
|
|
38
|
+
type WorktreeLifecycleDeps,
|
|
39
|
+
type WorktreeLifecycleTestOverrides,
|
|
40
|
+
} from "../worktree-lifecycle.ts";
|
|
37
41
|
import { WorktreeStateProjection } from "../worktree-state-projection.ts";
|
|
38
42
|
import { MergeConflictError } from "../git-service.ts";
|
|
39
43
|
import type { AutoSession } from "../auto/session.ts";
|
|
40
44
|
|
|
41
|
-
// Test-local:
|
|
42
|
-
// (shouldUseWorktreeIsolation, syncWorktreeStateBack,
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
|
|
45
|
+
// Test-local: extras the WorktreeResolver-era fixture passed but Lifecycle
|
|
46
|
+
// does not need (shouldUseWorktreeIsolation, syncWorktreeStateBack,
|
|
47
|
+
// captureIntegrationBranch). Lifecycle ignores them via structural typing.
|
|
48
|
+
// The C1-C4-inlined primitive overrides come from
|
|
49
|
+
// `WorktreeLifecycleTestOverrides`, the test seam exported by the Module.
|
|
50
|
+
type LegacyTestDeps = WorktreeLifecycleDeps & WorktreeLifecycleTestOverrides & {
|
|
46
51
|
shouldUseWorktreeIsolation?: () => boolean;
|
|
47
52
|
syncWorktreeStateBack?: (
|
|
48
53
|
mainBasePath: string,
|
|
@@ -50,6 +55,7 @@ type LegacyTestDeps = WorktreeLifecycleDeps & {
|
|
|
50
55
|
milestoneId: string,
|
|
51
56
|
) => { synced: string[] };
|
|
52
57
|
captureIntegrationBranch?: (basePath: string, mid: string | undefined) => void;
|
|
58
|
+
GitServiceImpl?: new (basePath: string, gitConfig: unknown) => unknown;
|
|
53
59
|
};
|
|
54
60
|
|
|
55
61
|
/**
|
|
@@ -96,7 +102,12 @@ function makeDeps(
|
|
|
96
102
|
enterAutoWorktree: () => "",
|
|
97
103
|
enterBranchModeForMilestone: () => undefined,
|
|
98
104
|
getAutoWorktreePath: () => null,
|
|
99
|
-
autoCommitCurrentBranch: (
|
|
105
|
+
autoCommitCurrentBranch: (
|
|
106
|
+
_basePath: string,
|
|
107
|
+
_unitType: string,
|
|
108
|
+
_unitId: string,
|
|
109
|
+
_taskContext?: unknown,
|
|
110
|
+
) => null,
|
|
100
111
|
getCurrentBranch: () => "worktree/M001",
|
|
101
112
|
checkoutBranch: () => undefined,
|
|
102
113
|
autoWorktreeBranch: (mid: string) => `worktree/${mid}`,
|
|
@@ -109,6 +120,8 @@ function makeDeps(
|
|
|
109
120
|
invalidateAllCaches: () => undefined,
|
|
110
121
|
captureIntegrationBranch: () => undefined,
|
|
111
122
|
worktreeProjection: new WorktreeStateProjection(),
|
|
123
|
+
// ADR-016 phase 2 / C4 (#5627): GitServiceImpl constructor → factory.
|
|
124
|
+
gitServiceFactory: () => ({}) as never,
|
|
112
125
|
...overrides,
|
|
113
126
|
};
|
|
114
127
|
}
|
|
@@ -128,14 +141,36 @@ function makeNotifyCtx(): {
|
|
|
128
141
|
|
|
129
142
|
describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", () => {
|
|
130
143
|
let baseDir: string;
|
|
144
|
+
const savedCwd = process.cwd();
|
|
131
145
|
|
|
132
146
|
beforeEach(() => {
|
|
133
147
|
baseDir = mkdtempSync(join(tmpdir(), "merge-conflict-stops-loop-"));
|
|
134
148
|
// Fake out a milestone directory so mergeAndExit reaches mergeMilestoneToMain.
|
|
135
149
|
mkdirSync(join(baseDir, ".gsd", "milestones", "M001"), { recursive: true });
|
|
150
|
+
// ADR-016 phase 2 / C1 (#5624): worktree-lifecycle.ts now calls
|
|
151
|
+
// node:fs.readFileSync directly (the dep was retired), so the roadmap
|
|
152
|
+
// file must exist on disk for the test to reach mergeMilestoneToMain.
|
|
153
|
+
writeFileSync(
|
|
154
|
+
join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
|
|
155
|
+
"# M001\n",
|
|
156
|
+
);
|
|
157
|
+
// ADR-016 phase 2 / C3 (#5626): `getIsolationMode` is also inlined.
|
|
158
|
+
// Without explicit isolation preferences the mode defaults to "none"
|
|
159
|
+
// and the merge short-circuits before the test's mocked
|
|
160
|
+
// `mergeMilestoneToMain` is reached. Write a preferences file so the
|
|
161
|
+
// standalone routes through worktree-mode merge.
|
|
162
|
+
writeFileSync(
|
|
163
|
+
join(baseDir, ".gsd", "preferences.md"),
|
|
164
|
+
"## Git\n- isolation: worktree\n",
|
|
165
|
+
);
|
|
136
166
|
});
|
|
137
167
|
|
|
138
168
|
afterEach(() => {
|
|
169
|
+
// ADR-016 phase 2 / C2 (#5625): the inlined `mergeMilestoneStandalone`
|
|
170
|
+
// chdirs into the project root before the merge body runs. Restore
|
|
171
|
+
// cwd before deleting `baseDir` so the next test's `process.cwd()`
|
|
172
|
+
// doesn't fail with ENOENT.
|
|
173
|
+
try { process.chdir(savedCwd); } catch { /* best-effort */ }
|
|
139
174
|
try {
|
|
140
175
|
rmSync(baseDir, { recursive: true, force: true });
|
|
141
176
|
} catch {
|
|
@@ -147,7 +182,7 @@ describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", (
|
|
|
147
182
|
const conflicted = ["src/feature.ts", "README.md"];
|
|
148
183
|
const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
|
|
149
184
|
const deps = makeDeps({
|
|
150
|
-
resolveMilestoneFile: (_base, _mid, type) =>
|
|
185
|
+
resolveMilestoneFile: (_base: string, _mid: string, type: string) =>
|
|
151
186
|
type === "ROADMAP" ? roadmapPath : null,
|
|
152
187
|
readFileSync: () => "# M001\n",
|
|
153
188
|
mergeMilestoneToMain: () => {
|
|
@@ -178,7 +213,7 @@ describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", (
|
|
|
178
213
|
const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
|
|
179
214
|
class FakePermError extends Error {}
|
|
180
215
|
const deps = makeDeps({
|
|
181
|
-
resolveMilestoneFile: (_base, _mid, type) =>
|
|
216
|
+
resolveMilestoneFile: (_base: string, _mid: string, type: string) =>
|
|
182
217
|
type === "ROADMAP" ? roadmapPath : null,
|
|
183
218
|
readFileSync: () => "# M001\n",
|
|
184
219
|
mergeMilestoneToMain: () => {
|
|
@@ -204,7 +239,7 @@ describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", (
|
|
|
204
239
|
test("successful merge does not throw", () => {
|
|
205
240
|
const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
|
|
206
241
|
const deps = makeDeps({
|
|
207
|
-
resolveMilestoneFile: (_base, _mid, type) =>
|
|
242
|
+
resolveMilestoneFile: (_base: string, _mid: string, type: string) =>
|
|
208
243
|
type === "ROADMAP" ? roadmapPath : null,
|
|
209
244
|
readFileSync: () => "# M001\n",
|
|
210
245
|
mergeMilestoneToMain: () => ({ pushed: false, codeFilesChanged: true }),
|
|
@@ -497,6 +497,7 @@ test('Scenario 11: Requirements edge cases', () => {
|
|
|
497
497
|
makeRequirement('', 'Another No ID', 'validated'),
|
|
498
498
|
makeRequirement('R005', 'Has ID', 'something-weird'),
|
|
499
499
|
makeRequirement('R006', 'Deferred One', 'DEFERRED'),
|
|
500
|
+
makeRequirement('AUTH-7', 'Legacy ID', 'active'),
|
|
500
501
|
],
|
|
501
502
|
phases: {
|
|
502
503
|
'1-req-edge': makePhase('1-req-edge', 1, 'req-edge'),
|
|
@@ -510,6 +511,8 @@ test('Scenario 11: Requirements edge cases', () => {
|
|
|
510
511
|
assert.deepStrictEqual(result.requirements[2]?.id, 'R005', 'req-edge: existing id preserved');
|
|
511
512
|
assert.deepStrictEqual(result.requirements[2]?.status, 'active', 'req-edge: unknown status normalized to active');
|
|
512
513
|
assert.deepStrictEqual(result.requirements[3]?.status, 'deferred', 'req-edge: uppercase DEFERRED normalized');
|
|
514
|
+
assert.deepStrictEqual(result.requirements[4]?.id, 'R003', 'req-edge: non-R legacy id gets next canonical id');
|
|
515
|
+
assert.ok(result.requirements[4]?.description.includes('Legacy ID: AUTH-7'), 'req-edge: original legacy id is preserved in description');
|
|
513
516
|
});
|
|
514
517
|
|
|
515
518
|
// ─── Scenario 12: Vision derivation ────────────────────────────────────────
|
|
@@ -553,6 +556,8 @@ test('Scenario 13: Decisions content', () => {
|
|
|
553
556
|
const result = transformToGSD(project);
|
|
554
557
|
|
|
555
558
|
assert.ok(result.decisionsContent.includes('decision-01'), 'decisions: extracts key-decisions from summaries');
|
|
559
|
+
assert.ok(result.decisionsContent.includes('| D001 |'), 'decisions: writes DB-importable decision ID');
|
|
560
|
+
assert.ok(result.decisionsContent.includes('| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |'), 'decisions: writes canonical table header');
|
|
556
561
|
});
|
|
557
562
|
|
|
558
563
|
// ─── Scenario 14: No undefined values in output ───────────────────────────
|
|
@@ -616,4 +621,3 @@ test('Scenario 15: Empty research', () => {
|
|
|
616
621
|
});
|
|
617
622
|
|
|
618
623
|
// ─── Results ───────────────────────────────────────────────────────────────
|
|
619
|
-
|