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,684 +0,0 @@
1
- "use strict";
2
-
3
- const DEFAULT_SCOPE = "default";
4
- const WRITE_PERMISSIONS = new Set(["write", "execute", "deploy", "approve", "own"]);
5
-
6
- function cleanScope(scope) {
7
- return String(scope || DEFAULT_SCOPE).toLowerCase().replace(/[^a-z0-9_-]/g, "") || DEFAULT_SCOPE;
8
- }
9
-
10
- function normalizeAgentName(name) {
11
- return String(name || "").trim().toLowerCase();
12
- }
13
-
14
- function parseJson(value, fallback) {
15
- if (value == null || value === "") return fallback;
16
- if (typeof value !== "string") return value;
17
- try { return JSON.parse(value); } catch { return fallback; }
18
- }
19
-
20
- function normalizeResourceKind(kind) {
21
- const value = String(kind || "scope")
22
- .trim()
23
- .toLowerCase()
24
- .replace(/[^a-z0-9]+/g, "_")
25
- .replace(/^_+|_+$/g, "");
26
- return value || "scope";
27
- }
28
-
29
- function normalizeResourceKey(kind, key) {
30
- const k = normalizeResourceKind(kind);
31
- const raw = String(key || "").trim().replace(/\\/g, "/");
32
- if (!raw) return "";
33
- if (k === "file") return raw.toLowerCase();
34
- if (k === "domain") return raw.toLowerCase().replace(/^https?:\/\//, "").replace(/\/+$/, "");
35
- if (k === "route") return raw.startsWith("/") ? raw.toLowerCase() : "/" + raw.toLowerCase();
36
- return raw.toLowerCase().replace(/\s+/g, " ").trim();
37
- }
38
-
39
- function permissionRank(permission) {
40
- const p = String(permission || "read").toLowerCase();
41
- if (p === "own") return 50;
42
- if (p === "approve") return 40;
43
- if (p === "deploy" || p === "execute") return 30;
44
- if (p === "write") return 20;
45
- return 10;
46
- }
47
-
48
- function requiredPermission(input = {}) {
49
- const action = String(input.action_type || "").toLowerCase();
50
- if (action === "deploy") return "deploy";
51
- if (["code_edit", "write", "delete", "move"].includes(action)) return "write";
52
- if (action === "external_comm") return "execute";
53
- return "read";
54
- }
55
-
56
- function isWriteLike(input = {}) {
57
- return WRITE_PERMISSIONS.has(requiredPermission(input));
58
- }
59
-
60
- function ensureResourceAccessSchema(db) {
61
- db.exec(`
62
- CREATE TABLE IF NOT EXISTS org_resource (
63
- id INTEGER PRIMARY KEY AUTOINCREMENT,
64
- scope TEXT NOT NULL DEFAULT 'default',
65
- project TEXT,
66
- resource_kind TEXT NOT NULL,
67
- resource_key TEXT NOT NULL,
68
- label TEXT,
69
- owner_agent TEXT,
70
- owning_department TEXT,
71
- risk_class TEXT NOT NULL DEFAULT 'normal',
72
- status TEXT NOT NULL DEFAULT 'active',
73
- notes TEXT,
74
- meta_json TEXT,
75
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
76
- updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
77
- UNIQUE(scope, resource_kind, resource_key)
78
- );
79
- CREATE INDEX IF NOT EXISTS idx_org_resource_owner ON org_resource(owner_agent, status);
80
- CREATE INDEX IF NOT EXISTS idx_org_resource_project ON org_resource(project, status);
81
-
82
- CREATE TABLE IF NOT EXISTS resource_acl (
83
- id INTEGER PRIMARY KEY AUTOINCREMENT,
84
- scope TEXT NOT NULL DEFAULT 'default',
85
- project TEXT,
86
- resource_kind TEXT NOT NULL,
87
- resource_key TEXT NOT NULL,
88
- agent_name TEXT,
89
- department_name TEXT,
90
- permission TEXT NOT NULL DEFAULT 'read',
91
- status TEXT NOT NULL DEFAULT 'active',
92
- granted_by TEXT,
93
- reason TEXT,
94
- claim_id INTEGER,
95
- approval_id INTEGER,
96
- expires_at TEXT,
97
- meta_json TEXT,
98
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
99
- updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
100
- );
101
- CREATE INDEX IF NOT EXISTS idx_resource_acl_lookup ON resource_acl(scope, resource_kind, resource_key, status);
102
- CREATE INDEX IF NOT EXISTS idx_resource_acl_agent ON resource_acl(agent_name, status, expires_at);
103
-
104
- CREATE TABLE IF NOT EXISTS approval_request (
105
- id INTEGER PRIMARY KEY AUTOINCREMENT,
106
- scope TEXT NOT NULL DEFAULT 'default',
107
- project TEXT,
108
- request_kind TEXT NOT NULL DEFAULT 'resource_access',
109
- resource_kind TEXT NOT NULL,
110
- resource_key TEXT NOT NULL,
111
- permission TEXT NOT NULL DEFAULT 'write',
112
- requester_agent TEXT NOT NULL,
113
- owner_agent TEXT,
114
- approver_agent TEXT,
115
- status TEXT NOT NULL DEFAULT 'pending',
116
- reason TEXT NOT NULL,
117
- decision TEXT,
118
- decided_by TEXT,
119
- requested_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
120
- decided_at TEXT,
121
- expires_at TEXT,
122
- claim_id INTEGER,
123
- meta_json TEXT
124
- );
125
- CREATE INDEX IF NOT EXISTS idx_approval_status ON approval_request(scope, status, requested_at DESC);
126
- CREATE INDEX IF NOT EXISTS idx_approval_owner ON approval_request(owner_agent, status, requested_at DESC);
127
- CREATE INDEX IF NOT EXISTS idx_approval_resource ON approval_request(scope, resource_kind, resource_key, status);
128
-
129
- CREATE TABLE IF NOT EXISTS resource_audit_log (
130
- id INTEGER PRIMARY KEY AUTOINCREMENT,
131
- scope TEXT NOT NULL DEFAULT 'default',
132
- project TEXT,
133
- event_kind TEXT NOT NULL,
134
- actor_agent TEXT,
135
- resource_kind TEXT,
136
- resource_key TEXT,
137
- permission TEXT,
138
- claim_id INTEGER,
139
- approval_id INTEGER,
140
- tool_name TEXT,
141
- reason TEXT,
142
- result TEXT,
143
- payload_json TEXT,
144
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
145
- );
146
- CREATE INDEX IF NOT EXISTS idx_resource_audit_resource ON resource_audit_log(scope, resource_kind, resource_key, created_at DESC);
147
- CREATE INDEX IF NOT EXISTS idx_resource_audit_actor ON resource_audit_log(actor_agent, created_at DESC);
148
- `);
149
- }
150
-
151
- function ensureWorkClaimSchemaForLookup(db) {
152
- db.exec(`
153
- CREATE TABLE IF NOT EXISTS work_claim (
154
- id INTEGER PRIMARY KEY AUTOINCREMENT,
155
- project TEXT NOT NULL,
156
- file_path TEXT NOT NULL,
157
- agent_name TEXT NOT NULL,
158
- summary TEXT,
159
- claim_kind TEXT NOT NULL DEFAULT 'file',
160
- scope_value TEXT,
161
- scope_key TEXT,
162
- claimed_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
163
- heartbeat_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
164
- stale_after_sec INTEGER NOT NULL DEFAULT 1800,
165
- expires_at TEXT NOT NULL,
166
- status TEXT NOT NULL DEFAULT 'active',
167
- released_at TEXT,
168
- takeover_count INTEGER NOT NULL DEFAULT 0,
169
- meta_json TEXT
170
- );
171
- CREATE INDEX IF NOT EXISTS idx_work_claim_scope_active ON work_claim(project, scope_key, status, expires_at);
172
- CREATE INDEX IF NOT EXISTS idx_work_claim_agent_status ON work_claim(agent_name, status, claimed_at DESC);
173
- `);
174
- }
175
-
176
- function audit(db, input = {}) {
177
- ensureResourceAccessSchema(db);
178
- try {
179
- db.prepare("INSERT INTO resource_audit_log (scope, project, event_kind, actor_agent, resource_kind, resource_key, permission, claim_id, approval_id, tool_name, reason, result, payload_json) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)")
180
- .run(cleanScope(input.scope), input.project || null, input.event_kind || "event", normalizeAgentName(input.actor_agent), input.resource_kind || null, input.resource_key || null, input.permission || null, input.claim_id || null, input.approval_id || null, input.tool_name || null, input.reason || null, input.result || null, JSON.stringify(input.payload || {}));
181
- } catch {}
182
- }
183
-
184
- function rowToResource(row) {
185
- return row ? Object.assign({}, row, { meta: parseJson(row.meta_json, {}) }) : null;
186
- }
187
-
188
- function rowToAcl(row) {
189
- return row ? Object.assign({}, row, { meta: parseJson(row.meta_json, {}) }) : null;
190
- }
191
-
192
- function rowToApproval(row) {
193
- return row ? Object.assign({}, row, { meta: parseJson(row.meta_json, {}) }) : null;
194
- }
195
-
196
- function resourceUpsert(db, input = {}) {
197
- ensureResourceAccessSchema(db);
198
- const scope = cleanScope(input.scope);
199
- const kind = normalizeResourceKind(input.resource_kind);
200
- const key = normalizeResourceKey(kind, input.resource_key || input.file_path || input.route || input.domain || input.system_name);
201
- if (!key) return { error: "resource_kind + resource_key required" };
202
- const owner = normalizeAgentName(input.owner_agent);
203
- db.prepare(
204
- "INSERT INTO org_resource (scope, project, resource_kind, resource_key, label, owner_agent, owning_department, risk_class, status, notes, meta_json) " +
205
- "VALUES (?,?,?,?,?,?,?,?,?,?,?) " +
206
- "ON CONFLICT(scope, resource_kind, resource_key) DO UPDATE SET project=excluded.project, label=excluded.label, owner_agent=excluded.owner_agent, owning_department=excluded.owning_department, risk_class=excluded.risk_class, status=excluded.status, notes=excluded.notes, meta_json=excluded.meta_json, updated_at=strftime('%Y-%m-%dT%H:%M:%fZ','now')"
207
- ).run(scope, input.project || null, kind, key, input.label || key, owner || null, input.owning_department || null, input.risk_class || "normal", input.status || "active", input.notes || null, JSON.stringify(input.meta || {}));
208
- audit(db, { scope, project: input.project, event_kind: "resource_upsert", actor_agent: input.updated_by || owner, resource_kind: kind, resource_key: key, result: "ok", payload: input });
209
- return { ok: true, scope, resource_kind: kind, resource_key: key, owner_agent: owner || null };
210
- }
211
-
212
- function resourceList(db, input = {}) {
213
- ensureResourceAccessSchema(db);
214
- const where = ["scope=?"];
215
- const params = [cleanScope(input.scope)];
216
- if (input.project) { where.push("project=?"); params.push(input.project); }
217
- if (input.resource_kind) { where.push("resource_kind=?"); params.push(normalizeResourceKind(input.resource_kind)); }
218
- if (input.owner_agent) { where.push("owner_agent=?"); params.push(normalizeAgentName(input.owner_agent)); }
219
- if (input.status) { where.push("status=?"); params.push(input.status); }
220
- else where.push("status!='deleted'");
221
- params.push(Math.min(Math.max(parseInt(input.limit || 100, 10) || 100, 1), 500));
222
- const rows = db.prepare("SELECT * FROM org_resource WHERE " + where.join(" AND ") + " ORDER BY updated_at DESC LIMIT ?").all(...params).map(rowToResource);
223
- return { ok: true, count: rows.length, resources: rows };
224
- }
225
-
226
- function getResource(db, scope, kind, key, project) {
227
- ensureResourceAccessSchema(db);
228
- return rowToResource(db.prepare(
229
- "SELECT * FROM org_resource WHERE scope=? AND resource_kind=? AND resource_key=? AND status='active' AND (project IS NULL OR project=? OR ? IS NULL) ORDER BY project DESC, id DESC LIMIT 1"
230
- ).get(cleanScope(scope), normalizeResourceKind(kind), normalizeResourceKey(kind, key), project || null, project || null));
231
- }
232
-
233
- function executiveAgents() {
234
- return new Set(String(process.env.MNEMO_EXECUTIVE_AGENTS || "")
235
- .split(",")
236
- .map(normalizeAgentName)
237
- .filter(Boolean));
238
- }
239
-
240
- function canGrantResource(resource, grantedBy) {
241
- const grantor = normalizeAgentName(grantedBy);
242
- if (!resource || !resource.owner_agent) return !!grantor;
243
- if (normalizeAgentName(resource.owner_agent) === grantor) return true;
244
- return process.env.MNEMO_ALLOW_EXECUTIVE_RESOURCE_OVERRIDE === "1" && executiveAgents().has(grantor);
245
- }
246
-
247
- function aclGrant(db, input = {}) {
248
- ensureResourceAccessSchema(db);
249
- const scope = cleanScope(input.scope);
250
- const kind = normalizeResourceKind(input.resource_kind);
251
- const key = normalizeResourceKey(kind, input.resource_key || input.file_path || input.route || input.domain || input.system_name);
252
- const agent = normalizeAgentName(input.agent_name);
253
- const permission = String(input.permission || "write").toLowerCase();
254
- if (!key || (!agent && !input.department_name)) return { error: "resource + agent_name/department_name required" };
255
- if (input.claim_id) {
256
- const claim = claimRow(db, input.claim_id);
257
- if (!claim) return { error: "claim_not_found", claim_id: input.claim_id };
258
- const claimOwner = normalizeAgentName(claim.agent_name);
259
- const grantor = normalizeAgentName(input.granted_by);
260
- if (claimOwner !== grantor) {
261
- return { error: "claim_owner_required", required_granted_by: claimOwner, provided_granted_by: grantor || null };
262
- }
263
- }
264
- const resource = getResource(db, scope, kind, key, input.project);
265
- if (resource && !canGrantResource(resource, input.granted_by)) {
266
- return {
267
- error: "resource_owner_approval_required",
268
- required_granted_by: resource.owner_agent,
269
- provided_granted_by: normalizeAgentName(input.granted_by) || null,
270
- resource
271
- };
272
- }
273
- db.prepare(
274
- "INSERT INTO resource_acl (scope, project, resource_kind, resource_key, agent_name, department_name, permission, status, granted_by, reason, claim_id, approval_id, expires_at, meta_json) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
275
- ).run(scope, input.project || null, kind, key, agent || null, input.department_name || null, permission, input.status || "active", normalizeAgentName(input.granted_by) || null, input.reason || null, input.claim_id || null, input.approval_id || null, input.expires_at || null, JSON.stringify(input.meta || {}));
276
- audit(db, { scope, project: input.project, event_kind: "acl_grant", actor_agent: input.granted_by, resource_kind: kind, resource_key: key, permission, claim_id: input.claim_id || null, approval_id: input.approval_id || null, reason: input.reason || null, result: "ok", payload: input });
277
- return { ok: true, scope, resource_kind: kind, resource_key: key, agent_name: agent || null, permission };
278
- }
279
-
280
- function aclList(db, input = {}) {
281
- ensureResourceAccessSchema(db);
282
- const where = ["scope=?"];
283
- const params = [cleanScope(input.scope)];
284
- if (input.project) { where.push("(project=? OR project IS NULL)"); params.push(input.project); }
285
- if (input.resource_kind) { where.push("resource_kind=?"); params.push(normalizeResourceKind(input.resource_kind)); }
286
- if (input.resource_key) { where.push("resource_key=?"); params.push(normalizeResourceKey(input.resource_kind, input.resource_key)); }
287
- if (input.agent_name) { where.push("agent_name=?"); params.push(normalizeAgentName(input.agent_name)); }
288
- if (input.status) { where.push("status=?"); params.push(input.status); }
289
- else where.push("status='active'");
290
- params.push(Math.min(Math.max(parseInt(input.limit || 100, 10) || 100, 1), 500));
291
- const rows = db.prepare("SELECT * FROM resource_acl WHERE " + where.join(" AND ") + " ORDER BY created_at DESC LIMIT ?").all(...params).map(rowToAcl);
292
- return { ok: true, count: rows.length, acl: rows };
293
- }
294
-
295
- function activeAclRows(db, input = {}) {
296
- ensureResourceAccessSchema(db);
297
- const scope = cleanScope(input.scope);
298
- const agent = normalizeAgentName(input.agent_name);
299
- const kind = normalizeResourceKind(input.resource_kind);
300
- const key = normalizeResourceKey(kind, input.resource_key);
301
- const permissionNeeded = input.permission || "read";
302
- if (!agent || !key) return [];
303
- return db.prepare(
304
- "SELECT * FROM resource_acl WHERE scope=? AND resource_kind=? AND resource_key=? AND agent_name=? AND status='active' " +
305
- "AND (project IS NULL OR project=? OR ? IS NULL) " +
306
- "AND (expires_at IS NULL OR expires_at >= strftime('%Y-%m-%dT%H:%M:%fZ','now')) " +
307
- "ORDER BY created_at DESC"
308
- ).all(scope, kind, key, agent, input.project || null, input.project || null)
309
- .filter((row) => permissionRank(row.permission) >= permissionRank(permissionNeeded))
310
- .map(rowToAcl);
311
- }
312
-
313
- function activeApprovalRows(db, input = {}) {
314
- ensureResourceAccessSchema(db);
315
- const scope = cleanScope(input.scope);
316
- const agent = normalizeAgentName(input.agent_name);
317
- const kind = normalizeResourceKind(input.resource_kind);
318
- const key = normalizeResourceKey(kind, input.resource_key);
319
- const permissionNeeded = input.permission || "read";
320
- if (!agent || !key) return [];
321
- return db.prepare(
322
- "SELECT * FROM approval_request WHERE scope=? AND resource_kind=? AND resource_key=? AND requester_agent=? AND status='approved' " +
323
- "AND (project IS NULL OR project=? OR ? IS NULL) " +
324
- "AND (expires_at IS NULL OR expires_at >= strftime('%Y-%m-%dT%H:%M:%fZ','now')) " +
325
- "ORDER BY decided_at DESC"
326
- ).all(scope, kind, key, agent, input.project || null, input.project || null)
327
- .filter((row) => permissionRank(row.permission) >= permissionRank(permissionNeeded))
328
- .map(rowToApproval);
329
- }
330
-
331
- function resourcesFromInput(input = {}) {
332
- const out = [];
333
- for (const file of Array.isArray(input.files) ? input.files : []) {
334
- const key = normalizeResourceKey("file", file);
335
- if (key) out.push({ resource_kind: "file", resource_key: key, label: file });
336
- }
337
- for (const route of Array.isArray(input.routes) ? input.routes : []) {
338
- const key = normalizeResourceKey("route", route);
339
- if (key) out.push({ resource_kind: "route", resource_key: key, label: route });
340
- }
341
- for (const domain of Array.isArray(input.domains) ? input.domains : []) {
342
- const key = normalizeResourceKey("domain", domain);
343
- if (key) out.push({ resource_kind: "domain", resource_key: key, label: domain });
344
- }
345
- for (const system of Array.isArray(input.system_names) ? input.system_names : []) {
346
- const key = normalizeResourceKey("system", system);
347
- if (key) out.push({ resource_kind: "system", resource_key: key, label: system });
348
- }
349
- for (const res of Array.isArray(input.resources) ? input.resources : []) {
350
- const kind = normalizeResourceKind(res && res.resource_kind);
351
- const key = normalizeResourceKey(kind, res && res.resource_key);
352
- if (key) out.push({ resource_kind: kind, resource_key: key, label: res.label || key });
353
- }
354
- const seen = new Set();
355
- return out.filter((resource) => {
356
- const k = resource.resource_kind + ":" + resource.resource_key;
357
- if (seen.has(k)) return false;
358
- seen.add(k);
359
- return true;
360
- });
361
- }
362
-
363
- function workClaimScopeKey(kind, key) {
364
- if (kind === "file") return "file:" + normalizeResourceKey("file", key);
365
- return kind + ":" + normalizeResourceKey(kind, key).replace(/[^a-z0-9]+/g, " ").trim();
366
- }
367
-
368
- function activeWorkClaimForResource(db, input = {}) {
369
- ensureWorkClaimSchemaForLookup(db);
370
- const key = workClaimScopeKey(normalizeResourceKind(input.resource_kind), input.resource_key);
371
- return db.prepare(
372
- "SELECT * FROM work_claim WHERE scope_key=? AND status='active' AND expires_at >= strftime('%Y-%m-%dT%H:%M:%fZ','now') " +
373
- "AND (project=? OR project='unknown' OR project='*' OR ? IS NULL) ORDER BY expires_at DESC LIMIT 1"
374
- ).get(key, input.project || "unknown", input.project || null) || null;
375
- }
376
-
377
- function resourceAccessCheck(db, input = {}) {
378
- ensureResourceAccessSchema(db);
379
- const scope = cleanScope(input.scope);
380
- const agent = normalizeAgentName(input.agent_name);
381
- const project = input.project || null;
382
- const permission = input.permission || requiredPermission(input);
383
- const writeLike = isWriteLike(Object.assign({}, input, { permission }));
384
- const blockers = [];
385
- const warnings = [];
386
- const checks = [];
387
- const resources = resourcesFromInput(input);
388
-
389
- for (const resourceRef of resources) {
390
- const resource = getResource(db, scope, resourceRef.resource_kind, resourceRef.resource_key, project);
391
- const activeClaim = activeWorkClaimForResource(db, Object.assign({}, resourceRef, { project }));
392
- const claimOwner = activeClaim ? normalizeAgentName(activeClaim.agent_name) : null;
393
- const acl = activeAclRows(db, Object.assign({}, resourceRef, { scope, project, agent_name: agent, permission }));
394
- const approvals = activeApprovalRows(db, Object.assign({}, resourceRef, { scope, project, agent_name: agent, permission }));
395
- const owner = normalizeAgentName(resource && resource.owner_agent);
396
- const ownerOk = owner && owner === agent;
397
- const claimOk = !activeClaim || claimOwner === agent || acl.some((row) => Number(row.claim_id || 0) === Number(activeClaim.id || 0)) || approvals.some((row) => Number(row.claim_id || 0) === Number(activeClaim.id || 0));
398
- const resourceManaged = !!resource || !!activeClaim || acl.length > 0;
399
- const ok = !resourceManaged || ownerOk || acl.length > 0 || approvals.length > 0;
400
- checks.push({
401
- resource: resourceRef,
402
- managed: resourceManaged,
403
- owner_agent: owner || null,
404
- active_claim: activeClaim ? { id: activeClaim.id, agent_name: activeClaim.agent_name, expires_at: activeClaim.expires_at } : null,
405
- acl_count: acl.length,
406
- approval_count: approvals.length,
407
- owner_ok: !!ownerOk,
408
- access_ok: !!ok,
409
- claim_ok: !!claimOk
410
- });
411
- if (!writeLike) {
412
- if (resourceManaged && !ok) warnings.push("resource managed by " + (owner || claimOwner || "another agent") + ": " + resourceRef.resource_kind + ":" + resourceRef.resource_key);
413
- continue;
414
- }
415
- if (activeClaim && claimOwner !== agent && !claimOk) {
416
- blockers.push("resource is actively claimed by " + claimOwner + ": " + resourceRef.resource_kind + ":" + resourceRef.resource_key + "; request claim access or transfer before writing.");
417
- continue;
418
- }
419
- if (resourceManaged && !ok) {
420
- blockers.push("resource access denied for " + agent + ": " + resourceRef.resource_kind + ":" + resourceRef.resource_key + " requires owner/ACL/approval from " + (owner || claimOwner || "resource owner") + ".");
421
- }
422
- }
423
-
424
- const status = blockers.length ? "block" : (warnings.length ? "warn" : "ok");
425
- return {
426
- ok: !blockers.length,
427
- status,
428
- scope,
429
- project,
430
- agent_name: agent,
431
- permission,
432
- write_like: writeLike,
433
- resources_checked: resources.length,
434
- blockers,
435
- warnings,
436
- checks,
437
- hint: blockers.length ? "Request access, get owner approval, or transfer the claim before editing." : "Resource access gate passed."
438
- };
439
- }
440
-
441
- function approvalRequest(db, input = {}) {
442
- ensureResourceAccessSchema(db);
443
- const scope = cleanScope(input.scope);
444
- const kind = normalizeResourceKind(input.resource_kind);
445
- const key = normalizeResourceKey(kind, input.resource_key || input.file_path || input.route || input.domain || input.system_name);
446
- const requester = normalizeAgentName(input.requester_agent || input.agent_name);
447
- if (!key || !requester || !input.reason) return { error: "resource + requester_agent + reason required" };
448
- const resource = getResource(db, scope, kind, key, input.project);
449
- const owner = normalizeAgentName(input.owner_agent || (resource && resource.owner_agent));
450
- const info = db.prepare(
451
- "INSERT INTO approval_request (scope, project, request_kind, resource_kind, resource_key, permission, requester_agent, owner_agent, approver_agent, status, reason, expires_at, claim_id, meta_json) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
452
- ).run(scope, input.project || null, input.request_kind || "resource_access", kind, key, input.permission || "write", requester, owner || null, owner || null, "pending", input.reason, input.expires_at || null, input.claim_id || null, JSON.stringify(input.meta || {}));
453
- audit(db, { scope, project: input.project, event_kind: "approval_request", actor_agent: requester, resource_kind: kind, resource_key: key, permission: input.permission || "write", claim_id: input.claim_id || null, approval_id: info.lastInsertRowid, reason: input.reason, result: "pending", payload: input });
454
- return { ok: true, id: info.lastInsertRowid, status: "pending", owner_agent: owner || null };
455
- }
456
-
457
- function approvalDecide(db, input = {}) {
458
- ensureResourceAccessSchema(db);
459
- const id = parseInt(input.id, 10);
460
- const decidedBy = normalizeAgentName(input.decided_by || input.approved_by);
461
- const status = String(input.status || input.decision || "").toLowerCase();
462
- if (!id || !decidedBy || !["approved", "denied", "cancelled"].includes(status)) return { error: "id + decided_by + status(approved|denied|cancelled) required" };
463
- const row = db.prepare("SELECT * FROM approval_request WHERE id=?").get(id);
464
- if (!row) return { error: "approval_not_found", id };
465
- const owner = normalizeAgentName(row.owner_agent);
466
- if (owner && owner !== decidedBy) {
467
- return { error: "approval_owner_required", required_decided_by: owner, provided_decided_by: decidedBy, approval: rowToApproval(row) };
468
- }
469
- db.prepare("UPDATE approval_request SET status=?, decision=?, decided_by=?, decided_at=strftime('%Y-%m-%dT%H:%M:%fZ','now'), expires_at=COALESCE(?, expires_at), meta_json=COALESCE(?, meta_json) WHERE id=?")
470
- .run(status, input.decision || status, decidedBy, input.expires_at || null, input.meta ? JSON.stringify(input.meta) : null, id);
471
- if (status === "approved" && input.grant_acl !== false) {
472
- aclGrant(db, {
473
- scope: row.scope,
474
- project: row.project,
475
- resource_kind: row.resource_kind,
476
- resource_key: row.resource_key,
477
- agent_name: row.requester_agent,
478
- permission: row.permission,
479
- granted_by: decidedBy,
480
- reason: "approval_request #" + id,
481
- claim_id: row.claim_id || null,
482
- approval_id: id,
483
- expires_at: input.expires_at || row.expires_at || null,
484
- meta: { approval_id: id }
485
- });
486
- }
487
- audit(db, { scope: row.scope, project: row.project, event_kind: "approval_" + status, actor_agent: decidedBy, resource_kind: row.resource_kind, resource_key: row.resource_key, permission: row.permission, claim_id: row.claim_id || null, approval_id: id, reason: input.reason || null, result: status, payload: input });
488
- return { ok: true, id, status };
489
- }
490
-
491
- function approvalList(db, input = {}) {
492
- ensureResourceAccessSchema(db);
493
- const where = ["scope=?"];
494
- const params = [cleanScope(input.scope)];
495
- if (input.project) { where.push("(project=? OR project IS NULL)"); params.push(input.project); }
496
- if (input.status) { where.push("status=?"); params.push(input.status); }
497
- if (input.owner_agent) { where.push("owner_agent=?"); params.push(normalizeAgentName(input.owner_agent)); }
498
- if (input.requester_agent) { where.push("requester_agent=?"); params.push(normalizeAgentName(input.requester_agent)); }
499
- params.push(Math.min(Math.max(parseInt(input.limit || 100, 10) || 100, 1), 500));
500
- const rows = db.prepare("SELECT * FROM approval_request WHERE " + where.join(" AND ") + " ORDER BY requested_at DESC LIMIT ?").all(...params).map(rowToApproval);
501
- return { ok: true, count: rows.length, approvals: rows };
502
- }
503
-
504
- function claimRow(db, id) {
505
- ensureWorkClaimSchemaForLookup(db);
506
- return db.prepare("SELECT * FROM work_claim WHERE id=?").get(id) || null;
507
- }
508
-
509
- function claimResourceFromRow(row) {
510
- if (!row) return null;
511
- const kind = normalizeResourceKind(row.claim_kind || "file");
512
- const key = kind === "file" ? normalizeResourceKey("file", row.file_path || row.scope_value) : normalizeResourceKey(kind, row.scope_value || row.file_path);
513
- return { resource_kind: kind, resource_key: key };
514
- }
515
-
516
- function claimRequestAccess(db, input = {}) {
517
- const id = parseInt(input.claim_id || input.id, 10);
518
- const row = claimRow(db, id);
519
- if (!row) return { error: "claim_not_found", claim_id: id || null };
520
- const res = claimResourceFromRow(row);
521
- return approvalRequest(db, {
522
- scope: input.scope,
523
- project: input.project || row.project,
524
- request_kind: "claim_access",
525
- resource_kind: res.resource_kind,
526
- resource_key: res.resource_key,
527
- requester_agent: input.requester_agent || input.agent_name,
528
- owner_agent: row.agent_name,
529
- permission: input.permission || "write",
530
- reason: input.reason || "request access to active claim #" + row.id,
531
- expires_at: input.expires_at || row.expires_at || null,
532
- claim_id: row.id,
533
- meta: Object.assign({}, input.meta || {}, { claim_owner: row.agent_name })
534
- });
535
- }
536
-
537
- function claimGrantAccess(db, input = {}) {
538
- const id = parseInt(input.claim_id || input.id, 10);
539
- const row = claimRow(db, id);
540
- if (!row) return { error: "claim_not_found", claim_id: id || null };
541
- const decidedBy = normalizeAgentName(input.decided_by || input.granted_by || input.approved_by);
542
- const owner = normalizeAgentName(row.agent_name);
543
- if (decidedBy !== owner) {
544
- return { error: "claim_owner_required", required_decided_by: owner, provided_decided_by: decidedBy || null };
545
- }
546
- let approvalId = input.approval_id || null;
547
- if (approvalId) {
548
- const decision = approvalDecide(db, { id: approvalId, status: "approved", decided_by: decidedBy, expires_at: input.expires_at || row.expires_at || null });
549
- if (decision.error) return decision;
550
- }
551
- const res = claimResourceFromRow(row);
552
- const grant = aclGrant(db, {
553
- scope: input.scope,
554
- project: input.project || row.project,
555
- resource_kind: res.resource_kind,
556
- resource_key: res.resource_key,
557
- agent_name: input.requester_agent || input.agent_name,
558
- permission: input.permission || "write",
559
- granted_by: decidedBy,
560
- reason: input.reason || "claim access granted for claim #" + row.id,
561
- claim_id: row.id,
562
- approval_id: approvalId,
563
- expires_at: input.expires_at || row.expires_at || null,
564
- meta: input.meta || {}
565
- });
566
- return Object.assign({ claim_id: row.id }, grant);
567
- }
568
-
569
- function claimDenyAccess(db, input = {}) {
570
- const id = parseInt(input.approval_id || input.id, 10);
571
- if (!id) return { error: "approval_id required" };
572
- return approvalDecide(db, { id, status: "denied", decided_by: input.decided_by || input.denied_by, reason: input.reason || "claim access denied" });
573
- }
574
-
575
- function claimTransfer(db, input = {}) {
576
- ensureWorkClaimSchemaForLookup(db);
577
- const id = parseInt(input.claim_id || input.id, 10);
578
- const row = claimRow(db, id);
579
- const toAgent = normalizeAgentName(input.to_agent || input.agent_name);
580
- const byAgent = normalizeAgentName(input.by_agent || input.transferred_by);
581
- if (!row || !toAgent || !byAgent) return { error: "claim_id + to_agent + by_agent required" };
582
- const owner = normalizeAgentName(row.agent_name);
583
- if (owner !== byAgent) return { error: "claim_owner_required", required_by_agent: owner, provided_by_agent: byAgent };
584
- db.prepare("UPDATE work_claim SET agent_name=?, summary=COALESCE(?, summary), heartbeat_at=strftime('%Y-%m-%dT%H:%M:%fZ','now'), meta_json=COALESCE(?, meta_json) WHERE id=?")
585
- .run(toAgent, input.summary || null, input.meta ? JSON.stringify(input.meta) : null, id);
586
- const res = claimResourceFromRow(row);
587
- audit(db, { scope: input.scope, project: row.project, event_kind: "claim_transfer", actor_agent: byAgent, resource_kind: res.resource_kind, resource_key: res.resource_key, permission: "write", claim_id: id, reason: input.reason || null, result: "ok", payload: input });
588
- return { ok: true, claim_id: id, from_agent: owner, to_agent: toAgent };
589
- }
590
-
591
- function auditList(db, input = {}) {
592
- ensureResourceAccessSchema(db);
593
- const where = ["scope=?"];
594
- const params = [cleanScope(input.scope)];
595
- if (input.project) { where.push("(project=? OR project IS NULL)"); params.push(input.project); }
596
- if (input.actor_agent) { where.push("actor_agent=?"); params.push(normalizeAgentName(input.actor_agent)); }
597
- if (input.resource_kind) { where.push("resource_kind=?"); params.push(normalizeResourceKind(input.resource_kind)); }
598
- if (input.resource_key) { where.push("resource_key=?"); params.push(normalizeResourceKey(input.resource_kind, input.resource_key)); }
599
- params.push(Math.min(Math.max(parseInt(input.limit || 100, 10) || 100, 1), 500));
600
- const rows = db.prepare("SELECT * FROM resource_audit_log WHERE " + where.join(" AND ") + " ORDER BY created_at DESC LIMIT ?").all(...params)
601
- .map((row) => Object.assign({}, row, { payload: parseJson(row.payload_json, {}) }));
602
- return { ok: true, count: rows.length, events: rows };
603
- }
604
-
605
- const RESOURCE_ACCESS_TOOL_DEFS = {
606
- mem_resource_upsert: {
607
- description: "Create/update a canonical company resource with owner, department, risk class, and status.",
608
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, resource_kind: { type: "string" }, resource_key: { type: "string" }, label: { type: "string" }, owner_agent: { type: "string" }, owning_department: { type: "string" }, risk_class: { type: "string" }, status: { type: "string" }, notes: { type: "string" }, meta: { type: "object" }, updated_by: { type: "string" } }, required: ["resource_kind", "resource_key"] }
609
- },
610
- mem_resource_list: {
611
- description: "List canonical resources and owners.",
612
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, resource_kind: { type: "string" }, owner_agent: { type: "string" }, status: { type: "string" }, limit: { type: "integer" } } }
613
- },
614
- mem_resource_acl_grant: {
615
- description: "Grant an agent or department permission on a resource. If the resource has an owner, only that owner may grant unless executive override is explicitly enabled.",
616
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, resource_kind: { type: "string" }, resource_key: { type: "string" }, agent_name: { type: "string" }, department_name: { type: "string" }, permission: { type: "string" }, granted_by: { type: "string" }, reason: { type: "string" }, claim_id: { type: "integer" }, approval_id: { type: "integer" }, expires_at: { type: "string" }, meta: { type: "object" } }, required: ["resource_kind", "resource_key", "permission", "granted_by"] }
617
- },
618
- mem_resource_acl_list: {
619
- description: "List active ACL entries.",
620
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, resource_kind: { type: "string" }, resource_key: { type: "string" }, agent_name: { type: "string" }, status: { type: "string" }, limit: { type: "integer" } } }
621
- },
622
- mem_resource_access_check: {
623
- description: "Check agent access for resources derived from files/routes/domains/systems before a write/deploy action.",
624
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, agent_name: { type: "string" }, action_type: { type: "string" }, permission: { type: "string" }, files: { 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" } } }, required: ["agent_name"] }
625
- },
626
- mem_approval_request: {
627
- description: "Request owner approval for resource access.",
628
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, request_kind: { type: "string" }, resource_kind: { type: "string" }, resource_key: { type: "string" }, requester_agent: { type: "string" }, owner_agent: { type: "string" }, permission: { type: "string" }, reason: { type: "string" }, expires_at: { type: "string" }, claim_id: { type: "integer" }, meta: { type: "object" } }, required: ["resource_kind", "resource_key", "requester_agent", "reason"] }
629
- },
630
- mem_approval_decide: {
631
- description: "Approve/deny/cancel an approval request. Owner approval is enforced.",
632
- inputSchema: { type: "object", properties: { id: { type: "integer" }, status: { type: "string" }, decided_by: { type: "string" }, reason: { type: "string" }, expires_at: { type: "string" }, grant_acl: { type: "boolean" }, meta: { type: "object" } }, required: ["id", "status", "decided_by"] }
633
- },
634
- mem_approval_list: {
635
- description: "List approval requests.",
636
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, status: { type: "string" }, owner_agent: { type: "string" }, requester_agent: { type: "string" }, limit: { type: "integer" } } }
637
- },
638
- mem_claim_request_access: {
639
- description: "Request access to another agent's active work claim.",
640
- inputSchema: { type: "object", properties: { scope: { type: "string" }, claim_id: { type: "integer" }, requester_agent: { type: "string" }, permission: { type: "string" }, reason: { type: "string" }, expires_at: { type: "string" }, meta: { type: "object" } }, required: ["claim_id", "requester_agent"] }
641
- },
642
- mem_claim_grant_access: {
643
- description: "Grant access to an active claim. Only the claim owner may grant.",
644
- inputSchema: { type: "object", properties: { scope: { type: "string" }, claim_id: { type: "integer" }, requester_agent: { type: "string" }, permission: { type: "string" }, granted_by: { type: "string" }, approval_id: { type: "integer" }, expires_at: { type: "string" }, reason: { type: "string" }, meta: { type: "object" } }, required: ["claim_id", "requester_agent", "granted_by"] }
645
- },
646
- mem_claim_deny_access: {
647
- description: "Deny a pending claim-access approval request.",
648
- inputSchema: { type: "object", properties: { approval_id: { type: "integer" }, denied_by: { type: "string" }, reason: { type: "string" } }, required: ["approval_id", "denied_by"] }
649
- },
650
- mem_claim_transfer: {
651
- description: "Transfer an active claim to another agent. Only the current claim owner may transfer.",
652
- inputSchema: { type: "object", properties: { scope: { type: "string" }, claim_id: { type: "integer" }, to_agent: { type: "string" }, by_agent: { type: "string" }, reason: { type: "string" }, summary: { type: "string" }, meta: { type: "object" } }, required: ["claim_id", "to_agent", "by_agent"] }
653
- },
654
- mem_resource_audit_list: {
655
- description: "List resource permission, approval, and claim-access audit events.",
656
- inputSchema: { type: "object", properties: { scope: { type: "string" }, project: { type: "string" }, actor_agent: { type: "string" }, resource_kind: { type: "string" }, resource_key: { type: "string" }, limit: { type: "integer" } } }
657
- }
658
- };
659
-
660
- function handleResourceAccessTool(db, name, input = {}) {
661
- if (name === "mem_resource_upsert") return { handled: true, result: resourceUpsert(db, input || {}) };
662
- if (name === "mem_resource_list") return { handled: true, result: resourceList(db, input || {}) };
663
- if (name === "mem_resource_acl_grant") return { handled: true, result: aclGrant(db, input || {}) };
664
- if (name === "mem_resource_acl_list") return { handled: true, result: aclList(db, input || {}) };
665
- if (name === "mem_resource_access_check") return { handled: true, result: resourceAccessCheck(db, input || {}) };
666
- if (name === "mem_approval_request") return { handled: true, result: approvalRequest(db, input || {}) };
667
- if (name === "mem_approval_decide") return { handled: true, result: approvalDecide(db, input || {}) };
668
- if (name === "mem_approval_list") return { handled: true, result: approvalList(db, input || {}) };
669
- if (name === "mem_claim_request_access") return { handled: true, result: claimRequestAccess(db, input || {}) };
670
- if (name === "mem_claim_grant_access") return { handled: true, result: claimGrantAccess(db, input || {}) };
671
- if (name === "mem_claim_deny_access") return { handled: true, result: claimDenyAccess(db, input || {}) };
672
- if (name === "mem_claim_transfer") return { handled: true, result: claimTransfer(db, input || {}) };
673
- if (name === "mem_resource_audit_list") return { handled: true, result: auditList(db, input || {}) };
674
- return { handled: false };
675
- }
676
-
677
- module.exports = {
678
- RESOURCE_ACCESS_TOOL_DEFS,
679
- ensureResourceAccessSchema,
680
- resourceAccessCheck,
681
- handleResourceAccessTool,
682
- normalizeResourceKind,
683
- normalizeResourceKey
684
- };