@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
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/a11y/cli.ts","../src/a11y/types.ts","../src/a11y/core/url.ts","../src/a11y/core/crawl.ts","../src/a11y/core/exclude.ts","../src/a11y/core/seeds.ts","../src/a11y/core/sitemap.ts","../src/a11y/commands/check.ts","../src/a11y/core/analyzer.ts","../src/a11y/core/config.ts","../src/a11y/reporters/github.ts","../src/a11y/reporters/json.ts","../src/a11y/reporters/pretty.ts","../src/a11y/reporters/index.ts","../src/a11y/reporters/progress.ts","../src/cite/cli.ts","../src/cite/reporters/sarif.ts","../src/cite/reporters/junit.ts","../src/docevals/cli.ts","../src/key/cli.ts","../src/key/reporters/json.ts","../src/key/reporters/pretty.ts","../src/graph/cli.ts","../src/graph/reporters/index.ts","../src/graph/commands/check.ts","../src/graph/reporters/github.ts","../src/graph/commands/init.ts","../src/lint/cli.ts","../src/term/cli.ts","../src/term/commands/check.ts","../src/term/core/config.ts","../src/term/errors.ts","../src/term/types.ts","../src/term/core/severity.ts","../src/term/core/check.ts","../src/term/commands/findings.ts","../src/term/commands/run.ts","../src/term/core/load-set.ts","../src/term/core/writers/markup.ts","../src/term/core/writers/entries.ts","../src/term/core/id.ts","../src/term/core/readers/normalize.ts","../src/term/core/readers/splice.ts","../src/term/core/readers/xml.ts","../src/term/core/readers/dita.ts","../src/term/core/readers/docbook.ts","../src/term/core/readers/html.ts","../src/term/core/readers/manifest.ts","../src/term/core/readers/page.ts","../src/term/core/readers/structured.ts","../src/term/core/readers/body.ts","../src/term/core/readers/asciidoc-glossary.ts","../src/term/core/readers/markdown-deflist.ts","../src/term/core/readers/rst-glossary.ts","../src/term/core/readers/text.ts","../src/term/core/readers/index.ts","../src/term/core/writers/documents.ts","../src/term/core/writers/page.ts","../src/term/core/writers/render-util.ts","../src/term/core/writers/csv.ts","../src/term/core/writers/json.ts","../src/term/core/writers/skos.ts","../src/term/core/writers/tbx.ts","../src/term/core/writers/vale.ts","../src/term/core/writers/interchange.ts","../src/term/core/writers/index.ts","../src/term/commands/formats.ts","../src/term/commands/get.ts","../src/term/core/lint.ts","../src/term/core/vale.ts","../src/term/commands/lint.ts","../src/term/commands/list.ts","../src/term/commands/write.ts","../src/term/reporters/csv.ts","../src/term/reporters/github.ts","../src/term/reporters/json.ts","../src/term/reporters/sarif.ts","../src/term/reporters/junit.ts","../src/term/reporters/pretty.ts","../src/term/commands/labels.ts","../src/tracevals/cli.ts"],"sourcesContent":["/**\n * The `manni` CLI: one bin, one subcommand per tool in the family.\n *\n * Each tool builds its own commander program and is mounted here under its\n * name, so `manni meta validate …` is the metadata tool's `validate` with\n * nothing in between. The umbrella owns only what is common to all of them:\n * the name, the version, and the exit-code contract in `runProgram`.\n *\n * Tools land here one at a time, on their own branches; until one merges its\n * subcommand does not exist.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { buildProgram as buildA11y } from \"./a11y/cli.js\";\nimport { buildProgram as buildCite } from \"./cite/cli.js\";\nimport { buildProgram as buildDocevals } from \"./docevals/cli.js\";\nimport { buildProgram as buildKey } from \"./key/cli.js\";\nimport { buildProgram as buildGraph } from \"./graph/cli.js\";\nimport { buildProgram as buildMeta } from \"./meta/cli.js\";\nimport { buildProgram as buildLint } from \"./lint/cli.js\";\nimport { buildProgram as buildTerm } from \"./term/index.js\";\nimport { buildProgram as buildTracevals } from \"./tracevals/cli.js\";\nimport { runIfMain } from \"./shared/run.js\";\n\nexport function buildProgram(): Command {\n const meta = buildMeta()\n .name(\"meta\")\n .description(\n \"Validate, read, query and fill document metadata against JSON Schema\",\n );\n const metaCommands = new Set(meta.commands.map((c) => c.name()));\n\n const program = new Command();\n program\n .name(\"manni\")\n .description(\"Tools for documentation that is meant to be checked.\")\n .version(pkg.version, \"-V, --version\")\n // A pointer, not the whole help screen. Commander appends this after every\n // usage error, and the message that precedes it already names the problem.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before `addCommand`, which copies the exit callback into the\n // mounted program by value. See the same note in ./meta/cli.ts.\n .exitOverride()\n .configureOutput({\n outputError: (str, write) => {\n write(str);\n // `manni validate …` is the most likely thing a docmeta user types\n // first. Commander's \"unknown command\" is correct and unhelpful; say\n // where the command went.\n const m = /unknown command '([^']+)'/.exec(str);\n const name = m?.[1];\n if (name !== undefined && metaCommands.has(name)) {\n write(\n `(\\`${name}\\` is a metadata command: try \\`manni meta ${name}\\`)\\n`,\n );\n }\n },\n });\n\n program.addCommand(meta);\n program.addCommand(\n buildA11y()\n .name(\"a11y\")\n .description(\n \"Crawl a site and check every page for accessibility violations with axe-core\",\n ),\n );\n program.addCommand(\n buildCite()\n .name(\"cite\")\n .description(\n \"Track citations from doc claims to source lines and check them for drift\",\n ),\n );\n program.addCommand(\n buildLint()\n .name(\"lint\")\n .description(\n \"Validate document structure against doctype templates, routed by a page's type\",\n ),\n );\n program.addCommand(\n buildDocevals()\n .name(\"docevals\")\n .description(\n \"Deterministic and LLM-as-judge evals for documentation pages, driven by frontmatter\",\n ),\n );\n program.addCommand(\n buildTerm()\n .name(\"term\")\n .description(\"Check, lint and render a docset's terms and the references into them\"),\n );\n program.addCommand(\n buildGraph()\n .name(\"graph\")\n .description(\n \"Deterministic knowledge graphs derived from documentation frontmatter and formatting\",\n ),\n );\n program.addCommand(\n buildTracevals()\n .name(\"tracevals\")\n .description(\n \"Deterministic and LLM-as-judge adherence evals for AI agent session traces\",\n ),\n );\n // Not a tool but a family resource with verbs (proposal 0045).\n program.addCommand(\n buildKey()\n .name(\"key\")\n .description(\"Set and rotate the family key that encrypted values are encrypted with.\"),\n );\n return program;\n}\n\nrunIfMain(import.meta.url, buildProgram);\n","/**\n * The a11y tool's CLI. A thin commander wrapper over `runCheck`, following\n * clig.dev the way meta's does: primary output to stdout, diagnostics to\n * stderr, color only on a TTY (never under NO_COLOR/--no-color), and the\n * exit codes 0 ok, 1 findings, 2 operational/usage.\n *\n * Every flag is validated here and turned into an `A11yError` before the\n * browser is asked to launch, so a typo costs a message and not a launch.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { shouldColor } from \"../shared/color.js\";\nimport { FAMILY_CONFIG_NAMES } from \"../shared/config-file.js\";\nimport { fail } from \"../shared/run.js\";\nimport { CHECK_DEFAULTS, runCheck } from \"./commands/check.js\";\nimport { createPlaywrightAnalyzer } from \"./core/analyzer.js\";\nimport { excludeEntryLabel, loadA11yConfig, type LoadedA11yConfig } from \"./core/config.js\";\nimport { MUST_START_WITH_SLASH, isUrlPathGlob, type ExcludeGlob } from \"./core/exclude.js\";\nimport { resolveSeeds } from \"./core/seeds.js\";\nimport { A11Y_FORMAT_LIST, isA11yFormat, render } from \"./reporters/index.js\";\nimport { CLEAR_LINE, createProgressReporter } from \"./reporters/progress.js\";\nimport {\n A11yError,\n SEVERITY_LIST,\n isSeverity,\n type Severity,\n type ProgressListener,\n} from \"./types.js\";\n\n/**\n * `--collection <name>` and `--exclude <glob>`: one value per occurrence,\n * never split on commas. The two lines are meta's `collect`, copied rather\n * than imported: a tool does not reach into a sibling tool's CLI.\n */\nfunction collect(value: string, prev: string[]): string[] {\n return prev.concat([value]);\n}\n\n/** `--tags <list>`: commas separate, whitespace around them is trimmed, empty items are dropped. */\nfunction splitList(value: string): string[] {\n return value\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/**\n * Whether to paint what goes to `stream`. The report and the progress line\n * are decided separately, since stdout may be a pipe while stderr is still\n * the terminal (`-f json | jq`), and the other way round.\n */\nfunction resolveColor(program: Command, stream: NodeJS.WriteStream): boolean {\n // commander maps --no-color to opts.color === false.\n const noColor = program.opts().color === false;\n // `isTTY` is undefined off a terminal, never false; `shouldColor` treats a\n // missing one as \"not a terminal\".\n return shouldColor({ noColor, isTTY: stream.isTTY });\n}\n\ninterface Progress {\n /** Hears the run's events; `undefined` keeps the run silent. */\n listener: ProgressListener | undefined;\n /**\n * Erase the status line. On a terminal it is rewritten in place, and a run\n * that dies mid-crawl (no browser, a seed that will not load) would leave\n * it there for the error to land on. A no-op everywhere else.\n */\n clear: () => void;\n}\n\n/**\n * `--progress` and `--no-progress` decide; with neither, progress is on\n * exactly when stderr is a terminal, so a CI log stays as it was.\n */\nfunction resolveProgress(program: Command, flag: boolean | undefined): Progress {\n // @types/node says boolean; off a terminal it is undefined (see resolveColor).\n const tty = (process.stderr.isTTY as boolean | undefined) ?? false;\n const silent: Progress = { listener: undefined, clear: () => undefined };\n if (!(flag ?? tty)) return silent;\n const listener = createProgressReporter({\n stream: process.stderr,\n color: resolveColor(program, process.stderr),\n tty,\n });\n if (!tty) return { listener, clear: silent.clear };\n return {\n listener,\n clear: () => {\n process.stderr.write(CLEAR_LINE);\n },\n };\n}\n\n/**\n * A positive integer flag, in canonical form. Anything else is a usage error:\n * `0`, `-3`, `2.5`, `many`, and `01`, since a leading zero is not how anyone\n * writes a page count and would read as an octal literal elsewhere.\n * Exported for its unit test only.\n */\nexport function positiveInteger(value: string, flag: string): number {\n if (!/^[1-9]\\d*$/.test(value)) {\n throw new A11yError(`${flag} must be an integer >= 1.`);\n }\n return Number(value);\n}\n\n/**\n * `--max-pages <n>` and `--no-max-pages` share one option value, the way `-c`\n * and `--no-config` do, so the pair has three states rather than two:\n * a number the user typed, `\"uncapped\"` for the negation, and `undefined`\n * when neither half was typed and the config key still decides.\n */\nexport type MaxPagesFlag = number | \"uncapped\" | undefined;\n\n/**\n * The typed half of that pair, in canonical form. commander hands the\n * negation over as `false`, which is not the same as saying nothing: it is\n * the typed way to ask for a run with no cap at all. Parsed before the config\n * file is read, so a bad value costs a message and nothing else.\n * Exported for its unit test only.\n */\nexport function parseMaxPages(value: string | false | undefined): MaxPagesFlag {\n if (value === false) return \"uncapped\";\n if (value === undefined) return undefined;\n return positiveInteger(value, \"--max-pages\");\n}\n\n/**\n * The cap in force: a typed flag beats the config key, and `undefined` out\n * means no cap, which is what `runCheck` reads as \"check everything found\".\n * Exported for its unit test only.\n */\nexport function resolveMaxPages(\n flag: MaxPagesFlag,\n configured: number | undefined,\n): number | undefined {\n if (flag === \"uncapped\") return undefined;\n return flag ?? configured;\n}\n\n/**\n * Whether to crawl: `--crawl` and `--no-crawl` are both declared, so\n * commander holds no default for the pair and `undefined` means the user\n * typed neither. Same three-way precedence as meta: CLI flag > config key >\n * built-in default.\n * Exported for its unit test only.\n */\nexport function resolveCrawl(flag: boolean | undefined, configured: boolean | undefined): boolean {\n return flag ?? configured ?? CHECK_DEFAULTS.crawl;\n}\n\n/**\n * Every `--exclude` value has to be able to match a path, which always starts\n * with `/`. Checked before the config file is read and long before a browser\n * launches, so a pattern that could only ever miss costs a message. Each\n * survivor carries the flag spelling a later message names it by.\n * Exported for its unit test only.\n */\nexport function assertExcludeGlobs(globs: readonly string[]): ExcludeGlob[] {\n return globs.map((glob) => {\n if (!isUrlPathGlob(glob)) {\n throw new A11yError(`--exclude \"${glob}\" ${MUST_START_WITH_SLASH}`);\n }\n return { glob, source: `--exclude \"${glob}\"` };\n });\n}\n\n/**\n * The same list as it arrives from `a11y.exclude:`, named the way the config\n * errors name it. A run whose patterns came from a file never reports them as\n * a flag, which would send a reader looking through a shell history for\n * something they never typed.\n * Exported for its unit test only.\n */\nexport function configExcludeGlobs(\n globs: readonly string[],\n source: string | null,\n): ExcludeGlob[] {\n // The CLI reaches here only with a file behind it, since `cfg.exclude` is\n // set, so the fallback is for a programmatic caller that passed a section\n // with no source. It names the file a reader would look for rather than\n // labelling an entry with \"null\".\n const file = source ?? FAMILY_CONFIG_NAMES[0] ?? \"manni.config.yaml\";\n return globs.map((glob, i) => ({ glob, source: excludeEntryLabel(file, i) }));\n}\n\nfunction assertSeverity(value: string): Severity {\n if (!isSeverity(value)) {\n throw new A11yError(`Unknown --severity \"${value}\". Use ${SEVERITY_LIST}.`);\n }\n return value;\n}\n\ninterface CheckCliOptions {\n /** `-f, --format` (default \"pretty\"). */\n format: string;\n /** `--crawl` → true, `--no-crawl` → false, neither → undefined (config decides). */\n crawl?: boolean;\n /** `--max-pages <n>` → the string; `--no-max-pages` → commander's false; neither → undefined. */\n maxPages?: string | false;\n /** `--tags <list>`, split on \",\" here (same helper shape as meta's --ext). */\n tags?: string;\n /** `--severity <level>`. */\n severity: string;\n /** `--timeout <ms>`, parsed to int here. */\n timeout: string;\n /** `-q, --quiet`. */\n quiet?: boolean;\n /** `--progress` → true, `--no-progress` → false, neither → undefined (auto). */\n progress?: boolean;\n /** `--collection <name>`, one value per occurrence. `[]` when never given. */\n collection: string[];\n /** `--exclude <glob>`, one value per occurrence. `[]` when never given. */\n exclude: string[];\n /** `-c <path>` | `--no-config` → false. */\n config?: string | false;\n}\n\n/** Commander program named \"a11y\"; the umbrella mounts it. No entry point. */\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"a11y\")\n .description(\"Crawl a site and check every page for accessibility violations with axe-core\")\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n // A pointer, not the whole help screen; the message before it already\n // names the offending flag.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before the `.command()` call below. `copyInheritedSettings`\n // copies `_exitCallback` **by value** at subcommand-creation time, so an\n // `exitOverride()` installed afterwards leaves the subcommand calling\n // `process.exit(1)` while the program-level case looks fixed.\n .exitOverride();\n\n program\n .command(\"check\")\n .description(\"Crawl from the given URLs and check every page with axe-core\")\n .argument(\n \"[urls...]\",\n \"http(s) seed URLs; falls back to a collection's url: or a11y.urls in manni.config.yaml\",\n )\n .option(\"-f, --format <format>\", `output: ${A11Y_FORMAT_LIST}`, \"pretty\")\n // `--crawl` first, so that `--no-crawl` leaves the pair's default\n // undefined instead of commander's `true` for a lone negation. Undefined\n // is what lets `crawl:` in config be read as the next rung down.\n .option(\"--crawl\", \"crawl from the given URLs: sitemap and link following (default)\")\n .option(\"--no-crawl\", \"check exactly the given URLs: no sitemap, no link following\")\n // No commander default on purpose: the built-in behaviour is to check\n // everything discovered, and \"no cap\" is not a value commander could hold.\n .option(\n \"--max-pages <n>\",\n \"cap on pages checked; the rest are reported as skipped (default: no cap)\",\n )\n .option(\"--no-max-pages\", \"check every page found, ignoring a configured maxPages\")\n .option(\n \"--exclude <glob>\",\n \"URL path glob to keep out of the crawl; repeatable\",\n collect,\n [],\n )\n .option(\"--tags <list>\", \"comma-separated axe tags to restrict the rules to\")\n .option(\n \"--severity <level>\",\n `minimum severity reported: ${SEVERITY_LIST}`,\n CHECK_DEFAULTS.severity,\n )\n .option(\n \"--timeout <ms>\",\n \"per-page navigation timeout in milliseconds\",\n String(CHECK_DEFAULTS.timeout),\n )\n .option(\"-q, --quiet\", \"in pretty output, hide pages with no violations\")\n // `--progress` first, so that adding `--no-progress` leaves the default\n // undefined (auto) instead of commander's `true` for a lone negation.\n .option(\"--progress\", \"report progress on stderr (default: only on a terminal)\")\n .option(\"--no-progress\", \"never report progress\")\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\")\n .action(async (urls: string[], options: CheckCliOptions, command: Command) => {\n // Settled once the flags are validated; until then there is no line to clear.\n let clearProgress = (): void => undefined;\n try {\n // A value commander filled in from the option's default yields to the\n // config file; one the user typed wins over it. Same three-way\n // precedence as meta: CLI flag > config key > default.\n const typed = (name: string): boolean =>\n command.getOptionValueSource(name) === \"cli\";\n\n const format = options.format;\n if (!isA11yFormat(format)) {\n throw new A11yError(`Unknown --format \"${format}\". Use ${A11Y_FORMAT_LIST}.`);\n }\n const severity = assertSeverity(options.severity);\n const maxPages = parseMaxPages(options.maxPages);\n const timeout = positiveInteger(options.timeout, \"--timeout\");\n const exclude = assertExcludeGlobs(options.exclude);\n\n const loaded: LoadedA11yConfig =\n options.config === false\n // --no-config drops the collections with the section: the file\n // the user told the run to ignore is where both live.\n ? { config: {}, source: null, collections: [] }\n : await loadA11yConfig(process.cwd(), options.config);\n const cfg = loaded.config;\n\n // Before the analyzer exists: a run with nothing to check, or a\n // --collection that cannot be honoured, costs a message and not a\n // browser launch.\n const seeds = resolveSeeds({\n urls,\n collections: options.collection,\n ...(cfg.urls === undefined ? {} : { configUrls: cfg.urls }),\n declared: loaded.collections,\n source: loaded.source,\n });\n\n const parent = command.parent ?? command;\n const progress = resolveProgress(parent, options.progress);\n clearProgress = progress.clear;\n\n const run = await runCheck(\n {\n urls: seeds,\n crawl: resolveCrawl(options.crawl, cfg.crawl),\n // Typed flag > config key > no cap. There is no default to fall\n // to, and `--no-max-pages` is the typed way to ask for none.\n maxPages: resolveMaxPages(maxPages, cfg.maxPages),\n tags:\n options.tags !== undefined\n ? splitList(options.tags)\n : (cfg.tags ?? CHECK_DEFAULTS.tags),\n // A typed flag replaces the config list entirely; the two do not\n // merge. Merging would only ever let a run exclude *more* than\n // the repository's default, so checking one excluded section on\n // purpose would need --no-config, which also drops collections:.\n exclude: typed(\"exclude\")\n ? exclude\n : configExcludeGlobs(cfg.exclude ?? [], loaded.source),\n severity: typed(\"severity\") ? severity : (cfg.severity ?? CHECK_DEFAULTS.severity),\n timeout: typed(\"timeout\") ? timeout : (cfg.timeout ?? CHECK_DEFAULTS.timeout),\n },\n { analyzer: createPlaywrightAnalyzer(), onProgress: progress.listener },\n );\n\n const color = resolveColor(parent, process.stdout);\n const text = render(format, run, { color, quiet: Boolean(options.quiet) });\n // Only `github` may say nothing on a clean run; every other format\n // owes its envelope even when it is empty.\n if (text.length > 0 || format !== \"github\") {\n process.stdout.write(`${text}\\n`);\n }\n process.exitCode = run.summary.failed > 0 ? 1 : 0;\n } catch (err) {\n clearProgress();\n fail(err);\n }\n });\n\n return program;\n}\n\n","/**\n * The shapes the a11y tool produces and the error it throws.\n *\n * Everything downstream of the browser — the crawl, the check core, the\n * reporters — speaks in these types, so the analyzer is the only module that\n * knows axe's own result shape.\n */\nimport { ToolError } from \"../shared/errors.js\";\nimport type { Severity } from \"../shared/severity.js\";\n\n/**\n * The severity scale is the family's, not a11y's. It is re-exported here so\n * the tool's own modules and tests have one import for everything they speak.\n */\nexport {\n SEVERITIES,\n SEVERITY_LIST,\n isSeverity,\n meetsSeverity,\n type Severity,\n} from \"../shared/severity.js\";\n\n/** Operational/usage failure of the a11y tool: one line on stderr, exit 2. */\nexport class A11yError extends ToolError {\n constructor(message: string) {\n super(message);\n this.name = \"A11yError\";\n }\n}\n\n/**\n * axe's own scale, which it calls impact. Least to most severe. The analyzer\n * maps these onto the family `Severity` (`severityOf`) and keeps the original\n * on the violation as `impact`.\n */\nexport const AXE_IMPACTS = [\"minor\", \"moderate\", \"serious\", \"critical\"] as const;\nexport type AxeImpact = (typeof AXE_IMPACTS)[number];\n\nexport function isAxeImpact(value: string): value is AxeImpact {\n return (AXE_IMPACTS as readonly string[]).includes(value);\n}\n\nexport interface ViolationNode {\n /** axe's CSS selector path to the element (joined `target`). */\n target: string;\n /** The element's outer HTML, as axe reports it (truncated to 200 chars in pretty output only). */\n html: string;\n /** axe's failureSummary: what to fix, in prose. */\n summary: string;\n}\n\nexport interface Violation {\n /** axe rule id, e.g. \"image-alt\". */\n id: string;\n /** The family level, mapped from `impact`. What the floor and the reporters use. */\n severity: Severity;\n /**\n * axe's own value, kept for lookup against Deque's rule pages and the axe\n * DevTools report a team already reads. An unknown or `null` impact is\n * recorded as `\"minor\"`.\n */\n impact: AxeImpact;\n /** Short rule description, e.g. \"Images must have alternate text\". */\n help: string;\n /** Deque University rule page. */\n helpUrl: string;\n /** axe tags, e.g. [\"cat.text-alternatives\", \"wcag2a\", \"wcag111\"]. */\n tags: string[];\n nodes: ViolationNode[];\n}\n\nexport interface PageResult {\n /** Normalized URL that was checked. */\n url: string;\n /** How the URL entered the run. */\n source: \"seed\" | \"sitemap\" | \"link\";\n /** Violations at or above the severity floor. Empty when `error` is set. */\n violations: Violation[];\n /** Count of axe rules that passed on this page. */\n passes: number;\n /** Count of rules axe could not decide (reported, never counted as failures). */\n incomplete: number;\n /**\n * round(100 × passes ÷ (passes + violations.length)), the share of applicable\n * axe rules that passed after severity filtering. Not a Lighthouse score.\n * `null` when the page did not load, or when no rule applied.\n */\n score: number | null;\n /** Set when the page could not be loaded or analyzed; the page counts as failed. */\n error?: string;\n}\n\n/**\n * A page that sent the browser elsewhere once it had loaded, by a meta refresh\n * or a script. It is not analyzed and is not a result: its destination joins\n * the crawl in its place, under the same rules as any other URL.\n */\nexport interface Redirect {\n /** The page that redirected, as queued. */\n url: string;\n /** Where it redirects, normalized. Present whether or not the destination was checked. */\n to: string;\n /** How the redirecting page entered the run. Its destination inherits it. */\n source: PageResult[\"source\"];\n}\n\nexport interface CheckSummary {\n /** Distinct URLs that entered the frontier (seeds + sitemap + links). */\n discovered: number;\n /** Pages actually analyzed. */\n checked: number;\n /** Discovered but not checked because the `maxPages` cap was reached; `0` without a cap. */\n skipped: number;\n /**\n * Discovered, then dropped unloaded because the browser had already landed\n * on the same page under another spelling (a redirect target). Neither\n * checked nor skipped:\n * `checked + skipped + duplicates + redirects === discovered`.\n */\n duplicates: number;\n /**\n * Pages discovered, then not analyzed because they redirect in the browser\n * (a meta refresh or a script). Each one is listed in `CheckRun.redirects`.\n */\n redirects: number;\n /**\n * Distinct URLs an `--exclude` pattern kept out of the crawl, counted once\n * each however many pages linked to them, and keyed the way the frontier\n * dedupes. It sits **outside** the identity above, because an excluded URL\n * never entered the frontier. `0` on a run that excludes nothing.\n */\n excluded: number;\n /** Pages with ≥1 remaining violation or an `error`. Drives exit 1. */\n failed: number;\n /** Total remaining violations across pages (rules, not nodes). */\n violations: number;\n /** Violations by family severity, always all three keys, zero-filled. */\n bySeverity: Record<Severity, number>;\n /** The sitemap URL that was found, or `null` if none was. Finding one is not using one: see `sitemapPages`. */\n sitemap: string | null;\n /**\n * Same-host, in-scope page URLs the sitemap listed. `0` when no sitemap was\n * found, and `0` when one was found whose every `<loc>` was out of scope — a\n * built sitemap listing production URLs, read on a local preview, is the\n * ordinary way that happens.\n *\n * This is the count the progress line reports, so it is taken before the\n * crawl dedupes against the seeds. A seed that the sitemap also lists is\n * counted here, which means the number can overstate what the sitemap alone\n * contributed to the frontier.\n */\n sitemapPages: number;\n /**\n * Whether the run discovered pages beyond the seeds (sitemap and same-host\n * links). `false` under `--no-crawl`, where `sitemap` is always `null` and\n * no link was followed.\n */\n crawl: boolean;\n}\n\nexport interface CheckRun {\n results: PageResult[];\n /** Pages that redirected in the browser, in visit order. Never in `results`. */\n redirects: Redirect[];\n summary: CheckSummary;\n}\n\n/**\n * What a run says while it is still running. The crawl emits these in order\n * (`browser`, then `page` and `checked` or `redirected` per page, then\n * `done`); the check core adds `sitemap` before them when it crawls. A\n * listener is optional, and nothing is emitted without one.\n */\nexport type ProgressEvent =\n /** About to launch the browser, before the first page. */\n | { kind: \"browser\" }\n /** Discovery finished: the sitemap that was found (or none), and how many in-scope URLs it gave. */\n | { kind: \"sitemap\"; source: string | null; urls: number }\n /**\n * Discovery settled and `--exclude` took `urls` distinct URLs out, across\n * `patterns` patterns. Emitted once, before the browser starts, and only\n * when something was excluded. There is no event per excluded URL: a\n * pattern that removes four hundred pages would bury the ones checked.\n *\n * `urls` is what the seeds and the sitemap gave the run. Links are followed\n * afterwards, and a page excluded that way is counted in `summary.excluded`\n * without reaching this event, so the two can disagree and the summary is\n * the authoritative total.\n */\n | { kind: \"excluded\"; urls: number; patterns: number }\n /** About to check page `index` (1-based); `queued` is every URL discovered so far. */\n | { kind: \"page\"; index: number; queued: number; url: string }\n /**\n * Page `index` finished. `violations` is axe's count for the page before the\n * severity floor is applied, so it can be higher than what the report keeps.\n * `error` is set when the page could not be loaded or analyzed. A seed that\n * fails ends the run instead, and is reported as the run's error.\n */\n | { kind: \"checked\"; index: number; url: string; violations: number; error?: string }\n /**\n * Page `index` sent the browser to `to` once loaded, so it was not\n * analyzed. Emitted in place of `checked`; the counter counts checked\n * pages, so the next page reuses `index`.\n */\n | { kind: \"redirected\"; index: number; url: string; to: string }\n /** The crawl is over: pages analyzed, and pages left in the frontier. */\n | { kind: \"done\"; checked: number; skipped: number };\n\nexport type ProgressListener = (event: ProgressEvent) => void;\n","/**\n * URL helpers for the crawl.\n *\n * Three questions, asked of every candidate before it enters the frontier:\n * what is its canonical spelling (so `/a#top` and `/a` are one page), is it\n * on a host the run is allowed to visit, and is it a page at all rather than\n * a stylesheet or a PDF. The WHATWG parser does most of the first one.\n */\nimport { A11yError } from \"../types.js\";\n\n/**\n * Canonical spelling for dedupe: parse with `new URL`, drop the fragment,\n * lowercase the hostname, drop a default port, keep path/query/trailing slash\n * exactly as given. Throws `A11yError` for an unparseable string.\n */\nexport function normalizeUrl(url: string): string {\n const parsed = parse(url);\n if (parsed === null) throw new A11yError(`Not a valid URL: \"${url}\".`);\n parsed.hash = \"\";\n return parsed.href;\n}\n\n/**\n * The key two spellings of one page share: `normalizeUrl`, then one trailing\n * `/` dropped from the path unless the path is exactly `/`. The query stays.\n * `/a` and `/a/` can be different resources, but on a static site they are one\n * page, and a crawl that checks both double-counts it. Only the seen set uses\n * this; the URL fetched and reported keeps the spelling it was given. Throws\n * `A11yError` for an unparseable string.\n */\nexport function dedupeKey(url: string): string {\n const parsed = new URL(normalizeUrl(url));\n if (parsed.pathname.length > 1 && parsed.pathname.endsWith(\"/\")) {\n parsed.pathname = parsed.pathname.slice(0, -1);\n }\n return parsed.href;\n}\n\n/** `http:` or `https:` and parseable. */\nexport function isHttpUrl(url: string): boolean {\n const parsed = parse(url);\n return parsed !== null && isHttpProtocol(parsed);\n}\n\n/**\n * Same site = same hostname (case-insensitive) and same non-default port.\n * `http://` and `https://` of one host are the same site; `www.example.com`\n * and `example.com` are not.\n */\nexport function sameHost(a: string, b: string): boolean {\n const left = parse(a);\n const right = parse(b);\n if (left === null || right === null) return false;\n // The parser has already dropped `:80` on http and `:443` on https, so an\n // empty port on both sides means \"the scheme's default\" and the two schemes\n // of one host compare equal, as the doc comment promises. Only an explicit\n // non-default port survives to differ.\n return (\n left.hostname.toLowerCase() === right.hostname.toLowerCase() &&\n left.port === right.port\n );\n}\n\n/**\n * A link worth loading as a page: http(s), not `mailto:`/`tel:`/`javascript:`/\n * `data:`, and the last path segment does not end in one of ASSET_EXTENSIONS.\n */\nexport function isPageLink(url: string): boolean {\n const parsed = parse(url);\n if (parsed === null || !isHttpProtocol(parsed)) return false;\n const last = parsed.pathname.slice(parsed.pathname.lastIndexOf(\"/\") + 1);\n const dot = last.lastIndexOf(\".\");\n if (dot === -1) return true;\n return !ASSET_EXTENSIONS.has(last.slice(dot).toLowerCase());\n}\n\nexport const ASSET_EXTENSIONS: ReadonlySet<string> = new Set([\n \".pdf\",\n \".zip\",\n \".gz\",\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".svg\",\n \".webp\",\n \".avif\",\n \".ico\",\n \".css\",\n \".js\",\n \".mjs\",\n \".map\",\n \".json\",\n \".xml\",\n \".txt\",\n \".mp3\",\n \".mp4\",\n \".webm\",\n \".woff\",\n \".woff2\",\n \".ttf\",\n]);\n\nfunction parse(url: string): URL | null {\n try {\n return new URL(url);\n } catch {\n return null;\n }\n}\n\nfunction isHttpProtocol(url: URL): boolean {\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n}\n","/**\n * The crawl: which pages a run visits, and in what order.\n *\n * A breadth-first walk over a FIFO frontier. Seeds go in first, then the\n * sitemap's pages, then every same-host link each visited page lists, in the\n * order it listed them. A page enters the frontier once, under its `dedupeKey`\n * (so `/a` and `/a/` are one page), keeping the spelling that arrived first.\n * Pages run one at a time so a site sees one request at a time.\n *\n * A page that redirects in the browser is not a page the run checks. Its\n * destination joins the frontier in its place, under the same rules.\n */\nimport type { AnalyzeOptions, PageAnalyzer } from \"./analyzer.js\";\nimport { A11yError, type PageResult, type ProgressListener, type Redirect } from \"../types.js\";\nimport type { ExcludeFilter, ExcludeGlob } from \"./exclude.js\";\nimport { dedupeKey, isHttpUrl, isPageLink, normalizeUrl, sameHost } from \"./url.js\";\n\nexport interface CrawlOptions {\n /** Normalized http(s) seeds; each seed's host is in scope. */\n seeds: string[];\n /** `false` = check exactly `seeds`. */\n crawl: boolean;\n /** Hard cap on pages analyzed. Absent means no cap: the whole frontier is analyzed. */\n maxPages?: number;\n /** Extra URLs to enqueue right after the seeds (from the sitemap). */\n extra: string[];\n /**\n * Keeps matching URLs out of the frontier, beside the same-host and\n * asset-extension checks. Absent means nothing is excluded.\n */\n exclude?: ExcludeFilter;\n analyze: AnalyzeOptions;\n /** Told about each step as it happens. Absent means silent. */\n onProgress?: ProgressListener;\n}\n\nexport interface CrawlOutcome {\n /** In visit order. `source` is \"seed\", \"sitemap\" (came from `extra`) or \"link\". */\n pages: Omit<PageResult, \"score\">[];\n /** Distinct pages (by `dedupeKey`) that entered the frontier. */\n discovered: number;\n /** Left in the frontier when `maxPages` stopped the run; `0` without a cap. */\n skipped: number;\n /**\n * Dequeued and dropped unloaded, because the browser had already landed on\n * that page under another spelling.\n * `checked + skipped + duplicates + redirects.length` is `discovered`.\n */\n duplicates: number;\n /** Pages that redirected in the browser, in visit order. Never in `pages`. */\n redirects: Redirect[];\n /**\n * Distinct URLs (by `dedupeKey`) an `exclude` pattern kept out. Never part\n * of `discovered`: an excluded URL is dropped where an off-host URL and a\n * `.png` link are, before the frontier.\n */\n excluded: number;\n}\n\ntype Source = PageResult[\"source\"];\n\n/** What `enqueue` did with a URL, and the pattern when one excluded it. */\ntype Enqueued =\n | { as: \"queued\" | \"seen\" | \"invalid\" | \"asset\" | \"off-host\" }\n | { as: \"excluded\"; pattern: ExcludeGlob };\n\ninterface Candidate {\n url: string;\n key: string;\n source: Source;\n}\n\n/**\n * BFS over a FIFO frontier: seeds, then `extra`, then links in the order each\n * page listed them. Every candidate goes through `normalizeUrl`, and is\n * enqueued once per `dedupeKey` (so a trailing slash does not make a second\n * page), only when `isPageLink` and `sameHost` with **any** seed. The first\n * spelling seen is the one fetched and reported. Pages run sequentially.\n * - A seed that fails to analyze rethrows (nothing was checked: exit 2).\n * - Any other page's failure is recorded as `error` and the crawl continues.\n * - A page's `finalUrl` (where the browser landed) counts as visited, so a\n * queued spelling of it is dropped at dequeue time (`duplicates`), and a\n * link to it seen afterwards is never queued.\n * - With `maxPages` set, stops when `pages.length === maxPages`; `skipped` =\n * frontier left behind. Without it, runs the frontier dry and `skipped` is 0.\n * - With `crawl: false`, `extra` is ignored and no links are followed.\n * - With `exclude` set, a URL whose path a pattern matches is never enqueued,\n * never fetched and never counted in `discovered`; `excluded` counts those,\n * once per key. `onProgress` hears one `excluded` event before `browser`\n * when the count is not zero.\n * - A page that redirects in the browser is recorded in `redirects`, not in\n * `pages`, and does not count toward `maxPages`. Its destination is\n * enqueued with the page's own `source`, under `crawl: false` too, since it\n * is the same page under a new address. A seed whose destination is not\n * http(s), is on another host, or is excluded, rethrows: otherwise nothing\n * would be checked.\n * - `onProgress` hears `browser` once before the first analyze (that is where\n * the lazy launch happens), `page` before each analyze, `checked` (or\n * `redirected`) after each, and `done` at the end. A failing seed rethrows\n * before `checked`.\n */\nexport async function crawl(opts: CrawlOptions, analyzer: PageAnalyzer): Promise<CrawlOutcome> {\n const frontier: Candidate[] = [];\n /** Keys that entered the frontier, or that the browser landed on. */\n const seen = new Set<string>();\n /** Keys analyzed, or that the browser landed on. */\n const visited = new Set<string>();\n /** Keys an `exclude` pattern kept out, so a page linked thirty times counts once. */\n const excluded = new Set<string>();\n const progress = opts.onProgress ?? (() => undefined);\n\n const enqueue = (raw: string, source: Source): Enqueued => {\n let url: string;\n let key: string;\n try {\n url = normalizeUrl(raw);\n key = dedupeKey(url);\n } catch {\n return { as: \"invalid\" };\n }\n // A seed is what the user asked for, so it is never filtered as an asset;\n // it still has to be on its own host, which it is by definition.\n if (source !== \"seed\" && !isPageLink(url)) return { as: \"asset\" };\n if (!opts.seeds.some((seed) => sameHost(seed, url))) return { as: \"off-host\" };\n // After the scope checks, so an off-host or asset URL is not also counted\n // as excluded; the two filters answer different questions and a URL that\n // was never in scope was not kept out by a pattern.\n const pattern = opts.exclude?.match(url) ?? null;\n if (pattern !== null) {\n excluded.add(key);\n return { as: \"excluded\", pattern };\n }\n if (seen.has(key)) return { as: \"seen\" };\n seen.add(key);\n frontier.push({ url, key, source });\n return { as: \"queued\" };\n };\n\n /** Where the browser landed is a page the run has now checked, whatever it was asked for. */\n const landed = (finalUrl: string | undefined): void => {\n if (finalUrl === undefined) return;\n try {\n const key = dedupeKey(finalUrl);\n seen.add(key);\n visited.add(key);\n } catch {\n // Not a URL the crawl could ever queue, so nothing to mark.\n }\n };\n\n for (const seed of opts.seeds) enqueue(seed, \"seed\");\n if (opts.crawl) for (const url of opts.extra) enqueue(url, \"sitemap\");\n // Discovery has settled as far as it can before a page is fetched, and this\n // is where a pattern that matched far more than intended is worth seeing:\n // the browser has not launched yet, so the run is still cheap to stop.\n if (excluded.size > 0) {\n progress({ kind: \"excluded\", urls: excluded.size, patterns: opts.exclude?.patterns.length ?? 0 });\n }\n\n const pages: CrawlOutcome[\"pages\"] = [];\n const redirects: Redirect[] = [];\n let duplicates = 0;\n const capped = (): boolean => opts.maxPages !== undefined && pages.length >= opts.maxPages;\n for (let next = 0; next < frontier.length && !capped(); next++) {\n const candidate = frontier[next];\n if (candidate === undefined) break;\n const { url, key, source } = candidate;\n if (visited.has(key)) {\n duplicates += 1;\n continue;\n }\n visited.add(key);\n const index = pages.length + 1;\n // Not `index === 1`: a redirect pushes no page, so the next one reuses that index.\n if (pages.length + redirects.length === 0) progress({ kind: \"browser\" });\n progress({ kind: \"page\", index, queued: frontier.length, url });\n try {\n const analyzed = await analyzer.analyze(url, opts.analyze);\n if (\"redirect\" in analyzed) {\n const to = normalized(analyzed.redirect);\n // Recorded and narrated before the seed checks below on purpose: the\n // `↪` line then precedes the fatal message that explains it, and a\n // throw discards `redirects` anyway.\n redirects.push({ url, to, source });\n progress({ kind: \"redirected\", index, url, to });\n const outcome = enqueue(to, source);\n if (source === \"seed\") {\n if (!isHttpUrl(to)) {\n throw new A11yError(`${url} redirects to ${to}, which is not an http(s) URL.`);\n }\n if (outcome.as === \"off-host\") {\n throw new A11yError(`${url} redirects to ${to}, which is on another host. Check ${to} instead.`);\n }\n if (outcome.as === \"excluded\") {\n throw new A11yError(`${outcome.pattern.source} excludes ${to}, where the seed ${url} redirects.`);\n }\n }\n continue;\n }\n pages.push({ ...analyzed.result, url, source });\n landed(analyzed.finalUrl);\n if (opts.crawl) for (const link of analyzed.links) enqueue(link, \"link\");\n progress({ kind: \"checked\", index, url, violations: analyzed.result.violations.length });\n } catch (err) {\n if (source === \"seed\") throw err;\n const error = err instanceof Error ? err.message : String(err);\n pages.push({ url, source, violations: [], passes: 0, incomplete: 0, error });\n progress({ kind: \"checked\", index, url, violations: 0, error });\n }\n }\n\n const skipped = frontier.length - pages.length - duplicates - redirects.length;\n progress({ kind: \"done\", checked: pages.length, skipped });\n return {\n pages,\n discovered: frontier.length,\n skipped,\n duplicates,\n redirects,\n excluded: excluded.size,\n };\n}\n\n/** `normalizeUrl`, or the string as it came when it is not a URL. */\nfunction normalized(url: string): string {\n try {\n return normalizeUrl(url);\n } catch {\n return url;\n }\n}\n","/**\n * Keeping part of a site out of the crawl (proposal 0059).\n *\n * A pattern is matched against the URL's **path** alone, never the scheme,\n * host, port, query or fragment. The host is exactly the part that changes\n * between a local preview and production, so one pattern has to survive the\n * move: `/proposals/**` reads the same against `http://127.0.0.1:4321/` and\n * against `https://example.com/`.\n *\n * A trailing slash is not part of the comparison, because a crawl produces\n * both spellings — a sitemap usually lists `/proposals/`, a bare link usually\n * points at `/proposals`. Stripping it means a pattern cannot catch one and\n * silently miss the other. Stripping it is also what makes `/proposals/**`\n * cover the section index as well as the pages under it, since picomatch's\n * `**` already matches zero segments.\n *\n * Matching itself is the family's file-glob matcher, so an exclusion and a\n * collection's `paths:` read a `*`, a `**` and a dot segment the same way. A\n * URL path never carries a raw backslash — the WHATWG parser rewrites one and\n * percent-encodes the rest — so that matcher's separator normalization cannot\n * change what a pattern here means.\n */\nimport { matchesFileGlob } from \"../../shared/globs.js\";\n\n/**\n * One pattern, and the name a message gives it.\n *\n * A pattern reaches a run from one of two places, and an error about it has to\n * say which. `--exclude \"/proposals/**\"` for a typed flag, and the config\n * file's own shape for a key, so that a run whose patterns came from\n * `a11y.exclude:` never names a flag the user did not type.\n */\nexport interface ExcludeGlob {\n glob: string;\n /** How a message names this pattern: a flag, or a file and a key. */\n source: string;\n}\n\nexport interface ExcludeFilter {\n /** The patterns, in the order they were given. */\n readonly patterns: readonly ExcludeGlob[];\n /** The first pattern that keeps `url` out of the crawl, or `null`. */\n match(url: string): ExcludeGlob | null;\n /** Whether any pattern keeps `url` out of the crawl. */\n matches(url: string): boolean;\n}\n\n/**\n * The tail every \"that is not a path glob\" message ends with, so the flag and\n * the config key say the same thing about the same mistake.\n */\nexport const MUST_START_WITH_SLASH = 'must start with \"/\": it matches a URL path.';\n\n/**\n * Can this pattern ever match a path? A path always starts with `/`, so a\n * pattern that does not is a silent near-miss rather than a filter, and both\n * the flag and the config key refuse it.\n */\nexport function isUrlPathGlob(pattern: string): boolean {\n return pattern.startsWith(\"/\");\n}\n\n/**\n * The path a pattern is matched against: the URL's `pathname` with one\n * trailing `/` dropped, unless the path is exactly `/`. `null` for a string\n * that is not a URL, which the crawl has already dropped for other reasons.\n */\nexport function excludePath(url: string): string | null {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return null;\n }\n const path = parsed.pathname;\n return path.length > 1 && path.endsWith(\"/\") ? path.slice(0, -1) : path;\n}\n\n/**\n * A filter over `patterns`, in order. An empty list excludes nothing, which is\n * the default and the shape a run with neither the flag nor the config key\n * has. Patterns are taken as given: one value is one pattern, and a comma\n * inside it is a literal comma, per 0034's one-separator rule.\n */\nexport function createExcludeFilter(patterns: readonly ExcludeGlob[]): ExcludeFilter {\n const list = [...patterns];\n const match = (url: string): ExcludeGlob | null => {\n if (list.length === 0) return null;\n const path = excludePath(url);\n if (path === null) return null;\n return list.find((pattern) => matchesFileGlob(path, pattern.glob)) ?? null;\n };\n return {\n patterns: list,\n match,\n matches: (url) => match(url) !== null,\n };\n}\n","/**\n * Where a check starts from.\n *\n * A collection may declare `url:`, the site root its documents are published\n * at (proposal 0041, rule 12), which makes \"check the guides\" something a\n * person can mean. Four sources can therefore name a seed, and this module is\n * the one place that decides between them: first non-empty wins, in the order\n * positional URLs, the collections named by `--collection`, `a11y.urls`, then\n * every declared collection that has a `url`.\n *\n * `a11y.urls` keeps its place ahead of the collections because a site has\n * entry points no documentation collection covers, and because nothing that\n * ships today should have to move.\n *\n * It is separate from the CLI, and pure, because the interesting part is the\n * order and the three refusals, and neither is worth a spawned bin with a\n * browser behind it to test.\n */\nimport { selectCollections, type CollectionConfig } from \"../../shared/collections.js\";\nimport { A11yError } from \"../types.js\";\n\n/**\n * Nothing to check. Also thrown by `runCheck` for a programmatic caller that\n * resolved its own seeds, which is why the text lives here and not there.\n */\nexport const NO_SEEDS_MESSAGE =\n \"No URLs to check. Pass one or more, set url: on a collection, or set a11y.urls in manni.config.yaml.\";\n\n/** The family file's name, for a message about a config that was never found. */\nconst CONFIG_NAME = \"manni.config.yaml\";\n\nexport interface SeedSources {\n /** Positional `[urls...]`, as typed. Validated and normalized by `runCheck`. */\n urls: readonly string[];\n /** `--collection` names, one per occurrence. Empty means none were named. */\n collections: readonly string[];\n /** `a11y.urls`, when the key is set. An empty list counts as unset. */\n configUrls?: readonly string[];\n /** Every collection the family file declares, in declaration order. */\n declared: readonly CollectionConfig[];\n /**\n * The config file as the user would name it, for the unknown-name message.\n * `null` or absent (no file found) names the canonical family file, since\n * that is where the missing `collections:` would go.\n */\n source?: string | null;\n}\n\n/**\n * The seeds a run checks, or an `A11yError` explaining why there are none.\n *\n * 1. `urls` when non-empty.\n * 2. The `url` of each collection named by `collections`, in **declaration**\n * order, repeats and shared urls collapsed. A named collection with no\n * `url` is an error, and so is a name that is not declared.\n * 3. `configUrls` when non-empty, exactly as configured.\n * 4. The `url` of every declared collection that has one, in declaration\n * order, shared urls collapsed. One without a `url` contributes nothing.\n *\n * Naming a url-less collection fails where leaving it out of the default set\n * does not: `--collection blog` asked for something specific and has to be\n * told it cannot be done, while a bare `manni a11y check` gets whatever is\n * publishable.\n */\nexport function resolveSeeds(sources: SeedSources): string[] {\n const { urls, collections: names, declared } = sources;\n\n if (names.length > 0) {\n // The shape of the invocation, before anything about the config: a run\n // that named both a collection and a URL has no reading to pick between.\n if (urls.length > 0) {\n throw new A11yError(\n \"--collection selects a configured collection; it cannot be combined with URLs.\",\n );\n }\n // No config at all — nothing was found, or `--no-config` refused it. The\n // flag selects from a config file, so say that rather than reporting the\n // name as unknown: \"Configured: (none).\" blames the name for the absence\n // of the file. `manni meta` refuses the same combination with the same\n // sentence, which is the parity CLAUDE.md asks for on a shared flag. A\n // real config always carries a source, so this cannot mistake a\n // programmatic caller that passed collections without one.\n if (sources.source == null && declared.length === 0) {\n throw new A11yError(\"--collection needs a config file to select from.\");\n }\n const selected = selectCollections(\n declared,\n names,\n sources.source ?? CONFIG_NAME,\n (message) => new A11yError(message),\n );\n const seeds: string[] = [];\n for (const collection of selected) {\n if (collection.url === undefined) {\n throw new A11yError(`collection \"${collection.name}\" has no url: to check.`);\n }\n seeds.push(collection.url);\n }\n return unique(seeds);\n }\n\n if (urls.length > 0) return [...urls];\n\n const configUrls = sources.configUrls ?? [];\n if (configUrls.length > 0) return [...configUrls];\n\n const published = unique(\n declared.flatMap((collection) => (collection.url === undefined ? [] : [collection.url])),\n );\n if (published.length > 0) return published;\n\n throw new A11yError(NO_SEEDS_MESSAGE);\n}\n\nfunction unique(values: readonly string[]): string[] {\n return [...new Set(values)];\n}\n","/**\n * Sitemap discovery: the page list a site publishes for itself.\n *\n * A sitemap reaches pages no link points at, so the crawl reads it first and\n * follows links second. Nothing here is allowed to fail the run: a site with\n * no sitemap, a broken one, or one behind a firewall is a site to crawl by\n * links alone, and the outcome says so with `source: null`.\n */\nimport { DOMParser } from \"@xmldom/xmldom\";\nimport { isHttpUrl, isPageLink, normalizeUrl, sameHost } from \"./url.js\";\n\n/** `fetch` narrowed to what this module needs, so tests inject a fake. */\nexport type Fetcher = (\n url: string,\n) => Promise<{ ok: boolean; status: number; text(): Promise<string> }>;\n\nexport interface SitemapDiscovery {\n /** The sitemap (or sitemap index) URL that was read, `null` when none was usable. */\n source: string | null;\n /** Same-host page URLs from every `<loc>`, normalized and deduped, in document order. */\n urls: string[];\n}\n\nexport interface ParsedSitemap {\n kind: \"index\" | \"urlset\";\n locs: string[];\n}\n\n/** How many levels of `<sitemapindex>` nesting are followed below the first. */\nconst MAX_INDEX_DEPTH = 3;\n/** How many child sitemaps one discovery reads, across every index it meets. */\nconst MAX_CHILD_SITEMAPS = 50;\n/** A robots.txt or sitemap that has not answered in this long is \"no sitemap\". */\nconst FETCH_TIMEOUT_MS = 10_000;\n\nconst defaultFetcher: Fetcher = (url) =>\n fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n\n/**\n * The file names tried in each directory of the seed's path, in this order.\n * `sitemap.xml` is the convention; `sitemap-index.xml` is what Astro (and so\n * Starlight) emits; `sitemap_index.xml` is Yoast's and Hugo's spelling.\n */\nconst WELL_KNOWN_SITEMAP_FILES = [\"sitemap.xml\", \"sitemap-index.xml\", \"sitemap_index.xml\"];\n\n/**\n * Candidates, in order:\n * 1. GET `<origin>/robots.txt`; every `Sitemap:` line (case-insensitive key,\n * absolute URL) is a candidate, in order.\n * 2. Then, for each directory of the seed's path from the seed's own\n * directory up to `/`, nearest first (`https://h/manni/meta/fix/` walks\n * `/manni/meta/fix/`, `/manni/meta/`, `/manni/`, `/`; a seed that names a\n * file, `https://h/manni/page.html`, starts at `/manni/`), the files\n * `sitemap.xml`, `sitemap-index.xml`, `sitemap_index.xml`, in that order\n * within each directory. A project site under a path prefix (GitHub Pages)\n * cannot write to the origin's `/robots.txt` or `/sitemap.xml`, which is\n * why the walk starts at the seed and not at the root.\n * Candidates are deduped, keeping the first position of each.\n *\n * Then parse the first candidate that returns 2xx with `@xmldom/xmldom`\n * (`DOMParser`, errors swallowed); a 2xx body that is not a sitemap is skipped\n * and the next candidate tried. A `<sitemapindex>` recurses into each child\n * `<sitemap><loc>` (depth ≤ 3, ≤ 50 child sitemaps). A `<urlset>` yields its\n * `<url><loc>` values. Keep only `sameHost(seed, loc) && isPageLink(loc)`.\n * `source` is the candidate that was actually used.\n *\n * A network error, non-2xx, or unparseable body means \"no sitemap here\" —\n * never an error, and never a page failure. `.xml.gz` bodies are not\n * decompressed (deferred).\n */\nexport async function discoverSitemap(\n seed: string,\n fetcher: Fetcher = defaultFetcher,\n): Promise<SitemapDiscovery> {\n const origin = new URL(seed).origin;\n const candidates = await robotsSitemaps(`${origin}/robots.txt`, fetcher);\n for (const candidate of wellKnownCandidates(seed)) {\n if (!candidates.includes(candidate)) candidates.push(candidate);\n }\n\n for (const candidate of candidates) {\n const parsed = await fetchSitemap(candidate, fetcher);\n if (parsed === null) continue;\n const walk: Walk = { fetcher, seen: new Set([candidate]), childBudget: MAX_CHILD_SITEMAPS };\n const locs = await expand(parsed, 0, walk);\n return { source: candidate, urls: pageUrls(seed, locs) };\n }\n return { source: null, urls: [] };\n}\n\n/** Pure parser, exported for tests: returns `{ kind: \"index\" | \"urlset\", locs: string[] }` or `null`. */\nexport function parseSitemapXml(text: string): ParsedSitemap | null {\n if (text.trim() === \"\") return null;\n let root: XmlNode | null;\n try {\n // Every parse problem is routed to `onError` and ignored; what matters is\n // whether a sitemap root came out the other side.\n const doc = new DOMParser({ onError: () => undefined }).parseFromString(text, \"text/xml\");\n root = doc.documentElement;\n } catch {\n return null;\n }\n if (root === null) return null;\n const kind = root.localName;\n if (kind !== \"sitemapindex\" && kind !== \"urlset\") return null;\n const entry = kind === \"sitemapindex\" ? \"sitemap\" : \"url\";\n const locs: string[] = [];\n for (const child of childElements(root, entry)) {\n for (const loc of childElements(child, \"loc\")) {\n const value = (loc.textContent ?? \"\").trim();\n if (value !== \"\") locs.push(value);\n }\n }\n return { kind: kind === \"sitemapindex\" ? \"index\" : \"urlset\", locs };\n}\n\ntype XmlDocument = ReturnType<DOMParser[\"parseFromString\"]>;\n/**\n * xmldom's `Node`, reached through the parser's own types rather than an\n * import so the alias tracks whatever the installed version declares. It is\n * enough here: `localName`, `textContent` and the sibling walk are all on\n * `Node`, and `documentElement` narrows to it.\n */\ntype XmlNode = NonNullable<XmlDocument[\"firstChild\"]>;\n\n/** Element children of `node` whose local name is `name`, in document order. */\nfunction childElements(node: XmlNode, name: string): XmlNode[] {\n const out: XmlNode[] = [];\n for (let n = node.firstChild; n !== null; n = n.nextSibling) {\n if (n.nodeType === 1 && n.localName === name) out.push(n);\n }\n return out;\n}\n\ninterface Walk {\n fetcher: Fetcher;\n /** Sitemap URLs already read, so an index that lists itself terminates. */\n seen: Set<string>;\n /** Child sitemaps still allowed; shared across the whole recursion. */\n childBudget: number;\n}\n\nasync function expand(parsed: ParsedSitemap, depth: number, walk: Walk): Promise<string[]> {\n if (parsed.kind === \"urlset\") return parsed.locs;\n if (depth >= MAX_INDEX_DEPTH) return [];\n const out: string[] = [];\n for (const child of parsed.locs) {\n if (walk.childBudget <= 0) break;\n if (!isHttpUrl(child) || walk.seen.has(child)) continue;\n walk.seen.add(child);\n walk.childBudget -= 1;\n const nested = await fetchSitemap(child, walk.fetcher);\n if (nested === null) continue;\n out.push(...(await expand(nested, depth + 1, walk)));\n }\n return out;\n}\n\n/**\n * The well-known sitemap file names in every directory of the seed's path,\n * nearest directory first, root last. Query and fragment are dropped; the\n * directory of `/manni/page.html` is `/manni/`, of `/manni/` is itself.\n */\nfunction wellKnownCandidates(seed: string): string[] {\n const url = new URL(seed);\n const directories = ancestorDirectories(url.pathname);\n return directories.flatMap((dir) =>\n WELL_KNOWN_SITEMAP_FILES.map((file) => `${url.origin}${dir}${file}`),\n );\n}\n\n/**\n * `/manni/meta/fix/` → `[\"/manni/meta/fix/\", \"/manni/meta/\", \"/manni/\", \"/\"]`;\n * `/manni/page.html` → `[\"/manni/\", \"/\"]`; `/` → `[\"/\"]`.\n */\nfunction ancestorDirectories(pathname: string): string[] {\n let dir = pathname.slice(0, pathname.lastIndexOf(\"/\") + 1);\n const out: string[] = [];\n for (;;) {\n out.push(dir);\n if (dir === \"/\") return out;\n // Drop the trailing slash, then everything after the previous one.\n const parent = dir.slice(0, dir.lastIndexOf(\"/\", dir.length - 2) + 1);\n dir = parent === \"\" ? \"/\" : parent;\n }\n}\n\n/** The `Sitemap:` candidates from a robots.txt, or none when it is missing. */\nasync function robotsSitemaps(url: string, fetcher: Fetcher): Promise<string[]> {\n const text = await fetchText(url, fetcher);\n if (text === null) return [];\n const out: string[] = [];\n for (const line of text.split(/\\r?\\n/)) {\n const match = /^\\s*sitemap\\s*:\\s*(\\S+)/i.exec(line);\n const candidate = match?.[1];\n if (candidate !== undefined && isHttpUrl(candidate) && !out.includes(candidate)) {\n out.push(candidate);\n }\n }\n return out;\n}\n\nasync function fetchSitemap(url: string, fetcher: Fetcher): Promise<ParsedSitemap | null> {\n const text = await fetchText(url, fetcher);\n return text === null ? null : parseSitemapXml(text);\n}\n\n/** The body of a 2xx response, or `null` for anything else, thrown included. */\nasync function fetchText(url: string, fetcher: Fetcher): Promise<string | null> {\n try {\n const response = await fetcher(url);\n if (!response.ok) return null;\n return await response.text();\n } catch {\n return null;\n }\n}\n\n/** Filter, normalize and dedupe the `<loc>` values into crawlable page URLs. */\nfunction pageUrls(seed: string, locs: string[]): string[] {\n const out: string[] = [];\n const seen = new Set<string>();\n for (const loc of locs) {\n if (!isHttpUrl(loc) || !sameHost(seed, loc) || !isPageLink(loc)) continue;\n const url = normalizeUrl(loc);\n if (seen.has(url)) continue;\n seen.add(url);\n out.push(url);\n }\n return out;\n}\n","/**\n * `manni a11y check`, the command core.\n *\n * Validates the seeds, finds the sitemap, runs the crawl, drops the findings\n * below the severity floor, scores each page and totals the summary. No CLI\n * and no IO of its own beyond the injected analyzer and fetcher, so it can be\n * tested end to end with neither a browser nor a network.\n */\nimport type { PageAnalyzer } from \"../core/analyzer.js\";\nimport { crawl, type CrawlOutcome } from \"../core/crawl.js\";\nimport { createExcludeFilter, type ExcludeGlob } from \"../core/exclude.js\";\nimport { NO_SEEDS_MESSAGE } from \"../core/seeds.js\";\nimport { discoverSitemap, type Fetcher, type SitemapDiscovery } from \"../core/sitemap.js\";\nimport { isHttpUrl, normalizeUrl } from \"../core/url.js\";\nimport {\n A11yError,\n meetsSeverity,\n type CheckRun,\n type CheckSummary,\n type Severity,\n type PageResult,\n type ProgressListener,\n} from \"../types.js\";\n\nexport interface CheckOptions {\n /** Seeds as typed (validated and normalized here). */\n urls: string[];\n /** Follow the sitemap and same-host links. Default `true`. */\n crawl: boolean;\n /** Stop after this many pages. Absent means no cap: every discovered page is checked. */\n maxPages?: number;\n /** axe tags to restrict to; empty is axe's default rule set. Default `[]`. */\n tags: string[];\n /** Minimum family severity reported and counted. Default `\"notice\"`, everything. */\n severity: Severity;\n /** Per-page navigation timeout in ms. Default `30000`. */\n timeout: number;\n /**\n * Globs matched against a URL's path; a match keeps the page out of the\n * crawl. Default `[]`, which excludes nothing. A pattern that excludes a\n * seed is an error, since the seed and the pattern are both the caller's\n * statement and a contradiction is not this command's to resolve. Each\n * pattern carries the name the refusal gives it, so the message points at\n * the flag or the config key the pattern actually came from.\n */\n exclude: ExcludeGlob[];\n}\n\nexport interface CheckDeps {\n analyzer: PageAnalyzer;\n /** Defaults to global `fetch`. */\n fetcher?: Fetcher;\n /**\n * Told about each step as it happens: `sitemap` once discovery is done\n * (only when crawling), then everything the crawl reports. Absent means\n * silent.\n */\n onProgress?: ProgressListener;\n}\n\n/**\n * `maxPages` is deliberately absent: the default is no cap. A capped crawl\n * reports a partial site as checked, so the cap is opt-in, through\n * `--max-pages` or the config key.\n */\nexport const CHECK_DEFAULTS: Readonly<Omit<CheckOptions, \"urls\">> = Object.freeze({\n crawl: true,\n tags: [],\n severity: \"notice\",\n timeout: 30000,\n exclude: [],\n});\n\n/**\n * 1. `urls.length === 0` → A11yError(NO_SEEDS_MESSAGE). The CLI resolves its\n * seeds with `resolveSeeds` and never arrives here empty; a programmatic\n * caller that passed none hears the same thing.\n * 2. Any non-http(s) url → A11yError(`Not an http(s) URL: \"<url>\".`)\n * 3. Any seed an `exclude` pattern matches → A11yError naming **every** such\n * seed, one per line, each under the pattern's own `source`. A user who\n * typed two wrong patterns should not need one run per fix, and nothing is\n * checked either way.\n * 4. When `crawl`: `discoverSitemap(firstSeed)` (one sitemap per run, the first seed's origin).\n * 5. `crawl(...)`, then per page: drop violations below `severity`, compute `score`.\n * 6. Build `CheckSummary`. Always awaits `analyzer.close()` in `finally`.\n */\nexport async function runCheck(opts: CheckOptions, deps: CheckDeps): Promise<CheckRun> {\n const { analyzer } = deps;\n try {\n if (opts.urls.length === 0) {\n throw new A11yError(NO_SEEDS_MESSAGE);\n }\n for (const url of opts.urls) {\n if (!isHttpUrl(url)) throw new A11yError(`Not an http(s) URL: \"${url}\".`);\n }\n const seeds = opts.urls.map(normalizeUrl);\n\n const exclude = createExcludeFilter(opts.exclude);\n const contradictions = seeds\n .map((seed) => {\n const pattern = exclude.match(seed);\n return pattern === null ? null : `${pattern.source} excludes the seed ${seed}.`;\n })\n .filter((line): line is string => line !== null);\n if (contradictions.length > 0) throw new A11yError(contradictions.join(\"\\n\"));\n\n let sitemap: SitemapDiscovery = { source: null, urls: [] };\n const first = seeds[0];\n if (opts.crawl && first !== undefined) {\n sitemap = await discoverSitemap(first, deps.fetcher);\n deps.onProgress?.({ kind: \"sitemap\", source: sitemap.source, urls: sitemap.urls.length });\n }\n\n const outcome = await crawl(\n {\n seeds,\n crawl: opts.crawl,\n maxPages: opts.maxPages,\n extra: sitemap.urls,\n exclude,\n analyze: { tags: opts.tags, timeout: opts.timeout },\n onProgress: deps.onProgress,\n },\n analyzer,\n );\n\n const results = outcome.pages.map((page) => finishPage(page, opts.severity));\n return {\n results,\n redirects: outcome.redirects,\n summary: summarize(results, outcome, sitemap, opts.crawl),\n };\n } finally {\n await analyzer.close();\n }\n}\n\n/** Apply the severity floor, then score what is left. */\nfunction finishPage(page: Omit<PageResult, \"score\">, floor: Severity): PageResult {\n if (page.error !== undefined) return { ...page, violations: [], score: null };\n const violations = page.violations.filter((v) => meetsSeverity(v.severity, floor));\n const applicable = page.passes + violations.length;\n const score = applicable === 0 ? null : Math.round((100 * page.passes) / applicable);\n return { ...page, violations, score };\n}\n\nfunction summarize(\n results: PageResult[],\n { discovered, skipped, duplicates, redirects, excluded }: CrawlOutcome,\n sitemap: SitemapDiscovery,\n crawl: boolean,\n): CheckSummary {\n // Spelled out so the compiler, not a test, says when the family scale moves.\n const bySeverity: Record<Severity, number> = { notice: 0, warning: 0, error: 0 };\n let failed = 0;\n let violations = 0;\n for (const page of results) {\n if (page.error !== undefined || page.violations.length > 0) failed += 1;\n for (const violation of page.violations) {\n violations += 1;\n bySeverity[violation.severity] += 1;\n }\n }\n return {\n discovered,\n checked: results.length,\n skipped,\n duplicates,\n redirects: redirects.length,\n excluded,\n failed,\n violations,\n bySeverity,\n sitemap: sitemap.source,\n // The count the progress line already reported as `(N pages)`, so the\n // report cannot disagree with the narration that preceded it.\n sitemapPages: sitemap.urls.length,\n crawl,\n };\n}\n","/**\n * The browser seam.\n *\n * Everything that needs a real page — navigation, the live DOM's links, axe\n * itself — sits behind `PageAnalyzer`, so the crawl and the check core can be\n * exercised with a canned analyzer and no browser. The Playwright-backed\n * implementation lives here too, behind the same interface.\n */\nimport { AxeBuilder } from \"@axe-core/playwright\";\nimport { chromium, type Browser, type Page, type Request, type Response } from \"playwright-core\";\nimport {\n A11yError,\n isAxeImpact,\n type AxeImpact,\n type PageResult,\n type Severity,\n type Violation,\n type ViolationNode,\n} from \"../types.js\";\nimport { dedupeKey } from \"./url.js\";\n\nexport interface AnalyzeOptions {\n /** axe tags to restrict to; empty = axe defaults. */\n tags: string[];\n /** Navigation timeout in ms. */\n timeout: number;\n}\n\nexport interface AnalyzedPage {\n /** Raw result: every violation regardless of severity; `source` and `score` are filled in by `runCheck`. */\n result: Omit<PageResult, \"source\" | \"score\">;\n /** Absolute `href` of every `a[href]` in the live DOM after load, unfiltered. */\n links: string[];\n /**\n * The browser's URL once navigation and any redirects settled. The crawl\n * marks it visited so a later queued spelling of the same page is not\n * loaded again. Absent when the analyzer does not know it.\n */\n finalUrl?: string;\n}\n\n/**\n * A page that sent the browser elsewhere once it had loaded: a meta refresh\n * to another page, or a navigation while links or axe were being read. It was\n * not analyzed. Tell it from `AnalyzedPage` with `\"redirect\" in x`.\n */\nexport interface RedirectedPage {\n /** The absolute URL the page redirects to. */\n redirect: string;\n}\n\nexport interface PageAnalyzer {\n /**\n * Load `url` and run axe, or report where the page redirects in the\n * browser. Rejects with `A11yError` on navigation failure or timeout\n * (message names the URL and the underlying reason); the caller decides\n * whether that is fatal (seed) or a per-page `error` (crawled page).\n */\n analyze(url: string, opts: AnalyzeOptions): Promise<AnalyzedPage | RedirectedPage>;\n /** Close the browser. Safe to call when nothing was launched, and twice. */\n close(): Promise<void>;\n}\n\nexport type BrowserChannel = \"chrome\" | \"msedge\" | \"chromium\";\n\n/** The message when nothing launches; the same words the CLI's ladder promises. */\nexport const NO_BROWSER_MESSAGE =\n \"No browser found. Install one with `npx playwright install chromium`, or install Google Chrome or Microsoft Edge.\";\n\n/** The launch order: what the machine already has first, Playwright's own download last. */\nconst CHANNELS: readonly BrowserChannel[] = [\"chrome\", \"msedge\", \"chromium\"];\n\nfunction launch(channel: BrowserChannel): Promise<Browser> {\n return channel === \"chromium\"\n ? chromium.launch({ headless: true })\n : chromium.launch({ channel, headless: true });\n}\n\n/** The first channel that launches, still open, or `null` when none does. */\nasync function launchAny(): Promise<{ browser: Browser; channel: BrowserChannel } | null> {\n for (const channel of CHANNELS) {\n try {\n return { browser: await launch(channel), channel };\n } catch {\n // Not installed, or not launchable here. Try the next one.\n }\n }\n return null;\n}\n\n/**\n * Try, in order: `chromium.launch({ channel: \"chrome\", headless: true })`,\n * `{ channel: \"msedge\" }`, `chromium.launch()` (Playwright's own download).\n * Returns the first that launches, closed again, or `null`. Exported so the\n * integration suite can `describe.skipIf`.\n */\nexport async function findBrowser(): Promise<BrowserChannel | null> {\n const found = await launchAny();\n if (found === null) return null;\n await found.browser.close();\n return found.channel;\n}\n\n/** axe's result shapes, as `@axe-core/playwright` declares them; no direct axe-core import. */\ntype AxeResults = Awaited<ReturnType<AxeBuilder[\"analyze\"]>>;\ntype AxeResult = AxeResults[\"violations\"][number];\ntype AxeNode = AxeResult[\"nodes\"][number];\n\ninterface Session {\n browser: Browser;\n page: Page;\n}\n\n/**\n * Playwright-backed analyzer. Lazy: the browser launches on the first\n * `analyze`, one context and one page are reused for every URL.\n * - `page.goto(url, { waitUntil: \"load\", timeout })`; `finalUrl` is `page.url()` after it\n * - one in-page evaluation reads every `a[href]`'s absolute `href` and the\n * first meta refresh; a refresh to another page (by `dedupeKey`) is a\n * redirect, returned before axe runs\n * - a read or axe that rejects because the page navigated: wait up to\n * `timeout` for the URL to change and return the redirect, else rethrow\n * - `new AxeBuilder({ page })`, `.withTags(tags)` only when `tags.length > 0`, `.analyze()`\n * - map axe `Result` → `Violation` (`severity` from `severityOf(impact)`, `impact` kept as\n * axe's word with `null`/`undefined` → \"minor\"; node `target` joined with \" \";\n * `failureSummary ?? \"\"`), `passes.length`, `incomplete.length`\n * - launch failure on every channel → `A11yError(NO_BROWSER_MESSAGE)`\n */\nexport function createPlaywrightAnalyzer(): PageAnalyzer {\n let session: Promise<Session> | null = null;\n\n const open = (): Promise<Session> => {\n session ??= (async () => {\n const found = await launchAny();\n if (found === null) throw new A11yError(NO_BROWSER_MESSAGE);\n const context = await found.browser.newContext();\n const page = await context.newPage();\n return { browser: found.browser, page };\n })();\n return session;\n };\n\n return {\n async analyze(url, opts) {\n const { page } = await open();\n // Every navigation the main frame starts, first hop only, so the one\n // that follows the load can be named even when it never commits (an\n // unresolvable host leaves the browser on its own error page).\n const navigations: Request[] = [];\n const onRequest = (request: Request): void => {\n if (\n request.isNavigationRequest() &&\n request.frame() === page.mainFrame() &&\n request.redirectedFrom() === null\n ) {\n navigations.push(request);\n }\n };\n page.on(\"request\", onRequest);\n try {\n return await analyzePage(page, url, opts, navigations);\n } finally {\n page.off(\"request\", onRequest);\n }\n },\n\n async close() {\n if (session === null) return;\n const pending = session;\n session = null;\n try {\n const { browser } = await pending;\n await browser.close();\n } catch {\n // The launch itself failed: there is nothing to close.\n }\n },\n };\n}\n\n/**\n * One `analyze`, on the session's page. `navigations` is filled while it\n * runs: the first hop of every main-frame navigation, in order.\n */\nasync function analyzePage(\n page: Page,\n url: string,\n opts: AnalyzeOptions,\n navigations: readonly Request[],\n): Promise<AnalyzedPage | RedirectedPage> {\n let response: Response | null;\n try {\n response = await page.goto(url, { waitUntil: \"load\", timeout: opts.timeout });\n } catch (err) {\n throw new A11yError(`Could not load ${url}: ${reason(err)}`);\n }\n // Where the load settled, HTTP redirects included. The browser being\n // anywhere else later means the page navigated on its own.\n const loaded = response?.url() ?? page.url();\n\n /**\n * The first navigation the main frame started after the load's own, or\n * `undefined` when it started none. The load's own is found by walking its\n * HTTP redirect hops back to the first request. When `goto` gave no\n * response (a service worker answered it), the listener was attached just\n * before `goto`, so its navigation is the first one recorded.\n */\n const nextNavigation = (): Request | undefined => {\n let first = response?.request() ?? null;\n for (let from = first?.redirectedFrom() ?? null; from !== null; from = from.redirectedFrom()) {\n first = from;\n }\n // No response means a service worker answered `goto`: its navigation is [0].\n const own = first === null ? 0 : navigations.indexOf(first);\n return own === -1 ? undefined : navigations[own + 1];\n };\n\n /**\n * Where the page sent the browser. The navigation request is named even\n * when it never commits, since an unresolvable host leaves the frame on the\n * browser's own error page. Without one, the frame's URL is the answer:\n * every caller has already seen it move off `loaded`, and Playwright\n * reports the request before the URL changes, so this is a fallback only.\n */\n const destination = (): string => nextNavigation()?.url() ?? page.url();\n\n /**\n * After a read rejected: when the page started a navigation, wait for the\n * main frame to commit it and return the redirect. When it started none,\n * the error was not a navigation and stands at once, rather than after a\n * second wait of `timeout`.\n */\n const navigatedAway = async (): Promise<RedirectedPage | null> => {\n if (nextNavigation() === undefined && samePage(page.url(), loaded)) return null;\n try {\n await page.waitForURL((u) => !samePage(u.href, loaded), {\n waitUntil: \"commit\",\n timeout: opts.timeout,\n });\n return { redirect: destination() };\n } catch {\n return null;\n }\n };\n\n let read: InPage;\n try {\n read = await page.evaluate(readPage);\n } catch (err) {\n const moved = await navigatedAway();\n if (moved !== null) return moved;\n throw new A11yError(`Could not analyze ${url}: ${reason(err)}`);\n }\n const refresh = refreshTarget(read.refresh, page.url());\n if (refresh !== null) return { redirect: refresh };\n\n let builder = new AxeBuilder({ page });\n if (opts.tags.length > 0) builder = builder.withTags(opts.tags);\n let results: AxeResults;\n try {\n results = await builder.analyze();\n } catch (err) {\n const moved = await navigatedAway();\n if (moved !== null) return moved;\n throw new A11yError(`Could not analyze ${url}: ${reason(err)}`);\n }\n // The page can navigate between two reads without either rejecting, and\n // then what was read belongs to the destination, not to `url`. Where it\n // went comes from the recorded request, with the frame's URL as fallback.\n // A script redirect that fires after axe returns is not seen at all: the\n // page was analyzed as it stood, which is what it was when it was read.\n if (!samePage(page.url(), loaded)) return { redirect: destination() };\n return {\n result: {\n url,\n violations: results.violations.map(toViolation),\n passes: results.passes.length,\n incomplete: results.incomplete.length,\n },\n links: read.links,\n finalUrl: page.url(),\n };\n}\n\n/** What one in-page evaluation reads before axe runs. */\ninterface InPage {\n /** Every `a[href]`'s absolute `href`. */\n links: string[];\n /** The first `<meta http-equiv=\"refresh\">`'s `content`, or `null`. */\n refresh: string | null;\n}\n\n/** Runs in the page. The project has no DOM lib, so the DOM is typed as narrowly as it is used. */\nfunction readPage(): InPage {\n const doc = (\n globalThis as unknown as {\n document: {\n querySelectorAll(selector: string): ArrayLike<{ href: string }>;\n querySelector(selector: string): { getAttribute(name: string): string | null } | null;\n };\n }\n ).document;\n return {\n links: Array.from(doc.querySelectorAll(\"a[href]\"), (a) => a.href),\n refresh:\n doc.querySelector('meta[http-equiv=\"refresh\" i]')?.getAttribute(\"content\") ?? null,\n };\n}\n\n/**\n * The URL part of a meta refresh's `content`: `<delay>;url=<url>` or\n * `<delay>, <url>`, `url=` optional and any case, quotes around the URL\n * optional. `null` for a bare delay, which is a reload rather than a redirect.\n */\nexport function refreshUrl(content: string): string | null {\n // The delay may be fractional (\"0.5\"), hence the dot. A malformed delay\n // such as \"...\" also passes, which costs nothing: only the URL is used.\n const match = /^\\s*[\\d.]*\\s*[;,]\\s*(?:url\\s*=\\s*)?(.*)$/is.exec(content);\n let target = match?.[1]?.trim() ?? \"\";\n const quote = target[0];\n if (quote === \"'\" || quote === '\"') {\n const end = target.indexOf(quote, 1);\n target = (end === -1 ? target.slice(1) : target.slice(1, end)).trim();\n }\n return target === \"\" ? null : target;\n}\n\n/**\n * Where a meta refresh sends the browser, resolved against the page, or\n * `null` when there is no refresh, no URL in it, or it points back at the\n * page itself.\n */\nfunction refreshTarget(content: string | null, base: string): string | null {\n if (content === null) return null;\n const target = refreshUrl(content);\n if (target === null) return null;\n let to: string;\n try {\n to = new URL(target, base).href;\n } catch {\n return null;\n }\n return samePage(to, base) ? null : to;\n}\n\n/** One page by `dedupeKey`; a string that is not an http(s) URL compares as itself. */\nfunction samePage(a: string, b: string): boolean {\n try {\n return dedupeKey(a) === dedupeKey(b);\n } catch {\n return a === b;\n }\n}\n\n/** What axe may put in `impact`; the same union `@axe-core/playwright` declares. */\ntype ImpactValue = AxeResult[\"impact\"];\n\n/**\n * axe's impact onto the family severity scale (`src/shared/severity.ts`).\n * Four levels fold onto three: `critical` and `serious` are both `error`,\n * `moderate` is `warning`, `minor` is `notice`. A missing impact, which axe\n * reports as `null` for a rule with no impact set, is the lowest level. The\n * original word is kept on the violation as `impact`, so nothing is lost for\n * anyone looking the rule up where axe names it.\n */\nexport function severityOf(impact: ImpactValue | null | undefined): Severity {\n switch (impact) {\n case \"critical\":\n case \"serious\":\n return \"error\";\n case \"moderate\":\n return \"warning\";\n default:\n return \"notice\";\n }\n}\n\n/** axe's word as it stands, or `minor` when it gave none. */\nfunction impactOf(impact: ImpactValue | null | undefined): AxeImpact {\n return impact != null && isAxeImpact(impact) ? impact : \"minor\";\n}\n\nfunction toViolation(result: AxeResult): Violation {\n return {\n id: result.id,\n severity: severityOf(result.impact),\n impact: impactOf(result.impact),\n help: result.help,\n helpUrl: result.helpUrl,\n tags: result.tags,\n nodes: result.nodes.map(toNode),\n };\n}\n\nfunction toNode(node: AxeNode): ViolationNode {\n return {\n // A shadow-DOM target is a nested list of selectors; flatten it the same way.\n target: node.target.map((t) => (Array.isArray(t) ? t.join(\" \") : t)).join(\" \"),\n html: node.html,\n summary: node.failureSummary ?? \"\",\n };\n}\n\n/**\n * The first line of a Playwright error. The rest is a call log that repeats\n * the URL and the timeout, which the caller's message already carries.\n */\nfunction reason(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err);\n return message.split(\"\\n\")[0]?.trim() ?? message;\n}\n","/**\n * The `a11y:` key of the family config file (`manni.config.yaml`).\n *\n * Finding the file is the shared layer's job (src/shared/config-file.ts);\n * what the section may contain is decided here. The posture is meta's: an\n * unknown key or a wrong type is an error that names the file and the key,\n * because a misspelled `maxPages:` that was silently ignored would run the\n * crawl on defaults and read as a clean pass.\n */\nimport type { CollectionConfig } from \"../../shared/collections.js\";\nimport {\n findConfigFile,\n readConfigFile,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport { A11yError, SEVERITIES, isSeverity, type Severity } from \"../types.js\";\nimport { MUST_START_WITH_SLASH, isUrlPathGlob } from \"./exclude.js\";\nimport { isHttpUrl } from \"./url.js\";\n\nexport interface A11yConfig {\n urls?: string[];\n crawl?: boolean;\n /** Cap on pages checked. Absent means no cap. */\n maxPages?: number;\n tags?: string[];\n severity?: Severity;\n timeout?: number;\n /** Globs matched against a URL's path; a match keeps the page out of the crawl. */\n exclude?: string[];\n}\n\nexport interface LoadedA11yConfig {\n config: A11yConfig;\n /** Where it came from, for messages. `null` when no file was found or `--no-config`. */\n source: string | null;\n /**\n * The family file's top-level `collections:`, passed straight through: a\n * collection's `url` is a seed source (proposal 0041, rule 12), and the\n * declaration belongs to the family rather than to `a11y:`. `[]` when no\n * file was found and when none are declared.\n */\n collections: CollectionConfig[];\n}\n\n/** The tool's key in the family file. */\nconst SECTION = \"a11y\";\n\n/**\n * The keys the section may carry. Adding a key to `A11yConfig` means adding\n * it here too, or a config using it is rejected; that coupling is the point.\n */\nconst CONFIG_KEYS = [\"urls\", \"crawl\", \"maxPages\", \"tags\", \"severity\", \"timeout\", \"exclude\"] as const;\n\nconst CONFIG_FILE: ConfigFileOptions = {\n section: SECTION,\n // The a11y tool never had a pre-family file of its own.\n legacyNames: [],\n toError: (message) => new A11yError(message),\n};\n\n/**\n * Discover (or read `explicitPath`) through the shared family-file loader with\n * `{ section: \"a11y\", legacyNames: [], toError: (m) => new A11yError(m) }`.\n * Unknown keys, wrong types, empty `urls` entries and non-`http(s)` urls are\n * `A11yError`s naming the file and key. `null` config (empty section) is `{}`.\n * The document's `collections:` come back alongside, parsed by the shared\n * loader: the key is the family's, not this section's.\n */\nexport async function loadA11yConfig(\n cwd: string,\n explicitPath?: string,\n): Promise<LoadedA11yConfig> {\n const file =\n explicitPath === undefined\n ? await findConfigFile(cwd, CONFIG_FILE)\n : await readConfigFile(explicitPath, cwd, CONFIG_FILE);\n if (file === null) return { config: {}, source: null, collections: [] };\n return {\n config: parseA11yConfig(file.value, file.source),\n source: file.source,\n collections: file.collections,\n };\n}\n\n/** Pure parser, exported for tests. */\nexport function parseA11yConfig(value: unknown, source: string): A11yConfig {\n if (value == null) return {};\n if (typeof value !== \"object\" || Array.isArray(value)) {\n throw new A11yError(`${source}: \\`${SECTION}:\\` must be a mapping.`);\n }\n const obj = value as Record<string, unknown>;\n for (const key of Object.keys(obj)) {\n if (!(CONFIG_KEYS as readonly string[]).includes(key)) {\n throw new A11yError(\n `${source}: \\`${SECTION}:\\` has unknown key \"${key}\". Supported keys: ${CONFIG_KEYS.join(\", \")}.`,\n );\n }\n }\n\n const config: A11yConfig = {};\n if (obj.urls !== undefined) config.urls = asUrls(obj.urls, source);\n if (obj.crawl !== undefined) config.crawl = asBoolean(obj.crawl, \"crawl\", source);\n if (obj.maxPages !== undefined) {\n config.maxPages = asPositiveInteger(obj.maxPages, \"maxPages\", source);\n }\n if (obj.tags !== undefined) config.tags = asStringList(obj.tags, \"tags\", source);\n if (obj.severity !== undefined) config.severity = asSeverity(obj.severity, source);\n if (obj.timeout !== undefined) {\n config.timeout = asPositiveInteger(obj.timeout, \"timeout\", source);\n }\n if (obj.exclude !== undefined) config.exclude = asExcludes(obj.exclude, source);\n return config;\n}\n\n/**\n * How a message names one entry of `a11y.exclude:`: the file it came from and\n * the entry's position in the list. Both the parse errors below and the\n * excluded-seed refusal in the check core name an entry this way, so a run\n * whose patterns came from config never mentions a flag the user did not type.\n */\nexport function excludeEntryLabel(source: string, index: number): string {\n return `${source}: \"${SECTION}.exclude[${String(index)}]\"`;\n}\n\n/**\n * Each entry has to be able to match a path, which always starts with `/`. A\n * pattern that cannot is a silent near-miss rather than a filter, so it is\n * refused here, naming whichever entry is wrong by its position in the list.\n */\nfunction asExcludes(value: unknown, source: string): string[] {\n const globs = asStringList(value, \"exclude\", source);\n globs.forEach((glob, i) => {\n const at = excludeEntryLabel(source, i);\n // An empty string fails the slash check too, so this is only about which\n // message it gets: \"must be a non-empty string\" names the mistake, where\n // \"must start with /\" would describe a pattern that is not there.\n if (glob === \"\") throw new A11yError(`${at} must be a non-empty string.`);\n if (!isUrlPathGlob(glob)) throw new A11yError(`${at} ${MUST_START_WITH_SLASH}`);\n });\n return globs;\n}\n\nfunction asStringList(value: unknown, field: string, source: string): string[] {\n if (!Array.isArray(value) || !value.every((v) => typeof v === \"string\")) {\n throw new A11yError(`${source}: \"${SECTION}.${field}\" must be a list of strings.`);\n }\n return value;\n}\n\nfunction asUrls(value: unknown, source: string): string[] {\n const urls = asStringList(value, \"urls\", source);\n urls.forEach((url, i) => {\n if (!isHttpUrl(url)) {\n throw new A11yError(\n `${source}: \"${SECTION}.urls[${i}]\" must be an http(s) URL, got \"${url}\".`,\n );\n }\n });\n return urls;\n}\n\nfunction asBoolean(value: unknown, field: string, source: string): boolean {\n if (typeof value !== \"boolean\") {\n throw new A11yError(`${source}: \"${SECTION}.${field}\" must be a boolean.`);\n }\n return value;\n}\n\nfunction asPositiveInteger(value: unknown, field: string, source: string): number {\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 1) {\n throw new A11yError(`${source}: \"${SECTION}.${field}\" must be an integer >= 1.`);\n }\n return value;\n}\n\nfunction asSeverity(value: unknown, source: string): Severity {\n if (typeof value !== \"string\" || !isSeverity(value)) {\n throw new A11yError(\n `${source}: \"${SECTION}.severity\" must be one of ${SEVERITIES.join(\", \")}.`,\n );\n }\n return value;\n}\n","/**\n * `--format github`: one workflow-command annotation per finding.\n *\n * There is no file to anchor to, since the check ran against a URL, so the\n * annotation carries the rule id as its title and names the page in the\n * message. Empty when the run is clean, so a clean CI step logs nothing.\n */\nimport {\n escapeWorkflowCommandMessage,\n escapeWorkflowCommandProperty,\n} from \"../../shared/github.js\";\nimport type { CheckRun, Severity } from \"../types.js\";\n\n/** The three levels a workflow command can carry. */\nexport type AnnotationLevel = \"error\" | \"warning\" | \"notice\";\n\n/**\n * The annotation level for a finding of the given severity.\n *\n * The family scale (`src/shared/severity.ts`) was chosen to match GitHub's,\n * so the map is one-to-one and this is the identity. It stays a function,\n * and stays exported, because it is the seam: the translation from a\n * domain's severity to an output's levels happens here and nowhere else,\n * and a reporter for a sink with another scale (SARIF's `note`) would carry\n * its own. axe's four impacts were folded onto these three by the analyzer\n * (`severityOf`), before any reporter saw the finding. Proposal 0035,\n * stress test 10.\n */\nexport function annotationLevel(severity: Severity): AnnotationLevel {\n return severity;\n}\n\nexport function renderGithub(run: CheckRun): string {\n const lines: string[] = [];\n for (const page of run.results) {\n if (page.error !== undefined) {\n // A page that did not load has no severity to translate. It is the most\n // serious thing a run can hold, so it is always an error.\n lines.push(\n `::error title=a11y/load::${escapeWorkflowCommandMessage(`${page.url}: ${page.error}`)}`,\n );\n continue;\n }\n for (const v of page.violations) {\n const n = v.nodes.length;\n const title = escapeWorkflowCommandProperty(`a11y/${v.id}`);\n const msg = escapeWorkflowCommandMessage(\n `${v.help} — ${n} node${n === 1 ? \"\" : \"s\"} on ${page.url} (${v.helpUrl})`,\n );\n lines.push(`::${annotationLevel(v.severity)} title=${title}::${msg}`);\n }\n }\n return lines.join(\"\\n\");\n}\n","/**\n * `--format json`: the `CheckRun` as it is, pretty-printed. Key order is the\n * order the types declare, so the envelope is stable from run to run.\n */\nimport type { CheckRun } from \"../types.js\";\n\nexport function renderJson(run: CheckRun): string {\n return JSON.stringify(run, null, 2);\n}\n","/**\n * `--format pretty`: the report a person reads in a terminal.\n *\n * One line per page, and under a failing page one line per rule followed by\n * the first three elements that failed it, each with axe's own statement of\n * which condition was not met. That per-element line is the deterministic\n * remediation: which rule, which selector, what to change. After the pages,\n * one `↪` line per page that redirected in the browser, hidden by `--quiet`\n * as a passing page is.\n *\n * Colors carry the meanings meta already gave them: ✓ green, ✗ red, URLs\n * cyan, and severity from dim (notice) through yellow (warning) to red\n * (error).\n *\n * Each violation line leads with the family severity, which is what the\n * floor and the exit code are decided on. axe's own word follows the rule id\n * in parentheses, `(axe: critical)`, so the line can still be matched\n * against the Deque rule page and the axe DevTools report that use it.\n */\nimport { palette, type Colors } from \"../../shared/color.js\";\nimport {\n SEVERITIES,\n type CheckRun,\n type Severity,\n type PageResult,\n type Violation,\n} from \"../types.js\";\nimport type { RenderOptions } from \"./index.js\";\n\n/** How many failing elements are listed under one rule before `(+N more)`. */\nconst MAX_NODES = 3;\n\nexport function renderPretty(run: CheckRun, opts: RenderOptions): string {\n const c = palette(opts.color);\n const { summary } = run;\n const lines: string[] = [];\n\n lines.push(`Checked ${summary.checked} of ${summary.discovered} pages (${where(run, c)})`);\n\n for (const page of run.results) {\n if (page.error !== undefined) {\n lines.push(`${c.red(\"✗\")} ${c.cyan(page.url)} could not load: ${page.error}`);\n continue;\n }\n if (page.violations.length === 0) {\n if (!opts.quiet) lines.push(`${c.green(\"✓\")} ${c.cyan(page.url)} score ${scoreText(page)}`);\n continue;\n }\n lines.push(\n `${c.red(\"✗\")} ${c.cyan(page.url)} score ${scoreText(page)} ${severityCounts(page.violations, c)}`,\n );\n for (const v of page.violations) lines.push(...violationLines(v, c));\n }\n\n if (!opts.quiet) {\n for (const r of run.redirects) {\n lines.push(`${c.dim(\"↪\")} ${c.cyan(r.url)} redirects to ${c.cyan(r.to)}`);\n }\n }\n\n const failed = summary.failed;\n const footer =\n `${summary.violations} violation${summary.violations === 1 ? \"\" : \"s\"} on ${failed} of ${summary.checked} pages` +\n (summary.skipped > 0 ? `; ${summary.skipped} skipped (--max-pages)` : \"\") +\n (summary.duplicates > 0\n ? `; ${summary.duplicates} duplicate${summary.duplicates === 1 ? \"\" : \"s\"} dropped`\n : \"\") +\n (summary.redirects > 0\n ? `; ${summary.redirects} redirect${summary.redirects === 1 ? \"\" : \"s\"}`\n : \"\") +\n (summary.excluded > 0 ? `; ${summary.excluded} excluded` : \"\");\n lines.push(\"\");\n lines.push(failed > 0 ? c.red(footer) : c.green(footer));\n return lines.join(\"\\n\");\n}\n\n/**\n * How the pages were found. `--no-crawl` never looks for a sitemap, so a null\n * `sitemap` alone cannot tell \"no crawl\" from \"crawled, found no sitemap\".\n *\n * A sitemap that was found is not a sitemap that supplied pages. One whose\n * every `<loc>` is on another host parses and yields nothing, which is what a\n * built sitemap does when the built site is served on a local preview. So a\n * named sitemap carries its count whenever links did some of the work, and\n * the run that was wholly a sitemap's says so with the URL alone.\n */\nfunction where(run: CheckRun, c: Colors): string {\n const { summary } = run;\n if (!summary.crawl) return \"no crawl\";\n if (summary.sitemap === null) return \"no sitemap; followed links\";\n const found = `sitemap: ${c.cyan(summary.sitemap)}`;\n const n = summary.sitemapPages;\n if (n === 0) return `${found}, 0 pages; followed links`;\n if (n >= summary.discovered) return found;\n return `${found}, ${n} page${n === 1 ? \"\" : \"s\"}; followed links for the rest`;\n}\n\nfunction scoreText(page: PageResult): string {\n return page.score === null ? \"n/a\" : String(page.score);\n}\n\n/** `2 errors, 1 notice`: most severe first, pluralised, zeros omitted. */\nfunction severityCounts(violations: Violation[], c: Colors): string {\n const counts: Record<Severity, number> = { notice: 0, warning: 0, error: 0 };\n for (const v of violations) counts[v.severity] += 1;\n return [...SEVERITIES]\n .reverse()\n .filter((severity) => counts[severity] > 0)\n .map((severity) => {\n const n = counts[severity];\n return paintSeverity(`${n} ${severity}${n === 1 ? \"\" : \"s\"}`, severity, c);\n })\n .join(\", \");\n}\n\nfunction violationLines(v: Violation, c: Colors): string[] {\n const n = v.nodes.length;\n const lines = [\n ` ${paintSeverity(v.severity, v.severity, c)} ${v.id} ${c.dim(`(axe: ${v.impact})`)} ${n} node${n === 1 ? \"\" : \"s\"} ${v.help} ${c.dim(v.helpUrl)}`,\n ];\n for (const node of v.nodes.slice(0, MAX_NODES)) {\n lines.push(` ${node.target} → ${oneLine(node.summary)}`);\n }\n if (n > MAX_NODES) lines.push(c.dim(` (+${n - MAX_NODES} more)`));\n return lines;\n}\n\n/**\n * axe's failureSummary is a heading line followed by one indented line per\n * unmet condition. On one line: the heading, then the conditions joined by\n * `; `.\n */\nfunction oneLine(summary: string): string {\n const [head, ...rest] = summary\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n if (head === undefined) return \"\";\n return rest.length === 0 ? head : `${head} ${rest.join(\"; \")}`;\n}\n\nfunction paintSeverity(text: string, severity: Severity, c: Colors): string {\n switch (severity) {\n case \"notice\":\n return c.dim(text);\n case \"warning\":\n return c.yellow(text);\n case \"error\":\n return c.red(text);\n }\n}\n","/**\n * The a11y reporters render a `CheckRun` to a string. The command layer writes\n * the result to stdout; diagnostics go to stderr separately.\n */\nimport { A11yError, type CheckRun } from \"../types.js\";\nimport { renderGithub } from \"./github.js\";\nimport { renderJson } from \"./json.js\";\nimport { renderPretty } from \"./pretty.js\";\n\nexport { renderGithub, annotationLevel } from \"./github.js\";\nexport type { AnnotationLevel } from \"./github.js\";\nexport { renderJson } from \"./json.js\";\nexport { renderPretty } from \"./pretty.js\";\n\n/**\n * Every value `--format` accepts, in the order help and error messages list\n * them. Stated once, so the union, the guard, the option text and the error\n * cannot drift apart. SARIF and JUnit are deferred (proposal 0035).\n */\nexport const A11Y_FORMATS = [\"pretty\", \"json\", \"github\"] as const;\nexport type A11yFormat = (typeof A11Y_FORMATS)[number];\n\n/** `\"pretty | json | github\"`, for messages and help text. */\nexport const A11Y_FORMAT_LIST: string = A11Y_FORMATS.join(\" | \");\n\nexport function isA11yFormat(value: string): value is A11yFormat {\n return (A11Y_FORMATS as readonly string[]).includes(value);\n}\n\nexport interface RenderOptions {\n /** From shared `shouldColor`. */\n color: boolean;\n /** pretty only: hide pages with no remaining violations. */\n quiet: boolean;\n}\n\n/** Returns the full text without a trailing newline; `github` returns \"\" when clean. */\nexport function render(format: A11yFormat, run: CheckRun, opts: RenderOptions): string {\n switch (format) {\n case \"pretty\":\n return renderPretty(run, opts);\n case \"json\":\n return renderJson(run);\n case \"github\":\n return renderGithub(run);\n default: {\n // Exhaustive: a format added to `A11Y_FORMATS` without a case here is a\n // compile error; the throw is for a caller who bypassed the guard.\n const unreachable: never = format;\n throw new A11yError(\n `Unknown report format ${JSON.stringify(unreachable)}. Use ${A11Y_FORMAT_LIST}.`,\n );\n }\n }\n}\n","/**\n * Progress on stderr, while the crawl runs.\n *\n * The browser launch alone takes seconds and a fifty-page site takes a\n * minute, and a command that says nothing for that long reads as hung. So\n * the run narrates itself on stderr, where a diagnostic belongs; stdout stays\n * the report, and `-f json | jq` keeps working.\n *\n * Two renderings. On a terminal, one status line rewritten in place\n * (`\\r`, erase line, then the text, no newline) and cleared on `done`, so the\n * report on stdout is not preceded by a dangling line. Off a terminal, one\n * plain line per event, newline-terminated and prefixed the way `warn()`\n * writes, with no escape codes, since a CI log keeps every line.\n *\n * Colours keep the meanings meta gave them: ✓ green, ✗ red, URLs cyan, the\n * counter dim. They apply on a terminal only.\n */\nimport { palette, type Colors } from \"../../shared/color.js\";\nimport { programName } from \"../../shared/program-name.js\";\nimport type { ProgressEvent, ProgressListener } from \"../types.js\";\n\nexport interface ProgressOptions {\n /** Where to write: `process.stderr`, or a fake in tests. */\n stream: { write(s: string): boolean; isTTY?: boolean; columns?: number };\n /** Paint the status line. Ignored off a terminal. */\n color: boolean;\n /** Rewrite one line in place (true) or append a line per event (false). */\n tty: boolean;\n}\n\n/** Carriage return, then erase the whole line: the start of every status line. */\nexport const CLEAR_LINE = \"\\r\\x1b[2K\";\n\n/** The width a status line is fitted to when the stream does not say. */\nconst DEFAULT_COLUMNS = 80;\n\n/** Returns a listener that renders events to `stream`. */\nexport function createProgressReporter(opts: ProgressOptions): ProgressListener {\n return opts.tty ? terminalReporter(opts) : plainReporter(opts.stream);\n}\n\nfunction plural(n: number, noun: string): string {\n return `${n} ${noun}${n === 1 ? \"\" : \"s\"}`;\n}\n\n/** `[3/51]`, from the last `page` event; `checked` carries no `queued` of its own. */\nfunction counter(index: number, queued: number): string {\n return `[${index}/${queued}]`;\n}\n\nfunction terminalReporter(opts: ProgressOptions): ProgressListener {\n const { stream } = opts;\n const c = palette(opts.color);\n let queued = 0;\n\n const show = (text: string): void => {\n stream.write(`${CLEAR_LINE}${text}`);\n };\n /** `prefix`, the URL, then `suffix`; the URL shortened in the middle to fit the line. */\n const showUrl = (prefix: string, url: string, suffix = \"\"): void => {\n const columns = stream.columns ?? DEFAULT_COLUMNS;\n const fitted = truncateMiddle(url, columns - visibleLength(prefix) - suffix.length);\n show(`${prefix}${c.cyan(fitted)}${suffix}`);\n };\n\n return (event: ProgressEvent): void => {\n switch (event.kind) {\n case \"browser\":\n show(\"Starting browser…\");\n return;\n case \"sitemap\":\n if (event.source === null) show(\"No sitemap; following links\");\n else showUrl(\"Sitemap: \", event.source, ` (${plural(event.urls, \"page\")})`);\n return;\n case \"excluded\":\n show(`Excluded ${plural(event.urls, \"page\")} (${plural(event.patterns, \"pattern\")})`);\n return;\n case \"page\":\n queued = event.queued;\n showUrl(`${c.dim(counter(event.index, queued))} `, event.url);\n return;\n case \"checked\":\n showUrl(`${c.dim(counter(event.index, queued))} ${outcome(event, c)}`, event.url);\n return;\n case \"redirected\":\n showUrl(`${c.dim(counter(event.index, queued))} ${c.dim(\"↪\")} redirects to `, event.to);\n return;\n case \"done\":\n stream.write(CLEAR_LINE);\n return;\n }\n };\n}\n\n/** `✓ `, `✗ 2 violations `, or `✗ could not load: … `: what goes between the counter and the URL. */\nfunction outcome(event: Extract<ProgressEvent, { kind: \"checked\" }>, c: Colors): string {\n if (event.error !== undefined) return `${c.red(\"✗\")} could not load: ${event.error} `;\n if (event.violations === 0) return `${c.green(\"✓\")} `;\n return `${c.red(\"✗\")} ${plural(event.violations, \"violation\")} `;\n}\n\nfunction plainReporter(stream: ProgressOptions[\"stream\"]): ProgressListener {\n let queued = 0;\n const say = (text: string): void => {\n stream.write(`${programName()}: ${text}\\n`);\n };\n\n return (event: ProgressEvent): void => {\n switch (event.kind) {\n case \"browser\":\n say(\"starting browser\");\n return;\n case \"sitemap\":\n if (event.source === null) say(\"no sitemap; following links\");\n else say(`sitemap ${event.source} (${plural(event.urls, \"page\")})`);\n return;\n case \"excluded\":\n say(`excluded ${plural(event.urls, \"page\")} (${plural(event.patterns, \"pattern\")})`);\n return;\n case \"page\":\n queued = event.queued;\n say(`${counter(event.index, queued)} ${event.url}`);\n return;\n case \"checked\": {\n const head = counter(event.index, queued);\n if (event.error !== undefined) say(`${head} could not load: ${event.error}`);\n else if (event.violations === 0) say(`${head} ✓`);\n else say(`${head} ✗ ${plural(event.violations, \"violation\")}`);\n return;\n }\n case \"redirected\":\n say(`${counter(event.index, queued)} ↪ redirects to ${event.to}`);\n return;\n case \"done\":\n say(`checked ${plural(event.checked, \"page\")}, ${event.skipped} skipped`);\n return;\n }\n };\n}\n\n/** Length as the terminal shows it, with ANSI sequences taken out. */\nfunction visibleLength(text: string): number {\n return text.replace(/\\x1b\\[[0-9;]*m/g, \"\").length;\n}\n\n/**\n * Shorten `text` to `room` characters by replacing its middle with `…`, so\n * both the host and the page's own name survive. Never shorter than a few\n * characters, however narrow the terminal.\n */\nfunction truncateMiddle(text: string, room: number): string {\n const max = Math.max(room, 8);\n if (text.length <= max) return text;\n const head = Math.ceil((max - 1) / 2);\n const tail = max - 1 - head;\n return `${text.slice(0, head)}…${text.slice(text.length - tail)}`;\n}\n","/**\n * The `cite` domain's commander program. Mounted by `src/cli.ts` under\n * `manni cite`; no entry point of its own. Grammar per proposal 0034: verbs are\n * `check`, `add`, `update`, `remove`; there is no default subcommand.\n *\n * Follows clig.dev as meta's does: primary output to stdout, diagnostics to\n * stderr, colour only on a TTY and never under `NO_COLOR`/`--no-color`, exit\n * `0` clean, `1` an error-severity finding, `2` operational/usage.\n */\nimport { Command, Option } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport {\n collect,\n configOption,\n explicitFalse,\n readStdin,\n reportConfig,\n splitList,\n} from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { splitPageArgument as splitSharedPageArgument } from \"../shared/pin.js\";\nimport { terminalConfirm } from \"../shared/prompt.js\";\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport {\n COMMON_FORMAT_LIST,\n OMITTED_WHEN_CLEAN,\n REPORT_FORMAT_LIST,\n STDIN_TOKEN,\n isMachineFormat,\n} from \"../meta/internal.js\";\nimport { REPORT_FORMATS, isReportFormat } from \"../meta/index.js\";\nimport { runAdd } from \"./commands/add.js\";\nimport { runCheck } from \"./commands/check.js\";\nimport { runRemove } from \"./commands/remove.js\";\nimport { runUpdate } from \"./commands/update.js\";\nimport { CiteError, asCiteError } from \"./errors.js\";\nimport { spellSource } from \"./core/range.js\";\nimport { shortCommit, shortLine, shortPin, shortSrc } from \"./core/spell.js\";\nimport { renderCheckGithub } from \"./reporters/github.js\";\nimport { renderCheckJson, renderRemoveJson, renderUpdateJson } from \"./reporters/json.js\";\nimport { renderCheckJunit } from \"./reporters/junit.js\";\nimport { renderCheckPretty, renderRemovePretty, renderUpdatePretty } from \"./reporters/pretty.js\";\nimport { renderCheckSarif } from \"./reporters/sarif.js\";\nimport type { AddResult, PageLines } from \"./types.js\";\n\nconst UPDATE_FORMATS = [\"pretty\", \"json\"] as const;\ntype UpdateFormat = (typeof UPDATE_FORMATS)[number];\n/** The same two `update` has: a removal is a write, and writes report alike. */\nconst REMOVE_FORMATS = UPDATE_FORMATS;\ntype RemoveFormat = UpdateFormat;\n\n/**\n * Whether `command`'s output gets colour: this domain's `--no-color` and\n * `NO_COLOR` turn it off, and otherwise only a TTY turns it on\n * (`shouldColor`). `isTTY` is passed uncoerced: Node leaves it undefined off\n * a terminal, never false, and `shouldColor` reads a missing one as \"not a\n * terminal\".\n */\nexport function colorFor(\n command: Command,\n isTTY: boolean | undefined,\n env?: NodeJS.ProcessEnv,\n): boolean {\n // commander maps --no-color to opts.color === false, on the command that\n // declares it.\n const noColor = colorOwner(command).opts().color === false;\n return shouldColor({ noColor, isTTY, env });\n}\n\n/**\n * The nearest command, this one or an ancestor, that declares `--no-color`:\n * the `cite` program, wherever it is mounted. Not the root: under the\n * umbrella that is `manni`, which has no `--no-color` of its own.\n */\nfunction colorOwner(command: Command): Command {\n for (let c: Command | null = command; c !== null; c = c.parent) {\n if (c.options.some((o) => o.long === \"--no-color\")) return c;\n }\n return command;\n}\n\nfunction isUpdateFormat(value: string): value is UpdateFormat {\n return (UPDATE_FORMATS as readonly string[]).includes(value);\n}\n\nfunction isRemoveFormat(value: string): value is RemoveFormat {\n return (REMOVE_FORMATS as readonly string[]).includes(value);\n}\n\n/**\n * Commander hands an `.action()` callback an untyped bag of option values, so\n * each subcommand declares the shape it actually reads. The `--no-<thing>`\n * flags are `boolean` and never `undefined`: commander supplies `true` when\n * the flag is absent, which is its default and not a choice, so only the\n * explicit `false` travels to the core (`explicitFalse`).\n */\ninterface InputCliOptions {\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 <format>`: force an extractor. */\n as?: string;\n /**\n * `-c, --config <path>` and `--no-config` share one commander attribute:\n * `undefined` with neither flag, the path with `-c`, `false` with\n * `--no-config`. Split by `configOption`.\n */\n config?: string | boolean;\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n gitignore: boolean;\n /** `--root <dir>`: where `src:` paths resolve from. */\n root?: string;\n}\n\ninterface CheckCliOptions extends InputCliOptions {\n /** `-f, --format <format>`. Always a string: the declaration has a default. */\n format: string;\n quiet?: boolean;\n /**\n * `--baseline [path]` / `--no-baseline`, the same three-state split as\n * `config`: absent leaves the config in charge, a string names a file, `true`\n * is a bare `--baseline` (the default path), `false` is `--no-baseline`.\n */\n baseline?: string | boolean;\n /** `--write-baseline [path]`; `true` for the bare flag. */\n writeBaseline?: string | boolean;\n /** `--no-check-sources`. */\n checkSources: boolean;\n showDiff?: boolean;\n reveal?: boolean;\n}\n\ninterface AddCliOptions {\n id?: string;\n marker?: boolean;\n quote?: boolean;\n /** `--encrypt`. */\n encrypt?: boolean;\n /** `--no-commit-sha`. */\n commitSha: boolean;\n dryRun?: boolean;\n as?: string;\n root?: string;\n config?: string | boolean;\n}\n\ninterface RemoveCliOptions extends Omit<InputCliOptions, \"root\"> {\n /** `--only <id>`, repeatable; commander's default value is `[]`. */\n only: string[];\n dryRun?: boolean;\n format: string;\n}\n\ninterface UpdateCliOptions extends InputCliOptions {\n /** `--no-check-sources`: declared so the refusal names the flag rather than commander rejecting it. */\n checkSources: boolean;\n accept?: boolean;\n recommit?: boolean;\n /** `--only <id>`, repeatable; commander's default value is `[]`. */\n only: string[];\n dryRun?: boolean;\n format: string;\n}\n\n/**\n * Split `docs/limits.md:9` or `docs/limits.md:14-18` into the page and the\n * claim's lines, under cite's error contract. The parsing is the shared pin\n * engine's (`splitPageArgument` in `src/shared/pin.ts`).\n */\nexport function splitPageArgument(arg: string): { page: string; lines?: PageLines } {\n return asCiteError(() => splitSharedPageArgument(arg));\n}\n\n/** `line 9`, or `lines 14-18` for a range. */\nfunction spellAt(lines: PageLines, noun = \"line\"): string {\n return lines.start === lines.end\n ? `${noun} ${String(lines.start)}`\n : `${noun}s ${String(lines.start)}-${String(lines.end)}`;\n}\n\n/**\n * What `add` says on success. One sentence composed from the result: what was\n * added, where it went, and what each end is pinned to. Lines are the page's\n * own, after the write. The source is spelled as it was written to the page,\n * abbreviated when it is a ciphertext, and quoted with its first pinned line\n * where the result carries one.\n */\nexport function addMessage(result: AddResult): string {\n const { citation, claimLines } = result;\n const claim = citation.claim;\n const name = citation.id ?? (claim === undefined ? \"a bare pin\" : \"an entry\");\n const src = shortSrc(spellSource(citation.source));\n const commit = citation.source[\"commit-sha\"];\n const quoted = result.sourceLine === undefined ? \"\" : shortLine(result.sourceLine);\n const line = quoted === \"\" ? \"\" : ` \"${quoted}\"`;\n const pin = `${src}${line}, ${shortPin(citation.source.integrity)}, ${commit === undefined ? \"no commit\" : shortCommit(commit)}`;\n // Where it went: the page's own frontmatter, or the manifest that owns the\n // page's citations, at the line the entry now sits on.\n const where =\n result.manifest === undefined\n ? \"frontmatter\"\n : `${result.manifest.file}:${String(result.manifest.line)}`;\n const head = `${result.file}: added ${name} to ${where}`;\n\n if (result.markerLine !== undefined) {\n const at =\n claimLines === undefined ? \"\" : `, claim pinned at ${spellAt(claimLines)}`;\n const wrote = result.markerJoined === true ? \"joined the marker at line\" : \"marker at line\";\n const marked = `${head}; ${wrote} ${String(result.markerLine)}${at}`;\n if (claim === undefined) return marked;\n if (citation.quote === true) return `${marked} (a block that reproduces ${src})`;\n return `${marked} (${shortPin(claim.integrity)}; source ${pin})`;\n }\n if (claim === undefined || claimLines === undefined) {\n return `${head} (source ${pin})`;\n }\n if (citation.quote === true) {\n return `${head} (claim ${spellAt(claimLines, \"line\")}, a block that reproduces ${src})`;\n }\n return `${head} (claim at ${spellAt(claimLines)}, ${shortPin(claim.integrity)}; source ${pin})`;\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"cite\")\n .description(\n \"Track citations from doc claims to source lines and check them for drift.\",\n )\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 program\n .command(\"check\")\n .description(\"Check every citation in the given pages against its source\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to check (use - for stdin)\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\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(\n \"-f, --format <format>\",\n `output: ${REPORT_FORMATS.join(\" | \")}`,\n \"pretty\",\n )\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\")\n .option(\"-q, --quiet\", \"in pretty output, hide current citations and clean files\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"check files .gitignore covers\")\n // No `defaultValue` and no `.preset()`, for the reasons meta's validate\n // gives: a bare flag must stay distinguishable from a typed path.\n .addOption(\n new Option(\n \"--baseline [path]\",\n \"compare against a baseline; fail only on findings not in it\",\n ),\n )\n .addOption(\n new Option(\n \"--write-baseline [path]\",\n \"record current findings as the baseline, then exit 0\",\n ),\n )\n .option(\"--no-baseline\", \"ignore a baseline configured by `baseline:`\")\n .option(\"--no-check-sources\", \"page-side rules only; every source status is skipped\")\n .option(\n \"--root <dir>\",\n \"directory src: paths resolve from (default: cite.root from config, else the git root, else the current directory)\",\n )\n .option(\"--show-diff\", \"in pretty output, print the diff and commit subjects for changed\")\n .option(\"--reveal\", \"in pretty output, print the decrypted path beside an encrypted source\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni cite check docs/ # walk a directory\",\n \" manni cite check --collection guides # one configured collection\",\n ' manni cite check \"docs/**/*.md\" -f github # CI annotations',\n \" manni cite check --show-diff docs/limits.md # see what changed\",\n \" manni cite check --baseline # fail only on new findings\",\n \" cat page.md | manni cite check - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: CheckCliOptions, command: Command) => {\n try {\n const format = options.format;\n if (!isReportFormat(format)) {\n throw new CiteError(\n `Unknown --format \"${format}\". Use ${REPORT_FORMAT_LIST}.`,\n );\n }\n const exts = options.ext ? splitList(options.ext) : undefined;\n const stdinContent = paths.includes(STDIN_TOKEN) ? await readStdin() : undefined;\n const cwd = process.cwd();\n\n const run = await runCheck({\n inputs: paths,\n collection: options.collection,\n exts,\n exclude: options.exclude,\n as: options.as,\n ...configOption(options.config),\n onConfigLoaded: reportConfig(!isMachineFormat(format), cwd),\n stdinContent,\n // `undefined` rather than `false` when absent, so config still wins.\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: explicitFalse(options.gitignore),\n onNotice: notice,\n baseline: options.baseline,\n writeBaseline: options.writeBaseline,\n checkSources: explicitFalse(options.checkSources),\n // Only so the run can say git is not there to give diffs; the diffs\n // themselves are the pretty reporter's.\n showDiff: options.showDiff ? true : undefined,\n root: options.root,\n });\n\n let text: string;\n switch (format) {\n case \"pretty\":\n text = renderCheckPretty(run, {\n color: colorFor(command, process.stdout.isTTY),\n quiet: Boolean(options.quiet),\n showDiff: Boolean(options.showDiff),\n reveal: Boolean(options.reveal),\n });\n break;\n case \"json\":\n text = renderCheckJson(run);\n break;\n case \"github\":\n text = renderCheckGithub(run);\n break;\n case \"sarif\":\n text = renderCheckSarif(run, { onNotice: notice });\n break;\n case \"junit\":\n text = renderCheckJunit(run);\n break;\n }\n // Only `github` may say nothing on a clean run; every other format\n // owes its envelope even when empty.\n if (text.length > 0 || !OMITTED_WHEN_CLEAN.has(format)) {\n process.stdout.write(`${text}\\n`);\n }\n // `failed` counts files with an unbaselined error-severity finding;\n // warnings never move it.\n process.exitCode = run.summary.failed > 0 ? 1 : 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"add\")\n .description(\"Mint a citation for a source range and write it to a page\")\n .argument(\n \"<page>\",\n \"the page to cite from, with the claim's lines: page:L or page:L1-L2 (use - for stdin, with --as)\",\n )\n .argument(\n \"<src>\",\n \"path, path:L or path:L1-L2 relative to --root, or an encrypted ~source with the same line forms\",\n )\n .option(\"--id <id>\", \"kebab-case id, unique on the page; required with --marker\")\n .option(\"--marker\", \"write a cite <id> marker above the paragraph holding the page lines and pin the text it anchors\")\n .option(\"--quote\", \"the page lines are a fenced block that reproduces the source\")\n .option(\n \"--encrypt\",\n \"write source.file encrypted, with an hmac-sha256- pin; with no key, offer to create one (an available key encrypts without the flag)\",\n )\n .option(\"--no-commit-sha\", \"do not record HEAD\")\n .option(\"--dry-run\", \"print the diff; write nothing\")\n .option(\"--as <format>\", \"force the page format\")\n .option(\"--root <dir>\", \"directory source paths resolve from (as check)\")\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni cite add docs/limits.md:9 lib/limits.ts:2 --id fetch-timeout\",\n \" manni cite add docs/limits.md:30 lib/limits.ts:8-12 --id timeouts --marker\",\n \" manni cite add docs/limits.md:14-18 lib/limits.ts:1-3 --quote\",\n \" manni cite add docs/limits.md lib/limits.ts --dry-run\",\n \" cat page.md | manni cite add -:9 lib/limits.ts:2 --as markdown > out.md\",\n ].join(\"\\n\"),\n )\n .action(async (pageArgument: string, src: string, options: AddCliOptions) => {\n try {\n const { page, lines } = splitPageArgument(pageArgument);\n const usingStdin = page === STDIN_TOKEN;\n const stdinContent = usingStdin ? await readStdin() : undefined;\n const dryRun = Boolean(options.dryRun);\n const cwd = process.cwd();\n\n const result = await runAdd({\n page,\n pageLines: lines,\n src,\n id: options.id,\n marker: options.marker ? true : undefined,\n quote: options.quote ? true : undefined,\n // `undefined` when absent, so the key decides: an available one\n // encrypts without the flag.\n encrypt: options.encrypt ? true : undefined,\n commitSha: explicitFalse(options.commitSha),\n dryRun,\n as: options.as,\n ...configOption(options.config),\n // With `-` the page owns stdout; so does the diff under --dry-run.\n onConfigLoaded: reportConfig(!usingStdin && !dryRun, cwd),\n stdinContent,\n root: options.root,\n onNotice: notice,\n // Only on a terminal: off one, a missing key is a refusal, not a\n // question nobody can answer. With `-` stdin is the page, so no\n // question is put either.\n confirm: terminalConfirm(),\n });\n\n const message = addMessage(result);\n // A dry run prints every diff the write would make: the page's, and\n // the manifest's when the entry goes there.\n const diffs = [result.diff, result.manifest?.diff ?? \"\"].filter((d) => d.length > 0);\n if (usingStdin) {\n // The rewritten page owns stdout; everything else is a diagnostic.\n process.stdout.write(result.content);\n if (dryRun) for (const diff of diffs) process.stderr.write(`${diff}\\n`);\n process.stderr.write(`${message}\\n`);\n } else if (dryRun) {\n for (const diff of diffs) process.stdout.write(`${diff}\\n`);\n process.stderr.write(`${message}\\n`);\n } else {\n process.stdout.write(`${message}\\n`);\n }\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"update\")\n .description(\"Rewrite moved citations in place; with --accept, re-mint changed ones\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to update (use - for stdin)\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\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(\"--no-config\", \"ignore any discovered config file\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"update files .gitignore covers\")\n .option(\"--no-check-sources\", \"refused: update needs the sources\")\n .option(\"--root <dir>\", \"directory src: paths resolve from (as check)\")\n .option(\"--accept\", \"re-mint changed and never-true entries at HEAD; prints old and new pins\")\n .option(\n \"--recommit\",\n \"re-record commit-sha where the recorded commit does not contain the pinned lines, or is outside HEAD's history\",\n )\n .option(\"--only <id>\", \"limit to entries with this id; repeatable\", collect, [])\n .option(\"--dry-run\", \"print the diffs; write nothing\")\n .option(\n \"-f, --format <format>\",\n `output: ${UPDATE_FORMATS.join(\" | \")}`,\n \"pretty\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni cite update docs/ # rewrite moved entries\",\n \" manni cite update --accept --only fetch-timeout docs/limits.md\",\n \" manni cite update --dry-run docs/ # see the diffs first\",\n \" manni cite update --recommit docs/ # repair unsupported commit-sha\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: UpdateCliOptions, command: Command) => {\n try {\n const format = options.format;\n if (!isUpdateFormat(format)) {\n throw new CiteError(\n `Unknown --format \"${format}\". Use ${COMMON_FORMAT_LIST}.`,\n );\n }\n if (!options.checkSources) {\n throw new CiteError(\n \"update needs the sources: drop --no-check-sources (or `checkSources: false`).\",\n );\n }\n const exts = options.ext ? splitList(options.ext) : undefined;\n const usingStdin = paths.includes(STDIN_TOKEN);\n const stdinContent = usingStdin ? await readStdin() : undefined;\n const dryRun = Boolean(options.dryRun);\n // With `-` the rewritten page owns stdout, as it does for `add -`; a\n // dry run prints the diffs instead, so the report keeps stdout.\n const pageToStdout = usingStdin && !dryRun;\n const cwd = process.cwd();\n\n const run = await runUpdate({\n inputs: paths,\n collection: options.collection,\n exts,\n exclude: options.exclude,\n as: options.as,\n ...configOption(options.config),\n onConfigLoaded: reportConfig(format === \"pretty\" && !pageToStdout, cwd),\n stdinContent,\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: explicitFalse(options.gitignore),\n onNotice: notice,\n root: options.root,\n accept: options.accept ? true : undefined,\n recommit: options.recommit ? true : undefined,\n only: options.only.length > 0 ? options.only : undefined,\n dryRun,\n });\n\n const text =\n format === \"json\"\n ? renderUpdateJson(run)\n : renderUpdatePretty(run, {\n color: colorFor(command, process.stdout.isTTY),\n // The diffs are the point of a dry run; a real run prints\n // what it rewrote and leaves the file to say the rest.\n showDiff: dryRun,\n });\n const stdinPage = pageToStdout ? run.pages.find((page) => page.content !== undefined) : undefined;\n if (stdinPage?.content !== undefined) {\n process.stdout.write(stdinPage.content);\n process.stderr.write(`${text}\\n`);\n } else {\n process.stdout.write(`${text}\\n`);\n }\n // Exit 1 when something was skipped with an error-severity finding:\n // work left undone, `fill`'s precedent.\n process.exitCode = run.exitCode;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"remove\")\n .description(\"Remove the named citations from the given pages, markers and all\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to remove from (use - for stdin)\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\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(\"--no-config\", \"ignore any discovered config file\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"remove from files .gitignore covers\")\n .option(\n \"--only <id>\",\n \"the entry to remove, by id or by pointer (/citations/N); required, and repeatable\",\n collect,\n [],\n )\n .option(\"--dry-run\", \"print the diffs and the report; write nothing\")\n .option(\n \"-f, --format <format>\",\n `output: ${REMOVE_FORMATS.join(\" | \")}`,\n \"pretty\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni cite remove docs/limits.md --only fetch-timeout\",\n \" manni cite remove docs/ --only fetch-timeout --only retries --dry-run\",\n \" manni cite remove --collection site --only /citations/3 -f json\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: RemoveCliOptions, command: Command) => {\n try {\n const format = options.format;\n if (!isRemoveFormat(format)) {\n throw new CiteError(\n `Unknown --format \"${format}\". Use ${COMMON_FORMAT_LIST}.`,\n );\n }\n const exts = options.ext ? splitList(options.ext) : undefined;\n const usingStdin = paths.includes(STDIN_TOKEN);\n const stdinContent = usingStdin ? await readStdin() : undefined;\n const dryRun = Boolean(options.dryRun);\n // With `-` the rewritten page owns stdout, exactly as on `update -`.\n const pageToStdout = usingStdin && !dryRun;\n const cwd = process.cwd();\n\n const run = await runRemove({\n inputs: paths,\n collection: options.collection,\n exts,\n exclude: options.exclude,\n as: options.as,\n ...configOption(options.config),\n onConfigLoaded: reportConfig(format === \"pretty\" && !pageToStdout, cwd),\n stdinContent,\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: explicitFalse(options.gitignore),\n onNotice: notice,\n only: options.only,\n dryRun,\n });\n\n const text =\n format === \"json\"\n ? renderRemoveJson(run)\n : renderRemovePretty(run, {\n color: colorFor(command, process.stdout.isTTY),\n // The diffs are the point of a dry run; a real run prints\n // what it removed and leaves the file to say the rest.\n showDiff: dryRun,\n dryRun,\n });\n const stdinPage = pageToStdout ? run.pages.find((page) => page.content !== undefined) : undefined;\n if (stdinPage?.content !== undefined) {\n process.stdout.write(stdinPage.content);\n process.stderr.write(`${text}\\n`);\n } else {\n process.stdout.write(`${text}\\n`);\n }\n // Everything named was removed, or previewed: there is no exit 1.\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n","/**\n * SARIF for `check`. Meta's renderer builds the envelope, the\n * repository-relative uris and the fingerprints the baseline shares, from the\n * adapted results. What it cannot know is what a cite rule is: it describes\n * every rule as a schema keyword, links meta's fix page, and prefixes each\n * message with the JSON Pointer of the entry, `(root)` for a finding about no\n * entry. This renderer replaces those three with the cite rule's own\n * description, a link to its row of the citations reference, and the message\n * the github annotation carries, which names the citation the pointer only\n * numbered. A message is no part of a fingerprint, so the baseline is\n * unaffected.\n */\nimport { renderSarif, type ValidationResult } from \"../../meta/index.js\";\nimport { errorSite } from \"../core/adapt.js\";\nimport { RULE_ID_PREFIX, isCiteRule } from \"../core/severity.js\";\nimport type { CheckRun, CiteRule } from \"../types.js\";\nimport { findingMessage } from \"./github.js\";\n\nconst INFORMATION_URI = \"https://hawkeyexl.github.io/manni/cite/\";\n\n/** The citations reference, whose rule tables anchor each row by rule name. */\nconst RULES_URI = \"https://hawkeyexl.github.io/manni/cite/reference/citations/\";\n\n/** What each rule is, as the citations reference's tables say it. */\nconst RULE_DESCRIPTIONS: Readonly<Record<CiteRule, string>> = {\n \"source-moved\": \"The cited source lines moved to one other place in the file.\",\n \"source-moved-ambiguous\": \"The cited source lines now match at several places in the file.\",\n \"source-changed\": \"The cited source lines changed since the citation pinned them.\",\n \"source-never-true\": \"The pin never matched the source at the recorded commit.\",\n \"source-missing\": \"The cited source file is not tracked under the root, or cannot be decrypted.\",\n \"claim-moved\": \"The cited sentence moved to other lines of the page.\",\n \"claim-moved-ambiguous\": \"The cited sentence now appears at several places on the page.\",\n \"claim-reanchored\": \"The cited sentence's words are unchanged since the claim's baseline, and only its layout moved.\",\n \"claim-changed\": \"The cited sentence was edited since the citation pinned it.\",\n \"marker-orphan\": \"A marker names an id no citation has.\",\n \"marker-invalid\": \"A marker is malformed, or the page has too many markers.\",\n \"marker-repeated\": \"Two markers name the same citation id.\",\n \"marker-misplaced\": \"A marker line sits inside the paragraph it anchors, and splits it.\",\n \"anchor-invalid\": \"A citation's anchor cannot work.\",\n \"entry-invalid\": \"A citation entry is malformed.\",\n \"quote-drift\": \"A quoted block no longer reproduces its source.\",\n};\n\n/**\n * The label meta's reporters put before a message: `(root) ` for a finding\n * about no entry, `/citations/N ` for one about an entry. Nothing else ever\n * opens a cite finding's adapted message.\n */\nexport const ENTRY_LABEL = /^(?:\\(root\\)|\\/citations\\/\\d+) /;\n\nexport interface SarifRule {\n id: string;\n shortDescription: { text: string };\n helpUri?: string;\n}\n\n/** As much of meta's SARIF as this renderer and its tests read back. */\nexport interface SarifLog {\n runs: {\n tool: { driver: { informationUri: string; rules: SarifRule[] } };\n results: { ruleId: string; message: { text: string } }[];\n }[];\n}\n\n/**\n * The adapted results with each message rewritten as the github annotation\n * says it. An error is paired with its finding by rule, entry, line and\n * message, as the baseline split pairs them; the baseline has already\n * dropped the errors it forgives.\n */\nexport function withFindingMessages(run: CheckRun): ValidationResult[] {\n return run.results.map((result) => {\n const page = run.pages.find((p) => p.file === result.file);\n if (page === undefined) return result;\n const errors = result.errors.map((error) => {\n const finding = page.findings.find(\n (f) =>\n f.rule === error.keyword &&\n (f.index === undefined ? \"\" : `/citations/${String(f.index)}`) === error.instancePath &&\n f.message === error.message &&\n (errorSite(f).line ?? null) === (error.line ?? null),\n );\n return finding === undefined ? error : { ...error, message: findingMessage(finding) };\n });\n return { ...result, errors };\n });\n}\n\n/** A rule as the citation tool describes it. */\nfunction describe(rule: SarifRule): SarifRule {\n const name = rule.id.slice(RULE_ID_PREFIX.length + 1);\n if (!isCiteRule(name)) return rule;\n return { id: rule.id, shortDescription: { text: RULE_DESCRIPTIONS[name] }, helpUri: `${RULES_URI}#${name}` };\n}\n\nexport function renderCheckSarif(run: CheckRun, opts: { onNotice?: (message: string) => void } = {}): string {\n const log = JSON.parse(\n renderSarif(withFindingMessages(run), {\n frame: run.frame,\n ...(opts.onNotice === undefined ? {} : { onNotice: opts.onNotice }),\n }),\n ) as SarifLog;\n for (const sarifRun of log.runs) {\n sarifRun.tool.driver.informationUri = INFORMATION_URI;\n sarifRun.tool.driver.rules = sarifRun.tool.driver.rules.map(describe);\n for (const result of sarifRun.results) result.message.text = result.message.text.replace(ENTRY_LABEL, \"\");\n }\n return JSON.stringify(log, null, 2);\n}\n","/**\n * JUnit for `check`: meta's renderer over the adapted results, under the\n * `manni.cite` classname, with each failure's message the one the github\n * annotation carries.\n * Meta's renderer opens every message with the entry's JSON Pointer, `(root)`\n * for a finding about no entry, which says nothing about a citation. The\n * failure's `type` is already the rule id.\n */\nimport { renderJunit } from \"../../meta/index.js\";\nimport type { CheckRun } from \"../types.js\";\nimport { ENTRY_LABEL, withFindingMessages } from \"./sarif.js\";\n\n/** JUnit `classname` for the citation tool's findings. */\nexport const JUNIT_CLASSNAME = \"manni.cite\";\n\n/** A `message=\"` attribute's opening label. The value is escaped, so `message=\"` opens nothing else. */\nconst MESSAGE_LABEL = new RegExp(`message=\"${ENTRY_LABEL.source.replace(/^\\^/, \"\")}`, \"g\");\n\nexport function renderCheckJunit(run: CheckRun): string {\n return renderJunit(withFindingMessages(run), { frame: run.frame, classname: JUNIT_CLASSNAME }).replace(\n MESSAGE_LABEL,\n 'message=\"',\n );\n}\n","/**\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","/**\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","/**\n * The graph program. Named `graph` because that is where it is mounted\n * (`manni graph …`); `src/cli.ts` adds it to the umbrella and runs it.\n *\n * Grammar per proposals 0034 and 0051 §2: the domain owns verbs and has no\n * default subcommand, `-f` means the output format everywhere and is checked\n * against the verb's list, and a list reaches a flag by exactly one\n * separator. The plumbing is the family's: `fail()` from `src/shared/run.ts`,\n * `warn()` from `src/shared/warn.ts`, and `--no-color` from\n * `src/shared/color.ts`.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport {\n collect,\n configOption,\n readStdin,\n splitList,\n} from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { fail } from \"../shared/run.js\";\nimport { warn } from \"../shared/warn.js\";\nimport { GraphError } from \"./types.js\";\nimport { LOCAL_FLAG_HELP } from \"../shared/providers.js\";\nimport { ALL_FILL_FIELDS, type FillField } from \"./core/config.js\";\nimport {\n assertInputFormat,\n DEFAULT_EXTENSIONS,\n STDIN,\n} from \"./core/discover.js\";\nimport {\n CHECK_FORMATS,\n CHECK_FORMAT_LIST,\n GRAPH_FORMATS,\n GRAPH_FORMAT_LIST,\n type CheckFormat,\n type GraphFormat,\n} from \"./reporters/index.js\";\nimport { runBuild } from \"./commands/build.js\";\nimport { renderCheck, runCheck } from \"./commands/check.js\";\nimport {\n EXPORT_TARGETS,\n runExport,\n type ExportFormat,\n} from \"./commands/export.js\";\nimport { renderQuery, runQuery } from \"./commands/query.js\";\nimport { renderFill, runFill } from \"./commands/fill.js\";\nimport { runInit } from \"./commands/init.js\";\nimport { renderEmbed, runEmbed } from \"./commands/embed.js\";\nimport {\n renderSearch,\n runSearch,\n SEARCH_MODES,\n type SearchMode,\n} from \"./commands/search.js\";\nimport { renderStats, runStats } from \"./commands/stats.js\";\nimport { renderTraverse, runTraverse } from \"./commands/traverse.js\";\n\n/**\n * Whether `command`'s output gets colour: this domain's `--no-color` and\n * `NO_COLOR` turn it off, and otherwise only a TTY turns it on\n * (`shouldColor`). `isTTY` is passed uncoerced: Node leaves it undefined off\n * a terminal, never false, and `shouldColor` reads a missing one as \"not a\n * terminal\".\n *\n * Exported because this is where the decision is testable — a spawned bin is\n * never a TTY. graph's reporters print no colour yet; when one does, it takes\n * the boolean from here rather than consulting the environment itself.\n */\nexport function colorFor(\n command: Command,\n isTTY: boolean | undefined,\n env?: NodeJS.ProcessEnv,\n): boolean {\n // commander maps --no-color to opts.color === false, on the command that\n // declares it.\n const noColor = colorOwner(command).opts().color === false;\n return shouldColor({ noColor, isTTY, env });\n}\n\n/**\n * The nearest command, this one or an ancestor, that declares `--no-color`:\n * the `graph` program, wherever it is mounted. Not the root: under the umbrella\n * that is `manni`, which has no `--no-color` of its own.\n */\nfunction colorOwner(command: Command): Command {\n for (let c: Command | null = command; c !== null; c = c.parent) {\n if (c.options.some((o) => o.long === \"--no-color\")) return c;\n }\n return command;\n}\n\nexport function buildProgram(): Command {\nconst program = new Command();\n\nprogram\n .name(\"graph\")\n .description(\n \"Deterministic knowledge graphs derived from documentation frontmatter and formatting.\",\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 still\n // calling `process.exit(1)` — which reports a usage error as a finding.\n .exitOverride();\n\n/**\n * Parse a numeric CLI option, refusing what the config schema refuses.\n *\n * `Number.parseFloat`/`parseInt` return NaN for `abc` and silently accept\n * out-of-range values, and NaN then disables whatever gate it feeds — a cost\n * cap that never fires, a confidence gate that writes everything, a `--top`\n * that asks for a negative number of rows. The documented precedence is\n * config → Ajv → CLI override, so the override has to be held to the same range.\n */\nfunction numericOption(\n flag: string,\n { min, max, integer }: { min: number; max?: number; integer?: boolean },\n) {\n return (raw: string): number => {\n const value = Number.parseFloat(raw);\n if (!Number.isFinite(value)) {\n throw new GraphError(`${flag} expects a number, got \"${raw}\".`);\n }\n if (integer && !Number.isInteger(value)) {\n throw new GraphError(`${flag} expects a whole number, got ${value}.`);\n }\n if (value < min || (max !== undefined && value > max)) {\n const range = max === undefined ? `>= ${min}` : `${min}..${max}`;\n throw new GraphError(`${flag} must be ${range}, got ${value}.`);\n }\n return value;\n };\n}\n\n/** A count: a whole number, at least `min` (1 unless the flag allows zero). */\nfunction countOption(flag: string, min = 1) {\n return numericOption(flag, { min, integer: true });\n}\n\n/**\n * Hold a CLI override to the same list its config key is held to.\n *\n * `fill.provider` is Ajv-validated against the schema enum; the `--provider`\n * override was an arbitrary string cast straight to `ProviderName`, so the\n * documented config → Ajv → CLI precedence had a hole at the last step.\n */\nfunction enumOption<T extends string>(flag: string, allowed: readonly T[]) {\n return (raw: string): T => {\n if (!(allowed as readonly string[]).includes(raw)) {\n throw new GraphError(\n `${flag} must be one of ${allowed.join(\" | \")}, got \"${raw}\".`,\n );\n }\n return raw as T;\n };\n}\n\n/**\n * A flag whose value is one of a named set, refused in the family's words:\n * `Unknown --format \"xml\". Use pretty | json.` The check runs while the\n * options are parsed, so a typo costs a message rather than a graph load.\n */\nfunction choiceOption<T extends string>(flag: string, allowed: readonly T[]) {\n return (raw: string): T => {\n if (!(allowed as readonly string[]).includes(raw)) {\n throw new GraphError(`Unknown ${flag} \"${raw}\". Use ${allowed.join(\" | \")}.`);\n }\n return raw as T;\n };\n}\n\n/** `-f, --format`: every verb's list is `pretty | json` (0051 §2). */\nconst formatOption = choiceOption(\"--format\", GRAPH_FORMATS);\n\n/** `check`'s own, which adds `github` — the CI gate's annotation format. */\nconst checkFormatOption = choiceOption(\"--format\", CHECK_FORMATS);\n\n/**\n * `--fields <list>`: comma-separated and given once, never repeatable — one\n * separator per list (proposal 0034), and the spelling `meta fill --fields`\n * already uses. Each value is held to the same list `fill.fields` is.\n */\nconst fieldsOption = (raw: string): FillField[] =>\n splitList(raw).map((value) => enumOption(\"--fields\", ALL_FILL_FIELDS)(value));\n\n/**\n * The document-set surface the verbs that read documents share (proposals\n * 0041 and 0051 §1): positional `[paths...]` with `-` for stdin,\n * `--collection` and `--exclude` (each one value per occurrence), `--as`,\n * `--ext` (comma-separated, given once), `--allow-empty`, and\n * `-c`/`--no-config`. Declared once so the verbs cannot drift apart on a name\n * or a description, and worded as `meta` and `lint` word them.\n */\nfunction documentInputs(command: Command, verb: string): Command {\n return command\n .argument(\n \"[paths...]\",\n `files, directories, or globs to ${verb} (use - for stdin)`,\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(\"--as <format>\", \"force an input format (markdown, mdx)\")\n .option(\n \"--ext <list>\",\n \"comma-separated extensions for directory walks\",\n DEFAULT_EXTENSIONS.join(\",\"),\n )\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\");\n}\n\n/** The input flags as commander hands them over. */\ninterface InputFlags {\n as?: string;\n ext: string;\n allowEmpty?: boolean;\n}\n\n/**\n * The input flags for a core, and stdin when `paths` holds `-`. `--as` is\n * checked first, so `-` without it is refused before anything waits on stdin.\n */\nasync function inputOptions(\n paths: string[],\n opts: InputFlags,\n): Promise<{\n as?: string;\n ext: string[];\n allowEmpty?: boolean;\n stdinContent?: string;\n}> {\n assertInputFormat(paths, opts.as);\n return {\n ...(opts.as === undefined ? {} : { as: opts.as }),\n ext: splitList(opts.ext),\n ...(opts.allowEmpty === true ? { allowEmpty: true } : {}),\n ...(paths.includes(STDIN) ? { stdinContent: await readStdin() } : {}),\n };\n}\n\n/**\n * `-c`/`--no-config` for a verb that reads a built graph rather than a\n * document set. They share one commander attribute, which `configOption`\n * splits.\n */\nfunction configInputs(command: Command): Command {\n return command\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\");\n}\n\n/**\n * `opts` minus the one attribute `-c` and `--no-config` share. `documentOptions`\n * restates it as the two fields a core reads, and spreading the raw value over\n * them would put commander's `false` back where a path belongs.\n */\nfunction rest<T extends { config?: string | boolean }>(\n opts: T,\n): Omit<T, \"config\"> {\n const { config, ...others } = opts;\n return others;\n}\n\n/** The shared options as the command cores take them. */\nfunction documentOptions(opts: {\n collection?: string[];\n exclude?: string[];\n config?: string | boolean;\n}): {\n config?: string;\n noConfig?: boolean;\n collection?: string[];\n exclude?: string[];\n} {\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\nprogram\n .command(\"init\")\n .description(\"Add a starter `graph:` section to manni.config.yaml in the current directory\")\n .action(async () => {\n try {\n console.log(`Created ${await runInit()}`);\n } catch (e) {\n fail(e);\n }\n });\n\ndocumentInputs(\n program\n .command(\"build\")\n .description(\"Derive the knowledge graph and write deterministic Turtle\"),\n \"build\",\n)\n .option(\"-o, --out <path>\", \"Output .ttl path (default: config out)\")\n .action(async (paths: string[], opts: InputFlags & {\n config?: string | boolean;\n collection?: string[];\n exclude?: string[];\n out?: string;\n }) => {\n try {\n const result = await runBuild({\n paths,\n ...documentOptions(opts),\n ...(await inputOptions(paths, opts)),\n out: opts.out,\n });\n // Warnings go to stderr so stdout stays the machine-readable summary;\n // a degraded build is still a successful one, so the exit code is 0.\n for (const warning of result.warnings) warn(warning);\n console.log(\n `Wrote ${result.outPath} (${result.docs} docs, ${result.quads} triples)`,\n );\n } catch (e) {\n fail(e);\n }\n });\n\nconfigInputs(\n program\n .command(\"check\")\n .description(\n \"Validate the built graph against the bundled SHACL shapes (errors exit 1)\",\n ),\n)\n .option(\"-g, --graph <path>\", \"Graph .ttl path (default: config out)\")\n // One path per occurrence, never split on commas: a path may hold one.\n .option(\n \"--shapes <path>\",\n \"Shapes .ttl file; repeatable (default: config check.shapes, then bundled)\",\n collect,\n [],\n )\n .option(\n \"-f, --format <format>\",\n `Output: ${CHECK_FORMAT_LIST}`,\n checkFormatOption,\n \"pretty\",\n )\n .action(\n async (opts: {\n config?: string | boolean;\n graph?: string;\n shapes: string[];\n format: CheckFormat;\n }) => {\n try {\n const report = await runCheck({ ...rest(opts), ...documentOptions(opts) });\n console.log(renderCheck(report, opts.format));\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n },\n );\n\ndocumentInputs(\n program\n .command(\"fill\")\n .description(\n \"Propose `graph:` frontmatter fields with an LLM, gated by confidence, and write them back\",\n ),\n \"fill\",\n)\n .option(\n \"-f, --format <format>\",\n `Output: ${GRAPH_FORMAT_LIST}`,\n formatOption,\n \"pretty\",\n )\n .option(\"--dry-run\", \"Report proposals without writing files\")\n .option(\"--force\", \"Overwrite human-set graph fields\")\n .option(\"--no-cache\", \"Bypass the proposal cache\")\n .option(\"--no-validate-graph\", \"Skip the SHACL graph guardrail on proposals\")\n .option(\"--sections\", \"Also propose per-section metadata\")\n .option(\n \"--max-turns <n>\",\n \"Stop after this many inference calls (a cached page costs none)\",\n countOption(\"--max-turns\"),\n )\n .option(\n \"--confidence <n>\",\n \"Minimum model confidence (0..1) to write a field (default: config, 0.7)\",\n numericOption(\"--confidence\", { min: 0, max: 1 }),\n )\n .option(\n // Comma-separated and given once: one separator per list (proposal 0034).\n \"--fields <list>\",\n `Fields to propose (comma-separated; default: config, then every field)`,\n fieldsOption,\n )\n // The nameable providers, and `auto`. `mock` is the library's test double:\n // accepted when asked for by name, never offered.\n .option(\n \"--provider <name>\",\n \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\",\n )\n .option(\"--model <model>\", \"Model override; needs a named provider, from here or config\")\n .option(\"--local\", LOCAL_FLAG_HELP)\n // Typed inline, as every other action in this file is. The option parsers\n // above (`numericOption`, `choiceOption`, `fieldsOption`) have already thrown\n // on anything malformed by the time this runs, so a cast per field would be\n // safe — but it would also be the one command with the most options and the\n // least help from the compiler.\n .action(async (paths: string[], opts: InputFlags & {\n config?: string | boolean;\n collection?: string[];\n exclude?: string[];\n dryRun?: boolean;\n force?: boolean;\n cache?: boolean;\n validateGraph?: boolean;\n sections?: boolean;\n maxTurns?: number;\n confidence?: number;\n fields?: FillField[];\n provider?: string;\n model?: string;\n local?: boolean;\n format: GraphFormat;\n }) => {\n try {\n const report = await runFill({\n paths,\n ...documentOptions(opts),\n ...(await inputOptions(paths, opts)),\n dryRun: opts.dryRun,\n force: opts.force,\n noCache: opts.cache === false,\n noValidateGraph: opts.validateGraph === false,\n sections: opts.sections,\n maxTurns: opts.maxTurns,\n confidence: opts.confidence,\n fields: opts.fields,\n provider: opts.provider,\n model: opts.model,\n local: opts.local,\n });\n // Same channel discipline as build: warnings on stderr, so stdout stays\n // the report, and a warning never changes the exit code.\n for (const warning of report.warnings) warn(warning);\n const rendered = renderFill(report, opts.format);\n if (paths.includes(STDIN)) {\n // With `-` the filled document owns stdout, as under `meta fill -`,\n // and the report in either format is a diagnostic on stderr.\n if (report.stdinDocument !== undefined) {\n process.stdout.write(report.stdinDocument);\n }\n if (rendered.length > 0) process.stderr.write(`${rendered}\\n`);\n } else {\n console.log(rendered);\n }\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\nprogram\n .command(\"query\")\n .description(\n \"Match triple patterns against the built graph (omit a term for wildcard)\",\n )\n // Long-only, and named for the triple position each one fills. `-o` is\n // `--out` on every other graph verb and `-s` is meta's schema flag; a\n // one-letter spelling that means two things in one family costs more than\n // the letters it saves.\n .option(\"--subject <term>\", \"Subject IRI or prefixed name\")\n .option(\"--predicate <term>\", \"Predicate IRI or prefixed name\")\n .option(\"--object <term>\", \"Object IRI, prefixed name, or literal value\")\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\")\n .option(\"-g, --graph <path>\", \"Graph .ttl path (default: config out)\")\n .option(\n \"-f, --format <format>\",\n `Output: ${GRAPH_FORMAT_LIST}`,\n formatOption,\n \"pretty\",\n )\n .action(\n (opts: {\n subject?: string;\n predicate?: string;\n object?: string;\n config?: string | boolean;\n graph?: string;\n format: GraphFormat;\n }) => {\n try {\n const { subject, predicate, object, ...others } = rest(opts);\n const result = runQuery({\n ...others,\n ...documentOptions(opts),\n ...(subject === undefined ? {} : { s: subject }),\n ...(predicate === undefined ? {} : { p: predicate }),\n ...(object === undefined ? {} : { o: object }),\n });\n console.log(renderQuery(result, opts.format));\n } catch (e) {\n fail(e);\n }\n },\n );\n\nprogram\n .command(\"stats\")\n .description(\n \"Summarize the built graph: counts, orphans, broken links, hubs, metadata coverage\",\n )\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\")\n .option(\"-g, --graph <path>\", \"Graph .ttl path (default: config out)\")\n .option(\n \"-f, --format <format>\",\n `Output: ${GRAPH_FORMAT_LIST}`,\n formatOption,\n \"pretty\",\n )\n .option(\n \"--check\",\n \"Exit 1 when broken internal links exist or coverage is below threshold\",\n )\n .option(\n \"--top <n>\",\n \"How many most-connected docs to list\",\n countOption(\"--top\"),\n )\n .option(\n \"--coverage-threshold <pct>\",\n \"Minimum metadata coverage % (all fields); overrides config for this run\",\n // A percentage, so 0..100 rather than the 0..1 of a confidence. NaN here is\n // worse than a wrong number: `pct < NaN` is false for every field, so the\n // gate this flag exists to tighten would silently pass instead.\n numericOption(\"--coverage-threshold\", { min: 0, max: 100 }),\n )\n .action(\n (opts: {\n config?: string | boolean;\n graph?: string;\n format: GraphFormat;\n check?: boolean;\n top?: number;\n coverageThreshold?: number;\n }) => {\n try {\n const report = runStats({ ...rest(opts), ...documentOptions(opts) });\n console.log(renderStats(report, opts.format));\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n },\n );\n\nprogram\n .command(\"search\")\n .description(\"Rank graph nodes for a text query (needs `export search`)\")\n .argument(\"<query>\", \"Text query\")\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\")\n .option(\"-g, --graph <path>\", \"Graph .ttl path (default: config out)\")\n .option(\n \"-i, --index <dir>\",\n \"Directory holding the indexes and manifest (default: beside the graph)\",\n )\n .option(\n \"--lang <tag>\",\n \"Which localization to search (required when the corpus has more than one)\",\n )\n .option(\"--limit <n>\", \"Maximum results (default 10)\", countOption(\"--limit\"))\n .option(\n \"--vectors <path>\",\n \"Vector sidecar path (default: from the manifest)\",\n )\n .option(\n \"--mode <mode>\",\n `Which legs to run: ${SEARCH_MODES.join(\" | \")} (default: hybrid when vectors exist)`,\n choiceOption(\"--mode\", SEARCH_MODES),\n )\n .option(\n \"-f, --format <format>\",\n `Output: ${GRAPH_FORMAT_LIST}`,\n formatOption,\n \"pretty\",\n )\n .action(\n async (\n query: string,\n opts: {\n config?: string | boolean;\n graph?: string;\n index?: string;\n lang?: string;\n limit?: number;\n vectors?: string;\n mode?: SearchMode;\n format: GraphFormat;\n },\n ) => {\n try {\n const report = await runSearch({\n ...rest(opts),\n ...documentOptions(opts),\n query,\n });\n console.log(renderSearch(report, opts.format));\n } catch (e) {\n fail(e);\n }\n },\n );\n\nprogram\n .command(\"traverse\")\n .description(\n \"Walk the graph from a node, honoring scope rules, with the full trace\",\n )\n .argument(\"<node>\", \"Starting node: a full IRI or a prefix:local CURIE\")\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\")\n .option(\"-g, --graph <path>\", \"Graph .ttl path (default: config out)\")\n .option(\n \"-d, --depth <n>\",\n \"Maximum hops from the node (default 1; 3 under --impact)\",\n // Zero is allowed: it means the node itself, which is a real answer.\n countOption(\"--depth\", 0),\n )\n // Comma-separated and given once: a CURIE holds no comma, so one separator\n // is enough, and a second spelling would be a second thing to document.\n .option(\n \"--predicates <list>\",\n \"Only follow these predicates (comma-separated)\",\n )\n .option(\"--reverse\", \"Follow inbound edges (who points at this node)\")\n .option(\"--impact\", \"Transitive inbound reach: what a change here affects\")\n .option(\n \"--variant <variant>\",\n \"Scope filter: product variant IRI, title, or slug\",\n )\n // Not `--subject`: on `query` that is a triple's subject, and one flag name\n // means one thing across the domain.\n .option(\"--software-subject <subject>\", \"Scope filter: software subject\")\n .option(\"--lang <tag>\", \"Scope filter: BCP-47 language tag, matched in any case\")\n .option(\"--limit <n>\", \"Stop after this many nodes\", countOption(\"--limit\"))\n .option(\n \"-f, --format <format>\",\n `Output: ${GRAPH_FORMAT_LIST}`,\n formatOption,\n \"pretty\",\n )\n .action(\n (\n node: string,\n opts: {\n config?: string | boolean;\n graph?: string;\n depth?: number;\n predicates?: string;\n reverse?: boolean;\n impact?: boolean;\n variant?: string;\n softwareSubject?: string;\n lang?: string;\n limit?: number;\n format: GraphFormat;\n },\n ) => {\n try {\n const { softwareSubject, ...others } = rest(opts);\n const report = runTraverse({\n ...others,\n ...documentOptions(opts),\n ...(softwareSubject === undefined ? {} : { subject: softwareSubject }),\n node,\n predicates:\n opts.predicates === undefined\n ? undefined\n : splitList(opts.predicates),\n });\n console.log(renderTraverse(report, opts.format));\n } catch (e) {\n fail(e);\n }\n },\n );\n\nprogram\n .command(\"embed\")\n .description(\n \"Compute local embeddings for the search index (needs @huggingface/transformers)\",\n )\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\")\n .option(\"-g, --graph <path>\", \"Graph .ttl path (default: config out)\")\n .option(\n \"-i, --index <dir>\",\n \"Directory holding the indexes and manifest (default: beside the graph)\",\n )\n .option(\n \"-o, --out <dir>\",\n \"Directory for the sidecars (default: the index directory)\",\n )\n // Not `--model`: on `fill` that is the inference model, a different thing.\n .option(\n \"--embedding-model <id>\",\n \"Embedding model id (any id; `mock` for offline runs)\",\n )\n .option(\"--dtype <dtype>\", \"Weight quantization (default q8)\")\n .option(\"--no-cache\", \"Ignore the vector cache\")\n .option(\n \"-f, --format <format>\",\n `Output: ${GRAPH_FORMAT_LIST}`,\n formatOption,\n \"pretty\",\n )\n .action(\n async (opts: {\n config?: string | boolean;\n graph?: string;\n index?: string;\n out?: string;\n embeddingModel?: string;\n dtype?: string;\n cache?: boolean;\n format: GraphFormat;\n }) => {\n try {\n const { embeddingModel, ...others } = rest(opts);\n const report = await runEmbed({\n ...others,\n ...documentOptions(opts),\n ...(embeddingModel === undefined ? {} : { model: embeddingModel }),\n noCache: opts.cache === false,\n });\n console.log(renderEmbed(report, opts.format));\n } catch (e) {\n fail(e);\n }\n },\n );\n\nprogram\n .command(\"export\")\n .description(\n \"Reserialize the built graph into a consumer format (jsonld file, iirds package, or search index)\",\n )\n // The target is a positional, not `-f`: `-f` is the output format in every\n // other verb of the family (0051 §2), and one flag cannot mean two things.\n .argument(\"<target>\", `What to write: ${EXPORT_TARGETS.join(\" | \")}`)\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\")\n .option(\"-g, --graph <path>\", \"Graph .ttl path (default: config out)\")\n .option(\n \"-o, --out <path>\",\n \"Output path (default: the graph path with the target's extension)\",\n )\n .action(\n async (\n target: string,\n opts: { config?: string | boolean; graph?: string; out?: string },\n ) => {\n try {\n if (!(EXPORT_TARGETS as readonly string[]).includes(target)) {\n throw new GraphError(\n `Unknown export target \"${target}\". Use ${EXPORT_TARGETS.join(\" | \")}.`,\n );\n }\n const result = await runExport({\n ...documentOptions(opts),\n graph: opts.graph,\n format: target as ExportFormat,\n out: opts.out,\n });\n for (const warning of result.warnings) warn(warning);\n console.log(\n `Wrote ${result.nodes} node${result.nodes === 1 ? \"\" : \"s\"} to ${result.outPath}`,\n );\n } catch (e) {\n fail(e);\n }\n },\n );\n\nreturn program;\n}\n","/**\n * What `-f` accepts, per verb.\n *\n * Each verb's renderer lives beside its command core (`renderCheck`,\n * `renderStats`, …); what belongs here is the *list*, stated once so the\n * union, the guard, the help text and the refusal sentence cannot drift\n * apart. It is the same shape a11y and cite keep (`A11Y_FORMATS`,\n * `REPORT_FORMATS`), which is why the sentence a user reads is the family's.\n *\n * Every verb takes `pretty | json`. `check` also takes `github`, because it is\n * the CI gate: it is the one graph verb whose output changes what a reviewer sees\n * on a pull request (proposal 0051 §2). It names its own list here rather than\n * widening the shared one, so no other verb advertises a format it cannot\n * render.\n */\n\n/** The list every graph verb's `-f` accepts, in the order messages list them. */\nexport const GRAPH_FORMATS = [\"pretty\", \"json\"] as const;\nexport type GraphFormat = (typeof GRAPH_FORMATS)[number];\n\n/** `\"pretty | json\"`, for help text and the refusal sentence. */\nexport const GRAPH_FORMAT_LIST: string = GRAPH_FORMATS.join(\" | \");\n\n/** `check`'s list: the shared two plus the CI annotation format. */\nexport const CHECK_FORMATS = [...GRAPH_FORMATS, \"github\"] as const;\nexport type CheckFormat = (typeof CHECK_FORMATS)[number];\n\n/** `\"pretty | json | github\"`, for help text and the refusal sentence. */\nexport const CHECK_FORMAT_LIST: string = CHECK_FORMATS.join(\" | \");\n","/**\n * `manni graph check` — graph-level validation: run the published SHACL shapes\n * (plus the TS-side SKOS integrity checks) over the built graph and report\n * findings with the doc paths responsible. Errors exit 1; warnings and\n * notices are reported but pass.\n */\nimport { resolve } from \"node:path\";\nimport type { Severity } from \"../../shared/severity.js\";\nimport { loadRunConfig } from \"../core/config.js\";\nimport { loadGraph, compactIri } from \"../core/load.js\";\nimport { bundledShapesPath } from \"../core/pkg.js\";\nimport { validateGraph, type CheckFinding } from \"../core/shacl.js\";\nimport { renderCheckGithub } from \"../reporters/github.js\";\nimport type { CheckFormat } from \"../reporters/index.js\";\n\nexport interface CheckOptions {\n config?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Graph .ttl path (default: config `out`). */\n graph?: string;\n /** Shapes .ttl paths (default: config `check.shapes`, then bundled). */\n shapes?: string[];\n cwd?: string;\n}\n\nexport interface CheckReport {\n findings: CheckFinding[];\n /** Counts on the family's scale, not SHACL's (proposal 0051 §2). */\n errors: number;\n warnings: number;\n notices: number;\n /** Shapes files used, as given (for reporting). */\n shapes: string[];\n exitCode: 0 | 1;\n}\n\nexport async function runCheck(opts: CheckOptions = {}): Promise<CheckReport> {\n const cwd = opts.cwd ?? process.cwd();\n const config = loadRunConfig(\n {\n ...(opts.config === undefined ? {} : { configPath: opts.config }),\n ...(opts.noConfig === undefined ? {} : { noConfig: opts.noConfig }),\n },\n cwd,\n );\n const store = loadGraph(resolve(cwd, opts.graph ?? config.out));\n\n // CLI flag over config over the bundled contract — same precedence as\n // every other knob.\n const shapesInput =\n opts.shapes && opts.shapes.length > 0 ? opts.shapes : config.check.shapes;\n const shapes =\n shapesInput.length > 0\n ? shapesInput.map((p) => resolve(cwd, p))\n : [bundledShapesPath(import.meta.url)];\n\n const findings = await validateGraph(store, shapes);\n const count = (severity: Severity): number =>\n findings.filter((f) => f.severity === severity).length;\n const errors = count(\"error\");\n\n return {\n findings,\n errors,\n warnings: count(\"warning\"),\n notices: count(\"notice\"),\n shapes,\n // Only an `error` fails the run; a warning and a notice are reported and\n // pass, as they were when they were called violations and warnings.\n exitCode: errors > 0 ? 1 : 0,\n };\n}\n\n/** `2 errors`, `1 warning`, `0 notices` — each count pluralized on its own. */\nfunction plural(n: number, word: string): string {\n return `${String(n)} ${word}${n === 1 ? \"\" : \"s\"}`;\n}\n\nexport function renderCheck(report: CheckReport, format: CheckFormat): string {\n if (format === \"json\") {\n const { exitCode: _exitCode, ...rest } = report;\n return JSON.stringify(rest, null, 2);\n }\n if (format === \"github\") return renderCheckGithub(report);\n const lines: string[] = [];\n for (const f of report.findings) {\n const where = f.docs.length > 0 ? ` [${f.docs.join(\", \")}]` : \"\";\n lines.push(\n `${f.severity}: ${compactIri(f.focusNode)}${\n f.path ? ` ${compactIri(f.path)}` : \"\"\n } — ${f.message}${where}`,\n );\n }\n if (report.findings.length > 0) lines.push(\"\");\n lines.push(\n `${plural(report.errors, \"error\")}, ${plural(report.warnings, \"warning\")}, ${plural(report.notices, \"notice\")}`,\n );\n return lines.join(\"\\n\");\n}\n","/**\n * `--format github`: one workflow-command annotation per `check` finding.\n *\n * `::error file=<first blamed doc>::<message> (<focus node>)`, with\n * `::warning` and `::notice` for the lower levels — the family scale is\n * GitHub's, so the level is the severity, exactly as a11y's and cite's\n * reporters have it.\n *\n * A SHACL finding carries no line number (stress test 5 of proposal 0051 says\n * why SARIF and JUnit are not here), and a finding about a shared node — a\n * concept, an agent, the scheme — may trace back to no document at all. Then\n * there is nothing to anchor to and the annotation goes out without `file=`,\n * which GitHub shows against the workflow run rather than dropping.\n *\n * Empty when the run is clean, so a clean CI step logs nothing.\n */\nimport {\n escapeWorkflowCommandMessage,\n escapeWorkflowCommandProperty,\n} from \"../../shared/github.js\";\nimport type { CheckReport } from \"../commands/check.js\";\nimport { compactIri } from \"../core/load.js\";\n\nexport function renderCheckGithub(report: CheckReport): string {\n const lines: string[] = [];\n for (const f of report.findings) {\n // The first, not all of them: one annotation lands on one file, and the\n // docs are sorted, so which one is stable across runs.\n const file = f.docs[0];\n const where =\n file === undefined ? \"\" : ` file=${escapeWorkflowCommandProperty(file)}`;\n const message = escapeWorkflowCommandMessage(\n `${f.message} (${compactIri(f.focusNode)})`,\n );\n lines.push(`::${f.severity}${where}::${message}`);\n }\n return lines.join(\"\\n\");\n}\n","/**\n * `manni graph init` — scaffold a starter `graph:` section in manni.config.yaml.\n *\n * The family file is shared with the other tools, so a file that already\n * exists is not overwritten: the section is appended to it, leaving the\n * siblings' keys and comments exactly as they were. A file that already has a\n * `graph:` key is refused.\n */\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { writeTextAtomic } from \"../../shared/write-file.js\";\nimport { GraphError } from \"../types.js\";\nimport { CONFIG_SECTION, DEFAULT_CONFIG_FILENAME } from \"../core/config.js\";\n\nconst HEADER = `# manni.config.yaml — shared configuration for the manni family of tools.\n# Each tool reads its own top-level key; manni graph reads \"graph:\".\n`;\n\nconst STARTER = `# Base IRI for every minted node. Set this to a namespace you control;\n# without it, IRIs fall back to the urn:manni:graph: placeholder.\n# baseIri: https://example.com/graph/\n\n# There is no document set here. \\`manni graph build\\` and \\`manni graph fill\\` read the\n# paths you name, or the collections declared once for every tool at the TOP\n# level of this file, beside \\`graph:\\` rather than inside it:\n#\n# collections:\n# - name: site\n# paths: [\"docs/**/*.md\"]\n#\n# Output of \\`manni graph build\\`.\nout: graph/graph.ttl\n\n# Map published-site routes back to source files so route-style links\n# (/docs/actions/find) become graph edges. A route may also carry the BCP-47\n# \\`language\\` labelling every document under its root; a page's own \\`lang\\`\n# frontmatter wins. Uncomment and adjust:\n# routes:\n# - basePath: /docs\n# root: docs\n# extensions: [.md, .mdx, .markdown]\n# indexFiles: [index, README]\n# - basePath: /docs/de\n# root: docs/de\n# language: de\n\n# What to derive triples from. Remove entries to opt out.\nbuild:\n derive: [frontmatter, sections, links, tags, images, code, provenance]\n\n# PROV-O settings. Git history is detected, not switched: per-file dates and\n# author agents, rename -> prov:wasRevisionOf, and the build activity's HEAD\n# committer date are derived wherever git can run over a repository, and a run\n# that cannot says so once and builds the rest. Deterministic per commit;\n# wall-clock time never enters the graph.\n# qualified: emit prov:qualifiedAttribution/qualifiedAssociation nodes\n# with roles alongside the direct properties.\nprovenance:\n qualified: true\n\n# Which fields a published graph may carry is read from x-manni-graph-output in\n# the schema set \\`manni meta validate\\` resolves for each page. Set that under\n# meta: (schemas, strict, register), not here. The default set keeps the\n# stewardship people fields (owner, stakeholders, reviewed-by) out.\n\n# SHACL shapes \\`manni graph check\\` validates the built graph against. Default:\n# the shapes contract bundled with manni (shapes/graph/shapes-1.0.0.ttl).\n# check:\n# shapes: [\"./my-shapes.ttl\"]\n\n# Metadata coverage gate for \\`manni graph stats --check\\`. A number applies to\n# every measured field; a map gates named fields only. Unset gates nothing.\n# stats:\n# coverageThreshold:\n# title: 100\n# description: 50\n\n# Which provider \\`manni graph fill\\` sends pages to. Unset, the family's\n# top-level providers: map decides, and then \\`auto\\`, which detects one: an\n# Anthropic key, then an OpenAI key, then the Claude CLI, then a local model.\n# Connection settings (apiKeyEnv, baseUrl, command) live in that map, declared\n# once for every manni tool. \\`--provider\\` wins over this, \\`--local\\` over both.\n# provider: anthropic # auto | anthropic | openai | claude-cli | llama-cpp\n# model: claude-sonnet-4-5 # the provider's default when omitted\n\n# LLM settings for \\`manni graph fill\\` (SKOS frontmatter proposals).\nfill:\n temperature: 0\n # Stop after this many inference calls. One page is one turn, and a cached\n # page spends none. Unset is unbounded.\n # maxTurns: 50\n cacheDir: .manni/graph/cache\n # fill proposes every field; confidence (0..1 per field) gates what is\n # written. Fields scored below the threshold are reported, not written.\n confidenceThreshold: 0.7\n # fields: defaults to every fillable field — uncomment to restrict.\n # Record meta-provenance (model + /graph/ pointers + confidence) on filled docs.\n writeProvenance: true\n # Reject proposals that would violate the SHACL shapes contract\n # (broader/narrower cycles, conflicting labels).\n validateGraph: true\n # Also propose per-section metadata. Off by default: it costs more output per\n # call, and section metadata is explicit-only, so review it as carefully.\n sections: false\n\n# Local embeddings for semantic search (\\`manni graph embed\\`). Needs the optional\n# peer: npm install @huggingface/transformers\n# embed:\n# model: onnx-community/granite-embedding-small-english-r2-ONNX\n# dtype: q8 # q8 keeps embedding reproducible across platforms\n# out: graph # directory for the per-language vector sidecars\n# cacheDir: .manni/graph/embed-cache\n\n# Optional enrichment for \\`manni graph export iirds\\` (the iiRDS package).\n# Absent, a minimal valid package is still produced.\n# export:\n# iirds:\n# title: My Docs # package title (default: \"manni graph export\")\n# creator: Acme Corp # Creator iirds:Party + vcard:Organization\n# version: \"1.3\" # iiRDS version literal: \"1.2\" | \"1.3\"\n`;\n\n/** The starter as a `graph:` section: every line nested one level. */\nfunction starterSection(): string {\n const body = STARTER.split(\"\\n\")\n .map((line) => (line === \"\" ? \"\" : ` ${line}`))\n .join(\"\\n\");\n return `${CONFIG_SECTION}:\\n${body}`;\n}\n\nexport async function runInit(cwd = process.cwd()): Promise<string> {\n const path = resolve(cwd, DEFAULT_CONFIG_FILENAME);\n if (!existsSync(path)) {\n await writeTextAtomic(path, `${HEADER}${starterSection()}`);\n return path;\n }\n\n // A family file is already here. Parse it to make sure a `graph:` key can be\n // appended: the document must be a mapping (or empty) without one.\n const text = readFileSync(path, \"utf8\");\n let doc: unknown;\n try {\n doc = parseYaml(text);\n } catch (e) {\n throw new GraphError(\n `Invalid YAML in ${DEFAULT_CONFIG_FILENAME}: ${errorMessage(e)}`,\n );\n }\n if (doc != null && (typeof doc !== \"object\" || Array.isArray(doc))) {\n throw new GraphError(\n `${DEFAULT_CONFIG_FILENAME}: top level must be a mapping — not adding a \\`${CONFIG_SECTION}:\\` section to it.`,\n );\n }\n if (doc != null && Object.hasOwn(doc, CONFIG_SECTION)) {\n throw new GraphError(\n `${DEFAULT_CONFIG_FILENAME} already has a \\`${CONFIG_SECTION}:\\` section — not overwriting.`,\n );\n }\n // Append as text rather than re-serialising the document, so the siblings'\n // keys and comments come out byte-for-byte as they went in.\n const separator = text === \"\" || text.endsWith(\"\\n\") ? \"\" : \"\\n\";\n const blank = text === \"\" ? \"\" : \"\\n\";\n await writeTextAtomic(\n path,\n `${text}${separator}${blank}${starterSection()}`,\n );\n return path;\n}\n","/**\n * The lint program. Named `lint` because that is where it is mounted\n * (`manni lint …`); `src/cli.ts` adds it to the umbrella and runs it. Thin\n * commander wrapper over the command cores. Follows clig.dev: primary output to\n * stdout, diagnostics to stderr, color only on a TTY (and never under\n * NO_COLOR/--no-color), meaningful exit codes.\n *\n * Grammar per proposal 0034: the verbs are `check`, `structure`, `templates`\n * and `tools`, and there is no default subcommand, so a bare `manni lint` is a\n * usage error that lists them. `check` runs every configured job; `structure`\n * runs one of them, and carries the options that belong to the tool performing\n * it.\n *\n * Exit codes are the contract CI reads:\n * 0 every file linted clean\n * 1 the run produced findings\n * 2 the tool could not do its job - bad usage, missing template, unreadable\n * input. A LintError is always this, never a lint failure.\n *\n * The 1/2 split is what lets a workflow tell \"the docs are wrong\" apart from\n * \"the linter is misconfigured\", which a single non-zero exit cannot.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport {\n collect,\n configOption,\n explicitFalse,\n readStdin,\n reportConfig,\n splitList,\n} from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport {\n OMITTED_WHEN_CLEAN,\n REPORT_FORMAT_LIST,\n STDIN_TOKEN,\n} from \"../meta/internal.js\";\nimport {\n REPORT_FORMATS,\n isReportFormat,\n type ReportFormat as FamilyFormat,\n} from \"../meta/index.js\";\nimport { LintError } from \"./types.js\";\nimport { runLint } from \"./commands/lint.js\";\nimport { runTemplates, runTemplatesInfer } from \"./commands/templates.js\";\nimport { runTools } from \"./commands/tools.js\";\nimport { INFER_FORMATS, isInferFormat, type InferFormat } from \"./core/infer.js\";\nimport {\n LINT_JOBS,\n TOOLS_BY_JOB,\n loadConfig,\n rebaseConfig,\n} from \"./core/config.js\";\nimport { resolveStructureTool } from \"./tools/index.js\";\nimport {\n render,\n renderTemplates,\n renderTools,\n type ListFormat,\n type ReportFormat,\n} from \"./reporters/index.js\";\n\n/** The options `check` and `structure` share, in the family's spelling. */\ninterface InputCliOptions {\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 <format>`: force a parser. */\n as?: string;\n /**\n * `-c, --config <path>` and `--no-config` share one commander attribute:\n * `undefined` with neither flag, the path with `-c`, `false` with\n * `--no-config`. Split by `configOption`.\n */\n config?: string | boolean;\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n gitignore: boolean;\n /** `-f, --format <format>`. Always a string: the declaration has a default. */\n format: string;\n}\n\n/** `structure` adds the options of the tool that performs the job. */\ninterface StructureCliOptions extends InputCliOptions {\n tool?: string;\n template?: string;\n /** `--templates <path>`, repeatable; commander's default value is `[]`. */\n templates: string[];\n explain?: boolean;\n}\n\n/** What commander parses for `templates`. */\ninterface TemplatesCommandOptions {\n templates: string[];\n config?: string | boolean;\n format: string;\n}\n\n/** What commander parses for `templates infer`. */\ninterface TemplatesInferCliOptions {\n as?: string;\n name?: string;\n config?: string | boolean;\n format: string;\n out?: string;\n force?: boolean;\n}\n\n/** What commander parses for `tools`. */\ninterface ToolsCommandOptions {\n config?: string | boolean;\n format: string;\n}\n\n// `explain` is reachable through `--explain`, not `-f`: it reports on\n// configuration rather than on documents, and offering it as a format would\n// invite `-f explain` alongside a lint that then never happens. The `-f` set\n// itself is the family's, from meta, rather than a fourth hand-kept copy of\n// the same five words.\nconst LIST_FORMATS = new Set<string>([\"pretty\", \"json\"]);\n\n/** The heading the tool's own options print under, after the shared ones. */\nconst TOOL_OPTIONS_GROUP = \"Tool options:\";\n\nfunction resolveColor(program: Command): boolean {\n // commander maps --no-color to opts.color === false.\n const noColor = program.opts().color === false;\n return shouldColor({ noColor, isTTY: process.stdout.isTTY });\n}\n\nfunction reportFormat(value: unknown): FamilyFormat {\n const format = String(value);\n if (!isReportFormat(format)) {\n throw new LintError(\n `Unknown --format \"${format}\". Use ${REPORT_FORMAT_LIST}.`,\n );\n }\n return format;\n}\n\n/**\n * Whether a clean run may print nothing at all in this format.\n *\n * Only `github` may: an empty annotation stream is a clean check. Every other\n * format owes its envelope - an empty JSON array, a SARIF log with no results,\n * a JUnit suite of passing testcases - because a consumer parsing stdout must\n * not have to treat \"no output\" as a third outcome. `explain` is never clean\n * or dirty; it always has something to say.\n */\nfunction omittedWhenClean(format: ReportFormat): boolean {\n return format !== \"explain\" && OMITTED_WHEN_CLEAN.has(format);\n}\n\nfunction listFormat(value: unknown): ListFormat {\n const format = String(value);\n if (!LIST_FORMATS.has(format)) {\n throw new LintError(\n `Unknown --format \"${format}\". Use pretty or json.`,\n );\n }\n return format as ListFormat;\n}\n\n/**\n * `templates infer -f`: the format a *template file* is written in, which is\n * not the set a report is rendered in. A template is YAML or JSON because those\n * are the two the loader reads back, and `pretty` would name a third thing the\n * tool cannot then load.\n */\nfunction inferFormat(value: unknown): InferFormat {\n const format = String(value);\n if (!isInferFormat(format)) {\n throw new LintError(`Unknown --format \"${format}\". Use yaml or json.`);\n }\n return format;\n}\n\n/**\n * `--tool <name>`: which tool performs the structure job. Refused by name\n * rather than ignored, because falling through to manni's engine would lint\n * with something other than what was asked for and say nothing.\n *\n * The refusal is the registry's, not a second copy of it here. `runLint`\n * refuses the same name with the same sentence for a caller that never touches\n * commander; this one fires first, so a bad `--tool` is reported before the\n * run asks what it was pointed at.\n */\nfunction assertStructureTool(value: string | undefined): void {\n if (value === undefined) return;\n resolveStructureTool(value);\n}\n\n/**\n * `-c/--config` and `--no-config`, in one place.\n *\n * Every verb here takes them, and they had been written out three times. A flag\n * two commands both have carries the same name *and* the same description, so\n * the declaration is shared rather than copied - which is what kept the fourth\n * copy, on `templates infer`, from spelling either of them slightly differently.\n */\nfunction withConfigOptions(command: Command): Command {\n return command\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\");\n}\n\n/**\n * The value of a flag a command and its parent both declare.\n *\n * Commander keeps parsing a parent's options past a subcommand name unless\n * `enablePositionalOptions()` is on, so `templates infer page.md -f json` sets\n * `format` on `templates` and leaves `infer` holding its own default. Both\n * commands declare `-f`, `-c` and `--no-config`, because \"commands must have\n * parallel behaviors\" and `infer` must list them in its own `--help`.\n *\n * Turning positional options on would fix it and move every other flag in this\n * program with it: `manni lint structure docs/ --no-color` is a root option\n * written after its command, and there are three more like it. So the lookup\n * changes instead. The nearest command actually *given* the flag wins, and the\n * subcommand's own default is the fallback - which is the reading a person\n * typing the line already has.\n */\nfunction optionValue(command: Command, key: string): unknown {\n for (\n let cmd: Command | null = command;\n cmd !== null;\n cmd = cmd.parent ?? null\n ) {\n if (cmd.getOptionValueSource(key) === \"cli\") return cmd.getOptionValue(key);\n }\n return command.getOptionValue(key);\n}\n\n/** The options every job verb takes, in one place so the two cannot drift. */\nfunction withInputOptions(command: Command): Command {\n command\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to lint (use - for stdin)\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\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 (e.g. markdown, mdx)\")\n .option(\n \"-f, --format <format>\",\n `output: ${REPORT_FORMATS.join(\" | \")}`,\n \"pretty\",\n );\n return withConfigOptions(command)\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"lint files .gitignore covers\");\n}\n\n/** The lint options every job verb turns its shared flags into. */\nfunction inputOptions(\n paths: string[],\n options: InputCliOptions,\n): {\n inputs: string[];\n collection: string[];\n exts?: string[];\n exclude: string[];\n as?: string;\n configPath?: string;\n noConfig?: boolean;\n allowEmpty?: boolean;\n respectGitignore?: boolean;\n onNotice: (message: string) => void;\n} {\n return {\n inputs: paths,\n collection: options.collection,\n ...(options.ext ? { exts: splitList(options.ext) } : {}),\n exclude: options.exclude,\n ...(options.as === undefined ? {} : { as: options.as }),\n ...configOption(options.config),\n // `undefined` rather than `false` when absent, so config still wins.\n ...(options.allowEmpty ? { allowEmpty: true } : {}),\n respectGitignore: explicitFalse(options.gitignore),\n onNotice: notice,\n };\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"lint\")\n .description(\n \"Validate document structure against doctype templates. Deterministic, CI-friendly.\",\n )\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n .showHelpAfterError()\n // Exit code 1 is reserved for \"the docs are wrong\". Commander exits 1 on a\n // usage error by default, which would make a typo'd flag look exactly like\n // a failing lint to a workflow. With no callback, commander throws the\n // CommanderError instead, and the umbrella's runner maps it: help and\n // --version stay 0, every other usage error becomes 2. Commander has\n // already written its own message. This has to precede .command(), which\n // copies the callback into each subcommand.\n .exitOverride();\n\n /** Run one lint, render it, and settle the exit code. Both job verbs share it. */\n const lint = async (\n paths: string[],\n options: StructureCliOptions | InputCliOptions,\n command: Command,\n job: { tool?: StructureCliOptions } = {},\n ): Promise<void> => {\n const tool = job.tool;\n const format = reportFormat(options.format);\n const explain = tool?.explain === true;\n const stdinContent = paths.includes(STDIN_TOKEN) ? await readStdin() : undefined;\n const cwd = process.cwd();\n\n const run = await runLint({\n ...inputOptions(paths, options),\n ...(tool?.tool === undefined ? {} : { tool: tool.tool }),\n ...(tool?.template === undefined ? {} : { template: tool.template }),\n ...(tool && tool.templates.length > 0 ? { templates: tool.templates } : {}),\n ...(explain ? { explain: true } : {}),\n ...(stdinContent === undefined ? {} : { stdinContent }),\n // Which config governed the run, said where a report cannot be parsed\n // around: discovery walks up to the project boundary, so an unexpected\n // ancestor config is the difference between a five-minute diagnosis and\n // an hour of confusion.\n onConfigLoaded: reportConfig(format === \"pretty\", cwd),\n });\n\n const color = resolveColor(command.parent ?? command);\n const chosen: ReportFormat = explain ? \"explain\" : format;\n const text = render(run, chosen, { color });\n if (text.length > 0 || !omittedWhenClean(chosen)) {\n process.stdout.write(`${text}\\n`);\n }\n // `--explain` answers a question about configuration, so its exit code\n // reports whether it could answer it - not whether the docs are clean.\n //\n // That covers routing failures too: a page whose `type` matches no\n // template is a answered question, not an unanswered one, so it exits 0\n // like everything else here. Automation must not read this code as\n // \"everything routed\" - the ordinary run is what reports that, with exit\n // 1. Said in `--help` and the README, because the distinction is invisible\n // from the exit code alone.\n process.exitCode = explain ? 0 : run.summary.failed > 0 ? 1 : 0;\n };\n\n withInputOptions(\n program\n .command(\"check\")\n .description(\"Run every configured lint job over the given files/dirs/globs\"),\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Jobs: structure.\",\n \"\",\n \"Examples:\",\n \" manni lint check docs/ # every configured job\",\n \" manni lint check # targets from collections:\",\n \" manni lint check --collection guides\",\n ' manni lint check \"**/*.md\" -f github # CI annotations',\n \" cat page.md | manni lint check - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: InputCliOptions, command: Command) => {\n try {\n // Which jobs this run covered, said once, beside the config line. The\n // full form also names the jobs that exist and are not configured;\n // `structure` is the only job there is, so today it is one word.\n if (options.format === \"pretty\") {\n process.stderr.write(`Checked: ${LINT_JOBS.join(\", \")}.\\n`);\n }\n await lint(paths, options, command);\n } catch (err) {\n fail(err);\n }\n });\n\n const structure = withInputOptions(\n program\n .command(\"structure\")\n .description(\n \"Lint document structure against doctype templates, routing each page by its `type`\",\n ),\n );\n structure\n .optionsGroup(TOOL_OPTIONS_GROUP)\n .option(\n \"--tool <name>\",\n `tool that performs the job: ${TOOLS_BY_JOB.structure.join(\", \")}`,\n )\n .option(\n \"-t, --template <ref>\",\n \"apply this template to every file, overriding type routing\",\n )\n .option(\n \"--templates <path>\",\n \"template file to route by: its `types:` win over built-ins; repeatable\",\n collect,\n [],\n )\n .option(\n \"--explain\",\n \"print how each file's template was chosen, and lint nothing (always exits 0, unrouted pages included)\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni lint structure docs/ # route each page by its `type`\",\n \" manni lint structure docs/ --templates ./templates.yaml # add your own templates\",\n \" manni lint structure # targets from collections:\",\n \" manni lint structure docs/ --explain # show why each page routed where\",\n \" manni lint structure page.md -t tgdp:how-to:1.6 # force one template\",\n ' manni lint structure \"**/*.md\" -f github # CI annotations',\n \" manni lint structure docs/ --exclude '**/drafts/**'\",\n \" cat page.md | manni lint structure - -t tgdp:how-to:1.6 --as markdown\",\n ].join(\"\\n\"),\n )\n .action(\n async (paths: string[], options: StructureCliOptions, command: Command) => {\n try {\n assertStructureTool(options.tool);\n await lint(paths, options, command, { tool: options });\n } catch (err) {\n fail(err);\n }\n },\n );\n\n const templates = program\n .command(\"templates\")\n .description(\"List the templates that can be applied, and the types they serve\")\n .option(\n \"--templates <path>\",\n \"also list the templates in this file; repeatable\",\n collect,\n [],\n );\n withConfigOptions(templates)\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .action(async (options: TemplatesCommandOptions, command: Command) => {\n try {\n const format = listFormat(options.format);\n // The listing answers \"what could route a page?\", so it has to see the\n // same template files a lint would - rebased the same way, or it would\n // answer for a different set of files depending on where it was run.\n const { configPath, noConfig } = configOption(options.config);\n const found = noConfig ? null : await loadConfig(configPath);\n const info = await runTemplates({\n templates:\n options.templates.length > 0\n ? options.templates\n : rebaseConfig(found).templates,\n });\n const color = resolveColor(command.parent ?? command);\n process.stdout.write(`${renderTemplates(info, format, { color })}\\n`);\n } catch (err) {\n fail(err);\n }\n });\n\n const inferCommand = templates\n .command(\"infer\")\n .description(\"Write a first template from a page that already has the shape you want\")\n .argument(\"<page>\", \"one file to infer from (use - for stdin)\")\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"--name <name>\",\n \"name for the template; defaults to the page's `type`, else its filename\",\n )\n .option(\"-f, --format <format>\", `output: ${INFER_FORMATS.join(\" | \")}`, \"yaml\")\n .option(\"-o, --out <path>\", \"write the template here instead of to stdout\")\n .option(\"--force\", \"overwrite the --out path\");\n withConfigOptions(inferCommand)\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni lint templates infer docs/guides/install.md\",\n \" manni lint templates infer docs/guides/install.md --name how-to\",\n \" manni lint templates infer page.mdx -f json\",\n \" manni lint templates infer page.md -o ./templates.yaml\",\n \" manni lint templates infer page.md -o ./templates.yaml --force\",\n \" cat page.md | manni lint templates infer - --as markdown\",\n \"\",\n \"One page, and every rule it writes is exactly one occurrence: a single\",\n \"page cannot show what varies. Loosening a heading into a list or a\",\n \"pattern, setting `min: 0`, and adding a trailing rule with no heading\",\n \"for the sections that may follow are your edits to make.\",\n ].join(\"\\n\"),\n )\n .action(\n async (\n page: string,\n options: TemplatesInferCliOptions,\n command: Command,\n ) => {\n try {\n // `-f`, `-c` and `--no-config` are read through `optionValue`: the\n // parent `templates` declares all three, and commander hands it any\n // of them typed after `infer`.\n const format = inferFormat(optionValue(command, \"format\"));\n const { configPath, noConfig } = configOption(\n optionValue(command, \"config\"),\n );\n const stdinContent =\n page === STDIN_TOKEN ? await readStdin() : undefined;\n const result = await runTemplatesInfer({\n page,\n format,\n ...(options.as === undefined ? {} : { as: options.as }),\n ...(options.name === undefined ? {} : { name: options.name }),\n ...(options.out === undefined ? {} : { out: options.out }),\n ...(options.force === undefined ? {} : { force: options.force }),\n ...(configPath === undefined ? {} : { configPath }),\n ...(noConfig === undefined ? {} : { noConfig }),\n ...(stdinContent === undefined ? {} : { stdinContent }),\n // The template is the primary output, so with no --out it owns\n // stdout and the config line goes to stderr beside it. With --out\n // stdout is free, and the line still belongs on stderr: a reader\n // piping nothing is not a reason to move a diagnostic.\n onConfigLoaded: reportConfig(false, process.cwd()),\n });\n\n if (result.written === undefined) {\n process.stdout.write(result.text);\n return;\n }\n // Said on stderr, so `-o` leaves stdout empty for a shell that is\n // watching it, and the template file is the whole output.\n process.stderr.write(\n `Wrote template \"${result.name}\" to ${result.written}\\n`,\n );\n } catch (err) {\n fail(err);\n }\n },\n );\n\n withConfigOptions(\n program\n .command(\"tools\")\n .description(\n \"List the lint jobs, the tool that performs each, and what it reads\",\n ),\n )\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .action(async (options: ToolsCommandOptions, command: Command) => {\n try {\n const format = listFormat(options.format);\n const tools = await runTools(configOption(options.config));\n const color = resolveColor(command.parent ?? command);\n process.stdout.write(`${renderTools(tools, format, { color })}\\n`);\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n","/**\n * The `term` domain's commander program. Mounted by `src/cli.ts` under\n * `manni term`; no entry point of its own. Grammar per proposal 0034: the verbs\n * are `list`, `get`, `check`, `lint`, `write` and `formats`, and there is no\n * default subcommand.\n *\n * Follows clig.dev as the family does: primary output to stdout, diagnostics\n * and notices to stderr, colour only on a TTY and never under\n * `NO_COLOR`/`--no-color`, exit `0` clean, `1` an error-severity finding or a\n * `--check` that found drift, `2` operational/usage.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { collect, readStdin, 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 { OMITTED_WHEN_CLEAN, STDIN_TOKEN } from \"../meta/internal.js\";\nimport { runCheck } from \"./commands/check.js\";\nimport { FINDING_FORMATS, type FindingFormat, type TermReport } from \"./commands/findings.js\";\nimport { FORMATS_FORMATS, listFormats } from \"./commands/formats.js\";\nimport { GET_FORMATS, runGet } from \"./commands/get.js\";\nimport { runLint } from \"./commands/lint.js\";\nimport { LIST_FORMATS, runList } from \"./commands/list.js\";\nimport { formatChoice, type TermCommandOptions } from \"./commands/run.js\";\nimport { runWrite, writeFormats } from \"./commands/write.js\";\nimport { renderListCsv } from \"./reporters/csv.js\";\nimport { renderFindingsGithub } from \"./reporters/github.js\";\nimport { renderFindingsJson, renderFormatsJson, renderGetJson, renderListJson } from \"./reporters/json.js\";\nimport { renderFindingsJunit } from \"./reporters/junit.js\";\nimport {\n renderFindingsPretty,\n renderFormatsPretty,\n renderGetPretty,\n renderListPretty,\n renderValeWiring,\n renderWritePretty,\n} from \"./reporters/pretty.js\";\nimport { renderFindingsSarif } from \"./reporters/sarif.js\";\nimport { registerTermLabelSource } from \"../shared/term-labels.js\";\nimport { termLabels } from \"./commands/labels.js\";\n\n// The umbrella loads this module, so under the `manni` bin `meta fill` offers\n// the termbase's labels. The `docmeta` bin never loads it, and offers none.\nregisterTermLabelSource(termLabels);\n\n/** What commander hands every verb that reads terms. */\ninterface InputCliOptions {\n as?: string;\n /** `--ext <list>`, comma-separated and given once. */\n ext?: string;\n /** `--exclude <glob>`, repeatable; commander's default value is `[]`. */\n exclude: string[];\n /** `--allow-empty`. */\n allowEmpty?: boolean;\n /** `--no-gitignore`: `false` when given. */\n gitignore: boolean;\n /** `--collection <name>`, repeatable; commander's default value is `[]`. */\n collection: string[];\n config?: string;\n /** `--no-color`: `false` when given. */\n color: boolean;\n}\n\ninterface FormatCliOptions extends InputCliOptions {\n format: string;\n}\n\ninterface CheckCliOptions extends FormatCliOptions {\n baseline?: boolean;\n}\n\ninterface WriteCliOptions extends InputCliOptions {\n format?: string;\n out?: string;\n check?: boolean;\n dryRun?: boolean;\n}\n\n/** Colour for a verb's pretty output: off under `--no-color` or `NO_COLOR`, on only for a TTY. */\nfunction colorFor(options: InputCliOptions): boolean {\n return shouldColor({ noColor: !options.color, isTTY: process.stdout.isTTY });\n}\n\n/** The core's shared options from commander's, with stdin read once when `-` is among the paths. */\nasync function coreOptions(paths: string[], options: InputCliOptions): Promise<TermCommandOptions> {\n return {\n inputs: paths,\n ...(paths.includes(STDIN_TOKEN) ? { stdin: await readStdin() } : {}),\n ...(options.as === undefined ? {} : { as: options.as }),\n ...(options.ext === undefined ? {} : { exts: splitList(options.ext) }),\n exclude: options.exclude,\n collection: options.collection,\n ...(options.allowEmpty === true ? { allowEmpty: true } : {}),\n ...(options.gitignore ? {} : { noGitignore: true }),\n ...(options.config === undefined ? {} : { configPath: options.config }),\n onNotice: notice,\n };\n}\n\n/** The shared input flags, declared once so every verb spells them alike. */\nfunction withInputs(command: Command): Command {\n return command\n .option(\"--as <format>\", \"input format for stdin (-)\")\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--collection <name>\", \"configured collection to read; repeatable\", collect, [])\n .option(\"--allow-empty\", \"treat a missing path, no matched files or no terms as success\")\n .option(\"--no-gitignore\", \"read files .gitignore covers\")\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-color\", \"disable colored output\");\n}\n\nfunction print(text: string): void {\n process.stdout.write(`${text}\\n`);\n}\n\nfunction renderFindings(report: TermReport, format: FindingFormat, options: InputCliOptions, references: boolean): void {\n let text: string;\n switch (format) {\n case \"pretty\":\n text = renderFindingsPretty(report, { color: colorFor(options), references });\n break;\n case \"json\":\n text = renderFindingsJson(report);\n break;\n case \"github\":\n text = renderFindingsGithub(report);\n break;\n case \"sarif\":\n text = renderFindingsSarif(report, { onNotice: notice });\n break;\n case \"junit\":\n text = renderFindingsJunit(report);\n break;\n }\n if (text.length > 0 || !OMITTED_WHEN_CLEAN.has(format)) print(text);\n process.exitCode = report.summary.failed > 0 ? 1 : 0;\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"term\")\n .description(\"Check, lint and render a docset's terms and the references into them.\")\n .version(pkg.version, \"-V, --version\")\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: commander copies the exit\n // callback into each subcommand by value when the subcommand is created.\n .exitOverride();\n\n withInputs(\n program\n .command(\"list\")\n .description(\"List the resolved entries\")\n .argument(\"[paths...]\", \"files, directories, or globs to read (use - for stdin)\"),\n )\n .option(\"-f, --format <format>\", `output: ${LIST_FORMATS.join(\" | \")}`, \"pretty\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni term list # every collection\",\n \" manni term list docs/terms/ # one directory\",\n \" manni term list -f csv | head -2 # for a script\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: FormatCliOptions) => {\n try {\n const format = formatChoice(options.format, LIST_FORMATS);\n const { terms } = await runList(await coreOptions(paths, options));\n print(format === \"json\" ? renderListJson(terms) : format === \"csv\" ? renderListCsv(terms) : renderListPretty(terms));\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n withInputs(\n program\n .command(\"get\")\n .description(\"Show one entry\")\n .argument(\"<term>\", \"the entry's id, or its label or an alt-label in any case\")\n .argument(\"[paths...]\", \"files, directories, or globs to read (use - for stdin)\"),\n )\n .option(\"-f, --format <format>\", `output: ${GET_FORMATS.join(\" | \")}`, \"pretty\")\n .addHelpText(\n \"after\",\n [\"\", \"Examples:\", \" manni term get progressive-lens\", ' manni term get \"progressive lens\" -f json'].join(\"\\n\"),\n )\n .action(async (term: string, paths: string[], options: FormatCliOptions) => {\n try {\n const format = formatChoice(options.format, GET_FORMATS);\n const found = await runGet({ ...(await coreOptions(paths, options)), term });\n print(format === \"json\" ? renderGetJson(found) : renderGetPretty(found, { color: colorFor(options) }));\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n withInputs(\n program\n .command(\"check\")\n .description(\"Check the set and every reference into it\")\n .argument(\"[paths...]\", \"files, directories, or globs to read (use - for stdin)\"),\n )\n .option(\"-f, --format <format>\", `output: ${FINDING_FORMATS.join(\" | \")}`, \"pretty\")\n .option(\"--baseline\", \"record the findings on the first run; after that, fail only on new ones\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni term check # every collection\",\n \" manni term check -f github # CI annotations\",\n \" manni term check --baseline # ramp in on an existing docset\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: CheckCliOptions) => {\n try {\n const format = formatChoice(options.format, FINDING_FORMATS);\n const report = await runCheck({\n ...(await coreOptions(paths, options)),\n ...(options.baseline === true ? { baseline: true } : {}),\n });\n renderFindings(report, format, options, true);\n } catch (err) {\n fail(err);\n }\n });\n\n withInputs(\n program\n .command(\"lint\")\n .description(\"Run Vale over the definitions\")\n .argument(\"[paths...]\", \"files, directories, or globs to read (use - for stdin)\"),\n )\n .option(\"-f, --format <format>\", `output: ${FINDING_FORMATS.join(\" | \")}`, \"pretty\")\n .addHelpText(\n \"after\",\n [\"\", \"Examples:\", \" manni term lint\", \" manni term lint -f github\"].join(\"\\n\"),\n )\n .action(async (paths: string[], options: FormatCliOptions) => {\n try {\n const format = formatChoice(options.format, FINDING_FORMATS);\n const report = await runLint(await coreOptions(paths, options));\n renderFindings(report, format, options, false);\n } catch (err) {\n fail(err);\n }\n });\n\n withInputs(\n program\n .command(\"write\")\n .description(\"Write the set back, or render it elsewhere\")\n .argument(\"[paths...]\", \"files, directories, or globs to read (use - for stdin)\"),\n )\n .option(\"-f, --format <format>\", `render as: ${writeFormats().join(\" | \")} (default: each entry's own, in place)`)\n .option(\"-o, --out <path>\", \"file or directory to render into; a trailing / means a directory\")\n .option(\"--check\", \"write nothing; exit 1 when the target differs from the render\")\n .option(\"--dry-run\", \"write nothing; print what would change\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni term write # each entry back to its source\",\n \" manni term write -f json -o build/terms.json\",\n \" manni term write -f vale # into Vale's styles directory\",\n \" manni term write -f vale --check # keep the style in step\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: WriteCliOptions) => {\n try {\n const report = await runWrite({\n ...(await coreOptions(paths, options)),\n ...(options.format === undefined ? {} : { format: options.format }),\n ...(options.out === undefined ? {} : { out: options.out }),\n ...(options.check === true ? { check: true } : {}),\n ...(options.dryRun === true ? { dryRun: true } : {}),\n });\n print(renderWritePretty(report));\n if (report.wiring !== undefined) process.stderr.write(`${renderValeWiring(report.wiring)}\\n`);\n process.exitCode = report.check && report.changes.length > 0 ? 1 : 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"formats\")\n .description(\"List the constructs read and written, per format\")\n .option(\"-f, --format <format>\", `output: ${FORMATS_FORMATS.join(\" | \")}`, \"pretty\")\n .action((options: { format: string }) => {\n try {\n const format = formatChoice(options.format, FORMATS_FORMATS);\n const rows = listFormats();\n print(format === \"json\" ? renderFormatsJson(rows) : renderFormatsPretty(rows));\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n","/**\n * `manni term check`: the referential integrity of the set (proposal 0052 § 7),\n * with the baseline ratchet meta and cite use.\n *\n * `--baseline` is one flag for both halves of the ratchet. When the baseline\n * file is not there yet, the run records one and exits 0: that is how a docset\n * whose terms were never checked ramps in. When it is there, the run fails only\n * on findings it does not hold. A configured `term.baseline` compares without\n * the flag, as `cite.baseline` does.\n */\nimport { existsSync } from \"node:fs\";\nimport { resolveBaselineRequest, settleBaseline } from \"../../meta/internal.js\";\nimport { checkTermSet } from \"../core/check.js\";\nimport { DEFAULT_TERM_BASELINE_PATH } from \"../core/config.js\";\nimport { TermError } from \"../errors.js\";\nimport { reportedFindings, summarize, toResults, type TermReport } from \"./findings.js\";\nimport { loadTerms, type TermCommandOptions } from \"./run.js\";\n\nexport interface CheckOptions extends TermCommandOptions {\n /** `--baseline`. */\n baseline?: boolean;\n}\n\nexport async function runCheck(opts: CheckOptions): Promise<TermReport> {\n const { cwd, run, set } = await loadTerms(opts);\n const config = run.config;\n const findings = checkTermSet(set, {\n ...(config?.severity === undefined ? {} : { severity: config.severity }),\n ...(config?.abstractMaxLength === undefined ? {} : { abstractMaxLength: config.abstractMaxLength }),\n });\n const { results, origin } = toResults(set, findings);\n\n // Fingerprints must not depend on where the command was run from.\n const frame = { cwd, base: run.configDir ?? cwd, runBase: run.base };\n let request = resolveBaselineRequest(\n opts.baseline === true ? { baseline: true } : {},\n config?.baseline,\n run.configDir,\n cwd,\n { current: DEFAULT_TERM_BASELINE_PATH },\n );\n if (request !== null && !existsSync(request.absPath)) {\n if (opts.baseline !== true) {\n throw new TermError(\n `Baseline \"${request.label}\" not found. Record one with \\`manni term check --baseline\\`.`,\n );\n }\n request = { ...request, write: true };\n }\n const { results: reported, baseline } = await settleBaseline(results, request, frame);\n\n return {\n findings: reportedFindings(reported, origin),\n results: reported,\n summary: summarize(reported, baseline),\n frame,\n terms: set.terms.length,\n references: set.references.length,\n ...(baseline === undefined ? {} : { baseline }),\n found: findings.length,\n cwd,\n };\n}\n","/**\n * The `term:` section of manni.config.yaml, and the run resolution every\n * command shares (proposal 0052). It follows cite's rules: positional inputs\n * resolve from cwd, a collection's `paths` and `term.manifests` from the config\n * directory. Unknown keys, rules or levels are errors that name what is\n * supported and never echo a value.\n *\n * Two things a reader might look for here are not `term:` keys. The document\n * set is the family `collections:` (proposal 0041). Vale's config path is the\n * family `tools.vale.config`, because Vale is not the term tool's alone.\n * Both are refused by name under `term:`, so the mistake says where the\n * setting went rather than calling it a typo.\n */\nimport { resolve } from \"node:path\";\nimport { selectCollections } from \"../../shared/collections.js\";\nimport {\n findConfigFile,\n readConfigFile,\n type ConfigFile,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport { SEVERITIES } from \"../../shared/severity.js\";\nimport { TermError } from \"../errors.js\";\nimport {\n TERM_RULES,\n type LoadedTermConfig,\n type TermConfig,\n type TermRule,\n type TermRun,\n type TermSeverity,\n} from \"../types.js\";\n\nexport const TERM_SECTION = \"term\";\n\nexport const DEFAULT_TERM_BASELINE_PATH = \".manni-term-baseline.json\";\n\nexport const DEFAULT_ABSTRACT_MAX_LENGTH = 60;\n\n/** The keys `term:` accepts, in the order the reference table lists them. */\nconst CONFIG_KEYS: readonly (keyof TermConfig)[] = [\n \"manifests\",\n \"abstractMaxLength\",\n \"baseline\",\n \"severity\",\n \"allowEmpty\",\n \"respectGitignore\",\n];\n\n/** Keys that belong to the family, refused by name with where they live. */\nconst COLLECTION_KEYS: readonly string[] = [\"paths\", \"exclude\"];\nconst TOOL_KEYS: readonly string[] = [\"vale\"];\n\n/** The family scale, least severe first as the reference spells it, then `off`. */\nconst SEVERITY_LEVELS: readonly TermSeverity[] = [...SEVERITIES, \"off\"];\n\nconst CONFIG_FILE: ConfigFileOptions = {\n section: TERM_SECTION,\n legacyNames: [],\n toError: (message) => new TermError(message),\n};\n\nfunction isMapping(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isLevel(value: unknown): value is TermSeverity {\n return typeof value === \"string\" && (SEVERITY_LEVELS as readonly string[]).includes(value);\n}\n\nfunction isTermRule(value: string): value is TermRule {\n return (TERM_RULES as readonly string[]).includes(value);\n}\n\nfunction rejectUnknownKeys(\n obj: Record<string, unknown>,\n allowed: readonly string[],\n where: string,\n source: string,\n): void {\n for (const key of Object.keys(obj)) {\n if (!allowed.includes(key)) {\n throw new TermError(\n `Unknown key \"${key}\" under ${where}: in ${source}. Supported keys: ${allowed.join(\", \")}.`,\n );\n }\n }\n}\n\n/**\n * Every type error names the key and the type it wanted, and nothing else. A\n * value can be a secret pasted under the wrong key, and quoting it would put it\n * in a CI log.\n */\nfunction wrongType(key: string, expected: string, source: string): TermError {\n return new TermError(`term.${key} in ${source} must be ${expected}.`);\n}\n\nfunction asBoolean(value: unknown, key: string, source: string): boolean {\n if (typeof value !== \"boolean\") throw wrongType(key, \"a boolean\", source);\n return value;\n}\n\nfunction asString(value: unknown, key: string, source: string): string {\n if (typeof value !== \"string\") throw wrongType(key, \"a string\", source);\n return value;\n}\n\nfunction asStringList(value: unknown, key: string, source: string): string[] {\n if (\n !Array.isArray(value) ||\n !value.every((item): item is string => typeof item === \"string\" && item.trim() !== \"\")\n ) {\n throw wrongType(key, \"a list of non-empty strings\", source);\n }\n return value;\n}\n\nfunction asNonNegativeInteger(value: unknown, key: string, source: string): number {\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 0) {\n throw wrongType(key, \"a non-negative integer\", source);\n }\n return value;\n}\n\nfunction parseSeverity(value: unknown, source: string): Partial<Record<TermRule, TermSeverity>> {\n if (!isMapping(value)) throw wrongType(\"severity\", \"a mapping\", source);\n rejectUnknownKeys(value, TERM_RULES, \"term.severity\", source);\n const severity: Partial<Record<TermRule, TermSeverity>> = {};\n for (const [rule, level] of Object.entries(value)) {\n if (!isTermRule(rule)) continue;\n if (!isLevel(level)) {\n // A level is not a secret, so a string one is quoted back: `eror` reads\n // as the typo it is. Anything else is described without its value.\n const quoted = typeof level === \"string\" ? ` \"${level}\"` : \"\";\n throw new TermError(\n `${source}: term.severity.${rule}${quoted} is not a level. Expected ${SEVERITY_LEVELS.join(\" | \")}.`,\n );\n }\n severity[rule] = level;\n }\n return severity;\n}\n\n/**\n * Validate the `term:` slice of a family file. `raw` is `null` for an empty\n * section, which is the same as no keys at all.\n */\nexport function parseTermConfig(raw: unknown, source: string): TermConfig {\n if (raw == null) return {};\n if (!isMapping(raw)) {\n throw new TermError(`term: in ${source} must be a mapping.`);\n }\n // Before the unknown-key check, which would call a family setting a typo.\n for (const key of COLLECTION_KEYS) {\n if (Object.hasOwn(raw, key)) {\n throw new TermError(\n `${source}: term does not carry \"${key}\". Name a collection under collections:.`,\n );\n }\n }\n for (const key of TOOL_KEYS) {\n if (Object.hasOwn(raw, key)) {\n throw new TermError(\n `${source}: term does not carry \"${key}\". Vale's settings live under tools.${key}.`,\n );\n }\n }\n rejectUnknownKeys(raw, CONFIG_KEYS, \"term\", source);\n\n const config: TermConfig = {};\n if (raw.manifests !== undefined) config.manifests = asStringList(raw.manifests, \"manifests\", source);\n if (raw.abstractMaxLength !== undefined) {\n config.abstractMaxLength = asNonNegativeInteger(raw.abstractMaxLength, \"abstractMaxLength\", source);\n }\n if (raw.baseline !== undefined) config.baseline = asString(raw.baseline, \"baseline\", source);\n if (raw.severity !== undefined) config.severity = parseSeverity(raw.severity, source);\n if (raw.allowEmpty !== undefined) config.allowEmpty = asBoolean(raw.allowEmpty, \"allowEmpty\", source);\n if (raw.respectGitignore !== undefined) {\n config.respectGitignore = asBoolean(raw.respectGitignore, \"respectGitignore\", source);\n }\n return config;\n}\n\n/** The family file, found by discovery or named with `-c`, before its `term:` slice is parsed. */\nexport function readTermConfigFile(\n explicitPath: string | undefined,\n cwd: string,\n): Promise<ConfigFile | null> {\n return explicitPath\n ? readConfigFile(explicitPath, cwd, CONFIG_FILE)\n : findConfigFile(cwd, CONFIG_FILE);\n}\n\nfunction toLoaded(file: ConfigFile): LoadedTermConfig {\n return {\n config: parseTermConfig(file.value, file.source),\n path: file.path,\n dir: file.dir,\n source: file.source,\n collections: file.collections,\n tools: file.tools,\n };\n}\n\n/** Load the config from an explicit path, or by discovery. `null` when discovery finds nothing. */\nexport async function loadTermConfig(\n explicitPath?: string,\n cwd: string = process.cwd(),\n): Promise<LoadedTermConfig | null> {\n const file = await readTermConfigFile(explicitPath, cwd);\n return file === null ? null : toLoaded(file);\n}\n\nexport interface TermRunOptions {\n cwd: string;\n /** `-c/--config`. */\n configPath?: string;\n /** Skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Positional inputs; empty means fall back to the selected collections' `paths:`. */\n inputs: string[];\n /** `--collection <name>`, repeatable. Empty means every declared collection. */\n collection?: string[];\n onConfigLoaded?: (info: { path: string; dir: string }) => void;\n}\n\n/** The stdin token, repeated so this module does not depend on the file loader. */\nconst STDIN = \"-\";\n\n/**\n * Settle what every command core needs before it touches a file: which config\n * governs the run, what to resolve and from where, the manifests, and the\n * family's tools.\n */\nexport async function resolveTermRun(opts: TermRunOptions): Promise<TermRun> {\n const cwd = resolve(opts.cwd);\n\n // The same two sentences meta, a11y and cite use. Stdin is one more input\n // rather than a path, so it rides beside the flag.\n const wanted = opts.collection ?? [];\n if (wanted.length > 0 && opts.inputs.some((input) => input !== STDIN)) {\n throw new TermError(\n \"--collection selects a configured collection; it cannot be combined with paths.\",\n );\n }\n\n const file = opts.noConfig ? null : await readTermConfigFile(opts.configPath, cwd);\n const loaded = file === null ? null : toLoaded(file);\n if (wanted.length > 0 && loaded === null) {\n throw new TermError(\"--collection needs a config file to select from.\");\n }\n if (loaded) opts.onConfigLoaded?.({ path: loaded.path, dir: loaded.dir });\n\n const collections = loaded\n ? selectCollections(loaded.collections, wanted, loaded.source, (message) => new TermError(message))\n : [];\n\n const fromCollections = opts.inputs.length === 0;\n const inputs = fromCollections ? collections.flatMap((c) => c.paths) : opts.inputs;\n const base = fromCollections && inputs.length > 0 && loaded ? loaded.dir : cwd;\n\n const manifests = loaded\n ? (loaded.config.manifests ?? []).map((written) => ({ path: resolve(loaded.dir, written), written }))\n : [];\n\n return {\n config: loaded ? loaded.config : null,\n inputs,\n base,\n collections,\n fromCollections,\n manifests,\n tools: loaded ? loaded.tools : {},\n ...(loaded ? { configDir: loaded.dir, configPath: loaded.path, configSource: loaded.source } : {}),\n ...(file === null ? {} : { configFile: file }),\n };\n}\n","import { ToolError } from \"../shared/errors.js\";\n\n/** An operational or usage error in the term tool: exit 2. */\nexport class TermError extends ToolError {\n constructor(message: string) {\n super(message);\n this.name = \"TermError\";\n }\n}\n","/**\n * The term tool's contract (proposal 0052). Every reader produces a `Term`,\n * every writer consumes one, and `check` and `lint` work on a `TermSet`. So a\n * new construct is one reader and one writer, and nothing after reading\n * changes, the same rule `MetadataExtractor` keeps for metadata.\n *\n * A term's record keeps the vocabulary's own kebab-case spelling\n * (`alt-labels`, `scope-note`), because it is the same record a page carries\n * and the one `term list -f json` prints. docevals keeps its eval entries in\n * frontmatter spelling for the same reason.\n */\nimport type { CollectionConfig } from \"../shared/collections.js\";\nimport type { ConfigFile } from \"../shared/config-file.js\";\nimport type { Severity } from \"../shared/severity.js\";\nimport type { ToolsConfig } from \"../shared/tools.js\";\n\n// ---------------------------------------------------------------------------\n// The record\n\n/** The ten fields of `manni:terminology:1.0.0`, in the order the reference lists them. */\nexport const TERM_FIELDS = [\n \"label\",\n \"definition\",\n \"abstract\",\n \"alt-labels\",\n \"hidden-labels\",\n \"broader\",\n \"narrower\",\n \"related-terms\",\n \"see\",\n \"scope-note\",\n] as const;\nexport type TermField = (typeof TERM_FIELDS)[number];\n\n/** The fields that hold a list. The vocabulary accepts a string or a list; a reader always yields a list. */\nexport const TERM_LIST_FIELDS = [\n \"alt-labels\",\n \"hidden-labels\",\n \"broader\",\n \"narrower\",\n \"related-terms\",\n] as const satisfies readonly TermField[];\nexport type TermListField = (typeof TERM_LIST_FIELDS)[number];\n\n/**\n * One term's fields, as the vocabulary names them.\n *\n * Normalized by every reader: a list field is a non-empty array of non-empty\n * strings, or absent. A string field is a non-empty string, or absent. An\n * empty value is never carried, so two sets read from different constructs\n * compare equal when they say the same thing. `definition` is required by the\n * vocabulary but absent here when a construct cannot hold one: an HTML `<dfn>`\n * names a term without defining it.\n */\nexport interface TermRecord {\n label: string;\n definition?: string;\n abstract?: string;\n \"alt-labels\"?: string[];\n \"hidden-labels\"?: string[];\n broader?: string[];\n narrower?: string[];\n \"related-terms\"?: string[];\n see?: string;\n \"scope-note\"?: string;\n}\n\n/** Every construct a term is read from. Each has exactly one reader. */\nexport const TERM_CONSTRUCTS = [\n /** The metadata channel of a one-term file, in any of the six formats. */\n \"page\",\n /** A YAML or JSON file listed under `term.manifests`. */\n \"manifest\",\n \"dita-glossentry\",\n \"dita-glossgroup\",\n \"docbook-glossary\",\n \"html-dl\",\n \"html-dfn\",\n /** Markdown and MDX. */\n \"markdown-deflist\",\n \"asciidoc-glossary\",\n \"rst-glossary\",\n] as const;\nexport type TermConstruct = (typeof TERM_CONSTRUCTS)[number];\n\n/** Where a term was read from, precisely enough to report on it and to write it back. */\nexport interface TermLocation {\n /** The file as the user would name it: posix, relative to where it was resolved. `<stdin>` for stdin. */\n file: string;\n /** Absolute path. Absent for stdin, which has nowhere to write back to. */\n path?: string;\n construct: TermConstruct;\n /** 1-based line the entry starts on. */\n line: number;\n /**\n * 1-based line of each field the reader could place. A lint finding sits on\n * its field's line; a field with no entry here sits on `line`.\n */\n fieldLines: Partial<Record<TermField, number>>;\n /**\n * The entry's UTF-16 offsets in the file's content, `[start, end)`, for a\n * body construct that is written back in place. Absent for `page` and\n * `manifest`, which are written through their own channel.\n */\n span?: { start: number; end: number };\n}\n\nexport interface Term {\n /**\n * The term's identity: the record's `id` where it has one, else the\n * construct's own identifier (`<dt id>`, `xml:id`, a DITA topic `@id`), else\n * the GitHub slug of `label`.\n */\n id: string;\n record: TermRecord;\n /** `language` from the file's metadata, when it carries one. */\n language?: string;\n location: TermLocation;\n}\n\n// ---------------------------------------------------------------------------\n// Reading\n\n/** One loaded file, as every reader sees it. */\nexport interface TermInput {\n content: string;\n /** As `TermLocation.file`. */\n file: string;\n /** As `TermLocation.path`. */\n path?: string;\n /** The extractor that read the file (`markdown`, `mdx`, `asciidoc`, `rst`, `html`, `xml`), or `manifest`. */\n format: string;\n /** The file's extracted metadata. `{}` for a manifest, which has none. */\n metadata: Record<string, unknown>;\n /** The extractor's JSON-Pointer line lookup for `metadata`. */\n lineFor: (pointer: string) => number | undefined;\n}\n\nexport interface TermReadResult {\n terms: Term[];\n /**\n * An entry the reader skipped, and why, said once per entry: a `<dt>` with no\n * term text, a glossentry with no `<glossterm>`. Reported as a notice, not a\n * finding, because no rule governs a construct manni could not read.\n */\n notices: string[];\n}\n\n/**\n * The read seam for one construct, and its in-place write where it has one.\n * Writability is derived from `apply` being present, as it is for an extractor.\n */\nexport interface TermReader {\n construct: TermConstruct;\n /** What `term formats` prints for it: `page`, `definition list`, `DITA glossentry`. */\n label: string;\n /** The `TermInput.format` values this construct appears in. */\n formats: readonly string[];\n /**\n * Every entry this construct holds in one file. `{ terms: [], notices: [] }`\n * when the file holds none, which is most files: the loader offers every file\n * of a matching format to every reader. Throws `TermError` only for a file\n * the construct claims and cannot parse.\n */\n read(this: void, input: TermInput): TermReadResult;\n /**\n * Rewrite this construct's entries in `input.content` from `terms`, which are\n * the terms this reader read from the same file, possibly edited. Returns the\n * new content. Absent for a construct that is not written in place.\n */\n apply?(this: void, input: TermInput, terms: readonly Term[]): string;\n}\n\n// ---------------------------------------------------------------------------\n// Writing\n\n/** Every `term write -f` value. */\nexport const TERM_WRITE_FORMATS = [\n \"markdown\",\n \"mdx\",\n \"asciidoc\",\n \"rst\",\n \"html\",\n \"dita\",\n \"docbook\",\n \"tbx\",\n \"skos\",\n \"csv\",\n \"json\",\n \"vale\",\n] as const;\nexport type TermWriteFormat = (typeof TERM_WRITE_FORMATS)[number];\n\n/** The path decides the shape: a directory gets one file per term, a file gets every term. */\nexport type TermShape = \"file\" | \"directory\";\n\nexport interface TermTarget {\n /** Absolute. */\n path: string;\n shape: TermShape;\n}\n\nexport interface TermRenderContext {\n /**\n * The files already under the target, absolute path to content. A writer that\n * owns a directory reads it: the Vale writer finds its own marked files to\n * remove, and refuses to replace a file it did not write.\n */\n existing: ReadonlyMap<string, string>;\n}\n\nexport interface RenderedFile {\n /** Absolute. */\n path: string;\n content: string;\n}\n\nexport interface DroppedField {\n id: string;\n field: TermField;\n}\n\nexport interface TermRender {\n files: RenderedFile[];\n /** Absolute paths the render owns and no longer produces. */\n removals: string[];\n /** Fields the target construct cannot hold, per term written. */\n dropped: DroppedField[];\n /**\n * Ids of the terms left out, in set order, because the target construct's\n * reader could not read them back: a definition list entry with no\n * definition. `[]` when every term was written.\n */\n skipped: string[];\n}\n\n/**\n * The render seam for one `-f` value. Pure: it computes files and never touches\n * the disk, so `--dry-run` and `--check` run the same code as a write.\n */\nexport interface TermWriter {\n format: TermWriteFormat;\n /** The shapes this format is written in. `tbx` is a file only; `vale` is a directory only. */\n shapes: readonly TermShape[];\n /** The fields a render in `shape` keeps. Everything else lands in `dropped`. */\n holds(this: void, shape: TermShape): readonly TermField[];\n /** Throws `TermError` for a target it refuses, such as a Vale style it did not write. */\n render(this: void, terms: readonly Term[], target: TermTarget, context: TermRenderContext): TermRender;\n}\n\n// ---------------------------------------------------------------------------\n// The set\n\n/** A page's claim that it is about a term: one value of `concepts:` or `graph.concepts`. */\nexport interface TermReference {\n file: string;\n line?: number;\n label: string;\n}\n\nexport interface TermSet {\n terms: Term[];\n /** Every `concepts:` and `graph.concepts` value in every file the run loaded. */\n references: TermReference[];\n /** Readers' notices, in load order. */\n notices: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Findings\n\n/** Every rule `term check` reports, stated once. The default severities derive from this order. */\nexport const TERM_RULES = [\n \"undefined-term\",\n \"duplicate-id\",\n \"label-collision\",\n \"alt-label-collision\",\n \"dangling-reference\",\n \"broader-cycle\",\n \"see-not-empty\",\n \"asymmetric-hierarchy\",\n \"abstract-too-long\",\n \"unused-term\",\n] as const;\nexport type TermRule = (typeof TERM_RULES)[number];\n\n/** A rule's level: the family scale plus `off`, which drops the rule's findings. */\nexport type TermSeverity = Severity | \"off\";\n\n/** Vale's own severity scale, kept beside the family's on a lint finding. */\nexport type ValeSeverity = \"error\" | \"warning\" | \"suggestion\";\n\nexport interface TermFinding {\n /** `manni:term/<rule>` from `check`; `manni:term/prose/<Style.Rule>` from `lint`. */\n ruleId: string;\n severity: Severity;\n message: string;\n file: string;\n line?: number;\n /** The entry the finding is about, when it is about one. */\n id?: string;\n /** Set on a `check` finding. */\n rule?: TermRule;\n /** Set on a `lint` finding: the tool that raised it. */\n tool?: \"vale\";\n /** Set on a `lint` finding: the tool's own rule name, `Direct.Length`. */\n check?: string;\n /** Set on a `lint` finding: the tool's own severity, before the fold. */\n toolSeverity?: ValeSeverity;\n /**\n * The field the finding concerns: on a `lint` finding, the field the prose\n * came from; on a `check` finding, the field that breaks the rule. Absent\n * for a finding about a whole entry (`duplicate-id`, `unused-term`) or about\n * a page (`undefined-term`).\n */\n field?: TermField;\n}\n\n// ---------------------------------------------------------------------------\n// Config\n\n/** The `term:` section. Every key is optional; a docset with none needs no section. */\nexport interface TermConfig {\n manifests?: string[];\n abstractMaxLength?: number;\n baseline?: string;\n severity?: Partial<Record<TermRule, TermSeverity>>;\n allowEmpty?: boolean;\n respectGitignore?: boolean;\n}\n\nexport interface LoadedTermConfig {\n config: TermConfig;\n path: string;\n dir: string;\n /** The file as the user would name it, for messages. */\n source: string;\n collections: CollectionConfig[];\n tools: ToolsConfig;\n}\n\n/** One `term.manifests` entry. */\nexport interface TermManifest {\n /** Absolute, resolved against the config directory. */\n path: string;\n /** As the config spells it, for messages. */\n written: string;\n}\n\n/** What every command core resolves before touching a file. */\nexport interface TermRun {\n config: TermConfig | null;\n /** The positional inputs, or the selected collections' `paths:` in declaration order. */\n inputs: string[];\n /** Directory `inputs` resolve from: cwd for positional inputs, the config directory for collections. */\n base: string;\n collections: CollectionConfig[];\n fromCollections: boolean;\n /** The `term.manifests` files, in the order the config lists them. */\n manifests: TermManifest[];\n /** The family `tools:`. `{}` when no config governs the run. */\n tools: ToolsConfig;\n configDir?: string;\n configPath?: string;\n configSource?: string;\n configFile?: ConfigFile;\n}\n","/**\n * Rule ids and levels for the term tool (proposal 0052). `check` findings are\n * `manni:term/<rule>`. A `lint` finding keeps Vale's own rule name,\n * `manni:term/prose/<Style.Rule>`, in the shape lint's proposal 0050 set for\n * its prose job, because that is the name Vale's documentation uses.\n */\nimport type { Severity } from \"../../shared/severity.js\";\nimport { TERM_RULES, type TermRule, type TermSeverity, type ValeSeverity } from \"../types.js\";\n\nexport const RULE_ID_PREFIX = \"manni:term\";\n\nexport const DEFAULT_SEVERITY: Readonly<Record<TermRule, TermSeverity>> = {\n \"undefined-term\": \"error\",\n \"duplicate-id\": \"error\",\n \"label-collision\": \"error\",\n \"alt-label-collision\": \"error\",\n \"dangling-reference\": \"error\",\n \"broader-cycle\": \"error\",\n \"see-not-empty\": \"error\",\n \"asymmetric-hierarchy\": \"warning\",\n \"abstract-too-long\": \"notice\",\n \"unused-term\": \"notice\",\n};\n\nexport function ruleId(rule: TermRule): string {\n return `${RULE_ID_PREFIX}/${rule}`;\n}\n\nexport function proseRuleId(check: string): string {\n return `${RULE_ID_PREFIX}/prose/${check}`;\n}\n\nexport function isTermRule(value: string): value is TermRule {\n return (TERM_RULES as readonly string[]).includes(value);\n}\n\n/** The defaults with config's overrides laid over them. */\nexport function resolveSeverity(\n overrides?: Partial<Record<TermRule, TermSeverity>>,\n): Record<TermRule, TermSeverity> {\n return { ...DEFAULT_SEVERITY, ...overrides };\n}\n\n/**\n * Vale's scale onto the family's. A finding keeps Vale's own value beside the\n * folded one, as an a11y violation keeps axe's `impact`.\n */\nexport function foldValeSeverity(severity: ValeSeverity): Severity {\n return severity === \"suggestion\" ? \"notice\" : severity;\n}\n","/**\n * `term check`'s rules (proposal 0052 § 7): the referential integrity of a term\n * set. Pure: it reads records and references and returns findings, so the\n * command core owns every file and the rules are tested on sets built inline.\n *\n * Every label comparison ignores case, because the Vale style `write -f vale`\n * renders is a `swap` map keyed on the lowercased term. Two labels that differ\n * only in case collide there silently, so they collide here out loud. Ids\n * compare ignoring case too, because references resolve them that way.\n */\nimport { TERM_RELATION_FIELDS } from \"../../shared/reference-fields.js\";\nimport { DEFAULT_ABSTRACT_MAX_LENGTH } from \"./config.js\";\nimport { resolveSeverity, ruleId } from \"./severity.js\";\nimport type { Term, TermField, TermFinding, TermRule, TermSet, TermSeverity } from \"../types.js\";\n\nexport interface CheckTermSetOptions {\n severity?: Partial<Record<TermRule, TermSeverity>>;\n /** Default `DEFAULT_ABSTRACT_MAX_LENGTH`. */\n abstractMaxLength?: number;\n}\n\n/** The fields whose values name other entries. */\nconst REFERENCE_FIELDS = TERM_RELATION_FIELDS;\ntype ReferenceField = (typeof REFERENCE_FIELDS)[number];\n\ninterface Draft {\n rule: TermRule;\n message: string;\n file: string;\n line?: number;\n id?: string;\n field?: TermField;\n}\n\nexport function checkTermSet(set: TermSet, opts: CheckTermSetOptions = {}): TermFinding[] {\n const levels = resolveSeverity(opts.severity);\n const maxLength = opts.abstractMaxLength ?? DEFAULT_ABSTRACT_MAX_LENGTH;\n const { terms } = set;\n const drafts: Draft[] = [];\n\n const fold = (value: string): string => value.toLowerCase();\n const where = (t: Term): string => `${t.location.file}:${String(t.location.line)}`;\n const onEntry = (t: Term, rule: TermRule, message: string, field?: TermField): Draft => ({\n rule,\n message,\n file: t.location.file,\n line: (field === undefined ? undefined : t.location.fieldLines[field]) ?? t.location.line,\n id: t.id,\n ...(field === undefined ? {} : { field }),\n });\n\n // The first entry claiming each folded label, and each folded id.\n const byLabel = new Map<string, number>();\n const byId = new Map<string, number>();\n terms.forEach((t, index) => {\n const label = fold(t.record.label);\n if (!byLabel.has(label)) byLabel.set(label, index);\n const id = fold(t.id);\n if (!byId.has(id)) byId.set(id, index);\n });\n const resolveReference = (value: string): number | undefined =>\n byLabel.get(fold(value)) ?? byId.get(fold(value));\n\n // undefined-term, and the folded labels some page names, for unused-term.\n const referenced = new Set<string>();\n for (const reference of set.references) {\n const label = fold(reference.label);\n referenced.add(label);\n if (byLabel.has(label)) continue;\n let message = `concepts: \"${reference.label}\" names no entry.`;\n const synonym = terms.find((t) => (t.record[\"alt-labels\"] ?? []).some((alt) => fold(alt) === label));\n if (synonym !== undefined) {\n message += ` \"${synonym.record.label}\" lists it as an alt-label.`;\n }\n drafts.push({\n rule: \"undefined-term\",\n message,\n file: reference.file,\n ...(reference.line === undefined ? {} : { line: reference.line }),\n });\n }\n\n // duplicate-id: ignoring case, as references resolve ids, on every entry\n // sharing the id.\n const sharing = new Map<string, Term[]>();\n for (const t of terms) {\n const id = fold(t.id);\n const group = sharing.get(id);\n if (group === undefined) sharing.set(id, [t]);\n else group.push(t);\n }\n for (const group of sharing.values()) {\n if (group.length < 2) continue;\n for (const t of group) {\n const others = group.filter((other) => other !== t).map(where);\n drafts.push(onEntry(t, \"duplicate-id\", `id: \"${t.id}\" is also used by ${others.join(\", \")}`));\n }\n }\n\n terms.forEach((t, index) => {\n // label-collision: on each later entry, naming the first.\n const first = byLabel.get(fold(t.record.label));\n const firstTerm = first === undefined ? undefined : terms[first];\n if (first !== undefined && first !== index && firstTerm !== undefined) {\n drafts.push(\n onEntry(\n t,\n \"label-collision\",\n `\"${t.record.label}\" is claimed by ${where(firstTerm)} as \"${firstTerm.record.label}\"`,\n \"label\",\n ),\n );\n }\n\n // alt-label-collision: an alt-label that is another entry's label.\n for (const alt of t.record[\"alt-labels\"] ?? []) {\n const owner = terms.find((other, otherIndex) => otherIndex !== index && fold(other.record.label) === fold(alt));\n if (owner !== undefined) {\n drafts.push(\n onEntry(t, \"alt-label-collision\", `alt-labels: \"${alt}\" is the label of ${where(owner)}`, \"alt-labels\"),\n );\n }\n }\n\n // dangling-reference: one finding per value that resolves to nothing.\n for (const field of REFERENCE_FIELDS) {\n for (const value of referenceValues(t, field)) {\n if (resolveReference(value) === undefined) {\n drafts.push(onEntry(t, \"dangling-reference\", `${field}: \"${value}\" names no entry`, field));\n }\n }\n }\n\n // see-not-empty: a redirect carries no definition.\n if (t.record.see !== undefined && t.record.definition !== undefined) {\n drafts.push(\n onEntry(t, \"see-not-empty\", `see: \"${t.record.see}\" redirects this entry, so remove its definition`, \"see\"),\n );\n }\n\n // abstract-too-long.\n const abstract = t.record.abstract;\n if (abstract !== undefined && abstract.length > maxLength) {\n drafts.push(\n onEntry(\n t,\n \"abstract-too-long\",\n `abstract: ${String(abstract.length)} characters is over the limit of ${String(maxLength)}, so shorten it`,\n \"abstract\",\n ),\n );\n }\n\n // unused-term: no reference names the label.\n if (!referenced.has(fold(t.record.label))) {\n drafts.push(onEntry(t, \"unused-term\", \"no page's concepts: names this term\"));\n }\n });\n\n // The resolved hierarchy, one edge per pair.\n const edges = (field: \"broader\" | \"narrower\"): Set<number>[] =>\n terms.map((t) => {\n const targets = new Set<number>();\n for (const value of referenceValues(t, field)) {\n const target = resolveReference(value);\n if (target !== undefined) targets.add(target);\n }\n return targets;\n });\n const broader = edges(\"broader\");\n const narrower = edges(\"narrower\");\n\n // asymmetric-hierarchy: each missing half, on the entry that should carry it.\n terms.forEach((t, index) => {\n for (const parent of broader[index] ?? []) {\n const parentTerm = terms[parent];\n if (parentTerm !== undefined && !(narrower[parent]?.has(index) ?? false)) {\n drafts.push(\n onEntry(\n parentTerm,\n \"asymmetric-hierarchy\",\n `narrower: omits \"${t.record.label}\", which lists this entry as broader`,\n \"narrower\",\n ),\n );\n }\n }\n for (const child of narrower[index] ?? []) {\n const childTerm = terms[child];\n if (childTerm !== undefined && !(broader[child]?.has(index) ?? false)) {\n drafts.push(\n onEntry(\n childTerm,\n \"asymmetric-hierarchy\",\n `broader: omits \"${t.record.label}\", which lists this entry as narrower`,\n \"broader\",\n ),\n );\n }\n }\n });\n\n // broader-cycle: every elementary cycle once, found from its earliest entry.\n for (const [start, path] of broaderCycles(broader)) {\n const startTerm = terms[start];\n if (startTerm === undefined) continue;\n const labels = [...path, start].map((index) => terms[index]?.record.label ?? \"\");\n drafts.push(onEntry(startTerm, \"broader-cycle\", `broader: ${labels.join(\" > \")}`, \"broader\"));\n }\n\n const findings: TermFinding[] = [];\n for (const draft of drafts) {\n const level = levels[draft.rule];\n if (level === \"off\") continue;\n findings.push({\n rule: draft.rule,\n ruleId: ruleId(draft.rule),\n severity: level,\n message: draft.message,\n file: draft.file,\n ...(draft.line === undefined ? {} : { line: draft.line }),\n ...(draft.id === undefined ? {} : { id: draft.id }),\n ...(draft.field === undefined ? {} : { field: draft.field }),\n });\n }\n return findings.sort(compareFindings);\n}\n\nfunction referenceValues(t: Term, field: ReferenceField): string[] {\n const value = t.record[field];\n if (value === undefined) return [];\n return typeof value === \"string\" ? [value] : value;\n}\n\n/**\n * Each elementary cycle of the `broader` graph, as its start and the path from\n * it. A search from `start` only visits later entries, so a cycle is found\n * exactly once, from the entry of it that comes first in set order.\n */\nfunction broaderCycles(broader: readonly Set<number>[]): [number, number[]][] {\n const cycles: [number, number[]][] = [];\n for (let start = 0; start < broader.length; start++) {\n const path: number[] = [start];\n const onPath = new Set<number>([start]);\n const walk = (node: number): void => {\n for (const next of broader[node] ?? []) {\n if (next === start) {\n cycles.push([start, [...path]]);\n } else if (next > start && !onPath.has(next)) {\n path.push(next);\n onPath.add(next);\n walk(next);\n path.pop();\n onPath.delete(next);\n }\n }\n };\n walk(start);\n }\n return cycles;\n}\n\nfunction compareText(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\nfunction compareFindings(a: TermFinding, b: TermFinding): number {\n return (\n compareText(a.file, b.file) ||\n (a.line ?? 0) - (b.line ?? 0) ||\n compareText(a.ruleId, b.ruleId) ||\n compareText(a.message, b.message)\n );\n}\n","/**\n * The report `check` and `lint` share, and the bridge from term findings to\n * meta's `ValidationResult`, so the SARIF and JUnit renderers and the baseline\n * ratchet work unchanged, as cite's adapter does for citations.\n *\n * FieldError: schema `manni:term` (a builtin-shaped ref, so fingerprints and\n * rule ids never depend on where the command ran), keyword = the rule id after\n * `manni:term/`, instancePath `/<field>` when the finding concerns one field\n * and `\"\"` when it concerns none (`undefined-term`, `duplicate-id`,\n * `unused-term`). A check finding and a lint finding carry the field the same\n * way. The subject is the entry, the field, and what the finding says, with any\n * `file:line` taken out: a line moves when a page is edited above the entry,\n * and a moved finding is not a new one.\n */\nimport {\n isErrorSeverity,\n type BaselineSummary,\n type FieldError,\n type FingerprintContext,\n type RunSummary,\n type ValidationResult,\n} from \"../../meta/index.js\";\nimport { RULE_ID_PREFIX } from \"../core/severity.js\";\nimport type { TermFinding, TermSet } from \"../types.js\";\n\nexport const FINDING_FORMATS = [\"pretty\", \"json\", \"github\", \"sarif\", \"junit\"] as const;\nexport type FindingFormat = (typeof FINDING_FORMATS)[number];\n\n/** JUnit `classname` for the term tool's findings. */\nexport const JUNIT_CLASSNAME = \"manni.term\";\n\n/** What `check` and `lint` return. */\nexport interface TermReport {\n /** The findings reported: a baselined one is not among them. */\n findings: TermFinding[];\n /** The same findings as meta's results, for SARIF and JUnit. One per file. */\n results: ValidationResult[];\n summary: RunSummary;\n frame: FingerprintContext;\n /** Entries in the set. */\n terms: number;\n /** `concepts:` values the run read. */\n references: number;\n /** How a baseline shaped the run, when one did. */\n baseline?: BaselineSummary;\n /** Findings before the baseline, for the line a recording run prints. */\n found: number;\n /** Where the run stood, for the paths the reporters print. */\n cwd: string;\n}\n\nconst LINE_REFERENCE = /:\\d+\\b/g;\n\nfunction toFieldError(finding: TermFinding): FieldError {\n const keyword = finding.ruleId.startsWith(`${RULE_ID_PREFIX}/`)\n ? finding.ruleId.slice(RULE_ID_PREFIX.length + 1)\n : finding.ruleId;\n const { field } = finding;\n const subject = [finding.id ?? \"\", field ?? \"\", finding.message.replace(LINE_REFERENCE, \"\")].join(\"\\u0000\");\n const error: FieldError = {\n schema: RULE_ID_PREFIX,\n instancePath: field === undefined ? \"\" : `/${field}`,\n message: finding.message,\n keyword,\n subject,\n severity: finding.severity,\n };\n if (finding.line !== undefined) error.line = finding.line;\n return error;\n}\n\n/**\n * One result per file: every file a term was read from, clean or not, and\n * every file a finding sits in. `origin` maps each error back to its finding.\n */\nexport function toResults(\n set: TermSet,\n findings: readonly TermFinding[],\n): { results: ValidationResult[]; origin: Map<FieldError, TermFinding> } {\n const origin = new Map<FieldError, TermFinding>();\n const byFile = new Map<string, FieldError[]>();\n for (const term of set.terms) {\n if (!byFile.has(term.location.file)) byFile.set(term.location.file, []);\n }\n for (const finding of findings) {\n const error = toFieldError(finding);\n origin.set(error, finding);\n const list = byFile.get(finding.file) ?? [];\n list.push(error);\n byFile.set(finding.file, list);\n }\n const results = [...byFile.keys()].sort().map((file): ValidationResult => {\n const errors = byFile.get(file) ?? [];\n return { file, format: \"term\", ok: !errors.some(isErrorSeverity), schemas: [RULE_ID_PREFIX], errors };\n });\n return { results, origin };\n}\n\n/** The run summary meta's renderers read, from results a baseline may have thinned. */\nexport function summarize(results: readonly ValidationResult[], baseline?: BaselineSummary): RunSummary {\n const failed = results.filter((r) => !r.ok).length;\n const count = (keep: (e: FieldError) => boolean): number =>\n results.reduce((n, r) => n + r.errors.filter(keep).length, 0);\n const warnings = count((e) => e.severity === \"warning\");\n const notices = count((e) => e.severity === \"notice\");\n return {\n files: results.length,\n passed: results.length - failed,\n failed,\n errors: count(isErrorSeverity),\n ...(warnings > 0 ? { warnings } : {}),\n ...(notices > 0 ? { notices } : {}),\n ...(baseline ? { baseline } : {}),\n };\n}\n\n/** The findings still reported once a baseline has thinned the results. */\nexport function reportedFindings(\n results: readonly ValidationResult[],\n origin: ReadonlyMap<FieldError, TermFinding>,\n): TermFinding[] {\n const kept: TermFinding[] = [];\n for (const result of results) {\n for (const error of result.errors) {\n const finding = origin.get(error);\n if (finding !== undefined) kept.push(finding);\n }\n }\n return kept.sort(compareFindings);\n}\n\nfunction compareFindings(a: TermFinding, b: TermFinding): number {\n if (a.file !== b.file) return a.file < b.file ? -1 : 1;\n const lineA = a.line ?? 0;\n const lineB = b.line ?? 0;\n if (lineA !== lineB) return lineA - lineB;\n if (a.ruleId !== b.ruleId) return a.ruleId < b.ruleId ? -1 : 1;\n return a.message < b.message ? -1 : a.message > b.message ? 1 : 0;\n}\n","/**\n * What every `manni term` command core shares: resolve the run, load the set,\n * and say the readers' notices. Kept free of commander and of stdout, so a core\n * is called directly by its tests; the CLI reads stdin once and hands it in.\n */\nimport { existsSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport { valeConfigPath } from \"../../shared/tools.js\";\nimport { resolveTermRun } from \"../core/config.js\";\nimport { loadTermSet } from \"../core/load-set.js\";\nimport { TermError } from \"../errors.js\";\nimport type { TermReader, TermRun, TermSet } from \"../types.js\";\n\n/** The inputs and flags `list`, `get`, `check`, `lint` and `write` share. */\nexport interface TermCommandOptions {\n /** Default `process.cwd()`. */\n cwd?: string;\n /** Positional `[paths...]`; `-` is stdin. Empty falls back to the collections. */\n inputs: string[];\n /** Stdin's content, read once by the CLI when `-` is among the inputs. */\n stdin?: string;\n /** `--as <format>`. */\n as?: string;\n /** `--exclude <glob>`, repeatable. */\n exclude?: string[];\n /** `--ext <list>`, already split. */\n exts?: string[];\n /** `--allow-empty`. */\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n noGitignore?: boolean;\n /** `--collection <name>`, repeatable. */\n collection?: string[];\n /** `-c, --config <path>`. */\n configPath?: string;\n /** Readers' notices and the loader's. */\n onNotice?: (message: string) => void;\n /** The readers to offer files to. Tests hand in their own. */\n readers?: readonly TermReader[];\n}\n\nexport interface LoadedTerms {\n cwd: string;\n run: TermRun;\n set: TermSet;\n}\n\nexport async function loadTerms(opts: TermCommandOptions): Promise<LoadedTerms> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const run = await resolveTermRun({\n cwd,\n inputs: opts.inputs,\n ...(opts.configPath === undefined ? {} : { configPath: opts.configPath }),\n ...(opts.collection === undefined ? {} : { collection: opts.collection }),\n });\n const set = await loadSet(run, opts);\n return { cwd, run, set };\n}\n\n/** Load the set a resolved run names, and say the readers' notices. */\nexport async function loadSet(run: TermRun, opts: TermCommandOptions): Promise<TermSet> {\n // A collection's `exclude:` shapes the collection, so it applies when the\n // inputs came from the collections and never to a path the operator typed.\n const exclude = [\n ...new Set([\n ...(opts.exclude ?? []),\n ...(run.fromCollections ? run.collections.flatMap((c) => c.exclude) : []),\n ]),\n ];\n const set = await loadTermSet({\n run,\n exclude,\n ...(opts.exts === undefined ? {} : { exts: opts.exts }),\n ...(opts.allowEmpty === true ? { allowEmpty: true } : {}),\n ...(opts.noGitignore === true ? { noGitignore: true } : {}),\n ...(opts.stdin === undefined ? {} : { stdin: opts.stdin }),\n ...(opts.as === undefined ? {} : { as: opts.as }),\n ...(opts.onNotice === undefined ? {} : { onNotice: opts.onNotice }),\n ...(opts.readers === undefined ? {} : { readers: opts.readers }),\n });\n for (const message of set.notices) opts.onNotice?.(message);\n return set;\n}\n\n/**\n * `value` when it is one of `allowed`, else the family's unknown-format\n * refusal, naming every value in declaration order.\n */\nexport function formatChoice<T extends string>(value: string, allowed: readonly T[]): T {\n const found = allowed.find((candidate) => candidate === value);\n if (found === undefined) {\n throw new TermError(`unknown format \"${value}\". Expected ${allowed.join(\" | \")}.`);\n }\n return found;\n}\n\n/** A path as a person standing in `cwd` would type it: relative, posix. An already-relative label is kept. */\nexport function displayPath(path: string, cwd: string): string {\n if (!isAbsolute(path)) return path;\n const rel = relative(cwd, path);\n return (rel === \"\" ? \".\" : rel).replaceAll(\"\\\\\", \"/\");\n}\n\n/**\n * Vale's config file for the run, absolute, or `undefined` when none is set\n * and Vale finds its own. A configured file that is not there is refused here,\n * before Vale reads it as a different complaint.\n */\nexport function valeConfigFor(run: TermRun): string | undefined {\n if (run.configDir === undefined) return undefined;\n const path = valeConfigPath(run.tools, run.configDir);\n if (path !== undefined && !existsSync(path)) {\n const source = run.configSource ?? \"manni.config.yaml\";\n throw new TermError(`${source}: tools.vale.config \"${run.tools.vale?.config ?? path}\" does not exist.`);\n }\n return path;\n}\n\n/** `1 term`, `2 terms`. */\nexport function plural(n: number, one: string, many = `${one}s`): string {\n return `${String(n)} ${n === 1 ? one : many}`;\n}\n","/**\n * Load a term set: resolve the run's files, extract each one's metadata with\n * meta's extractor, and offer it to every reader of its format. Every command\n * that reads terms goes through here, so a construct added as a reader is read\n * by `list`, `get`, `check`, `lint` and `write` at once.\n *\n * Every loaded file contributes its references too, term file or not: a\n * guide's `concepts:` is what `undefined-term` and `unused-term` are about.\n *\n * A file that cannot be read or parsed is an error, not a skip. A term set that\n * quietly lost a file would pass `check` on what was left, and report the\n * missing terms as undefined on pages that spell them correctly.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { extname, resolve } from \"node:path\";\nimport {\n STDIN_LABEL,\n STDIN_TOKEN,\n assertNonEmpty,\n extractorByName,\n extractorForExtension,\n gitignoreOptions,\n resolveTargetSet,\n} from \"../../meta/internal.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { CONCEPT_FIELDS, fieldPointer, valueAt } from \"../../shared/reference-fields.js\";\nimport { TermError } from \"../errors.js\";\nimport type { TermInput, TermReader, TermReference, TermRun, TermSet } from \"../types.js\";\nimport { TERM_READERS, readersForFormat } from \"./readers/index.js\";\n\n/** The `TermInput.format` a manifest is offered as. */\nexport const MANIFEST_FORMAT = \"manifest\";\n\n/** The extensions a file named on the command line is read as a manifest by. */\nconst MANIFEST_EXTENSIONS: ReadonlySet<string> = new Set([\".yaml\", \".yml\", \".json\"]);\n\n/** A manifest carries no page metadata; its reader parses the content itself. */\nfunction manifestInput(content: string, file: string, path: string): TermInput {\n return { content, file, path, format: MANIFEST_FORMAT, metadata: {}, lineFor: () => undefined };\n}\n\nexport interface LoadTermSetOptions {\n run: TermRun;\n /** Stdin's content, when `-` is among the run's inputs. */\n stdin?: string;\n /** `--as <format>`, which stdin needs. */\n as?: string;\n /** `--exclude <glob>`, repeatable. */\n exclude?: string[];\n /** `--ext <list>`: the extensions a directory or glob walk keeps. */\n exts?: string[];\n /** `--allow-empty`: wins over `term.allowEmpty`. */\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n noGitignore?: boolean;\n onNotice?: (message: string) => void;\n /** The readers to offer files to. Tests hand in their own. */\n readers?: readonly TermReader[];\n}\n\n/** One value or a list of them, as `concepts:` is spelled. Anything else contributes nothing. */\nfunction labelsOf(value: unknown): string[] {\n if (typeof value === \"string\") return value.trim() === \"\" ? [] : [value];\n if (Array.isArray(value)) {\n return value.filter((item): item is string => typeof item === \"string\" && item.trim() !== \"\");\n }\n return [];\n}\n\nfunction referencesOf(input: TermInput): TermReference[] {\n const references: TermReference[] = [];\n const add = (value: unknown, pointer: string): void => {\n for (const label of labelsOf(value)) {\n const line = input.lineFor(pointer);\n references.push({ file: input.file, label, ...(line === undefined ? {} : { line }) });\n }\n };\n for (const path of CONCEPT_FIELDS) add(valueAt(input.metadata, path), fieldPointer(path));\n return references;\n}\n\nfunction read(input: TermInput, readers: readonly TermReader[], set: TermSet): void {\n for (const reader of readersForFormat(input.format, readers)) {\n const result = reader.read(input);\n set.terms.push(...result.terms);\n set.notices.push(...result.notices);\n }\n}\n\nexport function extractInput(\n content: string,\n file: string,\n path: string | undefined,\n format: string,\n): TermInput {\n const extractor = extractorByName(format);\n if (extractor === undefined) {\n throw new TermError(`${file}: no reader for format \"${format}\".`);\n }\n let extracted;\n try {\n extracted = extractor.extract(content, path ?? file);\n } catch (error) {\n throw new TermError(`${file}: could not be read as ${format}: ${errorMessage(error)}`);\n }\n return {\n content,\n file,\n ...(path === undefined ? {} : { path }),\n format: extractor.name,\n metadata: extracted.data,\n lineFor: extracted.lineFor,\n };\n}\n\nexport async function loadTermSet(opts: LoadTermSetOptions): Promise<TermSet> {\n const { run } = opts;\n const readers = opts.readers ?? TERM_READERS;\n const exclude = opts.exclude ?? [];\n const allowEmpty = opts.allowEmpty ?? run.config?.allowEmpty === true;\n\n const usingStdin = run.inputs.includes(STDIN_TOKEN);\n const inputs = run.inputs.filter((input) => input !== STDIN_TOKEN);\n if (usingStdin && (opts.as === undefined || opts.as === \"\")) {\n throw new TermError(\"reading stdin needs --as <format>.\");\n }\n if (inputs.length === 0 && !usingStdin && run.manifests.length === 0) {\n throw new TermError(\n \"No files to read. Pass paths/globs, or declare a collection under `collections:` in manni.config.yaml.\",\n );\n }\n\n const set: TermSet = { terms: [], references: [], notices: [] };\n\n if (inputs.length > 0) {\n const { files, gitignoreSkipped, named } = await resolveTargetSet({\n inputs,\n cwd: run.base,\n exclude,\n ...(opts.exts === undefined ? {} : { exts: opts.exts }),\n allowEmpty,\n ...gitignoreOptions({\n ...(opts.noGitignore === true ? { flag: false } : {}),\n ...(run.config?.respectGitignore === undefined\n ? {}\n : { configured: run.config.respectGitignore }),\n ...(opts.onNotice ? { onNotice: opts.onNotice } : {}),\n }),\n });\n assertNonEmpty({\n files,\n inputs,\n usingStdin,\n allowEmpty,\n exclude,\n ...(opts.exts === undefined ? {} : { exts: opts.exts }),\n gitignoreSkipped,\n action: \"read\",\n });\n\n const namedFiles = new Set(named);\n for (const file of files) {\n const path = resolve(run.base, file);\n // A manifest is read when it is named, never when a walk passes it: a\n // directory of pages can hold YAML and JSON that are not terms at all.\n if (namedFiles.has(file) && MANIFEST_EXTENSIONS.has(extname(file).toLowerCase())) {\n let content: string;\n try {\n content = await readFile(path, \"utf8\");\n } catch (error) {\n throw new TermError(`${file}: could not be read: ${errorMessage(error)}`);\n }\n read(manifestInput(content, file, path), readers, set);\n continue;\n }\n const extractor = extractorForExtension(extname(file));\n // A file the walk returned always has a known extension; a path typed\n // with another one is refused here rather than read as nothing.\n if (extractor === undefined) {\n throw new TermError(`${file}: no reader for its extension. Pass --as <format> through stdin to read it.`);\n }\n let content: string;\n try {\n content = await readFile(path, \"utf8\");\n } catch (error) {\n throw new TermError(`${file}: could not be read: ${errorMessage(error)}`);\n }\n const input = extractInput(content, file, path, extractor.name);\n set.references.push(...referencesOf(input));\n read(input, readers, set);\n }\n }\n\n if (usingStdin && opts.as !== undefined) {\n const input = extractInput(opts.stdin ?? \"\", STDIN_LABEL, undefined, opts.as);\n set.references.push(...referencesOf(input));\n read(input, readers, set);\n }\n\n for (const { path, written } of run.manifests) {\n let content: string;\n try {\n content = await readFile(path, \"utf8\");\n } catch {\n const source = run.configSource ?? \"manni.config.yaml\";\n throw new TermError(`${source}: term.manifests \"${written}\" does not exist.`);\n }\n read(manifestInput(content, path, path), readers, set);\n }\n\n if (set.terms.length === 0 && !allowEmpty) {\n throw new TermError(\n \"no terms found. A term is a page declaring type: term, or an entry in a file declaring type: term-set.\",\n );\n }\n return set;\n}\n","/**\n * The small pieces every document writer and every in-place write shares:\n * escaping, a definition's paragraphs, the acronym test, and indentation.\n */\nimport type { Term } from \"../../types.js\";\n\nexport function xmlText(value: string): string {\n return value.replaceAll(\"&\", \"&amp;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\");\n}\n\nexport function xmlAttribute(value: string): string {\n return xmlText(value).replaceAll('\"', \"&quot;\");\n}\n\n/**\n * A definition's paragraphs, each as its lines: paragraphs split on blank\n * lines, each line trimmed, empty lines and paragraphs dropped. Every body\n * reader reads a definition back the same way, joining a paragraph's lines\n * with one space.\n */\nexport function paragraphsOf(definition: string | undefined): string[][] {\n if (definition === undefined) return [];\n return definition\n .split(/\\r?\\n[ \\t]*\\r?\\n/)\n .map((paragraph) =>\n paragraph\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line !== \"\"),\n )\n .filter((lines) => lines.length > 0);\n}\n\n/** A paragraph as one line, for markup whose readers collapse whitespace anyway. */\nexport function paragraphText(lines: readonly string[]): string {\n return lines.join(\" \");\n}\n\n/** Whether an alt-label is written as an acronym: it has letters, and none of them is lowercase. */\nexport function isAcronym(label: string): boolean {\n return /\\p{L}/u.test(label) && !/\\p{Ll}/u.test(label);\n}\n\n/** The language every term carries, when they all carry the same one. A file holds one language. */\nexport function sharedLanguage(terms: readonly Term[]): string | undefined {\n const [first] = terms;\n const language = first?.language;\n if (language === undefined) return undefined;\n return terms.every((t) => t.language === language) ? language : undefined;\n}\n\n/**\n * `text`, whose lines are at indentation zero, placed at `indent`: the first\n * line as is (it lands where the old entry started), every later non-empty\n * line prefixed, and lines joined with `eol`.\n */\nexport function reindent(text: string, indent: string, eol: string): string {\n return text\n .split(\"\\n\")\n .map((line, i) => (i === 0 || line === \"\" ? line : `${indent}${line}`))\n .join(eol);\n}\n\n/** Lines as a file: `\\n`-joined with one trailing newline. */\nexport function fileOf(lines: readonly string[]): string {\n return lines.map((line) => `${line}\\n`).join(\"\");\n}\n","/**\n * One entry of each many-per-file construct, as text. The document writers\n * assemble files from these, and each construct's reader splices the same\n * text back in place, so an entry a render wrote and an entry an in-place\n * write replaced are byte for byte the same.\n *\n * Each returns the entry's lines at indentation zero, `\\n`-joined, with no\n * trailing newline. The caller indents and terminates.\n */\nimport type { Term, TermField, TermRecord } from \"../../types.js\";\nimport { isAcronym, paragraphText, paragraphsOf, xmlAttribute, xmlText } from \"./markup.js\";\n\n/** What a definition list, `[glossary]` list, `.. glossary::` or `<dl>` can say. */\nexport const LIST_HOLDS: readonly TermField[] = [\"label\", \"definition\", \"alt-labels\"];\n/** What a DITA glossentry can say. */\nexport const DITA_HOLDS: readonly TermField[] = [\"label\", \"definition\", \"alt-labels\", \"scope-note\"];\n/** What a DocBook glossentry can say. */\nexport const DOCBOOK_HOLDS: readonly TermField[] = [\"label\", \"definition\", \"alt-labels\", \"see\", \"related-terms\"];\n\nfunction labelsOf(record: TermRecord): string[] {\n return [record.label, ...(record[\"alt-labels\"] ?? [])];\n}\n\n/**\n * A Markdown Extra definition list entry: the label and each alt-label on a\n * line, then `: ` and the definition, continuation lines and later\n * paragraphs indented four spaces. A term with no definition gets a bare `:`,\n * which the reader skips with a notice, so the file writer leaves such a term\n * out.\n */\nexport function markdownEntry(record: TermRecord): string {\n const lines = labelsOf(record);\n const paragraphs = paragraphsOf(record.definition);\n if (paragraphs.length === 0) return [...lines, \":\"].join(\"\\n\");\n paragraphs.forEach((paragraph, p) => {\n if (p > 0) lines.push(\"\");\n paragraph.forEach((line, i) => {\n lines.push(p === 0 && i === 0 ? `: ${line}` : ` ${line}`);\n });\n });\n return lines.join(\"\\n\");\n}\n\n/**\n * An AsciiDoc labelled list entry: each term as `term::`, the definition's\n * first line after the last term's `::`, and each later paragraph after a `+`\n * continuation line.\n */\nexport function asciidocEntry(record: TermRecord): string {\n const labels = labelsOf(record);\n const paragraphs = paragraphsOf(record.definition);\n const lines = labels.map((label) => `${label}::`);\n paragraphs.forEach((paragraph, p) => {\n if (p > 0) lines.push(\"+\");\n paragraph.forEach((line, i) => {\n if (p === 0 && i === 0) lines[lines.length - 1] = `${lines[lines.length - 1] ?? \"\"} ${line}`;\n else lines.push(line);\n });\n });\n return lines.join(\"\\n\");\n}\n\n/** A `.. glossary::` entry: the terms on their own lines, the definition indented three spaces. */\nexport function rstEntry(record: TermRecord): string {\n const lines = labelsOf(record);\n paragraphsOf(record.definition).forEach((paragraph, p) => {\n if (p > 0) lines.push(\"\");\n for (const line of paragraph) lines.push(` ${line}`);\n });\n return lines.join(\"\\n\");\n}\n\n/** The `<dd>` or `<glossdef>` body: one paragraph inline, several as `<p>`s. */\nfunction blockDefinition(open: string, close: string, paragraph: string, definition: string | undefined): string[] {\n const paragraphs = paragraphsOf(definition);\n const [only] = paragraphs;\n if (only === undefined) return [];\n if (paragraphs.length === 1) return [`${open}${xmlText(paragraphText(only))}${close}`];\n return [\n open,\n ...paragraphs.map((lines) => ` <${paragraph}>${xmlText(paragraphText(lines))}</${paragraph}>`),\n close,\n ];\n}\n\n/** An HTML `<dt>` per term, the first carrying the id, then a `<dd>` when there is a definition. */\nexport function htmlDlEntry(term: Term): string {\n const [label, ...alts] = labelsOf(term.record);\n return [\n `<dt id=\"${xmlAttribute(term.id)}\">${xmlText(label ?? \"\")}</dt>`,\n ...alts.map((alt) => `<dt>${xmlText(alt)}</dt>`),\n ...blockDefinition(\"<dd>\", \"</dd>\", \"p\", term.record.definition),\n ].join(\"\\n\");\n}\n\n/**\n * A DITA 2.0 `<glossentry>`: glossterm, glossdef, then a glossBody holding the\n * scope note as glossUsage and one glossAlt per alt-label. `language` is set as\n * `xml:lang` where the entry is the file's root, which is where a reader looks.\n */\nexport function ditaEntry(term: Term, language?: string): string {\n const { record } = term;\n const alts = record[\"alt-labels\"] ?? [];\n const scopeNote = record[\"scope-note\"];\n const lang = language === undefined ? \"\" : ` xml:lang=\"${xmlAttribute(language)}\"`;\n const body =\n scopeNote === undefined && alts.length === 0\n ? []\n : [\n \" <glossBody>\",\n ...(scopeNote === undefined ? [] : [` <glossUsage>${xmlText(scopeNote)}</glossUsage>`]),\n ...alts.flatMap((alt) => {\n const element = isAcronym(alt) ? \"glossAcronym\" : \"glossSynonym\";\n return [\" <glossAlt>\", ` <${element}>${xmlText(alt)}</${element}>`, \" </glossAlt>\"];\n }),\n \" </glossBody>\",\n ];\n return [\n `<glossentry id=\"${xmlAttribute(term.id)}\"${lang}>`,\n ` <glossterm>${xmlText(record.label)}</glossterm>`,\n ...blockDefinition(\"<glossdef>\", \"</glossdef>\", \"p\", record.definition).map((line) => ` ${line}`),\n ...body,\n \"</glossentry>\",\n ].join(\"\\n\");\n}\n\n/**\n * A DocBook `<glossentry>`: the label as glossterm, each alt-label as an\n * acronym when it is all caps and a glossterm otherwise, the definition as\n * paras with a glossseealso per related term, then a glosssee.\n */\nexport function docbookEntry(term: Term): string {\n const { record } = term;\n const related = record[\"related-terms\"] ?? [];\n const paragraphs = paragraphsOf(record.definition);\n const glossdef =\n paragraphs.length === 0 && related.length === 0\n ? []\n : [\n \" <glossdef>\",\n ...paragraphs.map((lines) => ` <para>${xmlText(paragraphText(lines))}</para>`),\n ...related.map((target) => ` <glossseealso>${xmlText(target)}</glossseealso>`),\n \" </glossdef>\",\n ];\n return [\n `<glossentry xml:id=\"${xmlAttribute(term.id)}\">`,\n ` <glossterm>${xmlText(record.label)}</glossterm>`,\n ...(record[\"alt-labels\"] ?? []).map((alt) =>\n isAcronym(alt) ? ` <acronym>${xmlText(alt)}</acronym>` : ` <glossterm>${xmlText(alt)}</glossterm>`,\n ),\n ...glossdef,\n ...(record.see === undefined ? [] : [` <glosssee>${xmlText(record.see)}</glosssee>`]),\n \"</glossentry>\",\n ].join(\"\\n\");\n}\n","/**\n * A term's identity when its record carries no `id` and its construct no\n * identifier of its own: the GitHub slug of its preferred label. The slug is\n * `github-slugger`'s, which is the one graph mints concept IRIs with, so a term\n * and its graph concept agree on a name without either carrying one.\n */\nimport { slug } from \"github-slugger\";\n\n/** The slug of `label`, trimmed first: a stray space is not part of a name. */\nexport function slugOf(label: string): string {\n return slug(label.trim());\n}\n","/**\n * The one normalization every reader applies to what it read, so that two\n * sets saying the same thing in different constructs compare equal (see\n * `TermRecord`). Also the pieces every reader shares: the id rule, the\n * skipped-entry notice, and the empty result.\n */\nimport { slugOf } from \"../id.js\";\nimport {\n TERM_FIELDS,\n TERM_LIST_FIELDS,\n type Term,\n type TermField,\n type TermInput,\n type TermListField,\n type TermLocation,\n type TermReadResult,\n type TermRecord,\n} from \"../../types.js\";\n\n/** A reader's answer for a file that holds none of its entries. */\nexport function nothing(): TermReadResult {\n return { terms: [], notices: [] };\n}\n\n/**\n * A scalar as a non-empty trimmed string, or `undefined`. A number counts,\n * because YAML and the attribute channels type `id: 42` as one.\n */\nexport function textOf(value: unknown): string | undefined {\n let text: string;\n if (typeof value === \"string\") text = value;\n else if (typeof value === \"number\" && Number.isFinite(value)) text = String(value);\n else return undefined;\n const trimmed = text.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/** A string or a list of them as a non-empty list of non-empty trimmed strings, or `undefined`. */\nexport function listOf(value: unknown): string[] | undefined {\n const items = Array.isArray(value) ? (value as unknown[]) : [value];\n const list = items.map(textOf).filter((item): item is string => item !== undefined);\n return list.length === 0 ? undefined : list;\n}\n\n/** Runs of whitespace, line breaks included, as one space: markup's text as a reader sees it. */\nexport function collapse(text: string): string {\n return text.replace(/\\s+/g, \" \").trim();\n}\n\nfunction isListField(field: TermField): field is TermListField {\n return (TERM_LIST_FIELDS as readonly TermField[]).includes(field);\n}\n\n/**\n * The record for raw field values, normalized, or `undefined` when there is no\n * label to make one. Keys other than the ten fields are ignored.\n */\nexport function recordOf(raw: Partial<Record<TermField, unknown>>): TermRecord | undefined {\n const label = textOf(raw.label);\n if (label === undefined) return undefined;\n const record: TermRecord = { label };\n for (const field of TERM_FIELDS) {\n if (isListField(field)) {\n const list = listOf(raw[field]);\n if (list !== undefined) record[field] = list;\n } else if (field !== \"label\") {\n const text = textOf(raw[field]);\n if (text !== undefined) record[field] = text;\n }\n }\n return record;\n}\n\n/**\n * The one-value fields whose value is present but is not text: a list, a\n * mapping, a boolean. `recordOf` leaves each out, and the reader says so, so a\n * `see: [x]` is reported rather than lost. An empty string is text with\n * nothing in it and is simply absent, as `TermRecord` defines.\n */\nexport function ignoredFields(raw: Partial<Record<TermField, unknown>>): IgnoredField[] {\n const ignored: IgnoredField[] = [];\n for (const field of TERM_FIELDS) {\n if (field === \"label\" || isListField(field)) continue;\n const value = raw[field];\n if (value === undefined || value === null || typeof value === \"string\") continue;\n if (textOf(value) !== undefined) continue;\n const given = Array.isArray(value) ? \"list\" : typeof value === \"object\" ? \"mapping\" : \"other\";\n ignored.push({ field, given });\n }\n return ignored;\n}\n\n/** A one-value field left out of a record, and what it was given instead of text. */\nexport interface IgnoredField {\n field: TermField;\n given: \"list\" | \"mapping\" | \"other\";\n}\n\n/**\n * The notice for a one-value field `ignoredFields` found. It names what the\n * field holds and, for a list or a mapping, what it was given.\n */\nexport function ignoredNotice(input: TermInput, line: number, label: string, ignored: IgnoredField): string {\n const { field, given } = ignored;\n const article = /^[aeiou]/.test(field) ? \"an\" : \"a\";\n const holds =\n given === \"list\" ? \"holds one value, not a list\" : given === \"mapping\" ? \"holds text, not a mapping\" : \"holds text\";\n return `${input.file}:${line}: ignored ${field} on \"${label}\": ${article} ${field} ${holds}.`;\n}\n\n/** The field lines worth keeping: those of fields the record actually carries. */\nexport function linesFor(\n record: TermRecord,\n lines: Partial<Record<TermField, number | undefined>>,\n): Partial<Record<TermField, number>> {\n const kept: Partial<Record<TermField, number>> = {};\n for (const field of TERM_FIELDS) {\n const line = lines[field];\n if (line !== undefined && record[field] !== undefined) kept[field] = line;\n }\n return kept;\n}\n\n/** The record's id, else the construct's own identifier, else the label's slug. */\nexport function idFor(record: TermRecord, recordId: unknown, constructId?: unknown): string {\n return textOf(recordId) ?? textOf(constructId) ?? slugOf(record.label);\n}\n\n/**\n * `language` from the file's metadata, when it carries one. An XML file says\n * it with `xml:lang` on its root, which is where DITA and DocBook put it.\n */\nexport function languageOf(input: TermInput): string | undefined {\n return textOf(input.metadata[\"language\"]) ?? textOf(input.metadata[\"xml:lang\"]);\n}\n\n/** Whether the file's metadata channel declares `type: <type>`. */\nexport function declares(input: TermInput, type: string): boolean {\n const value = input.metadata[\"type\"];\n return typeof value === \"string\" && value.trim() === type;\n}\n\n/** The notice for an entry with no term text. */\nexport function skipped(input: TermInput, line: number, label: string): string {\n return `${input.file}:${line}: skipped a ${label} entry with no term.`;\n}\n\nexport interface EntryParts {\n record: TermRecord;\n recordId?: unknown;\n constructId?: unknown;\n construct: TermLocation[\"construct\"];\n line: number;\n lines: Partial<Record<TermField, number | undefined>>;\n span?: { start: number; end: number };\n}\n\n/** A `Term` assembled from what a reader read, with the id, language and location rules applied. */\nexport function termOf(input: TermInput, parts: EntryParts): Term {\n const language = languageOf(input);\n const location: TermLocation = {\n file: input.file,\n ...(input.path === undefined ? {} : { path: input.path }),\n construct: parts.construct,\n line: parts.line,\n fieldLines: linesFor(parts.record, parts.lines),\n ...(parts.span === undefined ? {} : { span: parts.span }),\n };\n return {\n id: idFor(parts.record, parts.recordId, parts.constructId),\n record: parts.record,\n ...(language === undefined ? {} : { language }),\n location,\n };\n}\n","/**\n * The in-place write every body construct shares. The file is read again, and\n * an entry is rewritten only where the record it was handed differs from what\n * the file says, in a field the construct can hold. The rewrite replaces the\n * entry's span with the same text a render writes for it, indented where the\n * old entry sat and in the file's own line endings. So a write of unchanged\n * terms returns the file exactly as it was.\n */\nimport { TermError } from \"../../errors.js\";\nimport type { Term, TermField, TermInput, TermReadResult, TermRecord } from \"../../types.js\";\nimport { reindent } from \"../writers/markup.js\";\n\nexport interface EntryWrite {\n /** The fields the construct holds: a difference anywhere else is not written. */\n holds: readonly TermField[];\n /** Whether the construct holds the id, so a changed id is a change. */\n id: boolean;\n /** The entry's text at indentation zero, `\\n`-joined. */\n serialize: (term: Term, input: TermInput) => string;\n}\n\nfunction sameValue(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/** Whether two records say the same thing in `fields`. */\nexport function sameFields(a: TermRecord, b: TermRecord, fields: readonly TermField[]): boolean {\n return fields.every((field) => sameValue(a[field], b[field]));\n}\n\n/** The file's line ending: CRLF when it has one, else LF. */\nexport function lineEnding(content: string): string {\n return content.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n}\n\n/** The whitespace that opens the line `offset` sits on. */\nfunction indentAt(content: string, offset: number): string {\n const lineStart = content.lastIndexOf(\"\\n\", offset - 1) + 1;\n return /^[ \\t]*/.exec(content.slice(lineStart, offset))?.[0] ?? \"\";\n}\n\nexport function applyEntries(\n input: TermInput,\n read: (input: TermInput) => TermReadResult,\n terms: readonly Term[],\n write: EntryWrite,\n): string {\n const { content } = input;\n const current = read(input).terms;\n const eol = lineEnding(content);\n const edits: { start: number; end: number; text: string }[] = [];\n\n for (const term of terms) {\n const span = term.location.span;\n if (span === undefined) {\n throw new TermError(\n `${input.file}: term \"${term.id}\" cannot be written in place, because its entry has no position in the file.`,\n );\n }\n const found = current.find((t) => t.location.span?.start === span.start && t.location.span.end === span.end);\n if (found === undefined) {\n throw new TermError(\n `${input.file}: term \"${term.id}\" does not match an entry in the file. Read the file again before writing it.`,\n );\n }\n if (sameFields(found.record, term.record, write.holds) && (!write.id || found.id === term.id)) continue;\n const text = reindent(write.serialize(term, input), indentAt(content, span.start), eol);\n edits.push({ start: span.start, end: span.end, text });\n }\n\n let next = content;\n for (const edit of [...edits].sort((a, b) => b.start - a.start)) {\n next = next.slice(0, edit.start) + edit.text + next.slice(edit.end);\n }\n return next;\n}\n","/**\n * The XML parse the DITA and DocBook readers share: one parse per input,\n * element lookup by local name, and an element's span in the file's content.\n *\n * meta's XML read model sits behind the sibling-tool wall, so the few pieces\n * needed here are restated rather than imported. The parser is the same one\n * (`@xmldom/xmldom`), with the same tolerance for DTD-declared entities, so a\n * file meta extracted is a file this parses.\n */\nimport { DOMParser, type Element } from \"@xmldom/xmldom\";\nimport type { TermInput } from \"../../types.js\";\nimport { collapse } from \"./normalize.js\";\n\nexport type XmlElement = Element;\n\nexport interface ParsedXml {\n root: XmlElement;\n /** The content parsed: `input.content` minus a leading BOM. */\n body: string;\n /** How far `body` is shifted from `input.content`: 1 when a BOM was stripped. */\n shift: number;\n /** Offsets at which each 1-based line of `body` begins, counted as xmldom counts them. */\n starts: number[];\n}\n\nconst cache = new WeakMap<TermInput, ParsedXml | null>();\n\n/** The six break forms xmldom folds to LF before counting lines. */\nconst LINE_BREAK = /\\r\\n|\\r|\\n|\\u0085|\\u2028|\\u2029/g;\n\nfunction lineStarts(source: string): number[] {\n const starts = [0];\n for (const match of source.matchAll(LINE_BREAK)) starts.push(match.index + match[0].length);\n return starts;\n}\n\n/**\n * The input's XML, or `null` for a file that does not parse or has no root.\n * The loader has already extracted the file with meta's XML extractor, which\n * refuses a malformed one, so `null` here means \"not a document this reader\n * can hold entries in\", never a quiet skip of a broken file.\n */\nexport function parseXml(input: TermInput): ParsedXml | null {\n const cached = cache.get(input);\n if (cached !== undefined) return cached;\n const shift = input.content.charCodeAt(0) === 0xfeff ? 1 : 0;\n const body = input.content.slice(shift);\n const errors: string[] = [];\n let parsed: ParsedXml | null = null;\n try {\n const doc = new DOMParser({\n onError: (level, message) => {\n if (level !== \"error\" && level !== \"fatalError\") return;\n if (/entity not found/i.test(message)) return;\n errors.push(message);\n },\n }).parseFromString(body, \"text/xml\");\n const root = doc.documentElement;\n if (errors.length === 0 && root !== null) parsed = { root, body, shift, starts: lineStarts(body) };\n } catch {\n parsed = null;\n }\n cache.set(input, parsed);\n return parsed;\n}\n\n/** An element's local name, lowercased: DocBook 5 is namespaced, DocBook 4 and DITA are not. */\nexport function nameOf(el: XmlElement): string {\n return (el.localName ?? el.nodeName).toLowerCase();\n}\n\n/** The element children of `el`, optionally only those named `name` (lowercase). */\nexport function childrenOf(el: XmlElement, name?: string): XmlElement[] {\n const out: XmlElement[] = [];\n for (let i = 0; i < el.children.length; i++) {\n const child = el.children.item(i);\n if (child !== null && (name === undefined || nameOf(child) === name)) out.push(child);\n }\n return out;\n}\n\n/** Every descendant of `el` named `name` (lowercase), in document order. */\nexport function descendantsOf(el: XmlElement, name: string): XmlElement[] {\n const out: XmlElement[] = [];\n const walk = (parent: XmlElement): void => {\n for (const child of childrenOf(parent)) {\n if (nameOf(child) === name) out.push(child);\n walk(child);\n }\n };\n walk(el);\n return out;\n}\n\n/** An element's text, whitespace collapsed. */\nexport function textOfElement(el: XmlElement): string {\n return collapse(el.textContent ?? \"\");\n}\n\n/** The 1-based line an element starts on. */\nexport function lineOfElement(el: XmlElement): number {\n return el.lineNumber ?? 1;\n}\n\n/**\n * The offset just past the end of the markup construct starting at `from`\n * (a comment, CDATA section, processing instruction or declaration), or\n * `undefined` when `from` starts none of them.\n */\nfunction skipOpaque(body: string, from: number): number | undefined {\n const opaque: [string, string][] = [\n [\"<!--\", \"-->\"],\n [\"<![CDATA[\", \"]]>\"],\n [\"<?\", \"?>\"],\n [\"<!\", \">\"],\n ];\n for (const [open, close] of opaque) {\n if (body.startsWith(open, from)) {\n const end = body.indexOf(close, from + open.length);\n return end === -1 ? body.length : end + close.length;\n }\n }\n return undefined;\n}\n\n/** The offset past a tag's closing `>`, honouring quoted attribute values, and whether it self-closed. */\nfunction tagEnd(body: string, from: number): { end: number; selfClosing: boolean } | undefined {\n let quote: string | undefined;\n for (let i = from + 1; i < body.length; i++) {\n const ch = body[i];\n if (quote !== undefined) {\n if (ch === quote) quote = undefined;\n } else if (ch === '\"' || ch === \"'\") {\n quote = ch;\n } else if (ch === \">\") {\n return { end: i + 1, selfClosing: body[i - 1] === \"/\" };\n }\n }\n return undefined;\n}\n\nfunction namedAt(body: string, at: number, name: string): boolean {\n if (!body.startsWith(name, at)) return false;\n const after = body[at + name.length];\n return after === undefined || /[\\s/>]/.test(after);\n}\n\n/**\n * An element's `[start, end)` offsets in `input.content`. xmldom reports only\n * where an element starts, so the end is found by scanning forward for the\n * close tag that balances it, skipping comments, CDATA and processing\n * instructions.\n */\nexport function spanOfElement(xml: ParsedXml, el: XmlElement): { start: number; end: number } | undefined {\n const lineStart = xml.starts[(el.lineNumber ?? 1) - 1];\n if (lineStart === undefined) return undefined;\n const start = lineStart + (el.columnNumber ?? 1) - 1;\n const { body } = xml;\n if (body[start] !== \"<\") return undefined;\n const name = el.nodeName;\n const open = tagEnd(body, start);\n if (open === undefined) return undefined;\n if (open.selfClosing) return { start: start + xml.shift, end: open.end + xml.shift };\n\n let depth = 1;\n let i = open.end;\n while (i < body.length) {\n const lt = body.indexOf(\"<\", i);\n if (lt === -1) return undefined;\n const skipTo = skipOpaque(body, lt);\n if (skipTo !== undefined) {\n i = skipTo;\n continue;\n }\n const tag = tagEnd(body, lt);\n if (tag === undefined) return undefined;\n if (body[lt + 1] === \"/\" && namedAt(body, lt + 2, name)) {\n depth -= 1;\n if (depth === 0) return { start: start + xml.shift, end: tag.end + xml.shift };\n } else if (namedAt(body, lt + 1, name) && !tag.selfClosing) {\n depth += 1;\n }\n i = tag.end;\n }\n return undefined;\n}\n","/**\n * DITA 2.0 glossary topics. A `<glossentry>` is a topic, so a file whose root\n * is one holds one term; a `<glossgroup>` holds a term per glossentry inside\n * it. Both are self-declaring, so neither needs `type: term`.\n *\n * Only elements that survive in DITA 2.0 are read. `<glossdef>` is the\n * definition: DITA specializes it from `<abstract>`, but it is where a DITA\n * author writes what the term means, and mapping it anywhere else would drop\n * every definition from a round trip through DITA (proposal 0052 § 4).\n */\nimport type { Term, TermField, TermInput, TermReader, TermReadResult } from \"../../types.js\";\nimport { DITA_HOLDS, ditaEntry } from \"../writers/entries.js\";\nimport { nothing, recordOf, skipped, termOf, textOf } from \"./normalize.js\";\nimport { applyEntries } from \"./splice.js\";\nimport {\n childrenOf,\n descendantsOf,\n lineOfElement,\n nameOf,\n parseXml,\n spanOfElement,\n textOfElement,\n type ParsedXml,\n type XmlElement,\n} from \"./xml.js\";\n\ntype Construct = \"dita-glossentry\" | \"dita-glossgroup\";\n\n/** A glossdef's prose: its `<p>`s with a blank line between, or its text when it has none. */\nfunction definitionOf(glossdef: XmlElement): string {\n const paragraphs = childrenOf(glossdef, \"p\");\n if (paragraphs.length === 0) return textOfElement(glossdef);\n return paragraphs\n .map(textOfElement)\n .filter((text) => text !== \"\")\n .join(\"\\n\\n\");\n}\n\nfunction readEntry(\n input: TermInput,\n xml: ParsedXml,\n entry: XmlElement,\n construct: Construct,\n label: string,\n): Term | string {\n const raw: Partial<Record<TermField, unknown>> = {};\n const lines: Partial<Record<TermField, number | undefined>> = {};\n const [glossterm] = childrenOf(entry, \"glossterm\");\n if (glossterm !== undefined) {\n raw.label = textOfElement(glossterm);\n lines.label = lineOfElement(glossterm);\n }\n const [glossdef] = childrenOf(entry, \"glossdef\");\n if (glossdef !== undefined) {\n raw.definition = definitionOf(glossdef);\n lines.definition = lineOfElement(glossdef);\n }\n const alts: string[] = [];\n for (const body of childrenOf(entry, \"glossbody\")) {\n const [usage] = childrenOf(body, \"glossusage\");\n if (usage !== undefined && raw[\"scope-note\"] === undefined) {\n raw[\"scope-note\"] = textOfElement(usage);\n lines[\"scope-note\"] = lineOfElement(usage);\n }\n for (const alt of childrenOf(body, \"glossalt\")) {\n for (const form of childrenOf(alt)) {\n const name = nameOf(form);\n if (name !== \"glosssynonym\" && name !== \"glossacronym\") continue;\n alts.push(textOfElement(form));\n lines[\"alt-labels\"] ??= lineOfElement(form);\n }\n }\n }\n raw[\"alt-labels\"] = alts;\n\n const line = lineOfElement(entry);\n const record = recordOf(raw);\n if (record === undefined) return skipped(input, line, label);\n const span = spanOfElement(xml, entry);\n return termOf(input, {\n record,\n constructId: entry.getAttribute(\"id\"),\n construct,\n line,\n lines,\n ...(span === undefined ? {} : { span }),\n });\n}\n\nfunction collect(\n input: TermInput,\n xml: ParsedXml,\n entries: readonly XmlElement[],\n construct: Construct,\n label: string,\n): TermReadResult {\n const result = nothing();\n for (const entry of entries) {\n const read = readEntry(input, xml, entry, construct, label);\n if (typeof read === \"string\") result.notices.push(read);\n else result.terms.push(read);\n }\n return result;\n}\n\nconst GLOSSENTRY_LABEL = \"DITA glossentry\";\nconst GLOSSGROUP_LABEL = \"DITA glossgroup\";\n\nfunction readGlossentry(input: TermInput): TermReadResult {\n const xml = parseXml(input);\n if (xml === null || nameOf(xml.root) !== \"glossentry\") return nothing();\n return collect(input, xml, [xml.root], \"dita-glossentry\", GLOSSENTRY_LABEL);\n}\n\nfunction readGlossgroup(input: TermInput): TermReadResult {\n const xml = parseXml(input);\n if (xml === null || nameOf(xml.root) !== \"glossgroup\") return nothing();\n // A glossgroup may nest glossgroups; every glossentry inside is a term.\n return collect(input, xml, descendantsOf(xml.root, \"glossentry\"), \"dita-glossgroup\", GLOSSGROUP_LABEL);\n}\n\nexport const ditaGlossentryReader: TermReader = {\n construct: \"dita-glossentry\",\n label: GLOSSENTRY_LABEL,\n formats: [\"xml\"],\n read: readGlossentry,\n // The glossentry is the file's root, so the file's `xml:lang` sits on it and\n // is written again when the entry is.\n apply: (input, terms) =>\n applyEntries(input, readGlossentry, terms, {\n holds: DITA_HOLDS,\n id: true,\n serialize: (term, file) => ditaEntry(term, textOf(file.metadata[\"xml:lang\"]) === undefined ? undefined : term.language),\n }),\n};\n\nexport const ditaGlossgroupReader: TermReader = {\n construct: \"dita-glossgroup\",\n label: GLOSSGROUP_LABEL,\n formats: [\"xml\"],\n read: readGlossgroup,\n apply: (input, terms) =>\n applyEntries(input, readGlossgroup, terms, { holds: DITA_HOLDS, id: true, serialize: (term) => ditaEntry(term) }),\n};\n","/**\n * DocBook's `<glossary>`, in DocBook 5's namespace or DocBook 4's none. It is\n * self-declaring, so any file holding one is read, and every `<glossentry>`\n * under it, `<glossdiv>`s included, is a term.\n *\n * Where an entry names several terms, the first `<glossterm>` is the label and\n * a later one, or an `<acronym>`, is an alt-label (proposal 0052 § 4).\n */\nimport type { TermField, TermInput, TermReader, TermReadResult } from \"../../types.js\";\nimport { DOCBOOK_HOLDS, docbookEntry } from \"../writers/entries.js\";\nimport { nothing, recordOf, skipped, termOf, textOf } from \"./normalize.js\";\nimport { applyEntries } from \"./splice.js\";\nimport {\n childrenOf,\n descendantsOf,\n lineOfElement,\n nameOf,\n parseXml,\n spanOfElement,\n textOfElement,\n type XmlElement,\n} from \"./xml.js\";\n\nconst LABEL = \"DocBook glossary\";\n\n/** A cross-reference's target as written: its text, else its `otherterm` idref. */\nfunction referenceOf(el: XmlElement): string | undefined {\n return textOf(textOfElement(el)) ?? textOf(el.getAttribute(\"otherterm\"));\n}\n\n/** A glossdef's prose: each paragraph's text, a blank line between, cross-references left out. */\nfunction definitionOf(glossdef: XmlElement): string {\n const children = childrenOf(glossdef);\n const blocks = children.filter((child) => nameOf(child) !== \"glossseealso\");\n // Only cross-references: a glossdef with no prose of its own.\n if (blocks.length === 0) return children.length === 0 ? textOfElement(glossdef) : \"\";\n return blocks\n .map(textOfElement)\n .filter((text) => text !== \"\")\n .join(\"\\n\\n\");\n}\n\nfunction read(input: TermInput): TermReadResult {\n const xml = parseXml(input);\n if (xml === null) return nothing();\n const glossaries = nameOf(xml.root) === \"glossary\" ? [xml.root] : descendantsOf(xml.root, \"glossary\");\n if (glossaries.length === 0) return nothing();\n\n const seen = new Set<XmlElement>();\n const result = nothing();\n for (const glossary of glossaries) {\n for (const entry of descendantsOf(glossary, \"glossentry\")) {\n if (seen.has(entry)) continue;\n seen.add(entry);\n\n const raw: Partial<Record<TermField, unknown>> = {};\n const lines: Partial<Record<TermField, number | undefined>> = {};\n const alts: string[] = [];\n const definitions: string[] = [];\n const related: string[] = [];\n for (const child of childrenOf(entry)) {\n const name = nameOf(child);\n if (name === \"glossterm\" && raw.label === undefined) {\n raw.label = textOfElement(child);\n lines.label = lineOfElement(child);\n } else if (name === \"glossterm\" || name === \"acronym\") {\n alts.push(textOfElement(child));\n lines[\"alt-labels\"] ??= lineOfElement(child);\n } else if (name === \"glossdef\") {\n definitions.push(definitionOf(child));\n lines.definition ??= lineOfElement(child);\n for (const seeAlso of childrenOf(child, \"glossseealso\")) {\n const target = referenceOf(seeAlso);\n if (target !== undefined) related.push(target);\n lines[\"related-terms\"] ??= lineOfElement(seeAlso);\n }\n } else if (name === \"glosssee\" && raw.see === undefined) {\n raw.see = referenceOf(child);\n lines.see = lineOfElement(child);\n }\n }\n raw[\"alt-labels\"] = alts;\n raw.definition = definitions.filter((text) => text !== \"\").join(\"\\n\\n\");\n raw[\"related-terms\"] = related;\n\n const line = lineOfElement(entry);\n const record = recordOf(raw);\n if (record === undefined) {\n result.notices.push(skipped(input, line, LABEL));\n continue;\n }\n const span = spanOfElement(xml, entry);\n result.terms.push(\n termOf(input, {\n record,\n constructId: entry.getAttribute(\"xml:id\"),\n construct: \"docbook-glossary\",\n line,\n lines,\n ...(span === undefined ? {} : { span }),\n }),\n );\n }\n }\n return result;\n}\n\nexport const docbookGlossaryReader: TermReader = {\n construct: \"docbook-glossary\",\n label: LABEL,\n formats: [\"xml\"],\n read,\n apply: (input, terms) => applyEntries(input, read, terms, { holds: DOCBOOK_HOLDS, id: true, serialize: docbookEntry }),\n};\n","/**\n * HTML's two term constructs, `<dl>` and `<dfn>`. Neither says it is a\n * glossary, so both are read only where the page's metadata declares\n * `type: term-set` (proposal 0052 § 3).\n *\n * parse5 is the parser meta's HTML extractor uses; its location info gives\n * each element's offsets and line directly.\n */\nimport { parse, type DefaultTreeAdapterMap } from \"parse5\";\nimport type { Term, TermField, TermInput, TermReader, TermReadResult } from \"../../types.js\";\nimport { LIST_HOLDS, htmlDlEntry } from \"../writers/entries.js\";\nimport { collapse, declares, nothing, recordOf, skipped, termOf, textOf } from \"./normalize.js\";\nimport { applyEntries } from \"./splice.js\";\n\ntype Element = DefaultTreeAdapterMap[\"element\"];\ntype ChildNode = DefaultTreeAdapterMap[\"childNode\"];\ntype ParentNode = DefaultTreeAdapterMap[\"parentNode\"];\n\ninterface ParsedHtml {\n root: DefaultTreeAdapterMap[\"document\"];\n /** 1 when a leading BOM was stripped before parsing, so offsets map back onto `input.content`. */\n shift: number;\n}\n\nconst cache = new WeakMap<TermInput, ParsedHtml>();\n\nfunction parseHtml(input: TermInput): ParsedHtml {\n const cached = cache.get(input);\n if (cached !== undefined) return cached;\n // A BOM before `<html>` puts parse5 into a mode with no source locations for\n // the document's structure; meta's reader strips it for the same reason.\n const shift = input.content.charCodeAt(0) === 0xfeff ? 1 : 0;\n const parsed = { root: parse(input.content.slice(shift), { sourceCodeLocationInfo: true }), shift };\n cache.set(input, parsed);\n return parsed;\n}\n\nfunction isElement(node: ChildNode): node is Element {\n return \"tagName\" in node;\n}\n\nfunction childElements(node: ParentNode): Element[] {\n return node.childNodes.filter(isElement);\n}\n\nfunction elementsNamed(node: ParentNode, name: string): Element[] {\n const out: Element[] = [];\n const walk = (parent: ParentNode): void => {\n for (const child of childElements(parent)) {\n if (child.tagName === name) out.push(child);\n walk(child);\n }\n };\n walk(node);\n return out;\n}\n\nfunction rawText(node: ParentNode): string {\n let text = \"\";\n for (const child of node.childNodes) {\n if (child.nodeName === \"#text\" && \"value\" in child) text += child.value;\n else if (isElement(child)) text += rawText(child);\n }\n return text;\n}\n\nfunction textOfNode(node: ParentNode): string {\n return collapse(rawText(node));\n}\n\nfunction attr(el: Element, name: string): string | undefined {\n return el.attrs.find((a) => a.name === name)?.value;\n}\n\nfunction lineOf(el: Element): number {\n return el.sourceCodeLocation?.startLine ?? 1;\n}\n\nfunction spanOf(parsed: ParsedHtml, first: Element, last: Element): { start: number; end: number } | undefined {\n const start = first.sourceCodeLocation?.startOffset;\n const end = last.sourceCodeLocation?.endOffset;\n if (start === undefined || end === undefined) return undefined;\n return { start: start + parsed.shift, end: end + parsed.shift };\n}\n\n/** A `<dd>`'s definition: its paragraphs with a blank line between, or its text when it has none. */\nfunction definitionOf(dd: Element): string {\n const paragraphs = childElements(dd).filter((child) => child.tagName === \"p\");\n if (paragraphs.length === 0) return textOfNode(dd);\n return paragraphs\n .map(textOfNode)\n .filter((text) => text !== \"\")\n .join(\"\\n\\n\");\n}\n\n/** A `<dl>`'s `<dt>` and `<dd>` children, looking through the `<div>` wrappers HTML allows. */\nfunction listItems(dl: Element): Element[] {\n return childElements(dl).flatMap((child) => (child.tagName === \"div\" ? childElements(child) : [child]));\n}\n\nconst DL_LABEL = \"dl\";\n\nfunction readDl(input: TermInput): TermReadResult {\n if (!declares(input, \"term-set\")) return nothing();\n const parsed = parseHtml(input);\n const result = nothing();\n\n for (const dl of elementsNamed(parsed.root, \"dl\")) {\n const items = listItems(dl).filter((item) => item.tagName === \"dt\" || item.tagName === \"dd\");\n let i = 0;\n while (i < items.length) {\n const dts: Element[] = [];\n const dds: Element[] = [];\n for (let item = items[i]; item?.tagName === \"dt\"; item = items[++i]) dts.push(item);\n for (let item = items[i]; item?.tagName === \"dd\"; item = items[++i]) dds.push(item);\n const first = dts[0] ?? dds[0];\n const last = dds[dds.length - 1] ?? dts[dts.length - 1];\n if (first === undefined || last === undefined) break;\n\n const named = dts.filter((dt) => textOfNode(dt) !== \"\");\n const [labelDt, ...altDts] = named;\n const [dd] = dds;\n const raw: Partial<Record<TermField, unknown>> = {\n label: labelDt === undefined ? undefined : textOfNode(labelDt),\n \"alt-labels\": altDts.map(textOfNode),\n definition: dd === undefined ? undefined : definitionOf(dd),\n };\n const lines: Partial<Record<TermField, number | undefined>> = {\n label: labelDt === undefined ? undefined : lineOf(labelDt),\n \"alt-labels\": altDts[0] === undefined ? undefined : lineOf(altDts[0]),\n definition: dd === undefined ? undefined : lineOf(dd),\n };\n const line = lineOf(first);\n const record = recordOf(raw);\n if (record === undefined) {\n result.notices.push(skipped(input, line, DL_LABEL));\n continue;\n }\n const span = spanOf(parsed, first, last);\n const constructId = dts.map((dt) => textOf(attr(dt, \"id\"))).find((id) => id !== undefined);\n result.terms.push(\n termOf(input, {\n record,\n constructId,\n construct: \"html-dl\",\n line,\n lines,\n ...(span === undefined ? {} : { span }),\n }),\n );\n }\n }\n return result;\n}\n\nconst DFN_LABEL = \"dfn\";\n\n/** Whether `el` sits in a `<dt>`, where the `<dl>` reader already reads its term. */\nfunction insideDt(el: Element): boolean {\n let parent = el.parentNode;\n while (parent !== null && \"tagName\" in parent) {\n if (parent.tagName === \"dt\") return true;\n parent = parent.parentNode;\n }\n return false;\n}\n\n/**\n * The HTML spec's rule for the term a `<dfn>` defines: its `title`, else the\n * `title` of an `<abbr>` that is its only content, else its text. Where the\n * label came from an `<abbr>`, the abbreviation is an alt-label.\n */\nfunction dfnFields(dfn: Element): { label?: string; alt?: string } {\n const title = textOf(attr(dfn, \"title\"));\n if (title !== undefined) return { label: title };\n const content = dfn.childNodes.filter((child) =>\n child.nodeName === \"#text\" && \"value\" in child ? child.value.trim() !== \"\" : isElement(child),\n );\n const [only] = content;\n if (content.length === 1 && only !== undefined && isElement(only) && only.tagName === \"abbr\") {\n const abbrTitle = textOf(attr(only, \"title\"));\n if (abbrTitle !== undefined) return { label: abbrTitle, alt: textOfNode(only) };\n }\n return { label: textOfNode(dfn) };\n}\n\nfunction readDfn(input: TermInput): TermReadResult {\n if (!declares(input, \"term-set\")) return nothing();\n const parsed = parseHtml(input);\n const result = nothing();\n for (const dfn of elementsNamed(parsed.root, \"dfn\")) {\n if (insideDt(dfn)) continue;\n const { label, alt } = dfnFields(dfn);\n const line = lineOf(dfn);\n const record = recordOf({ label, \"alt-labels\": alt });\n if (record === undefined) {\n result.notices.push(skipped(input, line, DFN_LABEL));\n continue;\n }\n const span = spanOf(parsed, dfn, dfn);\n const term: Term = termOf(input, {\n record,\n constructId: attr(dfn, \"id\"),\n construct: \"html-dfn\",\n line,\n lines: { label: line, \"alt-labels\": line },\n ...(span === undefined ? {} : { span }),\n });\n result.terms.push(term);\n }\n return result;\n}\n\nexport const htmlDlReader: TermReader = {\n construct: \"html-dl\",\n label: DL_LABEL,\n formats: [\"html\"],\n read: readDl,\n apply: (input, terms) => applyEntries(input, readDl, terms, { holds: LIST_HOLDS, id: true, serialize: htmlDlEntry }),\n};\n\nexport const htmlDfnReader: TermReader = {\n construct: \"html-dfn\",\n label: DFN_LABEL,\n formats: [\"html\"],\n read: readDfn,\n};\n","/**\n * A term manifest: a YAML or JSON mapping of id to entry, for terms held\n * outside any document. Each entry is the ten fields with no envelope. The\n * line of each entry and each field is kept, so a finding names the entry's\n * own line (proposal 0052, after 0037's sidecar).\n *\n * A write edits the entries it was handed in place: YAML through the `yaml`\n * Document API, so comments, key order and other entries survive; JSON by\n * rewriting the file with two-space indentation. An entry the file lacks is\n * appended, and an entry the file holds but the write was not handed is left\n * alone, because removing a term is not a write-back.\n */\nimport { isMap, isNode, isScalar, isSeq, LineCounter, parseDocument, stringify as stringifyYaml, type Node, type YAMLMap } from \"yaml\";\nimport { errorMessage } from \"../../../shared/errors.js\";\nimport { TermError } from \"../../errors.js\";\nimport {\n TERM_FIELDS,\n type Term,\n type TermField,\n type TermInput,\n type TermReader,\n type TermReadResult,\n type TermRecord,\n} from \"../../types.js\";\nimport { ignoredFields, ignoredNotice, recordOf, skipped, textOf, termOf } from \"./normalize.js\";\n\nconst LABEL = \"manifest\";\nconst FIELDS: ReadonlySet<string> = new Set(TERM_FIELDS);\n\nfunction isField(key: string): key is TermField {\n return FIELDS.has(key);\n}\n\nfunction read(input: TermInput): TermReadResult {\n if ((input.path ?? input.file).toLowerCase().endsWith(\".json\")) {\n try {\n JSON.parse(input.content);\n } catch (error) {\n throw new TermError(`${input.file}: could not be parsed as JSON: ${errorMessage(error)}`);\n }\n }\n\n const lineCounter = new LineCounter();\n const doc = parseDocument(input.content, { lineCounter, prettyErrors: false });\n const [firstError] = doc.errors;\n if (firstError !== undefined) {\n throw new TermError(`${input.file}: could not be parsed as YAML: ${firstError.message}`);\n }\n const lineOf = (node: Node | null | undefined): number | undefined => {\n const range = node?.range;\n return range === undefined || range === null ? undefined : lineCounter.linePos(range[0]).line;\n };\n\n const root = doc.contents;\n // An empty file holds no entries; it is not a malformed one.\n if (root === null) return { terms: [], notices: [] };\n if (!isMap(root)) {\n throw new TermError(`${input.file}: a term manifest is a mapping of id to entry.`);\n }\n\n const terms: Term[] = [];\n const notices: string[] = [];\n for (const pair of root.items) {\n const keyNode = isScalar(pair.key) ? pair.key : undefined;\n const id = textOf(keyNode?.value);\n const line = lineOf(keyNode) ?? 1;\n if (id === undefined) {\n throw new TermError(`${input.file}:${line}: an entry's key is its id, and must be a non-empty string.`);\n }\n const value = pair.value;\n if (!isMap(value)) {\n throw new TermError(`${input.file}:${line}: entry \"${id}\" is not a mapping of fields.`);\n }\n const raw: Partial<Record<TermField, unknown>> = {};\n const lines: Partial<Record<TermField, number | undefined>> = {};\n for (const field of value.items) {\n const fieldKey = isScalar(field.key) ? field.key : undefined;\n const name = fieldKey?.value;\n if (typeof name !== \"string\" || !isField(name)) continue;\n const fieldValue: unknown = field.value;\n raw[name] = isNode(fieldValue) ? fieldValue.toJSON() : fieldValue;\n lines[name] = lineOf(fieldKey);\n }\n const record = recordOf(raw);\n if (record === undefined) {\n notices.push(skipped(input, line, LABEL));\n continue;\n }\n for (const ignored of ignoredFields(raw)) {\n notices.push(ignoredNotice(input, lines[ignored.field] ?? line, record.label, ignored));\n }\n terms.push(termOf(input, { record, recordId: id, construct: \"manifest\", line, lines }));\n }\n return { terms, notices };\n}\n\n/** A record as a manifest entry: its fields in the vocabulary's order. */\nfunction entryOf(record: TermRecord): Record<string, unknown> {\n const entry: Record<string, unknown> = {};\n for (const field of TERM_FIELDS) {\n const value = record[field];\n if (value !== undefined) entry[field] = value;\n }\n return entry;\n}\n\n/** The record an entry currently holds, as a reader normalizes it; `{}` for fields when it has no label. */\nfunction currentRecord(value: unknown): Partial<TermRecord> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return {};\n const raw: Partial<Record<TermField, unknown>> = {};\n for (const field of TERM_FIELDS) raw[field] = (value as Record<string, unknown>)[field];\n return recordOf(raw) ?? {};\n}\n\n/** The fields whose value differs between what the file holds and what the term says. */\nfunction changedFields(current: Partial<TermRecord>, record: TermRecord): TermField[] {\n return TERM_FIELDS.filter((field) => JSON.stringify(current[field]) !== JSON.stringify(record[field]));\n}\n\nfunction applyJson(input: TermInput, terms: readonly Term[]): string {\n let data: unknown;\n try {\n data = JSON.parse(input.content);\n } catch (error) {\n throw new TermError(`${input.file}: could not be parsed as JSON: ${errorMessage(error)}`);\n }\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n throw new TermError(`${input.file}: a term manifest is a mapping of id to entry.`);\n }\n const root = data as Record<string, unknown>;\n let changed = false;\n for (const term of terms) {\n const existing = root[term.id];\n if (typeof existing !== \"object\" || existing === null || Array.isArray(existing)) {\n if (existing !== undefined) {\n throw new TermError(`${input.file}: entry \"${term.id}\" is not a mapping of fields.`);\n }\n root[term.id] = entryOf(term.record);\n changed = true;\n continue;\n }\n const entry = existing as Record<string, unknown>;\n const fields = changedFields(currentRecord(entry), term.record);\n if (fields.length === 0) continue;\n // Rebuilt rather than mutated, so a field keeps its place and a removed one is simply not copied.\n const next: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(entry)) {\n if (!isField(key) || !fields.includes(key)) next[key] = value;\n else if (term.record[key] !== undefined) next[key] = term.record[key];\n }\n for (const field of fields) {\n if (term.record[field] !== undefined && !(field in next)) next[field] = term.record[field];\n }\n root[term.id] = next;\n changed = true;\n }\n if (!changed) return input.content;\n const text = `${JSON.stringify(root, null, 2)}\\n`;\n return input.content.includes(\"\\r\\n\") ? text.replaceAll(\"\\n\", \"\\r\\n\") : text;\n}\n\n/** Each top-level entry's `[start, end)` in the text it was parsed from: its key through its value. */\nfunction entryRanges(root: YAMLMap): Map<string, { start: number; end: number }> {\n const ranges = new Map<string, { start: number; end: number }>();\n for (const pair of root.items) {\n if (!isScalar(pair.key)) continue;\n const id = textOf(pair.key.value);\n const start = pair.key.range?.[0];\n const end = isNode(pair.value) ? pair.value.range?.[1] : pair.key.range?.[1];\n if (id !== undefined && start !== undefined && end !== undefined) ranges.set(id, { start, end });\n }\n return ranges;\n}\n\n/** Edit the fields of `entry` that differ from `record`. Returns whether anything changed. */\nfunction editEntry(doc: ReturnType<typeof parseDocument>, entry: YAMLMap, record: TermRecord): boolean {\n const fields = changedFields(currentRecord(entry.toJSON()), record);\n for (const field of fields) {\n const value = record[field];\n if (value === undefined) {\n entry.delete(field);\n } else if (Array.isArray(value)) {\n // A list keeps the style it was written in.\n const previous = entry.get(field, true);\n const node = doc.createNode(value);\n node.flow = isSeq(previous) && previous.flow === true;\n entry.set(field, node);\n } else {\n // A scalar set in place keeps its quoting and its comments.\n entry.set(field, value);\n }\n }\n return fields.length > 0;\n}\n\n/**\n * The document is edited through the Document API and stringified, and only\n * the entries that changed are taken from that text: every other byte of the\n * file stays as it was written, since stringifying reflows what it did not\n * touch (flow-list spacing, comment spacing).\n */\nfunction applyYaml(input: TermInput, terms: readonly Term[]): string {\n const { content } = input;\n const doc = parseDocument(content, { prettyErrors: false });\n const [firstError] = doc.errors;\n if (firstError !== undefined) {\n throw new TermError(`${input.file}: could not be parsed as YAML: ${firstError.message}`);\n }\n const eol = content.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const root = doc.contents;\n if (root === null) {\n // An empty manifest: every entry is new, and there is nothing to keep.\n if (terms.length === 0) return content;\n const entries = Object.fromEntries(terms.map((term) => [term.id, entryOf(term.record)]));\n return stringifyYaml(entries, { lineWidth: 0 }).replaceAll(\"\\n\", eol);\n }\n if (!isMap(root)) {\n throw new TermError(`${input.file}: a term manifest is a mapping of id to entry.`);\n }\n const wholeFile = root.flow === true;\n const before = entryRanges(root);\n\n const changed: string[] = [];\n const added: string[] = [];\n for (const term of terms) {\n const pair = root.items.find((item) => isScalar(item.key) && textOf(item.key.value) === term.id);\n if (pair === undefined) {\n root.add(doc.createPair(term.id, entryOf(term.record)));\n added.push(term.id);\n continue;\n }\n if (!isMap(pair.value)) {\n throw new TermError(`${input.file}: entry \"${term.id}\" is not a mapping of fields.`);\n }\n if (editEntry(doc, pair.value, term.record)) changed.push(term.id);\n }\n if (changed.length === 0 && added.length === 0) return content;\n\n const text = doc.toString({ lineWidth: 0 });\n if (wholeFile) return text.replaceAll(\"\\n\", eol);\n\n const written = parseDocument(text).contents;\n const after = isMap(written) ? entryRanges(written) : new Map<string, { start: number; end: number }>();\n const entryText = (id: string): string => {\n const range = after.get(id);\n if (range === undefined) throw new TermError(`${input.file}: could not write entry \"${id}\".`);\n return text.slice(range.start, range.end).replaceAll(\"\\n\", eol);\n };\n\n let next = content;\n const edits = changed\n .map((id) => ({ id, range: before.get(id) }))\n .sort((a, b) => (b.range?.start ?? 0) - (a.range?.start ?? 0));\n for (const { id, range } of edits) {\n if (range === undefined) throw new TermError(`${input.file}: could not write entry \"${id}\".`);\n next = next.slice(0, range.start) + entryText(id) + next.slice(range.end);\n }\n if (added.length > 0) {\n if (next !== \"\" && !next.endsWith(\"\\n\")) next += eol;\n next += added.map((id) => `${entryText(id)}${eol}`).join(\"\");\n }\n return next;\n}\n\nfunction isJson(input: TermInput): boolean {\n return (input.path ?? input.file).toLowerCase().endsWith(\".json\");\n}\n\nexport const manifestReader: TermReader = {\n construct: \"manifest\",\n label: LABEL,\n formats: [\"manifest\"],\n read,\n apply: (input, terms) => (isJson(input) ? applyJson(input, terms) : applyYaml(input, terms)),\n};\n","/**\n * A term page: one term per file, its record in the file's metadata channel.\n * Every extractor already reads that channel, so this reader works in every\n * format meta reads, and is told apart from any other page by `type: term`.\n *\n * It writes back through the same extractor: a field that changed is set, a\n * field that became absent is removed, and nothing outside the ten\n * terminology fields is touched.\n */\nimport { extractorByName } from \"../../../meta/internal.js\";\nimport { errorMessage } from \"../../../shared/errors.js\";\nimport { TermError } from \"../../errors.js\";\nimport {\n TERM_FIELDS,\n type Term,\n type TermField,\n type TermInput,\n type TermReader,\n type TermReadResult,\n} from \"../../types.js\";\nimport { declares, ignoredFields, ignoredNotice, nothing, recordOf, skipped, termOf } from \"./normalize.js\";\nimport { sameFields } from \"./splice.js\";\n\nconst LABEL = \"page\";\n\nfunction read(input: TermInput): TermReadResult {\n if (!declares(input, \"term\")) return nothing();\n const raw: Partial<Record<TermField, unknown>> = {};\n const lines: Partial<Record<TermField, number | undefined>> = {};\n for (const field of TERM_FIELDS) {\n raw[field] = input.metadata[field];\n lines[field] = input.lineFor(`/${field}`);\n }\n const record = recordOf(raw);\n if (record === undefined) return { terms: [], notices: [skipped(input, 1, LABEL)] };\n return {\n terms: [termOf(input, { record, recordId: input.metadata[\"id\"], construct: \"page\", line: 1, lines })],\n notices: ignoredFields(raw).map((ignored) =>\n ignoredNotice(input, lines[ignored.field] ?? 1, record.label, ignored),\n ),\n };\n}\n\nfunction apply(input: TermInput, terms: readonly Term[]): string {\n const [term] = terms;\n if (term === undefined) return input.content;\n const [current] = read(input).terms;\n if (current === undefined) {\n throw new TermError(`${input.file}: is not a term page any more. Read the file again before writing it.`);\n }\n\n const patch: Record<string, unknown> = {};\n const deletions: TermField[] = [];\n for (const field of TERM_FIELDS) {\n if (sameFields(current.record, term.record, [field])) continue;\n const value = term.record[field];\n if (value === undefined) deletions.push(field);\n else patch[field] = value;\n }\n if (Object.keys(patch).length === 0 && deletions.length === 0) return input.content;\n\n const extractor = extractorByName(input.format);\n if (extractor?.apply === undefined) {\n throw new TermError(`${input.file}: manni cannot write ${input.format} metadata.`);\n }\n const filePath = input.path ?? input.file;\n let next: string;\n try {\n next = extractor.apply(input.content, patch, { deletions, filePath });\n } catch (error) {\n throw new TermError(`${input.file}: ${errorMessage(error)}`);\n }\n // A writer that cannot remove a key ignores the request; say so rather than\n // report a write that left the field in place.\n const written = extractor.extract(next, filePath).data;\n for (const field of deletions) {\n if (written[field] !== undefined) {\n throw new TermError(`${input.file}: could not remove ${field} from its ${input.format} metadata. Remove it by hand.`);\n }\n }\n return next;\n}\n\nexport const pageReader: TermReader = {\n construct: \"page\",\n label: LABEL,\n formats: [\"markdown\", \"mdx\", \"asciidoc\", \"rst\", \"html\", \"xml\"],\n read,\n apply,\n};\n","/**\n * Readers for constructs whose parser gives structure directly: page\n * metadata through meta's extractors, manifests, DITA, DocBook and HTML.\n */\nimport type { TermReader } from \"../../types.js\";\nimport { ditaGlossentryReader, ditaGlossgroupReader } from \"./dita.js\";\nimport { docbookGlossaryReader } from \"./docbook.js\";\nimport { htmlDfnReader, htmlDlReader } from \"./html.js\";\nimport { manifestReader } from \"./manifest.js\";\nimport { pageReader } from \"./page.js\";\n\nexport const STRUCTURED_READERS: readonly TermReader[] = [\n pageReader,\n manifestReader,\n ditaGlossentryReader,\n ditaGlossgroupReader,\n docbookGlossaryReader,\n htmlDlReader,\n htmlDfnReader,\n];\n","/**\n * What the body readers share: the body as lines, with the ones inside fenced\n * code marked, and the one way an entry becomes a `Term`.\n *\n * The body starts after a leading fenced metadata block (`---`, `+++`, `;;;`),\n * found the way the extractors find it. A native header (an AsciiDoc\n * attribute block, an rST docinfo field list) is read from the top, because\n * no construct read here can be mistaken for one.\n */\nimport { locateFrontmatter } from \"../../../meta/index.js\";\nimport { codeEndAt, codeRegions } from \"../../../shared/code-regions.js\";\nimport type { Term, TermConstruct, TermField, TermInput, TermRecord } from \"../../types.js\";\nimport { slugOf } from \"../id.js\";\n\nexport interface BodyLine {\n /** The line without its terminator or a trailing CR. */\n text: string;\n /** Offset of the line's first character in the file's content. */\n start: number;\n /** Offset just past the line's text, before any CR or LF. */\n end: number;\n /** 1-based file line. */\n line: number;\n /** Whether the line sits in fenced code. */\n code: boolean;\n}\n\n/** Offset of the line's first non-blank character: where an entry that starts on it begins. */\nexport function textStart(line: BodyLine): number {\n return line.start + (line.text.length - line.text.trimStart().length);\n}\n\nexport function isBlank(line: BodyLine): boolean {\n return line.text.trim() === \"\";\n}\n\n/** The index of the first line at or after `from` that is not blank prose (the length when none). */\nexport function nextNonBlank(lines: readonly BodyLine[], from: number): number {\n let k = from;\n for (let line = lines[k]; line !== undefined && !line.code && isBlank(line); line = lines[k]) k++;\n return k;\n}\n\n/** The file's body, line by line. */\nexport function bodyLines(input: TermInput): BodyLine[] {\n const { content } = input;\n const bodyStart = locateFrontmatter(content)?.closeEnd ?? 0;\n const body = content.slice(bodyStart);\n const code = codeRegions(body, input.format, { spans: false });\n let line = 1;\n for (let i = 0; i < bodyStart; i++) {\n if (content.charCodeAt(i) === 10) line++;\n }\n const out: BodyLine[] = [];\n let pos = bodyStart;\n while (pos < content.length) {\n const nl = content.indexOf(\"\\n\", pos);\n const stop = nl === -1 ? content.length : nl;\n const end = stop > pos && content.charCodeAt(stop - 1) === 13 ? stop - 1 : stop;\n out.push({\n text: content.slice(pos, end),\n start: pos,\n end,\n line,\n code: codeEndAt(code, pos - bodyStart) !== undefined,\n });\n line++;\n pos = stop + 1;\n }\n return out;\n}\n\n/**\n * A definition's text: each line trimmed, the lines of a paragraph joined with\n * one space, paragraphs separated by one blank line. Undefined when nothing is\n * left.\n */\nexport function definitionText(paragraphs: readonly (readonly string[])[]): string | undefined {\n const text = paragraphs\n .map((lines) =>\n lines\n .map((l) => l.trim())\n .filter((l) => l !== \"\")\n .join(\" \"),\n )\n .filter((p) => p !== \"\")\n .join(\"\\n\\n\");\n return text === \"\" ? undefined : text;\n}\n\nexport interface EntryLabel {\n text: string;\n line: number;\n}\n\nexport interface Entry {\n /** The terms in source order; the first is the label. At least one, each non-empty. */\n labels: readonly EntryLabel[];\n definition: string;\n definitionLine: number;\n start: number;\n end: number;\n}\n\n/** A read entry as a `Term`. */\nexport function termOf(input: TermInput, construct: TermConstruct, entry: Entry): Term {\n const [first, ...rest] = entry.labels;\n const label = first?.text.trim() ?? \"\";\n const record: TermRecord = { label };\n const fieldLines: Partial<Record<TermField, number>> = { label: first?.line ?? entry.definitionLine };\n const alts = rest.map((l) => l.text.trim()).filter((t) => t !== \"\");\n const [firstAlt] = rest;\n if (alts.length > 0 && firstAlt !== undefined) {\n record[\"alt-labels\"] = alts;\n fieldLines[\"alt-labels\"] = firstAlt.line;\n }\n record.definition = entry.definition;\n fieldLines.definition = entry.definitionLine;\n const language = input.metadata[\"language\"];\n return {\n id: slugOf(label),\n record,\n ...(typeof language === \"string\" && language.trim() !== \"\" ? { language: language.trim() } : {}),\n location: {\n file: input.file,\n ...(input.path === undefined ? {} : { path: input.path }),\n construct,\n line: first?.line ?? entry.definitionLine,\n fieldLines,\n span: { start: entry.start, end: entry.end },\n },\n };\n}\n\n/** The notice for an entry a reader could not read. */\nexport function skippedNotice(\n input: TermInput,\n line: number,\n label: string,\n missing: \"term\" | \"definition\",\n): string {\n return `${input.file}:${String(line)}: skipped a ${label} entry with no ${missing}.`;\n}\n","/**\n * AsciiDoc glossary lists: a labelled list under a `[glossary]` block\n * attribute line, which says what it is, so no metadata declaration is needed.\n *\n * [glossary]\n * mud:: wet, cold dirt\n * jam::\n * sweet, sticky mess\n * command-line interface::\n * CLI:: a program you drive\n * +\n * A `+` line starts another paragraph of the same definition.\n *\n * A block title (`.Terms`) and blank lines may sit between the attribute and\n * the list. Terms stacked on adjacent lines share the definition below the\n * last of them; the first is the label and the rest are alt-labels. The\n * definition is the text after `::` and the non-blank lines directly below.\n * The list ends at a blank line followed by anything but another item, and at\n * a section title, a block attribute or title line, a delimited block, or code.\n */\nimport type { Term, TermInput, TermReadResult, TermReader } from \"../../types.js\";\nimport { LIST_HOLDS, asciidocEntry } from \"../writers/entries.js\";\nimport { applyEntries } from \"./splice.js\";\nimport {\n bodyLines,\n definitionText,\n isBlank,\n nextNonBlank,\n skippedNotice,\n termOf,\n textStart,\n type BodyLine,\n} from \"./body.js\";\n\nconst LABEL = \"[glossary] list\";\nconst ATTRIBUTE = /^\\[glossary\\][ \\t]*$/;\n/** `term::` or `term:: definition`. A term ending in `:` is a deeper `:::` level, not this list's. */\nconst ITEM = /^[ \\t]*(.*?[^:\\s])::(?:[ \\t]+(.*))?$/;\nconst BLOCK_TITLE = /^\\.[^.\\s]/;\n/** Lines that end the list outright: a section title, an attribute line, a delimiter. */\nconst LIST_END = /^(?:=+[ \\t]|\\[.*\\][ \\t]*$|(?:-{4,}|={4,}|\\*{4,}|\\.{4,}|_{4,}|\\+{4,}|\\|===)[ \\t]*$)/;\n\ninterface Open {\n labels: BodyLine[];\n definitionLine: number;\n paragraphs: string[][];\n last: BodyLine;\n}\n\nfunction item(line: BodyLine): { term: string; text: string | undefined } | undefined {\n const match = ITEM.exec(line.text);\n const term = match?.[1];\n if (match === null || term === undefined) return undefined;\n const text = match[2]?.trim();\n return { term, text: text === \"\" ? undefined : text };\n}\n\nfunction read(input: TermInput): TermReadResult {\n const terms: Term[] = [];\n const notices: string[] = [];\n const lines = bodyLines(input);\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n i++;\n if (line === undefined || line.code || !ATTRIBUTE.test(line.text)) continue;\n // Blank lines and a block title may sit between the attribute and its list.\n let start = i;\n for (let l = lines[start]; l !== undefined && !l.code && (isBlank(l) || BLOCK_TITLE.test(l.text)); l = lines[start]) {\n start++;\n }\n const first = lines[start];\n if (first === undefined || first.code || item(first) === undefined) continue;\n i = readList(input, lines, start, terms, notices);\n }\n return { terms, notices };\n}\n\n/** Read the list starting at index `at`, an item. Returns the index just past it. */\nfunction readList(\n input: TermInput,\n lines: readonly BodyLine[],\n at: number,\n terms: Term[],\n notices: string[],\n): number {\n let pending: BodyLine[] = [];\n let open: Open | undefined;\n\n const close = (): void => {\n if (open !== undefined) {\n const text = definitionText(open.paragraphs);\n const [firstLabel] = open.labels;\n if (text !== undefined && firstLabel !== undefined) {\n terms.push(\n termOf(input, \"asciidoc-glossary\", {\n labels: open.labels.map((l) => ({ text: itemTerm(l), line: l.line })),\n definition: text,\n definitionLine: open.definitionLine,\n start: textStart(firstLabel),\n end: open.last.end,\n }),\n );\n } else if (firstLabel !== undefined) {\n notices.push(skippedNotice(input, firstLabel.line, LABEL, \"definition\"));\n }\n open = undefined;\n }\n const [firstPending] = pending;\n if (firstPending !== undefined) {\n notices.push(skippedNotice(input, firstPending.line, LABEL, \"definition\"));\n pending = [];\n }\n };\n\n let i = at;\n for (;;) {\n const line = lines[i];\n if (line === undefined || line.code) break;\n\n if (isBlank(line)) {\n close();\n const k = nextNonBlank(lines, i);\n const next = lines[k];\n if (next === undefined || next.code || item(next) === undefined) break;\n i = k;\n continue;\n }\n\n const entry = item(line);\n if (entry !== undefined) {\n if (open !== undefined) close();\n pending.push(line);\n if (entry.text !== undefined) {\n open = { labels: pending, definitionLine: line.line, paragraphs: [[entry.text]], last: line };\n pending = [];\n }\n i++;\n continue;\n }\n\n if (line.text.trim() === \"+\" && open !== undefined) {\n open.paragraphs.push([]);\n i++;\n continue;\n }\n if (LIST_END.test(line.text) || BLOCK_TITLE.test(line.text)) break;\n\n if (open !== undefined) {\n open.paragraphs.at(-1)?.push(line.text);\n open.last = line;\n } else if (pending.length > 0) {\n open = { labels: pending, definitionLine: line.line, paragraphs: [[line.text]], last: line };\n pending = [];\n } else {\n break;\n }\n i++;\n }\n close();\n return i;\n}\n\nfunction itemTerm(line: BodyLine): string {\n return item(line)?.term ?? line.text;\n}\n\nexport const asciidocGlossaryReader: TermReader = {\n construct: \"asciidoc-glossary\",\n label: LABEL,\n formats: [\"asciidoc\"],\n read,\n apply: (input, terms) =>\n applyEntries(input, read, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => asciidocEntry(term.record) }),\n};\n","/**\n * Markdown and MDX definition lists, in PHP Markdown Extra's syntax:\n *\n * Term\n * Another term\n * : The definition, whose continuation lines\n * are indented by four spaces or a tab.\n *\n * A blank line and an indented line start a second paragraph.\n *\n * A definition list does not say what it is, so it is read only in a file\n * whose metadata declares `type: term-set`. The term lines sit directly above\n * the first `:` line; the first is the label and the rest are alt-labels. An\n * unindented line directly below a definition line continues it, as Markdown\n * Extra's lazy continuation does. A second `:` definition, directly below or\n * after a blank line, is kept out of the record and said as a notice.\n */\nimport type { Term, TermInput, TermReadResult, TermReader } from \"../../types.js\";\nimport { LIST_HOLDS, markdownEntry } from \"../writers/entries.js\";\nimport { applyEntries } from \"./splice.js\";\nimport {\n bodyLines,\n definitionText,\n isBlank,\n nextNonBlank,\n skippedNotice,\n termOf,\n textStart,\n type BodyLine,\n} from \"./body.js\";\n\nconst LABEL = \"definition list\";\n/** A definition line: `:` then one or more spaces or tabs and the text, or a bare `:`. */\nconst DEFINITION = /^:(?:[ \\t]+(.*))?$/;\nconst INDENTED = /^(?: {4}|\\t)/;\nconst HEADING = /^#{1,6}(?:[ \\t]|$)/;\n\ninterface Definition {\n line: number;\n paragraphs: string[][];\n}\n\nfunction definitionStart(line: BodyLine | undefined): string | undefined {\n if (line === undefined || line.code) return undefined;\n const match = DEFINITION.exec(line.text);\n return match === null ? undefined : (match[1] ?? \"\");\n}\n\nfunction read(input: TermInput): TermReadResult {\n const terms: Term[] = [];\n const notices: string[] = [];\n if (input.metadata[\"type\"] !== \"term-set\") return { terms, notices };\n\n const lines = bodyLines(input);\n let i = 0;\n while (i < lines.length) {\n const first = lines[i];\n if (first === undefined) break;\n if (first.code || isBlank(first)) {\n i++;\n continue;\n }\n\n // A run of term lines, then a definition line directly below them.\n const labels: BodyLine[] = [];\n let j = i;\n for (;;) {\n const line = lines[j];\n if (line === undefined || line.code || isBlank(line) || definitionStart(line) !== undefined) break;\n labels.push(line);\n j++;\n }\n const opener = definitionStart(lines[j]);\n if (opener === undefined) {\n // A paragraph, not an entry: skip to its end.\n i = j === i ? i + 1 : j;\n continue;\n }\n if (labels.length === 0 || labels.some((l) => HEADING.test(l.text))) {\n const orphan = lines[j];\n if (orphan !== undefined) notices.push(skippedNotice(input, orphan.line, LABEL, \"term\"));\n i = readDefinitions(lines, j, []);\n continue;\n }\n\n const definitions: Definition[] = [];\n i = readDefinitions(lines, j, definitions);\n const firstLabel = labels[0];\n const [kept] = definitions;\n if (firstLabel === undefined || kept === undefined) continue;\n const text = definitionText(kept.paragraphs);\n if (text === undefined) {\n notices.push(skippedNotice(input, firstLabel.line, LABEL, \"definition\"));\n continue;\n }\n for (const extra of definitions.slice(1)) {\n notices.push(\n `${input.file}:${String(extra.line)}: kept the first of ${String(definitions.length)} definitions for \"${firstLabel.text.trim()}\".`,\n );\n }\n const last = lastContentLine(lines, i);\n terms.push(\n termOf(input, \"markdown-deflist\", {\n labels: labels.map((l) => ({ text: l.text, line: l.line })),\n definition: text,\n definitionLine: kept.line,\n start: textStart(firstLabel),\n end: last?.end ?? firstLabel.end,\n }),\n );\n }\n return { terms, notices };\n}\n\n/** The last non-blank line before index `stop`. */\nfunction lastContentLine(lines: readonly BodyLine[], stop: number): BodyLine | undefined {\n for (let k = stop - 1; k >= 0; k--) {\n const line = lines[k];\n if (line !== undefined && !isBlank(line)) return line;\n }\n return undefined;\n}\n\n/**\n * Read the definitions starting at index `at`, which is a definition line,\n * into `out`. Returns the index just past the last line they cover.\n */\nfunction readDefinitions(lines: readonly BodyLine[], at: number, out: Definition[]): number {\n let i = at;\n for (;;) {\n const opener = lines[i];\n const text = definitionStart(opener);\n if (opener === undefined || text === undefined) return i;\n const definition: Definition = { line: opener.line, paragraphs: [[text]] };\n out.push(definition);\n i++;\n for (;;) {\n const line = lines[i];\n if (line === undefined || line.code) return i;\n if (definitionStart(line) !== undefined) break;\n if (!isBlank(line)) {\n // Indented or lazy, a line directly below belongs to the paragraph.\n definition.paragraphs.at(-1)?.push(line.text.replace(INDENTED, \"\"));\n i++;\n continue;\n }\n // A blank line: what follows decides.\n const k = nextNonBlank(lines, i);\n const next = lines[k];\n if (next === undefined || next.code) return i;\n if (definitionStart(next) !== undefined) {\n i = k;\n break;\n }\n if (!INDENTED.test(next.text)) return i;\n definition.paragraphs.push([]);\n i = k;\n }\n }\n}\n\nexport const markdownDeflistReader: TermReader = {\n construct: \"markdown-deflist\",\n label: LABEL,\n formats: [\"markdown\", \"mdx\"],\n read,\n apply: (input, terms) =>\n applyEntries(input, read, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => markdownEntry(term.record) }),\n};\n","/**\n * reStructuredText glossaries: the Sphinx `.. glossary::` directive, which says\n * what it is, so no metadata declaration is needed.\n *\n * .. glossary::\n * :sorted:\n *\n * source directory\n * source dir\n * The directory that holds sources.\n *\n * A blank line starts another paragraph.\n *\n * Option lines directly below the directive are skipped. The first content\n * line sets the base indentation: a line there is a term, a line indented\n * further is definition, and a blank line may sit between the two. Terms on\n * adjacent lines share the definition below them; the first is the label and the rest are alt-labels. A term's\n * classifier (`term : index key`) is not part of the label. The directive ends\n * where indentation returns to or below its own.\n *\n * rST has no fences, so code is found here: the body of a `code-block`,\n * `code` or `sourcecode` directive, and the literal block after a paragraph\n * ending in `::`, are never read.\n */\nimport type { Term, TermInput, TermReadResult, TermReader } from \"../../types.js\";\nimport { LIST_HOLDS, rstEntry } from \"../writers/entries.js\";\nimport { applyEntries } from \"./splice.js\";\nimport { bodyLines, definitionText, isBlank, skippedNotice, termOf, textStart, type BodyLine } from \"./body.js\";\n\nconst LABEL = \".. glossary::\";\nconst DIRECTIVE = /^[ \\t]*\\.\\.[ \\t]+glossary::[ \\t]*$/;\nconst CODE_DIRECTIVE = /^[ \\t]*\\.\\.[ \\t]+(?:code-block|code|sourcecode)::/;\nconst EXPLICIT_MARKUP = /^[ \\t]*\\.\\.(?:[ \\t]|$)/;\nconst OPTION = /^[ \\t]*:[^:\\s][^:]*:(?:[ \\t].*)?$/;\nconst CLASSIFIER = /[ \\t]+:[ \\t]+/;\n\n/** Indentation width, with a tab advancing to the next multiple of 8 as rST reads it. */\nfunction indentOf(text: string): number {\n let width = 0;\n for (const ch of text) {\n if (ch === \" \") width++;\n else if (ch === \"\\t\") width += 8 - (width % 8);\n else break;\n }\n return width;\n}\n\n/** Whether a line introduces an indented block that is code. */\nfunction opensLiteral(line: BodyLine): boolean {\n if (CODE_DIRECTIVE.test(line.text)) return true;\n return !EXPLICIT_MARKUP.test(line.text) && line.text.trimEnd().endsWith(\"::\");\n}\n\nfunction read(input: TermInput): TermReadResult {\n const terms: Term[] = [];\n const notices: string[] = [];\n const lines = bodyLines(input);\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n if (line === undefined) break;\n if (isBlank(line)) {\n i++;\n continue;\n }\n if (DIRECTIVE.test(line.text)) {\n i = readGlossary(input, lines, i, terms, notices);\n continue;\n }\n i = opensLiteral(line) ? blockEnd(lines, i + 1, indentOf(line.text)) : i + 1;\n }\n return { terms, notices };\n}\n\n/**\n * The index of the first non-blank line at or after `from` indented `indent`\n * or less: where a block opened at that indentation ends.\n */\nfunction blockEnd(lines: readonly BodyLine[], from: number, indent: number): number {\n let k = from;\n for (let l = lines[k]; l !== undefined && (isBlank(l) || indentOf(l.text) > indent); l = lines[k]) k++;\n return k;\n}\n\ninterface Definition {\n line: number;\n paragraphs: string[][];\n last: BodyLine;\n gap: boolean;\n}\n\n/** Read the glossary whose directive is at index `at`. Returns the index just past it. */\nfunction readGlossary(\n input: TermInput,\n lines: readonly BodyLine[],\n at: number,\n terms: Term[],\n notices: string[],\n): number {\n const directive = lines[at];\n if (directive === undefined) return at + 1;\n const end = blockEnd(lines, at + 1, indentOf(directive.text));\n\n let i = at + 1;\n for (let l = lines[i]; i < end && l !== undefined && !isBlank(l) && OPTION.test(l.text); l = lines[i]) i++;\n\n let base: number | undefined;\n let labels: BodyLine[] = [];\n let definition: Definition | undefined;\n let orphan = false;\n\n const close = (): void => {\n const [first] = labels;\n if (first !== undefined) {\n const text = definition === undefined ? undefined : definitionText(definition.paragraphs);\n if (definition !== undefined && text !== undefined) {\n terms.push(\n termOf(input, \"rst-glossary\", {\n labels: labels.map((l) => ({ text: termText(l), line: l.line })),\n definition: text,\n definitionLine: definition.line,\n start: textStart(first),\n end: definition.last.end,\n }),\n );\n } else {\n notices.push(skippedNotice(input, first.line, LABEL, \"definition\"));\n }\n }\n labels = [];\n definition = undefined;\n };\n\n let blank = false;\n for (; i < end; i++) {\n const line = lines[i];\n if (line === undefined) break;\n if (isBlank(line)) {\n if (definition !== undefined) definition.gap = true;\n blank = true;\n continue;\n }\n const indent = indentOf(line.text);\n base ??= indent;\n if (indent <= base) {\n // A term after a definition, or after a blank line below terms that\n // never got one, starts a new entry.\n if (definition !== undefined || blank) close();\n orphan = false;\n blank = false;\n labels.push(line);\n continue;\n }\n blank = false;\n if (definition !== undefined) {\n if (definition.gap) {\n definition.paragraphs.push([]);\n definition.gap = false;\n }\n definition.paragraphs.at(-1)?.push(line.text);\n definition.last = line;\n } else if (labels.length > 0) {\n definition = { line: line.line, paragraphs: [[line.text]], last: line, gap: false };\n } else if (!orphan) {\n notices.push(skippedNotice(input, line.line, LABEL, \"term\"));\n orphan = true;\n }\n }\n close();\n return end;\n}\n\n/** A term line's label: trimmed, without a classifier. */\nfunction termText(line: BodyLine): string {\n const text = line.text.trim();\n const match = CLASSIFIER.exec(text);\n return match === null ? text : text.slice(0, match.index);\n}\n\nexport const rstGlossaryReader: TermReader = {\n construct: \"rst-glossary\",\n label: LABEL,\n formats: [\"rst\"],\n read,\n apply: (input, terms) =>\n applyEntries(input, read, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => rstEntry(term.record) }),\n};\n","/**\n * Readers for term lists held in a text format's body: Markdown and MDX\n * definition lists, AsciiDoc `[glossary]`, and reStructuredText `.. glossary::`.\n */\nimport type { TermReader } from \"../../types.js\";\nimport { asciidocGlossaryReader } from \"./asciidoc-glossary.js\";\nimport { markdownDeflistReader } from \"./markdown-deflist.js\";\nimport { rstGlossaryReader } from \"./rst-glossary.js\";\n\nexport const TEXT_READERS: readonly TermReader[] = [\n markdownDeflistReader,\n asciidocGlossaryReader,\n rstGlossaryReader,\n];\n","/**\n * Every term reader, in the order `term formats` lists them. Split across two\n * files by how a construct is parsed, so the two groups change independently.\n */\nimport type { TermConstruct, TermReader } from \"../../types.js\";\nimport { STRUCTURED_READERS } from \"./structured.js\";\nimport { TEXT_READERS } from \"./text.js\";\n\nexport const TERM_READERS: readonly TermReader[] = [...STRUCTURED_READERS, ...TEXT_READERS];\n\n/** The readers offered a file of `format`. */\nexport function readersForFormat(\n format: string,\n readers: readonly TermReader[] = TERM_READERS,\n): TermReader[] {\n return readers.filter((reader) => reader.formats.includes(format));\n}\n\n/** The one reader for a construct, which is the one that writes it back in place. */\nexport function readerForConstruct(\n construct: TermConstruct,\n readers: readonly TermReader[] = TERM_READERS,\n): TermReader | undefined {\n return readers.find((reader) => reader.construct === construct);\n}\n","/**\n * Writers for the seven document formats. The target's shape decides the\n * construct: a directory gets one term page per term (a DITA glossentry topic\n * for DITA), a file gets every term in the format's list construct. DocBook\n * has no one-term construct, so it is written as a file only.\n */\nimport { join } from \"node:path\";\nimport { TermError } from \"../../errors.js\";\nimport {\n TERM_FIELDS,\n type Term,\n type TermField,\n type TermRender,\n type TermShape,\n type TermTarget,\n type TermWriteFormat,\n type TermWriter,\n} from \"../../types.js\";\nimport {\n DITA_HOLDS,\n DOCBOOK_HOLDS,\n LIST_HOLDS,\n asciidocEntry,\n ditaEntry,\n docbookEntry,\n htmlDlEntry,\n markdownEntry,\n rstEntry,\n} from \"./entries.js\";\nimport { fileOf, reindent, sharedLanguage, xmlAttribute } from \"./markup.js\";\nimport { htmlPage, metadataPage, yamlFrontmatter } from \"./page.js\";\nimport { droppedFields, requireShape } from \"./render-util.js\";\n\n/** Characters no file name may hold on any platform manni runs on. */\nconst UNSAFE_NAME = /[/\\\\:*?\"<>|]/;\n\ninterface DocumentSpec {\n format: TermWriteFormat;\n extension: string;\n file: {\n holds: readonly TermField[];\n render: (terms: readonly Term[]) => string;\n /**\n * Whether the file's construct reads an entry only when it has a\n * definition. A Markdown or AsciiDoc list and a `.. glossary::` skip one\n * with none, and a `<dl>` folds its `<dt>`s into the next entry's, so a\n * term with no definition is left out rather than written unreadable.\n */\n needsDefinition: boolean;\n };\n directory?: { holds: readonly TermField[]; render: (term: Term) => string };\n}\n\nfunction pagePaths(terms: readonly Term[], target: TermTarget, extension: string): string[] {\n const seen = new Set<string>();\n return terms.map((term) => {\n if (UNSAFE_NAME.test(term.id) || term.id === \".\" || term.id === \"..\") {\n throw new TermError(`the id \"${term.id}\" cannot name a file. Give the term an id without path characters.`);\n }\n if (seen.has(term.id)) {\n throw new TermError(`two terms have the id \"${term.id}\", and a directory holds one file per id.`);\n }\n seen.add(term.id);\n return join(target.path, `${term.id}${extension}`);\n });\n}\n\nfunction documentWriter(spec: DocumentSpec): TermWriter {\n const { directory } = spec;\n return {\n format: spec.format,\n shapes: directory === undefined ? [\"file\"] : [\"file\", \"directory\"],\n holds: (shape: TermShape) => (shape === \"directory\" && directory !== undefined ? directory.holds : spec.file.holds),\n render(terms, target): TermRender {\n if (target.shape === \"directory\" && directory !== undefined) {\n const paths = pagePaths(terms, target, spec.extension);\n return {\n files: terms.map((term, i) => ({ path: paths[i] ?? \"\", content: directory.render(term) })),\n removals: [],\n dropped: droppedFields(terms, directory.holds),\n skipped: [],\n };\n }\n requireShape(spec.format, target, \"file\");\n const written = spec.file.needsDefinition ? terms.filter((t) => t.record.definition !== undefined) : terms;\n return {\n files: [{ path: target.path, content: spec.file.render(written) }],\n removals: [],\n dropped: droppedFields(written, spec.file.holds),\n skipped: terms.filter((t) => !written.includes(t)).map((t) => t.id),\n };\n },\n };\n}\n\n/** Entries at indentation zero, a blank line between them, each indented to `indent`. */\nfunction entriesBlock(entries: readonly string[], indent = \"\"): string[] {\n return entries.flatMap((entry, i) => [\n ...(i === 0 ? [] : [\"\"]),\n `${indent}${reindent(entry, indent, \"\\n\")}`,\n ]);\n}\n\n/** Every line of each entry indented, no blank line between: markup keeps its entries adjacent. */\nfunction markupBlock(entries: readonly string[], indent: string): string[] {\n return entries.map((entry) => `${indent}${reindent(entry, indent, \"\\n\")}`);\n}\n\nfunction textPage(format: string): (term: Term) => string {\n return (term) => metadataPage(format, term);\n}\n\n/** The frontmatter a many-per-file text document opens with, or none when it would be empty. */\nfunction listFrontmatter(terms: readonly Term[], type: boolean): string[] {\n const metadata: Record<string, unknown> = {};\n if (type) metadata[\"type\"] = \"term-set\";\n const language = sharedLanguage(terms);\n if (language !== undefined) metadata[\"language\"] = language;\n if (Object.keys(metadata).length === 0) return [];\n return [yamlFrontmatter(metadata).replace(/\\n$/, \"\"), \"\"];\n}\n\nfunction markdownList(terms: readonly Term[]): string {\n return fileOf([...listFrontmatter(terms, true), ...entriesBlock(terms.map((t) => markdownEntry(t.record)))]);\n}\n\nconst XML_DECLARATION = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>';\n\nfunction langAttribute(language: string | undefined): string {\n return language === undefined ? \"\" : ` xml:lang=\"${xmlAttribute(language)}\"`;\n}\n\nexport const markdownWriter = documentWriter({\n format: \"markdown\",\n extension: \".md\",\n file: { holds: LIST_HOLDS, render: markdownList, needsDefinition: true },\n directory: { holds: TERM_FIELDS, render: textPage(\"markdown\") },\n});\n\nexport const mdxWriter = documentWriter({\n format: \"mdx\",\n extension: \".mdx\",\n file: { holds: LIST_HOLDS, render: markdownList, needsDefinition: true },\n directory: { holds: TERM_FIELDS, render: textPage(\"mdx\") },\n});\n\nexport const asciidocWriter = documentWriter({\n format: \"asciidoc\",\n extension: \".adoc\",\n file: {\n holds: LIST_HOLDS,\n needsDefinition: true,\n render: (terms) =>\n fileOf([...listFrontmatter(terms, false), \"[glossary]\", ...entriesBlock(terms.map((t) => asciidocEntry(t.record)))]),\n },\n directory: { holds: TERM_FIELDS, render: textPage(\"asciidoc\") },\n});\n\nexport const rstWriter = documentWriter({\n format: \"rst\",\n extension: \".rst\",\n file: {\n holds: LIST_HOLDS,\n needsDefinition: true,\n render: (terms) =>\n fileOf([\n ...listFrontmatter(terms, false),\n \".. glossary::\",\n \"\",\n ...entriesBlock(\n terms.map((t) => rstEntry(t.record)),\n \" \",\n ),\n ]),\n },\n directory: { holds: TERM_FIELDS, render: textPage(\"rst\") },\n});\n\nexport const htmlWriter = documentWriter({\n format: \"html\",\n extension: \".html\",\n file: {\n holds: LIST_HOLDS,\n needsDefinition: true,\n render: (terms) => {\n const language = sharedLanguage(terms);\n return fileOf([\n \"<!DOCTYPE html>\",\n \"<html>\",\n \" <head>\",\n \" <title>Glossary</title>\",\n ' <meta name=\"type\" content=\"term-set\">',\n ...(language === undefined ? [] : [` <meta name=\"language\" content=\"${xmlAttribute(language)}\">`]),\n \" </head>\",\n \" <body>\",\n \" <dl>\",\n ...markupBlock(terms.map(htmlDlEntry), \" \"),\n \" </dl>\",\n \" </body>\",\n \"</html>\",\n ]);\n },\n },\n directory: { holds: TERM_FIELDS, render: htmlPage },\n});\n\nexport const ditaWriter = documentWriter({\n format: \"dita\",\n extension: \".dita\",\n file: {\n holds: DITA_HOLDS,\n needsDefinition: false,\n render: (terms) =>\n fileOf([\n XML_DECLARATION,\n '<!DOCTYPE glossgroup PUBLIC \"-//OASIS//DTD DITA 2.0 Glossary Group//EN\" \"glossgroup.dtd\">',\n `<glossgroup id=\"glossary\"${langAttribute(sharedLanguage(terms))}>`,\n \" <title>Glossary</title>\",\n ...markupBlock(terms.map((t) => ditaEntry(t)), \" \"),\n \"</glossgroup>\",\n ]),\n },\n directory: {\n holds: DITA_HOLDS,\n render: (term) =>\n fileOf([\n XML_DECLARATION,\n '<!DOCTYPE glossentry PUBLIC \"-//OASIS//DTD DITA 2.0 Glossary Entry//EN\" \"glossentry.dtd\">',\n ditaEntry(term, term.language),\n ]),\n },\n});\n\nexport const docbookWriter = documentWriter({\n format: \"docbook\",\n extension: \".xml\",\n file: {\n holds: DOCBOOK_HOLDS,\n needsDefinition: false,\n render: (terms) =>\n fileOf([\n XML_DECLARATION,\n `<glossary xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\"${langAttribute(sharedLanguage(terms))}>`,\n \" <title>Glossary</title>\",\n ...markupBlock(terms.map(docbookEntry), \" \"),\n \"</glossary>\",\n ]),\n },\n});\n\nexport const DOCUMENT_WRITERS: readonly TermWriter[] = [\n markdownWriter,\n mdxWriter,\n asciidocWriter,\n rstWriter,\n htmlWriter,\n ditaWriter,\n docbookWriter,\n];\n","/**\n * A term page: one term per file, its record in the file's metadata channel\n * and an empty body. The metadata reads `title` (the label), `description`\n * (the abstract, when there is one), `type: term`, `id`, `language` (when the\n * term has one), then the ten fields in the vocabulary's order.\n */\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { extractorByName } from \"../../../meta/internal.js\";\nimport { TermError } from \"../../errors.js\";\nimport { TERM_FIELDS, type Term } from \"../../types.js\";\nimport { fileOf, xmlAttribute, xmlText } from \"./markup.js\";\n\nexport function pageMetadata(term: Term): Record<string, unknown> {\n const { record } = term;\n const metadata: Record<string, unknown> = { title: record.label };\n if (record.abstract !== undefined) metadata[\"description\"] = record.abstract;\n metadata[\"type\"] = \"term\";\n metadata[\"id\"] = term.id;\n if (term.language !== undefined) metadata[\"language\"] = term.language;\n for (const field of TERM_FIELDS) {\n const value = record[field];\n if (value !== undefined) metadata[field] = value;\n }\n return metadata;\n}\n\n/**\n * A Markdown, MDX, AsciiDoc or reStructuredText term page: a fenced YAML block\n * and no body. The block is written by the format's own extractor, the one an\n * in-place write goes through, so a render and a write-back agree on how a\n * value is spelled.\n */\nexport function metadataPage(format: string, term: Term): string {\n const apply = extractorByName(format)?.apply;\n if (apply === undefined) throw new TermError(`manni cannot write ${format} metadata.`);\n return apply(\"---\\n---\\n\", pageMetadata(term));\n}\n\n/** A fenced YAML block, which Markdown, MDX, AsciiDoc and reStructuredText all read. */\nexport function yamlFrontmatter(metadata: Record<string, unknown>): string {\n return `---\\n${stringifyYaml(metadata, { lineWidth: 0 })}---\\n`;\n}\n\n/**\n * A `<meta content>` value as the HTML extractor reads it back: the value is\n * parsed as a YAML scalar, so a string that would parse as anything else, and\n * every list, is written as JSON, which is YAML and stays on one line.\n */\nfunction metaContent(value: unknown): string {\n if (typeof value === \"string\" && !value.includes(\"\\n\")) {\n try {\n if (parseYaml(value) === value) return value;\n } catch {\n // Not plain YAML: JSON below.\n }\n }\n return JSON.stringify(value);\n}\n\nexport function htmlPage(term: Term): string {\n const metadata = pageMetadata(term);\n const metas = Object.entries(metadata)\n .filter(([key]) => key !== \"title\")\n .map(([key, value]) => ` <meta name=\"${xmlAttribute(key)}\" content=\"${xmlAttribute(metaContent(value))}\">`);\n return fileOf([\n \"<!DOCTYPE html>\",\n \"<html>\",\n \" <head>\",\n ` <title>${xmlText(term.record.label)}</title>`,\n ...metas,\n \" </head>\",\n \" <body></body>\",\n \"</html>\",\n ]);\n}\n","/** What every interchange writer shares: the dropped-field report and the shape guard. */\nimport { TermError } from \"../../errors.js\";\nimport {\n TERM_FIELDS,\n type DroppedField,\n type Term,\n type TermField,\n type TermShape,\n type TermTarget,\n type TermWriteFormat,\n} from \"../../types.js\";\n\n/** The language a term without one is written as. */\nexport const DEFAULT_LANGUAGE = \"en\";\n\n/** One entry per term per field the term carries and `held` does not include, in term then field order. */\nexport function droppedFields(terms: readonly Term[], held: readonly TermField[]): DroppedField[] {\n const dropped: DroppedField[] = [];\n for (const term of terms) {\n for (const field of TERM_FIELDS) {\n if (term.record[field] !== undefined && !held.includes(field)) dropped.push({ id: term.id, field });\n }\n }\n return dropped;\n}\n\n/** Throws when a writer is asked for a shape it does not render. The command checks `shapes` first; this is the backstop. */\nexport function requireShape(format: TermWriteFormat, target: TermTarget, shape: TermShape): void {\n if (target.shape === shape) return;\n throw new TermError(\n shape === \"file\"\n ? `-f ${format} writes one file, not a directory. Pass -o <file>.`\n : `-f ${format} writes a styles directory, not a file. Pass -o <styles directory>.`,\n );\n}\n","/**\n * `term write -f csv`: one row per term, for a translation or terminology\n * system to import. The headers describe themselves, so a system maps columns\n * by name: `ID`, then six columns per language the set holds, then the four\n * language-neutral relation columns.\n */\nimport { TERM_FIELDS, type Term, type TermField, type TermShape, type TermWriter } from \"../../types.js\";\nimport { DEFAULT_LANGUAGE, droppedFields, requireShape } from \"./render-util.js\";\n\n/** The per-language columns, in order, with their header names. */\nconst LANGUAGE_COLUMNS: readonly (readonly [TermField, string])[] = [\n [\"label\", \"Term\"],\n [\"definition\", \"Definition\"],\n [\"abstract\", \"Abstract\"],\n [\"alt-labels\", \"Alt labels\"],\n [\"hidden-labels\", \"Hidden labels\"],\n [\"scope-note\", \"Scope note\"],\n];\n\n/** The columns every language shares: they name other terms, not words in a language. */\nconst NEUTRAL_COLUMNS: readonly (readonly [TermField, string])[] = [\n [\"broader\", \"Broader\"],\n [\"narrower\", \"Narrower\"],\n [\"related-terms\", \"Related terms\"],\n [\"see\", \"See\"],\n];\n\n/**\n * The one separator a list field is joined with inside its cell. A value that\n * itself contains ` | ` cannot be split back apart; that is the price of one\n * cell per field, which is what a translation system imports.\n */\nconst LIST_SEPARATOR = \" | \";\n\n/** RFC 4180 quoting: a cell holding a quote, comma or line break is quoted, with quotes doubled. */\nfunction cell(value: string): string {\n return /[\",\\r\\n]/.test(value) ? `\"${value.replaceAll('\"', '\"\"')}\"` : value;\n}\n\nfunction fieldText(term: Term, field: TermField): string {\n const value = term.record[field];\n if (value === undefined) return \"\";\n return typeof value === \"string\" ? value : value.join(LIST_SEPARATOR);\n}\n\nexport const csvWriter: TermWriter = {\n format: \"csv\",\n shapes: [\"file\"],\n holds: (_shape: TermShape) => TERM_FIELDS,\n render(terms, target) {\n requireShape(\"csv\", target, \"file\");\n // Languages in order of first appearance, so the columns follow the set.\n const languages: string[] = [];\n for (const term of terms) {\n const language = term.language ?? DEFAULT_LANGUAGE;\n if (!languages.includes(language)) languages.push(language);\n }\n\n const header = [\n \"ID\",\n ...languages.flatMap((language) => LANGUAGE_COLUMNS.map(([, name]) => `${name} [${language}]`)),\n ...NEUTRAL_COLUMNS.map(([, name]) => name),\n ];\n const rows = terms.map((term) => {\n const own = term.language ?? DEFAULT_LANGUAGE;\n return [\n term.id,\n ...languages.flatMap((language) =>\n LANGUAGE_COLUMNS.map(([field]) => (language === own ? fieldText(term, field) : \"\")),\n ),\n ...NEUTRAL_COLUMNS.map(([field]) => fieldText(term, field)),\n ];\n });\n\n const content = [header, ...rows].map((row) => `${row.map(cell).join(\",\")}\\n`).join(\"\");\n return {\n files: [{ path: target.path, content }],\n removals: [],\n dropped: droppedFields(terms, TERM_FIELDS),\n skipped: [],\n };\n },\n};\n","/**\n * `term write -f json`: the set as `{ \"terms\": [...] }`, one object per term\n * holding its id, its language when it has one, and every record field in the\n * vocabulary's order. It is the shape `term list -f json` prints, so it holds\n * every field.\n */\nimport { TERM_FIELDS, type TermShape, type TermWriter } from \"../../types.js\";\nimport { droppedFields, requireShape } from \"./render-util.js\";\n\nexport const jsonWriter: TermWriter = {\n format: \"json\",\n shapes: [\"file\"],\n holds: (_shape: TermShape) => TERM_FIELDS,\n render(terms, target) {\n requireShape(\"json\", target, \"file\");\n const entries = terms.map((term) => {\n const entry: Record<string, unknown> = { id: term.id };\n if (term.language !== undefined) entry[\"language\"] = term.language;\n for (const field of TERM_FIELDS) {\n const value = term.record[field];\n if (value !== undefined) entry[field] = value;\n }\n return entry;\n });\n const content = `${JSON.stringify({ terms: entries }, null, 2)}\\n`;\n return {\n files: [{ path: target.path, content }],\n removals: [],\n dropped: droppedFields(terms, TERM_FIELDS),\n skipped: [],\n };\n },\n};\n","/**\n * `term write -f skos`: the set as a SKOS concept scheme in JSON-LD. The\n * document is the scheme, and each term is a concept at `#<id>` within it.\n *\n * A relation (`broader`, `narrower`, `related-terms`) names another term by\n * label or id, and becomes a reference to that concept. A value naming no term\n * is left out: a dangling reference is `check`'s finding, not a field this\n * format cannot hold.\n */\nimport type { Term, TermField, TermShape, TermWriter } from \"../../types.js\";\nimport { droppedFields, requireShape } from \"./render-util.js\";\n\nconst HOLDS: readonly TermField[] = [\n \"label\",\n \"definition\",\n \"alt-labels\",\n \"hidden-labels\",\n \"broader\",\n \"narrower\",\n \"related-terms\",\n \"scope-note\",\n];\n\nconst CONTEXT = {\n skos: \"http://www.w3.org/2004/02/skos/core#\",\n dcterms: \"http://purl.org/dc/terms/\",\n};\n\n/** The scheme's `@id`: the document itself, which the concepts' `#<id>` fragments sit in. */\nconst SCHEME_ID = \"\";\n\ntype Literal = string | { \"@value\": string; \"@language\": string };\n\nfunction literal(term: Term, value: string): Literal {\n return term.language === undefined ? value : { \"@value\": value, \"@language\": term.language };\n}\n\n/** The term a relation value names: a label first, then an id, compared case-insensitively. Never `self`. */\nfunction resolve(terms: readonly Term[], self: Term, value: string): Term | undefined {\n const wanted = value.toLowerCase();\n const others = terms.filter((t) => t !== self);\n return (\n others.find((t) => t.record.label.toLowerCase() === wanted) ?? others.find((t) => t.id.toLowerCase() === wanted)\n );\n}\n\nfunction references(terms: readonly Term[], self: Term, values: readonly string[] | undefined): { \"@id\": string }[] {\n const ids: string[] = [];\n for (const value of values ?? []) {\n const target = resolve(terms, self, value);\n if (target !== undefined && !ids.includes(target.id)) ids.push(target.id);\n }\n return ids.map((id) => ({ \"@id\": `#${id}` }));\n}\n\nfunction concept(terms: readonly Term[], term: Term): Record<string, unknown> {\n const { record } = term;\n const node: Record<string, unknown> = {\n \"@id\": `#${term.id}`,\n \"@type\": \"skos:Concept\",\n \"skos:inScheme\": { \"@id\": SCHEME_ID },\n \"skos:prefLabel\": literal(term, record.label),\n };\n if (record[\"alt-labels\"] !== undefined) node[\"skos:altLabel\"] = record[\"alt-labels\"].map((v) => literal(term, v));\n if (record[\"hidden-labels\"] !== undefined) {\n node[\"skos:hiddenLabel\"] = record[\"hidden-labels\"].map((v) => literal(term, v));\n }\n if (record.definition !== undefined) node[\"skos:definition\"] = literal(term, record.definition);\n if (record[\"scope-note\"] !== undefined) node[\"skos:scopeNote\"] = literal(term, record[\"scope-note\"]);\n const relations = [\n [\"skos:broader\", record.broader],\n [\"skos:narrower\", record.narrower],\n [\"skos:related\", record[\"related-terms\"]],\n ] as const;\n for (const [key, values] of relations) {\n const refs = references(terms, term, values);\n if (refs.length > 0) node[key] = refs;\n }\n return node;\n}\n\nexport const skosWriter: TermWriter = {\n format: \"skos\",\n shapes: [\"file\"],\n holds: (_shape: TermShape) => HOLDS,\n render(terms, target) {\n requireShape(\"skos\", target, \"file\");\n const document = {\n \"@context\": CONTEXT,\n \"@graph\": [\n {\n \"@id\": SCHEME_ID,\n \"@type\": \"skos:ConceptScheme\",\n \"dcterms:description\": \"Generated by manni term write.\",\n },\n ...terms.map((term) => concept(terms, term)),\n ],\n };\n const content = `${JSON.stringify(document, null, 2)}\\n`;\n return {\n files: [{ path: target.path, content }],\n removals: [],\n dropped: droppedFields(terms, HOLDS),\n skipped: [],\n };\n },\n};\n","/**\n * `term write -f tbx`: the set as a TBX v2 (2008) termbase, the exchange format\n * translation memory and terminology systems import. One `<termEntry>` per\n * term, one `<langSet>` in the term's language, and one `<tig>` per\n * designation, with its administrative status: the label is preferred, an\n * alt-label admitted, a hidden-label deprecated.\n */\nimport type { Term, TermField, TermShape, TermWriter } from \"../../types.js\";\nimport { DEFAULT_LANGUAGE, droppedFields, requireShape } from \"./render-util.js\";\n\nconst HOLDS: readonly TermField[] = [\"label\", \"definition\", \"alt-labels\", \"hidden-labels\"];\n\nfunction text(value: string): string {\n return value.replaceAll(\"&\", \"&amp;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\");\n}\n\nfunction attribute(value: string): string {\n return text(value).replaceAll('\"', \"&quot;\");\n}\n\nfunction tig(designation: string, status: string): string[] {\n return [\n \" <tig>\",\n ` <term>${text(designation)}</term>`,\n ` <termNote type=\"administrativeStatus\">${status}</termNote>`,\n \" </tig>\",\n ];\n}\n\nfunction termEntry(term: Term): string[] {\n const { record } = term;\n return [\n ` <termEntry id=\"${attribute(term.id)}\">`,\n ...(record.definition === undefined\n ? []\n : [` <descrip type=\"definition\">${text(record.definition)}</descrip>`]),\n ` <langSet xml:lang=\"${attribute(term.language ?? DEFAULT_LANGUAGE)}\">`,\n ...tig(record.label, \"preferredTerm-admn-sts\"),\n ...(record[\"alt-labels\"] ?? []).flatMap((label) => tig(label, \"admittedTerm-admn-sts\")),\n ...(record[\"hidden-labels\"] ?? []).flatMap((label) => tig(label, \"deprecatedTerm-admn-sts\")),\n \" </langSet>\",\n \" </termEntry>\",\n ];\n}\n\nexport const tbxWriter: TermWriter = {\n format: \"tbx\",\n shapes: [\"file\"],\n holds: (_shape: TermShape) => HOLDS,\n render(terms, target) {\n requireShape(\"tbx\", target, \"file\");\n // The file's default language is the first term's; each langSet states its own anyway.\n const language = terms[0]?.language ?? DEFAULT_LANGUAGE;\n const lines = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n `<martif type=\"TBX\" xml:lang=\"${attribute(language)}\">`,\n \" <martifHeader>\",\n \" <fileDesc>\",\n \" <sourceDesc>\",\n \" <p>manni term write</p>\",\n \" </sourceDesc>\",\n \" </fileDesc>\",\n \" </martifHeader>\",\n \" <text>\",\n \" <body>\",\n ...terms.flatMap(termEntry),\n \" </body>\",\n \" </text>\",\n \"</martif>\",\n ];\n const content = lines.map((line) => `${line}\\n`).join(\"\");\n return {\n files: [{ path: target.path, content }],\n removals: [],\n dropped: droppedFields(terms, HOLDS),\n skipped: [],\n };\n },\n};\n","/**\n * `term write -f vale`: a Vale style named `Terms`, written into a styles\n * directory (proposal 0052 § 6). Every rule shape here was chosen against a\n * real Vale 3.20.0 run.\n *\n * - `Terms/Casing.yml` enforces the exact form of a designation that starts\n * with a capital or a non-letter: `Kubernetes`, `K8s`, `.Net`.\n * - `Terms/Lowercase.yml` enforces an all-lowercase designation, allowing a\n * capital first letter so a sentence can start with it.\n * - `Terms/SentenceStart.yml` enforces a designation that starts lowercase and\n * holds a capital later (`iPhone`, `meta-schema URI`), allowing a capital\n * first letter the same way.\n * - `Terms/Deprecated.yml` swaps each hidden-label for its term's label.\n * - `Terms/<ACRONYM>.yml` asks for an all-caps alt-label to be spelled out on\n * first use, as `<label> (<ACRONYM>)`.\n *\n * An all-caps designation gets no casing rule: enforcing the case of `IT` fires\n * on nearly every paragraph. manni owns `Terms/`: every file opens with the\n * marker line, a file without it is someone else's and stops the write, and a\n * marked file the set no longer produces is removed.\n */\nimport { isAbsolute, join, relative, sep } from \"node:path\";\nimport { stringify } from \"yaml\";\nimport { TermError } from \"../../errors.js\";\nimport type { RenderedFile, TermField, TermShape, TermWriter } from \"../../types.js\";\nimport { droppedFields, requireShape } from \"./render-util.js\";\n\nexport const VALE_MARKER = \"# Generated by manni term write. Edit the terms, not this file.\";\nconst STYLE = \"Terms\";\nconst HOLDS: readonly TermField[] = [\"label\", \"alt-labels\", \"hidden-labels\"];\n/** The style's own files, which an acronym file may not replace. */\nconst OWN_FILES = [\"Casing\", \"Lowercase\", \"SentenceStart\", \"Deprecated\"] as const;\n\nconst REGEX_METACHARACTERS = /[\\\\^$.|?*+()[\\]{}]/g;\n\nfunction escapeRegex(value: string): string {\n return value.replace(REGEX_METACHARACTERS, \"\\\\$&\");\n}\n\n/**\n * A swap value as Vale reads it. Vale matches the value as a pattern against\n * the text it found, so a value holding a metacharacter is escaped, and only\n * then: the `%s` in the message prints the value, so the escape shows in that\n * message (`Use 'C\\+\\+' instead of 'c++'`). An exact message is worth more for\n * the common case than for the rare one.\n */\nfunction swapValue(value: string): string {\n return value.search(REGEX_METACHARACTERS) === -1 ? value : escapeRegex(value);\n}\n\n/**\n * A YAML scalar Vale's parser reads back as the same string. YAML 1.1 rules\n * quote `yes`, `on` and friends, which a 1.1 parser would read as booleans.\n * A line break cannot sit in a one-line key, so such a string is written as a\n * JSON string, which is valid double-quoted YAML.\n */\nfunction scalar(value: string): string {\n if (/[\\r\\n]/.test(value)) return JSON.stringify(value);\n const out = stringify(value, { version: \"1.1\", lineWidth: 0 });\n return out.endsWith(\"\\n\") ? out.slice(0, -1) : out;\n}\n\n/** A YAML double-quoted scalar on one line: a raw line break would fold to a space. */\nfunction doubleQuoted(value: string): string {\n const escaped = value\n .replaceAll(\"\\\\\", \"\\\\\\\\\")\n .replaceAll('\"', '\\\\\"')\n .replaceAll(\"\\n\", \"\\\\n\")\n .replaceAll(\"\\r\", \"\\\\r\");\n return `\"${escaped}\"`;\n}\n\n/** A YAML single-quoted scalar, which keeps backslashes literal for a regex. */\nfunction singleQuoted(value: string): string {\n return `'${value.replaceAll(\"'\", \"''\").replaceAll(/[\\r\\n]+/g, \" \")}'`;\n}\n\n/** Vale formats a message with Go's `fmt`, so a literal `%` is doubled. */\nfunction messageText(value: string): string {\n return value.replaceAll(\"%\", \"%%\");\n}\n\ntype Casing = \"none\" | \"all-caps\" | \"lowercase\" | \"lowercase-initial\" | \"mixed\";\n\nfunction casingOf(value: string): Casing {\n if (!/[\\p{Lu}\\p{Ll}\\p{Lt}]/u.test(value)) return \"none\";\n const letters = value.match(/\\p{L}/gu)?.length ?? 0;\n if (letters >= 2 && !/[\\p{Ll}\\p{Lt}]/u.test(value)) return \"all-caps\";\n if (!/[\\p{Lu}\\p{Lt}]/u.test(value)) return \"lowercase\";\n // `iPhone`: a mixed designation whose first character is a lowercase letter.\n if (/^\\p{Ll}/u.test(value)) return \"lowercase-initial\";\n return \"mixed\";\n}\n\n/** `progressive lens` → `[Pp]rogressive lens`: the first letter may be a capital, to start a sentence. */\nfunction sentenceStartPattern(value: string): string {\n const [first = \"\", ...rest] = Array.from(value);\n const upper = first.toUpperCase();\n const head = upper !== first && Array.from(upper).length === 1 ? `[${upper}${first}]` : escapeRegex(first);\n return `${head}${escapeRegex(rest.join(\"\"))}`;\n}\n\n/** A swap list in insertion order. A key already present keeps its first value, as YAML allows one. */\nclass Swaps {\n private readonly entries = new Map<string, string>();\n add(key: string, value: string): void {\n if (!this.entries.has(key)) this.entries.set(key, value);\n }\n get size(): number {\n return this.entries.size;\n }\n lines(): string[] {\n return [...this.entries].map(([key, value]) => ` ${scalar(key)}: ${scalar(value)}`);\n }\n}\n\n/**\n * A swap key with its own word boundaries. Vale wraps every key in `\\b…\\b`\n * unless a rule sets `nonword`, and Go regular expressions give `\\b` ASCII\n * word semantics. So a term whose first or last character is not an ASCII word\n * character never matched: `c++` before a space, `Café` before a full stop. A\n * real Vale 3.20.0 run confirmed `c++` went unflagged. Each edge is `\\b` beside\n * an ASCII word character and `\\B` beside anything else, which is exactly\n * Vale's default for an ordinary word and the right boundary for the rest.\n */\nconst ASCII_WORD = /^[A-Za-z0-9_]$/;\n\nfunction bounded(pattern: string, text: string): string {\n const chars = Array.from(text);\n const edge = (char: string | undefined): string =>\n char !== undefined && ASCII_WORD.test(char) ? \"\\\\b\" : \"\\\\B\";\n return `${edge(chars[0])}${pattern}${edge(chars.at(-1))}`;\n}\n\nfunction substitution(message: string, level: string, options: string[], swaps: Swaps): string {\n return [\n VALE_MARKER,\n \"extends: substitution\",\n `message: ${doubleQuoted(message)}`,\n `level: ${level}`,\n \"ignorecase: true\",\n \"nonword: true\",\n ...options,\n \"swap:\",\n ...swaps.lines(),\n ]\n .map((line) => `${line}\\n`)\n .join(\"\");\n}\n\nfunction acronymRule(acronym: string, label: string): string {\n const expansion = escapeRegex(label).replaceAll(/[\\r\\n]+/g, \" \");\n return [\n VALE_MARKER,\n \"extends: conditional\",\n `message: ${doubleQuoted(messageText(`Spell out '${acronym}' on first use, as '${label} (${acronym})'.`))}`,\n \"level: warning\",\n \"ignorecase: false\",\n `first: ${singleQuoted(`\\\\b(${escapeRegex(acronym)})\\\\b`)}`,\n `second: ${singleQuoted(`(?i)${expansion} \\\\((${escapeRegex(acronym)})\\\\)`)}`,\n ]\n .map((line) => `${line}\\n`)\n .join(\"\");\n}\n\n/** An acronym as a file name: anything a path or a Vale rule name cannot carry becomes `-`. */\nfunction acronymFileName(acronym: string): string {\n return acronym.replaceAll(/[^\\p{L}\\p{N}_-]/gu, \"-\");\n}\n\nfunction firstLine(content: string): string {\n const end = content.search(/\\r?\\n/);\n return end === -1 ? content : content.slice(0, end);\n}\n\nexport const valeWriter: TermWriter = {\n format: \"vale\",\n shapes: [\"directory\"],\n holds: (_shape: TermShape) => HOLDS,\n render(terms, target, context) {\n requireShape(\"vale\", target, \"directory\");\n const termsDir = join(target.path, STYLE);\n\n // Someone else's file in Terms/ stops the write before anything is computed.\n const marked: string[] = [];\n for (const [path, content] of context.existing) {\n const rel = relative(termsDir, path);\n if (rel === \"\" || rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel)) continue;\n if (firstLine(content) !== VALE_MARKER) {\n throw new TermError(`${path} was not written by manni. Move it, or pass -o <styles directory>.`);\n }\n if (!rel.includes(sep) && !rel.includes(\"/\")) marked.push(path);\n }\n\n const casing = new Swaps();\n const lowercase = new Swaps();\n const sentenceStart = new Swaps();\n const deprecated = new Swaps();\n const acronyms: { acronym: string; name: string; content: string }[] = [];\n const labels = new Set(terms.map((t) => t.record.label));\n\n for (const term of terms) {\n const { label } = term.record;\n const labelIsAllCaps = casingOf(label) === \"all-caps\";\n for (const designation of [label, ...(term.record[\"alt-labels\"] ?? [])]) {\n const kind = casingOf(designation);\n if (kind === \"lowercase\") lowercase.add(bounded(escapeRegex(designation), designation), sentenceStartPattern(designation));\n if (kind === \"lowercase-initial\") {\n sentenceStart.add(bounded(escapeRegex(designation.toLowerCase()), designation), sentenceStartPattern(designation));\n }\n if (kind === \"mixed\") casing.add(bounded(escapeRegex(designation.toLowerCase()), designation), swapValue(designation));\n if (kind !== \"all-caps\" || designation === label || labelIsAllCaps || labels.has(designation)) continue;\n const name = acronymFileName(designation);\n const own = OWN_FILES.find((file) => file.toLowerCase() === name.toLowerCase());\n if (own !== undefined) {\n throw new TermError(`the acronym \"${designation}\" would replace Terms/${own}.yml. Rename the alt-label.`);\n }\n const taken = acronyms.find((a) => a.name.toLowerCase() === name.toLowerCase());\n // The same acronym on a second term keeps the first term's rule.\n if (taken?.acronym === designation) continue;\n if (taken !== undefined) {\n throw new TermError(\n `the acronyms \"${taken.acronym}\" and \"${designation}\" would both write Terms/${taken.name}.yml. Rename one.`,\n );\n }\n acronyms.push({ acronym: designation, name, content: acronymRule(designation, label) });\n }\n for (const hidden of term.record[\"hidden-labels\"] ?? []) {\n deprecated.add(bounded(escapeRegex(hidden), hidden), swapValue(label));\n }\n }\n\n const files: RenderedFile[] = [];\n const add = (name: string, content: string): void => {\n files.push({ path: join(termsDir, `${name}.yml`), content });\n };\n if (casing.size > 0) {\n add(\"Casing\", substitution(\"Use '%s' instead of '%s'.\", \"error\", [\"vocab: false\"], casing));\n }\n if (lowercase.size > 0) {\n add(\n \"Lowercase\",\n substitution(\"Write '%[2]s' in lowercase, except to start a sentence.\", \"error\", [\"vocab: false\"], lowercase),\n );\n }\n if (sentenceStart.size > 0) {\n // Not Casing.yml: its message prints the value, which here is a pattern.\n add(\n \"SentenceStart\",\n substitution(\n \"Write '%[2]s' as the term list spells it, with a capital only to start a sentence.\",\n \"error\",\n [\"vocab: false\"],\n sentenceStart,\n ),\n );\n }\n if (deprecated.size > 0) {\n add(\"Deprecated\", substitution(\"Use '%s' instead of '%s'.\", \"warning\", [\"matchcase: true\"], deprecated));\n }\n for (const acronym of acronyms) add(acronym.name, acronym.content);\n\n // Compared without case: on a case-insensitive disk `pal.yml` and `PAL.yml`\n // are one file, and removing the old name would delete the new one.\n const produced = new Set(files.map((f) => relative(termsDir, f.path).toLowerCase()));\n const removals = marked.filter((path) => !produced.has(relative(termsDir, path).toLowerCase())).sort();\n\n return { files, removals, dropped: droppedFields(terms, HOLDS), skipped: [] };\n },\n};\n","/**\n * Writers for the formats a termbase leaves the docs in: TBX, SKOS, CSV, JSON,\n * and a Vale style.\n */\nimport type { TermWriter } from \"../../types.js\";\nimport { csvWriter } from \"./csv.js\";\nimport { jsonWriter } from \"./json.js\";\nimport { skosWriter } from \"./skos.js\";\nimport { tbxWriter } from \"./tbx.js\";\nimport { valeWriter } from \"./vale.js\";\n\nexport const INTERCHANGE_WRITERS: readonly TermWriter[] = [tbxWriter, skosWriter, csvWriter, jsonWriter, valeWriter];\n","/** Every term writer, one per `term write -f` value. */\nimport type { TermWriteFormat, TermWriter } from \"../../types.js\";\nimport { DOCUMENT_WRITERS } from \"./documents.js\";\nimport { INTERCHANGE_WRITERS } from \"./interchange.js\";\n\nexport const TERM_WRITERS: readonly TermWriter[] = [...DOCUMENT_WRITERS, ...INTERCHANGE_WRITERS];\n\nexport function writerFor(\n format: TermWriteFormat,\n writers: readonly TermWriter[] = TERM_WRITERS,\n): TermWriter | undefined {\n return writers.find((writer) => writer.format === format);\n}\n","/**\n * `manni term formats`: what is read and written, from the registries alone. A\n * construct a reader does not exist for is not listed, and `write` appears\n * only where a reader has `apply` or a registered document writer renders the\n * construct, so the listing never promises more than the build does.\n */\nimport { TERM_READERS } from \"../core/readers/index.js\";\nimport { TERM_WRITERS } from \"../core/writers/index.js\";\nimport type { TermConstruct, TermReader, TermShape, TermWriteFormat, TermWriter } from \"../types.js\";\n\nexport const FORMATS_FORMATS = [\"pretty\", \"json\"] as const;\nexport type FormatsFormat = (typeof FORMATS_FORMATS)[number];\n\nexport interface FormatRow {\n /** The input format a reader reads (`markdown`, `xml`), or a `write -f` value. */\n format: string;\n /** The construct, for a reader's row. */\n construct?: TermConstruct;\n /** What the construct or the render is called: `definition list`, `TBX v2 Core`; empty for none. */\n label: string;\n read: boolean;\n write: boolean;\n}\n\n/**\n * The construct each document `-f` value renders, per shape, and the input\n * format that construct is read back from. A directory holds one entry per\n * file, which is a page; a file holds them all, in the format's list construct.\n */\nexport const DOCUMENT_RENDERS: Partial<\n Record<TermWriteFormat, { input: string; shapes: Partial<Record<TermShape, TermConstruct>> }>\n> = {\n markdown: { input: \"markdown\", shapes: { directory: \"page\", file: \"markdown-deflist\" } },\n mdx: { input: \"mdx\", shapes: { directory: \"page\", file: \"markdown-deflist\" } },\n asciidoc: { input: \"asciidoc\", shapes: { directory: \"page\", file: \"asciidoc-glossary\" } },\n rst: { input: \"rst\", shapes: { directory: \"page\", file: \"rst-glossary\" } },\n html: { input: \"html\", shapes: { directory: \"page\", file: \"html-dl\" } },\n dita: { input: \"xml\", shapes: { directory: \"dita-glossentry\", file: \"dita-glossgroup\" } },\n docbook: { input: \"xml\", shapes: { file: \"docbook-glossary\" } },\n};\n\n/** What `formats` calls an interchange render. */\nconst INTERCHANGE_LABELS: Partial<Record<TermWriteFormat, string>> = {\n tbx: \"TBX v2 Core\",\n skos: \"JSON-LD\",\n vale: \"style\",\n};\n\nfunction rendered(writers: readonly TermWriter[], format: string, construct: TermConstruct): boolean {\n return writers.some((writer) => {\n const render = DOCUMENT_RENDERS[writer.format];\n if (render?.input !== format) return false;\n return writer.shapes.some((shape) => render.shapes[shape] === construct);\n });\n}\n\nexport function listFormats(\n opts: { readers?: readonly TermReader[]; writers?: readonly TermWriter[] } = {},\n): FormatRow[] {\n const readers = opts.readers ?? TERM_READERS;\n const writers = opts.writers ?? TERM_WRITERS;\n\n // Input formats in order of first appearance, then each format's readers in registry order.\n const formats: string[] = [];\n for (const reader of readers) {\n for (const format of reader.formats) if (!formats.includes(format)) formats.push(format);\n }\n const rows: FormatRow[] = [];\n for (const format of formats) {\n for (const reader of readers.filter((r) => r.formats.includes(format))) {\n rows.push({\n format,\n construct: reader.construct,\n label: reader.label,\n read: true,\n write: reader.apply !== undefined || rendered(writers, format, reader.construct),\n });\n }\n }\n for (const writer of writers) {\n if (DOCUMENT_RENDERS[writer.format] !== undefined) continue;\n rows.push({ format: writer.format, label: INTERCHANGE_LABELS[writer.format] ?? \"\", read: false, write: true });\n }\n return rows;\n}\n","/**\n * `manni term get <term>`: one entry, matched by id, else by label without\n * case, else by alt-label without case. A miss is a usage error that says how\n * big the set is and, when some id or label is a few edits away, which one,\n * because a typo is the likely cause.\n */\nimport { TermError } from \"../errors.js\";\nimport type { Term } from \"../types.js\";\nimport { loadTerms, plural, type TermCommandOptions } from \"./run.js\";\n\nexport const GET_FORMATS = [\"pretty\", \"json\"] as const;\nexport type GetFormat = (typeof GET_FORMATS)[number];\n\nexport interface GetOptions extends TermCommandOptions {\n /** The `<term>` argument: an id, a label or an alt-label. */\n term: string;\n}\n\n/**\n * The entry `query` names: an exact id first, then a label compared without\n * case, then an alt-label compared without case. Each pass takes the first\n * entry in set order.\n */\nexport function findTerm(terms: readonly Term[], query: string): Term | undefined {\n const folded = query.toLowerCase();\n return (\n terms.find((t) => t.id === query) ??\n terms.find((t) => t.record.label.toLowerCase() === folded) ??\n terms.find((t) => (t.record[\"alt-labels\"] ?? []).some((alt) => alt.toLowerCase() === folded))\n );\n}\n\n/** Levenshtein distance. */\nfunction editDistance(a: string, b: string): number {\n let prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const row = [i];\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n row.push(Math.min((row[j - 1] ?? 0) + 1, (prev[j] ?? 0) + 1, (prev[j - 1] ?? 0) + cost));\n }\n prev = row;\n }\n return prev[b.length] ?? 0;\n}\n\n/**\n * The name nearest `query` by edit distance, the first on a tie, when it is\n * within `max(2, floor(query.length / 3))` edits; `undefined` otherwise. A\n * name further off than that is not a typo of `query`, and suggesting it\n * points at an unrelated entry.\n */\nexport function closestName(query: string, names: readonly string[]): string | undefined {\n const limit = Math.max(2, Math.floor(query.length / 3));\n let best: string | undefined;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const name of names) {\n const distance = editDistance(query, name);\n if (distance < bestDistance) {\n best = name;\n bestDistance = distance;\n }\n }\n return bestDistance <= limit ? best : undefined;\n}\n\nexport async function runGet(opts: GetOptions): Promise<Term> {\n const { set } = await loadTerms(opts);\n const found = findTerm(set.terms, opts.term);\n if (found !== undefined) return found;\n const nearest = closestName(\n opts.term,\n set.terms.flatMap((t) => [t.id, t.record.label]),\n );\n const hint = nearest === undefined ? \".\" : `; did you mean \"${nearest}\"?`;\n throw new TermError(`no term \"${opts.term}\". ${plural(set.terms.length, \"term\")}${hint}`);\n}\n","/**\n * `term lint`: the definitions against the house voice (proposal 0052 § 6).\n *\n * Each entry's `definition`, `abstract` and `scope-note` is written to a\n * temporary `<id>.<field>.md`, and Vale runs once over the directory holding\n * them. The file name is the voice switch: a `[*.definition.md]` section in the\n * user's own `.vale.ini` applies to definitions alone. One file per field keeps\n * a document-wide rule from reaching across unrelated entries.\n *\n * Vale is given the directory rather than the file list so a large set does not\n * run into the platform's command-line length limit; the directory holds only\n * the files written here.\n */\nimport { mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Term, TermField, TermFinding, TermSet } from \"../types.js\";\nimport { foldValeSeverity, proseRuleId } from \"./severity.js\";\nimport { runValeJson } from \"./vale.js\";\n\nexport interface LintTermSetOptions {\n /** Absolute; from `valeConfigPath(run.tools, run.configDir)`. */\n valeConfig?: string;\n /** Where Vale runs, and so where it looks for its own config. */\n cwd?: string;\n runVale?: typeof runValeJson;\n}\n\n/** The prose fields `lint` reads, in the order it writes them. */\nexport const PROSE_FIELDS = [\"definition\", \"abstract\", \"scope-note\"] as const satisfies readonly TermField[];\ntype ProseField = (typeof PROSE_FIELDS)[number];\n\ninterface Written {\n term: Term;\n field: ProseField;\n value: string;\n}\n\n/** A term id made safe as a file name component. */\nfunction fileStem(id: string): string {\n const safe = id.replace(/[^A-Za-z0-9._-]/g, \"_\");\n return safe === \"\" ? \"_\" : safe;\n}\n\n/** The last component of a path printed by Vale, whichever separator it used. */\nfunction baseName(path: string): string {\n const parts = path.split(/[\\\\/]/);\n return parts[parts.length - 1] ?? path;\n}\n\n/** The source line a line of a field's prose sits on. */\nfunction sourceLine(written: Written, proseLine: number): number {\n const { term, field, value } = written;\n const fieldLine = term.location.fieldLines[field] ?? term.location.line;\n if (!value.includes(\"\\n\")) return fieldLine;\n const { construct } = term.location;\n return construct === \"page\" || construct === \"manifest\" ? fieldLine + proseLine : fieldLine + proseLine - 1;\n}\n\nfunction compareFindings(a: TermFinding, b: TermFinding): number {\n if (a.file !== b.file) return a.file < b.file ? -1 : 1;\n const lineA = a.line ?? 0;\n const lineB = b.line ?? 0;\n if (lineA !== lineB) return lineA - lineB;\n if (a.ruleId !== b.ruleId) return a.ruleId < b.ruleId ? -1 : 1;\n if (a.message !== b.message) return a.message < b.message ? -1 : 1;\n return 0;\n}\n\nexport async function lintTermSet(set: TermSet, opts: LintTermSetOptions = {}): Promise<TermFinding[]> {\n // Keyed by lowercased file name: Vale may print the path in another case, and\n // a case-insensitive file system would fold `API` and `api` onto one file.\n const byName = new Map<string, Written>();\n const files: { name: string; content: string }[] = [];\n const stemCount = new Map<string, number>();\n\n for (const term of set.terms) {\n const fields = PROSE_FIELDS.filter((field) => term.record[field] !== undefined);\n if (fields.length === 0) continue;\n const stem = fileStem(term.id);\n const seen = (stemCount.get(stem.toLowerCase()) ?? 0) + 1;\n stemCount.set(stem.toLowerCase(), seen);\n // A repeated id is suffixed before the field, so `*.definition.md` still matches it.\n const prefix = seen === 1 ? stem : `${stem}.${String(seen)}`;\n for (const field of fields) {\n const value = term.record[field];\n if (value === undefined) continue;\n const name = `${prefix}.${field}.md`;\n byName.set(name.toLowerCase(), { term, field, value });\n files.push({ name, content: `${value}\\n` });\n }\n }\n\n if (files.length === 0) return [];\n\n const runVale = opts.runVale ?? runValeJson;\n const dir = await mkdtemp(join(tmpdir(), \"manni-term-lint-\"));\n try {\n for (const file of files) await writeFile(join(dir, file.name), file.content, \"utf8\");\n const alerts = await runVale([dir], { config: opts.valeConfig, cwd: opts.cwd });\n\n const findings: TermFinding[] = [];\n for (const [path, list] of Object.entries(alerts)) {\n const written = byName.get(baseName(path).toLowerCase());\n if (written === undefined) continue;\n for (const alert of list) {\n findings.push({\n ruleId: proseRuleId(alert.Check),\n severity: foldValeSeverity(alert.Severity),\n message: alert.Message,\n file: written.term.location.file,\n line: sourceLine(written, alert.Line),\n id: written.term.id,\n tool: \"vale\",\n check: alert.Check,\n toolSeverity: alert.Severity,\n field: written.field,\n });\n }\n }\n return findings.sort(compareFindings);\n } finally {\n await rm(dir, { recursive: true, force: true });\n }\n}\n","/**\n * The Vale process seam (proposal 0052 § 6). The only module that starts Vale.\n *\n * manni asks Vale rather than reading its files: `vale --output=JSON` for the\n * alerts, `vale ls-config` for the resolved configuration. Vale is started with\n * an argv, never a shell string, and what it prints is validated here, because\n * it crosses a process boundary.\n */\nimport { execFile } from \"node:child_process\";\nimport type { ValeSeverity } from \"../types.js\";\nimport { TermError } from \"../errors.js\";\n\n/** One alert, as `vale --output=JSON` prints it, trimmed to the fields manni reads. */\nexport interface ValeAlert {\n Check: string;\n Message: string;\n Line: number;\n Span: [number, number];\n Severity: ValeSeverity;\n}\n\n/** `vale --output=JSON`: the path Vale printed for each file, to its alerts. */\nexport type ValeAlerts = Record<string, ValeAlert[]>;\n\n/** What `vale ls-config` resolved. */\nexport interface ValeResolvedConfig {\n /** The project's styles directory: the last entry of Vale's `Paths`. */\n stylesPath: string;\n /** The config file Vale resolved. */\n rootIni: string;\n /** Each section glob to its `BasedOnStyles`. */\n baseStyles: Record<string, string[]>;\n}\n\nexport interface ValeProcessResult {\n /** Vale's exit code; `null` when a signal ended it. */\n code: number | null;\n /**\n * The signal that ended it, when one did, and `code` is then null. Optional\n * because absent means what it says: the run was not killed.\n */\n signal?: string | null;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Start `vale` with `args` and wait for it. Resolves for any exit; rejects when\n * the process could not start, with an error whose `code` is `ENOENT` when\n * there is no `vale` on PATH. Tests inject a stub.\n */\nexport type ValeSpawn = (args: string[], opts: { cwd?: string }) => Promise<ValeProcessResult>;\n\nconst MAX_BUFFER = 64 * 1024 * 1024;\n\nconst SEVERITIES: readonly ValeSeverity[] = [\"error\", \"warning\", \"suggestion\"];\n\nexport const spawnVale: ValeSpawn = (args, opts) =>\n new Promise((settle, reject) => {\n execFile(\n \"vale\",\n args,\n { cwd: opts.cwd, windowsHide: true, maxBuffer: MAX_BUFFER, encoding: \"utf8\" },\n (error, stdout, stderr) => {\n if (!error) {\n settle({ code: 0, stdout, stderr });\n return;\n }\n if (typeof error.code === \"number\") {\n settle({ code: error.code, stdout, stderr });\n return;\n }\n // Killed by a signal. Node reports the exit code as **null** here,\n // not as undefined, so testing for undefined never matched: a killed\n // run fell through to `reject` and surfaced as though Vale could not\n // start. Settling instead keeps whatever Vale managed to write, which\n // is the part a reader can act on.\n if (error.code == null && typeof error.signal === \"string\") {\n settle({ code: null, signal: error.signal, stdout, stderr });\n return;\n }\n // A start failure (ENOENT) or an output over the buffer.\n const failure: Error = error;\n reject(failure);\n },\n );\n });\n\nfunction isEnoent(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && \"code\" in err && err.code === \"ENOENT\";\n}\n\nasync function start(\n spawn: ValeSpawn,\n args: string[],\n cwd: string | undefined,\n missing: string,\n): Promise<ValeProcessResult> {\n try {\n return await spawn(args, { cwd });\n } catch (err) {\n if (isEnoent(err)) throw new TermError(missing);\n throw err;\n }\n}\n\nfunction isMapping(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Vale's own account of a failure. Under `--output=JSON` it prints its error\n * as a JSON object whose `Text` is the message; otherwise the stderr is the\n * message.\n */\nfunction failureText(result: ValeProcessResult): string {\n const stderr = result.stderr.trim();\n try {\n const parsed: unknown = JSON.parse(stderr);\n if (isMapping(parsed) && typeof parsed[\"Text\"] === \"string\") return parsed[\"Text\"].trim();\n } catch {\n // Not JSON: the stderr is the message.\n }\n if (stderr !== \"\") return stderr;\n // Vale said nothing, so the ending is the only account there is. A signal\n // leaves no message behind, and \"exit code null\" names nothing a reader can\n // act on.\n if (result.signal != null) return `killed by ${result.signal}`;\n return `exit code ${String(result.code)}`;\n}\n\nfunction parseJson(stdout: string, what: string): unknown {\n try {\n return JSON.parse(stdout) as unknown;\n } catch {\n throw new TermError(`vale printed ${what} that is not JSON: ${stdout.trim().slice(0, 200)}`);\n }\n}\n\nfunction parseAlert(raw: unknown, path: string): ValeAlert {\n const unreadable = (): TermError =>\n new TermError(`vale printed an alert for ${path} that manni cannot read: ${JSON.stringify(raw)}`);\n if (!isMapping(raw)) throw unreadable();\n const { Check, Message, Line, Span, Severity } = raw;\n if (typeof Check !== \"string\" || typeof Message !== \"string\" || typeof Line !== \"number\") throw unreadable();\n if (!Array.isArray(Span) || Span.length !== 2) throw unreadable();\n const span: unknown[] = Span;\n const [from, to] = span;\n if (typeof from !== \"number\" || typeof to !== \"number\") throw unreadable();\n const severity = SEVERITIES.find((s) => s === Severity);\n if (severity === undefined) throw unreadable();\n return { Check, Message, Line, Span: [from, to], Severity: severity };\n}\n\nfunction parseAlerts(stdout: string): ValeAlerts {\n const parsed = parseJson(stdout, \"alerts\");\n if (!isMapping(parsed)) throw new TermError(\"vale printed alerts that are not a JSON object.\");\n const alerts: ValeAlerts = {};\n for (const [path, list] of Object.entries(parsed)) {\n if (!Array.isArray(list)) throw new TermError(`vale printed alerts for ${path} that are not a list.`);\n alerts[path] = list.map((raw: unknown) => parseAlert(raw, path));\n }\n return alerts;\n}\n\n/**\n * `vale --output=JSON [--config <config>] <files...>`. Exit 0 (no error-level\n * alert) and exit 1 (at least one) both carry alerts; any other exit means\n * Vale could not run.\n */\nexport async function runValeJson(\n files: string[],\n opts: { config?: string; cwd?: string },\n spawn: ValeSpawn = spawnVale,\n): Promise<ValeAlerts> {\n const args = [\"--output=JSON\", ...(opts.config === undefined ? [] : [\"--config\", opts.config]), ...files];\n const result = await start(spawn, args, opts.cwd, \"vale is not on PATH. Install Vale to lint definitions.\");\n if (result.code !== 0 && result.code !== 1) {\n throw new TermError(`vale could not lint definitions: ${failureText(result)}`);\n }\n return parseAlerts(result.stdout);\n}\n\nconst NO_CONFIG = /no config file found|\\.vale\\.ini not found/i;\n\nfunction stringList(value: unknown): string[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const list: string[] = [];\n for (const item of value as unknown[]) {\n if (typeof item !== \"string\") return undefined;\n list.push(item);\n }\n return list;\n}\n\n/**\n * `vale [--config <config>] ls-config`, run in `cwd`. `null` when Vale finds no\n * config file, which is a state the caller reports, not a failure to run.\n */\nexport async function valeLsConfig(\n opts: { config?: string; cwd: string },\n spawn: ValeSpawn = spawnVale,\n): Promise<ValeResolvedConfig | null> {\n const args = [...(opts.config === undefined ? [] : [\"--config\", opts.config]), \"ls-config\"];\n const result = await start(\n spawn,\n args,\n opts.cwd,\n \"vale is not on PATH. Install Vale, or pass -o <styles directory>.\",\n );\n if (result.code !== 0) {\n const text = failureText(result);\n if (NO_CONFIG.test(text)) return null;\n throw new TermError(`vale could not resolve its configuration: ${text}`);\n }\n\n const parsed = parseJson(result.stdout, \"a configuration\");\n if (!isMapping(parsed)) throw new TermError(\"vale printed a configuration that is not a JSON object.\");\n\n const paths = stringList(parsed[\"Paths\"]);\n const stylesPath = paths?.[paths.length - 1];\n if (stylesPath === undefined || stylesPath === \"\") {\n throw new TermError(\n \"vale's configuration names no styles directory. Set StylesPath in it, or pass -o <styles directory>.\",\n );\n }\n\n // Under --config, Vale 3.20.0 leaves RootINI empty and names the file in ConfigFiles.\n const root = parsed[\"RootINI\"];\n const configFiles = stringList(parsed[\"ConfigFiles\"]);\n const rootIni =\n typeof root === \"string\" && root !== \"\" ? root : (configFiles?.[configFiles.length - 1] ?? opts.config ?? \"\");\n\n const baseStyles: Record<string, string[]> = {};\n const sections = parsed[\"SBaseStyles\"];\n if (sections !== null && sections !== undefined) {\n if (!isMapping(sections)) throw new TermError(\"vale printed SBaseStyles that is not a JSON object.\");\n for (const [glob, styles] of Object.entries(sections)) {\n const list = stringList(styles);\n if (list === undefined) throw new TermError(`vale printed styles for ${glob} that are not a list of names.`);\n baseStyles[glob] = list;\n }\n }\n\n return { stylesPath, rootIni, baseStyles };\n}\n","/**\n * `manni term lint`: each entry's prose through Vale (proposal 0052 § 6). The\n * process seam is `lintTermSet`'s; this core resolves Vale's config from the\n * family `tools:` and shapes the report `check` shares.\n */\nimport { lintTermSet, type LintTermSetOptions } from \"../core/lint.js\";\nimport { summarize, toResults, reportedFindings, type TermReport } from \"./findings.js\";\nimport { loadTerms, valeConfigFor, type TermCommandOptions } from \"./run.js\";\n\nexport interface LintOptions extends TermCommandOptions {\n /** The Vale seam. Tests hand in a stub. */\n runVale?: LintTermSetOptions[\"runVale\"];\n}\n\nexport async function runLint(opts: LintOptions): Promise<TermReport> {\n const { cwd, run, set } = await loadTerms(opts);\n const valeConfig = valeConfigFor(run);\n const findings = await lintTermSet(set, {\n cwd,\n ...(valeConfig === undefined ? {} : { valeConfig }),\n ...(opts.runVale === undefined ? {} : { runVale: opts.runVale }),\n });\n const { results, origin } = toResults(set, findings);\n return {\n findings: reportedFindings(results, origin),\n results,\n summary: summarize(results),\n frame: { cwd, base: run.configDir ?? cwd, runBase: run.base },\n terms: set.terms.length,\n references: set.references.length,\n found: findings.length,\n cwd,\n };\n}\n","/** `manni term list`: the resolved entries, in load order. */\nimport type { Term, TermSet } from \"../types.js\";\nimport { loadTerms, type TermCommandOptions } from \"./run.js\";\n\nexport const LIST_FORMATS = [\"pretty\", \"json\", \"csv\"] as const;\nexport type ListFormat = (typeof LIST_FORMATS)[number];\n\nexport interface ListReport {\n terms: Term[];\n set: TermSet;\n}\n\nexport async function runList(opts: TermCommandOptions): Promise<ListReport> {\n const { set } = await loadTerms(opts);\n return { terms: set.terms, set };\n}\n","/**\n * `manni term write` (proposal 0052 § 5): the set written back to its sources,\n * or rendered somewhere new.\n *\n * With no `-f`, each file's entries go back through the reader that read them,\n * construct by construct. With `-f`, the registered writer renders the whole\n * set into `-o`, whose spelling decides the shape: a trailing separator, an\n * existing directory, or the Vale style make it a directory; anything else is\n * a file. `-f vale` without `-o` asks Vale where its styles live.\n *\n * Writers are pure, so `--check` and `--dry-run` run the same render a write\n * does and differ only in what happens to the result.\n */\nimport { existsSync, statSync } from \"node:fs\";\nimport { lstat, mkdir, readdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, extname, join, resolve } from \"node:path\";\nimport { extractorForExtension } from \"../../meta/internal.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { MANIFEST_FORMAT, extractInput } from \"../core/load-set.js\";\nimport { TERM_READERS, readerForConstruct } from \"../core/readers/index.js\";\nimport { valeLsConfig, type ValeResolvedConfig } from \"../core/vale.js\";\nimport { TERM_WRITERS } from \"../core/writers/index.js\";\nimport { TermError } from \"../errors.js\";\nimport {\n TERM_WRITE_FORMATS,\n type DroppedField,\n type RenderedFile,\n type Term,\n type TermConstruct,\n type TermInput,\n type TermReader,\n type TermShape,\n type TermTarget,\n type TermWriteFormat,\n type TermWriter,\n} from \"../types.js\";\nimport { DOCUMENT_RENDERS } from \"./formats.js\";\nimport { displayPath, formatChoice, loadTerms, valeConfigFor, type TermCommandOptions } from \"./run.js\";\n\nexport interface WriteOptions extends TermCommandOptions {\n /** `-f, --format`. Absent writes in place. */\n format?: string;\n /** `-o, --out <path>`. */\n out?: string;\n /** `--check`. */\n check?: boolean;\n /** `--dry-run`. */\n dryRun?: boolean;\n /** The writers to render with. Tests hand in their own. */\n writers?: readonly TermWriter[];\n /** `vale ls-config`. Tests hand in a stub. */\n lsConfig?: (opts: { config?: string; cwd: string }) => Promise<ValeResolvedConfig | null>;\n}\n\n/** One file the write would change, as a person in `cwd` would name it. */\nexport interface WriteChange {\n path: string;\n action: \"create\" | \"change\" | \"remove\";\n}\n\n/** The `BasedOnStyles` line the notice suggests, when no section uses `Terms`. */\nexport interface ValeWiring {\n /** The config file Vale resolved, relative to cwd. */\n rootIni: string;\n /** The section glob to add the style to: the first Vale reports, or `*.md` when it reports none. */\n section: string;\n /** The section's styles with `Terms` appended. `[\"Terms\"]` when Vale reports no section. */\n styles: string[];\n /** True when Vale reports no section with `BasedOnStyles`, so the notice says to add `section`. */\n addSection: boolean;\n}\n\n/** The section glob the notice suggests when Vale's config has none. */\nconst SUGGESTED_SECTION = \"*.md\";\n\nexport interface WriteReport {\n mode: \"in-place\" | \"render\";\n format?: TermWriteFormat;\n shape?: TermShape;\n /** `-o` as typed, or the Vale style directory; relative to cwd. */\n target?: string;\n terms: number;\n /** Files that differ from disk. Under `--check` and `--dry-run` nothing was written. */\n changes: WriteChange[];\n /** The rendered files, relative to cwd, with their content. */\n files: RenderedFile[];\n dropped: DroppedField[];\n /** What a dropped field was dropped from, and a skipped term left out of: `a definition list`, `tbx`. */\n droppedFrom?: string;\n /** Ids of the terms left out because the target construct cannot read them back, in set order. */\n skipped: string[];\n check: boolean;\n dryRun: boolean;\n wiring?: ValeWiring;\n}\n\nconst STYLE = \"Terms\";\n\n/** The registered `-f` values, in the order the reference lists them. */\nexport function writeFormats(writers: readonly TermWriter[] = TERM_WRITERS): TermWriteFormat[] {\n return TERM_WRITE_FORMATS.filter((format) => writers.some((writer) => writer.format === format));\n}\n\nfunction isDirectory(path: string): boolean {\n try {\n return statSync(path).isDirectory();\n } catch {\n return false;\n }\n}\n\n/**\n * The largest file under a render target a write reads into the render context.\n * A larger one is there as an empty string: a render never produces an empty\n * file, so it still differs, and the Vale writer refuses it as not its own.\n */\nexport const MAX_EXISTING_FILE_BYTES = 1024 * 1024;\n\n/** Every regular file under `dir`. A symlink is skipped, never followed. */\nasync function filesUnder(dir: string, into: Map<string, string>): Promise<void> {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const path = join(dir, entry.name);\n // A Dirent describes the entry itself, so a symlink is neither of these.\n if (entry.isDirectory()) await filesUnder(path, into);\n else if (entry.isFile()) {\n const { size } = await lstat(path);\n into.set(path, size > MAX_EXISTING_FILE_BYTES ? \"\" : await readFile(path, \"utf8\"));\n }\n }\n}\n\nasync function existingFor(target: TermTarget): Promise<Map<string, string>> {\n const existing = new Map<string, string>();\n if (target.shape === \"directory\") {\n await filesUnder(target.path, existing);\n } else if (existsSync(target.path) && !isDirectory(target.path)) {\n existing.set(target.path, await readFile(target.path, \"utf8\"));\n }\n return existing;\n}\n\n/** A writer's refusal, with every absolute path it names spelled from cwd. */\nfunction relativized(error: TermError, paths: readonly string[], cwd: string): TermError {\n let message = error.message;\n for (const path of [...paths].sort((a, b) => b.length - a.length)) {\n if (message.includes(path)) message = message.replaceAll(path, displayPath(path, cwd));\n }\n return message === error.message ? error : new TermError(message);\n}\n\n/** The noun a dropped field was dropped from. */\nfunction droppedFrom(format: TermWriteFormat, shape: TermShape, readers: readonly TermReader[]): string {\n const construct = DOCUMENT_RENDERS[format]?.shapes[shape];\n const reader = construct === undefined ? undefined : readerForConstruct(construct, readers);\n return reader === undefined ? format : `a ${reader.label}`;\n}\n\nasync function applyChanges(\n files: readonly RenderedFile[],\n removals: readonly string[],\n existing: ReadonlyMap<string, string>,\n cwd: string,\n write: boolean,\n): Promise<WriteChange[]> {\n const changes: WriteChange[] = [];\n for (const file of files) {\n const before = existing.get(file.path) ?? (existsSync(file.path) ? await readFile(file.path, \"utf8\") : undefined);\n if (before === file.content) continue;\n changes.push({ path: displayPath(file.path, cwd), action: before === undefined ? \"create\" : \"change\" });\n if (write) {\n await mkdir(dirname(file.path), { recursive: true });\n await writeFile(file.path, file.content, \"utf8\");\n }\n }\n for (const path of removals) {\n if (!existsSync(path)) continue;\n changes.push({ path: displayPath(path, cwd), action: \"remove\" });\n if (write) await rm(path, { force: true });\n }\n return changes;\n}\n\nexport async function runWrite(opts: WriteOptions): Promise<WriteReport> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const writers = opts.writers ?? TERM_WRITERS;\n const readers = opts.readers ?? TERM_READERS;\n const check = opts.check === true;\n const dryRun = opts.dryRun === true;\n if (check && dryRun) throw new TermError(\"--check and --dry-run cannot be combined.\");\n\n if (opts.format === undefined) {\n if (opts.out !== undefined) throw new TermError(\"-o needs -f <format>.\");\n return writeInPlace({ ...opts, cwd, readers }, check, dryRun);\n }\n\n const format = formatChoice(opts.format, writeFormats(writers));\n const writer = writers.find((w) => w.format === format);\n if (writer === undefined) throw new TermError(`unknown format \"${format}\".`);\n if (opts.out === undefined && format !== \"vale\") {\n throw new TermError(`-f ${format} needs -o <path>.`);\n }\n\n const { run, set } = await loadTerms({ ...opts, cwd, readers });\n\n // Where the render goes, and in which shape.\n let targetPath: string;\n let wiring: ValeWiring | undefined;\n if (opts.out === undefined) {\n const lsConfig = opts.lsConfig ?? ((o) => valeLsConfig(o));\n const config = valeConfigFor(run);\n const resolved = await lsConfig({ cwd, ...(config === undefined ? {} : { config }) });\n if (resolved === null) {\n throw new TermError(\n \"Vale found no config file. Set tools.vale.config in manni.config.yaml, or pass -o <styles directory>.\",\n );\n }\n targetPath = resolve(cwd, resolved.stylesPath);\n if (!Object.values(resolved.baseStyles).some((styles) => styles.includes(STYLE))) {\n const first = Object.entries(resolved.baseStyles)[0];\n const [section, styles] = first ?? [SUGGESTED_SECTION, []];\n wiring = {\n rootIni: displayPath(resolve(cwd, resolved.rootIni), cwd),\n section,\n styles: [...styles, STYLE],\n addSection: first === undefined,\n };\n }\n } else {\n targetPath = resolve(cwd, opts.out);\n }\n const shape: TermShape =\n format === \"vale\" || /[\\\\/]$/.test(opts.out ?? \"\") || isDirectory(targetPath) ? \"directory\" : \"file\";\n const target: TermTarget = { path: targetPath, shape };\n const existing = await existingFor(target);\n\n let render;\n try {\n render = writer.render(set.terms, target, { existing });\n } catch (error) {\n if (error instanceof TermError) throw relativized(error, [...existing.keys(), targetPath], cwd);\n throw error;\n }\n\n const changes = await applyChanges(render.files, render.removals, existing, cwd, !check && !dryRun);\n const shown =\n format === \"vale\" ? displayPath(join(targetPath, STYLE), cwd) : (opts.out ?? displayPath(targetPath, cwd));\n return {\n mode: \"render\",\n format,\n shape,\n target: shown,\n terms: set.terms.length,\n changes,\n files: render.files.map((file) => ({ path: displayPath(file.path, cwd), content: file.content })),\n // A Vale style holds designations only, by design; its dropped definitions are not news.\n dropped: format === \"vale\" ? [] : render.dropped,\n droppedFrom: droppedFrom(format, shape, readers),\n skipped: render.skipped,\n check,\n dryRun,\n ...(wiring === undefined ? {} : { wiring }),\n };\n}\n\n/** The `TermInput` a construct's reader reads from `content`, rebuilt as the loader built it. */\nfunction inputFor(content: string, path: string, construct: TermConstruct, file: string): TermInput {\n if (construct === \"manifest\") {\n return { content, file, path, format: MANIFEST_FORMAT, metadata: {}, lineFor: () => undefined };\n }\n const extractor = extractorForExtension(extname(path));\n if (extractor === undefined) throw new TermError(`${file}: no reader for its extension.`);\n return extractInput(content, file, path, extractor.name);\n}\n\n/**\n * The caller's records carried onto `current`, the entries a construct's reader\n * read from content an earlier construct rewrote. An entry is matched by `id`;\n * where the id repeats in either list, by its position within the construct.\n * An entry the caller left out keeps the record it was read with.\n */\nfunction carryRecords(current: readonly Term[], edited: readonly Term[]): Term[] {\n const count = (terms: readonly Term[], id: string): number => terms.filter((t) => t.id === id).length;\n return current.map((entry, index) => {\n const unique = count(current, entry.id) === 1 && count(edited, entry.id) === 1;\n const match = unique ? edited.find((t) => t.id === entry.id) : edited[index];\n return match?.id === entry.id ? { ...entry, record: match.record } : entry;\n });\n}\n\n/** One file's content with each construct's entries written back through its reader, in order. */\nexport function applyInPlace(\n original: string,\n path: string,\n file: string,\n constructs: ReadonlyMap<TermConstruct, readonly Term[]>,\n readers: readonly TermReader[],\n): string {\n let content = original;\n let first = true;\n for (const [construct, terms] of constructs) {\n const reader = readerForConstruct(construct, readers);\n if (reader?.apply === undefined) continue;\n const input = inputFor(content, path, construct, file);\n // The loaded terms carry offsets into the file as it was read. Once an\n // earlier construct has rewritten it, this one's entries are read again for\n // offsets that are the content's own, and the caller's records carried over.\n content = reader.apply(input, first ? terms : carryRecords(reader.read(input).terms, terms));\n first = false;\n }\n return content;\n}\n\nasync function writeInPlace(\n opts: WriteOptions & { cwd: string; readers: readonly TermReader[] },\n check: boolean,\n dryRun: boolean,\n): Promise<WriteReport> {\n const { cwd, readers } = opts;\n const { set } = await loadTerms(opts);\n\n // Every file's terms, per construct, in load order.\n const byPath = new Map<string, { file: string; constructs: Map<TermConstruct, Term[]> }>();\n for (const term of set.terms) {\n const { path, construct } = term.location;\n if (path === undefined) {\n throw new TermError(`${term.location.file} has nowhere to write back to. Pass -f <format> -o <path>.`);\n }\n const reader = readerForConstruct(construct, readers);\n if (reader?.apply === undefined) {\n const name = reader?.label ?? construct;\n throw new TermError(\n `${displayPath(term.location.file, cwd)}: a ${name} cannot be written in place. Pass -f <format> -o <path>.`,\n );\n }\n const entry = byPath.get(path) ?? { file: term.location.file, constructs: new Map<TermConstruct, Term[]>() };\n entry.constructs.set(construct, [...(entry.constructs.get(construct) ?? []), term]);\n byPath.set(path, entry);\n }\n\n const files: RenderedFile[] = [];\n const existing = new Map<string, string>();\n for (const [path, { file, constructs }] of byPath) {\n let original: string;\n try {\n original = await readFile(path, \"utf8\");\n } catch (error) {\n throw new TermError(`${file}: could not be read: ${errorMessage(error)}`);\n }\n existing.set(path, original);\n files.push({ path, content: applyInPlace(original, path, file, constructs, readers) });\n }\n\n const changes = await applyChanges(files, [], existing, cwd, !check && !dryRun);\n return {\n mode: \"in-place\",\n terms: set.terms.length,\n changes,\n files: files.map((f) => ({ path: displayPath(f.path, cwd), content: f.content })),\n dropped: [],\n skipped: [],\n check,\n dryRun,\n };\n}\n","/**\n * `term list -f csv`: one row per term for a script, `id,label,alt-labels,abstract`.\n * A list is joined with `|`, and a cell is quoted as RFC 4180 says.\n */\nimport type { Term } from \"../types.js\";\n\nconst LIST_SEPARATOR = \"|\";\n\nfunction cell(value: string): string {\n return /[\",\\r\\n]/.test(value) ? `\"${value.replaceAll('\"', '\"\"')}\"` : value;\n}\n\nexport function renderListCsv(terms: readonly Term[]): string {\n const rows = [\n [\"id\", \"label\", \"alt-labels\", \"abstract\"],\n ...terms.map((t) => [\n t.id,\n t.record.label,\n (t.record[\"alt-labels\"] ?? []).join(LIST_SEPARATOR),\n t.record.abstract ?? \"\",\n ]),\n ];\n return rows.map((row) => row.map(cell).join(\",\")).join(\"\\n\");\n}\n","/**\n * GitHub workflow commands, one per reported finding:\n * `::error file=<file>,line=<n>,title=<ruleId>::<message>`, with `::warning`\n * and `::notice` for the lower levels. Uses meta's escapes. A clean run is the\n * empty string, which the CLI prints nothing for.\n */\nimport { escapeWorkflowCommandMessage, escapeWorkflowCommandProperty } from \"../../meta/internal.js\";\nimport type { TermReport } from \"../commands/findings.js\";\nimport { displayPath } from \"../commands/run.js\";\n\nexport function renderFindingsGithub(report: TermReport): string {\n return report.findings\n .map((finding) => {\n const params = [`file=${escapeWorkflowCommandProperty(displayPath(finding.file, report.cwd))}`];\n if (finding.line !== undefined) params.push(`line=${String(finding.line)}`);\n params.push(`title=${escapeWorkflowCommandProperty(finding.ruleId)}`);\n return `::${finding.severity} ${params.join(\",\")}::${escapeWorkflowCommandMessage(finding.message)}`;\n })\n .join(\"\\n\");\n}\n","/**\n * JSON output for every `manni term` command. A term is the object\n * `write -f json` writes: its id, its language when it has one, and every field\n * in the vocabulary's order, so what `list -f json` prints can be read back as\n * a render.\n */\nimport { displayPath } from \"../commands/run.js\";\nimport type { FormatRow } from \"../commands/formats.js\";\nimport type { TermReport } from \"../commands/findings.js\";\nimport { TERM_FIELDS, type Term } from \"../types.js\";\n\nexport function termEntry(term: Term): Record<string, unknown> {\n const entry: Record<string, unknown> = { id: term.id };\n if (term.language !== undefined) entry[\"language\"] = term.language;\n for (const field of TERM_FIELDS) {\n const value = term.record[field];\n if (value !== undefined) entry[field] = value;\n }\n return entry;\n}\n\nexport function renderListJson(terms: readonly Term[]): string {\n return JSON.stringify({ terms: terms.map(termEntry) }, null, 2);\n}\n\nexport function renderGetJson(term: Term): string {\n return JSON.stringify(termEntry(term), null, 2);\n}\n\nexport function renderFindingsJson(report: TermReport): string {\n const count = (severity: string): number => report.findings.filter((f) => f.severity === severity).length;\n return JSON.stringify(\n {\n findings: report.findings.map((finding) => ({ ...finding, file: displayPath(finding.file, report.cwd) })),\n summary: {\n terms: report.terms,\n references: report.references,\n errors: count(\"error\"),\n warnings: count(\"warning\"),\n notices: count(\"notice\"),\n ...(report.baseline === undefined ? {} : { baseline: report.baseline }),\n },\n },\n null,\n 2,\n );\n}\n\nexport function renderFormatsJson(rows: readonly FormatRow[]): string {\n return JSON.stringify({ formats: rows }, null, 2);\n}\n","/**\n * SARIF for `check` and `lint`. Meta's renderer builds the envelope, the\n * repository-relative uris and the fingerprints the baseline shares, from the\n * adapted results. What it cannot know is what a term rule is: it describes\n * every rule as a schema keyword, links meta's fix page, and prefixes each\n * message with the JSON Pointer of the field, `(root)` for a finding about a\n * whole entry. This renderer replaces those three with the term rule's own\n * description, a link to its section of the rules page, and the finding's own\n * message.\n */\nimport { renderSarif } from \"../../meta/index.js\";\nimport { RULE_ID_PREFIX, isTermRule } from \"../core/severity.js\";\nimport type { TermReport } from \"../commands/findings.js\";\nimport { TERM_FIELDS, type TermRule } from \"../types.js\";\n\nconst INFORMATION_URI = \"https://hawkeyexl.github.io/manni/term/\";\n\n/** The rules reference, whose sections are anchored by rule name. */\nconst RULES_URI = \"https://hawkeyexl.github.io/manni/term/reference/rules/\";\n\n/** What each `check` rule is, as the rules reference's table says it. */\nconst RULE_DESCRIPTIONS: Readonly<Record<TermRule, string>> = {\n \"undefined-term\": \"A page's concepts: names a label no entry claims as its preferred label.\",\n \"duplicate-id\": \"Two entries share an id.\",\n \"label-collision\": \"Two entries claim the same preferred label, ignoring case.\",\n \"alt-label-collision\": \"An entry's alt-label is another entry's preferred label, ignoring case.\",\n \"dangling-reference\": \"A value of broader, narrower, related-terms or see names no entry, by label or by id.\",\n \"broader-cycle\": \"A chain of broader returns to where it started.\",\n \"see-not-empty\": \"An entry with see also carries a definition.\",\n \"asymmetric-hierarchy\": \"A names B as broader, and B omits A from narrower, or the reverse.\",\n \"abstract-too-long\": \"An abstract is longer than term.abstractMaxLength.\",\n \"unused-term\": \"No page's concepts: names the entry's preferred label.\",\n};\n\nconst PROSE_PREFIX = `${RULE_ID_PREFIX}/prose/`;\n\n/**\n * The label meta's reporters put before a message: `(root) ` for a finding\n * about the whole entry, `/<field> ` for one about a field. Nothing else ever\n * opens a term finding's adapted message.\n */\nexport const FIELD_LABEL = new RegExp(`^(?:\\\\(root\\\\)|/(?:${TERM_FIELDS.join(\"|\")})) `);\n\ninterface SarifRule {\n id: string;\n shortDescription: { text: string };\n helpUri?: string;\n}\n\ninterface SarifLog {\n runs: {\n tool: { driver: { informationUri: string; rules: SarifRule[] } };\n results: { message: { text: string } }[];\n }[];\n}\n\n/** A rule as the term tool describes it: a check rule links its section, a Vale rule links nothing manni documents. */\nfunction describe(rule: SarifRule): SarifRule {\n if (rule.id.startsWith(PROSE_PREFIX)) {\n const check = rule.id.slice(PROSE_PREFIX.length);\n return { id: rule.id, shortDescription: { text: `Vale's ${check} rule flagged the prose of an entry's field.` } };\n }\n const name = rule.id.slice(RULE_ID_PREFIX.length + 1);\n if (!isTermRule(name)) return rule;\n return { id: rule.id, shortDescription: { text: RULE_DESCRIPTIONS[name] }, helpUri: `${RULES_URI}#${name}` };\n}\n\nexport function renderFindingsSarif(report: TermReport, opts: { onNotice?: (message: string) => void } = {}): string {\n const log = JSON.parse(\n renderSarif(report.results, {\n frame: report.frame,\n ...(opts.onNotice === undefined ? {} : { onNotice: opts.onNotice }),\n }),\n ) as SarifLog;\n for (const run of log.runs) {\n run.tool.driver.informationUri = INFORMATION_URI;\n run.tool.driver.rules = run.tool.driver.rules.map(describe);\n for (const result of run.results) result.message.text = result.message.text.replace(FIELD_LABEL, \"\");\n }\n return JSON.stringify(log, null, 2);\n}\n","/**\n * JUnit for `check` and `lint`: meta's renderer over the adapted results,\n * under the `manni.term` classname, with each failure's message the finding's\n * own. Meta's renderer opens every message with the field's JSON Pointer,\n * `(root)` for a finding about a whole entry, which says nothing about a term.\n * The failure's `type` is already the rule id.\n */\nimport { renderJunit } from \"../../meta/index.js\";\nimport { JUNIT_CLASSNAME, type TermReport } from \"../commands/findings.js\";\nimport { FIELD_LABEL } from \"./sarif.js\";\n\n/** A `message=\"` attribute's opening label. The value is escaped, so `message=\"` opens nothing else. */\nconst MESSAGE_LABEL = new RegExp(`message=\"${FIELD_LABEL.source.slice(1)}`, \"g\");\n\nexport function renderFindingsJunit(report: TermReport): string {\n return renderJunit(report.results, { frame: report.frame, classname: JUNIT_CLASSNAME }).replace(\n MESSAGE_LABEL,\n 'message=\"',\n );\n}\n","/**\n * Human output for every `manni term` command, in the shapes the ladder of\n * proposal 0052 prints. Columns are padded to their widest value; prose wraps\n * to 80 columns under its own column, so a long definition or message never\n * runs back to the left edge.\n */\nimport { palette, type Colors } from \"../../shared/color.js\";\nimport type { TermReport } from \"../commands/findings.js\";\nimport type { FormatRow } from \"../commands/formats.js\";\nimport { displayPath, plural } from \"../commands/run.js\";\nimport type { ValeWiring, WriteReport } from \"../commands/write.js\";\nimport type { Severity } from \"../../shared/severity.js\";\nimport { TERM_FIELDS, type Term, type TermField, type TermFinding } from \"../types.js\";\n\nconst WIDTH = 80;\n\n/** Words packed into lines of at most `width` characters; a longer word stands alone. */\nfunction wrapWords(text: string, width: number): string[] {\n const lines: string[] = [];\n let line = \"\";\n for (const word of text.split(/\\s+/).filter((w) => w !== \"\")) {\n if (line === \"\") line = word;\n else if (line.length + 1 + word.length <= width) line = `${line} ${word}`;\n else {\n lines.push(line);\n line = word;\n }\n }\n if (line !== \"\") lines.push(line);\n return lines.length === 0 ? [\"\"] : lines;\n}\n\n/** Sentences packed into lines of at most `width`; a message that fits stays whole. */\nfunction wrapSentences(text: string, width: number): string[] {\n if (text.length <= width) return [text];\n const lines: string[] = [];\n let line = \"\";\n for (const sentence of text.split(/(?<=\\.)\\s+(?=\\S)/)) {\n if (line === \"\") line = sentence;\n else if (line.length + 1 + sentence.length <= width) line = `${line} ${sentence}`;\n else {\n lines.push(line);\n line = sentence;\n }\n }\n if (line !== \"\") lines.push(line);\n return lines;\n}\n\nfunction hanging(first: string, lines: readonly string[]): string[] {\n const indent = \" \".repeat(first.length);\n return lines.map((line, i) => `${i === 0 ? first : indent}${line}`.trimEnd());\n}\n\n// ---------------------------------------------------------------------------\n// list\n\nexport function renderListPretty(terms: readonly Term[]): string {\n const idWidth = Math.max(0, ...terms.map((t) => t.id.length)) + 3;\n const labelWidth = Math.max(0, ...terms.map((t) => t.record.label.length)) + 3;\n const rows = terms.map((t) =>\n `${t.id.padEnd(idWidth)}${t.record.label.padEnd(labelWidth)}${(t.record[\"alt-labels\"] ?? []).join(\", \")}`.trimEnd(),\n );\n return [...rows, plural(terms.length, \"term\")].join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// get\n\n/** The order `get` shows fields in: names first, then what they mean, the definition last. */\nconst GET_FIELDS: readonly TermField[] = [\n \"alt-labels\",\n \"hidden-labels\",\n \"broader\",\n \"narrower\",\n \"related-terms\",\n \"see\",\n \"abstract\",\n \"scope-note\",\n \"definition\",\n];\n\nconst KEY_WIDTH = Math.max(\"language\".length, ...TERM_FIELDS.map((f) => f.length)) + 2;\n\nexport function renderGetPretty(term: Term, opts: { color: boolean; cwd?: string }): string {\n const c = palette(opts.color);\n const where = `${displayPath(term.location.file, opts.cwd ?? process.cwd())}:${String(term.location.line)}`;\n const lines = [`${c.bold(term.record.label.padEnd(40))}${c.dim(where)}`];\n const row = (key: string, value: string): void => {\n const prefix = ` ${key.padEnd(KEY_WIDTH)}`;\n lines.push(...hanging(prefix, wrapWords(value, WIDTH - prefix.length)));\n };\n row(\"id\", term.id);\n if (term.language !== undefined) row(\"language\", term.language);\n for (const field of GET_FIELDS) {\n const value = term.record[field];\n if (value === undefined) continue;\n row(field, typeof value === \"string\" ? value : value.join(\", \"));\n }\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// check and lint\n\nconst RULE_WIDTH = 32;\n\nfunction severityText(c: Colors, severity: Severity): string {\n const padded = severity.padEnd(6);\n if (severity === \"error\") return c.red(padded);\n if (severity === \"warning\") return c.yellow(padded);\n return c.cyan(padded);\n}\n\nfunction counts(findings: readonly TermFinding[]): string {\n const parts: string[] = [];\n const n = (severity: Severity): number => findings.filter((f) => f.severity === severity).length;\n if (n(\"error\") > 0) parts.push(plural(n(\"error\"), \"error\"));\n if (n(\"warning\") > 0) parts.push(plural(n(\"warning\"), \"warning\"));\n if (n(\"notice\") > 0) parts.push(plural(n(\"notice\"), \"notice\"));\n return parts.join(\", \");\n}\n\nexport interface FindingsPrettyOptions {\n color: boolean;\n /** Whether the clean line counts references: `check` reads them, `lint` does not. */\n references?: boolean;\n}\n\nexport function renderFindingsPretty(report: TermReport, opts: FindingsPrettyOptions): string {\n const c = palette(opts.color);\n const { baseline } = report;\n if (baseline?.written === true) {\n return `${c.green(\"✓\")} ${plural(report.found, \"finding\")} recorded in ${baseline.path}`;\n }\n const baselined = baseline !== undefined && baseline.suppressed > 0 ? `, ${String(baseline.suppressed)} baselined` : \"\";\n const terms = plural(report.terms, \"term\");\n\n if (report.findings.length === 0) {\n const references = opts.references === false ? \"\" : `, ${plural(report.references, \"reference\")}`;\n return `${c.green(\"✓\")} ${terms}${references}, no findings${baselined}`;\n }\n\n const ruleWidth = Math.max(RULE_WIDTH, ...report.findings.map((f) => f.ruleId.length + 2));\n const lines: string[] = [];\n let group: string | undefined;\n for (const finding of report.findings) {\n const file = displayPath(finding.file, report.cwd);\n const header = finding.line === undefined ? file : `${file}:${String(finding.line)}`;\n if (header !== group) {\n lines.push(c.bold(header));\n group = header;\n }\n const prefixWidth = 2 + 6 + 1 + ruleWidth;\n const message = wrapSentences(finding.message, WIDTH - prefixWidth);\n const indent = \" \".repeat(prefixWidth);\n message.forEach((text, i) => {\n lines.push(\n i === 0 ? ` ${severityText(c, finding.severity)} ${finding.ruleId.padEnd(ruleWidth)}${text}` : `${indent}${text}`,\n );\n });\n }\n lines.push(\"\", `${counts(report.findings)} in ${terms}${baselined}`);\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// write\n\nfunction changeLine(change: WriteReport[\"changes\"][number]): string {\n switch (change.action) {\n case \"create\":\n return `${change.path} would be created`;\n case \"change\":\n return `${change.path} would change`;\n case \"remove\":\n return `${change.path} would be removed`;\n }\n}\n\n/** A generated Vale rule file's `swap:` entries. */\nfunction swapCount(content: string): number {\n const lines = content.split(/\\r?\\n/);\n const start = lines.indexOf(\"swap:\");\n if (start === -1) return 0;\n return lines.slice(start + 1).filter((line) => line.startsWith(\" \")).length;\n}\n\nfunction baseName(path: string): string {\n return path.split(/[\\\\/]/).pop() ?? path;\n}\n\nconst CASING_RULES = new Set([\"Casing.yml\", \"Lowercase.yml\", \"SentenceStart.yml\"]);\n\n/** What each file of a Vale style holds: rule files by name, the acronym files together. */\nfunction valeLines(report: WriteReport): string[] {\n const rows: [string, string][] = [];\n const acronyms: string[] = [];\n for (const file of report.files) {\n const name = baseName(file.path);\n // A casing rule swaps each label and alt-label, so what it counts is labels.\n if (CASING_RULES.has(name)) rows.push([name, plural(swapCount(file.content), \"label\")]);\n else if (name === \"Deprecated.yml\") rows.push([name, plural(swapCount(file.content), \"swap\")]);\n else acronyms.push(name);\n }\n if (acronyms.length > 0) rows.push([acronyms.join(\", \"), plural(acronyms.length, \"acronym\")]);\n const width = Math.max(0, ...rows.map(([name]) => name.length)) + 2;\n return rows.map(([name, what]) => ` ${name.padEnd(width)}${what}`);\n}\n\n/** ` dropped from a definition list: scope-note on 3 terms, hidden-labels on 12`. */\nfunction droppedLine(report: WriteReport): string | undefined {\n if (report.dropped.length === 0) return undefined;\n const ids = new Map<TermField, Set<string>>();\n for (const { id, field } of report.dropped) {\n const set = ids.get(field) ?? new Set<string>();\n set.add(id);\n ids.set(field, set);\n }\n const fields = [...ids.entries()]\n .map(([field, set]) => ({ field, n: set.size }))\n .sort((a, b) => a.n - b.n || TERM_FIELDS.indexOf(a.field) - TERM_FIELDS.indexOf(b.field));\n const parts = fields.map(({ field, n }, i) => `${field} on ${i === 0 ? plural(n, \"term\") : String(n)}`);\n return ` dropped from ${report.droppedFrom ?? report.format ?? \"the render\"}: ${parts.join(\", \")}`;\n}\n\n/** ` skipped 2 terms a definition list cannot read without a definition: varifocal, bifocal`. */\nfunction skippedLine(report: WriteReport): string | undefined {\n if (report.skipped.length === 0) return undefined;\n const construct = report.droppedFrom ?? report.format ?? \"the render\";\n const count = plural(report.skipped.length, \"term\");\n return ` skipped ${count} ${construct} cannot read without a definition: ${report.skipped.join(\", \")}`;\n}\n\n/** The dropped and skipped lines, which a write and a dry run print alike. */\nfunction renderNotes(report: WriteReport): string[] {\n return [droppedLine(report), skippedLine(report)].filter((line) => line !== undefined);\n}\n\nfunction unchangedLine(report: WriteReport): string {\n return report.mode === \"in-place\" ? \"Nothing to write\" : `${report.target ?? \"\"} is up to date`;\n}\n\nexport function renderWritePretty(report: WriteReport): string {\n if (report.check) {\n return report.changes.length > 0 ? report.changes.map(changeLine).join(\"\\n\") : unchangedLine(report);\n }\n if (report.dryRun) {\n const changes = report.changes.length > 0 ? report.changes.map(changeLine) : [unchangedLine(report)];\n return [...changes, ...renderNotes(report)].join(\"\\n\");\n }\n if (report.mode === \"in-place\") {\n return report.changes.length === 0 ? \"Nothing to write\" : `Wrote ${plural(report.changes.length, \"file\")}`;\n }\n const each = report.shape === \"directory\" && report.format !== \"vale\" ? \", one file each\" : \"\";\n const written = report.terms - report.skipped.length;\n const lines = [`Wrote ${plural(written, \"term\")} to ${report.target ?? \"\"}${each}`];\n if (report.format === \"vale\") lines.push(...valeLines(report));\n lines.push(...renderNotes(report));\n return lines.join(\"\\n\");\n}\n\n/** The notice `write -f vale` prints when no section of Vale's config uses the style, or there is no section. */\nexport function renderValeWiring(wiring: ValeWiring): string {\n return [\n wiring.addSection\n ? `notice: ${wiring.rootIni} has no section with BasedOnStyles. Add one that uses the Terms style:`\n : `notice: no section of ${wiring.rootIni} uses the Terms style. Add it to BasedOnStyles:`,\n ` [${wiring.section}]`,\n ` BasedOnStyles = ${wiring.styles.join(\", \")}`,\n ].join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// formats\n\nexport function renderFormatsPretty(rows: readonly FormatRow[]): string {\n const formatWidth = Math.max(0, ...rows.map((r) => r.format.length)) + 3;\n const labelWidth = Math.max(0, ...rows.map((r) => r.label.length)) + 3;\n return rows\n .map((r) =>\n `${r.format.padEnd(formatWidth)}${r.label.padEnd(labelWidth)}${r.read ? \"read \" : \" \"}${r.write ? \"write\" : \"\"}`.trimEnd(),\n )\n .join(\"\\n\");\n}\n","/**\n * The termbase as `meta fill` reads it: each term's label and id, from the\n * same config and the same files `manni term check` reads. Registered as the\n * family's term label source by this domain's CLI module (see\n * `src/shared/term-labels.ts`).\n */\nimport type { TermLabel, TermLabelRequest } from \"../../shared/term-labels.js\";\nimport { resolveTermRun } from \"../core/config.js\";\nimport { loadSet } from \"./run.js\";\n\nexport async function termLabels(request: TermLabelRequest): Promise<TermLabel[]> {\n const run = await resolveTermRun({\n cwd: request.cwd,\n inputs: [],\n ...(request.configPath === undefined ? {} : { configPath: request.configPath }),\n ...(request.noConfig === true ? { noConfig: true } : {}),\n });\n // No collection and no manifest names a file, so there is no termbase.\n if (run.inputs.length === 0 && run.manifests.length === 0) return [];\n const set = await loadSet(run, { inputs: [], allowEmpty: true });\n return set.terms.map((term) => ({ label: term.record.label, id: term.id }));\n}\n","/**\n * The tracevals program. Named `tracevals` because that is where it is\n * mounted (`manni tracevals …`); `src/cli.ts` adds it to the umbrella and\n * runs it. Thin commander wrapper; all behavior lives in commands.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { collect, configOption } from \"../shared/cli-options.js\";\nimport { LOCAL_FLAG_HELP } from \"../shared/providers.js\";\nimport { fail } from \"../shared/run.js\";\nimport { terminalConfirm } from \"../shared/prompt.js\";\nimport { colorFor } from \"../shared/color.js\";\nimport { notice } from \"../shared/warn.js\";\nimport { renderList, runList } from \"./commands/list.js\";\nimport { runFill } from \"./commands/fill.js\";\nimport { runRun } from \"./commands/run.js\";\nimport { TracevalsError } from \"./types.js\";\nimport { allowExecutionMessage, isExecutionGrant } from \"../shared/execution.js\";\nimport {\n CALIBRATE_FORMATS,\n REPORT_FORMATS,\n SUMMARY_FORMATS,\n parseFormat,\n type ReportFormat,\n type SummaryFormat,\n} from \"./reporters/index.js\";\n\nconst { version } = pkg;\n\nexport function buildProgram(): Command {\nconst program = new Command();\n\nprogram\n .name(\"tracevals\")\n .description(\n \"Deterministic and LLM-as-judge adherence evals for AI agent session traces.\",\n )\n .version(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\ninterface ConfigFlags {\n /** `-c <path>` gives a string, `--no-config` gives false, neither gives undefined. */\n config?: string | boolean;\n}\n\ninterface RunFlags extends ConfigFlags {\n project?: string;\n provider?: string;\n model?: string;\n local?: boolean;\n offline?: boolean;\n runs?: number;\n deterministicOnly?: boolean;\n cache?: boolean;\n maxTurns?: number;\n format?: ReportFormat;\n output?: string;\n history?: boolean;\n failOnReview?: boolean;\n allowExecution?: string[];\n execution?: boolean;\n require?: string[];\n reportUnusedArtifacts?: boolean;\n manifest?: string;\n allProjects?: boolean;\n newerThan?: string;\n limit?: number;\n}\n\n/**\n * Repeatable execution grant, validated on the way in. An unknown value is a\n * usage error rather than a grant that quietly matches nothing.\n */\nfunction collectGrant(value: string, previous: string[]): string[] {\n if (!isExecutionGrant(value)) fail(new TracevalsError(allowExecutionMessage(value)));\n return [...previous, value];\n}\n\n/**\n * `-c, --config <path>` and `--no-config`, on every verb that reads config.\n *\n * Declared once so the four cannot drift apart on a name or a description,\n * the way docevals' `documentInputs()` does it. `list` is the one verb without\n * them: it enumerates the session store and reads no config at all, and an\n * accepted flag that quietly does nothing is worse than an absent one.\n */\nfunction addConfigFlags(cmd: Command): Command {\n return cmd\n .option(\"-c, --config <path>\", \"Path to manni.config.yaml\")\n .option(\"--no-config\", \"Ignore any discovered config file\");\n}\n\n/** The config flags as the command cores take them. */\nfunction configOptions(opts: ConfigFlags): {\n config?: string;\n noConfig?: boolean;\n} {\n const { configPath, noConfig } = configOption(opts.config);\n return {\n ...(configPath === undefined ? {} : { config: configPath }),\n ...(noConfig === true ? { noConfig } : {}),\n };\n}\n\n/**\n * Commander argument parser for `-f/--format`. Routes through `fail()` for the\n * reason the numeric checks below do: commander only special-cases\n * InvalidArgumentError, so any other exception escapes `program.parse()`\n * uncaught — a stack trace and exit 1, when a bad flag owes exit 2.\n */\nfunction 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\nconst range = (min: number, max: number): string =>\n Number.isFinite(max) ? `between ${min} and ${max}` : `of at least ${min}`;\n\n/**\n * A numeric flag, checked before anything reads it.\n *\n * `parseFloat(\"abc\")` is NaN, and every comparison against NaN is false — so a\n * flag that failed to parse does **not** fall back to the config. `undefined`\n * is what defers to the config, and NaN is not undefined: it survives the `??`\n * overlay and lands in the runtime as a limit that can never be reached. A\n * budget of NaN bills without a ceiling while the report still claims one,\n * which is the most expensive way for a safety limit to fail. Range checks\n * therefore test for a *finite* number, not only for the range.\n */\nfunction numeric(\n name: string,\n value: number | undefined,\n min: number,\n max: number = Number.POSITIVE_INFINITY,\n): void {\n if (value === undefined) return;\n if (Number.isFinite(value) && value >= min && value <= max) return;\n throw new TracevalsError(\n `${name} must be a number ${range(min, max)}, got ${value}`,\n );\n}\n\n/**\n * The same for a count. Kept apart from `numeric` because a fraction is never\n * meant here: `--limit 2.5` and `--limit -1` both reach `slice(0, n)`, where\n * the negative one silently evaluates every trace except the oldest.\n */\nfunction whole(\n name: string,\n value: number | undefined,\n min: number,\n max: number = Number.POSITIVE_INFINITY,\n): void {\n if (value === undefined) return;\n if (Number.isInteger(value) && value >= min && value <= max) return;\n throw new TracevalsError(\n `${name} must be a whole number ${range(min, max)}, got ${value}`,\n );\n}\n\n/**\n * The single mapping from `addRunFlags`' options onto the shared run options.\n *\n * `run` and `calibrate` accept the same flags, and `calibrate` used to\n * hand-copy the list, which is how it came to accept a flag and drop it on\n * the floor. `addRunFlags`' own docstring says an accepted flag that\n * quietly does nothing is worse than an absent one, so there is now one place\n * to add a flag rather than two places to remember.\n *\n * Validation lives here for the same reason: both commands get it, or neither.\n */\nfunction sharedRunOptions(opts: RunFlags) {\n whole(\"--runs\", opts.runs, 1);\n whole(\"--limit\", opts.limit, 1);\n whole(\"--max-turns\", opts.maxTurns, 1);\n\n return {\n ...configOptions(opts),\n project: opts.project,\n provider: opts.provider,\n model: opts.model,\n local: opts.local,\n // `undefined` rather than `false` when absent, so a future config\n // `offline:` still decides on a run where the flag was never typed.\n offline: opts.offline ? true : undefined,\n runs: opts.runs,\n deterministicOnly: opts.deterministicOnly,\n noCache: opts.cache === false,\n maxTurns: opts.maxTurns,\n format: opts.format ?? \"pretty\",\n output: opts.output,\n // Undefined when neither spelling is passed, so the config still decides.\n // Both spellings are declared for precisely that reason: commander\n // defaults a lone `--no-x` to `true`, which makes the config's own value\n // unreachable from the command line.\n failOnReview: opts.failOnReview,\n // Commander's default is `[]`, which is \"no flag\", not \"run nothing\": only\n // a list someone typed narrows the run, and `--no-execution` runs none.\n ...(opts.execution === false\n ? { allowExecution: [] }\n : (opts.allowExecution ?? []).length > 0\n ? { allowExecution: opts.allowExecution }\n : {}),\n reportUnusedArtifacts: opts.reportUnusedArtifacts,\n ...(opts.require !== undefined ? { require: opts.require } : {}),\n ...(opts.allProjects !== undefined ? { allProjects: opts.allProjects } : {}),\n ...(opts.newerThan !== undefined ? { newerThan: opts.newerThan } : {}),\n ...(opts.limit !== undefined ? { limit: opts.limit } : {}),\n };\n}\n\nasync function executeRun(traces: string[], opts: RunFlags, color: boolean) {\n const shared = {\n ...sharedRunOptions(opts),\n color,\n // Run-only, both of them: `--history` is a point in one session's\n // timeline, and a manifest belongs to exactly one session (ADR 01024).\n history: opts.history,\n ...(opts.manifest !== undefined ? { manifest: opts.manifest } : {}),\n };\n\n // What decides the report shape is *how traces were selected*, not how many\n // came back. One named trace is a `RunReport`, byte for byte as before; a\n // discovery selector is a `BatchReport` even when it matches exactly one, so\n // a script piping `--format json` gets a stable shape (ADR 01018).\n const selecting =\n opts.allProjects === true ||\n opts.newerThan !== undefined ||\n opts.limit !== undefined;\n\n if (traces.length > 1 || selecting) {\n if (opts.manifest !== undefined) {\n // Each trace finds its own manifest by convention; one named file cannot\n // be evidence about more than the session it was captured for.\n throw new TracevalsError(\n \"--manifest names one session's manifest, so it cannot be used with a corpus; drop it and each trace will find its own\",\n );\n }\n const { runBatch } = await import(\"./commands/batch.js\");\n const { report, rendered } = await runBatch({\n ...shared,\n ...(traces.length > 0 ? { traces } : {}),\n });\n console.log(rendered);\n process.exitCode = report.exitCode;\n return;\n }\n\n let trace = traces[0];\n if (trace === undefined) {\n // The interactive picker needs a TTY; scripted callers must name a trace.\n if (!process.stdout.isTTY || !process.stdin.isTTY) {\n throw new TracevalsError(\n \"no trace given; pass a trace file or run `manni tracevals list`\",\n );\n }\n const { pickTrace } = await import(\"./trace/picker.js\");\n trace = await pickTrace();\n }\n const { report, rendered } = await runRun({ ...shared, tracePath: trace });\n console.log(rendered);\n process.exitCode = report.exitCode;\n}\n\n/**\n * Flags shared by `run` and `calibrate`. `--history` is run-only: calibration\n * is a measurement of a corpus, not a point in one session's timeline, and an\n * accepted flag that quietly does nothing is worse than an absent one.\n */\nfunction addRunFlags(\n cmd: Command,\n options: { history?: boolean; formats?: readonly ReportFormat[] } = {},\n): Command {\n const withHistory = options.history !== false;\n const formats = options.formats ?? REPORT_FORMATS;\n const base = addConfigFlags(cmd)\n .option(\n \"--project <dir>\",\n \"artifact-lookup root (overrides the trace's recorded cwd)\",\n )\n .option(\n \"--provider <name>\",\n \"Judge provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\",\n )\n .option(\n \"--model <model>\",\n \"Model override; needs a named provider, from here or config\",\n )\n .option(\"--local\", LOCAL_FLAG_HELP)\n // `Number`, not `parseInt`: parseInt truncates, so `--runs 1.5` would be\n // silently accepted as 1 and `--runs 1e3` as 1. `whole()` below refuses\n // what Number keeps.\n .option(\"--runs <n>\", \"ensemble runs per eval\", (v) => Number(v))\n .option(\"--deterministic-only\", \"skip LLM-judged evals\")\n .option(\n \"--offline\",\n \"never fetch a remote manifest; read external metadata from local manifests\",\n )\n .option(\"--no-cache\", \"bypass the judge cache\")\n .option(\n \"--max-turns <n>\",\n \"Stop after this many ensemble runs (a cached ensemble costs none)\",\n (v) => Number(v),\n )\n .option(\n \"-f, --format <format>\",\n `Output format: ${formats.join(\" | \")}`,\n parseFormatArg(\"--format\", formats),\n \"pretty\" as ReportFormat,\n )\n .option(\"-o, --output <file>\", \"also write the report to a file\")\n .option(\n \"--report-unused-artifacts\",\n \"list every skill and agent the session was offered and never used\",\n )\n .option(\"--fail-on-review\", \"Exit 1 when any eval lands in the human-review zone (the default)\")\n .option(\"--no-fail-on-review\", \"Do not fail the run on evals left for human review\")\n // `<kind>`, not `<kind...>`: a variadic option greedily eats the\n // positional `[traces...]` that follow it. Repeat the flag instead.\n .option(\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(\n \"--require <module>\",\n \"load a grader plugin; repeatable, and added to config plugins\",\n collect,\n [],\n )\n .option(\"--all-projects\", \"evaluate every project's traces in the session store\")\n .option(\n \"--newer-than <duration>\",\n \"only traces modified within this window, such as 30m, 24h, 7d or 2w\",\n )\n .option(\"--limit <n>\", \"maximum traces to evaluate\", (v) => Number(v));\n return withHistory\n ? base.option(\n \"--history\",\n \"append to history and compare with the previous run\",\n )\n : base;\n}\n\naddRunFlags(\n // No `isDefault` (proposal 0034): `run` is a verb, so a bare\n // `manni tracevals` prints the help and exits 2, and a trace path with no\n // verb is commander's unknown-command refusal rather than a silent run.\n program\n .command(\"run [traces...]\")\n .description(\n \"Evaluate one or more traces against the skills and instructions they used\",\n ),\n)\n // Run-only, and single-trace-only: a manifest belongs to exactly one session\n // (ADR 01024). A corpus still picks one up per trace by convention — this\n // flag is for naming one outright, which only a single trace can mean.\n .option(\n \"--manifest <file>\",\n \"session manifest to compare artifacts against; without it one is looked for beside the trace and under the project\",\n )\n .action(async (traces: string[], opts: RunFlags, command: Command) => {\n try {\n await executeRun(traces, opts, colorFor(command, process.stdout.isTTY));\n } catch (e) {\n fail(e);\n }\n });\n\n// `calibrate` shares `run`'s flags because it *is* a run — plus the labels it\n// is measured against. Kept a separate command rather than a flag on `run`:\n// the report answers a different question and carries a different shape, and\n// a script must be able to tell which it is asking for (ADR 01022).\naddRunFlags(\n program\n .command(\"calibrate [traces...]\")\n .description(\n \"Measure judged and graded verdicts against a labels file: false passes, false fails, and review volume\",\n )\n .option(\n \"--labels <file>\",\n \"calibration labels sidecar (default: calibrate.labels)\",\n )\n .option(\n \"--sweep\",\n \"re-score the corpus across the configured grid of zones and ensemble sizes, from cached verdicts\",\n )\n .option(\"--max-false-pass <n>\", \"exit 1 above this many false passes\", (v) =>\n Number(v),\n )\n .option(\"--max-false-fail <n>\", \"exit 1 above this many false fails\", (v) =>\n Number(v),\n )\n .option(\n \"--max-review <n>\",\n \"exit 1 above this many needs-review outcomes\",\n (v) => Number(v),\n ),\n { history: false, formats: CALIBRATE_FORMATS },\n).action(\n async (\n traces: string[],\n opts: RunFlags & {\n labels?: string;\n sweep?: boolean;\n maxFalsePass?: number;\n maxFalseFail?: number;\n maxReview?: number;\n },\n command: Command,\n ) => {\n try {\n const shared = {\n ...sharedRunOptions(opts),\n color: colorFor(command, process.stdout.isTTY),\n };\n // A threshold that never trips looks exactly like a threshold that held.\n whole(\"--max-false-pass\", opts.maxFalsePass, 0);\n whole(\"--max-false-fail\", opts.maxFalseFail, 0);\n whole(\"--max-review\", opts.maxReview, 0);\n\n const { runCalibrate } = await import(\"./commands/calibrate.js\");\n const { report, rendered } = await runCalibrate({\n ...shared,\n ...(traces.length > 0 ? { traces } : {}),\n ...(opts.labels !== undefined ? { labels: opts.labels } : {}),\n ...(opts.sweep !== undefined ? { sweep: opts.sweep } : {}),\n ...(opts.maxFalsePass !== undefined\n ? { maxFalsePass: opts.maxFalsePass }\n : {}),\n ...(opts.maxFalseFail !== undefined\n ? { maxFalseFail: opts.maxFalseFail }\n : {}),\n ...(opts.maxReview !== undefined ? { maxReview: opts.maxReview } : {}),\n });\n console.log(rendered);\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n },\n);\n\naddConfigFlags(\n program\n .command(\"fill [paths...]\")\n .description(\n \"Propose evals for skills, agent definitions, and project rules, and write those above the confidence threshold\",\n ),\n)\n .option(\"--project <dir>\", \"project root to scan (default: current directory)\")\n // Repeatable, one value per occurrence, never split on commas — the family's\n // one-separator-per-list rule. It narrows what `fill` scans; there is no\n // `--collection`, because a docs collection is not an artifact set.\n .option(\"--exclude <glob>\", \"Glob to exclude (repeatable)\", collect, [])\n .option(\"--dry-run\", \"report proposals without writing them\")\n .option(\n \"--confidence <n>\",\n \"minimum confidence to write (0-1)\",\n (v) => parseFloat(v),\n )\n .option(\n \"--max-evals <n>\",\n \"maximum evals per artifact, including existing ones\",\n (v) => Number(v),\n )\n .option(\n \"--max-turns <n>\",\n \"Stop after this many inference calls (a cached artifact costs none)\",\n (v) => Number(v),\n )\n .option(\"--no-cache\", \"bypass the proposal cache\")\n .option(\n \"--provider <name>\",\n \"Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp\",\n )\n .option(\n \"--model <model>\",\n \"Model override; needs a named provider, from here or config\",\n )\n .option(\"--local\", LOCAL_FLAG_HELP)\n .option(\n \"--offline\",\n \"never fetch a remote manifest; read external metadata from local manifests\",\n )\n .option(\n \"--require <module>\",\n \"load a grader plugin; repeatable, and added to config plugins\",\n collect,\n [],\n )\n .option(\n \"-f, --format <format>\",\n `Output format: ${SUMMARY_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", SUMMARY_FORMATS),\n \"pretty\" as SummaryFormat,\n )\n .action(async (paths: string[], opts: ConfigFlags & {\n project?: string;\n exclude?: string[];\n dryRun?: boolean;\n confidence?: number;\n maxEvals?: number;\n maxTurns?: number;\n cache?: boolean;\n provider?: string;\n model?: string;\n local?: boolean;\n offline?: boolean;\n require?: string[];\n format?: SummaryFormat;\n }, command: Command) => {\n try {\n numeric(\"--confidence\", opts.confidence, 0, 1);\n whole(\"--max-evals\", opts.maxEvals, 1);\n whole(\"--max-turns\", opts.maxTurns, 1);\n\n const { report, rendered } = await runFill({\n ...configOptions(opts),\n ...(paths.length > 0 ? { paths } : {}),\n ...(opts.project !== undefined ? { project: opts.project } : {}),\n ...(opts.exclude !== undefined ? { exclude: opts.exclude } : {}),\n ...(opts.dryRun !== undefined ? { dryRun: opts.dryRun } : {}),\n ...(opts.confidence !== undefined ? { confidence: opts.confidence } : {}),\n ...(opts.maxEvals !== undefined ? { maxEvals: opts.maxEvals } : {}),\n ...(opts.maxTurns !== undefined ? { maxTurns: opts.maxTurns } : {}),\n ...(opts.cache === false ? { noCache: true } : {}),\n ...(opts.provider !== undefined ? { provider: opts.provider } : {}),\n ...(opts.model !== undefined ? { model: opts.model } : {}),\n ...(opts.local !== undefined ? { local: opts.local } : {}),\n ...(opts.offline === true ? { offline: true } : {}),\n ...(opts.require !== undefined ? { require: opts.require } : {}),\n // P1 (proposal 0047): offered only on a terminal, where there is\n // someone to answer. Off one the block goes to the artifact and the\n // W1 line says so.\n confirm: terminalConfirm(),\n onNotice: notice,\n onRelocated: (result) => {\n const manifests = result.manifests.map((m) => m.file).join(\", \");\n notice(`moved ${String(result.summary.moved)} value(s) into ${manifests}.`);\n },\n color: colorFor(command, process.stdout.isTTY),\n });\n console.log(\n opts.format === \"json\" ? JSON.stringify(report, null, 2) : rendered,\n );\n process.exitCode = report.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\n// The one write path `run` never takes (ADR 01024). Meant for a `SessionStart`\n// hook, which is why it reads its payload on stdin and — in that mode — writes\n// its report to stderr: a SessionStart hook's stdout becomes model context.\naddConfigFlags(\n program\n .command(\"capture\")\n .description(\n \"Record a session manifest: sha256 of every instruction artifact plus the git SHA, read from a Claude Code hook payload on stdin\",\n ),\n)\n .option(\"--project <dir>\", \"project root to scan (default: the payload's cwd)\")\n .option(\"--session-id <id>\", \"session id (default: the payload's session_id)\")\n .option(\"-o, --out <file>\", \"write here instead of the configured directory\")\n .option(\n \"-f, --format <format>\",\n `Output format: ${SUMMARY_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", SUMMARY_FORMATS),\n \"pretty\" as SummaryFormat,\n )\n .action(async (opts: ConfigFlags & {\n project?: string;\n sessionId?: string;\n out?: string;\n format?: SummaryFormat;\n }) => {\n try {\n const { runCapture } = await import(\"./commands/capture.js\");\n const result = await runCapture({\n version,\n ...configOptions(opts),\n ...(opts.project !== undefined ? { project: opts.project } : {}),\n ...(opts.sessionId !== undefined ? { sessionId: opts.sessionId } : {}),\n ...(opts.out !== undefined ? { out: opts.out } : {}),\n format: opts.format ?? \"pretty\",\n });\n if (result.stdout !== \"\") console.log(result.stdout);\n // Hook mode's report, through the family's stderr writer rather than\n // `console.error`, so the `manni: ` prefix comes from `programName()`\n // and is never hand-spelled. `notice`, not `warn`: the report says what\n // this run did, so it is said every time rather than deduplicated.\n if (result.stderr !== \"\") notice(result.stderr);\n process.exitCode = result.exitCode;\n } catch (e) {\n fail(e);\n }\n });\n\nprogram\n .command(\"list\")\n .description(\"List discoverable traces (Claude Code session files)\")\n // The long spellings only, matching `run`: a short form that exists on one\n // verb and not on its sibling is exactly the drift \"commands must have\n // parallel behaviors\" exists to prevent.\n .option(\n \"--project <dir>\",\n \"project directory to scope to (default: current directory)\",\n )\n .option(\"--all-projects\", \"scan every project in the session store\")\n .option(\n \"--newer-than <duration>\",\n \"only traces modified within this window, such as 30m, 24h, 7d or 2w\",\n )\n .option(\"--limit <n>\", \"maximum traces to list\", (v) => Number(v))\n .option(\n \"-f, --format <format>\",\n `Output format: ${SUMMARY_FORMATS.join(\" | \")}`,\n parseFormatArg(\"--format\", SUMMARY_FORMATS),\n \"pretty\" as SummaryFormat,\n )\n // No `-c`/`--no-config`: `list` enumerates the session store and reads no\n // config at all, and an accepted flag that quietly does nothing is worse\n // than an absent one.\n .action(async (opts: {\n project?: string;\n allProjects?: boolean;\n newerThan?: string;\n limit?: number;\n format?: SummaryFormat;\n }, command: Command) => {\n try {\n // The same footgun as `run --limit`: `slice(0, -1)` lists everything but\n // the oldest, and reads as a shorter store rather than as a bad flag.\n whole(\"--limit\", opts.limit, 1);\n const run = await runList({\n project: opts.project,\n allProjects: opts.allProjects,\n ...(opts.newerThan !== undefined ? { newerThan: opts.newerThan } : {}),\n limit: opts.limit,\n });\n console.log(\n opts.format === \"json\"\n ? JSON.stringify(run, null, 2)\n : renderList(run, { color: colorFor(command, process.stdout.isTTY) }),\n );\n } catch (e) {\n fail(e);\n }\n });\n\nreturn program;\n}\n"],"mappings":"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","names":["Command","outcome","skipped","text","runCheck","outcome","skipped","crawl","read","counts","text","render","text","collect","splitList","buildProgram","runCheck","text","render","Command","colorFor","splitPageArgument","where","buildProgram","Command","text","Command","buildProgram","Command","REPORT_FORMATS","Command","plural","buildProgram","Command","Command","renderCheckGithub","where","runCheck","plural","renderCheckGithub","where","resolve","runInit","resolve","text","buildProgram","Command","inputOptions","runInit","runCheck","runFill","rendered","renderFill","Command","resolveColor","buildProgram","Command","text","render","Command","existsSync","resolve","CONFIG_KEYS","CONFIG_FILE","where","asBoolean","asStringList","item","STDIN","resolve","RULE_ID_PREFIX","isTermRule","where","start","JUNIT_CLASSNAME","RULE_ID_PREFIX","summarize","compareFindings","existsSync","resolve","resolve","text","text","item","read","text","DOMParser","DOMParser","nameOf","start","text","nameOf","collect","read","definitionOf","nameOf","text","parse","cache","parse","childElements","text","start","definitionOf","item","LABEL","read","lineOf","text","start","item","LABEL","read","text","termOf","LABEL","text","read","start","termOf","LABEL","read","text","termOf","LABEL","text","read","termOf","labelsOf","item","references","read","resolve","content","resolve","existsSync","plural","runCheck","existsSync","summarize","parseYaml","stringifyYaml","apply","stringifyYaml","parseYaml","resolve","HOLDS","isAbsolute","join","relative","HOLDS","text","join","relative","isAbsolute","render","plural","join","SEVERITIES","isMapping","item","text","compareFindings","join","runLint","summarize","LIST_FORMATS","runList","existsSync","readFile","rm","writeFile","extname","join","resolve","STYLE","join","readFile","existsSync","writeFile","rm","resolve","render","extname","unique","LIST_SEPARATOR","cell","termEntry","INFORMATION_URI","RULES_URI","RULE_DESCRIPTIONS","RULE_ID_PREFIX","describe","isTermRule","MESSAGE_LABEL","JUNIT_CLASSNAME","text","plural","where","references","start","baseName","colorFor","text","references","buildProgram","Command","LIST_FORMATS","runList","runCheck","runLint","Command","buildProgram","Command","parseFormat","report","rendered","runRun","REPORT_FORMATS","runCalibrate","SUMMARY_FORMATS","runFill","runList","renderList","buildProgram","Command"]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["/**\n * The `manni` CLI: one bin, one subcommand per tool in the family.\n *\n * Each tool builds its own commander program and is mounted here under its\n * name, so `manni meta validate …` is the metadata tool's `validate` with\n * nothing in between. The umbrella owns only what is common to all of them:\n * the name, the version, and the exit-code contract in `runProgram`.\n *\n * Tools land here one at a time, on their own branches; until one merges its\n * subcommand does not exist.\n *\n * Every domain is imported on demand. A domain's module graph is its whole\n * dependency tree (Playwright, axe, Asciidoctor, the RDF stack, ajv), and a\n * hook runs `manni check` after every edit, so the bin mounts only the domain\n * argv names. `--version` mounts none. Anything else (`--help`, a bare\n * `manni`, a typo) mounts them all, so help and \"unknown command\" read as\n * they always did.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { runIfMain } from \"./shared/run.js\";\n\ninterface Domain {\n /** The command names the loader mounts, known before it is loaded. */\n names: readonly string[];\n load: () => Promise<Command[]>;\n}\n\n// In the order `manni --help` lists them.\nconst DOMAINS: readonly Domain[] = [\n {\n names: [\"meta\"],\n load: async () => [\n (await import(\"./meta/cli.js\"))\n .buildProgram()\n .name(\"meta\")\n .description(\n \"Validate, read, query and fill document metadata against JSON Schema\",\n ),\n ],\n },\n {\n names: [\"a11y\"],\n load: async () => [\n (await import(\"./a11y/cli.js\"))\n .buildProgram()\n .name(\"a11y\")\n .description(\n \"Crawl a site and check every page for accessibility violations with axe-core\",\n ),\n ],\n },\n {\n names: [\"cite\"],\n load: async () => [\n (await import(\"./cite/cli.js\"))\n .buildProgram()\n .name(\"cite\")\n .description(\n \"Track citations from doc claims to source lines and check them for drift\",\n ),\n ],\n },\n {\n names: [\"lint\"],\n load: async () => [\n (await import(\"./lint/cli.js\"))\n .buildProgram()\n .name(\"lint\")\n .description(\n \"Validate document structure against doctype templates, routed by a page's type\",\n ),\n ],\n },\n {\n names: [\"docevals\"],\n load: async () => [\n (await import(\"./docevals/cli.js\"))\n .buildProgram()\n .name(\"docevals\")\n .description(\n \"Deterministic and LLM-as-judge evals for documentation pages, driven by frontmatter\",\n ),\n ],\n },\n {\n names: [\"term\"],\n load: async () => [\n (await import(\"./term/index.js\"))\n .buildProgram()\n .name(\"term\")\n .description(\"Check, lint and render a docset's terms and the references into them\"),\n ],\n },\n {\n names: [\"graph\"],\n load: async () => [\n (await import(\"./graph/cli.js\"))\n .buildProgram()\n .name(\"graph\")\n .description(\n \"Deterministic knowledge graphs derived from documentation frontmatter and formatting\",\n ),\n ],\n },\n {\n names: [\"tracevals\"],\n load: async () => [\n (await import(\"./tracevals/cli.js\"))\n .buildProgram()\n .name(\"tracevals\")\n .description(\n \"Deterministic and LLM-as-judge adherence evals for AI agent session traces\",\n ),\n ],\n },\n // Not a tool but a family resource with verbs (proposal 0045).\n {\n names: [\"key\"],\n load: async () => [\n (await import(\"./key/cli.js\"))\n .buildProgram()\n .name(\"key\")\n .description(\"Set and rotate the family key that encrypted values are encrypted with.\"),\n ],\n },\n // The two family verbs (proposal 0078), and the only verbs the umbrella\n // carries: each runs other domains' command cores and owns no checks.\n {\n names: [\"check\", \"status\"],\n load: async () => {\n const { buildCheck, buildStatus } = await import(\"./family/cli.js\");\n return [buildCheck(), buildStatus()];\n },\n },\n];\n\nconst VERSION_FLAGS = new Set([\"-V\", \"--version\"]);\n\n/**\n * The domains a run with these arguments (argv after the script) dispatches\n * to. The umbrella's only options are `--version` and `--help`, so the first\n * argument is one of them or the command commander will look up.\n */\nfunction domainsFor(args: readonly string[]): readonly Domain[] {\n const first = args[0];\n if (first === undefined) return DOMAINS;\n if (VERSION_FLAGS.has(first)) return [];\n const named = DOMAINS.find((d) => d.names.includes(first));\n return named === undefined ? DOMAINS : [named];\n}\n\nasync function mount(domains: readonly Domain[]): Promise<Command> {\n const mounted = (await Promise.all(domains.map((d) => d.load()))).flat();\n const metaCommands = new Set(\n mounted.find((c) => c.name() === \"meta\")?.commands.map((c) => c.name()),\n );\n\n const program = new Command();\n program\n .name(\"manni\")\n .description(\"Tools for documentation that is meant to be checked.\")\n .version(pkg.version, \"-V, --version\")\n // A pointer, not the whole help screen. Commander appends this after every\n // usage error, and the message that precedes it already names the problem.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before `addCommand`, which copies the exit callback into the\n // mounted program by value. See the same note in ./meta/cli.ts.\n .exitOverride()\n .configureOutput({\n outputError: (str, write) => {\n write(str);\n // `manni validate …` is the most likely thing a docmeta user types\n // first. Commander's \"unknown command\" is correct and unhelpful; say\n // where the command went.\n const m = /unknown command '([^']+)'/.exec(str);\n const name = m?.[1];\n if (name !== undefined && metaCommands.has(name)) {\n write(\n `(\\`${name}\\` is a metadata command: try \\`manni meta ${name}\\`)\\n`,\n );\n }\n },\n });\n\n for (const command of mounted) program.addCommand(command);\n return program;\n}\n\n/** The whole command tree, every domain mounted. */\nexport function buildProgram(): Promise<Command> {\n return mount(DOMAINS);\n}\n\n/** The tree a run with these arguments needs: the one domain they name, or all of them. */\nexport function buildProgramFor(args: readonly string[]): Promise<Command> {\n return mount(domainsFor(args));\n}\n\nrunIfMain(import.meta.url, () => buildProgramFor(process.argv.slice(2)));\n"],"mappings":"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","names":[]}