@soleri/core 9.0.4 → 9.3.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/data/flows/build.flow.yaml +8 -9
- package/data/flows/deliver.flow.yaml +9 -10
- package/data/flows/design.flow.yaml +3 -4
- package/data/flows/enhance.flow.yaml +5 -6
- package/data/flows/explore.flow.yaml +3 -4
- package/data/flows/fix.flow.yaml +5 -6
- package/data/flows/plan.flow.yaml +4 -5
- package/data/flows/review.flow.yaml +3 -4
- package/dist/brain/intelligence.d.ts +27 -0
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +160 -14
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/brain/learning-radar.d.ts +4 -0
- package/dist/brain/learning-radar.d.ts.map +1 -1
- package/dist/brain/learning-radar.js +20 -1
- package/dist/brain/learning-radar.js.map +1 -1
- package/dist/brain/strength-scorer.d.ts +31 -0
- package/dist/brain/strength-scorer.d.ts.map +1 -0
- package/dist/brain/strength-scorer.js +264 -0
- package/dist/brain/strength-scorer.js.map +1 -0
- package/dist/chat/agent-loop.d.ts.map +1 -1
- package/dist/chat/agent-loop.js +2 -0
- package/dist/chat/agent-loop.js.map +1 -1
- package/dist/chat/notifications.d.ts.map +1 -1
- package/dist/chat/notifications.js +2 -0
- package/dist/chat/notifications.js.map +1 -1
- package/dist/claudemd/compose.js +1 -1
- package/dist/claudemd/compose.js.map +1 -1
- package/dist/control/intent-router.d.ts.map +1 -1
- package/dist/control/intent-router.js +12 -4
- package/dist/control/intent-router.js.map +1 -1
- package/dist/curator/contradiction-detector.d.ts +27 -0
- package/dist/curator/contradiction-detector.d.ts.map +1 -0
- package/dist/curator/contradiction-detector.js +62 -0
- package/dist/curator/contradiction-detector.js.map +1 -0
- package/dist/curator/curator.d.ts +3 -4
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +94 -453
- package/dist/curator/curator.js.map +1 -1
- package/dist/curator/duplicate-detector.d.ts +14 -0
- package/dist/curator/duplicate-detector.d.ts.map +1 -0
- package/dist/curator/duplicate-detector.js +77 -0
- package/dist/curator/duplicate-detector.js.map +1 -0
- package/dist/curator/health-audit.d.ts +15 -0
- package/dist/curator/health-audit.d.ts.map +1 -0
- package/dist/curator/health-audit.js +97 -0
- package/dist/curator/health-audit.js.map +1 -0
- package/dist/curator/metadata-enricher.d.ts +17 -0
- package/dist/curator/metadata-enricher.d.ts.map +1 -0
- package/dist/curator/metadata-enricher.js +60 -0
- package/dist/curator/metadata-enricher.js.map +1 -0
- package/dist/curator/schema.d.ts +7 -0
- package/dist/curator/schema.d.ts.map +1 -0
- package/dist/curator/schema.js +62 -0
- package/dist/curator/schema.js.map +1 -0
- package/dist/curator/tag-manager.d.ts +36 -0
- package/dist/curator/tag-manager.d.ts.map +1 -0
- package/dist/curator/tag-manager.js +78 -0
- package/dist/curator/tag-manager.js.map +1 -0
- package/dist/engine/bin/soleri-engine.js +24 -3
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/core-ops.d.ts.map +1 -1
- package/dist/engine/core-ops.js +23 -8
- package/dist/engine/core-ops.js.map +1 -1
- package/dist/engine/module-manifest.d.ts.map +1 -1
- package/dist/engine/module-manifest.js +42 -2
- package/dist/engine/module-manifest.js.map +1 -1
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +50 -2
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/errors/retry.d.ts.map +1 -1
- package/dist/errors/retry.js +2 -0
- package/dist/errors/retry.js.map +1 -1
- package/dist/facades/types.d.ts +1 -1
- package/dist/flows/chain-types.d.ts +18 -18
- package/dist/flows/gate-evaluator.d.ts.map +1 -1
- package/dist/flows/gate-evaluator.js +22 -0
- package/dist/flows/gate-evaluator.js.map +1 -1
- package/dist/flows/types.d.ts +157 -28
- package/dist/flows/types.d.ts.map +1 -1
- package/dist/flows/types.js +4 -0
- package/dist/flows/types.js.map +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/intake/intake-pipeline.d.ts.map +1 -1
- package/dist/intake/intake-pipeline.js +1 -0
- package/dist/intake/intake-pipeline.js.map +1 -1
- package/dist/intake/text-ingester.d.ts.map +1 -1
- package/dist/intake/text-ingester.js +2 -0
- package/dist/intake/text-ingester.js.map +1 -1
- package/dist/llm/key-pool.d.ts +1 -1
- package/dist/llm/key-pool.d.ts.map +1 -1
- package/dist/llm/key-pool.js +3 -4
- package/dist/llm/key-pool.js.map +1 -1
- package/dist/llm/utils.d.ts.map +1 -1
- package/dist/llm/utils.js +2 -0
- package/dist/llm/utils.js.map +1 -1
- package/dist/migrations/migration-runner.test-helpers.d.ts +13 -0
- package/dist/migrations/migration-runner.test-helpers.d.ts.map +1 -0
- package/dist/migrations/migration-runner.test-helpers.js +47 -0
- package/dist/migrations/migration-runner.test-helpers.js.map +1 -0
- package/dist/operator/operator-profile.d.ts +44 -0
- package/dist/operator/operator-profile.d.ts.map +1 -0
- package/dist/operator/operator-profile.js +383 -0
- package/dist/operator/operator-profile.js.map +1 -0
- package/dist/operator/operator-signals.d.ts +45 -0
- package/dist/operator/operator-signals.d.ts.map +1 -0
- package/dist/operator/operator-signals.js +228 -0
- package/dist/operator/operator-signals.js.map +1 -0
- package/dist/operator/operator-types.d.ts +360 -0
- package/dist/operator/operator-types.d.ts.map +1 -0
- package/dist/operator/operator-types.js +24 -0
- package/dist/operator/operator-types.js.map +1 -0
- package/dist/packs/types.d.ts +27 -27
- package/dist/paths.d.ts +40 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +98 -0
- package/dist/paths.js.map +1 -0
- package/dist/persistence/index.d.ts +1 -1
- package/dist/persistence/index.d.ts.map +1 -1
- package/dist/persistence/index.js +1 -1
- package/dist/persistence/index.js.map +1 -1
- package/dist/persistence/sqlite-provider.d.ts +2 -0
- package/dist/persistence/sqlite-provider.d.ts.map +1 -1
- package/dist/persistence/sqlite-provider.js +8 -5
- package/dist/persistence/sqlite-provider.js.map +1 -1
- package/dist/planning/evidence-collector.d.ts +13 -1
- package/dist/planning/evidence-collector.d.ts.map +1 -1
- package/dist/planning/evidence-collector.js +33 -0
- package/dist/planning/evidence-collector.js.map +1 -1
- package/dist/planning/gap-analysis.d.ts +5 -4
- package/dist/planning/gap-analysis.d.ts.map +1 -1
- package/dist/planning/gap-analysis.js +7 -341
- package/dist/planning/gap-analysis.js.map +1 -1
- package/dist/planning/gap-passes.d.ts +19 -0
- package/dist/planning/gap-passes.d.ts.map +1 -0
- package/dist/planning/gap-passes.js +174 -0
- package/dist/planning/gap-passes.js.map +1 -0
- package/dist/planning/gap-patterns.d.ts +29 -0
- package/dist/planning/gap-patterns.d.ts.map +1 -0
- package/dist/planning/gap-patterns.js +175 -0
- package/dist/planning/gap-patterns.js.map +1 -0
- package/dist/planning/gap-types.d.ts +1 -1
- package/dist/planning/gap-types.d.ts.map +1 -1
- package/dist/planning/gap-types.js +1 -0
- package/dist/planning/gap-types.js.map +1 -1
- package/dist/planning/github-projection.d.ts +122 -0
- package/dist/planning/github-projection.d.ts.map +1 -0
- package/dist/planning/github-projection.js +313 -0
- package/dist/planning/github-projection.js.map +1 -0
- package/dist/planning/impact-analyzer.d.ts +26 -0
- package/dist/planning/impact-analyzer.d.ts.map +1 -0
- package/dist/planning/impact-analyzer.js +201 -0
- package/dist/planning/impact-analyzer.js.map +1 -0
- package/dist/planning/plan-lifecycle.d.ts +136 -0
- package/dist/planning/plan-lifecycle.d.ts.map +1 -0
- package/dist/planning/plan-lifecycle.js +309 -0
- package/dist/planning/plan-lifecycle.js.map +1 -0
- package/dist/planning/planner-types.d.ts +202 -0
- package/dist/planning/planner-types.d.ts.map +1 -0
- package/dist/planning/planner-types.js +6 -0
- package/dist/planning/planner-types.js.map +1 -0
- package/dist/planning/planner.d.ts +31 -383
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +151 -832
- package/dist/planning/planner.js.map +1 -1
- package/dist/planning/rationalization-detector.d.ts +32 -0
- package/dist/planning/rationalization-detector.d.ts.map +1 -0
- package/dist/planning/rationalization-detector.js +89 -0
- package/dist/planning/rationalization-detector.js.map +1 -0
- package/dist/planning/reconciliation-engine.d.ts +47 -0
- package/dist/planning/reconciliation-engine.d.ts.map +1 -0
- package/dist/planning/reconciliation-engine.js +128 -0
- package/dist/planning/reconciliation-engine.js.map +1 -0
- package/dist/planning/task-verifier.d.ts +85 -0
- package/dist/planning/task-verifier.d.ts.map +1 -0
- package/dist/planning/task-verifier.js +235 -0
- package/dist/planning/task-verifier.js.map +1 -0
- package/dist/plugins/types.d.ts +4 -4
- package/dist/runtime/admin-ops.d.ts +2 -2
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +44 -17
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
- package/dist/runtime/admin-setup-ops.js +22 -46
- package/dist/runtime/admin-setup-ops.js.map +1 -1
- package/dist/runtime/archive-ops.d.ts +10 -0
- package/dist/runtime/archive-ops.d.ts.map +1 -0
- package/dist/runtime/archive-ops.js +310 -0
- package/dist/runtime/archive-ops.js.map +1 -0
- package/dist/runtime/branching-ops.d.ts +12 -0
- package/dist/runtime/branching-ops.d.ts.map +1 -0
- package/dist/runtime/branching-ops.js +100 -0
- package/dist/runtime/branching-ops.js.map +1 -0
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +42 -7
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/claude-md-helpers.js +1 -1
- package/dist/runtime/claude-md-helpers.js.map +1 -1
- package/dist/runtime/context-health.d.ts +31 -0
- package/dist/runtime/context-health.d.ts.map +1 -0
- package/dist/runtime/context-health.js +57 -0
- package/dist/runtime/context-health.js.map +1 -0
- package/dist/runtime/facades/archive-facade.d.ts +10 -0
- package/dist/runtime/facades/archive-facade.d.ts.map +1 -0
- package/dist/runtime/facades/archive-facade.js +11 -0
- package/dist/runtime/facades/archive-facade.js.map +1 -0
- package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
- package/dist/runtime/facades/brain-facade.js +2 -0
- package/dist/runtime/facades/brain-facade.js.map +1 -1
- package/dist/runtime/facades/branching-facade.d.ts +7 -0
- package/dist/runtime/facades/branching-facade.d.ts.map +1 -0
- package/dist/runtime/facades/branching-facade.js +8 -0
- package/dist/runtime/facades/branching-facade.js.map +1 -0
- package/dist/runtime/facades/chat-facade.d.ts +7 -0
- package/dist/runtime/facades/chat-facade.d.ts.map +1 -1
- package/dist/runtime/facades/chat-facade.js +15 -800
- package/dist/runtime/facades/chat-facade.js.map +1 -1
- package/dist/runtime/facades/chat-service-ops.d.ts +9 -0
- package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -0
- package/dist/runtime/facades/chat-service-ops.js +332 -0
- package/dist/runtime/facades/chat-service-ops.js.map +1 -0
- package/dist/runtime/facades/chat-session-ops.d.ts +8 -0
- package/dist/runtime/facades/chat-session-ops.d.ts.map +1 -0
- package/dist/runtime/facades/chat-session-ops.js +136 -0
- package/dist/runtime/facades/chat-session-ops.js.map +1 -0
- package/dist/runtime/facades/chat-state.d.ts +31 -0
- package/dist/runtime/facades/chat-state.d.ts.map +1 -0
- package/dist/runtime/facades/chat-state.js +32 -0
- package/dist/runtime/facades/chat-state.js.map +1 -0
- package/dist/runtime/facades/chat-transport-ops.d.ts +9 -0
- package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -0
- package/dist/runtime/facades/chat-transport-ops.js +337 -0
- package/dist/runtime/facades/chat-transport-ops.js.map +1 -0
- package/dist/runtime/facades/control-facade.d.ts.map +1 -1
- package/dist/runtime/facades/control-facade.js +4 -1
- package/dist/runtime/facades/control-facade.js.map +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +48 -0
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/intake-facade.d.ts +9 -0
- package/dist/runtime/facades/intake-facade.d.ts.map +1 -0
- package/dist/runtime/facades/intake-facade.js +11 -0
- package/dist/runtime/facades/intake-facade.js.map +1 -0
- package/dist/runtime/facades/links-facade.d.ts +9 -0
- package/dist/runtime/facades/links-facade.d.ts.map +1 -0
- package/dist/runtime/facades/links-facade.js +10 -0
- package/dist/runtime/facades/links-facade.js.map +1 -0
- package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
- package/dist/runtime/facades/memory-facade.js +75 -6
- package/dist/runtime/facades/memory-facade.js.map +1 -1
- package/dist/runtime/facades/operator-facade.d.ts +8 -0
- package/dist/runtime/facades/operator-facade.d.ts.map +1 -0
- package/dist/runtime/facades/operator-facade.js +220 -0
- package/dist/runtime/facades/operator-facade.js.map +1 -0
- package/dist/runtime/facades/orchestrate-facade.js +3 -3
- package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
- package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
- package/dist/runtime/facades/plan-facade.js +42 -6
- package/dist/runtime/facades/plan-facade.js.map +1 -1
- package/dist/runtime/facades/review-facade.d.ts +7 -0
- package/dist/runtime/facades/review-facade.d.ts.map +1 -0
- package/dist/runtime/facades/review-facade.js +8 -0
- package/dist/runtime/facades/review-facade.js.map +1 -0
- package/dist/runtime/facades/sync-facade.d.ts +7 -0
- package/dist/runtime/facades/sync-facade.d.ts.map +1 -0
- package/dist/runtime/facades/sync-facade.js +8 -0
- package/dist/runtime/facades/sync-facade.js.map +1 -0
- package/dist/runtime/facades/tier-facade.d.ts +7 -0
- package/dist/runtime/facades/tier-facade.d.ts.map +1 -0
- package/dist/runtime/facades/tier-facade.js +8 -0
- package/dist/runtime/facades/tier-facade.js.map +1 -0
- package/dist/runtime/facades/vault-facade.d.ts +12 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +55 -251
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/github-integration.d.ts +49 -0
- package/dist/runtime/github-integration.d.ts.map +1 -0
- package/dist/runtime/github-integration.js +120 -0
- package/dist/runtime/github-integration.js.map +1 -0
- package/dist/runtime/grading-ops.js +1 -1
- package/dist/runtime/grading-ops.js.map +1 -1
- package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
- package/dist/runtime/memory-extra-ops.js +6 -2
- package/dist/runtime/memory-extra-ops.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +386 -37
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js +69 -4
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/review-ops.d.ts +10 -0
- package/dist/runtime/review-ops.d.ts.map +1 -0
- package/dist/runtime/review-ops.js +97 -0
- package/dist/runtime/review-ops.js.map +1 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +29 -12
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/session-briefing.d.ts +3 -0
- package/dist/runtime/session-briefing.d.ts.map +1 -1
- package/dist/runtime/session-briefing.js +72 -1
- package/dist/runtime/session-briefing.js.map +1 -1
- package/dist/runtime/sync-ops.d.ts +12 -0
- package/dist/runtime/sync-ops.d.ts.map +1 -0
- package/dist/runtime/sync-ops.js +288 -0
- package/dist/runtime/sync-ops.js.map +1 -0
- package/dist/runtime/tier-ops.d.ts +13 -0
- package/dist/runtime/tier-ops.d.ts.map +1 -0
- package/dist/runtime/tier-ops.js +110 -0
- package/dist/runtime/tier-ops.js.map +1 -0
- package/dist/runtime/types.d.ts +10 -4
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.d.ts +5 -4
- package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.js +5 -300
- package/dist/runtime/vault-extra-ops.js.map +1 -1
- package/dist/runtime/vault-sharing-ops.d.ts +4 -4
- package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
- package/dist/runtime/vault-sharing-ops.js +5 -300
- package/dist/runtime/vault-sharing-ops.js.map +1 -1
- package/dist/skills/sync-skills.d.ts +27 -0
- package/dist/skills/sync-skills.d.ts.map +1 -0
- package/dist/skills/sync-skills.js +81 -0
- package/dist/skills/sync-skills.js.map +1 -0
- package/dist/update-check.d.ts +14 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +96 -0
- package/dist/update-check.js.map +1 -0
- package/dist/vault/linking.d.ts +10 -12
- package/dist/vault/linking.d.ts.map +1 -1
- package/dist/vault/linking.js +140 -161
- package/dist/vault/linking.js.map +1 -1
- package/dist/vault/vault-entries.d.ts +69 -0
- package/dist/vault/vault-entries.d.ts.map +1 -0
- package/dist/vault/vault-entries.js +299 -0
- package/dist/vault/vault-entries.js.map +1 -0
- package/dist/vault/vault-interfaces.d.ts +153 -0
- package/dist/vault/vault-interfaces.d.ts.map +1 -0
- package/dist/vault/vault-interfaces.js +2 -0
- package/dist/vault/vault-interfaces.js.map +1 -0
- package/dist/vault/vault-maintenance.d.ts +40 -0
- package/dist/vault/vault-maintenance.d.ts.map +1 -0
- package/dist/vault/vault-maintenance.js +146 -0
- package/dist/vault/vault-maintenance.js.map +1 -0
- package/dist/vault/vault-markdown-sync.d.ts +22 -0
- package/dist/vault/vault-markdown-sync.d.ts.map +1 -0
- package/dist/vault/vault-markdown-sync.js +143 -0
- package/dist/vault/vault-markdown-sync.js.map +1 -0
- package/dist/vault/vault-memories.d.ts +61 -0
- package/dist/vault/vault-memories.d.ts.map +1 -0
- package/dist/vault/vault-memories.js +242 -0
- package/dist/vault/vault-memories.js.map +1 -0
- package/dist/vault/vault-schema.d.ts +9 -0
- package/dist/vault/vault-schema.d.ts.map +1 -0
- package/dist/vault/vault-schema.js +205 -0
- package/dist/vault/vault-schema.js.map +1 -0
- package/dist/vault/vault.d.ts +29 -81
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +82 -931
- package/dist/vault/vault.js.map +1 -1
- package/package.json +7 -7
- package/src/agency/agency-manager.test.ts +620 -0
- package/src/agency/default-rules.test.ts +236 -0
- package/src/{__tests__ → brain}/brain-intelligence.test.ts +37 -14
- package/src/{__tests__ → brain}/brain.test.ts +1 -1
- package/src/brain/intelligence.ts +196 -15
- package/src/brain/learning-radar.ts +22 -1
- package/src/{__tests__ → brain}/second-brain-features.test.ts +4 -4
- package/src/{__tests__ → brain}/session-lifecycle.test.ts +2 -2
- package/src/capabilities/chain-mapping.test.ts +66 -0
- package/src/capabilities/registry.test.ts +359 -0
- package/src/chat/agent-loop.test.ts +384 -0
- package/src/chat/agent-loop.ts +2 -0
- package/src/{__tests__ → chat}/chat-differentiators.test.ts +3 -3
- package/src/{__tests__ → chat}/chat-enhanced.test.ts +4 -4
- package/src/{__tests__ → chat}/chat-transport.test.ts +6 -6
- package/src/chat/mcp-bridge.test.ts +178 -0
- package/src/chat/notifications.ts +2 -0
- package/src/chat/output-compressor.test.ts +164 -0
- package/src/claudemd/compose.test.ts +178 -0
- package/src/claudemd/compose.ts +1 -1
- package/src/claudemd/inject.test.ts +201 -0
- package/src/context/context-engine.test.ts +506 -0
- package/src/control/identity-manager.test.ts +305 -0
- package/src/control/intent-router.test.ts +360 -0
- package/src/control/intent-router.ts +13 -4
- package/src/curator/classifier.test.ts +110 -0
- package/src/curator/contradiction-detector.test.ts +205 -0
- package/src/curator/contradiction-detector.ts +87 -0
- package/src/{__tests__ → curator}/curator-pipeline-e2e.test.ts +10 -10
- package/src/{__tests__ → curator}/curator.test.ts +77 -1
- package/src/curator/curator.ts +160 -600
- package/src/curator/duplicate-detector.test.ts +245 -0
- package/src/curator/duplicate-detector.ts +103 -0
- package/src/curator/health-audit.ts +126 -0
- package/src/curator/metadata-enricher.ts +84 -0
- package/src/curator/quality-gate.test.ts +175 -0
- package/src/curator/schema.ts +65 -0
- package/src/curator/tag-manager.test.ts +173 -0
- package/src/curator/tag-manager.ts +109 -0
- package/src/domain-packs/inject-rules.test.ts +117 -0
- package/src/domain-packs/knowledge-installer.test.ts +163 -0
- package/src/domain-packs/loader.test.ts +86 -0
- package/src/domain-packs/pack-runtime.test.ts +140 -0
- package/src/domain-packs/skills-installer.test.ts +135 -0
- package/src/domain-packs/token-resolver.test.ts +148 -0
- package/src/domain-packs/types.test.ts +144 -0
- package/src/enforcement/adapters/claude-code.test.ts +216 -0
- package/src/enforcement/registry.test.ts +258 -0
- package/src/engine/bin/soleri-engine.ts +30 -4
- package/src/engine/core-ops.test.ts +254 -0
- package/src/engine/core-ops.ts +25 -8
- package/src/engine/module-manifest.test.ts +125 -0
- package/src/engine/module-manifest.ts +42 -2
- package/src/engine/register-engine.test.ts +235 -0
- package/src/engine/register-engine.ts +50 -3
- package/src/errors/classify.test.ts +203 -0
- package/src/errors/retry.test.ts +153 -0
- package/src/errors/retry.ts +2 -0
- package/src/errors/types.test.ts +108 -0
- package/src/events/event-bus.test.ts +149 -0
- package/src/extensions/middleware.test.ts +234 -0
- package/src/facades/facade-factory.test.ts +470 -0
- package/src/flows/chain-runner.test.ts +273 -0
- package/src/flows/context-router.test.ts +52 -0
- package/src/flows/dispatch-registry.test.ts +128 -0
- package/src/flows/epilogue.test.ts +113 -0
- package/src/flows/executor.test.ts +263 -0
- package/src/flows/gate-evaluator.test.ts +200 -0
- package/src/flows/gate-evaluator.ts +23 -0
- package/src/flows/types.ts +4 -0
- package/src/governance/governance.test.ts +842 -0
- package/src/{__tests__ → health}/health-registry.test.ts +75 -55
- package/src/health/vault-integrity.test.ts +110 -0
- package/src/index.ts +92 -0
- package/src/intake/content-classifier.test.ts +279 -0
- package/src/intake/dedup-gate.test.ts +147 -0
- package/src/intake/intake-pipeline.test.ts +508 -0
- package/src/intake/intake-pipeline.ts +1 -0
- package/src/intake/text-ingester.test.ts +200 -0
- package/src/intake/text-ingester.ts +2 -0
- package/src/llm/key-pool.test.ts +234 -0
- package/src/llm/key-pool.ts +3 -4
- package/src/llm/llm-client.test.ts +342 -0
- package/src/llm/oauth-discovery.test.ts +180 -0
- package/src/llm/utils.test.ts +371 -0
- package/src/llm/utils.ts +2 -0
- package/src/{__tests__ → logging}/logger.test.ts +44 -62
- package/src/loop/loop-manager.test.ts +515 -0
- package/src/migrations/migration-runner.edge-cases.test.ts +314 -0
- package/src/migrations/migration-runner.test-helpers.ts +64 -0
- package/src/migrations/migration-runner.test.ts +385 -0
- package/src/operator/auto-signal-pipeline.test.ts +207 -0
- package/src/operator/operator-profile-extended.test.ts +330 -0
- package/src/operator/operator-profile.test.ts +332 -0
- package/src/operator/operator-profile.ts +485 -0
- package/src/operator/operator-signals-extended.test.ts +257 -0
- package/src/operator/operator-signals.test.ts +277 -0
- package/src/operator/operator-signals.ts +262 -0
- package/src/operator/operator-types.ts +444 -0
- package/src/operator/prompts/hook-precompact-operator-dispatch.md +98 -0
- package/src/operator/prompts/subagent-soft-signal-extractor.md +130 -0
- package/src/operator/prompts/subagent-synthesis-cognition.md +190 -0
- package/src/operator/prompts/subagent-synthesis-communication.md +146 -0
- package/src/operator/prompts/subagent-synthesis-technical.md +170 -0
- package/src/operator/prompts/subagent-synthesis-trust.md +149 -0
- package/src/{__tests__ → packs}/pack-lockfile.test.ts +3 -3
- package/src/{__tests__ → packs}/pack-system.test.ts +2 -2
- package/src/paths.ts +115 -0
- package/src/persistence/index.ts +1 -1
- package/src/persistence/sqlite-provider.test.ts +540 -0
- package/src/persistence/sqlite-provider.ts +8 -5
- package/src/persona/defaults.test.ts +55 -0
- package/src/persona/loader.test.ts +67 -0
- package/src/persona/prompt-generator.test.ts +127 -0
- package/src/planning/evidence-collector.test.ts +515 -0
- package/src/planning/evidence-collector.ts +47 -0
- package/src/planning/gap-analysis-alternatives.test.ts +199 -0
- package/src/planning/gap-analysis.ts +21 -636
- package/src/planning/gap-passes.test.ts +554 -0
- package/src/planning/gap-passes.ts +367 -0
- package/src/planning/gap-patterns.test.ts +394 -0
- package/src/planning/gap-patterns.ts +317 -0
- package/src/planning/gap-types.ts +4 -1
- package/src/planning/github-projection.test.ts +182 -0
- package/src/planning/github-projection.ts +446 -0
- package/src/planning/impact-analyzer.test.ts +167 -0
- package/src/planning/impact-analyzer.ts +251 -0
- package/src/planning/plan-lifecycle.test.ts +379 -0
- package/src/planning/plan-lifecycle.ts +377 -0
- package/src/planning/planner-types.ts +215 -0
- package/src/{__tests__ → planning}/planner.test.ts +179 -15
- package/src/planning/planner.ts +221 -1112
- package/src/planning/rationalization-detector.test.ts +156 -0
- package/src/planning/rationalization-detector.ts +136 -0
- package/src/planning/reconciliation-engine.test.ts +158 -0
- package/src/planning/reconciliation-engine.ts +161 -0
- package/src/planning/task-verifier.test.ts +267 -0
- package/src/planning/task-verifier.ts +309 -0
- package/src/planning/verification-protocol.test.ts +201 -0
- package/src/playbooks/generic/generic-playbooks.test.ts +438 -0
- package/src/playbooks/index.test.ts +77 -0
- package/src/playbooks/playbook-executor.test.ts +253 -0
- package/src/playbooks/playbook-registry.test.ts +232 -0
- package/src/playbooks/playbook-seeder.test.ts +153 -0
- package/src/plugins/plugin-loader.test.ts +217 -0
- package/src/plugins/plugin-registry.test.ts +284 -0
- package/src/project/project-registry.test.ts +439 -0
- package/src/prompts/parser.test.ts +100 -0
- package/src/prompts/template-manager.test.ts +112 -0
- package/src/{__tests__ → queue}/async-infrastructure.test.ts +3 -3
- package/src/queue/job-queue.test.ts +327 -0
- package/src/queue/pipeline-runner.test.ts +209 -0
- package/src/runtime/admin-extra-ops.test.ts +513 -0
- package/src/runtime/admin-ops.test.ts +255 -0
- package/src/runtime/admin-ops.ts +45 -17
- package/src/runtime/admin-setup-ops.test.ts +327 -0
- package/src/runtime/admin-setup-ops.ts +26 -42
- package/src/runtime/archive-ops.test.ts +272 -0
- package/src/runtime/archive-ops.ts +347 -0
- package/src/runtime/branching-ops.test.ts +144 -0
- package/src/runtime/branching-ops.ts +107 -0
- package/src/runtime/capture-ops.test.ts +419 -0
- package/src/runtime/capture-ops.ts +50 -8
- package/src/runtime/chain-ops.test.ts +159 -0
- package/src/runtime/claude-md-helpers.test.ts +189 -0
- package/src/runtime/claude-md-helpers.ts +1 -1
- package/src/runtime/context-health.test.ts +76 -0
- package/src/runtime/context-health.ts +83 -0
- package/src/runtime/curator-extra-ops.test.ts +204 -0
- package/src/runtime/deprecation.test.ts +98 -0
- package/src/runtime/domain-ops.test.ts +278 -0
- package/src/runtime/facades/admin-facade.test.ts +330 -0
- package/src/runtime/facades/agency-facade.test.ts +278 -0
- package/src/runtime/facades/archive-facade.test.ts +308 -0
- package/src/runtime/facades/archive-facade.ts +14 -0
- package/src/runtime/facades/brain-facade.test.ts +818 -0
- package/src/runtime/facades/brain-facade.ts +2 -0
- package/src/runtime/facades/branching-facade.test.ts +43 -0
- package/src/runtime/facades/branching-facade.ts +11 -0
- package/src/runtime/facades/chat-facade.test.ts +219 -0
- package/src/runtime/facades/chat-facade.ts +15 -906
- package/src/runtime/facades/chat-service-ops.test.ts +381 -0
- package/src/runtime/facades/chat-service-ops.ts +376 -0
- package/src/runtime/facades/chat-session-ops.test.ts +212 -0
- package/src/runtime/facades/chat-session-ops.ts +146 -0
- package/src/runtime/facades/chat-state.ts +60 -0
- package/src/runtime/facades/chat-transport-ops.test.ts +336 -0
- package/src/runtime/facades/chat-transport-ops.ts +379 -0
- package/src/runtime/facades/context-facade.test.ts +123 -0
- package/src/runtime/facades/control-facade.test.ts +436 -0
- package/src/runtime/facades/control-facade.ts +6 -1
- package/src/runtime/facades/curator-facade.test.ts +303 -0
- package/src/runtime/facades/index.ts +48 -0
- package/src/runtime/facades/intake-facade.test.ts +215 -0
- package/src/runtime/facades/intake-facade.ts +14 -0
- package/src/runtime/facades/links-facade.test.ts +203 -0
- package/src/runtime/facades/links-facade.ts +13 -0
- package/src/runtime/facades/loop-facade.test.ts +262 -0
- package/src/runtime/facades/memory-facade.test.ts +283 -0
- package/src/runtime/facades/memory-facade.ts +78 -6
- package/src/runtime/facades/operator-facade.test.ts +221 -0
- package/src/runtime/facades/operator-facade.ts +244 -0
- package/src/runtime/facades/orchestrate-facade.test.ts +191 -0
- package/src/runtime/facades/orchestrate-facade.ts +3 -3
- package/src/runtime/facades/plan-facade.test.ts +283 -0
- package/src/runtime/facades/plan-facade.ts +47 -6
- package/src/runtime/facades/review-facade.test.ts +82 -0
- package/src/runtime/facades/review-facade.ts +11 -0
- package/src/runtime/facades/sync-facade.test.ts +113 -0
- package/src/runtime/facades/sync-facade.ts +11 -0
- package/src/runtime/facades/tier-facade.test.ts +47 -0
- package/src/runtime/facades/tier-facade.ts +11 -0
- package/src/runtime/facades/vault-facade.test.ts +563 -0
- package/src/runtime/facades/vault-facade.ts +66 -265
- package/src/runtime/feature-flags.test.ts +140 -0
- package/src/runtime/github-integration.test.ts +89 -0
- package/src/runtime/github-integration.ts +162 -0
- package/src/runtime/grading-ops.test.ts +172 -0
- package/src/runtime/grading-ops.ts +1 -1
- package/src/runtime/intake-ops.test.ts +261 -0
- package/src/runtime/loop-ops.test.ts +248 -0
- package/src/runtime/memory-cross-project-ops.test.ts +188 -0
- package/src/runtime/memory-extra-ops.test.ts +453 -0
- package/src/runtime/memory-extra-ops.ts +6 -2
- package/src/runtime/orchestrate-ops.test.ts +302 -0
- package/src/runtime/orchestrate-ops.ts +461 -45
- package/src/runtime/pack-ops.test.ts +175 -0
- package/src/runtime/planning-extra-ops.test.ts +593 -0
- package/src/runtime/planning-extra-ops.ts +74 -4
- package/src/{__tests__ → runtime}/playbook-ops-execution.test.ts +3 -3
- package/src/runtime/playbook-ops.test.ts +285 -0
- package/src/runtime/plugin-ops.test.ts +259 -0
- package/src/runtime/project-ops.test.ts +255 -0
- package/src/runtime/review-ops.test.ts +142 -0
- package/src/runtime/review-ops.ts +99 -0
- package/src/runtime/runtime.test.ts +363 -0
- package/src/runtime/runtime.ts +41 -12
- package/src/runtime/session-briefing.test.ts +431 -0
- package/src/runtime/session-briefing.ts +86 -1
- package/src/runtime/sync-ops.test.ts +212 -0
- package/src/runtime/sync-ops.ts +325 -0
- package/src/runtime/telemetry-ops.test.ts +157 -0
- package/src/runtime/tier-ops.test.ts +159 -0
- package/src/runtime/tier-ops.ts +119 -0
- package/src/runtime/types.ts +10 -4
- package/src/runtime/vault-extra-ops.test.ts +270 -0
- package/src/runtime/vault-extra-ops.ts +5 -332
- package/src/runtime/vault-linking-ops.test.ts +237 -0
- package/src/runtime/vault-sharing-ops.test.ts +127 -0
- package/src/runtime/vault-sharing-ops.ts +5 -329
- package/src/skills/sync-skills.ts +98 -0
- package/src/streams/normalize.test.ts +95 -0
- package/src/streams/replayable-stream.test.ts +166 -0
- package/src/telemetry/telemetry.test.ts +143 -0
- package/src/transport/http-server.test.ts +394 -0
- package/src/transport/lsp-server.test.ts +458 -0
- package/src/transport/rate-limiter.test.ts +126 -0
- package/src/transport/session-manager.test.ts +133 -0
- package/src/transport/token-auth.test.ts +136 -0
- package/src/transport/ws-server.test.ts +297 -0
- package/src/update-check.ts +111 -0
- package/src/vault/__tests__/vault-characterization.test.ts +579 -0
- package/src/vault/content-hash.test.ts +78 -0
- package/src/vault/git-vault-sync.test.ts +234 -0
- package/src/vault/knowledge-review.test.ts +269 -0
- package/src/vault/linking.test.ts +391 -0
- package/src/vault/linking.ts +188 -181
- package/src/vault/obsidian-sync.test.ts +345 -0
- package/src/vault/playbook.test.ts +152 -0
- package/src/vault/scope-detector.test.ts +185 -0
- package/src/vault/vault-branching.test.ts +252 -0
- package/src/{__tests__ → vault}/vault-connect.test.ts +1 -1
- package/src/vault/vault-entries.ts +426 -0
- package/src/vault/vault-maintenance.ts +200 -0
- package/src/vault/vault-manager.test.ts +206 -0
- package/src/vault/vault-markdown-sync.test.ts +203 -0
- package/src/vault/vault-markdown-sync.ts +163 -0
- package/src/vault/vault-memories.ts +339 -0
- package/src/{__tests__ → vault}/vault-scaling.test.ts +1 -1
- package/src/vault/vault-schema.ts +238 -0
- package/src/{__tests__ → vault}/vault-sharing.test.ts +4 -4
- package/src/{__tests__ → vault}/vault.test.ts +2 -2
- package/src/vault/vault.ts +87 -1123
- package/dist/cognee/client.d.ts +0 -43
- package/dist/cognee/client.d.ts.map +0 -1
- package/dist/cognee/client.js +0 -375
- package/dist/cognee/client.js.map +0 -1
- package/dist/cognee/sync-manager.d.ts +0 -153
- package/dist/cognee/sync-manager.d.ts.map +0 -1
- package/dist/cognee/sync-manager.js +0 -390
- package/dist/cognee/sync-manager.js.map +0 -1
- package/dist/cognee/types.d.ts +0 -62
- package/dist/cognee/types.d.ts.map +0 -1
- package/dist/cognee/types.js +0 -3
- package/dist/cognee/types.js.map +0 -1
- package/dist/governance/index.d.ts +0 -3
- package/dist/governance/index.d.ts.map +0 -1
- package/dist/governance/index.js +0 -2
- package/dist/governance/index.js.map +0 -1
- package/dist/health/doctor-checks.d.ts +0 -15
- package/dist/health/doctor-checks.d.ts.map +0 -1
- package/dist/health/doctor-checks.js +0 -98
- package/dist/health/doctor-checks.js.map +0 -1
- package/dist/persistence/postgres-provider.d.ts +0 -81
- package/dist/persistence/postgres-provider.d.ts.map +0 -1
- package/dist/persistence/postgres-provider.js +0 -256
- package/dist/persistence/postgres-provider.js.map +0 -1
- package/dist/runtime/cognee-sync-ops.d.ts +0 -12
- package/dist/runtime/cognee-sync-ops.d.ts.map +0 -1
- package/dist/runtime/cognee-sync-ops.js +0 -93
- package/dist/runtime/cognee-sync-ops.js.map +0 -1
- package/dist/runtime/core-ops.d.ts +0 -23
- package/dist/runtime/core-ops.d.ts.map +0 -1
- package/dist/runtime/core-ops.js +0 -1296
- package/dist/runtime/core-ops.js.map +0 -1
- package/dist/runtime/facades/cognee-facade.d.ts +0 -8
- package/dist/runtime/facades/cognee-facade.d.ts.map +0 -1
- package/dist/runtime/facades/cognee-facade.js +0 -156
- package/dist/runtime/facades/cognee-facade.js.map +0 -1
- package/src/__tests__/admin-extra-ops.test.ts +0 -484
- package/src/__tests__/admin-ops.test.ts +0 -268
- package/src/__tests__/admin-setup-ops.test.ts +0 -355
- package/src/__tests__/agency-manager.test.ts +0 -374
- package/src/__tests__/agent-loop.test.ts +0 -256
- package/src/__tests__/capture-ops.test.ts +0 -784
- package/src/__tests__/claudemd.test.ts +0 -282
- package/src/__tests__/content-hash.test.ts +0 -60
- package/src/__tests__/context-engine.test.ts +0 -251
- package/src/__tests__/core-ops.test.ts +0 -550
- package/src/__tests__/curator-extra-ops.test.ts +0 -383
- package/src/__tests__/deprecation.test.ts +0 -78
- package/src/__tests__/domain-ops.test.ts +0 -226
- package/src/__tests__/domain-packs.test.ts +0 -421
- package/src/__tests__/enforcement.test.ts +0 -153
- package/src/__tests__/errors.test.ts +0 -388
- package/src/__tests__/extensions.test.ts +0 -233
- package/src/__tests__/facade-factory.test.ts +0 -271
- package/src/__tests__/feature-flags.test.ts +0 -137
- package/src/__tests__/flows.test.ts +0 -604
- package/src/__tests__/git-vault-sync.test.ts +0 -230
- package/src/__tests__/governance.test.ts +0 -522
- package/src/__tests__/grading-ops.test.ts +0 -361
- package/src/__tests__/identity-manager.test.ts +0 -243
- package/src/__tests__/intake-pipeline.test.ts +0 -162
- package/src/__tests__/intent-router.test.ts +0 -222
- package/src/__tests__/knowledge-review.test.ts +0 -104
- package/src/__tests__/llm-client.test.ts +0 -69
- package/src/__tests__/llm.test.ts +0 -556
- package/src/__tests__/loader.test.ts +0 -176
- package/src/__tests__/loop-ops.test.ts +0 -469
- package/src/__tests__/lsp-transport.test.ts +0 -442
- package/src/__tests__/memory-cross-project-ops.test.ts +0 -248
- package/src/__tests__/memory-extra-ops.test.ts +0 -352
- package/src/__tests__/migration-runner.test.ts +0 -170
- package/src/__tests__/module-manifest-drift.test.ts +0 -59
- package/src/__tests__/normalize.test.ts +0 -85
- package/src/__tests__/obsidian-sync.test.ts +0 -354
- package/src/__tests__/orchestrate-ops.test.ts +0 -289
- package/src/__tests__/pack-ops.test.ts +0 -146
- package/src/__tests__/persistence.test.ts +0 -291
- package/src/__tests__/planning-extra-ops.test.ts +0 -706
- package/src/__tests__/playbook-executor.test.ts +0 -249
- package/src/__tests__/playbook-registry.test.ts +0 -326
- package/src/__tests__/playbook-seeder.test.ts +0 -163
- package/src/__tests__/playbook.test.ts +0 -389
- package/src/__tests__/plugin-ops.test.ts +0 -411
- package/src/__tests__/plugin-system.test.ts +0 -509
- package/src/__tests__/project-ops.test.ts +0 -381
- package/src/__tests__/replayable-stream.test.ts +0 -177
- package/src/__tests__/runtime.test.ts +0 -95
- package/src/__tests__/scope-detector.test.ts +0 -121
- package/src/__tests__/template-manager.test.ts +0 -222
- package/src/__tests__/token-resolver.test.ts +0 -79
- package/src/__tests__/transport.test.ts +0 -758
- package/src/__tests__/vault-branching.test.ts +0 -274
- package/src/__tests__/vault-extra-ops.test.ts +0 -482
- package/src/__tests__/vault-integrity.test.ts +0 -71
- package/src/__tests__/vault-manager.test.ts +0 -238
- package/src/__tests__/ws-transport.test.ts +0 -479
- package/src/engine/index.ts +0 -21
- package/src/persona/index.ts +0 -9
package/dist/vault/vault.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { SQLitePersistenceProvider } from '../persistence/sqlite-provider.js';
|
|
2
|
-
import {
|
|
2
|
+
import { initializeSchema, checkFormatVersion, VAULT_FORMAT_VERSION } from './vault-schema.js';
|
|
3
|
+
import * as entries from './vault-entries.js';
|
|
4
|
+
import * as memories from './vault-memories.js';
|
|
5
|
+
import * as maintenance from './vault-maintenance.js';
|
|
3
6
|
export class Vault {
|
|
4
7
|
provider;
|
|
5
8
|
sqliteProvider;
|
|
6
9
|
linkManager = null;
|
|
7
10
|
autoLinkEnabled = true;
|
|
8
|
-
/** Minimum number of FTS5 suggestions to auto-link. Top N are linked. */
|
|
9
11
|
autoLinkMaxLinks = 3;
|
|
10
|
-
/**
|
|
11
|
-
* Create a Vault with a PersistenceProvider or a SQLite path (backward compat).
|
|
12
|
-
*/
|
|
13
12
|
constructor(providerOrPath = ':memory:') {
|
|
14
13
|
if (typeof providerOrPath === 'string') {
|
|
15
14
|
const sqlite = new SQLitePersistenceProvider(providerOrPath);
|
|
16
15
|
this.provider = sqlite;
|
|
17
16
|
this.sqliteProvider = sqlite;
|
|
18
|
-
// SQLite-specific pragmas
|
|
19
17
|
this.provider.run('PRAGMA journal_mode = WAL');
|
|
20
18
|
this.provider.run('PRAGMA foreign_keys = ON');
|
|
21
19
|
this.provider.run('PRAGMA synchronous = NORMAL');
|
|
@@ -25,29 +23,16 @@ export class Vault {
|
|
|
25
23
|
this.sqliteProvider =
|
|
26
24
|
providerOrPath instanceof SQLitePersistenceProvider ? providerOrPath : null;
|
|
27
25
|
}
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
26
|
+
initializeSchema(this.provider);
|
|
27
|
+
checkFormatVersion(this.provider);
|
|
30
28
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
static FORMAT_VERSION = 1;
|
|
39
|
-
checkFormatVersion() {
|
|
40
|
-
const row = this.provider.get('PRAGMA user_version');
|
|
41
|
-
const current = row?.user_version ?? 0;
|
|
42
|
-
if (current === 0) {
|
|
43
|
-
// Fresh database — stamp with current version
|
|
44
|
-
this.provider.run(`PRAGMA user_version = ${Vault.FORMAT_VERSION}`);
|
|
45
|
-
}
|
|
46
|
-
else if (current > Vault.FORMAT_VERSION) {
|
|
47
|
-
throw new Error(`Vault format version ${current} is newer than engine supports (${Vault.FORMAT_VERSION}). ` +
|
|
48
|
-
`Upgrade @soleri/core to a compatible version.`);
|
|
49
|
-
}
|
|
50
|
-
// current < FORMAT_VERSION → future: run migration scripts here
|
|
29
|
+
static FORMAT_VERSION = VAULT_FORMAT_VERSION;
|
|
30
|
+
getAutoLinkConfig() {
|
|
31
|
+
return {
|
|
32
|
+
linkManager: this.linkManager,
|
|
33
|
+
enabled: this.autoLinkEnabled,
|
|
34
|
+
maxLinks: this.autoLinkMaxLinks,
|
|
35
|
+
};
|
|
51
36
|
}
|
|
52
37
|
setLinkManager(mgr, opts) {
|
|
53
38
|
this.linkManager = mgr;
|
|
@@ -56,987 +41,153 @@ export class Vault {
|
|
|
56
41
|
if (opts?.maxLinks !== undefined)
|
|
57
42
|
this.autoLinkMaxLinks = opts.maxLinks;
|
|
58
43
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
* Called after seed() for each entry. Creates links for top N suggestions.
|
|
62
|
-
*/
|
|
63
|
-
autoLink(entryId) {
|
|
64
|
-
if (!this.linkManager || !this.autoLinkEnabled)
|
|
65
|
-
return;
|
|
66
|
-
try {
|
|
67
|
-
const suggestions = this.linkManager.suggestLinks(entryId, this.autoLinkMaxLinks);
|
|
68
|
-
for (const s of suggestions) {
|
|
69
|
-
this.linkManager.addLink(entryId, s.entryId, s.suggestedType, `auto: ${s.reason}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
// Auto-linking is best-effort — never block ingestion
|
|
74
|
-
}
|
|
44
|
+
isAutoLinkEnabled() {
|
|
45
|
+
return this.autoLinkEnabled && this.linkManager !== null;
|
|
75
46
|
}
|
|
76
|
-
/** Backward-compatible factory. */
|
|
77
47
|
static createWithSQLite(dbPath = ':memory:') {
|
|
78
48
|
return new Vault(dbPath);
|
|
79
49
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
id TEXT PRIMARY KEY,
|
|
84
|
-
type TEXT NOT NULL CHECK(type IN ('pattern', 'anti-pattern', 'rule', 'playbook')),
|
|
85
|
-
domain TEXT NOT NULL,
|
|
86
|
-
title TEXT NOT NULL,
|
|
87
|
-
severity TEXT NOT NULL CHECK(severity IN ('critical', 'warning', 'suggestion')),
|
|
88
|
-
description TEXT NOT NULL,
|
|
89
|
-
context TEXT, example TEXT, counter_example TEXT, why TEXT,
|
|
90
|
-
tags TEXT NOT NULL DEFAULT '[]',
|
|
91
|
-
applies_to TEXT DEFAULT '[]',
|
|
92
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
93
|
-
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
94
|
-
);
|
|
95
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS entries_fts USING fts5(
|
|
96
|
-
id, title, description, context, tags,
|
|
97
|
-
content='entries', content_rowid='rowid', tokenize='porter unicode61'
|
|
98
|
-
);
|
|
99
|
-
CREATE TRIGGER IF NOT EXISTS entries_ai AFTER INSERT ON entries BEGIN
|
|
100
|
-
INSERT INTO entries_fts(rowid,id,title,description,context,tags) VALUES(new.rowid,new.id,new.title,new.description,new.context,new.tags);
|
|
101
|
-
END;
|
|
102
|
-
CREATE TRIGGER IF NOT EXISTS entries_ad AFTER DELETE ON entries BEGIN
|
|
103
|
-
INSERT INTO entries_fts(entries_fts,rowid,id,title,description,context,tags) VALUES('delete',old.rowid,old.id,old.title,old.description,old.context,old.tags);
|
|
104
|
-
END;
|
|
105
|
-
CREATE TRIGGER IF NOT EXISTS entries_au AFTER UPDATE ON entries BEGIN
|
|
106
|
-
INSERT INTO entries_fts(entries_fts,rowid,id,title,description,context,tags) VALUES('delete',old.rowid,old.id,old.title,old.description,old.context,old.tags);
|
|
107
|
-
INSERT INTO entries_fts(rowid,id,title,description,context,tags) VALUES(new.rowid,new.id,new.title,new.description,new.context,new.tags);
|
|
108
|
-
END;
|
|
109
|
-
CREATE TABLE IF NOT EXISTS entries_archive (
|
|
110
|
-
id TEXT PRIMARY KEY,
|
|
111
|
-
type TEXT NOT NULL,
|
|
112
|
-
domain TEXT NOT NULL,
|
|
113
|
-
title TEXT NOT NULL,
|
|
114
|
-
severity TEXT NOT NULL,
|
|
115
|
-
description TEXT NOT NULL,
|
|
116
|
-
context TEXT, example TEXT, counter_example TEXT, why TEXT,
|
|
117
|
-
tags TEXT NOT NULL DEFAULT '[]',
|
|
118
|
-
applies_to TEXT DEFAULT '[]',
|
|
119
|
-
created_at INTEGER NOT NULL,
|
|
120
|
-
updated_at INTEGER NOT NULL,
|
|
121
|
-
valid_from INTEGER,
|
|
122
|
-
valid_until INTEGER,
|
|
123
|
-
archived_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
124
|
-
archive_reason TEXT
|
|
125
|
-
);
|
|
126
|
-
CREATE TABLE IF NOT EXISTS projects (
|
|
127
|
-
path TEXT PRIMARY KEY,
|
|
128
|
-
name TEXT NOT NULL,
|
|
129
|
-
registered_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
130
|
-
last_seen_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
131
|
-
session_count INTEGER NOT NULL DEFAULT 1
|
|
132
|
-
);
|
|
133
|
-
CREATE TABLE IF NOT EXISTS memories (
|
|
134
|
-
id TEXT PRIMARY KEY,
|
|
135
|
-
project_path TEXT NOT NULL,
|
|
136
|
-
type TEXT NOT NULL CHECK(type IN ('session', 'lesson', 'preference')),
|
|
137
|
-
context TEXT NOT NULL,
|
|
138
|
-
summary TEXT NOT NULL,
|
|
139
|
-
topics TEXT NOT NULL DEFAULT '[]',
|
|
140
|
-
files_modified TEXT NOT NULL DEFAULT '[]',
|
|
141
|
-
tools_used TEXT NOT NULL DEFAULT '[]',
|
|
142
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
143
|
-
archived_at INTEGER
|
|
144
|
-
);
|
|
145
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
146
|
-
id, context, summary, topics,
|
|
147
|
-
content='memories', content_rowid='rowid', tokenize='porter unicode61'
|
|
148
|
-
);`);
|
|
149
|
-
// Add new columns if they don't exist (backward-compatible migration)
|
|
150
|
-
const memCols = this.provider
|
|
151
|
-
.all(`PRAGMA table_info(memories)`)
|
|
152
|
-
.map((r) => r.name);
|
|
153
|
-
if (!memCols.includes('intent')) {
|
|
154
|
-
this.provider.execSql(`
|
|
155
|
-
ALTER TABLE memories ADD COLUMN intent TEXT;
|
|
156
|
-
ALTER TABLE memories ADD COLUMN decisions TEXT NOT NULL DEFAULT '[]';
|
|
157
|
-
ALTER TABLE memories ADD COLUMN current_state TEXT;
|
|
158
|
-
ALTER TABLE memories ADD COLUMN next_steps TEXT NOT NULL DEFAULT '[]';
|
|
159
|
-
ALTER TABLE memories ADD COLUMN vault_entries_referenced TEXT NOT NULL DEFAULT '[]';
|
|
160
|
-
`);
|
|
161
|
-
}
|
|
162
|
-
this.provider.execSql(`
|
|
163
|
-
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
164
|
-
INSERT INTO memories_fts(rowid,id,context,summary,topics) VALUES(new.rowid,new.id,new.context,new.summary,new.topics);
|
|
165
|
-
END;
|
|
166
|
-
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
167
|
-
INSERT INTO memories_fts(memories_fts,rowid,id,context,summary,topics) VALUES('delete',old.rowid,old.id,old.context,old.summary,old.topics);
|
|
168
|
-
END;
|
|
169
|
-
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
170
|
-
INSERT INTO memories_fts(memories_fts,rowid,id,context,summary,topics) VALUES('delete',old.rowid,old.id,old.context,old.summary,old.topics);
|
|
171
|
-
INSERT INTO memories_fts(rowid,id,context,summary,topics) VALUES(new.rowid,new.id,new.context,new.summary,new.topics);
|
|
172
|
-
END;
|
|
173
|
-
CREATE TABLE IF NOT EXISTS brain_vocabulary (
|
|
174
|
-
term TEXT PRIMARY KEY,
|
|
175
|
-
idf REAL NOT NULL,
|
|
176
|
-
doc_count INTEGER NOT NULL DEFAULT 1,
|
|
177
|
-
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
178
|
-
);
|
|
179
|
-
CREATE TABLE IF NOT EXISTS brain_feedback (
|
|
180
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
181
|
-
query TEXT NOT NULL,
|
|
182
|
-
entry_id TEXT NOT NULL,
|
|
183
|
-
action TEXT NOT NULL CHECK(action IN ('accepted', 'dismissed', 'modified', 'failed')),
|
|
184
|
-
source TEXT NOT NULL DEFAULT 'search',
|
|
185
|
-
confidence REAL NOT NULL DEFAULT 0.6,
|
|
186
|
-
duration INTEGER,
|
|
187
|
-
context TEXT NOT NULL DEFAULT '{}',
|
|
188
|
-
reason TEXT,
|
|
189
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
190
|
-
);
|
|
191
|
-
CREATE INDEX IF NOT EXISTS idx_brain_feedback_query ON brain_feedback(query);
|
|
192
|
-
CREATE INDEX IF NOT EXISTS idx_entries_domain ON entries(domain);
|
|
193
|
-
CREATE INDEX IF NOT EXISTS idx_entries_type ON entries(type);
|
|
194
|
-
CREATE INDEX IF NOT EXISTS idx_entries_severity ON entries(severity);
|
|
195
|
-
CREATE INDEX IF NOT EXISTS idx_memories_project ON memories(project_path);
|
|
196
|
-
CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);
|
|
197
|
-
`);
|
|
198
|
-
this.migrateBrainSchema();
|
|
199
|
-
this.migrateTemporalSchema();
|
|
200
|
-
this.migrateOriginColumn();
|
|
201
|
-
this.migrateContentHash();
|
|
202
|
-
this.migrateTierColumn();
|
|
203
|
-
}
|
|
204
|
-
migrateTierColumn() {
|
|
205
|
-
try {
|
|
206
|
-
this.provider.run("ALTER TABLE entries ADD COLUMN tier TEXT DEFAULT 'agent'");
|
|
207
|
-
}
|
|
208
|
-
catch {
|
|
209
|
-
// Column already exists
|
|
210
|
-
}
|
|
211
|
-
this.provider.execSql('CREATE INDEX IF NOT EXISTS idx_entries_tier ON entries(tier) WHERE tier IS NOT NULL');
|
|
212
|
-
}
|
|
213
|
-
migrateTemporalSchema() {
|
|
214
|
-
try {
|
|
215
|
-
this.provider.run('ALTER TABLE entries ADD COLUMN valid_from INTEGER');
|
|
216
|
-
}
|
|
217
|
-
catch {
|
|
218
|
-
// Column already exists
|
|
219
|
-
}
|
|
220
|
-
try {
|
|
221
|
-
this.provider.run('ALTER TABLE entries ADD COLUMN valid_until INTEGER');
|
|
222
|
-
}
|
|
223
|
-
catch {
|
|
224
|
-
// Column already exists
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
migrateOriginColumn() {
|
|
228
|
-
try {
|
|
229
|
-
this.provider.run("ALTER TABLE entries ADD COLUMN origin TEXT NOT NULL DEFAULT 'user' CHECK(origin IN ('agent', 'pack', 'user'))");
|
|
230
|
-
}
|
|
231
|
-
catch {
|
|
232
|
-
// Column already exists
|
|
233
|
-
}
|
|
234
|
-
this.provider.execSql('CREATE INDEX IF NOT EXISTS idx_entries_origin ON entries(origin)');
|
|
50
|
+
// ── Entry operations (vault-entries.ts) ───────────────────────────────
|
|
51
|
+
seed(entryList) {
|
|
52
|
+
return entries.seed(this.provider, entryList, this.getAutoLinkConfig());
|
|
235
53
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
this.provider.run('ALTER TABLE entries ADD COLUMN content_hash TEXT');
|
|
239
|
-
}
|
|
240
|
-
catch {
|
|
241
|
-
// Column already exists
|
|
242
|
-
}
|
|
243
|
-
this.provider.execSql('CREATE INDEX IF NOT EXISTS idx_entries_content_hash ON entries(content_hash) WHERE content_hash IS NOT NULL');
|
|
244
|
-
// Backfill existing entries that lack a hash
|
|
245
|
-
const unhashed = this.provider.all('SELECT id, type, domain, title, description, tags, example, counter_example FROM entries WHERE content_hash IS NULL');
|
|
246
|
-
if (unhashed.length > 0) {
|
|
247
|
-
this.provider.transaction(() => {
|
|
248
|
-
for (const row of unhashed) {
|
|
249
|
-
const hash = computeContentHash({
|
|
250
|
-
type: row.type,
|
|
251
|
-
domain: row.domain,
|
|
252
|
-
title: row.title,
|
|
253
|
-
description: row.description,
|
|
254
|
-
tags: JSON.parse(row.tags),
|
|
255
|
-
example: row.example ?? undefined,
|
|
256
|
-
counterExample: row.counter_example ?? undefined,
|
|
257
|
-
});
|
|
258
|
-
this.provider.run('UPDATE entries SET content_hash = @hash WHERE id = @id', {
|
|
259
|
-
hash,
|
|
260
|
-
id: row.id,
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}
|
|
54
|
+
installPack(entryList) {
|
|
55
|
+
return entries.installPack(this.provider, entryList, this.getAutoLinkConfig());
|
|
265
56
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const hasSource = columns.some((c) => c.name === 'source');
|
|
269
|
-
if (!hasSource && columns.length > 0) {
|
|
270
|
-
this.provider.transaction(() => {
|
|
271
|
-
this.provider.run(`
|
|
272
|
-
CREATE TABLE brain_feedback_new (
|
|
273
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
274
|
-
query TEXT NOT NULL,
|
|
275
|
-
entry_id TEXT NOT NULL,
|
|
276
|
-
action TEXT NOT NULL CHECK(action IN ('accepted', 'dismissed', 'modified', 'failed')),
|
|
277
|
-
source TEXT NOT NULL DEFAULT 'search',
|
|
278
|
-
confidence REAL NOT NULL DEFAULT 0.6,
|
|
279
|
-
duration INTEGER,
|
|
280
|
-
context TEXT NOT NULL DEFAULT '{}',
|
|
281
|
-
reason TEXT,
|
|
282
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
283
|
-
)
|
|
284
|
-
`);
|
|
285
|
-
this.provider.run(`
|
|
286
|
-
INSERT INTO brain_feedback_new (id, query, entry_id, action, created_at)
|
|
287
|
-
SELECT id, query, entry_id, action, created_at FROM brain_feedback
|
|
288
|
-
`);
|
|
289
|
-
this.provider.run('DROP TABLE brain_feedback');
|
|
290
|
-
this.provider.run('ALTER TABLE brain_feedback_new RENAME TO brain_feedback');
|
|
291
|
-
this.provider.run('CREATE INDEX IF NOT EXISTS idx_brain_feedback_query ON brain_feedback(query)');
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
try {
|
|
295
|
-
const sessionCols = this.provider.all('PRAGMA table_info(brain_sessions)');
|
|
296
|
-
if (sessionCols.length > 0 && !sessionCols.some((c) => c.name === 'extracted_at')) {
|
|
297
|
-
this.provider.run('ALTER TABLE brain_sessions ADD COLUMN extracted_at TEXT');
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
catch {
|
|
301
|
-
// brain_sessions table doesn't exist yet — BrainIntelligence will create it
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
seed(entries) {
|
|
305
|
-
const sql = `
|
|
306
|
-
INSERT INTO entries (id,type,domain,title,severity,description,context,example,counter_example,why,tags,applies_to,valid_from,valid_until,content_hash,tier,origin)
|
|
307
|
-
VALUES (@id,@type,@domain,@title,@severity,@description,@context,@example,@counterExample,@why,@tags,@appliesTo,@validFrom,@validUntil,@contentHash,@tier,@origin)
|
|
308
|
-
ON CONFLICT(id) DO UPDATE SET type=excluded.type,domain=excluded.domain,title=excluded.title,severity=excluded.severity,
|
|
309
|
-
description=excluded.description,context=excluded.context,example=excluded.example,counter_example=excluded.counter_example,
|
|
310
|
-
why=excluded.why,tags=excluded.tags,applies_to=excluded.applies_to,valid_from=excluded.valid_from,valid_until=excluded.valid_until,
|
|
311
|
-
content_hash=excluded.content_hash,tier=excluded.tier,origin=excluded.origin,updated_at=unixepoch()
|
|
312
|
-
`;
|
|
313
|
-
return this.provider.transaction(() => {
|
|
314
|
-
let count = 0;
|
|
315
|
-
for (const entry of entries) {
|
|
316
|
-
this.provider.run(sql, {
|
|
317
|
-
id: entry.id,
|
|
318
|
-
type: entry.type,
|
|
319
|
-
domain: entry.domain,
|
|
320
|
-
title: entry.title,
|
|
321
|
-
severity: entry.severity,
|
|
322
|
-
description: entry.description,
|
|
323
|
-
context: entry.context ?? null,
|
|
324
|
-
example: entry.example ?? null,
|
|
325
|
-
counterExample: entry.counterExample ?? null,
|
|
326
|
-
why: entry.why ?? null,
|
|
327
|
-
tags: JSON.stringify(entry.tags),
|
|
328
|
-
appliesTo: JSON.stringify(entry.appliesTo ?? []),
|
|
329
|
-
validFrom: entry.validFrom ?? null,
|
|
330
|
-
validUntil: entry.validUntil ?? null,
|
|
331
|
-
contentHash: computeContentHash(entry),
|
|
332
|
-
tier: entry.tier ?? 'agent',
|
|
333
|
-
origin: entry.origin ?? 'agent',
|
|
334
|
-
});
|
|
335
|
-
count++;
|
|
336
|
-
}
|
|
337
|
-
// Auto-link after all entries are inserted (so they can link to each other).
|
|
338
|
-
// Skip for large batches (>100) — use relink_vault for bulk imports.
|
|
339
|
-
if (entries.length <= 100) {
|
|
340
|
-
for (const entry of entries) {
|
|
341
|
-
this.autoLink(entry.id);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
return count;
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Install a knowledge pack — seeds entries with origin:'pack' and content-hash dedup.
|
|
349
|
-
* Packs are installable domain knowledge (UX laws, design tokens, clean code rules).
|
|
350
|
-
* Unlike seed(), this forces origin:'pack' regardless of what the entry says.
|
|
351
|
-
*/
|
|
352
|
-
installPack(entries) {
|
|
353
|
-
let installed = 0;
|
|
354
|
-
let skipped = 0;
|
|
355
|
-
// Tag all entries with origin:'pack' and seed — seed() handles its own transaction
|
|
356
|
-
const tagged = entries.map((e) => ({ ...e, origin: 'pack' }));
|
|
357
|
-
const results = this.seedDedup(tagged);
|
|
358
|
-
for (const r of results) {
|
|
359
|
-
if (r.action === 'inserted')
|
|
360
|
-
installed++;
|
|
361
|
-
else
|
|
362
|
-
skipped++;
|
|
363
|
-
}
|
|
364
|
-
return { installed, skipped };
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Seed entries with content-hash dedup. Returns per-entry results.
|
|
368
|
-
* Unlike seed(), skips entries whose content already exists in the vault.
|
|
369
|
-
*/
|
|
370
|
-
seedDedup(entries) {
|
|
371
|
-
return this.provider.transaction(() => {
|
|
372
|
-
const results = [];
|
|
373
|
-
for (const entry of entries) {
|
|
374
|
-
const hash = computeContentHash(entry);
|
|
375
|
-
const existing = this.findByContentHash(hash);
|
|
376
|
-
if (existing && existing !== entry.id) {
|
|
377
|
-
results.push({ id: entry.id, action: 'duplicate', existingId: existing });
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
this.seed([entry]);
|
|
381
|
-
results.push({ id: entry.id, action: 'inserted' });
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return results;
|
|
385
|
-
});
|
|
57
|
+
seedDedup(entryList) {
|
|
58
|
+
return entries.seedDedup(this.provider, entryList, this.getAutoLinkConfig());
|
|
386
59
|
}
|
|
387
60
|
search(query, options) {
|
|
388
|
-
|
|
389
|
-
const filters = [];
|
|
390
|
-
const fp = {};
|
|
391
|
-
if (options?.domain) {
|
|
392
|
-
filters.push('e.domain = @domain');
|
|
393
|
-
fp.domain = options.domain;
|
|
394
|
-
}
|
|
395
|
-
if (options?.type) {
|
|
396
|
-
filters.push('e.type = @type');
|
|
397
|
-
fp.type = options.type;
|
|
398
|
-
}
|
|
399
|
-
if (options?.severity) {
|
|
400
|
-
filters.push('e.severity = @severity');
|
|
401
|
-
fp.severity = options.severity;
|
|
402
|
-
}
|
|
403
|
-
if (options?.origin) {
|
|
404
|
-
filters.push('e.origin = @origin');
|
|
405
|
-
fp.origin = options.origin;
|
|
406
|
-
}
|
|
407
|
-
if (!options?.includeExpired) {
|
|
408
|
-
const now = Math.floor(Date.now() / 1000);
|
|
409
|
-
filters.push('(e.valid_until IS NULL OR e.valid_until > @now)');
|
|
410
|
-
filters.push('(e.valid_from IS NULL OR e.valid_from <= @now)');
|
|
411
|
-
fp.now = now;
|
|
412
|
-
}
|
|
413
|
-
const wc = filters.length > 0 ? `AND ${filters.join(' AND ')}` : '';
|
|
414
|
-
// Build FTS5 query: use OR between terms for broader matching,
|
|
415
|
-
// with title column boosted 3x for relevance ranking.
|
|
416
|
-
// FTS5 BM25 with default AND degrades with more entries because
|
|
417
|
-
// fewer documents match ALL terms simultaneously.
|
|
418
|
-
const ftsQuery = buildFtsQuery(query);
|
|
419
|
-
try {
|
|
420
|
-
const rows = this.provider.all(`SELECT e.*, bm25(entries_fts, 5.0, 10.0, 3.0, 1.0, 2.0) as score FROM entries_fts fts JOIN entries e ON e.rowid = fts.rowid WHERE entries_fts MATCH @query ${wc} ORDER BY score ASC LIMIT @limit`, { query: ftsQuery, limit, ...fp });
|
|
421
|
-
return rows.map(rowToSearchResult);
|
|
422
|
-
}
|
|
423
|
-
catch {
|
|
424
|
-
// Fallback: try original query if FTS5 syntax fails
|
|
425
|
-
try {
|
|
426
|
-
const rows = this.provider.all(`SELECT e.*, -rank as score FROM entries_fts fts JOIN entries e ON e.rowid = fts.rowid WHERE entries_fts MATCH @query ${wc} ORDER BY score DESC LIMIT @limit`, { query, limit, ...fp });
|
|
427
|
-
return rows.map(rowToSearchResult);
|
|
428
|
-
}
|
|
429
|
-
catch {
|
|
430
|
-
return [];
|
|
431
|
-
}
|
|
432
|
-
}
|
|
61
|
+
return entries.search(this.provider, query, options);
|
|
433
62
|
}
|
|
434
63
|
get(id) {
|
|
435
|
-
|
|
436
|
-
id,
|
|
437
|
-
]);
|
|
438
|
-
return row ? rowToEntry(row) : null;
|
|
64
|
+
return entries.get(this.provider, id);
|
|
439
65
|
}
|
|
440
66
|
list(options) {
|
|
441
|
-
|
|
442
|
-
const params = {};
|
|
443
|
-
if (options?.domain) {
|
|
444
|
-
filters.push('domain = @domain');
|
|
445
|
-
params.domain = options.domain;
|
|
446
|
-
}
|
|
447
|
-
if (options?.type) {
|
|
448
|
-
filters.push('type = @type');
|
|
449
|
-
params.type = options.type;
|
|
450
|
-
}
|
|
451
|
-
if (options?.severity) {
|
|
452
|
-
filters.push('severity = @severity');
|
|
453
|
-
params.severity = options.severity;
|
|
454
|
-
}
|
|
455
|
-
if (options?.origin) {
|
|
456
|
-
filters.push('origin = @origin');
|
|
457
|
-
params.origin = options.origin;
|
|
458
|
-
}
|
|
459
|
-
if (options?.tags?.length) {
|
|
460
|
-
const c = options.tags.map((t, i) => {
|
|
461
|
-
params[`tag${i}`] = `%"${t}"%`;
|
|
462
|
-
return `tags LIKE @tag${i}`;
|
|
463
|
-
});
|
|
464
|
-
filters.push(`(${c.join(' OR ')})`);
|
|
465
|
-
}
|
|
466
|
-
if (!options?.includeExpired) {
|
|
467
|
-
const now = Math.floor(Date.now() / 1000);
|
|
468
|
-
filters.push('(valid_until IS NULL OR valid_until > @now)');
|
|
469
|
-
filters.push('(valid_from IS NULL OR valid_from <= @now)');
|
|
470
|
-
params.now = now;
|
|
471
|
-
}
|
|
472
|
-
const wc = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '';
|
|
473
|
-
const rows = this.provider.all(`SELECT * FROM entries ${wc} ORDER BY severity, domain, title LIMIT @limit OFFSET @offset`, { ...params, limit: options?.limit ?? 50, offset: options?.offset ?? 0 });
|
|
474
|
-
return rows.map(rowToEntry);
|
|
67
|
+
return entries.list(this.provider, options);
|
|
475
68
|
}
|
|
476
69
|
stats() {
|
|
477
|
-
|
|
478
|
-
return {
|
|
479
|
-
totalEntries: total,
|
|
480
|
-
byType: gc(this.provider, 'type'),
|
|
481
|
-
byDomain: gc(this.provider, 'domain'),
|
|
482
|
-
bySeverity: gc(this.provider, 'severity'),
|
|
483
|
-
};
|
|
70
|
+
return entries.stats(this.provider);
|
|
484
71
|
}
|
|
485
72
|
add(entry) {
|
|
486
|
-
this.
|
|
73
|
+
entries.add(this.provider, entry, this.getAutoLinkConfig());
|
|
487
74
|
}
|
|
488
75
|
remove(id) {
|
|
489
|
-
|
|
490
|
-
return deleted;
|
|
76
|
+
return entries.remove(this.provider, id);
|
|
491
77
|
}
|
|
492
78
|
update(id, fields) {
|
|
493
|
-
|
|
494
|
-
if (!existing)
|
|
495
|
-
return null;
|
|
496
|
-
const merged = { ...existing, ...fields };
|
|
497
|
-
this.seed([merged]);
|
|
498
|
-
return this.get(id);
|
|
79
|
+
return entries.update(this.provider, id, fields, this.getAutoLinkConfig());
|
|
499
80
|
}
|
|
500
81
|
setTemporal(id, validFrom, validUntil) {
|
|
501
|
-
|
|
502
|
-
const params = { id };
|
|
503
|
-
if (validFrom !== undefined) {
|
|
504
|
-
sets.push('valid_from = @validFrom');
|
|
505
|
-
params.validFrom = validFrom;
|
|
506
|
-
}
|
|
507
|
-
if (validUntil !== undefined) {
|
|
508
|
-
sets.push('valid_until = @validUntil');
|
|
509
|
-
params.validUntil = validUntil;
|
|
510
|
-
}
|
|
511
|
-
if (sets.length === 0)
|
|
512
|
-
return false;
|
|
513
|
-
sets.push('updated_at = unixepoch()');
|
|
514
|
-
return (this.provider.run(`UPDATE entries SET ${sets.join(', ')} WHERE id = @id`, params).changes > 0);
|
|
82
|
+
return entries.setTemporal(this.provider, id, validFrom, validUntil);
|
|
515
83
|
}
|
|
516
84
|
findExpiring(withinDays) {
|
|
517
|
-
|
|
518
|
-
const cutoff = now + withinDays * 86400;
|
|
519
|
-
const rows = this.provider.all('SELECT * FROM entries WHERE valid_until IS NOT NULL AND valid_until > @now AND valid_until <= @cutoff ORDER BY valid_until ASC', { now, cutoff });
|
|
520
|
-
return rows.map(rowToEntry);
|
|
85
|
+
return entries.findExpiring(this.provider, withinDays);
|
|
521
86
|
}
|
|
522
87
|
findExpired(limit = 50) {
|
|
523
|
-
|
|
524
|
-
const rows = this.provider.all('SELECT * FROM entries WHERE valid_until IS NOT NULL AND valid_until <= @now ORDER BY valid_until DESC LIMIT @limit', { now, limit });
|
|
525
|
-
return rows.map(rowToEntry);
|
|
88
|
+
return entries.findExpired(this.provider, limit);
|
|
526
89
|
}
|
|
527
90
|
bulkRemove(ids) {
|
|
528
|
-
return this.provider
|
|
529
|
-
let count = 0;
|
|
530
|
-
for (const id of ids) {
|
|
531
|
-
count += this.provider.run('DELETE FROM entries WHERE id = ?', [id]).changes;
|
|
532
|
-
}
|
|
533
|
-
return count;
|
|
534
|
-
});
|
|
91
|
+
return entries.bulkRemove(this.provider, ids);
|
|
535
92
|
}
|
|
536
93
|
getTags() {
|
|
537
|
-
|
|
538
|
-
const counts = new Map();
|
|
539
|
-
for (const row of rows) {
|
|
540
|
-
const tags = JSON.parse(row.tags || '[]');
|
|
541
|
-
for (const tag of tags) {
|
|
542
|
-
counts.set(tag, (counts.get(tag) ?? 0) + 1);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
return Array.from(counts.entries())
|
|
546
|
-
.map(([tag, count]) => ({ tag, count }))
|
|
547
|
-
.sort((a, b) => b.count - a.count);
|
|
94
|
+
return entries.getTags(this.provider);
|
|
548
95
|
}
|
|
549
96
|
getDomains() {
|
|
550
|
-
return this.provider
|
|
97
|
+
return entries.getDomains(this.provider);
|
|
551
98
|
}
|
|
552
99
|
getRecent(limit = 20) {
|
|
553
|
-
|
|
554
|
-
|
|
100
|
+
return entries.getRecent(this.provider, limit);
|
|
101
|
+
}
|
|
102
|
+
findByContentHash(hash) {
|
|
103
|
+
return entries.findByContentHash(this.provider, hash);
|
|
555
104
|
}
|
|
105
|
+
contentHashStats() {
|
|
106
|
+
return entries.contentHashStats(this.provider);
|
|
107
|
+
}
|
|
108
|
+
// ── Maintenance operations (vault-maintenance.ts) ─────────────────────
|
|
556
109
|
exportAll() {
|
|
557
|
-
|
|
558
|
-
const entries = rows.map(rowToEntry);
|
|
559
|
-
return { entries, exportedAt: Math.floor(Date.now() / 1000), count: entries.length };
|
|
110
|
+
return maintenance.exportAll(this.provider);
|
|
560
111
|
}
|
|
561
112
|
getAgeReport() {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
let oldest = null;
|
|
573
|
-
let newest = null;
|
|
574
|
-
for (const row of rows) {
|
|
575
|
-
const ts = row.created_at;
|
|
576
|
-
if (oldest === null || ts < oldest)
|
|
577
|
-
oldest = ts;
|
|
578
|
-
if (newest === null || ts > newest)
|
|
579
|
-
newest = ts;
|
|
580
|
-
const ageDays = (now - ts) / 86400;
|
|
581
|
-
for (let i = 0; i < bucketDefs.length; i++) {
|
|
582
|
-
if (ageDays >= bucketDefs[i].minDays && ageDays < bucketDefs[i].maxDays) {
|
|
583
|
-
counts[i]++;
|
|
584
|
-
break;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return {
|
|
589
|
-
total: rows.length,
|
|
590
|
-
buckets: bucketDefs.map((b, i) => Object.assign({}, b, { count: counts[i] })),
|
|
591
|
-
oldestTimestamp: oldest,
|
|
592
|
-
newestTimestamp: newest,
|
|
593
|
-
};
|
|
113
|
+
return maintenance.getAgeReport(this.provider);
|
|
114
|
+
}
|
|
115
|
+
archive(options) {
|
|
116
|
+
return maintenance.archive(this.provider, options);
|
|
117
|
+
}
|
|
118
|
+
restore(id) {
|
|
119
|
+
return maintenance.restore(this.provider, id);
|
|
120
|
+
}
|
|
121
|
+
rebuildFtsIndex() {
|
|
122
|
+
maintenance.rebuildFtsIndex(this.provider);
|
|
594
123
|
}
|
|
124
|
+
optimize() {
|
|
125
|
+
return maintenance.optimize(this.provider);
|
|
126
|
+
}
|
|
127
|
+
// ── Project operations (vault-maintenance.ts) ─────────────────────────
|
|
595
128
|
registerProject(path, name) {
|
|
596
|
-
|
|
597
|
-
const existing = this.getProject(path);
|
|
598
|
-
if (existing) {
|
|
599
|
-
this.provider.run('UPDATE projects SET last_seen_at = unixepoch(), session_count = session_count + 1 WHERE path = ?', [path]);
|
|
600
|
-
return this.getProject(path);
|
|
601
|
-
}
|
|
602
|
-
this.provider.run('INSERT INTO projects (path, name) VALUES (?, ?)', [path, projectName]);
|
|
603
|
-
return this.getProject(path);
|
|
129
|
+
return maintenance.registerProject(this.provider, path, name);
|
|
604
130
|
}
|
|
605
131
|
getProject(path) {
|
|
606
|
-
|
|
607
|
-
if (!row)
|
|
608
|
-
return null;
|
|
609
|
-
return {
|
|
610
|
-
path: row.path,
|
|
611
|
-
name: row.name,
|
|
612
|
-
registeredAt: row.registered_at,
|
|
613
|
-
lastSeenAt: row.last_seen_at,
|
|
614
|
-
sessionCount: row.session_count,
|
|
615
|
-
};
|
|
132
|
+
return maintenance.getProject(this.provider, path);
|
|
616
133
|
}
|
|
617
134
|
listProjects() {
|
|
618
|
-
|
|
619
|
-
return rows.map((row) => ({
|
|
620
|
-
path: row.path,
|
|
621
|
-
name: row.name,
|
|
622
|
-
registeredAt: row.registered_at,
|
|
623
|
-
lastSeenAt: row.last_seen_at,
|
|
624
|
-
sessionCount: row.session_count,
|
|
625
|
-
}));
|
|
135
|
+
return maintenance.listProjects(this.provider);
|
|
626
136
|
}
|
|
137
|
+
// ── Memory operations (vault-memories.ts) ─────────────────────────────
|
|
627
138
|
captureMemory(memory) {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
summary: memory.summary,
|
|
636
|
-
topics: JSON.stringify(memory.topics),
|
|
637
|
-
filesModified: JSON.stringify(memory.filesModified),
|
|
638
|
-
toolsUsed: JSON.stringify(memory.toolsUsed),
|
|
639
|
-
intent: memory.intent ?? null,
|
|
640
|
-
decisions: JSON.stringify(memory.decisions ?? []),
|
|
641
|
-
currentState: memory.currentState ?? null,
|
|
642
|
-
nextSteps: JSON.stringify(memory.nextSteps ?? []),
|
|
643
|
-
vaultEntriesReferenced: JSON.stringify(memory.vaultEntriesReferenced ?? []),
|
|
644
|
-
});
|
|
645
|
-
return this.getMemory(id);
|
|
139
|
+
return memories.captureMemory(this.provider, memory);
|
|
140
|
+
}
|
|
141
|
+
getMemory(id) {
|
|
142
|
+
return memories.getMemory(this.provider, id);
|
|
143
|
+
}
|
|
144
|
+
deleteMemory(id) {
|
|
145
|
+
return memories.deleteMemory(this.provider, id);
|
|
646
146
|
}
|
|
647
147
|
searchMemories(query, options) {
|
|
648
|
-
|
|
649
|
-
const filters = ['m.archived_at IS NULL'];
|
|
650
|
-
const fp = {};
|
|
651
|
-
if (options?.type) {
|
|
652
|
-
filters.push('m.type = @type');
|
|
653
|
-
fp.type = options.type;
|
|
654
|
-
}
|
|
655
|
-
if (options?.projectPath) {
|
|
656
|
-
filters.push('m.project_path = @projectPath');
|
|
657
|
-
fp.projectPath = options.projectPath;
|
|
658
|
-
}
|
|
659
|
-
if (options?.intent) {
|
|
660
|
-
filters.push('m.intent = @intent');
|
|
661
|
-
fp.intent = options.intent;
|
|
662
|
-
}
|
|
663
|
-
const wc = filters.length > 0 ? `AND ${filters.join(' AND ')}` : '';
|
|
664
|
-
try {
|
|
665
|
-
const rows = this.provider.all(`SELECT m.* FROM memories_fts fts JOIN memories m ON m.rowid = fts.rowid WHERE memories_fts MATCH @query ${wc} ORDER BY rank LIMIT @limit`, { query, limit, ...fp });
|
|
666
|
-
return rows.map(rowToMemory);
|
|
667
|
-
}
|
|
668
|
-
catch {
|
|
669
|
-
return [];
|
|
670
|
-
}
|
|
148
|
+
return memories.searchMemories(this.provider, query, options);
|
|
671
149
|
}
|
|
672
150
|
listMemories(options) {
|
|
673
|
-
|
|
674
|
-
const params = {};
|
|
675
|
-
if (options?.type) {
|
|
676
|
-
filters.push('type = @type');
|
|
677
|
-
params.type = options.type;
|
|
678
|
-
}
|
|
679
|
-
if (options?.projectPath) {
|
|
680
|
-
filters.push('project_path = @projectPath');
|
|
681
|
-
params.projectPath = options.projectPath;
|
|
682
|
-
}
|
|
683
|
-
const wc = `WHERE ${filters.join(' AND ')}`;
|
|
684
|
-
const rows = this.provider.all(`SELECT * FROM memories ${wc} ORDER BY created_at DESC LIMIT @limit OFFSET @offset`, { ...params, limit: options?.limit ?? 50, offset: options?.offset ?? 0 });
|
|
685
|
-
return rows.map(rowToMemory);
|
|
151
|
+
return memories.listMemories(this.provider, options);
|
|
686
152
|
}
|
|
687
153
|
memoryStats() {
|
|
688
|
-
|
|
689
|
-
const byTypeRows = this.provider.all('SELECT type as key, COUNT(*) as count FROM memories WHERE archived_at IS NULL GROUP BY type');
|
|
690
|
-
const byProjectRows = this.provider.all('SELECT project_path as key, COUNT(*) as count FROM memories WHERE archived_at IS NULL GROUP BY project_path');
|
|
691
|
-
return {
|
|
692
|
-
total,
|
|
693
|
-
byType: Object.fromEntries(byTypeRows.map((r) => [r.key, r.count])),
|
|
694
|
-
byProject: Object.fromEntries(byProjectRows.map((r) => [r.key, r.count])),
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
getMemory(id) {
|
|
698
|
-
const row = this.provider.get('SELECT * FROM memories WHERE id = ?', [
|
|
699
|
-
id,
|
|
700
|
-
]);
|
|
701
|
-
return row ? rowToMemory(row) : null;
|
|
702
|
-
}
|
|
703
|
-
deleteMemory(id) {
|
|
704
|
-
return this.provider.run('DELETE FROM memories WHERE id = ?', [id]).changes > 0;
|
|
154
|
+
return memories.memoryStats(this.provider);
|
|
705
155
|
}
|
|
706
156
|
memoryStatsDetailed(options) {
|
|
707
|
-
|
|
708
|
-
const params = {};
|
|
709
|
-
if (options?.projectPath) {
|
|
710
|
-
filters.push('project_path = @projectPath');
|
|
711
|
-
params.projectPath = options.projectPath;
|
|
712
|
-
}
|
|
713
|
-
if (options?.fromDate) {
|
|
714
|
-
filters.push('created_at >= @fromDate');
|
|
715
|
-
params.fromDate = options.fromDate;
|
|
716
|
-
}
|
|
717
|
-
if (options?.toDate) {
|
|
718
|
-
filters.push('created_at <= @toDate');
|
|
719
|
-
params.toDate = options.toDate;
|
|
720
|
-
}
|
|
721
|
-
const wc = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '';
|
|
722
|
-
const total = this.provider.get(`SELECT COUNT(*) as count FROM memories ${wc}${wc ? ' AND' : ' WHERE'} archived_at IS NULL`, params).count;
|
|
723
|
-
const archivedCount = this.provider.get(`SELECT COUNT(*) as count FROM memories ${wc}${wc ? ' AND' : ' WHERE'} archived_at IS NOT NULL`, params).count;
|
|
724
|
-
const byTypeRows = this.provider.all(`SELECT type as key, COUNT(*) as count FROM memories ${wc}${wc ? ' AND' : ' WHERE'} archived_at IS NULL GROUP BY type`, params);
|
|
725
|
-
const byProjectRows = this.provider.all(`SELECT project_path as key, COUNT(*) as count FROM memories ${wc}${wc ? ' AND' : ' WHERE'} archived_at IS NULL GROUP BY project_path`, params);
|
|
726
|
-
const dateRange = this.provider.get(`SELECT MIN(created_at) as oldest, MAX(created_at) as newest FROM memories ${wc}${wc ? ' AND' : ' WHERE'} archived_at IS NULL`, params);
|
|
727
|
-
return {
|
|
728
|
-
total,
|
|
729
|
-
byType: Object.fromEntries(byTypeRows.map((r) => [r.key, r.count])),
|
|
730
|
-
byProject: Object.fromEntries(byProjectRows.map((r) => [r.key, r.count])),
|
|
731
|
-
oldest: dateRange.oldest,
|
|
732
|
-
newest: dateRange.newest,
|
|
733
|
-
archivedCount,
|
|
734
|
-
};
|
|
157
|
+
return memories.memoryStatsDetailed(this.provider, options);
|
|
735
158
|
}
|
|
736
159
|
exportMemories(options) {
|
|
737
|
-
|
|
738
|
-
const params = {};
|
|
739
|
-
if (!options?.includeArchived) {
|
|
740
|
-
filters.push('archived_at IS NULL');
|
|
741
|
-
}
|
|
742
|
-
if (options?.projectPath) {
|
|
743
|
-
filters.push('project_path = @projectPath');
|
|
744
|
-
params.projectPath = options.projectPath;
|
|
745
|
-
}
|
|
746
|
-
if (options?.type) {
|
|
747
|
-
filters.push('type = @type');
|
|
748
|
-
params.type = options.type;
|
|
749
|
-
}
|
|
750
|
-
const wc = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '';
|
|
751
|
-
const rows = this.provider.all(`SELECT * FROM memories ${wc} ORDER BY created_at ASC`, Object.keys(params).length > 0 ? params : undefined);
|
|
752
|
-
return rows.map(rowToMemory);
|
|
160
|
+
return memories.exportMemories(this.provider, options);
|
|
753
161
|
}
|
|
754
|
-
importMemories(
|
|
755
|
-
|
|
756
|
-
INSERT OR IGNORE INTO memories (id, project_path, type, context, summary, topics, files_modified, tools_used, created_at, archived_at)
|
|
757
|
-
VALUES (@id, @projectPath, @type, @context, @summary, @topics, @filesModified, @toolsUsed, @createdAt, @archivedAt)
|
|
758
|
-
`;
|
|
759
|
-
let imported = 0;
|
|
760
|
-
let skipped = 0;
|
|
761
|
-
this.provider.transaction(() => {
|
|
762
|
-
for (const m of memories) {
|
|
763
|
-
const result = this.provider.run(sql, {
|
|
764
|
-
id: m.id,
|
|
765
|
-
projectPath: m.projectPath,
|
|
766
|
-
type: m.type,
|
|
767
|
-
context: m.context,
|
|
768
|
-
summary: m.summary,
|
|
769
|
-
topics: JSON.stringify(m.topics),
|
|
770
|
-
filesModified: JSON.stringify(m.filesModified),
|
|
771
|
-
toolsUsed: JSON.stringify(m.toolsUsed),
|
|
772
|
-
createdAt: m.createdAt,
|
|
773
|
-
archivedAt: m.archivedAt,
|
|
774
|
-
});
|
|
775
|
-
if (result.changes > 0)
|
|
776
|
-
imported++;
|
|
777
|
-
else
|
|
778
|
-
skipped++;
|
|
779
|
-
}
|
|
780
|
-
});
|
|
781
|
-
return { imported, skipped };
|
|
162
|
+
importMemories(memoryList) {
|
|
163
|
+
return memories.importMemories(this.provider, memoryList);
|
|
782
164
|
}
|
|
783
165
|
pruneMemories(olderThanDays) {
|
|
784
|
-
|
|
785
|
-
const result = this.provider.run('DELETE FROM memories WHERE created_at < ? AND archived_at IS NULL', [cutoff]);
|
|
786
|
-
return { pruned: result.changes };
|
|
166
|
+
return memories.pruneMemories(this.provider, olderThanDays);
|
|
787
167
|
}
|
|
788
168
|
deduplicateMemories() {
|
|
789
|
-
|
|
790
|
-
SELECT m1.id as id1, m2.id as id2
|
|
791
|
-
FROM memories m1
|
|
792
|
-
JOIN memories m2 ON m1.summary = m2.summary
|
|
793
|
-
AND m1.project_path = m2.project_path
|
|
794
|
-
AND m1.type = m2.type
|
|
795
|
-
AND m1.id < m2.id
|
|
796
|
-
AND m1.archived_at IS NULL
|
|
797
|
-
AND m2.archived_at IS NULL
|
|
798
|
-
`);
|
|
799
|
-
const groupMap = new Map();
|
|
800
|
-
for (const row of dupeRows) {
|
|
801
|
-
if (!groupMap.has(row.id1))
|
|
802
|
-
groupMap.set(row.id1, new Set());
|
|
803
|
-
groupMap.get(row.id1).add(row.id2);
|
|
804
|
-
}
|
|
805
|
-
const groups = [];
|
|
806
|
-
const toRemove = new Set();
|
|
807
|
-
for (const [kept, removedSet] of groupMap) {
|
|
808
|
-
const removed = [...removedSet].filter((id) => !toRemove.has(id));
|
|
809
|
-
if (removed.length > 0) {
|
|
810
|
-
groups.push({ kept, removed });
|
|
811
|
-
for (const id of removed)
|
|
812
|
-
toRemove.add(id);
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
if (toRemove.size > 0) {
|
|
816
|
-
this.provider.transaction(() => {
|
|
817
|
-
for (const id of toRemove) {
|
|
818
|
-
this.provider.run('DELETE FROM memories WHERE id = ?', [id]);
|
|
819
|
-
}
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
return { removed: toRemove.size, groups };
|
|
169
|
+
return memories.deduplicateMemories(this.provider);
|
|
823
170
|
}
|
|
824
171
|
memoryTopics() {
|
|
825
|
-
|
|
826
|
-
const topicCounts = new Map();
|
|
827
|
-
for (const row of rows) {
|
|
828
|
-
const topics = JSON.parse(row.topics || '[]');
|
|
829
|
-
for (const topic of topics) {
|
|
830
|
-
topicCounts.set(topic, (topicCounts.get(topic) ?? 0) + 1);
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
return [...topicCounts.entries()]
|
|
834
|
-
.map(([topic, count]) => ({ topic, count }))
|
|
835
|
-
.sort((a, b) => b.count - a.count);
|
|
172
|
+
return memories.memoryTopics(this.provider);
|
|
836
173
|
}
|
|
837
174
|
memoriesByProject() {
|
|
838
|
-
|
|
839
|
-
return rows.map((row) => {
|
|
840
|
-
const memories = this.provider.all('SELECT * FROM memories WHERE project_path = ? AND archived_at IS NULL ORDER BY created_at DESC', [row.project]);
|
|
841
|
-
return {
|
|
842
|
-
project: row.project,
|
|
843
|
-
count: row.count,
|
|
844
|
-
memories: memories.map(rowToMemory),
|
|
845
|
-
};
|
|
846
|
-
});
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* Rebuild the FTS5 index for the entries table.
|
|
850
|
-
* Useful after bulk operations or if the index gets out of sync.
|
|
851
|
-
*/
|
|
852
|
-
rebuildFtsIndex() {
|
|
853
|
-
try {
|
|
854
|
-
this.provider.run("INSERT INTO entries_fts(entries_fts) VALUES('rebuild')");
|
|
855
|
-
}
|
|
856
|
-
catch {
|
|
857
|
-
// Graceful degradation — FTS rebuild failed (e.g. table doesn't exist yet)
|
|
858
|
-
}
|
|
175
|
+
return memories.memoriesByProject(this.provider);
|
|
859
176
|
}
|
|
860
|
-
|
|
861
|
-
* Archive entries older than N days. Moves them to entries_archive.
|
|
862
|
-
*/
|
|
863
|
-
archive(options) {
|
|
864
|
-
const cutoff = Math.floor(Date.now() / 1000) - options.olderThanDays * 86400;
|
|
865
|
-
const reason = options.reason ?? `Archived: older than ${options.olderThanDays} days`;
|
|
866
|
-
return this.provider.transaction(() => {
|
|
867
|
-
// Find candidates
|
|
868
|
-
const candidates = this.provider.all('SELECT id FROM entries WHERE updated_at < ?', [cutoff]);
|
|
869
|
-
if (candidates.length === 0)
|
|
870
|
-
return { archived: 0 };
|
|
871
|
-
let archived = 0;
|
|
872
|
-
for (const { id } of candidates) {
|
|
873
|
-
// Copy to archive
|
|
874
|
-
this.provider.run(`INSERT OR IGNORE INTO entries_archive (id, type, domain, title, severity, description, context, example, counter_example, why, tags, applies_to, created_at, updated_at, valid_from, valid_until, archive_reason)
|
|
875
|
-
SELECT id, type, domain, title, severity, description, context, example, counter_example, why, tags, applies_to, created_at, updated_at, valid_from, valid_until, ?
|
|
876
|
-
FROM entries WHERE id = ?`, [reason, id]);
|
|
877
|
-
// Delete from active
|
|
878
|
-
const result = this.provider.run('DELETE FROM entries WHERE id = ?', [id]);
|
|
879
|
-
archived += result.changes;
|
|
880
|
-
}
|
|
881
|
-
return { archived };
|
|
882
|
-
});
|
|
883
|
-
}
|
|
884
|
-
/**
|
|
885
|
-
* Restore an archived entry back to the active table.
|
|
886
|
-
*/
|
|
887
|
-
restore(id) {
|
|
888
|
-
return this.provider.transaction(() => {
|
|
889
|
-
const archived = this.provider.get('SELECT * FROM entries_archive WHERE id = ?', [id]);
|
|
890
|
-
if (!archived)
|
|
891
|
-
return false;
|
|
892
|
-
this.provider.run(`INSERT OR REPLACE INTO entries (id, type, domain, title, severity, description, context, example, counter_example, why, tags, applies_to, created_at, updated_at, valid_from, valid_until)
|
|
893
|
-
SELECT id, type, domain, title, severity, description, context, example, counter_example, why, tags, applies_to, created_at, updated_at, valid_from, valid_until
|
|
894
|
-
FROM entries_archive WHERE id = ?`, [id]);
|
|
895
|
-
this.provider.run('DELETE FROM entries_archive WHERE id = ?', [id]);
|
|
896
|
-
return true;
|
|
897
|
-
});
|
|
898
|
-
}
|
|
899
|
-
/**
|
|
900
|
-
* Optimize the database: VACUUM (SQLite only), ANALYZE, and FTS rebuild.
|
|
901
|
-
*/
|
|
902
|
-
optimize() {
|
|
903
|
-
let vacuumed = false;
|
|
904
|
-
let analyzed = false;
|
|
905
|
-
let ftsRebuilt = false;
|
|
906
|
-
// VACUUM only for SQLite
|
|
907
|
-
if (this.provider.backend === 'sqlite') {
|
|
908
|
-
try {
|
|
909
|
-
this.provider.execSql('VACUUM');
|
|
910
|
-
vacuumed = true;
|
|
911
|
-
}
|
|
912
|
-
catch {
|
|
913
|
-
// VACUUM may fail inside a transaction
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
try {
|
|
917
|
-
this.provider.execSql('ANALYZE');
|
|
918
|
-
analyzed = true;
|
|
919
|
-
}
|
|
920
|
-
catch {
|
|
921
|
-
// Non-critical
|
|
922
|
-
}
|
|
923
|
-
try {
|
|
924
|
-
this.provider.ftsRebuild('entries');
|
|
925
|
-
this.provider.ftsRebuild('memories');
|
|
926
|
-
ftsRebuilt = true;
|
|
927
|
-
}
|
|
928
|
-
catch {
|
|
929
|
-
// Non-critical
|
|
930
|
-
}
|
|
931
|
-
return { vacuumed, analyzed, ftsRebuilt };
|
|
932
|
-
}
|
|
933
|
-
/**
|
|
934
|
-
* Get the underlying persistence provider.
|
|
935
|
-
*/
|
|
177
|
+
// ── Provider access ───────────────────────────────────────────────────
|
|
936
178
|
getProvider() {
|
|
937
179
|
return this.provider;
|
|
938
180
|
}
|
|
939
|
-
/**
|
|
940
|
-
* Get the raw better-sqlite3 Database (backward compat).
|
|
941
|
-
* Throws if the provider is not SQLite.
|
|
942
|
-
*/
|
|
943
181
|
getDb() {
|
|
944
182
|
if (process.env.NODE_ENV !== 'test' && process.env.VITEST !== 'true') {
|
|
945
183
|
console.warn('Vault.getDb() is deprecated. Use vault.getProvider() instead.');
|
|
946
184
|
}
|
|
947
|
-
if (this.sqliteProvider)
|
|
185
|
+
if (this.sqliteProvider)
|
|
948
186
|
return this.sqliteProvider.getDatabase();
|
|
949
|
-
}
|
|
950
187
|
throw new Error('getDb() is only available with SQLite provider');
|
|
951
188
|
}
|
|
952
|
-
/** Check if an entry with this content hash already exists. Returns the existing ID or null. */
|
|
953
|
-
findByContentHash(hash) {
|
|
954
|
-
const row = this.provider.get('SELECT id FROM entries WHERE content_hash = @hash', { hash });
|
|
955
|
-
return row?.id ?? null;
|
|
956
|
-
}
|
|
957
|
-
/** Get content hash stats for dedup reporting. */
|
|
958
|
-
contentHashStats() {
|
|
959
|
-
const total = this.provider.get('SELECT COUNT(*) as c FROM entries')?.c ?? 0;
|
|
960
|
-
const hashed = this.provider.get('SELECT COUNT(*) as c FROM entries WHERE content_hash IS NOT NULL')?.c ?? 0;
|
|
961
|
-
const uniqueHashes = this.provider.get('SELECT COUNT(DISTINCT content_hash) as c FROM entries WHERE content_hash IS NOT NULL')?.c ?? 0;
|
|
962
|
-
return { total, hashed, uniqueHashes };
|
|
963
|
-
}
|
|
964
189
|
close() {
|
|
965
190
|
this.provider.close();
|
|
966
191
|
}
|
|
967
192
|
}
|
|
968
|
-
function gc(provider, col) {
|
|
969
|
-
const rows = provider.all(`SELECT ${col} as key, COUNT(*) as count FROM entries GROUP BY ${col}`);
|
|
970
|
-
return Object.fromEntries(rows.map((r) => [r.key, r.count]));
|
|
971
|
-
}
|
|
972
|
-
function rowToEntry(row) {
|
|
973
|
-
return {
|
|
974
|
-
id: row.id,
|
|
975
|
-
type: row.type,
|
|
976
|
-
domain: row.domain,
|
|
977
|
-
title: row.title,
|
|
978
|
-
severity: row.severity,
|
|
979
|
-
description: row.description,
|
|
980
|
-
context: row.context ?? undefined,
|
|
981
|
-
example: row.example ?? undefined,
|
|
982
|
-
counterExample: row.counter_example ?? undefined,
|
|
983
|
-
why: row.why ?? undefined,
|
|
984
|
-
tags: JSON.parse(row.tags || '[]'),
|
|
985
|
-
appliesTo: JSON.parse(row.applies_to || '[]'),
|
|
986
|
-
tier: row.tier ?? undefined,
|
|
987
|
-
origin: row.origin ?? undefined,
|
|
988
|
-
validFrom: row.valid_from ?? undefined,
|
|
989
|
-
validUntil: row.valid_until ?? undefined,
|
|
990
|
-
};
|
|
991
|
-
}
|
|
992
|
-
function rowToSearchResult(row) {
|
|
993
|
-
// bm25() returns negative scores (lower = better), normalize to positive
|
|
994
|
-
const rawScore = row.score;
|
|
995
|
-
const score = rawScore < 0 ? -rawScore : rawScore;
|
|
996
|
-
return { entry: rowToEntry(row), score };
|
|
997
|
-
}
|
|
998
|
-
/**
|
|
999
|
-
* Build an FTS5 query from natural language input.
|
|
1000
|
-
*
|
|
1001
|
-
* Converts "React render performance memo" to:
|
|
1002
|
-
* {title}: (react OR render OR performance OR memo) OR (react OR render OR performance OR memo)
|
|
1003
|
-
*
|
|
1004
|
-
* Uses OR matching (not AND) so results include partial matches.
|
|
1005
|
-
* FTS5 BM25 ranks documents with more matching terms higher.
|
|
1006
|
-
* Title column is boosted via bm25() weights in the SQL query.
|
|
1007
|
-
*/
|
|
1008
|
-
function buildFtsQuery(query) {
|
|
1009
|
-
const terms = query
|
|
1010
|
-
.toLowerCase()
|
|
1011
|
-
.split(/\s+/)
|
|
1012
|
-
.filter((t) => t.length >= 2)
|
|
1013
|
-
.map((t) => t.replace(/[^a-z0-9]/g, ''))
|
|
1014
|
-
.filter(Boolean);
|
|
1015
|
-
if (terms.length === 0)
|
|
1016
|
-
return query;
|
|
1017
|
-
if (terms.length === 1)
|
|
1018
|
-
return terms[0];
|
|
1019
|
-
// Use OR to match any term — BM25 ranks by how many terms match
|
|
1020
|
-
const orTerms = terms.join(' OR ');
|
|
1021
|
-
return orTerms;
|
|
1022
|
-
}
|
|
1023
|
-
function rowToMemory(row) {
|
|
1024
|
-
return {
|
|
1025
|
-
id: row.id,
|
|
1026
|
-
projectPath: row.project_path,
|
|
1027
|
-
type: row.type,
|
|
1028
|
-
context: row.context,
|
|
1029
|
-
summary: row.summary,
|
|
1030
|
-
topics: JSON.parse(row.topics || '[]'),
|
|
1031
|
-
filesModified: JSON.parse(row.files_modified || '[]'),
|
|
1032
|
-
toolsUsed: JSON.parse(row.tools_used || '[]'),
|
|
1033
|
-
intent: row.intent ?? null,
|
|
1034
|
-
decisions: JSON.parse(row.decisions || '[]'),
|
|
1035
|
-
currentState: row.current_state ?? null,
|
|
1036
|
-
nextSteps: JSON.parse(row.next_steps || '[]'),
|
|
1037
|
-
vaultEntriesReferenced: JSON.parse(row.vault_entries_referenced || '[]'),
|
|
1038
|
-
createdAt: row.created_at,
|
|
1039
|
-
archivedAt: row.archived_at ?? null,
|
|
1040
|
-
};
|
|
1041
|
-
}
|
|
1042
193
|
//# sourceMappingURL=vault.js.map
|