bikky 0.3.1 → 0.3.3

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 (342) hide show
  1. package/README.md +124 -35
  2. package/dist/cli.d.ts +1 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +7 -1
  5. package/dist/cli.js.map +1 -1
  6. package/dist/config.d.ts +22 -3
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +61 -6
  9. package/dist/config.js.map +1 -1
  10. package/dist/config.test.js +17 -9
  11. package/dist/config.test.js.map +1 -1
  12. package/dist/daemon/capture-policy.d.ts +95 -0
  13. package/dist/daemon/capture-policy.d.ts.map +1 -0
  14. package/dist/daemon/capture-policy.js +139 -0
  15. package/dist/daemon/capture-policy.js.map +1 -0
  16. package/dist/daemon/capture-policy.test.d.ts +2 -0
  17. package/dist/daemon/capture-policy.test.d.ts.map +1 -0
  18. package/dist/daemon/capture-policy.test.js +46 -0
  19. package/dist/daemon/capture-policy.test.js.map +1 -0
  20. package/dist/daemon/consolidation.d.ts.map +1 -1
  21. package/dist/daemon/consolidation.js +84 -98
  22. package/dist/daemon/consolidation.js.map +1 -1
  23. package/dist/daemon/episode-summary.d.ts +72 -0
  24. package/dist/daemon/episode-summary.d.ts.map +1 -0
  25. package/dist/daemon/episode-summary.js +208 -0
  26. package/dist/daemon/episode-summary.js.map +1 -0
  27. package/dist/daemon/episode-summary.test.d.ts +2 -0
  28. package/dist/daemon/episode-summary.test.d.ts.map +1 -0
  29. package/dist/daemon/episode-summary.test.js +101 -0
  30. package/dist/daemon/episode-summary.test.js.map +1 -0
  31. package/dist/daemon/extraction.d.ts +25 -0
  32. package/dist/daemon/extraction.d.ts.map +1 -1
  33. package/dist/daemon/extraction.js +244 -124
  34. package/dist/daemon/extraction.js.map +1 -1
  35. package/dist/daemon/extraction.test.d.ts +2 -0
  36. package/dist/daemon/extraction.test.d.ts.map +1 -0
  37. package/dist/daemon/extraction.test.js +106 -0
  38. package/dist/daemon/extraction.test.js.map +1 -0
  39. package/dist/daemon/loop.d.ts.map +1 -1
  40. package/dist/daemon/loop.js +8 -6
  41. package/dist/daemon/loop.js.map +1 -1
  42. package/dist/daemon/qdrant.d.ts +59 -8
  43. package/dist/daemon/qdrant.d.ts.map +1 -1
  44. package/dist/daemon/qdrant.js +74 -23
  45. package/dist/daemon/qdrant.js.map +1 -1
  46. package/dist/daemon/qdrant.test.js +2 -2
  47. package/dist/daemon/qdrant.test.js.map +1 -1
  48. package/dist/daemon/relations.d.ts +6 -1
  49. package/dist/daemon/relations.d.ts.map +1 -1
  50. package/dist/daemon/relations.js +44 -63
  51. package/dist/daemon/relations.js.map +1 -1
  52. package/dist/daemon/session-index.d.ts +60 -0
  53. package/dist/daemon/session-index.d.ts.map +1 -0
  54. package/dist/daemon/session-index.js +136 -0
  55. package/dist/daemon/session-index.js.map +1 -0
  56. package/dist/daemon/session-index.test.d.ts +2 -0
  57. package/dist/daemon/session-index.test.d.ts.map +1 -0
  58. package/dist/daemon/session-index.test.js +54 -0
  59. package/dist/daemon/session-index.test.js.map +1 -0
  60. package/dist/daemon/session-summary.d.ts +69 -0
  61. package/dist/daemon/session-summary.d.ts.map +1 -0
  62. package/dist/daemon/session-summary.js +200 -0
  63. package/dist/daemon/session-summary.js.map +1 -0
  64. package/dist/daemon/session-summary.test.d.ts +2 -0
  65. package/dist/daemon/session-summary.test.d.ts.map +1 -0
  66. package/dist/daemon/session-summary.test.js +160 -0
  67. package/dist/daemon/session-summary.test.js.map +1 -0
  68. package/dist/daemon/staleness.test.d.ts +7 -0
  69. package/dist/daemon/staleness.test.d.ts.map +1 -0
  70. package/dist/daemon/staleness.test.js +128 -0
  71. package/dist/daemon/staleness.test.js.map +1 -0
  72. package/dist/daemon/workstream-summary.d.ts +61 -0
  73. package/dist/daemon/workstream-summary.d.ts.map +1 -0
  74. package/dist/daemon/workstream-summary.js +220 -0
  75. package/dist/daemon/workstream-summary.js.map +1 -0
  76. package/dist/daemon/workstream-summary.test.d.ts +2 -0
  77. package/dist/daemon/workstream-summary.test.d.ts.map +1 -0
  78. package/dist/daemon/workstream-summary.test.js +86 -0
  79. package/dist/daemon/workstream-summary.test.js.map +1 -0
  80. package/dist/lib/qdrant-client.d.ts +6 -1
  81. package/dist/lib/qdrant-client.d.ts.map +1 -1
  82. package/dist/lib/qdrant-client.js +3 -4
  83. package/dist/lib/qdrant-client.js.map +1 -1
  84. package/dist/lib/qdrant-client.test.js +21 -2
  85. package/dist/lib/qdrant-client.test.js.map +1 -1
  86. package/dist/lifecycle.test.d.ts +8 -0
  87. package/dist/lifecycle.test.d.ts.map +1 -0
  88. package/dist/lifecycle.test.js +74 -0
  89. package/dist/lifecycle.test.js.map +1 -0
  90. package/dist/llm/embedding/index.d.ts +42 -0
  91. package/dist/llm/embedding/index.d.ts.map +1 -0
  92. package/dist/llm/embedding/index.js +78 -0
  93. package/dist/llm/embedding/index.js.map +1 -0
  94. package/dist/llm/embedding/index.test.d.ts +8 -0
  95. package/dist/llm/embedding/index.test.d.ts.map +1 -0
  96. package/dist/llm/embedding/index.test.js +100 -0
  97. package/dist/llm/embedding/index.test.js.map +1 -0
  98. package/dist/llm/embedding/providers/bedrock.d.ts +16 -0
  99. package/dist/llm/embedding/providers/bedrock.d.ts.map +1 -0
  100. package/dist/llm/embedding/providers/bedrock.js +90 -0
  101. package/dist/llm/embedding/providers/bedrock.js.map +1 -0
  102. package/dist/llm/embedding/providers/bedrock.test.d.ts +2 -0
  103. package/dist/llm/embedding/providers/bedrock.test.d.ts.map +1 -0
  104. package/dist/llm/embedding/providers/bedrock.test.js +24 -0
  105. package/dist/llm/embedding/providers/bedrock.test.js.map +1 -0
  106. package/dist/llm/embedding/providers/index.d.ts +9 -0
  107. package/dist/llm/embedding/providers/index.d.ts.map +1 -0
  108. package/dist/llm/embedding/providers/index.js +9 -0
  109. package/dist/llm/embedding/providers/index.js.map +1 -0
  110. package/dist/llm/embedding/providers/ollama.d.ts +6 -0
  111. package/dist/llm/embedding/providers/ollama.d.ts.map +1 -0
  112. package/dist/llm/embedding/providers/ollama.js +39 -0
  113. package/dist/llm/embedding/providers/ollama.js.map +1 -0
  114. package/dist/llm/embedding/providers/ollama.test.d.ts +2 -0
  115. package/dist/llm/embedding/providers/ollama.test.d.ts.map +1 -0
  116. package/dist/llm/embedding/providers/ollama.test.js +54 -0
  117. package/dist/llm/embedding/providers/ollama.test.js.map +1 -0
  118. package/dist/llm/embedding/providers/openai.d.ts +6 -0
  119. package/dist/llm/embedding/providers/openai.d.ts.map +1 -0
  120. package/dist/llm/embedding/providers/openai.js +44 -0
  121. package/dist/llm/embedding/providers/openai.js.map +1 -0
  122. package/dist/llm/embedding/providers/openai.test.d.ts +2 -0
  123. package/dist/llm/embedding/providers/openai.test.d.ts.map +1 -0
  124. package/dist/llm/embedding/providers/openai.test.js +48 -0
  125. package/dist/llm/embedding/providers/openai.test.js.map +1 -0
  126. package/dist/llm/embedding/providers/portkey.d.ts +15 -0
  127. package/dist/llm/embedding/providers/portkey.d.ts.map +1 -0
  128. package/dist/llm/embedding/providers/portkey.js +58 -0
  129. package/dist/llm/embedding/providers/portkey.js.map +1 -0
  130. package/dist/llm/embedding/providers/portkey.test.d.ts +2 -0
  131. package/dist/llm/embedding/providers/portkey.test.d.ts.map +1 -0
  132. package/dist/llm/embedding/providers/portkey.test.js +56 -0
  133. package/dist/llm/embedding/providers/portkey.test.js.map +1 -0
  134. package/dist/llm/embedding/registry.d.ts +14 -0
  135. package/dist/llm/embedding/registry.d.ts.map +1 -0
  136. package/dist/llm/embedding/registry.js +27 -0
  137. package/dist/llm/embedding/registry.js.map +1 -0
  138. package/dist/llm/embedding/registry.test.d.ts +7 -0
  139. package/dist/llm/embedding/registry.test.d.ts.map +1 -0
  140. package/dist/llm/embedding/registry.test.js +68 -0
  141. package/dist/llm/embedding/registry.test.js.map +1 -0
  142. package/dist/llm/embedding/types.d.ts +55 -0
  143. package/dist/llm/embedding/types.d.ts.map +1 -0
  144. package/dist/llm/embedding/types.js +12 -0
  145. package/dist/llm/embedding/types.js.map +1 -0
  146. package/dist/llm/errors.d.ts +95 -0
  147. package/dist/llm/errors.d.ts.map +1 -0
  148. package/dist/llm/errors.js +164 -0
  149. package/dist/llm/errors.js.map +1 -0
  150. package/dist/llm/errors.test.d.ts +2 -0
  151. package/dist/llm/errors.test.d.ts.map +1 -0
  152. package/dist/llm/errors.test.js +103 -0
  153. package/dist/llm/errors.test.js.map +1 -0
  154. package/dist/llm/fetch.d.ts +39 -0
  155. package/dist/llm/fetch.d.ts.map +1 -0
  156. package/dist/llm/fetch.js +52 -0
  157. package/dist/llm/fetch.js.map +1 -0
  158. package/dist/llm/index.d.ts +6 -3
  159. package/dist/llm/index.d.ts.map +1 -1
  160. package/dist/llm/index.js +2 -2
  161. package/dist/llm/index.js.map +1 -1
  162. package/dist/llm/inference/index.d.ts +39 -0
  163. package/dist/llm/inference/index.d.ts.map +1 -0
  164. package/dist/llm/inference/index.js +118 -0
  165. package/dist/llm/inference/index.js.map +1 -0
  166. package/dist/llm/inference/index.test.d.ts +6 -0
  167. package/dist/llm/inference/index.test.d.ts.map +1 -0
  168. package/dist/llm/inference/index.test.js +109 -0
  169. package/dist/llm/inference/index.test.js.map +1 -0
  170. package/dist/llm/inference/providers/bedrock.d.ts +18 -0
  171. package/dist/llm/inference/providers/bedrock.d.ts.map +1 -0
  172. package/dist/llm/inference/providers/bedrock.js +105 -0
  173. package/dist/llm/inference/providers/bedrock.js.map +1 -0
  174. package/dist/llm/inference/providers/bedrock.test.d.ts +2 -0
  175. package/dist/llm/inference/providers/bedrock.test.d.ts.map +1 -0
  176. package/dist/llm/inference/providers/bedrock.test.js +21 -0
  177. package/dist/llm/inference/providers/bedrock.test.js.map +1 -0
  178. package/dist/llm/inference/providers/index.d.ts +10 -0
  179. package/dist/llm/inference/providers/index.d.ts.map +1 -0
  180. package/dist/llm/inference/providers/index.js +10 -0
  181. package/dist/llm/inference/providers/index.js.map +1 -0
  182. package/dist/llm/inference/providers/ollama.d.ts +8 -0
  183. package/dist/llm/inference/providers/ollama.d.ts.map +1 -0
  184. package/dist/llm/inference/providers/ollama.js +63 -0
  185. package/dist/llm/inference/providers/ollama.js.map +1 -0
  186. package/dist/llm/inference/providers/ollama.test.d.ts +2 -0
  187. package/dist/llm/inference/providers/ollama.test.d.ts.map +1 -0
  188. package/dist/llm/inference/providers/ollama.test.js +57 -0
  189. package/dist/llm/inference/providers/ollama.test.js.map +1 -0
  190. package/dist/llm/inference/providers/openai.d.ts +11 -0
  191. package/dist/llm/inference/providers/openai.d.ts.map +1 -0
  192. package/dist/llm/inference/providers/openai.js +73 -0
  193. package/dist/llm/inference/providers/openai.js.map +1 -0
  194. package/dist/llm/inference/providers/openai.test.d.ts +2 -0
  195. package/dist/llm/inference/providers/openai.test.d.ts.map +1 -0
  196. package/dist/llm/inference/providers/openai.test.js +46 -0
  197. package/dist/llm/inference/providers/openai.test.js.map +1 -0
  198. package/dist/llm/inference/providers/portkey.d.ts +13 -0
  199. package/dist/llm/inference/providers/portkey.d.ts.map +1 -0
  200. package/dist/llm/inference/providers/portkey.js +80 -0
  201. package/dist/llm/inference/providers/portkey.js.map +1 -0
  202. package/dist/llm/inference/providers/portkey.test.d.ts +2 -0
  203. package/dist/llm/inference/providers/portkey.test.d.ts.map +1 -0
  204. package/dist/llm/inference/providers/portkey.test.js +48 -0
  205. package/dist/llm/inference/providers/portkey.test.js.map +1 -0
  206. package/dist/llm/inference/registry.d.ts +15 -0
  207. package/dist/llm/inference/registry.d.ts.map +1 -0
  208. package/dist/llm/inference/registry.js +28 -0
  209. package/dist/llm/inference/registry.js.map +1 -0
  210. package/dist/llm/inference/registry.test.d.ts +6 -0
  211. package/dist/llm/inference/registry.test.d.ts.map +1 -0
  212. package/dist/llm/inference/registry.test.js +63 -0
  213. package/dist/llm/inference/registry.test.js.map +1 -0
  214. package/dist/llm/inference/types.d.ts +84 -0
  215. package/dist/llm/inference/types.d.ts.map +1 -0
  216. package/dist/llm/inference/types.js +9 -0
  217. package/dist/llm/inference/types.js.map +1 -0
  218. package/dist/llm/telemetry.d.ts +25 -0
  219. package/dist/llm/telemetry.d.ts.map +1 -0
  220. package/dist/llm/telemetry.js +43 -0
  221. package/dist/llm/telemetry.js.map +1 -0
  222. package/dist/llm/telemetry.test.d.ts +5 -0
  223. package/dist/llm/telemetry.test.d.ts.map +1 -0
  224. package/dist/llm/telemetry.test.js +89 -0
  225. package/dist/llm/telemetry.test.js.map +1 -0
  226. package/dist/llm/types.d.ts +4 -37
  227. package/dist/llm/types.d.ts.map +1 -1
  228. package/dist/llm/types.js +4 -1
  229. package/dist/llm/types.js.map +1 -1
  230. package/dist/logger.d.ts +18 -3
  231. package/dist/logger.d.ts.map +1 -1
  232. package/dist/logger.js +102 -20
  233. package/dist/logger.js.map +1 -1
  234. package/dist/logger.test.d.ts +5 -0
  235. package/dist/logger.test.d.ts.map +1 -0
  236. package/dist/logger.test.js +103 -0
  237. package/dist/logger.test.js.map +1 -0
  238. package/dist/mcp/api.d.ts +15 -1
  239. package/dist/mcp/api.d.ts.map +1 -1
  240. package/dist/mcp/api.js +44 -19
  241. package/dist/mcp/api.js.map +1 -1
  242. package/dist/mcp/api.test.d.ts +6 -0
  243. package/dist/mcp/api.test.d.ts.map +1 -0
  244. package/dist/mcp/api.test.js +130 -0
  245. package/dist/mcp/api.test.js.map +1 -0
  246. package/dist/mcp/helpers.d.ts +1 -0
  247. package/dist/mcp/helpers.d.ts.map +1 -1
  248. package/dist/mcp/helpers.js +62 -6
  249. package/dist/mcp/helpers.js.map +1 -1
  250. package/dist/mcp/helpers.test.js +71 -10
  251. package/dist/mcp/helpers.test.js.map +1 -1
  252. package/dist/mcp/index.d.ts +7 -1
  253. package/dist/mcp/index.d.ts.map +1 -1
  254. package/dist/mcp/index.js +46 -21
  255. package/dist/mcp/index.js.map +1 -1
  256. package/dist/mcp/taxonomy.d.ts +251 -31
  257. package/dist/mcp/taxonomy.d.ts.map +1 -1
  258. package/dist/mcp/taxonomy.js +603 -171
  259. package/dist/mcp/taxonomy.js.map +1 -1
  260. package/dist/mcp/taxonomy.test.d.ts +1 -1
  261. package/dist/mcp/taxonomy.test.js +141 -302
  262. package/dist/mcp/taxonomy.test.js.map +1 -1
  263. package/dist/mcp/tools.d.ts +1 -1
  264. package/dist/mcp/tools.d.ts.map +1 -1
  265. package/dist/mcp/tools.integration.itest.d.ts +23 -0
  266. package/dist/mcp/tools.integration.itest.d.ts.map +1 -0
  267. package/dist/mcp/tools.integration.itest.js +172 -0
  268. package/dist/mcp/tools.integration.itest.js.map +1 -0
  269. package/dist/mcp/tools.js +422 -357
  270. package/dist/mcp/tools.js.map +1 -1
  271. package/dist/mcp/tools.test.d.ts +16 -0
  272. package/dist/mcp/tools.test.d.ts.map +1 -0
  273. package/dist/mcp/tools.test.js +472 -0
  274. package/dist/mcp/tools.test.js.map +1 -0
  275. package/dist/mcp/types.d.ts +63 -8
  276. package/dist/mcp/types.d.ts.map +1 -1
  277. package/dist/prompts/brief.d.ts +19 -0
  278. package/dist/prompts/brief.d.ts.map +1 -0
  279. package/dist/prompts/brief.js +67 -0
  280. package/dist/prompts/brief.js.map +1 -0
  281. package/dist/prompts/contradiction.d.ts +24 -0
  282. package/dist/prompts/contradiction.d.ts.map +1 -0
  283. package/dist/prompts/contradiction.js +73 -0
  284. package/dist/prompts/contradiction.js.map +1 -0
  285. package/dist/prompts/distill.d.ts +21 -0
  286. package/dist/prompts/distill.d.ts.map +1 -0
  287. package/dist/prompts/distill.js +92 -0
  288. package/dist/prompts/distill.js.map +1 -0
  289. package/dist/prompts/episode-summary.d.ts +15 -0
  290. package/dist/prompts/episode-summary.d.ts.map +1 -0
  291. package/dist/prompts/episode-summary.js +60 -0
  292. package/dist/prompts/episode-summary.js.map +1 -0
  293. package/dist/prompts/extraction.d.ts +14 -0
  294. package/dist/prompts/extraction.d.ts.map +1 -0
  295. package/dist/prompts/extraction.js +110 -0
  296. package/dist/prompts/extraction.js.map +1 -0
  297. package/dist/prompts/index.d.ts +52 -0
  298. package/dist/prompts/index.d.ts.map +1 -0
  299. package/dist/prompts/index.js +104 -0
  300. package/dist/prompts/index.js.map +1 -0
  301. package/dist/prompts/prompts.test.d.ts +8 -0
  302. package/dist/prompts/prompts.test.d.ts.map +1 -0
  303. package/dist/prompts/prompts.test.js +140 -0
  304. package/dist/prompts/prompts.test.js.map +1 -0
  305. package/dist/prompts/relations.d.ts +17 -0
  306. package/dist/prompts/relations.d.ts.map +1 -0
  307. package/dist/prompts/relations.js +72 -0
  308. package/dist/prompts/relations.js.map +1 -0
  309. package/dist/prompts/workstream-summary.d.ts +17 -0
  310. package/dist/prompts/workstream-summary.d.ts.map +1 -0
  311. package/dist/prompts/workstream-summary.js +72 -0
  312. package/dist/prompts/workstream-summary.js.map +1 -0
  313. package/dist/render.d.ts +41 -0
  314. package/dist/render.d.ts.map +1 -0
  315. package/dist/render.js +185 -0
  316. package/dist/render.js.map +1 -0
  317. package/dist/render.test.d.ts +8 -0
  318. package/dist/render.test.d.ts.map +1 -0
  319. package/dist/render.test.js +243 -0
  320. package/dist/render.test.js.map +1 -0
  321. package/docs/diagrams/architecture.svg +87 -0
  322. package/docs/diagrams/team-memory.svg +250 -0
  323. package/docs/screenshots/dashboard.png +0 -0
  324. package/docs/screenshots/graph.png +0 -0
  325. package/docs/screenshots/memory.png +0 -0
  326. package/package.json +12 -3
  327. package/dist/llm/embedding.d.ts +0 -13
  328. package/dist/llm/embedding.d.ts.map +0 -1
  329. package/dist/llm/embedding.js +0 -127
  330. package/dist/llm/embedding.js.map +0 -1
  331. package/dist/llm/embedding.test.d.ts +0 -8
  332. package/dist/llm/embedding.test.d.ts.map +0 -1
  333. package/dist/llm/embedding.test.js +0 -117
  334. package/dist/llm/embedding.test.js.map +0 -1
  335. package/dist/llm/inference.d.ts +0 -12
  336. package/dist/llm/inference.d.ts.map +0 -1
  337. package/dist/llm/inference.js +0 -146
  338. package/dist/llm/inference.js.map +0 -1
  339. package/dist/llm/inference.test.d.ts +0 -8
  340. package/dist/llm/inference.test.d.ts.map +0 -1
  341. package/dist/llm/inference.test.js +0 -117
  342. package/dist/llm/inference.test.js.map +0 -1
@@ -1,223 +1,655 @@
1
1
  /**
2
- * Memory Taxonomy — Single source of truth for all classification axes.
2
+ * Bikky memory ontology.
3
3
  *
4
- * Four orthogonal axes classify every fact:
5
- * category topic/subject matter (what the fact is about)
6
- * domain — life scope (work vs personal context)
7
- * kind — epistemic type (how the knowledge exists)
8
- * source — provenance (who/what created this fact)
4
+ * Ontology v2 separates ownership boundaries from semantic meaning:
5
+ * workspace -> domain -> repo/project/surface -> workstream -> episode -> memory objects.
9
6
  */
10
- // ─── Category: topic/subject matter ─────────────────────────────────────────
7
+ // ---------------------------------------------------------------------------
8
+ // Categories: subject matter
9
+ // ---------------------------------------------------------------------------
11
10
  export const CATEGORIES = {
11
+ codebase: {
12
+ description: "Repository structure, modules, important files, APIs, build/test commands, and code navigation knowledge.",
13
+ examples: [
14
+ "The auth middleware lives in src/server/auth.ts.",
15
+ "Run npm test -- --runInBand for flaky integration tests.",
16
+ ],
17
+ },
12
18
  infrastructure: {
13
- description: "Services, ports, configs, databases, deployments, environments",
14
- extractionHint: "Look for: service names, ports, hosts, connection strings, database engines, cluster details, deployment targets, environment variables, config values",
19
+ description: "Cloud, deployment, runtime, secrets, queues, databases, CI/CD, and environment topology.",
15
20
  examples: [
16
- { content: "ClickHouse runs on port 8123 in production clusters", entities: ["clickhouse"], confidence: 0.95, importance: 0.8 },
17
- { content: "The dbt project uses ReplacingMergeTree engine for dedup tables", entities: ["dbt", "clickhouse"], confidence: 0.9, importance: 0.7 },
18
- { content: "Redis cache is on redis-prod.internal:6379 with 30-min TTL", entities: ["redis"], confidence: 0.9, importance: 0.8 },
21
+ "Production runs on a Qdrant cluster (Cloud or self-hosted) for vector storage.",
22
+ "Deployments are promoted through GitHub Actions.",
19
23
  ],
20
24
  },
21
- decisions: {
22
- description: "Architectural decisions, technology choices, trade-offs, with who decided and why",
23
- extractionHint: "Look for: 'decided', 'chose', 'went with', 'instead of', 'because', trade-off discussions, architecture choices, technology selections",
25
+ operations: {
26
+ description: "Runbooks, incident handling, maintenance procedures, debugging steps, and operational gotchas.",
24
27
  examples: [
25
- { content: "Team decided to use JWT for service-to-service auth instead of mTLS", entities: ["auth", "jwt"], confidence: 0.9, importance: 0.85 },
26
- { content: "Team chose Qdrant over Pinecone for vector storage due to self-hosting option", entities: ["qdrant", "pinecone"], confidence: 0.95, importance: 0.8 },
28
+ "Restart the worker after changing queue visibility timeout.",
29
+ "If migrations hang, check the advisory lock table first.",
27
30
  ],
28
31
  },
29
- observation: {
30
- description: "Errors encountered, quirks, workarounds, debugging findings, gotchas, behavioral patterns",
31
- extractionHint: "Look for: error messages, debugging steps, 'turns out', 'the issue was', workarounds, unexpected behavior, gotchas, caveats",
32
+ decisions: {
33
+ description: "Architecture, product, process, and technical decisions with durable rationale.",
32
34
  examples: [
33
- { content: "ClickHouse OPTIMIZE FINAL is slow on large tables — use OPTIMIZE DEDUPLICATE instead", entities: ["clickhouse"], confidence: 0.9, importance: 0.7 },
34
- { content: "Node 25 fetch() doesn't support AbortSignal.timeout() in some edge cases", entities: ["node"], confidence: 0.7, importance: 0.5 },
35
+ "Use workspace_id as the access boundary instead of overloading domain.",
36
+ "Keep telemetry out of normal semantic recall.",
35
37
  ],
36
38
  },
37
- preferences: {
38
- description: "User/team preferences, working style, conventions, opinions, personal tastes",
39
- extractionHint: "Look for: 'prefer', 'like', 'want', 'always use', conventions, style guides, opinions, personal choices, hobbies, interests",
39
+ product_domain: {
40
+ description: "Product concepts, business rules, user workflows, domain vocabulary, and market assumptions.",
40
41
  examples: [
41
- { content: "User prefers dark mode and concise responses under 3 sentences", entities: ["user"], confidence: 0.85, importance: 0.3 },
42
- { content: "Code style: kebab-case for file names, camelCase for JS variables", entities: [], confidence: 0.8, importance: 0.4 },
42
+ "A workstream is the durable continuity unit for long-running tasks.",
43
+ "Recall quality should be measured by downstream usefulness, not just similarity.",
43
44
  ],
44
45
  },
45
46
  projects: {
46
- description: "What's in progress, blocked, completed, project structure, goals, personal endeavors",
47
- extractionHint: "Look for: task progress, blockers, completions, branch names, deployment status, milestones, goals, project structure, hobbies, personal projects",
47
+ description: "Project goals, milestones, current state, open questions, blockers, and active workstreams.",
48
+ examples: [
49
+ "The capture-policy RPI is implementing ontology v2 first.",
50
+ "The UI smoke suite is tracked in bikky-dev/bikky#13.",
51
+ ],
52
+ },
53
+ people: {
54
+ description: "Ownership, roles, collaboration patterns, responsibilities, and team preferences.",
55
+ examples: [
56
+ "Saber prefers concise implementation plans before code changes.",
57
+ "The platform team owns the deploy workflow.",
58
+ ],
59
+ },
60
+ preferences: {
61
+ description: "User, team, or workspace preferences about style, tooling, defaults, and interaction patterns.",
48
62
  examples: [
49
- { content: "The memory extraction daemon pipeline is being built", entities: ["bikky", "daemon"], confidence: 0.95, importance: 0.6 },
50
- { content: "User is growing tomatoes and herbs in the backyard garden", entities: ["user", "garden"], confidence: 0.85, importance: 0.4 },
63
+ "Prefer Node's built-in test runner for this repo.",
64
+ "Default new memory captures to software_engineering.",
51
65
  ],
52
66
  },
53
- team: {
54
- description: "People, roles, relationships, organizational structure, contacts",
55
- extractionHint: "Look for: names, titles, roles, reporting lines, team membership, expertise areas, contact details, who owns what",
67
+ observations: {
68
+ description: "Validated observations, troubleshooting evidence, behavioral notes, and learned facts that do not fit a narrower category.",
56
69
  examples: [
57
- { content: "Alice is the lead engineer on the platform team", entities: ["alice", "platform"], confidence: 0.95, importance: 0.7 },
58
- { content: "Alex handles DevOps and Kubernetes cluster management", entities: ["alex", "devops", "kubernetes"], confidence: 0.9, importance: 0.6 },
70
+ "The current ESLint config is incompatible with ESLint v9.",
71
+ "The dashboard shows stale facts separately from verified current facts.",
59
72
  ],
60
73
  },
61
74
  };
62
- // ─── Domain: life scope ─────────────────────────────────────────────────────
75
+ export const DEFAULT_CATEGORY = "observations";
76
+ // ---------------------------------------------------------------------------
77
+ // Domains: activity / knowledge profiles
78
+ // ---------------------------------------------------------------------------
63
79
  export const DOMAINS = {
64
- work: { description: "Engineering, company, professional context" },
65
- personal: { description: "Life, hobbies, health, family, personal projects" },
80
+ software_engineering: {
81
+ description: "Coding-agent work: repositories, code changes, architecture, infrastructure, debugging, tests, CI, and developer workflow.",
82
+ defaultCategories: [
83
+ "codebase",
84
+ "infrastructure",
85
+ "operations",
86
+ "decisions",
87
+ "projects",
88
+ "preferences",
89
+ "observations",
90
+ ],
91
+ },
92
+ product_strategy: {
93
+ description: "Product direction, positioning, roadmap tradeoffs, customer problems, metrics, and market learning.",
94
+ defaultCategories: [
95
+ "product_domain",
96
+ "decisions",
97
+ "projects",
98
+ "people",
99
+ "preferences",
100
+ "observations",
101
+ ],
102
+ },
103
+ business_operations: {
104
+ description: "Business process, vendors, finance, legal/admin operations, recurring procedures, and ownership.",
105
+ defaultCategories: [
106
+ "operations",
107
+ "decisions",
108
+ "projects",
109
+ "people",
110
+ "preferences",
111
+ "observations",
112
+ ],
113
+ },
114
+ research: {
115
+ description: "Research questions, sources, hypotheses, experiment findings, synthesis, and reusable insights.",
116
+ defaultCategories: [
117
+ "product_domain",
118
+ "decisions",
119
+ "projects",
120
+ "preferences",
121
+ "observations",
122
+ ],
123
+ },
124
+ personal_productivity: {
125
+ description: "Individual productivity, habits, planning preferences, reminders, and personal operating context.",
126
+ defaultCategories: [
127
+ "operations",
128
+ "projects",
129
+ "people",
130
+ "preferences",
131
+ "observations",
132
+ ],
133
+ },
134
+ };
135
+ export const DEFAULT_DOMAIN = "software_engineering";
136
+ // ---------------------------------------------------------------------------
137
+ // Layers: hierarchy placement
138
+ // ---------------------------------------------------------------------------
139
+ export const LAYERS = {
140
+ workspace: {
141
+ description: "Ownership, tenancy, access policy, sharing, redaction, retention, and quotas.",
142
+ },
143
+ domain: {
144
+ description: "Semantic profile that controls vocabulary, prompts, categories, ranking, and capture policy.",
145
+ },
146
+ surface: {
147
+ description: "Concrete operating surface such as a repo, project, package, service, branch, or channel.",
148
+ },
149
+ workstream: {
150
+ description: "Primary durable continuity key for a long-running objective or task.",
151
+ },
152
+ episode: {
153
+ description: "Coherent segment of activity within a session or transcript.",
154
+ },
155
+ memory_object: {
156
+ description: "A fact, summary, distilled learning, relation, or telemetry object.",
157
+ },
66
158
  };
67
- export const DEFAULT_DOMAIN = "work";
68
- // ─── Kind: epistemic type ───────────────────────────────────────────────────
159
+ // ---------------------------------------------------------------------------
160
+ // Kinds and subtypes: object shape
161
+ // ---------------------------------------------------------------------------
69
162
  export const KINDS = {
70
- fact: { description: "Atomic declarative assertion — the default" },
71
- summary: { description: "Compressed narrative of a session or time period" },
72
- distilled: { description: "Second-order pattern derived from multiple summaries" },
73
- relation: { description: "Typed edge between two entities (from type → to)" },
163
+ fact: {
164
+ description: "Atomic, durable memory that should be retrievable independently.",
165
+ examples: [
166
+ "The daemon stores extracted coding-agent observations in Qdrant.",
167
+ "The UI package uses Vite and Node's built-in test runner.",
168
+ ],
169
+ },
170
+ summary: {
171
+ description: "Compressed representation of a session index, coherent episode, or current workstream state.",
172
+ examples: [
173
+ "Episode summary of a coherent implementation task.",
174
+ "Current-state summary for a workstream.",
175
+ ],
176
+ },
177
+ distilled: {
178
+ description: "Pattern, convention, failure mode, or reusable learning synthesized from multiple memories.",
179
+ examples: [
180
+ "Prefer explicit workspace filters for scoped team memory.",
181
+ "Missing Qdrant payload indexes surface as query failures.",
182
+ ],
183
+ },
184
+ relation: {
185
+ description: "Typed edge between entities; relation_type carries the edge label.",
186
+ examples: [
187
+ "bikky -> uses -> qdrant",
188
+ "workspace_id -> represents -> access boundary",
189
+ ],
190
+ },
191
+ telemetry: {
192
+ description: "Memory-use, feedback, or outcome metadata used for product quality and operations; excluded from normal semantic recall.",
193
+ examples: [
194
+ "A recall event returned three facts for session abc.",
195
+ "A user marked a fact useful.",
196
+ ],
197
+ },
74
198
  };
75
- export const DEFAULT_KIND = "fact";
76
- // ─── Source: provenance ─────────────────────────────────────────────────────
199
+ export const MEMORY_SUBTYPES = {
200
+ fact: [
201
+ "codebase_map",
202
+ "architecture_decision",
203
+ "infra_topology",
204
+ "access_pattern",
205
+ "deployment_procedure",
206
+ "operational_procedure",
207
+ "domain_rule",
208
+ "troubleshooting_gotcha",
209
+ "preference",
210
+ "ownership",
211
+ ],
212
+ summary: ["session_index", "episode", "workstream"],
213
+ distilled: [
214
+ "runbook_candidate",
215
+ "failure_mode",
216
+ "convention",
217
+ "architecture_pattern",
218
+ "product_insight",
219
+ ],
220
+ relation: [],
221
+ telemetry: ["recall_event", "feedback_event", "outcome_event", "aggregate_rollup"],
222
+ };
223
+ export const DEFAULT_MEMORY_SUBTYPE_BY_KIND = {
224
+ fact: "codebase_map",
225
+ summary: "episode",
226
+ distilled: "convention",
227
+ relation: null,
228
+ telemetry: "recall_event",
229
+ };
230
+ export const MEMORY_SUBTYPE_DEFAULT_CATEGORY = {
231
+ codebase_map: "codebase",
232
+ architecture_decision: "decisions",
233
+ infra_topology: "infrastructure",
234
+ access_pattern: "infrastructure",
235
+ deployment_procedure: "operations",
236
+ operational_procedure: "operations",
237
+ domain_rule: "product_domain",
238
+ troubleshooting_gotcha: "operations",
239
+ preference: "preferences",
240
+ ownership: "people",
241
+ session_index: "projects",
242
+ episode: "projects",
243
+ workstream: "projects",
244
+ runbook_candidate: "operations",
245
+ failure_mode: "operations",
246
+ convention: "observations",
247
+ architecture_pattern: "decisions",
248
+ product_insight: "product_domain",
249
+ recall_event: "observations",
250
+ feedback_event: "observations",
251
+ outcome_event: "observations",
252
+ aggregate_rollup: "observations",
253
+ };
254
+ export const MEMORY_SUBTYPE_DEFAULT_LAYER = {
255
+ codebase_map: "surface",
256
+ architecture_decision: "surface",
257
+ infra_topology: "surface",
258
+ access_pattern: "surface",
259
+ deployment_procedure: "surface",
260
+ operational_procedure: "surface",
261
+ domain_rule: "domain",
262
+ troubleshooting_gotcha: "surface",
263
+ preference: "domain",
264
+ ownership: "surface",
265
+ session_index: "episode",
266
+ episode: "episode",
267
+ workstream: "workstream",
268
+ runbook_candidate: "workstream",
269
+ failure_mode: "workstream",
270
+ convention: "domain",
271
+ architecture_pattern: "domain",
272
+ product_insight: "domain",
273
+ recall_event: "memory_object",
274
+ feedback_event: "memory_object",
275
+ outcome_event: "memory_object",
276
+ aggregate_rollup: "workspace",
277
+ };
278
+ // ---------------------------------------------------------------------------
279
+ // Provenance
280
+ // ---------------------------------------------------------------------------
77
281
  export const SOURCES = {
78
- agent: { description: "Stored by an agent via MCP memory_store tool" },
79
- daemon: { description: "Extracted by the background daemon pipeline" },
80
- system: { description: "Generated by system processes (distillation, session summaries)" },
81
- user: { description: "Explicitly requested by the user (manual corrections, direct input)" },
82
- docs: { description: "Indexed from documentation (knowledge base)" },
282
+ agent: {
283
+ description: "Captured from an interactive agent tool call.",
284
+ },
285
+ daemon: {
286
+ description: "Captured automatically by the local Bikky daemon.",
287
+ },
288
+ system: {
289
+ description: "Generated by Bikky maintenance, migration, or lifecycle code.",
290
+ },
291
+ user: {
292
+ description: "Created or corrected directly by a user.",
293
+ },
294
+ docs: {
295
+ description: "Imported from documentation or explicit source material.",
296
+ },
83
297
  };
298
+ export const DEFAULT_KIND = "fact";
84
299
  export const DEFAULT_SOURCE = "agent";
85
- // ─── Decay configuration ────────────────────────────────────────────────────
86
- const FACT_DECAY = {
87
- "observation.work": 45,
88
- "observation.personal": 180,
89
- "infrastructure.work": 60,
90
- "infrastructure.personal": 180,
91
- "decisions.*": 120,
92
- "preferences.*": 365,
93
- "projects.work": 90,
94
- "projects.personal": 180,
95
- "team.*": 365,
96
- };
300
+ export const STALENESS_DAYS = 30;
97
301
  export const DECAY_DEFAULT_HALF_LIFE = 90;
98
- export function getDecayHalfLife(opts = {}) {
99
- const { kind, category, domain } = opts;
100
- if (kind === "summary" || kind === "distilled")
101
- return null;
102
- if (kind === "relation")
103
- return 180;
104
- const key = `${category ?? "observation"}.${domain ?? DEFAULT_DOMAIN}`;
105
- const keyVal = FACT_DECAY[key];
106
- if (keyVal !== undefined)
107
- return keyVal;
108
- const catKey = `${category ?? "observation"}.*`;
109
- const catVal = FACT_DECAY[catKey];
110
- if (catVal !== undefined)
111
- return catVal;
112
- return DECAY_DEFAULT_HALF_LIFE;
113
- }
114
- // Legacy flat map for old code paths
302
+ export const THRESHOLD_DUPLICATE = 0.92;
303
+ export const THRESHOLD_RELATED = 0.8;
304
+ // ---------------------------------------------------------------------------
305
+ // Decay policy: half-life in days by category + domain profile
306
+ // ---------------------------------------------------------------------------
115
307
  export const DECAY_HALF_LIFE = {
116
- infrastructure: 60,
117
- projects: 90,
118
- decisions: 120,
119
- observation: 45,
120
- personal: 365,
121
- preferences: 365,
122
- team: 365,
123
- relation: 180,
124
- session_summary: null,
125
- distilled: null,
308
+ // Software-engineering defaults.
309
+ "codebase.software_engineering": 120,
310
+ "infrastructure.software_engineering": 60,
311
+ "operations.software_engineering": 60,
312
+ "decisions.software_engineering": 180,
313
+ "product_domain.software_engineering": 120,
314
+ "projects.software_engineering": 45,
315
+ "people.software_engineering": 120,
316
+ "preferences.software_engineering": 180,
317
+ "observations.software_engineering": 45,
318
+ // Other domain profiles.
319
+ "product_domain.product_strategy": 120,
320
+ "decisions.product_strategy": 180,
321
+ "projects.product_strategy": 60,
322
+ "people.product_strategy": 120,
323
+ "preferences.product_strategy": 180,
324
+ "observations.product_strategy": 60,
325
+ "operations.business_operations": 120,
326
+ "decisions.business_operations": 180,
327
+ "projects.business_operations": 60,
328
+ "people.business_operations": 180,
329
+ "preferences.business_operations": 180,
330
+ "observations.business_operations": 90,
331
+ "product_domain.research": 120,
332
+ "decisions.research": 180,
333
+ "projects.research": 60,
334
+ "preferences.research": 180,
335
+ "observations.research": 90,
336
+ "operations.personal_productivity": 90,
337
+ "projects.personal_productivity": 45,
338
+ "people.personal_productivity": 180,
339
+ "preferences.personal_productivity": 180,
340
+ "observations.personal_productivity": 45,
126
341
  };
127
- // ─── Staleness ──────────────────────────────────────────────────────────────
128
- export const STALENESS_DAYS = 30;
129
- // ─── Similarity thresholds ──────────────────────────────────────────────────
130
- export const THRESHOLD_DUPLICATE = 0.92;
131
- export const THRESHOLD_RELATED = 0.80;
132
- // ─── Qdrant indexes ────────────────────────────────────────────────────────
342
+ // ---------------------------------------------------------------------------
343
+ // Qdrant payload indexes
344
+ // ---------------------------------------------------------------------------
133
345
  export const QDRANT_INDEXES = [
134
346
  { field_name: "category", field_schema: "keyword" },
135
347
  { field_name: "domain", field_schema: "keyword" },
136
348
  { field_name: "kind", field_schema: "keyword" },
349
+ { field_name: "memory_subtype", field_schema: "keyword" },
137
350
  { field_name: "source", field_schema: "keyword" },
138
- { field_name: "entities", field_schema: "keyword" },
139
- { field_name: "content_hash", field_schema: "keyword" },
140
- { field_name: "from_entity", field_schema: "keyword" },
141
- { field_name: "to_entity", field_schema: "keyword" },
142
- { field_name: "relation_type", field_schema: "keyword" },
143
- { field_name: "superseded_by", field_schema: "keyword" },
351
+ { field_name: "workspace_id", field_schema: "keyword" },
352
+ { field_name: "actor_id", field_schema: "keyword" },
353
+ { field_name: "review_status", field_schema: "keyword" },
354
+ { field_name: "created_at", field_schema: "datetime" },
355
+ { field_name: "updated_at", field_schema: "datetime" },
356
+ { field_name: "last_seen_at", field_schema: "datetime" },
357
+ { field_name: "stale_after", field_schema: "datetime" },
144
358
  { field_name: "session_id", field_schema: "keyword" },
145
- { field_name: "last_reinforced_at", field_schema: "datetime" },
146
- { field_name: "last_verified_at", field_schema: "datetime" },
359
+ { field_name: "episode_id", field_schema: "keyword" },
360
+ { field_name: "workstream_key", field_schema: "keyword" },
361
+ { field_name: "task_key", field_schema: "keyword" },
362
+ { field_name: "repo", field_schema: "keyword" },
363
+ { field_name: "branch", field_schema: "keyword" },
364
+ { field_name: "reviewed", field_schema: "bool" },
365
+ { field_name: "verified", field_schema: "bool" },
366
+ { field_name: "superseded", field_schema: "bool" },
367
+ { field_name: "useful_feedback_count", field_schema: "integer" },
368
+ { field_name: "not_useful_feedback_count", field_schema: "integer" },
369
+ { field_name: "recall_count", field_schema: "integer" },
370
+ { field_name: "last_recalled_at", field_schema: "datetime" },
147
371
  ];
148
- // ─── Source value migration (old → new) ─────────────────────────────────────
149
- export const SOURCE_MIGRATION = {
150
- conversation: "agent",
151
- task: "agent",
152
- observation: "agent",
153
- manual: "user",
154
- cortex: "daemon",
155
- };
156
- // ─── Normalization helpers ──────────────────────────────────────────────────
157
- export function normalizeCategory(cat) {
158
- const lower = String(cat).toLowerCase().trim();
159
- if (lower in CATEGORIES)
160
- return lower;
161
- if (lower === "personal")
162
- return "preferences";
163
- if (lower === "session_summary")
164
- return "projects";
165
- if (lower === "distilled")
166
- return "observation";
167
- if (lower === "relation")
168
- return "team";
169
- if (lower.includes("infra"))
372
+ function normalizeToken(value) {
373
+ return String(value ?? "")
374
+ .trim()
375
+ .toLowerCase()
376
+ .replace(/[\s-]+/g, "_");
377
+ }
378
+ export function normalizeText(text) {
379
+ return text.trim().replace(/\s+/g, " ");
380
+ }
381
+ export function normalizeCategory(category) {
382
+ const normalized = normalizeToken(category);
383
+ if (normalized in CATEGORIES) {
384
+ return normalized;
385
+ }
386
+ if (normalized.includes("infra"))
170
387
  return "infrastructure";
171
- if (lower.includes("decision"))
388
+ if (normalized.includes("decision"))
172
389
  return "decisions";
173
- if (lower.includes("observ") || lower.includes("error"))
174
- return "observation";
175
- if (lower.includes("prefer"))
176
- return "preferences";
177
- if (lower.includes("project"))
178
- return "projects";
179
- if (lower.includes("team") || lower.includes("people"))
180
- return "team";
181
- return "observation";
182
- }
183
- export function normalizeDomain(d) {
184
- if (!d)
185
- return DEFAULT_DOMAIN;
186
- const lower = String(d).toLowerCase().trim();
187
- if (lower in DOMAINS)
188
- return lower;
189
- if (lower.includes("personal") || lower.includes("life") || lower.includes("home"))
190
- return "personal";
390
+ if (normalized.includes("operation") || normalized.includes("runbook"))
391
+ return "operations";
392
+ if (normalized.includes("owner") || normalized.includes("people"))
393
+ return "people";
394
+ if (normalized.includes("product") || normalized.includes("domain"))
395
+ return "product_domain";
396
+ if (normalized.includes("repo") || normalized.includes("code"))
397
+ return "codebase";
398
+ return DEFAULT_CATEGORY;
399
+ }
400
+ export function normalizeDomain(domain) {
401
+ const normalized = normalizeToken(domain);
402
+ if (normalized in DOMAINS) {
403
+ return normalized;
404
+ }
191
405
  return DEFAULT_DOMAIN;
192
406
  }
193
- export function normalizeKind(k) {
194
- if (!k)
195
- return DEFAULT_KIND;
196
- const lower = String(k).toLowerCase().trim();
197
- if (lower in KINDS)
198
- return lower;
199
- if (lower.includes("summar"))
407
+ export function normalizeKind(kind) {
408
+ const normalized = normalizeToken(kind);
409
+ if (normalized in KINDS) {
410
+ return normalized;
411
+ }
412
+ if (normalized.includes("summar"))
200
413
  return "summary";
201
- if (lower.includes("distil"))
414
+ if (normalized.includes("distill"))
202
415
  return "distilled";
203
- if (lower.includes("relat") || lower.includes("edge"))
416
+ if (normalized.includes("relation") || normalized.includes("edge"))
204
417
  return "relation";
205
- return DEFAULT_KIND;
206
- }
207
- export function normalizeSource(s) {
208
- if (!s)
209
- return DEFAULT_SOURCE;
210
- const lower = String(s).toLowerCase().trim();
211
- if (lower in SOURCES)
212
- return lower;
213
- const migrated = SOURCE_MIGRATION[lower];
214
- if (migrated)
215
- return migrated;
418
+ if (normalized.includes("telemetry") || normalized.includes("feedback_event"))
419
+ return "telemetry";
420
+ return "fact";
421
+ }
422
+ export function normalizeSource(source) {
423
+ const normalized = normalizeToken(source);
424
+ if (normalized in SOURCES) {
425
+ return normalized;
426
+ }
216
427
  return DEFAULT_SOURCE;
217
428
  }
218
- // ─── Value arrays for z.enum consumption ────────────────────────────────────
219
- export const categoryValues = () => Object.keys(CATEGORIES);
220
- export const domainValues = () => Object.keys(DOMAINS);
221
- export const kindValues = () => Object.keys(KINDS);
222
- export const sourceValues = () => Object.keys(SOURCES);
429
+ export function normalizeLayer(layer) {
430
+ const normalized = normalizeToken(layer);
431
+ if (normalized in LAYERS) {
432
+ return normalized;
433
+ }
434
+ return null;
435
+ }
436
+ export function normalizeMemorySubtype(kind, subtype) {
437
+ const normalizedKind = normalizeKind(kind);
438
+ const normalizedSubtype = normalizeToken(subtype);
439
+ if (!normalizedSubtype)
440
+ return null;
441
+ const allowed = MEMORY_SUBTYPES[normalizedKind];
442
+ if (allowed.includes(normalizedSubtype)) {
443
+ return normalizedSubtype;
444
+ }
445
+ return null;
446
+ }
447
+ export function validateMemorySubtype(kind, subtype) {
448
+ if (!subtype)
449
+ return null;
450
+ const normalized = normalizeMemorySubtype(kind, subtype);
451
+ if (normalized)
452
+ return normalized;
453
+ const normalizedKind = normalizeKind(kind);
454
+ const allowed = MEMORY_SUBTYPES[normalizedKind];
455
+ const allowedText = allowed.length > 0 ? allowed.join(", ") : "none";
456
+ throw new Error(`Invalid memory_subtype "${subtype}" for kind "${normalizedKind}". Allowed subtypes: ${allowedText}.`);
457
+ }
458
+ export function defaultMemorySubtypeForKind(kind) {
459
+ return DEFAULT_MEMORY_SUBTYPE_BY_KIND[normalizeKind(kind)];
460
+ }
461
+ export function categoryForMemorySubtype(subtype) {
462
+ const normalized = normalizeToken(subtype);
463
+ if (normalized in MEMORY_SUBTYPE_DEFAULT_CATEGORY) {
464
+ return MEMORY_SUBTYPE_DEFAULT_CATEGORY[normalized];
465
+ }
466
+ return null;
467
+ }
468
+ export function layerForMemorySubtype(subtype) {
469
+ const normalized = normalizeToken(subtype);
470
+ if (normalized in MEMORY_SUBTYPE_DEFAULT_LAYER) {
471
+ return MEMORY_SUBTYPE_DEFAULT_LAYER[normalized];
472
+ }
473
+ return null;
474
+ }
475
+ export function normalizeEntities(entities) {
476
+ const seen = new Set();
477
+ const result = [];
478
+ for (const entity of entities) {
479
+ const normalized = entity.trim().toLowerCase();
480
+ if (normalized && !seen.has(normalized)) {
481
+ seen.add(normalized);
482
+ result.push(normalized);
483
+ }
484
+ }
485
+ return result;
486
+ }
487
+ export function inferEntities(content) {
488
+ const entities = [];
489
+ // Backtick code refs
490
+ const codeRefs = content.match(/`([^`]+)`/g);
491
+ if (codeRefs) {
492
+ for (const ref of codeRefs) {
493
+ entities.push(ref.slice(1, -1));
494
+ }
495
+ }
496
+ // Package-like names: qdrant, postgres, react, etc.
497
+ const techTerms = content.match(/\b(qdrant|postgres|postgresql|redis|docker|kubernetes|k8s|react|typescript|node|python|aws|gcp|azure|github|gitlab|notion|slack)\b/gi);
498
+ if (techTerms) {
499
+ entities.push(...techTerms);
500
+ }
501
+ return normalizeEntities(entities).slice(0, 10);
502
+ }
503
+ export function getDecayHalfLife(input) {
504
+ const kind = normalizeKind(input.kind);
505
+ if (kind === "relation" || kind === "telemetry")
506
+ return null;
507
+ const rawCategory = normalizeToken(input.category);
508
+ const rawDomain = normalizeToken(input.domain);
509
+ const categoryWasProvided = rawCategory.length > 0;
510
+ const categoryIsKnown = rawCategory in CATEGORIES ||
511
+ rawCategory.includes("infra") ||
512
+ rawCategory.includes("decision") ||
513
+ rawCategory.includes("operation") ||
514
+ rawCategory.includes("runbook") ||
515
+ rawCategory.includes("owner") ||
516
+ rawCategory.includes("people") ||
517
+ rawCategory.includes("product") ||
518
+ rawCategory.includes("domain") ||
519
+ rawCategory.includes("repo") ||
520
+ rawCategory.includes("code");
521
+ if (categoryWasProvided && !categoryIsKnown) {
522
+ return DECAY_DEFAULT_HALF_LIFE;
523
+ }
524
+ const canonicalCategory = normalizeCategory(input.category);
525
+ const canonicalDomain = normalizeDomain(input.domain);
526
+ return (DECAY_HALF_LIFE[`${canonicalCategory}.${canonicalDomain}`] ??
527
+ DECAY_HALF_LIFE[`${canonicalCategory}.${DEFAULT_DOMAIN}`] ??
528
+ DECAY_DEFAULT_HALF_LIFE);
529
+ }
530
+ // ---------------------------------------------------------------------------
531
+ // Validation helpers for tool schemas
532
+ // ---------------------------------------------------------------------------
533
+ export function categoryValues() {
534
+ return Object.keys(CATEGORIES);
535
+ }
536
+ export function canonicalCategoryValues() {
537
+ return Object.keys(CATEGORIES);
538
+ }
539
+ export function domainValues() {
540
+ return Object.keys(DOMAINS);
541
+ }
542
+ export function canonicalDomainValues() {
543
+ return Object.keys(DOMAINS);
544
+ }
545
+ export function kindValues() {
546
+ return Object.keys(KINDS);
547
+ }
548
+ export function layerValues() {
549
+ return Object.keys(LAYERS);
550
+ }
551
+ // ---------------------------------------------------------------------------
552
+ // Prompt rendering helpers — single source of truth shared with src/prompts/*
553
+ // ---------------------------------------------------------------------------
554
+ /**
555
+ * Render the documentation block for a single category — used inside LLM prompts
556
+ * so the model sees the same description and examples that taxonomy.ts declares
557
+ * as canonical. Keeps prompts and code in sync.
558
+ */
559
+ export function categoryPromptSection(category) {
560
+ const def = CATEGORIES[category];
561
+ if (!def)
562
+ return `### ${category}\n(unknown category)`;
563
+ const examples = (def.examples ?? []).map((ex) => ` • ${ex}`).join("\n");
564
+ return [
565
+ `### ${category}`,
566
+ def.description ?? "",
567
+ examples ? `Examples:\n${examples}` : "",
568
+ ]
569
+ .filter(Boolean)
570
+ .join("\n");
571
+ }
572
+ /** Render every category section back-to-back. */
573
+ export function allCategoryPromptSections() {
574
+ return Object.keys(CATEGORIES).map(categoryPromptSection).join("\n\n");
575
+ }
576
+ // ---------------------------------------------------------------------------
577
+ // MCP enum descriptions — single source of truth shared with src/mcp/tools.ts
578
+ // ---------------------------------------------------------------------------
579
+ //
580
+ // These render the canonical CATEGORIES / DOMAINS / KINDS / MEMORY_SUBTYPES /
581
+ // SOURCES tables into the multiline strings agents see when they inspect a
582
+ // tool schema. Keeping them here means tool descriptions never drift from
583
+ // the ontology definitions above.
584
+ function shortenDescription(text) {
585
+ // Collapse any whitespace and clip to the first sentence so per-value
586
+ // blurbs stay readable inside a tool schema description.
587
+ const collapsed = text.replace(/\s+/g, " ").trim();
588
+ const firstPeriod = collapsed.indexOf(". ");
589
+ if (firstPeriod > 0)
590
+ return collapsed.slice(0, firstPeriod + 1);
591
+ return collapsed;
592
+ }
593
+ /** Render the `category` enum description for memory_store / memory_recall. */
594
+ export function categoryEnumDescription() {
595
+ const lines = Object.entries(CATEGORIES).map(([name, def]) => ` • ${name} — ${shortenDescription(def.description)}`);
596
+ return [
597
+ "Subject matter of the fact. One of:",
598
+ ...lines,
599
+ `Default when omitted: ${DEFAULT_CATEGORY}.`,
600
+ ].join("\n");
601
+ }
602
+ /** Render the `domain` enum description. */
603
+ export function domainEnumDescription() {
604
+ const lines = Object.entries(DOMAINS).map(([name, def]) => ` • ${name} — ${shortenDescription(def.description)}`);
605
+ return [
606
+ "Activity profile that controls vocabulary and ranking. One of:",
607
+ ...lines,
608
+ `Default when omitted: ${DEFAULT_DOMAIN}.`,
609
+ ].join("\n");
610
+ }
611
+ /** Render the `kind` enum description. Telemetry is daemon-only — excluded. */
612
+ export function kindEnumDescription() {
613
+ const lines = Object.entries(KINDS)
614
+ .filter(([name]) => name !== "telemetry")
615
+ .map(([name, def]) => ` • ${name} — ${shortenDescription(def.description)}`);
616
+ return [
617
+ "Knowledge form of the memory object. One of:",
618
+ ...lines,
619
+ `Default when omitted: ${DEFAULT_KIND}. (telemetry is reserved for the daemon.)`,
620
+ ].join("\n");
621
+ }
622
+ /**
623
+ * Render the `memory_subtype` enum description, grouped by kind so the agent
624
+ * knows which subtypes pair with which kind (the runtime enforces this via
625
+ * validateMemorySubtype).
626
+ */
627
+ export function memorySubtypeEnumDescription() {
628
+ const groups = Object.entries(MEMORY_SUBTYPES)
629
+ .filter(([, subtypes]) => subtypes.length > 0)
630
+ .map(([kind, subtypes]) => ` • kind=${kind}: ${subtypes.join(", ")}`);
631
+ return [
632
+ "Optional finer-grained type within the kind. Only set when one of these clearly applies — otherwise leave blank.",
633
+ "Subtype must match the kind (validated server-side):",
634
+ ...groups,
635
+ ].join("\n");
636
+ }
637
+ /** Render the `source` enum description for memory_store. */
638
+ export function sourceEnumDescription() {
639
+ const lines = Object.entries(SOURCES).map(([name, def]) => ` • ${name} — ${shortenDescription(def.description)}`);
640
+ return [
641
+ "Who created this memory. One of:",
642
+ ...lines,
643
+ `Default when omitted: ${DEFAULT_SOURCE}. Only override when the human explicitly asked you to remember this (use 'user').`,
644
+ ].join("\n");
645
+ }
646
+ export function memorySubtypeValues() {
647
+ return Object.values(MEMORY_SUBTYPES).flat();
648
+ }
649
+ export function memorySubtypeValuesForKind(kind) {
650
+ return [...MEMORY_SUBTYPES[normalizeKind(kind)]];
651
+ }
652
+ export function sourceValues() {
653
+ return Object.keys(SOURCES);
654
+ }
223
655
  //# sourceMappingURL=taxonomy.js.map