@hawkeyexl/manni 4.10.0 → 4.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/README.md +1 -1
  2. package/dist/batch-EFSFG6GC.js +46 -0
  3. package/dist/build-NIO3UIWJ.js +36 -0
  4. package/dist/calibrate-6VO7URRV.js +41 -0
  5. package/dist/capture-NMBVJO3C.js +38 -0
  6. package/dist/check-SHOYX2B5.js +30 -0
  7. package/dist/check-XMJKH3KV.js +34 -0
  8. package/dist/{check-NLL4NRYA.js → check-Y62BJNC4.js} +35 -31
  9. package/dist/{check-NLL4NRYA.js.map → check-Y62BJNC4.js.map} +1 -1
  10. package/dist/{check-7B77ZD2N.js → check-ZMO3ZLMW.js} +19 -15
  11. package/dist/{chunk-PK7EKJ5T.js → chunk-24AJK2RG.js} +5 -10
  12. package/dist/chunk-24AJK2RG.js.map +1 -0
  13. package/dist/chunk-2OZF2VUB.js +164 -0
  14. package/dist/chunk-2OZF2VUB.js.map +1 -0
  15. package/dist/chunk-2UJZXVHR.js +1868 -0
  16. package/dist/chunk-2UJZXVHR.js.map +1 -0
  17. package/dist/{chunk-DNZUBCGZ.js → chunk-3BRJCQPY.js} +36 -7
  18. package/dist/chunk-3BRJCQPY.js.map +1 -0
  19. package/dist/{chunk-D2UW3ZCK.js → chunk-42VFJOAF.js} +13 -11
  20. package/dist/{chunk-D2UW3ZCK.js.map → chunk-42VFJOAF.js.map} +1 -1
  21. package/dist/{chunk-LQZQ5KGG.js → chunk-4Q24OYI3.js} +7 -7
  22. package/dist/{chunk-XU73V5XT.js → chunk-4WJTURRO.js} +15 -15
  23. package/dist/{chunk-WN47MNSK.js → chunk-5SID2SVL.js} +4 -4
  24. package/dist/{chunk-5REEVKGH.js → chunk-AANUY4BH.js} +2 -2
  25. package/dist/chunk-ANPIIYRH.js +2272 -0
  26. package/dist/chunk-ANPIIYRH.js.map +1 -0
  27. package/dist/{chunk-RZVCWX5R.js → chunk-AYVKN3PG.js} +4 -4
  28. package/dist/{chunk-2UCC26MO.js → chunk-CH6IOGXV.js} +9 -9
  29. package/dist/{chunk-RODZ7MB7.js → chunk-D5Z6B4M7.js} +6 -6
  30. package/dist/{chunk-IJ62BB2T.js → chunk-D6SELXQ2.js} +7 -7
  31. package/dist/{chunk-2JV7C4YV.js → chunk-DDILEF5F.js} +890 -1399
  32. package/dist/chunk-DDILEF5F.js.map +1 -0
  33. package/dist/{chunk-3E2X2RBU.js → chunk-DGRLHDM4.js} +9 -9
  34. package/dist/{chunk-2BV4FBC7.js → chunk-DHGB4JBG.js} +4 -3
  35. package/dist/chunk-DHGB4JBG.js.map +1 -0
  36. package/dist/{chunk-6LR73NMO.js → chunk-DLU5FCFT.js} +30 -28
  37. package/dist/chunk-DLU5FCFT.js.map +1 -0
  38. package/dist/chunk-DSWKBZWW.js +16 -0
  39. package/dist/chunk-DSWKBZWW.js.map +1 -0
  40. package/dist/{chunk-BD7IXBWE.js → chunk-F564FHMQ.js} +8 -8
  41. package/dist/{chunk-ABHG6I3G.js → chunk-FKAZUZQU.js} +469 -85
  42. package/dist/chunk-FKAZUZQU.js.map +1 -0
  43. package/dist/{chunk-DFCQ6BMI.js → chunk-G3MBUL5M.js} +4 -4
  44. package/dist/{chunk-SUTMSDQ2.js → chunk-GQ3KRY3B.js} +3 -3
  45. package/dist/chunk-HDPN46JP.js +393 -0
  46. package/dist/chunk-HDPN46JP.js.map +1 -0
  47. package/dist/{chunk-EAUIQADY.js → chunk-IQQAJROD.js} +6 -6
  48. package/dist/{chunk-ZHRPH52H.js → chunk-IZXN3WI6.js} +2 -2
  49. package/dist/{chunk-NCPWXHDO.js → chunk-JEUFYSFQ.js} +4 -4
  50. package/dist/{chunk-G6FNWRAI.js → chunk-JSSM7VVV.js} +4 -4
  51. package/dist/{chunk-CCWMACJL.js → chunk-KFGZPVFA.js} +229 -821
  52. package/dist/chunk-KFGZPVFA.js.map +1 -0
  53. package/dist/{chunk-H26VDFDS.js → chunk-KGFSPJLD.js} +2 -2
  54. package/dist/{chunk-AO5TSDKT.js → chunk-KMORGMCW.js} +7 -7
  55. package/dist/{chunk-WQWKYAAK.js → chunk-NUQF5F5J.js} +2 -2
  56. package/dist/{chunk-2YJ5H5E6.js → chunk-NZ6KSHFD.js} +23 -21
  57. package/dist/{chunk-2YJ5H5E6.js.map → chunk-NZ6KSHFD.js.map} +1 -1
  58. package/dist/{chunk-7Y3N4Y72.js → chunk-OHUDZRLK.js} +3 -3
  59. package/dist/{chunk-GCKHSBEN.js → chunk-OKMTUAWO.js} +4 -4
  60. package/dist/{chunk-6M5VJOC2.js → chunk-OTJOBZJ5.js} +167 -166
  61. package/dist/chunk-OTJOBZJ5.js.map +1 -0
  62. package/dist/{chunk-2W34HX2U.js → chunk-PS257NIU.js} +288 -373
  63. package/dist/chunk-PS257NIU.js.map +1 -0
  64. package/dist/chunk-QDC7JPFG.js +685 -0
  65. package/dist/chunk-QDC7JPFG.js.map +1 -0
  66. package/dist/chunk-QEAGL4V5.js +3185 -0
  67. package/dist/chunk-QEAGL4V5.js.map +1 -0
  68. package/dist/{chunk-GB2XPITA.js → chunk-QMY57PVW.js} +2 -2
  69. package/dist/{chunk-55GMOVKW.js → chunk-QNDDPXFR.js} +2 -2
  70. package/dist/{chunk-GXN7RRHR.js → chunk-QSIXNTRV.js} +4 -4
  71. package/dist/{chunk-G7XD4QH5.js → chunk-RGLFV4KO.js} +11372 -10218
  72. package/dist/chunk-RGLFV4KO.js.map +1 -0
  73. package/dist/{chunk-QBVP3SQP.js → chunk-SGR7ZAVE.js} +13 -7
  74. package/dist/chunk-SGR7ZAVE.js.map +1 -0
  75. package/dist/{chunk-KBG463UK.js → chunk-SMHAYK6I.js} +2409 -5243
  76. package/dist/chunk-SMHAYK6I.js.map +1 -0
  77. package/dist/{chunk-XG6PVB5S.js → chunk-SSQZB5SQ.js} +1 -11
  78. package/dist/chunk-SSQZB5SQ.js.map +1 -0
  79. package/dist/{chunk-GDLHTI5R.js → chunk-STPGIKPY.js} +8 -2
  80. package/dist/chunk-STPGIKPY.js.map +1 -0
  81. package/dist/{chunk-QJRQ4BRC.js → chunk-U22TOL5Y.js} +17 -17
  82. package/dist/{chunk-NGTVREIH.js → chunk-U6IHLEWT.js} +2 -2
  83. package/dist/{chunk-Z5YHMRLF.js → chunk-UUCCV3SI.js} +2 -2
  84. package/dist/{chunk-ZXXFP2LA.js → chunk-UXMCHBOJ.js} +2 -2
  85. package/dist/{chunk-VZVEP2OZ.js → chunk-VFAKGIDG.js} +2 -2
  86. package/dist/{chunk-QCHVR4ZM.js → chunk-VM7VAFJW.js} +33 -7
  87. package/dist/chunk-VM7VAFJW.js.map +1 -0
  88. package/dist/{chunk-VQK4VHLF.js → chunk-YQV75FIL.js} +2 -2
  89. package/dist/chunk-YUTVAMWW.js +2 -0
  90. package/dist/chunk-ZPLVANY2.js +15 -0
  91. package/dist/chunk-ZPLVANY2.js.map +1 -0
  92. package/dist/{cli-BIIUKPTE.js → cli-4CR7QIOK.js} +26 -22
  93. package/dist/{cli-BIIUKPTE.js.map → cli-4CR7QIOK.js.map} +1 -1
  94. package/dist/{cli-V2DI3K2R.js → cli-6R4W3HAH.js} +37 -33
  95. package/dist/{cli-V2DI3K2R.js.map → cli-6R4W3HAH.js.map} +1 -1
  96. package/dist/{cli-HO62TOM2.js → cli-BOMA2FMP.js} +14 -11
  97. package/dist/{cli-EH3I4IUX.js → cli-EDQPQOCE.js} +47 -41
  98. package/dist/cli-EDQPQOCE.js.map +1 -0
  99. package/dist/{cli-P2X7PNY6.js → cli-GBF76EXT.js} +25 -20
  100. package/dist/{cli-P2X7PNY6.js.map → cli-GBF76EXT.js.map} +1 -1
  101. package/dist/{cli-4YYC6LCY.js → cli-MQYCF3SR.js} +27 -23
  102. package/dist/{cli-4YYC6LCY.js.map → cli-MQYCF3SR.js.map} +1 -1
  103. package/dist/{cli-UETKXHJN.js → cli-OJKFXQOM.js} +9 -9
  104. package/dist/{cli-LWST5FQH.js → cli-PHZAO4LZ.js} +4 -4
  105. package/dist/{cli-TELPAMJO.js → cli-PTKFFNOW.js} +59 -35
  106. package/dist/cli-PTKFFNOW.js.map +1 -0
  107. package/dist/{cli-SGVFZOAW.js → cli-UW2K5Z5J.js} +34 -29
  108. package/dist/{cli-SGVFZOAW.js.map → cli-UW2K5Z5J.js.map} +1 -1
  109. package/dist/cli-XXTNPPKB.js +83 -0
  110. package/dist/cli-XXTNPPKB.js.map +1 -0
  111. package/dist/cli.js +24 -12
  112. package/dist/cli.js.map +1 -1
  113. package/dist/{config-TYXYQK3I.js → config-JJW75SBX.js} +5 -5
  114. package/dist/docmeta.js +13 -10
  115. package/dist/docmeta.js.map +1 -1
  116. package/dist/github-6VQKSB67.js +35 -0
  117. package/dist/github-RBSEM7ZK.js +30 -0
  118. package/dist/graph/runtime.d.ts +4 -1
  119. package/dist/graph/runtime.js +20 -9
  120. package/dist/graph/runtime.js.map +1 -1
  121. package/dist/{host-6GURH5HE.js → host-YSTYO5DX.js} +3 -3
  122. package/dist/index.d.ts +1214 -940
  123. package/dist/index.js +190 -160
  124. package/dist/index.js.map +1 -1
  125. package/dist/{json-QR4G35KA.js → json-PU2HLHDQ.js} +18 -14
  126. package/dist/labels-SJNSOPBI.js +73 -0
  127. package/dist/labels-SJNSOPBI.js.map +1 -0
  128. package/dist/lint-KIVTHLGU.js +34 -0
  129. package/dist/list-RDEJDDJF.js +32 -0
  130. package/dist/list-SUTDWL2J.js +35 -0
  131. package/dist/{page-FSXDXCDD.js → page-UMAA3NCM.js} +18 -13
  132. package/dist/{prepare-UPIBTFNS.js → prepare-3I3LOXXD.js} +24 -20
  133. package/dist/{prepare-UPIBTFNS.js.map → prepare-3I3LOXXD.js.map} +1 -1
  134. package/dist/{pretty-4IONWSEP.js → pretty-ANLRHU4O.js} +18 -14
  135. package/dist/{pretty-R4BQD2VH.js → pretty-Q3ZFKOR7.js} +18 -14
  136. package/dist/{provider-527CO4DM.js → provider-LBX4IXGX.js} +3 -3
  137. package/dist/{release-3D5PK6M7.js → release-VV3UTKE5.js} +3 -3
  138. package/dist/{reporters-M6LJ2IYU.js → reporters-26H3N2KW.js} +3 -3
  139. package/dist/{reporters-DHO2BXAD.js → reporters-ILT36CIH.js} +7 -7
  140. package/dist/{reporters-FPP6JNDP.js → reporters-PNDLWT6K.js} +16 -12
  141. package/dist/run-QXCK33Z4.js +37 -0
  142. package/dist/{term-ASM4LVYC.js → term-D2N7UN4P.js} +981 -138
  143. package/dist/term-D2N7UN4P.js.map +1 -0
  144. package/dist/validate-BRUCOT2O.js +19 -0
  145. package/dist/validate-BRUCOT2O.js.map +1 -0
  146. package/package.json +3 -2
  147. package/plugin/manni/.claude-plugin/plugin.json +1 -1
  148. package/shapes/graph/shapes-1.1.0.ttl +785 -0
  149. package/dist/batch-6NICDKRE.js +0 -41
  150. package/dist/build-3KP2K3XN.js +0 -32
  151. package/dist/calibrate-LUA3DWKD.js +0 -36
  152. package/dist/capture-NETOHCB4.js +0 -34
  153. package/dist/check-E4QCB7LS.js +0 -20
  154. package/dist/check-PTECPIIB.js +0 -26
  155. package/dist/chunk-2BV4FBC7.js.map +0 -1
  156. package/dist/chunk-2JV7C4YV.js.map +0 -1
  157. package/dist/chunk-2W34HX2U.js.map +0 -1
  158. package/dist/chunk-4DLF5SA4.js +0 -392
  159. package/dist/chunk-4DLF5SA4.js.map +0 -1
  160. package/dist/chunk-6AGESHHM.js +0 -387
  161. package/dist/chunk-6AGESHHM.js.map +0 -1
  162. package/dist/chunk-6LR73NMO.js.map +0 -1
  163. package/dist/chunk-6M5VJOC2.js.map +0 -1
  164. package/dist/chunk-ABHG6I3G.js.map +0 -1
  165. package/dist/chunk-CCWMACJL.js.map +0 -1
  166. package/dist/chunk-DNZUBCGZ.js.map +0 -1
  167. package/dist/chunk-G7XD4QH5.js.map +0 -1
  168. package/dist/chunk-GDLHTI5R.js.map +0 -1
  169. package/dist/chunk-KBG463UK.js.map +0 -1
  170. package/dist/chunk-PK7EKJ5T.js.map +0 -1
  171. package/dist/chunk-QBVP3SQP.js.map +0 -1
  172. package/dist/chunk-QCHVR4ZM.js.map +0 -1
  173. package/dist/chunk-VVVKBUBO.js +0 -818
  174. package/dist/chunk-VVVKBUBO.js.map +0 -1
  175. package/dist/chunk-XG6PVB5S.js.map +0 -1
  176. package/dist/cli-EH3I4IUX.js.map +0 -1
  177. package/dist/cli-TELPAMJO.js.map +0 -1
  178. package/dist/github-ESK45CEZ.js +0 -26
  179. package/dist/github-WER7JUTN.js +0 -31
  180. package/dist/lint-QTI7XK2A.js +0 -30
  181. package/dist/list-JO4G3TS3.js +0 -30
  182. package/dist/list-O2MJUP5V.js +0 -28
  183. package/dist/run-YH5Z7RJ7.js +0 -32
  184. package/dist/term-ASM4LVYC.js.map +0 -1
  185. package/dist/validate-7JI3H57P.js +0 -17
  186. /package/dist/{batch-6NICDKRE.js.map → batch-EFSFG6GC.js.map} +0 -0
  187. /package/dist/{build-3KP2K3XN.js.map → build-NIO3UIWJ.js.map} +0 -0
  188. /package/dist/{calibrate-LUA3DWKD.js.map → calibrate-6VO7URRV.js.map} +0 -0
  189. /package/dist/{capture-NETOHCB4.js.map → capture-NMBVJO3C.js.map} +0 -0
  190. /package/dist/{check-7B77ZD2N.js.map → check-SHOYX2B5.js.map} +0 -0
  191. /package/dist/{check-E4QCB7LS.js.map → check-XMJKH3KV.js.map} +0 -0
  192. /package/dist/{check-PTECPIIB.js.map → check-ZMO3ZLMW.js.map} +0 -0
  193. /package/dist/{chunk-LQZQ5KGG.js.map → chunk-4Q24OYI3.js.map} +0 -0
  194. /package/dist/{chunk-XU73V5XT.js.map → chunk-4WJTURRO.js.map} +0 -0
  195. /package/dist/{chunk-WN47MNSK.js.map → chunk-5SID2SVL.js.map} +0 -0
  196. /package/dist/{chunk-5REEVKGH.js.map → chunk-AANUY4BH.js.map} +0 -0
  197. /package/dist/{chunk-RZVCWX5R.js.map → chunk-AYVKN3PG.js.map} +0 -0
  198. /package/dist/{chunk-2UCC26MO.js.map → chunk-CH6IOGXV.js.map} +0 -0
  199. /package/dist/{chunk-RODZ7MB7.js.map → chunk-D5Z6B4M7.js.map} +0 -0
  200. /package/dist/{chunk-IJ62BB2T.js.map → chunk-D6SELXQ2.js.map} +0 -0
  201. /package/dist/{chunk-3E2X2RBU.js.map → chunk-DGRLHDM4.js.map} +0 -0
  202. /package/dist/{chunk-BD7IXBWE.js.map → chunk-F564FHMQ.js.map} +0 -0
  203. /package/dist/{chunk-DFCQ6BMI.js.map → chunk-G3MBUL5M.js.map} +0 -0
  204. /package/dist/{chunk-SUTMSDQ2.js.map → chunk-GQ3KRY3B.js.map} +0 -0
  205. /package/dist/{chunk-EAUIQADY.js.map → chunk-IQQAJROD.js.map} +0 -0
  206. /package/dist/{chunk-ZHRPH52H.js.map → chunk-IZXN3WI6.js.map} +0 -0
  207. /package/dist/{chunk-NCPWXHDO.js.map → chunk-JEUFYSFQ.js.map} +0 -0
  208. /package/dist/{chunk-G6FNWRAI.js.map → chunk-JSSM7VVV.js.map} +0 -0
  209. /package/dist/{chunk-H26VDFDS.js.map → chunk-KGFSPJLD.js.map} +0 -0
  210. /package/dist/{chunk-AO5TSDKT.js.map → chunk-KMORGMCW.js.map} +0 -0
  211. /package/dist/{chunk-WQWKYAAK.js.map → chunk-NUQF5F5J.js.map} +0 -0
  212. /package/dist/{chunk-7Y3N4Y72.js.map → chunk-OHUDZRLK.js.map} +0 -0
  213. /package/dist/{chunk-GCKHSBEN.js.map → chunk-OKMTUAWO.js.map} +0 -0
  214. /package/dist/{chunk-GB2XPITA.js.map → chunk-QMY57PVW.js.map} +0 -0
  215. /package/dist/{chunk-55GMOVKW.js.map → chunk-QNDDPXFR.js.map} +0 -0
  216. /package/dist/{chunk-GXN7RRHR.js.map → chunk-QSIXNTRV.js.map} +0 -0
  217. /package/dist/{chunk-QJRQ4BRC.js.map → chunk-U22TOL5Y.js.map} +0 -0
  218. /package/dist/{chunk-NGTVREIH.js.map → chunk-U6IHLEWT.js.map} +0 -0
  219. /package/dist/{chunk-Z5YHMRLF.js.map → chunk-UUCCV3SI.js.map} +0 -0
  220. /package/dist/{chunk-ZXXFP2LA.js.map → chunk-UXMCHBOJ.js.map} +0 -0
  221. /package/dist/{chunk-VZVEP2OZ.js.map → chunk-VFAKGIDG.js.map} +0 -0
  222. /package/dist/{chunk-VQK4VHLF.js.map → chunk-YQV75FIL.js.map} +0 -0
  223. /package/dist/{cli-HO62TOM2.js.map → chunk-YUTVAMWW.js.map} +0 -0
  224. /package/dist/{config-TYXYQK3I.js.map → cli-BOMA2FMP.js.map} +0 -0
  225. /package/dist/{cli-UETKXHJN.js.map → cli-OJKFXQOM.js.map} +0 -0
  226. /package/dist/{cli-LWST5FQH.js.map → cli-PHZAO4LZ.js.map} +0 -0
  227. /package/dist/{github-ESK45CEZ.js.map → config-JJW75SBX.js.map} +0 -0
  228. /package/dist/{github-WER7JUTN.js.map → github-6VQKSB67.js.map} +0 -0
  229. /package/dist/{host-6GURH5HE.js.map → github-RBSEM7ZK.js.map} +0 -0
  230. /package/dist/{json-QR4G35KA.js.map → host-YSTYO5DX.js.map} +0 -0
  231. /package/dist/{lint-QTI7XK2A.js.map → json-PU2HLHDQ.js.map} +0 -0
  232. /package/dist/{list-JO4G3TS3.js.map → lint-KIVTHLGU.js.map} +0 -0
  233. /package/dist/{list-O2MJUP5V.js.map → list-RDEJDDJF.js.map} +0 -0
  234. /package/dist/{page-FSXDXCDD.js.map → list-SUTDWL2J.js.map} +0 -0
  235. /package/dist/{pretty-4IONWSEP.js.map → page-UMAA3NCM.js.map} +0 -0
  236. /package/dist/{pretty-R4BQD2VH.js.map → pretty-ANLRHU4O.js.map} +0 -0
  237. /package/dist/{provider-527CO4DM.js.map → pretty-Q3ZFKOR7.js.map} +0 -0
  238. /package/dist/{reporters-DHO2BXAD.js.map → provider-LBX4IXGX.js.map} +0 -0
  239. /package/dist/{release-3D5PK6M7.js.map → release-VV3UTKE5.js.map} +0 -0
  240. /package/dist/{reporters-FPP6JNDP.js.map → reporters-26H3N2KW.js.map} +0 -0
  241. /package/dist/{reporters-M6LJ2IYU.js.map → reporters-ILT36CIH.js.map} +0 -0
  242. /package/dist/{run-YH5Z7RJ7.js.map → reporters-PNDLWT6K.js.map} +0 -0
  243. /package/dist/{validate-7JI3H57P.js.map → run-QXCK33Z4.js.map} +0 -0
@@ -1,10 +1,13 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ renderFindingsGithub
4
+ } from "./chunk-QNDDPXFR.js";
2
5
  import {
3
6
  renderFindingsJson,
4
7
  renderFormatsJson,
5
8
  renderGetJson,
6
9
  renderListJson
7
- } from "./chunk-ZXXFP2LA.js";
10
+ } from "./chunk-UXMCHBOJ.js";
8
11
  import {
9
12
  renderFindingsPretty,
10
13
  renderFormatsPretty,
@@ -12,7 +15,7 @@ import {
12
15
  renderListPretty,
13
16
  renderValeWiring,
14
17
  renderWritePretty
15
- } from "./chunk-GDLHTI5R.js";
18
+ } from "./chunk-STPGIKPY.js";
16
19
  import {
17
20
  FINDING_FORMATS,
18
21
  JUNIT_CLASSNAME,
@@ -24,22 +27,25 @@ import {
24
27
  runCheck,
25
28
  summarize,
26
29
  toResults
27
- } from "./chunk-4DLF5SA4.js";
30
+ } from "./chunk-QDC7JPFG.js";
28
31
  import {
29
32
  LIST_FORMATS,
30
33
  runList
31
- } from "./chunk-VZVEP2OZ.js";
32
- import {
33
- renderFindingsGithub
34
- } from "./chunk-55GMOVKW.js";
34
+ } from "./chunk-VFAKGIDG.js";
35
35
  import {
36
+ DEFAULT_CRAWL_MIN_PAGES,
37
+ DEFAULT_FILL_CACHE_DIR,
38
+ DEFAULT_FILL_CONFIDENCE,
36
39
  DEFAULT_LANGUAGE,
37
40
  DITA_HOLDS,
38
41
  DOCBOOK_HOLDS,
39
42
  LIST_HOLDS,
40
43
  MANIFEST_FORMAT,
44
+ SKOS,
45
+ SKOS_PROPERTIES,
41
46
  TBX_V3_NAMESPACE,
42
47
  TERM_FIELDS,
48
+ TERM_MATCH_FIELDS,
43
49
  TERM_READERS,
44
50
  TERM_RULES,
45
51
  TERM_WRITE_FORMATS,
@@ -70,49 +76,70 @@ import {
70
76
  resolveTermRun,
71
77
  rstEntry,
72
78
  sharedLanguage,
79
+ slugOf,
73
80
  tbxEntryLines,
74
81
  tbxInput,
75
82
  tbxSourceOf,
76
83
  valeConfigFor,
77
84
  xmlAttribute,
78
85
  xmlText
79
- } from "./chunk-ABHG6I3G.js";
80
- import "./chunk-77AINBYM.js";
86
+ } from "./chunk-FKAZUZQU.js";
81
87
  import "./chunk-IKEWBMCN.js";
82
- import "./chunk-G6FNWRAI.js";
88
+ import "./chunk-YUTVAMWW.js";
89
+ import "./chunk-JSSM7VVV.js";
83
90
  import {
84
- registerTermLabelSource
85
- } from "./chunk-2W34HX2U.js";
91
+ DEFAULT_CHUNK_CHARS,
92
+ splitBody
93
+ } from "./chunk-PS257NIU.js";
86
94
  import {
87
- collect,
88
- readStdin,
89
- splitList
90
- } from "./chunk-KBG463UK.js";
95
+ mergeMetaProvenance
96
+ } from "./chunk-2OZF2VUB.js";
91
97
  import {
92
98
  OMITTED_WHEN_CLEAN,
93
99
  renderJunit,
94
100
  renderSarif
95
- } from "./chunk-QBVP3SQP.js";
101
+ } from "./chunk-SGR7ZAVE.js";
102
+ import "./chunk-QEAGL4V5.js";
103
+ import {
104
+ collect,
105
+ readStdin,
106
+ splitList
107
+ } from "./chunk-SMHAYK6I.js";
108
+ import "./chunk-DSWKBZWW.js";
96
109
  import {
97
110
  STDIN_TOKEN,
98
111
  extractorByName,
99
112
  extractorForExtension
100
- } from "./chunk-G7XD4QH5.js";
101
- import {
102
- fail
103
- } from "./chunk-YEUYKR62.js";
113
+ } from "./chunk-RGLFV4KO.js";
114
+ import "./chunk-77AINBYM.js";
115
+ import "./chunk-MNH7QO4Z.js";
104
116
  import {
105
117
  shouldColor
106
118
  } from "./chunk-RNVYGWIC.js";
107
- import "./chunk-MNH7QO4Z.js";
108
- import "./chunk-6M5VJOC2.js";
109
119
  import {
110
- notice
120
+ fail
121
+ } from "./chunk-YEUYKR62.js";
122
+ import "./chunk-OTJOBZJ5.js";
123
+ import {
124
+ notice,
125
+ warn
111
126
  } from "./chunk-HX44GB4Z.js";
112
- import "./chunk-QCHVR4ZM.js";
127
+ import {
128
+ DEFAULT_PROVIDER,
129
+ LOCAL_FLAG_HELP,
130
+ assertKnownProvider,
131
+ assertLocalFlag,
132
+ assertModelHasProvider,
133
+ localNotice,
134
+ noOfflineModel,
135
+ offlineIdentity,
136
+ providerSpecFor,
137
+ resolveIdentity,
138
+ selectProvider
139
+ } from "./chunk-VM7VAFJW.js";
113
140
  import {
114
141
  package_default
115
- } from "./chunk-2BV4FBC7.js";
142
+ } from "./chunk-DHGB4JBG.js";
116
143
  import "./chunk-OWBRDNRZ.js";
117
144
  import {
118
145
  errorMessage
@@ -122,6 +149,143 @@ import "./chunk-2H7UOFLK.js";
122
149
  // src/term/cli.ts
123
150
  import { Command } from "commander";
124
151
 
152
+ // src/term/commands/fill.ts
153
+ import { existsSync } from "node:fs";
154
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
155
+ import { dirname as dirname2, extname as extname2, join as join3, resolve as resolve2 } from "node:path";
156
+ import {
157
+ JsonCache,
158
+ buildCacheKey,
159
+ completeValidatedJSON,
160
+ makeProvider as makeInferenceProvider,
161
+ sha256,
162
+ validatorFor
163
+ } from "@hawkeyexl/inference";
164
+
165
+ // src/term/core/fill-plan.ts
166
+ import { dirname, extname } from "node:path";
167
+ function fold(value) {
168
+ return value.trim().toLowerCase();
169
+ }
170
+ function termIndex(terms) {
171
+ const index = /* @__PURE__ */ new Map();
172
+ const claim = (key, term) => {
173
+ if (!index.has(fold(key))) index.set(fold(key), term);
174
+ };
175
+ for (const term of terms) {
176
+ claim(term.record.label, term);
177
+ claim(term.id, term);
178
+ for (const alt of term.record["alt-labels"] ?? []) claim(alt, term);
179
+ }
180
+ return index;
181
+ }
182
+ function addUnique(list, value) {
183
+ if (!list.some((v) => fold(v) === fold(value))) list.push(value);
184
+ }
185
+ var EDGE_LISTS = { broader: "broader", narrower: "narrower", "related-concepts": "related" };
186
+ function namedConcepts(set) {
187
+ const alias = /* @__PURE__ */ new Map();
188
+ for (const block of set.blocks) {
189
+ for (const alt of block.altLabels ?? []) if (!alias.has(fold(alt))) alias.set(fold(alt), block.label);
190
+ }
191
+ const concepts = [];
192
+ const byKey = /* @__PURE__ */ new Map();
193
+ const named = (value, at2, language) => {
194
+ const label = alias.get(fold(value)) ?? value;
195
+ let concept = byKey.get(fold(label));
196
+ if (concept === void 0) {
197
+ concept = { label: label.trim(), from: [], altLabels: [], broader: [], narrower: [], related: [] };
198
+ concepts.push(concept);
199
+ byKey.set(fold(label), concept);
200
+ }
201
+ if (concept.language === void 0 && language !== void 0) concept.language = language;
202
+ if (!concept.from.some((f) => f.file === at2.file && f.line === at2.line)) concept.from.push(at2);
203
+ };
204
+ const at = (file, line) => line === void 0 ? { file } : { file, line };
205
+ for (const reference of set.references) {
206
+ named(reference.label, at(reference.file, reference.line), reference.language);
207
+ }
208
+ for (const block of set.blocks) {
209
+ for (const edge of block.edges) named(edge.value, at(block.file, edge.line ?? block.line), block.language);
210
+ }
211
+ for (const block of set.blocks) {
212
+ const concept = byKey.get(fold(block.label));
213
+ if (concept !== void 0) enrich(concept, block);
214
+ }
215
+ return concepts;
216
+ }
217
+ function enrich(concept, block) {
218
+ for (const alt of block.altLabels ?? []) if (fold(alt) !== fold(concept.label)) addUnique(concept.altLabels, alt);
219
+ for (const edge of block.edges) addUnique(concept[EDGE_LISTS[edge.field]], edge.value);
220
+ if (concept.definition === void 0 && block.definition !== void 0) concept.definition = block.definition;
221
+ }
222
+ function planFromMetadata(set) {
223
+ const index = termIndex(set.terms);
224
+ const create = namedConcepts(set).filter((concept) => !index.has(fold(concept.label)));
225
+ const carried2 = /* @__PURE__ */ new Map();
226
+ for (const block of set.blocks) {
227
+ const term = index.get(fold(block.label));
228
+ if (term !== void 0 && block.definition !== void 0 && !carried2.has(term)) carried2.set(term, block.definition);
229
+ }
230
+ const missing = set.terms.filter((t) => t.record.definition === void 0 && t.record.see === void 0).map((term) => {
231
+ const definition = carried2.get(term);
232
+ return definition === void 0 ? { term } : { term, carried: definition };
233
+ });
234
+ return { create, missing };
235
+ }
236
+ function sharedTermDirectory(terms) {
237
+ const dirs = new Set(
238
+ terms.filter((t) => t.location.construct === "page" && t.location.path !== void 0).map((t) => dirname(t.location.path ?? ""))
239
+ );
240
+ return dirs.size === 1 ? [...dirs][0] : void 0;
241
+ }
242
+ var FILL_PAGE_FORMATS = {
243
+ ".md": "markdown",
244
+ ".mdx": "mdx",
245
+ ".adoc": "asciidoc",
246
+ ".rst": "rst",
247
+ ".html": "html",
248
+ ".dita": "dita"
249
+ };
250
+ function mostCommon(extensions) {
251
+ const counts = /* @__PURE__ */ new Map();
252
+ for (const ext of extensions) if (ext in FILL_PAGE_FORMATS) counts.set(ext, (counts.get(ext) ?? 0) + 1);
253
+ let best;
254
+ for (const [ext, n] of counts) if (best === void 0 || n > (counts.get(best) ?? 0)) best = ext;
255
+ return best;
256
+ }
257
+ function pageExtension(terms, dir, pages) {
258
+ const inDir = terms.filter((t) => t.location.construct === "page" && t.location.path !== void 0).filter((t) => dirname(t.location.path ?? "") === dir).map((t) => extname(t.location.path ?? "").toLowerCase());
259
+ return mostCommon(inDir) ?? mostCommon(pages.map((p) => extname(p).toLowerCase())) ?? ".md";
260
+ }
261
+ function mergeFound(found) {
262
+ const out = [];
263
+ const byKey = /* @__PURE__ */ new Map();
264
+ for (const f of found) {
265
+ let c = byKey.get(fold(f.label));
266
+ if (c === void 0) {
267
+ c = { label: f.label.trim(), altLabels: [], from: [] };
268
+ out.push(c);
269
+ byKey.set(fold(f.label), c);
270
+ }
271
+ for (const alt of f.altLabels ?? []) if (fold(alt) !== fold(c.label)) addUnique(c.altLabels, alt);
272
+ if (c.language === void 0 && f.language !== void 0) c.language = f.language;
273
+ if (!c.from.some((at) => at.file === f.file)) c.from.push(f.line === void 0 ? { file: f.file } : { file: f.file, line: f.line });
274
+ if (f.confidence !== void 0 && (c.confidence === void 0 || f.confidence > c.confidence)) {
275
+ c.confidence = f.confidence;
276
+ if (f.definition !== void 0) c.definition = f.definition;
277
+ } else if (c.definition === void 0 && f.definition !== void 0) {
278
+ c.definition = f.definition;
279
+ }
280
+ }
281
+ return out;
282
+ }
283
+ function newCandidates(candidates, known, minPages) {
284
+ return candidates.filter(
285
+ (c) => c.from.length >= minPages && !known.has(fold(c.label)) && !c.altLabels.some((a) => known.has(fold(a)))
286
+ );
287
+ }
288
+
125
289
  // src/term/core/writers/documents.ts
126
290
  import { join } from "node:path";
127
291
 
@@ -512,92 +676,179 @@ var jsonWriter = {
512
676
  };
513
677
 
514
678
  // src/term/core/writers/skos.ts
515
- var HOLDS2 = [
516
- "label",
517
- "definition",
518
- "alt-labels",
519
- "hidden-labels",
520
- "broader",
521
- "narrower",
522
- "related-terms",
523
- "scope-note"
524
- ];
525
- var CONTEXT = {
526
- skos: "http://www.w3.org/2004/02/skos/core#",
679
+ import { DataFactory, Writer } from "n3";
680
+ var HOLDS2 = SKOS_PROPERTIES.map((p) => p.field);
681
+ var REDIRECT_HOLDS = ["label", "see"];
682
+ var RDF_TYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
683
+ var PREFIXES = {
684
+ skos: SKOS,
527
685
  dcterms: "http://purl.org/dc/terms/"
528
686
  };
529
687
  var SCHEME_ID = "";
530
- function literal(term, value) {
531
- return term.language === void 0 ? value : { "@value": value, "@language": term.language };
688
+ var DESCRIPTION = "Generated by manni term write.";
689
+ var SINGLE = /* @__PURE__ */ new Set([
690
+ "skos:inScheme",
691
+ "skos:topConceptOf",
692
+ "skos:prefLabel",
693
+ "skos:definition",
694
+ "skos:scopeNote",
695
+ "skos:notation",
696
+ "dcterms:description"
697
+ ]);
698
+ function literal(term, text) {
699
+ return term.language === void 0 ? { text } : { text, language: term.language };
532
700
  }
533
701
  function resolve(terms, self, value) {
534
702
  const wanted = value.toLowerCase();
535
- const others = terms.filter((t) => t !== self);
703
+ const others = terms.filter((t) => t.id !== self);
536
704
  return others.find((t) => t.record.label.toLowerCase() === wanted) ?? others.find((t) => t.id.toLowerCase() === wanted);
537
705
  }
538
- function references(terms, self, values) {
539
- const ids = [];
540
- for (const value of values ?? []) {
541
- const target = resolve(terms, self, value);
542
- if (target !== void 0 && !ids.includes(target.id)) ids.push(target.id);
543
- }
544
- return ids.map((id) => ({ "@id": `#${id}` }));
706
+ function sameValue(a, b) {
707
+ if ("iri" in a) return "iri" in b && a.iri === b.iri;
708
+ return !("iri" in b) && a.text === b.text && a.language === b.language;
545
709
  }
546
- function concept(terms, term) {
547
- const { record } = term;
548
- const node = {
549
- "@id": `#${term.id}`,
550
- "@type": "skos:Concept",
551
- "skos:inScheme": { "@id": SCHEME_ID },
552
- "skos:prefLabel": literal(term, record.label)
553
- };
554
- if (record["alt-labels"] !== void 0) node["skos:altLabel"] = record["alt-labels"].map((v) => literal(term, v));
555
- if (record["hidden-labels"] !== void 0) {
556
- node["skos:hiddenLabel"] = record["hidden-labels"].map((v) => literal(term, v));
557
- }
558
- if (record.definition !== void 0) node["skos:definition"] = literal(term, record.definition);
559
- if (record["scope-note"] !== void 0) node["skos:scopeNote"] = literal(term, record["scope-note"]);
560
- const relations = [
561
- ["skos:broader", record.broader],
562
- ["skos:narrower", record.narrower],
563
- ["skos:related", record["related-terms"]]
564
- ];
565
- for (const [key, values] of relations) {
566
- const refs = references(terms, term, values);
567
- if (refs.length > 0) node[key] = refs;
568
- }
569
- return node;
710
+ function pushUnique(values, value) {
711
+ if (!values.some((v) => sameValue(v, value))) values.push(value);
570
712
  }
571
- var skosWriter = {
572
- format: "skos",
573
- shapes: ["file"],
574
- holds: (_shape) => HOLDS2,
575
- render(terms, target) {
576
- requireShape("skos", target, "file");
577
- const document = {
578
- "@context": CONTEXT,
579
- "@graph": [
580
- {
581
- "@id": SCHEME_ID,
582
- "@type": "skos:ConceptScheme",
583
- "dcterms:description": "Generated by manni term write."
584
- },
585
- ...terms.map((term) => concept(terms, term))
586
- ]
713
+ function graphOf(terms) {
714
+ const redirects = /* @__PURE__ */ new Map();
715
+ for (const term of terms) {
716
+ const target = term.record.see === void 0 ? void 0 : resolve(terms, term.id, term.record.see);
717
+ if (target !== void 0) redirects.set(term, target.id);
718
+ }
719
+ const concepts = terms.filter((t) => !redirects.has(t));
720
+ const conflicts = [];
721
+ const nodes = [];
722
+ const tops = [];
723
+ for (const group of conceptGroups(concepts)) {
724
+ const [first] = group;
725
+ if (first === void 0) continue;
726
+ const { id } = first;
727
+ const values = /* @__PURE__ */ new Map();
728
+ const add = (property, value) => {
729
+ const list = values.get(property) ?? [];
730
+ pushUnique(list, value);
731
+ values.set(property, list);
587
732
  };
588
- const content = `${JSON.stringify(document, null, 2)}
733
+ for (const { property, field, kind } of SKOS_PROPERTIES) {
734
+ const name = `skos:${property}`;
735
+ if (kind === "code") {
736
+ const merged = mergeFirst(id, group.map((t) => ({ [field]: t.record[field] })));
737
+ conflicts.push(...merged.conflicts);
738
+ const text = merged.merged[field];
739
+ if (typeof text === "string") add(name, { text });
740
+ continue;
741
+ }
742
+ for (const term of group) {
743
+ const raw = term.record[field];
744
+ const list = raw === void 0 ? [] : typeof raw === "string" ? [raw] : raw;
745
+ for (const value of list) {
746
+ if (kind === "iris") add(name, { iri: value });
747
+ else if (kind === "concepts") {
748
+ const target = resolve(terms, id, value);
749
+ if (target !== void 0) add(name, { iri: `#${target.id}` });
750
+ } else add(name, literal(term, value));
751
+ }
752
+ }
753
+ if (property === "altLabel") {
754
+ for (const [redirect, target] of redirects) if (target === id) add(name, literal(redirect, redirect.record.label));
755
+ }
756
+ }
757
+ const top = !values.has("skos:broader");
758
+ if (top) tops.push({ iri: `#${id}` });
759
+ nodes.push({
760
+ id: `#${id}`,
761
+ type: "skos:Concept",
762
+ properties: [
763
+ ["skos:inScheme", [{ iri: SCHEME_ID }]],
764
+ ...top ? [["skos:topConceptOf", [{ iri: SCHEME_ID }]]] : [],
765
+ ...SKOS_PROPERTIES.flatMap(({ property }) => {
766
+ const list = values.get(`skos:${property}`);
767
+ return list === void 0 ? [] : [[`skos:${property}`, list]];
768
+ })
769
+ ]
770
+ });
771
+ }
772
+ const scheme = {
773
+ id: SCHEME_ID,
774
+ type: "skos:ConceptScheme",
775
+ properties: [["dcterms:description", [{ text: DESCRIPTION }]], ...tops.length === 0 ? [] : [["skos:hasTopConcept", tops]]]
776
+ };
777
+ const dropped = terms.flatMap((t) => droppedFields([t], redirects.has(t) ? REDIRECT_HOLDS : HOLDS2));
778
+ return { nodes: [scheme, ...nodes], dropped, conflicts };
779
+ }
780
+ function jsonValue(value) {
781
+ if ("iri" in value) return { "@id": value.iri };
782
+ return value.language === void 0 ? value.text : { "@value": value.text, "@language": value.language };
783
+ }
784
+ function jsonLd(nodes) {
785
+ const graph = nodes.map((node) => {
786
+ const out = { "@id": node.id, "@type": node.type };
787
+ for (const [property, values] of node.properties) {
788
+ const [only] = values;
789
+ out[property] = SINGLE.has(property) && values.length === 1 && only !== void 0 ? jsonValue(only) : values.map(jsonValue);
790
+ }
791
+ return out;
792
+ });
793
+ return `${JSON.stringify({ "@context": PREFIXES, "@graph": graph }, null, 2)}
589
794
  `;
590
- return {
591
- files: [{ path: target.path, content }],
592
- removals: [],
593
- dropped: droppedFields(terms, HOLDS2),
594
- skipped: []
595
- };
795
+ }
796
+ function expand(name) {
797
+ const [prefix = "", local = ""] = name.split(":");
798
+ if (!Object.hasOwn(PREFIXES, prefix)) throw new Error(`skos writer: unknown prefix "${prefix}" in ${name}`);
799
+ return `${PREFIXES[prefix]}${local}`;
800
+ }
801
+ function turtle(nodes) {
802
+ const iri = (value) => DataFactory.namedNode(value);
803
+ const writer = new Writer({ prefixes: PREFIXES });
804
+ for (const node of nodes) {
805
+ const subject = iri(node.id);
806
+ writer.addQuad(DataFactory.quad(subject, iri(RDF_TYPE), iri(expand(node.type))));
807
+ for (const [property, values] of node.properties) {
808
+ for (const value of values) {
809
+ const object = "iri" in value ? iri(value.iri) : DataFactory.literal(value.text, value.language);
810
+ writer.addQuad(DataFactory.quad(subject, iri(expand(property)), object));
811
+ }
812
+ }
596
813
  }
597
- };
814
+ let content = "";
815
+ writer.end((_error, result) => {
816
+ content = result;
817
+ });
818
+ return content;
819
+ }
820
+ function skosWriterFor(format, serialize) {
821
+ return {
822
+ format,
823
+ shapes: ["file"],
824
+ holds: (_shape) => HOLDS2,
825
+ render(terms, target) {
826
+ requireShape(format, target, "file");
827
+ const { nodes, dropped, conflicts } = graphOf(terms);
828
+ return {
829
+ files: [{ path: target.path, content: serialize(nodes) }],
830
+ removals: [],
831
+ dropped,
832
+ skipped: [],
833
+ ...conflicts.length === 0 ? {} : { conflicts }
834
+ };
835
+ }
836
+ };
837
+ }
838
+ var skosWriter = skosWriterFor("skos", jsonLd);
839
+ var skosTtlWriter = skosWriterFor("skos-ttl", turtle);
598
840
 
599
841
  // src/term/core/writers/tbx.ts
600
- var NOT_HELD = ["abstract", "broader", "narrower", "related-terms", "see", "scope-note"];
842
+ var NOT_HELD = [
843
+ "abstract",
844
+ "broader",
845
+ "narrower",
846
+ "related-terms",
847
+ "see",
848
+ "scope-note",
849
+ "notation",
850
+ ...TERM_MATCH_FIELDS
851
+ ];
601
852
  var HOLDS3 = TERM_FIELDS.filter((field) => !NOT_HELD.includes(field));
602
853
  var LINGUIST_FIELDS = ["register", "reading", "reading-note", "grammatical-number", "transfer-comments"];
603
854
  var ENTRY_INDENT = " ";
@@ -899,11 +1150,514 @@ var valeWriter = {
899
1150
  };
900
1151
 
901
1152
  // src/term/core/writers/interchange.ts
902
- var INTERCHANGE_WRITERS = [tbxWriter, tbx3Writer, skosWriter, csvWriter, jsonWriter, valeWriter];
1153
+ var INTERCHANGE_WRITERS = [tbxWriter, tbx3Writer, skosWriter, skosTtlWriter, csvWriter, jsonWriter, valeWriter];
903
1154
 
904
1155
  // src/term/core/writers/index.ts
905
1156
  var TERM_WRITERS = [...DOCUMENT_WRITERS, ...INTERCHANGE_WRITERS];
906
1157
 
1158
+ // src/term/commands/fill.ts
1159
+ var FILL_FORMATS = ["pretty", "json"];
1160
+ var TURN_BUDGET_REASON = "turn budget";
1161
+ var PROMPT_VERSION = 1;
1162
+ var META_PROVENANCE_KEY = "meta-provenance";
1163
+ var DEFINITION_SYSTEM = [
1164
+ "You write glossary definitions for a documentation set's termbase.",
1165
+ "Define the term in one sentence, as the pages quoted use it.",
1166
+ "Give your confidence, from 0 to 1, that the definition is right for these pages.",
1167
+ "When the context is too thin to be sure, say so with a low confidence rather than guessing."
1168
+ ].join(" ");
1169
+ var DEFINITION_SCHEMA = {
1170
+ type: "object",
1171
+ additionalProperties: false,
1172
+ required: ["definition", "confidence"],
1173
+ properties: { definition: { type: "string" }, confidence: { type: "number" } }
1174
+ };
1175
+ var CRAWL_SYSTEM = [
1176
+ "You find the domain terms a documentation page uses: product concepts, technical terms and jargon a glossary should define.",
1177
+ "Leave out everyday words, people, and code identifiers.",
1178
+ "For each term give its label in singular form, any synonyms the page uses, a one-sentence definition from the page's context,",
1179
+ "and your confidence, from 0 to 1, that it belongs in a glossary and that the definition is right."
1180
+ ].join(" ");
1181
+ var CRAWL_SCHEMA = {
1182
+ type: "object",
1183
+ additionalProperties: false,
1184
+ required: ["terms"],
1185
+ properties: {
1186
+ terms: {
1187
+ type: "array",
1188
+ items: {
1189
+ type: "object",
1190
+ additionalProperties: false,
1191
+ required: ["label", "alt-labels", "definition", "confidence"],
1192
+ properties: {
1193
+ label: { type: "string" },
1194
+ "alt-labels": { type: "array", items: { type: "string" } },
1195
+ definition: { type: "string" },
1196
+ confidence: { type: "number" }
1197
+ }
1198
+ }
1199
+ }
1200
+ }
1201
+ };
1202
+ var validateDefinition = validatorFor(DEFINITION_SCHEMA);
1203
+ var validateCrawl = validatorFor(CRAWL_SCHEMA);
1204
+ function score(value) {
1205
+ return typeof value === "number" && value >= 0 && value <= 1 ? Math.round(value * 100) / 100 : 0;
1206
+ }
1207
+ function nonEmpty(value) {
1208
+ return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
1209
+ }
1210
+ function strings(value) {
1211
+ return Array.isArray(value) ? value.map(nonEmpty).filter((v) => v !== void 0) : [];
1212
+ }
1213
+ function keywordsOf(value) {
1214
+ return typeof value === "string" ? strings([value]) : strings(value);
1215
+ }
1216
+ function wholeWord(label) {
1217
+ const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1218
+ return new RegExp(`(?<![\\p{L}\\p{N}])${escaped}(?![\\p{L}\\p{N}])`, "iu");
1219
+ }
1220
+ function lineOf(content, label) {
1221
+ const match = wholeWord(label).exec(content);
1222
+ return match === null ? void 0 : content.slice(0, match.index).split("\n").length;
1223
+ }
1224
+ function fromList(from, cwd) {
1225
+ return from.map((at) => {
1226
+ const file = displayPath(at.file, cwd);
1227
+ return at.line === void 0 ? file : `${file}:${String(at.line)}`;
1228
+ });
1229
+ }
1230
+ var toTermError = (message) => new TermError(message);
1231
+ async function resolveModel(opts, run) {
1232
+ const injected = (provider) => ({
1233
+ provider,
1234
+ identity: { provider: provider.provider(), model: provider.modelName() }
1235
+ });
1236
+ const offline = opts.offline === true;
1237
+ if (opts.providerInstance !== void 0 && !offline) return injected(opts.providerInstance);
1238
+ const flags = {
1239
+ ...opts.provider === void 0 ? {} : { provider: opts.provider },
1240
+ ...opts.model === void 0 ? {} : { model: opts.model },
1241
+ ...opts.local === true ? { local: true } : {},
1242
+ ...offline ? { offline: true } : {}
1243
+ };
1244
+ assertLocalFlag(flags, toTermError);
1245
+ const family = run.configFile?.providers ?? {};
1246
+ const selection = selectProvider(flags, [
1247
+ {
1248
+ ...run.config?.provider === void 0 ? {} : { provider: run.config.provider },
1249
+ ...run.config?.model === void 0 ? {} : { model: run.config.model },
1250
+ origin: "term.provider"
1251
+ },
1252
+ {
1253
+ ...family.provider === void 0 ? {} : { provider: family.provider },
1254
+ ...family.model === void 0 ? {} : { model: family.model },
1255
+ origin: "providers.provider"
1256
+ }
1257
+ ]);
1258
+ const { provider: name, model: chosen } = selection;
1259
+ assertKnownProvider(name, toTermError);
1260
+ assertModelHasProvider(name, chosen, "term.provider", toTermError);
1261
+ const named = [flags.provider, flags.model, run.config?.provider, run.config?.model, family.provider, family.model].some(
1262
+ (value) => value !== void 0 && value !== DEFAULT_PROVIDER
1263
+ );
1264
+ const notice2 = localNotice(selection, flags);
1265
+ if (notice2 !== void 0) opts.onNotice?.(notice2);
1266
+ try {
1267
+ const spec = providerSpecFor(family, { provider: name, model: chosen ?? null });
1268
+ const identity = offline ? await offlineIdentity(spec, toTermError) : await resolveIdentity(spec, toTermError);
1269
+ if (identity === void 0) return void 0;
1270
+ if (opts.providerInstance !== void 0) return injected(opts.providerInstance);
1271
+ return { provider: makeInferenceProvider(providerSpecFor(family, identity)), identity };
1272
+ } catch (error) {
1273
+ if (named) opts.onNotice?.(`the configured provider "${name}" could not run: ${errorMessage(error)}`);
1274
+ return void 0;
1275
+ }
1276
+ }
1277
+ async function runFill(opts) {
1278
+ const cwd = resolve2(opts.cwd ?? process.cwd());
1279
+ const run = await resolveTermRun({
1280
+ cwd,
1281
+ inputs: opts.inputs,
1282
+ ...opts.configPath === void 0 ? {} : { configPath: opts.configPath },
1283
+ ...opts.collection === void 0 ? {} : { collection: opts.collection }
1284
+ });
1285
+ const pages = [];
1286
+ const onPage = (input) => {
1287
+ const language = input.metadata["language"];
1288
+ const keywordsLine = input.lineFor("/keywords");
1289
+ pages.push({
1290
+ file: input.file,
1291
+ ...input.path === void 0 ? {} : { path: input.path },
1292
+ content: input.content,
1293
+ metadata: input.metadata,
1294
+ ...typeof language === "string" && language !== "" ? { language } : {},
1295
+ ...keywordsLine === void 0 ? {} : { keywordsLine }
1296
+ });
1297
+ };
1298
+ const set = await loadSet(run, { ...opts, cwd, allowEmpty: true, onPage });
1299
+ const fillConfig = run.config?.fill ?? {};
1300
+ const configDir = run.configDir ?? cwd;
1301
+ const threshold = opts.confidence ?? fillConfig.confidenceThreshold ?? DEFAULT_FILL_CONFIDENCE;
1302
+ const maxTurns = opts.maxTurns ?? fillConfig.maxTurns ?? null;
1303
+ const minPages = fillConfig.crawl?.minPages ?? DEFAULT_CRAWL_MIN_PAGES;
1304
+ const chunkChars = opts.chunkChars ?? DEFAULT_CHUNK_CHARS;
1305
+ const crawl = opts.crawl === true;
1306
+ const dryRun = opts.dryRun === true;
1307
+ const plan = planFromMetadata(set);
1308
+ const needsDir = crawl || plan.create.length > 0;
1309
+ const outDir = !needsDir ? void 0 : opts.out !== void 0 ? resolve2(cwd, opts.out) : fillConfig.out !== void 0 ? resolve2(configDir, fillConfig.out) : sharedTermDirectory(set.terms);
1310
+ if (needsDir && outDir === void 0) {
1311
+ throw new TermError("new term pages need a directory; pass -o or set term.fill.out.");
1312
+ }
1313
+ const ext = outDir === void 0 ? ".md" : pageExtension(set.terms, outDir, pages.map((p) => p.file));
1314
+ const format = FILL_PAGE_FORMATS[ext] ?? "markdown";
1315
+ const wantsModel = crawl || plan.create.some((c) => c.definition === void 0) || plan.missing.some((m) => m.carried === void 0);
1316
+ let model;
1317
+ if (wantsModel) {
1318
+ model = await resolveModel(opts, run);
1319
+ if (model === void 0) {
1320
+ if (crawl) {
1321
+ throw new TermError(
1322
+ opts.offline === true ? "--crawl needs a model, and none is available offline; drop --offline, or download a local model first." : "--crawl needs a model, and no provider is configured; pass --provider or set providers:."
1323
+ );
1324
+ }
1325
+ warn(
1326
+ opts.offline === true ? noOfflineModel("new terms have no definition") : "no model provider is configured, so new terms have no definition; pass --provider or --local."
1327
+ );
1328
+ }
1329
+ }
1330
+ const modelName = model === void 0 ? void 0 : `${model.identity.provider}/${model.identity.model}`;
1331
+ const cache = new JsonCache(
1332
+ resolve2(configDir, fillConfig.cacheDir ?? DEFAULT_FILL_CACHE_DIR),
1333
+ opts.noCache !== true,
1334
+ "manni"
1335
+ );
1336
+ let turns = 0;
1337
+ const ask = async (m, kind, system, user, schema, validate) => {
1338
+ const key = buildCacheKey([m.identity.provider, m.identity.model, `v${String(PROMPT_VERSION)}`, kind, sha256(user)]);
1339
+ const cached = cache.get(key);
1340
+ if (cached !== void 0 && validate(cached)) return cached;
1341
+ if (maxTurns !== null && turns >= maxTurns) return void 0;
1342
+ turns++;
1343
+ const answer = await completeValidatedJSON({ provider: m.provider, system, user, schema, validate });
1344
+ if (answer.result === void 0) throw new TermError(answer.error ?? "the model returned no answer.");
1345
+ cache.set(key, answer.result);
1346
+ return answer.result;
1347
+ };
1348
+ const pageByFile = new Map(pages.map((p) => [p.file, p]));
1349
+ const definitionPrompt = (label, language, record, from) => {
1350
+ const lines = [`Term: ${label}`];
1351
+ if (language !== void 0) lines.push(`Language: ${language}`);
1352
+ const lists = [
1353
+ ["Also called", record["alt-labels"]],
1354
+ ["Broader", record.broader],
1355
+ ["Narrower", record.narrower],
1356
+ ["Related", record["related-terms"]]
1357
+ ];
1358
+ for (const [name, values] of lists) if (values !== void 0 && values.length > 0) lines.push(`${name}: ${values.join(", ")}`);
1359
+ const files = [...new Set(from.map((f) => f.file))].slice(0, 3);
1360
+ for (const file of files) {
1361
+ const page = pageByFile.get(file);
1362
+ if (page === void 0) continue;
1363
+ lines.push("", `Page ${file}`);
1364
+ for (const key of ["title", "description"]) {
1365
+ const value = nonEmpty(page.metadata[key]);
1366
+ if (value !== void 0) lines.push(`${key}: ${value}`);
1367
+ }
1368
+ const word = wholeWord(label);
1369
+ const uses = page.content.split("\n").filter((line) => word.test(line)).slice(0, 3);
1370
+ for (const use of uses) lines.push(`> ${use.trim()}`);
1371
+ }
1372
+ return lines.join("\n");
1373
+ };
1374
+ const draft = async (label, language, record, from) => {
1375
+ if (model === void 0) return void 0;
1376
+ let answer;
1377
+ try {
1378
+ answer = await ask(model, "definition", DEFINITION_SYSTEM, definitionPrompt(label, language, record, from), DEFINITION_SCHEMA, validateDefinition);
1379
+ } catch (error) {
1380
+ return { skip: `model error: ${errorMessage(error)}` };
1381
+ }
1382
+ if (answer === void 0) return { skip: TURN_BUDGET_REASON };
1383
+ const definition = nonEmpty(answer["definition"]);
1384
+ const confidence = score(answer["confidence"]);
1385
+ if (definition === void 0) return { skip: "the model gave no definition" };
1386
+ return { status: confidence >= threshold ? "drafted" : "below-threshold", definition, confidence };
1387
+ };
1388
+ const entries2 = [];
1389
+ const writes = [];
1390
+ const planned = /* @__PURE__ */ new Set();
1391
+ const known = new Set(termIndex(set.terms).keys());
1392
+ const render = (term, provenance) => {
1393
+ const writer = TERM_WRITERS.find((w) => w.format === format);
1394
+ const target = { path: outDir ?? cwd, shape: "directory" };
1395
+ const content = writer?.render([term], target, { existing: /* @__PURE__ */ new Map() }).files[0]?.content;
1396
+ if (content === void 0) throw new TermError(`manni cannot write a ${format} term page.`);
1397
+ if (provenance === void 0 || model === void 0) return content;
1398
+ const merged = mergeMetaProvenance(
1399
+ void 0,
1400
+ model.identity.model,
1401
+ "fields",
1402
+ provenance.fields.map((name) => ({ name, confidence: provenance.confidence }))
1403
+ );
1404
+ const extractor = extractorForExtension(ext);
1405
+ if (merged === void 0 || extractor?.apply === void 0) return content;
1406
+ return extractor.apply(content, { [META_PROVENANCE_KEY]: merged.list }, { filePath: join3(target.path, `x${ext}`) });
1407
+ };
1408
+ const create = async (concept, source, definition) => {
1409
+ const id = slugOf(concept.label);
1410
+ const path = join3(outDir ?? cwd, `${id}${ext}`);
1411
+ const base = {
1412
+ file: displayPath(path, cwd),
1413
+ id,
1414
+ label: concept.label,
1415
+ ...concept.language === void 0 ? {} : { language: concept.language },
1416
+ source,
1417
+ from: fromList(concept.from, cwd)
1418
+ };
1419
+ if (planned.has(path) || existsSync(path)) {
1420
+ entries2.push({ action: "exists", ...base, definition: { status: "missing" } });
1421
+ return;
1422
+ }
1423
+ const record = { label: concept.label };
1424
+ const lists = [
1425
+ ["alt-labels", concept.altLabels],
1426
+ ["broader", concept.broader],
1427
+ ["narrower", concept.narrower],
1428
+ ["related-terms", concept.related]
1429
+ ];
1430
+ for (const [field, values] of lists) if (values !== void 0 && values.length > 0) record[field] = values;
1431
+ let status = "missing";
1432
+ let confidence;
1433
+ let fields;
1434
+ if (definition.carried !== void 0) {
1435
+ record.definition = definition.carried;
1436
+ status = "carried";
1437
+ } else {
1438
+ const got = definition.drafted ?? await draft(concept.label, concept.language, record, concept.from);
1439
+ if (got !== void 0 && "skip" in got) {
1440
+ entries2.push({ action: "skip", ...base, definition: { status: "missing" }, reason: got.skip });
1441
+ return;
1442
+ }
1443
+ if (got !== void 0) {
1444
+ confidence = got.confidence;
1445
+ const below = "status" in got ? got.status === "below-threshold" : got.confidence < threshold;
1446
+ if (below) {
1447
+ status = "below-threshold";
1448
+ } else {
1449
+ record.definition = got.definition;
1450
+ status = "drafted";
1451
+ fields = definition.fields ?? ["/definition"];
1452
+ }
1453
+ }
1454
+ }
1455
+ const term = {
1456
+ id,
1457
+ record,
1458
+ ...concept.language === void 0 ? {} : { language: concept.language },
1459
+ location: { file: base.file, path, construct: "page", line: 1, fieldLines: {} }
1460
+ };
1461
+ planned.add(path);
1462
+ known.add(fold(concept.label));
1463
+ for (const alt of concept.altLabels) known.add(fold(alt));
1464
+ writes.push({ path, content: render(term, fields === void 0 || confidence === void 0 ? void 0 : { fields, confidence }) });
1465
+ entries2.push({
1466
+ action: "create",
1467
+ ...base,
1468
+ definition: {
1469
+ status,
1470
+ ...confidence === void 0 ? {} : { confidence },
1471
+ ...modelName === void 0 || confidence === void 0 ? {} : { model: modelName }
1472
+ }
1473
+ });
1474
+ };
1475
+ for (const concept of plan.create) {
1476
+ await create(concept, "metadata", concept.definition === void 0 ? {} : { carried: concept.definition });
1477
+ }
1478
+ for (const { term, carried: carried2 } of plan.missing) {
1479
+ if (carried2 === void 0 && model === void 0) continue;
1480
+ const path = term.location.path;
1481
+ const base = {
1482
+ file: displayPath(term.location.file, cwd),
1483
+ id: term.id,
1484
+ label: term.record.label,
1485
+ ...term.language === void 0 ? {} : { language: term.language },
1486
+ source: "metadata",
1487
+ from: [`${displayPath(term.location.file, cwd)}:${String(term.location.line)}`]
1488
+ };
1489
+ if (term.location.construct !== "page" || path === void 0) {
1490
+ entries2.push({ action: "skip", ...base, definition: { status: "missing" }, reason: "not a term page" });
1491
+ continue;
1492
+ }
1493
+ let definition;
1494
+ let provenance;
1495
+ if (carried2 !== void 0) {
1496
+ definition = carried2;
1497
+ } else {
1498
+ const got = await draft(term.record.label, term.language, term.record, [{ file: term.location.file }]);
1499
+ if (got === void 0) continue;
1500
+ if ("skip" in got) {
1501
+ entries2.push({ action: "skip", ...base, definition: { status: "missing" }, reason: got.skip });
1502
+ continue;
1503
+ }
1504
+ if (got.status === "below-threshold") {
1505
+ entries2.push({
1506
+ action: "skip",
1507
+ ...base,
1508
+ definition: { status: "below-threshold", confidence: got.confidence, ...modelName === void 0 ? {} : { model: modelName } }
1509
+ });
1510
+ continue;
1511
+ }
1512
+ definition = got.definition;
1513
+ provenance = { confidence: got.confidence };
1514
+ }
1515
+ writes.push({ path, content: await fillInPlace(path, term.location.file, definition, provenance, model) });
1516
+ entries2.push({
1517
+ action: "fill",
1518
+ ...base,
1519
+ definition: provenance === void 0 ? { status: "carried" } : { status: "drafted", confidence: provenance.confidence, ...modelName === void 0 ? {} : { model: modelName } }
1520
+ });
1521
+ }
1522
+ if (crawl && model !== void 0) {
1523
+ const found = [];
1524
+ let spent = false;
1525
+ for (const page of pages) {
1526
+ const type = page.metadata["type"];
1527
+ if (type === "term" || type === "term-set") continue;
1528
+ for (const keyword of keywordsOf(page.metadata["keywords"])) {
1529
+ found.push({
1530
+ file: page.file,
1531
+ label: keyword,
1532
+ ...page.keywordsLine === void 0 ? {} : { line: page.keywordsLine },
1533
+ ...page.language === void 0 ? {} : { language: page.language }
1534
+ });
1535
+ }
1536
+ if (spent) continue;
1537
+ const chunks = splitBody(page.content, chunkChars);
1538
+ for (const [i, chunk] of chunks.entries()) {
1539
+ const user = `Page ${page.file}${chunks.length > 1 ? ` (part ${String(i + 1)} of ${String(chunks.length)})` : ""}
1540
+
1541
+ ${chunk}`;
1542
+ let answer;
1543
+ try {
1544
+ answer = await ask(model, "crawl", CRAWL_SYSTEM, user, CRAWL_SCHEMA, validateCrawl);
1545
+ } catch (error) {
1546
+ opts.onNotice?.(`${page.file}: the model could not read it: ${errorMessage(error)}`);
1547
+ continue;
1548
+ }
1549
+ if (answer === void 0) {
1550
+ spent = true;
1551
+ opts.onNotice?.(`--max-turns reached (${String(maxTurns)}); some pages were not crawled.`);
1552
+ break;
1553
+ }
1554
+ const terms = Array.isArray(answer["terms"]) ? answer["terms"] : [];
1555
+ for (const item of terms) {
1556
+ if (typeof item !== "object" || item === null) continue;
1557
+ const t = item;
1558
+ const label = nonEmpty(t["label"]);
1559
+ if (label === void 0) continue;
1560
+ const definition = nonEmpty(t["definition"]);
1561
+ const line = lineOf(page.content, label);
1562
+ found.push({
1563
+ file: page.file,
1564
+ label,
1565
+ altLabels: strings(t["alt-labels"]),
1566
+ ...definition === void 0 ? {} : { definition },
1567
+ confidence: score(t["confidence"]),
1568
+ ...line === void 0 ? {} : { line },
1569
+ ...page.language === void 0 ? {} : { language: page.language }
1570
+ });
1571
+ }
1572
+ }
1573
+ }
1574
+ for (const candidate of newCandidates(mergeFound(found), known, minPages)) {
1575
+ const concept = { label: candidate.label, from: candidate.from, altLabels: candidate.altLabels, ...candidate.language === void 0 ? {} : { language: candidate.language } };
1576
+ const fields = ["/label", ...candidate.altLabels.length > 0 ? ["/alt-labels"] : [], "/definition"];
1577
+ if (candidate.confidence === void 0 || candidate.definition === void 0) {
1578
+ const got = await draft(candidate.label, candidate.language, {}, candidate.from);
1579
+ if (got === void 0 || "skip" in got || got.status === "below-threshold") {
1580
+ entries2.push({
1581
+ action: "skip",
1582
+ file: displayPath(join3(outDir ?? cwd, `${slugOf(candidate.label)}${ext}`), cwd),
1583
+ id: slugOf(candidate.label),
1584
+ label: candidate.label,
1585
+ ...candidate.language === void 0 ? {} : { language: candidate.language },
1586
+ source: "crawl",
1587
+ from: fromList(candidate.from, cwd),
1588
+ ...got !== void 0 && "skip" in got ? { definition: { status: "missing" }, reason: got.skip } : {
1589
+ definition: {
1590
+ status: "below-threshold",
1591
+ ...got === void 0 ? {} : { confidence: got.confidence },
1592
+ ...modelName === void 0 ? {} : { model: modelName }
1593
+ }
1594
+ }
1595
+ });
1596
+ continue;
1597
+ }
1598
+ await create(concept, "crawl", { drafted: got, fields });
1599
+ continue;
1600
+ }
1601
+ if (candidate.confidence < threshold) {
1602
+ entries2.push({
1603
+ action: "skip",
1604
+ file: displayPath(join3(outDir ?? cwd, `${slugOf(candidate.label)}${ext}`), cwd),
1605
+ id: slugOf(candidate.label),
1606
+ label: candidate.label,
1607
+ ...candidate.language === void 0 ? {} : { language: candidate.language },
1608
+ source: "crawl",
1609
+ from: fromList(candidate.from, cwd),
1610
+ definition: { status: "below-threshold", confidence: candidate.confidence, ...modelName === void 0 ? {} : { model: modelName } }
1611
+ });
1612
+ continue;
1613
+ }
1614
+ await create(concept, "crawl", { drafted: { definition: candidate.definition, confidence: candidate.confidence }, fields });
1615
+ }
1616
+ }
1617
+ if (!dryRun) {
1618
+ for (const { path, content } of writes) {
1619
+ await mkdir(dirname2(path), { recursive: true });
1620
+ await writeFile(path, content, "utf8");
1621
+ }
1622
+ }
1623
+ const count = (action) => entries2.filter((e) => e.action === action).length;
1624
+ return {
1625
+ entries: entries2,
1626
+ summary: {
1627
+ created: count("create"),
1628
+ filled: count("fill"),
1629
+ skipped: count("skip"),
1630
+ withoutDefinition: entries2.filter(
1631
+ (e) => (e.action === "create" || e.action === "skip") && e.definition.status !== "drafted" && e.definition.status !== "carried"
1632
+ ).length,
1633
+ turns
1634
+ },
1635
+ dryRun,
1636
+ threshold
1637
+ };
1638
+ }
1639
+ async function fillInPlace(path, file, definition, provenance, model) {
1640
+ let content;
1641
+ try {
1642
+ content = await readFile(path, "utf8");
1643
+ } catch (error) {
1644
+ throw new TermError(`${file}: could not be read: ${errorMessage(error)}`);
1645
+ }
1646
+ const extractor = extractorForExtension(extname2(path)) ?? extractorByName("markdown");
1647
+ if (extractor?.apply === void 0) throw new TermError(`${file}: manni cannot write its metadata.`);
1648
+ const patch = { definition };
1649
+ if (provenance !== void 0 && model !== void 0) {
1650
+ const held = extractor.extract(content, path).data[META_PROVENANCE_KEY];
1651
+ const merged = mergeMetaProvenance(held, model.identity.model, "fields", [{ name: "/definition", confidence: provenance.confidence }]);
1652
+ if (merged !== void 0) patch[META_PROVENANCE_KEY] = merged.list;
1653
+ }
1654
+ try {
1655
+ return extractor.apply(content, patch, { filePath: path });
1656
+ } catch (error) {
1657
+ throw new TermError(`${file}: ${errorMessage(error)}`);
1658
+ }
1659
+ }
1660
+
907
1661
  // src/term/commands/formats.ts
908
1662
  var FORMATS_FORMATS = ["pretty", "json"];
909
1663
  var DOCUMENT_RENDERS = {
@@ -919,12 +1673,14 @@ var INTERCHANGE_LABELS = {
919
1673
  tbx: "TBX v2",
920
1674
  tbx3: "TBX v3",
921
1675
  skos: "JSON-LD",
1676
+ "skos-ttl": "Turtle",
922
1677
  vale: "style"
923
1678
  };
924
1679
  function rendered(writers, format, construct) {
925
1680
  return writers.some((writer) => {
926
1681
  const render = DOCUMENT_RENDERS[writer.format];
927
- if (render?.input !== format) return false;
1682
+ if (render === void 0) return writer.format === format;
1683
+ if (render.input !== format) return false;
928
1684
  return writer.shapes.some((shape) => render.shapes[shape] === construct);
929
1685
  });
930
1686
  }
@@ -998,9 +1754,9 @@ async function runGet(opts) {
998
1754
  }
999
1755
 
1000
1756
  // src/term/core/lint.ts
1001
- import { mkdtemp, rm, writeFile } from "node:fs/promises";
1757
+ import { mkdtemp, rm, writeFile as writeFile2 } from "node:fs/promises";
1002
1758
  import { tmpdir } from "node:os";
1003
- import { join as join3 } from "node:path";
1759
+ import { join as join4 } from "node:path";
1004
1760
 
1005
1761
  // src/term/core/vale.ts
1006
1762
  import { execFile } from "node:child_process";
@@ -1188,9 +1944,9 @@ async function lintTermSet(set, opts = {}) {
1188
1944
  }
1189
1945
  if (files.length === 0) return [];
1190
1946
  const runVale = opts.runVale ?? runValeJson;
1191
- const dir = await mkdtemp(join3(tmpdir(), "manni-term-lint-"));
1947
+ const dir = await mkdtemp(join4(tmpdir(), "manni-term-lint-"));
1192
1948
  try {
1193
- for (const file of files) await writeFile(join3(dir, file.name), file.content, "utf8");
1949
+ for (const file of files) await writeFile2(join4(dir, file.name), file.content, "utf8");
1194
1950
  const alerts = await runVale([dir], { config: opts.valeConfig, cwd: opts.cwd });
1195
1951
  const findings = [];
1196
1952
  for (const [path, list] of Object.entries(alerts)) {
@@ -1240,9 +1996,9 @@ async function runLint(opts) {
1240
1996
  }
1241
1997
 
1242
1998
  // src/term/commands/write.ts
1243
- import { existsSync, statSync } from "node:fs";
1244
- import { lstat, mkdir, readdir, readFile, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
1245
- import { dirname, extname, join as join4, resolve as resolve2 } from "node:path";
1999
+ import { existsSync as existsSync2, statSync } from "node:fs";
2000
+ import { lstat, mkdir as mkdir2, readdir, readFile as readFile2, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
2001
+ import { dirname as dirname3, extname as extname3, join as join5, resolve as resolve3 } from "node:path";
1246
2002
  var SUGGESTED_SECTION = "*.md";
1247
2003
  var STYLE2 = "Terms";
1248
2004
  function writeFormats(writers = TERM_WRITERS) {
@@ -1264,11 +2020,11 @@ async function filesUnder(dir, into) {
1264
2020
  return;
1265
2021
  }
1266
2022
  for (const entry of entries2) {
1267
- const path = join4(dir, entry.name);
2023
+ const path = join5(dir, entry.name);
1268
2024
  if (entry.isDirectory()) await filesUnder(path, into);
1269
2025
  else if (entry.isFile()) {
1270
2026
  const { size } = await lstat(path);
1271
- into.set(path, size > MAX_EXISTING_FILE_BYTES ? "" : await readFile(path, "utf8"));
2027
+ into.set(path, size > MAX_EXISTING_FILE_BYTES ? "" : await readFile2(path, "utf8"));
1272
2028
  }
1273
2029
  }
1274
2030
  }
@@ -1276,8 +2032,8 @@ async function existingFor(target) {
1276
2032
  const existing = /* @__PURE__ */ new Map();
1277
2033
  if (target.shape === "directory") {
1278
2034
  await filesUnder(target.path, existing);
1279
- } else if (existsSync(target.path) && !isDirectory(target.path)) {
1280
- existing.set(target.path, await readFile(target.path, "utf8"));
2035
+ } else if (existsSync2(target.path) && !isDirectory(target.path)) {
2036
+ existing.set(target.path, await readFile2(target.path, "utf8"));
1281
2037
  }
1282
2038
  return existing;
1283
2039
  }
@@ -1296,23 +2052,23 @@ function droppedFrom(format, shape, readers) {
1296
2052
  async function applyChanges(files, removals, existing, cwd, write) {
1297
2053
  const changes = [];
1298
2054
  for (const file of files) {
1299
- const before = existing.get(file.path) ?? (existsSync(file.path) ? await readFile(file.path, "utf8") : void 0);
2055
+ const before = existing.get(file.path) ?? (existsSync2(file.path) ? await readFile2(file.path, "utf8") : void 0);
1300
2056
  if (before === file.content) continue;
1301
2057
  changes.push({ path: displayPath(file.path, cwd), action: before === void 0 ? "create" : "change" });
1302
2058
  if (write) {
1303
- await mkdir(dirname(file.path), { recursive: true });
1304
- await writeFile2(file.path, file.content, "utf8");
2059
+ await mkdir2(dirname3(file.path), { recursive: true });
2060
+ await writeFile3(file.path, file.content, "utf8");
1305
2061
  }
1306
2062
  }
1307
2063
  for (const path of removals) {
1308
- if (!existsSync(path)) continue;
2064
+ if (!existsSync2(path)) continue;
1309
2065
  changes.push({ path: displayPath(path, cwd), action: "remove" });
1310
2066
  if (write) await rm2(path, { force: true });
1311
2067
  }
1312
2068
  return changes;
1313
2069
  }
1314
2070
  async function runWrite(opts) {
1315
- const cwd = resolve2(opts.cwd ?? process.cwd());
2071
+ const cwd = resolve3(opts.cwd ?? process.cwd());
1316
2072
  const writers = opts.writers ?? TERM_WRITERS;
1317
2073
  const readers = opts.readers ?? TERM_READERS;
1318
2074
  const check = opts.check === true;
@@ -1340,19 +2096,19 @@ async function runWrite(opts) {
1340
2096
  "Vale found no config file. Set tools.vale.config in manni.config.yaml, or pass -o <styles directory>."
1341
2097
  );
1342
2098
  }
1343
- targetPath = resolve2(cwd, resolved.stylesPath);
2099
+ targetPath = resolve3(cwd, resolved.stylesPath);
1344
2100
  if (!Object.values(resolved.baseStyles).some((styles) => styles.includes(STYLE2))) {
1345
2101
  const first = Object.entries(resolved.baseStyles)[0];
1346
2102
  const [section, styles] = first ?? [SUGGESTED_SECTION, []];
1347
2103
  wiring = {
1348
- rootIni: displayPath(resolve2(cwd, resolved.rootIni), cwd),
2104
+ rootIni: displayPath(resolve3(cwd, resolved.rootIni), cwd),
1349
2105
  section,
1350
2106
  styles: [...styles, STYLE2],
1351
2107
  addSection: first === void 0
1352
2108
  };
1353
2109
  }
1354
2110
  } else {
1355
- targetPath = resolve2(cwd, opts.out);
2111
+ targetPath = resolve3(cwd, opts.out);
1356
2112
  }
1357
2113
  const shape = format === "vale" || /[\\/]$/.test(opts.out ?? "") || isDirectory(targetPath) ? "directory" : "file";
1358
2114
  const target = { path: targetPath, shape };
@@ -1365,7 +2121,7 @@ async function runWrite(opts) {
1365
2121
  throw error;
1366
2122
  }
1367
2123
  const changes = await applyChanges(render.files, render.removals, existing, cwd, !check && !dryRun);
1368
- const shown = format === "vale" ? displayPath(join4(targetPath, STYLE2), cwd) : opts.out ?? displayPath(targetPath, cwd);
2124
+ const shown = format === "vale" ? displayPath(join5(targetPath, STYLE2), cwd) : opts.out ?? displayPath(targetPath, cwd);
1369
2125
  return {
1370
2126
  mode: "render",
1371
2127
  format,
@@ -1392,7 +2148,7 @@ function inputFor(content, path, construct, file) {
1392
2148
  return { content, file, path, format: MANIFEST_FORMAT, metadata: {}, lineFor: () => void 0 };
1393
2149
  }
1394
2150
  if (construct === "tbx-entry") return tbxInput(content, file, path);
1395
- const extractor = extractorForExtension(extname(path));
2151
+ const extractor = extractorForExtension(extname3(path));
1396
2152
  if (extractor === void 0) throw new TermError(`${file}: no reader for its extension.`);
1397
2153
  return extractInput(content, file, path, extractor.name);
1398
2154
  }
@@ -1425,6 +2181,11 @@ async function writeInPlace(opts, check, dryRun) {
1425
2181
  if (path === void 0) {
1426
2182
  throw new TermError(`${term.location.file} has nowhere to write back to. Pass -f <format> -o <path>.`);
1427
2183
  }
2184
+ if (construct === "skos") {
2185
+ throw new TermError(
2186
+ `${displayPath(term.location.file, cwd)} is SKOS and is not rewritten in place; render it with -f skos or -f skos-ttl.`
2187
+ );
2188
+ }
1428
2189
  const reader = readerForConstruct(construct, readers);
1429
2190
  if (reader?.apply === void 0) {
1430
2191
  const name = reader?.label ?? construct;
@@ -1442,7 +2203,7 @@ async function writeInPlace(opts, check, dryRun) {
1442
2203
  for (const [path, { file, constructs }] of byPath) {
1443
2204
  let original;
1444
2205
  try {
1445
- original = await readFile(path, "utf8");
2206
+ original = await readFile2(path, "utf8");
1446
2207
  } catch (error) {
1447
2208
  throw new TermError(`${file}: could not be read: ${errorMessage(error)}`);
1448
2209
  }
@@ -1486,16 +2247,28 @@ function renderListCsv(terms) {
1486
2247
  var INFORMATION_URI = "https://hawkeyexl.github.io/manni/term/";
1487
2248
  var RULES_URI = "https://hawkeyexl.github.io/manni/term/reference/rules/";
1488
2249
  var RULE_DESCRIPTIONS = {
1489
- "undefined-term": "A page's concepts: names a label no entry claims as its preferred label.",
2250
+ "undefined-term": "A page's concepts: names no entry, by label, id or alt-label.",
1490
2251
  "duplicate-id": "Two entries share an id.",
1491
2252
  "label-collision": "Two entries claim the same preferred label, ignoring case.",
1492
2253
  "alt-label-collision": "An entry's alt-label is another entry's preferred label, ignoring case.",
1493
2254
  "dangling-reference": "A value of broader, narrower, related-terms or see names no entry, by label or by id.",
1494
2255
  "broader-cycle": "A chain of broader returns to where it started.",
1495
2256
  "see-not-empty": "An entry with see also carries a definition.",
2257
+ "missing-definition": "An entry has neither a definition nor see.",
2258
+ "conflicting-matches": "One IRI is listed under two of an entry's match kinds.",
1496
2259
  "asymmetric-hierarchy": "A names B as broader, and B omits A from narrower, or the reverse.",
2260
+ "alt-label-reference": "A page's concepts: names an entry by one of its alt-labels.",
1497
2261
  "abstract-too-long": "An abstract is longer than term.abstractMaxLength.",
1498
- "unused-term": "No page's concepts: names the entry's preferred label."
2262
+ "unused-term": "No page's concepts: names the entry.",
2263
+ "hierarchy-outside-termbase": "A page's graph: block gives a term a broader, narrower or related concept its own entry does not list.",
2264
+ "label-overlap": "A hidden-label or alt-label repeats one of the entry's own names, or a hidden-label is another entry's label or alt-label.",
2265
+ "asymmetric-related": "A names B in related-terms, and B omits A.",
2266
+ "related-in-hierarchy": "A related term is also broader or narrower than the entry, at any depth.",
2267
+ "ambiguous-alt-label": "Two entries share an alt-label, ignoring case.",
2268
+ "deprecated-label": "The entry's label is deprecated or superseded in its designations.",
2269
+ "related-siblings": "Two related terms share a broader term.",
2270
+ "orphan-term": "An entry has no broader, narrower or related term, in a termbase with a hierarchy.",
2271
+ "keyword-candidate": "A free keyword is on several pages and names no term."
1499
2272
  };
1500
2273
  var PROSE_PREFIX = `${RULE_ID_PREFIX}/prose/`;
1501
2274
  var FIELD_LABEL = new RegExp(`^(?:\\(root\\)|/(?:${TERM_FIELDS.join("|")})) `);
@@ -1532,21 +2305,53 @@ function renderFindingsJunit(report) {
1532
2305
  );
1533
2306
  }
1534
2307
 
1535
- // src/term/commands/labels.ts
1536
- async function termLabels(request) {
1537
- const run = await resolveTermRun({
1538
- cwd: request.cwd,
1539
- inputs: [],
1540
- ...request.configPath === void 0 ? {} : { configPath: request.configPath },
1541
- ...request.noConfig === true ? { noConfig: true } : {}
1542
- });
1543
- if (run.inputs.length === 0 && run.manifests.length === 0) return [];
1544
- const set = await loadSet(run, { inputs: [], allowEmpty: true });
1545
- return set.terms.map((term) => ({ label: term.record.label, id: term.id }));
2308
+ // src/term/reporters/fill.ts
2309
+ var DONE = { create: "created", fill: "filled", skip: "skipped", exists: "exists" };
2310
+ var WOULD = { create: "would create", fill: "would fill", skip: "skipped", exists: "exists" };
2311
+ function detail(entry, threshold) {
2312
+ if (entry.reason !== void 0) return entry.reason;
2313
+ const { status, confidence } = entry.definition;
2314
+ if (entry.action === "exists") return "the file is already there";
2315
+ switch (status) {
2316
+ case "carried":
2317
+ return "definition from graph: block";
2318
+ case "drafted":
2319
+ return `definition drafted (${(confidence ?? 0).toFixed(2)})`;
2320
+ case "below-threshold": {
2321
+ const under = `confidence ${(confidence ?? 0).toFixed(2)} is under ${String(threshold)}`;
2322
+ return entry.action === "create" ? `stub, ${under}` : under;
2323
+ }
2324
+ case "missing":
2325
+ return "stub, no definition";
2326
+ }
2327
+ }
2328
+ function renderFillPretty(report) {
2329
+ const words = report.dryRun ? WOULD : DONE;
2330
+ const actionWidth = Math.max(0, ...report.entries.map((e) => words[e.action].length));
2331
+ const fileWidth = Math.max(0, ...report.entries.map((e) => e.file.length)) + 3;
2332
+ const labelWidth = Math.max(0, ...report.entries.map((e) => e.label.length)) + 3;
2333
+ const lines = report.entries.map(
2334
+ (e) => `${words[e.action].padEnd(actionWidth)} ${e.file.padEnd(fileWidth)}${e.label.padEnd(labelWidth)}${detail(e, report.threshold)}`
2335
+ );
2336
+ const { created, filled, skipped, withoutDefinition } = report.summary;
2337
+ const skips = skipped > 0 ? `, ${String(skipped)} skipped` : "";
2338
+ lines.push(
2339
+ report.dryRun ? `${plural(created, "term")} would be created, ${String(filled)} would be filled, ${String(withoutDefinition)} left without a definition${skips}` : `${plural(created, "term")} created, ${String(filled)} filled, ${String(withoutDefinition)} left without a definition${skips}`
2340
+ );
2341
+ return lines.join("\n");
2342
+ }
2343
+ function renderFillJson(report) {
2344
+ return JSON.stringify({ entries: report.entries, summary: report.summary }, null, 2);
1546
2345
  }
1547
2346
 
1548
2347
  // src/term/cli.ts
1549
- registerTermLabelSource(termLabels);
2348
+ function numeric(name, value, min, max, integer = false) {
2349
+ if (value === void 0) return;
2350
+ if (!Number.isFinite(value) || value < min || value > max || integer && !Number.isInteger(value)) {
2351
+ const kind = integer ? "a whole number" : "a number";
2352
+ throw new TermError(`${name} must be ${kind} between ${String(min)} and ${String(max)}, got ${String(value)}.`);
2353
+ }
2354
+ }
1550
2355
  function colorFor(options) {
1551
2356
  return shouldColor({ noColor: !options.color, isTTY: process.stdout.isTTY });
1552
2357
  }
@@ -1571,11 +2376,11 @@ function print(text) {
1571
2376
  process.stdout.write(`${text}
1572
2377
  `);
1573
2378
  }
1574
- function renderFindings(report, format, options, references2) {
2379
+ function renderFindings(report, format, options, references) {
1575
2380
  let text;
1576
2381
  switch (format) {
1577
2382
  case "pretty":
1578
- text = renderFindingsPretty(report, { color: colorFor(options), references: references2 });
2383
+ text = renderFindingsPretty(report, { color: colorFor(options), references });
1579
2384
  break;
1580
2385
  case "json":
1581
2386
  text = renderFindingsJson(report);
@@ -1700,6 +2505,44 @@ function buildProgram() {
1700
2505
  fail(err);
1701
2506
  }
1702
2507
  });
2508
+ withInputs(
2509
+ program.command("fill").description("Create term pages for the concepts pages name, and draft missing definitions").argument("[paths...]", "files, directories, or globs to read (use - for stdin)")
2510
+ ).option("-o, --out <dir>", "directory for new term pages").option("--crawl", "also ask the model for terms that page bodies and keywords use").option("--offline", "no network egress: only a model already downloaded, never a remote provider").option("--provider <name>", "provider: auto (default), anthropic, openai, claude-cli, llama-cpp").option("--model <model>", "model override; needs a named provider, from here or config").option("--local", LOCAL_FLAG_HELP).option("--confidence <n>", "minimum confidence to write a definition (0-1)", parseFloat).option("--max-turns <n>", "stop after this many inference calls", parseFloat).option("--chunk-chars <n>", "characters of page per call under --crawl (default 12000)", parseFloat).option("--no-cache", "bypass the answer cache").option("--dry-run", "write nothing; print what would change").option("-f, --format <format>", `output: ${FILL_FORMATS.join(" | ")}`, "pretty").addHelpText(
2511
+ "after",
2512
+ [
2513
+ "",
2514
+ "Examples:",
2515
+ " manni term fill --offline --dry-run # what is missing, nothing sent",
2516
+ " manni term fill # pages and drafted definitions",
2517
+ " manni term fill --crawl -o docs/glossary/ # terms no metadata named",
2518
+ " manni term fill --dry-run -f json # for a script"
2519
+ ].join("\n")
2520
+ ).action(async (paths, options) => {
2521
+ try {
2522
+ const format = formatChoice(options.format, FILL_FORMATS);
2523
+ numeric("--confidence", options.confidence, 0, 1);
2524
+ numeric("--max-turns", options.maxTurns, 1, Number.MAX_SAFE_INTEGER, true);
2525
+ numeric("--chunk-chars", options.chunkChars, 1, Number.MAX_SAFE_INTEGER, true);
2526
+ const report = await runFill({
2527
+ ...await coreOptions(paths, options),
2528
+ ...options.out === void 0 ? {} : { out: options.out },
2529
+ ...options.crawl === true ? { crawl: true } : {},
2530
+ ...options.offline === true ? { offline: true } : {},
2531
+ ...options.provider === void 0 ? {} : { provider: options.provider },
2532
+ ...options.model === void 0 ? {} : { model: options.model },
2533
+ ...options.local === true ? { local: true } : {},
2534
+ ...options.confidence === void 0 ? {} : { confidence: options.confidence },
2535
+ ...options.maxTurns === void 0 ? {} : { maxTurns: options.maxTurns },
2536
+ ...options.chunkChars === void 0 ? {} : { chunkChars: options.chunkChars },
2537
+ ...options.cache ? {} : { noCache: true },
2538
+ ...options.dryRun === true ? { dryRun: true } : {}
2539
+ });
2540
+ print(format === "json" ? renderFillJson(report) : renderFillPretty(report));
2541
+ process.exitCode = 0;
2542
+ } catch (err) {
2543
+ fail(err);
2544
+ }
2545
+ });
1703
2546
  program.command("formats").description("List the constructs read and written, per format").option("-f, --format <format>", `output: ${FORMATS_FORMATS.join(" | ")}`, "pretty").action((options) => {
1704
2547
  try {
1705
2548
  const format = formatChoice(options.format, FORMATS_FORMATS);
@@ -1717,4 +2560,4 @@ export {
1717
2560
  TermError,
1718
2561
  buildProgram
1719
2562
  };
1720
- //# sourceMappingURL=term-ASM4LVYC.js.map
2563
+ //# sourceMappingURL=term-D2N7UN4P.js.map