@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.
Files changed (744) hide show
  1. package/data/flows/build.flow.yaml +8 -9
  2. package/data/flows/deliver.flow.yaml +9 -10
  3. package/data/flows/design.flow.yaml +3 -4
  4. package/data/flows/enhance.flow.yaml +5 -6
  5. package/data/flows/explore.flow.yaml +3 -4
  6. package/data/flows/fix.flow.yaml +5 -6
  7. package/data/flows/plan.flow.yaml +4 -5
  8. package/data/flows/review.flow.yaml +3 -4
  9. package/dist/brain/intelligence.d.ts +27 -0
  10. package/dist/brain/intelligence.d.ts.map +1 -1
  11. package/dist/brain/intelligence.js +160 -14
  12. package/dist/brain/intelligence.js.map +1 -1
  13. package/dist/brain/learning-radar.d.ts +4 -0
  14. package/dist/brain/learning-radar.d.ts.map +1 -1
  15. package/dist/brain/learning-radar.js +20 -1
  16. package/dist/brain/learning-radar.js.map +1 -1
  17. package/dist/brain/strength-scorer.d.ts +31 -0
  18. package/dist/brain/strength-scorer.d.ts.map +1 -0
  19. package/dist/brain/strength-scorer.js +264 -0
  20. package/dist/brain/strength-scorer.js.map +1 -0
  21. package/dist/chat/agent-loop.d.ts.map +1 -1
  22. package/dist/chat/agent-loop.js +2 -0
  23. package/dist/chat/agent-loop.js.map +1 -1
  24. package/dist/chat/notifications.d.ts.map +1 -1
  25. package/dist/chat/notifications.js +2 -0
  26. package/dist/chat/notifications.js.map +1 -1
  27. package/dist/claudemd/compose.js +1 -1
  28. package/dist/claudemd/compose.js.map +1 -1
  29. package/dist/control/intent-router.d.ts.map +1 -1
  30. package/dist/control/intent-router.js +12 -4
  31. package/dist/control/intent-router.js.map +1 -1
  32. package/dist/curator/contradiction-detector.d.ts +27 -0
  33. package/dist/curator/contradiction-detector.d.ts.map +1 -0
  34. package/dist/curator/contradiction-detector.js +62 -0
  35. package/dist/curator/contradiction-detector.js.map +1 -0
  36. package/dist/curator/curator.d.ts +3 -4
  37. package/dist/curator/curator.d.ts.map +1 -1
  38. package/dist/curator/curator.js +94 -453
  39. package/dist/curator/curator.js.map +1 -1
  40. package/dist/curator/duplicate-detector.d.ts +14 -0
  41. package/dist/curator/duplicate-detector.d.ts.map +1 -0
  42. package/dist/curator/duplicate-detector.js +77 -0
  43. package/dist/curator/duplicate-detector.js.map +1 -0
  44. package/dist/curator/health-audit.d.ts +15 -0
  45. package/dist/curator/health-audit.d.ts.map +1 -0
  46. package/dist/curator/health-audit.js +97 -0
  47. package/dist/curator/health-audit.js.map +1 -0
  48. package/dist/curator/metadata-enricher.d.ts +17 -0
  49. package/dist/curator/metadata-enricher.d.ts.map +1 -0
  50. package/dist/curator/metadata-enricher.js +60 -0
  51. package/dist/curator/metadata-enricher.js.map +1 -0
  52. package/dist/curator/schema.d.ts +7 -0
  53. package/dist/curator/schema.d.ts.map +1 -0
  54. package/dist/curator/schema.js +62 -0
  55. package/dist/curator/schema.js.map +1 -0
  56. package/dist/curator/tag-manager.d.ts +36 -0
  57. package/dist/curator/tag-manager.d.ts.map +1 -0
  58. package/dist/curator/tag-manager.js +78 -0
  59. package/dist/curator/tag-manager.js.map +1 -0
  60. package/dist/engine/bin/soleri-engine.js +24 -3
  61. package/dist/engine/bin/soleri-engine.js.map +1 -1
  62. package/dist/engine/core-ops.d.ts.map +1 -1
  63. package/dist/engine/core-ops.js +23 -8
  64. package/dist/engine/core-ops.js.map +1 -1
  65. package/dist/engine/module-manifest.d.ts.map +1 -1
  66. package/dist/engine/module-manifest.js +42 -2
  67. package/dist/engine/module-manifest.js.map +1 -1
  68. package/dist/engine/register-engine.d.ts.map +1 -1
  69. package/dist/engine/register-engine.js +50 -2
  70. package/dist/engine/register-engine.js.map +1 -1
  71. package/dist/errors/retry.d.ts.map +1 -1
  72. package/dist/errors/retry.js +2 -0
  73. package/dist/errors/retry.js.map +1 -1
  74. package/dist/facades/types.d.ts +1 -1
  75. package/dist/flows/chain-types.d.ts +18 -18
  76. package/dist/flows/gate-evaluator.d.ts.map +1 -1
  77. package/dist/flows/gate-evaluator.js +22 -0
  78. package/dist/flows/gate-evaluator.js.map +1 -1
  79. package/dist/flows/types.d.ts +157 -28
  80. package/dist/flows/types.d.ts.map +1 -1
  81. package/dist/flows/types.js +4 -0
  82. package/dist/flows/types.js.map +1 -1
  83. package/dist/index.d.ts +10 -2
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +9 -1
  86. package/dist/index.js.map +1 -1
  87. package/dist/intake/intake-pipeline.d.ts.map +1 -1
  88. package/dist/intake/intake-pipeline.js +1 -0
  89. package/dist/intake/intake-pipeline.js.map +1 -1
  90. package/dist/intake/text-ingester.d.ts.map +1 -1
  91. package/dist/intake/text-ingester.js +2 -0
  92. package/dist/intake/text-ingester.js.map +1 -1
  93. package/dist/llm/key-pool.d.ts +1 -1
  94. package/dist/llm/key-pool.d.ts.map +1 -1
  95. package/dist/llm/key-pool.js +3 -4
  96. package/dist/llm/key-pool.js.map +1 -1
  97. package/dist/llm/utils.d.ts.map +1 -1
  98. package/dist/llm/utils.js +2 -0
  99. package/dist/llm/utils.js.map +1 -1
  100. package/dist/migrations/migration-runner.test-helpers.d.ts +13 -0
  101. package/dist/migrations/migration-runner.test-helpers.d.ts.map +1 -0
  102. package/dist/migrations/migration-runner.test-helpers.js +47 -0
  103. package/dist/migrations/migration-runner.test-helpers.js.map +1 -0
  104. package/dist/operator/operator-profile.d.ts +44 -0
  105. package/dist/operator/operator-profile.d.ts.map +1 -0
  106. package/dist/operator/operator-profile.js +383 -0
  107. package/dist/operator/operator-profile.js.map +1 -0
  108. package/dist/operator/operator-signals.d.ts +45 -0
  109. package/dist/operator/operator-signals.d.ts.map +1 -0
  110. package/dist/operator/operator-signals.js +228 -0
  111. package/dist/operator/operator-signals.js.map +1 -0
  112. package/dist/operator/operator-types.d.ts +360 -0
  113. package/dist/operator/operator-types.d.ts.map +1 -0
  114. package/dist/operator/operator-types.js +24 -0
  115. package/dist/operator/operator-types.js.map +1 -0
  116. package/dist/packs/types.d.ts +27 -27
  117. package/dist/paths.d.ts +40 -0
  118. package/dist/paths.d.ts.map +1 -0
  119. package/dist/paths.js +98 -0
  120. package/dist/paths.js.map +1 -0
  121. package/dist/persistence/index.d.ts +1 -1
  122. package/dist/persistence/index.d.ts.map +1 -1
  123. package/dist/persistence/index.js +1 -1
  124. package/dist/persistence/index.js.map +1 -1
  125. package/dist/persistence/sqlite-provider.d.ts +2 -0
  126. package/dist/persistence/sqlite-provider.d.ts.map +1 -1
  127. package/dist/persistence/sqlite-provider.js +8 -5
  128. package/dist/persistence/sqlite-provider.js.map +1 -1
  129. package/dist/planning/evidence-collector.d.ts +13 -1
  130. package/dist/planning/evidence-collector.d.ts.map +1 -1
  131. package/dist/planning/evidence-collector.js +33 -0
  132. package/dist/planning/evidence-collector.js.map +1 -1
  133. package/dist/planning/gap-analysis.d.ts +5 -4
  134. package/dist/planning/gap-analysis.d.ts.map +1 -1
  135. package/dist/planning/gap-analysis.js +7 -341
  136. package/dist/planning/gap-analysis.js.map +1 -1
  137. package/dist/planning/gap-passes.d.ts +19 -0
  138. package/dist/planning/gap-passes.d.ts.map +1 -0
  139. package/dist/planning/gap-passes.js +174 -0
  140. package/dist/planning/gap-passes.js.map +1 -0
  141. package/dist/planning/gap-patterns.d.ts +29 -0
  142. package/dist/planning/gap-patterns.d.ts.map +1 -0
  143. package/dist/planning/gap-patterns.js +175 -0
  144. package/dist/planning/gap-patterns.js.map +1 -0
  145. package/dist/planning/gap-types.d.ts +1 -1
  146. package/dist/planning/gap-types.d.ts.map +1 -1
  147. package/dist/planning/gap-types.js +1 -0
  148. package/dist/planning/gap-types.js.map +1 -1
  149. package/dist/planning/github-projection.d.ts +122 -0
  150. package/dist/planning/github-projection.d.ts.map +1 -0
  151. package/dist/planning/github-projection.js +313 -0
  152. package/dist/planning/github-projection.js.map +1 -0
  153. package/dist/planning/impact-analyzer.d.ts +26 -0
  154. package/dist/planning/impact-analyzer.d.ts.map +1 -0
  155. package/dist/planning/impact-analyzer.js +201 -0
  156. package/dist/planning/impact-analyzer.js.map +1 -0
  157. package/dist/planning/plan-lifecycle.d.ts +136 -0
  158. package/dist/planning/plan-lifecycle.d.ts.map +1 -0
  159. package/dist/planning/plan-lifecycle.js +309 -0
  160. package/dist/planning/plan-lifecycle.js.map +1 -0
  161. package/dist/planning/planner-types.d.ts +202 -0
  162. package/dist/planning/planner-types.d.ts.map +1 -0
  163. package/dist/planning/planner-types.js +6 -0
  164. package/dist/planning/planner-types.js.map +1 -0
  165. package/dist/planning/planner.d.ts +31 -383
  166. package/dist/planning/planner.d.ts.map +1 -1
  167. package/dist/planning/planner.js +151 -832
  168. package/dist/planning/planner.js.map +1 -1
  169. package/dist/planning/rationalization-detector.d.ts +32 -0
  170. package/dist/planning/rationalization-detector.d.ts.map +1 -0
  171. package/dist/planning/rationalization-detector.js +89 -0
  172. package/dist/planning/rationalization-detector.js.map +1 -0
  173. package/dist/planning/reconciliation-engine.d.ts +47 -0
  174. package/dist/planning/reconciliation-engine.d.ts.map +1 -0
  175. package/dist/planning/reconciliation-engine.js +128 -0
  176. package/dist/planning/reconciliation-engine.js.map +1 -0
  177. package/dist/planning/task-verifier.d.ts +85 -0
  178. package/dist/planning/task-verifier.d.ts.map +1 -0
  179. package/dist/planning/task-verifier.js +235 -0
  180. package/dist/planning/task-verifier.js.map +1 -0
  181. package/dist/plugins/types.d.ts +4 -4
  182. package/dist/runtime/admin-ops.d.ts +2 -2
  183. package/dist/runtime/admin-ops.d.ts.map +1 -1
  184. package/dist/runtime/admin-ops.js +44 -17
  185. package/dist/runtime/admin-ops.js.map +1 -1
  186. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  187. package/dist/runtime/admin-setup-ops.js +22 -46
  188. package/dist/runtime/admin-setup-ops.js.map +1 -1
  189. package/dist/runtime/archive-ops.d.ts +10 -0
  190. package/dist/runtime/archive-ops.d.ts.map +1 -0
  191. package/dist/runtime/archive-ops.js +310 -0
  192. package/dist/runtime/archive-ops.js.map +1 -0
  193. package/dist/runtime/branching-ops.d.ts +12 -0
  194. package/dist/runtime/branching-ops.d.ts.map +1 -0
  195. package/dist/runtime/branching-ops.js +100 -0
  196. package/dist/runtime/branching-ops.js.map +1 -0
  197. package/dist/runtime/capture-ops.d.ts.map +1 -1
  198. package/dist/runtime/capture-ops.js +42 -7
  199. package/dist/runtime/capture-ops.js.map +1 -1
  200. package/dist/runtime/claude-md-helpers.js +1 -1
  201. package/dist/runtime/claude-md-helpers.js.map +1 -1
  202. package/dist/runtime/context-health.d.ts +31 -0
  203. package/dist/runtime/context-health.d.ts.map +1 -0
  204. package/dist/runtime/context-health.js +57 -0
  205. package/dist/runtime/context-health.js.map +1 -0
  206. package/dist/runtime/facades/archive-facade.d.ts +10 -0
  207. package/dist/runtime/facades/archive-facade.d.ts.map +1 -0
  208. package/dist/runtime/facades/archive-facade.js +11 -0
  209. package/dist/runtime/facades/archive-facade.js.map +1 -0
  210. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  211. package/dist/runtime/facades/brain-facade.js +2 -0
  212. package/dist/runtime/facades/brain-facade.js.map +1 -1
  213. package/dist/runtime/facades/branching-facade.d.ts +7 -0
  214. package/dist/runtime/facades/branching-facade.d.ts.map +1 -0
  215. package/dist/runtime/facades/branching-facade.js +8 -0
  216. package/dist/runtime/facades/branching-facade.js.map +1 -0
  217. package/dist/runtime/facades/chat-facade.d.ts +7 -0
  218. package/dist/runtime/facades/chat-facade.d.ts.map +1 -1
  219. package/dist/runtime/facades/chat-facade.js +15 -800
  220. package/dist/runtime/facades/chat-facade.js.map +1 -1
  221. package/dist/runtime/facades/chat-service-ops.d.ts +9 -0
  222. package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -0
  223. package/dist/runtime/facades/chat-service-ops.js +332 -0
  224. package/dist/runtime/facades/chat-service-ops.js.map +1 -0
  225. package/dist/runtime/facades/chat-session-ops.d.ts +8 -0
  226. package/dist/runtime/facades/chat-session-ops.d.ts.map +1 -0
  227. package/dist/runtime/facades/chat-session-ops.js +136 -0
  228. package/dist/runtime/facades/chat-session-ops.js.map +1 -0
  229. package/dist/runtime/facades/chat-state.d.ts +31 -0
  230. package/dist/runtime/facades/chat-state.d.ts.map +1 -0
  231. package/dist/runtime/facades/chat-state.js +32 -0
  232. package/dist/runtime/facades/chat-state.js.map +1 -0
  233. package/dist/runtime/facades/chat-transport-ops.d.ts +9 -0
  234. package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -0
  235. package/dist/runtime/facades/chat-transport-ops.js +337 -0
  236. package/dist/runtime/facades/chat-transport-ops.js.map +1 -0
  237. package/dist/runtime/facades/control-facade.d.ts.map +1 -1
  238. package/dist/runtime/facades/control-facade.js +4 -1
  239. package/dist/runtime/facades/control-facade.js.map +1 -1
  240. package/dist/runtime/facades/index.d.ts.map +1 -1
  241. package/dist/runtime/facades/index.js +48 -0
  242. package/dist/runtime/facades/index.js.map +1 -1
  243. package/dist/runtime/facades/intake-facade.d.ts +9 -0
  244. package/dist/runtime/facades/intake-facade.d.ts.map +1 -0
  245. package/dist/runtime/facades/intake-facade.js +11 -0
  246. package/dist/runtime/facades/intake-facade.js.map +1 -0
  247. package/dist/runtime/facades/links-facade.d.ts +9 -0
  248. package/dist/runtime/facades/links-facade.d.ts.map +1 -0
  249. package/dist/runtime/facades/links-facade.js +10 -0
  250. package/dist/runtime/facades/links-facade.js.map +1 -0
  251. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  252. package/dist/runtime/facades/memory-facade.js +75 -6
  253. package/dist/runtime/facades/memory-facade.js.map +1 -1
  254. package/dist/runtime/facades/operator-facade.d.ts +8 -0
  255. package/dist/runtime/facades/operator-facade.d.ts.map +1 -0
  256. package/dist/runtime/facades/operator-facade.js +220 -0
  257. package/dist/runtime/facades/operator-facade.js.map +1 -0
  258. package/dist/runtime/facades/orchestrate-facade.js +3 -3
  259. package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
  260. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  261. package/dist/runtime/facades/plan-facade.js +42 -6
  262. package/dist/runtime/facades/plan-facade.js.map +1 -1
  263. package/dist/runtime/facades/review-facade.d.ts +7 -0
  264. package/dist/runtime/facades/review-facade.d.ts.map +1 -0
  265. package/dist/runtime/facades/review-facade.js +8 -0
  266. package/dist/runtime/facades/review-facade.js.map +1 -0
  267. package/dist/runtime/facades/sync-facade.d.ts +7 -0
  268. package/dist/runtime/facades/sync-facade.d.ts.map +1 -0
  269. package/dist/runtime/facades/sync-facade.js +8 -0
  270. package/dist/runtime/facades/sync-facade.js.map +1 -0
  271. package/dist/runtime/facades/tier-facade.d.ts +7 -0
  272. package/dist/runtime/facades/tier-facade.d.ts.map +1 -0
  273. package/dist/runtime/facades/tier-facade.js +8 -0
  274. package/dist/runtime/facades/tier-facade.js.map +1 -0
  275. package/dist/runtime/facades/vault-facade.d.ts +12 -1
  276. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  277. package/dist/runtime/facades/vault-facade.js +55 -251
  278. package/dist/runtime/facades/vault-facade.js.map +1 -1
  279. package/dist/runtime/github-integration.d.ts +49 -0
  280. package/dist/runtime/github-integration.d.ts.map +1 -0
  281. package/dist/runtime/github-integration.js +120 -0
  282. package/dist/runtime/github-integration.js.map +1 -0
  283. package/dist/runtime/grading-ops.js +1 -1
  284. package/dist/runtime/grading-ops.js.map +1 -1
  285. package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
  286. package/dist/runtime/memory-extra-ops.js +6 -2
  287. package/dist/runtime/memory-extra-ops.js.map +1 -1
  288. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  289. package/dist/runtime/orchestrate-ops.js +386 -37
  290. package/dist/runtime/orchestrate-ops.js.map +1 -1
  291. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  292. package/dist/runtime/planning-extra-ops.js +69 -4
  293. package/dist/runtime/planning-extra-ops.js.map +1 -1
  294. package/dist/runtime/review-ops.d.ts +10 -0
  295. package/dist/runtime/review-ops.d.ts.map +1 -0
  296. package/dist/runtime/review-ops.js +97 -0
  297. package/dist/runtime/review-ops.js.map +1 -0
  298. package/dist/runtime/runtime.d.ts.map +1 -1
  299. package/dist/runtime/runtime.js +29 -12
  300. package/dist/runtime/runtime.js.map +1 -1
  301. package/dist/runtime/session-briefing.d.ts +3 -0
  302. package/dist/runtime/session-briefing.d.ts.map +1 -1
  303. package/dist/runtime/session-briefing.js +72 -1
  304. package/dist/runtime/session-briefing.js.map +1 -1
  305. package/dist/runtime/sync-ops.d.ts +12 -0
  306. package/dist/runtime/sync-ops.d.ts.map +1 -0
  307. package/dist/runtime/sync-ops.js +288 -0
  308. package/dist/runtime/sync-ops.js.map +1 -0
  309. package/dist/runtime/tier-ops.d.ts +13 -0
  310. package/dist/runtime/tier-ops.d.ts.map +1 -0
  311. package/dist/runtime/tier-ops.js +110 -0
  312. package/dist/runtime/tier-ops.js.map +1 -0
  313. package/dist/runtime/types.d.ts +10 -4
  314. package/dist/runtime/types.d.ts.map +1 -1
  315. package/dist/runtime/vault-extra-ops.d.ts +5 -4
  316. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  317. package/dist/runtime/vault-extra-ops.js +5 -300
  318. package/dist/runtime/vault-extra-ops.js.map +1 -1
  319. package/dist/runtime/vault-sharing-ops.d.ts +4 -4
  320. package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
  321. package/dist/runtime/vault-sharing-ops.js +5 -300
  322. package/dist/runtime/vault-sharing-ops.js.map +1 -1
  323. package/dist/skills/sync-skills.d.ts +27 -0
  324. package/dist/skills/sync-skills.d.ts.map +1 -0
  325. package/dist/skills/sync-skills.js +81 -0
  326. package/dist/skills/sync-skills.js.map +1 -0
  327. package/dist/update-check.d.ts +14 -0
  328. package/dist/update-check.d.ts.map +1 -0
  329. package/dist/update-check.js +96 -0
  330. package/dist/update-check.js.map +1 -0
  331. package/dist/vault/linking.d.ts +10 -12
  332. package/dist/vault/linking.d.ts.map +1 -1
  333. package/dist/vault/linking.js +140 -161
  334. package/dist/vault/linking.js.map +1 -1
  335. package/dist/vault/vault-entries.d.ts +69 -0
  336. package/dist/vault/vault-entries.d.ts.map +1 -0
  337. package/dist/vault/vault-entries.js +299 -0
  338. package/dist/vault/vault-entries.js.map +1 -0
  339. package/dist/vault/vault-interfaces.d.ts +153 -0
  340. package/dist/vault/vault-interfaces.d.ts.map +1 -0
  341. package/dist/vault/vault-interfaces.js +2 -0
  342. package/dist/vault/vault-interfaces.js.map +1 -0
  343. package/dist/vault/vault-maintenance.d.ts +40 -0
  344. package/dist/vault/vault-maintenance.d.ts.map +1 -0
  345. package/dist/vault/vault-maintenance.js +146 -0
  346. package/dist/vault/vault-maintenance.js.map +1 -0
  347. package/dist/vault/vault-markdown-sync.d.ts +22 -0
  348. package/dist/vault/vault-markdown-sync.d.ts.map +1 -0
  349. package/dist/vault/vault-markdown-sync.js +143 -0
  350. package/dist/vault/vault-markdown-sync.js.map +1 -0
  351. package/dist/vault/vault-memories.d.ts +61 -0
  352. package/dist/vault/vault-memories.d.ts.map +1 -0
  353. package/dist/vault/vault-memories.js +242 -0
  354. package/dist/vault/vault-memories.js.map +1 -0
  355. package/dist/vault/vault-schema.d.ts +9 -0
  356. package/dist/vault/vault-schema.d.ts.map +1 -0
  357. package/dist/vault/vault-schema.js +205 -0
  358. package/dist/vault/vault-schema.js.map +1 -0
  359. package/dist/vault/vault.d.ts +29 -81
  360. package/dist/vault/vault.d.ts.map +1 -1
  361. package/dist/vault/vault.js +82 -931
  362. package/dist/vault/vault.js.map +1 -1
  363. package/package.json +7 -7
  364. package/src/agency/agency-manager.test.ts +620 -0
  365. package/src/agency/default-rules.test.ts +236 -0
  366. package/src/{__tests__ → brain}/brain-intelligence.test.ts +37 -14
  367. package/src/{__tests__ → brain}/brain.test.ts +1 -1
  368. package/src/brain/intelligence.ts +196 -15
  369. package/src/brain/learning-radar.ts +22 -1
  370. package/src/{__tests__ → brain}/second-brain-features.test.ts +4 -4
  371. package/src/{__tests__ → brain}/session-lifecycle.test.ts +2 -2
  372. package/src/capabilities/chain-mapping.test.ts +66 -0
  373. package/src/capabilities/registry.test.ts +359 -0
  374. package/src/chat/agent-loop.test.ts +384 -0
  375. package/src/chat/agent-loop.ts +2 -0
  376. package/src/{__tests__ → chat}/chat-differentiators.test.ts +3 -3
  377. package/src/{__tests__ → chat}/chat-enhanced.test.ts +4 -4
  378. package/src/{__tests__ → chat}/chat-transport.test.ts +6 -6
  379. package/src/chat/mcp-bridge.test.ts +178 -0
  380. package/src/chat/notifications.ts +2 -0
  381. package/src/chat/output-compressor.test.ts +164 -0
  382. package/src/claudemd/compose.test.ts +178 -0
  383. package/src/claudemd/compose.ts +1 -1
  384. package/src/claudemd/inject.test.ts +201 -0
  385. package/src/context/context-engine.test.ts +506 -0
  386. package/src/control/identity-manager.test.ts +305 -0
  387. package/src/control/intent-router.test.ts +360 -0
  388. package/src/control/intent-router.ts +13 -4
  389. package/src/curator/classifier.test.ts +110 -0
  390. package/src/curator/contradiction-detector.test.ts +205 -0
  391. package/src/curator/contradiction-detector.ts +87 -0
  392. package/src/{__tests__ → curator}/curator-pipeline-e2e.test.ts +10 -10
  393. package/src/{__tests__ → curator}/curator.test.ts +77 -1
  394. package/src/curator/curator.ts +160 -600
  395. package/src/curator/duplicate-detector.test.ts +245 -0
  396. package/src/curator/duplicate-detector.ts +103 -0
  397. package/src/curator/health-audit.ts +126 -0
  398. package/src/curator/metadata-enricher.ts +84 -0
  399. package/src/curator/quality-gate.test.ts +175 -0
  400. package/src/curator/schema.ts +65 -0
  401. package/src/curator/tag-manager.test.ts +173 -0
  402. package/src/curator/tag-manager.ts +109 -0
  403. package/src/domain-packs/inject-rules.test.ts +117 -0
  404. package/src/domain-packs/knowledge-installer.test.ts +163 -0
  405. package/src/domain-packs/loader.test.ts +86 -0
  406. package/src/domain-packs/pack-runtime.test.ts +140 -0
  407. package/src/domain-packs/skills-installer.test.ts +135 -0
  408. package/src/domain-packs/token-resolver.test.ts +148 -0
  409. package/src/domain-packs/types.test.ts +144 -0
  410. package/src/enforcement/adapters/claude-code.test.ts +216 -0
  411. package/src/enforcement/registry.test.ts +258 -0
  412. package/src/engine/bin/soleri-engine.ts +30 -4
  413. package/src/engine/core-ops.test.ts +254 -0
  414. package/src/engine/core-ops.ts +25 -8
  415. package/src/engine/module-manifest.test.ts +125 -0
  416. package/src/engine/module-manifest.ts +42 -2
  417. package/src/engine/register-engine.test.ts +235 -0
  418. package/src/engine/register-engine.ts +50 -3
  419. package/src/errors/classify.test.ts +203 -0
  420. package/src/errors/retry.test.ts +153 -0
  421. package/src/errors/retry.ts +2 -0
  422. package/src/errors/types.test.ts +108 -0
  423. package/src/events/event-bus.test.ts +149 -0
  424. package/src/extensions/middleware.test.ts +234 -0
  425. package/src/facades/facade-factory.test.ts +470 -0
  426. package/src/flows/chain-runner.test.ts +273 -0
  427. package/src/flows/context-router.test.ts +52 -0
  428. package/src/flows/dispatch-registry.test.ts +128 -0
  429. package/src/flows/epilogue.test.ts +113 -0
  430. package/src/flows/executor.test.ts +263 -0
  431. package/src/flows/gate-evaluator.test.ts +200 -0
  432. package/src/flows/gate-evaluator.ts +23 -0
  433. package/src/flows/types.ts +4 -0
  434. package/src/governance/governance.test.ts +842 -0
  435. package/src/{__tests__ → health}/health-registry.test.ts +75 -55
  436. package/src/health/vault-integrity.test.ts +110 -0
  437. package/src/index.ts +92 -0
  438. package/src/intake/content-classifier.test.ts +279 -0
  439. package/src/intake/dedup-gate.test.ts +147 -0
  440. package/src/intake/intake-pipeline.test.ts +508 -0
  441. package/src/intake/intake-pipeline.ts +1 -0
  442. package/src/intake/text-ingester.test.ts +200 -0
  443. package/src/intake/text-ingester.ts +2 -0
  444. package/src/llm/key-pool.test.ts +234 -0
  445. package/src/llm/key-pool.ts +3 -4
  446. package/src/llm/llm-client.test.ts +342 -0
  447. package/src/llm/oauth-discovery.test.ts +180 -0
  448. package/src/llm/utils.test.ts +371 -0
  449. package/src/llm/utils.ts +2 -0
  450. package/src/{__tests__ → logging}/logger.test.ts +44 -62
  451. package/src/loop/loop-manager.test.ts +515 -0
  452. package/src/migrations/migration-runner.edge-cases.test.ts +314 -0
  453. package/src/migrations/migration-runner.test-helpers.ts +64 -0
  454. package/src/migrations/migration-runner.test.ts +385 -0
  455. package/src/operator/auto-signal-pipeline.test.ts +207 -0
  456. package/src/operator/operator-profile-extended.test.ts +330 -0
  457. package/src/operator/operator-profile.test.ts +332 -0
  458. package/src/operator/operator-profile.ts +485 -0
  459. package/src/operator/operator-signals-extended.test.ts +257 -0
  460. package/src/operator/operator-signals.test.ts +277 -0
  461. package/src/operator/operator-signals.ts +262 -0
  462. package/src/operator/operator-types.ts +444 -0
  463. package/src/operator/prompts/hook-precompact-operator-dispatch.md +98 -0
  464. package/src/operator/prompts/subagent-soft-signal-extractor.md +130 -0
  465. package/src/operator/prompts/subagent-synthesis-cognition.md +190 -0
  466. package/src/operator/prompts/subagent-synthesis-communication.md +146 -0
  467. package/src/operator/prompts/subagent-synthesis-technical.md +170 -0
  468. package/src/operator/prompts/subagent-synthesis-trust.md +149 -0
  469. package/src/{__tests__ → packs}/pack-lockfile.test.ts +3 -3
  470. package/src/{__tests__ → packs}/pack-system.test.ts +2 -2
  471. package/src/paths.ts +115 -0
  472. package/src/persistence/index.ts +1 -1
  473. package/src/persistence/sqlite-provider.test.ts +540 -0
  474. package/src/persistence/sqlite-provider.ts +8 -5
  475. package/src/persona/defaults.test.ts +55 -0
  476. package/src/persona/loader.test.ts +67 -0
  477. package/src/persona/prompt-generator.test.ts +127 -0
  478. package/src/planning/evidence-collector.test.ts +515 -0
  479. package/src/planning/evidence-collector.ts +47 -0
  480. package/src/planning/gap-analysis-alternatives.test.ts +199 -0
  481. package/src/planning/gap-analysis.ts +21 -636
  482. package/src/planning/gap-passes.test.ts +554 -0
  483. package/src/planning/gap-passes.ts +367 -0
  484. package/src/planning/gap-patterns.test.ts +394 -0
  485. package/src/planning/gap-patterns.ts +317 -0
  486. package/src/planning/gap-types.ts +4 -1
  487. package/src/planning/github-projection.test.ts +182 -0
  488. package/src/planning/github-projection.ts +446 -0
  489. package/src/planning/impact-analyzer.test.ts +167 -0
  490. package/src/planning/impact-analyzer.ts +251 -0
  491. package/src/planning/plan-lifecycle.test.ts +379 -0
  492. package/src/planning/plan-lifecycle.ts +377 -0
  493. package/src/planning/planner-types.ts +215 -0
  494. package/src/{__tests__ → planning}/planner.test.ts +179 -15
  495. package/src/planning/planner.ts +221 -1112
  496. package/src/planning/rationalization-detector.test.ts +156 -0
  497. package/src/planning/rationalization-detector.ts +136 -0
  498. package/src/planning/reconciliation-engine.test.ts +158 -0
  499. package/src/planning/reconciliation-engine.ts +161 -0
  500. package/src/planning/task-verifier.test.ts +267 -0
  501. package/src/planning/task-verifier.ts +309 -0
  502. package/src/planning/verification-protocol.test.ts +201 -0
  503. package/src/playbooks/generic/generic-playbooks.test.ts +438 -0
  504. package/src/playbooks/index.test.ts +77 -0
  505. package/src/playbooks/playbook-executor.test.ts +253 -0
  506. package/src/playbooks/playbook-registry.test.ts +232 -0
  507. package/src/playbooks/playbook-seeder.test.ts +153 -0
  508. package/src/plugins/plugin-loader.test.ts +217 -0
  509. package/src/plugins/plugin-registry.test.ts +284 -0
  510. package/src/project/project-registry.test.ts +439 -0
  511. package/src/prompts/parser.test.ts +100 -0
  512. package/src/prompts/template-manager.test.ts +112 -0
  513. package/src/{__tests__ → queue}/async-infrastructure.test.ts +3 -3
  514. package/src/queue/job-queue.test.ts +327 -0
  515. package/src/queue/pipeline-runner.test.ts +209 -0
  516. package/src/runtime/admin-extra-ops.test.ts +513 -0
  517. package/src/runtime/admin-ops.test.ts +255 -0
  518. package/src/runtime/admin-ops.ts +45 -17
  519. package/src/runtime/admin-setup-ops.test.ts +327 -0
  520. package/src/runtime/admin-setup-ops.ts +26 -42
  521. package/src/runtime/archive-ops.test.ts +272 -0
  522. package/src/runtime/archive-ops.ts +347 -0
  523. package/src/runtime/branching-ops.test.ts +144 -0
  524. package/src/runtime/branching-ops.ts +107 -0
  525. package/src/runtime/capture-ops.test.ts +419 -0
  526. package/src/runtime/capture-ops.ts +50 -8
  527. package/src/runtime/chain-ops.test.ts +159 -0
  528. package/src/runtime/claude-md-helpers.test.ts +189 -0
  529. package/src/runtime/claude-md-helpers.ts +1 -1
  530. package/src/runtime/context-health.test.ts +76 -0
  531. package/src/runtime/context-health.ts +83 -0
  532. package/src/runtime/curator-extra-ops.test.ts +204 -0
  533. package/src/runtime/deprecation.test.ts +98 -0
  534. package/src/runtime/domain-ops.test.ts +278 -0
  535. package/src/runtime/facades/admin-facade.test.ts +330 -0
  536. package/src/runtime/facades/agency-facade.test.ts +278 -0
  537. package/src/runtime/facades/archive-facade.test.ts +308 -0
  538. package/src/runtime/facades/archive-facade.ts +14 -0
  539. package/src/runtime/facades/brain-facade.test.ts +818 -0
  540. package/src/runtime/facades/brain-facade.ts +2 -0
  541. package/src/runtime/facades/branching-facade.test.ts +43 -0
  542. package/src/runtime/facades/branching-facade.ts +11 -0
  543. package/src/runtime/facades/chat-facade.test.ts +219 -0
  544. package/src/runtime/facades/chat-facade.ts +15 -906
  545. package/src/runtime/facades/chat-service-ops.test.ts +381 -0
  546. package/src/runtime/facades/chat-service-ops.ts +376 -0
  547. package/src/runtime/facades/chat-session-ops.test.ts +212 -0
  548. package/src/runtime/facades/chat-session-ops.ts +146 -0
  549. package/src/runtime/facades/chat-state.ts +60 -0
  550. package/src/runtime/facades/chat-transport-ops.test.ts +336 -0
  551. package/src/runtime/facades/chat-transport-ops.ts +379 -0
  552. package/src/runtime/facades/context-facade.test.ts +123 -0
  553. package/src/runtime/facades/control-facade.test.ts +436 -0
  554. package/src/runtime/facades/control-facade.ts +6 -1
  555. package/src/runtime/facades/curator-facade.test.ts +303 -0
  556. package/src/runtime/facades/index.ts +48 -0
  557. package/src/runtime/facades/intake-facade.test.ts +215 -0
  558. package/src/runtime/facades/intake-facade.ts +14 -0
  559. package/src/runtime/facades/links-facade.test.ts +203 -0
  560. package/src/runtime/facades/links-facade.ts +13 -0
  561. package/src/runtime/facades/loop-facade.test.ts +262 -0
  562. package/src/runtime/facades/memory-facade.test.ts +283 -0
  563. package/src/runtime/facades/memory-facade.ts +78 -6
  564. package/src/runtime/facades/operator-facade.test.ts +221 -0
  565. package/src/runtime/facades/operator-facade.ts +244 -0
  566. package/src/runtime/facades/orchestrate-facade.test.ts +191 -0
  567. package/src/runtime/facades/orchestrate-facade.ts +3 -3
  568. package/src/runtime/facades/plan-facade.test.ts +283 -0
  569. package/src/runtime/facades/plan-facade.ts +47 -6
  570. package/src/runtime/facades/review-facade.test.ts +82 -0
  571. package/src/runtime/facades/review-facade.ts +11 -0
  572. package/src/runtime/facades/sync-facade.test.ts +113 -0
  573. package/src/runtime/facades/sync-facade.ts +11 -0
  574. package/src/runtime/facades/tier-facade.test.ts +47 -0
  575. package/src/runtime/facades/tier-facade.ts +11 -0
  576. package/src/runtime/facades/vault-facade.test.ts +563 -0
  577. package/src/runtime/facades/vault-facade.ts +66 -265
  578. package/src/runtime/feature-flags.test.ts +140 -0
  579. package/src/runtime/github-integration.test.ts +89 -0
  580. package/src/runtime/github-integration.ts +162 -0
  581. package/src/runtime/grading-ops.test.ts +172 -0
  582. package/src/runtime/grading-ops.ts +1 -1
  583. package/src/runtime/intake-ops.test.ts +261 -0
  584. package/src/runtime/loop-ops.test.ts +248 -0
  585. package/src/runtime/memory-cross-project-ops.test.ts +188 -0
  586. package/src/runtime/memory-extra-ops.test.ts +453 -0
  587. package/src/runtime/memory-extra-ops.ts +6 -2
  588. package/src/runtime/orchestrate-ops.test.ts +302 -0
  589. package/src/runtime/orchestrate-ops.ts +461 -45
  590. package/src/runtime/pack-ops.test.ts +175 -0
  591. package/src/runtime/planning-extra-ops.test.ts +593 -0
  592. package/src/runtime/planning-extra-ops.ts +74 -4
  593. package/src/{__tests__ → runtime}/playbook-ops-execution.test.ts +3 -3
  594. package/src/runtime/playbook-ops.test.ts +285 -0
  595. package/src/runtime/plugin-ops.test.ts +259 -0
  596. package/src/runtime/project-ops.test.ts +255 -0
  597. package/src/runtime/review-ops.test.ts +142 -0
  598. package/src/runtime/review-ops.ts +99 -0
  599. package/src/runtime/runtime.test.ts +363 -0
  600. package/src/runtime/runtime.ts +41 -12
  601. package/src/runtime/session-briefing.test.ts +431 -0
  602. package/src/runtime/session-briefing.ts +86 -1
  603. package/src/runtime/sync-ops.test.ts +212 -0
  604. package/src/runtime/sync-ops.ts +325 -0
  605. package/src/runtime/telemetry-ops.test.ts +157 -0
  606. package/src/runtime/tier-ops.test.ts +159 -0
  607. package/src/runtime/tier-ops.ts +119 -0
  608. package/src/runtime/types.ts +10 -4
  609. package/src/runtime/vault-extra-ops.test.ts +270 -0
  610. package/src/runtime/vault-extra-ops.ts +5 -332
  611. package/src/runtime/vault-linking-ops.test.ts +237 -0
  612. package/src/runtime/vault-sharing-ops.test.ts +127 -0
  613. package/src/runtime/vault-sharing-ops.ts +5 -329
  614. package/src/skills/sync-skills.ts +98 -0
  615. package/src/streams/normalize.test.ts +95 -0
  616. package/src/streams/replayable-stream.test.ts +166 -0
  617. package/src/telemetry/telemetry.test.ts +143 -0
  618. package/src/transport/http-server.test.ts +394 -0
  619. package/src/transport/lsp-server.test.ts +458 -0
  620. package/src/transport/rate-limiter.test.ts +126 -0
  621. package/src/transport/session-manager.test.ts +133 -0
  622. package/src/transport/token-auth.test.ts +136 -0
  623. package/src/transport/ws-server.test.ts +297 -0
  624. package/src/update-check.ts +111 -0
  625. package/src/vault/__tests__/vault-characterization.test.ts +579 -0
  626. package/src/vault/content-hash.test.ts +78 -0
  627. package/src/vault/git-vault-sync.test.ts +234 -0
  628. package/src/vault/knowledge-review.test.ts +269 -0
  629. package/src/vault/linking.test.ts +391 -0
  630. package/src/vault/linking.ts +188 -181
  631. package/src/vault/obsidian-sync.test.ts +345 -0
  632. package/src/vault/playbook.test.ts +152 -0
  633. package/src/vault/scope-detector.test.ts +185 -0
  634. package/src/vault/vault-branching.test.ts +252 -0
  635. package/src/{__tests__ → vault}/vault-connect.test.ts +1 -1
  636. package/src/vault/vault-entries.ts +426 -0
  637. package/src/vault/vault-maintenance.ts +200 -0
  638. package/src/vault/vault-manager.test.ts +206 -0
  639. package/src/vault/vault-markdown-sync.test.ts +203 -0
  640. package/src/vault/vault-markdown-sync.ts +163 -0
  641. package/src/vault/vault-memories.ts +339 -0
  642. package/src/{__tests__ → vault}/vault-scaling.test.ts +1 -1
  643. package/src/vault/vault-schema.ts +238 -0
  644. package/src/{__tests__ → vault}/vault-sharing.test.ts +4 -4
  645. package/src/{__tests__ → vault}/vault.test.ts +2 -2
  646. package/src/vault/vault.ts +87 -1123
  647. package/dist/cognee/client.d.ts +0 -43
  648. package/dist/cognee/client.d.ts.map +0 -1
  649. package/dist/cognee/client.js +0 -375
  650. package/dist/cognee/client.js.map +0 -1
  651. package/dist/cognee/sync-manager.d.ts +0 -153
  652. package/dist/cognee/sync-manager.d.ts.map +0 -1
  653. package/dist/cognee/sync-manager.js +0 -390
  654. package/dist/cognee/sync-manager.js.map +0 -1
  655. package/dist/cognee/types.d.ts +0 -62
  656. package/dist/cognee/types.d.ts.map +0 -1
  657. package/dist/cognee/types.js +0 -3
  658. package/dist/cognee/types.js.map +0 -1
  659. package/dist/governance/index.d.ts +0 -3
  660. package/dist/governance/index.d.ts.map +0 -1
  661. package/dist/governance/index.js +0 -2
  662. package/dist/governance/index.js.map +0 -1
  663. package/dist/health/doctor-checks.d.ts +0 -15
  664. package/dist/health/doctor-checks.d.ts.map +0 -1
  665. package/dist/health/doctor-checks.js +0 -98
  666. package/dist/health/doctor-checks.js.map +0 -1
  667. package/dist/persistence/postgres-provider.d.ts +0 -81
  668. package/dist/persistence/postgres-provider.d.ts.map +0 -1
  669. package/dist/persistence/postgres-provider.js +0 -256
  670. package/dist/persistence/postgres-provider.js.map +0 -1
  671. package/dist/runtime/cognee-sync-ops.d.ts +0 -12
  672. package/dist/runtime/cognee-sync-ops.d.ts.map +0 -1
  673. package/dist/runtime/cognee-sync-ops.js +0 -93
  674. package/dist/runtime/cognee-sync-ops.js.map +0 -1
  675. package/dist/runtime/core-ops.d.ts +0 -23
  676. package/dist/runtime/core-ops.d.ts.map +0 -1
  677. package/dist/runtime/core-ops.js +0 -1296
  678. package/dist/runtime/core-ops.js.map +0 -1
  679. package/dist/runtime/facades/cognee-facade.d.ts +0 -8
  680. package/dist/runtime/facades/cognee-facade.d.ts.map +0 -1
  681. package/dist/runtime/facades/cognee-facade.js +0 -156
  682. package/dist/runtime/facades/cognee-facade.js.map +0 -1
  683. package/src/__tests__/admin-extra-ops.test.ts +0 -484
  684. package/src/__tests__/admin-ops.test.ts +0 -268
  685. package/src/__tests__/admin-setup-ops.test.ts +0 -355
  686. package/src/__tests__/agency-manager.test.ts +0 -374
  687. package/src/__tests__/agent-loop.test.ts +0 -256
  688. package/src/__tests__/capture-ops.test.ts +0 -784
  689. package/src/__tests__/claudemd.test.ts +0 -282
  690. package/src/__tests__/content-hash.test.ts +0 -60
  691. package/src/__tests__/context-engine.test.ts +0 -251
  692. package/src/__tests__/core-ops.test.ts +0 -550
  693. package/src/__tests__/curator-extra-ops.test.ts +0 -383
  694. package/src/__tests__/deprecation.test.ts +0 -78
  695. package/src/__tests__/domain-ops.test.ts +0 -226
  696. package/src/__tests__/domain-packs.test.ts +0 -421
  697. package/src/__tests__/enforcement.test.ts +0 -153
  698. package/src/__tests__/errors.test.ts +0 -388
  699. package/src/__tests__/extensions.test.ts +0 -233
  700. package/src/__tests__/facade-factory.test.ts +0 -271
  701. package/src/__tests__/feature-flags.test.ts +0 -137
  702. package/src/__tests__/flows.test.ts +0 -604
  703. package/src/__tests__/git-vault-sync.test.ts +0 -230
  704. package/src/__tests__/governance.test.ts +0 -522
  705. package/src/__tests__/grading-ops.test.ts +0 -361
  706. package/src/__tests__/identity-manager.test.ts +0 -243
  707. package/src/__tests__/intake-pipeline.test.ts +0 -162
  708. package/src/__tests__/intent-router.test.ts +0 -222
  709. package/src/__tests__/knowledge-review.test.ts +0 -104
  710. package/src/__tests__/llm-client.test.ts +0 -69
  711. package/src/__tests__/llm.test.ts +0 -556
  712. package/src/__tests__/loader.test.ts +0 -176
  713. package/src/__tests__/loop-ops.test.ts +0 -469
  714. package/src/__tests__/lsp-transport.test.ts +0 -442
  715. package/src/__tests__/memory-cross-project-ops.test.ts +0 -248
  716. package/src/__tests__/memory-extra-ops.test.ts +0 -352
  717. package/src/__tests__/migration-runner.test.ts +0 -170
  718. package/src/__tests__/module-manifest-drift.test.ts +0 -59
  719. package/src/__tests__/normalize.test.ts +0 -85
  720. package/src/__tests__/obsidian-sync.test.ts +0 -354
  721. package/src/__tests__/orchestrate-ops.test.ts +0 -289
  722. package/src/__tests__/pack-ops.test.ts +0 -146
  723. package/src/__tests__/persistence.test.ts +0 -291
  724. package/src/__tests__/planning-extra-ops.test.ts +0 -706
  725. package/src/__tests__/playbook-executor.test.ts +0 -249
  726. package/src/__tests__/playbook-registry.test.ts +0 -326
  727. package/src/__tests__/playbook-seeder.test.ts +0 -163
  728. package/src/__tests__/playbook.test.ts +0 -389
  729. package/src/__tests__/plugin-ops.test.ts +0 -411
  730. package/src/__tests__/plugin-system.test.ts +0 -509
  731. package/src/__tests__/project-ops.test.ts +0 -381
  732. package/src/__tests__/replayable-stream.test.ts +0 -177
  733. package/src/__tests__/runtime.test.ts +0 -95
  734. package/src/__tests__/scope-detector.test.ts +0 -121
  735. package/src/__tests__/template-manager.test.ts +0 -222
  736. package/src/__tests__/token-resolver.test.ts +0 -79
  737. package/src/__tests__/transport.test.ts +0 -758
  738. package/src/__tests__/vault-branching.test.ts +0 -274
  739. package/src/__tests__/vault-extra-ops.test.ts +0 -482
  740. package/src/__tests__/vault-integrity.test.ts +0 -71
  741. package/src/__tests__/vault-manager.test.ts +0 -238
  742. package/src/__tests__/ws-transport.test.ts +0 -479
  743. package/src/engine/index.ts +0 -21
  744. package/src/persona/index.ts +0 -9
@@ -1,102 +1,49 @@
1
- import { tokenize, calculateTfIdf, cosineSimilarity, } from '../text/similarity.js';
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.initializeTables();
30
- this.seedDefaultAliases();
17
+ this.tagStore = this.createTagStore();
18
+ initializeTables(this.provider);
19
+ this.provider.transaction(() => seedDefaultAliases(this.tagStore));
31
20
  }
32
- // ─── Schema ─────────────────────────────────────────────────────
33
- initializeTables() {
34
- this.provider.execSql(`
35
- CREATE TABLE IF NOT EXISTS curator_entry_state (
36
- entry_id TEXT PRIMARY KEY,
37
- status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'stale', 'archived')),
38
- confidence REAL NOT NULL DEFAULT 1.0,
39
- source TEXT NOT NULL DEFAULT 'unknown' CHECK(source IN ('manual', 'capture', 'seed', 'unknown')),
40
- last_groomed_at INTEGER,
41
- created_at INTEGER NOT NULL DEFAULT (unixepoch())
42
- );
43
-
44
- CREATE TABLE IF NOT EXISTS curator_tag_canonical (
45
- tag TEXT PRIMARY KEY,
46
- description TEXT,
47
- created_at INTEGER NOT NULL DEFAULT (unixepoch())
48
- );
49
-
50
- CREATE TABLE IF NOT EXISTS curator_tag_alias (
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 = ?', [
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
- // ─── Tag Normalization ──────────────────────────────────────────
66
+ // ─── Tags (delegates to tag-manager) ──────────────────────────
120
67
  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 };
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
- const lower = alias.toLowerCase().trim();
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
- 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;
88
+ return getCanonicalTagsPure(this.tagStore);
178
89
  }
179
- // ─── Duplicate Detection ────────────────────────────────────────
90
+ // ─── Duplicates (delegates to duplicate-detector) ─────────────
180
91
  detectDuplicates(entryId, threshold) {
181
- const effectiveThreshold = threshold ?? DEFAULT_DUPLICATE_THRESHOLD;
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 effectiveThreshold = threshold ?? DEFAULT_CONTRADICTION_THRESHOLD;
226
- const entries = this.vault.list({ limit: 100000 });
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
- const rows = this.provider.all(query, status ? [status] : undefined);
267
- return rows.map((r) => this.rowToContradiction(r));
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 effectiveThreshold = threshold ?? DEFAULT_CONTRADICTION_THRESHOLD;
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: detected,
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
- // Upsert entry state
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 staleThreshold = now - staleDaysThreshold * 86400;
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
- const rows = this.provider.all('SELECT * FROM curator_changelog WHERE entry_id = ? ORDER BY created_at DESC, id DESC LIMIT ?', [entryId, limit ?? 50]);
409
- return rows.map((r) => this.rowToChangelog(r));
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 recommendations = [];
415
- if (entries.length === 0) {
416
- return {
417
- score: 100,
418
- metrics: { coverage: 1, freshness: 1, quality: 1, tagHealth: 1 },
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
- const rows = this.provider.all('SELECT * FROM curator_entry_history WHERE entry_id = ? ORDER BY created_at ASC, id ASC', [entryId]);
518
- return rows.map((row) => ({
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 totalEntries = (this.provider.get('SELECT COUNT(*) as count FROM entries') ?? { count: 0 }).count;
530
- const groomedEntries = (this.provider.get('SELECT COUNT(*) as count FROM curator_entry_state WHERE last_groomed_at IS NOT NULL') ?? { count: 0 }).count;
531
- const ungroomedEntries = totalEntries - groomedEntries;
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 staleThreshold = now - 30 * 86400;
534
- const freshThreshold = now - 7 * 86400;
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 sumRow = this.provider.get('SELECT SUM(? - last_groomed_at) as total FROM curator_entry_state WHERE last_groomed_at IS NOT NULL', [now]) ?? { total: 0 };
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
- const updates = {};
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
- buildVocabulary(entries) {
621
- const docCount = entries.length;
622
- const termDocFreq = new Map();
623
- for (const entry of entries) {
624
- const text = [entry.title, entry.description, entry.context ?? '', entry.tags.join(' ')].join(' ');
625
- const tokens = new Set(tokenize(text));
626
- for (const token of tokens) {
627
- termDocFreq.set(token, (termDocFreq.get(token) ?? 0) + 1);
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
- const vocabulary = new Map();
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]);