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,1256 +0,0 @@
1
- "use strict";
2
-
3
- const crypto = require("crypto");
4
- const {
5
- boolFlag,
6
- cleanScope,
7
- compactContent,
8
- jsonSafe,
9
- parseMaybeJson,
10
- uniqueAgentNames,
11
- uniqueStrings,
12
- normalizeAgentName,
13
- } = require("./shared_utils");
14
- const { capabilityTokenCheck } = require("./agent_governance");
15
- const {
16
- DEPLOY_PRECHECK_REQUIRED_EVIDENCE,
17
- DEPLOY_REQUIRED_EVIDENCE,
18
- } = require("./agent_governance");
19
-
20
- const DEFAULT_SCOPE = "default";
21
-
22
- function scopeName(scope) {
23
- return cleanScope(scope || DEFAULT_SCOPE);
24
- }
25
-
26
- function normalizeRuntimeName(value) {
27
- return String(value || "")
28
- .trim()
29
- .toLowerCase()
30
- .replace(/[^a-z0-9._-]+/g, "-")
31
- .replace(/^-+|-+$/g, "") || "runtime";
32
- }
33
-
34
- function normalizeCapabilityKind(value) {
35
- return String(value || "tool")
36
- .trim()
37
- .toLowerCase()
38
- .replace(/[^a-z0-9]+/g, "_")
39
- .replace(/^_+|_+$/g, "") || "tool";
40
- }
41
-
42
- function normalizeKey(value) {
43
- return String(value || "")
44
- .trim()
45
- .toLowerCase()
46
- .replace(/\s+/g, " ");
47
- }
48
-
49
- function normalizeStringList(value) {
50
- if (Array.isArray(value)) return uniqueStrings(value.map((item) => String(item || "").trim()).filter(Boolean));
51
- const parsed = parseMaybeJson(value, null);
52
- if (Array.isArray(parsed)) return uniqueStrings(parsed.map((item) => String(item || "").trim()).filter(Boolean));
53
- return uniqueStrings(String(value || "").split(/[\n,;]+/).map((item) => item.trim()).filter(Boolean));
54
- }
55
-
56
- function nowIso() {
57
- return new Date().toISOString();
58
- }
59
-
60
- function sha(value) {
61
- return crypto.createHash("sha256").update(String(value)).digest("hex");
62
- }
63
-
64
- function ensureMinimalEventJournalSchema(db) {
65
- db.exec(`
66
- CREATE TABLE IF NOT EXISTS mnemo_event_journal (
67
- id INTEGER PRIMARY KEY AUTOINCREMENT,
68
- source TEXT NOT NULL,
69
- channel TEXT,
70
- direction TEXT NOT NULL DEFAULT 'internal',
71
- actor TEXT,
72
- actor_id TEXT,
73
- event_kind TEXT NOT NULL,
74
- ref_kind TEXT,
75
- ref_id TEXT,
76
- thread_id TEXT,
77
- status TEXT,
78
- content TEXT,
79
- payload_json TEXT,
80
- meta_json TEXT,
81
- occurred_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
82
- ingested_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
83
- );
84
- CREATE INDEX IF NOT EXISTS idx_event_journal_occurred ON mnemo_event_journal(occurred_at DESC);
85
- CREATE INDEX IF NOT EXISTS idx_event_journal_source_channel ON mnemo_event_journal(source, channel, occurred_at DESC);
86
- CREATE INDEX IF NOT EXISTS idx_event_journal_actor ON mnemo_event_journal(actor, occurred_at DESC);
87
- CREATE INDEX IF NOT EXISTS idx_event_journal_kind ON mnemo_event_journal(event_kind, occurred_at DESC);
88
- CREATE INDEX IF NOT EXISTS idx_event_journal_ref ON mnemo_event_journal(ref_kind, ref_id);
89
- `);
90
- }
91
-
92
- function normalizeBindingKey(input = {}) {
93
- const explicit = String(input.binding_key || "").trim();
94
- if (explicit) return explicit.toLowerCase();
95
- const parts = [
96
- input.agent_name || "",
97
- input.session_key || "",
98
- input.channel || "",
99
- input.account_id || "",
100
- input.peer_kind || "",
101
- input.peer_id || "",
102
- input.workspace || "",
103
- ].map((part) => String(part || "").trim()).filter(Boolean);
104
- if (parts.length) return parts.join("|").toLowerCase();
105
- return "binding:" + sha(JSON.stringify(input || {})).slice(0, 16);
106
- }
107
-
108
- function normalizeCapabilityRef(input = {}) {
109
- const explicit = String(input.capability_ref || "").trim();
110
- if (explicit) return explicit.toLowerCase();
111
- const kind = normalizeCapabilityKind(input.capability_kind);
112
- const key = normalizeKey(input.capability_key || input.tool_name || input.channel || input.capability || "*") || "*";
113
- const agent = normalizeAgentName(input.agent_name || "");
114
- const channel = normalizeKey(input.channel || "");
115
- return [kind, key, agent || "*", channel || "*"].join("|");
116
- }
117
-
118
- function safeJson(value, fallback) {
119
- if (value == null) return JSON.stringify(fallback);
120
- return jsonSafe(value, 20000) || JSON.stringify(fallback);
121
- }
122
-
123
- function parseJsonField(value, fallback) {
124
- return parseMaybeJson(value, fallback);
125
- }
126
-
127
- function tableExists(db, tableName) {
128
- try {
129
- return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type IN ('table','view') AND name=?").get(tableName);
130
- } catch {
131
- return false;
132
- }
133
- }
134
-
135
- function normalizeEvidenceText(value) {
136
- return String(value || "")
137
- .toLowerCase()
138
- .replace(/[^\p{L}\p{N}]+/gu, " ")
139
- .replace(/\s+/g, " ")
140
- .trim();
141
- }
142
-
143
- function runtimeEvidenceText(item = {}) {
144
- const parts = [
145
- item.check,
146
- item.name,
147
- item.label,
148
- item.test_step,
149
- item.command,
150
- item.file_path,
151
- item.url,
152
- item.output_ref,
153
- item.result,
154
- item.status
155
- ];
156
- for (const field of ["files", "urls", "artifacts", "screenshots", "required_evidence"]) {
157
- if (Array.isArray(item[field])) parts.push(...item[field]);
158
- }
159
- return parts.filter(Boolean).join(" ");
160
- }
161
-
162
- function validateRuntimeEvidenceItem(item, index) {
163
- if (!item || typeof item !== "object" || Array.isArray(item)) {
164
- return "evidence[" + index + "] must be an object";
165
- }
166
- const hasOutcome = item.result != null || item.status != null || item.exit_code != null || item.exitCode != null;
167
- const hasCheck = !!String(item.check || item.name || item.label || item.test_step || item.command || "").trim();
168
- const hasTarget = !!String(item.file_path || item.url || item.output_ref || item.receipt_id || item.screenshot_path || item.media_id || "").trim()
169
- || ["files", "urls", "artifacts", "screenshots"].some((field) => Array.isArray(item[field]) && item[field].length > 0);
170
- if (!hasOutcome) return "evidence[" + index + "] needs result/status/exit_code";
171
- if (!hasCheck && !hasTarget) return "evidence[" + index + "] needs command/test_step/check or file/url/artifact reference";
172
- if (item.command && item.exit_code == null && item.exitCode == null) return "evidence[" + index + "] command evidence needs exit_code";
173
- return null;
174
- }
175
-
176
- function nonPassRuntimeEvidenceReason(item, index) {
177
- const exitCode = item && (item.exit_code != null ? item.exit_code : item.exitCode);
178
- if (exitCode != null) {
179
- const n = Number(exitCode);
180
- if (!Number.isFinite(n) || n !== 0) {
181
- return "evidence[" + index + "] exit_code must be 0 for done";
182
- }
183
- }
184
- const outcome = normalizeEvidenceText([item && item.result, item && item.status].filter(Boolean).join(" "));
185
- if (outcome && /\b(fail|failed|failure|error|errored|exception|blocked|block|needs review|needs_review|incomplete|missing|skipped|cancelled|canceled|timeout|timed out|red|not ok|nok)\b/.test(outcome)) {
186
- return "evidence[" + index + "] outcome is not passing for done";
187
- }
188
- return null;
189
- }
190
-
191
- function validateRuntimeEvidenceSet(evidence = []) {
192
- const invalid = evidence.map(validateRuntimeEvidenceItem).filter(Boolean);
193
- if (invalid.length) return { ok: false, error: "evidence_invalid", invalid };
194
- const failing = evidence.map(nonPassRuntimeEvidenceReason).filter(Boolean);
195
- if (failing.length) return { ok: false, error: "evidence_not_passing", invalid: failing };
196
- return { ok: true, invalid: [] };
197
- }
198
-
199
- function runtimeEvidenceMatchesRequirement(item, requirement) {
200
- const req = normalizeEvidenceText(requirement);
201
- if (!req) return true;
202
- const text = normalizeEvidenceText(runtimeEvidenceText(item));
203
- if (!text) return false;
204
- if (text.includes(req)) return true;
205
- const tokens = req.split(" ").filter((token) => token.length > 2);
206
- return tokens.length > 0 && tokens.every((token) => text.includes(token));
207
- }
208
-
209
- function missingRuntimeRequiredEvidence(evidence = [], requiredEvidence = []) {
210
- const required = normalizeStringList(requiredEvidence);
211
- if (!required.length) return [];
212
- return required.filter((requirement) => !evidence.some((item) => runtimeEvidenceMatchesRequirement(item, requirement)));
213
- }
214
-
215
- function runtimeEvidenceListFromInput(input = {}, fields = []) {
216
- const out = [];
217
- const keys = fields.length ? fields : ["evidence", "predeploy_evidence", "pre_deploy_evidence", "deploy_precheck_evidence", "deploy_evidence"];
218
- for (const key of keys) {
219
- if (Array.isArray(input[key])) out.push(...input[key]);
220
- }
221
- const meta = input.meta && typeof input.meta === "object" ? input.meta : {};
222
- for (const key of keys) {
223
- if (Array.isArray(meta[key])) out.push(...meta[key]);
224
- }
225
- return out.filter((item) => item && typeof item === "object" && !Array.isArray(item));
226
- }
227
-
228
- function runtimeDeployPrecheck(input = {}, preflight = null) {
229
- const evidence = runtimeEvidenceListFromInput(input);
230
- if (preflight && typeof preflight === "object") {
231
- evidence.push(...runtimeEvidenceListFromInput(preflight));
232
- if (Array.isArray(preflight.checks)) {
233
- for (const check of preflight.checks) {
234
- if (!check || typeof check !== "object") continue;
235
- if (/deploy[_\s-]*precheck|pre[_\s-]*deploy/i.test(String(check.name || check.check || check.label || ""))) evidence.push(check);
236
- }
237
- }
238
- }
239
- const missing = missingRuntimeRequiredEvidence(evidence, DEPLOY_PRECHECK_REQUIRED_EVIDENCE);
240
- return {
241
- required: true,
242
- ok: missing.length === 0,
243
- missing,
244
- evidence_count: evidence.length,
245
- required_evidence: DEPLOY_PRECHECK_REQUIRED_EVIDENCE,
246
- };
247
- }
248
-
249
- function deployManifestCheck(row, evidence = []) {
250
- if (String(row && row.action_type || "").toLowerCase() !== "deploy") return { ok: true, missing: [] };
251
- const manifestEvidence = evidence.find((item) => {
252
- if (!item || typeof item !== "object") return false;
253
- if (item.deploy_manifest || item.manifest) return true;
254
- return /deploy manifest|who what when where how/i.test(runtimeEvidenceText(item));
255
- });
256
- if (!manifestEvidence) {
257
- return { ok: false, missing: ["deploy manifest who what when where how"] };
258
- }
259
- const manifest = Object.assign({}, manifestEvidence.deploy_manifest || manifestEvidence.manifest || {}, manifestEvidence);
260
- const values = {
261
- who: manifest.who || manifest.actor || manifest.agent_name || row.agent_name,
262
- what: manifest.what || manifest.change || manifest.summary || row.task,
263
- when: manifest.when || manifest.timestamp || row.finished_at || row.started_at,
264
- where: manifest.where || manifest.target || manifest.url || manifest.server || manifest.project || row.project,
265
- how: manifest.how || manifest.method || manifest.command || row.tool_name,
266
- };
267
- const missing = Object.keys(values).filter((key) => !String(values[key] || "").trim());
268
- return { ok: missing.length === 0, missing, manifest: values };
269
- }
270
-
271
- function preflightRequiredEvidence(preflight = null) {
272
- if (!preflight || typeof preflight !== "object") return [];
273
- let required = normalizeStringList(preflight.required_evidence || preflight.requirements);
274
- const capability = preflight.capability_check && typeof preflight.capability_check === "object" ? preflight.capability_check : null;
275
- if (capability) required = required.concat(normalizeStringList(capability.required_evidence));
276
- if (Array.isArray(preflight.checks)) {
277
- for (const check of preflight.checks) {
278
- if (!check || typeof check !== "object") continue;
279
- required = required.concat(normalizeStringList(check.required_evidence));
280
- if (check.name === "capability_token") required = required.concat(normalizeStringList(check.required_evidence));
281
- }
282
- }
283
- return uniqueStrings(required);
284
- }
285
-
286
- function handoffEvidenceCheck(db, handoffId) {
287
- const id = parseInt(handoffId, 10);
288
- if (!id) return { ok: false, error: "handoff_id_invalid", evidence_count: 0 };
289
- if (!tableExists(db, "session_handoff")) return { ok: false, error: "handoff_table_missing", handoff_id: id, evidence_count: 0 };
290
- const row = db.prepare("SELECT * FROM session_handoff WHERE id=?").get(id);
291
- if (!row) return { ok: false, error: "handoff_not_found", handoff_id: id, evidence_count: 0 };
292
- const meta = parseJsonField(row.meta_json, {});
293
- const evidence = Array.isArray(meta.evidence) ? meta.evidence : [];
294
- if (!evidence.length) return { ok: false, error: "handoff_evidence_required", handoff_id: id, evidence_count: 0 };
295
- const check = validateRuntimeEvidenceSet(evidence);
296
- return Object.assign({}, check, { handoff_id: id, evidence_count: evidence.length });
297
- }
298
-
299
- function normalizePolicyPart(value, fallback = "*") {
300
- const raw = String(value == null ? "" : value).trim();
301
- if (!raw || raw === "*") return fallback;
302
- return raw.toLowerCase();
303
- }
304
-
305
- function normalizePolicyRuntime(value) {
306
- const raw = String(value == null ? "" : value).trim();
307
- if (!raw || raw === "*") return "*";
308
- return normalizeRuntimeName(raw);
309
- }
310
-
311
- function normalizePolicyAgent(value) {
312
- const raw = String(value == null ? "" : value).trim();
313
- if (!raw || raw === "*") return "*";
314
- return normalizeAgentName(raw) || "*";
315
- }
316
-
317
- function normalizePolicyKey(input = {}) {
318
- const explicit = String(input.policy_key || "").trim();
319
- if (explicit) return explicit.toLowerCase();
320
- return [
321
- normalizePolicyRuntime(input.runtime_name),
322
- normalizePolicyAgent(input.agent_name),
323
- normalizePolicyPart(input.channel),
324
- normalizePolicyPart(input.project),
325
- ].join("|");
326
- }
327
-
328
- function intFlag(value, fallback, min = 0, max = 1000000) {
329
- if (value === undefined || value === null || value === "") return fallback;
330
- const n = Number.parseInt(value, 10);
331
- if (!Number.isFinite(n)) return fallback;
332
- return Math.min(Math.max(n, min), max);
333
- }
334
-
335
- function minutesSince(value) {
336
- if (value === undefined || value === null || value === "") return null;
337
- if (typeof value === "number") return Math.max(0, value);
338
- const parsedNumber = Number(value);
339
- if (Number.isFinite(parsedNumber) && String(value).trim() !== "") return Math.max(0, parsedNumber);
340
- const ms = Date.parse(String(value));
341
- if (!Number.isFinite(ms)) return null;
342
- return Math.max(0, Math.floor((Date.now() - ms) / 60000));
343
- }
344
-
345
- function defaultRuntimePolicy(input = {}) {
346
- const agent = normalizePolicyAgent(input.agent_name);
347
- const base = {
348
- id: null,
349
- scope: scopeName(input.scope),
350
- runtime_name: normalizePolicyRuntime(input.runtime_name || "runtime-a"),
351
- agent_name: agent,
352
- channel: normalizePolicyPart(input.channel),
353
- project: normalizePolicyPart(input.project),
354
- policy_key: normalizePolicyKey(input),
355
- required_brief_pull: true,
356
- required_recall: true,
357
- required_project_board: true,
358
- required_chat_sync: true,
359
- required_memory_update: true,
360
- required_message_capture: true,
361
- required_board: "",
362
- stale_after_minutes: 15,
363
- full_sync_every_messages: 10,
364
- response_allowed_when_context_missing: false,
365
- warning_token_required: true,
366
- status: "active",
367
- required_actions: ["mem_capture_ingest", "mem_brief_pull", "mem_recall", "mem_project_board", "mem_work_report_feed", "mem_project_timeline_report", "mem_event_log"],
368
- meta: { source: "default" },
369
- updated_by: null,
370
- created_at: null,
371
- updated_at: null,
372
- };
373
- if (agent === "agent-c") {
374
- base.required_board = "builder-v2-board";
375
- base.response_allowed_when_context_missing = false;
376
- } else if (agent === "agent-a") {
377
- base.required_board = "builder-v2-board";
378
- base.response_allowed_when_context_missing = false;
379
- }
380
- return base;
381
- }
382
-
383
- function ensureRuntimeGovernanceSchema(db) {
384
- ensureMinimalEventJournalSchema(db);
385
- db.exec(`
386
- CREATE TABLE IF NOT EXISTS runtime_binding (
387
- id INTEGER PRIMARY KEY AUTOINCREMENT,
388
- scope TEXT NOT NULL DEFAULT 'default',
389
- runtime_name TEXT NOT NULL,
390
- binding_key TEXT NOT NULL,
391
- agent_name TEXT,
392
- project TEXT,
393
- session_key TEXT,
394
- channel TEXT,
395
- account_id TEXT,
396
- peer_kind TEXT,
397
- peer_id TEXT,
398
- workspace TEXT,
399
- mode TEXT,
400
- connector_system TEXT,
401
- capabilities_json TEXT,
402
- status TEXT NOT NULL DEFAULT 'active',
403
- source_ref TEXT,
404
- meta_json TEXT,
405
- updated_by TEXT,
406
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
407
- updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
408
- UNIQUE(scope, runtime_name, binding_key)
409
- );
410
- CREATE INDEX IF NOT EXISTS idx_runtime_binding_agent ON runtime_binding(agent_name, status, updated_at DESC);
411
- CREATE INDEX IF NOT EXISTS idx_runtime_binding_project ON runtime_binding(project, status, updated_at DESC);
412
- CREATE INDEX IF NOT EXISTS idx_runtime_binding_session ON runtime_binding(runtime_name, session_key, status);
413
-
414
- CREATE TABLE IF NOT EXISTS runtime_capability (
415
- id INTEGER PRIMARY KEY AUTOINCREMENT,
416
- scope TEXT NOT NULL DEFAULT 'default',
417
- runtime_name TEXT NOT NULL,
418
- capability_ref TEXT NOT NULL,
419
- capability_kind TEXT NOT NULL DEFAULT 'tool',
420
- capability_key TEXT NOT NULL,
421
- agent_name TEXT,
422
- channel TEXT,
423
- permission TEXT NOT NULL DEFAULT 'allow',
424
- risk_class TEXT NOT NULL DEFAULT 'normal',
425
- requires_preflight INTEGER NOT NULL DEFAULT 1,
426
- requires_receipt INTEGER NOT NULL DEFAULT 1,
427
- enabled INTEGER NOT NULL DEFAULT 1,
428
- allowed_agents_json TEXT,
429
- status TEXT NOT NULL DEFAULT 'active',
430
- notes TEXT,
431
- source_ref TEXT,
432
- meta_json TEXT,
433
- updated_by TEXT,
434
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
435
- updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
436
- UNIQUE(scope, runtime_name, capability_ref)
437
- );
438
- CREATE INDEX IF NOT EXISTS idx_runtime_capability_lookup ON runtime_capability(scope, runtime_name, capability_kind, capability_key, status);
439
- CREATE INDEX IF NOT EXISTS idx_runtime_capability_agent ON runtime_capability(agent_name, status);
440
-
441
- CREATE TABLE IF NOT EXISTS runtime_tool_receipt (
442
- receipt_id TEXT PRIMARY KEY,
443
- scope TEXT NOT NULL DEFAULT 'default',
444
- runtime_name TEXT NOT NULL,
445
- agent_name TEXT NOT NULL,
446
- project TEXT,
447
- task TEXT,
448
- action_type TEXT,
449
- tool_name TEXT NOT NULL,
450
- tool_kind TEXT,
451
- session_key TEXT,
452
- channel TEXT,
453
- request_id TEXT,
454
- binding_id INTEGER,
455
- connector_system TEXT,
456
- status TEXT NOT NULL DEFAULT 'started',
457
- allowed INTEGER NOT NULL DEFAULT 0,
458
- evidence_required INTEGER NOT NULL DEFAULT 0,
459
- preflight_status TEXT,
460
- preflight_action_id INTEGER,
461
- preflight_json TEXT,
462
- capability_check_json TEXT,
463
- claim_ids_json TEXT,
464
- approval_ids_json TEXT,
465
- resources_json TEXT,
466
- tools_json TEXT,
467
- evidence_json TEXT,
468
- result_summary TEXT,
469
- result_json TEXT,
470
- error TEXT,
471
- meta_json TEXT,
472
- started_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
473
- finished_at TEXT
474
- );
475
- CREATE INDEX IF NOT EXISTS idx_runtime_receipt_agent ON runtime_tool_receipt(agent_name, started_at DESC);
476
- CREATE INDEX IF NOT EXISTS idx_runtime_receipt_project ON runtime_tool_receipt(project, started_at DESC);
477
- CREATE INDEX IF NOT EXISTS idx_runtime_receipt_status ON runtime_tool_receipt(status, started_at DESC);
478
- CREATE INDEX IF NOT EXISTS idx_runtime_receipt_runtime ON runtime_tool_receipt(runtime_name, session_key, started_at DESC);
479
-
480
- CREATE TABLE IF NOT EXISTS runtime_policy (
481
- id INTEGER PRIMARY KEY AUTOINCREMENT,
482
- scope TEXT NOT NULL DEFAULT 'default',
483
- runtime_name TEXT NOT NULL DEFAULT '*',
484
- agent_name TEXT NOT NULL DEFAULT '*',
485
- channel TEXT NOT NULL DEFAULT '*',
486
- project TEXT NOT NULL DEFAULT '*',
487
- policy_key TEXT NOT NULL,
488
- required_brief_pull INTEGER NOT NULL DEFAULT 1,
489
- required_recall INTEGER NOT NULL DEFAULT 1,
490
- required_project_board INTEGER NOT NULL DEFAULT 1,
491
- required_chat_sync INTEGER NOT NULL DEFAULT 1,
492
- required_memory_update INTEGER NOT NULL DEFAULT 1,
493
- required_message_capture INTEGER NOT NULL DEFAULT 1,
494
- required_board TEXT,
495
- stale_after_minutes INTEGER NOT NULL DEFAULT 15,
496
- full_sync_every_messages INTEGER NOT NULL DEFAULT 10,
497
- response_allowed_when_context_missing INTEGER NOT NULL DEFAULT 1,
498
- warning_token_required INTEGER NOT NULL DEFAULT 1,
499
- status TEXT NOT NULL DEFAULT 'active',
500
- required_actions_json TEXT,
501
- meta_json TEXT,
502
- updated_by TEXT,
503
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
504
- updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
505
- UNIQUE(scope, runtime_name, policy_key)
506
- );
507
- CREATE INDEX IF NOT EXISTS idx_runtime_policy_lookup ON runtime_policy(scope, runtime_name, agent_name, channel, project, status);
508
- CREATE INDEX IF NOT EXISTS idx_runtime_policy_agent ON runtime_policy(agent_name, status, updated_at DESC);
509
- `);
510
-
511
- try {
512
- db.exec("ALTER TABLE runtime_policy ADD COLUMN required_message_capture INTEGER NOT NULL DEFAULT 1");
513
- } catch {}
514
-
515
- try {
516
- db.exec(`
517
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_runtime_binding_ai AFTER INSERT ON runtime_binding BEGIN
518
- INSERT INTO mnemo_event_journal
519
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
520
- VALUES
521
- ('runtime_binding', NEW.channel, 'internal', NEW.updated_by, 'runtime_binding_insert', 'runtime_binding', CAST(NEW.id AS TEXT), NEW.status, COALESCE(NEW.runtime_name, '') || ' ' || COALESCE(NEW.agent_name, '') || ' ' || COALESCE(NEW.session_key, ''), NULL, NEW.meta_json, NEW.updated_at);
522
- END;
523
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_runtime_binding_au AFTER UPDATE ON runtime_binding BEGIN
524
- INSERT INTO mnemo_event_journal
525
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
526
- VALUES
527
- ('runtime_binding', NEW.channel, 'internal', NEW.updated_by, 'runtime_binding_update', 'runtime_binding', CAST(NEW.id AS TEXT), NEW.status, COALESCE(NEW.runtime_name, '') || ' ' || COALESCE(NEW.agent_name, '') || ' ' || COALESCE(NEW.session_key, ''), NULL, NEW.meta_json, NEW.updated_at);
528
- END;
529
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_runtime_capability_ai AFTER INSERT ON runtime_capability BEGIN
530
- INSERT INTO mnemo_event_journal
531
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
532
- VALUES
533
- ('runtime_capability', NEW.channel, 'internal', NEW.updated_by, 'runtime_capability_insert', 'runtime_capability', CAST(NEW.id AS TEXT), NEW.status, COALESCE(NEW.runtime_name, '') || ' ' || COALESCE(NEW.capability_kind, '') || ':' || COALESCE(NEW.capability_key, ''), NULL, NEW.meta_json, NEW.updated_at);
534
- END;
535
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_runtime_receipt_ai AFTER INSERT ON runtime_tool_receipt BEGIN
536
- INSERT INTO mnemo_event_journal
537
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
538
- VALUES
539
- ('runtime_tool_receipt', NEW.channel, 'internal', NEW.agent_name, 'runtime_tool_receipt_start', 'runtime_tool_receipt', NEW.receipt_id, NEW.status, COALESCE(NEW.tool_name, '') || ' ' || COALESCE(NEW.task, ''), NEW.resources_json, NEW.meta_json, NEW.started_at);
540
- END;
541
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_runtime_receipt_au AFTER UPDATE ON runtime_tool_receipt BEGIN
542
- INSERT INTO mnemo_event_journal
543
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
544
- VALUES
545
- ('runtime_tool_receipt', NEW.channel, 'internal', NEW.agent_name, 'runtime_tool_receipt_update', 'runtime_tool_receipt', NEW.receipt_id, NEW.status, COALESCE(NEW.result_summary, NEW.error, NEW.tool_name), NEW.result_json, NEW.meta_json, COALESCE(NEW.finished_at, strftime('%Y-%m-%dT%H:%M:%fZ','now')));
546
- END;
547
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_runtime_policy_ai AFTER INSERT ON runtime_policy BEGIN
548
- INSERT INTO mnemo_event_journal
549
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
550
- VALUES
551
- ('runtime_policy', NEW.channel, 'internal', NEW.updated_by, 'runtime_policy_insert', 'runtime_policy', CAST(NEW.id AS TEXT), NEW.status, NEW.policy_key, NEW.required_actions_json, NEW.meta_json, NEW.updated_at);
552
- END;
553
- CREATE TRIGGER IF NOT EXISTS mnemo_journal_runtime_policy_au AFTER UPDATE ON runtime_policy BEGIN
554
- INSERT INTO mnemo_event_journal
555
- (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at)
556
- VALUES
557
- ('runtime_policy', NEW.channel, 'internal', NEW.updated_by, 'runtime_policy_update', 'runtime_policy', CAST(NEW.id AS TEXT), NEW.status, NEW.policy_key, NEW.required_actions_json, NEW.meta_json, NEW.updated_at);
558
- END;
559
- `);
560
- } catch {}
561
- }
562
-
563
- function bindingUpsert(db, input = {}) {
564
- ensureRuntimeGovernanceSchema(db);
565
- const scope = scopeName(input.scope);
566
- const runtime = normalizeRuntimeName(input.runtime_name);
567
- const bindingKey = normalizeBindingKey(input);
568
- const agent = normalizeAgentName(input.agent_name || "");
569
- const capabilities = normalizeStringList(input.capabilities);
570
- db.prepare(
571
- "INSERT INTO runtime_binding (scope, runtime_name, binding_key, agent_name, project, session_key, channel, account_id, peer_kind, peer_id, workspace, mode, connector_system, capabilities_json, status, source_ref, meta_json, updated_by, updated_at) " +
572
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,strftime('%Y-%m-%dT%H:%M:%fZ','now')) " +
573
- "ON CONFLICT(scope, runtime_name, binding_key) DO UPDATE SET agent_name=excluded.agent_name, project=excluded.project, session_key=excluded.session_key, channel=excluded.channel, account_id=excluded.account_id, peer_kind=excluded.peer_kind, peer_id=excluded.peer_id, workspace=excluded.workspace, mode=excluded.mode, connector_system=excluded.connector_system, capabilities_json=excluded.capabilities_json, status=excluded.status, source_ref=excluded.source_ref, meta_json=excluded.meta_json, updated_by=excluded.updated_by, updated_at=excluded.updated_at"
574
- ).run(
575
- scope,
576
- runtime,
577
- bindingKey,
578
- agent || null,
579
- input.project || null,
580
- input.session_key || null,
581
- input.channel || null,
582
- input.account_id || null,
583
- input.peer_kind || null,
584
- input.peer_id || null,
585
- input.workspace || null,
586
- input.mode || null,
587
- input.connector_system || null,
588
- JSON.stringify(capabilities),
589
- input.status || "active",
590
- input.source_ref || null,
591
- safeJson(input.meta || {}, {}),
592
- normalizeAgentName(input.updated_by || input.agent_name || "") || null
593
- );
594
- const row = db.prepare("SELECT * FROM runtime_binding WHERE scope=? AND runtime_name=? AND binding_key=?").get(scope, runtime, bindingKey);
595
- return { ok: true, binding: rowToBinding(row) };
596
- }
597
-
598
- function rowToBinding(row) {
599
- return row ? Object.assign({}, row, {
600
- capabilities: parseJsonField(row.capabilities_json, []),
601
- meta: parseJsonField(row.meta_json, {}),
602
- }) : null;
603
- }
604
-
605
- function bindingList(db, input = {}) {
606
- ensureRuntimeGovernanceSchema(db);
607
- const where = ["scope=?"];
608
- const params = [scopeName(input.scope)];
609
- if (input.runtime_name) { where.push("runtime_name=?"); params.push(normalizeRuntimeName(input.runtime_name)); }
610
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
611
- if (input.project) { where.push("project=?"); params.push(input.project); }
612
- if (input.session_key) { where.push("session_key=?"); params.push(input.session_key); }
613
- if (input.channel) { where.push("channel=?"); params.push(input.channel); }
614
- if (input.status) { where.push("status=?"); params.push(input.status); }
615
- else where.push("status!='deleted'");
616
- params.push(Math.min(Math.max(parseInt(input.limit || 100, 10) || 100, 1), 500));
617
- const rows = db.prepare("SELECT * FROM runtime_binding WHERE " + where.join(" AND ") + " ORDER BY updated_at DESC LIMIT ?").all(...params).map(rowToBinding);
618
- return { ok: true, count: rows.length, bindings: rows };
619
- }
620
-
621
- function capabilityUpsert(db, input = {}) {
622
- ensureRuntimeGovernanceSchema(db);
623
- const scope = scopeName(input.scope);
624
- const runtime = normalizeRuntimeName(input.runtime_name);
625
- const kind = normalizeCapabilityKind(input.capability_kind || (input.tool_name ? "tool" : "capability"));
626
- const key = normalizeKey(input.capability_key || input.tool_name || input.capability || "*") || "*";
627
- const ref = normalizeCapabilityRef(Object.assign({}, input, { capability_kind: kind, capability_key: key }));
628
- const allowedAgents = uniqueAgentNames(normalizeStringList(input.allowed_agents));
629
- db.prepare(
630
- "INSERT INTO runtime_capability (scope, runtime_name, capability_ref, capability_kind, capability_key, agent_name, channel, permission, risk_class, requires_preflight, requires_receipt, enabled, allowed_agents_json, status, notes, source_ref, meta_json, updated_by, updated_at) " +
631
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,strftime('%Y-%m-%dT%H:%M:%fZ','now')) " +
632
- "ON CONFLICT(scope, runtime_name, capability_ref) DO UPDATE SET capability_kind=excluded.capability_kind, capability_key=excluded.capability_key, agent_name=excluded.agent_name, channel=excluded.channel, permission=excluded.permission, risk_class=excluded.risk_class, requires_preflight=excluded.requires_preflight, requires_receipt=excluded.requires_receipt, enabled=excluded.enabled, allowed_agents_json=excluded.allowed_agents_json, status=excluded.status, notes=excluded.notes, source_ref=excluded.source_ref, meta_json=excluded.meta_json, updated_by=excluded.updated_by, updated_at=excluded.updated_at"
633
- ).run(
634
- scope,
635
- runtime,
636
- ref,
637
- kind,
638
- key,
639
- normalizeAgentName(input.agent_name || "") || null,
640
- input.channel || null,
641
- String(input.permission || "allow").toLowerCase(),
642
- input.risk_class || "normal",
643
- boolFlag(input.requires_preflight, true) ? 1 : 0,
644
- boolFlag(input.requires_receipt, true) ? 1 : 0,
645
- boolFlag(input.enabled, true) ? 1 : 0,
646
- JSON.stringify(allowedAgents),
647
- input.status || "active",
648
- input.notes || null,
649
- input.source_ref || null,
650
- safeJson(input.meta || {}, {}),
651
- normalizeAgentName(input.updated_by || input.agent_name || "") || null
652
- );
653
- const row = db.prepare("SELECT * FROM runtime_capability WHERE scope=? AND runtime_name=? AND capability_ref=?").get(scope, runtime, ref);
654
- return { ok: true, capability: rowToCapability(row) };
655
- }
656
-
657
- function rowToCapability(row) {
658
- return row ? Object.assign({}, row, {
659
- requires_preflight: !!row.requires_preflight,
660
- requires_receipt: !!row.requires_receipt,
661
- enabled: !!row.enabled,
662
- allowed_agents: parseJsonField(row.allowed_agents_json, []),
663
- meta: parseJsonField(row.meta_json, {}),
664
- }) : null;
665
- }
666
-
667
- function capabilityList(db, input = {}) {
668
- ensureRuntimeGovernanceSchema(db);
669
- const where = ["scope=?"];
670
- const params = [scopeName(input.scope)];
671
- if (input.runtime_name) { where.push("runtime_name=?"); params.push(normalizeRuntimeName(input.runtime_name)); }
672
- if (input.capability_kind) { where.push("capability_kind=?"); params.push(normalizeCapabilityKind(input.capability_kind)); }
673
- if (input.capability_key) { where.push("capability_key=?"); params.push(normalizeKey(input.capability_key)); }
674
- if (input.agent_name) { where.push("(agent_name=? OR agent_name IS NULL)"); params.push(normalizeAgentName(input.agent_name)); }
675
- if (input.channel) { where.push("(channel=? OR channel IS NULL)"); params.push(input.channel); }
676
- if (input.status) { where.push("status=?"); params.push(input.status); }
677
- else where.push("status='active'");
678
- params.push(Math.min(Math.max(parseInt(input.limit || 100, 10) || 100, 1), 500));
679
- const rows = db.prepare("SELECT * FROM runtime_capability WHERE " + where.join(" AND ") + " ORDER BY updated_at DESC LIMIT ?").all(...params).map(rowToCapability);
680
- return { ok: true, count: rows.length, capabilities: rows };
681
- }
682
-
683
- function runtimeCapabilityCheck(db, input = {}) {
684
- ensureRuntimeGovernanceSchema(db);
685
- const scope = scopeName(input.scope);
686
- const runtime = normalizeRuntimeName(input.runtime_name);
687
- const agent = normalizeAgentName(input.agent_name || "");
688
- const channel = input.channel || null;
689
- const requested = uniqueStrings([])
690
- .concat(normalizeStringList(input.capabilities))
691
- .concat(input.tool_name ? [String(input.tool_name)] : [])
692
- .concat(input.tool_kind ? [String(input.tool_kind)] : [])
693
- .map((item) => normalizeKey(item))
694
- .filter(Boolean);
695
- const allRows = db.prepare(
696
- "SELECT * FROM runtime_capability WHERE scope IN (?, 'default') AND runtime_name IN (?, '*') AND status='active' ORDER BY updated_at DESC"
697
- ).all(scope, runtime).map(rowToCapability);
698
- const matched = [];
699
- const blockers = [];
700
- const warnings = [];
701
- for (const row of allRows) {
702
- const key = normalizeKey(row.capability_key);
703
- const agentMatch = !row.agent_name || row.agent_name === agent;
704
- const channelMatch = !row.channel || row.channel === channel;
705
- const keyMatch = key === "*" || requested.includes(key);
706
- if (!agentMatch || !channelMatch || !keyMatch) continue;
707
- matched.push(row);
708
- const allowedAgents = uniqueAgentNames(row.allowed_agents || []);
709
- if (!row.enabled || ["deny", "block", "disabled"].includes(String(row.permission || "").toLowerCase())) {
710
- blockers.push(`runtime capability denied: ${row.runtime_name} ${row.capability_kind}:${row.capability_key}`);
711
- }
712
- if (allowedAgents.length && !allowedAgents.includes(agent)) {
713
- blockers.push(`runtime capability ${row.capability_key} does not allow agent ${agent}`);
714
- }
715
- }
716
- if (!matched.length) {
717
- const msg = `runtime capability not registered for ${runtime}: ${requested.join(", ") || input.tool_name || "tool"}`;
718
- if (input.require_registered_capability) blockers.push(msg);
719
- else warnings.push(msg);
720
- }
721
- return {
722
- ok: blockers.length === 0,
723
- status: blockers.length ? "block" : (warnings.length ? "warn" : "ok"),
724
- runtime_name: runtime,
725
- agent_name: agent,
726
- requested,
727
- blockers,
728
- warnings,
729
- matched_count: matched.length,
730
- matched_capabilities: matched,
731
- requires_preflight: matched.length ? matched.some((row) => row.requires_preflight) : true,
732
- requires_receipt: matched.length ? matched.some((row) => row.requires_receipt) : true,
733
- };
734
- }
735
-
736
- function rowToRuntimePolicy(row) {
737
- return row ? Object.assign({}, row, {
738
- required_brief_pull: !!row.required_brief_pull,
739
- required_recall: !!row.required_recall,
740
- required_project_board: !!row.required_project_board,
741
- required_chat_sync: !!row.required_chat_sync,
742
- required_memory_update: !!row.required_memory_update,
743
- required_message_capture: row.required_message_capture == null ? true : !!row.required_message_capture,
744
- response_allowed_when_context_missing: !!row.response_allowed_when_context_missing,
745
- warning_token_required: !!row.warning_token_required,
746
- required_actions: parseJsonField(row.required_actions_json, []),
747
- meta: parseJsonField(row.meta_json, {}),
748
- }) : null;
749
- }
750
-
751
- function runtimePolicySet(db, input = {}) {
752
- ensureRuntimeGovernanceSchema(db);
753
- const scope = scopeName(input.scope);
754
- const runtime = normalizePolicyRuntime(input.runtime_name || "*");
755
- const agent = normalizePolicyAgent(input.agent_name || "*");
756
- const channel = normalizePolicyPart(input.channel || "*");
757
- const project = normalizePolicyPart(input.project || "*");
758
- const policyKey = normalizePolicyKey({ runtime_name: runtime, agent_name: agent, channel, project, policy_key: input.policy_key });
759
- const base = defaultRuntimePolicy({ scope, runtime_name: runtime, agent_name: agent, channel, project, policy_key: policyKey });
760
- const requiredActions = normalizeStringList(input.required_actions || input.required_actions_json || base.required_actions);
761
- db.prepare(
762
- "INSERT INTO runtime_policy (scope, runtime_name, agent_name, channel, project, policy_key, required_brief_pull, required_recall, required_project_board, required_chat_sync, required_memory_update, required_message_capture, required_board, stale_after_minutes, full_sync_every_messages, response_allowed_when_context_missing, warning_token_required, status, required_actions_json, meta_json, updated_by, updated_at) " +
763
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,strftime('%Y-%m-%dT%H:%M:%fZ','now')) " +
764
- "ON CONFLICT(scope, runtime_name, policy_key) DO UPDATE SET agent_name=excluded.agent_name, channel=excluded.channel, project=excluded.project, required_brief_pull=excluded.required_brief_pull, required_recall=excluded.required_recall, required_project_board=excluded.required_project_board, required_chat_sync=excluded.required_chat_sync, required_memory_update=excluded.required_memory_update, required_message_capture=excluded.required_message_capture, required_board=excluded.required_board, stale_after_minutes=excluded.stale_after_minutes, full_sync_every_messages=excluded.full_sync_every_messages, response_allowed_when_context_missing=excluded.response_allowed_when_context_missing, warning_token_required=excluded.warning_token_required, status=excluded.status, required_actions_json=excluded.required_actions_json, meta_json=excluded.meta_json, updated_by=excluded.updated_by, updated_at=excluded.updated_at"
765
- ).run(
766
- scope,
767
- runtime,
768
- agent,
769
- channel,
770
- project,
771
- policyKey,
772
- boolFlag(input.required_brief_pull, base.required_brief_pull) ? 1 : 0,
773
- boolFlag(input.required_recall, base.required_recall) ? 1 : 0,
774
- boolFlag(input.required_project_board, base.required_project_board) ? 1 : 0,
775
- boolFlag(input.required_chat_sync, base.required_chat_sync) ? 1 : 0,
776
- boolFlag(input.required_memory_update, base.required_memory_update) ? 1 : 0,
777
- boolFlag(input.required_message_capture, base.required_message_capture) ? 1 : 0,
778
- input.required_board != null ? String(input.required_board) : base.required_board,
779
- intFlag(input.stale_after_minutes, base.stale_after_minutes, 1, 10080),
780
- intFlag(input.full_sync_every_messages, base.full_sync_every_messages, 1, 100000),
781
- boolFlag(input.response_allowed_when_context_missing, base.response_allowed_when_context_missing) ? 1 : 0,
782
- boolFlag(input.warning_token_required, base.warning_token_required) ? 1 : 0,
783
- input.status || "active",
784
- safeJson(requiredActions, []),
785
- safeJson(input.meta || {}, {}),
786
- normalizeAgentName(input.updated_by || input.agent_name || "") || null
787
- );
788
- const row = db.prepare("SELECT * FROM runtime_policy WHERE scope=? AND runtime_name=? AND policy_key=?").get(scope, runtime, policyKey);
789
- return { ok: true, policy: rowToRuntimePolicy(row) };
790
- }
791
-
792
- function runtimePolicySpecificity(row, input = {}) {
793
- const runtime = normalizePolicyRuntime(input.runtime_name || "runtime-a");
794
- const agent = normalizePolicyAgent(input.agent_name || "*");
795
- const channel = normalizePolicyPart(input.channel || "*");
796
- const project = normalizePolicyPart(input.project || "*");
797
- let score = 0;
798
- if (row.scope === scopeName(input.scope)) score += 32;
799
- if (row.runtime_name === runtime) score += 16;
800
- if (row.agent_name === agent) score += 8;
801
- if (row.project === project) score += 4;
802
- if (row.channel === channel) score += 2;
803
- if (row.policy_key && row.policy_key !== "*") score += 1;
804
- return score;
805
- }
806
-
807
- function runtimePolicyGet(db, input = {}) {
808
- ensureRuntimeGovernanceSchema(db);
809
- const scope = scopeName(input.scope);
810
- const runtime = normalizePolicyRuntime(input.runtime_name || "runtime-a");
811
- const agent = normalizePolicyAgent(input.agent_name || "*");
812
- const channel = normalizePolicyPart(input.channel || "*");
813
- const project = normalizePolicyPart(input.project || "*");
814
- const rows = db.prepare(
815
- "SELECT * FROM runtime_policy WHERE scope IN (?, 'default') AND runtime_name IN (?, '*') AND agent_name IN (?, '*') AND channel IN (?, '*') AND project IN (?, '*') AND status='active'"
816
- ).all(scope, runtime, agent, channel, project).map(rowToRuntimePolicy);
817
- rows.sort((a, b) => runtimePolicySpecificity(b, input) - runtimePolicySpecificity(a, input));
818
- if (rows.length) return { ok: true, source: "stored", policy: rows[0], matched_policy_id: rows[0].id };
819
- return { ok: true, source: "default", policy: defaultRuntimePolicy({ scope, runtime_name: runtime, agent_name: agent, channel, project }) };
820
- }
821
-
822
- function requirementStale(input, key, staleAfter) {
823
- const has = boolFlag(input[`has_${key}`], false);
824
- const minutes = minutesSince(input[`${key}_at`] || input[`last_${key}_at`] || input[`minutes_since_${key}`]);
825
- if (!has) return { missing: true, reason: `${key} missing`, age_minutes: minutes };
826
- if (minutes != null && minutes > staleAfter) return { missing: true, reason: `${key} stale (${minutes}m > ${staleAfter}m)`, age_minutes: minutes };
827
- return { missing: false, reason: "ok", age_minutes: minutes };
828
- }
829
-
830
- function journalRuntimePolicyCheck(db, input, result) {
831
- try {
832
- const info = db.prepare(
833
- "INSERT INTO mnemo_event_journal (source, channel, direction, actor, event_kind, ref_kind, ref_id, status, content, payload_json, meta_json, occurred_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,strftime('%Y-%m-%dT%H:%M:%fZ','now'))"
834
- ).run(
835
- "runtime_policy",
836
- input.channel || null,
837
- "internal",
838
- normalizeAgentName(input.agent_name || "") || null,
839
- "runtime_policy_check",
840
- "runtime_policy",
841
- result.policy && result.policy.id ? String(result.policy.id) : result.policy_key,
842
- result.status,
843
- `runtime policy ${result.status}: ${result.agent_name || ""} ${result.project || ""}`.trim(),
844
- safeJson({ missing_context: result.missing_context, required_actions: result.required_actions, full_sync_due: result.full_sync_due }, {}),
845
- safeJson({ input, policy: result.policy, warning_token: result.warning_token || null }, {})
846
- );
847
- return Number(info.lastInsertRowid || 0) || null;
848
- } catch {
849
- return null;
850
- }
851
- }
852
-
853
- function runtimePolicyCheck(db, input = {}) {
854
- ensureRuntimeGovernanceSchema(db);
855
- const policyResult = runtimePolicyGet(db, input);
856
- const policy = policyResult.policy || defaultRuntimePolicy(input);
857
- const staleAfter = intFlag(policy.stale_after_minutes, 15, 1, 10080);
858
- const every = intFlag(policy.full_sync_every_messages, 10, 1, 100000);
859
- const messageCount = intFlag(input.message_count_since_full_sync ?? input.messages_since_full_sync ?? input.message_count, 0, 0, 100000000);
860
- const turnNumber = intFlag(input.turn_number ?? input.message_number, 0, 0, 100000000);
861
- const fullSyncDue = !boolFlag(input.has_full_sync, false) && !boolFlag(input.full_sync_completed, false) && (messageCount >= every || (turnNumber > 0 && turnNumber % every === 0));
862
- const missing = [];
863
- const addMissing = (name, check) => {
864
- if (check.missing) missing.push({ requirement: name, reason: check.reason, age_minutes: check.age_minutes });
865
- };
866
- if (policy.required_brief_pull) addMissing("mem_brief_pull", requirementStale(input, "brief_pull", staleAfter));
867
- if (policy.required_recall) addMissing("mem_recall", requirementStale(input, "recall", staleAfter));
868
- if (policy.required_project_board) addMissing("mem_project_board", requirementStale(input, "project_board", staleAfter));
869
- if (policy.required_chat_sync) addMissing("chat_sync", requirementStale(input, "chat_sync", staleAfter));
870
- if (policy.required_memory_update) addMissing("memory_update", requirementStale(input, "memory_update", staleAfter));
871
- if (policy.required_message_capture) addMissing("message_capture", requirementStale(input, "message_capture", staleAfter));
872
- if (policy.required_board) {
873
- const board = String(input.board || input.project_board || "").trim().toLowerCase();
874
- const requiredBoard = String(policy.required_board || "").trim().toLowerCase();
875
- if (requiredBoard && board && board !== requiredBoard) {
876
- missing.push({ requirement: "required_board", reason: `board mismatch: ${board} != ${requiredBoard}`, expected: policy.required_board, actual: input.board || input.project_board });
877
- } else if (requiredBoard && !board) {
878
- missing.push({ requirement: "required_board", reason: `board ${policy.required_board} not loaded`, expected: policy.required_board });
879
- }
880
- }
881
- if (fullSyncDue) {
882
- missing.push({ requirement: "full_sync_every_messages", reason: `full sync due after ${messageCount || turnNumber} messages`, every });
883
- }
884
- const responseAllowed = missing.length === 0 || !!policy.response_allowed_when_context_missing;
885
- const status = missing.length === 0 ? "ok" : (responseAllowed ? "warn" : "block");
886
- const requiredActions = uniqueStrings(
887
- []
888
- .concat(policy.required_actions || [])
889
- .concat(missing.map((entry) => entry.requirement))
890
- .concat(fullSyncDue ? ["mem_event_log", "chat_sync", "memory_update"] : [])
891
- );
892
- const result = {
893
- ok: responseAllowed,
894
- allowed: responseAllowed,
895
- response_allowed: responseAllowed,
896
- status,
897
- source: policyResult.source,
898
- runtime_name: normalizePolicyRuntime(input.runtime_name || policy.runtime_name || "runtime-a"),
899
- agent_name: normalizePolicyAgent(input.agent_name || policy.agent_name),
900
- channel: normalizePolicyPart(input.channel || policy.channel),
901
- project: normalizePolicyPart(input.project || policy.project),
902
- policy_key: policy.policy_key || normalizePolicyKey(input),
903
- policy,
904
- missing_context: missing,
905
- required_actions: requiredActions,
906
- full_sync_due: fullSyncDue,
907
- full_sync_every_messages: every,
908
- message_count_since_full_sync: messageCount,
909
- warning_token: missing.length && policy.warning_token_required ? "MNEMO_CONTEXT_STALE" : null,
910
- hint: missing.length ? "Run the required Mnemo sync actions before responding, then check this policy again." : "Context is fresh enough to respond."
911
- };
912
- result.audit_id = journalRuntimePolicyCheck(db, input, result);
913
- return result;
914
- }
915
-
916
- function inferActionType(input = {}) {
917
- if (input.action_type) return String(input.action_type);
918
- const text = [input.tool_name, input.tool_kind, input.task, input.summary]
919
- .filter(Boolean)
920
- .join(" ")
921
- .toLowerCase()
922
- .replace(/[_-]+/g, " ");
923
- if (/\b(deploy|pm2|nginx|dns|restart|ssh|scp|rsync)\b/.test(text)) return "deploy";
924
- if (/\b(write|edit|patch|apply|delete|remove|move|rename|create|generate|save)\b/.test(text)) return "code_edit";
925
- if (/\b(send|post|message|email|reply|webhook|api)\b/.test(text)) return "external_comm";
926
- return "read";
927
- }
928
-
929
- function isEvidenceRequired(input = {}) {
930
- if (input.evidence_required != null) return boolFlag(input.evidence_required, false);
931
- const action = inferActionType(input).toLowerCase();
932
- return ["deploy", "code_edit", "write", "delete", "move", "external_comm"].includes(action);
933
- }
934
-
935
- function resourcesFromInput(input = {}) {
936
- return {
937
- files: Array.isArray(input.files) ? input.files : [],
938
- urls: Array.isArray(input.urls) ? input.urls : [],
939
- routes: Array.isArray(input.routes) ? input.routes : [],
940
- domains: Array.isArray(input.domains) ? input.domains : [],
941
- system_names: Array.isArray(input.system_names) ? input.system_names : [],
942
- resources: Array.isArray(input.resources) ? input.resources : [],
943
- };
944
- }
945
-
946
- function runtimeToolReceiptStart(db, input = {}, options = {}) {
947
- ensureRuntimeGovernanceSchema(db);
948
- const runtime = normalizeRuntimeName(input.runtime_name);
949
- const agent = normalizeAgentName(input.agent_name);
950
- const toolName = String(input.tool_name || "").trim();
951
- if (!agent || !toolName) return { error: "agent_name + tool_name required" };
952
- const actionType = inferActionType(input);
953
- const capCheck = runtimeCapabilityCheck(db, Object.assign({}, input, { action_type: actionType }));
954
- const tokenCheck = capabilityTokenCheck(db, Object.assign({}, input, {
955
- action_type: actionType,
956
- tool_name: toolName,
957
- token_id: input.token_id || input.capability_token_id || input.capability_token || "",
958
- }));
959
- const preflight = options.preflight || input.preflight || null;
960
- const preflightStatus = preflight && (preflight.status || (preflight.ok ? "ok" : "block")) || (input.preflight_required === false ? "skipped" : "missing");
961
- let requiredEvidence = uniqueStrings(
962
- normalizeStringList(input.required_evidence || input.requirements)
963
- .concat(preflightRequiredEvidence(preflight))
964
- .concat(normalizeStringList(tokenCheck.required_evidence))
965
- );
966
- const deployPrecheck = String(actionType || "").toLowerCase() === "deploy" ? runtimeDeployPrecheck(input, preflight) : { required: false, ok: true, missing: [] };
967
- if (deployPrecheck.required) requiredEvidence = uniqueStrings(requiredEvidence.concat(DEPLOY_REQUIRED_EVIDENCE));
968
- const blockers = []
969
- .concat(capCheck.blockers || [])
970
- .concat(tokenCheck && !tokenCheck.ok ? ["capability token " + (tokenCheck.reason || "blocked")] : [])
971
- .concat(preflight && Array.isArray(preflight.blockers) ? preflight.blockers : []);
972
- if (input.preflight_required !== false && !preflight) blockers.push("missing Mnemo preflight result");
973
- if (deployPrecheck.required && !deployPrecheck.ok) blockers.push("deploy precheck required before deploy: " + deployPrecheck.missing.join(", "));
974
- const allowed = blockers.length === 0;
975
- const status = allowed ? "started" : "blocked";
976
- const receiptId = input.receipt_id || "rt-" + sha([runtime, agent, toolName, input.request_id || "", nowIso(), Math.random()].join("|")).slice(0, 24);
977
- const evidenceRequired = isEvidenceRequired(Object.assign({}, input, { action_type: actionType }));
978
- const claims = uniqueStrings([])
979
- .concat(Array.isArray(input.claim_ids) ? input.claim_ids.map(String) : [])
980
- .concat(Array.isArray(preflight && preflight.claims) ? preflight.claims.map((claim) => String(claim && (claim.id || claim.claim_id) || "")).filter(Boolean) : []);
981
- const approvals = uniqueStrings(Array.isArray(input.approval_ids) ? input.approval_ids.map(String) : []);
982
- const toolsUsed = uniqueStrings([])
983
- .concat(input.tool_name ? [input.tool_name] : [])
984
- .concat(Array.isArray(input.tools_used) ? input.tools_used : []);
985
- const meta = Object.assign({}, input.meta || {}, {
986
- blockers,
987
- capability_status: capCheck.status,
988
- token_status: tokenCheck.ok ? "ok" : "block",
989
- preflight_status: preflightStatus,
990
- required_evidence: requiredEvidence,
991
- deploy_precheck: deployPrecheck,
992
- request_payload: input.payload || null,
993
- });
994
- db.prepare(
995
- "INSERT INTO runtime_tool_receipt (receipt_id, scope, runtime_name, agent_name, project, task, action_type, tool_name, tool_kind, session_key, channel, request_id, binding_id, connector_system, status, allowed, evidence_required, preflight_status, preflight_action_id, preflight_json, capability_check_json, claim_ids_json, approval_ids_json, resources_json, tools_json, evidence_json, meta_json, started_at) " +
996
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,strftime('%Y-%m-%dT%H:%M:%fZ','now')) " +
997
- "ON CONFLICT(receipt_id) DO UPDATE SET status=excluded.status, allowed=excluded.allowed, preflight_status=excluded.preflight_status, preflight_action_id=excluded.preflight_action_id, preflight_json=excluded.preflight_json, capability_check_json=excluded.capability_check_json, claim_ids_json=excluded.claim_ids_json, approval_ids_json=excluded.approval_ids_json, resources_json=excluded.resources_json, tools_json=excluded.tools_json, meta_json=excluded.meta_json"
998
- ).run(
999
- receiptId,
1000
- scopeName(input.scope),
1001
- runtime,
1002
- agent,
1003
- input.project || null,
1004
- input.task || input.summary || `runtime toolrun ${toolName}`,
1005
- actionType,
1006
- toolName,
1007
- input.tool_kind || null,
1008
- input.session_key || null,
1009
- input.channel || null,
1010
- input.request_id || null,
1011
- input.binding_id || null,
1012
- input.connector_system || null,
1013
- status,
1014
- allowed ? 1 : 0,
1015
- evidenceRequired ? 1 : 0,
1016
- preflightStatus,
1017
- preflight && preflight.preflight_action_id || null,
1018
- safeJson(preflight || {}, {}),
1019
- safeJson(capCheck, {}),
1020
- JSON.stringify(claims),
1021
- JSON.stringify(approvals),
1022
- safeJson(resourcesFromInput(input), {}),
1023
- JSON.stringify(toolsUsed),
1024
- JSON.stringify([]),
1025
- safeJson(meta, {})
1026
- );
1027
- return {
1028
- ok: true,
1029
- receipt_id: receiptId,
1030
- allowed,
1031
- status,
1032
- runtime_name: runtime,
1033
- agent_name: agent,
1034
- preflight_status: preflightStatus,
1035
- preflight_action_id: preflight && preflight.preflight_action_id || null,
1036
- evidence_required: evidenceRequired,
1037
- required_evidence: requiredEvidence,
1038
- blockers,
1039
- warnings: capCheck.warnings || [],
1040
- capability_check: capCheck,
1041
- token_check: tokenCheck,
1042
- hint: allowed ? "Toolrun may proceed. Finish this receipt with mem_runtime_tool_receipt_finish." : "Do not execute the toolrun. Resolve blockers or request approval/claim access."
1043
- };
1044
- }
1045
-
1046
- function runtimeToolReceiptFinish(db, input = {}) {
1047
- ensureRuntimeGovernanceSchema(db);
1048
- const receiptId = String(input.receipt_id || "").trim();
1049
- if (!receiptId) return { error: "receipt_id required" };
1050
- const row = db.prepare("SELECT * FROM runtime_tool_receipt WHERE receipt_id=?").get(receiptId);
1051
- if (!row) return { error: "receipt_not_found", receipt_id: receiptId };
1052
- const status = String(input.status || "done").toLowerCase();
1053
- if (!["done", "failed", "blocked", "cancelled", "skipped"].includes(status)) return { error: "invalid_status", allowed: ["done", "failed", "blocked", "cancelled", "skipped"] };
1054
- if (status === "done" && !row.allowed) {
1055
- return {
1056
- error: "receipt_not_allowed",
1057
- receipt_id: receiptId,
1058
- hint: "A blocked receipt cannot be completed as done. Resolve the gate and open a new allowed receipt."
1059
- };
1060
- }
1061
- const rowMeta = parseJsonField(row.meta_json, {});
1062
- let requiredEvidence = normalizeStringList(rowMeta.required_evidence || []);
1063
- if (String(row.action_type || "").toLowerCase() === "deploy") {
1064
- requiredEvidence = uniqueStrings(requiredEvidence.concat(DEPLOY_REQUIRED_EVIDENCE));
1065
- }
1066
- const evidence = Array.isArray(input.evidence) ? input.evidence : [];
1067
- let evidenceCheck = { ok: true, invalid: [] };
1068
- let handoffEvidence = null;
1069
- if (status === "done" && !!row.evidence_required) {
1070
- if (evidence.length) {
1071
- evidenceCheck = validateRuntimeEvidenceSet(evidence);
1072
- if (!evidenceCheck.ok) {
1073
- return {
1074
- error: evidenceCheck.error,
1075
- receipt_id: receiptId,
1076
- invalid: evidenceCheck.invalid,
1077
- hint: "done requires passing evidence with result/status/exit_code and a concrete command, check, file, URL, or artifact reference."
1078
- };
1079
- }
1080
- } else if (input.handoff_id) {
1081
- handoffEvidence = handoffEvidenceCheck(db, input.handoff_id);
1082
- if (!handoffEvidence.ok) {
1083
- return {
1084
- error: handoffEvidence.error,
1085
- receipt_id: receiptId,
1086
- handoff_id: input.handoff_id,
1087
- invalid: handoffEvidence.invalid || [],
1088
- hint: "Linked handoff must exist and contain passing evidence in meta.evidence."
1089
- };
1090
- }
1091
- } else {
1092
- return {
1093
- error: "evidence_required",
1094
- receipt_id: receiptId,
1095
- hint: "Pass evidence=[{target|url|file_path|server|screenshot_path, test_step, result, timestamp}] or link a handoff_id that contains passing evidence."
1096
- };
1097
- }
1098
- if (requiredEvidence.length) {
1099
- if (!evidence.length) {
1100
- return {
1101
- error: "evidence_required",
1102
- receipt_id: receiptId,
1103
- required_evidence: requiredEvidence,
1104
- missing_required: requiredEvidence,
1105
- hint: "This receipt carries required_evidence from Mnemo preflight. Finish with explicit evidence covering every required item."
1106
- };
1107
- }
1108
- const missing = missingRuntimeRequiredEvidence(evidence, requiredEvidence);
1109
- if (missing.length) {
1110
- return {
1111
- error: "evidence_missing_required",
1112
- receipt_id: receiptId,
1113
- required_evidence: requiredEvidence,
1114
- missing_required: missing,
1115
- hint: "Each required_evidence item from Mnemo preflight must be explicitly covered before status=done."
1116
- };
1117
- }
1118
- evidenceCheck = Object.assign({}, evidenceCheck, { required_evidence: requiredEvidence, missing_required: [] });
1119
- }
1120
- const deployManifest = deployManifestCheck(row, evidence);
1121
- if (!deployManifest.ok) {
1122
- return {
1123
- error: "deploy_manifest_incomplete",
1124
- receipt_id: receiptId,
1125
- missing_required: deployManifest.missing,
1126
- hint: "Deploy completion requires a manifest evidence object with who, what, when, where, and how."
1127
- };
1128
- }
1129
- if (deployManifest.manifest) evidenceCheck = Object.assign({}, evidenceCheck, { deploy_manifest: deployManifest.manifest });
1130
- }
1131
- const shapedEvidence = evidence.map((item) => Object.assign({}, item, { timestamp: item && item.timestamp || nowIso() }));
1132
- const resultSummary = compactContent(input.result_summary || input.summary || input.result || input.error || status, 1200);
1133
- const meta = Object.assign(rowMeta, input.meta || {}, {
1134
- handoff_id: input.handoff_id || null,
1135
- output_ref: input.output_ref || null,
1136
- evidence_check: evidenceCheck,
1137
- handoff_evidence: handoffEvidence,
1138
- });
1139
- db.prepare(
1140
- "UPDATE runtime_tool_receipt SET status=?, evidence_json=?, result_summary=?, result_json=?, error=?, meta_json=?, finished_at=strftime('%Y-%m-%dT%H:%M:%fZ','now') WHERE receipt_id=?"
1141
- ).run(
1142
- status,
1143
- safeJson(shapedEvidence, []),
1144
- resultSummary || null,
1145
- safeJson(input.result_json != null ? input.result_json : input.result, {}),
1146
- input.error || null,
1147
- safeJson(meta, {}),
1148
- receiptId
1149
- );
1150
- return { ok: true, receipt_id: receiptId, status, evidence_count: shapedEvidence.length, handoff_id: input.handoff_id || null, evidence_check: evidenceCheck, handoff_evidence: handoffEvidence, required_evidence: requiredEvidence };
1151
- }
1152
-
1153
- function rowToReceipt(row) {
1154
- return row ? Object.assign({}, row, {
1155
- allowed: !!row.allowed,
1156
- evidence_required: !!row.evidence_required,
1157
- preflight: parseJsonField(row.preflight_json, {}),
1158
- capability_check: parseJsonField(row.capability_check_json, {}),
1159
- claim_ids: parseJsonField(row.claim_ids_json, []),
1160
- approval_ids: parseJsonField(row.approval_ids_json, []),
1161
- resources: parseJsonField(row.resources_json, {}),
1162
- tools_used: parseJsonField(row.tools_json, []),
1163
- evidence: parseJsonField(row.evidence_json, []),
1164
- result: parseJsonField(row.result_json, {}),
1165
- meta: parseJsonField(row.meta_json, {}),
1166
- }) : null;
1167
- }
1168
-
1169
- function runtimeToolReceiptList(db, input = {}) {
1170
- ensureRuntimeGovernanceSchema(db);
1171
- const where = ["scope=?"];
1172
- const params = [scopeName(input.scope)];
1173
- if (input.runtime_name) { where.push("runtime_name=?"); params.push(normalizeRuntimeName(input.runtime_name)); }
1174
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
1175
- if (input.project) { where.push("project=?"); params.push(input.project); }
1176
- if (input.status) { where.push("status=?"); params.push(input.status); }
1177
- if (input.session_key) { where.push("session_key=?"); params.push(input.session_key); }
1178
- if (input.tool_name) { where.push("tool_name=?"); params.push(input.tool_name); }
1179
- params.push(Math.min(Math.max(parseInt(input.limit || 100, 10) || 100, 1), 500));
1180
- const rows = db.prepare("SELECT * FROM runtime_tool_receipt WHERE " + where.join(" AND ") + " ORDER BY started_at DESC LIMIT ?").all(...params).map(rowToReceipt);
1181
- return { ok: true, count: rows.length, receipts: rows };
1182
- }
1183
-
1184
- const RUNTIME_GOVERNANCE_TOOL_DEFS = {
1185
- mem_runtime_binding_upsert: {
1186
- description: "Register or update an external runtime/session/channel binding so runtime gateway-like gateways map to one Mnemo agent, project, connector, and capability set.",
1187
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, binding_key: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, session_key: { type: "string" }, channel: { type: "string" }, account_id: { type: "string" }, peer_kind: { type: "string" }, peer_id: { type: "string" }, workspace: { type: "string" }, mode: { type: "string" }, connector_system: { type: "string" }, capabilities: { anyOf: [{ type: "array", items: { type: "string" } }, { type: "string" }] }, status: { type: "string" }, source_ref: { type: "string" }, meta: { type: "object" }, updated_by: { type: "string" } }, required: ["runtime_name"] }
1188
- },
1189
- mem_runtime_binding_list: {
1190
- description: "List external runtime/session/channel bindings.",
1191
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, session_key: { type: "string" }, channel: { type: "string" }, status: { type: "string" }, limit: { type: "integer" } } }
1192
- },
1193
- mem_runtime_capability_upsert: {
1194
- description: "Register a runtime, channel, or tool capability with allow/deny, agent allowlist, risk class, and receipt/preflight requirements.",
1195
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, capability_ref: { type: "string" }, capability_kind: { type: "string" }, capability_key: { type: "string" }, tool_name: { type: "string" }, agent_name: { type: "string" }, channel: { type: "string" }, permission: { type: "string" }, risk_class: { type: "string" }, requires_preflight: { type: "boolean" }, requires_receipt: { type: "boolean" }, enabled: { type: "boolean" }, allowed_agents: { anyOf: [{ type: "array", items: { type: "string" } }, { type: "string" }] }, status: { type: "string" }, notes: { type: "string" }, source_ref: { type: "string" }, meta: { type: "object" }, updated_by: { type: "string" } }, required: ["runtime_name"] }
1196
- },
1197
- mem_runtime_capability_list: {
1198
- description: "List runtime/channel/tool capabilities and their preflight/receipt requirements.",
1199
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, capability_kind: { type: "string" }, capability_key: { type: "string" }, agent_name: { type: "string" }, channel: { type: "string" }, status: { type: "string" }, limit: { type: "integer" } } }
1200
- },
1201
- mem_runtime_capability_check: {
1202
- description: "Check whether an external runtime tool/capability is allowed for an agent before execution.",
1203
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, agent_name: { type: "string" }, channel: { type: "string" }, tool_name: { type: "string" }, tool_kind: { type: "string" }, capabilities: { anyOf: [{ type: "array", items: { type: "string" } }, { type: "string" }] }, require_registered_capability: { type: "boolean" } }, required: ["runtime_name", "agent_name"] }
1204
- },
1205
- mem_runtime_policy_set: {
1206
- description: "Set an adapter/runtime response policy for an agent/channel/project, including mandatory Mnemo context sync, stale limits, and every-N-message full sync cadence.",
1207
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, agent_name: { type: "string" }, channel: { type: "string" }, project: { type: "string" }, policy_key: { type: "string" }, required_brief_pull: { type: "boolean" }, required_recall: { type: "boolean" }, required_project_board: { type: "boolean" }, required_chat_sync: { type: "boolean" }, required_memory_update: { type: "boolean" }, required_message_capture: { type: "boolean" }, required_board: { type: "string" }, stale_after_minutes: { type: "integer" }, full_sync_every_messages: { type: "integer" }, response_allowed_when_context_missing: { type: "boolean" }, warning_token_required: { type: "boolean" }, required_actions: { anyOf: [{ type: "array", items: { type: "string" } }, { type: "string" }] }, status: { type: "string" }, meta: { type: "object" }, updated_by: { type: "string" } } }
1208
- },
1209
- mem_runtime_policy_get: {
1210
- description: "Return the effective runtime response policy for an agent/channel/project, falling back to built-in defaults when no stored policy exists.",
1211
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, agent_name: { type: "string" }, channel: { type: "string" }, project: { type: "string" } } }
1212
- },
1213
- mem_runtime_policy_check: {
1214
- description: "Check whether a runtime/agent is allowed to answer now, enforcing stale Mnemo context, project-board load, chat/memory sync, and every-N-message full sync. Writes an audit event and returns audit_id.",
1215
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, agent_name: { type: "string" }, channel: { type: "string" }, project: { type: "string" }, board: { type: "string" }, project_board: { type: "string" }, message_count_since_full_sync: { type: "integer" }, messages_since_full_sync: { type: "integer" }, turn_number: { type: "integer" }, has_full_sync: { type: "boolean" }, full_sync_completed: { type: "boolean" }, has_brief_pull: { type: "boolean" }, has_recall: { type: "boolean" }, has_project_board: { type: "boolean" }, has_chat_sync: { type: "boolean" }, has_memory_update: { type: "boolean" }, has_message_capture: { type: "boolean" }, brief_pull_at: { type: "string" }, recall_at: { type: "string" }, project_board_at: { type: "string" }, chat_sync_at: { type: "string" }, memory_update_at: { type: "string" }, message_capture_at: { type: "string" }, minutes_since_brief_pull: { type: "number" }, minutes_since_recall: { type: "number" }, minutes_since_project_board: { type: "number" }, minutes_since_chat_sync: { type: "number" }, minutes_since_memory_update: { type: "number" }, minutes_since_message_capture: { type: "number" }, message_ref: { type: "string" }, session_key: { type: "string" }, meta: { type: "object" } } }
1216
- },
1217
- mem_runtime_tool_receipt_start: {
1218
- description: "Open a Mnemo receipt for an external runtime toolrun. This must run before runtime gateway-like tool execution and stores the preflight result, capability gate, claims, approvals, resources, and receipt id.",
1219
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, task: { type: "string" }, summary: { type: "string" }, action_type: { type: "string" }, tool_name: { type: "string" }, tool_kind: { type: "string" }, session_key: { type: "string" }, channel: { type: "string" }, request_id: { type: "string" }, binding_id: { type: "integer" }, connector_system: { type: "string" }, token_id: { type: "string" }, capability_token_id: { type: "string" }, work_order_id: { type: "integer" }, files: { type: "array", items: { type: "string" } }, urls: { type: "array", items: { type: "string" } }, routes: { type: "array", items: { type: "string" } }, domains: { type: "array", items: { type: "string" } }, system_names: { type: "array", items: { type: "string" } }, resources: { type: "array", items: { type: "object" } }, capabilities: { anyOf: [{ type: "array", items: { type: "string" } }, { type: "string" }] }, claim_ids: { type: "array", items: { type: "string" } }, approval_ids: { type: "array", items: { type: "string" } }, evidence: { type: "array", items: { type: "object" } }, predeploy_evidence: { type: "array", items: { type: "object" } }, deploy_precheck_evidence: { type: "array", items: { type: "object" } }, evidence_required: { type: "boolean" }, preflight_required: { type: "boolean" }, require_project_rules: { type: "boolean" }, require_registered_capability: { type: "boolean" }, payload: { type: "object" }, meta: { type: "object" } }, required: ["runtime_name", "agent_name", "tool_name"] }
1220
- },
1221
- mem_runtime_tool_receipt_finish: {
1222
- description: "Finish an external runtime toolrun receipt with result, error, evidence, output reference, and optional handoff link.",
1223
- inputSchema: { type: "object", properties: { receipt_id: { type: "string" }, status: { type: "string" }, result_summary: { type: "string" }, summary: { type: "string" }, result: {}, result_json: { type: "object" }, error: { type: "string" }, evidence: { type: "array", items: { type: "object" } }, output_ref: { type: "string" }, handoff_id: { type: "integer" }, meta: { type: "object" } }, required: ["receipt_id"] }
1224
- },
1225
- mem_runtime_tool_receipt_list: {
1226
- description: "List external runtime tool receipts with preflight, capability, evidence, and result state.",
1227
- inputSchema: { type: "object", properties: { scope: { type: "string" }, runtime_name: { type: "string" }, agent_name: { type: "string" }, project: { type: "string" }, status: { type: "string" }, session_key: { type: "string" }, tool_name: { type: "string" }, limit: { type: "integer" } } }
1228
- }
1229
- };
1230
-
1231
- function handleRuntimeGovernanceTool(db, name, input = {}) {
1232
- if (name === "mem_runtime_binding_upsert") return { handled: true, result: bindingUpsert(db, input || {}) };
1233
- if (name === "mem_runtime_binding_list") return { handled: true, result: bindingList(db, input || {}) };
1234
- if (name === "mem_runtime_capability_upsert") return { handled: true, result: capabilityUpsert(db, input || {}) };
1235
- if (name === "mem_runtime_capability_list") return { handled: true, result: capabilityList(db, input || {}) };
1236
- if (name === "mem_runtime_capability_check") return { handled: true, result: runtimeCapabilityCheck(db, input || {}) };
1237
- if (name === "mem_runtime_policy_set") return { handled: true, result: runtimePolicySet(db, input || {}) };
1238
- if (name === "mem_runtime_policy_get") return { handled: true, result: runtimePolicyGet(db, input || {}) };
1239
- if (name === "mem_runtime_policy_check") return { handled: true, result: runtimePolicyCheck(db, input || {}) };
1240
- if (name === "mem_runtime_tool_receipt_start") return { handled: true, result: runtimeToolReceiptStart(db, input || {}) };
1241
- if (name === "mem_runtime_tool_receipt_finish") return { handled: true, result: runtimeToolReceiptFinish(db, input || {}) };
1242
- if (name === "mem_runtime_tool_receipt_list") return { handled: true, result: runtimeToolReceiptList(db, input || {}) };
1243
- return { handled: false };
1244
- }
1245
-
1246
- module.exports = {
1247
- RUNTIME_GOVERNANCE_TOOL_DEFS,
1248
- ensureRuntimeGovernanceSchema,
1249
- handleRuntimeGovernanceTool,
1250
- runtimeToolReceiptStart,
1251
- runtimeToolReceiptFinish,
1252
- runtimeCapabilityCheck,
1253
- runtimePolicySet,
1254
- runtimePolicyGet,
1255
- runtimePolicyCheck,
1256
- };