@hawkeyexl/manni 4.3.1 → 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-CFDUZRM2.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-KJR7OVDX.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-UBMMXS2Y.js → chunk-KCGV52AM.js} +69 -48
  67. package/dist/{chunk-UBMMXS2Y.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-HAPTXWU2.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-5HNHEUD5.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-G5CM2VGQ.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 -7661
  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-A5HZKYIW.js +0 -18
  206. package/dist/calibrate-S5K6QHUY.js +0 -13
  207. package/dist/capture-OZEZDABQ.js +0 -15
  208. package/dist/chunk-3R23C5DT.js.map +0 -1
  209. package/dist/chunk-CFDUZRM2.js.map +0 -1
  210. package/dist/chunk-G5CM2VGQ.js.map +0 -1
  211. package/dist/chunk-KJR7OVDX.js.map +0 -1
  212. package/dist/chunk-V4KUVE47.js +0 -27170
  213. package/dist/chunk-V4KUVE47.js.map +0 -1
  214. package/dist/chunk-ZQBTK3DO.js +0 -26518
  215. package/dist/chunk-ZQBTK3DO.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-A5HZKYIW.js.map → batch-DFRCLY77.js.map} +0 -0
  220. /package/dist/{calibrate-S5K6QHUY.js.map → build-Q5C6SX5J.js.map} +0 -0
  221. /package/dist/{capture-OZEZDABQ.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-HAPTXWU2.js.map → chunk-MYC3O5EJ.js.map} +0 -0
  224. /package/dist/{chunk-5HNHEUD5.js.map → chunk-XYLUCIKQ.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/term/cli.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/write.ts","../src/term/reporters/csv.ts","../src/term/reporters/sarif.ts","../src/term/reporters/junit.ts","../src/term/commands/labels.ts"],"sourcesContent":["/**\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 * 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","/**\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 * 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 * 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"],"mappings":"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","names":["HOLDS","join","HOLDS","text","join","join","text","join","rm","writeFile","join","resolve","STYLE","join","writeFile","rm","resolve","LIST_SEPARATOR","cell","text","references"]}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DocevalsError
4
+ } from "./chunk-SE4JN5XN.js";
5
+ import "./chunk-G3T47CFV.js";
6
+ import "./chunk-2H7UOFLK.js";
7
+ export {
8
+ DocevalsError
9
+ };
10
+ //# sourceMappingURL=types-Y6TXHM7M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runValidate
4
+ } from "./chunk-V46OILVC.js";
5
+ import "./chunk-RLR4TKUZ.js";
6
+ import "./chunk-JVTNMVYU.js";
7
+ import "./chunk-YEUYKR62.js";
8
+ import "./chunk-Q35YIDBV.js";
9
+ import "./chunk-UZC7LDAQ.js";
10
+ import "./chunk-OWBRDNRZ.js";
11
+ import "./chunk-G3T47CFV.js";
12
+ import "./chunk-2H7UOFLK.js";
13
+ export {
14
+ runValidate
15
+ };
16
+ //# sourceMappingURL=validate-GQRM77YN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hawkeyexl/manni",
3
- "version": "4.3.1",
3
+ "version": "4.4.0",
4
4
  "description": "One command line for documentation that is meant to be checked. `manni meta` validates the presence and format of document metadata (Markdown frontmatter and more) against JSON Schema, built for CI. Formerly docmeta.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "manni",
3
+ "description": "Checks the docs an agent edits against everything the repository set up in manni, blocks on errors, and records the session manifest tracevals reads.",
4
+ "version": "4.4.0",
5
+ "author": { "name": "hawkeyexl" },
6
+ "homepage": "https://hawkeyexl.github.io/manni/",
7
+ "repository": "https://github.com/hawkeyexl/manni",
8
+ "license": "MIT"
9
+ }
@@ -0,0 +1,52 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "npx --no @hawkeyexl/manni tracevals capture",
10
+ "timeout": 60,
11
+ "statusMessage": "Recording the session manifest…"
12
+ }
13
+ ]
14
+ },
15
+ {
16
+ "hooks": [
17
+ {
18
+ "type": "command",
19
+ "command": "npx --no @hawkeyexl/manni status",
20
+ "timeout": 30,
21
+ "statusMessage": "Reading what manni checks here…"
22
+ }
23
+ ]
24
+ }
25
+ ],
26
+ "PostToolUse": [
27
+ {
28
+ "matcher": "Edit|Write|MultiEdit|NotebookEdit",
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "npx --no @hawkeyexl/manni check",
33
+ "timeout": 120,
34
+ "statusMessage": "Checking the edited file…"
35
+ }
36
+ ]
37
+ }
38
+ ],
39
+ "Stop": [
40
+ {
41
+ "hooks": [
42
+ {
43
+ "type": "command",
44
+ "command": "npx --no @hawkeyexl/manni check",
45
+ "timeout": 600,
46
+ "statusMessage": "Checking every file you changed…"
47
+ }
48
+ ]
49
+ }
50
+ ]
51
+ }
52
+ }
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: check
3
+ description: Run manni check over the repository and walk the findings. Use when asked to check, verify or validate the docs, or when a hook reports manni errors.
4
+ allowed-tools: Bash(npx manni *), Bash(npx --no @hawkeyexl/manni *)
5
+ ---
6
+
7
+ # Check the docs with manni
8
+
9
+ `manni check` runs every check the repository set up, and nothing else.
10
+
11
+ 1. Run `npx --no @hawkeyexl/manni status`. It lists each domain as in play, not set up or not checked.
12
+ 2. Run `npx --no @hawkeyexl/manni check`. Add paths to check only those files, as in `manni check docs/limits.md`.
13
+ 3. Read the report. Each section names the check that found the problem, such as `meta validate` or `cite check`.
14
+ 4. Only errors fail the run. Warnings and notices are information.
15
+ 5. For each error, follow the `fix` skill. Do not guess a repair from the message alone.
16
+ 6. Run `manni check` again until it exits 0.
17
+
18
+ A skipped check means its domain is not set up. That is not a failure.
19
+ If the report says no config was found, use the `setup` skill.
20
+ Exit code 2 means a check could not run. Read its message and fix the cause before you trust the result.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: evals
3
+ description: Author evals for docs pages or for agent artifacts such as CLAUDE.md, skills and subagents. Use when asked to add, propose or promote evals.
4
+ allowed-tools: Bash(npx manni *), Bash(npx --no @hawkeyexl/manni *)
5
+ ---
6
+
7
+ # Author evals
8
+
9
+ Evals declare what a page or an agent artifact must satisfy. Propose them, show the diff, and let the user review.
10
+
11
+ ## Pages
12
+
13
+ 1. Run `npx --no @hawkeyexl/manni docevals list` to see the evals each page resolves.
14
+ 2. Run `manni docevals fill <path>` to have the model propose frontmatter evals. It writes only proposals above the confidence threshold.
15
+ 3. Run `manni docevals generate <path>` to write check scripts for command evals that have an assertion but no command.
16
+ 4. Run `manni docevals promote` to find model-graded evals that a deterministic check can express. Add `--write` to convert them.
17
+ 5. Run `manni docevals run --deterministic-only` to confirm the new evals pass.
18
+
19
+ ## Agent artifacts
20
+
21
+ Run `manni tracevals fill <path>` over a skill, a subagent definition or a rules file. It proposes evals in the artifact's `metadata.evals` block.
22
+ `manni tracevals list` shows what the evals cover.
23
+
24
+ ## Review
25
+
26
+ Show the user `git diff` of every file an authoring command wrote.
27
+ Do not weaken an assertion so that a page passes. A new eval should fail on the defect it describes.
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: fix
3
+ description: Repair manni findings in docs. Use after manni check or a hook reports errors in metadata, citations, terms, structure, evals or the graph.
4
+ allowed-tools: Bash(npx manni *), Bash(npx --no @hawkeyexl/manni *)
5
+ ---
6
+
7
+ # Repair manni findings
8
+
9
+ Start from the report of `npx --no @hawkeyexl/manni check`. Each section names the check. Match it to a repair below.
10
+
11
+ ## Guardrails
12
+
13
+ - Never loosen a schema, a config key or an eval to make a check pass. Fix the page.
14
+ - Never run `manni cite update --accept` before you read the changed source lines.
15
+ - Run `manni check` after every repair. A fix in one domain can break another.
16
+ - If a finding is wrong, stop and tell the user why. Do not hide it.
17
+
18
+ ## meta validate
19
+
20
+ The finding names a field path, such as `/description`. Edit the page frontmatter so the field is present and valid.
21
+
22
+ Some fields are managed. Stamp them from history with `npx --no @hawkeyexl/manni meta derive <path>`. Add `--check` to see which are stale without writing.
23
+ Do not hand-edit a managed field. `derive` writes it.
24
+
25
+ ## cite check
26
+
27
+ Each finding has a rule id.
28
+
29
+ | Rule | Repair |
30
+ |---|---|
31
+ | `source-moved` | The cited lines moved. Run `manni cite update <path>`. |
32
+ | `claim-moved`, `claim-reanchored` | The sentence moved. Run `manni cite update <path>`. |
33
+ | `source-changed` | The cited source changed since the pin. Read the lines at the current commit. If the sentence is still true, run `manni cite update --accept --only <id> <path>`. If it is not, rewrite the sentence first, then accept. |
34
+ | `source-never-true`, `source-missing`, `source-moved-ambiguous` | Open the source and find the lines the sentence rests on. Fix the pin or the sentence. |
35
+ | `marker-orphan`, `marker-invalid`, `anchor-invalid`, `entry-invalid` | Fix the marker or the entry the finding names. |
36
+
37
+ Preview any rewrite with `--dry-run`. It prints the diffs and writes nothing.
38
+
39
+ ## term check
40
+
41
+ The glossary and the `concepts:` pages disagree. Fix the term page or the concept name.
42
+ After you change a term page, run `manni term write` to regenerate any rendered output the repository commits. Add `--check` to see whether it is stale.
43
+
44
+ ## lint check
45
+
46
+ Run `manni lint structure <path> --explain` to see which template routed the page and why.
47
+ Then edit the page to meet that template. Change the page `type` only if the routing is wrong.
48
+
49
+ ## docevals run
50
+
51
+ An eval failed. Read the eval assertion and the evidence it cites. Fix the page so the assertion holds.
52
+ Do not edit the eval to pass. To change an eval on purpose, use the `evals` skill.
53
+
54
+ ## graph check
55
+
56
+ A shape failed. The finding names the node and the property. Fix the frontmatter, the link or the heading it points at.
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: setup
3
+ description: Set up manni in a repository. Use when there is no manni.config.yaml, when the user asks to add manni, or when manni check reports that nothing is set up.
4
+ allowed-tools: Bash(npm *), Bash(npx manni *), Bash(npx --no @hawkeyexl/manni *)
5
+ ---
6
+
7
+ # Set up manni
8
+
9
+ Do these steps in order. Ask before you choose anything that changes how the docs are judged.
10
+
11
+ 1. Install the package: `npm install --save-dev @hawkeyexl/manni`.
12
+ 2. Find the docs. Look for Markdown and MDX folders, such as `docs/`. Ask the user to confirm the paths.
13
+ 3. Write `manni.config.yaml` at the repository root with a top-level `collections:` entry for those docs.
14
+
15
+ ```yaml
16
+ collections:
17
+ - name: site
18
+ paths:
19
+ - "docs/**/*.{md,mdx}"
20
+ exclude:
21
+ - "docs/drafts/**"
22
+ ```
23
+
24
+ `name` is required and unique. The name `docs` is refused, so pick another. `exclude` is optional.
25
+
26
+ 4. Ask which domains to set up. A domain is in play only when its section exists. Offer these:
27
+
28
+ | Domain | What it checks | How to set it up |
29
+ |---|---|---|
30
+ | meta | Frontmatter against JSON Schema | Add a `meta:` section with `schemas:`. Run `manni meta schemas` to list the built-in ones. |
31
+ | lint | Page structure against templates | Add a `lint:` section. See `manni lint templates`. |
32
+ | docevals | Evals declared in page frontmatter | Add a `docevals:` section. |
33
+ | graph | The knowledge graph and its SHACL shapes | Run `manni graph init`. It appends a `graph:` section. |
34
+
35
+ Run `manni docevals init` only when no config file exists. It refuses an existing one. With a config in place, write the `docevals:` section by hand.
36
+ Citations and terms need no section. They are in play when the pages carry them.
37
+
38
+ 5. Run `npx --no @hawkeyexl/manni status` and show the user the table.
39
+ 6. Run `npx --no @hawkeyexl/manni check`. Report the result and use the `fix` skill for any error.
40
+
41
+ Do not add a section for a domain the user declined. A section that exists turns that domain's checks on.
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- keepNewerThan,
4
- parseNewerThan,
5
- resolveBatchTraces,
6
- runBatch
7
- } from "./chunk-KJR7OVDX.js";
8
- import "./chunk-CFDUZRM2.js";
9
- import "./chunk-ZQBTK3DO.js";
10
- import "./chunk-3R23C5DT.js";
11
- import "./chunk-IOYXPBCL.js";
12
- export {
13
- keepNewerThan,
14
- parseNewerThan,
15
- resolveBatchTraces,
16
- runBatch
17
- };
18
- //# sourceMappingURL=batch-A5HZKYIW.js.map