blun-king-cli 9.0.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/LIESMICH.txt +32 -13
  2. package/README.md +39 -20
  3. package/bin/blun.js +248 -160
  4. package/bin/core-bootstrap.js +47 -0
  5. package/bin/king.js +277 -1
  6. package/bin/launcher-mode.js +15 -3
  7. package/bin/launcher-runtime.js +293 -0
  8. package/bin/plugin-bootstrap.js +11 -4
  9. package/bin/private-paths.js +1577 -10
  10. package/bin/update-lease.js +399 -0
  11. package/bin/update-notice.js +1245 -0
  12. package/blun.mjs +26606 -25239
  13. package/dist-web/assets/{CodeBlockNode-Bsvp6ZEy.js → CodeBlockNode-CXnTLMNr.js} +1 -1
  14. package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-ta7hLjia.js → CodeBlockShell.vue_vue_type_style_index_0_lang-CCF8Ntnq.js} +1 -1
  15. package/dist-web/assets/{DesignSystemView-BmDDe28A.js → DesignSystemView-BbMOu-XO.js} +1 -1
  16. package/dist-web/assets/{Tooltip-nEEfaYVY.js → Tooltip-CFQEzqC-.js} +1 -1
  17. package/dist-web/assets/abnfDiagram-N423BO3Z-CsByy-GW.js +1 -0
  18. package/dist-web/assets/abnfDiagram-N423BO3Z-Z1APZG5m.js +1 -0
  19. package/dist-web/assets/arc-C-LXCaja.js +1 -0
  20. package/dist-web/assets/arc-C4VyWloT.js +1 -0
  21. package/dist-web/assets/architectureDiagram-T3A2C74G-DZq4L18e.js +36 -0
  22. package/dist-web/assets/architectureDiagram-T3A2C74G-DpddbUcM.js +36 -0
  23. package/dist-web/assets/blockDiagram-VBNYF7ZC-BV4sIf98.js +132 -0
  24. package/dist-web/assets/blockDiagram-VBNYF7ZC-BqccOSMr.js +132 -0
  25. package/dist-web/assets/{c4Diagram-AAUBKEIU-DtzacMnD.js → c4Diagram-5PPSVZJV-0MRkZlgP.js} +1 -1
  26. package/dist-web/assets/{c4Diagram-AAUBKEIU-D1VdMx8d.js → c4Diagram-5PPSVZJV-OHAcJrTy.js} +1 -1
  27. package/dist-web/assets/channel-B2VOQOI-.js +1 -0
  28. package/dist-web/assets/channel-DKjwM05G.js +1 -0
  29. package/dist-web/assets/{chunk-ND2GUHAM-DJoY9wNJ.js → chunk-2GRJ4B5K-DqJHs8Fw.js} +1 -1
  30. package/dist-web/assets/{chunk-ND2GUHAM-C4-rwdcv.js → chunk-2GRJ4B5K-oO6nqeLA.js} +1 -1
  31. package/dist-web/assets/{chunk-QZHKN3VN-C7YGaShq.js → chunk-2Q5K7J3B-B1nCd91o.js} +1 -1
  32. package/dist-web/assets/{chunk-QZHKN3VN-_Rz9_NuS.js → chunk-2Q5K7J3B-BC0Hsfqy.js} +1 -1
  33. package/dist-web/assets/chunk-5RXB4S5H-BfZa4yDH.js +231 -0
  34. package/dist-web/assets/chunk-5RXB4S5H-neG70kZx.js +231 -0
  35. package/dist-web/assets/{chunk-FMBD7UC4-DlLNDUx6.js → chunk-5VM5RSS4-l7biGqeH.js} +1 -1
  36. package/dist-web/assets/{chunk-FMBD7UC4-B2zs_Y-d.js → chunk-5VM5RSS4-u00AcpiJ.js} +1 -1
  37. package/dist-web/assets/chunk-6Q2QTUOP-BO-F11Gs.js +88 -0
  38. package/dist-web/assets/chunk-6Q2QTUOP-RUVRPBzG.js +88 -0
  39. package/dist-web/assets/{chunk-727SXJPM-Dn5wkDO_.js → chunk-GF5L2VYU-Ba-86KTd.js} +5 -5
  40. package/dist-web/assets/{chunk-727SXJPM-Dk2Xa3bA.js → chunk-GF5L2VYU-BtC69fw0.js} +5 -5
  41. package/dist-web/assets/{chunk-4BX2VUAB-DxZViaHS.js → chunk-JWPE2WC7-DIOubEqr.js} +1 -1
  42. package/dist-web/assets/{chunk-4BX2VUAB-WqrE2gaw.js → chunk-JWPE2WC7-u8Pcfhwh.js} +1 -1
  43. package/dist-web/assets/{chunk-2J33WTMH-Dm_s0_4f.js → chunk-KBJHAD2P-DDUeH_Ba.js} +1 -1
  44. package/dist-web/assets/{chunk-2J33WTMH-w4sdiKFO.js → chunk-KBJHAD2P-DS3BL64y.js} +1 -1
  45. package/dist-web/assets/chunk-RYQCIY6F-B9gFMVbS.js +1 -0
  46. package/dist-web/assets/chunk-RYQCIY6F-xg3EO0le.js +1 -0
  47. package/dist-web/assets/{chunk-55IACEB6-B5dE1-Um.js → chunk-XXDRQBXY-B60H0rRC.js} +1 -1
  48. package/dist-web/assets/{chunk-55IACEB6-B12zGIFz.js → chunk-XXDRQBXY-Bn1Xz6TQ.js} +1 -1
  49. package/dist-web/assets/classDiagram-JCYQIIEL-BA1TjAxj.js +1 -0
  50. package/dist-web/assets/classDiagram-JCYQIIEL-BNU7Qn4k.js +1 -0
  51. package/dist-web/assets/classDiagram-v2-OCEON4UE-BA1TjAxj.js +1 -0
  52. package/dist-web/assets/classDiagram-v2-OCEON4UE-BNU7Qn4k.js +1 -0
  53. package/dist-web/assets/{cose-bilkent-S5V4N54A-Bi19n8m-.js → cose-bilkent-JH36ORCC-4Ybddg08.js} +1 -1
  54. package/dist-web/assets/{cose-bilkent-S5V4N54A-c8o8NFp5.js → cose-bilkent-JH36ORCC-DqigO3T4.js} +1 -1
  55. package/dist-web/assets/cynefin-VYW2F7L2-C-EfYT07.js +178 -0
  56. package/dist-web/assets/cynefin-VYW2F7L2-rpD93tQ-.js +178 -0
  57. package/dist-web/assets/cynefinDiagram-MW4NZA55-DWZPLJcD.js +62 -0
  58. package/dist-web/assets/cynefinDiagram-MW4NZA55-DbTqnkVJ.js +62 -0
  59. package/dist-web/assets/dagre-VZM6K2ZE-DcM8aEVY.js +4 -0
  60. package/dist-web/assets/dagre-VZM6K2ZE-M_HVNtqP.js +4 -0
  61. package/dist-web/assets/diagram-7IWD3JNH-DoNximNF.js +30 -0
  62. package/dist-web/assets/diagram-7IWD3JNH-UymgsBNa.js +30 -0
  63. package/dist-web/assets/{diagram-KO2AKTUF-CFQs13i5.js → diagram-B4RE2ZJO-BVA2EhnC.js} +3 -3
  64. package/dist-web/assets/{diagram-KO2AKTUF-agFIuPJW.js → diagram-B4RE2ZJO-BiYu5WPF.js} +3 -3
  65. package/dist-web/assets/{diagram-LMA3HP47-TMIXizxR.js → diagram-LBJQPF4R-BD3kkgOO.js} +2 -2
  66. package/dist-web/assets/{diagram-LMA3HP47-He5zlyMt.js → diagram-LBJQPF4R-m3a1Euj3.js} +2 -2
  67. package/dist-web/assets/diagram-Q27KOJAE-D1mYQ_cI.js +24 -0
  68. package/dist-web/assets/diagram-Q27KOJAE-hy_T73PK.js +24 -0
  69. package/dist-web/assets/diagram-UB23O5K3-BWkoQZ4A.js +41 -0
  70. package/dist-web/assets/diagram-UB23O5K3-BtX8u6HG.js +41 -0
  71. package/dist-web/assets/ebnfDiagram-BXEA7PRR-BKs9JUHW.js +1 -0
  72. package/dist-web/assets/ebnfDiagram-BXEA7PRR-CBAnFkRF.js +1 -0
  73. package/dist-web/assets/erDiagram-JOGREHBK-3vKcWsxm.js +85 -0
  74. package/dist-web/assets/erDiagram-JOGREHBK-BIpd6dTf.js +85 -0
  75. package/dist-web/assets/flowDiagram-UKHOOZJN-D9wBbHm2.js +156 -0
  76. package/dist-web/assets/flowDiagram-UKHOOZJN-Z83i2UWI.js +156 -0
  77. package/dist-web/assets/ganttDiagram-PKOTCBZU-Cd_dViF-.js +292 -0
  78. package/dist-web/assets/ganttDiagram-PKOTCBZU-DFrb_S1d.js +292 -0
  79. package/dist-web/assets/{gitGraphDiagram-PVQCEYII-BSDFfwdY.js → gitGraphDiagram-DS77QQ5N-BiEEtTo7.js} +3 -3
  80. package/dist-web/assets/{gitGraphDiagram-PVQCEYII-DMbTATyw.js → gitGraphDiagram-DS77QQ5N-Dp3Ar-hi.js} +3 -3
  81. package/dist-web/assets/{graph-BwjfAU3j.js → graph-CAUpWmoK.js} +1 -1
  82. package/dist-web/assets/{graph--OzhPTMs.js → graph-DOmOIIwC.js} +1 -1
  83. package/dist-web/assets/{index-W6VnSrkB.js → index-Ba1OvLjf.js} +2 -2
  84. package/dist-web/assets/{index-CkVgGDpx.js → index-CiPA8Kex.js} +4 -4
  85. package/dist-web/assets/{index-BzK4vJBu.js → index-DdEakFJM.js} +1 -1
  86. package/dist-web/assets/{index10-Czg_oF-W.js → index10-CNr4U-Nw.js} +1 -1
  87. package/dist-web/assets/{index11-BjzCZuCr.js → index11-Dto_yZNz.js} +1 -1
  88. package/dist-web/assets/{index5-DlVoNkCD.js → index5-B2PldaO2.js} +1 -1
  89. package/dist-web/assets/{index6-BxiXA2yo.js → index6-CBdZmmyx.js} +1 -1
  90. package/dist-web/assets/{index7-BPdza6d1.js → index7-Dz9oCsUF.js} +1 -1
  91. package/dist-web/assets/{index8-Q_XzGC1Z.js → index8-B6k25jtU.js} +2 -2
  92. package/dist-web/assets/{infoDiagram-5YYISTIA-2JF3XEdD.js → infoDiagram-6WML65LV-BSa2g04G.js} +1 -1
  93. package/dist-web/assets/{infoDiagram-5YYISTIA-UrQusrJq.js → infoDiagram-6WML65LV-D4ph2sIH.js} +1 -1
  94. package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-7RVUL-vB.js → ishikawaDiagram-WSZJBQD7-DjKjbMm9.js} +5 -5
  95. package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-C5OstRVV.js → ishikawaDiagram-WSZJBQD7-Hm36UOQe.js} +5 -5
  96. package/dist-web/assets/{journeyDiagram-JHISSGLW-B34fCMu9.js → journeyDiagram-NVQOT4AX-DttHDfPQ.js} +1 -1
  97. package/dist-web/assets/{journeyDiagram-JHISSGLW-yctdo4bX.js → journeyDiagram-NVQOT4AX-MvWWPNDV.js} +1 -1
  98. package/dist-web/assets/{kanban-definition-UN3LZRKU-BS4FBZsQ.js → kanban-definition-27J2QSJJ-C5gB-W0d.js} +7 -7
  99. package/dist-web/assets/{kanban-definition-UN3LZRKU-CxBCv27E.js → kanban-definition-27J2QSJJ-Cu-E_cXA.js} +5 -5
  100. package/dist-web/assets/layout-CvP6o9AK.js +1 -0
  101. package/dist-web/assets/layout-D-LzfAck.js +1 -0
  102. package/dist-web/assets/{linear-3mB6q2-g.js → linear-B3HWgQI2.js} +1 -1
  103. package/dist-web/assets/{linear-BKCnUo31.js → linear-BRGe4-d6.js} +1 -1
  104. package/dist-web/assets/map-CWKZqZjr.js +1 -0
  105. package/dist-web/assets/map-DxJ2ADlA.js +1 -0
  106. package/dist-web/assets/mermaid.core-D-9Sx1No.js +314 -0
  107. package/dist-web/assets/mermaidParser.worker-PTFfzpoB.js +318 -0
  108. package/dist-web/assets/{mindmap-definition-RKZ34NQL-BmJZpjh6.js → mindmap-definition-FAOFIHXS-C4vnms3i.js} +2 -2
  109. package/dist-web/assets/{mindmap-definition-RKZ34NQL-1mjWUcf6.js → mindmap-definition-FAOFIHXS-Cg_hoVIq.js} +1 -1
  110. package/dist-web/assets/pegDiagram-VL7TDLO6-B2fFEFUH.js +1 -0
  111. package/dist-web/assets/pegDiagram-VL7TDLO6-CSX9hitD.js +1 -0
  112. package/dist-web/assets/pieDiagram-7S7Q4E2Y-0L0mxahZ.js +39 -0
  113. package/dist-web/assets/pieDiagram-7S7Q4E2Y-C7T0Cmw1.js +39 -0
  114. package/dist-web/assets/{quadrantDiagram-W4KKPZXB-BmT_qM09.js → quadrantDiagram-CIZ2JOQS-BBy7w4kD.js} +3 -3
  115. package/dist-web/assets/{quadrantDiagram-W4KKPZXB-C0kPuyNP.js → quadrantDiagram-CIZ2JOQS-U483z0er.js} +3 -3
  116. package/dist-web/assets/railroadDiagram-AXF67PYL-D80a2_DJ.js +1 -0
  117. package/dist-web/assets/railroadDiagram-AXF67PYL-DX8y0MzW.js +1 -0
  118. package/dist-web/assets/{requirementDiagram-4Y6WPE33-C0YP_Amt.js → requirementDiagram-LRYGKXZP-CeyHfq8t.js} +3 -3
  119. package/dist-web/assets/{requirementDiagram-4Y6WPE33-CZrxH1Y2.js → requirementDiagram-LRYGKXZP-DGD5J_4k.js} +3 -3
  120. package/dist-web/assets/sankeyDiagram-W5VNT64P-CCISkkrR.js +40 -0
  121. package/dist-web/assets/sankeyDiagram-W5VNT64P-CT5PdZz2.js +40 -0
  122. package/dist-web/assets/sequenceDiagram-SI44F4Z6-BeMzHWXI.js +162 -0
  123. package/dist-web/assets/sequenceDiagram-SI44F4Z6-jQfm2XS7.js +162 -0
  124. package/dist-web/assets/sizeCapture-X5ZJPWSS-BQsTdtrv.js +1 -0
  125. package/dist-web/assets/sizeCapture-X5ZJPWSS-lRZsmCoS.js +1 -0
  126. package/dist-web/assets/stateDiagram-OKZ733FA-ClCgTdUm.js +1 -0
  127. package/dist-web/assets/stateDiagram-OKZ733FA-Cv59z5YT.js +1 -0
  128. package/dist-web/assets/stateDiagram-v2-UEYNNEHI-R8jTc--F.js +1 -0
  129. package/dist-web/assets/stateDiagram-v2-UEYNNEHI-fi_lrTAx.js +1 -0
  130. package/dist-web/assets/swimlanes-SLNWSIFB-BCdOUN05.js +2 -0
  131. package/dist-web/assets/swimlanes-SLNWSIFB-Cu5l7SuR.js +1 -0
  132. package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-BUd_uYK3.js +8 -0
  133. package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-CalrsgPK.js +8 -0
  134. package/dist-web/assets/{timeline-definition-PNZ67QCA-DsVZdrZa.js → timeline-definition-Z64GVDOM-CMjnh4bu.js} +4 -4
  135. package/dist-web/assets/{timeline-definition-PNZ67QCA-DnB6Usl0.js → timeline-definition-Z64GVDOM-DpWutSKa.js} +4 -4
  136. package/dist-web/assets/vennDiagram-T6HMQDX7-DKJW_8oU.js +34 -0
  137. package/dist-web/assets/vennDiagram-T6HMQDX7-DVC5JVsc.js +34 -0
  138. package/dist-web/assets/{vue.runtime.esm-bundler-pgHGheCW.js → vue.runtime.esm-bundler-BwwRtQwQ.js} +1 -1
  139. package/dist-web/assets/{wardleyDiagram-YWT4CUSO-oBauTCEw.js → wardleyDiagram-T6FBY63Y-BK2mrq7L.js} +3 -3
  140. package/dist-web/assets/{wardleyDiagram-YWT4CUSO-DCiyDQNB.js → wardleyDiagram-T6FBY63Y-oUvgepFn.js} +3 -3
  141. package/dist-web/assets/xychartDiagram-ELKLHX3M-DI6n79q0.js +7 -0
  142. package/dist-web/assets/xychartDiagram-ELKLHX3M-DUJu9F7-.js +7 -0
  143. package/dist-web/index.html +1 -1
  144. package/dist-web/vis/index.html.gz +0 -0
  145. package/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  146. package/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  147. package/package.json +9 -11
  148. package/skills/screenshot-lesen/SKILL.md +0 -1
  149. package/skills/web-lesen/SKILL.md +0 -1
  150. package/telegram-plugin/dist/bridge.mjs +7 -25
  151. package/telegram-plugin/dist/mcp-server.mjs +236 -71
  152. package/dist-web/assets/arc-4xPfymbf.js +0 -1
  153. package/dist-web/assets/arc-Doj0wRZ0.js +0 -1
  154. package/dist-web/assets/architectureDiagram-3BPJPVTR-BGih283a.js +0 -36
  155. package/dist-web/assets/architectureDiagram-3BPJPVTR-CQ09RrbH.js +0 -36
  156. package/dist-web/assets/blockDiagram-GPEHLZMM-3ShMf1gu.js +0 -132
  157. package/dist-web/assets/blockDiagram-GPEHLZMM-CAtDjkJt.js +0 -132
  158. package/dist-web/assets/channel-DNkUo9e6.js +0 -1
  159. package/dist-web/assets/channel-DcnUTIGB.js +0 -1
  160. package/dist-web/assets/chunk-AQP2D5EJ-FS8-f8lF.js +0 -231
  161. package/dist-web/assets/chunk-AQP2D5EJ-UKhb4V4r.js +0 -231
  162. package/dist-web/assets/classDiagram-4FO5ZUOK-B1ZO8EbE.js +0 -1
  163. package/dist-web/assets/classDiagram-4FO5ZUOK-xk6cM9Kq.js +0 -1
  164. package/dist-web/assets/classDiagram-v2-Q7XG4LA2-B1ZO8EbE.js +0 -1
  165. package/dist-web/assets/classDiagram-v2-Q7XG4LA2-xk6cM9Kq.js +0 -1
  166. package/dist-web/assets/dagre-BM42HDAG-CmUO9qKN.js +0 -4
  167. package/dist-web/assets/dagre-BM42HDAG-DLMfLCoV.js +0 -4
  168. package/dist-web/assets/diagram-2AECGRRQ-DQTst0OH.js +0 -43
  169. package/dist-web/assets/diagram-2AECGRRQ-L74iLMqd.js +0 -43
  170. package/dist-web/assets/diagram-5GNKFQAL-BiBm7CJR.js +0 -10
  171. package/dist-web/assets/diagram-5GNKFQAL-DoE6q7H1.js +0 -10
  172. package/dist-web/assets/diagram-OG6HWLK6-BHCt1E0n.js +0 -24
  173. package/dist-web/assets/diagram-OG6HWLK6-DRyxjFMa.js +0 -24
  174. package/dist-web/assets/erDiagram-TEJ5UH35-BoDczjGG.js +0 -85
  175. package/dist-web/assets/erDiagram-TEJ5UH35-yd6SOv_7.js +0 -85
  176. package/dist-web/assets/flowDiagram-I6XJVG4X-DHoceI7r.js +0 -162
  177. package/dist-web/assets/flowDiagram-I6XJVG4X-DkYNQv0R.js +0 -162
  178. package/dist-web/assets/ganttDiagram-6RSMTGT7-Cg1TQBc0.js +0 -292
  179. package/dist-web/assets/ganttDiagram-6RSMTGT7-Z6klo7KK.js +0 -292
  180. package/dist-web/assets/layout-C1ojF0zw.js +0 -1
  181. package/dist-web/assets/layout-SsrduOYp.js +0 -1
  182. package/dist-web/assets/mermaid.core-D_lKT0dR.js +0 -309
  183. package/dist-web/assets/mermaidParser.worker-Dx4jPi9z.js +0 -313
  184. package/dist-web/assets/pieDiagram-4H26LBE5-BU41t2A_.js +0 -30
  185. package/dist-web/assets/pieDiagram-4H26LBE5-BkwDAvbt.js +0 -30
  186. package/dist-web/assets/sankeyDiagram-5OEKKPKP-De_o7hDr.js +0 -40
  187. package/dist-web/assets/sankeyDiagram-5OEKKPKP-Dvuj6bMA.js +0 -40
  188. package/dist-web/assets/sequenceDiagram-3UESZ5HK-DuCrgPyA.js +0 -162
  189. package/dist-web/assets/sequenceDiagram-3UESZ5HK-VAxffBe7.js +0 -162
  190. package/dist-web/assets/stateDiagram-AJRCARHV-CYLupxM7.js +0 -1
  191. package/dist-web/assets/stateDiagram-AJRCARHV-nDExQydZ.js +0 -1
  192. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-BhEc7Thx.js +0 -1
  193. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-BzwD_BIl.js +0 -1
  194. package/dist-web/assets/vennDiagram-CIIHVFJN-BBHQmCFf.js +0 -34
  195. package/dist-web/assets/vennDiagram-CIIHVFJN-Cfj-K9NW.js +0 -34
  196. package/dist-web/assets/wardley-L42UT6IY-BJFn8eDD.js +0 -173
  197. package/dist-web/assets/wardley-L42UT6IY-BSu8-4hg.js +0 -173
  198. package/dist-web/assets/xychartDiagram-2RQKCTM6-C2iZpl9I.js +0 -7
  199. package/dist-web/assets/xychartDiagram-2RQKCTM6-Db_VoDBV.js +0 -7
  200. package/mnemo/access_routes.js +0 -692
  201. package/mnemo/agent_governance.js +0 -4242
  202. package/mnemo/agent_mail.js +0 -901
  203. package/mnemo/bootstrap_auto.js +0 -137
  204. package/mnemo/brief_coordination.js +0 -226
  205. package/mnemo/code_read_tools.js +0 -375
  206. package/mnemo/context_preview_tools.js +0 -603
  207. package/mnemo/embeddings.js +0 -66
  208. package/mnemo/external_repo_ops.js +0 -575
  209. package/mnemo/facts/example-project-rules.json +0 -90
  210. package/mnemo/facts/example.json +0 -34
  211. package/mnemo/identity_schema.sql +0 -139
  212. package/mnemo/journal_schema.js +0 -561
  213. package/mnemo/loop_doctor_tools.js +0 -661
  214. package/mnemo/mail_secret_refs.js +0 -150
  215. package/mnemo/mcp.js +0 -9309
  216. package/mnemo/memory_consolidation.js +0 -1914
  217. package/mnemo/memory_health_tools.js +0 -165
  218. package/mnemo/package.json +0 -79
  219. package/mnemo/protected_scope_gate.js +0 -627
  220. package/mnemo/resource_access_control.js +0 -684
  221. package/mnemo/runtime_governance.js +0 -1256
  222. package/mnemo/runtime_turn_gate.js +0 -862
  223. package/mnemo/sandbox.js +0 -143
  224. package/mnemo/schema.sql +0 -389
  225. package/mnemo/shared_utils.js +0 -763
  226. package/mnemo/skills/agent-auto-resume/SKILL.md +0 -56
  227. package/mnemo/skills/agent_hand/SKILL.md +0 -43
  228. package/mnemo/skills/agent_hand/run.js +0 -63
  229. package/mnemo/skills/book_flight/SKILL.md +0 -34
  230. package/mnemo/skills/external_repo_review/SKILL.md +0 -43
  231. package/mnemo/skills/external_repo_review/run.js +0 -73
  232. package/mnemo/skills/pay_invoice/SKILL.md +0 -34
  233. package/mnemo/team_quality_ops.js +0 -944
  234. package/mnemo/timeline_report_tools.js +0 -810
  235. package/mnemo/write_gate_risk.js +0 -80
  236. package/mnemo/writer_health.js +0 -152
  237. package/skills/doku-ingestion/SKILL.md +0 -48
  238. package/skills/doku-ingestion/ingest_docs.py +0 -133
@@ -1,1914 +0,0 @@
1
- "use strict";
2
-
3
- const crypto = require("crypto");
4
- const {
5
- cleanScope,
6
- compactContent,
7
- freshnessFromAgeDays,
8
- isoAgeDays,
9
- jsonSafe,
10
- normalizeAgentName,
11
- parseMaybeJson,
12
- uniqueStrings,
13
- } = require("./shared_utils");
14
-
15
- const DEFAULT_SCOPE = "default";
16
- const PHASES = new Set(["light", "daily", "deep", "rem"]);
17
- const DREAM_BUCKET_KEYS = ["wrong_made", "right_made", "praise_received", "called_out", "broke_things"];
18
-
19
- function nowIso() {
20
- return new Date().toISOString();
21
- }
22
-
23
- function sha(value) {
24
- return crypto.createHash("sha256").update(String(value)).digest("hex");
25
- }
26
-
27
- function scopeName(scope) {
28
- return cleanScope(scope || DEFAULT_SCOPE);
29
- }
30
-
31
- function normalizeDepartment(value) {
32
- return String(value || "")
33
- .trim()
34
- .toLowerCase()
35
- .replace(/[^a-z0-9._-]+/g, "-")
36
- .replace(/^-+|-+$/g, "") || "general";
37
- }
38
-
39
- function textOrNull(value, max = 8000) {
40
- const compact = compactContent(value, max);
41
- return compact && compact.trim() ? compact : null;
42
- }
43
-
44
- function listInput(value) {
45
- if (Array.isArray(value)) return uniqueStrings(value);
46
- const parsed = parseMaybeJson(value, null);
47
- if (Array.isArray(parsed)) return uniqueStrings(parsed);
48
- return uniqueStrings(String(value || "").split(/[\n,;]+/).map((item) => item.trim()).filter(Boolean));
49
- }
50
-
51
- function clampInt(value, fallback, min, max) {
52
- const n = parseInt(value, 10);
53
- if (!Number.isFinite(n)) return fallback;
54
- return Math.min(Math.max(n, min), max);
55
- }
56
-
57
- function tableExists(db, tableName) {
58
- try {
59
- return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type IN ('table','view') AND name=?").get(tableName);
60
- } catch {
61
- return false;
62
- }
63
- }
64
-
65
- function tableColumns(db, tableName) {
66
- try {
67
- return db.prepare(`PRAGMA table_info(${tableName})`).all().map((col) => col.name);
68
- } catch {
69
- return [];
70
- }
71
- }
72
-
73
- function hasColumn(db, tableName, columnName) {
74
- return tableColumns(db, tableName).includes(columnName);
75
- }
76
-
77
- function safeJson(value, fallback) {
78
- if (value === undefined) return JSON.stringify(fallback);
79
- return jsonSafe(value, 30000) || JSON.stringify(fallback);
80
- }
81
-
82
- function parseJson(value, fallback) {
83
- return parseMaybeJson(value, fallback);
84
- }
85
-
86
- function ensureMemoryLayerColumn(db) {
87
- if (!tableExists(db, "memory")) return false;
88
- const cols = tableColumns(db, "memory");
89
- if (!cols.includes("layer")) {
90
- try {
91
- db.exec("ALTER TABLE memory ADD COLUMN layer TEXT");
92
- } catch {}
93
- }
94
- try {
95
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_layer ON memory(layer)");
96
- db.exec(`
97
- UPDATE memory SET layer = CASE
98
- WHEN kind IN ('tool_call','ssh_cmd','web_fetch','skill','skill_run') THEN 'procedural'
99
- WHEN kind IN ('memory_md','decision','scar','manual','dream','reflection','memory_consolidation','company_fact_set') THEN 'semantic'
100
- WHEN kind IN ('message','edit') THEN 'episodic'
101
- ELSE 'episodic'
102
- END
103
- WHERE layer IS NULL OR layer = ''
104
- `);
105
- } catch {}
106
- return hasColumn(db, "memory", "layer");
107
- }
108
-
109
- function ensureMemoryConsolidationSchema(db) {
110
- ensureMemoryLayerColumn(db);
111
- db.exec(`
112
- CREATE TABLE IF NOT EXISTS daily_reflection (
113
- id INTEGER PRIMARY KEY AUTOINCREMENT,
114
- reflection_date TEXT NOT NULL UNIQUE,
115
- generated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
116
- events_examined INTEGER NOT NULL DEFAULT 0,
117
- corrections INTEGER NOT NULL DEFAULT 0,
118
- praises INTEGER NOT NULL DEFAULT 0,
119
- trait_diffs_json TEXT,
120
- belief_diffs_json TEXT,
121
- summary TEXT,
122
- next_day_focus TEXT
123
- );
124
- CREATE INDEX IF NOT EXISTS idx_reflection_date ON daily_reflection(reflection_date);
125
-
126
- CREATE TABLE IF NOT EXISTS cycle_event (
127
- id INTEGER PRIMARY KEY AUTOINCREMENT,
128
- phase TEXT NOT NULL,
129
- ran_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
130
- window_from TEXT NOT NULL,
131
- window_to TEXT NOT NULL,
132
- inputs_count INTEGER NOT NULL DEFAULT 0,
133
- promoted_count INTEGER NOT NULL DEFAULT 0,
134
- summary TEXT,
135
- delta_json TEXT
136
- );
137
- CREATE INDEX IF NOT EXISTS idx_cycle_phase ON cycle_event(phase);
138
- CREATE INDEX IF NOT EXISTS idx_cycle_ran ON cycle_event(ran_at);
139
-
140
- CREATE TABLE IF NOT EXISTS memory_consolidation_run (
141
- id INTEGER PRIMARY KEY AUTOINCREMENT,
142
- scope TEXT NOT NULL DEFAULT 'default',
143
- agent_name TEXT,
144
- project TEXT,
145
- phase TEXT NOT NULL,
146
- source_window_start TEXT NOT NULL,
147
- source_window_end TEXT NOT NULL,
148
- source_counts_json TEXT,
149
- selected_refs_json TEXT,
150
- summary TEXT NOT NULL,
151
- promoted_memory_id INTEGER,
152
- status TEXT NOT NULL DEFAULT 'draft',
153
- confidence TEXT NOT NULL DEFAULT 'derived',
154
- review_status TEXT NOT NULL DEFAULT 'draft',
155
- meta_json TEXT,
156
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
157
- );
158
- CREATE INDEX IF NOT EXISTS idx_mem_consolidation_phase ON memory_consolidation_run(phase, created_at DESC);
159
- CREATE INDEX IF NOT EXISTS idx_mem_consolidation_project ON memory_consolidation_run(project, created_at DESC);
160
- CREATE INDEX IF NOT EXISTS idx_mem_consolidation_agent ON memory_consolidation_run(agent_name, created_at DESC);
161
-
162
- CREATE TABLE IF NOT EXISTS department_journal (
163
- id INTEGER PRIMARY KEY AUTOINCREMENT,
164
- scope TEXT NOT NULL DEFAULT 'default',
165
- department_name TEXT NOT NULL,
166
- agent_name TEXT,
167
- project TEXT,
168
- journal_date TEXT NOT NULL,
169
- progress TEXT,
170
- blockers TEXT,
171
- risks TEXT,
172
- open_questions TEXT,
173
- dependencies_json TEXT,
174
- foreign_scope_requests_json TEXT,
175
- status TEXT NOT NULL DEFAULT 'open',
176
- meta_json TEXT,
177
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
178
- );
179
- CREATE INDEX IF NOT EXISTS idx_department_journal_dept ON department_journal(scope, department_name, journal_date DESC);
180
- CREATE INDEX IF NOT EXISTS idx_department_journal_project ON department_journal(project, journal_date DESC);
181
- CREATE INDEX IF NOT EXISTS idx_department_journal_agent ON department_journal(agent_name, journal_date DESC);
182
-
183
- CREATE TABLE IF NOT EXISTS agent_sleep_note (
184
- id INTEGER PRIMARY KEY AUTOINCREMENT,
185
- scope TEXT NOT NULL DEFAULT 'default',
186
- agent_name TEXT NOT NULL,
187
- project TEXT,
188
- note_date TEXT NOT NULL,
189
- learned TEXT,
190
- uncertainty TEXT,
191
- recurring_errors TEXT,
192
- needed_context TEXT,
193
- improvement_idea TEXT,
194
- source_ref TEXT,
195
- status TEXT NOT NULL DEFAULT 'draft',
196
- meta_json TEXT,
197
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
198
- );
199
- CREATE INDEX IF NOT EXISTS idx_agent_sleep_agent ON agent_sleep_note(scope, agent_name, note_date DESC);
200
- CREATE INDEX IF NOT EXISTS idx_agent_sleep_project ON agent_sleep_note(project, note_date DESC);
201
-
202
- CREATE TABLE IF NOT EXISTS memory_promotion_proposal (
203
- id INTEGER PRIMARY KEY AUTOINCREMENT,
204
- scope TEXT NOT NULL DEFAULT 'default',
205
- proposal_kind TEXT NOT NULL,
206
- title TEXT NOT NULL,
207
- body TEXT,
208
- project TEXT,
209
- department_name TEXT,
210
- agent_name TEXT,
211
- source_kind TEXT,
212
- source_id TEXT,
213
- evidence_json TEXT,
214
- status TEXT NOT NULL DEFAULT 'proposed',
215
- reviewer TEXT,
216
- review_notes TEXT,
217
- promoted_ref_kind TEXT,
218
- promoted_ref_id TEXT,
219
- meta_json TEXT,
220
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
221
- decided_at TEXT
222
- );
223
- CREATE INDEX IF NOT EXISTS idx_memory_promotion_status ON memory_promotion_proposal(scope, status, created_at DESC);
224
- CREATE INDEX IF NOT EXISTS idx_memory_promotion_project ON memory_promotion_proposal(project, status, created_at DESC);
225
- CREATE INDEX IF NOT EXISTS idx_memory_promotion_agent ON memory_promotion_proposal(agent_name, status, created_at DESC);
226
-
227
- CREATE TABLE IF NOT EXISTS dreammode_run (
228
- id INTEGER PRIMARY KEY AUTOINCREMENT,
229
- scope TEXT NOT NULL DEFAULT 'default',
230
- agent_name TEXT NOT NULL DEFAULT '',
231
- project TEXT NOT NULL DEFAULT '',
232
- dream_date TEXT NOT NULL,
233
- source_window_start TEXT NOT NULL,
234
- source_window_end TEXT NOT NULL,
235
- messages_examined INTEGER NOT NULL DEFAULT 0,
236
- actions_examined INTEGER NOT NULL DEFAULT 0,
237
- events_examined INTEGER NOT NULL DEFAULT 0,
238
- wrong_made_json TEXT,
239
- right_made_json TEXT,
240
- praise_received_json TEXT,
241
- called_out_json TEXT,
242
- broke_things_json TEXT,
243
- lessons_json TEXT,
244
- rem_run_ids_json TEXT,
245
- summary TEXT NOT NULL,
246
- brief_id INTEGER,
247
- status TEXT NOT NULL DEFAULT 'draft',
248
- meta_json TEXT,
249
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
250
- UNIQUE(scope, agent_name, project, dream_date)
251
- );
252
- CREATE INDEX IF NOT EXISTS idx_dreammode_date ON dreammode_run(scope, dream_date DESC);
253
- CREATE INDEX IF NOT EXISTS idx_dreammode_project ON dreammode_run(project, dream_date DESC);
254
- CREATE INDEX IF NOT EXISTS idx_dreammode_agent ON dreammode_run(agent_name, dream_date DESC);
255
- `);
256
- try {
257
- db.exec(`
258
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_memory_consolidation_ai AFTER INSERT ON memory_consolidation_run BEGIN
259
- INSERT INTO mnemo_event_journal
260
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
261
- VALUES
262
- ('memory_consolidation', NEW.project, 'internal', NEW.agent_name, 'memory_consolidation_insert', 'memory_consolidation_run', CAST(NEW.id AS TEXT), NEW.status, NEW.summary, NEW.selected_refs_json, NEW.meta_json, NEW.created_at);
263
- END;
264
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_department_journal_ai AFTER INSERT ON department_journal BEGIN
265
- INSERT INTO mnemo_event_journal
266
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
267
- VALUES
268
- ('department_journal', NEW.project, 'internal', NEW.agent_name, 'department_journal_insert', 'department_journal', CAST(NEW.id AS TEXT), NEW.status, COALESCE(NEW.progress, NEW.blockers, NEW.risks, ''), NEW.dependencies_json, NEW.meta_json, NEW.created_at);
269
- END;
270
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_agent_sleep_ai AFTER INSERT ON agent_sleep_note BEGIN
271
- INSERT INTO mnemo_event_journal
272
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
273
- VALUES
274
- ('agent_sleep_note', NEW.project, 'internal', NEW.agent_name, 'agent_sleep_note_insert', 'agent_sleep_note', CAST(NEW.id AS TEXT), NEW.status, COALESCE(NEW.learned, NEW.uncertainty, NEW.recurring_errors, ''), NULL, NEW.meta_json, NEW.created_at);
275
- END;
276
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_memory_promotion_ai AFTER INSERT ON memory_promotion_proposal BEGIN
277
- INSERT INTO mnemo_event_journal
278
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
279
- VALUES
280
- ('memory_promotion_proposal', NEW.project, 'internal', NEW.agent_name, 'memory_promotion_proposal_insert', 'memory_promotion_proposal', CAST(NEW.id AS TEXT), NEW.status, NEW.title || CASE WHEN NEW.body IS NULL THEN '' ELSE ': ' || NEW.body END, NEW.evidence_json, NEW.meta_json, NEW.created_at);
281
- END;
282
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_dreammode_ai AFTER INSERT ON dreammode_run BEGIN
283
- INSERT INTO mnemo_event_journal
284
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
285
- VALUES
286
- ('dreammode', NEW.project, 'internal', NEW.agent_name, 'dreammode_run_insert', 'dreammode_run', CAST(NEW.id AS TEXT), NEW.status, NEW.summary, NEW.lessons_json, NEW.meta_json, NEW.created_at);
287
- END;
288
- `);
289
- } catch {}
290
- }
291
-
292
- function whereProject(input, column = "topic") {
293
- const project = String(input.project || "").trim();
294
- if (!project) return { sql: "", params: [] };
295
- return { sql: ` AND (COALESCE(${column}, '') = ? OR COALESCE(meta_json, '') LIKE ?)`, params: [project, `%${project}%`] };
296
- }
297
-
298
- function countTable(db, tableName, whereSql = "", params = []) {
299
- if (!tableExists(db, tableName)) return 0;
300
- try {
301
- return db.prepare(`SELECT COUNT(*) c FROM ${tableName}${whereSql}`).get(...params).c || 0;
302
- } catch {
303
- return 0;
304
- }
305
- }
306
-
307
- function latestRow(db, tableName, orderCol, whereSql = "", params = []) {
308
- if (!tableExists(db, tableName)) return null;
309
- try {
310
- return db.prepare(`SELECT * FROM ${tableName}${whereSql} ORDER BY ${orderCol} DESC LIMIT 1`).get(...params) || null;
311
- } catch {
312
- return null;
313
- }
314
- }
315
-
316
- function memoryLayerCounts(db, input = {}) {
317
- if (!tableExists(db, "memory")) return [];
318
- ensureMemoryLayerColumn(db);
319
- const days = clampInt(input.days, 7, 1, 3650);
320
- const since = input.since || new Date(Date.now() - days * 86400000).toISOString();
321
- const project = whereProject(input, "topic");
322
- try {
323
- return db.prepare(`
324
- SELECT COALESCE(layer, 'episodic') AS layer, kind, COUNT(*) AS count, MAX(occurred_at) AS last_at
325
- FROM memory
326
- WHERE occurred_at >= ?${project.sql}
327
- GROUP BY COALESCE(layer, 'episodic'), kind
328
- ORDER BY layer, count DESC
329
- `).all(since, ...project.params);
330
- } catch {
331
- return [];
332
- }
333
- }
334
-
335
- function sourceCounts(db, input = {}) {
336
- const days = clampInt(input.days, 7, 1, 3650);
337
- const since = input.since || new Date(Date.now() - days * 86400000).toISOString();
338
- const counts = {
339
- since,
340
- memory: 0,
341
- transcript: 0,
342
- capture_receipt: 0,
343
- mnemo_event_journal: 0,
344
- agent_action: 0,
345
- session_handoff: 0,
346
- decision_log: 0,
347
- quality_finding: 0,
348
- daily_reflection: 0,
349
- cycle_event: 0,
350
- runtime_tool_receipt: 0,
351
- department_journal: 0,
352
- agent_sleep_note: 0,
353
- memory_promotion_proposal: 0,
354
- };
355
- if (tableExists(db, "memory")) {
356
- const p = whereProject(input, "topic");
357
- counts.memory = countTable(db, "memory", ` WHERE occurred_at >= ?${p.sql}`, [since, ...p.params]);
358
- }
359
- if (tableExists(db, "transcript")) counts.transcript = countTable(db, "transcript", " WHERE occurred_at >= ?", [since]);
360
- if (tableExists(db, "capture_receipt")) counts.capture_receipt = countTable(db, "capture_receipt", " WHERE last_seen_at >= ?", [since]);
361
- if (tableExists(db, "mnemo_event_journal")) counts.mnemo_event_journal = countTable(db, "mnemo_event_journal", " WHERE occurred_at >= ?", [since]);
362
- if (tableExists(db, "agent_action")) counts.agent_action = countTable(db, "agent_action", " WHERE started_at >= ?", [since]);
363
- if (tableExists(db, "session_handoff")) counts.session_handoff = countTable(db, "session_handoff", " WHERE created_at >= ?", [since]);
364
- if (tableExists(db, "decision_log")) counts.decision_log = countTable(db, "decision_log", " WHERE decided_at >= ?", [since]);
365
- if (tableExists(db, "quality_finding")) counts.quality_finding = countTable(db, "quality_finding", " WHERE created_at >= ?", [since]);
366
- if (tableExists(db, "daily_reflection")) counts.daily_reflection = countTable(db, "daily_reflection", " WHERE generated_at >= ?", [since]);
367
- if (tableExists(db, "cycle_event")) counts.cycle_event = countTable(db, "cycle_event", " WHERE ran_at >= ?", [since]);
368
- if (tableExists(db, "runtime_tool_receipt")) counts.runtime_tool_receipt = countTable(db, "runtime_tool_receipt", " WHERE started_at >= ?", [since]);
369
- if (tableExists(db, "department_journal")) counts.department_journal = countTable(db, "department_journal", " WHERE created_at >= ?", [since]);
370
- if (tableExists(db, "agent_sleep_note")) counts.agent_sleep_note = countTable(db, "agent_sleep_note", " WHERE created_at >= ?", [since]);
371
- if (tableExists(db, "memory_promotion_proposal")) counts.memory_promotion_proposal = countTable(db, "memory_promotion_proposal", " WHERE created_at >= ?", [since]);
372
- return counts;
373
- }
374
-
375
- function canonicalMemoryModel() {
376
- return {
377
- authority: "mnemo",
378
- rule: "External runtimes may collect or execute, but Mnemo owns durable truth, identity, claims, approvals, evidence, and memory promotion.",
379
- layers: [
380
- { name: "company_ledger", mnemo_sources: ["decision_log", "work_claim", "approval_request", "runtime_tool_receipt", "session_handoff", "quality_finding", "project_rules"], purpose: "official company truth and audit trail" },
381
- { name: "department_journal", mnemo_sources: ["department_journal"], purpose: "department-level diary; explains work history but is not official truth until promoted" },
382
- { name: "agent_sleep_notes", mnemo_sources: ["agent_sleep_note"], purpose: "personal agent REM notes; never official truth until reviewed" },
383
- { name: "session", mnemo_sources: ["transcript", "capture_receipt", "agent_action", "memory:episodic"], purpose: "current conversation, tool steps, raw events" },
384
- { name: "daily", mnemo_sources: ["daily_reflection", "memory_consolidation_run:daily"], purpose: "day-level journal and correction/praise signal" },
385
- { name: "long_term", mnemo_sources: ["memory:semantic", "decision_log", "scar_event", "company facts"], purpose: "stable rules, decisions, scars, project facts" },
386
- { name: "recall", mnemo_sources: ["mem_recall", "mem_recall_layered", "memory_fts", "mnemo_search_fts"], purpose: "searchable retrieval, not a second store" },
387
- { name: "rem", mnemo_sources: ["cycle_event", "memory_consolidation_run:rem"], purpose: "background consolidation and pattern extraction" },
388
- ],
389
- };
390
- }
391
-
392
- function latestDailyReflection(db) {
393
- if (!tableExists(db, "daily_reflection")) return null;
394
- const cols = tableColumns(db, "daily_reflection");
395
- const dateCol = cols.includes("reflection_date") ? "reflection_date" : (cols.includes("date") ? "date" : null);
396
- if (!dateCol) return null;
397
- try {
398
- return db.prepare(`SELECT * FROM daily_reflection ORDER BY ${dateCol} DESC, generated_at DESC LIMIT 1`).get() || null;
399
- } catch {
400
- return null;
401
- }
402
- }
403
-
404
- function latestConsolidationByPhase(db) {
405
- const out = {};
406
- if (!tableExists(db, "memory_consolidation_run")) return out;
407
- for (const phase of PHASES) {
408
- out[phase] = latestRow(db, "memory_consolidation_run", "created_at", " WHERE phase=?", [phase]);
409
- }
410
- return out;
411
- }
412
-
413
- function latestCycleByPhase(db) {
414
- const out = {};
415
- if (!tableExists(db, "cycle_event")) return out;
416
- for (const phase of ["pulse", "settle", "arc"]) {
417
- out[phase] = latestRow(db, "cycle_event", "ran_at", " WHERE phase=?", [phase]);
418
- }
419
- return out;
420
- }
421
-
422
- function memoryLayerStatus(db, input = {}) {
423
- ensureMemoryConsolidationSchema(db);
424
- const days = clampInt(input.days, 7, 1, 3650);
425
- const counts = sourceCounts(db, input);
426
- const layers = memoryLayerCounts(db, input);
427
- const latestDaily = latestDailyReflection(db);
428
- const consolidation = latestConsolidationByPhase(db);
429
- const cycles = latestCycleByPhase(db);
430
- const latestRem = consolidation.rem || cycles.arc || null;
431
- const warnings = [];
432
- if (!counts.memory && !counts.transcript && !counts.mnemo_event_journal) warnings.push("no recent raw memory/session events in selected window");
433
- if (!latestDaily) warnings.push("no daily_reflection row found yet");
434
- if (!latestRem) warnings.push("no REM/arc consolidation found yet");
435
- return {
436
- ok: true,
437
- checked_at: nowIso(),
438
- scope: scopeName(input.scope),
439
- agent_name: input.agent_name ? normalizeAgentName(input.agent_name) : null,
440
- project: input.project || null,
441
- days,
442
- canonical_model: canonicalMemoryModel(),
443
- source_counts: counts,
444
- memory_layers: layers,
445
- latest: {
446
- daily_reflection: latestDaily,
447
- consolidation,
448
- cycle_event: cycles,
449
- },
450
- freshness: {
451
- daily_reflection: freshnessFromAgeDays(isoAgeDays(latestDaily && (latestDaily.generated_at || latestDaily.reflection_date)), 2, 7),
452
- rem: freshnessFromAgeDays(isoAgeDays(latestRem && (latestRem.created_at || latestRem.ran_at)), 7, 21),
453
- },
454
- warnings,
455
- };
456
- }
457
-
458
- function phaseWindowDays(phase, inputDays) {
459
- if (inputDays) return clampInt(inputDays, 1, 1, 3650);
460
- if (phase === "light") return 1;
461
- if (phase === "daily") return 1;
462
- if (phase === "deep") return 3;
463
- return 7;
464
- }
465
-
466
- function memoryRemPlan(db, input = {}) {
467
- ensureMemoryConsolidationSchema(db);
468
- const status = memoryLayerStatus(db, input);
469
- const today = (input.date || new Date().toISOString().slice(0, 10)).slice(0, 10);
470
- const latest = status.latest.consolidation || {};
471
- const counts = status.source_counts || {};
472
- const phases = [];
473
- const add = (phase, due, reason, run_hint) => phases.push({ phase, due, reason, run_hint });
474
- const lightAge = isoAgeDays(latest.light && latest.light.created_at);
475
- const dailyExists = tableExists(db, "daily_reflection")
476
- ? !!db.prepare("SELECT 1 FROM daily_reflection WHERE reflection_date=?").get(today)
477
- : false;
478
- const deepAge = isoAgeDays(latest.deep && latest.deep.created_at);
479
- const remAge = isoAgeDays((latest.rem && latest.rem.created_at) || (status.latest.cycle_event.arc && status.latest.cycle_event.arc.ran_at));
480
-
481
- add("light", (counts.transcript + counts.agent_action + counts.capture_receipt + counts.mnemo_event_journal) > 0 && (lightAge == null || lightAge >= 1),
482
- "Collect the current working/session layer into a short reviewable summary.",
483
- { tool: "mem_memory_rem_run", args: { phase: "light", days: 1, agent_name: input.agent_name || undefined, project: input.project || undefined } });
484
- add("daily", !dailyExists,
485
- `Create or refresh daily reflection for ${today}.`,
486
- { tool: "mem_memory_rem_run", args: { phase: "daily", date: today, agent_name: input.agent_name || undefined, project: input.project || undefined } });
487
- add("deep", (counts.memory + counts.session_handoff + counts.decision_log + counts.quality_finding) > 0 && (deepAge == null || deepAge >= 1),
488
- "Promote durable decisions, handoffs, scars, and high-signal facts into semantic memory.",
489
- { tool: "mem_memory_rem_run", args: { phase: "deep", days: 3, agent_name: input.agent_name || undefined, project: input.project || undefined } });
490
- add("rem", remAge == null || remAge >= 7,
491
- "Weekly REM pass: extract cross-day patterns without deleting or overwriting old facts.",
492
- { tool: "mem_memory_rem_run", args: { phase: "rem", days: 7, agent_name: input.agent_name || undefined, project: input.project || undefined } });
493
-
494
- return {
495
- ok: true,
496
- generated_at: nowIso(),
497
- scope: scopeName(input.scope),
498
- project: input.project || null,
499
- agent_name: input.agent_name ? normalizeAgentName(input.agent_name) : null,
500
- canonical_model: canonicalMemoryModel(),
501
- phases,
502
- next_due: phases.filter((p) => p.due),
503
- status,
504
- rule: "Run phases via Mnemo tools only. Runtimes may feed raw events, but promotion and long-term truth stay in Mnemo.",
505
- };
506
- }
507
-
508
- function getRows(db, tableName, sql, params = []) {
509
- if (!tableExists(db, tableName)) return [];
510
- try {
511
- return db.prepare(sql).all(...params);
512
- } catch {
513
- return [];
514
- }
515
- }
516
-
517
- function selectMemoryRows(db, input, since, limit) {
518
- if (!tableExists(db, "memory")) return [];
519
- const p = whereProject(input, "topic");
520
- const agent = input.agent_name ? normalizeAgentName(input.agent_name) : "";
521
- const where = [`occurred_at >= ?${p.sql}`];
522
- const params = [since, ...p.params];
523
- if (agent) {
524
- where.push("(LOWER(COALESCE(actor,''))=? OR COALESCE(meta_json,'') LIKE ?)");
525
- params.push(agent, `%${agent}%`);
526
- }
527
- params.push(limit);
528
- return getRows(db, "memory", `
529
- SELECT 'memory' AS ref_kind, CAST(id AS TEXT) AS ref_id, kind AS subtype, actor, topic, occurred_at AS at,
530
- importance, substr(text,1,700) AS preview
531
- FROM memory
532
- WHERE ${where.join(" AND ")}
533
- ORDER BY importance DESC, occurred_at DESC
534
- LIMIT ?
535
- `, params);
536
- }
537
-
538
- function selectHandoffRows(db, input, since, limit) {
539
- if (!tableExists(db, "session_handoff")) return [];
540
- const where = ["created_at >= ?"];
541
- const params = [since];
542
- if (input.project) { where.push("project=?"); params.push(input.project); }
543
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
544
- params.push(limit);
545
- return getRows(db, "session_handoff", `
546
- SELECT 'session_handoff' AS ref_kind, CAST(id AS TEXT) AS ref_id, 'handoff' AS subtype, agent_name AS actor,
547
- project AS topic, created_at AS at, 8 AS importance, substr(summary,1,700) AS preview
548
- FROM session_handoff
549
- WHERE ${where.join(" AND ")}
550
- ORDER BY created_at DESC
551
- LIMIT ?
552
- `, params);
553
- }
554
-
555
- function selectDecisionRows(db, input, since, limit) {
556
- if (!tableExists(db, "decision_log")) return [];
557
- const where = ["decided_at >= ?"];
558
- const params = [since];
559
- if (input.scope) { where.push("scope=?"); params.push(scopeName(input.scope)); }
560
- if (input.project) { where.push("(body LIKE ? OR title LIKE ? OR files_affected LIKE ? OR entities_affected LIKE ?)"); params.push(`%${input.project}%`, `%${input.project}%`, `%${input.project}%`, `%${input.project}%`); }
561
- params.push(limit);
562
- return getRows(db, "decision_log", `
563
- SELECT 'decision_log' AS ref_kind, CAST(id AS TEXT) AS ref_id, 'decision' AS subtype, decided_by AS actor,
564
- scope AS topic, decided_at AS at, 9 AS importance, substr(title || ': ' || COALESCE(body,''),1,700) AS preview
565
- FROM decision_log
566
- WHERE ${where.join(" AND ")}
567
- ORDER BY decided_at DESC
568
- LIMIT ?
569
- `, params);
570
- }
571
-
572
- function selectFindingRows(db, input, since, limit) {
573
- if (!tableExists(db, "quality_finding")) return [];
574
- const where = ["created_at >= ?"];
575
- const params = [since];
576
- if (input.project) { where.push("project=?"); params.push(input.project); }
577
- params.push(limit);
578
- return getRows(db, "quality_finding", `
579
- SELECT 'quality_finding' AS ref_kind, CAST(id AS TEXT) AS ref_id, category AS subtype, source_agent AS actor,
580
- project AS topic, created_at AS at,
581
- CASE severity WHEN 'H' THEN 9 WHEN 'M' THEN 7 ELSE 5 END AS importance,
582
- substr(title || CASE WHEN actual IS NULL THEN '' ELSE ' actual=' || actual END,1,700) AS preview
583
- FROM quality_finding
584
- WHERE ${where.join(" AND ")}
585
- ORDER BY CASE severity WHEN 'H' THEN 3 WHEN 'M' THEN 2 ELSE 1 END DESC, created_at DESC
586
- LIMIT ?
587
- `, params);
588
- }
589
-
590
- function selectActionRows(db, input, since, limit) {
591
- if (!tableExists(db, "agent_action")) return [];
592
- const where = ["started_at >= ?"];
593
- const params = [since];
594
- if (input.project) { where.push("topic=?"); params.push(input.project); }
595
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
596
- params.push(limit);
597
- return getRows(db, "agent_action", `
598
- SELECT 'agent_action' AS ref_kind, CAST(id AS TEXT) AS ref_id, COALESCE(action_kind,'action') AS subtype, agent_name AS actor,
599
- topic, started_at AS at, 5 AS importance,
600
- substr(COALESCE(action_kind,'action') || ' ' || COALESCE(target,'') || ' status=' || COALESCE(status,''),1,700) AS preview
601
- FROM agent_action
602
- WHERE ${where.join(" AND ")}
603
- ORDER BY started_at DESC
604
- LIMIT ?
605
- `, params);
606
- }
607
-
608
- function selectJournalRows(db, input, since, limit) {
609
- if (!tableExists(db, "mnemo_event_journal")) return [];
610
- const where = ["occurred_at >= ?"];
611
- const params = [since];
612
- if (input.project) { where.push("(channel=? OR content LIKE ? OR payload_json LIKE ? OR meta_json LIKE ?)"); params.push(input.project, `%${input.project}%`, `%${input.project}%`, `%${input.project}%`); }
613
- if (input.agent_name) { where.push("LOWER(COALESCE(actor,''))=?"); params.push(normalizeAgentName(input.agent_name)); }
614
- params.push(limit);
615
- return getRows(db, "mnemo_event_journal", `
616
- SELECT 'mnemo_event_journal' AS ref_kind, CAST(id AS TEXT) AS ref_id, event_kind AS subtype, actor,
617
- channel AS topic, occurred_at AS at, 4 AS importance, substr(COALESCE(content,''),1,700) AS preview
618
- FROM mnemo_event_journal
619
- WHERE ${where.join(" AND ")}
620
- ORDER BY occurred_at DESC
621
- LIMIT ?
622
- `, params);
623
- }
624
-
625
- function selectDailyReflection(db, input, since, limit) {
626
- if (!tableExists(db, "daily_reflection")) return [];
627
- const cols = tableColumns(db, "daily_reflection");
628
- const dateCol = cols.includes("reflection_date") ? "reflection_date" : (cols.includes("date") ? "date" : null);
629
- if (!dateCol) return [];
630
- return getRows(db, "daily_reflection", `
631
- SELECT 'daily_reflection' AS ref_kind, CAST(id AS TEXT) AS ref_id, 'daily' AS subtype, 'mnemo' AS actor,
632
- ${dateCol} AS topic, generated_at AS at, 7 AS importance, substr(COALESCE(summary,''),1,700) AS preview
633
- FROM daily_reflection
634
- WHERE generated_at >= ?
635
- ORDER BY ${dateCol} DESC
636
- LIMIT ?
637
- `, [since, limit]);
638
- }
639
-
640
- function selectDepartmentJournalRows(db, input, since, limit) {
641
- if (!tableExists(db, "department_journal")) return [];
642
- const where = ["created_at >= ?"];
643
- const params = [since];
644
- if (input.project) { where.push("project=?"); params.push(input.project); }
645
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
646
- if (input.department_name) { where.push("department_name=?"); params.push(normalizeDepartment(input.department_name)); }
647
- params.push(limit);
648
- return getRows(db, "department_journal", `
649
- SELECT 'department_journal' AS ref_kind, CAST(id AS TEXT) AS ref_id, department_name AS subtype, agent_name AS actor,
650
- project AS topic, created_at AS at, 7 AS importance,
651
- substr('progress=' || COALESCE(progress,'') || ' blockers=' || COALESCE(blockers,'') || ' risks=' || COALESCE(risks,''),1,700) AS preview
652
- FROM department_journal
653
- WHERE ${where.join(" AND ")}
654
- ORDER BY journal_date DESC, created_at DESC
655
- LIMIT ?
656
- `, params);
657
- }
658
-
659
- function selectAgentSleepRows(db, input, since, limit) {
660
- if (!tableExists(db, "agent_sleep_note")) return [];
661
- const where = ["created_at >= ?"];
662
- const params = [since];
663
- if (input.project) { where.push("project=?"); params.push(input.project); }
664
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
665
- params.push(limit);
666
- return getRows(db, "agent_sleep_note", `
667
- SELECT 'agent_sleep_note' AS ref_kind, CAST(id AS TEXT) AS ref_id, status AS subtype, agent_name AS actor,
668
- project AS topic, created_at AS at, 6 AS importance,
669
- substr('learned=' || COALESCE(learned,'') || ' uncertainty=' || COALESCE(uncertainty,'') || ' recurring=' || COALESCE(recurring_errors,''),1,700) AS preview
670
- FROM agent_sleep_note
671
- WHERE ${where.join(" AND ")}
672
- ORDER BY note_date DESC, created_at DESC
673
- LIMIT ?
674
- `, params);
675
- }
676
-
677
- function selectPromotionRows(db, input, since, limit) {
678
- if (!tableExists(db, "memory_promotion_proposal")) return [];
679
- const where = ["created_at >= ?"];
680
- const params = [since];
681
- if (input.project) { where.push("project=?"); params.push(input.project); }
682
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
683
- if (input.department_name) { where.push("department_name=?"); params.push(normalizeDepartment(input.department_name)); }
684
- params.push(limit);
685
- return getRows(db, "memory_promotion_proposal", `
686
- SELECT 'memory_promotion_proposal' AS ref_kind, CAST(id AS TEXT) AS ref_id, proposal_kind AS subtype, agent_name AS actor,
687
- project AS topic, created_at AS at, CASE status WHEN 'proposed' THEN 8 ELSE 6 END AS importance,
688
- substr(status || ' ' || title || CASE WHEN body IS NULL THEN '' ELSE ': ' || body END,1,700) AS preview
689
- FROM memory_promotion_proposal
690
- WHERE ${where.join(" AND ")}
691
- ORDER BY CASE status WHEN 'proposed' THEN 2 ELSE 1 END DESC, created_at DESC
692
- LIMIT ?
693
- `, params);
694
- }
695
-
696
- function selectRowsForPhase(db, phase, input = {}) {
697
- const days = phaseWindowDays(phase, input.days);
698
- const since = input.since || new Date(Date.now() - days * 86400000).toISOString();
699
- const limit = clampInt(input.limit, 60, 5, 300);
700
- let rows = [];
701
- if (phase === "light") {
702
- rows = rows.concat(selectActionRows(db, input, since, Math.ceil(limit / 3)));
703
- rows = rows.concat(selectJournalRows(db, input, since, Math.ceil(limit / 3)));
704
- rows = rows.concat(selectMemoryRows(db, input, since, Math.ceil(limit / 3)));
705
- } else if (phase === "daily") {
706
- rows = rows.concat(selectMemoryRows(db, input, since, Math.ceil(limit / 2)));
707
- rows = rows.concat(selectHandoffRows(db, input, since, Math.ceil(limit / 4)));
708
- rows = rows.concat(selectFindingRows(db, input, since, Math.ceil(limit / 4)));
709
- rows = rows.concat(selectDepartmentJournalRows(db, input, since, Math.ceil(limit / 4)));
710
- rows = rows.concat(selectAgentSleepRows(db, input, since, Math.ceil(limit / 4)));
711
- } else if (phase === "deep") {
712
- rows = rows.concat(selectDecisionRows(db, input, since, Math.ceil(limit / 4)));
713
- rows = rows.concat(selectHandoffRows(db, input, since, Math.ceil(limit / 4)));
714
- rows = rows.concat(selectFindingRows(db, input, since, Math.ceil(limit / 4)));
715
- rows = rows.concat(selectMemoryRows(db, input, since, Math.ceil(limit / 4)));
716
- rows = rows.concat(selectPromotionRows(db, input, since, Math.ceil(limit / 4)));
717
- } else {
718
- rows = rows.concat(selectDailyReflection(db, input, since, Math.ceil(limit / 4)));
719
- rows = rows.concat(selectDepartmentJournalRows(db, input, since, Math.ceil(limit / 4)));
720
- rows = rows.concat(selectAgentSleepRows(db, input, since, Math.ceil(limit / 4)));
721
- rows = rows.concat(selectPromotionRows(db, input, since, Math.ceil(limit / 4)));
722
- rows = rows.concat(selectDecisionRows(db, input, since, Math.ceil(limit / 4)));
723
- rows = rows.concat(selectHandoffRows(db, input, since, Math.ceil(limit / 4)));
724
- rows = rows.concat(selectFindingRows(db, input, since, Math.ceil(limit / 4)));
725
- rows = rows.concat(selectMemoryRows(db, input, since, Math.ceil(limit / 4)));
726
- }
727
- const dedup = [];
728
- const seen = new Set();
729
- for (const row of rows) {
730
- const key = `${row.ref_kind}:${row.ref_id}`;
731
- if (seen.has(key)) continue;
732
- seen.add(key);
733
- dedup.push(row);
734
- }
735
- dedup.sort((a, b) => (b.importance - a.importance) || String(b.at || "").localeCompare(String(a.at || "")));
736
- return { since, until: nowIso(), rows: dedup.slice(0, limit) };
737
- }
738
-
739
- function groupRows(rows) {
740
- const groups = {
741
- decisions: [],
742
- handoffs: [],
743
- findings: [],
744
- actions: [],
745
- memories: [],
746
- reflections: [],
747
- department_journals: [],
748
- sleep_notes: [],
749
- promotions: [],
750
- events: [],
751
- };
752
- for (const row of rows) {
753
- if (row.ref_kind === "decision_log" || row.subtype === "decision") groups.decisions.push(row);
754
- else if (row.ref_kind === "session_handoff") groups.handoffs.push(row);
755
- else if (row.ref_kind === "quality_finding") groups.findings.push(row);
756
- else if (row.ref_kind === "agent_action") groups.actions.push(row);
757
- else if (row.ref_kind === "daily_reflection") groups.reflections.push(row);
758
- else if (row.ref_kind === "department_journal") groups.department_journals.push(row);
759
- else if (row.ref_kind === "agent_sleep_note") groups.sleep_notes.push(row);
760
- else if (row.ref_kind === "memory_promotion_proposal") groups.promotions.push(row);
761
- else if (row.ref_kind === "mnemo_event_journal") groups.events.push(row);
762
- else groups.memories.push(row);
763
- }
764
- return groups;
765
- }
766
-
767
- function bulletRows(rows, maxRows) {
768
- return rows.slice(0, maxRows).map((row) => {
769
- const who = row.actor ? ` ${row.actor}` : "";
770
- const topic = row.topic ? ` [${row.topic}]` : "";
771
- return `- ${row.ref_kind}:${row.ref_id}${topic}${who}: ${compactContent(row.preview, 240) || "(empty)"}`;
772
- });
773
- }
774
-
775
- function buildSummary(phase, input, selection, counts) {
776
- const rows = selection.rows || [];
777
- const groups = groupRows(rows);
778
- const lines = [];
779
- lines.push(`# Memory consolidation: ${phase}`);
780
- lines.push("");
781
- lines.push(`Scope: ${scopeName(input.scope)}${input.project ? ` | project: ${input.project}` : ""}${input.agent_name ? ` | agent: ${normalizeAgentName(input.agent_name)}` : ""}`);
782
- lines.push(`Window: ${selection.since} -> ${selection.until}`);
783
- lines.push(`Sources examined: memory=${counts.memory || 0}, transcript=${counts.transcript || 0}, actions=${counts.agent_action || 0}, handoffs=${counts.session_handoff || 0}, findings=${counts.quality_finding || 0}, events=${counts.mnemo_event_journal || 0}`);
784
- lines.push("");
785
- if (phase === "light") lines.push("Purpose: compress recent working/session events into a reviewable note. This is not canonical truth by itself.");
786
- if (phase === "daily") lines.push("Purpose: create the day journal layer and surface corrections, blockers, handoffs, and durable decisions.");
787
- if (phase === "deep") lines.push("Purpose: promote high-signal operational facts into semantic long-term memory candidates.");
788
- if (phase === "rem") lines.push("Purpose: weekly REM pass over daily/deep material to reveal recurring patterns and weak governance rules.");
789
- lines.push("");
790
- const sections = [
791
- ["Decisions", groups.decisions, 6],
792
- ["Handoffs", groups.handoffs, 6],
793
- ["Findings", groups.findings, 6],
794
- ["Department journals", groups.department_journals, 6],
795
- ["Agent sleep notes", groups.sleep_notes, 6],
796
- ["Promotion proposals", groups.promotions, 8],
797
- ["Reflections", groups.reflections, 4],
798
- ["Actions", groups.actions, 6],
799
- ["Memory/events", groups.memories.concat(groups.events), 10],
800
- ];
801
- for (const [title, values, maxRows] of sections) {
802
- if (!values.length) continue;
803
- lines.push(`## ${title}`);
804
- lines.push(...bulletRows(values, maxRows));
805
- lines.push("");
806
- }
807
- if (rows.length === 0) {
808
- lines.push("No source rows matched this consolidation window.");
809
- lines.push("");
810
- }
811
- lines.push("Review status: draft. A human or assigned agent may promote concrete lines into project truth, rules, scars, or runbooks.");
812
- return compactContent(lines.join("\n"), 12000);
813
- }
814
-
815
- function runDailyReflection(db, input = {}, selection) {
816
- const date = (input.date || new Date().toISOString().slice(0, 10)).slice(0, 10);
817
- const fromTs = date + "T00:00:00Z";
818
- const toTs = date + "T23:59:59Z";
819
- const events = tableExists(db, "memory")
820
- ? db.prepare("SELECT actor, text FROM memory WHERE kind='message' AND occurred_at BETWEEN ? AND ? ORDER BY occurred_at ASC").all(fromTs, toTs)
821
- : [];
822
- let corrections = 0;
823
- let praises = 0;
824
- const correctionPatterns = /\b(nicht so|nein|stop|hor auf|hoer auf|falsch|kein|fantasi|verarscht|kacke|scheisse|scheisse|kaputt|broken)\b/i;
825
- const praisePatterns = /\b(geil|super|perfekt|top|stark|hammer|well done|great)\b/i;
826
- const owner = String(process.env.MNEMO_OWNER_NAME || "owner").toLowerCase();
827
- for (const event of events) {
828
- const actor = String(event.actor || "").toLowerCase();
829
- if (actor && actor !== owner && actor !== "owner") continue;
830
- if (correctionPatterns.test(event.text || "")) corrections++;
831
- if (praisePatterns.test(event.text || "")) praises++;
832
- }
833
- const summary = `${events.length} message rows, ${corrections} corrections, ${praises} praises on ${date}. Consolidation selected ${selection.rows.length} durable source rows.`;
834
- db.prepare(`
835
- INSERT INTO daily_reflection (reflection_date, events_examined, corrections, praises, summary, trait_diffs_json, belief_diffs_json)
836
- VALUES (?,?,?,?,?,?,?)
837
- ON CONFLICT(reflection_date) DO UPDATE SET
838
- events_examined=excluded.events_examined,
839
- corrections=excluded.corrections,
840
- praises=excluded.praises,
841
- summary=excluded.summary,
842
- generated_at=strftime('%Y-%m-%dT%H:%M:%fZ','now')
843
- `).run(date, events.length, corrections, praises, summary, "{}", "{}");
844
- return { date, events_examined: events.length, corrections, praises, summary };
845
- }
846
-
847
- function foldSignalText(value) {
848
- return String(value || "")
849
- .toLowerCase()
850
- .normalize("NFKD")
851
- .replace(/[\u0300-\u036f]/g, "")
852
- .replace(/\u00df/g, "ss");
853
- }
854
-
855
- function dreamDateWindow(input = {}) {
856
- const date = (input.dream_date || input.date || new Date().toISOString().slice(0, 10)).slice(0, 10);
857
- const since = input.since || `${date}T00:00:00Z`;
858
- const until = input.until || `${date}T23:59:59Z`;
859
- return { date, since, until };
860
- }
861
-
862
- function selectDreamRows(db, input = {}) {
863
- const win = dreamDateWindow(input);
864
- const limit = clampInt(input.limit, 800, 20, 5000);
865
- const project = String(input.project || "").trim();
866
- const agent = input.agent_name ? normalizeAgentName(input.agent_name) : "";
867
- const feedbackActors = uniqueStrings(["owner", "owner-channel", process.env.MNEMO_OWNER_NAME || "owner"]).map(normalizeAgentName);
868
- const rows = [];
869
- const pushRows = (values) => {
870
- for (const row of values || []) {
871
- rows.push(Object.assign({ status: null }, row));
872
- if (rows.length >= limit * 2) break;
873
- }
874
- };
875
-
876
- if (tableExists(db, "memory")) {
877
- const where = ["occurred_at BETWEEN ? AND ?"];
878
- const params = [win.since, win.until];
879
- if (project) {
880
- where.push("(COALESCE(topic,'')=? OR COALESCE(text,'') LIKE ? OR COALESCE(meta_json,'') LIKE ?)");
881
- params.push(project, `%${project}%`, `%${project}%`);
882
- }
883
- if (agent) {
884
- const ownerPlaceholders = feedbackActors.map(() => "?").join(",");
885
- where.push(`(LOWER(COALESCE(actor,''))=? OR LOWER(COALESCE(actor,'')) IN (${ownerPlaceholders}) OR COALESCE(meta_json,'') LIKE ?)`);
886
- params.push(agent, ...feedbackActors, `%${agent}%`);
887
- }
888
- params.push(limit);
889
- pushRows(getRows(db, "memory", `
890
- SELECT 'memory' AS ref_kind, CAST(id AS TEXT) AS ref_id, kind AS subtype, actor,
891
- topic, occurred_at AS at, NULL AS status, importance,
892
- substr(COALESCE(text,''),1,1200) AS preview
893
- FROM memory
894
- WHERE ${where.join(" AND ")}
895
- ORDER BY occurred_at ASC
896
- LIMIT ?
897
- `, params));
898
- }
899
-
900
- if (tableExists(db, "mnemo_event_journal")) {
901
- const where = ["occurred_at BETWEEN ? AND ?"];
902
- const params = [win.since, win.until];
903
- if (project) {
904
- where.push("(COALESCE(channel,'')=? OR COALESCE(content,'') LIKE ? OR COALESCE(payload_json,'') LIKE ? OR COALESCE(meta_json,'') LIKE ?)");
905
- params.push(project, `%${project}%`, `%${project}%`, `%${project}%`);
906
- }
907
- if (agent) {
908
- const ownerPlaceholders = feedbackActors.map(() => "?").join(",");
909
- where.push(`(LOWER(COALESCE(actor,''))=? OR LOWER(COALESCE(actor,'')) IN (${ownerPlaceholders}) OR COALESCE(meta_json,'') LIKE ?)`);
910
- params.push(agent, ...feedbackActors, `%${agent}%`);
911
- }
912
- params.push(limit);
913
- pushRows(getRows(db, "mnemo_event_journal", `
914
- SELECT 'mnemo_event_journal' AS ref_kind, CAST(id AS TEXT) AS ref_id, event_kind AS subtype, actor,
915
- channel AS topic, occurred_at AS at, status, 4 AS importance,
916
- substr(COALESCE(content,'') || ' ' || COALESCE(payload_json,'') || ' ' || COALESCE(meta_json,''),1,1200) AS preview
917
- FROM mnemo_event_journal
918
- WHERE ${where.join(" AND ")}
919
- ORDER BY occurred_at ASC
920
- LIMIT ?
921
- `, params));
922
- }
923
-
924
- if (tableExists(db, "agent_action")) {
925
- const where = ["started_at BETWEEN ? AND ?"];
926
- const params = [win.since, win.until];
927
- if (project) {
928
- where.push("(COALESCE(topic,'')=? OR COALESCE(payload_json,'') LIKE ? OR COALESCE(meta_json,'') LIKE ?)");
929
- params.push(project, `%${project}%`, `%${project}%`);
930
- }
931
- if (agent) {
932
- where.push("LOWER(COALESCE(agent_name,''))=?");
933
- params.push(agent);
934
- }
935
- params.push(limit);
936
- pushRows(getRows(db, "agent_action", `
937
- SELECT 'agent_action' AS ref_kind, CAST(id AS TEXT) AS ref_id, action_kind AS subtype, agent_name AS actor,
938
- topic, started_at AS at, status, 5 AS importance,
939
- substr(COALESCE(action_kind,'') || ' ' || COALESCE(target,'') || ' status=' || COALESCE(status,'') || ' ' || COALESCE(result_json,'') || ' ' || COALESCE(payload_json,''),1,1200) AS preview
940
- FROM agent_action
941
- WHERE ${where.join(" AND ")}
942
- ORDER BY started_at ASC
943
- LIMIT ?
944
- `, params));
945
- }
946
-
947
- if (tableExists(db, "quality_finding")) {
948
- const where = ["created_at BETWEEN ? AND ?"];
949
- const params = [win.since, win.until];
950
- const qcols = tableColumns(db, "quality_finding");
951
- const hasAssigned = qcols.includes("assigned_agent");
952
- if (project) { where.push("project=?"); params.push(project); }
953
- if (agent) {
954
- where.push(hasAssigned ? "(LOWER(COALESCE(source_agent,''))=? OR LOWER(COALESCE(assigned_agent,''))=?)" : "LOWER(COALESCE(source_agent,''))=?");
955
- params.push(agent);
956
- if (hasAssigned) params.push(agent);
957
- }
958
- params.push(limit);
959
- const actorExpr = hasAssigned ? "COALESCE(source_agent, assigned_agent)" : "source_agent";
960
- pushRows(getRows(db, "quality_finding", `
961
- SELECT 'quality_finding' AS ref_kind, CAST(id AS TEXT) AS ref_id, category AS subtype, ${actorExpr} AS actor,
962
- project AS topic, created_at AS at, COALESCE(status,'open') AS status, 8 AS importance,
963
- substr(COALESCE(severity,'') || ' ' || COALESCE(title,'') || ' ' || COALESCE(actual,'') || ' ' || COALESCE(expected,''),1,1200) AS preview
964
- FROM quality_finding
965
- WHERE ${where.join(" AND ")}
966
- ORDER BY created_at ASC
967
- LIMIT ?
968
- `, params));
969
- }
970
-
971
- const dedup = [];
972
- const seen = new Set();
973
- for (const row of rows) {
974
- const key = `${row.ref_kind}:${row.ref_id}`;
975
- if (seen.has(key)) continue;
976
- seen.add(key);
977
- dedup.push(row);
978
- }
979
- dedup.sort((a, b) => String(a.at || "").localeCompare(String(b.at || "")));
980
- return Object.assign(win, { rows: dedup.slice(0, limit) });
981
- }
982
-
983
- function emptyDreamBuckets() {
984
- const out = {};
985
- for (const key of DREAM_BUCKET_KEYS) out[key] = { count: 0, examples: [] };
986
- return out;
987
- }
988
-
989
- function dreamBucketMatches(row) {
990
- const text = foldSignalText([row.preview, row.subtype, row.status, row.topic].filter(Boolean).join(" "));
991
- const matches = [];
992
- const add = (key, reason) => matches.push({ key, reason });
993
-
994
- if (/\b(super|perfekt|top|stark|danke|geil|sauber|besser|bestaetigt|bestatigt|demo-bereit|b[aehm]*hm|well done|great)\b/.test(text)) {
995
- add("praise_received", "human/peer praise or green feedback");
996
- }
997
- if (/\b(ok|done|passed|pass|green|grun|gruen|verified|verifiziert|bestaetigt|bestatigt|gefixt|live|closed|acceptance|funktioniert wieder|passt jetzt|smoke grun|tests? grun|0 failed|70 passed)\b/.test(text)) {
998
- add("right_made", "verified success or completed action");
999
- }
1000
- if (/\b(falsch|fehler|bug|blocker|regression|nicht live|nichts geaendert|nichts geandert|geht nicht|funktioniert nicht|ignoriert|vermischt|fallback|404|502|broken|fail|failed|error|rot|kaputt)\b/.test(text)) {
1001
- add("wrong_made", "failure, bug, or red verification");
1002
- }
1003
- if (/\b(stop|hoer auf|hor auf|verdammt|nervt|spam|pennt|lump|kacke|scheiss|scheisse|was machst|du hast|nicht in die gruppe|konsole|heimlich)\b/.test(text)) {
1004
- add("called_out", "direct correction or frustration signal");
1005
- }
1006
- if (/\b(kaputt gemacht|abgeschossen|weg gefegt|weggefegt|server down|production-down|prod down|502|crash|crashed|kill|killed|orphan|stopped|telegram kaputt|deploy.*kaputt|service.*down)\b/.test(text)) {
1007
- add("broke_things", "incident or caused damage");
1008
- }
1009
-
1010
- if (/^(done|ok|success|passed)$/i.test(String(row.status || ""))) {
1011
- add("right_made", "status indicates completed work");
1012
- } else if (/^(error|failed|fail|blocked)$/i.test(String(row.status || ""))) {
1013
- add("wrong_made", "status indicates failure/blocker");
1014
- }
1015
- return matches;
1016
- }
1017
-
1018
- function addDreamExample(bucket, row, reason) {
1019
- bucket.count++;
1020
- if (bucket.examples.length >= 20) return;
1021
- bucket.examples.push({
1022
- ref_kind: row.ref_kind,
1023
- ref_id: row.ref_id,
1024
- actor: row.actor || null,
1025
- topic: row.topic || null,
1026
- at: row.at || null,
1027
- reason,
1028
- preview: compactContent(row.preview, 360),
1029
- });
1030
- }
1031
-
1032
- function classifyDreamRows(rows) {
1033
- const buckets = emptyDreamBuckets();
1034
- for (const row of rows) {
1035
- for (const match of dreamBucketMatches(row)) {
1036
- addDreamExample(buckets[match.key], row, match.reason);
1037
- }
1038
- }
1039
- return buckets;
1040
- }
1041
-
1042
- function dreamLessons(buckets) {
1043
- const lessons = [];
1044
- const firstRef = (key) => {
1045
- const ex = buckets[key] && buckets[key].examples && buckets[key].examples[0];
1046
- return ex ? `${ex.ref_kind}:${ex.ref_id}` : null;
1047
- };
1048
- if (buckets.broke_things.count > 0) {
1049
- lessons.push({ type: "stop_doing", text: "Production, Telegram, and deploy incidents need a gate, receipt, and rollback path before more changes.", evidence_ref: firstRef("broke_things") });
1050
- }
1051
- if (buckets.called_out.count > 0) {
1052
- lessons.push({ type: "behavior_adjustment", text: "User frustration is a hard signal: reduce spam, write in the requested channel, and keep status updates short.", evidence_ref: firstRef("called_out") });
1053
- }
1054
- if (buckets.wrong_made.count > 0) {
1055
- lessons.push({ type: "fix_next", text: "Red verifications and repeated bugs become next-day tasks until explicitly closed with evidence.", evidence_ref: firstRef("wrong_made") });
1056
- }
1057
- if (buckets.right_made.count > 0) {
1058
- lessons.push({ type: "keep_doing", text: "Keep the workflows that produced green verification: concrete checks, URLs, exit codes, and direct acceptance evidence.", evidence_ref: firstRef("right_made") });
1059
- }
1060
- if (buckets.praise_received.count > 0) {
1061
- lessons.push({ type: "positive_reinforcement", text: "Praise marks a useful pattern; preserve the exact behavior that led to it.", evidence_ref: firstRef("praise_received") });
1062
- }
1063
- if (!lessons.length) {
1064
- lessons.push({ type: "low_signal", text: "No strong praise/correction/failure signal was detected; keep collecting raw messages and evidence." });
1065
- }
1066
- return lessons;
1067
- }
1068
-
1069
- function dreamSummary(input, source, buckets, lessons, remRuns) {
1070
- const labels = {
1071
- wrong_made: "Falsch gemacht",
1072
- right_made: "Richtig gemacht",
1073
- praise_received: "Lob bekommen",
1074
- called_out: "Angemacht/korrigiert",
1075
- broke_things: "Scheisse gebaut",
1076
- };
1077
- const lines = [];
1078
- lines.push(`# Dreammode Review: ${source.date}`);
1079
- lines.push("");
1080
- lines.push(`Scope: ${scopeName(input.scope)}${input.project ? ` | project: ${input.project}` : ""}${input.agent_name ? ` | agent: ${normalizeAgentName(input.agent_name)}` : ""}`);
1081
- lines.push(`Window: ${source.since} -> ${source.until}`);
1082
- lines.push(`Sources examined: ${source.rows.length} rows. REM phases: ${remRuns.map((r) => r.phase + "#" + r.run_id).join(", ") || "none"}.`);
1083
- lines.push("");
1084
- for (const key of DREAM_BUCKET_KEYS) {
1085
- const bucket = buckets[key];
1086
- lines.push(`## ${labels[key]} (${bucket.count})`);
1087
- if (!bucket.examples.length) {
1088
- lines.push("- none detected");
1089
- } else {
1090
- for (const ex of bucket.examples.slice(0, 8)) {
1091
- const who = ex.actor ? ` ${ex.actor}` : "";
1092
- const topic = ex.topic ? ` [${ex.topic}]` : "";
1093
- lines.push(`- ${ex.ref_kind}:${ex.ref_id}${topic}${who}: ${compactContent(ex.preview, 220)}`);
1094
- }
1095
- }
1096
- lines.push("");
1097
- }
1098
- lines.push("## Daraus lernen");
1099
- for (const lesson of lessons) {
1100
- lines.push(`- ${lesson.type}: ${lesson.text}${lesson.evidence_ref ? ` (${lesson.evidence_ref})` : ""}`);
1101
- }
1102
- lines.push("");
1103
- lines.push("Rule: Dreammode is draft processing. It may propose lessons, but official truth/rules still need explicit promotion or task updates.");
1104
- return compactContent(lines.join("\n"), 16000);
1105
- }
1106
-
1107
- function rowToDreammodeRun(row) {
1108
- return row ? Object.assign({}, row, {
1109
- wrong_made: parseJson(row.wrong_made_json, { count: 0, examples: [] }),
1110
- right_made: parseJson(row.right_made_json, { count: 0, examples: [] }),
1111
- praise_received: parseJson(row.praise_received_json, { count: 0, examples: [] }),
1112
- called_out: parseJson(row.called_out_json, { count: 0, examples: [] }),
1113
- broke_things: parseJson(row.broke_things_json, { count: 0, examples: [] }),
1114
- lessons: parseJson(row.lessons_json, []),
1115
- rem_run_ids: parseJson(row.rem_run_ids_json, []),
1116
- meta: parseJson(row.meta_json, {}),
1117
- }) : null;
1118
- }
1119
-
1120
- function dreammodeRun(db, input = {}) {
1121
- ensureMemoryConsolidationSchema(db);
1122
- const agent = input.agent_name ? normalizeAgentName(input.agent_name) : "";
1123
- const project = String(input.project || "").trim();
1124
- const scope = scopeName(input.scope);
1125
- const source = selectDreamRows(db, input);
1126
- const existing = db.prepare("SELECT * FROM dreammode_run WHERE scope=? AND agent_name=? AND project=? AND dream_date=?")
1127
- .get(scope, agent, project, source.date);
1128
- if (existing && input.force !== true) {
1129
- return { ok: true, skipped: true, reason: "dreammode already ran for this agent/project/date", run: rowToDreammodeRun(existing) };
1130
- }
1131
-
1132
- const remRuns = [];
1133
- if (input.run_rem_phases !== false) {
1134
- const phases = input.phases && Array.isArray(input.phases) ? input.phases : ["light", "daily", "deep", "rem"];
1135
- for (const phase of phases) {
1136
- const normalized = String(phase || "").toLowerCase();
1137
- if (!PHASES.has(normalized)) continue;
1138
- const result = memoryRemRun(db, {
1139
- scope,
1140
- agent_name: agent || undefined,
1141
- project: project || undefined,
1142
- phase: normalized,
1143
- date: source.date,
1144
- days: normalized === "rem" ? clampInt(input.rem_days, 7, 1, 3650) : undefined,
1145
- meta: Object.assign({}, input.meta || {}, { dreammode: true, dream_date: source.date }),
1146
- });
1147
- if (result && result.ok) remRuns.push({ phase: normalized, run_id: result.run_id, promoted_memory_id: result.promoted_memory_id || null });
1148
- }
1149
- }
1150
-
1151
- const buckets = classifyDreamRows(source.rows);
1152
- const lessons = dreamLessons(buckets);
1153
- const summary = dreamSummary(input, source, buckets, lessons, remRuns);
1154
- let briefId = null;
1155
- const writeBrief = input.write_brief !== false;
1156
- if (writeBrief && tableExists(db, "agent_brief")) {
1157
- const coordinator = normalizeAgentName(input.coordinator_agent || input.agent_name || "agent-a");
1158
- const info = db.prepare("INSERT INTO agent_brief (agent_name, source_agent, content, meta_json) VALUES (?,?,?,?)")
1159
- .run(coordinator || "agent-a", normalizeAgentName(input.source_agent || "mnemo-dreammode"), summary, safeJson({ kind: "dreammode_review", project: project || null, agent_name: agent || null, dream_date: source.date }, {}));
1160
- briefId = info.lastInsertRowid;
1161
- }
1162
-
1163
- const insertArgs = [
1164
- scope,
1165
- agent,
1166
- project,
1167
- source.date,
1168
- source.since,
1169
- source.until,
1170
- source.rows.filter((row) => row.ref_kind === "memory").length,
1171
- source.rows.filter((row) => row.ref_kind === "agent_action").length,
1172
- source.rows.filter((row) => row.ref_kind === "mnemo_event_journal").length,
1173
- safeJson(buckets.wrong_made, {}),
1174
- safeJson(buckets.right_made, {}),
1175
- safeJson(buckets.praise_received, {}),
1176
- safeJson(buckets.called_out, {}),
1177
- safeJson(buckets.broke_things, {}),
1178
- safeJson(lessons, []),
1179
- safeJson(remRuns, []),
1180
- summary,
1181
- briefId,
1182
- input.status || "draft",
1183
- safeJson(Object.assign({}, input.meta || {}, { no_destructive_migration: true, human_style_review: true }), {}),
1184
- ];
1185
- const info = db.prepare(`
1186
- INSERT INTO dreammode_run
1187
- (scope, agent_name, project, dream_date, source_window_start, source_window_end, messages_examined, actions_examined, events_examined,
1188
- wrong_made_json, right_made_json, praise_received_json, called_out_json, broke_things_json, lessons_json, rem_run_ids_json, summary, brief_id, status, meta_json)
1189
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
1190
- ON CONFLICT(scope, agent_name, project, dream_date) DO UPDATE SET
1191
- source_window_start=excluded.source_window_start,
1192
- source_window_end=excluded.source_window_end,
1193
- messages_examined=excluded.messages_examined,
1194
- actions_examined=excluded.actions_examined,
1195
- events_examined=excluded.events_examined,
1196
- wrong_made_json=excluded.wrong_made_json,
1197
- right_made_json=excluded.right_made_json,
1198
- praise_received_json=excluded.praise_received_json,
1199
- called_out_json=excluded.called_out_json,
1200
- broke_things_json=excluded.broke_things_json,
1201
- lessons_json=excluded.lessons_json,
1202
- rem_run_ids_json=excluded.rem_run_ids_json,
1203
- summary=excluded.summary,
1204
- brief_id=excluded.brief_id,
1205
- status=excluded.status,
1206
- meta_json=excluded.meta_json,
1207
- created_at=strftime('%Y-%m-%dT%H:%M:%fZ','now')
1208
- `).run(...insertArgs);
1209
- const row = db.prepare("SELECT * FROM dreammode_run WHERE scope=? AND agent_name=? AND project=? AND dream_date=?").get(scope, agent, project, source.date);
1210
- return {
1211
- ok: true,
1212
- skipped: false,
1213
- run_id: row ? row.id : info.lastInsertRowid,
1214
- dream_date: source.date,
1215
- source_count: source.rows.length,
1216
- brief_id: briefId,
1217
- rem_runs: remRuns,
1218
- buckets,
1219
- lessons,
1220
- summary,
1221
- run: rowToDreammodeRun(row),
1222
- };
1223
- }
1224
-
1225
- function dreammodeStatus(db, input = {}) {
1226
- ensureMemoryConsolidationSchema(db);
1227
- const where = ["scope=?"];
1228
- const params = [scopeName(input.scope)];
1229
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
1230
- if (input.project !== undefined) { where.push("project=?"); params.push(String(input.project || "").trim()); }
1231
- if (input.date || input.dream_date) { where.push("dream_date=?"); params.push(String(input.date || input.dream_date).slice(0, 10)); }
1232
- params.push(clampInt(input.limit, 20, 1, 200));
1233
- const rows = db.prepare(`
1234
- SELECT * FROM dreammode_run
1235
- WHERE ${where.join(" AND ")}
1236
- ORDER BY dream_date DESC, created_at DESC
1237
- LIMIT ?
1238
- `).all(...params).map(rowToDreammodeRun);
1239
- return { ok: true, count: rows.length, runs: rows };
1240
- }
1241
-
1242
- function insertPromotedMemory(db, phase, input, runId, summary, selectedRefs) {
1243
- if (!tableExists(db, "memory")) return null;
1244
- const occurred = nowIso();
1245
- const sourceRef = `memory_consolidation_run:${runId}`;
1246
- const kind = "memory_consolidation";
1247
- const actor = normalizeAgentName(input.agent_name || "mnemo");
1248
- const topic = input.project || "memory_consolidation";
1249
- const meta = {
1250
- phase,
1251
- source_ref: sourceRef,
1252
- confidence: "derived",
1253
- review_status: "draft",
1254
- selected_refs: selectedRefs,
1255
- canonical_model: canonicalMemoryModel(),
1256
- };
1257
- const hash = sha([kind, sourceRef, occurred, summary].join("|"));
1258
- const hasLayer = ensureMemoryLayerColumn(db);
1259
- const sql = hasLayer
1260
- ? "INSERT OR IGNORE INTO memory (kind, source, source_ref, occurred_at, actor, topic, importance, layer, text, meta_json, hash) VALUES (?,?,?,?,?,?,?,?,?,?,?)"
1261
- : "INSERT OR IGNORE INTO memory (kind, source, source_ref, occurred_at, actor, topic, importance, text, meta_json, hash) VALUES (?,?,?,?,?,?,?,?,?,?)";
1262
- const args = hasLayer
1263
- ? [kind, "mnemo:rem", sourceRef, occurred, actor, topic, phase === "rem" ? 8 : 7, "semantic", summary, safeJson(meta, {}), hash]
1264
- : [kind, "mnemo:rem", sourceRef, occurred, actor, topic, phase === "rem" ? 8 : 7, summary, safeJson(meta, {}), hash];
1265
- const info = db.prepare(sql).run(...args);
1266
- if (info.changes > 0) return info.lastInsertRowid;
1267
- const row = db.prepare("SELECT id FROM memory WHERE hash=?").get(hash);
1268
- return row ? row.id : null;
1269
- }
1270
-
1271
- function memoryRemRun(db, input = {}) {
1272
- ensureMemoryConsolidationSchema(db);
1273
- const phase = String(input.phase || "light").toLowerCase();
1274
- if (!PHASES.has(phase)) return { error: "phase must be light|daily|deep|rem" };
1275
- const days = phaseWindowDays(phase, input.days);
1276
- const selection = selectRowsForPhase(db, phase, Object.assign({}, input, { days }));
1277
- const counts = sourceCounts(db, Object.assign({}, input, { since: selection.since, days }));
1278
- const dailyReflection = phase === "daily" ? runDailyReflection(db, input, selection) : null;
1279
- const selectedRefs = selection.rows.map((row) => ({
1280
- ref_kind: row.ref_kind,
1281
- ref_id: row.ref_id,
1282
- subtype: row.subtype || null,
1283
- at: row.at || null,
1284
- importance: row.importance || null,
1285
- }));
1286
- const summary = buildSummary(phase, input, selection, counts);
1287
- const info = db.prepare(`
1288
- INSERT INTO memory_consolidation_run
1289
- (scope, agent_name, project, phase, source_window_start, source_window_end, source_counts_json, selected_refs_json, summary, status, confidence, review_status, meta_json)
1290
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
1291
- `).run(
1292
- scopeName(input.scope),
1293
- input.agent_name ? normalizeAgentName(input.agent_name) : null,
1294
- input.project || null,
1295
- phase,
1296
- selection.since,
1297
- selection.until,
1298
- safeJson(counts, {}),
1299
- safeJson(selectedRefs, []),
1300
- summary,
1301
- input.status || "draft",
1302
- input.confidence || "derived",
1303
- input.review_status || "draft",
1304
- safeJson(Object.assign({}, input.meta || {}, { daily_reflection: dailyReflection, no_destructive_migration: true }), {})
1305
- );
1306
- const runId = info.lastInsertRowid;
1307
- const promotedMemoryId = input.promote_to_memory === false ? null : insertPromotedMemory(db, phase, input, runId, summary, selectedRefs);
1308
- if (promotedMemoryId) {
1309
- db.prepare("UPDATE memory_consolidation_run SET promoted_memory_id=? WHERE id=?").run(promotedMemoryId, runId);
1310
- }
1311
- return {
1312
- ok: true,
1313
- run_id: runId,
1314
- phase,
1315
- status: input.status || "draft",
1316
- confidence: input.confidence || "derived",
1317
- review_status: input.review_status || "draft",
1318
- selected_count: selectedRefs.length,
1319
- source_counts: counts,
1320
- promoted_memory_id: promotedMemoryId,
1321
- daily_reflection: dailyReflection,
1322
- summary,
1323
- rule: "Draft consolidation only. Promote concrete facts through the proper Mnemo truth/rules/scar tools.",
1324
- };
1325
- }
1326
-
1327
- function rowToConsolidation(row) {
1328
- if (!row) return null;
1329
- return Object.assign({}, row, {
1330
- source_counts: parseJson(row.source_counts_json, {}),
1331
- selected_refs: parseJson(row.selected_refs_json, []),
1332
- meta: parseJson(row.meta_json, {}),
1333
- });
1334
- }
1335
-
1336
- function memoryConsolidationList(db, input = {}) {
1337
- ensureMemoryConsolidationSchema(db);
1338
- const where = ["scope=?"];
1339
- const params = [scopeName(input.scope)];
1340
- if (input.phase) { where.push("phase=?"); params.push(String(input.phase).toLowerCase()); }
1341
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
1342
- if (input.project) { where.push("project=?"); params.push(input.project); }
1343
- if (input.status) { where.push("status=?"); params.push(input.status); }
1344
- params.push(clampInt(input.limit, 50, 1, 500));
1345
- const rows = db.prepare(`
1346
- SELECT * FROM memory_consolidation_run
1347
- WHERE ${where.join(" AND ")}
1348
- ORDER BY created_at DESC
1349
- LIMIT ?
1350
- `).all(...params).map(rowToConsolidation);
1351
- return { ok: true, count: rows.length, runs: rows };
1352
- }
1353
-
1354
- function rowToDepartmentJournal(row) {
1355
- if (!row) return null;
1356
- return Object.assign({}, row, {
1357
- dependencies: parseJson(row.dependencies_json, []),
1358
- foreign_scope_requests: parseJson(row.foreign_scope_requests_json, []),
1359
- meta: parseJson(row.meta_json, {}),
1360
- });
1361
- }
1362
-
1363
- function departmentJournalAdd(db, input = {}) {
1364
- ensureMemoryConsolidationSchema(db);
1365
- const department = normalizeDepartment(input.department_name || input.department);
1366
- const date = (input.journal_date || input.date || new Date().toISOString().slice(0, 10)).slice(0, 10);
1367
- const agent = input.agent_name ? normalizeAgentName(input.agent_name) : null;
1368
- const info = db.prepare(`
1369
- INSERT INTO department_journal
1370
- (scope, department_name, agent_name, project, journal_date, progress, blockers, risks, open_questions, dependencies_json, foreign_scope_requests_json, status, meta_json)
1371
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
1372
- `).run(
1373
- scopeName(input.scope),
1374
- department,
1375
- agent,
1376
- input.project || null,
1377
- date,
1378
- textOrNull(input.progress || input.summary),
1379
- textOrNull(input.blockers),
1380
- textOrNull(input.risks),
1381
- textOrNull(input.open_questions),
1382
- safeJson(listInput(input.dependencies), []),
1383
- safeJson(listInput(input.foreign_scope_requests || input.access_requests), []),
1384
- input.status || "open",
1385
- safeJson(input.meta || {}, {})
1386
- );
1387
- return { ok: true, id: info.lastInsertRowid, department_name: department, journal_date: date };
1388
- }
1389
-
1390
- function departmentJournalList(db, input = {}) {
1391
- ensureMemoryConsolidationSchema(db);
1392
- const where = ["scope=?"];
1393
- const params = [scopeName(input.scope)];
1394
- if (input.department_name || input.department) { where.push("department_name=?"); params.push(normalizeDepartment(input.department_name || input.department)); }
1395
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
1396
- if (input.project) { where.push("project=?"); params.push(input.project); }
1397
- if (input.status) { where.push("status=?"); params.push(input.status); }
1398
- if (input.since) { where.push("created_at>=?"); params.push(input.since); }
1399
- params.push(clampInt(input.limit, 50, 1, 500));
1400
- const rows = db.prepare(`
1401
- SELECT * FROM department_journal
1402
- WHERE ${where.join(" AND ")}
1403
- ORDER BY journal_date DESC, created_at DESC
1404
- LIMIT ?
1405
- `).all(...params).map(rowToDepartmentJournal);
1406
- return { ok: true, count: rows.length, journals: rows };
1407
- }
1408
-
1409
- function rowToSleepNote(row) {
1410
- return row ? Object.assign({}, row, { meta: parseJson(row.meta_json, {}) }) : null;
1411
- }
1412
-
1413
- function agentSleepNoteAdd(db, input = {}) {
1414
- ensureMemoryConsolidationSchema(db);
1415
- const agent = normalizeAgentName(input.agent_name);
1416
- if (!agent) return { error: "agent_name required" };
1417
- const date = (input.note_date || input.date || new Date().toISOString().slice(0, 10)).slice(0, 10);
1418
- const info = db.prepare(`
1419
- INSERT INTO agent_sleep_note
1420
- (scope, agent_name, project, note_date, learned, uncertainty, recurring_errors, needed_context, improvement_idea, source_ref, status, meta_json)
1421
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
1422
- `).run(
1423
- scopeName(input.scope),
1424
- agent,
1425
- input.project || null,
1426
- date,
1427
- textOrNull(input.learned),
1428
- textOrNull(input.uncertainty),
1429
- textOrNull(input.recurring_errors),
1430
- textOrNull(input.needed_context),
1431
- textOrNull(input.improvement_idea),
1432
- input.source_ref || null,
1433
- input.status || "draft",
1434
- safeJson(input.meta || {}, {})
1435
- );
1436
- return { ok: true, id: info.lastInsertRowid, agent_name: agent, note_date: date };
1437
- }
1438
-
1439
- function agentSleepNoteList(db, input = {}) {
1440
- ensureMemoryConsolidationSchema(db);
1441
- const where = ["scope=?"];
1442
- const params = [scopeName(input.scope)];
1443
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
1444
- if (input.project) { where.push("project=?"); params.push(input.project); }
1445
- if (input.status) { where.push("status=?"); params.push(input.status); }
1446
- if (input.since) { where.push("created_at>=?"); params.push(input.since); }
1447
- params.push(clampInt(input.limit, 50, 1, 500));
1448
- const rows = db.prepare(`
1449
- SELECT * FROM agent_sleep_note
1450
- WHERE ${where.join(" AND ")}
1451
- ORDER BY note_date DESC, created_at DESC
1452
- LIMIT ?
1453
- `).all(...params).map(rowToSleepNote);
1454
- return { ok: true, count: rows.length, notes: rows };
1455
- }
1456
-
1457
- function normalizeProposalKind(value) {
1458
- const kind = String(value || "project_memory").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
1459
- const allowed = new Set(["decision", "rule", "project_memory", "risk", "owner_question", "scar", "runbook"]);
1460
- return allowed.has(kind) ? kind : "project_memory";
1461
- }
1462
-
1463
- function proposalTitle(input = {}) {
1464
- const explicit = String(input.title || "").trim();
1465
- if (explicit) return explicit.slice(0, 220);
1466
- const body = String(input.body || input.summary || input.question || "").replace(/\s+/g, " ").trim();
1467
- return (body ? body.slice(0, 180) : "Memory promotion proposal");
1468
- }
1469
-
1470
- function rowToPromotion(row) {
1471
- return row ? Object.assign({}, row, {
1472
- evidence: parseJson(row.evidence_json, []),
1473
- meta: parseJson(row.meta_json, {}),
1474
- }) : null;
1475
- }
1476
-
1477
- function memoryPromotionPropose(db, input = {}) {
1478
- ensureMemoryConsolidationSchema(db);
1479
- const kind = normalizeProposalKind(input.proposal_kind || input.kind);
1480
- const title = proposalTitle(input);
1481
- const agent = input.agent_name ? normalizeAgentName(input.agent_name) : null;
1482
- const info = db.prepare(`
1483
- INSERT INTO memory_promotion_proposal
1484
- (scope, proposal_kind, title, body, project, department_name, agent_name, source_kind, source_id, evidence_json, status, meta_json)
1485
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
1486
- `).run(
1487
- scopeName(input.scope),
1488
- kind,
1489
- title,
1490
- textOrNull(input.body || input.summary || input.question),
1491
- input.project || null,
1492
- input.department_name ? normalizeDepartment(input.department_name) : null,
1493
- agent,
1494
- input.source_kind || null,
1495
- input.source_id != null ? String(input.source_id) : null,
1496
- safeJson(Array.isArray(input.evidence) ? input.evidence : [], []),
1497
- input.status || "proposed",
1498
- safeJson(input.meta || {}, {})
1499
- );
1500
- return { ok: true, id: info.lastInsertRowid, status: input.status || "proposed", proposal_kind: kind, title };
1501
- }
1502
-
1503
- function insertPromotionMemory(db, proposal, decidedBy) {
1504
- if (!tableExists(db, "memory")) return null;
1505
- const kind = proposal.proposal_kind === "decision" ? "decision" : "manual";
1506
- const occurred = nowIso();
1507
- const sourceRef = `memory_promotion_proposal:${proposal.id}`;
1508
- const text = [
1509
- `Promotion kind: ${proposal.proposal_kind}`,
1510
- `Title: ${proposal.title}`,
1511
- proposal.body ? `Body: ${proposal.body}` : null,
1512
- `Approved by: ${decidedBy || proposal.reviewer || "unknown"}`,
1513
- ].filter(Boolean).join("\n");
1514
- const meta = {
1515
- proposal_id: proposal.id,
1516
- proposal_kind: proposal.proposal_kind,
1517
- confidence: "confirmed",
1518
- review_status: "approved",
1519
- source_kind: proposal.source_kind,
1520
- source_id: proposal.source_id,
1521
- };
1522
- const hash = sha([kind, sourceRef, occurred, text].join("|"));
1523
- const hasLayer = ensureMemoryLayerColumn(db);
1524
- const sql = hasLayer
1525
- ? "INSERT OR IGNORE INTO memory (kind, source, source_ref, occurred_at, actor, topic, importance, layer, text, meta_json, hash) VALUES (?,?,?,?,?,?,?,?,?,?,?)"
1526
- : "INSERT OR IGNORE INTO memory (kind, source, source_ref, occurred_at, actor, topic, importance, text, meta_json, hash) VALUES (?,?,?,?,?,?,?,?,?,?)";
1527
- const args = hasLayer
1528
- ? [kind, "mnemo:promotion", sourceRef, occurred, decidedBy || proposal.agent_name || "mnemo", proposal.project || "memory_promotion", 9, "semantic", text, safeJson(meta, {}), hash]
1529
- : [kind, "mnemo:promotion", sourceRef, occurred, decidedBy || proposal.agent_name || "mnemo", proposal.project || "memory_promotion", 9, text, safeJson(meta, {}), hash];
1530
- const info = db.prepare(sql).run(...args);
1531
- return info.changes > 0 ? info.lastInsertRowid : ((db.prepare("SELECT id FROM memory WHERE hash=?").get(hash) || {}).id || null);
1532
- }
1533
-
1534
- function insertPromotionDecision(db, proposal, decidedBy) {
1535
- if (!tableExists(db, "decision_log")) return null;
1536
- try {
1537
- const info = db.prepare("INSERT INTO decision_log (scope, title, body, decided_by, agents_involved, entities_affected) VALUES (?,?,?,?,?,?)")
1538
- .run(proposal.scope || DEFAULT_SCOPE, proposal.title, proposal.body || "", decidedBy || proposal.reviewer || "mnemo", proposal.agent_name || null, proposal.project || null);
1539
- return info.lastInsertRowid;
1540
- } catch {
1541
- return null;
1542
- }
1543
- }
1544
-
1545
- function memoryPromotionDecide(db, input = {}) {
1546
- ensureMemoryConsolidationSchema(db);
1547
- const id = parseInt(input.id || input.proposal_id, 10);
1548
- const status = String(input.status || input.decision || "").toLowerCase();
1549
- const reviewer = normalizeAgentName(input.reviewer || input.decided_by || input.approved_by);
1550
- if (!id || !reviewer || !["approved", "rejected", "promoted"].includes(status)) {
1551
- return { error: "id + reviewer + status(approved|rejected|promoted) required" };
1552
- }
1553
- const row = db.prepare("SELECT * FROM memory_promotion_proposal WHERE id=?").get(id);
1554
- if (!row) return { error: "proposal_not_found", id };
1555
- const proposal = rowToPromotion(row);
1556
- let promotedRef = { kind: null, id: null };
1557
- if (status === "promoted" || (status === "approved" && input.promote === true)) {
1558
- if (proposal.proposal_kind === "decision") {
1559
- const decisionId = insertPromotionDecision(db, proposal, reviewer);
1560
- if (decisionId) promotedRef = { kind: "decision_log", id: String(decisionId) };
1561
- }
1562
- if (!promotedRef.id) {
1563
- const memoryId = insertPromotionMemory(db, proposal, reviewer);
1564
- if (memoryId) promotedRef = { kind: "memory", id: String(memoryId) };
1565
- }
1566
- }
1567
- db.prepare(`
1568
- UPDATE memory_promotion_proposal
1569
- SET status=?, reviewer=?, review_notes=?, promoted_ref_kind=?, promoted_ref_id=?, decided_at=strftime('%Y-%m-%dT%H:%M:%fZ','now'), meta_json=COALESCE(?, meta_json)
1570
- WHERE id=?
1571
- `).run(
1572
- status,
1573
- reviewer,
1574
- input.review_notes || input.reason || null,
1575
- promotedRef.kind,
1576
- promotedRef.id,
1577
- input.meta ? safeJson(input.meta, {}) : null,
1578
- id
1579
- );
1580
- return { ok: true, id, status, reviewer, promoted_ref: promotedRef };
1581
- }
1582
-
1583
- function memoryPromotionList(db, input = {}) {
1584
- ensureMemoryConsolidationSchema(db);
1585
- const where = ["scope=?"];
1586
- const params = [scopeName(input.scope)];
1587
- if (input.status) { where.push("status=?"); params.push(input.status); }
1588
- if (input.proposal_kind || input.kind) { where.push("proposal_kind=?"); params.push(normalizeProposalKind(input.proposal_kind || input.kind)); }
1589
- if (input.project) { where.push("project=?"); params.push(input.project); }
1590
- if (input.department_name) { where.push("department_name=?"); params.push(normalizeDepartment(input.department_name)); }
1591
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
1592
- params.push(clampInt(input.limit, 50, 1, 500));
1593
- const rows = db.prepare(`
1594
- SELECT * FROM memory_promotion_proposal
1595
- WHERE ${where.join(" AND ")}
1596
- ORDER BY created_at DESC
1597
- LIMIT ?
1598
- `).all(...params).map(rowToPromotion);
1599
- return { ok: true, count: rows.length, proposals: rows };
1600
- }
1601
-
1602
- function activeClaims(db, input = {}, limit = 20) {
1603
- if (!tableExists(db, "work_claim")) return [];
1604
- const where = ["status IN ('active','stale')"];
1605
- const params = [];
1606
- if (input.project) { where.push("project=?"); params.push(input.project); }
1607
- params.push(limit);
1608
- return getRows(db, "work_claim", `
1609
- SELECT id, project, agent_name, claim_kind, scope_value, scope_key, summary, claimed_at, heartbeat_at, expires_at, status
1610
- FROM work_claim
1611
- WHERE ${where.join(" AND ")}
1612
- ORDER BY CASE status WHEN 'stale' THEN 2 ELSE 1 END DESC, expires_at ASC
1613
- LIMIT ?
1614
- `, params);
1615
- }
1616
-
1617
- function pendingApprovals(db, input = {}, limit = 20) {
1618
- if (!tableExists(db, "approval_request")) return [];
1619
- const where = ["status='pending'"];
1620
- const params = [];
1621
- if (input.project) { where.push("(project=? OR project IS NULL)"); params.push(input.project); }
1622
- params.push(limit);
1623
- return getRows(db, "approval_request", `
1624
- SELECT id, project, request_kind, resource_kind, resource_key, permission, requester_agent, owner_agent, reason, requested_at, expires_at, status
1625
- FROM approval_request
1626
- WHERE ${where.join(" AND ")}
1627
- ORDER BY requested_at DESC
1628
- LIMIT ?
1629
- `, params);
1630
- }
1631
-
1632
- function companyRemBrief(db, input = {}) {
1633
- ensureMemoryConsolidationSchema(db);
1634
- const days = clampInt(input.days, 1, 1, 30);
1635
- const since = input.since || new Date(Date.now() - days * 86400000).toISOString();
1636
- const journals = departmentJournalList(db, Object.assign({}, input, { since, limit: 30 })).journals || [];
1637
- const sleepNotes = agentSleepNoteList(db, Object.assign({}, input, { since, limit: 30 })).notes || [];
1638
- const proposals = memoryPromotionList(db, Object.assign({}, input, { status: "proposed", limit: 50 })).proposals || [];
1639
- const claims = activeClaims(db, input, 30);
1640
- const approvals = pendingApprovals(db, input, 30);
1641
- const status = memoryLayerStatus(db, Object.assign({}, input, { since, days }));
1642
- const remRuns = memoryConsolidationList(db, Object.assign({}, input, { phase: "rem", limit: 5 })).runs || [];
1643
-
1644
- const lines = [];
1645
- lines.push("# Coordinator REM Brief");
1646
- lines.push("");
1647
- lines.push(`Window: ${since} -> ${nowIso()}`);
1648
- if (input.project) lines.push(`Project: ${input.project}`);
1649
- lines.push("");
1650
- lines.push("## Situation");
1651
- lines.push(`- Department journal entries: ${journals.length}`);
1652
- lines.push(`- Agent sleep notes: ${sleepNotes.length}`);
1653
- lines.push(`- Promotion proposals needing review: ${proposals.length}`);
1654
- lines.push(`- Active/stale claims: ${claims.length}`);
1655
- lines.push(`- Pending approvals: ${approvals.length}`);
1656
- lines.push(`- Recent REM runs: ${remRuns.length}`);
1657
- lines.push("");
1658
-
1659
- const pushRows = (title, rows, formatter, max = 10) => {
1660
- lines.push(`## ${title}`);
1661
- if (!rows.length) lines.push("- none");
1662
- for (const row of rows.slice(0, max)) lines.push(formatter(row));
1663
- lines.push("");
1664
- };
1665
- pushRows("Open Promotion Proposals", proposals, (p) => `- #${p.id} ${p.proposal_kind} ${p.project || ""} ${p.title}`.trim(), 12);
1666
- pushRows("Pending Approvals", approvals, (a) => `- #${a.id} ${a.requester_agent} requests ${a.permission} on ${a.resource_kind}:${a.resource_key}${a.owner_agent ? ` from ${a.owner_agent}` : ""}`, 12);
1667
- pushRows("Claims", claims, (c) => `- #${c.id} ${c.status} ${c.agent_name} ${c.claim_kind || "scope"}:${c.scope_value || c.scope_key || c.file_path || ""} until ${c.expires_at || "unknown"}`, 12);
1668
- pushRows("Department Journals", journals, (j) => `- #${j.id} ${j.department_name}${j.project ? `/${j.project}` : ""}: ${compactContent(j.progress || j.blockers || j.risks || "", 180) || "(empty)"}`, 8);
1669
- pushRows("Agent Sleep Notes", sleepNotes, (n) => `- #${n.id} ${n.agent_name}${n.project ? `/${n.project}` : ""}: ${compactContent(n.learned || n.uncertainty || n.recurring_errors || "", 180) || "(empty)"}`, 8);
1670
- lines.push("## Required Coordinator Decisions");
1671
- if (proposals.length) lines.push("- Review proposed promotions and decide approved/rejected/promoted.");
1672
- if (approvals.length) lines.push("- Decide pending approvals or route to owners.");
1673
- if (claims.some((c) => c.status === "stale")) lines.push("- Recover or transfer stale claims.");
1674
- if (!proposals.length && !approvals.length && !claims.some((c) => c.status === "stale")) lines.push("- none");
1675
- lines.push("");
1676
- lines.push("Rule: this brief is management input. It does not promote truth by itself.");
1677
-
1678
- const markdown = lines.join("\n");
1679
- let briefId = null;
1680
- if (input.write_brief === true && tableExists(db, "agent_brief")) {
1681
- const coordinator = normalizeAgentName(input.coordinator_agent || "agent-a");
1682
- const info = db.prepare("INSERT INTO agent_brief (agent_name, source_agent, content, meta_json) VALUES (?,?,?,?)")
1683
- .run(coordinator, normalizeAgentName(input.source_agent || "mnemo-rem"), markdown, safeJson({ kind: "company_rem_brief", project: input.project || null, source_counts: status.source_counts }, {}));
1684
- briefId = info.lastInsertRowid;
1685
- }
1686
- return {
1687
- ok: true,
1688
- generated_at: nowIso(),
1689
- scope: scopeName(input.scope),
1690
- project: input.project || null,
1691
- markdown,
1692
- brief_id: briefId,
1693
- counts: {
1694
- journals: journals.length,
1695
- sleep_notes: sleepNotes.length,
1696
- proposals: proposals.length,
1697
- claims: claims.length,
1698
- approvals: approvals.length,
1699
- rem_runs: remRuns.length,
1700
- },
1701
- proposals,
1702
- pending_approvals: approvals,
1703
- active_claims: claims,
1704
- status,
1705
- };
1706
- }
1707
-
1708
- const MEMORY_CONSOLIDATION_TOOL_DEFS = {
1709
- mem_memory_layer_status: {
1710
- description: "Show Mnemo's canonical memory layers: session, daily, long_term, recall, and REM. Use this before adding any runtime gateway-like memory path.",
1711
- inputSchema: { type: "object", properties: { scope: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, days: { type: "integer", default: 7 }, since: { type: "string" } } },
1712
- },
1713
- mem_memory_rem_plan: {
1714
- description: "Return the next safe Memory/REM consolidation phases and exact Mnemo tool calls. Does not write.",
1715
- inputSchema: { type: "object", properties: { scope: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, days: { type: "integer" }, date: { type: "string" } } },
1716
- },
1717
- mem_memory_rem_run: {
1718
- description: "Run a deterministic Mnemo memory consolidation pass: light, daily, deep, or rem. Writes a draft run and a semantic memory_consolidation row; never deletes or rewrites old facts.",
1719
- inputSchema: {
1720
- type: "object",
1721
- properties: {
1722
- scope: { type: "string" },
1723
- agent_name: { type: "string" },
1724
- project: { type: "string" },
1725
- phase: { type: "string", enum: ["light", "daily", "deep", "rem"], default: "light" },
1726
- days: { type: "integer" },
1727
- date: { type: "string" },
1728
- limit: { type: "integer" },
1729
- status: { type: "string" },
1730
- confidence: { type: "string" },
1731
- review_status: { type: "string" },
1732
- promote_to_memory: { type: "boolean", default: true },
1733
- meta: { type: "object" },
1734
- },
1735
- },
1736
- },
1737
- mem_memory_consolidation_list: {
1738
- description: "List memory consolidation runs with selected source refs, source counts, status, confidence, and promoted memory id.",
1739
- inputSchema: { type: "object", properties: { scope: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, phase: { type: "string" }, status: { type: "string" }, limit: { type: "integer" } } },
1740
- },
1741
- mem_department_journal_add: {
1742
- description: "Append a department diary entry: progress, blockers, risks, open questions, dependencies, and foreign-scope requests. Not official truth until promoted.",
1743
- inputSchema: {
1744
- type: "object",
1745
- properties: {
1746
- scope: { type: "string" },
1747
- department_name: { type: "string" },
1748
- department: { type: "string" },
1749
- agent_name: { type: "string" },
1750
- project: { type: "string" },
1751
- journal_date: { type: "string" },
1752
- date: { type: "string" },
1753
- progress: { type: "string" },
1754
- summary: { type: "string" },
1755
- blockers: { type: "string" },
1756
- risks: { type: "string" },
1757
- open_questions: { type: "string" },
1758
- dependencies: { anyOf: [{ type: "array", items: { type: "string" } }, { type: "string" }] },
1759
- foreign_scope_requests: { anyOf: [{ type: "array", items: { type: "string" } }, { type: "string" }] },
1760
- access_requests: { anyOf: [{ type: "array", items: { type: "string" } }, { type: "string" }] },
1761
- status: { type: "string" },
1762
- meta: { type: "object" },
1763
- },
1764
- required: ["department_name"],
1765
- },
1766
- },
1767
- mem_department_journal_list: {
1768
- description: "List department diary entries for REM, handoff, and coordinator review.",
1769
- inputSchema: { type: "object", properties: { scope: { type: "string" }, department_name: { type: "string" }, department: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, status: { type: "string" }, since: { type: "string" }, limit: { type: "integer" } } },
1770
- },
1771
- mem_agent_sleep_note_add: {
1772
- description: "Append personal agent REM notes: learned, uncertainty, recurring errors, needed context, and improvement ideas. Not official truth until promoted.",
1773
- inputSchema: {
1774
- type: "object",
1775
- properties: {
1776
- scope: { type: "string" },
1777
- agent_name: { type: "string" },
1778
- project: { type: "string" },
1779
- note_date: { type: "string" },
1780
- date: { type: "string" },
1781
- learned: { type: "string" },
1782
- uncertainty: { type: "string" },
1783
- recurring_errors: { type: "string" },
1784
- needed_context: { type: "string" },
1785
- improvement_idea: { type: "string" },
1786
- source_ref: { type: "string" },
1787
- status: { type: "string" },
1788
- meta: { type: "object" },
1789
- },
1790
- required: ["agent_name"],
1791
- },
1792
- },
1793
- mem_agent_sleep_note_list: {
1794
- description: "List personal agent REM notes.",
1795
- inputSchema: { type: "object", properties: { scope: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, status: { type: "string" }, since: { type: "string" }, limit: { type: "integer" } } },
1796
- },
1797
- mem_memory_promotion_propose: {
1798
- description: "Propose a REM finding for official promotion. Creates a review item only; it does not change company truth.",
1799
- inputSchema: {
1800
- type: "object",
1801
- properties: {
1802
- scope: { type: "string" },
1803
- proposal_kind: { type: "string", enum: ["decision", "rule", "project_memory", "risk", "owner_question", "scar", "runbook"] },
1804
- kind: { type: "string" },
1805
- title: { type: "string" },
1806
- body: { type: "string" },
1807
- summary: { type: "string" },
1808
- question: { type: "string" },
1809
- project: { type: "string" },
1810
- department_name: { type: "string" },
1811
- agent_name: { type: "string" },
1812
- source_kind: { type: "string" },
1813
- source_id: { type: "string" },
1814
- evidence: { type: "array", items: { type: "object" } },
1815
- status: { type: "string" },
1816
- meta: { type: "object" },
1817
- },
1818
- },
1819
- },
1820
- mem_memory_promotion_list: {
1821
- description: "List REM promotion proposals waiting for coordinator/owner review.",
1822
- inputSchema: { type: "object", properties: { scope: { type: "string" }, status: { type: "string" }, proposal_kind: { type: "string" }, kind: { type: "string" }, project: { type: "string" }, department_name: { type: "string" }, agent_name: { type: "string" }, limit: { type: "integer" } } },
1823
- },
1824
- mem_memory_promotion_decide: {
1825
- description: "Approve, reject, or promote a REM promotion proposal. Promotion is an explicit Mnemo API action with reviewer attribution.",
1826
- inputSchema: {
1827
- type: "object",
1828
- properties: {
1829
- id: { type: "integer" },
1830
- proposal_id: { type: "integer" },
1831
- status: { type: "string", enum: ["approved", "rejected", "promoted"] },
1832
- decision: { type: "string" },
1833
- reviewer: { type: "string" },
1834
- decided_by: { type: "string" },
1835
- approved_by: { type: "string" },
1836
- review_notes: { type: "string" },
1837
- reason: { type: "string" },
1838
- promote: { type: "boolean" },
1839
- meta: { type: "object" },
1840
- },
1841
- required: ["id", "reviewer", "status"],
1842
- },
1843
- },
1844
- mem_company_rem_brief: {
1845
- description: "Generate a coordinator morning brief from department journals, sleep notes, promotion proposals, active claims, pending approvals, and REM state. Optionally writes an agent_brief.",
1846
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, days: { type: "integer", default: 1 }, since: { type: "string" }, write_brief: { type: "boolean" }, coordinator_agent: { type: "string" }, source_agent: { type: "string" } } },
1847
- },
1848
- mem_dreammode_run: {
1849
- description: "Run the nightly human-style Dreammode: classify the day into wrong made, right made, praise received, called out, broke things, and lessons. Also runs REM phases by default. Draft only; no automatic truth promotion.",
1850
- inputSchema: {
1851
- type: "object",
1852
- properties: {
1853
- scope: { type: "string" },
1854
- agent_name: { type: "string" },
1855
- project: { type: "string" },
1856
- dream_date: { type: "string" },
1857
- date: { type: "string" },
1858
- since: { type: "string" },
1859
- until: { type: "string" },
1860
- limit: { type: "integer" },
1861
- force: { type: "boolean" },
1862
- write_brief: { type: "boolean", default: true },
1863
- coordinator_agent: { type: "string" },
1864
- run_rem_phases: { type: "boolean", default: true },
1865
- phases: { type: "array", items: { type: "string", enum: ["light", "daily", "deep", "rem"] } },
1866
- rem_days: { type: "integer", default: 7 },
1867
- status: { type: "string" },
1868
- meta: { type: "object" },
1869
- },
1870
- },
1871
- },
1872
- mem_dreammode_status: {
1873
- description: "List recent Dreammode runs with human-style buckets and lessons.",
1874
- inputSchema: { type: "object", properties: { scope: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, dream_date: { type: "string" }, date: { type: "string" }, limit: { type: "integer" } } },
1875
- },
1876
- };
1877
-
1878
- function handleMemoryConsolidationTool(db, name, input = {}) {
1879
- if (name === "mem_memory_layer_status") return { handled: true, result: memoryLayerStatus(db, input || {}) };
1880
- if (name === "mem_memory_rem_plan") return { handled: true, result: memoryRemPlan(db, input || {}) };
1881
- if (name === "mem_memory_rem_run") return { handled: true, result: memoryRemRun(db, input || {}) };
1882
- if (name === "mem_memory_consolidation_list") return { handled: true, result: memoryConsolidationList(db, input || {}) };
1883
- if (name === "mem_department_journal_add") return { handled: true, result: departmentJournalAdd(db, input || {}) };
1884
- if (name === "mem_department_journal_list") return { handled: true, result: departmentJournalList(db, input || {}) };
1885
- if (name === "mem_agent_sleep_note_add") return { handled: true, result: agentSleepNoteAdd(db, input || {}) };
1886
- if (name === "mem_agent_sleep_note_list") return { handled: true, result: agentSleepNoteList(db, input || {}) };
1887
- if (name === "mem_memory_promotion_propose") return { handled: true, result: memoryPromotionPropose(db, input || {}) };
1888
- if (name === "mem_memory_promotion_list") return { handled: true, result: memoryPromotionList(db, input || {}) };
1889
- if (name === "mem_memory_promotion_decide") return { handled: true, result: memoryPromotionDecide(db, input || {}) };
1890
- if (name === "mem_company_rem_brief") return { handled: true, result: companyRemBrief(db, input || {}) };
1891
- if (name === "mem_dreammode_run") return { handled: true, result: dreammodeRun(db, input || {}) };
1892
- if (name === "mem_dreammode_status") return { handled: true, result: dreammodeStatus(db, input || {}) };
1893
- return { handled: false };
1894
- }
1895
-
1896
- module.exports = {
1897
- MEMORY_CONSOLIDATION_TOOL_DEFS,
1898
- ensureMemoryConsolidationSchema,
1899
- handleMemoryConsolidationTool,
1900
- memoryLayerStatus,
1901
- memoryRemPlan,
1902
- memoryRemRun,
1903
- memoryConsolidationList,
1904
- departmentJournalAdd,
1905
- departmentJournalList,
1906
- agentSleepNoteAdd,
1907
- agentSleepNoteList,
1908
- memoryPromotionPropose,
1909
- memoryPromotionList,
1910
- memoryPromotionDecide,
1911
- companyRemBrief,
1912
- dreammodeRun,
1913
- dreammodeStatus,
1914
- };