@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/curator/curator.js
CHANGED
|
@@ -1,102 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { detectDuplicates as detectDuplicatesPure, DEFAULT_DUPLICATE_THRESHOLD, } from './duplicate-detector.js';
|
|
2
|
+
import { findContradictions, DEFAULT_CONTRADICTION_THRESHOLD, } from './contradiction-detector.js';
|
|
3
|
+
import { normalizeTag as normalizeTagPure, normalizeAndDedup, addTagAlias as addTagAliasPure, getCanonicalTags as getCanonicalTagsPure, seedDefaultAliases, } from './tag-manager.js';
|
|
4
|
+
import { initializeTables } from './schema.js';
|
|
5
|
+
import { computeHealthAudit } from './health-audit.js';
|
|
6
|
+
import { enrichEntryMetadata } from './metadata-enricher.js';
|
|
2
7
|
// ─── Constants ──────────────────────────────────────────────────────
|
|
3
|
-
const DEFAULT_DUPLICATE_THRESHOLD = 0.45;
|
|
4
|
-
const MERGE_SUGGESTION_THRESHOLD = 0.65;
|
|
5
|
-
const DEFAULT_CONTRADICTION_THRESHOLD = 0.4;
|
|
6
8
|
const DEFAULT_STALE_DAYS = 90;
|
|
7
|
-
const DEFAULT_TAG_ALIASES = [
|
|
8
|
-
['a11y', 'accessibility'],
|
|
9
|
-
['ts', 'typescript'],
|
|
10
|
-
['js', 'javascript'],
|
|
11
|
-
['css', 'styling'],
|
|
12
|
-
['tailwind', 'styling'],
|
|
13
|
-
['tw', 'styling'],
|
|
14
|
-
['vitest', 'testing'],
|
|
15
|
-
['jest', 'testing'],
|
|
16
|
-
['perf', 'performance'],
|
|
17
|
-
['sec', 'security'],
|
|
18
|
-
['auth', 'authentication'],
|
|
19
|
-
['i18n', 'internationalization'],
|
|
20
|
-
['l10n', 'localization'],
|
|
21
|
-
];
|
|
22
9
|
// ─── Curator Class ──────────────────────────────────────────────────
|
|
23
10
|
export class Curator {
|
|
24
11
|
vault;
|
|
25
12
|
provider;
|
|
13
|
+
tagStore;
|
|
26
14
|
constructor(vault) {
|
|
27
15
|
this.vault = vault;
|
|
28
16
|
this.provider = vault.getProvider();
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
17
|
+
this.tagStore = this.createTagStore();
|
|
18
|
+
initializeTables(this.provider);
|
|
19
|
+
this.provider.transaction(() => seedDefaultAliases(this.tagStore));
|
|
31
20
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59
|
-
action TEXT NOT NULL,
|
|
60
|
-
entry_id TEXT NOT NULL,
|
|
61
|
-
before_value TEXT,
|
|
62
|
-
after_value TEXT,
|
|
63
|
-
reason TEXT NOT NULL,
|
|
64
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
CREATE TABLE IF NOT EXISTS curator_entry_history (
|
|
68
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
69
|
-
entry_id TEXT NOT NULL,
|
|
70
|
-
snapshot TEXT NOT NULL,
|
|
71
|
-
changed_by TEXT DEFAULT 'system',
|
|
72
|
-
change_reason TEXT,
|
|
73
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
CREATE TABLE IF NOT EXISTS curator_contradictions (
|
|
77
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
78
|
-
pattern_id TEXT NOT NULL,
|
|
79
|
-
antipattern_id TEXT NOT NULL,
|
|
80
|
-
similarity REAL NOT NULL,
|
|
81
|
-
status TEXT NOT NULL DEFAULT 'open' CHECK(status IN ('open', 'resolved', 'dismissed')),
|
|
82
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
83
|
-
resolved_at INTEGER,
|
|
84
|
-
UNIQUE(pattern_id, antipattern_id)
|
|
85
|
-
);
|
|
86
|
-
CREATE INDEX IF NOT EXISTS idx_curator_state_status ON curator_entry_state(status);
|
|
87
|
-
CREATE INDEX IF NOT EXISTS idx_curator_changelog_entry ON curator_changelog(entry_id);
|
|
88
|
-
`);
|
|
89
|
-
}
|
|
90
|
-
seedDefaultAliases() {
|
|
91
|
-
this.provider.transaction(() => {
|
|
92
|
-
const canonicals = new Set(DEFAULT_TAG_ALIASES.map(([, c]) => c));
|
|
93
|
-
for (const tag of canonicals) {
|
|
94
|
-
this.provider.run('INSERT OR IGNORE INTO curator_tag_canonical (tag) VALUES (?)', [tag]);
|
|
95
|
-
}
|
|
96
|
-
for (const [alias, canonical] of DEFAULT_TAG_ALIASES) {
|
|
97
|
-
this.provider.run('INSERT OR IGNORE INTO curator_tag_alias (alias, canonical) VALUES (?, ?)', [alias, canonical]);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
21
|
+
createTagStore() {
|
|
22
|
+
const p = this.provider;
|
|
23
|
+
return {
|
|
24
|
+
getAlias(lower) {
|
|
25
|
+
return (p.get('SELECT canonical FROM curator_tag_alias WHERE alias = ?', [
|
|
26
|
+
lower,
|
|
27
|
+
])?.canonical ?? null);
|
|
28
|
+
},
|
|
29
|
+
insertCanonical(tag) {
|
|
30
|
+
p.run('INSERT OR IGNORE INTO curator_tag_canonical (tag) VALUES (?)', [tag]);
|
|
31
|
+
},
|
|
32
|
+
upsertAlias(alias, canonical) {
|
|
33
|
+
p.run('INSERT OR REPLACE INTO curator_tag_alias (alias, canonical) VALUES (?, ?)', [
|
|
34
|
+
alias,
|
|
35
|
+
canonical,
|
|
36
|
+
]);
|
|
37
|
+
},
|
|
38
|
+
getCanonicalRows() {
|
|
39
|
+
return p.all(`SELECT c.tag, c.description, (SELECT COUNT(*) FROM curator_tag_alias a WHERE a.canonical = c.tag) as alias_count FROM curator_tag_canonical c ORDER BY c.tag`);
|
|
40
|
+
},
|
|
41
|
+
countTagUsage(tag) {
|
|
42
|
+
return (p.get('SELECT COUNT(*) as count FROM entries WHERE tags LIKE ?', [
|
|
43
|
+
`%"${tag}"%`,
|
|
44
|
+
])?.count ?? 0);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
100
47
|
}
|
|
101
48
|
// ─── Status ─────────────────────────────────────────────────────
|
|
102
49
|
getStatus() {
|
|
@@ -116,31 +63,16 @@ export class Curator {
|
|
|
116
63
|
lastGroomedAt: lastGroomed.ts,
|
|
117
64
|
};
|
|
118
65
|
}
|
|
119
|
-
// ───
|
|
66
|
+
// ─── Tags (delegates to tag-manager) ──────────────────────────
|
|
120
67
|
normalizeTag(tag) {
|
|
121
|
-
|
|
122
|
-
const row = this.provider.get('SELECT canonical FROM curator_tag_alias WHERE alias = ?', [lower]);
|
|
123
|
-
if (row) {
|
|
124
|
-
return { original: tag, normalized: row.canonical, wasAliased: true };
|
|
125
|
-
}
|
|
126
|
-
return { original: tag, normalized: lower, wasAliased: false };
|
|
68
|
+
return normalizeTagPure(tag, this.tagStore);
|
|
127
69
|
}
|
|
128
70
|
normalizeTags(entryId) {
|
|
129
71
|
const entry = this.vault.get(entryId);
|
|
130
72
|
if (!entry)
|
|
131
73
|
return [];
|
|
132
|
-
const results =
|
|
133
|
-
const normalizedTags = [];
|
|
134
|
-
let changed = false;
|
|
135
|
-
for (const tag of entry.tags) {
|
|
136
|
-
const result = this.normalizeTag(tag);
|
|
137
|
-
results.push(result);
|
|
138
|
-
normalizedTags.push(result.normalized);
|
|
139
|
-
if (result.normalized !== tag)
|
|
140
|
-
changed = true;
|
|
141
|
-
}
|
|
74
|
+
const { results, dedupedTags, changed } = normalizeAndDedup(entry.tags, this.tagStore);
|
|
142
75
|
if (changed) {
|
|
143
|
-
const dedupedTags = [...new Set(normalizedTags)];
|
|
144
76
|
this.provider.run('UPDATE entries SET tags = ?, updated_at = unixepoch() WHERE id = ?', [
|
|
145
77
|
JSON.stringify(dedupedTags),
|
|
146
78
|
entryId,
|
|
@@ -150,121 +82,27 @@ export class Curator {
|
|
|
150
82
|
return results;
|
|
151
83
|
}
|
|
152
84
|
addTagAlias(alias, canonical) {
|
|
153
|
-
|
|
154
|
-
const canonicalLower = canonical.toLowerCase().trim();
|
|
155
|
-
this.provider.run('INSERT OR IGNORE INTO curator_tag_canonical (tag) VALUES (?)', [
|
|
156
|
-
canonicalLower,
|
|
157
|
-
]);
|
|
158
|
-
this.provider.run('INSERT OR REPLACE INTO curator_tag_alias (alias, canonical) VALUES (?, ?)', [
|
|
159
|
-
lower,
|
|
160
|
-
canonicalLower,
|
|
161
|
-
]);
|
|
85
|
+
addTagAliasPure(alias, canonical, this.tagStore);
|
|
162
86
|
}
|
|
163
87
|
getCanonicalTags() {
|
|
164
|
-
|
|
165
|
-
(SELECT COUNT(*) FROM curator_tag_alias a WHERE a.canonical = c.tag) as alias_count
|
|
166
|
-
FROM curator_tag_canonical c
|
|
167
|
-
ORDER BY c.tag`);
|
|
168
|
-
return rows.map((row) => ({
|
|
169
|
-
tag: row.tag,
|
|
170
|
-
description: row.description,
|
|
171
|
-
usageCount: this.countTagUsage(row.tag),
|
|
172
|
-
aliasCount: row.alias_count,
|
|
173
|
-
}));
|
|
174
|
-
}
|
|
175
|
-
countTagUsage(tag) {
|
|
176
|
-
const row = this.provider.get('SELECT COUNT(*) as count FROM entries WHERE tags LIKE ?', [`%"${tag}"%`]);
|
|
177
|
-
return row?.count ?? 0;
|
|
88
|
+
return getCanonicalTagsPure(this.tagStore);
|
|
178
89
|
}
|
|
179
|
-
// ───
|
|
90
|
+
// ─── Duplicates (delegates to duplicate-detector) ─────────────
|
|
180
91
|
detectDuplicates(entryId, threshold) {
|
|
181
|
-
|
|
182
|
-
const entries = this.vault.list({ limit: 100000 });
|
|
183
|
-
if (entries.length === 0)
|
|
184
|
-
return [];
|
|
185
|
-
// Build transient vocabulary
|
|
186
|
-
const vocabulary = this.buildVocabulary(entries);
|
|
187
|
-
// Build vectors for all entries
|
|
188
|
-
const vectors = new Map();
|
|
189
|
-
for (const entry of entries) {
|
|
190
|
-
const text = [entry.title, entry.description, entry.context ?? '', entry.tags.join(' ')].join(' ');
|
|
191
|
-
vectors.set(entry.id, calculateTfIdf(tokenize(text), vocabulary));
|
|
192
|
-
}
|
|
193
|
-
const targetEntries = entryId ? entries.filter((e) => e.id === entryId) : entries;
|
|
194
|
-
const results = [];
|
|
195
|
-
for (const entry of targetEntries) {
|
|
196
|
-
const entryVec = vectors.get(entry.id);
|
|
197
|
-
const matches = [];
|
|
198
|
-
for (const other of entries) {
|
|
199
|
-
if (other.id === entry.id)
|
|
200
|
-
continue;
|
|
201
|
-
const otherVec = vectors.get(other.id);
|
|
202
|
-
const similarity = cosineSimilarity(entryVec, otherVec);
|
|
203
|
-
if (similarity >= effectiveThreshold) {
|
|
204
|
-
matches.push({
|
|
205
|
-
entryId: other.id,
|
|
206
|
-
title: other.title,
|
|
207
|
-
similarity,
|
|
208
|
-
suggestMerge: similarity >= MERGE_SUGGESTION_THRESHOLD,
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
if (matches.length > 0) {
|
|
213
|
-
matches.sort((a, b) => b.similarity - a.similarity);
|
|
214
|
-
results.push({
|
|
215
|
-
entryId: entry.id,
|
|
216
|
-
matches,
|
|
217
|
-
scannedCount: entries.length - 1,
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return results;
|
|
92
|
+
return detectDuplicatesPure(this.vault.list({ limit: 100000 }), entryId, threshold);
|
|
222
93
|
}
|
|
223
|
-
// ─── Contradictions
|
|
94
|
+
// ─── Contradictions (delegates to contradiction-detector) ─────
|
|
224
95
|
detectContradictions(threshold) {
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
const antipatterns = entries.filter((e) => e.type === 'anti-pattern');
|
|
228
|
-
const patterns = entries.filter((e) => e.type === 'pattern');
|
|
229
|
-
if (antipatterns.length === 0 || patterns.length === 0)
|
|
230
|
-
return [];
|
|
231
|
-
const vocabulary = this.buildVocabulary(entries);
|
|
232
|
-
const detected = [];
|
|
233
|
-
for (const ap of antipatterns) {
|
|
234
|
-
// Stage 1: FTS5 candidate retrieval (fall back to all patterns if FTS returns empty)
|
|
235
|
-
let candidates;
|
|
236
|
-
try {
|
|
237
|
-
const searchResults = this.vault.search(ap.title, { type: 'pattern', limit: 20 });
|
|
238
|
-
candidates = searchResults.length > 0 ? searchResults.map((r) => r.entry) : patterns;
|
|
239
|
-
}
|
|
240
|
-
catch {
|
|
241
|
-
candidates = patterns;
|
|
242
|
-
}
|
|
243
|
-
// Stage 2: TF-IDF cosine similarity
|
|
244
|
-
const apText = [ap.title, ap.description, ap.context ?? ''].join(' ');
|
|
245
|
-
const apVec = calculateTfIdf(tokenize(apText), vocabulary);
|
|
246
|
-
for (const pattern of candidates) {
|
|
247
|
-
const pText = [pattern.title, pattern.description, pattern.context ?? ''].join(' ');
|
|
248
|
-
const pVec = calculateTfIdf(tokenize(pText), vocabulary);
|
|
249
|
-
const similarity = cosineSimilarity(apVec, pVec);
|
|
250
|
-
if (similarity >= effectiveThreshold) {
|
|
251
|
-
const result = this.provider.run('INSERT OR IGNORE INTO curator_contradictions (pattern_id, antipattern_id, similarity) VALUES (?, ?, ?)', [pattern.id, ap.id, similarity]);
|
|
252
|
-
if (result.changes > 0) {
|
|
253
|
-
const row = this.provider.get('SELECT * FROM curator_contradictions WHERE pattern_id = ? AND antipattern_id = ?', [pattern.id, ap.id]);
|
|
254
|
-
if (row)
|
|
255
|
-
detected.push(this.rowToContradiction(row));
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return detected;
|
|
96
|
+
const searchFn = (title) => this.vault.search(title, { type: 'pattern', limit: 20 }).map((r) => r.entry);
|
|
97
|
+
return this.persistContradictions(findContradictions(this.vault.list({ limit: 100000 }), threshold, searchFn));
|
|
261
98
|
}
|
|
262
99
|
getContradictions(status) {
|
|
263
100
|
const query = status
|
|
264
101
|
? 'SELECT * FROM curator_contradictions WHERE status = ? ORDER BY similarity DESC'
|
|
265
102
|
: 'SELECT * FROM curator_contradictions ORDER BY similarity DESC';
|
|
266
|
-
|
|
267
|
-
|
|
103
|
+
return this.provider
|
|
104
|
+
.all(query, status ? [status] : undefined)
|
|
105
|
+
.map((r) => this.rowToContradiction(r));
|
|
268
106
|
}
|
|
269
107
|
resolveContradiction(id, resolution) {
|
|
270
108
|
this.provider.run('UPDATE curator_contradictions SET status = ?, resolved_at = unixepoch() WHERE id = ?', [resolution, id]);
|
|
@@ -272,73 +110,30 @@ export class Curator {
|
|
|
272
110
|
return row ? this.rowToContradiction(row) : null;
|
|
273
111
|
}
|
|
274
112
|
async detectContradictionsHybrid(threshold) {
|
|
275
|
-
const
|
|
276
|
-
const entries = this.vault.list({ limit: 100000 });
|
|
277
|
-
const antipatterns = entries.filter((e) => e.type === 'anti-pattern');
|
|
278
|
-
const patterns = entries.filter((e) => e.type === 'pattern');
|
|
279
|
-
if (antipatterns.length === 0 || patterns.length === 0) {
|
|
280
|
-
return { contradictions: [], method: 'tfidf-only' };
|
|
281
|
-
}
|
|
282
|
-
const vocabulary = this.buildVocabulary(entries);
|
|
283
|
-
const detected = [];
|
|
284
|
-
for (const ap of antipatterns) {
|
|
285
|
-
let candidates;
|
|
286
|
-
try {
|
|
287
|
-
const searchResults = this.vault.search(ap.title, { type: 'pattern', limit: 20 });
|
|
288
|
-
candidates = searchResults.length > 0 ? searchResults.map((r) => r.entry) : patterns;
|
|
289
|
-
}
|
|
290
|
-
catch {
|
|
291
|
-
candidates = patterns;
|
|
292
|
-
}
|
|
293
|
-
const apText = [ap.title, ap.description, ap.context ?? ''].join(' ');
|
|
294
|
-
const apVec = calculateTfIdf(tokenize(apText), vocabulary);
|
|
295
|
-
for (const pattern of candidates) {
|
|
296
|
-
const pText = [pattern.title, pattern.description, pattern.context ?? ''].join(' ');
|
|
297
|
-
const pVec = calculateTfIdf(tokenize(pText), vocabulary);
|
|
298
|
-
const finalScore = cosineSimilarity(apVec, pVec);
|
|
299
|
-
if (finalScore >= effectiveThreshold) {
|
|
300
|
-
const result = this.provider.run('INSERT OR IGNORE INTO curator_contradictions (pattern_id, antipattern_id, similarity) VALUES (?, ?, ?)', [pattern.id, ap.id, finalScore]);
|
|
301
|
-
if (result.changes > 0) {
|
|
302
|
-
const row = this.provider.get('SELECT * FROM curator_contradictions WHERE pattern_id = ? AND antipattern_id = ?', [pattern.id, ap.id]);
|
|
303
|
-
if (row)
|
|
304
|
-
detected.push(this.rowToContradiction(row));
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
113
|
+
const searchFn = (title) => this.vault.search(title, { type: 'pattern', limit: 20 }).map((r) => r.entry);
|
|
309
114
|
return {
|
|
310
|
-
contradictions:
|
|
115
|
+
contradictions: this.persistContradictions(findContradictions(this.vault.list({ limit: 100000 }), threshold, searchFn)),
|
|
311
116
|
method: 'tfidf-only',
|
|
312
117
|
};
|
|
313
118
|
}
|
|
314
|
-
// ─── Grooming
|
|
119
|
+
// ─── Grooming ─────────────────────────────────────────────────
|
|
315
120
|
groomEntry(entryId) {
|
|
316
121
|
const entry = this.vault.get(entryId);
|
|
317
122
|
if (!entry)
|
|
318
123
|
return null;
|
|
319
124
|
const tagsNormalized = this.normalizeTags(entryId);
|
|
320
|
-
// Check staleness based on entry's updated_at timestamp
|
|
321
125
|
const row = this.provider.get('SELECT updated_at FROM entries WHERE id = ?', [entryId]);
|
|
322
126
|
const now = Math.floor(Date.now() / 1000);
|
|
323
127
|
const stale = row ? now - row.updated_at > DEFAULT_STALE_DAYS * 86400 : false;
|
|
324
128
|
const status = stale ? 'stale' : 'active';
|
|
325
|
-
|
|
326
|
-
this.provider.run(`INSERT INTO curator_entry_state (entry_id, status, last_groomed_at)
|
|
327
|
-
VALUES (?, ?, unixepoch())
|
|
328
|
-
ON CONFLICT(entry_id) DO UPDATE SET status = excluded.status, last_groomed_at = unixepoch()`, [entryId, status]);
|
|
129
|
+
this.provider.run(`INSERT INTO curator_entry_state (entry_id, status, last_groomed_at) VALUES (?, ?, unixepoch()) ON CONFLICT(entry_id) DO UPDATE SET status = excluded.status, last_groomed_at = unixepoch()`, [entryId, status]);
|
|
329
130
|
this.logChange('groom', entryId, null, `status=${status}`, 'Routine grooming');
|
|
330
|
-
return {
|
|
331
|
-
entryId,
|
|
332
|
-
tagsNormalized,
|
|
333
|
-
stale,
|
|
334
|
-
lastGroomedAt: now,
|
|
335
|
-
};
|
|
131
|
+
return { entryId, tagsNormalized, stale, lastGroomedAt: now };
|
|
336
132
|
}
|
|
337
133
|
groomAll() {
|
|
338
134
|
const start = Date.now();
|
|
339
135
|
const entries = this.vault.list({ limit: 100000 });
|
|
340
|
-
let tagsNormalized = 0;
|
|
341
|
-
let staleCount = 0;
|
|
136
|
+
let tagsNormalized = 0, staleCount = 0;
|
|
342
137
|
for (const entry of entries) {
|
|
343
138
|
const result = this.groomEntry(entry.id);
|
|
344
139
|
if (result) {
|
|
@@ -355,33 +150,25 @@ export class Curator {
|
|
|
355
150
|
durationMs: Date.now() - start,
|
|
356
151
|
};
|
|
357
152
|
}
|
|
358
|
-
// ─── Consolidation
|
|
153
|
+
// ─── Consolidation ───────────────────────────────────────────
|
|
359
154
|
consolidate(options) {
|
|
360
155
|
const start = Date.now();
|
|
361
156
|
const dryRun = options?.dryRun ?? true;
|
|
362
157
|
const staleDaysThreshold = options?.staleDaysThreshold ?? DEFAULT_STALE_DAYS;
|
|
363
158
|
const duplicateThreshold = options?.duplicateThreshold ?? DEFAULT_DUPLICATE_THRESHOLD;
|
|
364
159
|
const contradictionThreshold = options?.contradictionThreshold ?? DEFAULT_CONTRADICTION_THRESHOLD;
|
|
365
|
-
// Detect duplicates
|
|
366
160
|
const duplicates = this.detectDuplicates(undefined, duplicateThreshold);
|
|
367
|
-
// Detect stale entries
|
|
368
161
|
const now = Math.floor(Date.now() / 1000);
|
|
369
|
-
const
|
|
370
|
-
const staleRows = this.provider.all('SELECT id FROM entries WHERE updated_at < ?', [staleThreshold]);
|
|
162
|
+
const staleRows = this.provider.all('SELECT id FROM entries WHERE updated_at < ?', [now - staleDaysThreshold * 86400]);
|
|
371
163
|
const staleEntries = staleRows.map((r) => r.id);
|
|
372
|
-
// Detect contradictions
|
|
373
164
|
const contradictions = this.detectContradictions(contradictionThreshold);
|
|
374
165
|
let mutations = 0;
|
|
375
166
|
if (!dryRun) {
|
|
376
|
-
// Archive stale entries
|
|
377
167
|
for (const entryId of staleEntries) {
|
|
378
|
-
this.provider.run(`INSERT INTO curator_entry_state (entry_id, status, last_groomed_at)
|
|
379
|
-
VALUES (?, 'archived', unixepoch())
|
|
380
|
-
ON CONFLICT(entry_id) DO UPDATE SET status = 'archived', last_groomed_at = unixepoch()`, [entryId]);
|
|
168
|
+
this.provider.run(`INSERT INTO curator_entry_state (entry_id, status, last_groomed_at) VALUES (?, 'archived', unixepoch()) ON CONFLICT(entry_id) DO UPDATE SET status = 'archived', last_groomed_at = unixepoch()`, [entryId]);
|
|
381
169
|
this.logChange('archive', entryId, 'active', 'archived', 'Stale entry archived during consolidation');
|
|
382
170
|
mutations++;
|
|
383
171
|
}
|
|
384
|
-
// Remove lower-similarity duplicates (keep the first entry, remove matches)
|
|
385
172
|
const removed = new Set();
|
|
386
173
|
for (const result of duplicates) {
|
|
387
174
|
for (const match of result.matches) {
|
|
@@ -403,109 +190,24 @@ export class Curator {
|
|
|
403
190
|
durationMs: Date.now() - start,
|
|
404
191
|
};
|
|
405
192
|
}
|
|
406
|
-
// ─── Changelog
|
|
193
|
+
// ─── Changelog ────────────────────────────────────────────────
|
|
407
194
|
getEntryHistory(entryId, limit) {
|
|
408
|
-
|
|
409
|
-
|
|
195
|
+
return this.provider
|
|
196
|
+
.all('SELECT * FROM curator_changelog WHERE entry_id = ? ORDER BY created_at DESC, id DESC LIMIT ?', [entryId, limit ?? 50])
|
|
197
|
+
.map((r) => this.rowToChangelog(r));
|
|
410
198
|
}
|
|
411
|
-
// ─── Health Audit
|
|
199
|
+
// ─── Health Audit (delegates to health-audit) ─────────────────
|
|
412
200
|
healthAudit() {
|
|
413
201
|
const entries = this.vault.list({ limit: 100000 });
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
recommendations: ['Vault is empty — add knowledge entries to get started.'],
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
let score = 100;
|
|
423
|
-
// Coverage: penalize if no anti-patterns or no patterns
|
|
424
|
-
const typeCount = { pattern: 0, 'anti-pattern': 0, rule: 0 };
|
|
425
|
-
for (const e of entries) {
|
|
426
|
-
typeCount[e.type] = (typeCount[e.type] ?? 0) + 1;
|
|
427
|
-
}
|
|
428
|
-
const hasPatterns = typeCount.pattern > 0;
|
|
429
|
-
const hasAntiPatterns = typeCount['anti-pattern'] > 0;
|
|
430
|
-
const hasRules = typeCount.rule > 0;
|
|
431
|
-
let coverageScore = 1;
|
|
432
|
-
if (!hasPatterns) {
|
|
433
|
-
score -= 10;
|
|
434
|
-
coverageScore -= 0.33;
|
|
435
|
-
recommendations.push('No patterns found — add patterns to improve coverage.');
|
|
436
|
-
}
|
|
437
|
-
if (!hasAntiPatterns) {
|
|
438
|
-
score -= 5;
|
|
439
|
-
coverageScore -= 0.17;
|
|
440
|
-
recommendations.push('No anti-patterns found — add anti-patterns to detect contradictions.');
|
|
441
|
-
}
|
|
442
|
-
if (!hasRules) {
|
|
443
|
-
score -= 5;
|
|
444
|
-
coverageScore -= 0.17;
|
|
445
|
-
recommendations.push('No rules found — add rules for completeness.');
|
|
446
|
-
}
|
|
447
|
-
coverageScore = Math.max(0, coverageScore);
|
|
448
|
-
// Freshness: penalize stale entries
|
|
449
|
-
const now = Math.floor(Date.now() / 1000);
|
|
450
|
-
const staleThreshold = now - DEFAULT_STALE_DAYS * 86400;
|
|
451
|
-
const staleCount = (this.provider.get('SELECT COUNT(*) as count FROM entries WHERE updated_at < ?', [staleThreshold]) ?? { count: 0 }).count;
|
|
452
|
-
const staleRatio = staleCount / entries.length;
|
|
453
|
-
const freshnessScore = 1 - staleRatio;
|
|
454
|
-
if (staleRatio > 0.3) {
|
|
455
|
-
const penalty = Math.min(20, Math.round(staleRatio * 30));
|
|
456
|
-
score -= penalty;
|
|
457
|
-
recommendations.push(`${staleCount} stale entries (${Math.round(staleRatio * 100)}%) — run grooming to update.`);
|
|
458
|
-
}
|
|
459
|
-
// Quality: penalize duplicates and contradictions
|
|
460
|
-
const duplicates = this.detectDuplicates();
|
|
461
|
-
const contradictions = this.getContradictions('open');
|
|
462
|
-
let qualityScore = 1;
|
|
463
|
-
if (duplicates.length > 0) {
|
|
464
|
-
const penalty = Math.min(15, duplicates.length * 3);
|
|
465
|
-
score -= penalty;
|
|
466
|
-
qualityScore -= penalty / 30;
|
|
467
|
-
recommendations.push(`${duplicates.length} entries have duplicates — run consolidation.`);
|
|
468
|
-
}
|
|
469
|
-
if (contradictions.length > 0) {
|
|
470
|
-
const penalty = Math.min(15, contradictions.length * 5);
|
|
471
|
-
score -= penalty;
|
|
472
|
-
qualityScore -= penalty / 30;
|
|
473
|
-
recommendations.push(`${contradictions.length} open contradictions — resolve or dismiss.`);
|
|
474
|
-
}
|
|
475
|
-
qualityScore = Math.max(0, qualityScore);
|
|
476
|
-
// Tag health: penalize entries with few or no tags
|
|
477
|
-
const lowTagEntries = entries.filter((e) => e.tags.length < 2);
|
|
478
|
-
const lowTagRatio = lowTagEntries.length / entries.length;
|
|
479
|
-
const tagHealthScore = 1 - lowTagRatio;
|
|
480
|
-
if (lowTagRatio > 0.3) {
|
|
481
|
-
const penalty = Math.min(10, Math.round(lowTagRatio * 15));
|
|
482
|
-
score -= penalty;
|
|
483
|
-
recommendations.push(`${lowTagEntries.length} entries have fewer than 2 tags — improve tagging.`);
|
|
484
|
-
}
|
|
485
|
-
// Penalize ungroomed entries
|
|
486
|
-
const groomedCount = (this.provider.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL') ?? { count: 0 }).count;
|
|
487
|
-
if (groomedCount < entries.length) {
|
|
488
|
-
const ungroomed = entries.length - groomedCount;
|
|
489
|
-
const penalty = Math.min(10, Math.round((ungroomed / entries.length) * 10));
|
|
490
|
-
score -= penalty;
|
|
491
|
-
recommendations.push(`${ungroomed} entries never groomed — run groomAll().`);
|
|
492
|
-
}
|
|
493
|
-
score = Math.max(0, score);
|
|
494
|
-
if (recommendations.length === 0) {
|
|
495
|
-
recommendations.push('Vault is healthy — no issues detected.');
|
|
496
|
-
}
|
|
497
|
-
return {
|
|
498
|
-
score,
|
|
499
|
-
metrics: {
|
|
500
|
-
coverage: coverageScore,
|
|
501
|
-
freshness: freshnessScore,
|
|
502
|
-
quality: qualityScore,
|
|
503
|
-
tagHealth: tagHealthScore,
|
|
504
|
-
},
|
|
505
|
-
recommendations,
|
|
202
|
+
const dataProvider = {
|
|
203
|
+
getStaleCount: (threshold) => (this.provider.get('SELECT COUNT(*) as count FROM entries WHERE updated_at < ?', [threshold]) ?? { count: 0 }).count,
|
|
204
|
+
getGroomedCount: () => (this.provider.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL') ?? { count: 0 }).count,
|
|
205
|
+
getDuplicates: () => this.detectDuplicates(),
|
|
206
|
+
getOpenContradictions: () => this.getContradictions('open'),
|
|
506
207
|
};
|
|
208
|
+
return computeHealthAudit(entries, dataProvider, DEFAULT_STALE_DAYS);
|
|
507
209
|
}
|
|
508
|
-
// ─── Entry History (Version Snapshots)
|
|
210
|
+
// ─── Entry History (Version Snapshots) ────────────────────────
|
|
509
211
|
recordSnapshot(entryId, changedBy, changeReason) {
|
|
510
212
|
const entry = this.vault.get(entryId);
|
|
511
213
|
if (!entry)
|
|
@@ -514,8 +216,9 @@ export class Curator {
|
|
|
514
216
|
return { recorded: true, historyId: Number(result.lastInsertRowid) };
|
|
515
217
|
}
|
|
516
218
|
getVersionHistory(entryId) {
|
|
517
|
-
|
|
518
|
-
|
|
219
|
+
return this.provider
|
|
220
|
+
.all('SELECT * FROM curator_entry_history WHERE entry_id = ? ORDER BY created_at ASC, id ASC', [entryId])
|
|
221
|
+
.map((row) => ({
|
|
519
222
|
historyId: row.id,
|
|
520
223
|
entryId: row.entry_id,
|
|
521
224
|
snapshot: JSON.parse(row.snapshot),
|
|
@@ -524,115 +227,53 @@ export class Curator {
|
|
|
524
227
|
createdAt: row.created_at,
|
|
525
228
|
}));
|
|
526
229
|
}
|
|
527
|
-
// ─── Queue Stats
|
|
230
|
+
// ─── Queue Stats ─────────────────────────────────────────────
|
|
528
231
|
getQueueStats() {
|
|
529
|
-
const
|
|
530
|
-
const
|
|
531
|
-
const
|
|
232
|
+
const p = this.provider;
|
|
233
|
+
const totalEntries = (p.get('SELECT COUNT(*) as count FROM entries') ?? { count: 0 }).count;
|
|
234
|
+
const groomedEntries = (p.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL') ?? { count: 0 }).count;
|
|
532
235
|
const now = Math.floor(Date.now() / 1000);
|
|
533
|
-
const
|
|
534
|
-
const
|
|
535
|
-
const staleEntries = (this.provider.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL AND last_groomed_at < ?', [staleThreshold]) ?? { count: 0 }).count;
|
|
536
|
-
const freshEntries = (this.provider.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL AND last_groomed_at >= ?', [freshThreshold]) ?? { count: 0 }).count;
|
|
236
|
+
const staleEntries = (p.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL AND last_groomed_at < ?', [now - 30 * 86400]) ?? { count: 0 }).count;
|
|
237
|
+
const freshEntries = (p.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL AND last_groomed_at >= ?', [now - 7 * 86400]) ?? { count: 0 }).count;
|
|
537
238
|
let avgDaysSinceGroom = 0;
|
|
538
239
|
if (groomedEntries > 0) {
|
|
539
|
-
const
|
|
540
|
-
const totalSeconds = sumRow.total ?? 0;
|
|
240
|
+
const totalSeconds = (p.get('SELECT SUM(? - last_groomed_at) as total FROM curator_entry_state WHERE last_groomed_at IS NOT NULL', [now]) ?? { total: 0 }).total ?? 0;
|
|
541
241
|
avgDaysSinceGroom = Math.round((totalSeconds / groomedEntries / 86400) * 100) / 100;
|
|
542
242
|
}
|
|
543
243
|
return {
|
|
544
244
|
totalEntries,
|
|
545
245
|
groomedEntries,
|
|
546
|
-
ungroomedEntries,
|
|
246
|
+
ungroomedEntries: totalEntries - groomedEntries,
|
|
547
247
|
staleEntries,
|
|
548
248
|
freshEntries,
|
|
549
249
|
avgDaysSinceGroom,
|
|
550
250
|
};
|
|
551
251
|
}
|
|
552
|
-
// ─── Metadata Enrichment
|
|
252
|
+
// ─── Metadata Enrichment (delegates to metadata-enricher) ────
|
|
553
253
|
enrichMetadata(entryId) {
|
|
554
254
|
const entry = this.vault.get(entryId);
|
|
555
255
|
if (!entry)
|
|
556
256
|
return { enriched: false, changes: [] };
|
|
557
|
-
const changes =
|
|
558
|
-
|
|
559
|
-
// Auto-capitalize title
|
|
560
|
-
if (entry.title.length > 0 && entry.title[0] !== entry.title[0].toUpperCase()) {
|
|
561
|
-
const capitalized = entry.title[0].toUpperCase() + entry.title.slice(1);
|
|
562
|
-
changes.push({ field: 'title', before: entry.title, after: capitalized });
|
|
563
|
-
updates.title = capitalized;
|
|
564
|
-
}
|
|
565
|
-
// Normalize tags: lowercase, trim, dedup
|
|
566
|
-
const normalizedTags = [...new Set(entry.tags.map((t) => t.toLowerCase().trim()))];
|
|
567
|
-
const tagsChanged = normalizedTags.length !== entry.tags.length ||
|
|
568
|
-
normalizedTags.some((t, i) => t !== entry.tags[i]);
|
|
569
|
-
if (tagsChanged) {
|
|
570
|
-
changes.push({
|
|
571
|
-
field: 'tags',
|
|
572
|
-
before: JSON.stringify(entry.tags),
|
|
573
|
-
after: JSON.stringify(normalizedTags),
|
|
574
|
-
});
|
|
575
|
-
updates.tags = normalizedTags;
|
|
576
|
-
}
|
|
577
|
-
// Infer severity from keywords if currently 'suggestion'
|
|
578
|
-
if (entry.severity === 'suggestion') {
|
|
579
|
-
const text = (entry.title + ' ' + entry.description).toLowerCase();
|
|
580
|
-
const criticalKeywords = ['never', 'must not', 'critical', 'security', 'vulnerability'];
|
|
581
|
-
const warningKeywords = ['avoid', 'should not', 'deprecated', 'careful', 'warning'];
|
|
582
|
-
if (criticalKeywords.some((k) => text.includes(k))) {
|
|
583
|
-
changes.push({ field: 'severity', before: entry.severity, after: 'critical' });
|
|
584
|
-
updates.severity = 'critical';
|
|
585
|
-
}
|
|
586
|
-
else if (warningKeywords.some((k) => text.includes(k))) {
|
|
587
|
-
changes.push({ field: 'severity', before: entry.severity, after: 'warning' });
|
|
588
|
-
updates.severity = 'warning';
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
// Infer type from title patterns
|
|
592
|
-
if (entry.type === 'pattern') {
|
|
593
|
-
const titleLower = entry.title.toLowerCase();
|
|
594
|
-
if (titleLower.startsWith('avoid') ||
|
|
595
|
-
titleLower.startsWith('never') ||
|
|
596
|
-
titleLower.startsWith("don't") ||
|
|
597
|
-
titleLower.startsWith('do not')) {
|
|
598
|
-
changes.push({ field: 'type', before: entry.type, after: 'anti-pattern' });
|
|
599
|
-
updates.type = 'anti-pattern';
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
// Trim whitespace from description
|
|
603
|
-
const trimmed = entry.description.trim();
|
|
604
|
-
if (trimmed !== entry.description) {
|
|
605
|
-
changes.push({ field: 'description', before: entry.description, after: trimmed });
|
|
606
|
-
updates.description = trimmed;
|
|
607
|
-
}
|
|
608
|
-
if (changes.length === 0) {
|
|
257
|
+
const { changes, updates } = enrichEntryMetadata(entry);
|
|
258
|
+
if (changes.length === 0)
|
|
609
259
|
return { enriched: false, changes: [] };
|
|
610
|
-
}
|
|
611
|
-
// Apply updates
|
|
612
260
|
this.vault.update(entryId, updates);
|
|
613
|
-
// Record snapshot
|
|
614
261
|
this.recordSnapshot(entryId, 'curator', 'Metadata enrichment');
|
|
615
|
-
// Log change
|
|
616
262
|
this.logChange('enrich_metadata', entryId, JSON.stringify(changes.map((c) => c.field)), JSON.stringify(changes.map((c) => c.after)), 'Rule-based metadata enrichment');
|
|
617
263
|
return { enriched: true, changes };
|
|
618
264
|
}
|
|
619
|
-
// ─── Private Helpers
|
|
620
|
-
|
|
621
|
-
const
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
265
|
+
// ─── Private Helpers ──────────────────────────────────────────
|
|
266
|
+
persistContradictions(candidates) {
|
|
267
|
+
const detected = [];
|
|
268
|
+
for (const c of candidates) {
|
|
269
|
+
const result = this.provider.run('INSERT OR IGNORE INTO curator_contradictions (pattern_id, antipattern_id, similarity) VALUES (?, ?, ?)', [c.patternId, c.antipatternId, c.similarity]);
|
|
270
|
+
if (result.changes > 0) {
|
|
271
|
+
const row = this.provider.get('SELECT * FROM curator_contradictions WHERE pattern_id = ? AND antipattern_id = ?', [c.patternId, c.antipatternId]);
|
|
272
|
+
if (row)
|
|
273
|
+
detected.push(this.rowToContradiction(row));
|
|
628
274
|
}
|
|
629
275
|
}
|
|
630
|
-
|
|
631
|
-
for (const [term, df] of termDocFreq) {
|
|
632
|
-
const idf = Math.log((docCount + 1) / (df + 1)) + 1;
|
|
633
|
-
vocabulary.set(term, idf);
|
|
634
|
-
}
|
|
635
|
-
return vocabulary;
|
|
276
|
+
return detected;
|
|
636
277
|
}
|
|
637
278
|
logChange(action, entryId, beforeValue, afterValue, reason) {
|
|
638
279
|
this.provider.run('INSERT INTO curator_changelog (action, entry_id, before_value, after_value, reason) VALUES (?, ?, ?, ?, ?)', [action, entryId, beforeValue, afterValue, reason]);
|