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,810 +0,0 @@
1
- "use strict";
2
-
3
- const { parseMaybeJson } = require("./shared_utils");
4
-
5
- const TIMELINE_REPORT_TOOL_DEFS = {
6
- mem_project_timeline_report: {
7
- description: "Render a token-budgeted project dossier: recent timeline, live-readiness gates, open defects, claims, briefs, handoffs, decisions, and concrete next actions.",
8
- inputSchema: {
9
- type: "object",
10
- properties: {
11
- project: { type: "string" },
12
- agent_name: { type: "string" },
13
- days: { type: "integer", default: 30 },
14
- token_budget: { type: "integer", default: 3000 },
15
- max_items: { type: "integer", default: 8 },
16
- live_focus: { type: "boolean", default: true },
17
- include_doc: { type: "boolean", default: true },
18
- },
19
- required: ["project"],
20
- },
21
- },
22
- };
23
-
24
- function handleTimelineReportTool(db, name, args) {
25
- if (!TIMELINE_REPORT_TOOL_DEFS[name]) return { handled: false };
26
- return { handled: true, result: projectTimelineReport(db, args || {}) };
27
- }
28
-
29
- function projectTimelineReport(db, args) {
30
- const project = clean(args.project || args.name, 160);
31
- if (!project) return { error: "project required" };
32
- const agentName = normalizeAgentId(args.agent_name);
33
- const days = clampInt(args.days, 30, 1, 3650);
34
- const tokenBudget = clampInt(args.token_budget, 3000, 800, 24000);
35
- const maxItems = clampInt(args.max_items, 8, 3, 50);
36
- const liveFocus = args.live_focus !== false;
37
- const includeDoc = args.include_doc !== false;
38
- const sinceIso = new Date(Date.now() - days * 86400000).toISOString();
39
-
40
- const registry = selectProjectRegistry(db, project);
41
- const rules = selectProjectRules(db, project);
42
- const siteContract = selectSiteContract(db, project);
43
- const latestGolden = selectLatestGoldenCheck(db, project);
44
- const openFindings = selectOpenFindings(db, project, maxItems);
45
- const activeClaims = selectActiveClaims(db, project, maxItems);
46
- const autonomyTasks = selectAutonomyTasks(db, project, maxItems);
47
- const departmentCoverage = selectDepartmentCoverage(db, project);
48
- const pendingBriefs = selectPendingBriefs(db, project, agentName, maxItems);
49
- const handoffs = selectRecentHandoffs(db, project, agentName, sinceIso, maxItems);
50
- const decisions = selectRecentDecisions(db, project, sinceIso, maxItems);
51
- const actions = selectRecentActions(db, project, agentName, sinceIso, maxItems);
52
- const memories = selectMemorySnippets(db, project, sinceIso, maxItems);
53
- const timeline = buildTimeline({
54
- registry,
55
- rules,
56
- siteContract,
57
- latestGolden,
58
- openFindings,
59
- activeClaims,
60
- autonomyTasks,
61
- pendingBriefs,
62
- handoffs,
63
- decisions,
64
- actions,
65
- memories,
66
- maxItems,
67
- });
68
- const readiness = deriveLiveReadiness({
69
- project,
70
- registry,
71
- rules,
72
- siteContract,
73
- latestGolden,
74
- openFindings,
75
- activeClaims,
76
- autonomyTasks,
77
- liveFocus,
78
- });
79
- const nextActions = deriveNextActions(readiness, {
80
- openFindings,
81
- activeClaims,
82
- autonomyTasks,
83
- pendingBriefs,
84
- latestGolden,
85
- });
86
-
87
- const report = {
88
- ok: true,
89
- generated_at: new Date().toISOString(),
90
- project,
91
- agent_name: agentName || null,
92
- days,
93
- live_focus: liveFocus,
94
- token_budget: tokenBudget,
95
- summary: {
96
- status: readiness.status,
97
- readiness_percent: readiness.readiness_percent,
98
- blockers: readiness.blockers.length,
99
- warnings: readiness.warnings.length,
100
- open_findings: openFindings.length,
101
- active_claims: activeClaims.length,
102
- autonomy_open_or_review: autonomyTasks.filter((t) => !["done", "closed", "resolved"].includes(String(t.status || "").toLowerCase())).length,
103
- pending_or_dispatched_briefs: pendingBriefs.length,
104
- latest_golden_check_status: latestGolden ? latestGolden.status : null,
105
- last_activity_at: timeline.length ? timeline[0].at : null,
106
- },
107
- live_readiness: readiness,
108
- next_actions: nextActions,
109
- sections: {
110
- registry: registry ? redactRow(registry) : null,
111
- project_rules: rules ? redactRuleRow(rules) : null,
112
- site_contract: siteContract ? redactSiteContract(siteContract) : null,
113
- latest_golden_check: latestGolden ? redactRow(latestGolden) : null,
114
- open_findings: openFindings.map(redactRow),
115
- active_claims: activeClaims.map(redactRow),
116
- autonomy_tasks: autonomyTasks.map(redactRow),
117
- department_coverage: departmentCoverage.map(redactRow),
118
- pending_briefs: pendingBriefs.map(redactRow),
119
- recent_handoffs: handoffs.map(redactRow),
120
- recent_decisions: decisions.map(redactRow),
121
- recent_actions: actions.map(redactRow),
122
- memory_snippets: memories.map(redactRow),
123
- timeline,
124
- },
125
- };
126
-
127
- if (includeDoc) {
128
- const rendered = renderReport(report, tokenBudget);
129
- report.doc = rendered.doc;
130
- report.estimated_doc_tokens = rendered.estimated_tokens;
131
- report.truncated = rendered.truncated;
132
- }
133
- report.next_step = readiness.status === "ready"
134
- ? "Assign a reviewer to run the golden checks and capture the evidence before marking the project live."
135
- : "Work the blockers in next_actions first, then re-run mem_project_timeline_report until status is ready.";
136
- return report;
137
- }
138
-
139
- function selectProjectRegistry(db, project) {
140
- if (!tableExists(db, "project_registry")) return null;
141
- return safeGet(db, "SELECT * FROM project_registry WHERE lower(name)=lower(?) LIMIT 1", [project]);
142
- }
143
-
144
- function selectProjectRules(db, project) {
145
- if (!tableExists(db, "project_rules")) return null;
146
- return safeGet(db, "SELECT * FROM project_rules WHERE lower(project)=lower(?) LIMIT 1", [project]);
147
- }
148
-
149
- function selectSiteContract(db, project) {
150
- if (!tableExists(db, "site_contract")) return null;
151
- return safeGet(db, "SELECT * FROM site_contract WHERE lower(project)=lower(?) LIMIT 1", [project]);
152
- }
153
-
154
- function selectLatestGoldenCheck(db, project) {
155
- if (!tableExists(db, "golden_check_run")) return null;
156
- return safeGet(db, "SELECT id, project, agent_name, status, command, summary, evidence_json, findings_json, created_at FROM golden_check_run WHERE lower(project)=lower(?) ORDER BY created_at DESC LIMIT 1", [project]);
157
- }
158
-
159
- function selectOpenFindings(db, project, limit) {
160
- if (!tableExists(db, "quality_finding")) return [];
161
- return safeAll(db, `
162
- SELECT id, project, category, severity, title, url, expected, actual, status, source_agent, updated_at, created_at
163
- FROM quality_finding
164
- WHERE lower(project)=lower(?)
165
- AND COALESCE(status,'open') NOT IN ('resolved','closed','done')
166
- ORDER BY CASE lower(severity)
167
- WHEN 'critical' THEN 0 WHEN 'crit' THEN 0 WHEN 'c' THEN 0 WHEN 'p0' THEN 0
168
- WHEN 'high' THEN 1 WHEN 'h' THEN 1 WHEN 'p1' THEN 1
169
- WHEN 'medium' THEN 2 WHEN 'm' THEN 2 WHEN 'p2' THEN 2
170
- ELSE 3 END, updated_at DESC
171
- LIMIT ?`, [project, limit]);
172
- }
173
-
174
- function selectActiveClaims(db, project, limit) {
175
- if (!tableExists(db, "work_claim")) return [];
176
- return safeAll(db, `
177
- SELECT id, project, file_path, agent_name, summary, claimed_at, expires_at, status
178
- FROM work_claim
179
- WHERE lower(project)=lower(?)
180
- AND COALESCE(status,'active')='active'
181
- AND (expires_at IS NULL OR expires_at > strftime('%Y-%m-%dT%H:%M:%fZ','now'))
182
- ORDER BY expires_at ASC
183
- LIMIT ?`, [project, limit]);
184
- }
185
-
186
- function selectAutonomyTasks(db, project, limit) {
187
- if (!tableExists(db, "autonomy_task")) return [];
188
- return safeAll(db, `
189
- SELECT id, project, department_name, title, category, severity, status, assigned_agent, reviewer_agent, updated_at, created_at
190
- FROM autonomy_task
191
- WHERE lower(project)=lower(?)
192
- AND COALESCE(status,'open') NOT IN ('done','closed','resolved')
193
- ORDER BY CASE lower(severity)
194
- WHEN 'critical' THEN 0 WHEN 'crit' THEN 0 WHEN 'c' THEN 0 WHEN 'p0' THEN 0
195
- WHEN 'high' THEN 1 WHEN 'h' THEN 1 WHEN 'p1' THEN 1
196
- WHEN 'medium' THEN 2 WHEN 'm' THEN 2 WHEN 'p2' THEN 2
197
- ELSE 3 END, updated_at DESC
198
- LIMIT ?`, [project, limit]);
199
- }
200
-
201
- function selectDepartmentCoverage(db, project) {
202
- if (!tableExists(db, "autonomy_task")) return [];
203
- return safeAll(db, `
204
- SELECT department_name, status, COUNT(*) AS count
205
- FROM autonomy_task
206
- WHERE lower(project)=lower(?)
207
- GROUP BY department_name, status
208
- ORDER BY department_name ASC, status ASC`, [project]);
209
- }
210
-
211
- function selectPendingBriefs(db, project, agentName, limit) {
212
- if (!tableExists(db, "agent_brief")) return [];
213
- const params = [];
214
- const where = ["status IN ('pending','dispatched')"];
215
- if (agentName) {
216
- where.push("lower(agent_name)=lower(?)");
217
- params.push(agentName);
218
- }
219
- where.push("(content LIKE ? OR meta_json LIKE ?)");
220
- params.push(like(project), like(project));
221
- params.push(limit);
222
- return safeAll(db, `
223
- SELECT id, agent_name, source_agent, status, created_at, dispatched_at, substr(content,1,260) AS preview
224
- FROM agent_brief
225
- WHERE ${where.join(" AND ")}
226
- ORDER BY created_at DESC
227
- LIMIT ?`, params);
228
- }
229
-
230
- function selectRecentHandoffs(db, project, agentName, sinceIso, limit) {
231
- if (!tableExists(db, "session_handoff")) return [];
232
- const params = [sinceIso, project, like(project), like(project)];
233
- const where = [
234
- "created_at >= ?",
235
- "(lower(project)=lower(?) OR summary LIKE ? OR meta_json LIKE ?)",
236
- ];
237
- if (agentName) {
238
- where.push("lower(agent_name)=lower(?)");
239
- params.push(agentName);
240
- }
241
- params.push(limit);
242
- return safeAll(db, `
243
- SELECT id, agent_name, project, summary, changed_files, tests, deploys, blockers, next_actions, created_at
244
- FROM session_handoff
245
- WHERE ${where.join(" AND ")}
246
- ORDER BY created_at DESC
247
- LIMIT ?`, params);
248
- }
249
-
250
- function selectRecentDecisions(db, project, sinceIso, limit) {
251
- if (!tableExists(db, "decision_log")) return [];
252
- return safeAll(db, `
253
- SELECT id, scope, title, substr(body,1,320) AS body, decided_by, decided_at, status, files_affected, entities_affected
254
- FROM decision_log
255
- WHERE decided_at >= ?
256
- AND COALESCE(status,'active')='active'
257
- AND (lower(scope)=lower(?) OR title LIKE ? OR body LIKE ? OR files_affected LIKE ? OR entities_affected LIKE ?)
258
- ORDER BY decided_at DESC
259
- LIMIT ?`, [sinceIso, project, like(project), like(project), like(project), like(project), limit]);
260
- }
261
-
262
- function selectRecentActions(db, project, agentName, sinceIso, limit) {
263
- if (!tableExists(db, "agent_action")) return [];
264
- const params = [sinceIso, project, like(project), like(project), like(project), like(project), like(project)];
265
- const where = [
266
- "started_at >= ?",
267
- "(lower(target)=lower(?) OR target LIKE ? OR topic LIKE ? OR payload_json LIKE ? OR result_json LIKE ? OR meta_json LIKE ?)",
268
- ];
269
- if (agentName) {
270
- where.push("lower(agent_name)=lower(?)");
271
- params.push(agentName);
272
- }
273
- params.push(limit);
274
- return safeAll(db, `
275
- SELECT id, agent_name, action_kind, target, status, topic, started_at, finished_at
276
- FROM agent_action
277
- WHERE ${where.join(" AND ")}
278
- ORDER BY started_at DESC
279
- LIMIT ?`, params);
280
- }
281
-
282
- function selectMemorySnippets(db, project, sinceIso, limit) {
283
- if (!tableExists(db, "memory")) return [];
284
- return safeAll(db, `
285
- SELECT id, kind, actor, topic, importance, occurred_at, substr(text,1,300) AS preview
286
- FROM memory
287
- WHERE occurred_at >= ?
288
- AND (topic LIKE ? OR text LIKE ?)
289
- ORDER BY importance DESC, occurred_at DESC
290
- LIMIT ?`, [sinceIso, like(project), like(project), limit]);
291
- }
292
-
293
- function buildTimeline(data) {
294
- const events = [];
295
- const max = Math.max(6, data.maxItems * 3);
296
- addEvent(events, "registry", data.registry && data.registry.updated_at, "project registry updated", data.registry && data.registry.live_status, data.registry && data.registry.updated_by);
297
- addEvent(events, "rules", data.rules && data.rules.updated_at, "project rules updated", data.rules && data.rules.notes, data.rules && data.rules.updated_by);
298
- addEvent(events, "site_contract", data.siteContract && data.siteContract.updated_at, "site contract updated", data.siteContract && data.siteContract.notes, data.siteContract && data.siteContract.updated_by);
299
- addEvent(events, "golden_check", data.latestGolden && data.latestGolden.created_at, "latest golden check", data.latestGolden && `${data.latestGolden.status}: ${data.latestGolden.summary || ""}`, data.latestGolden && data.latestGolden.agent_name);
300
-
301
- for (const row of data.openFindings || []) addEvent(events, "finding", row.updated_at || row.created_at, row.title, `${row.severity || ""} ${row.category || ""} ${row.status || ""}`, row.source_agent, row.id);
302
- for (const row of data.activeClaims || []) addEvent(events, "claim", row.claimed_at, row.file_path || row.summary, row.summary, row.agent_name, row.id);
303
- for (const row of data.autonomyTasks || []) addEvent(events, "autonomy_task", row.updated_at || row.created_at, row.title, `${row.department_name || ""} ${row.status || ""}`, row.assigned_agent, row.id);
304
- for (const row of data.pendingBriefs || []) addEvent(events, "brief", row.created_at, row.preview, row.status, row.agent_name, row.id);
305
- for (const row of data.handoffs || []) addEvent(events, "handoff", row.created_at, row.summary, row.next_actions || row.blockers, row.agent_name, row.id);
306
- for (const row of data.decisions || []) addEvent(events, "decision", row.decided_at, row.title, row.body, row.decided_by, row.id);
307
- for (const row of data.actions || []) addEvent(events, "action", row.started_at, row.action_kind || row.topic || row.target, row.status, row.agent_name, row.id);
308
- for (const row of data.memories || []) addEvent(events, "memory", row.occurred_at, row.preview, row.topic, row.actor, row.id);
309
-
310
- return events
311
- .filter((event) => event.at)
312
- .sort((a, b) => Date.parse(b.at) - Date.parse(a.at))
313
- .slice(0, max)
314
- .map((event) => redactRow(event));
315
- }
316
-
317
- function addEvent(events, kind, at, title, detail, actor, refId) {
318
- if (!at || !title) return;
319
- events.push({
320
- at,
321
- kind,
322
- title: clean(title, 180),
323
- detail: clean(detail, 220),
324
- actor: actor || null,
325
- ref_id: refId || null,
326
- });
327
- }
328
-
329
- function deriveLiveReadiness(data) {
330
- const checklist = parseMaybeJson(data.registry && data.registry.health_checklist, {});
331
- const missingBlocks = parseList(data.registry && data.registry.missing_blocks);
332
- const requiredGates = collectRequiredGates(data.rules, data.siteContract, data.liveFocus);
333
- const gateRows = requiredGates.map((gate) => {
334
- const state = gateStatus(gate, checklist);
335
- return {
336
- gate,
337
- status: state.status,
338
- source: state.source,
339
- value: state.value === undefined ? null : state.value,
340
- };
341
- });
342
- const requirements = standardRequirements(data.registry, data.rules, data.siteContract, checklist);
343
- const blockers = [];
344
- const warnings = [];
345
-
346
- if (!data.registry) {
347
- blockers.push(makeIssue("missing_project_registry", "critical", "No project_registry row exists.", "Create or seed project_registry before assigning live work."));
348
- }
349
- if (!data.rules) {
350
- blockers.push(makeIssue("missing_project_rules", "high", "No project_rules row exists.", "Create project rules for nav, auth, language, pricing, checkout, VAT, design, deploy and required gates."));
351
- }
352
- if (data.liveFocus && !data.siteContract) {
353
- warnings.push(makeIssue("missing_site_contract", "medium", "No site_contract row exists.", "Store canonical URLs, paths, forbidden hosts, locales, header/menu/footer/logo/auth/pricing/checkout checks."));
354
- }
355
- for (const item of missingBlocks) {
356
- blockers.push(makeIssue("registry_missing_block", "high", clean(item, 160), "Clear missing_blocks in project_registry only after evidence exists."));
357
- }
358
- for (const gate of gateRows) {
359
- if (gate.status === "block") blockers.push(makeIssue(`gate_blocked:${gate.gate}`, "high", `Required gate '${gate.gate}' is blocked.`, "Fix the gate and update project_registry.health_checklist."));
360
- if (gate.status === "unknown") warnings.push(makeIssue(`gate_unknown:${gate.gate}`, "medium", `Required gate '${gate.gate}' is unknown.`, "Run the check and record pass/fail in project_registry.health_checklist."));
361
- }
362
- for (const requirement of requirements) {
363
- if (requirement.status === "block") blockers.push(makeIssue(`requirement_blocked:${requirement.key}`, "high", `${requirement.label} is blocked.`, requirement.next_action));
364
- if (requirement.status === "unknown") warnings.push(makeIssue(`requirement_unknown:${requirement.key}`, "medium", `${requirement.label} is not documented.`, requirement.next_action));
365
- }
366
- for (const finding of data.openFindings || []) {
367
- if (isHighSeverity(finding.severity)) {
368
- blockers.push(makeIssue(`finding:${finding.id}`, severityName(finding.severity), finding.title, "Fix the finding, capture verification, then mark it resolved."));
369
- }
370
- }
371
- if (data.latestGolden) {
372
- const status = String(data.latestGolden.status || "").toLowerCase();
373
- if (["fail", "failed", "block", "blocked", "red"].includes(status)) {
374
- blockers.push(makeIssue("golden_check_failed", "high", data.latestGolden.summary || "Latest golden check failed.", "Fix failures and persist a passing mem_site_golden_check_report."));
375
- } else if (!["pass", "passed", "ok", "green", "approved"].includes(status)) {
376
- warnings.push(makeIssue("golden_check_unclear", "medium", `Latest golden check status is '${data.latestGolden.status}'.`, "Run a fresh golden check with clear pass/fail evidence."));
377
- }
378
- } else if (data.liveFocus) {
379
- warnings.push(makeIssue("golden_check_missing", "medium", "No golden check history found.", "Run mem_site_golden_check_plan, execute checks, then store mem_site_golden_check_report."));
380
- }
381
- if ((data.activeClaims || []).length) {
382
- warnings.push(makeIssue("active_claims", "medium", `${data.activeClaims.length} active work claim(s) exist.`, "Wait for release or coordinate before marking the project ready."));
383
- }
384
- if ((data.autonomyTasks || []).some((task) => ["blocked", "review"].includes(String(task.status || "").toLowerCase()))) {
385
- warnings.push(makeIssue("autonomy_review_or_blocked", "medium", "Autonomy tasks are still blocked or waiting for review.", "Route blocked/review tasks to their reviewer before live sign-off."));
386
- }
387
-
388
- const passedGates = gateRows.filter((gate) => gate.status === "pass").map((gate) => gate.gate);
389
- const blockedGates = gateRows.filter((gate) => gate.status === "block").map((gate) => gate.gate);
390
- const unknownGates = gateRows.filter((gate) => gate.status === "unknown").map((gate) => gate.gate);
391
- const status = blockers.length ? "block" : (warnings.length || unknownGates.length ? "attention" : "ready");
392
- const readinessPercent = Math.max(0, Math.min(100, 100 - blockers.length * 18 - warnings.length * 6 - unknownGates.length * 3));
393
-
394
- return {
395
- status,
396
- readiness_percent: readinessPercent,
397
- required_gates: requiredGates,
398
- gate_status: gateRows,
399
- requirements,
400
- passed_gates: passedGates,
401
- blocked_gates: blockedGates,
402
- unknown_gates: unknownGates,
403
- blockers: uniqueIssues(blockers),
404
- warnings: uniqueIssues(warnings),
405
- };
406
- }
407
-
408
- function collectRequiredGates(rules, siteContract, liveFocus) {
409
- const fromRules = parseList(rules && rules.required_gates);
410
- if (fromRules.length) return unique(fromRules.map((item) => clean(item, 80)).filter(Boolean));
411
- const fromSite = parseList(siteContract && siteContract.required_checks);
412
- if (fromSite.length) return unique(fromSite.map((item) => clean(item, 80)).filter(Boolean));
413
- if (!liveFocus) return ["planning", "implementation", "review"];
414
- return [
415
- "nav",
416
- "links",
417
- "header_footer",
418
- "logo",
419
- "mobile",
420
- "i18n",
421
- "auth",
422
- "pricing",
423
- "checkout",
424
- "vat",
425
- "legal",
426
- "deploy",
427
- "monitoring",
428
- ];
429
- }
430
-
431
- function standardRequirements(registry, rules, siteContract, checklist) {
432
- const defs = [
433
- { key: "nav", label: "Navigation/menu contract", fields: [rules && rules.canonical_nav, siteContract && siteContract.menu_rules], gates: ["nav", "menu", "navigation"], next: "Document canonical menu links and verify every locale/domain." },
434
- { key: "header_footer", label: "Header/footer consistency", fields: [siteContract && siteContract.header_rules, siteContract && siteContract.footer_rules], gates: ["header_footer", "header", "footer"], next: "Store header/footer rules and prove pages match the canonical shell." },
435
- { key: "logo", label: "Logo and dark-mode assets", fields: [siteContract && siteContract.logo_rules], gates: ["logo", "dark_logo", "darkmode_logo"], next: "Document logo rules including light/dark variants and verify them visually." },
436
- { key: "links", label: "Internal/legal links", fields: [siteContract && siteContract.paths, siteContract && siteContract.forbidden_hosts], gates: ["links", "legal_links", "forbidden_hosts"], next: "Run link checks for all stored paths/locales and remove forbidden cross-domain links." },
437
- { key: "mobile", label: "Mobile responsiveness", fields: [siteContract && siteContract.mobile_viewports], gates: ["mobile", "responsive"], next: "Run mobile viewport checks and store evidence." },
438
- { key: "i18n", label: "Language parity", fields: [registry && registry.langs, rules && rules.language_matrix, siteContract && siteContract.required_locales], gates: ["i18n", "language", "languages", "locales"], next: "Store required locales and verify every menu/legal/pricing path in each language." },
439
- { key: "auth", label: "Auth crossover", fields: [registry && registry.auth_system, rules && rules.auth_matrix, siteContract && siteContract.auth_rules], gates: ["auth", "login", "sso"], next: "Document shared auth rules and test one login across all related surfaces." },
440
- { key: "pricing", label: "Pricing source of truth", fields: [rules && rules.pricing_rules, siteContract && siteContract.pricing_rules], gates: ["pricing", "prices"], next: "Store pricing rules and verify every page displaying prices uses the same source." },
441
- { key: "checkout", label: "Checkout and billing", fields: [registry && registry.stripe_product_ids, rules && rules.checkout_rules, siteContract && siteContract.checkout_rules], gates: ["checkout", "billing", "stripe"], next: "Document checkout flow, product IDs, webhooks, and customer self-service checks." },
442
- { key: "vat", label: "VAT/OSS handling", fields: [registry && registry.vat_status, rules && rules.vat_rules], gates: ["vat", "oss", "tax"], next: "Record VAT/OSS decision and where VAT checks are already implemented." },
443
- { key: "deploy", label: "Deploy and rollback", fields: [registry && registry.server, registry && registry.pm2_processes, registry && registry.nginx_files, rules && rules.deploy_rules], gates: ["deploy", "server", "rollback"], next: "Record server/process/proxy coordinates and deploy/rollback rule." },
444
- { key: "legal", label: "Legal pages and public claims", fields: [siteContract && siteContract.paths, rules && rules.notes], gates: ["legal", "privacy", "terms", "impressum"], next: "Verify legal pages, locale routing, and public claims before launch." },
445
- ];
446
- return defs.map((def) => evaluateRequirement(def, checklist));
447
- }
448
-
449
- function evaluateRequirement(def, checklist) {
450
- const gate = firstGateStatus(def.gates, checklist);
451
- if (gate.status === "block") {
452
- return { key: def.key, label: def.label, status: "block", source: gate.source, next_action: def.next };
453
- }
454
- if (gate.status === "pass") {
455
- return { key: def.key, label: def.label, status: "pass", source: gate.source, next_action: null };
456
- }
457
- const hasField = (def.fields || []).some((value) => hasMeaningfulValue(value));
458
- return {
459
- key: def.key,
460
- label: def.label,
461
- status: hasField ? "documented" : "unknown",
462
- source: hasField ? "registry/rules/site_contract" : "missing",
463
- next_action: hasField ? null : def.next,
464
- };
465
- }
466
-
467
- function firstGateStatus(keys, checklist) {
468
- for (const key of keys || []) {
469
- const status = gateStatus(key, checklist);
470
- if (status.status !== "unknown") return status;
471
- }
472
- return { status: "unknown", source: "health_checklist", value: null };
473
- }
474
-
475
- function gateStatus(gate, checklist) {
476
- const normalized = normalizeKey(gate);
477
- if (!checklist || typeof checklist !== "object" || Array.isArray(checklist)) {
478
- return { status: "unknown", source: "health_checklist", value: null };
479
- }
480
- for (const [key, value] of Object.entries(checklist)) {
481
- if (normalizeKey(key) !== normalized) continue;
482
- return { status: normalizeStatus(value), source: `health_checklist.${key}`, value: redactValue(value) };
483
- }
484
- return { status: "unknown", source: "health_checklist", value: null };
485
- }
486
-
487
- function normalizeStatus(value) {
488
- if (value === true) return "pass";
489
- if (value === false) return "block";
490
- if (value && typeof value === "object" && !Array.isArray(value)) {
491
- if ("status" in value) return normalizeStatus(value.status);
492
- if ("passed" in value) return normalizeStatus(value.passed);
493
- if ("ok" in value) return normalizeStatus(value.ok);
494
- if ("done" in value) return normalizeStatus(value.done);
495
- }
496
- const text = String(value == null ? "" : value).toLowerCase().trim();
497
- if (["pass", "passed", "ok", "done", "green", "approved", "true", "yes", "ready"].includes(text)) return "pass";
498
- if (["block", "blocked", "fail", "failed", "red", "missing", "false", "no", "broken"].includes(text)) return "block";
499
- return "unknown";
500
- }
501
-
502
- function deriveNextActions(readiness, data) {
503
- const actions = [];
504
- for (const issue of readiness.blockers.slice(0, 8)) {
505
- actions.push({ priority: "P0", source: issue.id, action: issue.next_action || issue.title });
506
- }
507
- for (const issue of readiness.warnings.slice(0, 8)) {
508
- actions.push({ priority: "P1", source: issue.id, action: issue.next_action || issue.title });
509
- }
510
- for (const finding of (data.openFindings || []).filter((row) => !isHighSeverity(row.severity)).slice(0, 5)) {
511
- actions.push({ priority: "P2", source: `finding:${finding.id}`, action: `Resolve ${finding.category || "finding"}: ${clean(finding.title, 140)}` });
512
- }
513
- for (const task of (data.autonomyTasks || []).slice(0, 5)) {
514
- actions.push({ priority: task.status === "blocked" ? "P1" : "P2", source: `autonomy_task:${task.id}`, action: `${task.department_name || "department"}: ${clean(task.title, 140)}` });
515
- }
516
- if (!actions.length && readiness.status === "ready") {
517
- actions.push({ priority: "P1", source: "review", action: "Run final reviewer pass with site golden checks, deploy evidence, and handoff capture." });
518
- }
519
- return uniqueActions(actions).slice(0, 12);
520
- }
521
-
522
- function renderReport(report, tokenBudget) {
523
- const lines = [];
524
- lines.push(`# Project timeline report: ${report.project}`);
525
- lines.push("");
526
- lines.push(`Generated: ${report.generated_at}`);
527
- lines.push(`Window: ${report.days} days`);
528
- lines.push(`Status: ${report.summary.status} (${report.summary.readiness_percent}%)`);
529
- lines.push(`Open: ${report.summary.open_findings} finding(s), ${report.summary.active_claims} active claim(s), ${report.summary.autonomy_open_or_review} autonomy task(s), ${report.summary.pending_or_dispatched_briefs} brief(s)`);
530
- lines.push("");
531
-
532
- lines.push("## Live readiness");
533
- addIssueLines(lines, "Blockers", report.live_readiness.blockers);
534
- addIssueLines(lines, "Warnings", report.live_readiness.warnings);
535
- lines.push(`Passed gates: ${report.live_readiness.passed_gates.join(", ") || "none"}`);
536
- lines.push(`Unknown gates: ${report.live_readiness.unknown_gates.join(", ") || "none"}`);
537
- lines.push("");
538
-
539
- lines.push("## Next actions");
540
- if (report.next_actions.length) {
541
- for (const action of report.next_actions) lines.push(`- ${action.priority} ${action.source}: ${action.action}`);
542
- } else {
543
- lines.push("- No next action detected.");
544
- }
545
- lines.push("");
546
-
547
- lines.push("## Project coordinates");
548
- const registry = report.sections.registry;
549
- if (registry) {
550
- pushKV(lines, "Domain", registry.domain);
551
- pushKV(lines, "Live URL", registry.live_url);
552
- pushKV(lines, "Staging URL", registry.staging_url);
553
- pushKV(lines, "Repo", registry.repo);
554
- pushKV(lines, "Server", registry.server);
555
- pushKV(lines, "Auth", registry.auth_system);
556
- pushKV(lines, "VAT", registry.vat_status);
557
- pushKV(lines, "Languages", registry.langs);
558
- pushKV(lines, "Live status", registry.live_status);
559
- } else {
560
- lines.push("- No registry row.");
561
- }
562
- lines.push("");
563
-
564
- lines.push("## Requirement map");
565
- for (const requirement of report.live_readiness.requirements) {
566
- lines.push(`- ${requirement.key}: ${requirement.status}${requirement.source ? ` (${requirement.source})` : ""}`);
567
- }
568
- lines.push("");
569
-
570
- renderTable(lines, "Open findings", report.sections.open_findings, (row) => `${row.severity || ""} ${row.category || ""} #${row.id}: ${row.title}${row.url ? ` (${row.url})` : ""}`);
571
- renderTable(lines, "Active claims", report.sections.active_claims, (row) => `${row.agent_name || "agent"} ${row.file_path || ""}: ${row.summary || ""}`);
572
- renderTable(lines, "Autonomy tasks", report.sections.autonomy_tasks, (row) => `${row.severity || ""} ${row.status || ""} ${row.department_name || ""} #${row.id}: ${row.title}`);
573
- renderTable(lines, "Pending/dispatched briefs", report.sections.pending_briefs, (row) => `${row.status || ""} ${row.agent_name || ""} #${row.id}: ${row.preview || ""}`);
574
- renderTable(lines, "Recent handoffs", report.sections.recent_handoffs, (row) => `${row.created_at || ""} ${row.agent_name || ""}: ${row.summary || ""}`);
575
- renderTable(lines, "Recent decisions", report.sections.recent_decisions, (row) => `${row.decided_at || ""} #${row.id}: ${row.title}`);
576
- renderTable(lines, "Timeline", report.sections.timeline, (row) => `${row.at || ""} ${row.kind || ""}: ${row.title || ""}${row.actor ? ` (${row.actor})` : ""}`);
577
-
578
- let doc = lines.join("\n");
579
- const maxChars = Math.max(1200, tokenBudget * 4);
580
- let truncated = false;
581
- if (doc.length > maxChars) {
582
- doc = doc.slice(0, maxChars - 120).trimEnd() + "\n\n[truncated: raise token_budget or lower max_items for a smaller report]";
583
- truncated = true;
584
- }
585
- return { doc, estimated_tokens: estimateTokens(doc), truncated };
586
- }
587
-
588
- function addIssueLines(lines, title, issues) {
589
- lines.push(`${title}:`);
590
- if (!issues || !issues.length) {
591
- lines.push("- none");
592
- return;
593
- }
594
- for (const issue of issues) {
595
- lines.push(`- ${issue.severity || "medium"} ${issue.id}: ${issue.title}${issue.next_action ? ` -> ${issue.next_action}` : ""}`);
596
- }
597
- }
598
-
599
- function renderTable(lines, title, rows, formatter) {
600
- lines.push(`## ${title}`);
601
- if (!rows || !rows.length) {
602
- lines.push("- none");
603
- lines.push("");
604
- return;
605
- }
606
- for (const row of rows) lines.push(`- ${clean(formatter(row), 320)}`);
607
- lines.push("");
608
- }
609
-
610
- function pushKV(lines, key, value) {
611
- if (hasMeaningfulValue(value)) lines.push(`- ${key}: ${clean(renderValue(value), 260)}`);
612
- }
613
-
614
- function makeIssue(id, severity, title, nextAction) {
615
- return {
616
- id,
617
- severity: severity || "medium",
618
- title: clean(title, 220),
619
- next_action: clean(nextAction, 240),
620
- };
621
- }
622
-
623
- function uniqueIssues(issues) {
624
- const seen = new Set();
625
- const out = [];
626
- for (const issue of issues || []) {
627
- const key = issue.id || issue.title;
628
- if (!key || seen.has(key)) continue;
629
- seen.add(key);
630
- out.push(issue);
631
- }
632
- return out;
633
- }
634
-
635
- function uniqueActions(actions) {
636
- const seen = new Set();
637
- const out = [];
638
- for (const action of actions || []) {
639
- const key = `${action.priority}:${action.source}:${action.action}`;
640
- if (seen.has(key)) continue;
641
- seen.add(key);
642
- out.push(action);
643
- }
644
- return out;
645
- }
646
-
647
- function redactRuleRow(row) {
648
- const out = redactRow(row);
649
- for (const key of ["canonical_nav", "allowed_domains", "auth_matrix", "language_matrix", "pricing_rules", "checkout_rules", "vat_rules", "deploy_rules", "design_rules", "required_gates"]) {
650
- if (out[key]) out[key] = summarizeJsonish(out[key], 420);
651
- }
652
- return out;
653
- }
654
-
655
- function redactSiteContract(row) {
656
- const out = redactRow(row);
657
- for (const key of ["target_urls", "paths", "forbidden_hosts", "required_locales", "mobile_viewports", "desktop_viewports", "required_checks"]) {
658
- if (out[key]) out[key] = summarizeJsonish(out[key], 300);
659
- }
660
- for (const key of ["header_rules", "menu_rules", "footer_rules", "logo_rules", "auth_rules", "pricing_rules", "checkout_rules"]) {
661
- if (out[key]) out[key] = summarizeJsonish(out[key], 420);
662
- }
663
- return out;
664
- }
665
-
666
- function summarizeJsonish(value, max) {
667
- const parsed = parseMaybeJson(value, null);
668
- if (parsed == null || parsed === value) return redact(value, max);
669
- if (Array.isArray(parsed)) return parsed.slice(0, 12).map((item) => redactValue(item));
670
- if (parsed && typeof parsed === "object") {
671
- const out = {};
672
- for (const key of Object.keys(parsed).slice(0, 12)) out[key] = redactValue(parsed[key]);
673
- return out;
674
- }
675
- return parsed;
676
- }
677
-
678
- function redactRow(row) {
679
- const out = {};
680
- for (const [key, value] of Object.entries(row || {})) out[key] = redactValue(value);
681
- return out;
682
- }
683
-
684
- function redactValue(value) {
685
- if (typeof value === "string") return redact(value, 420);
686
- if (Array.isArray(value)) return value.slice(0, 20).map(redactValue);
687
- if (value && typeof value === "object") {
688
- const out = {};
689
- for (const [key, item] of Object.entries(value).slice(0, 20)) out[key] = redactValue(item);
690
- return out;
691
- }
692
- return value;
693
- }
694
-
695
- function parseList(value) {
696
- const parsed = parseMaybeJson(value, value);
697
- if (!parsed) return [];
698
- if (Array.isArray(parsed)) return parsed.map((item) => renderValue(item)).filter(Boolean);
699
- if (parsed && typeof parsed === "object") return Object.keys(parsed).filter(Boolean);
700
- return String(parsed)
701
- .split(/[\n,;|]/)
702
- .map((item) => clean(item, 120))
703
- .filter(Boolean)
704
- .filter((item) => item !== "[]" && item !== "{}");
705
- }
706
-
707
- function renderValue(value) {
708
- if (value == null) return "";
709
- if (typeof value === "string") return value;
710
- if (typeof value === "number" || typeof value === "boolean") return String(value);
711
- try { return JSON.stringify(value); } catch { return String(value); }
712
- }
713
-
714
- function hasMeaningfulValue(value) {
715
- if (value == null) return false;
716
- if (typeof value === "boolean") return value;
717
- if (typeof value === "number") return true;
718
- const text = String(value).trim();
719
- if (!text || text === "[]" || text === "{}" || text.toLowerCase() === "null") return false;
720
- return true;
721
- }
722
-
723
- function normalizeKey(value) {
724
- return String(value || "").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
725
- }
726
-
727
- function severityName(value) {
728
- const text = String(value || "").toLowerCase();
729
- if (["critical", "crit", "c", "p0"].includes(text)) return "critical";
730
- if (["high", "h", "p1"].includes(text)) return "high";
731
- if (["medium", "m", "p2"].includes(text)) return "medium";
732
- return text || "low";
733
- }
734
-
735
- function isHighSeverity(value) {
736
- return ["critical", "crit", "c", "p0", "high", "h", "p1"].includes(String(value || "").toLowerCase());
737
- }
738
-
739
- function severityRank(value) {
740
- const text = String(value || "").toLowerCase();
741
- if (["critical", "crit", "c", "p0"].includes(text)) return 0;
742
- if (["high", "h", "p1"].includes(text)) return 1;
743
- if (["medium", "m", "p2"].includes(text)) return 2;
744
- return 3;
745
- }
746
-
747
- function safeGet(db, sql, params) {
748
- try {
749
- return db.prepare(sql).get(...(params || [])) || null;
750
- } catch {
751
- return null;
752
- }
753
- }
754
-
755
- function safeAll(db, sql, params) {
756
- try {
757
- return db.prepare(sql).all(...(params || []));
758
- } catch {
759
- return [];
760
- }
761
- }
762
-
763
- function tableExists(db, name) {
764
- try { return !!db.prepare("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name=?").get(name); } catch { return false; }
765
- }
766
-
767
- function clean(value, max) {
768
- const text = String(value || "").replace(/\s+/g, " ").trim();
769
- if (!text) return "";
770
- if (!max || text.length <= max) return text;
771
- return text.slice(0, max - 1).trimEnd() + "...";
772
- }
773
-
774
- function normalizeAgentId(value) {
775
- return String(value || "").trim().toLowerCase();
776
- }
777
-
778
- function clampInt(value, fallback, min, max) {
779
- const parsed = Number.parseInt(value, 10);
780
- if (!Number.isFinite(parsed)) return fallback;
781
- return Math.max(min, Math.min(max, parsed));
782
- }
783
-
784
- function like(term) {
785
- return `%${String(term || "").replace(/[%_]/g, "")}%`;
786
- }
787
-
788
- function unique(items) {
789
- return Array.from(new Set((items || []).filter(Boolean)));
790
- }
791
-
792
- function estimateTokens(text) {
793
- return Math.ceil(String(text || "").length / 4);
794
- }
795
-
796
- function redact(value, max) {
797
- let text = String(value || "");
798
- text = text.replace(/<private>[\s\S]*?<\/private>/gi, "[private]");
799
- text = text.replace(/\b(sk|pk|rk|ghp|gho|github_pat)_[A-Za-z0-9_=-]{12,}\b/g, "[secret]");
800
- text = text.replace(/\b(password|passwd|token|secret|api[_-]?key)\s*[:=]\s*[^,\s;}]+/gi, "$1=[secret]");
801
- text = text.replace(/\s+/g, " ").trim();
802
- if (!text || !max || text.length <= max) return text;
803
- return text.slice(0, max - 1).trimEnd() + "...";
804
- }
805
-
806
- module.exports = {
807
- TIMELINE_REPORT_TOOL_DEFS,
808
- handleTimelineReportTool,
809
- projectTimelineReport,
810
- };