gsd-pi 2.82.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -32
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +10 -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/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +1 -1
- package/dist/resources/extensions/cmux/index.js +5 -0
- package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
- package/dist/resources/extensions/gsd/auto/loop.js +19 -6
- package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
- package/dist/resources/extensions/gsd/auto/phases.js +90 -31
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +246 -133
- package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
- package/dist/resources/extensions/gsd/auto-recovery.js +71 -14
- package/dist/resources/extensions/gsd/auto-start.js +87 -14
- package/dist/resources/extensions/gsd/auto-verification.js +45 -26
- package/dist/resources/extensions/gsd/auto-worktree.js +176 -10
- package/dist/resources/extensions/gsd/auto.js +178 -63
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -9
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +17 -3
- package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +39 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +7 -2
- package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
- package/dist/resources/extensions/gsd/context-store.js +112 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +43 -5
- package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
- package/dist/resources/extensions/gsd/db-writer.js +150 -84
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +87 -7
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
- package/dist/resources/extensions/gsd/doctor.js +2 -28
- package/dist/resources/extensions/gsd/export-html.js +27 -425
- package/dist/resources/extensions/gsd/forensics.js +3 -3
- package/dist/resources/extensions/gsd/git-service.js +45 -3
- package/dist/resources/extensions/gsd/gsd-db.js +21 -6
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
- package/dist/resources/extensions/gsd/guided-flow.js +101 -116
- package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
- 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 +16 -9
- 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/parsers.js +10 -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/migration-auto-check.js +12 -17
- package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
- package/dist/resources/extensions/gsd/paths.js +4 -0
- package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
- package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
- package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- 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/queue-reorder-ui.js +30 -13
- package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
- package/dist/resources/extensions/gsd/state.js +3 -3
- package/dist/resources/extensions/gsd/status-guards.js +11 -0
- package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/dist/resources/extensions/gsd/templates/plan.md +9 -5
- package/dist/resources/extensions/gsd/templates/task-plan.md +10 -2
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
- package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +87 -14
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +68 -7
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
- package/dist/resources/extensions/gsd/worktree-manager.js +1 -1
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- package/dist/resources/extensions/subagent/index.js +448 -78
- package/dist/resources/extensions/subagent/launch.js +77 -0
- package/dist/resources/extensions/subagent/run-store.js +148 -0
- package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
- package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
- package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/dist/resources/extensions/visual-brief/index.js +5 -0
- package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
- package/dist/resources/extensions/visual-brief/prompts.js +140 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +5 -5
- 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.js.nft.json +1 -1
- 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 +4 -7
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
- 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 +4 -5
- 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 +2 -5
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -7
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
- 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 +4 -5
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- 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/2973.33f26573894b6153.js +2 -0
- package/dist/web/standalone/.next/static/chunks/8359.65b24fac92188a6b.js +10 -0
- package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-b23b3f6858dc6dc8.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/package.json +6 -5
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +14 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/tsconfig.json +2 -1
- package/packages/native/tsconfig.tsbuildinfo +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/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +5 -6
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
- 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/google-gemini-cli.test.ts +49 -0
- package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
- package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
- package/packages/pi-ai/src/providers/simple-options.ts +5 -6
- 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/agent-session-thinking-level.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js.map +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/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +71 -97
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.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/agent-session-thinking-level.test.ts +79 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
- package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -102
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
- 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__/terminal.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +12 -0
- package/packages/pi-tui/dist/terminal.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__/terminal.test.ts +121 -0
- package/packages/pi-tui/src/terminal.ts +11 -0
- 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/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +10 -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/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +1 -1
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +9 -0
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
- package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
- package/src/resources/extensions/gsd/auto/loop.ts +22 -6
- package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
- package/src/resources/extensions/gsd/auto/phases.ts +104 -38
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +21 -19
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +279 -144
- package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
- package/src/resources/extensions/gsd/auto-recovery.ts +74 -11
- package/src/resources/extensions/gsd/auto-start.ts +94 -12
- package/src/resources/extensions/gsd/auto-verification.ts +58 -36
- package/src/resources/extensions/gsd/auto-worktree.ts +193 -10
- package/src/resources/extensions/gsd/auto.ts +187 -61
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +20 -4
- package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +42 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +8 -3
- package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
- package/src/resources/extensions/gsd/context-store.ts +120 -1
- package/src/resources/extensions/gsd/crash-recovery.ts +44 -4
- package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
- package/src/resources/extensions/gsd/db-writer.ts +167 -84
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +89 -7
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +3 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -27
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/forensics.ts +3 -3
- package/src/resources/extensions/gsd/git-service.ts +51 -4
- package/src/resources/extensions/gsd/gsd-db.ts +21 -6
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
- package/src/resources/extensions/gsd/guided-flow.ts +134 -133
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -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 +16 -9
- 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/parsers.ts +11 -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/migration-auto-check.ts +15 -23
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
- package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
- package/src/resources/extensions/gsd/paths.ts +5 -0
- package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/src/resources/extensions/gsd/prompts/queue.md +4 -4
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- 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/queue-reorder-ui.ts +31 -13
- package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
- package/src/resources/extensions/gsd/state.ts +3 -3
- package/src/resources/extensions/gsd/status-guards.ts +13 -0
- package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/src/resources/extensions/gsd/templates/plan.md +9 -5
- package/src/resources/extensions/gsd/templates/task-plan.md +10 -2
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +18 -6
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +91 -6
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +378 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +86 -2
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
- 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 +59 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +112 -1
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +46 -0
- 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/memory-consolidation-scanner.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +251 -2
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -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 +10 -0
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +13 -1
- package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +103 -7
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
- package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +97 -12
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +78 -6
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
- package/src/resources/extensions/gsd/worktree-manager.ts +1 -1
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/subagent/index.ts +567 -103
- package/src/resources/extensions/subagent/launch.ts +131 -0
- package/src/resources/extensions/subagent/run-store.ts +218 -0
- package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
- package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
- package/src/resources/extensions/ttsr/ttsr-manager.ts +5 -1
- package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
- package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/src/resources/extensions/visual-brief/index.ts +8 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
- package/src/resources/extensions/visual-brief/prompts.ts +183 -0
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
- package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +0 -10
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-9ecfd95f343793f0.js +0 -1
- package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
- package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
- package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → qoMxZh-xuwuvpFW0x0k01}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → qoMxZh-xuwuvpFW0x0k01}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// GSD-2 — Guided workflow Unit context.
|
|
2
|
+
// Tracks the guided Unit whose queued turn should use manifest Tool Contract policy.
|
|
3
|
+
const guidedUnitContextByBasePath = new Map();
|
|
4
|
+
export function setGuidedUnitContext(basePath, unitType) {
|
|
5
|
+
const context = { basePath, unitType, startedAt: Date.now() };
|
|
6
|
+
guidedUnitContextByBasePath.set(basePath, context);
|
|
7
|
+
return context;
|
|
8
|
+
}
|
|
9
|
+
export function getGuidedUnitContext(basePath) {
|
|
10
|
+
if (basePath)
|
|
11
|
+
return guidedUnitContextByBasePath.get(basePath) ?? null;
|
|
12
|
+
if (guidedUnitContextByBasePath.size === 1)
|
|
13
|
+
return guidedUnitContextByBasePath.values().next().value;
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
export function clearGuidedUnitContext(basePath) {
|
|
17
|
+
if (basePath) {
|
|
18
|
+
guidedUnitContextByBasePath.delete(basePath);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
guidedUnitContextByBasePath.clear();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// GSD2 — KNOWLEDGE.md -> memories backfill (ADR-013 Stage 2b).
|
|
2
|
+
//
|
|
3
|
+
// Idempotent migration of `.gsd/KNOWLEDGE.md` Patterns and Lessons rows into
|
|
4
|
+
// the `memories` table. Patterns become memories with `category: "pattern"`;
|
|
5
|
+
// Lessons become memories with `category: "gotcha"` (mirroring the ADR-013
|
|
6
|
+
// line 38 contract). Rules (K###) are NOT migrated — they remain manually
|
|
7
|
+
// maintained in `KNOWLEDGE.md` per ADR-013 line 39.
|
|
8
|
+
//
|
|
9
|
+
// Idempotency is enforced by tagging each backfilled memory with
|
|
10
|
+
// `structured_fields.sourceKnowledgeId = "<P|L>NNN"`. The
|
|
11
|
+
// memory-consolidation-scanner (PR #5765) checks for the same marker.
|
|
12
|
+
//
|
|
13
|
+
// Triggered opportunistically by `buildBeforeAgentStartResult` so the cost
|
|
14
|
+
// only ever fires once per project. Costs O(N) inserts on first run where N
|
|
15
|
+
// is the row count; subsequent runs are an O(N) lookup that finds existing
|
|
16
|
+
// markers and exits.
|
|
17
|
+
import { _getAdapter, isDbAvailable } from "./gsd-db.js";
|
|
18
|
+
import { createMemory } from "./memory-store.js";
|
|
19
|
+
import { parseKnowledgeRows, readKnowledgeMd } from "./knowledge-parser.js";
|
|
20
|
+
import { logWarning } from "./workflow-logger.js";
|
|
21
|
+
/**
|
|
22
|
+
* Backfill KNOWLEDGE.md Patterns + Lessons rows into the memories table.
|
|
23
|
+
*
|
|
24
|
+
* - Idempotent (per-row): each migrated memory carries
|
|
25
|
+
* `structured_fields.sourceKnowledgeId = "<P|L>NNN"`. Rows whose ID is
|
|
26
|
+
* already present in the memory store are skipped.
|
|
27
|
+
* - Best-effort: never throws. Logs and returns 0 on failure so a broken
|
|
28
|
+
* backfill cannot block agent startup.
|
|
29
|
+
* - Rules (K###) are intentionally skipped — they remain manually maintained
|
|
30
|
+
* in `KNOWLEDGE.md` per ADR-013.
|
|
31
|
+
*
|
|
32
|
+
* Returns the number of memories written (0 when there's nothing to migrate
|
|
33
|
+
* or when the file is absent).
|
|
34
|
+
*/
|
|
35
|
+
export function backfillKnowledgeToMemories(basePath) {
|
|
36
|
+
if (!isDbAvailable())
|
|
37
|
+
return 0;
|
|
38
|
+
const adapter = _getAdapter();
|
|
39
|
+
if (!adapter)
|
|
40
|
+
return 0;
|
|
41
|
+
try {
|
|
42
|
+
const content = readKnowledgeMd(basePath);
|
|
43
|
+
if (!content.trim())
|
|
44
|
+
return 0;
|
|
45
|
+
const rows = parseKnowledgeRows(content);
|
|
46
|
+
if (rows.length === 0)
|
|
47
|
+
return 0;
|
|
48
|
+
const checkExisting = adapter.prepare("SELECT 1 FROM memories WHERE structured_fields LIKE :pattern LIMIT 1");
|
|
49
|
+
let written = 0;
|
|
50
|
+
for (const row of rows) {
|
|
51
|
+
const synth = synthesize(row);
|
|
52
|
+
if (!synth)
|
|
53
|
+
continue;
|
|
54
|
+
// Pattern is anchored on both sides of the value to avoid prefix
|
|
55
|
+
// collisions (e.g. P1 vs P10).
|
|
56
|
+
const matchPattern = `%"sourceKnowledgeId":"${synth.id}"%`;
|
|
57
|
+
if (checkExisting.get({ ":pattern": matchPattern }))
|
|
58
|
+
continue;
|
|
59
|
+
const id = createMemory({
|
|
60
|
+
category: synth.category,
|
|
61
|
+
content: synth.content,
|
|
62
|
+
scope: synth.scope,
|
|
63
|
+
confidence: 0.85,
|
|
64
|
+
structuredFields: synth.structuredFields,
|
|
65
|
+
});
|
|
66
|
+
if (id)
|
|
67
|
+
written += 1;
|
|
68
|
+
}
|
|
69
|
+
return written;
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
logWarning("memory-backfill", `KNOWLEDGE.md -> memories backfill failed: ${e.message}`);
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Convert a parsed KNOWLEDGE.md row into the memory payload we insert.
|
|
78
|
+
* Returns `null` for Rules (K###) which are not migrated, or for rows whose
|
|
79
|
+
* primary content cell is empty (defensive against malformed manual edits).
|
|
80
|
+
*/
|
|
81
|
+
function synthesize(row) {
|
|
82
|
+
if (row.table === "rules")
|
|
83
|
+
return null;
|
|
84
|
+
if (row.table === "patterns") {
|
|
85
|
+
// Cells: [P###, Pattern, Where, Notes]
|
|
86
|
+
const [, pattern, where, notes] = row.cells;
|
|
87
|
+
const cleaned = (pattern ?? "").trim();
|
|
88
|
+
if (!cleaned)
|
|
89
|
+
return null;
|
|
90
|
+
const contentParts = [cleaned];
|
|
91
|
+
if (where && where.trim() && where.trim() !== "—") {
|
|
92
|
+
contentParts.push(`Where: ${where.trim()}.`);
|
|
93
|
+
}
|
|
94
|
+
if (notes && notes.trim() && notes.trim() !== "—") {
|
|
95
|
+
contentParts.push(`Notes: ${notes.trim()}.`);
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
table: "patterns",
|
|
99
|
+
id: row.id,
|
|
100
|
+
category: "pattern",
|
|
101
|
+
content: trim(contentParts.join(" "), 600),
|
|
102
|
+
scope: (where ?? "").trim() || "project",
|
|
103
|
+
structuredFields: {
|
|
104
|
+
sourceKnowledgeId: row.id,
|
|
105
|
+
sourceKnowledgeTable: "patterns",
|
|
106
|
+
pattern: cleaned,
|
|
107
|
+
where: (where ?? "").trim(),
|
|
108
|
+
notes: (notes ?? "").trim(),
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// table === "lessons"
|
|
113
|
+
// Cells: [L###, What Happened, Root Cause, Fix, Scope]
|
|
114
|
+
const [, whatHappened, rootCause, fix, scope] = row.cells;
|
|
115
|
+
const cleanedWhat = (whatHappened ?? "").trim();
|
|
116
|
+
if (!cleanedWhat)
|
|
117
|
+
return null;
|
|
118
|
+
const contentParts = [cleanedWhat];
|
|
119
|
+
if (rootCause && rootCause.trim() && rootCause.trim() !== "—") {
|
|
120
|
+
contentParts.push(`Root cause: ${rootCause.trim()}.`);
|
|
121
|
+
}
|
|
122
|
+
if (fix && fix.trim() && fix.trim() !== "—") {
|
|
123
|
+
contentParts.push(`Fix: ${fix.trim()}.`);
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
table: "lessons",
|
|
127
|
+
id: row.id,
|
|
128
|
+
category: "gotcha",
|
|
129
|
+
content: trim(contentParts.join(" "), 600),
|
|
130
|
+
scope: (scope ?? "").trim() || "project",
|
|
131
|
+
structuredFields: {
|
|
132
|
+
sourceKnowledgeId: row.id,
|
|
133
|
+
sourceKnowledgeTable: "lessons",
|
|
134
|
+
whatHappened: cleanedWhat,
|
|
135
|
+
rootCause: (rootCause ?? "").trim(),
|
|
136
|
+
fix: (fix ?? "").trim(),
|
|
137
|
+
scopeText: (scope ?? "").trim(),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function trim(value, max) {
|
|
142
|
+
const cleaned = value.replace(/\s+/g, " ").trim();
|
|
143
|
+
return cleaned.length > max ? cleaned.slice(0, max - 1) + "…" : cleaned;
|
|
144
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// GSD2 — KNOWLEDGE.md write-side cutover (ADR-013 Stage 2c).
|
|
2
|
+
//
|
|
3
|
+
// Replaces the legacy `appendKnowledge` file-append path for Patterns and
|
|
4
|
+
// Lessons with `createMemory` calls. Rules (K###) continue to flow through
|
|
5
|
+
// the legacy file-append because they are intentionally not migrated to
|
|
6
|
+
// memories per ADR-013 line 39.
|
|
7
|
+
//
|
|
8
|
+
// Next-ID assignment is the cross-surface stable rule: read the existing
|
|
9
|
+
// `.gsd/KNOWLEDGE.md` for the highest <prefix>### in that section, AND read
|
|
10
|
+
// the memories table for the highest `sourceKnowledgeId` with the matching
|
|
11
|
+
// prefix, take the max, and increment. This stays stable across the
|
|
12
|
+
// knowledge backfill mid-run (when some rows exist only in the file and
|
|
13
|
+
// others only in memories) and on a fresh project where neither has any
|
|
14
|
+
// entries yet.
|
|
15
|
+
import { _getAdapter, isDbAvailable } from "./gsd-db.js";
|
|
16
|
+
import { createMemory } from "./memory-store.js";
|
|
17
|
+
import { parseKnowledgeRows, readKnowledgeMd } from "./knowledge-parser.js";
|
|
18
|
+
import { logWarning } from "./workflow-logger.js";
|
|
19
|
+
/**
|
|
20
|
+
* Append a new Pattern or Lesson by writing it as a memory row carrying a
|
|
21
|
+
* `sourceKnowledgeId` marker. The next session's KNOWLEDGE.md projection
|
|
22
|
+
* render (`knowledge-projection.ts`) picks it up and emits the row into the
|
|
23
|
+
* appropriate section.
|
|
24
|
+
*
|
|
25
|
+
* `entryText` is treated as the row's primary description cell (Pattern for
|
|
26
|
+
* patterns, "What Happened" for lessons). Auxiliary cells (Where/Notes for
|
|
27
|
+
* patterns; Root Cause/Fix/Scope for lessons) are left empty — the projection
|
|
28
|
+
* renders `—` for empty cells. Users who need richer structure can call
|
|
29
|
+
* `capture_thought` directly with a fuller `structuredFields` payload.
|
|
30
|
+
*/
|
|
31
|
+
export function captureKnowledgeEntry(basePath, type, entryText, scope) {
|
|
32
|
+
const cleaned = entryText.trim();
|
|
33
|
+
const idPrefix = type === "pattern" ? "P" : "L";
|
|
34
|
+
const id = nextKnowledgeId(basePath, idPrefix);
|
|
35
|
+
if (!cleaned) {
|
|
36
|
+
return { id, written: false };
|
|
37
|
+
}
|
|
38
|
+
if (!isDbAvailable()) {
|
|
39
|
+
logWarning("knowledge-capture", "DB unavailable; cannot persist knowledge entry");
|
|
40
|
+
return { id, written: false };
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const category = type === "pattern" ? "pattern" : "gotcha";
|
|
44
|
+
const structuredFields = type === "pattern"
|
|
45
|
+
? {
|
|
46
|
+
sourceKnowledgeId: id,
|
|
47
|
+
sourceKnowledgeTable: "patterns",
|
|
48
|
+
pattern: cleaned,
|
|
49
|
+
where: "",
|
|
50
|
+
notes: "",
|
|
51
|
+
}
|
|
52
|
+
: {
|
|
53
|
+
sourceKnowledgeId: id,
|
|
54
|
+
sourceKnowledgeTable: "lessons",
|
|
55
|
+
whatHappened: cleaned,
|
|
56
|
+
rootCause: "",
|
|
57
|
+
fix: "",
|
|
58
|
+
scopeText: scope,
|
|
59
|
+
};
|
|
60
|
+
const memoryId = createMemory({
|
|
61
|
+
category,
|
|
62
|
+
content: cleaned,
|
|
63
|
+
scope: scope || "project",
|
|
64
|
+
confidence: 0.85,
|
|
65
|
+
structuredFields,
|
|
66
|
+
});
|
|
67
|
+
return { id, written: !!memoryId };
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
logWarning("knowledge-capture", `failed to persist ${type} entry as memory: ${e.message}`);
|
|
71
|
+
return { id, written: false };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Compute the next <prefix>### identifier across both the legacy
|
|
76
|
+
* `.gsd/KNOWLEDGE.md` and the `memories.structured_fields.sourceKnowledgeId`
|
|
77
|
+
* surface. Takes the max numeric suffix from either side and increments.
|
|
78
|
+
*
|
|
79
|
+
* Padded to three digits to match the existing `appendKnowledge` convention.
|
|
80
|
+
* Exported for tests; production callers go through `captureKnowledgeEntry`.
|
|
81
|
+
*/
|
|
82
|
+
export function nextKnowledgeId(basePath, prefix) {
|
|
83
|
+
const fromFile = maxIdInFile(basePath, prefix);
|
|
84
|
+
const fromMemories = maxIdInMemories(prefix);
|
|
85
|
+
const next = Math.max(fromFile, fromMemories) + 1;
|
|
86
|
+
return `${prefix}${String(next).padStart(3, "0")}`;
|
|
87
|
+
}
|
|
88
|
+
function maxIdInFile(basePath, prefix) {
|
|
89
|
+
const content = readKnowledgeMd(basePath);
|
|
90
|
+
if (!content.trim())
|
|
91
|
+
return 0;
|
|
92
|
+
const expectedTable = prefix === "K" ? "rules" : prefix === "P" ? "patterns" : "lessons";
|
|
93
|
+
let max = 0;
|
|
94
|
+
for (const row of parseKnowledgeRows(content)) {
|
|
95
|
+
if (row.table !== expectedTable)
|
|
96
|
+
continue;
|
|
97
|
+
const num = parseInt(row.id.slice(1), 10);
|
|
98
|
+
if (Number.isFinite(num) && num > max)
|
|
99
|
+
max = num;
|
|
100
|
+
}
|
|
101
|
+
return max;
|
|
102
|
+
}
|
|
103
|
+
function maxIdInMemories(prefix) {
|
|
104
|
+
if (!isDbAvailable())
|
|
105
|
+
return 0;
|
|
106
|
+
const adapter = _getAdapter();
|
|
107
|
+
if (!adapter)
|
|
108
|
+
return 0;
|
|
109
|
+
try {
|
|
110
|
+
const rows = adapter
|
|
111
|
+
.prepare("SELECT structured_fields FROM memories WHERE structured_fields LIKE :pattern")
|
|
112
|
+
.all({ ":pattern": `%"sourceKnowledgeId":"${prefix}%` });
|
|
113
|
+
let max = 0;
|
|
114
|
+
for (const row of rows) {
|
|
115
|
+
if (!row.structured_fields)
|
|
116
|
+
continue;
|
|
117
|
+
let sf;
|
|
118
|
+
try {
|
|
119
|
+
sf = JSON.parse(row.structured_fields);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const sourceId = sf["sourceKnowledgeId"];
|
|
125
|
+
if (typeof sourceId !== "string" || !sourceId.startsWith(prefix))
|
|
126
|
+
continue;
|
|
127
|
+
const num = parseInt(sourceId.slice(1), 10);
|
|
128
|
+
if (Number.isFinite(num) && num > max)
|
|
129
|
+
max = num;
|
|
130
|
+
}
|
|
131
|
+
return max;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// GSD-2 — KNOWLEDGE.md parsing helpers shared by the consolidation scanner,
|
|
2
|
+
// the Patterns/Lessons backfill, and the hybrid projection renderer
|
|
3
|
+
// (ADR-013 Stage 2a/2b).
|
|
4
|
+
//
|
|
5
|
+
// The KNOWLEDGE.md format is locked in `files.ts:appendKnowledge`:
|
|
6
|
+
//
|
|
7
|
+
// # Project Knowledge
|
|
8
|
+
//
|
|
9
|
+
// <optional intro prose>
|
|
10
|
+
//
|
|
11
|
+
// ## Rules
|
|
12
|
+
//
|
|
13
|
+
// | # | Scope | Rule | Why | Added |
|
|
14
|
+
// |---|-------|------|-----|-------|
|
|
15
|
+
// | K001 | project | <rule text> | <reason> | <date> |
|
|
16
|
+
//
|
|
17
|
+
// ## Patterns
|
|
18
|
+
//
|
|
19
|
+
// | # | Pattern | Where | Notes |
|
|
20
|
+
// |---|---------|-------|-------|
|
|
21
|
+
// | P001 | <pattern> | <location> | <notes> |
|
|
22
|
+
//
|
|
23
|
+
// ## Lessons Learned
|
|
24
|
+
//
|
|
25
|
+
// | # | What Happened | Root Cause | Fix | Scope |
|
|
26
|
+
// |---|--------------|------------|-----|-------|
|
|
27
|
+
// | L001 | <what> | <cause> | <fix> | <scope> |
|
|
28
|
+
//
|
|
29
|
+
// Row IDs use a strict <prefix><digits> format (K001, P001, L001 …). Parsers
|
|
30
|
+
// skip the column-title and separator rows; only rows whose first cell
|
|
31
|
+
// matches the expected prefix are emitted.
|
|
32
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
33
|
+
import { resolveGsdRootFile } from "./paths.js";
|
|
34
|
+
export const KNOWLEDGE_SECTIONS = [
|
|
35
|
+
{ table: "rules", heading: "## Rules", idPrefix: "K" },
|
|
36
|
+
{ table: "patterns", heading: "## Patterns", idPrefix: "P" },
|
|
37
|
+
{ table: "lessons", heading: "## Lessons Learned", idPrefix: "L" },
|
|
38
|
+
];
|
|
39
|
+
/** Read `.gsd/KNOWLEDGE.md` content if present. Returns "" when absent or unreadable. */
|
|
40
|
+
export function readKnowledgeMd(basePath) {
|
|
41
|
+
const path = resolveGsdRootFile(basePath, "KNOWLEDGE");
|
|
42
|
+
if (!existsSync(path))
|
|
43
|
+
return "";
|
|
44
|
+
try {
|
|
45
|
+
return readFileSync(path, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Resolve the canonical `.gsd/KNOWLEDGE.md` path. */
|
|
52
|
+
export function knowledgeMdPath(basePath) {
|
|
53
|
+
return resolveGsdRootFile(basePath, "KNOWLEDGE");
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parse KNOWLEDGE.md into row records. Skips intro prose, table headers,
|
|
57
|
+
* separator lines, and rows from unrecognized sections. Each row's first
|
|
58
|
+
* cell must match the section's expected prefix (K/P/L + digits).
|
|
59
|
+
*/
|
|
60
|
+
export function parseKnowledgeRows(content) {
|
|
61
|
+
const rows = [];
|
|
62
|
+
if (!content.trim())
|
|
63
|
+
return rows;
|
|
64
|
+
const lines = content.split("\n");
|
|
65
|
+
let activeSection;
|
|
66
|
+
for (const line of lines) {
|
|
67
|
+
const trimmed = line.trim();
|
|
68
|
+
if (trimmed.startsWith("## ")) {
|
|
69
|
+
activeSection = KNOWLEDGE_SECTIONS.find((s) => s.heading === trimmed);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!activeSection)
|
|
73
|
+
continue;
|
|
74
|
+
if (!trimmed.startsWith("|"))
|
|
75
|
+
continue;
|
|
76
|
+
const idMatch = new RegExp(`^\\|\\s*(${activeSection.idPrefix}\\d+)\\s*\\|`).exec(trimmed);
|
|
77
|
+
if (!idMatch)
|
|
78
|
+
continue;
|
|
79
|
+
rows.push({
|
|
80
|
+
table: activeSection.table,
|
|
81
|
+
id: idMatch[1] ?? "",
|
|
82
|
+
raw: trimmed,
|
|
83
|
+
cells: splitPipeRow(trimmed),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return rows;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Slice the KNOWLEDGE.md content to just the intro prose plus the `## Rules`
|
|
90
|
+
* section, dropping `## Patterns` and `## Lessons Learned`. Used by
|
|
91
|
+
* `loadKnowledgeBlock` to avoid double-injecting Patterns and Lessons —
|
|
92
|
+
* those reach the LLM via `loadMemoryBlock` after the ADR-013 Stage 2b
|
|
93
|
+
* cutover, so re-emitting them through the KNOWLEDGE.md block is pure
|
|
94
|
+
* token-cost overhead.
|
|
95
|
+
*
|
|
96
|
+
* Returns the full content unchanged when no `## Rules` heading exists
|
|
97
|
+
* (legacy projects or unusual layouts — better to over-inject than drop
|
|
98
|
+
* unfamiliar content silently).
|
|
99
|
+
*/
|
|
100
|
+
export function extractIntroAndRules(content) {
|
|
101
|
+
if (!content.trim())
|
|
102
|
+
return "";
|
|
103
|
+
const lines = content.split("\n");
|
|
104
|
+
const rulesIdx = lines.findIndex((l) => l.trim() === "## Rules");
|
|
105
|
+
if (rulesIdx === -1)
|
|
106
|
+
return content;
|
|
107
|
+
// End of the Rules section is the next `## ` heading (Patterns or
|
|
108
|
+
// Lessons Learned) or end-of-file. Drop trailing blank lines so the
|
|
109
|
+
// caller can join the slice without producing a triple newline.
|
|
110
|
+
let endIdx = lines.length;
|
|
111
|
+
for (let i = rulesIdx + 1; i < lines.length; i++) {
|
|
112
|
+
if (lines[i].startsWith("## ")) {
|
|
113
|
+
endIdx = i;
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const slice = lines.slice(0, endIdx);
|
|
118
|
+
while (slice.length > 0 && slice[slice.length - 1].trim() === "") {
|
|
119
|
+
slice.pop();
|
|
120
|
+
}
|
|
121
|
+
return slice.join("\n") + "\n";
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Split a Markdown table row on un-escaped pipes. Returns the cell values
|
|
125
|
+
* (without the leading/trailing empty fragments from `| ... |`), each
|
|
126
|
+
* trimmed. Escaped pipes (`\|`) inside a cell are preserved as `|` in the
|
|
127
|
+
* output.
|
|
128
|
+
*/
|
|
129
|
+
export function splitPipeRow(row) {
|
|
130
|
+
const cells = [];
|
|
131
|
+
let current = "";
|
|
132
|
+
for (let i = 0; i < row.length; i++) {
|
|
133
|
+
const ch = row[i];
|
|
134
|
+
if (ch === "\\" && row[i + 1] === "|") {
|
|
135
|
+
current += "|";
|
|
136
|
+
i += 1;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (ch === "|") {
|
|
140
|
+
cells.push(current.trim());
|
|
141
|
+
current = "";
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
current += ch;
|
|
145
|
+
}
|
|
146
|
+
if (current.trim().length > 0) {
|
|
147
|
+
cells.push(current.trim());
|
|
148
|
+
}
|
|
149
|
+
// Drop the leading empty fragment from `|<cell>|...|` — the first split
|
|
150
|
+
// produces an empty string before the first pipe.
|
|
151
|
+
if (cells.length > 0 && cells[0] === "")
|
|
152
|
+
cells.shift();
|
|
153
|
+
return cells;
|
|
154
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// GSD2 — KNOWLEDGE.md hybrid projection renderer (ADR-013 Stage 2b).
|
|
2
|
+
//
|
|
3
|
+
// Renders `.gsd/KNOWLEDGE.md` as a hybrid file:
|
|
4
|
+
// - Rules section: read directly from the existing KNOWLEDGE.md (manual,
|
|
5
|
+
// per ADR-013 line 39 — Rules are not migrated to memories).
|
|
6
|
+
// - Patterns section: read from `memories` where `category = "pattern"`
|
|
7
|
+
// AND `structured_fields.sourceKnowledgeId` is set (matches the marker
|
|
8
|
+
// written by knowledge-backfill.ts).
|
|
9
|
+
// - Lessons Learned section: read from `memories` where
|
|
10
|
+
// `category = "gotcha"` AND `structured_fields.sourceKnowledgeId` is set.
|
|
11
|
+
//
|
|
12
|
+
// Triggered opportunistically by `buildBeforeAgentStartResult` after the
|
|
13
|
+
// knowledge backfill runs. Output is byte-stable when nothing has changed
|
|
14
|
+
// (atomic write). The Rules section is preserved verbatim — including
|
|
15
|
+
// indentation, trailing whitespace, and comments — so manual edits to that
|
|
16
|
+
// section continue to round-trip through `/gsd knowledge`.
|
|
17
|
+
//
|
|
18
|
+
// Memories captured directly via `capture_thought` (without a
|
|
19
|
+
// `sourceKnowledgeId` marker) are intentionally NOT rendered into
|
|
20
|
+
// KNOWLEDGE.md. They remain accessible via the loadMemoryBlock auto-injection
|
|
21
|
+
// surface; KNOWLEDGE.md projects only the KNOWLEDGE.md-originating subset.
|
|
22
|
+
import { atomicWriteSync } from "./atomic-write.js";
|
|
23
|
+
import { _getAdapter, isDbAvailable } from "./gsd-db.js";
|
|
24
|
+
import { KNOWLEDGE_SECTIONS, knowledgeMdPath, readKnowledgeMd, } from "./knowledge-parser.js";
|
|
25
|
+
import { logWarning } from "./workflow-logger.js";
|
|
26
|
+
const RULES_HEADING = "## Rules";
|
|
27
|
+
const PATTERNS_HEADING = "## Patterns";
|
|
28
|
+
const LESSONS_HEADING = "## Lessons Learned";
|
|
29
|
+
const PATTERNS_HEADER = "| # | Pattern | Where | Notes |";
|
|
30
|
+
const PATTERNS_SEPARATOR = "|---|---------|-------|-------|";
|
|
31
|
+
const LESSONS_HEADER = "| # | What Happened | Root Cause | Fix | Scope |";
|
|
32
|
+
const LESSONS_SEPARATOR = "|---|--------------|------------|-----|-------|";
|
|
33
|
+
const DEFAULT_INTRO = [
|
|
34
|
+
"# Project Knowledge",
|
|
35
|
+
"",
|
|
36
|
+
"Append-only register of project-specific rules, patterns, and lessons learned.",
|
|
37
|
+
"Agents read this before every unit. Add entries when you discover something worth remembering.",
|
|
38
|
+
"",
|
|
39
|
+
].join("\n");
|
|
40
|
+
/**
|
|
41
|
+
* Read pattern memories that originated from KNOWLEDGE.md, ordered by
|
|
42
|
+
* `sourceKnowledgeId` (lexicographic — P001 < P002 < P010). Memories whose
|
|
43
|
+
* structuredFields fail to parse are skipped silently; they are diagnosed
|
|
44
|
+
* separately by the memory-consolidation scanner.
|
|
45
|
+
*/
|
|
46
|
+
function readKnowledgeMemories(category) {
|
|
47
|
+
if (!isDbAvailable())
|
|
48
|
+
return { ok: false, rows: [] };
|
|
49
|
+
const adapter = _getAdapter();
|
|
50
|
+
if (!adapter)
|
|
51
|
+
return { ok: false, rows: [] };
|
|
52
|
+
try {
|
|
53
|
+
const rows = adapter
|
|
54
|
+
.prepare("SELECT structured_fields FROM memories WHERE category = :cat AND structured_fields IS NOT NULL")
|
|
55
|
+
.all({ ":cat": category });
|
|
56
|
+
const out = [];
|
|
57
|
+
for (const row of rows) {
|
|
58
|
+
if (!row.structured_fields)
|
|
59
|
+
continue;
|
|
60
|
+
let sf;
|
|
61
|
+
try {
|
|
62
|
+
sf = JSON.parse(row.structured_fields);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const sourceId = sf["sourceKnowledgeId"];
|
|
68
|
+
if (typeof sourceId !== "string" || sourceId.length === 0)
|
|
69
|
+
continue;
|
|
70
|
+
out.push({ sourceId, structured: sf });
|
|
71
|
+
}
|
|
72
|
+
// Lexicographic sort matches the docstring contract (P001 < P002 < P010).
|
|
73
|
+
// DB seq order is creation-time; sorting by sourceId stabilizes the
|
|
74
|
+
// rendered output across reruns.
|
|
75
|
+
out.sort((a, b) => a.sourceId.localeCompare(b.sourceId));
|
|
76
|
+
return { ok: true, rows: out };
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return { ok: false, rows: [] };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function escapeCell(value) {
|
|
83
|
+
return (value ?? "")
|
|
84
|
+
.replace(/\s+/g, " ")
|
|
85
|
+
.replace(/\|/g, "\\|")
|
|
86
|
+
.trim();
|
|
87
|
+
}
|
|
88
|
+
function renderPatternsSection(memories) {
|
|
89
|
+
const lines = [PATTERNS_HEADING, "", PATTERNS_HEADER, PATTERNS_SEPARATOR];
|
|
90
|
+
for (const m of memories) {
|
|
91
|
+
const pattern = escapeCell(typeof m.structured["pattern"] === "string" ? m.structured["pattern"] : "");
|
|
92
|
+
const where = escapeCell(typeof m.structured["where"] === "string" ? m.structured["where"] : "");
|
|
93
|
+
const notes = escapeCell(typeof m.structured["notes"] === "string" ? m.structured["notes"] : "");
|
|
94
|
+
lines.push(`| ${m.sourceId} | ${pattern} | ${where || "—"} | ${notes || "—"} |`);
|
|
95
|
+
}
|
|
96
|
+
lines.push("");
|
|
97
|
+
return lines;
|
|
98
|
+
}
|
|
99
|
+
function renderLessonsSection(memories) {
|
|
100
|
+
const lines = [LESSONS_HEADING, "", LESSONS_HEADER, LESSONS_SEPARATOR];
|
|
101
|
+
for (const m of memories) {
|
|
102
|
+
const what = escapeCell(typeof m.structured["whatHappened"] === "string" ? m.structured["whatHappened"] : "");
|
|
103
|
+
const rootCause = escapeCell(typeof m.structured["rootCause"] === "string" ? m.structured["rootCause"] : "");
|
|
104
|
+
const fix = escapeCell(typeof m.structured["fix"] === "string" ? m.structured["fix"] : "");
|
|
105
|
+
const scope = escapeCell(typeof m.structured["scopeText"] === "string" ? m.structured["scopeText"] : "");
|
|
106
|
+
lines.push(`| ${m.sourceId} | ${what} | ${rootCause || "—"} | ${fix || "—"} | ${scope || "project"} |`);
|
|
107
|
+
}
|
|
108
|
+
lines.push("");
|
|
109
|
+
return lines;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Extract the Rules section (heading + table) from the existing
|
|
113
|
+
* `KNOWLEDGE.md` content, verbatim. Returns an empty default section
|
|
114
|
+
* (heading + empty table) when the source has no `## Rules` heading.
|
|
115
|
+
*/
|
|
116
|
+
function extractRulesSection(existing) {
|
|
117
|
+
const lines = existing.split("\n");
|
|
118
|
+
const startIdx = lines.findIndex((l) => l.trim() === RULES_HEADING);
|
|
119
|
+
if (startIdx === -1) {
|
|
120
|
+
return [
|
|
121
|
+
RULES_HEADING,
|
|
122
|
+
"",
|
|
123
|
+
"| # | Scope | Rule | Why | Added |",
|
|
124
|
+
"|---|-------|------|-----|-------|",
|
|
125
|
+
"",
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
// Find the next H2 heading that ends the Rules section.
|
|
129
|
+
let endIdx = lines.length;
|
|
130
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
131
|
+
if (lines[i].startsWith("## ")) {
|
|
132
|
+
endIdx = i;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Strip trailing blank lines from the captured slice — the assembled
|
|
137
|
+
// output adds its own separator blank line between sections.
|
|
138
|
+
const slice = lines.slice(startIdx, endIdx);
|
|
139
|
+
while (slice.length > 0 && slice[slice.length - 1].trim() === "") {
|
|
140
|
+
slice.pop();
|
|
141
|
+
}
|
|
142
|
+
slice.push("");
|
|
143
|
+
return slice;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Extract the intro prose (anything before `## Rules`) verbatim, preserving
|
|
147
|
+
* any title (`# Project Knowledge`), comments, and description text. Falls
|
|
148
|
+
* back to the `DEFAULT_INTRO` template when the source has no Rules heading
|
|
149
|
+
* yet.
|
|
150
|
+
*/
|
|
151
|
+
function extractIntro(existing) {
|
|
152
|
+
if (!existing.trim())
|
|
153
|
+
return DEFAULT_INTRO;
|
|
154
|
+
const lines = existing.split("\n");
|
|
155
|
+
const rulesIdx = lines.findIndex((l) => l.trim() === RULES_HEADING);
|
|
156
|
+
if (rulesIdx === -1)
|
|
157
|
+
return DEFAULT_INTRO;
|
|
158
|
+
// Trim trailing blank lines so the assembly adds its own separator.
|
|
159
|
+
const slice = lines.slice(0, rulesIdx);
|
|
160
|
+
while (slice.length > 0 && slice[slice.length - 1].trim() === "") {
|
|
161
|
+
slice.pop();
|
|
162
|
+
}
|
|
163
|
+
slice.push("");
|
|
164
|
+
return slice.join("\n");
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Render the hybrid `KNOWLEDGE.md`: manual Rules + projected Patterns +
|
|
168
|
+
* projected Lessons. Returns the rendered content and a flag indicating
|
|
169
|
+
* whether the file was written (skipped when content is byte-identical to
|
|
170
|
+
* what's on disk).
|
|
171
|
+
*
|
|
172
|
+
* Best-effort: catches all errors and returns `{ written: false, content: "" }`.
|
|
173
|
+
*/
|
|
174
|
+
export function renderKnowledgeProjection(basePath) {
|
|
175
|
+
try {
|
|
176
|
+
const existing = readKnowledgeMd(basePath);
|
|
177
|
+
const intro = extractIntro(existing);
|
|
178
|
+
const rules = extractRulesSection(existing);
|
|
179
|
+
const patternMemories = readKnowledgeMemories("pattern");
|
|
180
|
+
const lessonMemories = readKnowledgeMemories("gotcha");
|
|
181
|
+
if (!patternMemories.ok || !lessonMemories.ok) {
|
|
182
|
+
return { written: false, content: existing };
|
|
183
|
+
}
|
|
184
|
+
const patterns = renderPatternsSection(patternMemories.rows);
|
|
185
|
+
const lessons = renderLessonsSection(lessonMemories.rows);
|
|
186
|
+
const introText = intro
|
|
187
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
188
|
+
.replace(/\s+$/g, "");
|
|
189
|
+
const projectedText = [...patterns, ...lessons]
|
|
190
|
+
.join("\n")
|
|
191
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
192
|
+
.replace(/\s+$/g, "");
|
|
193
|
+
const content = [introText, rules.join("\n"), projectedText]
|
|
194
|
+
.join("\n")
|
|
195
|
+
.replace(/\s+$/g, "")
|
|
196
|
+
+ "\n";
|
|
197
|
+
if (content === existing) {
|
|
198
|
+
return { written: false, content };
|
|
199
|
+
}
|
|
200
|
+
atomicWriteSync(knowledgeMdPath(basePath), content, "utf-8");
|
|
201
|
+
return { written: true, content };
|
|
202
|
+
}
|
|
203
|
+
catch (e) {
|
|
204
|
+
logWarning("renderer", `KNOWLEDGE.md projection render failed: ${e.message}`);
|
|
205
|
+
return { written: false, content: "" };
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Re-export the section headings so tests can assert on the canonical
|
|
209
|
+
// structure without re-defining the strings.
|
|
210
|
+
export { KNOWLEDGE_SECTIONS };
|