@hawkeyexl/manni 4.11.0 → 4.12.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/README.md +1 -1
  2. package/dist/{batch-UAULUMGH.js → batch-EFSFG6GC.js} +20 -19
  3. package/dist/build-NIO3UIWJ.js +36 -0
  4. package/dist/calibrate-6VO7URRV.js +41 -0
  5. package/dist/capture-NMBVJO3C.js +38 -0
  6. package/dist/check-SHOYX2B5.js +30 -0
  7. package/dist/check-XMJKH3KV.js +34 -0
  8. package/dist/{check-VELUQAUW.js → check-Y62BJNC4.js} +35 -34
  9. package/dist/{check-VELUQAUW.js.map → check-Y62BJNC4.js.map} +1 -1
  10. package/dist/{check-YEOYBFST.js → check-ZMO3ZLMW.js} +19 -18
  11. package/dist/{chunk-BKVHX6FU.js → chunk-24AJK2RG.js} +5 -10
  12. package/dist/chunk-24AJK2RG.js.map +1 -0
  13. package/dist/{chunk-M42DZCOU.js → chunk-2OZF2VUB.js} +2 -2
  14. package/dist/chunk-2UJZXVHR.js +1868 -0
  15. package/dist/chunk-2UJZXVHR.js.map +1 -0
  16. package/dist/{chunk-HQR2ZBHW.js → chunk-3BRJCQPY.js} +36 -7
  17. package/dist/chunk-3BRJCQPY.js.map +1 -0
  18. package/dist/{chunk-U7CTFN2J.js → chunk-42VFJOAF.js} +7 -7
  19. package/dist/{chunk-LBSCW232.js → chunk-4Q24OYI3.js} +7 -7
  20. package/dist/{chunk-OPXWPJDA.js → chunk-4WJTURRO.js} +14 -14
  21. package/dist/{chunk-GDVZ5VII.js → chunk-5SID2SVL.js} +4 -4
  22. package/dist/{chunk-FUCPZVRY.js → chunk-AANUY4BH.js} +2 -2
  23. package/dist/chunk-ANPIIYRH.js +2272 -0
  24. package/dist/chunk-ANPIIYRH.js.map +1 -0
  25. package/dist/{chunk-WDWXAYVH.js → chunk-AYVKN3PG.js} +4 -4
  26. package/dist/{chunk-FQXWVS6J.js → chunk-CH6IOGXV.js} +9 -9
  27. package/dist/{chunk-4CK6ZSOK.js → chunk-D5Z6B4M7.js} +3 -3
  28. package/dist/{chunk-HA6MQMOY.js → chunk-D6SELXQ2.js} +6 -6
  29. package/dist/{chunk-2DRHT73U.js → chunk-DDILEF5F.js} +890 -1399
  30. package/dist/chunk-DDILEF5F.js.map +1 -0
  31. package/dist/{chunk-PCS4VJBV.js → chunk-DGRLHDM4.js} +9 -9
  32. package/dist/{chunk-2MJ62AYQ.js → chunk-DHGB4JBG.js} +4 -3
  33. package/dist/chunk-DHGB4JBG.js.map +1 -0
  34. package/dist/{chunk-Y6DOMTQD.js → chunk-DLU5FCFT.js} +27 -27
  35. package/dist/chunk-DLU5FCFT.js.map +1 -0
  36. package/dist/chunk-DSWKBZWW.js +16 -0
  37. package/dist/chunk-DSWKBZWW.js.map +1 -0
  38. package/dist/{chunk-KGEQJ5CC.js → chunk-F564FHMQ.js} +8 -8
  39. package/dist/{chunk-J6IDQGJL.js → chunk-FKAZUZQU.js} +469 -85
  40. package/dist/chunk-FKAZUZQU.js.map +1 -0
  41. package/dist/{chunk-IGSHYP74.js → chunk-G3MBUL5M.js} +4 -4
  42. package/dist/{chunk-ADMEPUBT.js → chunk-GQ3KRY3B.js} +3 -3
  43. package/dist/{chunk-T7JAOYE5.js → chunk-HDPN46JP.js} +6 -6
  44. package/dist/{chunk-R4WXQIOZ.js → chunk-IQQAJROD.js} +3 -3
  45. package/dist/{chunk-2IR4T5PO.js → chunk-IZXN3WI6.js} +2 -2
  46. package/dist/{chunk-NCPWXHDO.js → chunk-JEUFYSFQ.js} +4 -4
  47. package/dist/{chunk-LKP7QDFN.js → chunk-JSSM7VVV.js} +4 -4
  48. package/dist/{chunk-2IAZEB45.js → chunk-KFGZPVFA.js} +229 -821
  49. package/dist/chunk-KFGZPVFA.js.map +1 -0
  50. package/dist/{chunk-EIFCP6CZ.js → chunk-KGFSPJLD.js} +2 -2
  51. package/dist/{chunk-RLT5SEML.js → chunk-KMORGMCW.js} +6 -6
  52. package/dist/{chunk-WQWKYAAK.js → chunk-NUQF5F5J.js} +2 -2
  53. package/dist/{chunk-54F74XR3.js → chunk-NZ6KSHFD.js} +19 -19
  54. package/dist/{chunk-4D5IZSXM.js → chunk-OHUDZRLK.js} +3 -3
  55. package/dist/{chunk-FBMZJEB3.js → chunk-OKMTUAWO.js} +4 -4
  56. package/dist/{chunk-QLWC7MKD.js → chunk-OTJOBZJ5.js} +135 -135
  57. package/dist/chunk-OTJOBZJ5.js.map +1 -0
  58. package/dist/{chunk-6HWBRZIN.js → chunk-PS257NIU.js} +252 -193
  59. package/dist/chunk-PS257NIU.js.map +1 -0
  60. package/dist/chunk-QDC7JPFG.js +685 -0
  61. package/dist/chunk-QDC7JPFG.js.map +1 -0
  62. package/dist/{chunk-PCQ7ELJH.js → chunk-QEAGL4V5.js} +109 -5
  63. package/dist/chunk-QEAGL4V5.js.map +1 -0
  64. package/dist/{chunk-BBT6AVUG.js → chunk-QMY57PVW.js} +2 -2
  65. package/dist/{chunk-LPIF5LIE.js → chunk-QNDDPXFR.js} +2 -2
  66. package/dist/{chunk-PWBH7DCQ.js → chunk-QSIXNTRV.js} +4 -4
  67. package/dist/{chunk-VSEBFHAY.js → chunk-RGLFV4KO.js} +11369 -10218
  68. package/dist/chunk-RGLFV4KO.js.map +1 -0
  69. package/dist/{chunk-D4N2V43Z.js → chunk-SGR7ZAVE.js} +13 -7
  70. package/dist/chunk-SGR7ZAVE.js.map +1 -0
  71. package/dist/{chunk-GV56WGL2.js → chunk-SMHAYK6I.js} +1036 -883
  72. package/dist/chunk-SMHAYK6I.js.map +1 -0
  73. package/dist/{chunk-JPQDNYXH.js → chunk-STPGIKPY.js} +8 -2
  74. package/dist/chunk-STPGIKPY.js.map +1 -0
  75. package/dist/{chunk-NSBXVPZL.js → chunk-U22TOL5Y.js} +17 -17
  76. package/dist/{chunk-NGTVREIH.js → chunk-U6IHLEWT.js} +2 -2
  77. package/dist/{chunk-ODRPL3WB.js → chunk-UUCCV3SI.js} +2 -2
  78. package/dist/{chunk-MSRU4D4P.js → chunk-UXMCHBOJ.js} +2 -2
  79. package/dist/{chunk-B7XYNRJQ.js → chunk-VFAKGIDG.js} +2 -2
  80. package/dist/{chunk-QCHVR4ZM.js → chunk-VM7VAFJW.js} +33 -7
  81. package/dist/chunk-VM7VAFJW.js.map +1 -0
  82. package/dist/{chunk-VQK4VHLF.js → chunk-YQV75FIL.js} +2 -2
  83. package/dist/chunk-YUTVAMWW.js +2 -0
  84. package/dist/{cli-4MF37HAQ.js → cli-4CR7QIOK.js} +26 -25
  85. package/dist/{cli-4MF37HAQ.js.map → cli-4CR7QIOK.js.map} +1 -1
  86. package/dist/{cli-6KZTHWGP.js → cli-6R4W3HAH.js} +37 -36
  87. package/dist/{cli-6KZTHWGP.js.map → cli-6R4W3HAH.js.map} +1 -1
  88. package/dist/{cli-I62SRH3R.js → cli-BOMA2FMP.js} +14 -13
  89. package/dist/{cli-DRMZBZLB.js → cli-EDQPQOCE.js} +43 -42
  90. package/dist/{cli-DRMZBZLB.js.map → cli-EDQPQOCE.js.map} +1 -1
  91. package/dist/{cli-VID7PJS3.js → cli-GBF76EXT.js} +23 -22
  92. package/dist/{cli-VID7PJS3.js.map → cli-GBF76EXT.js.map} +1 -1
  93. package/dist/{cli-3BTCK4AB.js → cli-MQYCF3SR.js} +27 -26
  94. package/dist/{cli-3BTCK4AB.js.map → cli-MQYCF3SR.js.map} +1 -1
  95. package/dist/{cli-ONTC5PKT.js → cli-OJKFXQOM.js} +9 -9
  96. package/dist/{cli-VUKMWSSF.js → cli-PHZAO4LZ.js} +4 -4
  97. package/dist/{cli-RORDPAPE.js → cli-PTKFFNOW.js} +59 -38
  98. package/dist/cli-PTKFFNOW.js.map +1 -0
  99. package/dist/{cli-O4ABTN4Z.js → cli-UW2K5Z5J.js} +31 -30
  100. package/dist/{cli-O4ABTN4Z.js.map → cli-UW2K5Z5J.js.map} +1 -1
  101. package/dist/{cli-JJMOVIKS.js → cli-XXTNPPKB.js} +14 -14
  102. package/dist/cli.js +19 -13
  103. package/dist/cli.js.map +1 -1
  104. package/dist/{config-XDA42RJL.js → config-JJW75SBX.js} +5 -5
  105. package/dist/docmeta.js +13 -12
  106. package/dist/docmeta.js.map +1 -1
  107. package/dist/github-6VQKSB67.js +35 -0
  108. package/dist/github-RBSEM7ZK.js +30 -0
  109. package/dist/graph/runtime.d.ts +4 -1
  110. package/dist/graph/runtime.js +20 -9
  111. package/dist/graph/runtime.js.map +1 -1
  112. package/dist/{host-6GURH5HE.js → host-YSTYO5DX.js} +3 -3
  113. package/dist/index.d.ts +192 -26
  114. package/dist/index.js +129 -124
  115. package/dist/index.js.map +1 -1
  116. package/dist/{json-BXY44ED7.js → json-PU2HLHDQ.js} +18 -17
  117. package/dist/labels-SJNSOPBI.js +73 -0
  118. package/dist/labels-SJNSOPBI.js.map +1 -0
  119. package/dist/lint-KIVTHLGU.js +34 -0
  120. package/dist/list-RDEJDDJF.js +32 -0
  121. package/dist/list-SUTDWL2J.js +35 -0
  122. package/dist/{page-EV7OUBAU.js → page-UMAA3NCM.js} +18 -16
  123. package/dist/{prepare-JHJDJB6I.js → prepare-3I3LOXXD.js} +22 -21
  124. package/dist/{prepare-JHJDJB6I.js.map → prepare-3I3LOXXD.js.map} +1 -1
  125. package/dist/{pretty-SCRK66M5.js → pretty-ANLRHU4O.js} +18 -17
  126. package/dist/{pretty-Q5Y2PA64.js → pretty-Q3ZFKOR7.js} +18 -17
  127. package/dist/{provider-527CO4DM.js → provider-LBX4IXGX.js} +3 -3
  128. package/dist/{release-3D5PK6M7.js → release-VV3UTKE5.js} +3 -3
  129. package/dist/{reporters-M6LJ2IYU.js → reporters-26H3N2KW.js} +3 -3
  130. package/dist/{reporters-RBYTASMI.js → reporters-ILT36CIH.js} +7 -7
  131. package/dist/{reporters-A5ADKDYR.js → reporters-PNDLWT6K.js} +16 -15
  132. package/dist/run-QXCK33Z4.js +37 -0
  133. package/dist/{term-CQAGNG3Q.js → term-D2N7UN4P.js} +981 -141
  134. package/dist/term-D2N7UN4P.js.map +1 -0
  135. package/dist/validate-BRUCOT2O.js +19 -0
  136. package/package.json +3 -2
  137. package/plugin/manni/.claude-plugin/plugin.json +1 -1
  138. package/shapes/graph/shapes-1.1.0.ttl +785 -0
  139. package/dist/build-QSPNK5AL.js +0 -35
  140. package/dist/calibrate-KXN4URPM.js +0 -40
  141. package/dist/capture-JHTSUPUC.js +0 -37
  142. package/dist/check-MDGXEUWL.js +0 -20
  143. package/dist/check-WOQRKNZK.js +0 -29
  144. package/dist/chunk-2DRHT73U.js.map +0 -1
  145. package/dist/chunk-2IAZEB45.js.map +0 -1
  146. package/dist/chunk-2MJ62AYQ.js.map +0 -1
  147. package/dist/chunk-4VBSTXN6.js +0 -392
  148. package/dist/chunk-4VBSTXN6.js.map +0 -1
  149. package/dist/chunk-6HWBRZIN.js.map +0 -1
  150. package/dist/chunk-BKVHX6FU.js.map +0 -1
  151. package/dist/chunk-D4N2V43Z.js.map +0 -1
  152. package/dist/chunk-EFW7CAG4.js +0 -387
  153. package/dist/chunk-EFW7CAG4.js.map +0 -1
  154. package/dist/chunk-GV56WGL2.js.map +0 -1
  155. package/dist/chunk-HQR2ZBHW.js.map +0 -1
  156. package/dist/chunk-J6IDQGJL.js.map +0 -1
  157. package/dist/chunk-JPQDNYXH.js.map +0 -1
  158. package/dist/chunk-JROBZ7JA.js +0 -818
  159. package/dist/chunk-JROBZ7JA.js.map +0 -1
  160. package/dist/chunk-PCQ7ELJH.js.map +0 -1
  161. package/dist/chunk-QCHVR4ZM.js.map +0 -1
  162. package/dist/chunk-QLWC7MKD.js.map +0 -1
  163. package/dist/chunk-TU2WUBVZ.js +0 -2
  164. package/dist/chunk-VSEBFHAY.js.map +0 -1
  165. package/dist/chunk-Y6DOMTQD.js.map +0 -1
  166. package/dist/cli-RORDPAPE.js.map +0 -1
  167. package/dist/github-RY3FRA6P.js +0 -29
  168. package/dist/github-YKQSH7FS.js +0 -34
  169. package/dist/lint-YJ2L22BW.js +0 -33
  170. package/dist/list-NSG24VVX.js +0 -31
  171. package/dist/list-V6EGCSHX.js +0 -34
  172. package/dist/run-BUE2DDXN.js +0 -36
  173. package/dist/term-CQAGNG3Q.js.map +0 -1
  174. package/dist/validate-ZBW44RHT.js +0 -18
  175. /package/dist/{batch-UAULUMGH.js.map → batch-EFSFG6GC.js.map} +0 -0
  176. /package/dist/{build-QSPNK5AL.js.map → build-NIO3UIWJ.js.map} +0 -0
  177. /package/dist/{calibrate-KXN4URPM.js.map → calibrate-6VO7URRV.js.map} +0 -0
  178. /package/dist/{capture-JHTSUPUC.js.map → capture-NMBVJO3C.js.map} +0 -0
  179. /package/dist/{check-MDGXEUWL.js.map → check-SHOYX2B5.js.map} +0 -0
  180. /package/dist/{check-WOQRKNZK.js.map → check-XMJKH3KV.js.map} +0 -0
  181. /package/dist/{check-YEOYBFST.js.map → check-ZMO3ZLMW.js.map} +0 -0
  182. /package/dist/{chunk-M42DZCOU.js.map → chunk-2OZF2VUB.js.map} +0 -0
  183. /package/dist/{chunk-U7CTFN2J.js.map → chunk-42VFJOAF.js.map} +0 -0
  184. /package/dist/{chunk-LBSCW232.js.map → chunk-4Q24OYI3.js.map} +0 -0
  185. /package/dist/{chunk-OPXWPJDA.js.map → chunk-4WJTURRO.js.map} +0 -0
  186. /package/dist/{chunk-GDVZ5VII.js.map → chunk-5SID2SVL.js.map} +0 -0
  187. /package/dist/{chunk-FUCPZVRY.js.map → chunk-AANUY4BH.js.map} +0 -0
  188. /package/dist/{chunk-WDWXAYVH.js.map → chunk-AYVKN3PG.js.map} +0 -0
  189. /package/dist/{chunk-FQXWVS6J.js.map → chunk-CH6IOGXV.js.map} +0 -0
  190. /package/dist/{chunk-4CK6ZSOK.js.map → chunk-D5Z6B4M7.js.map} +0 -0
  191. /package/dist/{chunk-HA6MQMOY.js.map → chunk-D6SELXQ2.js.map} +0 -0
  192. /package/dist/{chunk-PCS4VJBV.js.map → chunk-DGRLHDM4.js.map} +0 -0
  193. /package/dist/{chunk-KGEQJ5CC.js.map → chunk-F564FHMQ.js.map} +0 -0
  194. /package/dist/{chunk-IGSHYP74.js.map → chunk-G3MBUL5M.js.map} +0 -0
  195. /package/dist/{chunk-ADMEPUBT.js.map → chunk-GQ3KRY3B.js.map} +0 -0
  196. /package/dist/{chunk-T7JAOYE5.js.map → chunk-HDPN46JP.js.map} +0 -0
  197. /package/dist/{chunk-R4WXQIOZ.js.map → chunk-IQQAJROD.js.map} +0 -0
  198. /package/dist/{chunk-2IR4T5PO.js.map → chunk-IZXN3WI6.js.map} +0 -0
  199. /package/dist/{chunk-NCPWXHDO.js.map → chunk-JEUFYSFQ.js.map} +0 -0
  200. /package/dist/{chunk-LKP7QDFN.js.map → chunk-JSSM7VVV.js.map} +0 -0
  201. /package/dist/{chunk-EIFCP6CZ.js.map → chunk-KGFSPJLD.js.map} +0 -0
  202. /package/dist/{chunk-RLT5SEML.js.map → chunk-KMORGMCW.js.map} +0 -0
  203. /package/dist/{chunk-WQWKYAAK.js.map → chunk-NUQF5F5J.js.map} +0 -0
  204. /package/dist/{chunk-54F74XR3.js.map → chunk-NZ6KSHFD.js.map} +0 -0
  205. /package/dist/{chunk-4D5IZSXM.js.map → chunk-OHUDZRLK.js.map} +0 -0
  206. /package/dist/{chunk-FBMZJEB3.js.map → chunk-OKMTUAWO.js.map} +0 -0
  207. /package/dist/{chunk-BBT6AVUG.js.map → chunk-QMY57PVW.js.map} +0 -0
  208. /package/dist/{chunk-LPIF5LIE.js.map → chunk-QNDDPXFR.js.map} +0 -0
  209. /package/dist/{chunk-PWBH7DCQ.js.map → chunk-QSIXNTRV.js.map} +0 -0
  210. /package/dist/{chunk-NSBXVPZL.js.map → chunk-U22TOL5Y.js.map} +0 -0
  211. /package/dist/{chunk-NGTVREIH.js.map → chunk-U6IHLEWT.js.map} +0 -0
  212. /package/dist/{chunk-ODRPL3WB.js.map → chunk-UUCCV3SI.js.map} +0 -0
  213. /package/dist/{chunk-MSRU4D4P.js.map → chunk-UXMCHBOJ.js.map} +0 -0
  214. /package/dist/{chunk-B7XYNRJQ.js.map → chunk-VFAKGIDG.js.map} +0 -0
  215. /package/dist/{chunk-VQK4VHLF.js.map → chunk-YQV75FIL.js.map} +0 -0
  216. /package/dist/{chunk-TU2WUBVZ.js.map → chunk-YUTVAMWW.js.map} +0 -0
  217. /package/dist/{cli-I62SRH3R.js.map → cli-BOMA2FMP.js.map} +0 -0
  218. /package/dist/{cli-ONTC5PKT.js.map → cli-OJKFXQOM.js.map} +0 -0
  219. /package/dist/{cli-VUKMWSSF.js.map → cli-PHZAO4LZ.js.map} +0 -0
  220. /package/dist/{cli-JJMOVIKS.js.map → cli-XXTNPPKB.js.map} +0 -0
  221. /package/dist/{config-XDA42RJL.js.map → config-JJW75SBX.js.map} +0 -0
  222. /package/dist/{github-RY3FRA6P.js.map → github-6VQKSB67.js.map} +0 -0
  223. /package/dist/{github-YKQSH7FS.js.map → github-RBSEM7ZK.js.map} +0 -0
  224. /package/dist/{host-6GURH5HE.js.map → host-YSTYO5DX.js.map} +0 -0
  225. /package/dist/{json-BXY44ED7.js.map → json-PU2HLHDQ.js.map} +0 -0
  226. /package/dist/{lint-YJ2L22BW.js.map → lint-KIVTHLGU.js.map} +0 -0
  227. /package/dist/{list-NSG24VVX.js.map → list-RDEJDDJF.js.map} +0 -0
  228. /package/dist/{list-V6EGCSHX.js.map → list-SUTDWL2J.js.map} +0 -0
  229. /package/dist/{page-EV7OUBAU.js.map → page-UMAA3NCM.js.map} +0 -0
  230. /package/dist/{pretty-Q5Y2PA64.js.map → pretty-ANLRHU4O.js.map} +0 -0
  231. /package/dist/{pretty-SCRK66M5.js.map → pretty-Q3ZFKOR7.js.map} +0 -0
  232. /package/dist/{provider-527CO4DM.js.map → provider-LBX4IXGX.js.map} +0 -0
  233. /package/dist/{release-3D5PK6M7.js.map → release-VV3UTKE5.js.map} +0 -0
  234. /package/dist/{reporters-A5ADKDYR.js.map → reporters-26H3N2KW.js.map} +0 -0
  235. /package/dist/{reporters-M6LJ2IYU.js.map → reporters-ILT36CIH.js.map} +0 -0
  236. /package/dist/{reporters-RBYTASMI.js.map → reporters-PNDLWT6K.js.map} +0 -0
  237. /package/dist/{run-BUE2DDXN.js.map → run-QXCK33Z4.js.map} +0 -0
  238. /package/dist/{validate-ZBW44RHT.js.map → validate-BRUCOT2O.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/docevals/cli.ts"],"sourcesContent":["/**\n * The docevals program. Named `docevals` because that is where it is mounted\n * (`manni docevals …`); `src/cli.ts` adds it to the umbrella and runs it.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport { terminalConfirm } from \"../shared/prompt.js\";\nimport { collect, configOption } from \"../shared/cli-options.js\";\nimport { LOCAL_FLAG_HELP } from \"../shared/providers.js\";\nimport type { DocumentInputOptions } from \"./core/discover.js\";\nimport { colorFor, palette } from \"../shared/color.js\";\nimport { DocevalsError } from \"./types.js\";\nimport { allowExecutionMessage, isExecutionGrant } from \"../shared/execution.js\";\nimport { runList, renderList } from \"./commands/list.js\";\nimport { runRun } from \"./commands/run.js\";\nimport { runGenerate } from \"./commands/generate.js\";\nimport { runFill, renderFill } from \"./commands/fill.js\";\nimport { runPromote } from \"./commands/promote.js\";\nimport { listReviews, renderReviews, runReview } from \"./commands/review.js\";\nimport {\n runCalibrate,\n renderCalibration,\n seedGoldenCases,\n} from \"./commands/calibrate.js\";\nimport { runInit } from \"./commands/init.js\";\nimport {\n render,\n parseFormat,\n REPORT_FORMATS,\n SUMMARY_FORMATS,\n type ReportFormat,\n type SummaryFormat,\n} from \"./reporters/index.js\";\n\n/**\n * Whether `command`'s output gets colour: the family's rule, read off this\n * domain's `--no-color`. Exported for the tests that pin it.\n */\nexport { colorFor };\n\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"docevals\")\n .description(\n \"Deterministic and LLM-as-judge evals for documentation pages, driven by frontmatter.\",\n )\n .version(pkg.version)\n .option(\"--no-color\", \"disable colored output\")\n // A pointer, not the whole help screen: the message that precedes it\n // already names the offending flag.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before the `.command()` calls below. `copyInheritedSettings`\n // copies `_exitCallback` by value at subcommand-creation time, so an\n // `exitOverride()` installed afterwards leaves every subcommand calling\n // `process.exit(1)` on a parse error, which is a usage error owed exit 2.\n .exitOverride();\n\n /**\n * Repeatable execution grant, validated on the way in.\n *\n * An unknown value is a usage error rather than a silent no-op (ADR 01007, the\n * same rule `--format` follows): a mistyped grant that quietly granted nothing\n * would skip every command eval and still exit 0, which reads as \"the corpus\n * is clean\" rather than \"you misspelled a flag\".\n */\n function collectGrant(value: string, previous: string[]): string[] {\n if (!isExecutionGrant(value)) {\n fail(new DocevalsError(allowExecutionMessage(value)));\n }\n return [...previous, value];\n }\n\n function parseIntArg(name: string) {\n return (value: string): number => {\n const n = Number.parseInt(value, 10);\n if (Number.isNaN(n) || n < 1) {\n fail(new DocevalsError(`${name} must be a positive integer, got \"${value}\"`));\n }\n return n;\n };\n }\n\n /**\n * Repeatable single-value option, e.g. `--eval a --eval b`.\n *\n * NOT commander's variadic `<name...>`: a variadic consumes every following\n * non-option token, so `run --eval fresh-enough docs/guide.md` parsed the glob\n * as a second eval name and left `globs` empty — silently widening the run to\n * the whole configured corpus, which is the opposite of what selection is for.\n */\n function collectArg(value: string, previous: string[]): string[] {\n return [...previous, value];\n }\n\n function parseFloatArg(name: string) {\n return (value: string): number => {\n const n = Number.parseFloat(value);\n if (Number.isNaN(n) || n < 0) {\n fail(new DocevalsError(`${name} must be a non-negative number, got \"${value}\"`));\n }\n return n;\n };\n }\n\n /**\n * Commander argument parser for `-f/--format` (ADR 01007). Routes through\n * `fail()` for the same reason the numeric parsers do: commander only special-\n * cases InvalidArgumentError, so any other exception escapes `program.parse()`\n * uncaught — a stack trace and exit 1, when a bad flag owes exit 2.\n */\n function parseFormatArg<T extends string>(name: string, allowed: readonly T[]) {\n return (value: string): T => {\n try {\n return parseFormat(value, allowed, name);\n } catch (e) {\n fail(e);\n }\n };\n }\n\n /**\n * The document-set surface every verb that reads pages shares (proposal\n * 0041): positional `[paths...]`, `--collection` and `--exclude` (each one\n * value per occurrence), and `-c`/`--no-config`. Declared once so the five\n * verbs cannot drift apart on a name or a description.\n */\n function documentInputs(command: Command, verb: string): Command {\n return command\n .argument(\n \"[paths...]\",\n `Files, directories, or globs to ${verb} (default: the configured collections)`,\n )\n .option(\n \"--collection <name>\",\n \"Configured collection to read (repeatable)\",\n collect,\n [],\n )\n .option(\"--exclude <glob>\", \"Glob to exclude (repeatable)\", collect, [])\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\");\n }\n\n /** The shared options as the command cores take them. */\n function documentOptions(opts: {\n collection?: string[];\n exclude?: string[];\n config?: string | boolean;\n }): DocumentInputOptions {\n const { configPath, noConfig } = configOption(opts.config);\n return {\n ...(configPath === undefined ? {} : { config: configPath }),\n ...(noConfig === true ? { noConfig } : {}),\n ...(opts.collection === undefined ? {} : { collection: opts.collection }),\n ...(opts.exclude === undefined ? {} : { exclude: opts.exclude }),\n };\n }\n\n documentInputs(\n program\n .command(\"list\")\n .description(\"Show the resolved eval plan per page without running anything\"),\n \"list\",\n )\n .option(\n \"-f, --format <format>\",\n `Output format: ${SUMMARY_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", SUMMARY_FORMATS),\n \"pretty\" as SummaryFormat,\n )\n .option(\"--eval <name>\", \"Show only this eval (repeatable)\", collectArg, [])\n .option(\"--suite <name>\", \"Show only evals in this suite\")\n .action(\n async (\n paths: string[],\n opts: {\n config?: string | boolean;\n collection?: string[];\n exclude?: string[];\n format: SummaryFormat;\n eval?: string[];\n suite?: string;\n },\n command: Command,\n ) => {\n try {\n const run = await runList(paths, {\n ...documentOptions(opts),\n format: opts.format,\n evalNames: opts.eval,\n suite: opts.suite,\n });\n console.log(\n renderList(run, opts.format, {\n color: colorFor(command, process.stdout.isTTY),\n }),\n );\n process.exitCode = run.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\n documentInputs(\n program.command(\"run\").description(\"Run evals against documentation pages\"),\n \"evaluate\",\n )\n .option(\n \"-f, --format <format>\",\n `Output format: ${REPORT_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", REPORT_FORMATS),\n \"pretty\" as ReportFormat,\n )\n .option(\"--deterministic-only\", \"Run only command/tool graders, skip the AI judge\")\n .option(\"--ai-only\", \"Run only AI-judged evals, skip deterministic graders\")\n .option(\n // `<kind>`, not `<kind...>`: a variadic option greedily eats the\n // positional `[paths...]` that follow it, so `--allow-execution\n // frontmatter-commands docs/**` would silently swallow the glob and run\n // over the default file set instead. Repeat the flag to grant twice.\n \"--allow-execution <kind>\",\n \"Run only these execution grants (repeatable): frontmatter-commands\",\n collectGrant,\n [],\n )\n .option(\"--no-execution\", \"Clear every execution grant for this run\")\n .option(\"--no-generate\", \"Do not generate scripts for command evals missing a command\")\n .option(\"--no-cache\", \"Bypass the judge response cache\")\n .option(\"--fail-on-review\", \"Exit 1 when any eval lands in the human-review zone\")\n .option(\"--provider <name>\", \"Judge provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .option(\"--runs <n>\", \"Ensemble runs per eval\", parseIntArg(\"--runs\"))\n .option(\n \"--chunk-chars <n>\",\n \"Characters of page per judge call; longer pages are read in parts\",\n parseIntArg(\"--chunk-chars\"),\n )\n .option(\n \"--eval <name>\",\n \"Run only this eval (repeatable); suite targets are not evaluated on a filtered run\",\n collectArg,\n [],\n )\n .option(\"--suite <name>\", \"Run only evals in this suite\")\n .option(\n \"--since <ref>\",\n \"Evaluate only pages whose file or eval manifest changed between this git ref and HEAD\",\n )\n .option(\n \"--newer-than <duration>\",\n \"Evaluate only pages whose file or eval manifest changed within this window, \" +\n \"such as 30m, 24h, 7d or 2w; in CI, prefer --since\",\n )\n .option(\n \"--max-turns <n>\",\n \"Stop after this many ensemble runs (a cached ensemble costs none)\",\n parseIntArg(\"--max-turns\"),\n )\n .option(\n \"--baseline [path]\",\n \"Fail only on findings a recorded baseline does not already hold\",\n )\n .option(\"--no-baseline\", \"Ignore the configured baseline for this run\")\n .option(\n \"--write-baseline [path]\",\n \"Record this run's findings as the baseline; without a path, the configured one\",\n )\n .action(async (paths: string[], opts: Record<string, unknown>, command: Command) => {\n try {\n const report = await runRun(paths, {\n ...documentOptions({\n config: opts.config as string | boolean | undefined,\n collection: opts.collection as string[] | undefined,\n exclude: opts.exclude as string[] | undefined,\n }),\n // parseFormatArg validated this at parse time; the cast only re-narrows\n // from the `unknown` that the Record-typed options bag erases it to.\n format: opts.format as ReportFormat,\n deterministicOnly: opts.deterministicOnly as boolean | undefined,\n aiOnly: opts.aiOnly as boolean | undefined,\n // Commander's default is `[]`, which is \"no flag\", not \"run nothing\":\n // only a list someone typed narrows the run.\n allowExecution:\n (opts.allowExecution as string[]).length > 0\n ? (opts.allowExecution as string[])\n : undefined,\n execution: opts.execution as boolean | undefined,\n generate: opts.generate as boolean | undefined,\n cache: opts.cache as boolean | undefined,\n failOnReview: opts.failOnReview as boolean | undefined,\n provider: opts.provider as string | undefined,\n model: opts.model as string | undefined,\n local: opts.local as boolean | undefined,\n runs: opts.runs as number | undefined,\n chunkChars: opts.chunkChars as number | undefined,\n maxTurns: opts.maxTurns as number | undefined,\n evalNames: opts.eval as string[] | undefined,\n suite: opts.suite as string | undefined,\n since: opts.since as string | undefined,\n newerThan: opts.newerThan as string | undefined,\n // commander collapses `--baseline` to true and `--no-baseline` to\n // false on the same key; a string is an explicit path.\n baseline: opts.baseline as string | boolean | undefined,\n writeBaseline: opts.writeBaseline as string | boolean | undefined,\n toolVersion: pkg.version,\n });\n console.log(\n render(report, opts.format as ReportFormat, {\n color: colorFor(command, process.stdout.isTTY),\n }),\n );\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\n documentInputs(\n program\n .command(\"generate\")\n .description(\n \"Generate check scripts for command evals with a plain-language assertion but no command\",\n ),\n \"read\",\n )\n .option(\"--provider <name>\", \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .action(\n async (\n paths: string[],\n opts: {\n config?: string | boolean;\n collection?: string[];\n exclude?: string[];\n provider?: string;\n model?: string;\n local?: boolean;\n },\n command: Command,\n ) => {\n try {\n const pc = palette(colorFor(command, process.stdout.isTTY));\n const result = await runGenerate(paths, {\n ...documentOptions(opts),\n provider: opts.provider,\n model: opts.model,\n local: opts.local,\n });\n if (result.targets === 0) {\n console.log(\"Nothing to generate — every command eval has a command.\");\n return;\n }\n console.log(\n `Generated ${result.generatedPaths.length}/${result.targets} check script(s):`,\n );\n for (const p of result.generatedPaths) console.log(` ${p}`);\n // Evals whose command reference had nowhere to go (proposal 0047).\n for (const r of result.refusals) console.log(pc.red(` ${r.message}`));\n if (result.generatedPaths.length < result.targets) {\n process.exitCode = 1;\n }\n } catch (e) {\n fail(e);\n }\n },\n );\n\n documentInputs(\n program\n .command(\"fill\")\n .description(\n \"Propose frontmatter evals for pages with an LLM; writes proposals at or above the confidence threshold\",\n ),\n \"fill\",\n )\n .option(\n \"-f, --format <format>\",\n `Output format: ${SUMMARY_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", SUMMARY_FORMATS),\n \"pretty\" as SummaryFormat,\n )\n .option(\"--dry-run\", \"Report proposals without writing frontmatter\")\n .option(\n \"--confidence <n>\",\n \"Minimum confidence to write (0-1, default: config fill.confidenceThreshold)\",\n parseFloatArg(\"--confidence\"),\n )\n .option(\n \"--max-turns <n>\",\n \"Stop after this many inference calls (a cached page costs none)\",\n parseIntArg(\"--max-turns\"),\n )\n .option(\"--no-cache\", \"Bypass the fill proposal cache\")\n .option(\n \"--chunk-chars <n>\",\n \"Characters of page per fill call; longer pages are proposed in parts\",\n parseIntArg(\"--chunk-chars\"),\n )\n .option(\"--provider <name>\", \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .action(async (paths: string[], opts: Record<string, unknown>, command: Command) => {\n try {\n const confidence = opts.confidence as number | undefined;\n if (confidence !== undefined && confidence > 1) {\n fail(new DocevalsError(`--confidence must be between 0 and 1, got ${confidence}`));\n }\n const report = await runFill(paths, {\n ...documentOptions({\n config: opts.config as string | boolean | undefined,\n collection: opts.collection as string[] | undefined,\n exclude: opts.exclude as string[] | undefined,\n }),\n dryRun: opts.dryRun as boolean | undefined,\n confidence,\n maxTurns: opts.maxTurns as number | undefined,\n noCache: opts.cache === false ? true : undefined,\n provider: opts.provider as string | undefined,\n model: opts.model as string | undefined,\n local: opts.local as boolean | undefined,\n // P1 (proposal 0047): offered only on a terminal, where there is\n // someone to answer. Off one the evals go to the page and the W1\n // line says so.\n confirm: terminalConfirm(),\n onNotice: notice,\n onRelocated: (result) => {\n const manifests = result.manifests.map((m) => m.file).join(\", \");\n notice(\n `moved ${String(result.summary.moved)} value(s) into ${manifests}.`,\n );\n },\n });\n // As in `run`: parseFormatArg validated this at parse time, and the cast\n // only re-narrows from the `unknown` the Record-typed options bag erases\n // it to. renderFill guards itself regardless.\n console.log(\n renderFill(report, opts.format as SummaryFormat, {\n color: colorFor(command, process.stdout.isTTY),\n }),\n );\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\n documentInputs(\n program\n .command(\"promote\")\n .description(\n \"Find ai-graded evals expressible as deterministic checks; --write converts them\",\n ),\n \"read\",\n )\n .option(\"--write\", \"Apply promotions (write scripts and rewrite evals)\")\n .option(\"--provider <name>\", \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .action(\n async (\n paths: string[],\n opts: {\n config?: string | boolean;\n collection?: string[];\n exclude?: string[];\n write?: boolean;\n provider?: string;\n model?: string;\n local?: boolean;\n },\n command: Command,\n ) => {\n try {\n const pc = palette(colorFor(command, process.stdout.isTTY));\n const proposals = await runPromote(paths, {\n ...documentOptions(opts),\n write: opts.write,\n provider: opts.provider,\n model: opts.model,\n local: opts.local,\n });\n if (proposals.length === 0) {\n console.log(\"No ai-graded evals found.\");\n return;\n }\n for (const p of proposals) {\n const tag = p.promotable\n ? p.applied\n ? pc.green(\"promoted\")\n : pc.cyan(\"promotable\")\n : pc.dim(\"keep-ai\");\n const script = p.scriptPath ? pc.dim(` -> ${p.scriptPath}`) : \"\";\n console.log(`${tag} ${p.evalName} (${p.source}, ${p.file})${script}`);\n console.log(pc.dim(` ${p.rationale}`));\n // Promotable, and nowhere to write it (proposal 0047).\n if (p.error !== undefined) console.log(pc.red(` ${p.error}`));\n }\n if (!opts.write && proposals.some((p) => p.promotable)) {\n console.log(pc.cyan(\"\\nRe-run with --write to apply promotions.\"));\n }\n } catch (e) {\n fail(e);\n }\n },\n );\n\n program\n .command(\"calibrate\")\n .description(\n \"Measure judge agreement against a human-verified golden set (.manni/docevals/golden/*.yaml)\",\n )\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--golden <dir>\", \"Golden set directory\", \".manni/docevals/golden\")\n .option(\n \"--seed\",\n \"Write golden candidates from recorded reviews and exit; judges nothing, needs no provider\",\n )\n .option(\"--provider <name>\", \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .option(\"--runs <n>\", \"Ensemble runs per case\", parseIntArg(\"--runs\"))\n .option(\n \"--max-turns <n>\",\n \"Stop after this many ensemble runs (a cached ensemble costs none)\",\n parseIntArg(\"--max-turns\"),\n )\n .option(\"--no-cache\", \"Bypass the judge response cache\")\n .action(\n async (opts: {\n config?: string;\n golden?: string;\n seed?: boolean;\n provider?: string;\n model?: string;\n local?: boolean;\n runs?: number;\n maxTurns?: number;\n cache?: boolean;\n }, command: Command) => {\n try {\n const color = colorFor(command, process.stdout.isTTY);\n const pc = palette(color);\n if (opts.seed) {\n // No `config`: reviews.yaml and the golden directory both resolve\n // against the working directory, not the config's, so passing it\n // would imply an influence it does not have.\n const seeded = seedGoldenCases({ golden: opts.golden });\n if (seeded.total === 0) {\n console.log(\n \"No recorded reviews to seed from — run `manni docevals review <file> <eval> <pass|fail>` first.\",\n );\n return;\n }\n // The lead number is what moved, not the file's size: `total`\n // counts cases already confirmed and left alone, so leading with it\n // read as \"wrote 8 candidates\" on a re-seed that wrote none.\n const changed = seeded.added + seeded.updated;\n console.log(\n changed === 0\n ? `No new reviews to seed — ${seeded.total} golden case(s) already in ${seeded.path}.`\n : `Wrote ${changed} golden candidate(s) to ${seeded.path} ` +\n `(${seeded.added} new, ${seeded.updated} updated; ${seeded.total} total).`,\n );\n if (seeded.unreviewed > 0) {\n console.log(\n pc.yellow(\n `${seeded.unreviewed} case(s) are \\`reviewed: false\\`. Read them and set ` +\n \"`reviewed: true` — a golden set assembled without a human is not one.\",\n ),\n );\n }\n return;\n }\n const report = await runCalibrate({\n config: opts.config,\n golden: opts.golden,\n provider: opts.provider,\n model: opts.model,\n local: opts.local,\n runs: opts.runs,\n maxTurns: opts.maxTurns,\n noCache: opts.cache === false,\n });\n console.log(renderCalibration(report, { color }));\n // Both conditions: the judge has to agree enough, AND the set has to\n // have been measured. A stale golden file whose pages were renamed\n // used to certify on whatever still resolved.\n process.exitCode =\n report.meetsThreshold &&\n report.unjudged === 0 &&\n report.balanced\n ? 0\n : 1;\n } catch (e) {\n fail(e);\n }\n },\n );\n\n program\n .command(\"init\")\n .description(\"Create a starter manni.config.yaml in the current directory\")\n .action(() => {\n try {\n console.log(`Created ${runInit()}`);\n } catch (e) {\n fail(e);\n }\n });\n\n program\n .command(\"review\")\n .description(\n \"Record a human verdict for an eval in the human-review zone (or list recorded reviews)\",\n )\n .argument(\"[file]\", \"Page path\")\n .argument(\"[eval]\", \"Eval name\")\n .argument(\"[verdict]\", \"pass | fail\")\n .option(\"--reviewer <name>\", \"Reviewer name recorded with the verdict\")\n .option(\"--note <text>\", \"Optional note\")\n .action(\n (\n file: string | undefined,\n evalName: string | undefined,\n verdict: string | undefined,\n opts: { reviewer?: string; note?: string },\n command: Command,\n ) => {\n try {\n if (!file) {\n console.log(\n renderReviews(listReviews(), {\n color: colorFor(command, process.stdout.isTTY),\n }),\n );\n return;\n }\n if (!evalName || !verdict) {\n throw new DocevalsError(\n \"Usage: manni docevals review <file> <eval> <pass|fail>\",\n );\n }\n const entry = runReview(file, evalName, verdict, opts);\n console.log(\n `Recorded ${entry.verdict} for ${entry.evalName} on ${entry.file}`,\n );\n } catch (e) {\n fail(e);\n }\n },\n );\n\n return program;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/docevals/cli.ts"],"sourcesContent":["/**\n * The docevals program. Named `docevals` because that is where it is mounted\n * (`manni docevals …`); `src/cli.ts` adds it to the umbrella and runs it.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport { terminalConfirm } from \"../shared/prompt.js\";\nimport { collect, configOption } from \"../shared/cli-options.js\";\nimport { LOCAL_FLAG_HELP } from \"../shared/providers.js\";\nimport type { DocumentInputOptions } from \"./core/discover.js\";\nimport { colorFor, palette } from \"../shared/color.js\";\nimport { DocevalsError } from \"./types.js\";\nimport { allowExecutionMessage, isExecutionGrant } from \"../shared/execution.js\";\nimport { runList, renderList } from \"./commands/list.js\";\nimport { runRun } from \"./commands/run.js\";\nimport { runGenerate } from \"./commands/generate.js\";\nimport { runFill, renderFill } from \"./commands/fill.js\";\nimport { runPromote } from \"./commands/promote.js\";\nimport { listReviews, renderReviews, runReview } from \"./commands/review.js\";\nimport {\n runCalibrate,\n renderCalibration,\n seedGoldenCases,\n} from \"./commands/calibrate.js\";\nimport { runInit } from \"./commands/init.js\";\nimport {\n render,\n parseFormat,\n REPORT_FORMATS,\n SUMMARY_FORMATS,\n type ReportFormat,\n type SummaryFormat,\n} from \"./reporters/index.js\";\n\n/**\n * Whether `command`'s output gets colour: the family's rule, read off this\n * domain's `--no-color`. Exported for the tests that pin it.\n */\nexport { colorFor };\n\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"docevals\")\n .description(\n \"Deterministic and LLM-as-judge evals for documentation pages, driven by frontmatter.\",\n )\n .version(pkg.version)\n .option(\"--no-color\", \"disable colored output\")\n // A pointer, not the whole help screen: the message that precedes it\n // already names the offending flag.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before the `.command()` calls below. `copyInheritedSettings`\n // copies `_exitCallback` by value at subcommand-creation time, so an\n // `exitOverride()` installed afterwards leaves every subcommand calling\n // `process.exit(1)` on a parse error, which is a usage error owed exit 2.\n .exitOverride();\n\n /**\n * Repeatable execution grant, validated on the way in.\n *\n * An unknown value is a usage error rather than a silent no-op (ADR 01007, the\n * same rule `--format` follows): a mistyped grant that quietly granted nothing\n * would skip every command eval and still exit 0, which reads as \"the corpus\n * is clean\" rather than \"you misspelled a flag\".\n */\n function collectGrant(value: string, previous: string[]): string[] {\n if (!isExecutionGrant(value)) {\n fail(new DocevalsError(allowExecutionMessage(value)));\n }\n return [...previous, value];\n }\n\n function parseIntArg(name: string) {\n return (value: string): number => {\n const n = Number.parseInt(value, 10);\n if (Number.isNaN(n) || n < 1) {\n fail(new DocevalsError(`${name} must be a positive integer, got \"${value}\"`));\n }\n return n;\n };\n }\n\n /**\n * Repeatable single-value option, e.g. `--eval a --eval b`.\n *\n * NOT commander's variadic `<name...>`: a variadic consumes every following\n * non-option token, so `run --eval fresh-enough docs/guide.md` parsed the glob\n * as a second eval name and left `globs` empty — silently widening the run to\n * the whole configured corpus, which is the opposite of what selection is for.\n */\n function collectArg(value: string, previous: string[]): string[] {\n return [...previous, value];\n }\n\n function parseFloatArg(name: string) {\n return (value: string): number => {\n const n = Number.parseFloat(value);\n if (Number.isNaN(n) || n < 0) {\n fail(new DocevalsError(`${name} must be a non-negative number, got \"${value}\"`));\n }\n return n;\n };\n }\n\n /**\n * Commander argument parser for `-f/--format` (ADR 01007). Routes through\n * `fail()` for the same reason the numeric parsers do: commander only special-\n * cases InvalidArgumentError, so any other exception escapes `program.parse()`\n * uncaught — a stack trace and exit 1, when a bad flag owes exit 2.\n */\n function parseFormatArg<T extends string>(name: string, allowed: readonly T[]) {\n return (value: string): T => {\n try {\n return parseFormat(value, allowed, name);\n } catch (e) {\n fail(e);\n }\n };\n }\n\n /**\n * The document-set surface every verb that reads pages shares (proposal\n * 0041): positional `[paths...]`, `--collection` and `--exclude` (each one\n * value per occurrence), and `-c`/`--no-config`. Declared once so the five\n * verbs cannot drift apart on a name or a description.\n */\n function documentInputs(command: Command, verb: string): Command {\n return command\n .argument(\n \"[paths...]\",\n `Files, directories, or globs to ${verb} (default: the configured collections)`,\n )\n .option(\n \"--collection <name>\",\n \"Configured collection to read (repeatable)\",\n collect,\n [],\n )\n .option(\"--exclude <glob>\", \"Glob to exclude (repeatable)\", collect, [])\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\");\n }\n\n /** The shared options as the command cores take them. */\n function documentOptions(opts: {\n collection?: string[];\n exclude?: string[];\n config?: string | boolean;\n }): DocumentInputOptions {\n const { configPath, noConfig } = configOption(opts.config);\n return {\n ...(configPath === undefined ? {} : { config: configPath }),\n ...(noConfig === true ? { noConfig } : {}),\n ...(opts.collection === undefined ? {} : { collection: opts.collection }),\n ...(opts.exclude === undefined ? {} : { exclude: opts.exclude }),\n };\n }\n\n documentInputs(\n program\n .command(\"list\")\n .description(\"Show the resolved eval plan per page without running anything\"),\n \"list\",\n )\n .option(\n \"-f, --format <format>\",\n `Output format: ${SUMMARY_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", SUMMARY_FORMATS),\n \"pretty\" as SummaryFormat,\n )\n .option(\"--eval <name>\", \"Show only this eval (repeatable)\", collectArg, [])\n .option(\"--suite <name>\", \"Show only evals in this suite\")\n .action(\n async (\n paths: string[],\n opts: {\n config?: string | boolean;\n collection?: string[];\n exclude?: string[];\n format: SummaryFormat;\n eval?: string[];\n suite?: string;\n },\n command: Command,\n ) => {\n try {\n const run = await runList(paths, {\n ...documentOptions(opts),\n format: opts.format,\n evalNames: opts.eval,\n suite: opts.suite,\n });\n console.log(\n renderList(run, opts.format, {\n color: colorFor(command, process.stdout.isTTY),\n }),\n );\n process.exitCode = run.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\n documentInputs(\n program.command(\"run\").description(\"Run evals against documentation pages\"),\n \"evaluate\",\n )\n .option(\n \"-f, --format <format>\",\n `Output format: ${REPORT_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", REPORT_FORMATS),\n \"pretty\" as ReportFormat,\n )\n .option(\"--deterministic-only\", \"Run only command/tool graders, skip the AI judge\")\n .option(\"--ai-only\", \"Run only AI-judged evals, skip deterministic graders\")\n .option(\n // `<kind>`, not `<kind...>`: a variadic option greedily eats the\n // positional `[paths...]` that follow it, so `--allow-execution\n // frontmatter-commands docs/**` would silently swallow the glob and run\n // over the default file set instead. Repeat the flag to grant twice.\n \"--allow-execution <kind>\",\n \"Run only these execution grants (repeatable): frontmatter-commands\",\n collectGrant,\n [],\n )\n .option(\"--no-execution\", \"Clear every execution grant for this run\")\n .option(\"--no-generate\", \"Do not generate scripts for command evals missing a command\")\n .option(\"--no-cache\", \"Bypass the judge response cache\")\n .option(\"--fail-on-review\", \"Exit 1 when any eval lands in the human-review zone\")\n .option(\"--provider <name>\", \"Judge provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .option(\"--runs <n>\", \"Ensemble runs per eval\", parseIntArg(\"--runs\"))\n .option(\n \"--chunk-chars <n>\",\n \"Characters of page per judge call; longer pages are read in parts\",\n parseIntArg(\"--chunk-chars\"),\n )\n .option(\n \"--eval <name>\",\n \"Run only this eval (repeatable); suite targets are not evaluated on a filtered run\",\n collectArg,\n [],\n )\n .option(\"--suite <name>\", \"Run only evals in this suite\")\n .option(\n \"--since <ref>\",\n \"Evaluate only pages whose file or eval manifest changed between this git ref and HEAD\",\n )\n .option(\n \"--newer-than <duration>\",\n \"Evaluate only pages whose file or eval manifest changed within this window, \" +\n \"such as 30m, 24h, 7d or 2w; in CI, prefer --since\",\n )\n .option(\n \"--max-turns <n>\",\n \"Stop after this many ensemble runs (a cached ensemble costs none)\",\n parseIntArg(\"--max-turns\"),\n )\n .option(\n \"--baseline [path]\",\n \"Fail only on findings a recorded baseline does not already hold\",\n )\n .option(\"--no-baseline\", \"Ignore the configured baseline for this run\")\n .option(\n \"--write-baseline [path]\",\n \"Record this run's findings as the baseline; without a path, the configured one\",\n )\n .action(async (paths: string[], opts: Record<string, unknown>, command: Command) => {\n try {\n const report = await runRun(paths, {\n ...documentOptions({\n config: opts.config as string | boolean | undefined,\n collection: opts.collection as string[] | undefined,\n exclude: opts.exclude as string[] | undefined,\n }),\n // parseFormatArg validated this at parse time; the cast only re-narrows\n // from the `unknown` that the Record-typed options bag erases it to.\n format: opts.format as ReportFormat,\n deterministicOnly: opts.deterministicOnly as boolean | undefined,\n aiOnly: opts.aiOnly as boolean | undefined,\n // Commander's default is `[]`, which is \"no flag\", not \"run nothing\":\n // only a list someone typed narrows the run.\n allowExecution:\n (opts.allowExecution as string[]).length > 0\n ? (opts.allowExecution as string[])\n : undefined,\n execution: opts.execution as boolean | undefined,\n generate: opts.generate as boolean | undefined,\n cache: opts.cache as boolean | undefined,\n failOnReview: opts.failOnReview as boolean | undefined,\n provider: opts.provider as string | undefined,\n model: opts.model as string | undefined,\n local: opts.local as boolean | undefined,\n runs: opts.runs as number | undefined,\n chunkChars: opts.chunkChars as number | undefined,\n maxTurns: opts.maxTurns as number | undefined,\n evalNames: opts.eval as string[] | undefined,\n suite: opts.suite as string | undefined,\n since: opts.since as string | undefined,\n newerThan: opts.newerThan as string | undefined,\n // commander collapses `--baseline` to true and `--no-baseline` to\n // false on the same key; a string is an explicit path.\n baseline: opts.baseline as string | boolean | undefined,\n writeBaseline: opts.writeBaseline as string | boolean | undefined,\n toolVersion: pkg.version,\n });\n console.log(\n render(report, opts.format as ReportFormat, {\n color: colorFor(command, process.stdout.isTTY),\n }),\n );\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\n documentInputs(\n program\n .command(\"generate\")\n .description(\n \"Generate check scripts for command evals with a plain-language assertion but no command\",\n ),\n \"read\",\n )\n .option(\"--provider <name>\", \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .action(\n async (\n paths: string[],\n opts: {\n config?: string | boolean;\n collection?: string[];\n exclude?: string[];\n provider?: string;\n model?: string;\n local?: boolean;\n },\n command: Command,\n ) => {\n try {\n const pc = palette(colorFor(command, process.stdout.isTTY));\n const result = await runGenerate(paths, {\n ...documentOptions(opts),\n provider: opts.provider,\n model: opts.model,\n local: opts.local,\n });\n if (result.targets === 0) {\n console.log(\"Nothing to generate — every command eval has a command.\");\n return;\n }\n console.log(\n `Generated ${result.generatedPaths.length}/${result.targets} check script(s):`,\n );\n for (const p of result.generatedPaths) console.log(` ${p}`);\n // Evals whose command reference had nowhere to go (proposal 0047).\n for (const r of result.refusals) console.log(pc.red(` ${r.message}`));\n if (result.generatedPaths.length < result.targets) {\n process.exitCode = 1;\n }\n } catch (e) {\n fail(e);\n }\n },\n );\n\n documentInputs(\n program\n .command(\"fill\")\n .description(\n \"Propose frontmatter evals for pages with an LLM; writes proposals at or above the confidence threshold\",\n ),\n \"fill\",\n )\n .option(\n \"-f, --format <format>\",\n `Output format: ${SUMMARY_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", SUMMARY_FORMATS),\n \"pretty\" as SummaryFormat,\n )\n .option(\"--dry-run\", \"Report proposals without writing frontmatter\")\n .option(\n \"--confidence <n>\",\n \"Minimum confidence to write (0-1, default: config fill.confidenceThreshold)\",\n parseFloatArg(\"--confidence\"),\n )\n .option(\n \"--max-turns <n>\",\n \"Stop after this many inference calls (a cached page costs none)\",\n parseIntArg(\"--max-turns\"),\n )\n .option(\"--no-cache\", \"Bypass the fill proposal cache\")\n .option(\n \"--chunk-chars <n>\",\n \"Characters of page per fill call; longer pages are proposed in parts\",\n parseIntArg(\"--chunk-chars\"),\n )\n .option(\"--provider <name>\", \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .action(async (paths: string[], opts: Record<string, unknown>, command: Command) => {\n try {\n const confidence = opts.confidence as number | undefined;\n if (confidence !== undefined && confidence > 1) {\n fail(new DocevalsError(`--confidence must be between 0 and 1, got ${confidence}`));\n }\n const report = await runFill(paths, {\n ...documentOptions({\n config: opts.config as string | boolean | undefined,\n collection: opts.collection as string[] | undefined,\n exclude: opts.exclude as string[] | undefined,\n }),\n dryRun: opts.dryRun as boolean | undefined,\n confidence,\n maxTurns: opts.maxTurns as number | undefined,\n noCache: opts.cache === false ? true : undefined,\n provider: opts.provider as string | undefined,\n model: opts.model as string | undefined,\n local: opts.local as boolean | undefined,\n // P1 (proposal 0047): offered only on a terminal, where there is\n // someone to answer. Off one the evals go to the page and the W1\n // line says so.\n confirm: terminalConfirm(),\n onNotice: notice,\n onRelocated: (result) => {\n const manifests = result.manifests.map((m) => m.file).join(\", \");\n notice(\n `moved ${String(result.summary.moved)} value(s) into ${manifests}.`,\n );\n },\n });\n // As in `run`: parseFormatArg validated this at parse time, and the cast\n // only re-narrows from the `unknown` the Record-typed options bag erases\n // it to. renderFill guards itself regardless.\n console.log(\n renderFill(report, opts.format as SummaryFormat, {\n color: colorFor(command, process.stdout.isTTY),\n }),\n );\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\n documentInputs(\n program\n .command(\"promote\")\n .description(\n \"Find ai-graded evals expressible as deterministic checks; --write converts them\",\n ),\n \"read\",\n )\n .option(\"--write\", \"Apply promotions (write scripts and rewrite evals)\")\n .option(\"--provider <name>\", \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .action(\n async (\n paths: string[],\n opts: {\n config?: string | boolean;\n collection?: string[];\n exclude?: string[];\n write?: boolean;\n provider?: string;\n model?: string;\n local?: boolean;\n },\n command: Command,\n ) => {\n try {\n const pc = palette(colorFor(command, process.stdout.isTTY));\n const proposals = await runPromote(paths, {\n ...documentOptions(opts),\n write: opts.write,\n provider: opts.provider,\n model: opts.model,\n local: opts.local,\n });\n if (proposals.length === 0) {\n console.log(\"No ai-graded evals found.\");\n return;\n }\n for (const p of proposals) {\n const tag = p.promotable\n ? p.applied\n ? pc.green(\"promoted\")\n : pc.cyan(\"promotable\")\n : pc.dim(\"keep-ai\");\n const script = p.scriptPath ? pc.dim(` -> ${p.scriptPath}`) : \"\";\n console.log(`${tag} ${p.evalName} (${p.source}, ${p.file})${script}`);\n console.log(pc.dim(` ${p.rationale}`));\n // Promotable, and nowhere to write it (proposal 0047).\n if (p.error !== undefined) console.log(pc.red(` ${p.error}`));\n }\n if (!opts.write && proposals.some((p) => p.promotable)) {\n console.log(pc.cyan(\"\\nRe-run with --write to apply promotions.\"));\n }\n } catch (e) {\n fail(e);\n }\n },\n );\n\n program\n .command(\"calibrate\")\n .description(\n \"Measure judge agreement against a human-verified golden set (.manni/docevals/golden/*.yaml)\",\n )\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--golden <dir>\", \"Golden set directory\", \".manni/docevals/golden\")\n .option(\n \"--seed\",\n \"Write golden candidates from recorded reviews and exit; judges nothing, needs no provider\",\n )\n .option(\"--provider <name>\", \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\")\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n .option(\"--runs <n>\", \"Ensemble runs per case\", parseIntArg(\"--runs\"))\n .option(\n \"--max-turns <n>\",\n \"Stop after this many ensemble runs (a cached ensemble costs none)\",\n parseIntArg(\"--max-turns\"),\n )\n .option(\"--no-cache\", \"Bypass the judge response cache\")\n .action(\n async (opts: {\n config?: string;\n golden?: string;\n seed?: boolean;\n provider?: string;\n model?: string;\n local?: boolean;\n runs?: number;\n maxTurns?: number;\n cache?: boolean;\n }, command: Command) => {\n try {\n const color = colorFor(command, process.stdout.isTTY);\n const pc = palette(color);\n if (opts.seed) {\n // No `config`: reviews.yaml and the golden directory both resolve\n // against the working directory, not the config's, so passing it\n // would imply an influence it does not have.\n const seeded = seedGoldenCases({ golden: opts.golden });\n if (seeded.total === 0) {\n console.log(\n \"No recorded reviews to seed from — run `manni docevals review <file> <eval> <pass|fail>` first.\",\n );\n return;\n }\n // The lead number is what moved, not the file's size: `total`\n // counts cases already confirmed and left alone, so leading with it\n // read as \"wrote 8 candidates\" on a re-seed that wrote none.\n const changed = seeded.added + seeded.updated;\n console.log(\n changed === 0\n ? `No new reviews to seed — ${seeded.total} golden case(s) already in ${seeded.path}.`\n : `Wrote ${changed} golden candidate(s) to ${seeded.path} ` +\n `(${seeded.added} new, ${seeded.updated} updated; ${seeded.total} total).`,\n );\n if (seeded.unreviewed > 0) {\n console.log(\n pc.yellow(\n `${seeded.unreviewed} case(s) are \\`reviewed: false\\`. Read them and set ` +\n \"`reviewed: true` — a golden set assembled without a human is not one.\",\n ),\n );\n }\n return;\n }\n const report = await runCalibrate({\n config: opts.config,\n golden: opts.golden,\n provider: opts.provider,\n model: opts.model,\n local: opts.local,\n runs: opts.runs,\n maxTurns: opts.maxTurns,\n noCache: opts.cache === false,\n });\n console.log(renderCalibration(report, { color }));\n // Both conditions: the judge has to agree enough, AND the set has to\n // have been measured. A stale golden file whose pages were renamed\n // used to certify on whatever still resolved.\n process.exitCode =\n report.meetsThreshold &&\n report.unjudged === 0 &&\n report.balanced\n ? 0\n : 1;\n } catch (e) {\n fail(e);\n }\n },\n );\n\n program\n .command(\"init\")\n .description(\"Create a starter manni.config.yaml in the current directory\")\n .action(() => {\n try {\n console.log(`Created ${runInit()}`);\n } catch (e) {\n fail(e);\n }\n });\n\n program\n .command(\"review\")\n .description(\n \"Record a human verdict for an eval in the human-review zone (or list recorded reviews)\",\n )\n .argument(\"[file]\", \"Page path\")\n .argument(\"[eval]\", \"Eval name\")\n .argument(\"[verdict]\", \"pass | fail\")\n .option(\"--reviewer <name>\", \"Reviewer name recorded with the verdict\")\n .option(\"--note <text>\", \"Optional note\")\n .action(\n (\n file: string | undefined,\n evalName: string | undefined,\n verdict: string | undefined,\n opts: { reviewer?: string; note?: string },\n command: Command,\n ) => {\n try {\n if (!file) {\n console.log(\n renderReviews(listReviews(), {\n color: colorFor(command, process.stdout.isTTY),\n }),\n );\n return;\n }\n if (!evalName || !verdict) {\n throw new DocevalsError(\n \"Usage: manni docevals review <file> <eval> <pass|fail>\",\n );\n }\n const entry = runReview(file, evalName, verdict, opts);\n console.log(\n `Recorded ${entry.verdict} for ${entry.evalName} on ${entry.file}`,\n );\n } catch (e) {\n fail(e);\n }\n },\n );\n\n return program;\n}\n"],"mappings":"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","names":[]}
@@ -3,46 +3,47 @@ import {
3
3
  KeyError,
4
4
  runKeyRotate,
5
5
  runKeySet
6
- } from "./chunk-NSBXVPZL.js";
7
- import "./chunk-FQXWVS6J.js";
8
- import "./chunk-PCS4VJBV.js";
9
- import "./chunk-ADMEPUBT.js";
10
- import "./chunk-4D5IZSXM.js";
11
- import "./chunk-WDWXAYVH.js";
6
+ } from "./chunk-U22TOL5Y.js";
7
+ import "./chunk-CH6IOGXV.js";
8
+ import "./chunk-DGRLHDM4.js";
9
+ import "./chunk-GQ3KRY3B.js";
10
+ import "./chunk-OHUDZRLK.js";
11
+ import "./chunk-AYVKN3PG.js";
12
+ import "./chunk-24AJK2RG.js";
12
13
  import "./chunk-PCE7QHXJ.js";
13
- import "./chunk-77AINBYM.js";
14
- import "./chunk-BKVHX6FU.js";
15
14
  import "./chunk-IKEWBMCN.js";
16
- import "./chunk-TU2WUBVZ.js";
17
- import "./chunk-LKP7QDFN.js";
18
- import "./chunk-6HWBRZIN.js";
19
- import "./chunk-M42DZCOU.js";
20
- import "./chunk-PCQ7ELJH.js";
15
+ import "./chunk-YUTVAMWW.js";
16
+ import "./chunk-JSSM7VVV.js";
17
+ import "./chunk-PS257NIU.js";
18
+ import "./chunk-2OZF2VUB.js";
19
+ import {
20
+ COMMON_FORMAT_LIST
21
+ } from "./chunk-SGR7ZAVE.js";
22
+ import "./chunk-QEAGL4V5.js";
21
23
  import {
22
24
  collect,
23
25
  explicitFalse,
24
26
  splitList
25
- } from "./chunk-GV56WGL2.js";
26
- import {
27
- COMMON_FORMAT_LIST
28
- } from "./chunk-D4N2V43Z.js";
29
- import "./chunk-VSEBFHAY.js";
30
- import {
31
- fail
32
- } from "./chunk-YEUYKR62.js";
27
+ } from "./chunk-SMHAYK6I.js";
28
+ import "./chunk-DSWKBZWW.js";
29
+ import "./chunk-RGLFV4KO.js";
30
+ import "./chunk-77AINBYM.js";
31
+ import "./chunk-MNH7QO4Z.js";
33
32
  import {
34
33
  palette,
35
34
  shouldColor
36
35
  } from "./chunk-RNVYGWIC.js";
37
- import "./chunk-MNH7QO4Z.js";
38
- import "./chunk-QLWC7MKD.js";
36
+ import {
37
+ fail
38
+ } from "./chunk-YEUYKR62.js";
39
+ import "./chunk-OTJOBZJ5.js";
39
40
  import {
40
41
  notice
41
42
  } from "./chunk-HX44GB4Z.js";
42
- import "./chunk-QCHVR4ZM.js";
43
+ import "./chunk-VM7VAFJW.js";
43
44
  import {
44
45
  package_default
45
- } from "./chunk-2MJ62AYQ.js";
46
+ } from "./chunk-DHGB4JBG.js";
46
47
  import "./chunk-OWBRDNRZ.js";
47
48
  import "./chunk-G3T47CFV.js";
48
49
  import "./chunk-2H7UOFLK.js";
@@ -231,4 +232,4 @@ function buildProgram() {
231
232
  export {
232
233
  buildProgram
233
234
  };
234
- //# sourceMappingURL=cli-3BTCK4AB.js.map
235
+ //# sourceMappingURL=cli-MQYCF3SR.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/key/cli.ts","../src/key/reporters/json.ts","../src/key/reporters/pretty.ts"],"sourcesContent":["/**\n * The `key` domain's commander program. Mounted by `src/cli.ts` under\n * `manni key`; no entry point of its own. Proposal 0045 extends 0034's\n * grammar: a domain is a tool, or a family resource with verbs. `key` is the\n * second kind, with two verbs, `set` and `rotate`, and no default subcommand.\n *\n * clig.dev as every tool has it: the report to stdout, diagnostics to stderr,\n * colour only on a TTY and never under `NO_COLOR`/`--no-color`, exit `0` done,\n * `1` a value that could not be re-encrypted, `2` operational/usage. Nothing\n * this program prints is ever a key.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { collect, explicitFalse, splitList } from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport { COMMON_FORMAT_LIST } from \"../meta/internal.js\";\nimport { runKeyRotate } from \"./commands/rotate.js\";\nimport { runKeySet } from \"./commands/set.js\";\nimport { KeyError } from \"./errors.js\";\nimport { renderRotateJson } from \"./reporters/json.js\";\nimport { BASELINE_NOTICE, renderRotatePretty, setMessage } from \"./reporters/pretty.js\";\n\nconst ROTATE_FORMATS = [\"pretty\", \"json\"] as const;\ntype RotateFormat = (typeof ROTATE_FORMATS)[number];\n\nfunction isRotateFormat(value: string): value is RotateFormat {\n return (ROTATE_FORMATS as readonly string[]).includes(value);\n}\n\n/** What commander hands `set`'s action. */\ninterface SetCliOptions {\n /** `-c, --config <path>`. */\n config?: string;\n dryRun?: boolean;\n}\n\n/**\n * What commander hands `rotate`'s action. The `--no-<thing>` flags are\n * `boolean` and never `undefined`: commander supplies `true` when the flag is\n * absent, so only the explicit `false` travels to the core (`explicitFalse`).\n */\ninterface RotateCliOptions {\n to?: string;\n /** `--collection <name>`, repeatable; commander's default value is `[]`. */\n collection: string[];\n /** `--ext <list>`; the command splits it. */\n ext?: string;\n /** `--exclude <glob>`, repeatable; commander's default value is `[]`. */\n exclude: string[];\n as?: string;\n config?: string;\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n gitignore: boolean;\n root?: string;\n dryRun?: boolean;\n /** `-f, --format <format>`. Always a string: the declaration has a default. */\n format: string;\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"key\")\n .description(\"Set and rotate the family key that encrypted values are encrypted with.\")\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n // A pointer, not the whole help screen: the message that precedes it\n // already names the offending flag.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before the `.command()` calls below. `copyInheritedSettings`\n // copies `_exitCallback` by value at subcommand-creation time, so an\n // `exitOverride()` installed afterwards leaves every subcommand still\n // calling `process.exit(1)`.\n .exitOverride();\n\n /** This domain's `--no-color`, wherever the domain is mounted. */\n const color = (): boolean =>\n shouldColor({ noColor: program.opts().color === false, isTTY: process.stdout.isTTY });\n\n program\n .command(\"set\")\n .description(\"Write the family encryption key to manni.config.yaml; generate one when no value is given\")\n .argument(\"[value]\", \"the key, at least 32 hex or base64url characters (default: 64 random hex)\")\n .option(\n \"-c, --config <path>\",\n \"the config file to write (default: the nearest manni.config.yaml, else a new one at the git root)\",\n )\n .option(\"--dry-run\", \"say what would be written; write nothing\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni key set # generate 256 bits into manni.config.yaml\",\n \" manni key set --dry-run # name the file, write nothing\",\n \" manni key set -c ops/manni.config.yaml 0123456789abcdef0123456789abcdef\",\n ].join(\"\\n\"),\n )\n .action(async (value: string | undefined, options: SetCliOptions) => {\n try {\n const result = await runKeySet({\n value,\n configPath: options.config,\n dryRun: Boolean(options.dryRun),\n onNotice: notice,\n });\n process.stdout.write(`${setMessage(result)}\\n`);\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"rotate\")\n .description(\"Re-encrypt every encrypted value under a new key, then write the key\")\n .argument(\"[paths...]\", \"files, directories, or globs (default: every collection)\")\n .option(\n \"--to <value>\",\n \"the new key (default: 64 random hex); required for a narrowed run and a key from MANNI_ENCRYPTION_KEY\",\n )\n .option(\"--collection <name>\", \"configured collection to run over; repeatable\", collect, [])\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format for every input\")\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"include files .gitignore covers\")\n .option(\n \"--root <dir>\",\n \"directory cited sources resolve from (default: cite.root from config, else the git root)\",\n )\n .option(\"--dry-run\", \"print what would change; write nothing\")\n .option(\"-f, --format <format>\", `output: ${ROTATE_FORMATS.join(\" | \")}`, \"pretty\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni key rotate # every collection, then the key\",\n \" manni key rotate --dry-run # see every change first\",\n ' manni key rotate --collection site --to \"$NEW_KEY\" # part of the family',\n ' MANNI_ENCRYPTION_KEY=… manni key rotate --to \"$NEW_KEY\"',\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: RotateCliOptions) => {\n try {\n const format = options.format;\n if (!isRotateFormat(format)) {\n throw new KeyError(`Unknown --format \"${format}\". Use ${COMMON_FORMAT_LIST}.`);\n }\n const result = await runKeyRotate({\n inputs: paths,\n collection: options.collection,\n to: options.to,\n exts: options.ext ? splitList(options.ext) : undefined,\n exclude: options.exclude,\n as: options.as,\n configPath: options.config,\n // `undefined` rather than `false` when absent.\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: explicitFalse(options.gitignore),\n root: options.root,\n dryRun: Boolean(options.dryRun),\n onNotice: notice,\n });\n if (format === \"json\") {\n process.stdout.write(`${renderRotateJson(result)}\\n`);\n // stdout is the JSON's; the notice is a diagnostic.\n if (result.baselineStale) notice(BASELINE_NOTICE);\n } else {\n process.stdout.write(`${renderRotatePretty(result, { color: color() })}\\n`);\n }\n process.exitCode = result.exitCode;\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n","/**\n * JSON output for `key rotate`: every page and every local external-metadata\n * manifest with something encrypted in it, each value's full ciphertext\n * before and after, and the counts. The key is never in it.\n */\nimport type { KeyRotateResult } from \"../types.js\";\n\nexport function renderRotateJson(result: KeyRotateResult): string {\n return JSON.stringify(\n {\n pages: result.pages,\n manifests: result.manifests,\n reencrypted: result.reencrypted,\n skipped: result.skipped,\n keyWritten: result.keyWritten,\n },\n null,\n 2,\n );\n}\n","/**\n * Pretty output for `key set` and `key rotate`. A ciphertext is shown as `~`\n * and its first four characters, then `…`, with a citation's line suffix\n * after it: `~AQx7…`, `~AQm4…:2`. The full values are in `-f json`; the key\n * is in neither. Colour via `shouldColor`; never under `--no-color`/`NO_COLOR`.\n */\nimport { palette } from \"../../shared/color.js\";\nimport type { KeyRotateResult, KeySetResult, RotatedValue, SkippedValue } from \"../types.js\";\n\nexport interface PrettyOptions {\n color: boolean;\n}\n\n/** Said at the end of a writing rotation when a citation baseline exists. */\nexport const BASELINE_NOTICE =\n \"The citation baseline fingerprints id-less encrypted citations by their pin; re-record it with `manni cite check --write-baseline`.\";\n\nconst NARROWED =\n \"Key not written: this run covered part of the family. Finish with a whole run under the same key: `manni key rotate --to <the same value>`.\";\nconst FROM_ENV =\n \"Key not written: it comes from MANNI_ENCRYPTION_KEY. Update the secret to the value you passed.\";\n\nconst plural = (n: number, one: string, many = `${one}s`): string =>\n `${String(n)} ${n === 1 ? one : many}`;\n\n/** What `set` says: the file, never the key. */\nexport function setMessage(result: KeySetResult): string {\n return result.dryRun\n ? `Would write encryptionKey to ${result.source}.`\n : `Encryption key written to ${result.source}.`;\n}\n\n/** `~AQx7…`, and a citation's line suffix after it: `~AQm4…:2`. */\nexport function shortCiphertext(value: string): string {\n // base64url has no `:`, so the first one starts the line suffix.\n const colon = value.indexOf(\":\");\n const token = colon === -1 ? value : value.slice(0, colon);\n const suffix = colon === -1 ? \"\" : value.slice(colon);\n return `${token.slice(0, 5)}…${suffix}`;\n}\n\n/** A metadata value by its pointer; a citation by its id, else where it sits. */\nfunction nameOf(row: RotatedValue | SkippedValue): string {\n if (row.kind === \"metadata\") return row.pointer;\n if (row.id !== undefined) return row.id;\n if (row.index !== undefined) return `/citations/${String(row.index)}`;\n return `line ${String(row.line ?? 0)}`;\n}\n\nfunction closing(result: KeyRotateResult): string | undefined {\n switch (result.outcome) {\n case \"written\":\n return result.configSource === undefined\n ? undefined\n : `Encryption key written to ${result.configSource}.`;\n case \"finished\":\n // Said before the counts: the key was written by the run that stopped.\n return undefined;\n case \"narrowed\":\n return NARROWED;\n case \"env\":\n return FROM_ENV;\n case \"skipped\":\n return result.skipped === 1\n ? \"Key not written: 1 value could not be re-encrypted. Fix it and rotate again.\"\n : `Key not written: ${String(result.skipped)} values could not be re-encrypted. Fix them and rotate again.`;\n case \"dry-run\":\n return \"Dry run: nothing written.\";\n }\n}\n\nexport function renderRotatePretty(result: KeyRotateResult, opts: PrettyOptions): string {\n const c = palette(opts.color);\n const lines: string[] = [];\n for (const page of result.pages) {\n for (const row of page.rewritten) {\n // A metadata value has no line suffix; two spaces keep its arrow in the\n // column a `:L` suffix would take.\n const gap = row.kind === \"metadata\" ? \" \" : \" \";\n lines.push(\n `${page.file}: ${nameOf(row)} ${c.dim(shortCiphertext(row.from))}${gap}-> ${shortCiphertext(row.to)}`,\n );\n }\n for (const row of page.skipped) {\n lines.push(`${page.file}: ${nameOf(row)} ${c.red(\"skipped:\")} ${row.message}`);\n }\n }\n // A manifest value is named by the entry it belongs to and the pointer\n // inside it, so one line says which document's private half moved.\n for (const manifest of result.manifests) {\n for (const row of manifest.rewritten) {\n lines.push(\n `${manifest.file}: ${row.entry}${row.pointer} ${c.dim(shortCiphertext(row.from))} -> ${shortCiphertext(row.to)}`,\n );\n }\n for (const row of manifest.skipped) {\n lines.push(\n `${manifest.file}: ${row.entry}${row.pointer} ${c.red(\"skipped:\")} ${row.message}`,\n );\n }\n }\n if (result.outcome === \"finished\" && result.configSource !== undefined) {\n lines.push(`Finished the interrupted rotation in ${result.configSource}.`);\n }\n const files =\n result.pages.filter((page) => page.rewritten.length > 0).length +\n result.manifests.filter((manifest) => manifest.rewritten.length > 0).length;\n lines.push(\n `${plural(result.reencrypted, \"value\")} re-encrypted in ${plural(files, \"file\")}, ${String(result.skipped)} skipped`,\n );\n const last = closing(result);\n if (last !== undefined) lines.push(result.outcome === \"skipped\" ? c.red(last) : last);\n if (result.baselineStale) lines.push(BASELINE_NOTICE);\n return lines.join(\"\\n\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,SAAS,eAAe;;;ACJjB,SAAS,iBAAiB,QAAiC;AAChE,SAAO,KAAK;AAAA,IACV;AAAA,MACE,OAAO,OAAO;AAAA,MACd,WAAW,OAAO;AAAA,MAClB,aAAa,OAAO;AAAA,MACpB,SAAS,OAAO;AAAA,MAChB,YAAY,OAAO;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACLO,IAAM,kBACX;AAEF,IAAM,WACJ;AACF,IAAM,WACJ;AAEF,IAAM,SAAS,CAAC,GAAW,KAAa,OAAO,GAAG,GAAG,QACnD,GAAG,OAAO,CAAC,CAAC,IAAI,MAAM,IAAI,MAAM,IAAI;AAG/B,SAAS,WAAW,QAA8B;AACvD,SAAO,OAAO,SACV,gCAAgC,OAAO,MAAM,MAC7C,6BAA6B,OAAO,MAAM;AAChD;AAGO,SAAS,gBAAgB,OAAuB;AAErD,QAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,QAAM,QAAQ,UAAU,KAAK,QAAQ,MAAM,MAAM,GAAG,KAAK;AACzD,QAAM,SAAS,UAAU,KAAK,KAAK,MAAM,MAAM,KAAK;AACpD,SAAO,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC,SAAI,MAAM;AACvC;AAGA,SAAS,OAAO,KAA0C;AACxD,MAAI,IAAI,SAAS,WAAY,QAAO,IAAI;AACxC,MAAI,IAAI,OAAO,OAAW,QAAO,IAAI;AACrC,MAAI,IAAI,UAAU,OAAW,QAAO,cAAc,OAAO,IAAI,KAAK,CAAC;AACnE,SAAO,QAAQ,OAAO,IAAI,QAAQ,CAAC,CAAC;AACtC;AAEA,SAAS,QAAQ,QAA6C;AAC5D,UAAQ,OAAO,SAAS;AAAA,IACtB,KAAK;AACH,aAAO,OAAO,iBAAiB,SAC3B,SACA,6BAA6B,OAAO,YAAY;AAAA,IACtD,KAAK;AAEH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,OAAO,YAAY,IACtB,iFACA,oBAAoB,OAAO,OAAO,OAAO,CAAC;AAAA,IAChD,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEO,SAAS,mBAAmB,QAAyB,MAA6B;AACvF,QAAM,IAAI,QAAQ,KAAK,KAAK;AAC5B,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,OAAO,OAAO;AAC/B,eAAW,OAAO,KAAK,WAAW;AAGhC,YAAM,MAAM,IAAI,SAAS,aAAa,OAAO;AAC7C,YAAM;AAAA,QACJ,GAAG,KAAK,IAAI,KAAK,OAAO,GAAG,CAAC,KAAK,EAAE,IAAI,gBAAgB,IAAI,IAAI,CAAC,CAAC,GAAG,GAAG,MAAM,gBAAgB,IAAI,EAAE,CAAC;AAAA,MACtG;AAAA,IACF;AACA,eAAW,OAAO,KAAK,SAAS;AAC9B,YAAM,KAAK,GAAG,KAAK,IAAI,KAAK,OAAO,GAAG,CAAC,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,IAAI,OAAO,EAAE;AAAA,IAChF;AAAA,EACF;AAGA,aAAW,YAAY,OAAO,WAAW;AACvC,eAAW,OAAO,SAAS,WAAW;AACpC,YAAM;AAAA,QACJ,GAAG,SAAS,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,OAAO,KAAK,EAAE,IAAI,gBAAgB,IAAI,IAAI,CAAC,CAAC,QAAQ,gBAAgB,IAAI,EAAE,CAAC;AAAA,MAClH;AAAA,IACF;AACA,eAAW,OAAO,SAAS,SAAS;AAClC,YAAM;AAAA,QACJ,GAAG,SAAS,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,OAAO,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,IAAI,OAAO;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,YAAY,cAAc,OAAO,iBAAiB,QAAW;AACtE,UAAM,KAAK,wCAAwC,OAAO,YAAY,GAAG;AAAA,EAC3E;AACA,QAAM,QACJ,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,UAAU,SAAS,CAAC,EAAE,SACzD,OAAO,UAAU,OAAO,CAAC,aAAa,SAAS,UAAU,SAAS,CAAC,EAAE;AACvE,QAAM;AAAA,IACJ,GAAG,OAAO,OAAO,aAAa,OAAO,CAAC,oBAAoB,OAAO,OAAO,MAAM,CAAC,KAAK,OAAO,OAAO,OAAO,CAAC;AAAA,EAC5G;AACA,QAAM,OAAO,QAAQ,MAAM;AAC3B,MAAI,SAAS,OAAW,OAAM,KAAK,OAAO,YAAY,YAAY,EAAE,IAAI,IAAI,IAAI,IAAI;AACpF,MAAI,OAAO,cAAe,OAAM,KAAK,eAAe;AACpD,SAAO,MAAM,KAAK,IAAI;AACxB;;;AF1FA,IAAM,iBAAiB,CAAC,UAAU,MAAM;AAGxC,SAAS,eAAe,OAAsC;AAC5D,SAAQ,eAAqC,SAAS,KAAK;AAC7D;AAiCO,SAAS,eAAwB;AACtC,QAAM,UAAU,IAAI,QAAQ;AAC5B,UACG,KAAK,KAAK,EACV,YAAY,yEAAyE,EACrF,QAAQ,gBAAI,SAAS,eAAe,EACpC,OAAO,cAAc,wBAAwB,EAG7C,mBAAmB,wBAAwB,EAK3C,aAAa;AAGhB,QAAM,QAAQ,MACZ,YAAY,EAAE,SAAS,QAAQ,KAAK,EAAE,UAAU,OAAO,OAAO,QAAQ,OAAO,MAAM,CAAC;AAEtF,UACG,QAAQ,KAAK,EACb,YAAY,2FAA2F,EACvG,SAAS,WAAW,2EAA2E,EAC/F;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,aAAa,0CAA0C,EAC9D;AAAA,IACC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb,EACC,OAAO,OAAO,OAA2B,YAA2B;AACnE,QAAI;AACF,YAAM,SAAS,MAAM,UAAU;AAAA,QAC7B;AAAA,QACA,YAAY,QAAQ;AAAA,QACpB,QAAQ,QAAQ,QAAQ,MAAM;AAAA,QAC9B,UAAU;AAAA,MACZ,CAAC;AACD,cAAQ,OAAO,MAAM,GAAG,WAAW,MAAM,CAAC;AAAA,CAAI;AAC9C,cAAQ,WAAW;AAAA,IACrB,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAEH,UACG,QAAQ,QAAQ,EAChB,YAAY,sEAAsE,EAClF,SAAS,cAAc,0DAA0D,EACjF;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,uBAAuB,iDAAiD,SAAS,CAAC,CAAC,EAC1F,OAAO,gBAAgB,gDAAgD,EACvE,OAAO,oBAAoB,+BAA+B,SAAS,CAAC,CAAC,EACrE,OAAO,iBAAiB,uCAAuC,EAC/D,OAAO,uBAAuB,6BAA6B,EAC3D,OAAO,iBAAiB,qCAAqC,EAC7D,OAAO,kBAAkB,iCAAiC,EAC1D;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,aAAa,wCAAwC,EAC5D,OAAO,yBAAyB,WAAW,eAAe,KAAK,KAAK,CAAC,IAAI,QAAQ,EACjF;AAAA,IACC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb,EACC,OAAO,OAAO,OAAiB,YAA8B;AAC5D,QAAI;AACF,YAAM,SAAS,QAAQ;AACvB,UAAI,CAAC,eAAe,MAAM,GAAG;AAC3B,cAAM,IAAI,SAAS,qBAAqB,MAAM,UAAU,kBAAkB,GAAG;AAAA,MAC/E;AACA,YAAM,SAAS,MAAM,aAAa;AAAA,QAChC,QAAQ;AAAA,QACR,YAAY,QAAQ;AAAA,QACpB,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ,MAAM,UAAU,QAAQ,GAAG,IAAI;AAAA,QAC7C,SAAS,QAAQ;AAAA,QACjB,IAAI,QAAQ;AAAA,QACZ,YAAY,QAAQ;AAAA;AAAA,QAEpB,YAAY,QAAQ,aAAa,OAAO;AAAA,QACxC,kBAAkB,cAAc,QAAQ,SAAS;AAAA,QACjD,MAAM,QAAQ;AAAA,QACd,QAAQ,QAAQ,QAAQ,MAAM;AAAA,QAC9B,UAAU;AAAA,MACZ,CAAC;AACD,UAAI,WAAW,QAAQ;AACrB,gBAAQ,OAAO,MAAM,GAAG,iBAAiB,MAAM,CAAC;AAAA,CAAI;AAEpD,YAAI,OAAO,cAAe,QAAO,eAAe;AAAA,MAClD,OAAO;AACL,gBAAQ,OAAO,MAAM,GAAG,mBAAmB,QAAQ,EAAE,OAAO,MAAM,EAAE,CAAC,CAAC;AAAA,CAAI;AAAA,MAC5E;AACA,cAAQ,WAAW,OAAO;AAAA,IAC5B,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAEH,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/key/cli.ts","../src/key/reporters/json.ts","../src/key/reporters/pretty.ts"],"sourcesContent":["/**\n * The `key` domain's commander program. Mounted by `src/cli.ts` under\n * `manni key`; no entry point of its own. Proposal 0045 extends 0034's\n * grammar: a domain is a tool, or a family resource with verbs. `key` is the\n * second kind, with two verbs, `set` and `rotate`, and no default subcommand.\n *\n * clig.dev as every tool has it: the report to stdout, diagnostics to stderr,\n * colour only on a TTY and never under `NO_COLOR`/`--no-color`, exit `0` done,\n * `1` a value that could not be re-encrypted, `2` operational/usage. Nothing\n * this program prints is ever a key.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { collect, explicitFalse, splitList } from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport { COMMON_FORMAT_LIST } from \"../meta/internal.js\";\nimport { runKeyRotate } from \"./commands/rotate.js\";\nimport { runKeySet } from \"./commands/set.js\";\nimport { KeyError } from \"./errors.js\";\nimport { renderRotateJson } from \"./reporters/json.js\";\nimport { BASELINE_NOTICE, renderRotatePretty, setMessage } from \"./reporters/pretty.js\";\n\nconst ROTATE_FORMATS = [\"pretty\", \"json\"] as const;\ntype RotateFormat = (typeof ROTATE_FORMATS)[number];\n\nfunction isRotateFormat(value: string): value is RotateFormat {\n return (ROTATE_FORMATS as readonly string[]).includes(value);\n}\n\n/** What commander hands `set`'s action. */\ninterface SetCliOptions {\n /** `-c, --config <path>`. */\n config?: string;\n dryRun?: boolean;\n}\n\n/**\n * What commander hands `rotate`'s action. The `--no-<thing>` flags are\n * `boolean` and never `undefined`: commander supplies `true` when the flag is\n * absent, so only the explicit `false` travels to the core (`explicitFalse`).\n */\ninterface RotateCliOptions {\n to?: string;\n /** `--collection <name>`, repeatable; commander's default value is `[]`. */\n collection: string[];\n /** `--ext <list>`; the command splits it. */\n ext?: string;\n /** `--exclude <glob>`, repeatable; commander's default value is `[]`. */\n exclude: string[];\n as?: string;\n config?: string;\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n gitignore: boolean;\n root?: string;\n dryRun?: boolean;\n /** `-f, --format <format>`. Always a string: the declaration has a default. */\n format: string;\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"key\")\n .description(\"Set and rotate the family key that encrypted values are encrypted with.\")\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n // A pointer, not the whole help screen: the message that precedes it\n // already names the offending flag.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before the `.command()` calls below. `copyInheritedSettings`\n // copies `_exitCallback` by value at subcommand-creation time, so an\n // `exitOverride()` installed afterwards leaves every subcommand still\n // calling `process.exit(1)`.\n .exitOverride();\n\n /** This domain's `--no-color`, wherever the domain is mounted. */\n const color = (): boolean =>\n shouldColor({ noColor: program.opts().color === false, isTTY: process.stdout.isTTY });\n\n program\n .command(\"set\")\n .description(\"Write the family encryption key to manni.config.yaml; generate one when no value is given\")\n .argument(\"[value]\", \"the key, at least 32 hex or base64url characters (default: 64 random hex)\")\n .option(\n \"-c, --config <path>\",\n \"the config file to write (default: the nearest manni.config.yaml, else a new one at the git root)\",\n )\n .option(\"--dry-run\", \"say what would be written; write nothing\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni key set # generate 256 bits into manni.config.yaml\",\n \" manni key set --dry-run # name the file, write nothing\",\n \" manni key set -c ops/manni.config.yaml 0123456789abcdef0123456789abcdef\",\n ].join(\"\\n\"),\n )\n .action(async (value: string | undefined, options: SetCliOptions) => {\n try {\n const result = await runKeySet({\n value,\n configPath: options.config,\n dryRun: Boolean(options.dryRun),\n onNotice: notice,\n });\n process.stdout.write(`${setMessage(result)}\\n`);\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"rotate\")\n .description(\"Re-encrypt every encrypted value under a new key, then write the key\")\n .argument(\"[paths...]\", \"files, directories, or globs (default: every collection)\")\n .option(\n \"--to <value>\",\n \"the new key (default: 64 random hex); required for a narrowed run and a key from MANNI_ENCRYPTION_KEY\",\n )\n .option(\"--collection <name>\", \"configured collection to run over; repeatable\", collect, [])\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format for every input\")\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"include files .gitignore covers\")\n .option(\n \"--root <dir>\",\n \"directory cited sources resolve from (default: cite.root from config, else the git root)\",\n )\n .option(\"--dry-run\", \"print what would change; write nothing\")\n .option(\"-f, --format <format>\", `output: ${ROTATE_FORMATS.join(\" | \")}`, \"pretty\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni key rotate # every collection, then the key\",\n \" manni key rotate --dry-run # see every change first\",\n ' manni key rotate --collection site --to \"$NEW_KEY\" # part of the family',\n ' MANNI_ENCRYPTION_KEY=… manni key rotate --to \"$NEW_KEY\"',\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: RotateCliOptions) => {\n try {\n const format = options.format;\n if (!isRotateFormat(format)) {\n throw new KeyError(`Unknown --format \"${format}\". Use ${COMMON_FORMAT_LIST}.`);\n }\n const result = await runKeyRotate({\n inputs: paths,\n collection: options.collection,\n to: options.to,\n exts: options.ext ? splitList(options.ext) : undefined,\n exclude: options.exclude,\n as: options.as,\n configPath: options.config,\n // `undefined` rather than `false` when absent.\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: explicitFalse(options.gitignore),\n root: options.root,\n dryRun: Boolean(options.dryRun),\n onNotice: notice,\n });\n if (format === \"json\") {\n process.stdout.write(`${renderRotateJson(result)}\\n`);\n // stdout is the JSON's; the notice is a diagnostic.\n if (result.baselineStale) notice(BASELINE_NOTICE);\n } else {\n process.stdout.write(`${renderRotatePretty(result, { color: color() })}\\n`);\n }\n process.exitCode = result.exitCode;\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n","/**\n * JSON output for `key rotate`: every page and every local external-metadata\n * manifest with something encrypted in it, each value's full ciphertext\n * before and after, and the counts. The key is never in it.\n */\nimport type { KeyRotateResult } from \"../types.js\";\n\nexport function renderRotateJson(result: KeyRotateResult): string {\n return JSON.stringify(\n {\n pages: result.pages,\n manifests: result.manifests,\n reencrypted: result.reencrypted,\n skipped: result.skipped,\n keyWritten: result.keyWritten,\n },\n null,\n 2,\n );\n}\n","/**\n * Pretty output for `key set` and `key rotate`. A ciphertext is shown as `~`\n * and its first four characters, then `…`, with a citation's line suffix\n * after it: `~AQx7…`, `~AQm4…:2`. The full values are in `-f json`; the key\n * is in neither. Colour via `shouldColor`; never under `--no-color`/`NO_COLOR`.\n */\nimport { palette } from \"../../shared/color.js\";\nimport type { KeyRotateResult, KeySetResult, RotatedValue, SkippedValue } from \"../types.js\";\n\nexport interface PrettyOptions {\n color: boolean;\n}\n\n/** Said at the end of a writing rotation when a citation baseline exists. */\nexport const BASELINE_NOTICE =\n \"The citation baseline fingerprints id-less encrypted citations by their pin; re-record it with `manni cite check --write-baseline`.\";\n\nconst NARROWED =\n \"Key not written: this run covered part of the family. Finish with a whole run under the same key: `manni key rotate --to <the same value>`.\";\nconst FROM_ENV =\n \"Key not written: it comes from MANNI_ENCRYPTION_KEY. Update the secret to the value you passed.\";\n\nconst plural = (n: number, one: string, many = `${one}s`): string =>\n `${String(n)} ${n === 1 ? one : many}`;\n\n/** What `set` says: the file, never the key. */\nexport function setMessage(result: KeySetResult): string {\n return result.dryRun\n ? `Would write encryptionKey to ${result.source}.`\n : `Encryption key written to ${result.source}.`;\n}\n\n/** `~AQx7…`, and a citation's line suffix after it: `~AQm4…:2`. */\nexport function shortCiphertext(value: string): string {\n // base64url has no `:`, so the first one starts the line suffix.\n const colon = value.indexOf(\":\");\n const token = colon === -1 ? value : value.slice(0, colon);\n const suffix = colon === -1 ? \"\" : value.slice(colon);\n return `${token.slice(0, 5)}…${suffix}`;\n}\n\n/** A metadata value by its pointer; a citation by its id, else where it sits. */\nfunction nameOf(row: RotatedValue | SkippedValue): string {\n if (row.kind === \"metadata\") return row.pointer;\n if (row.id !== undefined) return row.id;\n if (row.index !== undefined) return `/citations/${String(row.index)}`;\n return `line ${String(row.line ?? 0)}`;\n}\n\nfunction closing(result: KeyRotateResult): string | undefined {\n switch (result.outcome) {\n case \"written\":\n return result.configSource === undefined\n ? undefined\n : `Encryption key written to ${result.configSource}.`;\n case \"finished\":\n // Said before the counts: the key was written by the run that stopped.\n return undefined;\n case \"narrowed\":\n return NARROWED;\n case \"env\":\n return FROM_ENV;\n case \"skipped\":\n return result.skipped === 1\n ? \"Key not written: 1 value could not be re-encrypted. Fix it and rotate again.\"\n : `Key not written: ${String(result.skipped)} values could not be re-encrypted. Fix them and rotate again.`;\n case \"dry-run\":\n return \"Dry run: nothing written.\";\n }\n}\n\nexport function renderRotatePretty(result: KeyRotateResult, opts: PrettyOptions): string {\n const c = palette(opts.color);\n const lines: string[] = [];\n for (const page of result.pages) {\n for (const row of page.rewritten) {\n // A metadata value has no line suffix; two spaces keep its arrow in the\n // column a `:L` suffix would take.\n const gap = row.kind === \"metadata\" ? \" \" : \" \";\n lines.push(\n `${page.file}: ${nameOf(row)} ${c.dim(shortCiphertext(row.from))}${gap}-> ${shortCiphertext(row.to)}`,\n );\n }\n for (const row of page.skipped) {\n lines.push(`${page.file}: ${nameOf(row)} ${c.red(\"skipped:\")} ${row.message}`);\n }\n }\n // A manifest value is named by the entry it belongs to and the pointer\n // inside it, so one line says which document's private half moved.\n for (const manifest of result.manifests) {\n for (const row of manifest.rewritten) {\n lines.push(\n `${manifest.file}: ${row.entry}${row.pointer} ${c.dim(shortCiphertext(row.from))} -> ${shortCiphertext(row.to)}`,\n );\n }\n for (const row of manifest.skipped) {\n lines.push(\n `${manifest.file}: ${row.entry}${row.pointer} ${c.red(\"skipped:\")} ${row.message}`,\n );\n }\n }\n if (result.outcome === \"finished\" && result.configSource !== undefined) {\n lines.push(`Finished the interrupted rotation in ${result.configSource}.`);\n }\n const files =\n result.pages.filter((page) => page.rewritten.length > 0).length +\n result.manifests.filter((manifest) => manifest.rewritten.length > 0).length;\n lines.push(\n `${plural(result.reencrypted, \"value\")} re-encrypted in ${plural(files, \"file\")}, ${String(result.skipped)} skipped`,\n );\n const last = closing(result);\n if (last !== undefined) lines.push(result.outcome === \"skipped\" ? c.red(last) : last);\n if (result.baselineStale) lines.push(BASELINE_NOTICE);\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
@@ -6,28 +6,28 @@ import {
6
6
  meetsSeverity
7
7
  } from "./chunk-77AINBYM.js";
8
8
  import {
9
- fail
10
- } from "./chunk-YEUYKR62.js";
9
+ escapeWorkflowCommandMessage,
10
+ escapeWorkflowCommandProperty
11
+ } from "./chunk-MNH7QO4Z.js";
11
12
  import {
12
13
  palette,
13
14
  shouldColor
14
15
  } from "./chunk-RNVYGWIC.js";
15
16
  import {
16
- escapeWorkflowCommandMessage,
17
- escapeWorkflowCommandProperty
18
- } from "./chunk-MNH7QO4Z.js";
17
+ fail
18
+ } from "./chunk-YEUYKR62.js";
19
19
  import {
20
20
  FAMILY_CONFIG_NAMES,
21
21
  findConfigFile,
22
22
  matchesFileGlob,
23
23
  readConfigFile,
24
24
  selectCollections
25
- } from "./chunk-QLWC7MKD.js";
25
+ } from "./chunk-OTJOBZJ5.js";
26
26
  import "./chunk-HX44GB4Z.js";
27
- import "./chunk-QCHVR4ZM.js";
27
+ import "./chunk-VM7VAFJW.js";
28
28
  import {
29
29
  package_default
30
- } from "./chunk-2MJ62AYQ.js";
30
+ } from "./chunk-DHGB4JBG.js";
31
31
  import {
32
32
  programName
33
33
  } from "./chunk-OWBRDNRZ.js";
@@ -1202,4 +1202,4 @@ export {
1202
1202
  resolveCrawl,
1203
1203
  resolveMaxPages
1204
1204
  };
1205
- //# sourceMappingURL=cli-ONTC5PKT.js.map
1205
+ //# sourceMappingURL=cli-OJKFXQOM.js.map
@@ -10,15 +10,15 @@ import {
10
10
  findConfigFileSync,
11
11
  readConfigFileSync,
12
12
  searchPath
13
- } from "./chunk-QLWC7MKD.js";
13
+ } from "./chunk-OTJOBZJ5.js";
14
14
  import {
15
15
  notice,
16
16
  warn
17
17
  } from "./chunk-HX44GB4Z.js";
18
- import "./chunk-QCHVR4ZM.js";
18
+ import "./chunk-VM7VAFJW.js";
19
19
  import {
20
20
  package_default
21
- } from "./chunk-2MJ62AYQ.js";
21
+ } from "./chunk-DHGB4JBG.js";
22
22
  import "./chunk-OWBRDNRZ.js";
23
23
  import {
24
24
  ToolError,
@@ -836,4 +836,4 @@ function buildProgram() {
836
836
  export {
837
837
  buildProgram
838
838
  };
839
- //# sourceMappingURL=cli-VUKMWSSF.js.map
839
+ //# sourceMappingURL=cli-PHZAO4LZ.js.map
@@ -2,71 +2,73 @@
2
2
  import {
3
3
  renderCheck,
4
4
  runCheck
5
- } from "./chunk-HQR2ZBHW.js";
5
+ } from "./chunk-3BRJCQPY.js";
6
6
  import {
7
7
  EXPORT_TARGETS,
8
- SEARCH_MODES,
9
8
  renderEmbed,
10
9
  renderFill,
11
10
  renderQuery,
12
- renderSearch,
13
11
  renderStats,
14
12
  renderTraverse,
15
13
  runEmbed,
16
14
  runExport,
17
15
  runFill,
18
16
  runQuery,
19
- runSearch,
20
17
  runStats,
21
18
  runTraverse
22
- } from "./chunk-2DRHT73U.js";
19
+ } from "./chunk-DDILEF5F.js";
23
20
  import {
24
- DEFAULT_EXTENSIONS,
25
- STDIN,
26
- assertInputFormat,
27
21
  runBuild
28
- } from "./chunk-2IAZEB45.js";
29
- import "./chunk-EFW7CAG4.js";
22
+ } from "./chunk-KFGZPVFA.js";
23
+ import {
24
+ SEARCH_MODES,
25
+ renderSearch,
26
+ runSearch
27
+ } from "./chunk-ANPIIYRH.js";
30
28
  import {
31
29
  ALL_FILL_FIELDS,
32
30
  CONFIG_SECTION,
33
31
  DEFAULT_CONFIG_FILENAME,
34
- GraphError
35
- } from "./chunk-JROBZ7JA.js";
36
- import "./chunk-2IR4T5PO.js";
32
+ DEFAULT_EXTENSIONS,
33
+ GraphError,
34
+ STDIN,
35
+ assertInputFormat
36
+ } from "./chunk-2UJZXVHR.js";
37
37
  import "./chunk-TIUTIOFB.js";
38
+ import "./chunk-IZXN3WI6.js";
38
39
  import "./chunk-YGFIQ6Y5.js";
39
- import "./chunk-TU2WUBVZ.js";
40
- import "./chunk-LKP7QDFN.js";
41
- import "./chunk-6HWBRZIN.js";
42
- import "./chunk-M42DZCOU.js";
43
- import "./chunk-PCQ7ELJH.js";
40
+ import "./chunk-YUTVAMWW.js";
41
+ import "./chunk-JSSM7VVV.js";
42
+ import "./chunk-PS257NIU.js";
43
+ import "./chunk-2OZF2VUB.js";
44
+ import "./chunk-SGR7ZAVE.js";
45
+ import "./chunk-QEAGL4V5.js";
44
46
  import {
45
47
  collect,
46
48
  configOption,
47
49
  readStdin,
48
50
  splitList,
49
51
  writeTextAtomic
50
- } from "./chunk-GV56WGL2.js";
51
- import "./chunk-D4N2V43Z.js";
52
- import "./chunk-VSEBFHAY.js";
53
- import {
54
- fail
55
- } from "./chunk-YEUYKR62.js";
52
+ } from "./chunk-SMHAYK6I.js";
53
+ import "./chunk-DSWKBZWW.js";
54
+ import "./chunk-RGLFV4KO.js";
55
+ import "./chunk-MNH7QO4Z.js";
56
56
  import {
57
57
  shouldColor
58
58
  } from "./chunk-RNVYGWIC.js";
59
- import "./chunk-MNH7QO4Z.js";
60
- import "./chunk-QLWC7MKD.js";
59
+ import {
60
+ fail
61
+ } from "./chunk-YEUYKR62.js";
62
+ import "./chunk-OTJOBZJ5.js";
61
63
  import {
62
64
  warn
63
65
  } from "./chunk-HX44GB4Z.js";
64
66
  import {
65
67
  LOCAL_FLAG_HELP
66
- } from "./chunk-QCHVR4ZM.js";
68
+ } from "./chunk-VM7VAFJW.js";
67
69
  import {
68
70
  package_default
69
- } from "./chunk-2MJ62AYQ.js";
71
+ } from "./chunk-DHGB4JBG.js";
70
72
  import "./chunk-OWBRDNRZ.js";
71
73
  import {
72
74
  errorMessage
@@ -119,7 +121,7 @@ out: graph/graph.ttl
119
121
 
120
122
  # What to derive triples from. Remove entries to opt out.
121
123
  build:
122
- derive: [frontmatter, sections, links, tags, images, code, provenance]
124
+ derive: [frontmatter, sections, links, tags, images, code, provenance, terms]
123
125
 
124
126
  # PROV-O settings. Git history is detected, not switched: per-file dates and
125
127
  # author agents, rename -> prov:wasRevisionOf, and the build activity's HEAD
@@ -137,7 +139,7 @@ provenance:
137
139
  # stewardship people fields (owner, stakeholders, reviewed-by) out.
138
140
 
139
141
  # SHACL shapes \`manni graph check\` validates the built graph against. Default:
140
- # the shapes contract bundled with manni (shapes/graph/shapes-1.0.0.ttl).
142
+ # the shapes contract bundled with manni (shapes/graph/shapes-1.1.0.ttl).
141
143
  # check:
142
144
  # shapes: ["./my-shapes.ttl"]
143
145
 
@@ -156,7 +158,7 @@ provenance:
156
158
  # provider: anthropic # auto | anthropic | openai | claude-cli | llama-cpp
157
159
  # model: claude-sonnet-4-5 # the provider's default when omitted
158
160
 
159
- # LLM settings for \`manni graph fill\` (SKOS frontmatter proposals).
161
+ # LLM settings for \`manni graph fill\` (SKOS frontmatter proposals and sample questions).
160
162
  fill:
161
163
  temperature: 0
162
164
  # Stop after this many inference calls. One page is one turn, and a cached
@@ -175,6 +177,13 @@ fill:
175
177
  # Also propose per-section metadata. Off by default: it costs more output per
176
178
  # call, and section metadata is explicit-only, so review it as carefully.
177
179
  sections: false
180
+ # Sample questions: draft until a page has perPage, each pinned to the lines
181
+ # that answer it. A question request sends at most chunkChars of a page.
182
+ questions:
183
+ perPage: 3
184
+ chunkChars: 12000
185
+ # Send nothing off this machine: only a local model already downloaded.
186
+ offline: false
178
187
 
179
188
  # Local embeddings for semantic search (\`manni graph embed\`). Needs the optional
180
189
  # peer: npm install @huggingface/transformers
@@ -349,8 +358,10 @@ function buildProgram() {
349
358
  out: opts.out
350
359
  });
351
360
  for (const warning of result.warnings) warn(warning);
361
+ const { total, fromTermbase } = result.concepts;
362
+ const termbase = fromTermbase > 0 ? ` (${fromTermbase} from the termbase)` : "";
352
363
  console.log(
353
- `Wrote ${result.outPath} (${result.docs} docs, ${result.quads} triples)`
364
+ `Wrote ${result.outPath} (${result.docs} docs, ${result.quads} triples, ${total} concepts${termbase})`
354
365
  );
355
366
  } catch (e) {
356
367
  fail(e);
@@ -383,7 +394,7 @@ function buildProgram() {
383
394
  );
384
395
  documentInputs(
385
396
  program.command("fill").description(
386
- "Propose `graph:` frontmatter fields with an LLM, gated by confidence, and write them back"
397
+ "Propose `graph:` fields and sample questions with an LLM, gated by confidence, and write them back"
387
398
  ),
388
399
  "fill"
389
400
  ).option(
@@ -407,7 +418,14 @@ function buildProgram() {
407
418
  ).option(
408
419
  "--provider <name>",
409
420
  "Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp"
410
- ).option("--model <model>", "Model override; needs a named provider, from here or config").option("--local", LOCAL_FLAG_HELP).action(async (paths, opts) => {
421
+ ).option("--model <model>", "Model override; needs a named provider, from here or config").option("--local", LOCAL_FLAG_HELP).option(
422
+ "--offline",
423
+ "no network egress: only a model already downloaded, never a remote provider"
424
+ ).option(
425
+ "--chunk-chars <n>",
426
+ "characters of page per question request (default: config, then 12000)",
427
+ countOption("--chunk-chars")
428
+ ).action(async (paths, opts) => {
411
429
  try {
412
430
  const report = await runFill({
413
431
  paths,
@@ -423,7 +441,9 @@ function buildProgram() {
423
441
  fields: opts.fields,
424
442
  provider: opts.provider,
425
443
  model: opts.model,
426
- local: opts.local
444
+ local: opts.local,
445
+ offline: opts.offline,
446
+ chunkChars: opts.chunkChars
427
447
  });
428
448
  for (const warning of report.warnings) warn(warning);
429
449
  const rendered = renderFill(report, opts.format);
@@ -597,7 +617,7 @@ function buildProgram() {
597
617
  }
598
618
  );
599
619
  program.command("export").description(
600
- "Reserialize the built graph into a consumer format (jsonld file, iirds package, or search index)"
620
+ "Reserialize the built graph into a consumer format (jsonld file, iirds package, search index, or question set)"
601
621
  ).argument("<target>", `What to write: ${EXPORT_TARGETS.join(" | ")}`).option("-c, --config <path>", "Path to manni.config.yaml").option("--no-config", "Ignore any discovered config file").option("-g, --graph <path>", "Graph .ttl path (default: config out)").option(
602
622
  "-o, --out <path>",
603
623
  "Output path (default: the graph path with the target's extension)"
@@ -616,8 +636,9 @@ function buildProgram() {
616
636
  out: opts.out
617
637
  });
618
638
  for (const warning of result.warnings) warn(warning);
639
+ const noun = result.format === "questions" ? "question" : "node";
619
640
  console.log(
620
- `Wrote ${result.nodes} node${result.nodes === 1 ? "" : "s"} to ${result.outPath}`
641
+ `Wrote ${result.nodes} ${noun}${result.nodes === 1 ? "" : "s"} to ${result.outPath}`
621
642
  );
622
643
  } catch (e) {
623
644
  fail(e);
@@ -630,4 +651,4 @@ export {
630
651
  buildProgram,
631
652
  colorFor
632
653
  };
633
- //# sourceMappingURL=cli-RORDPAPE.js.map
654
+ //# sourceMappingURL=cli-PTKFFNOW.js.map