@soleri/core 2.12.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (430) hide show
  1. package/data/flows/build.flow.yaml +128 -0
  2. package/data/flows/deliver.flow.yaml +110 -0
  3. package/data/flows/design.flow.yaml +108 -0
  4. package/data/flows/enhance.flow.yaml +90 -0
  5. package/data/flows/explore.flow.yaml +84 -0
  6. package/data/flows/fix.flow.yaml +90 -0
  7. package/data/flows/plan.flow.yaml +87 -0
  8. package/data/flows/review.flow.yaml +90 -0
  9. package/dist/agency/agency-manager.d.ts +27 -1
  10. package/dist/agency/agency-manager.d.ts.map +1 -1
  11. package/dist/agency/agency-manager.js +180 -9
  12. package/dist/agency/agency-manager.js.map +1 -1
  13. package/dist/agency/default-rules.d.ts +7 -0
  14. package/dist/agency/default-rules.d.ts.map +1 -0
  15. package/dist/agency/default-rules.js +79 -0
  16. package/dist/agency/default-rules.js.map +1 -0
  17. package/dist/agency/types.d.ts +48 -0
  18. package/dist/agency/types.d.ts.map +1 -1
  19. package/dist/brain/brain.d.ts +17 -2
  20. package/dist/brain/brain.d.ts.map +1 -1
  21. package/dist/brain/brain.js +118 -8
  22. package/dist/brain/brain.js.map +1 -1
  23. package/dist/brain/intelligence.d.ts.map +1 -1
  24. package/dist/brain/intelligence.js +16 -2
  25. package/dist/brain/intelligence.js.map +1 -1
  26. package/dist/brain/knowledge-synthesizer.d.ts +37 -0
  27. package/dist/brain/knowledge-synthesizer.d.ts.map +1 -0
  28. package/dist/brain/knowledge-synthesizer.js +161 -0
  29. package/dist/brain/knowledge-synthesizer.js.map +1 -0
  30. package/dist/brain/learning-radar.d.ts +96 -0
  31. package/dist/brain/learning-radar.d.ts.map +1 -0
  32. package/dist/brain/learning-radar.js +202 -0
  33. package/dist/brain/learning-radar.js.map +1 -0
  34. package/dist/brain/types.d.ts +15 -0
  35. package/dist/brain/types.d.ts.map +1 -1
  36. package/dist/capabilities/chain-mapping.d.ts +21 -0
  37. package/dist/capabilities/chain-mapping.d.ts.map +1 -0
  38. package/dist/capabilities/chain-mapping.js +86 -0
  39. package/dist/capabilities/chain-mapping.js.map +1 -0
  40. package/dist/capabilities/index.d.ts +10 -0
  41. package/dist/capabilities/index.d.ts.map +1 -0
  42. package/dist/capabilities/index.js +8 -0
  43. package/dist/capabilities/index.js.map +1 -0
  44. package/dist/capabilities/registry.d.ts +95 -0
  45. package/dist/capabilities/registry.d.ts.map +1 -0
  46. package/dist/capabilities/registry.js +227 -0
  47. package/dist/capabilities/registry.js.map +1 -0
  48. package/dist/capabilities/types.d.ts +106 -0
  49. package/dist/capabilities/types.d.ts.map +1 -0
  50. package/dist/capabilities/types.js +12 -0
  51. package/dist/capabilities/types.js.map +1 -0
  52. package/dist/context/context-engine.d.ts.map +1 -1
  53. package/dist/context/context-engine.js +82 -17
  54. package/dist/context/context-engine.js.map +1 -1
  55. package/dist/context/types.d.ts +5 -0
  56. package/dist/context/types.d.ts.map +1 -1
  57. package/dist/control/intent-router.d.ts +12 -1
  58. package/dist/control/intent-router.d.ts.map +1 -1
  59. package/dist/control/intent-router.js +126 -2
  60. package/dist/control/intent-router.js.map +1 -1
  61. package/dist/control/types.d.ts +17 -0
  62. package/dist/control/types.d.ts.map +1 -1
  63. package/dist/curator/classifier.d.ts +18 -0
  64. package/dist/curator/classifier.d.ts.map +1 -0
  65. package/dist/curator/classifier.js +61 -0
  66. package/dist/curator/classifier.js.map +1 -0
  67. package/dist/curator/quality-gate.d.ts +29 -0
  68. package/dist/curator/quality-gate.d.ts.map +1 -0
  69. package/dist/curator/quality-gate.js +88 -0
  70. package/dist/curator/quality-gate.js.map +1 -0
  71. package/dist/domain-packs/index.d.ts +8 -0
  72. package/dist/domain-packs/index.d.ts.map +1 -0
  73. package/dist/domain-packs/index.js +8 -0
  74. package/dist/domain-packs/index.js.map +1 -0
  75. package/dist/domain-packs/inject-rules.d.ts +24 -0
  76. package/dist/domain-packs/inject-rules.d.ts.map +1 -0
  77. package/dist/domain-packs/inject-rules.js +65 -0
  78. package/dist/domain-packs/inject-rules.js.map +1 -0
  79. package/dist/domain-packs/knowledge-installer.d.ts +27 -0
  80. package/dist/domain-packs/knowledge-installer.d.ts.map +1 -0
  81. package/dist/domain-packs/knowledge-installer.js +89 -0
  82. package/dist/domain-packs/knowledge-installer.js.map +1 -0
  83. package/dist/domain-packs/loader.d.ts +28 -0
  84. package/dist/domain-packs/loader.d.ts.map +1 -0
  85. package/dist/domain-packs/loader.js +105 -0
  86. package/dist/domain-packs/loader.js.map +1 -0
  87. package/dist/domain-packs/pack-runtime.d.ts +80 -0
  88. package/dist/domain-packs/pack-runtime.d.ts.map +1 -0
  89. package/dist/domain-packs/pack-runtime.js +36 -0
  90. package/dist/domain-packs/pack-runtime.js.map +1 -0
  91. package/dist/domain-packs/skills-installer.d.ts +21 -0
  92. package/dist/domain-packs/skills-installer.d.ts.map +1 -0
  93. package/dist/domain-packs/skills-installer.js +38 -0
  94. package/dist/domain-packs/skills-installer.js.map +1 -0
  95. package/dist/domain-packs/token-resolver.d.ts +37 -0
  96. package/dist/domain-packs/token-resolver.d.ts.map +1 -0
  97. package/dist/domain-packs/token-resolver.js +109 -0
  98. package/dist/domain-packs/token-resolver.js.map +1 -0
  99. package/dist/domain-packs/types.d.ts +91 -0
  100. package/dist/domain-packs/types.d.ts.map +1 -0
  101. package/dist/domain-packs/types.js +122 -0
  102. package/dist/domain-packs/types.js.map +1 -0
  103. package/dist/engine/bin/soleri-engine.d.ts +12 -0
  104. package/dist/engine/bin/soleri-engine.d.ts.map +1 -0
  105. package/dist/engine/bin/soleri-engine.js +184 -0
  106. package/dist/engine/bin/soleri-engine.js.map +1 -0
  107. package/dist/engine/core-ops.d.ts +27 -0
  108. package/dist/engine/core-ops.d.ts.map +1 -0
  109. package/dist/engine/core-ops.js +159 -0
  110. package/dist/engine/core-ops.js.map +1 -0
  111. package/dist/engine/index.d.ts +19 -0
  112. package/dist/engine/index.d.ts.map +1 -0
  113. package/dist/engine/index.js +17 -0
  114. package/dist/engine/index.js.map +1 -0
  115. package/dist/engine/register-engine.d.ts +54 -0
  116. package/dist/engine/register-engine.d.ts.map +1 -0
  117. package/dist/engine/register-engine.js +270 -0
  118. package/dist/engine/register-engine.js.map +1 -0
  119. package/dist/engine/test-helpers.d.ts +30 -0
  120. package/dist/engine/test-helpers.d.ts.map +1 -0
  121. package/dist/engine/test-helpers.js +59 -0
  122. package/dist/engine/test-helpers.js.map +1 -0
  123. package/dist/events/event-bus.d.ts +30 -0
  124. package/dist/events/event-bus.d.ts.map +1 -0
  125. package/dist/events/event-bus.js +51 -0
  126. package/dist/events/event-bus.js.map +1 -0
  127. package/dist/flows/chain-runner.d.ts +46 -0
  128. package/dist/flows/chain-runner.d.ts.map +1 -0
  129. package/dist/flows/chain-runner.js +271 -0
  130. package/dist/flows/chain-runner.js.map +1 -0
  131. package/dist/flows/chain-types.d.ts +103 -0
  132. package/dist/flows/chain-types.d.ts.map +1 -0
  133. package/dist/flows/chain-types.js +23 -0
  134. package/dist/flows/chain-types.js.map +1 -0
  135. package/dist/flows/context-router.d.ts +39 -0
  136. package/dist/flows/context-router.d.ts.map +1 -0
  137. package/dist/flows/context-router.js +206 -0
  138. package/dist/flows/context-router.js.map +1 -0
  139. package/dist/flows/dispatch-registry.d.ts +24 -0
  140. package/dist/flows/dispatch-registry.d.ts.map +1 -0
  141. package/dist/flows/dispatch-registry.js +70 -0
  142. package/dist/flows/dispatch-registry.js.map +1 -0
  143. package/dist/flows/epilogue.d.ts +24 -0
  144. package/dist/flows/epilogue.d.ts.map +1 -0
  145. package/dist/flows/epilogue.js +52 -0
  146. package/dist/flows/epilogue.js.map +1 -0
  147. package/dist/flows/executor.d.ts +25 -0
  148. package/dist/flows/executor.d.ts.map +1 -0
  149. package/dist/flows/executor.js +153 -0
  150. package/dist/flows/executor.js.map +1 -0
  151. package/dist/flows/gate-evaluator.d.ts +26 -0
  152. package/dist/flows/gate-evaluator.d.ts.map +1 -0
  153. package/dist/flows/gate-evaluator.js +162 -0
  154. package/dist/flows/gate-evaluator.js.map +1 -0
  155. package/dist/flows/index.d.ts +14 -0
  156. package/dist/flows/index.d.ts.map +1 -0
  157. package/dist/flows/index.js +20 -0
  158. package/dist/flows/index.js.map +1 -0
  159. package/dist/flows/loader.d.ts +17 -0
  160. package/dist/flows/loader.d.ts.map +1 -0
  161. package/dist/flows/loader.js +61 -0
  162. package/dist/flows/loader.js.map +1 -0
  163. package/dist/flows/plan-builder.d.ts +40 -0
  164. package/dist/flows/plan-builder.d.ts.map +1 -0
  165. package/dist/flows/plan-builder.js +213 -0
  166. package/dist/flows/plan-builder.js.map +1 -0
  167. package/dist/flows/probes.d.ts +11 -0
  168. package/dist/flows/probes.d.ts.map +1 -0
  169. package/dist/flows/probes.js +62 -0
  170. package/dist/flows/probes.js.map +1 -0
  171. package/dist/flows/types.d.ts +950 -0
  172. package/dist/flows/types.d.ts.map +1 -0
  173. package/dist/flows/types.js +105 -0
  174. package/dist/flows/types.js.map +1 -0
  175. package/dist/health/doctor-checks.d.ts +15 -0
  176. package/dist/health/doctor-checks.d.ts.map +1 -0
  177. package/dist/health/doctor-checks.js +98 -0
  178. package/dist/health/doctor-checks.js.map +1 -0
  179. package/dist/index.d.ts +11 -1
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +10 -1
  182. package/dist/index.js.map +1 -1
  183. package/dist/intake/text-ingester.d.ts +52 -0
  184. package/dist/intake/text-ingester.d.ts.map +1 -0
  185. package/dist/intake/text-ingester.js +181 -0
  186. package/dist/intake/text-ingester.js.map +1 -0
  187. package/dist/intelligence/loader.d.ts +19 -0
  188. package/dist/intelligence/loader.d.ts.map +1 -1
  189. package/dist/intelligence/loader.js +35 -0
  190. package/dist/intelligence/loader.js.map +1 -1
  191. package/dist/intelligence/types.d.ts +1 -0
  192. package/dist/intelligence/types.d.ts.map +1 -1
  193. package/dist/llm/llm-client.d.ts.map +1 -1
  194. package/dist/llm/llm-client.js +37 -1
  195. package/dist/llm/llm-client.js.map +1 -1
  196. package/dist/llm/oauth-discovery.d.ts +26 -0
  197. package/dist/llm/oauth-discovery.d.ts.map +1 -0
  198. package/dist/llm/oauth-discovery.js +149 -0
  199. package/dist/llm/oauth-discovery.js.map +1 -0
  200. package/dist/packs/types.d.ts +58 -19
  201. package/dist/packs/types.d.ts.map +1 -1
  202. package/dist/packs/types.js +14 -0
  203. package/dist/packs/types.js.map +1 -1
  204. package/dist/planning/evidence-collector.d.ts +41 -0
  205. package/dist/planning/evidence-collector.d.ts.map +1 -0
  206. package/dist/planning/evidence-collector.js +194 -0
  207. package/dist/planning/evidence-collector.js.map +1 -0
  208. package/dist/planning/planner.d.ts +4 -0
  209. package/dist/planning/planner.d.ts.map +1 -1
  210. package/dist/planning/planner.js +11 -0
  211. package/dist/planning/planner.js.map +1 -1
  212. package/dist/playbooks/generic/onboarding.d.ts +9 -0
  213. package/dist/playbooks/generic/onboarding.d.ts.map +1 -0
  214. package/dist/playbooks/generic/onboarding.js +74 -0
  215. package/dist/playbooks/generic/onboarding.js.map +1 -0
  216. package/dist/playbooks/playbook-registry.d.ts.map +1 -1
  217. package/dist/playbooks/playbook-registry.js +2 -0
  218. package/dist/playbooks/playbook-registry.js.map +1 -1
  219. package/dist/queue/job-queue.d.ts +92 -0
  220. package/dist/queue/job-queue.d.ts.map +1 -0
  221. package/dist/queue/job-queue.js +180 -0
  222. package/dist/queue/job-queue.js.map +1 -0
  223. package/dist/queue/pipeline-runner.d.ts +62 -0
  224. package/dist/queue/pipeline-runner.d.ts.map +1 -0
  225. package/dist/queue/pipeline-runner.js +126 -0
  226. package/dist/queue/pipeline-runner.js.map +1 -0
  227. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  228. package/dist/runtime/admin-extra-ops.js +15 -9
  229. package/dist/runtime/admin-extra-ops.js.map +1 -1
  230. package/dist/runtime/admin-ops.js +4 -4
  231. package/dist/runtime/admin-ops.js.map +1 -1
  232. package/dist/runtime/admin-setup-ops.d.ts +20 -0
  233. package/dist/runtime/admin-setup-ops.d.ts.map +1 -0
  234. package/dist/runtime/admin-setup-ops.js +583 -0
  235. package/dist/runtime/admin-setup-ops.js.map +1 -0
  236. package/dist/runtime/capture-ops.d.ts.map +1 -1
  237. package/dist/runtime/capture-ops.js +33 -1
  238. package/dist/runtime/capture-ops.js.map +1 -1
  239. package/dist/runtime/chain-ops.d.ts +9 -0
  240. package/dist/runtime/chain-ops.d.ts.map +1 -0
  241. package/dist/runtime/chain-ops.js +107 -0
  242. package/dist/runtime/chain-ops.js.map +1 -0
  243. package/dist/runtime/claude-md-helpers.d.ts +65 -0
  244. package/dist/runtime/claude-md-helpers.d.ts.map +1 -0
  245. package/dist/runtime/claude-md-helpers.js +173 -0
  246. package/dist/runtime/claude-md-helpers.js.map +1 -0
  247. package/dist/runtime/curator-extra-ops.d.ts +3 -2
  248. package/dist/runtime/curator-extra-ops.d.ts.map +1 -1
  249. package/dist/runtime/curator-extra-ops.js +81 -3
  250. package/dist/runtime/curator-extra-ops.js.map +1 -1
  251. package/dist/runtime/domain-ops.d.ts +21 -5
  252. package/dist/runtime/domain-ops.d.ts.map +1 -1
  253. package/dist/runtime/domain-ops.js +64 -6
  254. package/dist/runtime/domain-ops.js.map +1 -1
  255. package/dist/runtime/facades/admin-facade.d.ts.map +1 -1
  256. package/dist/runtime/facades/admin-facade.js +4 -0
  257. package/dist/runtime/facades/admin-facade.js.map +1 -1
  258. package/dist/runtime/facades/agency-facade.d.ts.map +1 -1
  259. package/dist/runtime/facades/agency-facade.js +64 -0
  260. package/dist/runtime/facades/agency-facade.js.map +1 -1
  261. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  262. package/dist/runtime/facades/brain-facade.js +122 -1
  263. package/dist/runtime/facades/brain-facade.js.map +1 -1
  264. package/dist/runtime/facades/cognee-facade.d.ts.map +1 -1
  265. package/dist/runtime/facades/cognee-facade.js +3 -1
  266. package/dist/runtime/facades/cognee-facade.js.map +1 -1
  267. package/dist/runtime/facades/control-facade.d.ts.map +1 -1
  268. package/dist/runtime/facades/control-facade.js +42 -0
  269. package/dist/runtime/facades/control-facade.js.map +1 -1
  270. package/dist/runtime/facades/index.d.ts.map +1 -1
  271. package/dist/runtime/facades/index.js +10 -6
  272. package/dist/runtime/facades/index.js.map +1 -1
  273. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  274. package/dist/runtime/facades/memory-facade.js +20 -2
  275. package/dist/runtime/facades/memory-facade.js.map +1 -1
  276. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  277. package/dist/runtime/facades/plan-facade.js +2 -0
  278. package/dist/runtime/facades/plan-facade.js.map +1 -1
  279. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  280. package/dist/runtime/facades/vault-facade.js +27 -5
  281. package/dist/runtime/facades/vault-facade.js.map +1 -1
  282. package/dist/runtime/intake-ops.d.ts +7 -5
  283. package/dist/runtime/intake-ops.d.ts.map +1 -1
  284. package/dist/runtime/intake-ops.js +98 -5
  285. package/dist/runtime/intake-ops.js.map +1 -1
  286. package/dist/runtime/memory-extra-ops.d.ts +6 -3
  287. package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
  288. package/dist/runtime/memory-extra-ops.js +292 -4
  289. package/dist/runtime/memory-extra-ops.js.map +1 -1
  290. package/dist/runtime/orchestrate-ops.d.ts +8 -7
  291. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  292. package/dist/runtime/orchestrate-ops.js +217 -61
  293. package/dist/runtime/orchestrate-ops.js.map +1 -1
  294. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  295. package/dist/runtime/planning-extra-ops.js +85 -0
  296. package/dist/runtime/planning-extra-ops.js.map +1 -1
  297. package/dist/runtime/playbook-ops.js +1 -1
  298. package/dist/runtime/playbook-ops.js.map +1 -1
  299. package/dist/runtime/runtime.d.ts.map +1 -1
  300. package/dist/runtime/runtime.js +165 -18
  301. package/dist/runtime/runtime.js.map +1 -1
  302. package/dist/runtime/session-briefing.d.ts +23 -0
  303. package/dist/runtime/session-briefing.d.ts.map +1 -0
  304. package/dist/runtime/session-briefing.js +140 -0
  305. package/dist/runtime/session-briefing.js.map +1 -0
  306. package/dist/runtime/types.d.ts +29 -2
  307. package/dist/runtime/types.d.ts.map +1 -1
  308. package/dist/runtime/vault-linking-ops.d.ts +13 -0
  309. package/dist/runtime/vault-linking-ops.d.ts.map +1 -0
  310. package/dist/runtime/vault-linking-ops.js +365 -0
  311. package/dist/runtime/vault-linking-ops.js.map +1 -0
  312. package/dist/vault/linking.d.ts +46 -0
  313. package/dist/vault/linking.d.ts.map +1 -0
  314. package/dist/vault/linking.js +275 -0
  315. package/dist/vault/linking.js.map +1 -0
  316. package/dist/vault/vault-types.d.ts +37 -0
  317. package/dist/vault/vault-types.d.ts.map +1 -1
  318. package/dist/vault/vault.d.ts +37 -0
  319. package/dist/vault/vault.d.ts.map +1 -1
  320. package/dist/vault/vault.js +152 -9
  321. package/dist/vault/vault.js.map +1 -1
  322. package/package.json +4 -1
  323. package/src/__tests__/admin-extra-ops.test.ts +1 -1
  324. package/src/__tests__/admin-ops.test.ts +2 -1
  325. package/src/__tests__/admin-setup-ops.test.ts +355 -0
  326. package/src/__tests__/async-infrastructure.test.ts +307 -0
  327. package/src/__tests__/cognee-client-gaps.test.ts +474 -0
  328. package/src/__tests__/cognee-hybrid-search.test.ts +492 -0
  329. package/src/__tests__/cognee-sync-manager-deep.test.ts +654 -0
  330. package/src/__tests__/cognee-sync-manager.test.ts +1 -0
  331. package/src/__tests__/core-ops.test.ts +9 -61
  332. package/src/__tests__/curator-extra-ops.test.ts +6 -2
  333. package/src/__tests__/curator-pipeline-e2e.test.ts +358 -0
  334. package/src/__tests__/domain-packs.test.ts +421 -0
  335. package/src/__tests__/flows.test.ts +604 -0
  336. package/src/__tests__/memory-extra-ops.test.ts +2 -2
  337. package/src/__tests__/planning-extra-ops.test.ts +2 -2
  338. package/src/__tests__/playbook-registry.test.ts +2 -2
  339. package/src/__tests__/playbook-seeder.test.ts +8 -8
  340. package/src/__tests__/playbook.test.ts +5 -5
  341. package/src/__tests__/second-brain-features.test.ts +583 -0
  342. package/src/__tests__/token-resolver.test.ts +79 -0
  343. package/src/agency/agency-manager.ts +217 -9
  344. package/src/agency/default-rules.ts +83 -0
  345. package/src/agency/types.ts +61 -0
  346. package/src/brain/brain.ts +110 -8
  347. package/src/brain/intelligence.ts +21 -2
  348. package/src/brain/knowledge-synthesizer.ts +218 -0
  349. package/src/brain/learning-radar.ts +340 -0
  350. package/src/brain/types.ts +16 -0
  351. package/src/capabilities/chain-mapping.ts +93 -0
  352. package/src/capabilities/index.ts +21 -0
  353. package/src/capabilities/registry.ts +290 -0
  354. package/src/capabilities/types.ts +143 -0
  355. package/src/context/context-engine.ts +114 -15
  356. package/src/context/types.ts +5 -0
  357. package/src/control/intent-router.ts +153 -2
  358. package/src/control/types.ts +10 -0
  359. package/src/curator/classifier.ts +88 -0
  360. package/src/curator/quality-gate.ts +129 -0
  361. package/src/domain-packs/index.ts +27 -0
  362. package/src/domain-packs/inject-rules.ts +74 -0
  363. package/src/domain-packs/knowledge-installer.ts +116 -0
  364. package/src/domain-packs/loader.ts +124 -0
  365. package/src/domain-packs/pack-runtime.ts +99 -0
  366. package/src/domain-packs/skills-installer.ts +56 -0
  367. package/src/domain-packs/token-resolver.ts +126 -0
  368. package/src/domain-packs/types.ts +229 -0
  369. package/src/engine/__tests__/register-engine.test.ts +104 -0
  370. package/src/engine/bin/soleri-engine.ts +218 -0
  371. package/src/engine/core-ops.ts +178 -0
  372. package/src/engine/index.ts +19 -0
  373. package/src/engine/register-engine.ts +385 -0
  374. package/src/engine/test-helpers.ts +83 -0
  375. package/src/events/event-bus.ts +58 -0
  376. package/src/flows/chain-runner.ts +369 -0
  377. package/src/flows/chain-types.ts +57 -0
  378. package/src/flows/context-router.ts +257 -0
  379. package/src/flows/dispatch-registry.ts +80 -0
  380. package/src/flows/epilogue.ts +65 -0
  381. package/src/flows/executor.ts +182 -0
  382. package/src/flows/gate-evaluator.ts +171 -0
  383. package/src/flows/index.ts +52 -0
  384. package/src/flows/loader.ts +63 -0
  385. package/src/flows/plan-builder.ts +250 -0
  386. package/src/flows/probes.ts +70 -0
  387. package/src/flows/types.ts +217 -0
  388. package/src/health/doctor-checks.ts +115 -0
  389. package/src/index.ts +68 -1
  390. package/src/intake/text-ingester.ts +234 -0
  391. package/src/intelligence/loader.ts +38 -0
  392. package/src/intelligence/types.ts +1 -0
  393. package/src/llm/llm-client.ts +38 -1
  394. package/src/llm/oauth-discovery.ts +169 -0
  395. package/src/packs/types.ts +19 -0
  396. package/src/planning/evidence-collector.ts +247 -0
  397. package/src/planning/planner.ts +11 -0
  398. package/src/playbooks/generic/onboarding.ts +79 -0
  399. package/src/playbooks/playbook-registry.ts +2 -0
  400. package/src/queue/job-queue.ts +281 -0
  401. package/src/queue/pipeline-runner.ts +149 -0
  402. package/src/runtime/admin-extra-ops.ts +14 -8
  403. package/src/runtime/admin-ops.ts +4 -4
  404. package/src/runtime/admin-setup-ops.ts +664 -0
  405. package/src/runtime/capture-ops.ts +40 -1
  406. package/src/runtime/chain-ops.ts +121 -0
  407. package/src/runtime/claude-md-helpers.ts +236 -0
  408. package/src/runtime/curator-extra-ops.ts +86 -3
  409. package/src/runtime/domain-ops.ts +71 -5
  410. package/src/runtime/facades/admin-facade.ts +4 -0
  411. package/src/runtime/facades/agency-facade.ts +68 -0
  412. package/src/runtime/facades/brain-facade.ts +142 -1
  413. package/src/runtime/facades/cognee-facade.ts +3 -1
  414. package/src/runtime/facades/control-facade.ts +45 -0
  415. package/src/runtime/facades/index.ts +12 -6
  416. package/src/runtime/facades/memory-facade.ts +20 -2
  417. package/src/runtime/facades/plan-facade.ts +2 -0
  418. package/src/runtime/facades/vault-facade.ts +30 -5
  419. package/src/runtime/intake-ops.ts +107 -5
  420. package/src/runtime/memory-extra-ops.ts +312 -4
  421. package/src/runtime/orchestrate-ops.ts +261 -65
  422. package/src/runtime/planning-extra-ops.ts +94 -0
  423. package/src/runtime/playbook-ops.ts +1 -1
  424. package/src/runtime/runtime.ts +164 -19
  425. package/src/runtime/session-briefing.ts +161 -0
  426. package/src/runtime/types.ts +29 -2
  427. package/src/runtime/vault-linking-ops.ts +452 -0
  428. package/src/vault/linking.ts +333 -0
  429. package/src/vault/vault-types.ts +46 -0
  430. package/src/vault/vault.ts +173 -11
@@ -16,8 +16,33 @@ import type {
16
16
  IntentClassification,
17
17
  ModeConfig,
18
18
  MorphResult,
19
+ RoutingAccuracyReport,
19
20
  } from './types.js';
20
21
 
22
+ // ─── Token Stemming ─────────────────────────────────────────────────
23
+ // Lightweight suffix stripping for intent matching.
24
+ // Handles: "crashes" → "crash", "deploying" → "deploy", "broken" → "broke",
25
+ // "issues" → "issue", "building" → "build", "optimizing" → "optimize"
26
+
27
+ function stemToken(token: string): string {
28
+ if (token.length < 4) return token;
29
+ // Order matters — check longer suffixes first
30
+ if (token.endsWith('ying')) return token.slice(0, -4) + 'y'; // deploying → deploy
31
+ if (token.endsWith('izing')) return token.slice(0, -3) + 'e'; // optimizing → optimize
32
+ if (token.endsWith('ating')) return token.slice(0, -3) + 'e'; // creating → create
33
+ if (token.endsWith('ting')) return token.slice(0, -4) + 't'; // getting → get (approx)
34
+ if (token.endsWith('ning')) return token.slice(0, -4) + 'n'; // planning → plan (approx)
35
+ if (token.endsWith('ing')) return token.slice(0, -3); // fixing → fix, building → build
36
+ if (token.endsWith('ies')) return token.slice(0, -3) + 'y'; // queries → query
37
+ if (token.endsWith('shes')) return token.slice(0, -2); // crashes → crash
38
+ if (token.endsWith('ches')) return token.slice(0, -2); // searches → search
39
+ if (token.endsWith('ses')) return token.slice(0, -2); // releases → releas (close enough)
40
+ if (token.endsWith('es') && token.length > 4) return token.slice(0, -1); // issues → issue
41
+ if (token.endsWith('ed') && token.length > 4) return token.slice(0, -2); // fixed → fix
42
+ if (token.endsWith('s') && !token.endsWith('ss') && token.length > 3) return token.slice(0, -1); // bugs → bug
43
+ return token;
44
+ }
45
+
21
46
  // ─── Default Mode Definitions ───────────────────────────────────────
22
47
 
23
48
  const DEFAULT_MODES: ModeConfig[] = [
@@ -33,7 +58,23 @@ const DEFAULT_MODES: ModeConfig[] = [
33
58
  intent: 'fix',
34
59
  description: 'Fixing bugs, errors, and broken behavior',
35
60
  behaviorRules: ['Identify root cause first', 'Verify fix with tests', 'Check for regressions'],
36
- keywords: ['fix', 'bug', 'broken', 'error', 'crash', 'issue', 'debug', 'repair', 'janky'],
61
+ keywords: [
62
+ 'fix',
63
+ 'bug',
64
+ 'broken',
65
+ 'error',
66
+ 'crash',
67
+ 'issue',
68
+ 'debug',
69
+ 'repair',
70
+ 'janky',
71
+ 'fail',
72
+ 'wrong',
73
+ 'stuck',
74
+ 'regression',
75
+ 'fault',
76
+ 'defect',
77
+ ],
37
78
  },
38
79
  {
39
80
  mode: 'VALIDATE-MODE',
@@ -128,6 +169,16 @@ export class IntentRouter {
128
169
  matched_keywords TEXT NOT NULL DEFAULT '[]',
129
170
  created_at TEXT NOT NULL DEFAULT (datetime('now'))
130
171
  );
172
+
173
+ CREATE TABLE IF NOT EXISTS routing_feedback (
174
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
175
+ routing_log_id INTEGER,
176
+ initial_intent TEXT NOT NULL,
177
+ actual_intent TEXT NOT NULL,
178
+ correction INTEGER NOT NULL DEFAULT 0,
179
+ confidence REAL NOT NULL,
180
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
181
+ );
131
182
  `);
132
183
  }
133
184
 
@@ -152,7 +203,11 @@ export class IntentRouter {
152
203
  // ─── Intent Classification ──────────────────────────────────────────
153
204
 
154
205
  routeIntent(prompt: string): IntentClassification {
155
- const tokens = new Set(prompt.toLowerCase().split(/\s+/).filter(Boolean));
206
+ const rawTokens = prompt.toLowerCase().split(/\s+/).filter(Boolean);
207
+ // Stem tokens: strip common suffixes for fuzzy matching
208
+ // "crashes" → "crash", "broken" stays "broken", "deploying" → "deploy"
209
+ const stemmed = rawTokens.map((t) => stemToken(t));
210
+ const tokens = new Set([...rawTokens, ...stemmed]);
156
211
  const modes = this.getModes();
157
212
 
158
213
  let bestMode: ModeConfig | null = null;
@@ -270,6 +325,102 @@ export class IntentRouter {
270
325
  }
271
326
  }
272
327
 
328
+ // ─── Routing Feedback ─────────────────────────────────────────────
329
+
330
+ recordRoutingFeedback(input: {
331
+ routingLogId?: number;
332
+ initialIntent: string;
333
+ actualIntent: string;
334
+ confidence: number;
335
+ correction: boolean;
336
+ }): { recorded: boolean; id: number } {
337
+ const result = this.provider.run(
338
+ `INSERT INTO routing_feedback (routing_log_id, initial_intent, actual_intent, correction, confidence)
339
+ VALUES (?, ?, ?, ?, ?)`,
340
+ [
341
+ input.routingLogId ?? null,
342
+ input.initialIntent,
343
+ input.actualIntent,
344
+ input.correction ? 1 : 0,
345
+ input.confidence,
346
+ ],
347
+ );
348
+ return { recorded: true, id: Number(result.lastInsertRowid) };
349
+ }
350
+
351
+ getRoutingAccuracy(periodDays: number = 30): RoutingAccuracyReport {
352
+ const cutoff = new Date(Date.now() - periodDays * 86400000).toISOString();
353
+
354
+ const total = this.provider.get<{ count: number }>(
355
+ 'SELECT COUNT(*) as count FROM routing_feedback WHERE created_at >= ?',
356
+ [cutoff],
357
+ )!.count;
358
+
359
+ const correct = this.provider.get<{ count: number }>(
360
+ 'SELECT COUNT(*) as count FROM routing_feedback WHERE initial_intent = actual_intent AND created_at >= ?',
361
+ [cutoff],
362
+ )!.count;
363
+
364
+ const corrections = this.provider.get<{ count: number }>(
365
+ 'SELECT COUNT(*) as count FROM routing_feedback WHERE correction = 1 AND created_at >= ?',
366
+ [cutoff],
367
+ )!.count;
368
+
369
+ // Common misroutes
370
+ const misrouteRows = this.provider.all<{
371
+ from_intent: string;
372
+ to_intent: string;
373
+ count: number;
374
+ }>(
375
+ `SELECT initial_intent as from_intent, actual_intent as to_intent, COUNT(*) as count
376
+ FROM routing_feedback
377
+ WHERE initial_intent != actual_intent AND created_at >= ?
378
+ GROUP BY initial_intent, actual_intent
379
+ ORDER BY count DESC
380
+ LIMIT 10`,
381
+ [cutoff],
382
+ );
383
+
384
+ // Confidence calibration: group by confidence bucket and check accuracy per bucket
385
+ const calibrationRows = this.provider.all<{ bucket: string; total: number; correct: number }>(
386
+ `SELECT
387
+ CASE
388
+ WHEN confidence >= 0.8 THEN 'high'
389
+ WHEN confidence >= 0.4 THEN 'medium'
390
+ ELSE 'low'
391
+ END as bucket,
392
+ COUNT(*) as total,
393
+ SUM(CASE WHEN initial_intent = actual_intent THEN 1 ELSE 0 END) as correct
394
+ FROM routing_feedback
395
+ WHERE created_at >= ?
396
+ GROUP BY bucket`,
397
+ [cutoff],
398
+ );
399
+
400
+ const calibration: Record<string, { total: number; correct: number; accuracy: number }> = {};
401
+ for (const row of calibrationRows) {
402
+ calibration[row.bucket] = {
403
+ total: row.total,
404
+ correct: row.correct,
405
+ accuracy: row.total > 0 ? Math.round((row.correct / row.total) * 100) : 0,
406
+ };
407
+ }
408
+
409
+ return {
410
+ periodDays,
411
+ total,
412
+ correct,
413
+ accuracy: total > 0 ? Math.round((correct / total) * 100) : 100,
414
+ corrections,
415
+ commonMisroutes: misrouteRows.map((r) => ({
416
+ from: r.from_intent,
417
+ to: r.to_intent,
418
+ count: r.count,
419
+ })),
420
+ confidenceCalibration: calibration,
421
+ };
422
+ }
423
+
273
424
  // ─── Analytics ──────────────────────────────────────────────────────
274
425
 
275
426
  getRoutingStats(): {
@@ -100,3 +100,13 @@ export interface MorphResult {
100
100
  currentMode: OperationalMode;
101
101
  behaviorRules: string[];
102
102
  }
103
+
104
+ export interface RoutingAccuracyReport {
105
+ periodDays: number;
106
+ total: number;
107
+ correct: number;
108
+ accuracy: number;
109
+ corrections: number;
110
+ commonMisroutes: Array<{ from: string; to: string; count: number }>;
111
+ confidenceCalibration: Record<string, { total: number; correct: number; accuracy: number }>;
112
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Classifier — LLM-based auto-categorization for vault entries.
3
+ *
4
+ * Suggests category, severity, and additional tags based on entry content.
5
+ * Graceful degradation: returns empty suggestions when LLM is unavailable.
6
+ */
7
+
8
+ import type { LLMClient } from '../llm/llm-client.js';
9
+ import type { IntelligenceEntry } from '../intelligence/types.js';
10
+
11
+ // ─── Types ───────────────────────────────────────────────────────────
12
+
13
+ export interface ClassificationResult {
14
+ classified: boolean;
15
+ suggestedDomain: string | null;
16
+ suggestedSeverity: string | null;
17
+ suggestedTags: string[];
18
+ confidence: number;
19
+ error?: string;
20
+ }
21
+
22
+ // ─── Classify ────────────────────────────────────────────────────────
23
+
24
+ const CLASSIFY_PROMPT = `Classify this knowledge entry. Suggest the best domain, severity, and 3-5 tags.
25
+
26
+ **Title:** {title}
27
+ **Type:** {type}
28
+ **Current tags:** {tags}
29
+ **Description:** {description}
30
+
31
+ Respond with ONLY this JSON (no markdown fences):
32
+ {"domain":"string","severity":"critical|warning|suggestion","tags":["tag1","tag2","tag3"],"confidence":0.0-1.0}
33
+
34
+ Rules:
35
+ - domain: a single word (e.g., architecture, testing, security, design, performance, accessibility)
36
+ - severity: critical = must-know, warning = important, suggestion = nice-to-know
37
+ - tags: lowercase, hyphenated, specific and useful for search
38
+ - confidence: how sure you are about this classification (0.0-1.0)`;
39
+
40
+ export async function classifyEntry(
41
+ entry: IntelligenceEntry,
42
+ llm: LLMClient | null,
43
+ ): Promise<ClassificationResult> {
44
+ const fallback: ClassificationResult = {
45
+ classified: false,
46
+ suggestedDomain: null,
47
+ suggestedSeverity: null,
48
+ suggestedTags: [],
49
+ confidence: 0,
50
+ };
51
+
52
+ if (!llm) return fallback;
53
+
54
+ const prompt = CLASSIFY_PROMPT.replace('{title}', entry.title)
55
+ .replace('{type}', entry.type)
56
+ .replace('{tags}', entry.tags.join(', ') || 'none')
57
+ .replace('{description}', entry.description);
58
+
59
+ try {
60
+ const result = await llm.complete({
61
+ provider: 'openai',
62
+ model: 'gpt-4o-mini',
63
+ systemPrompt: 'You are a knowledge classifier. Respond only with JSON.',
64
+ userPrompt: prompt,
65
+ temperature: 0.1,
66
+ maxTokens: 300,
67
+ caller: 'classifier',
68
+ task: 'classify',
69
+ });
70
+
71
+ const parsed = JSON.parse(result.text) as {
72
+ domain: string;
73
+ severity: string;
74
+ tags: string[];
75
+ confidence: number;
76
+ };
77
+
78
+ return {
79
+ classified: true,
80
+ suggestedDomain: parsed.domain ?? null,
81
+ suggestedSeverity: parsed.severity ?? null,
82
+ suggestedTags: parsed.tags ?? [],
83
+ confidence: parsed.confidence ?? 0.5,
84
+ };
85
+ } catch (err) {
86
+ return { ...fallback, error: (err as Error).message };
87
+ }
88
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Quality Gate — LLM-based entry quality evaluation.
3
+ *
4
+ * Evaluates vault entries on 5 criteria (novelty, actionability, specificity,
5
+ * relevance, informationDensity). Entries scoring below threshold are rejected.
6
+ *
7
+ * Graceful degradation: returns ACCEPT when LLM is unavailable.
8
+ */
9
+
10
+ import type { LLMClient } from '../llm/llm-client.js';
11
+ import type { IntelligenceEntry } from '../intelligence/types.js';
12
+
13
+ // ─── Types ───────────────────────────────────────────────────────────
14
+
15
+ export type QualityVerdict = 'ACCEPT' | 'REJECT';
16
+
17
+ export interface QualityScores {
18
+ novelty: number;
19
+ actionability: number;
20
+ specificity: number;
21
+ relevance: number;
22
+ informationDensity: number;
23
+ }
24
+
25
+ export interface QualityResult {
26
+ evaluated: boolean;
27
+ verdict: QualityVerdict;
28
+ overallScore: number;
29
+ scores: QualityScores;
30
+ reasoning: string;
31
+ rejectReasons?: string[];
32
+ error?: string;
33
+ }
34
+
35
+ // ─── Constants ───────────────────────────────────────────────────────
36
+
37
+ const REJECT_THRESHOLD = 50;
38
+ const CRITICAL_LOW = 15;
39
+
40
+ const QUALITY_PROMPT = `You are a strict knowledge base curator deciding whether an entry deserves to be in a high-quality vault.
41
+
42
+ Your job is to REJECT junk and keep the vault clean. Be ruthless but fair.
43
+
44
+ ## Entry Under Review
45
+ - **Type:** {type}
46
+ - **Title:** {title}
47
+ - **Tags:** {tags}
48
+ - **Description:** {description}
49
+ {why}{example}{context}
50
+
51
+ ## Scoring Criteria (each 0-100)
52
+
53
+ 1. **novelty** — Is this genuinely new knowledge or a truism? ("Write clean code" = 5, "Use driver adapter pattern to avoid Prisma lock-in" = 90)
54
+ 2. **actionability** — Can someone act on this? Vague advice = low, specific do/don't = high
55
+ 3. **specificity** — Is this specific to a real context or generic fluff?
56
+ 4. **relevance** — Does this belong in a technical knowledge vault?
57
+ 5. **informationDensity** — Is there real substance or mostly filler?
58
+
59
+ ## Verdict Rules
60
+ - Overall score = average of all 5 criteria
61
+ - **REJECT** if overall < ${REJECT_THRESHOLD}, or if ANY criterion scores <= ${CRITICAL_LOW}
62
+ - **ACCEPT** otherwise
63
+ - When in doubt, REJECT.
64
+
65
+ Respond with ONLY this JSON (no markdown fences):
66
+ {"verdict":"ACCEPT or REJECT","overallScore":0-100,"scores":{"novelty":N,"actionability":N,"specificity":N,"relevance":N,"informationDensity":N},"reasoning":"2-3 sentences","rejectReasons":["reason1"]}`;
67
+
68
+ // ─── Evaluate ────────────────────────────────────────────────────────
69
+
70
+ export async function evaluateQuality(
71
+ entry: IntelligenceEntry,
72
+ llm: LLMClient | null,
73
+ ): Promise<QualityResult> {
74
+ const fallback: QualityResult = {
75
+ evaluated: false,
76
+ verdict: 'ACCEPT',
77
+ overallScore: 50,
78
+ scores: {
79
+ novelty: 50,
80
+ actionability: 50,
81
+ specificity: 50,
82
+ relevance: 50,
83
+ informationDensity: 50,
84
+ },
85
+ reasoning: 'LLM unavailable — defaulting to accept',
86
+ };
87
+
88
+ if (!llm) return fallback;
89
+
90
+ const prompt = QUALITY_PROMPT.replace('{type}', entry.type)
91
+ .replace('{title}', entry.title)
92
+ .replace('{tags}', entry.tags.join(', ') || 'none')
93
+ .replace('{description}', entry.description)
94
+ .replace('{why}', entry.why ? `- **Why:** ${entry.why}\n` : '')
95
+ .replace('{example}', entry.example ? `- **Example:** ${entry.example}\n` : '')
96
+ .replace('{context}', entry.context ? `- **Context:** ${entry.context}\n` : '');
97
+
98
+ try {
99
+ const result = await llm.complete({
100
+ provider: 'openai',
101
+ model: 'gpt-4o-mini',
102
+ systemPrompt: 'You are a knowledge quality evaluator. Respond only with JSON.',
103
+ userPrompt: prompt,
104
+ temperature: 0.1,
105
+ maxTokens: 500,
106
+ caller: 'quality-gate',
107
+ task: 'evaluate',
108
+ });
109
+
110
+ const parsed = JSON.parse(result.text) as {
111
+ verdict: string;
112
+ overallScore: number;
113
+ scores: QualityScores;
114
+ reasoning: string;
115
+ rejectReasons?: string[];
116
+ };
117
+
118
+ return {
119
+ evaluated: true,
120
+ verdict: (parsed.verdict === 'REJECT' ? 'REJECT' : 'ACCEPT') as QualityVerdict,
121
+ overallScore: parsed.overallScore ?? 50,
122
+ scores: parsed.scores ?? fallback.scores,
123
+ reasoning: parsed.reasoning ?? '',
124
+ rejectReasons: parsed.rejectReasons,
125
+ };
126
+ } catch (err) {
127
+ return { ...fallback, error: (err as Error).message };
128
+ }
129
+ }
@@ -0,0 +1,27 @@
1
+ export {
2
+ type DomainPack,
3
+ type DomainPackManifest,
4
+ type DomainPackRef,
5
+ type KnowledgeManifest,
6
+ type PackSkillDefinition,
7
+ type ValidateResult,
8
+ validateDomainPack,
9
+ SEMANTIC_FACADE_NAMES,
10
+ } from './types.js';
11
+
12
+ export { loadDomainPack, loadDomainPacksFromConfig, resolveDependencies } from './loader.js';
13
+
14
+ export { installKnowledge, type KnowledgeInstallResult } from './knowledge-installer.js';
15
+
16
+ export { installSkills, type SkillsInstallResult } from './skills-installer.js';
17
+
18
+ export { injectDomainRules, removeDomainRules } from './inject-rules.js';
19
+
20
+ export {
21
+ type PackRuntime,
22
+ type PackProjectContext,
23
+ type PackCheckContext,
24
+ createPackRuntime,
25
+ } from './pack-runtime.js';
26
+
27
+ export { resolveToken, listProjectTokens, buildReverseIndex } from './token-resolver.js';
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Domain-level CLAUDE.md injection for domain packs.
3
+ *
4
+ * Each pack can inject behavioral rules under its own marker:
5
+ * <!-- domain:packName --> ... <!-- /domain:packName -->
6
+ *
7
+ * Injection is idempotent — existing content between markers is replaced.
8
+ */
9
+
10
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
11
+
12
+ const OPEN_MARKER = (name: string) => `<!-- domain:${name} -->`;
13
+ const CLOSE_MARKER = (name: string) => `<!-- /domain:${name} -->`;
14
+
15
+ /**
16
+ * Inject domain rules into a CLAUDE.md file.
17
+ *
18
+ * @param filePath - Path to CLAUDE.md
19
+ * @param packName - Domain pack name (used in markers)
20
+ * @param rulesContent - Markdown content to inject
21
+ */
22
+ export function injectDomainRules(filePath: string, packName: string, rulesContent: string): void {
23
+ if (!rulesContent || rulesContent.trim().length === 0) return;
24
+
25
+ const open = OPEN_MARKER(packName);
26
+ const close = CLOSE_MARKER(packName);
27
+ const block = `${open}\n${rulesContent.trim()}\n${close}`;
28
+
29
+ if (!existsSync(filePath)) {
30
+ writeFileSync(filePath, block + '\n', 'utf-8');
31
+ return;
32
+ }
33
+
34
+ let content = readFileSync(filePath, 'utf-8');
35
+
36
+ // Replace existing block if present (idempotent)
37
+ const openIdx = content.indexOf(open);
38
+ const closeIdx = content.indexOf(close);
39
+
40
+ if (openIdx !== -1 && closeIdx !== -1) {
41
+ const before = content.slice(0, openIdx);
42
+ const after = content.slice(closeIdx + close.length);
43
+ content = before + block + after;
44
+ } else {
45
+ // Append at end
46
+ content = content.trimEnd() + '\n\n' + block + '\n';
47
+ }
48
+
49
+ writeFileSync(filePath, content, 'utf-8');
50
+ }
51
+
52
+ /**
53
+ * Remove domain rules from a CLAUDE.md file.
54
+ *
55
+ * @param filePath - Path to CLAUDE.md
56
+ * @param packName - Domain pack name
57
+ */
58
+ export function removeDomainRules(filePath: string, packName: string): void {
59
+ if (!existsSync(filePath)) return;
60
+
61
+ const open = OPEN_MARKER(packName);
62
+ const close = CLOSE_MARKER(packName);
63
+
64
+ let content = readFileSync(filePath, 'utf-8');
65
+ const openIdx = content.indexOf(open);
66
+ const closeIdx = content.indexOf(close);
67
+
68
+ if (openIdx !== -1 && closeIdx !== -1) {
69
+ const before = content.slice(0, openIdx);
70
+ const after = content.slice(closeIdx + close.length);
71
+ content = (before + after).replace(/\n{3,}/g, '\n\n');
72
+ writeFileSync(filePath, content, 'utf-8');
73
+ }
74
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Three-tier knowledge installer for domain packs.
3
+ *
4
+ * Respects KnowledgeManifest tiers:
5
+ * - canonical/: seed_canonical (immutable, highest authority)
6
+ * - curated/: import via vault (curator-eligible)
7
+ * - captured/: import via vault (tier=captured)
8
+ *
9
+ * All entries tagged with origin=pack and source=packName.
10
+ */
11
+
12
+ import { readdirSync, readFileSync, existsSync } from 'node:fs';
13
+ import { join, resolve } from 'node:path';
14
+ import type { AgentRuntime } from '../runtime/types.js';
15
+ import type { DomainPack } from './types.js';
16
+
17
+ export interface KnowledgeInstallResult {
18
+ canonical: number;
19
+ curated: number;
20
+ captured: number;
21
+ skipped: number;
22
+ }
23
+
24
+ /**
25
+ * Install knowledge from a domain pack into the agent's vault.
26
+ *
27
+ * @param pack - The domain pack with knowledge manifest
28
+ * @param runtime - Agent runtime with vault access
29
+ * @param rootDir - Absolute path to the pack's root directory
30
+ */
31
+ export async function installKnowledge(
32
+ pack: DomainPack,
33
+ runtime: AgentRuntime,
34
+ rootDir: string,
35
+ ): Promise<KnowledgeInstallResult> {
36
+ const result: KnowledgeInstallResult = { canonical: 0, curated: 0, captured: 0, skipped: 0 };
37
+
38
+ if (!pack.knowledge) return result;
39
+
40
+ const { vault } = runtime;
41
+ const knowledge = pack.knowledge;
42
+
43
+ // Tier 1: Canonical (immutable)
44
+ if (knowledge.canonical) {
45
+ const dir = resolve(rootDir, knowledge.canonical);
46
+ if (existsSync(dir)) {
47
+ const count = importMarkdownEntries(vault, dir, {
48
+ tier: 'canonical',
49
+ origin: 'pack',
50
+ source: pack.name,
51
+ immutable: true,
52
+ });
53
+ result.canonical = count;
54
+ }
55
+ }
56
+
57
+ // Tier 2: Curated (grooming-eligible)
58
+ if (knowledge.curated) {
59
+ const dir = resolve(rootDir, knowledge.curated);
60
+ if (existsSync(dir)) {
61
+ const count = importMarkdownEntries(vault, dir, {
62
+ tier: 'curated',
63
+ origin: 'pack',
64
+ source: pack.name,
65
+ });
66
+ result.curated = count;
67
+ }
68
+ }
69
+
70
+ // Tier 3: Captured (seed learnings)
71
+ if (knowledge.captured) {
72
+ const dir = resolve(rootDir, knowledge.captured);
73
+ if (existsSync(dir)) {
74
+ const count = importMarkdownEntries(vault, dir, {
75
+ tier: 'captured',
76
+ origin: 'pack',
77
+ source: pack.name,
78
+ });
79
+ result.captured = count;
80
+ }
81
+ }
82
+
83
+ return result;
84
+ }
85
+
86
+ /** Import markdown files from a directory into the vault. */
87
+ function importMarkdownEntries(
88
+ vault: AgentRuntime['vault'],
89
+ dir: string,
90
+ meta: { tier: string; origin: string; source: string; immutable?: boolean },
91
+ ): number {
92
+ const files = readdirSync(dir).filter((f) => f.endsWith('.md'));
93
+ let imported = 0;
94
+
95
+ for (const file of files) {
96
+ const content = readFileSync(join(dir, file), 'utf-8');
97
+ const id = `pack-${meta.source}-${file.replace(/\.md$/, '')}`;
98
+
99
+ // Skip if canonical entry already exists (immutable = never overwrite)
100
+ if (meta.immutable && vault.get(id)) continue;
101
+
102
+ vault.add({
103
+ id,
104
+ type: 'pattern',
105
+ title: file.replace(/\.md$/, '').replace(/-/g, ' '),
106
+ description: content.slice(0, 200),
107
+ severity: 'suggestion',
108
+ tags: [`pack:${meta.source}`, `tier:${meta.tier}`],
109
+ domain: meta.source,
110
+ origin: meta.origin as 'pack' | 'agent' | 'user',
111
+ });
112
+ imported++;
113
+ }
114
+
115
+ return imported;
116
+ }