bikky 0.3.1 → 0.3.2

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 (329) hide show
  1. package/README.md +79 -26
  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 +77 -0
  24. package/dist/daemon/episode-summary.d.ts.map +1 -0
  25. package/dist/daemon/episode-summary.js +239 -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 +68 -0
  73. package/dist/daemon/workstream-summary.d.ts.map +1 -0
  74. package/dist/daemon/workstream-summary.js +253 -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 +38 -20
  255. package/dist/mcp/index.js.map +1 -1
  256. package/dist/mcp/taxonomy.d.ts +237 -31
  257. package/dist/mcp/taxonomy.d.ts.map +1 -1
  258. package/dist/mcp/taxonomy.js +533 -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 +338 -302
  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 +74 -0
  288. package/dist/prompts/distill.js.map +1 -0
  289. package/dist/prompts/extraction.d.ts +14 -0
  290. package/dist/prompts/extraction.d.ts.map +1 -0
  291. package/dist/prompts/extraction.js +87 -0
  292. package/dist/prompts/extraction.js.map +1 -0
  293. package/dist/prompts/index.d.ts +50 -0
  294. package/dist/prompts/index.d.ts.map +1 -0
  295. package/dist/prompts/index.js +102 -0
  296. package/dist/prompts/index.js.map +1 -0
  297. package/dist/prompts/prompts.test.d.ts +8 -0
  298. package/dist/prompts/prompts.test.d.ts.map +1 -0
  299. package/dist/prompts/prompts.test.js +140 -0
  300. package/dist/prompts/prompts.test.js.map +1 -0
  301. package/dist/prompts/relations.d.ts +17 -0
  302. package/dist/prompts/relations.d.ts.map +1 -0
  303. package/dist/prompts/relations.js +72 -0
  304. package/dist/prompts/relations.js.map +1 -0
  305. package/dist/render.d.ts +41 -0
  306. package/dist/render.d.ts.map +1 -0
  307. package/dist/render.js +173 -0
  308. package/dist/render.js.map +1 -0
  309. package/dist/render.test.d.ts +8 -0
  310. package/dist/render.test.d.ts.map +1 -0
  311. package/dist/render.test.js +212 -0
  312. package/dist/render.test.js.map +1 -0
  313. package/package.json +9 -2
  314. package/dist/llm/embedding.d.ts +0 -13
  315. package/dist/llm/embedding.d.ts.map +0 -1
  316. package/dist/llm/embedding.js +0 -127
  317. package/dist/llm/embedding.js.map +0 -1
  318. package/dist/llm/embedding.test.d.ts +0 -8
  319. package/dist/llm/embedding.test.d.ts.map +0 -1
  320. package/dist/llm/embedding.test.js +0 -117
  321. package/dist/llm/embedding.test.js.map +0 -1
  322. package/dist/llm/inference.d.ts +0 -12
  323. package/dist/llm/inference.d.ts.map +0 -1
  324. package/dist/llm/inference.js +0 -146
  325. package/dist/llm/inference.js.map +0 -1
  326. package/dist/llm/inference.test.d.ts +0 -8
  327. package/dist/llm/inference.test.d.ts.map +0 -1
  328. package/dist/llm/inference.test.js +0 -117
  329. package/dist/llm/inference.test.js.map +0 -1
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Daemon-owned capture policy for ontology v2.
3
+ *
4
+ * These constants define when Bikky should capture memory, how large each
5
+ * generated object should be, and which prompt/capture versions are stored on
6
+ * payloads for later audits and prompt evolution.
7
+ */
8
+ import type { Category, MemorySubtype } from "../mcp/taxonomy.js";
9
+ export declare const CAPTURE_POLICY_VERSION = "capture-policy-v2";
10
+ export declare const PROMPT_VERSIONS: {
11
+ readonly factExtraction: "fact-extraction-v2";
12
+ readonly sessionIndex: "session-index-v1";
13
+ readonly episodeSummary: "episode-summary-v1";
14
+ readonly workstreamSummary: "workstream-summary-v1";
15
+ readonly distillation: "distillation-v1";
16
+ };
17
+ export declare const CAPTURE_TRIGGERS: {
18
+ readonly factExtraction: {
19
+ readonly minEvents: 10;
20
+ readonly minUsefulCharacters: 280;
21
+ readonly maxEventsPerBatch: 120;
22
+ readonly cooldownSeconds: 300;
23
+ };
24
+ readonly episodeSummary: {
25
+ readonly minEvents: 12;
26
+ readonly minUsefulCharacters: 600;
27
+ readonly maxEventsPerEpisode: 80;
28
+ readonly idleGapMinutes: 20;
29
+ readonly forceCheckpointEvents: 140;
30
+ };
31
+ readonly sessionIndex: {
32
+ readonly minEvents: 1;
33
+ readonly forceCheckpointEvents: 140;
34
+ readonly maxRecentEpisodeRefs: 12;
35
+ };
36
+ readonly workstreamSummary: {
37
+ readonly minEpisodeCount: 1;
38
+ readonly minConfidence: 0.65;
39
+ readonly maxEpisodesPerUpdate: 8;
40
+ };
41
+ readonly distillation: {
42
+ readonly minSourceSummaries: 5;
43
+ readonly maxSourceSummaries: 20;
44
+ readonly lookbackDays: 14;
45
+ };
46
+ };
47
+ export declare const CAPTURE_BUDGETS: {
48
+ readonly fact: {
49
+ readonly maxFactsPerBatch: 6;
50
+ readonly targetWords: readonly [12, 45];
51
+ readonly maxEntities: 8;
52
+ };
53
+ readonly episodeSummary: {
54
+ readonly targetWords: readonly [90, 180];
55
+ readonly maxTasks: 8;
56
+ readonly maxDecisions: 8;
57
+ readonly maxOpenQuestions: 6;
58
+ };
59
+ readonly sessionIndex: {
60
+ readonly targetWords: readonly [30, 80];
61
+ readonly maxEpisodeRefs: 12;
62
+ };
63
+ readonly workstreamSummary: {
64
+ readonly targetWords: readonly [120, 240];
65
+ readonly maxCurrentDecisions: 8;
66
+ readonly maxNextSteps: 8;
67
+ readonly maxBlockers: 6;
68
+ };
69
+ readonly distilled: {
70
+ readonly targetWords: readonly [60, 160];
71
+ readonly maxSourceRefs: 12;
72
+ };
73
+ };
74
+ export declare const QUALITY_THRESHOLDS: {
75
+ readonly minFactConfidence: 0.55;
76
+ readonly minFactQualityScore: 0.6;
77
+ readonly minImportanceForLowConfidenceFact: 0.75;
78
+ readonly rejectStatusOnlyFacts: true;
79
+ readonly rejectDuplicatedTranscriptNarration: true;
80
+ };
81
+ export declare const CAPTURE_KIND_SUBTYPES: {
82
+ readonly fact: readonly ["codebase_map", "architecture_decision", "infra_topology", "access_pattern", "deployment_procedure", "operational_procedure", "domain_rule", "troubleshooting_gotcha", "preference", "ownership"];
83
+ readonly summary: readonly ["session_index", "episode", "workstream"];
84
+ readonly distilled: readonly ["runbook_candidate", "failure_mode", "convention", "architecture_pattern", "product_insight"];
85
+ };
86
+ export declare const FACT_CATEGORY_TO_SUBTYPE: Record<Category, MemorySubtype>;
87
+ export declare const DEFAULT_CAPTURE_CONTEXT: {
88
+ readonly domain: "software_engineering" | "product_strategy" | "business_operations" | "research" | "personal_productivity";
89
+ readonly source: "daemon";
90
+ readonly reviewStatus: "candidate";
91
+ readonly volatility: "medium";
92
+ };
93
+ export declare function promptVersionForSubtype(subtype: MemorySubtype): string;
94
+ export declare function subtypeForCategory(category: Category): MemorySubtype;
95
+ //# sourceMappingURL=capture-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-policy.d.ts","sourceRoot":"","sources":["../../src/daemon/capture-policy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAQ,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxE,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAE1D,eAAO,MAAM,eAAe;;;;;;CAMlB,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BnB,CAAC;AAEX,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BlB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;CAMrB,CAAC;AAEX,eAAO,MAAM,qBAAqB;;;;CAqBkC,CAAC;AAErE,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,QAAQ,EAAE,aAAa,CAUpE,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;CAK1B,CAAC;AAEX,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CActE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,aAAa,CAEpE"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Daemon-owned capture policy for ontology v2.
3
+ *
4
+ * These constants define when Bikky should capture memory, how large each
5
+ * generated object should be, and which prompt/capture versions are stored on
6
+ * payloads for later audits and prompt evolution.
7
+ */
8
+ import { DEFAULT_DOMAIN } from "../mcp/taxonomy.js";
9
+ export const CAPTURE_POLICY_VERSION = "capture-policy-v2";
10
+ export const PROMPT_VERSIONS = {
11
+ factExtraction: "fact-extraction-v2",
12
+ sessionIndex: "session-index-v1",
13
+ episodeSummary: "episode-summary-v1",
14
+ workstreamSummary: "workstream-summary-v1",
15
+ distillation: "distillation-v1",
16
+ };
17
+ export const CAPTURE_TRIGGERS = {
18
+ factExtraction: {
19
+ minEvents: 10,
20
+ minUsefulCharacters: 280,
21
+ maxEventsPerBatch: 120,
22
+ cooldownSeconds: 300,
23
+ },
24
+ episodeSummary: {
25
+ minEvents: 12,
26
+ minUsefulCharacters: 600,
27
+ maxEventsPerEpisode: 80,
28
+ idleGapMinutes: 20,
29
+ forceCheckpointEvents: 140,
30
+ },
31
+ sessionIndex: {
32
+ minEvents: 1,
33
+ forceCheckpointEvents: 140,
34
+ maxRecentEpisodeRefs: 12,
35
+ },
36
+ workstreamSummary: {
37
+ minEpisodeCount: 1,
38
+ minConfidence: 0.65,
39
+ maxEpisodesPerUpdate: 8,
40
+ },
41
+ distillation: {
42
+ minSourceSummaries: 5,
43
+ maxSourceSummaries: 20,
44
+ lookbackDays: 14,
45
+ },
46
+ };
47
+ export const CAPTURE_BUDGETS = {
48
+ fact: {
49
+ maxFactsPerBatch: 6,
50
+ targetWords: [12, 45],
51
+ maxEntities: 8,
52
+ },
53
+ episodeSummary: {
54
+ targetWords: [90, 180],
55
+ maxTasks: 8,
56
+ maxDecisions: 8,
57
+ maxOpenQuestions: 6,
58
+ },
59
+ sessionIndex: {
60
+ targetWords: [30, 80],
61
+ maxEpisodeRefs: 12,
62
+ },
63
+ workstreamSummary: {
64
+ targetWords: [120, 240],
65
+ maxCurrentDecisions: 8,
66
+ maxNextSteps: 8,
67
+ maxBlockers: 6,
68
+ },
69
+ distilled: {
70
+ targetWords: [60, 160],
71
+ maxSourceRefs: 12,
72
+ },
73
+ };
74
+ export const QUALITY_THRESHOLDS = {
75
+ minFactConfidence: 0.55,
76
+ minFactQualityScore: 0.6,
77
+ minImportanceForLowConfidenceFact: 0.75,
78
+ rejectStatusOnlyFacts: true,
79
+ rejectDuplicatedTranscriptNarration: true,
80
+ };
81
+ export const CAPTURE_KIND_SUBTYPES = {
82
+ fact: [
83
+ "codebase_map",
84
+ "architecture_decision",
85
+ "infra_topology",
86
+ "access_pattern",
87
+ "deployment_procedure",
88
+ "operational_procedure",
89
+ "domain_rule",
90
+ "troubleshooting_gotcha",
91
+ "preference",
92
+ "ownership",
93
+ ],
94
+ summary: ["session_index", "episode", "workstream"],
95
+ distilled: [
96
+ "runbook_candidate",
97
+ "failure_mode",
98
+ "convention",
99
+ "architecture_pattern",
100
+ "product_insight",
101
+ ],
102
+ };
103
+ export const FACT_CATEGORY_TO_SUBTYPE = {
104
+ codebase: "codebase_map",
105
+ infrastructure: "infra_topology",
106
+ operations: "operational_procedure",
107
+ decisions: "architecture_decision",
108
+ product_domain: "domain_rule",
109
+ projects: "codebase_map",
110
+ people: "ownership",
111
+ preferences: "preference",
112
+ observations: "troubleshooting_gotcha",
113
+ };
114
+ export const DEFAULT_CAPTURE_CONTEXT = {
115
+ domain: DEFAULT_DOMAIN,
116
+ source: "daemon",
117
+ reviewStatus: "candidate",
118
+ volatility: "medium",
119
+ };
120
+ export function promptVersionForSubtype(subtype) {
121
+ if (subtype === "session_index")
122
+ return PROMPT_VERSIONS.sessionIndex;
123
+ if (subtype === "episode")
124
+ return PROMPT_VERSIONS.episodeSummary;
125
+ if (subtype === "workstream")
126
+ return PROMPT_VERSIONS.workstreamSummary;
127
+ if (subtype === "runbook_candidate" ||
128
+ subtype === "failure_mode" ||
129
+ subtype === "convention" ||
130
+ subtype === "architecture_pattern" ||
131
+ subtype === "product_insight") {
132
+ return PROMPT_VERSIONS.distillation;
133
+ }
134
+ return PROMPT_VERSIONS.factExtraction;
135
+ }
136
+ export function subtypeForCategory(category) {
137
+ return FACT_CATEGORY_TO_SUBTYPE[category];
138
+ }
139
+ //# sourceMappingURL=capture-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-policy.js","sourceRoot":"","sources":["../../src/daemon/capture-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=capture-policy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-policy.test.d.ts","sourceRoot":"","sources":["../../src/daemon/capture-policy.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { CAPTURE_BUDGETS, CAPTURE_KIND_SUBTYPES, CAPTURE_POLICY_VERSION, CAPTURE_TRIGGERS, DEFAULT_CAPTURE_CONTEXT, PROMPT_VERSIONS, QUALITY_THRESHOLDS, promptVersionForSubtype, subtypeForCategory, } from "./capture-policy.js";
4
+ describe("daemon/capture-policy", () => {
5
+ it("uses ontology v2 and software_engineering defaults", () => {
6
+ assert.strictEqual(CAPTURE_POLICY_VERSION, "capture-policy-v2");
7
+ assert.strictEqual(DEFAULT_CAPTURE_CONTEXT.domain, "software_engineering");
8
+ assert.strictEqual(DEFAULT_CAPTURE_CONTEXT.source, "daemon");
9
+ assert.strictEqual(DEFAULT_CAPTURE_CONTEXT.reviewStatus, "candidate");
10
+ });
11
+ it("keeps fact extraction cadence aligned with config defaults", () => {
12
+ assert.strictEqual(CAPTURE_TRIGGERS.factExtraction.minEvents, 10);
13
+ assert.strictEqual(CAPTURE_TRIGGERS.factExtraction.cooldownSeconds, 300);
14
+ assert.ok(CAPTURE_TRIGGERS.factExtraction.maxEventsPerBatch > CAPTURE_TRIGGERS.factExtraction.minEvents);
15
+ });
16
+ it("defines bounded budgets for every first-slice object", () => {
17
+ assert.ok(CAPTURE_BUDGETS.fact.maxFactsPerBatch > 0);
18
+ assert.ok(CAPTURE_BUDGETS.episodeSummary.targetWords[0] < CAPTURE_BUDGETS.episodeSummary.targetWords[1]);
19
+ assert.ok(CAPTURE_BUDGETS.workstreamSummary.targetWords[0] < CAPTURE_BUDGETS.workstreamSummary.targetWords[1]);
20
+ assert.ok(CAPTURE_BUDGETS.distilled.maxSourceRefs > 0);
21
+ });
22
+ it("maps each capture kind to approved subtypes", () => {
23
+ assert.ok(CAPTURE_KIND_SUBTYPES.fact?.includes("codebase_map"));
24
+ assert.ok(CAPTURE_KIND_SUBTYPES.summary?.includes("episode"));
25
+ assert.ok(CAPTURE_KIND_SUBTYPES.distilled?.includes("convention"));
26
+ });
27
+ it("maps categories to deterministic default fact subtypes", () => {
28
+ assert.strictEqual(subtypeForCategory("codebase"), "codebase_map");
29
+ assert.strictEqual(subtypeForCategory("infrastructure"), "infra_topology");
30
+ assert.strictEqual(subtypeForCategory("people"), "ownership");
31
+ assert.strictEqual(subtypeForCategory("preferences"), "preference");
32
+ });
33
+ it("selects prompt versions by subtype lifecycle", () => {
34
+ assert.strictEqual(promptVersionForSubtype("codebase_map"), PROMPT_VERSIONS.factExtraction);
35
+ assert.strictEqual(promptVersionForSubtype("session_index"), PROMPT_VERSIONS.sessionIndex);
36
+ assert.strictEqual(promptVersionForSubtype("episode"), PROMPT_VERSIONS.episodeSummary);
37
+ assert.strictEqual(promptVersionForSubtype("workstream"), PROMPT_VERSIONS.workstreamSummary);
38
+ assert.strictEqual(promptVersionForSubtype("convention"), PROMPT_VERSIONS.distillation);
39
+ });
40
+ it("sets quality thresholds that reject weak daemon memories", () => {
41
+ assert.ok(QUALITY_THRESHOLDS.minFactConfidence > 0.5);
42
+ assert.ok(QUALITY_THRESHOLDS.minFactQualityScore > 0.5);
43
+ assert.strictEqual(QUALITY_THRESHOLDS.rejectStatusOnlyFacts, true);
44
+ });
45
+ });
46
+ //# sourceMappingURL=capture-policy.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-policy.test.js","sourceRoot":"","sources":["../../src/daemon/capture-policy.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"consolidation.d.ts","sourceRoot":"","sources":["../../src/daemon/consolidation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAA4B,MAAM,aAAa,CAAC;AAMnE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;CACzD;AASD,QAAA,MAAM,SAAS,GAAI,IAAI,KAAK,KAAG,IAAuB,CAAC;AAgIvD;;;GAGG;AACH,QAAA,MAAM,mBAAmB,GACvB,MAAM;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EACpF,SAAS,WAAW,KACnB,OAAO,CAAC,mBAAmB,CAmE7B,CAAC;AAwPF;;;GAGG;AACH,QAAA,MAAM,IAAI,GAAU,QAAQ,WAAW,EAAE,OAAM,wBAA6B,KAAG,OAAO,CAAC,IAAI,CAkC1F,CAAC;AAEF,iCAAiC;AACjC,QAAA,MAAM,MAAM,QAAO,IAElB,CAAC;AAEF,OAAO,EACL,mBAAmB,EACnB,IAAI,EACJ,SAAS,EACT,MAAM,GACP,CAAC"}
1
+ {"version":3,"file":"consolidation.d.ts","sourceRoot":"","sources":["../../src/daemon/consolidation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAmBH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAA4B,MAAM,aAAa,CAAC;AAMnE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;CACzD;AASD,QAAA,MAAM,SAAS,GAAI,IAAI,KAAK,KAAG,IAAuB,CAAC;AA6IvD;;;GAGG;AACH,QAAA,MAAM,mBAAmB,GACvB,MAAM;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EACpF,SAAS,WAAW,KACnB,OAAO,CAAC,mBAAmB,CAyE7B,CAAC;AAuOF;;;GAGG;AACH,QAAA,MAAM,IAAI,GAAU,QAAQ,WAAW,EAAE,OAAM,wBAA6B,KAAG,OAAO,CAAC,IAAI,CAkC1F,CAAC;AAEF,iCAAiC;AACjC,QAAA,MAAM,MAAM,QAAO,IAElB,CAAC;AAEF,OAAO,EACL,mBAAmB,EACnB,IAAI,EACJ,SAAS,EACT,MAAM,GACP,CAAC"}
@@ -14,7 +14,8 @@ import { join, dirname } from "node:path";
14
14
  import { createHash } from "node:crypto";
15
15
  import * as qdrant from "./qdrant.js";
16
16
  import { chatCompletion } from "../llm/index.js";
17
- import { categoryValues } from "../mcp/taxonomy.js";
17
+ import { categoryValues, normalizeCategory, normalizeDomain } from "../mcp/taxonomy.js";
18
+ import { distillPrompt, DISTILL_PROMPT_DESCRIPTOR, contradictionPrompt, briefPrompt, BRIEF_PROMPT_DESCRIPTOR, safeParseJson, } from "../prompts/index.js";
18
19
  import { STATE_DIR } from "../config.js";
19
20
  // ---------------------------------------------------------------------------
20
21
  // State
@@ -65,35 +66,33 @@ const autoDistill = async (_config, { minSummaries = 5 } = {}) => {
65
66
  if (points.length < minSummaries) {
66
67
  return { distilled: false, count: points.length };
67
68
  }
68
- // Sort by date (oldest first)
69
- points.sort((a, b) => (a.payload?.created_at || "").localeCompare(b.payload?.created_at || ""));
70
- // Take the oldest batch (up to 20)
69
+ // Sort by date — newest first (recent patterns are more actionable)
70
+ points.sort((a, b) => (b.payload?.created_at || "").localeCompare(a.payload?.created_at || ""));
71
+ // Take the latest batch (up to 20)
71
72
  const batch = points.slice(0, 20);
72
- const summaryTexts = batch.map(pt => `[${pt.payload?.created_at?.slice(0, 10)}] ${pt.payload?.content}`).join("\n");
73
- const raw = await chatCompletion({
74
- messages: [
75
- { role: "system", content: "You consolidate session summaries into high-level patterns. Output only valid JSON." },
76
- { role: "user", content: `Consolidate these ${batch.length} session summaries into 3-5 distilled patterns.
77
-
78
- ## Session Summaries:
79
- ${summaryTexts}
80
-
81
- ## Output (JSON array):
82
- Each object: { "content": "pattern description (1-2 sentences)", "entities": ["entity1", "entity2"], "importance": 0.0-1.0 }
83
-
84
- Return ONLY the JSON array.` },
85
- ],
86
- temperature: 0.2,
87
- max_tokens: 1000,
73
+ const rendered = distillPrompt({
74
+ summaries: batch.map((pt, i) => ({
75
+ id: i + 1,
76
+ date: pt.payload?.created_at?.slice(0, 10) ?? "unknown",
77
+ content: pt.payload?.content ?? "",
78
+ })),
88
79
  });
80
+ const raw = await chatCompletion(rendered);
89
81
  if (!raw) {
90
82
  logFn("WARN", "Auto-distill LLM returned empty");
91
83
  return { distilled: false };
92
84
  }
93
- const jsonStr = raw.replace(/^```json?\n?/, "").replace(/\n?```$/, "").trim();
94
- const patterns = JSON.parse(jsonStr);
95
- if (!Array.isArray(patterns) || patterns.length === 0)
85
+ const parsed = safeParseJson(raw);
86
+ let patterns = [];
87
+ if (Array.isArray(parsed)) {
88
+ patterns = parsed;
89
+ }
90
+ else if (parsed && Array.isArray(parsed.patterns)) {
91
+ patterns = parsed.patterns;
92
+ }
93
+ if (patterns.length === 0)
96
94
  return { distilled: false };
95
+ const promptStamp = `${DISTILL_PROMPT_DESCRIPTOR.id}@${DISTILL_PROMPT_DESCRIPTOR.version}`;
97
96
  // Store distilled patterns
98
97
  for (const pattern of patterns) {
99
98
  if (!pattern.content)
@@ -101,15 +100,19 @@ Return ONLY the JSON array.` },
101
100
  const hash = createHash("sha256").update(`distilled:${pattern.content}`).digest("hex");
102
101
  await qdrant.storeFact({
103
102
  content: pattern.content,
104
- category: "observation",
105
- domain: "work",
103
+ category: normalizeCategory(pattern.category ?? "observation"),
104
+ domain: normalizeDomain(pattern.domain ?? "work"),
106
105
  kind: "distilled",
107
106
  entities: Array.isArray(pattern.entities) ? pattern.entities.map(e => String(e).toLowerCase()) : [],
108
107
  source: "system",
109
108
  confidence: 0.85,
110
109
  importance: pattern.importance || 0.7,
111
110
  content_hash: hash,
112
- metadata: { distilled_from: batch.length.toString(), distilled_at: new Date().toISOString() },
111
+ metadata: {
112
+ distilled_from: batch.length.toString(),
113
+ distilled_at: new Date().toISOString(),
114
+ distilled_by_prompt: promptStamp,
115
+ },
113
116
  });
114
117
  }
115
118
  // Supersede the source summaries
@@ -132,54 +135,54 @@ Return ONLY the JSON array.` },
132
135
  const detectContradiction = async (fact, _config) => {
133
136
  if (!qdrant.isReady())
134
137
  return { contradiction: false };
135
- if ((fact.importance || 0) < 0.5)
138
+ if ((fact.importance || 0) < 0.3)
136
139
  return { contradiction: false };
137
140
  try {
138
141
  const vector = await qdrant.embed(fact.content);
142
+ // Search across ALL categories — contradictions can cross category lines
143
+ // (e.g. an "infrastructure" port fact vs an "observation" workaround fact).
139
144
  const results = await qdrant.qdrantRequest("POST", `/collections/${qdrant.collection}/points/search`, {
140
145
  vector,
141
- filter: {
142
- must: [
143
- { key: "category", match: { value: fact.category } },
144
- { is_null: { key: "superseded_by" } },
145
- ],
146
- },
147
- limit: 3,
146
+ filter: { must: [{ is_null: { key: "superseded_by" } }] },
147
+ limit: 5,
148
148
  with_payload: true,
149
149
  });
150
150
  const candidates = (results.result || [])
151
151
  .filter(r => r.score >= 0.75 && r.score < 0.92);
152
152
  if (candidates.length === 0)
153
153
  return { contradiction: false };
154
- // Use LLM to check if any candidate contradicts the new fact
155
- const candidateTexts = candidates.map(c => `ID: ${c.id}\nFact: ${c.payload?.content}\nSimilarity: ${c.score.toFixed(3)}`).join("\n\n");
156
- const raw = await chatCompletion({
157
- messages: [
158
- { role: "system", content: "You detect contradictions between facts. Output only valid JSON." },
159
- { role: "user", content: `Does the NEW fact contradict any of the EXISTING facts?
160
-
161
- NEW FACT: ${fact.content}
162
-
163
- EXISTING FACTS:
164
- ${candidateTexts}
165
-
166
- If a contradiction exists, return: {"contradiction": true, "existing_id": "the contradicted fact ID", "reason": "brief explanation"}
167
- If no contradiction: {"contradiction": false}
168
-
169
- Return ONLY the JSON object.` },
170
- ],
171
- temperature: 0.1,
172
- max_tokens: 200,
154
+ const rendered = contradictionPrompt({
155
+ newFact: { content: fact.content, category: fact.category },
156
+ candidates: candidates.map((c) => ({
157
+ id: c.id,
158
+ content: c.payload?.content ?? "",
159
+ category: c.payload?.category ?? "unknown",
160
+ score: c.score,
161
+ })),
173
162
  });
163
+ const raw = await chatCompletion(rendered);
174
164
  if (!raw)
175
165
  return { contradiction: false };
176
- const result = JSON.parse(raw.replace(/^```json?\n?/, "").replace(/\n?```$/, "").trim());
177
- if (result.contradiction && result.existing_id) {
178
- logFn("INFO", `Contradiction detected: "${fact.content}" vs existing ${result.existing_id}: ${result.reason}`);
166
+ const result = safeParseJson(raw);
167
+ if (!result)
168
+ return { contradiction: false };
169
+ const outcome = result.outcome
170
+ ?? (result.contradiction === true ? "contradicted" : "compatible");
171
+ if (outcome === "compatible")
172
+ return { contradiction: false };
173
+ if (outcome === "superseded" && result.existing_id) {
174
+ // Auto-resolve: caller (extraction) marks the old fact superseded via
175
+ // qdrant dedup machinery; here we just signal it's not a contradiction.
176
+ logFn("INFO", `Supersede detected: "${fact.content.slice(0, 60)}…" → existing ${result.existing_id} (${result.reason ?? ""})`);
177
+ return { contradiction: false };
178
+ }
179
+ if (outcome === "contradicted" && result.existing_id) {
180
+ const existing = candidates.find((c) => c.id === result.existing_id);
181
+ logFn("INFO", `Contradiction detected: "${fact.content}" vs existing ${result.existing_id}: ${result.reason ?? ""}`);
179
182
  return {
180
183
  contradiction: true,
181
184
  existingId: result.existing_id,
182
- existingContent: candidates.find(c => c.id === result.existing_id)?.payload?.content,
185
+ existingContent: existing?.payload?.content,
183
186
  reason: result.reason,
184
187
  };
185
188
  }
@@ -327,6 +330,16 @@ const formatHealthReport = (report) => {
327
330
  * Generate a compact memory brief from top facts.
328
331
  * Written to ~/.bikky/state/brief.md for agent orientation.
329
332
  */
333
+ const CATEGORY_TO_HEADING = {
334
+ team: "Key People & Team",
335
+ people: "Key People & Team",
336
+ projects: "Active Projects",
337
+ infrastructure: "Infrastructure Overview",
338
+ decisions: "Recent Decisions",
339
+ observation: "Known Gotchas",
340
+ observations: "Known Gotchas",
341
+ preferences: "Preferences & Conventions",
342
+ };
330
343
  const generateMemoryBrief = async (_config) => {
331
344
  if (!qdrant.isReady())
332
345
  return false;
@@ -335,6 +348,9 @@ const generateMemoryBrief = async (_config) => {
335
348
  const sections = {};
336
349
  const categories = CATEGORIES;
337
350
  for (const cat of categories) {
351
+ const heading = CATEGORY_TO_HEADING[cat];
352
+ if (!heading)
353
+ continue;
338
354
  const result = await qdrant.qdrantRequest("POST", `/collections/${qdrant.collection}/points/scroll`, {
339
355
  filter: {
340
356
  must: [
@@ -349,55 +365,25 @@ const generateMemoryBrief = async (_config) => {
349
365
  .sort((a, b) => (b.payload?.importance || 0) - (a.payload?.importance || 0))
350
366
  .slice(0, 10);
351
367
  if (points.length > 0) {
352
- sections[cat] = points.map(pt => pt.payload?.content).filter(Boolean);
368
+ const existing = sections[heading] ?? [];
369
+ const newOnes = points.map(pt => pt.payload?.content).filter(Boolean);
370
+ sections[heading] = [...existing, ...newOnes];
353
371
  }
354
372
  }
355
373
  if (Object.keys(sections).length === 0)
356
374
  return false;
357
- // Use LLM to synthesize into a structured brief
358
- const factsText = Object.entries(sections)
359
- .map(([cat, facts]) => `### ${cat}\n${facts.map(f => `- ${f}`).join("\n")}`)
360
- .join("\n\n");
361
- const brief = await chatCompletion({
362
- messages: [
363
- { role: "system", content: "You generate concise orientation documents for AI agents. Write in a structured, scannable format." },
364
- { role: "user", content: `Generate a compact memory brief from these facts. This brief will be loaded by AI agents at session start for orientation.
365
-
366
- ## Facts by Category:
367
- ${factsText}
368
-
369
- ## Output Format (markdown):
370
- # Memory Brief
371
- Generated: [date]
372
-
373
- ## Key People & Team
374
- [who matters and their roles]
375
-
376
- ## Active Projects
377
- [what's in progress, blocked, recently completed]
378
-
379
- ## Infrastructure Overview
380
- [key services, databases, deployment details]
381
-
382
- ## Recent Decisions
383
- [important architectural/technical decisions]
384
-
385
- ## Known Gotchas
386
- [errors, workarounds, caveats to watch for]
387
-
388
- ## Preferences & Conventions
389
- [user/team preferences, coding style, etc.]
390
-
391
- Keep each section to 3-5 bullet points. Omit empty sections. Be factual, not chatty.` },
392
- ],
393
- temperature: 0.2,
394
- max_tokens: 1500,
395
- });
375
+ const generatedAt = new Date().toISOString().slice(0, 10);
376
+ const rendered = briefPrompt({ generatedAt, sections });
377
+ const brief = await chatCompletion(rendered);
396
378
  if (!brief)
397
379
  return false;
380
+ // Stamp the prompt version as a comment so we know which prompt produced
381
+ // a given on-disk brief (debugging aid; ignored by markdown renderers).
382
+ const promptStamp = `${BRIEF_PROMPT_DESCRIPTOR.id}@${BRIEF_PROMPT_DESCRIPTOR.version}`;
383
+ const output = `<!-- generated by ${promptStamp} -->\n${brief}\n`;
398
384
  // Write to disk
399
385
  mkdirSync(dirname(MEMORY_BRIEF_PATH), { recursive: true });
400
- writeFileSync(MEMORY_BRIEF_PATH, brief + "\n", "utf8");
386
+ writeFileSync(MEMORY_BRIEF_PATH, output, "utf8");
401
387
  logFn("INFO", `Memory brief generated: ${MEMORY_BRIEF_PATH} (${brief.length} chars)`);
402
388
  return true;
403
389
  }