@soleri/core 9.0.4 → 9.2.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/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 +90 -525
- 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 +22 -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 +26 -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 +377 -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 +157 -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 +129 -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 +294 -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 +199 -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 +296 -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 +154 -878
- 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 +227 -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 +21 -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/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/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 +330 -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 +6 -0
- package/dist/runtime/facades/index.js.map +1 -1
- 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 +39 -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/vault-facade.d.ts +4 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +13 -66
- 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 +113 -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 +367 -40
- 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 +27 -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 +68 -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/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 +104 -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 +257 -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 +142 -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 +240 -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 +179 -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 +78 -931
- package/dist/vault/vault.js.map +1 -1
- package/package.json +1 -1
- package/src/agency/agency-manager.test.ts +600 -0
- package/src/agency/default-rules.test.ts +228 -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/brain/strength-scorer.ts +404 -0
- package/src/capabilities/chain-mapping.test.ts +66 -0
- package/src/capabilities/registry.test.ts +369 -0
- package/src/chat/agent-loop.test.ts +394 -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 +173 -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 +211 -0
- package/src/context/context-engine.test.ts +461 -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 +104 -0
- package/src/curator/contradiction-detector.test.ts +180 -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 +115 -777
- package/src/curator/duplicate-detector.test.ts +183 -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 +135 -0
- package/src/curator/schema.ts +65 -0
- package/src/curator/tag-manager.test.ts +165 -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 +171 -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 +150 -0
- package/src/domain-packs/types.test.ts +130 -0
- package/src/enforcement/adapters/claude-code.test.ts +216 -0
- package/src/enforcement/registry.test.ts +264 -0
- package/src/engine/bin/soleri-engine.ts +28 -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 +124 -0
- package/src/engine/module-manifest.ts +22 -2
- package/src/engine/register-engine.test.ts +230 -0
- package/src/engine/register-engine.ts +26 -2
- package/src/errors/classify.test.ts +199 -0
- package/src/errors/retry.test.ts +156 -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 +424 -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 +107 -0
- package/src/flows/executor.test.ts +263 -0
- package/src/flows/gate-evaluator.test.ts +194 -0
- package/src/flows/gate-evaluator.ts +25 -0
- package/src/flows/types.ts +4 -0
- package/src/governance/governance.test.ts +726 -0
- package/src/health/health-registry.test.ts +186 -0
- package/src/health/vault-integrity.test.ts +110 -0
- package/src/index.ts +92 -0
- package/src/intake/content-classifier.test.ts +209 -0
- package/src/intake/dedup-gate.test.ts +131 -0
- package/src/intake/intake-pipeline.test.ts +506 -0
- package/src/intake/intake-pipeline.ts +1 -0
- package/src/intake/text-ingester.test.ts +194 -0
- package/src/intake/text-ingester.ts +2 -0
- package/src/llm/key-pool.test.ts +236 -0
- package/src/llm/key-pool.ts +3 -4
- package/src/llm/llm-client.test.ts +345 -0
- package/src/llm/oauth-discovery.test.ts +180 -0
- package/src/llm/utils.test.ts +327 -0
- package/src/llm/utils.ts +2 -0
- package/src/{__tests__ → logging}/logger.test.ts +41 -62
- package/src/loop/loop-manager.test.ts +519 -0
- package/src/migrations/migration-runner.edge-cases.test.ts +319 -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 +320 -0
- package/src/operator/operator-profile.test.ts +314 -0
- package/src/operator/operator-profile.ts +469 -0
- package/src/operator/operator-signals-extended.test.ts +245 -0
- package/src/operator/operator-signals.test.ts +281 -0
- package/src/operator/operator-signals.ts +261 -0
- package/src/operator/operator-types.ts +444 -0
- package/src/operator/prompts/hook-precompact-operator-dispatch.md +94 -0
- package/src/operator/prompts/subagent-soft-signal-extractor.md +125 -0
- package/src/operator/prompts/subagent-synthesis-cognition.md +181 -0
- package/src/operator/prompts/subagent-synthesis-communication.md +140 -0
- package/src/operator/prompts/subagent-synthesis-technical.md +160 -0
- package/src/operator/prompts/subagent-synthesis-trust.md +143 -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 +59 -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 +406 -0
- package/src/planning/evidence-collector.ts +50 -0
- package/src/planning/gap-analysis-alternatives.test.ts +169 -0
- package/src/planning/gap-analysis.ts +21 -636
- package/src/planning/gap-passes.test.ts +372 -0
- package/src/planning/gap-passes.ts +298 -0
- package/src/planning/gap-patterns.test.ts +320 -0
- package/src/planning/gap-patterns.ts +234 -0
- package/src/planning/gap-types.ts +4 -1
- package/src/planning/github-projection.test.ts +177 -0
- package/src/planning/github-projection.ts +425 -0
- package/src/planning/impact-analyzer.test.ts +180 -0
- package/src/planning/impact-analyzer.ts +264 -0
- package/src/planning/plan-lifecycle.test.ts +312 -0
- package/src/planning/plan-lifecycle.ts +346 -0
- package/src/planning/planner-types.ts +215 -0
- package/src/{__tests__ → planning}/planner.test.ts +169 -15
- package/src/planning/planner.ts +197 -1228
- package/src/planning/rationalization-detector.test.ts +171 -0
- package/src/planning/rationalization-detector.ts +138 -0
- package/src/planning/reconciliation-engine.test.ts +141 -0
- package/src/planning/reconciliation-engine.ts +162 -0
- package/src/planning/task-verifier.test.ts +235 -0
- package/src/planning/task-verifier.ts +303 -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 +255 -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 +212 -0
- package/src/plugins/plugin-registry.test.ts +272 -0
- package/src/project/project-registry.test.ts +428 -0
- package/src/prompts/parser.test.ts +100 -0
- package/src/prompts/template-manager.test.ts +109 -0
- package/src/{__tests__ → queue}/async-infrastructure.test.ts +3 -3
- package/src/queue/job-queue.test.ts +331 -0
- package/src/queue/pipeline-runner.test.ts +209 -0
- package/src/runtime/admin-extra-ops.test.ts +527 -0
- package/src/runtime/admin-ops.test.ts +257 -0
- package/src/runtime/admin-ops.ts +45 -17
- package/src/runtime/admin-setup-ops.test.ts +328 -0
- package/src/runtime/admin-setup-ops.ts +20 -43
- package/src/runtime/archive-ops.test.ts +269 -0
- package/src/runtime/archive-ops.ts +347 -0
- package/src/runtime/capture-ops.test.ts +433 -0
- package/src/runtime/capture-ops.ts +50 -8
- package/src/runtime/chain-ops.test.ts +149 -0
- package/src/runtime/claude-md-helpers.test.ts +191 -0
- package/src/runtime/claude-md-helpers.ts +1 -1
- package/src/runtime/context-health.test.ts +78 -0
- package/src/runtime/context-health.ts +85 -0
- package/src/runtime/curator-extra-ops.test.ts +202 -0
- package/src/runtime/deprecation.test.ts +98 -0
- package/src/runtime/domain-ops.test.ts +268 -0
- package/src/runtime/facades/admin-facade.test.ts +333 -0
- package/src/runtime/facades/agency-facade.test.ts +278 -0
- package/src/runtime/facades/archive-facade.test.ts +294 -0
- package/src/runtime/facades/archive-facade.ts +14 -0
- package/src/runtime/facades/brain-facade.test.ts +714 -0
- package/src/runtime/facades/brain-facade.ts +2 -0
- package/src/runtime/facades/chat-facade.test.ts +166 -0
- package/src/runtime/facades/chat-facade.ts +15 -906
- package/src/runtime/facades/chat-service-ops.test.ts +276 -0
- package/src/runtime/facades/chat-service-ops.ts +374 -0
- package/src/runtime/facades/chat-session-ops.test.ts +197 -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 +269 -0
- package/src/runtime/facades/chat-transport-ops.ts +380 -0
- package/src/runtime/facades/context-facade.test.ts +108 -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 +6 -0
- package/src/runtime/facades/loop-facade.test.ts +245 -0
- package/src/runtime/facades/memory-facade.test.ts +269 -0
- package/src/runtime/facades/memory-facade.ts +78 -6
- package/src/runtime/facades/operator-facade.test.ts +208 -0
- package/src/runtime/facades/operator-facade.ts +236 -0
- package/src/runtime/facades/orchestrate-facade.test.ts +185 -0
- package/src/runtime/facades/orchestrate-facade.ts +3 -3
- package/src/runtime/facades/plan-facade.test.ts +266 -0
- package/src/runtime/facades/plan-facade.ts +42 -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/vault-facade.test.ts +631 -0
- package/src/runtime/facades/vault-facade.ts +15 -70
- package/src/runtime/feature-flags.test.ts +140 -0
- package/src/runtime/github-integration.test.ts +89 -0
- package/src/runtime/github-integration.ts +159 -0
- package/src/runtime/grading-ops.test.ts +141 -0
- package/src/runtime/grading-ops.ts +1 -1
- package/src/runtime/intake-ops.test.ts +208 -0
- package/src/runtime/loop-ops.test.ts +238 -0
- package/src/runtime/memory-cross-project-ops.test.ts +177 -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 +435 -46
- package/src/runtime/pack-ops.test.ts +158 -0
- package/src/runtime/planning-extra-ops.test.ts +583 -0
- package/src/runtime/planning-extra-ops.ts +72 -4
- package/src/{__tests__ → runtime}/playbook-ops-execution.test.ts +3 -3
- package/src/runtime/playbook-ops.test.ts +262 -0
- package/src/runtime/plugin-ops.test.ts +201 -0
- package/src/runtime/project-ops.test.ts +235 -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 +39 -12
- package/src/runtime/session-briefing.test.ts +302 -0
- package/src/runtime/session-briefing.ts +80 -1
- package/src/runtime/sync-ops.test.ts +221 -0
- package/src/runtime/sync-ops.ts +325 -0
- package/src/runtime/telemetry-ops.test.ts +132 -0
- package/src/runtime/types.ts +10 -4
- package/src/runtime/vault-extra-ops.test.ts +246 -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 +130 -0
- package/src/runtime/vault-sharing-ops.ts +5 -329
- package/src/skills/sync-skills.ts +108 -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 +294 -0
- package/src/update-check.ts +111 -0
- package/src/vault/__tests__/vault-characterization.test.ts +168 -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 +358 -0
- package/src/vault/linking.ts +149 -183
- package/src/vault/obsidian-sync.test.ts +342 -0
- package/src/vault/playbook.test.ts +152 -0
- package/src/vault/scope-detector.test.ts +187 -0
- package/src/vault/vault-branching.test.ts +250 -0
- package/src/{__tests__ → vault}/vault-connect.test.ts +1 -1
- package/src/vault/vault-entries.ts +282 -0
- package/src/vault/vault-interfaces.ts +56 -0
- package/src/vault/vault-maintenance.ts +205 -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 +160 -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 +181 -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 +89 -1171
- 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__/health-registry.test.ts +0 -173
- 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/dist/curator/curator.js
CHANGED
|
@@ -1,270 +1,80 @@
|
|
|
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
|
-
alias TEXT PRIMARY KEY,
|
|
52
|
-
canonical TEXT NOT NULL,
|
|
53
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
54
|
-
FOREIGN KEY (canonical) REFERENCES curator_tag_canonical(tag)
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
CREATE TABLE IF NOT EXISTS curator_changelog (
|
|
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 = ?', [lower])?.canonical ?? null;
|
|
26
|
+
},
|
|
27
|
+
insertCanonical(tag) {
|
|
28
|
+
p.run('INSERT OR IGNORE INTO curator_tag_canonical (tag) VALUES (?)', [tag]);
|
|
29
|
+
},
|
|
30
|
+
upsertAlias(alias, canonical) {
|
|
31
|
+
p.run('INSERT OR REPLACE INTO curator_tag_alias (alias, canonical) VALUES (?, ?)', [alias, canonical]);
|
|
32
|
+
},
|
|
33
|
+
getCanonicalRows() {
|
|
34
|
+
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`);
|
|
35
|
+
},
|
|
36
|
+
countTagUsage(tag) {
|
|
37
|
+
return p.get('SELECT COUNT(*) as count FROM entries WHERE tags LIKE ?', [`%"${tag}"%`])?.count ?? 0;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
100
40
|
}
|
|
101
41
|
// ─── Status ─────────────────────────────────────────────────────
|
|
102
42
|
getStatus() {
|
|
103
|
-
const tableCount = (table) => (this.provider.get(`SELECT COUNT(*) as count FROM ${table}`) ?? {
|
|
104
|
-
count: 0,
|
|
105
|
-
}).count;
|
|
43
|
+
const tableCount = (table) => (this.provider.get(`SELECT COUNT(*) as count FROM ${table}`) ?? { count: 0 }).count;
|
|
106
44
|
const lastGroomed = this.provider.get('SELECT MAX(last_groomed_at) as ts FROM curator_entry_state WHERE last_groomed_at IS NOT NULL') ?? { ts: null };
|
|
107
45
|
return {
|
|
108
46
|
initialized: true,
|
|
109
|
-
tables: {
|
|
110
|
-
entry_state: tableCount('curator_entry_state'),
|
|
111
|
-
tag_canonical: tableCount('curator_tag_canonical'),
|
|
112
|
-
tag_alias: tableCount('curator_tag_alias'),
|
|
113
|
-
changelog: tableCount('curator_changelog'),
|
|
114
|
-
contradictions: tableCount('curator_contradictions'),
|
|
115
|
-
},
|
|
47
|
+
tables: { entry_state: tableCount('curator_entry_state'), tag_canonical: tableCount('curator_tag_canonical'), tag_alias: tableCount('curator_tag_alias'), changelog: tableCount('curator_changelog'), contradictions: tableCount('curator_contradictions') },
|
|
116
48
|
lastGroomedAt: lastGroomed.ts,
|
|
117
49
|
};
|
|
118
50
|
}
|
|
119
|
-
// ───
|
|
120
|
-
normalizeTag(tag) {
|
|
121
|
-
const lower = tag.toLowerCase().trim();
|
|
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 };
|
|
127
|
-
}
|
|
51
|
+
// ─── Tags (delegates to tag-manager) ──────────────────────────
|
|
52
|
+
normalizeTag(tag) { return normalizeTagPure(tag, this.tagStore); }
|
|
128
53
|
normalizeTags(entryId) {
|
|
129
54
|
const entry = this.vault.get(entryId);
|
|
130
55
|
if (!entry)
|
|
131
56
|
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
|
-
}
|
|
57
|
+
const { results, dedupedTags, changed } = normalizeAndDedup(entry.tags, this.tagStore);
|
|
142
58
|
if (changed) {
|
|
143
|
-
|
|
144
|
-
this.provider.run('UPDATE entries SET tags = ?, updated_at = unixepoch() WHERE id = ?', [
|
|
145
|
-
JSON.stringify(dedupedTags),
|
|
146
|
-
entryId,
|
|
147
|
-
]);
|
|
59
|
+
this.provider.run('UPDATE entries SET tags = ?, updated_at = unixepoch() WHERE id = ?', [JSON.stringify(dedupedTags), entryId]);
|
|
148
60
|
this.logChange('normalize_tags', entryId, JSON.stringify(entry.tags), JSON.stringify(dedupedTags), 'Tag normalization');
|
|
149
61
|
}
|
|
150
62
|
return results;
|
|
151
63
|
}
|
|
152
|
-
addTagAlias(alias, canonical) {
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
]);
|
|
162
|
-
}
|
|
163
|
-
getCanonicalTags() {
|
|
164
|
-
const rows = this.provider.all(`SELECT c.tag, c.description,
|
|
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;
|
|
178
|
-
}
|
|
179
|
-
// ─── Duplicate Detection ────────────────────────────────────────
|
|
64
|
+
addTagAlias(alias, canonical) { addTagAliasPure(alias, canonical, this.tagStore); }
|
|
65
|
+
getCanonicalTags() { return getCanonicalTagsPure(this.tagStore); }
|
|
66
|
+
// ─── Duplicates (delegates to duplicate-detector) ─────────────
|
|
180
67
|
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;
|
|
68
|
+
return detectDuplicatesPure(this.vault.list({ limit: 100000 }), entryId, threshold);
|
|
222
69
|
}
|
|
223
|
-
// ─── Contradictions
|
|
70
|
+
// ─── Contradictions (delegates to contradiction-detector) ─────
|
|
224
71
|
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;
|
|
72
|
+
const searchFn = (title) => this.vault.search(title, { type: 'pattern', limit: 20 }).map((r) => r.entry);
|
|
73
|
+
return this.persistContradictions(findContradictions(this.vault.list({ limit: 100000 }), threshold, searchFn));
|
|
261
74
|
}
|
|
262
75
|
getContradictions(status) {
|
|
263
|
-
const query = status
|
|
264
|
-
|
|
265
|
-
: 'SELECT * FROM curator_contradictions ORDER BY similarity DESC';
|
|
266
|
-
const rows = this.provider.all(query, status ? [status] : undefined);
|
|
267
|
-
return rows.map((r) => this.rowToContradiction(r));
|
|
76
|
+
const query = status ? 'SELECT * FROM curator_contradictions WHERE status = ? ORDER BY similarity DESC' : 'SELECT * FROM curator_contradictions ORDER BY similarity DESC';
|
|
77
|
+
return this.provider.all(query, status ? [status] : undefined).map((r) => this.rowToContradiction(r));
|
|
268
78
|
}
|
|
269
79
|
resolveContradiction(id, resolution) {
|
|
270
80
|
this.provider.run('UPDATE curator_contradictions SET status = ?, resolved_at = unixepoch() WHERE id = ?', [resolution, id]);
|
|
@@ -272,73 +82,27 @@ export class Curator {
|
|
|
272
82
|
return row ? this.rowToContradiction(row) : null;
|
|
273
83
|
}
|
|
274
84
|
async detectContradictionsHybrid(threshold) {
|
|
275
|
-
const
|
|
276
|
-
|
|
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
|
-
}
|
|
309
|
-
return {
|
|
310
|
-
contradictions: detected,
|
|
311
|
-
method: 'tfidf-only',
|
|
312
|
-
};
|
|
85
|
+
const searchFn = (title) => this.vault.search(title, { type: 'pattern', limit: 20 }).map((r) => r.entry);
|
|
86
|
+
return { contradictions: this.persistContradictions(findContradictions(this.vault.list({ limit: 100000 }), threshold, searchFn)), method: 'tfidf-only' };
|
|
313
87
|
}
|
|
314
|
-
// ─── Grooming
|
|
88
|
+
// ─── Grooming ─────────────────────────────────────────────────
|
|
315
89
|
groomEntry(entryId) {
|
|
316
90
|
const entry = this.vault.get(entryId);
|
|
317
91
|
if (!entry)
|
|
318
92
|
return null;
|
|
319
93
|
const tagsNormalized = this.normalizeTags(entryId);
|
|
320
|
-
// Check staleness based on entry's updated_at timestamp
|
|
321
94
|
const row = this.provider.get('SELECT updated_at FROM entries WHERE id = ?', [entryId]);
|
|
322
95
|
const now = Math.floor(Date.now() / 1000);
|
|
323
96
|
const stale = row ? now - row.updated_at > DEFAULT_STALE_DAYS * 86400 : false;
|
|
324
97
|
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]);
|
|
98
|
+
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
99
|
this.logChange('groom', entryId, null, `status=${status}`, 'Routine grooming');
|
|
330
|
-
return {
|
|
331
|
-
entryId,
|
|
332
|
-
tagsNormalized,
|
|
333
|
-
stale,
|
|
334
|
-
lastGroomedAt: now,
|
|
335
|
-
};
|
|
100
|
+
return { entryId, tagsNormalized, stale, lastGroomedAt: now };
|
|
336
101
|
}
|
|
337
102
|
groomAll() {
|
|
338
103
|
const start = Date.now();
|
|
339
104
|
const entries = this.vault.list({ limit: 100000 });
|
|
340
|
-
let tagsNormalized = 0;
|
|
341
|
-
let staleCount = 0;
|
|
105
|
+
let tagsNormalized = 0, staleCount = 0;
|
|
342
106
|
for (const entry of entries) {
|
|
343
107
|
const result = this.groomEntry(entry.id);
|
|
344
108
|
if (result) {
|
|
@@ -347,41 +111,27 @@ export class Curator {
|
|
|
347
111
|
staleCount++;
|
|
348
112
|
}
|
|
349
113
|
}
|
|
350
|
-
return {
|
|
351
|
-
totalEntries: entries.length,
|
|
352
|
-
groomedCount: entries.length,
|
|
353
|
-
tagsNormalized,
|
|
354
|
-
staleCount,
|
|
355
|
-
durationMs: Date.now() - start,
|
|
356
|
-
};
|
|
114
|
+
return { totalEntries: entries.length, groomedCount: entries.length, tagsNormalized, staleCount, durationMs: Date.now() - start };
|
|
357
115
|
}
|
|
358
|
-
// ─── Consolidation
|
|
116
|
+
// ─── Consolidation ───────────────────────────────────────────
|
|
359
117
|
consolidate(options) {
|
|
360
118
|
const start = Date.now();
|
|
361
119
|
const dryRun = options?.dryRun ?? true;
|
|
362
120
|
const staleDaysThreshold = options?.staleDaysThreshold ?? DEFAULT_STALE_DAYS;
|
|
363
121
|
const duplicateThreshold = options?.duplicateThreshold ?? DEFAULT_DUPLICATE_THRESHOLD;
|
|
364
122
|
const contradictionThreshold = options?.contradictionThreshold ?? DEFAULT_CONTRADICTION_THRESHOLD;
|
|
365
|
-
// Detect duplicates
|
|
366
123
|
const duplicates = this.detectDuplicates(undefined, duplicateThreshold);
|
|
367
|
-
// Detect stale entries
|
|
368
124
|
const now = Math.floor(Date.now() / 1000);
|
|
369
|
-
const
|
|
370
|
-
const staleRows = this.provider.all('SELECT id FROM entries WHERE updated_at < ?', [staleThreshold]);
|
|
125
|
+
const staleRows = this.provider.all('SELECT id FROM entries WHERE updated_at < ?', [now - staleDaysThreshold * 86400]);
|
|
371
126
|
const staleEntries = staleRows.map((r) => r.id);
|
|
372
|
-
// Detect contradictions
|
|
373
127
|
const contradictions = this.detectContradictions(contradictionThreshold);
|
|
374
128
|
let mutations = 0;
|
|
375
129
|
if (!dryRun) {
|
|
376
|
-
// Archive stale entries
|
|
377
130
|
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]);
|
|
131
|
+
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
132
|
this.logChange('archive', entryId, 'active', 'archived', 'Stale entry archived during consolidation');
|
|
382
133
|
mutations++;
|
|
383
134
|
}
|
|
384
|
-
// Remove lower-similarity duplicates (keep the first entry, remove matches)
|
|
385
135
|
const removed = new Set();
|
|
386
136
|
for (const result of duplicates) {
|
|
387
137
|
for (const match of result.matches) {
|
|
@@ -394,118 +144,24 @@ export class Curator {
|
|
|
394
144
|
}
|
|
395
145
|
}
|
|
396
146
|
}
|
|
397
|
-
return {
|
|
398
|
-
dryRun,
|
|
399
|
-
duplicates,
|
|
400
|
-
staleEntries,
|
|
401
|
-
contradictions,
|
|
402
|
-
mutations,
|
|
403
|
-
durationMs: Date.now() - start,
|
|
404
|
-
};
|
|
147
|
+
return { dryRun, duplicates, staleEntries, contradictions, mutations, durationMs: Date.now() - start };
|
|
405
148
|
}
|
|
406
|
-
// ─── Changelog
|
|
149
|
+
// ─── Changelog ────────────────────────────────────────────────
|
|
407
150
|
getEntryHistory(entryId, limit) {
|
|
408
|
-
|
|
409
|
-
return rows.map((r) => this.rowToChangelog(r));
|
|
151
|
+
return this.provider.all('SELECT * FROM curator_changelog WHERE entry_id = ? ORDER BY created_at DESC, id DESC LIMIT ?', [entryId, limit ?? 50]).map((r) => this.rowToChangelog(r));
|
|
410
152
|
}
|
|
411
|
-
// ─── Health Audit
|
|
153
|
+
// ─── Health Audit (delegates to health-audit) ─────────────────
|
|
412
154
|
healthAudit() {
|
|
413
155
|
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,
|
|
156
|
+
const dataProvider = {
|
|
157
|
+
getStaleCount: (threshold) => (this.provider.get('SELECT COUNT(*) as count FROM entries WHERE updated_at < ?', [threshold]) ?? { count: 0 }).count,
|
|
158
|
+
getGroomedCount: () => (this.provider.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL') ?? { count: 0 }).count,
|
|
159
|
+
getDuplicates: () => this.detectDuplicates(),
|
|
160
|
+
getOpenContradictions: () => this.getContradictions('open'),
|
|
506
161
|
};
|
|
162
|
+
return computeHealthAudit(entries, dataProvider, DEFAULT_STALE_DAYS);
|
|
507
163
|
}
|
|
508
|
-
// ─── Entry History (Version Snapshots)
|
|
164
|
+
// ─── Entry History (Version Snapshots) ────────────────────────
|
|
509
165
|
recordSnapshot(entryId, changedBy, changeReason) {
|
|
510
166
|
const entry = this.vault.get(entryId);
|
|
511
167
|
if (!entry)
|
|
@@ -514,150 +170,59 @@ export class Curator {
|
|
|
514
170
|
return { recorded: true, historyId: Number(result.lastInsertRowid) };
|
|
515
171
|
}
|
|
516
172
|
getVersionHistory(entryId) {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
historyId: row.id,
|
|
520
|
-
entryId: row.entry_id,
|
|
521
|
-
snapshot: JSON.parse(row.snapshot),
|
|
522
|
-
changedBy: row.changed_by,
|
|
523
|
-
changeReason: row.change_reason ?? null,
|
|
524
|
-
createdAt: row.created_at,
|
|
173
|
+
return this.provider.all('SELECT * FROM curator_entry_history WHERE entry_id = ? ORDER BY created_at ASC, id ASC', [entryId]).map((row) => ({
|
|
174
|
+
historyId: row.id, entryId: row.entry_id, snapshot: JSON.parse(row.snapshot), changedBy: row.changed_by, changeReason: row.change_reason ?? null, createdAt: row.created_at,
|
|
525
175
|
}));
|
|
526
176
|
}
|
|
527
|
-
// ─── Queue Stats
|
|
177
|
+
// ─── Queue Stats ─────────────────────────────────────────────
|
|
528
178
|
getQueueStats() {
|
|
529
|
-
const
|
|
530
|
-
const
|
|
531
|
-
const
|
|
179
|
+
const p = this.provider;
|
|
180
|
+
const totalEntries = (p.get('SELECT COUNT(*) as count FROM entries') ?? { count: 0 }).count;
|
|
181
|
+
const groomedEntries = (p.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL') ?? { count: 0 }).count;
|
|
532
182
|
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;
|
|
183
|
+
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;
|
|
184
|
+
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
185
|
let avgDaysSinceGroom = 0;
|
|
538
186
|
if (groomedEntries > 0) {
|
|
539
|
-
const
|
|
540
|
-
const totalSeconds = sumRow.total ?? 0;
|
|
187
|
+
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
188
|
avgDaysSinceGroom = Math.round((totalSeconds / groomedEntries / 86400) * 100) / 100;
|
|
542
189
|
}
|
|
543
|
-
return {
|
|
544
|
-
totalEntries,
|
|
545
|
-
groomedEntries,
|
|
546
|
-
ungroomedEntries,
|
|
547
|
-
staleEntries,
|
|
548
|
-
freshEntries,
|
|
549
|
-
avgDaysSinceGroom,
|
|
550
|
-
};
|
|
190
|
+
return { totalEntries, groomedEntries, ungroomedEntries: totalEntries - groomedEntries, staleEntries, freshEntries, avgDaysSinceGroom };
|
|
551
191
|
}
|
|
552
|
-
// ─── Metadata Enrichment
|
|
192
|
+
// ─── Metadata Enrichment (delegates to metadata-enricher) ────
|
|
553
193
|
enrichMetadata(entryId) {
|
|
554
194
|
const entry = this.vault.get(entryId);
|
|
555
195
|
if (!entry)
|
|
556
196
|
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) {
|
|
197
|
+
const { changes, updates } = enrichEntryMetadata(entry);
|
|
198
|
+
if (changes.length === 0)
|
|
609
199
|
return { enriched: false, changes: [] };
|
|
610
|
-
}
|
|
611
|
-
// Apply updates
|
|
612
200
|
this.vault.update(entryId, updates);
|
|
613
|
-
// Record snapshot
|
|
614
201
|
this.recordSnapshot(entryId, 'curator', 'Metadata enrichment');
|
|
615
|
-
// Log change
|
|
616
202
|
this.logChange('enrich_metadata', entryId, JSON.stringify(changes.map((c) => c.field)), JSON.stringify(changes.map((c) => c.after)), 'Rule-based metadata enrichment');
|
|
617
203
|
return { enriched: true, changes };
|
|
618
204
|
}
|
|
619
|
-
// ─── Private Helpers
|
|
620
|
-
|
|
621
|
-
const
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
205
|
+
// ─── Private Helpers ──────────────────────────────────────────
|
|
206
|
+
persistContradictions(candidates) {
|
|
207
|
+
const detected = [];
|
|
208
|
+
for (const c of candidates) {
|
|
209
|
+
const result = this.provider.run('INSERT OR IGNORE INTO curator_contradictions (pattern_id, antipattern_id, similarity) VALUES (?, ?, ?)', [c.patternId, c.antipatternId, c.similarity]);
|
|
210
|
+
if (result.changes > 0) {
|
|
211
|
+
const row = this.provider.get('SELECT * FROM curator_contradictions WHERE pattern_id = ? AND antipattern_id = ?', [c.patternId, c.antipatternId]);
|
|
212
|
+
if (row)
|
|
213
|
+
detected.push(this.rowToContradiction(row));
|
|
628
214
|
}
|
|
629
215
|
}
|
|
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;
|
|
216
|
+
return detected;
|
|
636
217
|
}
|
|
637
218
|
logChange(action, entryId, beforeValue, afterValue, reason) {
|
|
638
219
|
this.provider.run('INSERT INTO curator_changelog (action, entry_id, before_value, after_value, reason) VALUES (?, ?, ?, ?, ?)', [action, entryId, beforeValue, afterValue, reason]);
|
|
639
220
|
}
|
|
640
221
|
rowToContradiction(row) {
|
|
641
|
-
return {
|
|
642
|
-
id: row.id,
|
|
643
|
-
patternId: row.pattern_id,
|
|
644
|
-
antipatternId: row.antipattern_id,
|
|
645
|
-
similarity: row.similarity,
|
|
646
|
-
status: row.status,
|
|
647
|
-
createdAt: row.created_at,
|
|
648
|
-
resolvedAt: row.resolved_at ?? null,
|
|
649
|
-
};
|
|
222
|
+
return { id: row.id, patternId: row.pattern_id, antipatternId: row.antipattern_id, similarity: row.similarity, status: row.status, createdAt: row.created_at, resolvedAt: row.resolved_at ?? null };
|
|
650
223
|
}
|
|
651
224
|
rowToChangelog(row) {
|
|
652
|
-
return {
|
|
653
|
-
id: row.id,
|
|
654
|
-
action: row.action,
|
|
655
|
-
entryId: row.entry_id,
|
|
656
|
-
beforeValue: row.before_value ?? null,
|
|
657
|
-
afterValue: row.after_value ?? null,
|
|
658
|
-
reason: row.reason,
|
|
659
|
-
createdAt: row.created_at,
|
|
660
|
-
};
|
|
225
|
+
return { id: row.id, action: row.action, entryId: row.entry_id, beforeValue: row.before_value ?? null, afterValue: row.after_value ?? null, reason: row.reason, createdAt: row.created_at };
|
|
661
226
|
}
|
|
662
227
|
}
|
|
663
228
|
//# sourceMappingURL=curator.js.map
|