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,944 +0,0 @@
1
- "use strict";
2
-
3
- const TRAINING_STATUS_ACTIVE = "active";
4
- const SITE_JSON_FIELDS = [
5
- "target_urls",
6
- "paths",
7
- "forbidden_hosts",
8
- "required_locales",
9
- "header_rules",
10
- "menu_rules",
11
- "footer_rules",
12
- "logo_rules",
13
- "auth_rules",
14
- "pricing_rules",
15
- "checkout_rules",
16
- "mobile_viewports",
17
- "desktop_viewports",
18
- "required_checks",
19
- ];
20
-
21
- const TEAM_QUALITY_TOOL_DEFS = {
22
- mem_agent_scorecard: {
23
- description: "Score one agent or all agents from real Mnemo work signals: actions, briefs, guard failures, quality findings, autonomy tasks, and training rules.",
24
- inputSchema: {
25
- type: "object",
26
- properties: {
27
- agent_name: { type: "string" },
28
- days: { type: "integer", default: 14 },
29
- include_doc: { type: "boolean" },
30
- },
31
- },
32
- },
33
- mem_agent_scoreboard: {
34
- description: "Render a compact team scoreboard with blockers, score, guard issues, open findings, pending briefs, and training notes.",
35
- inputSchema: {
36
- type: "object",
37
- properties: {
38
- days: { type: "integer", default: 14 },
39
- limit: { type: "integer", default: 50 },
40
- },
41
- },
42
- },
43
- mem_agent_training_rule_upsert: {
44
- description: "Store a durable training rule for one agent, one project, or the whole team. Use when owner feedback or a repeated mistake must never be forgotten.",
45
- inputSchema: {
46
- type: "object",
47
- properties: {
48
- id: { type: "integer" },
49
- agent_name: { type: "string" },
50
- scope: { type: "string" },
51
- project: { type: "string" },
52
- rule_kind: { type: "string" },
53
- title: { type: "string" },
54
- body: { type: "string" },
55
- source_kind: { type: "string" },
56
- source_id: { type: "string" },
57
- severity: { type: "string" },
58
- status: { type: "string" },
59
- created_by: { type: "string" },
60
- },
61
- required: ["title", "body"],
62
- },
63
- },
64
- mem_agent_training_rules: {
65
- description: "List active training rules relevant to an agent, project, or scope.",
66
- inputSchema: {
67
- type: "object",
68
- properties: {
69
- agent_name: { type: "string" },
70
- project: { type: "string" },
71
- scope: { type: "string" },
72
- status: { type: "string" },
73
- limit: { type: "integer" },
74
- },
75
- },
76
- },
77
- mem_correction_capture: {
78
- description: "Turn owner/reviewer feedback into a scar event plus a durable agent training rule so the team does not repeat the same mistake.",
79
- inputSchema: {
80
- type: "object",
81
- properties: {
82
- agent_name: { type: "string" },
83
- project: { type: "string" },
84
- text: { type: "string" },
85
- title: { type: "string" },
86
- category: { type: "string" },
87
- severity: { type: "string" },
88
- source_kind: { type: "string" },
89
- source_id: { type: "string" },
90
- created_by: { type: "string" },
91
- make_rule: { type: "boolean" },
92
- create_finding: { type: "boolean" },
93
- finding_url: { type: "string" },
94
- },
95
- required: ["text"],
96
- },
97
- },
98
- mem_site_contract_set: {
99
- description: "Store the canonical website contract for a project: canonical source, targets, paths, forbidden hosts, locales, header/menu/footer/logo/auth/pricing/checkout/mobile rules, and required checks.",
100
- inputSchema: {
101
- type: "object",
102
- properties: {
103
- project: { type: "string" },
104
- canonical_url: { type: "string" },
105
- target_urls: { type: "array", items: { type: "string" } },
106
- paths: { type: "array", items: { type: "string" } },
107
- forbidden_hosts: { type: "array", items: { type: "string" } },
108
- required_locales: { type: "array", items: { type: "string" } },
109
- header_rules: { type: "object" },
110
- menu_rules: { type: "object" },
111
- footer_rules: { type: "object" },
112
- logo_rules: { type: "object" },
113
- auth_rules: { type: "object" },
114
- pricing_rules: { type: "object" },
115
- checkout_rules: { type: "object" },
116
- mobile_viewports: { type: "array" },
117
- desktop_viewports: { type: "array" },
118
- required_checks: { type: "array", items: { type: "string" } },
119
- notes: { type: "string" },
120
- updated_by: { type: "string" },
121
- },
122
- required: ["project"],
123
- },
124
- },
125
- mem_site_contract_get: {
126
- description: "Read the website contract for one project, merged with registry and project-rule hints when available.",
127
- inputSchema: {
128
- type: "object",
129
- properties: {
130
- project: { type: "string" },
131
- },
132
- required: ["project"],
133
- },
134
- },
135
- mem_site_contract_list: {
136
- description: "List projects with stored site contracts.",
137
- inputSchema: {
138
- type: "object",
139
- properties: {
140
- limit: { type: "integer" },
141
- },
142
- },
143
- },
144
- mem_site_golden_check_plan: {
145
- description: "Build the mandatory golden-check plan for a website change, including audit command, browser evidence, mobile/desktop, locale, logo, menu, footer, and forbidden-domain checks.",
146
- inputSchema: {
147
- type: "object",
148
- properties: {
149
- project: { type: "string" },
150
- agent_name: { type: "string" },
151
- change_summary: { type: "string" },
152
- include_browser_steps: { type: "boolean" },
153
- },
154
- required: ["project"],
155
- },
156
- },
157
- mem_site_golden_check_report: {
158
- description: "Persist the actual golden-check result and optionally create quality findings for failed checks.",
159
- inputSchema: {
160
- type: "object",
161
- properties: {
162
- project: { type: "string" },
163
- agent_name: { type: "string" },
164
- status: { type: "string" },
165
- command: { type: "string" },
166
- summary: { type: "string" },
167
- evidence: { type: "object" },
168
- findings: { type: "array" },
169
- create_findings: { type: "boolean" },
170
- },
171
- required: ["project", "status"],
172
- },
173
- },
174
- mem_site_golden_check_history: {
175
- description: "List recent golden-check runs for one project or all projects.",
176
- inputSchema: {
177
- type: "object",
178
- properties: {
179
- project: { type: "string" },
180
- limit: { type: "integer" },
181
- },
182
- },
183
- },
184
- };
185
-
186
- function ensureTeamQualityTables(db) {
187
- db.exec(`
188
- CREATE TABLE IF NOT EXISTS correction_pattern (
189
- id INTEGER PRIMARY KEY AUTOINCREMENT,
190
- pattern TEXT NOT NULL UNIQUE,
191
- classifier TEXT NOT NULL,
192
- actor_scope TEXT,
193
- trait_to_adjust TEXT,
194
- delta REAL,
195
- hit_count INTEGER NOT NULL DEFAULT 0,
196
- last_hit_at TEXT
197
- );
198
- CREATE TABLE IF NOT EXISTS scar_event (
199
- id INTEGER PRIMARY KEY AUTOINCREMENT,
200
- scar_slug TEXT NOT NULL,
201
- triggering_memory_id INTEGER REFERENCES memory(id) ON DELETE SET NULL,
202
- pattern_id INTEGER REFERENCES correction_pattern(id) ON DELETE SET NULL,
203
- trait_delta_applied REAL NOT NULL DEFAULT 0,
204
- notes TEXT,
205
- occurred_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
206
- );
207
- CREATE INDEX IF NOT EXISTS idx_scar_event_pattern ON scar_event(pattern_id);
208
- CREATE INDEX IF NOT EXISTS idx_scar_event_occurred ON scar_event(occurred_at);
209
- CREATE TABLE IF NOT EXISTS scar_high_water (
210
- k TEXT PRIMARY KEY,
211
- v INTEGER NOT NULL DEFAULT 0
212
- );
213
- CREATE TABLE IF NOT EXISTS agent_training_rule (
214
- id INTEGER PRIMARY KEY AUTOINCREMENT,
215
- agent_name TEXT,
216
- scope TEXT NOT NULL DEFAULT 'global',
217
- project TEXT,
218
- rule_kind TEXT NOT NULL,
219
- title TEXT NOT NULL,
220
- body TEXT NOT NULL,
221
- source_kind TEXT,
222
- source_id TEXT,
223
- severity TEXT NOT NULL DEFAULT 'M',
224
- status TEXT NOT NULL DEFAULT 'active',
225
- created_by TEXT,
226
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
227
- updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
228
- );
229
- CREATE INDEX IF NOT EXISTS idx_training_agent_status ON agent_training_rule(agent_name, status, updated_at DESC);
230
- CREATE INDEX IF NOT EXISTS idx_training_scope_status ON agent_training_rule(scope, status, updated_at DESC);
231
- CREATE INDEX IF NOT EXISTS idx_training_project_status ON agent_training_rule(project, status, updated_at DESC);
232
- CREATE TABLE IF NOT EXISTS site_contract (
233
- project TEXT PRIMARY KEY,
234
- canonical_url TEXT,
235
- target_urls TEXT,
236
- paths TEXT,
237
- forbidden_hosts TEXT,
238
- required_locales TEXT,
239
- header_rules TEXT,
240
- menu_rules TEXT,
241
- footer_rules TEXT,
242
- logo_rules TEXT,
243
- auth_rules TEXT,
244
- pricing_rules TEXT,
245
- checkout_rules TEXT,
246
- mobile_viewports TEXT,
247
- desktop_viewports TEXT,
248
- required_checks TEXT,
249
- notes TEXT,
250
- updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
251
- updated_by TEXT
252
- );
253
- CREATE TABLE IF NOT EXISTS golden_check_run (
254
- id INTEGER PRIMARY KEY AUTOINCREMENT,
255
- project TEXT NOT NULL,
256
- agent_name TEXT,
257
- status TEXT NOT NULL,
258
- command TEXT,
259
- summary TEXT,
260
- evidence_json TEXT,
261
- findings_json TEXT,
262
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
263
- );
264
- CREATE INDEX IF NOT EXISTS idx_golden_project_time ON golden_check_run(project, created_at DESC);
265
- CREATE INDEX IF NOT EXISTS idx_golden_status ON golden_check_run(status, created_at DESC);
266
- `);
267
- }
268
-
269
- function handleTeamQualityTool(db, name, args) {
270
- if (!TEAM_QUALITY_TOOL_DEFS[name]) return { handled: false };
271
- const a = args || {};
272
- ensureTeamQualityTables(db);
273
- switch (name) {
274
- case "mem_agent_scorecard":
275
- return { handled: true, result: agentScorecard(db, a) };
276
- case "mem_agent_scoreboard":
277
- return { handled: true, result: agentScoreboard(db, a) };
278
- case "mem_agent_training_rule_upsert":
279
- return { handled: true, result: trainingRuleUpsert(db, a) };
280
- case "mem_agent_training_rules":
281
- return { handled: true, result: trainingRules(db, a) };
282
- case "mem_correction_capture":
283
- return { handled: true, result: correctionCapture(db, a) };
284
- case "mem_site_contract_set":
285
- return { handled: true, result: siteContractSet(db, a) };
286
- case "mem_site_contract_get":
287
- return { handled: true, result: siteContractGet(db, a) };
288
- case "mem_site_contract_list":
289
- return { handled: true, result: siteContractList(db, a) };
290
- case "mem_site_golden_check_plan":
291
- return { handled: true, result: siteGoldenCheckPlan(db, a) };
292
- case "mem_site_golden_check_report":
293
- return { handled: true, result: siteGoldenCheckReport(db, a) };
294
- case "mem_site_golden_check_history":
295
- return { handled: true, result: siteGoldenCheckHistory(db, a) };
296
- default:
297
- return { handled: false };
298
- }
299
- }
300
-
301
- function agentScorecard(db, a) {
302
- const days = clampInt(a.days, 14, 1, 365);
303
- const since = new Date(Date.now() - days * 86400000).toISOString();
304
- const agents = collectAgents(db, a.agent_name, since);
305
- const cards = agents.map((agent) => buildAgentCard(db, agent, since, days));
306
- cards.sort((x, y) => x.score - y.score || y.findings.open_high - x.findings.open_high || x.agent_name.localeCompare(y.agent_name));
307
- const result = {
308
- since,
309
- days,
310
- count: cards.length,
311
- agents: cards,
312
- summary: {
313
- average_score: cards.length ? Math.round(cards.reduce((n, c) => n + c.score, 0) / cards.length) : null,
314
- needs_training: cards.filter((c) => c.needs_training).length,
315
- blocked: cards.filter((c) => c.status === "block").length,
316
- attention: cards.filter((c) => c.status === "attention").length,
317
- },
318
- };
319
- if (a.agent_name) result.card = cards[0] || null;
320
- if (a.include_doc) result.doc = formatScoreboard(result, clampInt(a.limit, 50, 1, 200));
321
- return result;
322
- }
323
-
324
- function agentScoreboard(db, a) {
325
- const board = agentScorecard(db, { days: a.days, include_doc: true, limit: a.limit });
326
- return board;
327
- }
328
-
329
- function buildAgentCard(db, agent, since, days) {
330
- const actions = safeGet(db, `
331
- SELECT
332
- COUNT(*) AS total,
333
- SUM(CASE WHEN lower(status) IN ('done','ok','pass','ready','approved','reviewed','complete','completed','resolved') THEN 1 ELSE 0 END) AS done,
334
- SUM(CASE WHEN lower(status) IN ('error','failed','fail') THEN 1 ELSE 0 END) AS failed,
335
- SUM(CASE WHEN lower(status) IN ('block','blocked') THEN 1 ELSE 0 END) AS blocked,
336
- SUM(CASE WHEN (lower(action_kind) LIKE '%guard%' OR lower(topic) LIKE '%guard%' OR lower(action_kind) IN ('pre_action_check','agent_preflight')) THEN 1 ELSE 0 END) AS guard_total,
337
- SUM(CASE WHEN (lower(action_kind) LIKE '%guard%' OR lower(topic) LIKE '%guard%' OR lower(action_kind) IN ('pre_action_check','agent_preflight')) AND lower(status) IN ('block','blocked','missing','error','failed','fail') THEN 1 ELSE 0 END) AS guard_blocked,
338
- SUM(CASE WHEN lower(status) IN ('pending','started','open') AND julianday(started_at) < julianday('now','-6 hours') THEN 1 ELSE 0 END) AS stale
339
- FROM agent_action
340
- WHERE agent_name=? AND started_at>=?
341
- `, [agent, since], zeroActionStats());
342
-
343
- const briefs = safeGet(db, `
344
- SELECT
345
- COUNT(*) AS total,
346
- SUM(CASE WHEN lower(status)='pending' THEN 1 ELSE 0 END) AS pending,
347
- SUM(CASE WHEN lower(status)='dispatched' THEN 1 ELSE 0 END) AS dispatched,
348
- SUM(CASE WHEN lower(status) IN ('done','complete','completed','resolved') THEN 1 ELSE 0 END) AS done,
349
- SUM(CASE WHEN lower(status) IN ('failed','error','blocked') THEN 1 ELSE 0 END) AS failed
350
- FROM agent_brief
351
- WHERE agent_name=? AND created_at>=?
352
- `, [agent, since], zeroBriefStats());
353
-
354
- const findings = safeGet(db, `
355
- SELECT
356
- COUNT(*) AS total,
357
- SUM(CASE WHEN status='open' THEN 1 ELSE 0 END) AS open,
358
- SUM(CASE WHEN status='open' AND severity IN ('H','critical') THEN 1 ELSE 0 END) AS open_high,
359
- SUM(CASE WHEN status<>'open' THEN 1 ELSE 0 END) AS closed
360
- FROM quality_finding
361
- WHERE source_agent=? AND created_at>=?
362
- `, [agent, since], zeroFindingStats());
363
-
364
- const tasks = safeGet(db, `
365
- SELECT
366
- COUNT(*) AS total,
367
- SUM(CASE WHEN lower(status) IN ('done','reviewed','approved','resolved') THEN 1 ELSE 0 END) AS done,
368
- SUM(CASE WHEN lower(status) IN ('open','claimed','review') THEN 1 ELSE 0 END) AS open,
369
- SUM(CASE WHEN lower(status) IN ('block','blocked') THEN 1 ELSE 0 END) AS blocked
370
- FROM autonomy_task
371
- WHERE (assigned_agent=? OR reviewer_agent=?) AND created_at>=?
372
- `, [agent, agent, since], zeroTaskStats());
373
-
374
- const training = safeAll(db, `
375
- SELECT id, agent_name, scope, project, rule_kind, title, severity, updated_at
376
- FROM agent_training_rule
377
- WHERE status='active'
378
- AND (agent_name IS NULL OR agent_name=? OR scope='global')
379
- ORDER BY CASE severity WHEN 'critical' THEN 0 WHEN 'H' THEN 1 WHEN 'M' THEN 2 ELSE 3 END, updated_at DESC
380
- LIMIT 8
381
- `, [agent]);
382
-
383
- let score = 100;
384
- score -= num(actions.failed) * 4;
385
- score -= num(actions.blocked) * 5;
386
- score -= num(actions.guard_blocked) * 8;
387
- score -= num(actions.stale) * 3;
388
- score -= num(briefs.failed) * 4;
389
- score -= Math.max(0, num(briefs.pending) + num(briefs.dispatched) - 5) * 2;
390
- score -= num(findings.open_high) * 12;
391
- score -= Math.max(0, num(findings.open) - num(findings.open_high)) * 4;
392
- score -= num(tasks.blocked) * 5;
393
- score += Math.min(num(actions.done), 20) * 0.4;
394
- score += Math.min(num(tasks.done), 10) * 0.5;
395
- score = Math.max(0, Math.min(100, Math.round(score)));
396
-
397
- const trainingBrief = [];
398
- if (!num(actions.total)) trainingBrief.push("No recent action trail: verify the loop is online and logging work.");
399
- if (num(actions.guard_blocked)) trainingBrief.push("Guard misses detected: reload session/project context and pass pre-work before execution.");
400
- if (num(findings.open_high)) trainingBrief.push("High open findings from this agent: fix or hand off before new live work.");
401
- if (num(briefs.pending) + num(briefs.dispatched) > 5) trainingBrief.push("Brief backlog is growing: pull, process, or explicitly reassign.");
402
- if (num(actions.failed) || num(briefs.failed) || num(tasks.blocked)) trainingBrief.push("Failures/blockers must become durable rules or findings, not chat-only notes.");
403
- if (!trainingBrief.length && training.length) trainingBrief.push("Active training rules exist: review them at session start.");
404
-
405
- const status = score < 70 || num(findings.open_high) || num(actions.guard_blocked) ? "block" : (score < 85 || trainingBrief.length ? "attention" : "ok");
406
- return {
407
- agent_name: agent,
408
- status,
409
- score,
410
- window_days: days,
411
- actions: normalizeStats(actions),
412
- briefs: normalizeStats(briefs),
413
- findings: normalizeStats(findings),
414
- autonomy_tasks: normalizeStats(tasks),
415
- training_rules: training,
416
- needs_training: status !== "ok",
417
- training_brief: trainingBrief,
418
- };
419
- }
420
-
421
- function trainingRuleUpsert(db, a) {
422
- const title = cleanText(a.title, 160);
423
- const body = String(a.body || "").trim();
424
- if (!title || !body) return { error: "title and body required" };
425
- const ruleKind = cleanText(a.rule_kind || "training", 60) || "training";
426
- const scope = cleanText(a.scope || "global", 80) || "global";
427
- const severity = validSeverity(a.severity || "M");
428
- const status = cleanText(a.status || TRAINING_STATUS_ACTIVE, 30) || TRAINING_STATUS_ACTIVE;
429
- if (a.id) {
430
- const info = db.prepare(`
431
- UPDATE agent_training_rule
432
- SET agent_name=?, scope=?, project=?, rule_kind=?, title=?, body=?, source_kind=?, source_id=?, severity=?, status=?, created_by=COALESCE(created_by, ?), updated_at=strftime('%Y-%m-%dT%H:%M:%fZ','now')
433
- WHERE id=?
434
- `).run(a.agent_name || null, scope, a.project || null, ruleKind, title, body, a.source_kind || null, a.source_id || null, severity, status, a.created_by || null, a.id);
435
- return { ok: info.changes > 0, id: a.id, action: "updated", status };
436
- }
437
- const existing = db.prepare(`
438
- SELECT id FROM agent_training_rule
439
- WHERE title=? AND scope=? AND COALESCE(agent_name,'')=COALESCE(?, '') AND COALESCE(project,'')=COALESCE(?, '') AND status='active'
440
- ORDER BY id DESC LIMIT 1
441
- `).get(title, scope, a.agent_name || null, a.project || null);
442
- if (existing) {
443
- db.prepare(`
444
- UPDATE agent_training_rule
445
- SET body=?, rule_kind=?, source_kind=?, source_id=?, severity=?, created_by=COALESCE(created_by, ?), updated_at=strftime('%Y-%m-%dT%H:%M:%fZ','now')
446
- WHERE id=?
447
- `).run(body, ruleKind, a.source_kind || null, a.source_id || null, severity, a.created_by || null, existing.id);
448
- return { ok: true, id: existing.id, action: "refreshed", status: "active" };
449
- }
450
- const info = db.prepare(`
451
- INSERT INTO agent_training_rule (agent_name, scope, project, rule_kind, title, body, source_kind, source_id, severity, status, created_by)
452
- VALUES (?,?,?,?,?,?,?,?,?,?,?)
453
- `).run(a.agent_name || null, scope, a.project || null, ruleKind, title, body, a.source_kind || null, a.source_id || null, severity, status, a.created_by || null);
454
- logAction(db, a.created_by || a.agent_name || "training-rule", "agent_training_rule_upsert", a.agent_name || scope, "done", { id: info.lastInsertRowid, title, severity }, "training");
455
- return { ok: true, id: info.lastInsertRowid, action: "created", status };
456
- }
457
-
458
- function trainingRules(db, a) {
459
- const where = ["status=?"];
460
- const params = [a.status || TRAINING_STATUS_ACTIVE];
461
- if (a.agent_name) {
462
- where.push("(agent_name IS NULL OR agent_name=? OR scope='global')");
463
- params.push(a.agent_name);
464
- }
465
- if (a.project) {
466
- where.push("(project IS NULL OR project=?)");
467
- params.push(a.project);
468
- }
469
- if (a.scope) {
470
- where.push("(scope=? OR scope='global')");
471
- params.push(a.scope);
472
- }
473
- params.push(clampInt(a.limit, 100, 1, 500));
474
- const rows = db.prepare(`
475
- SELECT * FROM agent_training_rule
476
- WHERE ${where.join(" AND ")}
477
- ORDER BY CASE severity WHEN 'critical' THEN 0 WHEN 'H' THEN 1 WHEN 'M' THEN 2 ELSE 3 END, updated_at DESC
478
- LIMIT ?
479
- `).all(...params);
480
- return { count: rows.length, rules: rows };
481
- }
482
-
483
- function correctionCapture(db, a) {
484
- const text = String(a.text || "").trim();
485
- if (!text) return { error: "text required" };
486
- const agentName = a.agent_name || null;
487
- const project = a.project || null;
488
- const title = cleanText(a.title || firstSentence(text), 160) || "Correction captured";
489
- const severity = validSeverity(a.severity || "H");
490
- const category = cleanText(a.category || "correction", 80) || "correction";
491
- const slug = slugify([project, agentName, title].filter(Boolean).join("-")) || "correction";
492
- const created = { scar_event_id: null, training_rule: null, quality_finding: null };
493
-
494
- const scarInfo = db.prepare("INSERT INTO scar_event (scar_slug, trait_delta_applied, notes) VALUES (?,?,?)")
495
- .run(slug, 0, text);
496
- created.scar_event_id = scarInfo.lastInsertRowid;
497
-
498
- if (a.make_rule !== false) {
499
- created.training_rule = trainingRuleUpsert(db, {
500
- agent_name: agentName,
501
- project,
502
- scope: project ? "project" : "global",
503
- rule_kind: "correction",
504
- title,
505
- body: text,
506
- source_kind: a.source_kind || "correction_capture",
507
- source_id: a.source_id || String(scarInfo.lastInsertRowid),
508
- severity,
509
- created_by: a.created_by || "owner-feedback",
510
- });
511
- }
512
-
513
- if (a.create_finding && project) {
514
- const info = db.prepare("INSERT INTO quality_finding (project, category, severity, title, url, expected, actual, source_agent, evidence_json) VALUES (?,?,?,?,?,?,?,?,?)")
515
- .run(project, category, severity, title, a.finding_url || null, "The team must not repeat this correction.", text, agentName || a.created_by || null, JSON.stringify({ source: "mem_correction_capture", scar_event_id: scarInfo.lastInsertRowid }));
516
- created.quality_finding = { id: info.lastInsertRowid, project, status: "open", severity };
517
- }
518
-
519
- logAction(db, a.created_by || "owner-feedback", "correction_capture", project || agentName || "global", "done", { title, agent_name: agentName, project, scar_event_id: scarInfo.lastInsertRowid }, "training");
520
- return {
521
- ok: true,
522
- title,
523
- severity,
524
- agent_name: agentName,
525
- project,
526
- ...created,
527
- };
528
- }
529
-
530
- function siteContractSet(db, a) {
531
- const project = cleanText(a.project, 160);
532
- if (!project) return { error: "project required" };
533
- const fields = ["project"];
534
- const placeholders = ["?"];
535
- const values = [project];
536
- const updates = [];
537
- for (const key of ["canonical_url", "notes", "updated_by"]) {
538
- if (a[key] !== undefined) {
539
- fields.push(key);
540
- placeholders.push("?");
541
- values.push(a[key] || null);
542
- updates.push(key + "=excluded." + key);
543
- }
544
- }
545
- for (const key of SITE_JSON_FIELDS) {
546
- if (a[key] !== undefined) {
547
- fields.push(key);
548
- placeholders.push("?");
549
- values.push(JSON.stringify(a[key]));
550
- updates.push(key + "=excluded." + key);
551
- }
552
- }
553
- if (!updates.length) updates.push("updated_at=strftime('%Y-%m-%dT%H:%M:%fZ','now')");
554
- else updates.push("updated_at=strftime('%Y-%m-%dT%H:%M:%fZ','now')");
555
- const sql = `INSERT INTO site_contract (${fields.join(",")}) VALUES (${placeholders.join(",")}) ON CONFLICT(project) DO UPDATE SET ${updates.join(", ")}`;
556
- db.prepare(sql).run(...values);
557
- logAction(db, a.updated_by || "site-contract", "site_contract_set", project, "done", { keys: Object.keys(a).filter((k) => k !== "project") }, "site_contract");
558
- return { ok: true, project };
559
- }
560
-
561
- function siteContractGet(db, a) {
562
- const project = cleanText(a.project, 160);
563
- if (!project) return { error: "project required" };
564
- const row = safeGet(db, "SELECT * FROM site_contract WHERE project=?", [project], null);
565
- const registry = safeGet(db, "SELECT name, domain, live_url, staging_url, health_checklist FROM project_registry WHERE name=?", [project], null);
566
- const rules = safeGet(db, "SELECT canonical_nav, allowed_domains, language_matrix, design_rules, pricing_rules, checkout_rules FROM project_rules WHERE project=?", [project], null);
567
- const contract = row ? parseSiteContract(row) : defaultContract(project, registry, rules);
568
- if (rules) {
569
- contract.project_rules_hint = {
570
- canonical_nav: json(rules.canonical_nav, null),
571
- allowed_domains: json(rules.allowed_domains, null),
572
- language_matrix: json(rules.language_matrix, null),
573
- design_rules: json(rules.design_rules, null),
574
- pricing_rules: json(rules.pricing_rules, null),
575
- checkout_rules: json(rules.checkout_rules, null),
576
- };
577
- }
578
- if (registry) contract.registry_hint = registry;
579
- contract.audit_command = buildAuditCommand(contract);
580
- contract.required_evidence = requiredSiteEvidence(contract);
581
- return contract;
582
- }
583
-
584
- function siteContractList(db, a) {
585
- const rows = db.prepare("SELECT project, canonical_url, updated_at, updated_by, notes FROM site_contract ORDER BY updated_at DESC LIMIT ?")
586
- .all(clampInt(a.limit, 100, 1, 500));
587
- return { count: rows.length, contracts: rows };
588
- }
589
-
590
- function siteGoldenCheckPlan(db, a) {
591
- const contract = siteContractGet(db, { project: a.project });
592
- if (contract.error) return contract;
593
- const checks = requiredSiteEvidence(contract);
594
- const command = buildAuditCommand(contract);
595
- const browserSteps = a.include_browser_steps === false ? [] : [
596
- "Open canonical source and each target URL at desktop viewport.",
597
- "Open canonical source and each target URL at mobile viewport.",
598
- "Compare header style, menu order, href targets, footer/legal links, and logo assets.",
599
- "Confirm same-label menu items point to the target domain and expected target path, not the copied canonical domain.",
600
- "Check each required locale route keeps the same language and does not fall back to the wrong locale.",
601
- "Check legal footer links preserve the active locale on localized pages.",
602
- "Check light and dark theme logos when the product supports themes.",
603
- "Confirm mobile viewport meta exists and mobile header/menu is usable.",
604
- "Record screenshots or explicit browser observations before reporting pass.",
605
- ];
606
- const plan = {
607
- project: contract.project,
608
- change_summary: a.change_summary || null,
609
- status: command ? "ready" : "blocked",
610
- blockers: command ? [] : ["site contract needs canonical_url and at least one target_url"],
611
- contract,
612
- command,
613
- checks,
614
- browser_steps: browserSteps,
615
- pass_condition: "No high findings, no forbidden domain leaks, required locales checked, mobile+desktop checked, relevant logos/themes checked, and findings reported with mem_site_golden_check_report.",
616
- };
617
- logAction(db, a.agent_name || "site-golden-plan", "site_golden_check_plan", contract.project, plan.status, { command, checks }, "site_contract");
618
- return plan;
619
- }
620
-
621
- function siteGoldenCheckReport(db, a) {
622
- const status = cleanText(a.status, 40) || "unknown";
623
- const project = cleanText(a.project, 160);
624
- if (!project) return { error: "project required" };
625
- const findings = Array.isArray(a.findings) ? a.findings : [];
626
- const info = db.prepare("INSERT INTO golden_check_run (project, agent_name, status, command, summary, evidence_json, findings_json) VALUES (?,?,?,?,?,?,?)")
627
- .run(project, a.agent_name || null, status, a.command || null, a.summary || null, a.evidence ? JSON.stringify(a.evidence) : null, JSON.stringify(findings));
628
- const created = [];
629
- if (a.create_findings !== false) {
630
- for (const group of groupGoldenFindings(findings, status)) {
631
- const existing = db.prepare("SELECT id FROM quality_finding WHERE project=? AND title=? AND status='open' ORDER BY id DESC LIMIT 1")
632
- .get(project, group.title);
633
- const evidence = { source: "golden_check_run", run_id: info.lastInsertRowid, count: group.count, examples: group.examples, urls: group.urls };
634
- const actual = `${group.count} ${group.type} finding(s). Examples: ${group.examples.map((x) => x.summary).join(" | ")}`;
635
- if (existing) {
636
- db.prepare("UPDATE quality_finding SET severity=?, url=?, expected=?, actual=?, source_agent=?, evidence_json=?, updated_at=strftime('%Y-%m-%dT%H:%M:%fZ','now') WHERE id=?")
637
- .run(group.severity, group.urls[0] || null, group.expected, actual, a.agent_name || null, JSON.stringify(evidence), existing.id);
638
- created.push({ id: existing.id, title: group.title, severity: group.severity, action: "updated", count: group.count });
639
- } else {
640
- const q = db.prepare("INSERT INTO quality_finding (project, category, severity, title, url, expected, actual, source_agent, evidence_json) VALUES (?,?,?,?,?,?,?,?,?)")
641
- .run(project, group.category, group.severity, group.title, group.urls[0] || null, group.expected, actual, a.agent_name || null, JSON.stringify(evidence));
642
- created.push({ id: q.lastInsertRowid, title: group.title, severity: group.severity, action: "created", count: group.count });
643
- }
644
- }
645
- }
646
- logAction(db, a.agent_name || "golden-check", "site_golden_check_report", project, status, { run_id: info.lastInsertRowid, findings: findings.length, created_findings: created.length }, "site_contract");
647
- return { ok: true, id: info.lastInsertRowid, project, status, created_findings: created };
648
- }
649
-
650
- function siteGoldenCheckHistory(db, a) {
651
- const where = [];
652
- const params = [];
653
- if (a.project) {
654
- where.push("project=?");
655
- params.push(a.project);
656
- }
657
- params.push(clampInt(a.limit, 50, 1, 500));
658
- const rows = db.prepare(`
659
- SELECT id, project, agent_name, status, command, summary, created_at
660
- FROM golden_check_run
661
- ${where.length ? "WHERE " + where.join(" AND ") : ""}
662
- ORDER BY created_at DESC
663
- LIMIT ?
664
- `).all(...params);
665
- return { count: rows.length, runs: rows };
666
- }
667
-
668
- function groupGoldenFindings(findings, status) {
669
- const groups = new Map();
670
- for (const f of findings || []) {
671
- if (!f || (!f.type && !f.title)) continue;
672
- const type = cleanText(f.type || f.title || "golden_check_finding", 120);
673
- const key = type;
674
- const sev = validSeverity(f.severity || (status === "fail" ? "H" : "M"));
675
- const current = groups.get(key) || {
676
- type,
677
- title: "Golden audit: " + type,
678
- category: f.category || type || "site_contract",
679
- severity: sev,
680
- expected: f.expected || "Site contract passes for every checked path, locale, link, logo and viewport.",
681
- count: 0,
682
- urls: [],
683
- examples: [],
684
- };
685
- current.severity = higherSeverity(current.severity, sev);
686
- current.count += 1;
687
- const url = f.url || f.href || null;
688
- if (url && !current.urls.includes(url)) current.urls.push(url);
689
- if (current.examples.length < 8) {
690
- current.examples.push({
691
- url,
692
- label: f.label || f.text || null,
693
- href: f.href || null,
694
- status: f.status || null,
695
- summary: summarizeGoldenFinding(f),
696
- });
697
- }
698
- groups.set(key, current);
699
- }
700
- return Array.from(groups.values()).sort((a, b) => severityRank(a.severity) - severityRank(b.severity) || b.count - a.count);
701
- }
702
-
703
- function summarizeGoldenFinding(f) {
704
- const parts = [];
705
- if (f.type || f.title) parts.push(String(f.type || f.title));
706
- if (f.label || f.text) parts.push("label=" + String(f.label || f.text).slice(0, 80));
707
- if (f.href) parts.push("href=" + String(f.href).slice(0, 120));
708
- if (f.url) parts.push("url=" + String(f.url).slice(0, 120));
709
- if (f.status) parts.push("status=" + String(f.status));
710
- return parts.join(" ");
711
- }
712
-
713
- function higherSeverity(a, b) {
714
- return severityRank(b) < severityRank(a) ? b : a;
715
- }
716
-
717
- function severityRank(value) {
718
- if (value === "critical") return 0;
719
- if (value === "H") return 1;
720
- if (value === "M") return 2;
721
- return 3;
722
- }
723
-
724
- function defaultContract(project, registry, rules) {
725
- const liveUrl = registry && (registry.live_url || registry.staging_url) || null;
726
- const lang = rules ? json(rules.language_matrix, {}) || {} : {};
727
- const locales = Array.isArray(lang.required_locales) ? lang.required_locales : (Array.isArray(lang.locales) ? lang.locales : []);
728
- const paths = locales.length ? unique(["/"].concat(locales.map((l) => "/" + String(l).replace(/^\/+/, "")))) : ["/"];
729
- return {
730
- project,
731
- canonical_url: liveUrl,
732
- target_urls: liveUrl ? [liveUrl] : [],
733
- paths,
734
- forbidden_hosts: [],
735
- required_locales: locales,
736
- header_rules: {},
737
- menu_rules: rules ? { canonical_nav: json(rules.canonical_nav, null) } : {},
738
- footer_rules: {},
739
- logo_rules: {},
740
- auth_rules: {},
741
- pricing_rules: rules ? json(rules.pricing_rules, {}) || {} : {},
742
- checkout_rules: rules ? json(rules.checkout_rules, {}) || {} : {},
743
- mobile_viewports: ["390x844"],
744
- desktop_viewports: ["1440x900"],
745
- required_checks: defaultRequiredChecks(),
746
- notes: "Generated fallback. Store a real contract with mem_site_contract_set.",
747
- updated_at: null,
748
- updated_by: null,
749
- _generated: true,
750
- };
751
- }
752
-
753
- function parseSiteContract(row) {
754
- const out = Object.assign({}, row);
755
- for (const key of SITE_JSON_FIELDS) out[key] = json(out[key], defaultForSiteField(key));
756
- if (!Array.isArray(out.paths) || !out.paths.length) out.paths = ["/"];
757
- if (!Array.isArray(out.mobile_viewports) || !out.mobile_viewports.length) out.mobile_viewports = ["390x844"];
758
- if (!Array.isArray(out.desktop_viewports) || !out.desktop_viewports.length) out.desktop_viewports = ["1440x900"];
759
- if (!Array.isArray(out.required_checks) || !out.required_checks.length) out.required_checks = defaultRequiredChecks();
760
- return out;
761
- }
762
-
763
- function defaultForSiteField(key) {
764
- if (["target_urls", "paths", "forbidden_hosts", "required_locales", "mobile_viewports", "desktop_viewports", "required_checks"].includes(key)) return [];
765
- return {};
766
- }
767
-
768
- function defaultRequiredChecks() {
769
- return ["header_style", "menu_structure", "menu_href_targets", "footer_legal_links", "forbidden_domain_leaks", "locale_routes", "legal_locale_links", "light_dark_logos", "viewport_meta", "mobile", "desktop"];
770
- }
771
-
772
- function requiredSiteEvidence(contract) {
773
- const required = Array.isArray(contract.required_checks) && contract.required_checks.length ? contract.required_checks : defaultRequiredChecks();
774
- return {
775
- required_checks: required,
776
- paths: contract.paths || ["/"],
777
- locales: contract.required_locales || [],
778
- mobile_viewports: contract.mobile_viewports || ["390x844"],
779
- desktop_viewports: contract.desktop_viewports || ["1440x900"],
780
- must_record: [
781
- "audit command output",
782
- "browser/screenshot evidence when style or layout changed",
783
- "same-label menu hrefs checked for target-domain and expected path",
784
- "links checked for target-domain preservation",
785
- "localized legal links checked for locale preservation",
786
- "logo and dark-logo assets checked when applicable",
787
- "open findings created for every failed check",
788
- ],
789
- };
790
- }
791
-
792
- function buildAuditCommand(contract) {
793
- if (!contract || !contract.canonical_url || !Array.isArray(contract.target_urls) || !contract.target_urls.length) return "";
794
- const args = [
795
- "node packages/core/bin/site-contract-audit.js",
796
- "--canonical " + shellQuote(contract.canonical_url),
797
- "--targets " + shellQuote(contract.target_urls.join(",")),
798
- "--paths " + shellQuote((contract.paths && contract.paths.length ? contract.paths : ["/"]).join(",")),
799
- ];
800
- if (Array.isArray(contract.forbidden_hosts) && contract.forbidden_hosts.length) {
801
- args.push("--forbidden-hosts " + shellQuote(contract.forbidden_hosts.join(",")));
802
- }
803
- const allowed = allowedHostsFromContract(contract);
804
- if (allowed.length) args.push("--allowed-hosts " + shellQuote(allowed.join(",")));
805
- const logo = contract.logo_rules || {};
806
- if (logo.require_dark_logo || logo.dark_logo_required || logo.dark_mode === true) args.push("--require-dark-logo");
807
- args.push("--report");
808
- args.push("--project " + shellQuote(contract.project));
809
- return args.join(" ");
810
- }
811
-
812
- function allowedHostsFromContract(contract) {
813
- const set = new Set();
814
- const hint = contract && contract.project_rules_hint;
815
- const allowed = hint && Array.isArray(hint.allowed_domains) ? hint.allowed_domains : [];
816
- for (const item of allowed) {
817
- const raw = String(item || "").trim();
818
- if (!raw) continue;
819
- try { set.add(new URL(raw.includes("://") ? raw : "https://" + raw).host); }
820
- catch { set.add(raw.replace(/^https?:\/\//, "").replace(/\/.*$/, "")); }
821
- }
822
- return Array.from(set).filter(Boolean);
823
- }
824
-
825
- function collectAgents(db, agentName, since) {
826
- if (agentName) return [agentName];
827
- const set = new Set();
828
- for (const row of safeAll(db, "SELECT agent_name FROM agent_registry WHERE agent_name IS NOT NULL", [])) set.add(row.agent_name);
829
- for (const row of safeAll(db, "SELECT DISTINCT agent_name FROM agent_action WHERE agent_name IS NOT NULL AND started_at>=?", [since])) set.add(row.agent_name);
830
- for (const row of safeAll(db, "SELECT DISTINCT agent_name FROM agent_brief WHERE agent_name IS NOT NULL AND created_at>=?", [since])) set.add(row.agent_name);
831
- for (const row of safeAll(db, "SELECT DISTINCT source_agent AS agent_name FROM agent_brief WHERE source_agent IS NOT NULL AND created_at>=?", [since])) set.add(row.agent_name);
832
- for (const row of safeAll(db, "SELECT DISTINCT assigned_agent AS agent_name FROM autonomy_task WHERE assigned_agent IS NOT NULL AND created_at>=?", [since])) set.add(row.agent_name);
833
- for (const row of safeAll(db, "SELECT DISTINCT source_agent AS agent_name FROM quality_finding WHERE source_agent IS NOT NULL AND created_at>=?", [since])) set.add(row.agent_name);
834
- return Array.from(set).filter(Boolean).sort();
835
- }
836
-
837
- function formatScoreboard(board, limit) {
838
- const lines = ["# Agent Scoreboard", "", `Window: ${board.days} days | agents: ${board.count} | needs training: ${board.summary.needs_training}`, ""];
839
- for (const c of board.agents.slice(0, limit)) {
840
- lines.push(`## ${c.agent_name}`);
841
- lines.push(`- Status: ${c.status} | score: ${c.score}`);
842
- lines.push(`- Actions: ${c.actions.done}/${c.actions.total} done, ${c.actions.failed} failed, ${c.actions.guard_blocked} guard blocks`);
843
- lines.push(`- Briefs: ${c.briefs.pending} pending, ${c.briefs.dispatched} dispatched, ${c.briefs.failed} failed`);
844
- lines.push(`- Findings: ${c.findings.open} open (${c.findings.open_high} high/critical)`);
845
- if (c.training_brief.length) lines.push(`- Training: ${c.training_brief.join(" ")}`);
846
- lines.push("");
847
- }
848
- return lines.join("\n");
849
- }
850
-
851
- function logAction(db, agentName, kind, target, status, payload, topic) {
852
- try {
853
- db.prepare("INSERT INTO agent_action (agent_name, action_kind, target, status, payload_json, topic) VALUES (?,?,?,?,?,?)")
854
- .run(agentName || "unknown", kind, target || null, status || "done", payload ? JSON.stringify(payload) : null, topic || null);
855
- } catch {}
856
- }
857
-
858
- function safeGet(db, sql, params, fallback) {
859
- try { return db.prepare(sql).get(...(params || [])) || fallback; } catch { return fallback; }
860
- }
861
-
862
- function safeAll(db, sql, params) {
863
- try { return db.prepare(sql).all(...(params || [])); } catch { return []; }
864
- }
865
-
866
- function json(value, fallback) {
867
- if (value == null || value === "") return fallback;
868
- if (typeof value !== "string") return value;
869
- try { return JSON.parse(value); } catch { return fallback === undefined ? value : fallback; }
870
- }
871
-
872
- function cleanText(value, max) {
873
- const s = String(value || "").trim();
874
- if (!s) return "";
875
- return s.slice(0, max || 1000);
876
- }
877
-
878
- function firstSentence(text) {
879
- const clean = String(text || "").replace(/\s+/g, " ").trim();
880
- const m = clean.match(/^(.{1,140}?)(?:[.!?]\s|$)/);
881
- return m ? m[1] : clean.slice(0, 140);
882
- }
883
-
884
- function slugify(value) {
885
- return String(value || "")
886
- .toLowerCase()
887
- .replace(/[^a-z0-9]+/g, "-")
888
- .replace(/^-+|-+$/g, "")
889
- .slice(0, 120);
890
- }
891
-
892
- function validSeverity(value) {
893
- return ["L", "M", "H", "critical"].includes(value) ? value : "M";
894
- }
895
-
896
- function clampInt(value, fallback, min, max) {
897
- const n = Number.parseInt(value, 10);
898
- if (!Number.isFinite(n)) return fallback;
899
- return Math.max(min, Math.min(max, n));
900
- }
901
-
902
- function num(value) {
903
- return Number(value || 0);
904
- }
905
-
906
- function normalizeStats(stats) {
907
- const out = {};
908
- for (const [k, v] of Object.entries(stats || {})) out[k] = num(v);
909
- return out;
910
- }
911
-
912
- function zeroActionStats() {
913
- return { total: 0, done: 0, failed: 0, blocked: 0, guard_total: 0, guard_blocked: 0, stale: 0 };
914
- }
915
-
916
- function zeroBriefStats() {
917
- return { total: 0, pending: 0, dispatched: 0, done: 0, failed: 0 };
918
- }
919
-
920
- function zeroFindingStats() {
921
- return { total: 0, open: 0, open_high: 0, closed: 0 };
922
- }
923
-
924
- function zeroTaskStats() {
925
- return { total: 0, done: 0, open: 0, blocked: 0 };
926
- }
927
-
928
- function unique(arr) {
929
- return Array.from(new Set((arr || []).filter(Boolean)));
930
- }
931
-
932
- function shellQuote(value) {
933
- const s = String(value || "");
934
- if (/^[A-Za-z0-9_./:,@%+=-]+$/.test(s)) return s;
935
- return '"' + s.replace(/"/g, '\\"') + '"';
936
- }
937
-
938
- module.exports = {
939
- TEAM_QUALITY_TOOL_DEFS,
940
- SITE_JSON_FIELDS,
941
- ensureTeamQualityTables,
942
- handleTeamQualityTool,
943
- buildAuditCommand,
944
- };