gsd-pi 2.81.0 → 2.82.0-dev.725028083
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -30
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
- package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
- package/dist/resources/extensions/gsd/auto/loop.js +111 -8
- package/dist/resources/extensions/gsd/auto/phases.js +199 -97
- package/dist/resources/extensions/gsd/auto/run-unit.js +66 -3
- package/dist/resources/extensions/gsd/auto/session.js +9 -0
- package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +43 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +182 -178
- package/dist/resources/extensions/gsd/auto-dispatch.js +14 -11
- package/dist/resources/extensions/gsd/auto-post-unit.js +7 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +11 -3
- package/dist/resources/extensions/gsd/auto-recovery.js +6 -181
- package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -0
- package/dist/resources/extensions/gsd/auto-start.js +20 -23
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +33 -5
- package/dist/resources/extensions/gsd/auto-verification.js +12 -6
- package/dist/resources/extensions/gsd/auto-worktree.js +8 -0
- package/dist/resources/extensions/gsd/auto.js +265 -76
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +13 -6
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +13 -2
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +4 -8
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +4 -10
- package/dist/resources/extensions/gsd/commands/handlers/parallel.js +9 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
- package/dist/resources/extensions/gsd/context-store.js +112 -0
- package/dist/resources/extensions/gsd/db-writer.js +150 -84
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
- package/dist/resources/extensions/gsd/git-service.js +2 -1
- package/dist/resources/extensions/gsd/gsd-db.js +7 -23
- package/dist/resources/extensions/gsd/health-widget-core.js +1 -1
- package/dist/resources/extensions/gsd/health-widget.js +4 -10
- package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
- package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
- package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
- package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +6 -96
- package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +14 -14
- package/dist/resources/extensions/gsd/notification-overlay.js +35 -40
- package/dist/resources/extensions/gsd/parallel-merge.js +53 -30
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +25 -33
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +14 -12
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
- package/dist/resources/extensions/gsd/prompts/discuss.md +20 -2
- package/dist/resources/extensions/gsd/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
- package/dist/resources/extensions/gsd/recovery-classification.js +15 -1
- package/dist/resources/extensions/gsd/session-lock.js +40 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +131 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +247 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +50 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +87 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +50 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +124 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +32 -0
- package/dist/resources/extensions/gsd/state-reconciliation/errors.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +99 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +24 -0
- package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +43 -0
- package/dist/resources/extensions/gsd/state-reconciliation/types.js +3 -0
- package/dist/resources/extensions/gsd/state-reconciliation.js +5 -26
- package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/dist/resources/extensions/gsd/tui/render-kit.js +74 -0
- package/dist/resources/extensions/gsd/watch/header-renderer.js +92 -69
- package/dist/resources/extensions/gsd/watch/splash-palette.js +10 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +722 -316
- package/dist/resources/extensions/gsd/worktree-telemetry.js +3 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.d.ts +0 -7
- package/dist/welcome-screen.js +60 -69
- package/package.json +3 -2
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +2 -0
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -2
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -1
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/index.ts +7 -2
- package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js +47 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +76 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +30 -29
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +10 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +13 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +58 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +2 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +12 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -41
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +86 -82
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts +35 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js +152 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts +16 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js +73 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +12 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +105 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +27 -26
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +9 -6
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +56 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +113 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +48 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +10 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +43 -42
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +14 -14
- package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +64 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +13 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +15 -42
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -104
- package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +196 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tui-style-kit.ts +94 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +14 -9
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +106 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +27 -26
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +9 -6
- package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +14 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.js +9 -6
- package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +20 -1
- package/packages/pi-tui/src/overlay-layout.ts +10 -7
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
- package/pkg/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +105 -1
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +27 -26
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
- package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +9 -5
- package/src/resources/extensions/gsd/auto/loop.ts +113 -9
- package/src/resources/extensions/gsd/auto/phases.ts +158 -19
- package/src/resources/extensions/gsd/auto/run-unit.ts +69 -4
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +230 -183
- package/src/resources/extensions/gsd/auto-dispatch.ts +15 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +7 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +11 -3
- package/src/resources/extensions/gsd/auto-recovery.ts +7 -209
- package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
- package/src/resources/extensions/gsd/auto-start.ts +22 -22
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +51 -0
- package/src/resources/extensions/gsd/auto-verification.ts +12 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +8 -0
- package/src/resources/extensions/gsd/auto.ts +295 -75
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -6
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -2
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +4 -10
- package/src/resources/extensions/gsd/commands/handlers/parallel.ts +12 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
- package/src/resources/extensions/gsd/context-store.ts +120 -1
- package/src/resources/extensions/gsd/db-writer.ts +167 -84
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/git-service.ts +2 -0
- package/src/resources/extensions/gsd/gsd-db.ts +7 -23
- package/src/resources/extensions/gsd/health-widget-core.ts +1 -1
- package/src/resources/extensions/gsd/health-widget.ts +6 -10
- package/src/resources/extensions/gsd/journal.ts +2 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
- package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
- package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
- package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +10 -96
- package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +14 -13
- package/src/resources/extensions/gsd/notification-overlay.ts +50 -46
- package/src/resources/extensions/gsd/parallel-merge.ts +61 -34
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +33 -35
- package/src/resources/extensions/gsd/prompts/complete-slice.md +14 -12
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +20 -2
- package/src/resources/extensions/gsd/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +18 -1
- package/src/resources/extensions/gsd/session-lock.ts +41 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +337 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +69 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +109 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
- package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
- package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +60 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
- package/src/resources/extensions/gsd/state-reconciliation.ts +21 -53
- package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +729 -176
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +291 -4
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +20 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
- package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +116 -24
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
- package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
- package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +46 -11
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +78 -41
- package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +12 -217
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +38 -6
- package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +65 -58
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +952 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +158 -58
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +572 -118
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +18 -0
- package/src/resources/extensions/gsd/tui/render-kit.ts +109 -0
- package/src/resources/extensions/gsd/watch/header-renderer.ts +121 -79
- package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +1151 -524
- package/src/resources/extensions/gsd/worktree-telemetry.ts +7 -2
- package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → KDRTXR-22LPCsa80X9dey}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → KDRTXR-22LPCsa80X9dey}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// ADR-013 Stage 2c — /gsd knowledge write-side redirect tests.
|
|
2
|
+
//
|
|
3
|
+
// Locks in four properties of captureKnowledgeEntry / nextKnowledgeId:
|
|
4
|
+
// 1. Pattern entries write a memory row with category="pattern" and a
|
|
5
|
+
// sourceKnowledgeId marker — but do NOT touch KNOWLEDGE.md.
|
|
6
|
+
// 2. Lesson entries write a memory row with category="gotcha" — same
|
|
7
|
+
// file-vs-memory split.
|
|
8
|
+
// 3. Next-ID is monotonic across both surfaces: a P004 in the file plus a
|
|
9
|
+
// P007 in memories yields P008 next.
|
|
10
|
+
// 4. The legacy appendKnowledge stays the canonical path for Rules
|
|
11
|
+
// (covered indirectly via no-memory side effect on type="rule").
|
|
12
|
+
|
|
13
|
+
import test from "node:test";
|
|
14
|
+
import assert from "node:assert/strict";
|
|
15
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { tmpdir } from "node:os";
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
_getAdapter,
|
|
21
|
+
closeDatabase,
|
|
22
|
+
openDatabase,
|
|
23
|
+
} from "../gsd-db.ts";
|
|
24
|
+
import { captureKnowledgeEntry, nextKnowledgeId } from "../knowledge-capture.ts";
|
|
25
|
+
import { knowledgeMdPath } from "../knowledge-parser.ts";
|
|
26
|
+
|
|
27
|
+
function makeTmpBase(): string {
|
|
28
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-knowledge-capture-"));
|
|
29
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
30
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
31
|
+
return base;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function cleanup(base: string): void {
|
|
35
|
+
try {
|
|
36
|
+
closeDatabase();
|
|
37
|
+
} catch {
|
|
38
|
+
/* noop */
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
rmSync(base, { recursive: true, force: true });
|
|
42
|
+
} catch {
|
|
43
|
+
/* noop */
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function readMemoriesWithMarker(prefix: "P" | "L"): Array<{ category: string; sf: Record<string, unknown> }> {
|
|
48
|
+
const adapter = _getAdapter();
|
|
49
|
+
if (!adapter) return [];
|
|
50
|
+
const rows = adapter
|
|
51
|
+
.prepare(
|
|
52
|
+
"SELECT category, structured_fields FROM memories WHERE structured_fields LIKE :pattern ORDER BY seq",
|
|
53
|
+
)
|
|
54
|
+
.all({ ":pattern": `%"sourceKnowledgeId":"${prefix}%` }) as Array<{
|
|
55
|
+
category: string;
|
|
56
|
+
structured_fields: string;
|
|
57
|
+
}>;
|
|
58
|
+
return rows.map((r) => ({ category: r.category, sf: JSON.parse(r.structured_fields) }));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ─── Pattern path ───────────────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
test("pattern entry creates a memory and assigns the next P### id", () => {
|
|
64
|
+
const base = makeTmpBase();
|
|
65
|
+
try {
|
|
66
|
+
const result = captureKnowledgeEntry(base, "pattern", "Repository pattern at the seam", "M001");
|
|
67
|
+
assert.equal(result.id, "P001", "first pattern on a fresh project should be P001");
|
|
68
|
+
assert.equal(result.written, true);
|
|
69
|
+
|
|
70
|
+
const memories = readMemoriesWithMarker("P");
|
|
71
|
+
assert.equal(memories.length, 1);
|
|
72
|
+
assert.equal(memories[0]?.category, "pattern");
|
|
73
|
+
assert.equal(memories[0]?.sf.sourceKnowledgeId, "P001");
|
|
74
|
+
assert.equal(memories[0]?.sf.pattern, "Repository pattern at the seam");
|
|
75
|
+
assert.equal(memories[0]?.sf.where, "");
|
|
76
|
+
assert.equal(memories[0]?.sf.notes, "");
|
|
77
|
+
} finally {
|
|
78
|
+
cleanup(base);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("pattern entry does NOT write to KNOWLEDGE.md (memory-only)", () => {
|
|
83
|
+
const base = makeTmpBase();
|
|
84
|
+
try {
|
|
85
|
+
captureKnowledgeEntry(base, "pattern", "Adapter at the seam", "project");
|
|
86
|
+
assert.equal(
|
|
87
|
+
existsSync(knowledgeMdPath(base)),
|
|
88
|
+
false,
|
|
89
|
+
"KNOWLEDGE.md should remain untouched — projection re-renders on next session start",
|
|
90
|
+
);
|
|
91
|
+
} finally {
|
|
92
|
+
cleanup(base);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("repeated pattern captures advance the ID monotonically", () => {
|
|
97
|
+
const base = makeTmpBase();
|
|
98
|
+
try {
|
|
99
|
+
const a = captureKnowledgeEntry(base, "pattern", "First", "project");
|
|
100
|
+
const b = captureKnowledgeEntry(base, "pattern", "Second", "project");
|
|
101
|
+
const c = captureKnowledgeEntry(base, "pattern", "Third", "project");
|
|
102
|
+
assert.deepEqual([a.id, b.id, c.id], ["P001", "P002", "P003"]);
|
|
103
|
+
} finally {
|
|
104
|
+
cleanup(base);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ─── Lesson path ────────────────────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
test("lesson entry creates a memory with category=gotcha and L### id", () => {
|
|
111
|
+
const base = makeTmpBase();
|
|
112
|
+
try {
|
|
113
|
+
const result = captureKnowledgeEntry(base, "lesson", "Cache poisoning via reused key", "M001/S01");
|
|
114
|
+
assert.equal(result.id, "L001");
|
|
115
|
+
assert.equal(result.written, true);
|
|
116
|
+
|
|
117
|
+
const memories = readMemoriesWithMarker("L");
|
|
118
|
+
assert.equal(memories.length, 1);
|
|
119
|
+
assert.equal(memories[0]?.category, "gotcha");
|
|
120
|
+
assert.equal(memories[0]?.sf.sourceKnowledgeId, "L001");
|
|
121
|
+
assert.equal(memories[0]?.sf.whatHappened, "Cache poisoning via reused key");
|
|
122
|
+
assert.equal(memories[0]?.sf.scopeText, "M001/S01");
|
|
123
|
+
} finally {
|
|
124
|
+
cleanup(base);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// ─── Empty input ────────────────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
test("empty entry text does NOT create a memory but still assigns an id", () => {
|
|
131
|
+
const base = makeTmpBase();
|
|
132
|
+
try {
|
|
133
|
+
const result = captureKnowledgeEntry(base, "pattern", " ", "project");
|
|
134
|
+
assert.equal(result.written, false);
|
|
135
|
+
assert.equal(readMemoriesWithMarker("P").length, 0);
|
|
136
|
+
} finally {
|
|
137
|
+
cleanup(base);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// ─── nextKnowledgeId — cross-surface monotonicity ───────────────────────────
|
|
142
|
+
|
|
143
|
+
test("nextKnowledgeId takes max of file and memory surfaces", () => {
|
|
144
|
+
const base = makeTmpBase();
|
|
145
|
+
try {
|
|
146
|
+
// Pre-existing patterns in KNOWLEDGE.md and one new pattern in memories.
|
|
147
|
+
// The legacy appendKnowledge format starts P at 001 — we simulate higher
|
|
148
|
+
// existing IDs to verify the take-max-then-+1 rule.
|
|
149
|
+
writeFileSync(
|
|
150
|
+
knowledgeMdPath(base),
|
|
151
|
+
`## Patterns
|
|
152
|
+
|
|
153
|
+
| # | Pattern | Where | Notes |
|
|
154
|
+
|---|---------|-------|-------|
|
|
155
|
+
| P004 | Legacy pattern | services/ | preserved |
|
|
156
|
+
`,
|
|
157
|
+
"utf-8",
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// Capture jumps the memory ID forward.
|
|
161
|
+
captureKnowledgeEntry(base, "pattern", "Memory-only pattern", "project");
|
|
162
|
+
captureKnowledgeEntry(base, "pattern", "Another memory-only pattern", "project");
|
|
163
|
+
captureKnowledgeEntry(base, "pattern", "And another", "project");
|
|
164
|
+
|
|
165
|
+
// After: file has P004 (max=4); memories have P005, P006, P007 (max=7).
|
|
166
|
+
// Next must be P008.
|
|
167
|
+
assert.equal(nextKnowledgeId(base, "P"), "P008");
|
|
168
|
+
} finally {
|
|
169
|
+
cleanup(base);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("nextKnowledgeId works per-prefix without cross-talk", () => {
|
|
174
|
+
const base = makeTmpBase();
|
|
175
|
+
try {
|
|
176
|
+
captureKnowledgeEntry(base, "pattern", "P entry", "project");
|
|
177
|
+
captureKnowledgeEntry(base, "pattern", "P entry 2", "project");
|
|
178
|
+
captureKnowledgeEntry(base, "lesson", "L entry", "project");
|
|
179
|
+
|
|
180
|
+
assert.equal(nextKnowledgeId(base, "P"), "P003");
|
|
181
|
+
assert.equal(nextKnowledgeId(base, "L"), "L002");
|
|
182
|
+
// K has no entries on this project — first one should be K001.
|
|
183
|
+
assert.equal(nextKnowledgeId(base, "K"), "K001");
|
|
184
|
+
} finally {
|
|
185
|
+
cleanup(base);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test("nextKnowledgeId pads to three digits even at the rollover", () => {
|
|
190
|
+
const base = makeTmpBase();
|
|
191
|
+
try {
|
|
192
|
+
writeFileSync(
|
|
193
|
+
knowledgeMdPath(base),
|
|
194
|
+
`## Patterns
|
|
195
|
+
|
|
196
|
+
| # | Pattern | Where | Notes |
|
|
197
|
+
|---|---------|-------|-------|
|
|
198
|
+
| P099 | high water mark | — | — |
|
|
199
|
+
`,
|
|
200
|
+
"utf-8",
|
|
201
|
+
);
|
|
202
|
+
assert.equal(nextKnowledgeId(base, "P"), "P100");
|
|
203
|
+
} finally {
|
|
204
|
+
cleanup(base);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// ─── Sanity: file-side reads still see existing rows after capture ─────────
|
|
209
|
+
|
|
210
|
+
test("after pattern capture, KNOWLEDGE.md untouched but next id reflects memory state", () => {
|
|
211
|
+
const base = makeTmpBase();
|
|
212
|
+
try {
|
|
213
|
+
captureKnowledgeEntry(base, "pattern", "First", "project");
|
|
214
|
+
// KNOWLEDGE.md still absent.
|
|
215
|
+
assert.equal(existsSync(knowledgeMdPath(base)), false);
|
|
216
|
+
// Next-ID logic sees the new memory.
|
|
217
|
+
assert.equal(nextKnowledgeId(base, "P"), "P002");
|
|
218
|
+
} finally {
|
|
219
|
+
cleanup(base);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test("rule writes still flow through appendKnowledge (file-canonical) — memory unchanged", async () => {
|
|
224
|
+
const base = makeTmpBase();
|
|
225
|
+
try {
|
|
226
|
+
// We invoke the legacy file path directly here; the command handler
|
|
227
|
+
// dispatch is verified separately at the integration level. The point
|
|
228
|
+
// of this test is to lock in that captureKnowledgeEntry is NOT the
|
|
229
|
+
// rule path — rules must go through appendKnowledge.
|
|
230
|
+
const { appendKnowledge } = await import("../files.ts");
|
|
231
|
+
await appendKnowledge(base, "rule", "Always pin SQLite version", "project");
|
|
232
|
+
|
|
233
|
+
const md = readFileSync(knowledgeMdPath(base), "utf-8");
|
|
234
|
+
assert.match(md, /\| K001 \| project \| Always pin SQLite version /);
|
|
235
|
+
|
|
236
|
+
// No pattern/lesson memories should exist as a side effect.
|
|
237
|
+
assert.equal(readMemoriesWithMarker("P").length, 0);
|
|
238
|
+
assert.equal(readMemoriesWithMarker("L").length, 0);
|
|
239
|
+
} finally {
|
|
240
|
+
cleanup(base);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
@@ -187,7 +187,7 @@ test('loadKnowledgeBlock: uses project knowledge alone when no global file', ()
|
|
|
187
187
|
writeFileSync(join(cwd, '.gsd', 'KNOWLEDGE.md'), 'K001: Use real DB');
|
|
188
188
|
|
|
189
189
|
const result = loadKnowledgeBlock(gsdHome, cwd);
|
|
190
|
-
assert.ok(result.block.includes('[KNOWLEDGE — Rules
|
|
190
|
+
assert.ok(result.block.includes('[KNOWLEDGE — Rules from KNOWLEDGE.md'));
|
|
191
191
|
assert.ok(result.block.includes('## Project Knowledge'));
|
|
192
192
|
assert.ok(result.block.includes('K001: Use real DB'));
|
|
193
193
|
assert.ok(!result.block.includes('## Global Knowledge'));
|
|
@@ -205,7 +205,7 @@ test('loadKnowledgeBlock: uses global knowledge alone when no project file', ()
|
|
|
205
205
|
writeFileSync(join(gsdHome, 'agent', 'KNOWLEDGE.md'), 'G001: Respond in English');
|
|
206
206
|
|
|
207
207
|
const result = loadKnowledgeBlock(gsdHome, cwd);
|
|
208
|
-
assert.ok(result.block.includes('[KNOWLEDGE — Rules
|
|
208
|
+
assert.ok(result.block.includes('[KNOWLEDGE — Rules from KNOWLEDGE.md'));
|
|
209
209
|
assert.ok(result.block.includes('## Global Knowledge'));
|
|
210
210
|
assert.ok(result.block.includes('G001: Respond in English'));
|
|
211
211
|
assert.ok(!result.block.includes('## Project Knowledge'));
|
|
@@ -234,6 +234,51 @@ test('loadKnowledgeBlock: merges global before project when both exist', () => {
|
|
|
234
234
|
rmSync(tmp, { recursive: true, force: true });
|
|
235
235
|
});
|
|
236
236
|
|
|
237
|
+
test('loadKnowledgeBlock: strips patterns and lessons from project knowledge', () => {
|
|
238
|
+
const tmp = realpathSync(mkdtempSync(join(tmpdir(), 'gsd-kb-strip-')));
|
|
239
|
+
const gsdHome = join(tmp, 'home');
|
|
240
|
+
const cwd = join(tmp, 'project');
|
|
241
|
+
mkdirSync(join(cwd, '.gsd'), { recursive: true });
|
|
242
|
+
mkdirSync(join(gsdHome, 'agent'), { recursive: true });
|
|
243
|
+
writeFileSync(
|
|
244
|
+
join(cwd, '.gsd', 'KNOWLEDGE.md'),
|
|
245
|
+
[
|
|
246
|
+
'# Project Knowledge',
|
|
247
|
+
'',
|
|
248
|
+
'Intro note that should stay with manual rules.',
|
|
249
|
+
'',
|
|
250
|
+
'## Rules',
|
|
251
|
+
'',
|
|
252
|
+
'| ID | Rule | Notes |',
|
|
253
|
+
'|---|---|---|',
|
|
254
|
+
'| K001 | Use real DB | - |',
|
|
255
|
+
'',
|
|
256
|
+
'## Patterns',
|
|
257
|
+
'',
|
|
258
|
+
'| ID | Pattern | Where | Notes |',
|
|
259
|
+
'|---|---|---|---|',
|
|
260
|
+
'| P001 | Prefer async | server | - |',
|
|
261
|
+
'',
|
|
262
|
+
'## Lessons Learned',
|
|
263
|
+
'',
|
|
264
|
+
'| ID | What Happened | Root Cause | Fix | Scope |',
|
|
265
|
+
'|---|---|---|---|---|',
|
|
266
|
+
'| L001 | Missed cache | N/A | Add TTL | project |',
|
|
267
|
+
].join('\n'),
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
const result = loadKnowledgeBlock(gsdHome, cwd);
|
|
271
|
+
assert.ok(result.block.includes('[KNOWLEDGE — Rules from KNOWLEDGE.md'));
|
|
272
|
+
assert.ok(result.block.includes('Intro note that should stay with manual rules.'));
|
|
273
|
+
assert.ok(result.block.includes('K001'), 'rules entry should be present');
|
|
274
|
+
assert.ok(!result.block.includes('P001'), 'patterns should be stripped and injected via memories');
|
|
275
|
+
assert.ok(!result.block.includes('L001'), 'lessons should be stripped and injected via memories');
|
|
276
|
+
assert.ok(!result.block.includes('## Patterns'), 'Patterns heading should not appear');
|
|
277
|
+
assert.ok(!result.block.includes('## Lessons Learned'), 'Lessons heading should not appear');
|
|
278
|
+
|
|
279
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
280
|
+
});
|
|
281
|
+
|
|
237
282
|
test('loadKnowledgeBlock: reports globalSizeKb above 4KB threshold', () => {
|
|
238
283
|
const tmp = realpathSync(mkdtempSync(join(tmpdir(), 'gsd-kb-')));
|
|
239
284
|
const gsdHome = join(tmp, 'home');
|
|
@@ -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,
|