@hawkeyexl/manni 4.3.0 → 4.4.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 (224) hide show
  1. package/README.md +9 -1
  2. package/dist/batch-DFRCLY77.js +36 -0
  3. package/dist/build-Q5C6SX5J.js +31 -0
  4. package/dist/calibrate-XQILKXS3.js +31 -0
  5. package/dist/capture-JQMOC3BW.js +32 -0
  6. package/dist/check-HYNGXYJV.js +18 -0
  7. package/dist/check-HYNGXYJV.js.map +1 -0
  8. package/dist/check-NFZQLJKN.js +27 -0
  9. package/dist/check-NFZQLJKN.js.map +1 -0
  10. package/dist/check-U54XV6BP.js +40 -0
  11. package/dist/check-U54XV6BP.js.map +1 -0
  12. package/dist/chunk-252LNOEG.js +622 -0
  13. package/dist/chunk-252LNOEG.js.map +1 -0
  14. package/dist/chunk-2H7UOFLK.js +11 -0
  15. package/dist/chunk-2H7UOFLK.js.map +1 -0
  16. package/dist/chunk-2U3ORT6D.js +230 -0
  17. package/dist/chunk-2U3ORT6D.js.map +1 -0
  18. package/dist/chunk-3AFUD75K.js +23 -0
  19. package/dist/chunk-3AFUD75K.js.map +1 -0
  20. package/dist/{chunk-3R23C5DT.js → chunk-4TSWU2SU.js} +2 -14
  21. package/dist/chunk-4TSWU2SU.js.map +1 -0
  22. package/dist/chunk-5KHIFVD2.js +1192 -0
  23. package/dist/chunk-5KHIFVD2.js.map +1 -0
  24. package/dist/chunk-5YXBLLAC.js +2165 -0
  25. package/dist/chunk-5YXBLLAC.js.map +1 -0
  26. package/dist/chunk-644JVKJ4.js +3872 -0
  27. package/dist/chunk-644JVKJ4.js.map +1 -0
  28. package/dist/chunk-6OYEI2VV.js +88 -0
  29. package/dist/chunk-6OYEI2VV.js.map +1 -0
  30. package/dist/chunk-77AINBYM.js +19 -0
  31. package/dist/chunk-77AINBYM.js.map +1 -0
  32. package/dist/chunk-77HX34KD.js +1287 -0
  33. package/dist/chunk-77HX34KD.js.map +1 -0
  34. package/dist/{chunk-MOQXWXSG.js → chunk-7QMCHA4N.js} +32 -240
  35. package/dist/chunk-7QMCHA4N.js.map +1 -0
  36. package/dist/chunk-BUXDLRDT.js +455 -0
  37. package/dist/chunk-BUXDLRDT.js.map +1 -0
  38. package/dist/chunk-C6OH6CNF.js +388 -0
  39. package/dist/chunk-C6OH6CNF.js.map +1 -0
  40. package/dist/chunk-CK7SKVHR.js +1042 -0
  41. package/dist/chunk-CK7SKVHR.js.map +1 -0
  42. package/dist/chunk-CYWHFSRT.js +6737 -0
  43. package/dist/chunk-CYWHFSRT.js.map +1 -0
  44. package/dist/chunk-ERMSO34F.js +17 -0
  45. package/dist/chunk-ERMSO34F.js.map +1 -0
  46. package/dist/{chunk-IOYXPBCL.js → chunk-G3T47CFV.js} +1 -7
  47. package/dist/{chunk-IOYXPBCL.js.map → chunk-G3T47CFV.js.map} +1 -1
  48. package/dist/chunk-G7NJSREW.js +979 -0
  49. package/dist/chunk-G7NJSREW.js.map +1 -0
  50. package/dist/chunk-GLP5PSXB.js +72 -0
  51. package/dist/chunk-GLP5PSXB.js.map +1 -0
  52. package/dist/chunk-H2DLH2JI.js +198 -0
  53. package/dist/chunk-H2DLH2JI.js.map +1 -0
  54. package/dist/chunk-H6FZ66XR.js +634 -0
  55. package/dist/chunk-H6FZ66XR.js.map +1 -0
  56. package/dist/{chunk-CI2GOU3A.js → chunk-IEQHSCZG.js} +56 -137
  57. package/dist/chunk-IEQHSCZG.js.map +1 -0
  58. package/dist/chunk-IKEWBMCN.js +98 -0
  59. package/dist/chunk-IKEWBMCN.js.map +1 -0
  60. package/dist/chunk-JOHKIAVH.js +5440 -0
  61. package/dist/chunk-JOHKIAVH.js.map +1 -0
  62. package/dist/chunk-JVTNMVYU.js +10921 -0
  63. package/dist/chunk-JVTNMVYU.js.map +1 -0
  64. package/dist/chunk-K3D6FPV6.js +164 -0
  65. package/dist/chunk-K3D6FPV6.js.map +1 -0
  66. package/dist/{chunk-MFDD3YGU.js → chunk-KCGV52AM.js} +69 -48
  67. package/dist/{chunk-MFDD3YGU.js.map → chunk-KCGV52AM.js.map} +1 -1
  68. package/dist/chunk-LAKAWRV5.js +1651 -0
  69. package/dist/chunk-LAKAWRV5.js.map +1 -0
  70. package/dist/chunk-LJ2RDH3F.js +49 -0
  71. package/dist/chunk-LJ2RDH3F.js.map +1 -0
  72. package/dist/chunk-M2JCK5F6.js +805 -0
  73. package/dist/chunk-M2JCK5F6.js.map +1 -0
  74. package/dist/chunk-MNH7QO4Z.js +15 -0
  75. package/dist/chunk-MNH7QO4Z.js.map +1 -0
  76. package/dist/{chunk-RVVCA4WL.js → chunk-MYC3O5EJ.js} +4 -4
  77. package/dist/chunk-MYMBCTDE.js +387 -0
  78. package/dist/chunk-MYMBCTDE.js.map +1 -0
  79. package/dist/chunk-NCPWXHDO.js +683 -0
  80. package/dist/chunk-NCPWXHDO.js.map +1 -0
  81. package/dist/chunk-NWZ2SLYL.js +2957 -0
  82. package/dist/chunk-NWZ2SLYL.js.map +1 -0
  83. package/dist/chunk-OBFENF3U.js +934 -0
  84. package/dist/chunk-OBFENF3U.js.map +1 -0
  85. package/dist/chunk-OWBRDNRZ.js +16 -0
  86. package/dist/chunk-OWBRDNRZ.js.map +1 -0
  87. package/dist/{chunk-KTSJ2ZHA.js → chunk-PAU352SV.js} +5 -3
  88. package/dist/{chunk-KTSJ2ZHA.js.map → chunk-PAU352SV.js.map} +1 -1
  89. package/dist/chunk-PCE7QHXJ.js +68 -0
  90. package/dist/chunk-PCE7QHXJ.js.map +1 -0
  91. package/dist/chunk-PCHZY2I7.js +299 -0
  92. package/dist/chunk-PCHZY2I7.js.map +1 -0
  93. package/dist/chunk-PHF3D7ER.js +1042 -0
  94. package/dist/chunk-PHF3D7ER.js.map +1 -0
  95. package/dist/chunk-Q35YIDBV.js +1202 -0
  96. package/dist/chunk-Q35YIDBV.js.map +1 -0
  97. package/dist/chunk-RLR4TKUZ.js +4398 -0
  98. package/dist/chunk-RLR4TKUZ.js.map +1 -0
  99. package/dist/chunk-RNVYGWIC.js +30 -0
  100. package/dist/chunk-RNVYGWIC.js.map +1 -0
  101. package/dist/chunk-SE4JN5XN.js +19 -0
  102. package/dist/chunk-SE4JN5XN.js.map +1 -0
  103. package/dist/chunk-TIUTIOFB.js +25 -0
  104. package/dist/chunk-TIUTIOFB.js.map +1 -0
  105. package/dist/chunk-TU2WUBVZ.js +2 -0
  106. package/dist/chunk-TU2WUBVZ.js.map +1 -0
  107. package/dist/chunk-TZOYZK2E.js +98 -0
  108. package/dist/chunk-TZOYZK2E.js.map +1 -0
  109. package/dist/chunk-UKZNLVJW.js +17 -0
  110. package/dist/chunk-UKZNLVJW.js.map +1 -0
  111. package/dist/chunk-UZC7LDAQ.js +178 -0
  112. package/dist/chunk-UZC7LDAQ.js.map +1 -0
  113. package/dist/chunk-V46OILVC.js +3090 -0
  114. package/dist/chunk-V46OILVC.js.map +1 -0
  115. package/dist/chunk-WQE54PNH.js +1975 -0
  116. package/dist/chunk-WQE54PNH.js.map +1 -0
  117. package/dist/chunk-X3BPBDGQ.js +52 -0
  118. package/dist/chunk-X3BPBDGQ.js.map +1 -0
  119. package/dist/chunk-XSLV76YK.js +54 -0
  120. package/dist/chunk-XSLV76YK.js.map +1 -0
  121. package/dist/{chunk-QROCFW5S.js → chunk-XYLUCIKQ.js} +3 -3
  122. package/dist/chunk-YEUYKR62.js +72 -0
  123. package/dist/chunk-YEUYKR62.js.map +1 -0
  124. package/dist/{chunk-ESJ5W7EV.js → chunk-YFQBFNQS.js} +8 -94
  125. package/dist/chunk-YFQBFNQS.js.map +1 -0
  126. package/dist/chunk-YIL4XLLJ.js +1661 -0
  127. package/dist/chunk-YIL4XLLJ.js.map +1 -0
  128. package/dist/chunk-YNHZHSSM.js +41 -0
  129. package/dist/chunk-YNHZHSSM.js.map +1 -0
  130. package/dist/chunk-YTCZRLTU.js +96 -0
  131. package/dist/chunk-YTCZRLTU.js.map +1 -0
  132. package/dist/chunk-YYBFZLAJ.js +374 -0
  133. package/dist/chunk-YYBFZLAJ.js.map +1 -0
  134. package/dist/chunk-ZXRAE55H.js +31 -0
  135. package/dist/chunk-ZXRAE55H.js.map +1 -0
  136. package/dist/cli-2QPR2OZG.js +232 -0
  137. package/dist/cli-2QPR2OZG.js.map +1 -0
  138. package/dist/cli-4IOPGZHR.js +1203 -0
  139. package/dist/cli-4IOPGZHR.js.map +1 -0
  140. package/dist/cli-5FL73WHA.js +346 -0
  141. package/dist/cli-5FL73WHA.js.map +1 -0
  142. package/dist/cli-C262QOWM.js +739 -0
  143. package/dist/cli-C262QOWM.js.map +1 -0
  144. package/dist/cli-LJLLIQB2.js +423 -0
  145. package/dist/cli-LJLLIQB2.js.map +1 -0
  146. package/dist/cli-OFPZ5MAS.js +626 -0
  147. package/dist/cli-OFPZ5MAS.js.map +1 -0
  148. package/dist/cli-SHSMSRQY.js +28 -0
  149. package/dist/cli-SHSMSRQY.js.map +1 -0
  150. package/dist/cli-SRHFUZHA.js +473 -0
  151. package/dist/cli-SRHFUZHA.js.map +1 -0
  152. package/dist/cli-URZQXL4K.js +552 -0
  153. package/dist/cli-URZQXL4K.js.map +1 -0
  154. package/dist/cli.d.ts +12 -2
  155. package/dist/cli.js +109 -7651
  156. package/dist/cli.js.map +1 -1
  157. package/dist/docmeta.js +15 -3
  158. package/dist/docmeta.js.map +1 -1
  159. package/dist/github-FE6KCNYJ.js +27 -0
  160. package/dist/github-FE6KCNYJ.js.map +1 -0
  161. package/dist/github-QXL3VMK2.js +32 -0
  162. package/dist/github-QXL3VMK2.js.map +1 -0
  163. package/dist/index.d.ts +65 -3
  164. package/dist/index.js +407 -337
  165. package/dist/index.js.map +1 -1
  166. package/dist/json-7WV7KL6H.js +17 -0
  167. package/dist/json-7WV7KL6H.js.map +1 -0
  168. package/dist/json-SGZ6ZRFD.js +35 -0
  169. package/dist/json-SGZ6ZRFD.js.map +1 -0
  170. package/dist/lint-DL4LJRAY.js +28 -0
  171. package/dist/lint-DL4LJRAY.js.map +1 -0
  172. package/dist/list-6BAXTZUM.js +29 -0
  173. package/dist/list-6BAXTZUM.js.map +1 -0
  174. package/dist/list-7BKNYPSB.js +31 -0
  175. package/dist/list-7BKNYPSB.js.map +1 -0
  176. package/dist/page-3U2GCFNE.js +41 -0
  177. package/dist/page-3U2GCFNE.js.map +1 -0
  178. package/dist/picker-3XF36MJF.js +14 -0
  179. package/dist/picker-3XF36MJF.js.map +1 -0
  180. package/dist/pretty-2H57QVTY.js +43 -0
  181. package/dist/pretty-2H57QVTY.js.map +1 -0
  182. package/dist/pretty-N6DO4OOL.js +37 -0
  183. package/dist/pretty-N6DO4OOL.js.map +1 -0
  184. package/dist/reporters-M6LJ2IYU.js +21 -0
  185. package/dist/reporters-M6LJ2IYU.js.map +1 -0
  186. package/dist/reporters-N6GHXSS7.js +42 -0
  187. package/dist/reporters-N6GHXSS7.js.map +1 -0
  188. package/dist/reporters-UCNEV7PH.js +71 -0
  189. package/dist/reporters-UCNEV7PH.js.map +1 -0
  190. package/dist/run-XZDAREJE.js +33 -0
  191. package/dist/run-XZDAREJE.js.map +1 -0
  192. package/dist/term-5ICGKPC3.js +1592 -0
  193. package/dist/term-5ICGKPC3.js.map +1 -0
  194. package/dist/types-Y6TXHM7M.js +10 -0
  195. package/dist/types-Y6TXHM7M.js.map +1 -0
  196. package/dist/validate-GQRM77YN.js +16 -0
  197. package/dist/validate-GQRM77YN.js.map +1 -0
  198. package/package.json +1 -1
  199. package/plugin/manni/.claude-plugin/plugin.json +9 -0
  200. package/plugin/manni/hooks/hooks.json +52 -0
  201. package/plugin/manni/skills/check/SKILL.md +20 -0
  202. package/plugin/manni/skills/evals/SKILL.md +27 -0
  203. package/plugin/manni/skills/fix/SKILL.md +56 -0
  204. package/plugin/manni/skills/setup/SKILL.md +41 -0
  205. package/dist/batch-7JJWXWSF.js +0 -18
  206. package/dist/calibrate-IA2ARFMH.js +0 -13
  207. package/dist/capture-C32JXIFN.js +0 -15
  208. package/dist/chunk-3R23C5DT.js.map +0 -1
  209. package/dist/chunk-CI2GOU3A.js.map +0 -1
  210. package/dist/chunk-DP2ZA3WH.js +0 -26518
  211. package/dist/chunk-DP2ZA3WH.js.map +0 -1
  212. package/dist/chunk-ESJ5W7EV.js.map +0 -1
  213. package/dist/chunk-MOQXWXSG.js.map +0 -1
  214. package/dist/chunk-O6RVQKK6.js +0 -27170
  215. package/dist/chunk-O6RVQKK6.js.map +0 -1
  216. package/dist/picker-6HRMETE7.js +0 -12
  217. package/plugin/tracevals/.claude-plugin/plugin.json +0 -9
  218. package/plugin/tracevals/hooks/hooks.json +0 -17
  219. /package/dist/{batch-7JJWXWSF.js.map → batch-DFRCLY77.js.map} +0 -0
  220. /package/dist/{calibrate-IA2ARFMH.js.map → build-Q5C6SX5J.js.map} +0 -0
  221. /package/dist/{capture-C32JXIFN.js.map → calibrate-XQILKXS3.js.map} +0 -0
  222. /package/dist/{picker-6HRMETE7.js.map → capture-JQMOC3BW.js.map} +0 -0
  223. /package/dist/{chunk-RVVCA4WL.js.map → chunk-MYC3O5EJ.js.map} +0 -0
  224. /package/dist/{chunk-QROCFW5S.js.map → chunk-XYLUCIKQ.js.map} +0 -0
@@ -0,0 +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":[]}
@@ -0,0 +1,552 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runAdd,
4
+ runRemove,
5
+ runUpdate
6
+ } from "./chunk-5YXBLLAC.js";
7
+ import {
8
+ runCheck
9
+ } from "./chunk-LAKAWRV5.js";
10
+ import {
11
+ findingMessage,
12
+ renderCheckGithub
13
+ } from "./chunk-XSLV76YK.js";
14
+ import {
15
+ renderCheckPretty,
16
+ renderRemovePretty,
17
+ renderUpdatePretty
18
+ } from "./chunk-BUXDLRDT.js";
19
+ import {
20
+ errorSite,
21
+ shortCommit,
22
+ shortLine,
23
+ shortPin,
24
+ shortSrc
25
+ } from "./chunk-252LNOEG.js";
26
+ import {
27
+ renderCheckJson,
28
+ renderRemoveJson,
29
+ renderUpdateJson
30
+ } from "./chunk-PCE7QHXJ.js";
31
+ import "./chunk-77AINBYM.js";
32
+ import {
33
+ CiteError,
34
+ RULE_ID_PREFIX,
35
+ asCiteError,
36
+ isCiteRule,
37
+ spellSource
38
+ } from "./chunk-G7NJSREW.js";
39
+ import "./chunk-IKEWBMCN.js";
40
+ import "./chunk-TU2WUBVZ.js";
41
+ import "./chunk-H2DLH2JI.js";
42
+ import {
43
+ terminalConfirm
44
+ } from "./chunk-CYWHFSRT.js";
45
+ import "./chunk-K3D6FPV6.js";
46
+ import {
47
+ collect,
48
+ configOption,
49
+ explicitFalse,
50
+ readStdin,
51
+ reportConfig,
52
+ splitList
53
+ } from "./chunk-V46OILVC.js";
54
+ import {
55
+ splitPageArgument
56
+ } from "./chunk-RLR4TKUZ.js";
57
+ import {
58
+ COMMON_FORMAT_LIST,
59
+ OMITTED_WHEN_CLEAN,
60
+ REPORT_FORMATS,
61
+ REPORT_FORMAT_LIST,
62
+ isMachineFormat,
63
+ isReportFormat,
64
+ renderJunit,
65
+ renderSarif
66
+ } from "./chunk-C6OH6CNF.js";
67
+ import {
68
+ STDIN_TOKEN
69
+ } from "./chunk-JVTNMVYU.js";
70
+ import {
71
+ fail
72
+ } from "./chunk-YEUYKR62.js";
73
+ import {
74
+ shouldColor
75
+ } from "./chunk-RNVYGWIC.js";
76
+ import "./chunk-MNH7QO4Z.js";
77
+ import {
78
+ notice
79
+ } from "./chunk-Q35YIDBV.js";
80
+ import {
81
+ package_default
82
+ } from "./chunk-UZC7LDAQ.js";
83
+ import "./chunk-OWBRDNRZ.js";
84
+ import "./chunk-G3T47CFV.js";
85
+ import "./chunk-2H7UOFLK.js";
86
+
87
+ // src/cite/cli.ts
88
+ import { Command, Option } from "commander";
89
+
90
+ // src/cite/reporters/sarif.ts
91
+ var INFORMATION_URI = "https://hawkeyexl.github.io/manni/cite/";
92
+ var RULES_URI = "https://hawkeyexl.github.io/manni/cite/reference/citations/";
93
+ var RULE_DESCRIPTIONS = {
94
+ "source-moved": "The cited source lines moved to one other place in the file.",
95
+ "source-moved-ambiguous": "The cited source lines now match at several places in the file.",
96
+ "source-changed": "The cited source lines changed since the citation pinned them.",
97
+ "source-never-true": "The pin never matched the source at the recorded commit.",
98
+ "source-missing": "The cited source file is not tracked under the root, or cannot be decrypted.",
99
+ "claim-moved": "The cited sentence moved to other lines of the page.",
100
+ "claim-moved-ambiguous": "The cited sentence now appears at several places on the page.",
101
+ "claim-reanchored": "The cited sentence's words are unchanged since the claim's baseline, and only its layout moved.",
102
+ "claim-changed": "The cited sentence was edited since the citation pinned it.",
103
+ "marker-orphan": "A marker names an id no citation has.",
104
+ "marker-invalid": "A marker is malformed, or the page has too many markers.",
105
+ "marker-repeated": "Two markers name the same citation id.",
106
+ "marker-misplaced": "A marker line sits inside the paragraph it anchors, and splits it.",
107
+ "anchor-invalid": "A citation's anchor cannot work.",
108
+ "entry-invalid": "A citation entry is malformed.",
109
+ "quote-drift": "A quoted block no longer reproduces its source."
110
+ };
111
+ var ENTRY_LABEL = /^(?:\(root\)|\/citations\/\d+) /;
112
+ function withFindingMessages(run) {
113
+ return run.results.map((result) => {
114
+ const page = run.pages.find((p) => p.file === result.file);
115
+ if (page === void 0) return result;
116
+ const errors = result.errors.map((error) => {
117
+ const finding = page.findings.find(
118
+ (f) => f.rule === error.keyword && (f.index === void 0 ? "" : `/citations/${String(f.index)}`) === error.instancePath && f.message === error.message && (errorSite(f).line ?? null) === (error.line ?? null)
119
+ );
120
+ return finding === void 0 ? error : { ...error, message: findingMessage(finding) };
121
+ });
122
+ return { ...result, errors };
123
+ });
124
+ }
125
+ function describe(rule) {
126
+ const name = rule.id.slice(RULE_ID_PREFIX.length + 1);
127
+ if (!isCiteRule(name)) return rule;
128
+ return { id: rule.id, shortDescription: { text: RULE_DESCRIPTIONS[name] }, helpUri: `${RULES_URI}#${name}` };
129
+ }
130
+ function renderCheckSarif(run, opts = {}) {
131
+ const log = JSON.parse(
132
+ renderSarif(withFindingMessages(run), {
133
+ frame: run.frame,
134
+ ...opts.onNotice === void 0 ? {} : { onNotice: opts.onNotice }
135
+ })
136
+ );
137
+ for (const sarifRun of log.runs) {
138
+ sarifRun.tool.driver.informationUri = INFORMATION_URI;
139
+ sarifRun.tool.driver.rules = sarifRun.tool.driver.rules.map(describe);
140
+ for (const result of sarifRun.results) result.message.text = result.message.text.replace(ENTRY_LABEL, "");
141
+ }
142
+ return JSON.stringify(log, null, 2);
143
+ }
144
+
145
+ // src/cite/reporters/junit.ts
146
+ var JUNIT_CLASSNAME = "manni.cite";
147
+ var MESSAGE_LABEL = new RegExp(`message="${ENTRY_LABEL.source.replace(/^\^/, "")}`, "g");
148
+ function renderCheckJunit(run) {
149
+ return renderJunit(withFindingMessages(run), { frame: run.frame, classname: JUNIT_CLASSNAME }).replace(
150
+ MESSAGE_LABEL,
151
+ 'message="'
152
+ );
153
+ }
154
+
155
+ // src/cite/cli.ts
156
+ var UPDATE_FORMATS = ["pretty", "json"];
157
+ var REMOVE_FORMATS = UPDATE_FORMATS;
158
+ function colorFor(command, isTTY, env) {
159
+ const noColor = colorOwner(command).opts().color === false;
160
+ return shouldColor({ noColor, isTTY, env });
161
+ }
162
+ function colorOwner(command) {
163
+ for (let c = command; c !== null; c = c.parent) {
164
+ if (c.options.some((o) => o.long === "--no-color")) return c;
165
+ }
166
+ return command;
167
+ }
168
+ function isUpdateFormat(value) {
169
+ return UPDATE_FORMATS.includes(value);
170
+ }
171
+ function isRemoveFormat(value) {
172
+ return REMOVE_FORMATS.includes(value);
173
+ }
174
+ function splitPageArgument2(arg) {
175
+ return asCiteError(() => splitPageArgument(arg));
176
+ }
177
+ function spellAt(lines, noun = "line") {
178
+ return lines.start === lines.end ? `${noun} ${String(lines.start)}` : `${noun}s ${String(lines.start)}-${String(lines.end)}`;
179
+ }
180
+ function addMessage(result) {
181
+ const { citation, claimLines } = result;
182
+ const claim = citation.claim;
183
+ const name = citation.id ?? (claim === void 0 ? "a bare pin" : "an entry");
184
+ const src = shortSrc(spellSource(citation.source));
185
+ const commit = citation.source["commit-sha"];
186
+ const quoted = result.sourceLine === void 0 ? "" : shortLine(result.sourceLine);
187
+ const line = quoted === "" ? "" : ` "${quoted}"`;
188
+ const pin = `${src}${line}, ${shortPin(citation.source.integrity)}, ${commit === void 0 ? "no commit" : shortCommit(commit)}`;
189
+ const where = result.manifest === void 0 ? "frontmatter" : `${result.manifest.file}:${String(result.manifest.line)}`;
190
+ const head = `${result.file}: added ${name} to ${where}`;
191
+ if (result.markerLine !== void 0) {
192
+ const at = claimLines === void 0 ? "" : `, claim pinned at ${spellAt(claimLines)}`;
193
+ const wrote = result.markerJoined === true ? "joined the marker at line" : "marker at line";
194
+ const marked = `${head}; ${wrote} ${String(result.markerLine)}${at}`;
195
+ if (claim === void 0) return marked;
196
+ if (citation.quote === true) return `${marked} (a block that reproduces ${src})`;
197
+ return `${marked} (${shortPin(claim.integrity)}; source ${pin})`;
198
+ }
199
+ if (claim === void 0 || claimLines === void 0) {
200
+ return `${head} (source ${pin})`;
201
+ }
202
+ if (citation.quote === true) {
203
+ return `${head} (claim ${spellAt(claimLines, "line")}, a block that reproduces ${src})`;
204
+ }
205
+ return `${head} (claim at ${spellAt(claimLines)}, ${shortPin(claim.integrity)}; source ${pin})`;
206
+ }
207
+ function buildProgram() {
208
+ const program = new Command();
209
+ program.name("cite").description(
210
+ "Track citations from doc claims to source lines and check them for drift."
211
+ ).version(package_default.version, "-V, --version").option("--no-color", "disable colored output").showHelpAfterError("(add --help for usage)").exitOverride();
212
+ program.command("check").description("Check every citation in the given pages against its source").argument(
213
+ "[paths...]",
214
+ "files, directories, or globs to check (use - for stdin)"
215
+ ).option(
216
+ "--collection <name>",
217
+ "configured collection to run over; repeatable",
218
+ collect,
219
+ []
220
+ ).option("--ext <list>", "comma-separated extensions for directory walks").option("--exclude <glob>", "glob to exclude; repeatable", collect, []).option("--as <format>", "force an input format for every input").option(
221
+ "-f, --format <format>",
222
+ `output: ${REPORT_FORMATS.join(" | ")}`,
223
+ "pretty"
224
+ ).option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").option("-q, --quiet", "in pretty output, hide current citations and clean files").option("--allow-empty", "treat zero matched files as success").option("--no-gitignore", "check files .gitignore covers").addOption(
225
+ new Option(
226
+ "--baseline [path]",
227
+ "compare against a baseline; fail only on findings not in it"
228
+ )
229
+ ).addOption(
230
+ new Option(
231
+ "--write-baseline [path]",
232
+ "record current findings as the baseline, then exit 0"
233
+ )
234
+ ).option("--no-baseline", "ignore a baseline configured by `baseline:`").option("--no-check-sources", "page-side rules only; every source status is skipped").option(
235
+ "--root <dir>",
236
+ "directory src: paths resolve from (default: cite.root from config, else the git root, else the current directory)"
237
+ ).option("--show-diff", "in pretty output, print the diff and commit subjects for changed").option("--reveal", "in pretty output, print the decrypted path beside an encrypted source").addHelpText(
238
+ "after",
239
+ [
240
+ "",
241
+ "Examples:",
242
+ " manni cite check docs/ # walk a directory",
243
+ " manni cite check --collection guides # one configured collection",
244
+ ' manni cite check "docs/**/*.md" -f github # CI annotations',
245
+ " manni cite check --show-diff docs/limits.md # see what changed",
246
+ " manni cite check --baseline # fail only on new findings",
247
+ " cat page.md | manni cite check - --as markdown"
248
+ ].join("\n")
249
+ ).action(async (paths, options, command) => {
250
+ try {
251
+ const format = options.format;
252
+ if (!isReportFormat(format)) {
253
+ throw new CiteError(
254
+ `Unknown --format "${format}". Use ${REPORT_FORMAT_LIST}.`
255
+ );
256
+ }
257
+ const exts = options.ext ? splitList(options.ext) : void 0;
258
+ const stdinContent = paths.includes(STDIN_TOKEN) ? await readStdin() : void 0;
259
+ const cwd = process.cwd();
260
+ const run = await runCheck({
261
+ inputs: paths,
262
+ collection: options.collection,
263
+ exts,
264
+ exclude: options.exclude,
265
+ as: options.as,
266
+ ...configOption(options.config),
267
+ onConfigLoaded: reportConfig(!isMachineFormat(format), cwd),
268
+ stdinContent,
269
+ // `undefined` rather than `false` when absent, so config still wins.
270
+ allowEmpty: options.allowEmpty ? true : void 0,
271
+ respectGitignore: explicitFalse(options.gitignore),
272
+ onNotice: notice,
273
+ baseline: options.baseline,
274
+ writeBaseline: options.writeBaseline,
275
+ checkSources: explicitFalse(options.checkSources),
276
+ // Only so the run can say git is not there to give diffs; the diffs
277
+ // themselves are the pretty reporter's.
278
+ showDiff: options.showDiff ? true : void 0,
279
+ root: options.root
280
+ });
281
+ let text;
282
+ switch (format) {
283
+ case "pretty":
284
+ text = renderCheckPretty(run, {
285
+ color: colorFor(command, process.stdout.isTTY),
286
+ quiet: Boolean(options.quiet),
287
+ showDiff: Boolean(options.showDiff),
288
+ reveal: Boolean(options.reveal)
289
+ });
290
+ break;
291
+ case "json":
292
+ text = renderCheckJson(run);
293
+ break;
294
+ case "github":
295
+ text = renderCheckGithub(run);
296
+ break;
297
+ case "sarif":
298
+ text = renderCheckSarif(run, { onNotice: notice });
299
+ break;
300
+ case "junit":
301
+ text = renderCheckJunit(run);
302
+ break;
303
+ }
304
+ if (text.length > 0 || !OMITTED_WHEN_CLEAN.has(format)) {
305
+ process.stdout.write(`${text}
306
+ `);
307
+ }
308
+ process.exitCode = run.summary.failed > 0 ? 1 : 0;
309
+ } catch (err) {
310
+ fail(err);
311
+ }
312
+ });
313
+ program.command("add").description("Mint a citation for a source range and write it to a page").argument(
314
+ "<page>",
315
+ "the page to cite from, with the claim's lines: page:L or page:L1-L2 (use - for stdin, with --as)"
316
+ ).argument(
317
+ "<src>",
318
+ "path, path:L or path:L1-L2 relative to --root, or an encrypted ~source with the same line forms"
319
+ ).option("--id <id>", "kebab-case id, unique on the page; required with --marker").option("--marker", "write a cite <id> marker above the paragraph holding the page lines and pin the text it anchors").option("--quote", "the page lines are a fenced block that reproduces the source").option(
320
+ "--encrypt",
321
+ "write source.file encrypted, with an hmac-sha256- pin; with no key, offer to create one (an available key encrypts without the flag)"
322
+ ).option("--no-commit-sha", "do not record HEAD").option("--dry-run", "print the diff; write nothing").option("--as <format>", "force the page format").option("--root <dir>", "directory source paths resolve from (as check)").option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").addHelpText(
323
+ "after",
324
+ [
325
+ "",
326
+ "Examples:",
327
+ " manni cite add docs/limits.md:9 lib/limits.ts:2 --id fetch-timeout",
328
+ " manni cite add docs/limits.md:30 lib/limits.ts:8-12 --id timeouts --marker",
329
+ " manni cite add docs/limits.md:14-18 lib/limits.ts:1-3 --quote",
330
+ " manni cite add docs/limits.md lib/limits.ts --dry-run",
331
+ " cat page.md | manni cite add -:9 lib/limits.ts:2 --as markdown > out.md"
332
+ ].join("\n")
333
+ ).action(async (pageArgument, src, options) => {
334
+ try {
335
+ const { page, lines } = splitPageArgument2(pageArgument);
336
+ const usingStdin = page === STDIN_TOKEN;
337
+ const stdinContent = usingStdin ? await readStdin() : void 0;
338
+ const dryRun = Boolean(options.dryRun);
339
+ const cwd = process.cwd();
340
+ const result = await runAdd({
341
+ page,
342
+ pageLines: lines,
343
+ src,
344
+ id: options.id,
345
+ marker: options.marker ? true : void 0,
346
+ quote: options.quote ? true : void 0,
347
+ // `undefined` when absent, so the key decides: an available one
348
+ // encrypts without the flag.
349
+ encrypt: options.encrypt ? true : void 0,
350
+ commitSha: explicitFalse(options.commitSha),
351
+ dryRun,
352
+ as: options.as,
353
+ ...configOption(options.config),
354
+ // With `-` the page owns stdout; so does the diff under --dry-run.
355
+ onConfigLoaded: reportConfig(!usingStdin && !dryRun, cwd),
356
+ stdinContent,
357
+ root: options.root,
358
+ onNotice: notice,
359
+ // Only on a terminal: off one, a missing key is a refusal, not a
360
+ // question nobody can answer. With `-` stdin is the page, so no
361
+ // question is put either.
362
+ confirm: terminalConfirm()
363
+ });
364
+ const message = addMessage(result);
365
+ const diffs = [result.diff, result.manifest?.diff ?? ""].filter((d) => d.length > 0);
366
+ if (usingStdin) {
367
+ process.stdout.write(result.content);
368
+ if (dryRun) for (const diff of diffs) process.stderr.write(`${diff}
369
+ `);
370
+ process.stderr.write(`${message}
371
+ `);
372
+ } else if (dryRun) {
373
+ for (const diff of diffs) process.stdout.write(`${diff}
374
+ `);
375
+ process.stderr.write(`${message}
376
+ `);
377
+ } else {
378
+ process.stdout.write(`${message}
379
+ `);
380
+ }
381
+ process.exitCode = 0;
382
+ } catch (err) {
383
+ fail(err);
384
+ }
385
+ });
386
+ program.command("update").description("Rewrite moved citations in place; with --accept, re-mint changed ones").argument(
387
+ "[paths...]",
388
+ "files, directories, or globs to update (use - for stdin)"
389
+ ).option(
390
+ "--collection <name>",
391
+ "configured collection to run over; repeatable",
392
+ collect,
393
+ []
394
+ ).option("--ext <list>", "comma-separated extensions for directory walks").option("--exclude <glob>", "glob to exclude; repeatable", collect, []).option("--as <format>", "force an input format for every input").option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").option("--allow-empty", "treat zero matched files as success").option("--no-gitignore", "update files .gitignore covers").option("--no-check-sources", "refused: update needs the sources").option("--root <dir>", "directory src: paths resolve from (as check)").option("--accept", "re-mint changed and never-true entries at HEAD; prints old and new pins").option(
395
+ "--recommit",
396
+ "re-record commit-sha where the recorded commit does not contain the pinned lines, or is outside HEAD's history"
397
+ ).option("--only <id>", "limit to entries with this id; repeatable", collect, []).option("--dry-run", "print the diffs; write nothing").option(
398
+ "-f, --format <format>",
399
+ `output: ${UPDATE_FORMATS.join(" | ")}`,
400
+ "pretty"
401
+ ).addHelpText(
402
+ "after",
403
+ [
404
+ "",
405
+ "Examples:",
406
+ " manni cite update docs/ # rewrite moved entries",
407
+ " manni cite update --accept --only fetch-timeout docs/limits.md",
408
+ " manni cite update --dry-run docs/ # see the diffs first",
409
+ " manni cite update --recommit docs/ # repair unsupported commit-sha"
410
+ ].join("\n")
411
+ ).action(async (paths, options, command) => {
412
+ try {
413
+ const format = options.format;
414
+ if (!isUpdateFormat(format)) {
415
+ throw new CiteError(
416
+ `Unknown --format "${format}". Use ${COMMON_FORMAT_LIST}.`
417
+ );
418
+ }
419
+ if (!options.checkSources) {
420
+ throw new CiteError(
421
+ "update needs the sources: drop --no-check-sources (or `checkSources: false`)."
422
+ );
423
+ }
424
+ const exts = options.ext ? splitList(options.ext) : void 0;
425
+ const usingStdin = paths.includes(STDIN_TOKEN);
426
+ const stdinContent = usingStdin ? await readStdin() : void 0;
427
+ const dryRun = Boolean(options.dryRun);
428
+ const pageToStdout = usingStdin && !dryRun;
429
+ const cwd = process.cwd();
430
+ const run = await runUpdate({
431
+ inputs: paths,
432
+ collection: options.collection,
433
+ exts,
434
+ exclude: options.exclude,
435
+ as: options.as,
436
+ ...configOption(options.config),
437
+ onConfigLoaded: reportConfig(format === "pretty" && !pageToStdout, cwd),
438
+ stdinContent,
439
+ allowEmpty: options.allowEmpty ? true : void 0,
440
+ respectGitignore: explicitFalse(options.gitignore),
441
+ onNotice: notice,
442
+ root: options.root,
443
+ accept: options.accept ? true : void 0,
444
+ recommit: options.recommit ? true : void 0,
445
+ only: options.only.length > 0 ? options.only : void 0,
446
+ dryRun
447
+ });
448
+ const text = format === "json" ? renderUpdateJson(run) : renderUpdatePretty(run, {
449
+ color: colorFor(command, process.stdout.isTTY),
450
+ // The diffs are the point of a dry run; a real run prints
451
+ // what it rewrote and leaves the file to say the rest.
452
+ showDiff: dryRun
453
+ });
454
+ const stdinPage = pageToStdout ? run.pages.find((page) => page.content !== void 0) : void 0;
455
+ if (stdinPage?.content !== void 0) {
456
+ process.stdout.write(stdinPage.content);
457
+ process.stderr.write(`${text}
458
+ `);
459
+ } else {
460
+ process.stdout.write(`${text}
461
+ `);
462
+ }
463
+ process.exitCode = run.exitCode;
464
+ } catch (err) {
465
+ fail(err);
466
+ }
467
+ });
468
+ program.command("remove").description("Remove the named citations from the given pages, markers and all").argument(
469
+ "[paths...]",
470
+ "files, directories, or globs to remove from (use - for stdin)"
471
+ ).option(
472
+ "--collection <name>",
473
+ "configured collection to run over; repeatable",
474
+ collect,
475
+ []
476
+ ).option("--ext <list>", "comma-separated extensions for directory walks").option("--exclude <glob>", "glob to exclude; repeatable", collect, []).option("--as <format>", "force an input format for every input").option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").option("--allow-empty", "treat zero matched files as success").option("--no-gitignore", "remove from files .gitignore covers").option(
477
+ "--only <id>",
478
+ "the entry to remove, by id or by pointer (/citations/N); required, and repeatable",
479
+ collect,
480
+ []
481
+ ).option("--dry-run", "print the diffs and the report; write nothing").option(
482
+ "-f, --format <format>",
483
+ `output: ${REMOVE_FORMATS.join(" | ")}`,
484
+ "pretty"
485
+ ).addHelpText(
486
+ "after",
487
+ [
488
+ "",
489
+ "Examples:",
490
+ " manni cite remove docs/limits.md --only fetch-timeout",
491
+ " manni cite remove docs/ --only fetch-timeout --only retries --dry-run",
492
+ " manni cite remove --collection site --only /citations/3 -f json"
493
+ ].join("\n")
494
+ ).action(async (paths, options, command) => {
495
+ try {
496
+ const format = options.format;
497
+ if (!isRemoveFormat(format)) {
498
+ throw new CiteError(
499
+ `Unknown --format "${format}". Use ${COMMON_FORMAT_LIST}.`
500
+ );
501
+ }
502
+ const exts = options.ext ? splitList(options.ext) : void 0;
503
+ const usingStdin = paths.includes(STDIN_TOKEN);
504
+ const stdinContent = usingStdin ? await readStdin() : void 0;
505
+ const dryRun = Boolean(options.dryRun);
506
+ const pageToStdout = usingStdin && !dryRun;
507
+ const cwd = process.cwd();
508
+ const run = await runRemove({
509
+ inputs: paths,
510
+ collection: options.collection,
511
+ exts,
512
+ exclude: options.exclude,
513
+ as: options.as,
514
+ ...configOption(options.config),
515
+ onConfigLoaded: reportConfig(format === "pretty" && !pageToStdout, cwd),
516
+ stdinContent,
517
+ allowEmpty: options.allowEmpty ? true : void 0,
518
+ respectGitignore: explicitFalse(options.gitignore),
519
+ onNotice: notice,
520
+ only: options.only,
521
+ dryRun
522
+ });
523
+ const text = format === "json" ? renderRemoveJson(run) : renderRemovePretty(run, {
524
+ color: colorFor(command, process.stdout.isTTY),
525
+ // The diffs are the point of a dry run; a real run prints
526
+ // what it removed and leaves the file to say the rest.
527
+ showDiff: dryRun,
528
+ dryRun
529
+ });
530
+ const stdinPage = pageToStdout ? run.pages.find((page) => page.content !== void 0) : void 0;
531
+ if (stdinPage?.content !== void 0) {
532
+ process.stdout.write(stdinPage.content);
533
+ process.stderr.write(`${text}
534
+ `);
535
+ } else {
536
+ process.stdout.write(`${text}
537
+ `);
538
+ }
539
+ process.exitCode = 0;
540
+ } catch (err) {
541
+ fail(err);
542
+ }
543
+ });
544
+ return program;
545
+ }
546
+ export {
547
+ addMessage,
548
+ buildProgram,
549
+ colorFor,
550
+ splitPageArgument2 as splitPageArgument
551
+ };
552
+ //# sourceMappingURL=cli-URZQXL4K.js.map