@hawkeyexl/manni 4.11.0 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{batch-UAULUMGH.js → batch-EFSFG6GC.js} +20 -19
- package/dist/build-NIO3UIWJ.js +36 -0
- package/dist/calibrate-6VO7URRV.js +41 -0
- package/dist/capture-NMBVJO3C.js +38 -0
- package/dist/check-SHOYX2B5.js +30 -0
- package/dist/check-XMJKH3KV.js +34 -0
- package/dist/{check-VELUQAUW.js → check-Y62BJNC4.js} +35 -34
- package/dist/{check-VELUQAUW.js.map → check-Y62BJNC4.js.map} +1 -1
- package/dist/{check-YEOYBFST.js → check-ZMO3ZLMW.js} +19 -18
- package/dist/{chunk-BKVHX6FU.js → chunk-24AJK2RG.js} +5 -10
- package/dist/chunk-24AJK2RG.js.map +1 -0
- package/dist/{chunk-M42DZCOU.js → chunk-2OZF2VUB.js} +2 -2
- package/dist/chunk-2UJZXVHR.js +1868 -0
- package/dist/chunk-2UJZXVHR.js.map +1 -0
- package/dist/{chunk-HQR2ZBHW.js → chunk-3BRJCQPY.js} +36 -7
- package/dist/chunk-3BRJCQPY.js.map +1 -0
- package/dist/{chunk-U7CTFN2J.js → chunk-42VFJOAF.js} +7 -7
- package/dist/{chunk-LBSCW232.js → chunk-4Q24OYI3.js} +7 -7
- package/dist/{chunk-OPXWPJDA.js → chunk-4WJTURRO.js} +14 -14
- package/dist/{chunk-GDVZ5VII.js → chunk-5SID2SVL.js} +4 -4
- package/dist/{chunk-FUCPZVRY.js → chunk-AANUY4BH.js} +2 -2
- package/dist/chunk-ANPIIYRH.js +2272 -0
- package/dist/chunk-ANPIIYRH.js.map +1 -0
- package/dist/{chunk-WDWXAYVH.js → chunk-AYVKN3PG.js} +4 -4
- package/dist/{chunk-FQXWVS6J.js → chunk-CH6IOGXV.js} +9 -9
- package/dist/{chunk-4CK6ZSOK.js → chunk-D5Z6B4M7.js} +3 -3
- package/dist/{chunk-HA6MQMOY.js → chunk-D6SELXQ2.js} +6 -6
- package/dist/{chunk-2DRHT73U.js → chunk-DDILEF5F.js} +890 -1399
- package/dist/chunk-DDILEF5F.js.map +1 -0
- package/dist/{chunk-PCS4VJBV.js → chunk-DGRLHDM4.js} +9 -9
- package/dist/{chunk-2MJ62AYQ.js → chunk-DHGB4JBG.js} +4 -3
- package/dist/chunk-DHGB4JBG.js.map +1 -0
- package/dist/{chunk-Y6DOMTQD.js → chunk-DLU5FCFT.js} +27 -27
- package/dist/chunk-DLU5FCFT.js.map +1 -0
- package/dist/chunk-DSWKBZWW.js +16 -0
- package/dist/chunk-DSWKBZWW.js.map +1 -0
- package/dist/{chunk-KGEQJ5CC.js → chunk-F564FHMQ.js} +8 -8
- package/dist/{chunk-J6IDQGJL.js → chunk-FKAZUZQU.js} +469 -85
- package/dist/chunk-FKAZUZQU.js.map +1 -0
- package/dist/{chunk-IGSHYP74.js → chunk-G3MBUL5M.js} +4 -4
- package/dist/{chunk-ADMEPUBT.js → chunk-GQ3KRY3B.js} +3 -3
- package/dist/{chunk-T7JAOYE5.js → chunk-HDPN46JP.js} +6 -6
- package/dist/{chunk-R4WXQIOZ.js → chunk-IQQAJROD.js} +3 -3
- package/dist/{chunk-2IR4T5PO.js → chunk-IZXN3WI6.js} +2 -2
- package/dist/{chunk-NCPWXHDO.js → chunk-JEUFYSFQ.js} +4 -4
- package/dist/{chunk-LKP7QDFN.js → chunk-JSSM7VVV.js} +4 -4
- package/dist/{chunk-2IAZEB45.js → chunk-KFGZPVFA.js} +229 -821
- package/dist/chunk-KFGZPVFA.js.map +1 -0
- package/dist/{chunk-EIFCP6CZ.js → chunk-KGFSPJLD.js} +2 -2
- package/dist/{chunk-RLT5SEML.js → chunk-KMORGMCW.js} +6 -6
- package/dist/{chunk-WQWKYAAK.js → chunk-NUQF5F5J.js} +2 -2
- package/dist/{chunk-54F74XR3.js → chunk-NZ6KSHFD.js} +19 -19
- package/dist/{chunk-4D5IZSXM.js → chunk-OHUDZRLK.js} +3 -3
- package/dist/{chunk-FBMZJEB3.js → chunk-OKMTUAWO.js} +4 -4
- package/dist/{chunk-QLWC7MKD.js → chunk-OTJOBZJ5.js} +135 -135
- package/dist/chunk-OTJOBZJ5.js.map +1 -0
- package/dist/{chunk-6HWBRZIN.js → chunk-PS257NIU.js} +252 -193
- package/dist/chunk-PS257NIU.js.map +1 -0
- package/dist/chunk-QDC7JPFG.js +685 -0
- package/dist/chunk-QDC7JPFG.js.map +1 -0
- package/dist/{chunk-PCQ7ELJH.js → chunk-QEAGL4V5.js} +109 -5
- package/dist/chunk-QEAGL4V5.js.map +1 -0
- package/dist/{chunk-BBT6AVUG.js → chunk-QMY57PVW.js} +2 -2
- package/dist/{chunk-LPIF5LIE.js → chunk-QNDDPXFR.js} +2 -2
- package/dist/{chunk-PWBH7DCQ.js → chunk-QSIXNTRV.js} +4 -4
- package/dist/{chunk-VSEBFHAY.js → chunk-RGLFV4KO.js} +11369 -10218
- package/dist/chunk-RGLFV4KO.js.map +1 -0
- package/dist/{chunk-D4N2V43Z.js → chunk-SGR7ZAVE.js} +13 -7
- package/dist/chunk-SGR7ZAVE.js.map +1 -0
- package/dist/{chunk-GV56WGL2.js → chunk-SMHAYK6I.js} +1036 -883
- package/dist/chunk-SMHAYK6I.js.map +1 -0
- package/dist/{chunk-JPQDNYXH.js → chunk-STPGIKPY.js} +8 -2
- package/dist/chunk-STPGIKPY.js.map +1 -0
- package/dist/{chunk-NSBXVPZL.js → chunk-U22TOL5Y.js} +17 -17
- package/dist/{chunk-NGTVREIH.js → chunk-U6IHLEWT.js} +2 -2
- package/dist/{chunk-ODRPL3WB.js → chunk-UUCCV3SI.js} +2 -2
- package/dist/{chunk-MSRU4D4P.js → chunk-UXMCHBOJ.js} +2 -2
- package/dist/{chunk-B7XYNRJQ.js → chunk-VFAKGIDG.js} +2 -2
- package/dist/{chunk-QCHVR4ZM.js → chunk-VM7VAFJW.js} +33 -7
- package/dist/chunk-VM7VAFJW.js.map +1 -0
- package/dist/{chunk-VQK4VHLF.js → chunk-YQV75FIL.js} +2 -2
- package/dist/chunk-YUTVAMWW.js +2 -0
- package/dist/{cli-4MF37HAQ.js → cli-4CR7QIOK.js} +26 -25
- package/dist/{cli-4MF37HAQ.js.map → cli-4CR7QIOK.js.map} +1 -1
- package/dist/{cli-6KZTHWGP.js → cli-6R4W3HAH.js} +37 -36
- package/dist/{cli-6KZTHWGP.js.map → cli-6R4W3HAH.js.map} +1 -1
- package/dist/{cli-I62SRH3R.js → cli-BOMA2FMP.js} +14 -13
- package/dist/{cli-DRMZBZLB.js → cli-EDQPQOCE.js} +43 -42
- package/dist/{cli-DRMZBZLB.js.map → cli-EDQPQOCE.js.map} +1 -1
- package/dist/{cli-VID7PJS3.js → cli-GBF76EXT.js} +23 -22
- package/dist/{cli-VID7PJS3.js.map → cli-GBF76EXT.js.map} +1 -1
- package/dist/{cli-3BTCK4AB.js → cli-MQYCF3SR.js} +27 -26
- package/dist/{cli-3BTCK4AB.js.map → cli-MQYCF3SR.js.map} +1 -1
- package/dist/{cli-ONTC5PKT.js → cli-OJKFXQOM.js} +9 -9
- package/dist/{cli-VUKMWSSF.js → cli-PHZAO4LZ.js} +4 -4
- package/dist/{cli-RORDPAPE.js → cli-PTKFFNOW.js} +59 -38
- package/dist/cli-PTKFFNOW.js.map +1 -0
- package/dist/{cli-O4ABTN4Z.js → cli-UW2K5Z5J.js} +31 -30
- package/dist/{cli-O4ABTN4Z.js.map → cli-UW2K5Z5J.js.map} +1 -1
- package/dist/{cli-JJMOVIKS.js → cli-XXTNPPKB.js} +14 -14
- package/dist/cli.js +19 -13
- package/dist/cli.js.map +1 -1
- package/dist/{config-XDA42RJL.js → config-JJW75SBX.js} +5 -5
- package/dist/docmeta.js +13 -12
- package/dist/docmeta.js.map +1 -1
- package/dist/github-6VQKSB67.js +35 -0
- package/dist/github-RBSEM7ZK.js +30 -0
- package/dist/graph/runtime.d.ts +4 -1
- package/dist/graph/runtime.js +20 -9
- package/dist/graph/runtime.js.map +1 -1
- package/dist/{host-6GURH5HE.js → host-YSTYO5DX.js} +3 -3
- package/dist/index.d.ts +192 -26
- package/dist/index.js +129 -124
- package/dist/index.js.map +1 -1
- package/dist/{json-BXY44ED7.js → json-PU2HLHDQ.js} +18 -17
- package/dist/labels-SJNSOPBI.js +73 -0
- package/dist/labels-SJNSOPBI.js.map +1 -0
- package/dist/lint-KIVTHLGU.js +34 -0
- package/dist/list-RDEJDDJF.js +32 -0
- package/dist/list-SUTDWL2J.js +35 -0
- package/dist/{page-EV7OUBAU.js → page-UMAA3NCM.js} +18 -16
- package/dist/{prepare-JHJDJB6I.js → prepare-3I3LOXXD.js} +22 -21
- package/dist/{prepare-JHJDJB6I.js.map → prepare-3I3LOXXD.js.map} +1 -1
- package/dist/{pretty-SCRK66M5.js → pretty-ANLRHU4O.js} +18 -17
- package/dist/{pretty-Q5Y2PA64.js → pretty-Q3ZFKOR7.js} +18 -17
- package/dist/{provider-527CO4DM.js → provider-LBX4IXGX.js} +3 -3
- package/dist/{release-3D5PK6M7.js → release-VV3UTKE5.js} +3 -3
- package/dist/{reporters-M6LJ2IYU.js → reporters-26H3N2KW.js} +3 -3
- package/dist/{reporters-RBYTASMI.js → reporters-ILT36CIH.js} +7 -7
- package/dist/{reporters-A5ADKDYR.js → reporters-PNDLWT6K.js} +16 -15
- package/dist/run-QXCK33Z4.js +37 -0
- package/dist/{term-CQAGNG3Q.js → term-D2N7UN4P.js} +981 -141
- package/dist/term-D2N7UN4P.js.map +1 -0
- package/dist/validate-BRUCOT2O.js +19 -0
- package/package.json +3 -2
- package/plugin/manni/.claude-plugin/plugin.json +1 -1
- package/shapes/graph/shapes-1.1.0.ttl +785 -0
- package/dist/build-QSPNK5AL.js +0 -35
- package/dist/calibrate-KXN4URPM.js +0 -40
- package/dist/capture-JHTSUPUC.js +0 -37
- package/dist/check-MDGXEUWL.js +0 -20
- package/dist/check-WOQRKNZK.js +0 -29
- package/dist/chunk-2DRHT73U.js.map +0 -1
- package/dist/chunk-2IAZEB45.js.map +0 -1
- package/dist/chunk-2MJ62AYQ.js.map +0 -1
- package/dist/chunk-4VBSTXN6.js +0 -392
- package/dist/chunk-4VBSTXN6.js.map +0 -1
- package/dist/chunk-6HWBRZIN.js.map +0 -1
- package/dist/chunk-BKVHX6FU.js.map +0 -1
- package/dist/chunk-D4N2V43Z.js.map +0 -1
- package/dist/chunk-EFW7CAG4.js +0 -387
- package/dist/chunk-EFW7CAG4.js.map +0 -1
- package/dist/chunk-GV56WGL2.js.map +0 -1
- package/dist/chunk-HQR2ZBHW.js.map +0 -1
- package/dist/chunk-J6IDQGJL.js.map +0 -1
- package/dist/chunk-JPQDNYXH.js.map +0 -1
- package/dist/chunk-JROBZ7JA.js +0 -818
- package/dist/chunk-JROBZ7JA.js.map +0 -1
- package/dist/chunk-PCQ7ELJH.js.map +0 -1
- package/dist/chunk-QCHVR4ZM.js.map +0 -1
- package/dist/chunk-QLWC7MKD.js.map +0 -1
- package/dist/chunk-TU2WUBVZ.js +0 -2
- package/dist/chunk-VSEBFHAY.js.map +0 -1
- package/dist/chunk-Y6DOMTQD.js.map +0 -1
- package/dist/cli-RORDPAPE.js.map +0 -1
- package/dist/github-RY3FRA6P.js +0 -29
- package/dist/github-YKQSH7FS.js +0 -34
- package/dist/lint-YJ2L22BW.js +0 -33
- package/dist/list-NSG24VVX.js +0 -31
- package/dist/list-V6EGCSHX.js +0 -34
- package/dist/run-BUE2DDXN.js +0 -36
- package/dist/term-CQAGNG3Q.js.map +0 -1
- package/dist/validate-ZBW44RHT.js +0 -18
- /package/dist/{batch-UAULUMGH.js.map → batch-EFSFG6GC.js.map} +0 -0
- /package/dist/{build-QSPNK5AL.js.map → build-NIO3UIWJ.js.map} +0 -0
- /package/dist/{calibrate-KXN4URPM.js.map → calibrate-6VO7URRV.js.map} +0 -0
- /package/dist/{capture-JHTSUPUC.js.map → capture-NMBVJO3C.js.map} +0 -0
- /package/dist/{check-MDGXEUWL.js.map → check-SHOYX2B5.js.map} +0 -0
- /package/dist/{check-WOQRKNZK.js.map → check-XMJKH3KV.js.map} +0 -0
- /package/dist/{check-YEOYBFST.js.map → check-ZMO3ZLMW.js.map} +0 -0
- /package/dist/{chunk-M42DZCOU.js.map → chunk-2OZF2VUB.js.map} +0 -0
- /package/dist/{chunk-U7CTFN2J.js.map → chunk-42VFJOAF.js.map} +0 -0
- /package/dist/{chunk-LBSCW232.js.map → chunk-4Q24OYI3.js.map} +0 -0
- /package/dist/{chunk-OPXWPJDA.js.map → chunk-4WJTURRO.js.map} +0 -0
- /package/dist/{chunk-GDVZ5VII.js.map → chunk-5SID2SVL.js.map} +0 -0
- /package/dist/{chunk-FUCPZVRY.js.map → chunk-AANUY4BH.js.map} +0 -0
- /package/dist/{chunk-WDWXAYVH.js.map → chunk-AYVKN3PG.js.map} +0 -0
- /package/dist/{chunk-FQXWVS6J.js.map → chunk-CH6IOGXV.js.map} +0 -0
- /package/dist/{chunk-4CK6ZSOK.js.map → chunk-D5Z6B4M7.js.map} +0 -0
- /package/dist/{chunk-HA6MQMOY.js.map → chunk-D6SELXQ2.js.map} +0 -0
- /package/dist/{chunk-PCS4VJBV.js.map → chunk-DGRLHDM4.js.map} +0 -0
- /package/dist/{chunk-KGEQJ5CC.js.map → chunk-F564FHMQ.js.map} +0 -0
- /package/dist/{chunk-IGSHYP74.js.map → chunk-G3MBUL5M.js.map} +0 -0
- /package/dist/{chunk-ADMEPUBT.js.map → chunk-GQ3KRY3B.js.map} +0 -0
- /package/dist/{chunk-T7JAOYE5.js.map → chunk-HDPN46JP.js.map} +0 -0
- /package/dist/{chunk-R4WXQIOZ.js.map → chunk-IQQAJROD.js.map} +0 -0
- /package/dist/{chunk-2IR4T5PO.js.map → chunk-IZXN3WI6.js.map} +0 -0
- /package/dist/{chunk-NCPWXHDO.js.map → chunk-JEUFYSFQ.js.map} +0 -0
- /package/dist/{chunk-LKP7QDFN.js.map → chunk-JSSM7VVV.js.map} +0 -0
- /package/dist/{chunk-EIFCP6CZ.js.map → chunk-KGFSPJLD.js.map} +0 -0
- /package/dist/{chunk-RLT5SEML.js.map → chunk-KMORGMCW.js.map} +0 -0
- /package/dist/{chunk-WQWKYAAK.js.map → chunk-NUQF5F5J.js.map} +0 -0
- /package/dist/{chunk-54F74XR3.js.map → chunk-NZ6KSHFD.js.map} +0 -0
- /package/dist/{chunk-4D5IZSXM.js.map → chunk-OHUDZRLK.js.map} +0 -0
- /package/dist/{chunk-FBMZJEB3.js.map → chunk-OKMTUAWO.js.map} +0 -0
- /package/dist/{chunk-BBT6AVUG.js.map → chunk-QMY57PVW.js.map} +0 -0
- /package/dist/{chunk-LPIF5LIE.js.map → chunk-QNDDPXFR.js.map} +0 -0
- /package/dist/{chunk-PWBH7DCQ.js.map → chunk-QSIXNTRV.js.map} +0 -0
- /package/dist/{chunk-NSBXVPZL.js.map → chunk-U22TOL5Y.js.map} +0 -0
- /package/dist/{chunk-NGTVREIH.js.map → chunk-U6IHLEWT.js.map} +0 -0
- /package/dist/{chunk-ODRPL3WB.js.map → chunk-UUCCV3SI.js.map} +0 -0
- /package/dist/{chunk-MSRU4D4P.js.map → chunk-UXMCHBOJ.js.map} +0 -0
- /package/dist/{chunk-B7XYNRJQ.js.map → chunk-VFAKGIDG.js.map} +0 -0
- /package/dist/{chunk-VQK4VHLF.js.map → chunk-YQV75FIL.js.map} +0 -0
- /package/dist/{chunk-TU2WUBVZ.js.map → chunk-YUTVAMWW.js.map} +0 -0
- /package/dist/{cli-I62SRH3R.js.map → cli-BOMA2FMP.js.map} +0 -0
- /package/dist/{cli-ONTC5PKT.js.map → cli-OJKFXQOM.js.map} +0 -0
- /package/dist/{cli-VUKMWSSF.js.map → cli-PHZAO4LZ.js.map} +0 -0
- /package/dist/{cli-JJMOVIKS.js.map → cli-XXTNPPKB.js.map} +0 -0
- /package/dist/{config-XDA42RJL.js.map → config-JJW75SBX.js.map} +0 -0
- /package/dist/{github-RY3FRA6P.js.map → github-6VQKSB67.js.map} +0 -0
- /package/dist/{github-YKQSH7FS.js.map → github-RBSEM7ZK.js.map} +0 -0
- /package/dist/{host-6GURH5HE.js.map → host-YSTYO5DX.js.map} +0 -0
- /package/dist/{json-BXY44ED7.js.map → json-PU2HLHDQ.js.map} +0 -0
- /package/dist/{lint-YJ2L22BW.js.map → lint-KIVTHLGU.js.map} +0 -0
- /package/dist/{list-NSG24VVX.js.map → list-RDEJDDJF.js.map} +0 -0
- /package/dist/{list-V6EGCSHX.js.map → list-SUTDWL2J.js.map} +0 -0
- /package/dist/{page-EV7OUBAU.js.map → page-UMAA3NCM.js.map} +0 -0
- /package/dist/{pretty-Q5Y2PA64.js.map → pretty-ANLRHU4O.js.map} +0 -0
- /package/dist/{pretty-SCRK66M5.js.map → pretty-Q3ZFKOR7.js.map} +0 -0
- /package/dist/{provider-527CO4DM.js.map → provider-LBX4IXGX.js.map} +0 -0
- /package/dist/{release-3D5PK6M7.js.map → release-VV3UTKE5.js.map} +0 -0
- /package/dist/{reporters-A5ADKDYR.js.map → reporters-26H3N2KW.js.map} +0 -0
- /package/dist/{reporters-M6LJ2IYU.js.map → reporters-ILT36CIH.js.map} +0 -0
- /package/dist/{reporters-RBYTASMI.js.map → reporters-PNDLWT6K.js.map} +0 -0
- /package/dist/{run-BUE2DDXN.js.map → run-QXCK33Z4.js.map} +0 -0
- /package/dist/{validate-ZBW44RHT.js.map → validate-BRUCOT2O.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graph/types.ts","../src/graph/core/iri.ts","../src/graph/core/vocab.ts","../src/graph/core/config.ts","../src/graph/core/config-schema.json","../src/graph/core/iirds.ts","../src/graph/core/coverage.ts","../src/graph/embed/types.ts","../src/graph/core/analyze.ts","../src/graph/core/discover.ts","../src/graph/core/sort.ts","../src/graph/core/external.ts","../src/graph/core/localizations.ts","../src/graph/core/questions.ts","../src/graph/core/questions-schema.json"],"sourcesContent":["/** Shared types for manni graph. */\nimport { ToolError } from \"../shared/errors.js\";\nimport type { DocFormat } from \"./core/analyze.js\";\n\n/** Operational error: expected failure reported to the user, exit code 2. */\nexport class GraphError extends ToolError {\n constructor(message: string) {\n super(message);\n this.name = \"GraphError\";\n }\n}\n\n/** A heading-derived section within a document. */\nexport interface Section {\n /** GitHub-style slug, disambiguated (`install`, `install-1`, ...). */\n slug: string;\n /** Heading text. */\n title: string;\n /** Heading level, 1-6. */\n level: number;\n /** 1-based position among siblings under the same parent. */\n order: number;\n /** Slug of the enclosing section, or null when the parent is the document. */\n parentSlug: string | null;\n}\n\n/** A link found in a document body. */\nexport interface DocLink {\n /** The raw target as written in the source. */\n raw: string;\n /**\n * internal: resolves to a discovered doc (repo-relative path in `resolvedPath`,\n * optional `anchor`);\n * external: absolute URL;\n * broken: relative target that does not match a discovered doc.\n */\n kind: \"internal\" | \"external\" | \"broken\";\n /** Repo-relative path of the target doc (internal links only). */\n resolvedPath?: string;\n /** Fragment identifier without `#`, when present. */\n anchor?: string;\n /** Normalized absolute URL (external links only). */\n url?: string;\n}\n\n/** An image reference found in a document body. */\nexport interface DocImage {\n raw: string;\n /** Absolute URL or repo-relative path resolved from the doc's location. */\n target: string;\n external: boolean;\n}\n\n/** Everything dockg derives from one source file. */\nexport interface DocModel {\n /** Repo-relative path with forward slashes, e.g. `docs/guide.md`. */\n path: string;\n /** Parsed frontmatter data ({} when absent). */\n frontmatter: Record<string, unknown>;\n /** Whether a frontmatter block was present. */\n frontmatterPresent: boolean;\n /** The format the page was parsed as: `--as`, else its extension. */\n format: DocFormat;\n /** First H1 text, if any (used as title fallback). */\n firstH1?: string;\n sections: Section[];\n links: DocLink[];\n images: DocImage[];\n /** Distinct fenced code block languages, sorted. */\n codeLanguages: string[];\n /**\n * BCP-47 tag from the nearest enclosing route mapping that declares one\n * (ADR 01037), or undefined when no route covers this path or none in the\n * chain declares a language. The page's own `lang`/`language` frontmatter\n * outranks it.\n */\n routeLanguage?: string;\n /**\n * Lowercase sha256 hex digest of the document's UTF-8 content, as read —\n * line endings included, so it matches `sha256sum <file>` (ADR 01036).\n */\n contentHash: string;\n}\n","/**\n * Deterministic IRI minting. Every node in the graph gets a stable IRI derived\n * from the base IRI plus repo-relative paths, heading slugs, or concept labels —\n * never blank nodes. Identical inputs mint identical IRIs on every OS.\n */\nimport { slug as githubSlug } from \"github-slugger\";\n\n/** Default base when the config sets none: valid, deterministic, obviously placeholder. */\nexport const DEFAULT_BASE_IRI = \"urn:manni:graph:\";\n\n/** Normalize a config base IRI; http(s) bases get a trailing slash. */\nexport function resolveBaseIri(base: string | undefined): string {\n if (!base) return DEFAULT_BASE_IRI;\n if (base.endsWith(\"/\") || base.endsWith(\":\")) return base;\n return `${base}/`;\n}\n\n/** Repo-relative path with forward slashes and no leading `./`. */\nexport function normalizeDocPath(p: string): string {\n let out = p.replace(/\\\\/g, \"/\");\n while (out.startsWith(\"./\")) out = out.slice(2);\n return out;\n}\n\n/** RFC 3986 strict percent-encoding of one path segment (UTF-8 for non-ASCII). */\nexport function encodeSegment(segment: string): string {\n return encodeURIComponent(segment).replace(\n /[!'()*]/g,\n (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n}\n\n/**\n * The display path of a document read from stdin (`-`). It has no file name,\n * so its node is `{base}stdin` rather than a `doc/` path, and its links\n * resolve from the working directory.\n */\nexport const STDIN_PATH = \"<stdin>\";\n\n/**\n * `{base}doc/{repo-relative-path}`, segment-wise percent-encoded. A document\n * read from stdin is `{base}stdin`.\n */\nexport function mintDocIri(base: string, relPath: string): string {\n if (relPath === STDIN_PATH) return `${base}stdin`;\n const path = normalizeDocPath(relPath)\n .split(\"/\")\n .map(encodeSegment)\n .join(\"/\");\n return `${base}doc/${path}`;\n}\n\n/** `{docIri}#{slug}` — the slug comes pre-disambiguated from analysis. */\nexport function mintSectionIri(docIri: string, slugValue: string): string {\n return `${docIri}#${slugValue}`;\n}\n\n/** Stateless GitHub-style slug; identical labels always converge. */\nexport function conceptSlug(label: string): string {\n return githubSlug(label);\n}\n\n/** `{base}concept/{slug(label)}` — one shared namespace for all concepts. */\nexport function mintConceptIri(base: string, label: string): string {\n return `${base}concept/${encodeSegment(conceptSlug(label))}`;\n}\n\n/**\n * `{base}concept/{id}` — a concept the termbase defines (proposal 0086 §1).\n * The id is the term's own, encoded as one segment. A term's id defaults to\n * its label's slug, so most term concepts keep the IRI a label would mint.\n */\nexport function mintTermConceptIri(base: string, id: string): string {\n return `${base}concept/${encodeSegment(id)}`;\n}\n\n/**\n * `{base}product/{slug(label)}` — iiRDS ProductVariant nodes (graph.applies-to).\n * Separate `product/` segment so a product and a concept sharing a label\n * cannot converge on one IRI.\n */\nexport function mintProductIri(base: string, label: string): string {\n return `${base}product/${encodeSegment(conceptSlug(label))}`;\n}\n\n/** The single skos:ConceptScheme node for the graph. */\nexport function mintSchemeIri(base: string): string {\n return `${base}scheme`;\n}\n\n/**\n * The kind of actor an agent IRI names, mirroring PROV-O's three\n * `prov:Agent` subclasses. Segmenting by kind keeps a person and a model\n * whose names slug alike (\"GPT 4\" / \"gpt-4\") from merging into one node.\n */\nexport type AgentKind = \"person\" | \"org\" | \"software\";\n\n/** `{base}agent/{kind}/{slug(name)}`. */\nexport function mintAgentIri(\n base: string,\n kind: AgentKind,\n name: string,\n): string {\n return `${base}agent/${kind}/${encodeSegment(conceptSlug(name))}`;\n}\n\n/** The graph itself as a prov:Entity. */\nexport function mintGraphIri(base: string): string {\n return `${base}graph`;\n}\n\n/** The build run as a prov:Activity. */\nexport function mintBuildActivityIri(base: string): string {\n return `${base}activity/build`;\n}\n","/**\n * Namespace table. Standard vocabularies wherever a term exists; the custom\n * `graph:` namespace stays minimal, and the newest vocabulary document under\n * `ns/` defines every term it holds — a bidirectional drift guard in\n * test/graph/unit/vocabulary.test.ts enforces both directions. Neither the term\n * count nor the version is written here: both went stale the first time a term\n * was added, and the guard resolves the file rather than naming it. The prefix\n * set is fixed — every emitted graph carries the same header.\n *\n * The custom prefix is `graph:` and its namespace is the manni site's, which is\n * where it dereferences (proposal 0051 §7). Both were `dockg` until the tool\n * joined the family, and graph ADR 01030's rule — the namespace IRI must resolve\n * — is why they moved rather than staying: `hawkeyexl.github.io/dockg` never\n * served anything and never will.\n *\n * The block an author writes on a page is `graph:`, and the prefix is `graph:`\n * too. The spelling is shared but the things differ: the key names frontmatter,\n * the prefix abbreviates an IRI in emitted RDF, and the prefix carries the\n * tool's name because `…/manni/graph/ns#` is the tool's namespace. Nothing\n * collides: no other prefix in this table is `graph`, and a `graph:` CURIE typed\n * at `--predicates` or `--subject` expanded to nothing before.\n */\nexport const NS = {\n dcterms: \"http://purl.org/dc/terms/\",\n foaf: \"http://xmlns.com/foaf/0.1/\",\n graph: \"https://hawkeyexl.github.io/manni/graph/ns#\",\n iirds: \"http://iirds.tekom.de/iirds#\",\n iirdsSft: \"http://iirds.tekom.de/iirds/domain/software#\",\n prov: \"http://www.w3.org/ns/prov#\",\n rdf: \"http://www.w3.org/1999/02/22-rdf-syntax-ns#\",\n schema: \"https://schema.org/\",\n skos: \"http://www.w3.org/2004/02/skos/core#\",\n xsd: \"http://www.w3.org/2001/XMLSchema#\",\n} as const;\n\nexport type Prefix = keyof typeof NS;\n\n/** Prefixes in emission order (sorted by prefix name). */\nexport const PREFIXES: ReadonlyArray<[Prefix, string]> = (\n Object.entries(NS) as Array<[Prefix, string]>\n).sort(([a], [b]) => (a < b ? -1 : 1));\n\nexport const RDF_TYPE = `${NS.rdf}type`;\n\n/**\n * Role individuals for qualified provenance (prov:hadRole objects). Part of\n * the deliberately small graph vocabulary.\n */\nexport const ROLE = {\n author: `${NS.graph}authorRole`,\n generator: `${NS.graph}generatorRole`,\n tool: `${NS.graph}toolRole`,\n} as const;\n","/**\n * Loads and validates the `graph:` section of `manni.config.yaml`. Discovery is\n * the family's (`src/shared/config-file.ts`); validation is JSON Schema\n * (2020-12) via Ajv; defaults are applied in code afterward so the resolved\n * shape is fully typed. Mirrors the docevals config pattern.\n */\nimport { dirname, resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport configSchema from \"./config-schema.json\" with { type: \"json\" };\nimport {\n findConfigFileSync,\n readConfigFileSync,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport type { CollectionConfig } from \"../../shared/collections.js\";\nimport { parseCollections } from \"../../shared/collections.js\";\nimport {\n PROVIDERS_KEY,\n assertKnownProvider,\n parseProviders,\n type ProvidersConfig,\n} from \"../../shared/providers.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\n// meta's budget, shared rather than copied, as `term fill` shares it.\nimport { DEFAULT_CHUNK_CHARS } from \"../../meta/commands/fill-prompt.js\";\nimport type { Severity } from \"../../shared/severity.js\";\nimport { GraphError } from \"../types.js\";\nimport { resolveBaseIri } from \"./iri.js\";\nimport { UNIFORM_COVERAGE_FIELD_NAMES } from \"./coverage.js\";\n// Pure data module (no transformers import), so config stays Node-light.\nimport { DEFAULT_MODEL as DEFAULT_EMBED_MODEL } from \"../embed/types.js\";\n\nexport type DeriveSource =\n | \"frontmatter\"\n | \"sections\"\n | \"links\"\n | \"tags\"\n | \"images\"\n | \"code\"\n | \"provenance\"\n | \"terms\";\n\nexport type FillField =\n // SKOS concept fields\n | \"label\"\n | \"alt-labels\"\n | \"broader\"\n | \"narrower\"\n | \"related-concepts\"\n | \"concepts\"\n // iiRDS typing + negative scope (ADR 01015)\n | \"type\"\n | \"applies-to\"\n | \"about-product-lifecycle\"\n | \"about-product-aspect\"\n | \"not-applicable-to\"\n | \"not-about-product-aspect\"\n // A page's own questions, beside the graph block (proposal 0087)\n | \"sample-questions\";\n\n/** The fields `fill` writes into the `graph:` block: every fill field but questions. */\nexport type GraphFillField = Exclude<FillField, \"sample-questions\">;\n\n/** Every fillable field, in a stable order — the default `fill.fields`. */\nexport const ALL_FILL_FIELDS: FillField[] = [\n \"label\",\n \"alt-labels\",\n \"broader\",\n \"narrower\",\n \"related-concepts\",\n \"concepts\",\n \"type\",\n \"applies-to\",\n \"about-product-lifecycle\",\n \"about-product-aspect\",\n \"not-applicable-to\",\n \"not-about-product-aspect\",\n \"sample-questions\",\n];\n\n/** Maps published-site routes back to source files. */\nexport interface RouteMapping {\n /** Site prefix, normalized: leading `/`, no trailing `/`; `\"\"` = site root. */\n basePath: string;\n /** Repo-relative directory routes resolve into (no trailing slash). */\n root: string;\n /** Extensions to try when the route names a page without one. */\n extensions: string[];\n /** Basenames to try for directory routes (`/docs/actions/`). */\n indexFiles: string[];\n /**\n * BCP-47 tag labelling every document under `root` (ADR 01037). A page's own\n * `lang`/`language` frontmatter wins; absent that, the nearest enclosing\n * route that declares one applies. Omitted, the route says nothing about\n * language.\n */\n language?: string;\n}\n\nexport interface GraphConfig {\n /**\n * The family's document sets, from the file's top-level `collections:`\n * (proposal 0041). `[]` when the key is absent or no file governs the run.\n */\n collections: CollectionConfig[];\n /**\n * The config file as the user would name it, for messages; `null` when no\n * file governs the run and every value is a built-in default.\n */\n configSource: string | null;\n /**\n * `graph.provider`, or `null` when unset: the family's `providers.provider`\n * decides then, and `auto` (detect) after it. `--provider` wins over it and\n * `--local` overrides both (proposal 0051 §3).\n */\n provider: string | null;\n /**\n * The model within the provider, or `null` for the provider's own default.\n * manni pins no model: the inference library chooses, and the model it\n * resolves to is what every cache key names. Not `embed.model`, which is a\n * local embedding model id and has nothing to do with a provider.\n */\n model: string | null;\n /**\n * The family's top-level `providers:`: the provider and model every tool\n * falls back to, and the connection settings for each provider. `{}` when\n * the file declares none, or no file governs the run.\n */\n providers: ProvidersConfig;\n /** Normalized base IRI (trailing slash for http(s); `urn:manni:graph:` default). */\n baseIri: string;\n /** Output path of the built Turtle file, relative to configDir. */\n out: string;\n routes: RouteMapping[];\n /**\n * Golden-set files, as the config names them, relative to `configDir`\n * (proposal 0087). `check` asks their questions beside each page's.\n */\n questionFiles: string[];\n build: { derive: DeriveSource[] };\n /** Graph-level SHACL validation (`manni graph check`). */\n check: {\n /** Shapes .ttl paths; empty = the shapes bundled with manni. */\n shapes: string[];\n /**\n * Each page's `sample-questions`, asked through the retrieval `search`\n * uses (proposal 0086 §7). A page outside the `top` results for its own\n * question is a finding at `severity`; `off` reports none of them.\n * `foundThreshold` fails the run when the share of reviewed questions\n * found falls below it, a percentage; `null` sets no rate gate\n * (proposal 0087).\n */\n questions: { top: number; severity: Severity | \"off\"; foundThreshold: number | null };\n };\n provenance: {\n /**\n * Emit qualified attribution/association nodes with roles.\n *\n * The one provenance setting left. `git` was tri-state until proposal\n * 0051 §6: git history is *detected* now, used wherever git can run over a\n * repository and degraded to a warning where it cannot (graph ADR 01010's\n * `\"auto\"`, minus the switch). `qualified` stays because it switches what\n * is written, not what is discovered.\n */\n qualified: boolean;\n };\n fill: {\n temperature: number;\n /**\n * Stop after this many inference calls; `null` (the default) is\n * unbounded. One page is one turn, and a cached proposal spends none.\n * Replaces the dollar cap graph ADR 01027 found unenforceable, as docevals\n * ADR 01019 replaced its own (proposal 0051 §3).\n */\n maxTurns: number | null;\n cacheDir: string;\n fields: FillField[];\n /**\n * Minimum model self-confidence (0..1) to write a proposed field; below\n * this it is reported but not written (ADR 01015). Default 0.7. Named as\n * meta, docevals and tracevals name it (proposal 0051 §3).\n */\n confidenceThreshold: number;\n /** Record the page-level meta-provenance on filled docs (proposal 0046). */\n writeProvenance: boolean;\n /** Reject proposals that would violate the SHACL shapes contract. */\n validateGraph: boolean;\n /** Also propose per-section metadata (ADR 01032). Opt-in: more output. */\n sections: boolean;\n /** The largest body piece one question request sends (proposal 0087). */\n chunkChars: number;\n /** Send nothing off this machine: a downloaded local model, or none. */\n offline: boolean;\n questions: {\n /** Draft until a page has this many questions, reviewed or drafted. */\n perPage: number;\n };\n };\n stats: {\n /**\n * Per-field minimum coverage percentages (0–100) enforced under\n * `stats --check`. Resolved shape is always a map; a uniform number in the\n * config expands across every measured field. Default `{}` gates nothing.\n * See ADR 01011.\n */\n coverageThreshold: Record<string, number>;\n };\n embed: {\n /**\n * Embedding model id (ADR 01020). An open string, not an enum: the\n * documented table is the *tested* set, not the permitted set, so a newer\n * model works without a manni release.\n */\n model: string;\n /** Weight quantization. `q8` keeps int32 accumulation, which is associative. */\n dtype: string;\n /**\n * Directory the sidecars are written into (ADR 01038). One file per\n * language, named by `vectorIndexFilename`, so this is a directory rather\n * than the single path it was before the fan-out. Resolved from the\n * working directory, as `out` is. Undefined means the index directory,\n * which is why it has no default here.\n */\n out: string | undefined;\n /**\n * Per-language model overrides, keyed by BCP-47 tag (ADR 01038). A German\n * corpus embedded with an English-only model returns confident, meaningless\n * vectors and fails nothing, so this is the knob that makes the fan-out\n * worth having. Unset languages use `model`/`dtype`.\n */\n byLanguage: Record<string, { model?: string; dtype?: string }>;\n /** Per-text vector cache, keyed on text+model+dtype. */\n cacheDir: string;\n };\n export: {\n /** iiRDS package export metadata (ADR 01017); all fields optional. */\n iirds: {\n /** Package title; when absent the exporter uses a default. */\n title?: string;\n /** Creator organization name → a Creator iirds:Party + vcard:Organization. */\n creator?: string;\n /** iiRDS version literal written to the package. Default \"1.3\". */\n version: \"1.2\" | \"1.3\";\n };\n };\n /** Absolute path of the loaded config file. */\n configPath: string;\n /** Directory containing the config file; relative paths resolve against it. */\n configDir: string;\n}\n\n/** The family config file; this tool reads its `graph:` key. */\nexport const DEFAULT_CONFIG_FILENAME = \"manni.config.yaml\";\n/** The tool's key in the family file. */\nexport const CONFIG_SECTION = \"graph\";\n/** The family's top-level key for document sets (proposal 0041). */\nconst COLLECTIONS_KEY = \"collections\";\n\n/**\n * Where the metadata tool's configuration reference documents `collections:`.\n * The literal docevals', cite's and meta's config modules carry, repeated\n * because those modules are theirs.\n */\nconst CONFIG_REF =\n \"https://hawkeyexl.github.io/manni/meta/reference/configuration/\";\n\n/**\n * The keys proposal 0041 moved out of `graph:` and up to the family level.\n * Refused rather than aliased, as meta, cite and docevals refuse theirs: an\n * alias would be a second place to declare a document set that is meant to be\n * declared once. Checked before Ajv, which would call them unknown keys.\n */\nconst MOVED_KEYS = [\"inputs\", \"exclude\"] as const;\n\nexport const ALL_DERIVE_SOURCES: DeriveSource[] = [\n \"frontmatter\",\n \"sections\",\n \"links\",\n \"tags\",\n \"images\",\n \"code\",\n \"provenance\",\n \"terms\",\n];\n\n/**\n * Default candidates for extensionless link targets (routes AND relative\n * links), and the extensions that name a document rather than an asset.\n * Markdown first, so a tree holding `install.md` and a built `install.html`\n * resolves a pretty URL to the source. No `.xml`: a link to `pom.xml` is an\n * asset, as a walk never collects one (proposal 0077 §3).\n */\nexport const DEFAULT_LINK_EXTENSIONS = [\n \".md\",\n \".mdx\",\n \".markdown\",\n \".html\",\n \".htm\",\n \".adoc\",\n \".asciidoc\",\n \".rst\",\n \".dita\",\n \".ditamap\",\n];\nexport const DEFAULT_INDEX_FILES = [\"index\", \"README\"];\n\n/** `/docs/` -> `/docs`; `/` or `` -> `` (site root). */\nfunction normalizeBasePath(basePath: string): string {\n let out = basePath.trim();\n if (!out.startsWith(\"/\")) out = `/${out}`;\n out = out.replace(/\\/+$/, \"\");\n return out;\n}\n\nconst ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true });\nconst validateConfig = ajv.compile(configSchema);\n\n/** One `routes:` entry as the file spells it; only `root` is required. */\ninterface RawRouteMapping {\n basePath?: string;\n root: string;\n extensions?: string[];\n indexFiles?: string[];\n language?: string;\n}\n\n/**\n * The config file's own shape, in its own spelling.\n *\n * Ajv has already validated `raw` against `config-schema.json` by the time this\n * is used, so the optionality here is the schema's, not a guess. Declaring it is\n * what lets `parseConfigSection` read the file without an `any` — and an `any`\n * here would be the worst place for one, since every default in the tool flows\n * through this function. `RawDocevalsConfig` is the same declaration in the\n * evals tool.\n */\ninterface RawGraphConfig {\n provider?: string;\n model?: string;\n baseIri?: string;\n out?: string;\n routes?: RawRouteMapping[];\n questionFiles?: string[];\n build?: { derive?: DeriveSource[] };\n check?: {\n shapes?: string[];\n questions?: { top?: number; severity?: Severity | \"off\"; foundThreshold?: number | null };\n };\n provenance?: { qualified?: boolean };\n stats?: { coverageThreshold?: number | Record<string, number> };\n fill?: {\n temperature?: number;\n maxTurns?: number | null;\n cacheDir?: string;\n confidenceThreshold?: number;\n writeProvenance?: boolean;\n validateGraph?: boolean;\n fields?: FillField[];\n sections?: boolean;\n chunkChars?: number;\n offline?: boolean;\n questions?: { perPage?: number };\n };\n embed?: {\n model?: string;\n dtype?: string;\n out?: string;\n cacheDir?: string;\n byLanguage?: Record<string, { model?: string; dtype?: string }>;\n };\n export?: {\n iirds?: { title?: string; creator?: string; version?: \"1.2\" | \"1.3\" };\n };\n}\n\n/**\n * One Ajv error, as a line a reader can act on.\n *\n * Ajv reports an unknown key against the *parent* object, so the bare message\n * (\"must NOT have additional properties\") leaves the reader to diff their file\n * against the schema to find which key it meant. Name it, as docevals does\n * (PR #10): the common case here is a key that was removed — `version:`,\n * `provenance.git:` and `fill.provider:` after proposal 0051 — and a message\n * that makes you guess is one people work around.\n *\n * The path is the one the user writes. Ajv validates the `graph:` section on its\n * own, so its `instancePath` starts inside it; `/graph` goes back on the front,\n * so a reader can find `/graph/fill` in `manni.config.yaml` without translating.\n */\nfunction configErrorLine(e: {\n instancePath: string;\n keyword: string;\n params: unknown;\n message?: string | undefined;\n}): string {\n const extra =\n e.keyword === \"additionalProperties\"\n ? (e.params as { additionalProperty?: string }).additionalProperty\n : undefined;\n const where = `/${CONFIG_SECTION}${e.instancePath}`;\n return extra === undefined\n ? ` ${where}: ${e.message ?? \"is invalid\"}`\n : ` ${where}: unknown key \"${extra}\"`;\n}\n\n/**\n * Normalize `stats.coverageThreshold` to a per-field map. Ajv has already\n * validated the input as a number, an object of known fields, or absent; a\n * uniform number expands across every field it gates, which is every measured\n * field but `sample-questions`, so the resolved shape is always a map\n * (default `{}`).\n */\nfunction resolveCoverageThreshold(\n raw: number | Record<string, number> | undefined,\n): Record<string, number> {\n if (raw == null) return {};\n if (typeof raw === \"number\")\n return Object.fromEntries(UNIFORM_COVERAGE_FIELD_NAMES.map((f) => [f, raw]));\n return { ...raw };\n}\n\n/** What the file the section came from carries beside it. */\nexport interface ConfigFileContext {\n /** The file as the user would name it, for messages. */\n source: string;\n /** The file's top-level `collections:`. */\n collections: CollectionConfig[];\n /** The file's top-level `providers:`; `{}` when it declares none. */\n providers?: ProvidersConfig;\n}\n\n/**\n * Parse and validate config YAML text. A document with a `graph:` key is a family\n * file, so its top-level `collections:` is read too; anything else is the\n * tool's section on its own.\n */\nexport function parseConfig(text: string, configPath: string): GraphConfig {\n let raw: unknown;\n try {\n raw = parseYaml(text);\n } catch (e) {\n throw new GraphError(\n `Invalid YAML in ${configPath}: ${errorMessage(e)}`,\n );\n }\n if (raw == null) return parseConfigSection(null, configPath);\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new GraphError(`Invalid config in ${configPath}: root must be an object`);\n }\n const doc = raw as Record<string, unknown>;\n const wrapped = Object.hasOwn(doc, CONFIG_SECTION);\n const toError = (message: string): Error => new GraphError(message);\n // The family keys, parsed as the shared loader parses them, so a config\n // built from text selects from the same collections, and the same\n // providers, a discovered file would.\n const collections = Object.hasOwn(doc, COLLECTIONS_KEY)\n ? parseCollections(doc[COLLECTIONS_KEY], configPath, toError)\n : [];\n const providers = Object.hasOwn(doc, PROVIDERS_KEY)\n ? parseProviders(\n doc[PROVIDERS_KEY],\n configPath,\n dirname(resolve(configPath)),\n toError,\n )\n : {};\n return parseConfigSection(wrapped ? doc[CONFIG_SECTION] : doc, configPath, {\n source: configPath,\n collections,\n providers,\n });\n}\n\n/**\n * Validate the tool's section. `raw` is what sat under `graph:` in a family\n * file, or the whole document of an explicit path with no wrapper key.\n * Messages name `configPath`; relative paths in the config resolve against its\n * directory. `file` carries the family keys; absent, the section is its own\n * source and declares no collections.\n *\n * `null` is an empty section, which is every default: a `graph:` key somebody\n * added while migrating and has not filled in yet is a config, not an error.\n */\nexport function parseConfigSection(\n raw: unknown,\n configPath: string,\n file: ConfigFileContext = { source: configPath, collections: [] },\n): GraphConfig {\n if (raw == null) raw = {};\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new GraphError(\n `Invalid config in ${configPath}: root must be an object`,\n );\n }\n for (const key of MOVED_KEYS) {\n if (Object.hasOwn(raw as Record<string, unknown>, key)) {\n throw new GraphError(\n `${file.source}: \"${key}\" is no longer a graph key. Document sets are declared once for every tool, under a top-level collections: list. See ${CONFIG_REF}#${COLLECTIONS_KEY}`,\n );\n }\n }\n if (!validateConfig(raw)) {\n const details = (validateConfig.errors ?? [])\n .map((e) => configErrorLine(e))\n .join(\"\\n\");\n throw new GraphError(`Invalid config in ${configPath}:\\n${details}`);\n }\n\n // Past this point Ajv has validated `raw` against config-schema.json, so the\n // shape is known-good and reading fields off it is safe. The cast is to that\n // shape, spelled out once in `RawGraphConfig`, rather than to `any`: the file's\n // optionality is then the schema's and every default below is checked.\n const r = raw as RawGraphConfig;\n const abs = resolve(configPath);\n const dir = dirname(abs);\n\n // The name is checked here, with the message `manni meta fill` gives, so a\n // typo is caught by every verb and not only the one that reaches a model.\n // Whether a model has a provider to own it waits for the flags: a\n // `--provider`, or the family's `providers.provider`, can supply the\n // provider a configured model needs.\n const provider: string | null = r.provider ?? null;\n if (provider !== null) {\n assertKnownProvider(provider, (message) => new GraphError(message));\n }\n\n return {\n collections: file.collections,\n configSource: file.source,\n provider,\n model: r.model ?? null,\n providers: file.providers ?? {},\n baseIri: resolveBaseIri(r.baseIri),\n out: r.out ?? \"graph/graph.ttl\",\n routes: (r.routes ?? []).map((m) => ({\n basePath: normalizeBasePath(m.basePath ?? \"/\"),\n root: m.root\n .replace(/\\\\/g, \"/\")\n .replace(/^\\.\\//, \"\")\n .replace(/\\/+$/, \"\"),\n extensions: m.extensions ?? [...DEFAULT_LINK_EXTENSIONS],\n indexFiles: m.indexFiles ?? [...DEFAULT_INDEX_FILES],\n ...(m.language === undefined ? {} : { language: m.language }),\n })),\n questionFiles: r.questionFiles ?? [],\n build: {\n derive: r.build?.derive ?? [...ALL_DERIVE_SOURCES],\n },\n check: {\n // Empty means: use the shapes bundled with manni (see bundledShapesPath).\n shapes: r.check?.shapes ?? [],\n questions: {\n top: r.check?.questions?.top ?? 5,\n severity: r.check?.questions?.severity ?? \"warning\",\n foundThreshold: r.check?.questions?.foundThreshold ?? null,\n },\n },\n provenance: {\n qualified: r.provenance?.qualified ?? true,\n },\n stats: {\n coverageThreshold: resolveCoverageThreshold(r.stats?.coverageThreshold),\n },\n fill: {\n temperature: r.fill?.temperature ?? 0,\n maxTurns: r.fill?.maxTurns ?? null,\n cacheDir: r.fill?.cacheDir ?? \".manni/graph/cache\",\n fields: r.fill?.fields ?? [...ALL_FILL_FIELDS],\n confidenceThreshold: r.fill?.confidenceThreshold ?? 0.7,\n writeProvenance: r.fill?.writeProvenance ?? true,\n validateGraph: r.fill?.validateGraph ?? true,\n sections: r.fill?.sections ?? false,\n chunkChars: r.fill?.chunkChars ?? DEFAULT_CHUNK_CHARS,\n offline: r.fill?.offline ?? false,\n questions: { perPage: r.fill?.questions?.perPage ?? 3 },\n },\n embed: {\n model: r.embed?.model ?? DEFAULT_EMBED_MODEL,\n dtype: r.embed?.dtype ?? \"q8\",\n out: r.embed?.out,\n cacheDir: r.embed?.cacheDir ?? \".manni/graph/embed-cache\",\n byLanguage: r.embed?.byLanguage ?? {},\n },\n export: {\n iirds: {\n title: r.export?.iirds?.title,\n creator: r.export?.iirds?.creator,\n version: r.export?.iirds?.version ?? \"1.3\",\n },\n },\n configPath: abs,\n configDir: dir,\n };\n}\n\nconst CONFIG_FILE: ConfigFileOptions = {\n section: CONFIG_SECTION,\n // The tool was `dockg` before it joined the family (proposal 0051 §7), but\n // it published no config file under that old name, so — like cite, a11y and\n // docevals — there is no pre-family filename to read (proposal 0051 §2).\n legacyNames: [],\n toError: (message) => new GraphError(message),\n};\n\n/**\n * Load config from an explicit path, or discover the family file from the\n * working directory upward (`src/shared/config-file.ts`: `manni.config.yaml`\n * read at its `graph:` key). With no config file present, built-in defaults\n * apply.\n */\nexport function loadConfig(path?: string, cwd = process.cwd()): GraphConfig {\n const file = path\n ? readConfigFileSync(path, cwd, CONFIG_FILE)\n : findConfigFileSync(cwd, CONFIG_FILE);\n if (file === null) return defaultConfig(cwd);\n return parseConfigSection(file.value, file.path, {\n source: file.source,\n collections: file.collections,\n ...(file.providers === undefined ? {} : { providers: file.providers }),\n });\n}\n\n/**\n * Every built-in default, with no file behind it: what a run gets when\n * discovery finds nothing, or under `--no-config`. It declares no collections,\n * so such a run reads only the paths it was given.\n */\nexport function defaultConfig(cwd = process.cwd()): GraphConfig {\n return {\n ...parseConfigSection(null, resolve(cwd, DEFAULT_CONFIG_FILENAME)),\n configSource: null,\n };\n}\n\nexport interface RunConfigOptions {\n /** `-c/--config`. */\n configPath?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Positional paths; checked here only for how they combine with `collection`. */\n paths?: string[];\n /** `--collection <name>`, repeatable. */\n collection?: string[];\n}\n\n/**\n * The config a command runs under. `--collection` names something only a\n * config can define and selects a set the operator did not type, so pairing it\n * with paths is refused before discovery, and the message is about the flags\n * rather than about whatever the walk found.\n */\nexport function loadRunConfig(\n opts: RunConfigOptions,\n cwd = process.cwd(),\n): GraphConfig {\n assertCollectionWithoutPaths(opts.collection, opts.paths);\n return opts.noConfig ? defaultConfig(cwd) : loadConfig(opts.configPath, cwd);\n}\n\n/** The message meta, cite and docevals give, in graph's error class. */\nexport function assertCollectionWithoutPaths(\n collection: readonly string[] | undefined,\n paths: readonly string[] | undefined,\n): void {\n if ((collection ?? []).length > 0 && (paths ?? []).length > 0) {\n throw new GraphError(\n \"--collection selects a configured collection; it cannot be combined with paths.\",\n );\n }\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"manni:graph:config\",\n \"title\": \"manni graph configuration\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Which provider `manni graph fill` sends pages to: auto | anthropic | openai | claude-cli | llama-cpp. Unset, the family's top-level providers.provider decides, then auto, detected exactly as manni meta fill detects: an Anthropic key, then an OpenAI key, then the Claude CLI, then a local model. --provider wins over it, and --local overrides both. Connection settings live in the family's top-level providers: map.\"\n },\n \"model\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The model, within the provider named beside it. A model is carried only to the provider its own level names: a differing --provider or providers.provider takes its own default instead. With no provider here, it goes to whichever provider is in force, which must not be auto, because a model name does not say which provider owns it. Unset (the default) takes the provider's default model from the inference library; manni pins none. --model wins over it. This is not `embed.model`, which is a local embedding model id.\"\n },\n \"baseIri\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"out\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"questionFiles\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"description\": \"Golden-set files, relative to the config file. They hold questions that span pages or that the docs don't answer, and `check` asks them beside each page's sample-questions. Default none.\"\n },\n \"routes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"root\"],\n \"properties\": {\n \"basePath\": {\n \"type\": \"string\"\n },\n \"root\": {\n \"type\": \"string\"\n },\n \"extensions\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\.\"\n }\n },\n \"language\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Za-z]{2,3}(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*$\"\n },\n \"indexFiles\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n }\n }\n },\n \"build\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"derive\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n \"items\": {\n \"enum\": [\n \"frontmatter\",\n \"sections\",\n \"links\",\n \"tags\",\n \"images\",\n \"code\",\n \"provenance\",\n \"terms\"\n ]\n }\n }\n }\n },\n \"check\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"shapes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"questions\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"top\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"severity\": {\n \"enum\": [\"notice\", \"warning\", \"error\", \"off\"]\n },\n \"foundThreshold\": {\n \"anyOf\": [\n { \"type\": \"number\", \"minimum\": 0, \"maximum\": 100 },\n { \"type\": \"null\" }\n ],\n \"description\": \"`check` exits 1 when the percentage of reviewed questions found in the top `top` falls below this, 0-100. The same scale as stats.coverageThreshold. Null (the default) sets no rate gate. questions.severity does not touch it.\"\n }\n }\n }\n }\n },\n \"provenance\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"qualified\": {\n \"type\": \"boolean\"\n }\n }\n },\n \"stats\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"coverageThreshold\": {\n \"anyOf\": [\n {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"title\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"description\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"creator\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"created\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"modified\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"subject\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"label\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"language\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"type\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"applies-to\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"about-product-lifecycle\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"about-product-aspect\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n },\n \"sample-questions\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 100\n }\n }\n }\n ]\n }\n }\n },\n \"fill\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"temperature\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 2\n },\n \"maxTurns\": {\n \"type\": [\"integer\", \"null\"],\n \"minimum\": 1,\n \"description\": \"Stop after this many inference calls. One page is one turn, and a cached proposal spends none. Null (the default) is unbounded. Replaces the maxCostUsd ceiling, which read as zero for every model outside the library's price table — see graph ADR 01027 and docevals ADR 01019.\"\n },\n \"cacheDir\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"confidenceThreshold\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1,\n \"description\": \"Minimum model self-confidence (0..1) to write a proposed field; below it the field is reported and not written. Default 0.7. `--confidence` wins over it.\"\n },\n \"writeProvenance\": {\n \"type\": \"boolean\"\n },\n \"validateGraph\": {\n \"type\": \"boolean\"\n },\n \"fields\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n \"items\": {\n \"enum\": [\n \"label\",\n \"alt-labels\",\n \"broader\",\n \"narrower\",\n \"related-concepts\",\n \"concepts\",\n \"type\",\n \"applies-to\",\n \"about-product-lifecycle\",\n \"about-product-aspect\",\n \"not-applicable-to\",\n \"not-about-product-aspect\",\n \"sample-questions\"\n ]\n }\n },\n \"sections\": {\n \"type\": \"boolean\"\n },\n \"chunkChars\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"The largest body piece one question request sends. Default 12000, as meta fill's. `--chunk-chars` wins over it.\"\n },\n \"offline\": {\n \"type\": \"boolean\",\n \"description\": \"Send nothing off this machine: use only a local model that is already downloaded. Default false. `--offline` wins over it.\"\n },\n \"questions\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"perPage\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Draft until a page has this many sample questions, reviewed or drafted. Default 3.\"\n }\n }\n }\n }\n },\n \"embed\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"model\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"dtype\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"out\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"cacheDir\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"byLanguage\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"patternProperties\": {\n \"^[A-Za-z]{2,3}(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*$\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"model\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"dtype\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n }\n }\n }\n }\n },\n \"export\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"iirds\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"creator\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"version\": {\n \"enum\": [\"1.2\", \"1.3\"]\n }\n }\n }\n }\n }\n }\n}\n","/**\n * iiRDS Core + Software-domain term IRIs and the frontmatter-value → IRI maps\n * (ADR 01012). Every IRI here is byte-verified against the published\n * `iirds-core.rdf` / `iirds-software.rdf` in iirds-consortium/models. dockg\n * references these IRIs; it never redefines or re-types them (iiRDS is\n * CC BY-ND). This is the single source of truth shared by the schema\n * (via the schema-sync drift guard), derive, and shapes.\n */\nimport { NS } from \"./vocab.js\";\n\n/** Predicates (Core). */\nexport const IIRDS_HAS_TOPIC_TYPE = `${NS.iirds}has-topic-type`;\nexport const IIRDS_RELATES_TO_PRODUCT_VARIANT = `${NS.iirds}relates-to-product-variant`;\nexport const IIRDS_RELATES_TO_LIFECYCLE_PHASE = `${NS.iirds}relates-to-product-lifecycle-phase`;\nexport const IIRDS_HAS_SUBJECT = `${NS.iirds}has-subject`;\n\n/** Class minted for `graph.applies-to` nodes. */\nexport const IIRDS_PRODUCT_VARIANT = `${NS.iirds}ProductVariant`;\n\n/**\n * Package-serialization terms (iiRDS package export, ADR 01017). Local names\n * byte-verified against the canonical RDF/XML example in the published spec\n * (`sections/structure/serialization.md`). Used only by the package projection —\n * never emitted into the built graph. IUs are typed `iirds:Topic` (the subclass\n * that carries `has-topic-type`/`has-subject`), one of the valid IU subclasses.\n */\nexport const IIRDS_PACKAGE = `${NS.iirds}Package`;\nexport const IIRDS_IIRDS_VERSION = `${NS.iirds}iiRDSVersion`;\nexport const IIRDS_TOPIC = `${NS.iirds}Topic`;\nexport const IIRDS_IS_PART_OF_PACKAGE = `${NS.iirds}is-part-of-package`;\nexport const IIRDS_HAS_RENDITION = `${NS.iirds}has-rendition`;\nexport const IIRDS_RENDITION = `${NS.iirds}Rendition`;\nexport const IIRDS_SOURCE = `${NS.iirds}source`;\nexport const IIRDS_FORMAT = `${NS.iirds}format`;\nexport const IIRDS_TITLE = `${NS.iirds}title`;\nexport const IIRDS_LANGUAGE = `${NS.iirds}language`;\nexport const IIRDS_PARTY = `${NS.iirds}Party`;\nexport const IIRDS_HAS_PARTY_ROLE = `${NS.iirds}has-party-role`;\nexport const IIRDS_CREATOR = `${NS.iirds}Creator`;\nexport const IIRDS_RELATES_TO_PARTY = `${NS.iirds}relates-to-party`;\nexport const IIRDS_RELATES_TO_VCARD = `${NS.iirds}relates-to-vcard`;\n\n/** vcard namespace — package-local (not in the global NS/PREFIXES table). */\nexport const VCARD_NS = \"http://www.w3.org/2006/vcard/ns#\";\nexport const VCARD_ORGANIZATION = `${VCARD_NS}Organization`;\nexport const VCARD_ORGANIZATION_NAME = `${VCARD_NS}organization-name`;\n\n/**\n * Negative-scope predicates (ADR 01014). Minted into `graph:` — no standard\n * term exists, and OWL negative property assertions require blank nodes. Each\n * mirrors, and is SHACL-disjoint from, its positive counterpart above.\n */\nexport const GRAPH_NOT_APPLICABLE_TO_VARIANT = `${NS.graph}notApplicableToVariant`;\nexport const GRAPH_NOT_SOFTWARE_SUBJECT = `${NS.graph}notSoftwareSubject`;\n\n/**\n * Page-level `type` → `graph.type` (ADR 01024). The page's `type` is an open\n * vocabulary (docmeta:core); `graph.type` is the closed iiRDS enum. When the block\n * is silent, the page's value derives one through this map — an unmapped page\n * type derives nothing rather than inventing a topic type. An explicit\n * `graph.type` always wins: deeper wins, the page level is the fallback.\n */\nexport const PAGE_TYPE_TO_TOPIC_TYPE: Readonly<Record<string, string>> = {\n \"how-to\": \"task\",\n tutorial: \"learning\",\n explanation: \"concept\",\n reference: \"reference\",\n troubleshooting: \"troubleshooting\",\n};\n\n/** `graph.type` value → `iirds:has-topic-type` object IRI. */\nexport const TOPIC_TYPE_IRIS: Readonly<Record<string, string>> = {\n task: `${NS.iirds}GenericTask`,\n concept: `${NS.iirds}GenericConcept`,\n reference: `${NS.iirds}GenericReference`,\n learning: `${NS.iirds}GenericLearning`,\n troubleshooting: `${NS.iirds}GenericTroubleshooting`,\n form: `${NS.iirds}GenericForm`,\n};\n\n/**\n * `graph.about-product-lifecycle` value → `iirds:relates-to-product-lifecycle-phase`\n * object IRI (Software domain: iirds:Use/PuttingToUse/AfterUse instances).\n */\nexport const SOFTWARE_LIFECYCLE_IRIS: Readonly<Record<string, string>> = {\n administration: `${NS.iirdsSft}Administration`,\n customization: `${NS.iirdsSft}Customization`,\n update: `${NS.iirdsSft}Update`,\n deployment: `${NS.iirdsSft}Deployment`,\n integration: `${NS.iirdsSft}Integration`,\n deinstallation: `${NS.iirdsSft}Deinstallation`,\n};\n\n/**\n * `graph.about-product-aspect` value → `iirds:has-subject` object IRI (Software domain:\n * iirds:TechnicalOverview/TechnicalData instances).\n */\nexport const SOFTWARE_SUBJECT_IRIS: Readonly<Record<string, string>> = {\n architecture: `${NS.iirdsSft}Architecture`,\n interface: `${NS.iirdsSft}Interface`,\n \"system-requirement\": `${NS.iirdsSft}SystemRequirement`,\n};\n","/**\n * Metadata coverage fields (ADR 01011). Coverage answers the ADR 01008\n * question — what can a graph-side consumer see — by counting `graph:Document`\n * nodes that carry each predicate. The list is fixed and deliberate: a\n * predicate absent from every document still shows as 0%, which a dynamic\n * census could not surface. It is shared between the config parser (which\n * expands a uniform threshold across every field) and `manni graph stats` (which\n * reports and gates), and pinned by test/unit/schema-sync.ts against the\n * config schema so it cannot silently drift.\n */\nimport { NS } from \"./vocab.js\";\nimport {\n IIRDS_HAS_SUBJECT,\n IIRDS_HAS_TOPIC_TYPE,\n IIRDS_RELATES_TO_LIFECYCLE_PHASE,\n IIRDS_RELATES_TO_PRODUCT_VARIANT,\n} from \"./iirds.js\";\n\nexport interface CoverageField {\n /** Config/report key. */\n field: string;\n /** Full predicate IRI counted against `graph:Document` subjects. */\n iri: string;\n /**\n * Gated only when the per-field `coverageThreshold` map names it. A uniform\n * threshold, from config or `--coverage-threshold`, leaves it ungated, so a\n * gate that passed before the row existed keeps passing (proposal 0087).\n */\n namedOnly?: true;\n}\n\n/**\n * Report order is this array's order. Only the IRI is stored; the compact form\n * shown in the report is derived from it with `compactIri`, so there is one\n * source of truth for the namespace.\n */\nexport const COVERAGE_FIELDS: readonly CoverageField[] = [\n { field: \"title\", iri: `${NS.dcterms}title` },\n { field: \"description\", iri: `${NS.dcterms}description` },\n { field: \"creator\", iri: `${NS.dcterms}creator` },\n { field: \"created\", iri: `${NS.dcterms}created` },\n { field: \"modified\", iri: `${NS.dcterms}modified` },\n { field: \"subject\", iri: `${NS.dcterms}subject` },\n { field: \"label\", iri: `${NS.foaf}primaryTopic` },\n // Dropped by ADR 01011 as \"near-universally 0% noise\", which was true on the\n // monolingual corpora it was measured against and false the moment language\n // means something. Restored by ADR 01037, which made it a scope dimension:\n // an unlabelled document in a translated corpus cannot be filtered, indexed\n // per locale, or counted against the right audience.\n { field: \"language\", iri: `${NS.dcterms}language` },\n // The iiRDS typing added in Phases 2–4. Coverage predates all of it, so the\n // measure of \"what a graph-side consumer can see\" was silent about the\n // vocabulary the project spent four phases adding (ADR 01029).\n { field: \"type\", iri: IIRDS_HAS_TOPIC_TYPE },\n { field: \"applies-to\", iri: IIRDS_RELATES_TO_PRODUCT_VARIANT },\n {\n field: \"about-product-lifecycle\",\n iri: IIRDS_RELATES_TO_LIFECYCLE_PHASE,\n },\n { field: \"about-product-aspect\", iri: IIRDS_HAS_SUBJECT },\n // Pages with a reader question (proposal 0087). Gated only by name.\n { field: \"sample-questions\", iri: `${NS.graph}sampleQuestion`, namedOnly: true },\n];\n\n/**\n * Section-level coverage: the fields a `graph.sections` block can attach\n * (ADR 01013), measured over `graph:Section` nodes.\n *\n * Sections are explicit-only — a section gets exactly what its own block\n * declares and nothing from its document — so these numbers are low by\n * construction on most corpora. That is the point: the granularity golden rule\n * says content granularity must match node granularity, and this is the number\n * that says whether it does.\n *\n * `label` is absent deliberately: ADR 01013 rejected `prefLabel` at section\n * level as meaningless, so it cannot be missing.\n */\n/** Section-attachable field NAMES; the IRIs come from COVERAGE_FIELDS, so a\n * namespace revision cannot move one table and not the other. */\nconst SECTION_FIELD_NAMES: readonly string[] = [\n \"type\",\n \"applies-to\",\n \"about-product-lifecycle\",\n \"about-product-aspect\",\n \"subject\",\n];\n\nexport const SECTION_COVERAGE_FIELDS: readonly CoverageField[] =\n SECTION_FIELD_NAMES.map((name) => {\n const field = COVERAGE_FIELDS.find((f) => f.field === name);\n /* c8 ignore next 3 -- unreachable while the two lists agree, which the\n drift guard in test/unit/schema-sync.test.ts keeps true. */\n if (field === undefined) {\n throw new Error(\n `SECTION_FIELD_NAMES names ${name}, which COVERAGE_FIELDS does not define`,\n );\n }\n return field;\n });\n\n/** The measured field names, in report order. */\nexport const COVERAGE_FIELD_NAMES: readonly string[] = COVERAGE_FIELDS.map(\n (f) => f.field,\n);\n\n/** The fields a uniform coverage threshold gates: all but the `namedOnly` ones. */\nexport const UNIFORM_COVERAGE_FIELD_NAMES: readonly string[] = COVERAGE_FIELDS.flatMap(\n (f) => (f.namedOnly ? [] : [f.field]),\n);\n\n/**\n * The two negative predicates (ADR 01014) are deliberately not measured.\n *\n * Coverage answers \"what can a consumer see that the author lifted\". A document\n * with no `not-applicable-to` is not under-annotated — under open-world\n * semantics its absence means *unknown*, which is the normal and correct state\n * for almost every document. Counting it as a gap would put every healthy\n * corpus permanently near zero on two rows and teach readers to ignore the\n * table.\n */\nexport const UNMEASURED_BY_DESIGN: readonly string[] = [\n \"not-applicable-to\",\n \"not-about-product-aspect\",\n];\n","/**\n * The embedder seam (ADR 01020). Platform-neutral and dependency-free, so the\n * runtime and the CLI can both speak it without either pulling in a model.\n *\n * Everything that computes embeddings — the local transformers.js embedder, the\n * deterministic mock, or a host's own — implements `Embedder`.\n */\n\nexport interface Embedder {\n /** Stable identity of the model; recorded in the sidecar header. */\n readonly model: string;\n /** Weight quantization the vectors were produced under. */\n readonly dtype: string;\n /** Output dimensions. Never assumed by callers — always read from here. */\n readonly dims: number;\n /**\n * Embed one text. Single-text rather than batched **on purpose**: float\n * addition is not associative, so a batched vector depends on what it was\n * batched with, and adding one document would perturb its neighbours' vectors\n * (ADR 01020). Determinism is worth more here than throughput.\n */\n embed(text: string): Promise<Float32Array>;\n}\n\n/**\n * A model's quirks, applied on both the build and query sides so a user cannot\n * get them wrong. Some models require a prefix on queries and/or passages and\n * degrade *silently* without it.\n */\nexport interface ModelProfile {\n /** Hugging Face repo id. */\n id: string;\n /** Prepended when embedding a search query. */\n queryPrefix?: string;\n /** Prepended when embedding indexed content. */\n passagePrefix?: string;\n /** Human note surfaced in docs and `--help`. */\n note?: string;\n}\n\n/** What a text is being embedded *for* — decides which prefix applies. */\nexport type EmbedRole = \"query\" | \"passage\";\n\n/**\n * Models dockg has been tested against. This is the *tested* set, not the\n * permitted set: `embed.model` accepts any id, and an unknown one is used\n * as-is with no prefixes.\n */\n/**\n * The default, named rather than found at index 0: `DEFAULT_MODEL` below then\n * reads it directly instead of asserting that the list has a first element.\n */\nconst DEFAULT_PROFILE: ModelProfile = {\n id: \"onnx-community/granite-embedding-small-english-r2-ONNX\",\n note: \"Default. 384-d, 8192-token context so sections are never truncated; no prefixes.\",\n};\n\nexport const MODEL_PROFILES: readonly ModelProfile[] = [\n DEFAULT_PROFILE,\n {\n id: \"Xenova/gte-small\",\n note: \"Lighter (~34 MB). 384-d, 512-token context; no prefixes.\",\n },\n {\n id: \"Xenova/bge-small-en-v1.5\",\n queryPrefix: \"Represent this sentence for searching relevant passages: \",\n note: \"384-d. Needs a query prefix — applied automatically here, since omitting it degrades retrieval silently.\",\n },\n {\n id: \"Xenova/all-MiniLM-L6-v2\",\n note: \"Smallest (~23 MB) but truncates at 256 wordpieces (~190 words), so long sections lose their tail.\",\n },\n];\n\nexport const DEFAULT_MODEL = DEFAULT_PROFILE.id;\n\n/** The profile for a model id, or a bare profile when it is not a tested one. */\nexport function profileFor(id: string): ModelProfile {\n return MODEL_PROFILES.find((p) => p.id === id) ?? { id };\n}\n\n/** Apply the model's prefix convention for the role, if it has one. */\nexport function withPrefix(\n profile: ModelProfile,\n role: EmbedRole,\n text: string,\n): string {\n const prefix = role === \"query\" ? profile.queryPrefix : profile.passagePrefix;\n return prefix ? `${prefix}${text}` : text;\n}\n","/**\n * Document analysis: one source file → a `DocModel`. Metadata comes from the\n * metadata tool's extractor (the same one `manni meta validate` reads a page\n * with). Markdown and MDX body structure (headings, links, images, code\n * fences) comes from a remark/mdast walk in document order; every other format\n * comes from lint's section tree (proposal 0077 §2).\n */\nimport { createHash } from \"node:crypto\";\nimport { extname } from \"node:path\";\nimport { unified } from \"unified\";\nimport remarkParse from \"remark-parse\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkFrontmatter from \"remark-frontmatter\";\nimport remarkMdx from \"remark-mdx\";\nimport { toString as mdastToString } from \"mdast-util-to-string\";\nimport GithubSlugger from \"github-slugger\";\nimport {\n extractFrontmatter,\n extractorForExtension,\n type MetadataExtractor,\n} from \"../../meta/index.js\";\nimport { parserByName, parserForExtension } from \"../../lint/parsers/index.js\";\nimport type {\n ContentNode,\n DocumentTree,\n SectionNode,\n} from \"../../lint/types.js\";\nimport type { Root, RootContent, Definition } from \"mdast\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { GraphError } from \"../types.js\";\nimport type { DocImage, DocLink, DocModel, Section } from \"../types.js\";\nimport {\n DEFAULT_INDEX_FILES,\n DEFAULT_LINK_EXTENSIONS,\n type RouteMapping,\n} from \"./config.js\";\nimport { normalizeDocPath } from \"./iri.js\";\n\n/** The formats graph parses, as `--as` names them: lint's parser names. */\nexport const DOC_FORMATS = [\n \"asciidoc\",\n \"html\",\n \"markdown\",\n \"mdx\",\n \"rst\",\n \"xml\",\n] as const;\nexport type DocFormat = (typeof DOC_FORMATS)[number];\n/** The formats read through lint's tree rather than graph's mdast walk. */\nexport type TreeFormat = Exclude<DocFormat, \"markdown\" | \"mdx\">;\n\nexport function isTreeFormat(format: DocFormat): format is TreeFormat {\n return format !== \"markdown\" && format !== \"mdx\";\n}\n\nexport function isDocFormat(name: string): name is DocFormat {\n return (DOC_FORMATS as readonly string[]).includes(name);\n}\n\n/**\n * The format a page parses as: `format` (`--as`) when given, else the lint\n * parser claiming its extension. An extension nobody claims reaches here only\n * through `--ext`, and reads as markdown, as every page did before 0077.\n */\nexport function formatOf(path: string, format?: DocFormat): DocFormat {\n if (format !== undefined) return format;\n const name = parserForExtension(extname(path))?.name;\n return name !== undefined && isDocFormat(name) ? name : \"markdown\";\n}\n\nexport interface AnalyzeOptions {\n /** Site-route mappings for resolving root-absolute links. */\n routes?: RouteMapping[];\n /** `--as`: parse as this format whatever the path says. Absent, see `formatOf`. */\n format?: DocFormat;\n /**\n * How the body is parsed. Absent, `parseBody`. `graph build` passes a cache's\n * `parse` here, which returns what `parseBody` would (`analyze-cache.ts`).\n */\n parse?: (content: string, path: string, format: DocFormat) => DocBody;\n}\n\n/**\n * What a page's body yields before anything else in the corpus is consulted:\n * headings, and link and image targets as written, in document order.\n *\n * A pure function of the bytes and the format, so it can be cached across\n * runs. Resolving a target needs the rest of the corpus and the routes, so\n * that happens after, in `analyzeDoc`.\n */\nexport interface DocBody {\n firstH1?: string;\n sections: Section[];\n /** Raw link targets: links, resolved link references, and JSX `href`s. */\n linkTargets: string[];\n /** Raw image targets: images, resolved image references, and JSX `src`s. */\n imageTargets: string[];\n /** Code fence languages, sorted and distinct. */\n codeLanguages: string[];\n}\n\nconst processor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkFrontmatter, [\"yaml\", \"toml\"]);\n\n/**\n * MDX gets its own processor, selected by extension (ADR 01022). It cannot be\n * the default: MDX reads `{` as an expression delimiter, so ordinary Markdown\n * prose containing braces would become a syntax error.\n */\nconst mdxProcessor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkFrontmatter, [\"yaml\", \"toml\"])\n .use(remarkMdx);\n\n/** MDX JSX attribute, narrowed to the literal-string case we can act on. */\ninterface JsxAttribute {\n type: string;\n name?: string;\n value?: unknown;\n}\n\n/**\n * Elements whose `src` is an image.\n *\n * `href` is HTML's hyperlink attribute wherever it appears, so reading it from\n * any element only ever yields an extra edge. `src` is not analogous: it is the\n * generic external-resource attribute, shared by `iframe`, `video`, `script`,\n * `audio`, `source`, and `embed`. Emitting `schema:image` for a video embed or\n * an analytics script would be a wrong *type* assertion rather than a merely\n * extra one, so `src` is read only where it means an image (ADR 01022).\n */\nconst IMAGE_ELEMENTS = new Set([\"img\", \"image\"]);\n\n/**\n * The value of a JSX attribute, when it is a plain string literal.\n *\n * An expression attribute (`href={route}`) yields undefined rather than a\n * guess: its value is not knowable without evaluating the module, and a wrong\n * edge asserted confidently is worse than an absent one.\n */\nfunction jsxAttributeValue(\n node: unknown,\n attributeName: string,\n): string | undefined {\n const attributes = (node as { attributes?: JsxAttribute[] }).attributes;\n if (!Array.isArray(attributes)) return undefined;\n for (const attribute of attributes) {\n if (attribute.type !== \"mdxJsxAttribute\") continue;\n if (attribute.name !== attributeName) continue;\n return typeof attribute.value === \"string\" ? attribute.value : undefined;\n }\n return undefined;\n}\n\n/** True when the target has a URI scheme (http:, https:, mailto:, ...). */\nexport function hasScheme(target: string): boolean {\n return /^[a-z][a-z0-9+.-]*:/i.test(target);\n}\n\n/**\n * Resolve a relative link target against the linking doc's directory using\n * pure string math (posix, OS-independent). Returns null when the target\n * escapes the corpus root. A page labelled above the root (`../docs/a.md`)\n * already climbs, so its leading `..` segments are kept, never popped as if\n * they were directories, and its links may climb further.\n */\nexport function resolveRelative(\n docPath: string,\n target: string,\n): string | null {\n const baseSegments = normalizeDocPath(docPath).split(\"/\").slice(0, -1);\n const segments = [...baseSegments];\n for (const part of target.split(\"/\")) {\n if (part === \"\" || part === \".\") continue;\n if (part === \"..\") {\n if (segments.length === 0) return null;\n if (segments[segments.length - 1] === \"..\") segments.push(\"..\");\n else segments.pop();\n } else {\n segments.push(part);\n }\n }\n return segments.join(\"/\");\n}\n\nconst HAS_EXTENSION = /\\.[a-z0-9]+$/i;\n\n/**\n * Whether a link target addresses a *document* at all (ADR 01033).\n *\n * An extension list declares what documents look like in a corpus. A target\n * carrying some other explicit extension — `/manni/graph/ns.ttl`, `./dist.zip`, a\n * linked PDF — is a static asset the site serves, not a document dockg failed\n * to find, and reporting it as a broken link produces a finding the author\n * cannot act on: there is no `.md` they could add to fix it.\n *\n * Extensionless and directory targets stay in scope, so a genuine typo in a\n * pretty URL is still caught.\n */\nfunction addressesDocument(target: string, extensions: string[]): boolean {\n if (target === \"\" || !HAS_EXTENSION.test(target)) return true;\n // No configured extensions means the mapping has declared nothing about what\n // its documents look like — so there is no list to judge the target against,\n // and the narrowing does not apply. Gating on an empty list would answer \"no\"\n // to every extension-bearing target and skip genuinely broken `.md` links,\n // turning a narrowing into a way to switch the check off. `extensions: []` is\n // schema-valid (no minItems), so this is reachable config, not a theoretical.\n if (extensions.length === 0) return true;\n const ext = target.slice(target.lastIndexOf(\".\")).toLowerCase();\n return extensions.some((e) => e.toLowerCase() === ext);\n}\n\n/** Slug normalization for route matching: lowercase, dashes/underscores stripped. */\nfunction slugNorm(path: string): string {\n return path.toLowerCase().replace(/[-_]/g, \"\");\n}\n\n/**\n * Tiered lookup over the corpus: exact path, then case-insensitive, then\n * slug-normalized (published slugs are often kebab-cased versions of\n * camelCase filenames, e.g. Fern's /stop-record for stopRecord.mdx).\n * Ambiguous fallback matches (two files normalizing identically) stay\n * unresolved rather than guessing.\n */\nclass PathIndex {\n private readonly lower = new Map<string, string | null>();\n private readonly slugged = new Map<string, string | null>();\n\n constructor(private readonly exact: ReadonlySet<string>) {\n for (const path of exact) {\n const lower = path.toLowerCase();\n this.lower.set(lower, this.lower.has(lower) ? null : path);\n const slug = slugNorm(path);\n this.slugged.set(slug, this.slugged.has(slug) ? null : path);\n }\n }\n\n resolve(candidate: string): string | undefined {\n if (this.exact.has(candidate)) return candidate;\n return (\n this.lower.get(candidate.toLowerCase()) ??\n this.slugged.get(slugNorm(candidate)) ??\n undefined\n );\n }\n}\n\n/** decodeURIComponent that falls back to the raw string on malformed input. */\nfunction safeDecode(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\n/**\n * Candidate repo paths for an extensionless (or extension-bearing) link\n * target. Shared by route and relative resolution so both link forms resolve\n * identically: an explicit extension is taken verbatim; a trailing slash\n * prefers the directory's index files but falls back to extension candidates\n * (pretty URLs — Hugo/Docusaurus serve foo.md at /foo/); otherwise extensions\n * are tried before index files.\n */\nfunction targetCandidates(\n target: string,\n isDirectory: boolean,\n extensions: string[],\n indexFiles: string[],\n): string[] {\n if (target !== \"\" && HAS_EXTENSION.test(target)) return [target];\n const extensionCandidates =\n target === \"\" ? [] : extensions.map((ext) => `${target}${ext}`);\n const dir = target === \"\" ? \"\" : `${target}/`;\n const indexCandidates: string[] = [];\n for (const indexFile of indexFiles) {\n for (const ext of extensions)\n indexCandidates.push(`${dir}${indexFile}${ext}`);\n }\n return isDirectory\n ? [...indexCandidates, ...extensionCandidates]\n : [...extensionCandidates, ...indexCandidates];\n}\n\n/**\n * The language labelling a source path, from the nearest enclosing route\n * mapping that declares one (ADR 01037).\n *\n * \"Nearest\" is the longest matching `root`, so a `docs/de` mapping beats a\n * `docs` one for a file under both. A mapping that declares no language is\n * transparent rather than blocking: `{root: docs, language: en}` plus\n * `{root: docs/api}` still labels `docs/api/x.md` as English, the way a nested\n * directory inherits the setting of its parent.\n */\nexport function routeLanguageFor(\n path: string,\n routes: readonly RouteMapping[],\n): string | undefined {\n let best: { root: string; language: string } | undefined;\n for (const mapping of routes) {\n if (mapping.language === undefined) continue;\n const root = mapping.root;\n const covers = root === \"\" || path === root || path.startsWith(`${root}/`);\n if (!covers) continue;\n if (best === undefined || root.length > best.root.length) {\n best = { root, language: mapping.language };\n }\n }\n return best?.language;\n}\n\n/**\n * Resolve a root-absolute route (`/docs/actions/find`) to a source file via\n * the configured mappings. Returns the repo path, \"broken\" when a mapping's\n * basePath matched but no candidate file exists, or null when no mapping\n * covers the route.\n */\nfunction resolveRoute(\n pathPart: string,\n routes: RouteMapping[],\n index: PathIndex,\n): string | null {\n const isDirectory = /\\/+$/.test(pathPart);\n const clean = safeDecode(pathPart).replace(/\\/+$/, \"\");\n let anyMatched = false;\n for (const mapping of routes) {\n if (\n clean !== mapping.basePath &&\n !clean.startsWith(`${mapping.basePath}/`)\n ) {\n continue;\n }\n // Matched the basePath, but this mapping's documents do not carry that\n // extension — so the mapping says nothing about this target. Leave\n // `anyMatched` alone: another mapping may still claim it, and if none\n // does the caller skips the link rather than calling it broken.\n const rest = clean.slice(mapping.basePath.length).replace(/^\\/+/, \"\");\n if (!addressesDocument(rest, mapping.extensions)) continue;\n anyMatched = true;\n const prefix = mapping.root ? `${mapping.root}/` : \"\";\n // Bare basePath targets the root directory itself (index files only).\n const stem = rest === \"\" ? mapping.root : `${prefix}${rest}`;\n const candidates = targetCandidates(\n stem,\n isDirectory || rest === \"\",\n mapping.extensions,\n mapping.indexFiles,\n );\n for (const candidate of candidates) {\n const resolved = index.resolve(candidate);\n if (resolved) return resolved;\n }\n }\n return anyMatched ? \"broken\" : null;\n}\n\n/** One PathIndex per corpus set — analyzeDoc is called once per doc over the same set. */\nconst indexCache = new WeakMap<ReadonlySet<string>, PathIndex>();\n\nfunction pathIndexFor(allPaths: ReadonlySet<string>): PathIndex {\n let index = indexCache.get(allPaths);\n if (!index) {\n index = new PathIndex(allPaths);\n indexCache.set(allPaths, index);\n }\n return index;\n}\n\nfunction classifyLink(\n docPath: string,\n rawTarget: string,\n allPaths: ReadonlySet<string>,\n routes: RouteMapping[],\n): DocLink | null {\n const raw = rawTarget;\n if (hasScheme(raw)) {\n try {\n return { raw, kind: \"external\", url: new URL(raw).href };\n } catch {\n // Scheme-bearing but unparseable — example junk, not a link. Skip.\n return null;\n }\n }\n const hashAt = raw.indexOf(\"#\");\n const pathPart = hashAt === -1 ? raw : raw.slice(0, hashAt);\n const anchor = hashAt === -1 ? undefined : raw.slice(hashAt + 1);\n if (pathPart === \"\") return null; // same-document anchor\n // Site-root-absolute URLs (/docs/x/) are published-site routes. With route\n // mappings configured they resolve to source files (or count as broken when\n // a mapped basePath has no matching file); unmapped routes are skipped.\n if (pathPart.startsWith(\"/\")) {\n const resolved = resolveRoute(pathPart, routes, pathIndexFor(allPaths));\n if (resolved === null) return null;\n if (resolved === \"broken\") return { raw, kind: \"broken\" };\n const link: DocLink = { raw, kind: \"internal\", resolvedPath: resolved };\n if (anchor) link.anchor = anchor;\n return link;\n }\n const resolved = resolveRelative(docPath, safeDecode(pathPart));\n if (resolved !== null) {\n const index = pathIndexFor(allPaths);\n let candidates: string[];\n if (allPaths.has(resolved)) {\n candidates = [resolved];\n } else if (HAS_EXTENSION.test(resolved)) {\n // Exact-or-broken — unless the extension is not a document extension at\n // all, in which case it is an asset and no document was ever addressed\n // (ADR 01033). Checked after `allPaths`, so an asset that IS in the\n // corpus still links.\n if (!addressesDocument(resolved, DEFAULT_LINK_EXTENSIONS)) return null;\n candidates = [];\n } else {\n candidates = targetCandidates(\n resolved,\n pathPart.endsWith(\"/\"),\n DEFAULT_LINK_EXTENSIONS,\n DEFAULT_INDEX_FILES,\n );\n }\n for (const candidate of candidates) {\n const hit = index.resolve(candidate);\n if (hit) {\n const link: DocLink = { raw, kind: \"internal\", resolvedPath: hit };\n if (anchor) link.anchor = anchor;\n return link;\n }\n }\n }\n return { raw, kind: \"broken\" };\n}\n\nfunction classifyImage(docPath: string, rawTarget: string): DocImage {\n if (hasScheme(rawTarget)) {\n return { raw: rawTarget, target: rawTarget, external: true };\n }\n const resolved = resolveRelative(docPath, rawTarget);\n return { raw: rawTarget, target: resolved ?? rawTarget, external: false };\n}\n\n/**\n * meta's extractor for a non-Markdown format. Lint's parser names are meta's\n * extractor names, so the parser's own extension finds the extractor under\n * `--as` too, where the path's would not.\n */\nexport function extractorFor(format: TreeFormat): MetadataExtractor | undefined {\n return extractorForExtension(parserByName(format)?.extensions[0] ?? \"\");\n}\n\n/**\n * A page's own metadata, as `manni meta validate` reads it. `build` reads a\n * page with it and `fill` reads what a page already holds with it, so the two\n * cannot disagree about a format.\n */\nexport function metadataOf(\n content: string,\n path: string,\n format: DocFormat,\n): { data: Record<string, unknown>; present: boolean } {\n try {\n const meta =\n format === \"markdown\" || format === \"mdx\"\n ? extractFrontmatter(content, \"markdown\")\n : extractorFor(format)?.extract(content, path);\n return meta === undefined\n ? { data: {}, present: false }\n : { data: meta.data, present: meta.present };\n } catch (error) {\n // The extractor knows the bytes, not the file. Left as it is, build and\n // fill would report a YAML error with no hint of which page carries it.\n throw new GraphError(`${path}: ${errorMessage(error)}`);\n }\n}\n\n/** Analyze one document. `allPaths` is the discovered corpus for link resolution. */\nexport function analyzeDoc(\n content: string,\n relPath: string,\n allPaths: ReadonlySet<string>,\n options: AnalyzeOptions = {},\n): DocModel {\n const routes = options.routes ?? [];\n const path = normalizeDocPath(relPath);\n const format = formatOf(path, options.format);\n const parse = options.parse ?? parseBody;\n // A tree format is parsed first, so a malformed page is reported as a parse\n // failure rather than as whatever the metadata reader tripped on. Markdown\n // keeps its order: its parse cannot fail where its frontmatter can.\n let body = isTreeFormat(format) ? parse(content, path, format) : undefined;\n const meta = metadataOf(content, path, format);\n body ??= parse(content, path, format);\n\n const links: DocLink[] = [];\n for (const target of body.linkTargets) {\n const link = classifyLink(path, target, allPaths, routes);\n if (link) links.push(link);\n }\n const routeLanguage = routeLanguageFor(path, routes);\n\n return {\n path,\n frontmatter: meta.data,\n frontmatterPresent: meta.present,\n format,\n firstH1: body.firstH1,\n sections: body.sections,\n links,\n images: body.imageTargets.map((target) => classifyImage(path, target)),\n codeLanguages: body.codeLanguages,\n // Omitted rather than set to undefined, so a doc under no localized route\n // carries no key at all — `routeLanguage` in JSON output means something.\n ...(routeLanguage === undefined ? {} : { routeLanguage }),\n // Over the content as read — line endings included, so the digest is\n // byte-faithful and equals `sha256sum <file>` for any valid-UTF-8 file\n // (ADR 01036). The CRLF corpus fixture depends on this not normalizing.\n contentHash: createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\"),\n };\n}\n\n/** Parse a page's body into its `DocBody`. `path` only names the page in an error. */\nexport function parseBody(\n content: string,\n path: string,\n format: DocFormat,\n): DocBody {\n if (isTreeFormat(format)) return parseTreeBody(content, path, format);\n const isMdx = format === \"mdx\";\n let tree: Root;\n try {\n tree = (isMdx ? mdxProcessor : processor).parse(content);\n } catch (error) {\n // Parsing MDX makes parse *failures* possible where Markdown had none:\n // remark-parse accepts anything, the MDX extension does not. Left raw, the\n // micromark throw escapes cli.ts's `fail()` — which only converts\n // GraphError — so the CLI dumps a stack trace, exits 1 (the code the\n // contract reserves for findings), and never names the file. Convert it.\n if (!isMdx) throw error;\n const reason = errorMessage(error);\n throw new GraphError(`Could not parse MDX in ${path}: ${reason}`);\n }\n\n const sections: Section[] = [];\n const linkTargets: string[] = [];\n const imageTargets: string[] = [];\n const codeLanguages = new Set<string>();\n const definitions = new Map<string, Definition>();\n let firstH1: string | undefined;\n\n // First pass: collect reference-link definitions.\n visit(tree, (node) => {\n if (node.type === \"definition\") {\n const def = node;\n definitions.set(def.identifier, def);\n }\n });\n\n const slugger = new GithubSlugger();\n /** Stack of open sections: [level, slug]. */\n const stack: Array<{ level: number; slug: string }> = [];\n /** Child counters keyed by parent slug (\"\" = document). */\n const childCount = new Map<string, number>();\n\n visit(tree, (node) => {\n switch (node.type) {\n case \"heading\": {\n const level = (node as { depth: number }).depth;\n const title = mdastToString(node);\n const slug = slugger.slug(title);\n if (level === 1 && firstH1 === undefined) firstH1 = title;\n // Reading the top frame *is* the emptiness test, so what the loop pops\n // is what the loop looked at.\n for (\n let top = stack.at(-1);\n top !== undefined && top.level >= level;\n top = stack.at(-1)\n ) {\n stack.pop();\n }\n const parentSlug = stack.at(-1)?.slug ?? null;\n const parentKey = parentSlug ?? \"\";\n const order = (childCount.get(parentKey) ?? 0) + 1;\n childCount.set(parentKey, order);\n sections.push({ slug, title, level, order, parentSlug });\n stack.push({ level, slug });\n break;\n }\n case \"link\": {\n linkTargets.push((node as { url: string }).url);\n break;\n }\n case \"linkReference\": {\n const def = definitions.get(\n (node as { identifier: string }).identifier,\n );\n if (def) linkTargets.push(def.url);\n break;\n }\n case \"image\": {\n imageTargets.push((node as { url: string }).url);\n break;\n }\n case \"imageReference\": {\n const def = definitions.get(\n (node as { identifier: string }).identifier,\n );\n if (def) imageTargets.push(def.url);\n break;\n }\n case \"code\": {\n const lang = (node as { lang?: string | null }).lang;\n if (lang) codeLanguages.add(lang);\n break;\n }\n // A JSX element's `href` is a link and its `src` is an image, on any\n // element (ADR 01022). Those are HTML's own names for the relationships,\n // so this stays structural — dockg never learns what `<LinkCard>` means.\n case \"mdxJsxFlowElement\":\n case \"mdxJsxTextElement\": {\n const href = jsxAttributeValue(node, \"href\");\n if (href !== undefined) linkTargets.push(href);\n const name = (node as { name?: string | null }).name ?? \"\";\n if (IMAGE_ELEMENTS.has(name.toLowerCase())) {\n const src = jsxAttributeValue(node, \"src\");\n if (src !== undefined) imageTargets.push(src);\n }\n break;\n }\n }\n });\n\n return {\n firstH1,\n sections,\n linkTargets,\n imageTargets,\n codeLanguages: [...codeLanguages].sort(),\n };\n}\n\n/**\n * Lint's tree for `content`, parsed as `format`. A parser's throw names the\n * format and the file, and exits 2, as an MDX parse failure does.\n */\nexport function parseTree(\n content: string,\n path: string,\n format: TreeFormat,\n): DocumentTree {\n const parser = parserByName(format);\n if (parser === undefined) {\n throw new GraphError(`No parser reads ${format}.`);\n }\n try {\n return parser.parse(content, path);\n } catch (error) {\n throw new GraphError(\n `Could not parse ${format} in ${path}: ${errorMessage(error)}`,\n );\n }\n}\n\n/**\n * Characters an IRI fragment accepts unchanged: the XML NCName set plus `:`,\n * which covers HTML ids, DITA `@id`, `xml:id`, Asciidoctor's `_install` and\n * Sphinx labels. Anything else is slugged, because a section IRI is never\n * percent-encoded.\n */\nconst IRI_SAFE_ID = /^[A-Za-z_][A-Za-z0-9_.:-]*$/;\n\n/** The sections minted from a lint tree, and the content each one owns. */\nexport interface TreeSections {\n sections: Section[];\n /** The content each section owns, parallel to `sections`. */\n owned: ContentNode[][];\n /** The lint node each section was minted from, parallel to `sections`. */\n nodes: SectionNode[];\n /** Content no minted section owns: the lead's, and a skipped heading's. */\n unowned: ContentNode[];\n firstH1: string | undefined;\n}\n\n/**\n * Mint graph sections from lint's tree, in document order. `analyzeDoc` and\n * the search index both call it, so their anchors agree.\n *\n * The anchor is the source's own id verbatim when it is IRI-safe, so a link\n * written to `#GUID-A1B2-C3D4` reaches the section; else the slugged title.\n * Ids and slugs share one namespace per document, so a duplicate of either\n * kind gains a `-N` suffix rather than merging two sections into one node.\n *\n * The level-0 lead, a heading lint made from a metadata title, and an\n * untitled heading (a DITA map's `topicref` without a navtitle) are not\n * sections. Each is transparent: its content belongs to the document, and its\n * subsections nest under its own parent, as Markdown's do under no heading.\n */\nexport function mintTreeSections(roots: SectionNode[]): TreeSections {\n const out: TreeSections = {\n sections: [],\n owned: [],\n nodes: [],\n unowned: [],\n firstH1: undefined,\n };\n const slugger = new GithubSlugger();\n const taken = new Set<string>();\n const childCount = new Map<string, number>();\n\n const anchorFor = (node: SectionNode): string => {\n const id = node.id;\n // `prov.` fragments are the provenance nodes' (derive.ts), minted with a\n // dot precisely because a slug never holds one. A verbatim id may.\n if (id !== undefined && IRI_SAFE_ID.test(id) && !id.startsWith(\"prov.\")) {\n let anchor = id;\n for (let n = 1; taken.has(anchor); n++) anchor = `${id}-${String(n)}`;\n taken.add(anchor);\n return anchor;\n }\n // The slugger dedupes against its own output only, so a slug an earlier\n // verbatim id took is asked for again until it is free. Each call advances\n // the slugger's suffix (-1, -2, ...), which is what ends the loop.\n let anchor = slugger.slug(node.title);\n while (taken.has(anchor)) anchor = slugger.slug(node.title);\n taken.add(anchor);\n return anchor;\n };\n\n const walk = (nodes: SectionNode[], parentSlug: string | null): void => {\n for (const node of nodes) {\n if (node.level === 0 || node.synthetic || node.title.trim() === \"\") {\n out.unowned.push(...node.children);\n walk(node.sections, parentSlug);\n continue;\n }\n const slug = anchorFor(node);\n if (node.level === 1 && out.firstH1 === undefined) {\n out.firstH1 = node.title;\n }\n const parentKey = parentSlug ?? \"\";\n const order = (childCount.get(parentKey) ?? 0) + 1;\n childCount.set(parentKey, order);\n out.sections.push({\n slug,\n title: node.title,\n level: node.level,\n order,\n parentSlug,\n });\n out.owned.push(node.children);\n out.nodes.push(node);\n walk(node.sections, slug);\n }\n };\n walk(roots, null);\n return out;\n}\n\n/** Every content node, nested ones included, in document order. */\nfunction eachContent(\n nodes: readonly ContentNode[],\n fn: (node: ContentNode) => void,\n): void {\n for (const node of nodes) {\n fn(node);\n switch (node.kind) {\n case \"list\":\n for (const item of node.items) eachContent(item.children, fn);\n break;\n case \"table\":\n for (const row of node.children) {\n for (const cell of row.children) eachContent(cell.children, fn);\n }\n break;\n case \"definitionList\":\n for (const item of node.children) eachContent(item.definition, fn);\n break;\n case \"admonition\":\n case \"blockquote\":\n case \"element\":\n eachContent(node.children, fn);\n break;\n default:\n break;\n }\n }\n}\n\n/** Every content node a tree's sections own directly, whichever section. */\nfunction treeContent(sections: readonly SectionNode[]): ContentNode[] {\n return sections.flatMap((s) => [...s.children, ...treeContent(s.sections)]);\n}\n\n/** A non-Markdown page's body, from lint's tree. */\nfunction parseTreeBody(\n content: string,\n path: string,\n format: TreeFormat,\n): DocBody {\n const tree = parseTree(content, path, format);\n const minted = mintTreeSections(tree.sections);\n const imageTargets: string[] = [];\n const codeLanguages = new Set<string>();\n eachContent(treeContent(tree.sections), (node) => {\n if (node.kind === \"image\") imageTargets.push(node.url);\n else if (node.kind === \"codeBlock\" && node.language) {\n codeLanguages.add(node.language);\n }\n });\n return {\n ...(minted.firstH1 === undefined ? {} : { firstH1: minted.firstH1 }),\n sections: minted.sections,\n linkTargets: tree.links.map((l) => l.target),\n imageTargets,\n codeLanguages: [...codeLanguages].sort(),\n };\n}\n\n/** Minimal depth-first mdast walk in document order. */\nfunction visit(\n node: Root | RootContent,\n fn: (node: RootContent) => void,\n): void {\n const children = (node as { children?: RootContent[] }).children;\n if (!children) return;\n for (const child of children) {\n fn(child);\n visit(child, fn);\n }\n}\n","/**\n * Input discovery: expand the run's document set to a stable, sorted,\n * deduplicated list of cwd-relative forward-slash paths. Determinism starts\n * here — the file list order is independent of glob order and filesystem\n * enumeration order.\n *\n * The set itself is the family's (proposal 0041, and 0051 §1 copying 0048 §1):\n * positional paths, or the collections declared once at the top level of\n * `manni.config.yaml`. `graph.inputs` and `graph.exclude` are gone, and a run that\n * names neither is an operational error rather than a silent walk of every\n * markdown file beneath the working directory (proposal 0014).\n */\nimport { statSync } from \"node:fs\";\nimport { extname, relative, resolve } from \"node:path\";\nimport fg from \"fast-glob\";\nimport {\n parserForExtension,\n supportedExtensions,\n unsupportedFormatMessage,\n} from \"../../lint/parsers/index.js\";\nimport { STDIN_REQUIRES_AS } from \"../../shared/cli-options.js\";\nimport { selectCollections } from \"../../shared/collections.js\";\nimport { warn } from \"../../shared/warn.js\";\nimport { GraphError } from \"../types.js\";\nimport { DOC_FORMATS, isDocFormat, type DocFormat } from \"./analyze.js\";\nimport {\n assertCollectionWithoutPaths,\n DEFAULT_CONFIG_FILENAME,\n type GraphConfig,\n type RouteMapping,\n} from \"./config.js\";\nimport { byCodeUnit } from \"./sort.js\";\n\nexport function discoverFiles(\n inputs: string[],\n exclude: string[],\n cwd: string,\n): string[] {\n const matches = fg.sync(inputs, {\n cwd,\n ignore: exclude,\n onlyFiles: true,\n dot: false,\n unique: true,\n });\n return [...new Set(matches.map((m) => m.replace(/\\\\/g, \"/\")))].sort(\n byCodeUnit,\n );\n}\n\n/**\n * What every tool in the family never reads, whatever it was asked for. The\n * same pair meta's file walk, cite's source index and docevals' discovery\n * ignore; it replaced graph's own `exclude` default (proposal 0041).\n */\nconst FAMILY_EXCLUDE = [\"**/node_modules/**\", \"**/.git/**\"];\n\n/**\n * What a directory walk or a glob keeps when `--ext` is not given: lint's walk\n * set, read from its registry so the two domains cannot drift (proposal 0077\n * §3). The filter matters because a positional path may be a *directory*,\n * which expands to everything beneath it. Without it, `manni graph build docs`\n * would mint a graph node for every image and data file in the tree, and a\n * node's IRI is the part of the output a consumer stores. `.xml` is not in\n * it, so a `pom.xml` is never swept in; a named one is still read.\n */\nexport const DEFAULT_EXTENSIONS = supportedExtensions();\n\n/** The positional that reads stdin. One more input, never instead of the rest. */\nexport const STDIN = \"-\";\n\n/**\n * Hold `--as` to the formats graph parses, and require it with `-`: stdin has\n * no file name to choose a parser by. Returns the format, or undefined when\n * none was forced.\n */\nexport function assertInputFormat(\n paths: readonly string[],\n as: string | undefined,\n): DocFormat | undefined {\n if (as === undefined) {\n if (paths.includes(STDIN)) throw new GraphError(STDIN_REQUIRES_AS);\n return undefined;\n }\n if (!isDocFormat(as)) {\n throw new GraphError(\n `Unknown format \"${as}\". Known formats: ${DOC_FORMATS.join(\", \")}.`,\n );\n }\n return as;\n}\n\n/** The word the empty-input message uses for what the command would do. */\nexport type DocumentVerb = \"build\" | \"fill\";\n\nexport interface DocumentSetOptions {\n /**\n * Positional paths: files, directories and globs, relative to the working\n * directory. Empty or absent means the selected collections' `paths:`.\n */\n paths?: string[];\n /**\n * `--collection <name>`, repeatable. Empty or absent means every declared\n * collection, because commander's collector hands `[]` over when the flag\n * was never typed (see `selectCollections`).\n */\n collection?: string[];\n /** `--exclude <glob>`, repeatable. Applies to paths and collections alike. */\n exclude?: string[];\n /**\n * `--ext <list>`: what a directory walk or a glob keeps. Absent means\n * `DEFAULT_EXTENSIONS`. A file named outright is never filtered by it.\n */\n ext?: string[];\n /** `--as <format>`: parse every input as this format. Required with `-`. */\n as?: string;\n}\n\n/**\n * The document-set options every command that reads documents takes beside its\n * positional paths: `-c`, `--no-config`, `--collection` and `--exclude`.\n */\nexport interface DocumentInputOptions extends DocumentSetOptions {\n /** `-c/--config`. */\n config?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n}\n\n/**\n * Every file `inputs` match beneath `base`, as absolute paths, split by how\n * they were reached. A file named outright is `named`. A directory expands to\n * everything beneath it, and a glob is left for fast-glob to interpret; both\n * land in `walked`, the half `--ext` filters. A literal path with `(` or `[`\n * in its name still means itself, because only the glob is a pattern.\n */\nfunction expandInputs(\n inputs: string[],\n base: string,\n ignore: string[],\n): { named: string[]; walked: string[] } {\n const named: string[] = [];\n const patterns: string[] = [];\n for (const input of inputs) {\n if (fg.isDynamicPattern(input)) {\n patterns.push(input.replace(/\\\\/g, \"/\"));\n continue;\n }\n let isDirectory: boolean;\n try {\n isDirectory = statSync(resolve(base, input)).isDirectory();\n } catch {\n // Missing: kept as written, so it matches nothing and the caller's\n // empty-match error names it.\n patterns.push(input.replace(/\\\\/g, \"/\"));\n continue;\n }\n const literal = fg.convertPathToPattern(input);\n if (isDirectory) patterns.push(`${literal.replace(/\\/$/, \"\")}/**/*`);\n else named.push(...glob([literal], base, ignore));\n }\n return { named, walked: glob(patterns, base, ignore) };\n}\n\nfunction glob(patterns: string[], base: string, ignore: string[]): string[] {\n if (patterns.length === 0) return [];\n return fg.sync(patterns, {\n cwd: base,\n ignore,\n absolute: true,\n dot: false,\n onlyFiles: true,\n });\n}\n\n/** `--ext` values as lower-case extensions with their dot. */\nfunction normalizeExtensions(exts: readonly string[]): Set<string> {\n return new Set(\n exts.map((e) => {\n const lower = e.toLowerCase();\n return lower.startsWith(\".\") ? lower : `.${lower}`;\n }),\n );\n}\n\n/**\n * The documents a run covers. Positional `paths` are what the operator typed,\n * resolved from `cwd`. Without them the run reads the selected collections,\n * each collection's `paths:` resolved from the config file's directory and\n * narrowed by its own `exclude:`. The family-wide exclusions and `--exclude`\n * apply to both. Labels are relative to `base`, which `documentBase` picks\n * the way `manni meta validate` does, so a collection page's IRI does not\n * depend on where the run started.\n *\n * `-` is not a file, so it is left out of what this returns: the caller reads\n * stdin itself. It still counts as a positional path, so a run given only `-`\n * reads stdin alone and never falls back to the collections.\n */\nexport function resolveDocumentSet(\n config: GraphConfig,\n options: DocumentSetOptions = {},\n verb: DocumentVerb = \"build\",\n cwd = process.cwd(),\n base = documentBase(config, options, cwd),\n): string[] {\n const paths = options.paths ?? [];\n const wanted = options.collection ?? [];\n assertCollectionWithoutPaths(wanted, paths);\n const format = assertInputFormat(paths, options.as);\n if (wanted.length > 0 && config.configSource === null) {\n throw new GraphError(\"--collection needs a config file to select from.\");\n }\n const collections = selectCollections(\n config.collections,\n wanted,\n config.configSource ?? DEFAULT_CONFIG_FILENAME,\n (message) => new GraphError(message),\n );\n\n const exclude = [...FAMILY_EXCLUDE, ...(options.exclude ?? [])];\n let named: string[] = [];\n let walked: string[];\n if (paths.length > 0) {\n ({ named, walked } = expandInputs(\n paths.filter((p) => p !== STDIN),\n cwd,\n exclude,\n ));\n } else {\n // A collection's `exclude:` shapes that collection only, so each is walked\n // with its own and the results are joined.\n const patterns = collections.flatMap((c) => c.paths);\n if (patterns.length === 0) {\n throw new GraphError(\n `No files to ${verb}. Pass paths/globs, or declare a collection under \\`collections:\\` in manni.config.yaml.`,\n );\n }\n walked = collections.flatMap((c) => {\n const found = expandInputs(c.paths, config.configDir, [\n ...exclude,\n ...c.exclude,\n ]);\n return [...found.named, ...found.walked];\n });\n }\n\n const exts = normalizeExtensions(options.ext ?? DEFAULT_EXTENSIONS);\n // A named file is read when a parser claims it, or when `--as` picks one.\n // Anything else is skipped by name, with lint's sentence for it, so the\n // run's \"No input files matched\" never hides a file the user did name.\n const keepNamed = (p: string): boolean => {\n const ext = extname(p);\n if (format !== undefined || parserForExtension(ext) !== undefined) {\n return true;\n }\n const label = relative(base, p).replace(/\\\\/g, \"/\");\n warn(`skipped ${label}: ${unsupportedFormatMessage(ext || label)}`);\n return false;\n };\n const keepWalked = (p: string): boolean => exts.has(extname(p).toLowerCase());\n return [\n ...new Set(\n [...named.filter(keepNamed), ...walked.filter(keepWalked)].map((p) =>\n relative(base, p).replace(/\\\\/g, \"/\"),\n ),\n ),\n ].sort(byCodeUnit);\n}\n\n/**\n * The directory a run's document labels are relative to, decided as\n * `manni meta validate` decides it. Positional paths are what the operator\n * typed, so they are labelled from the working directory. Collection pages are\n * labelled from the config file's directory, so one collection builds one graph\n * from anywhere beneath it. A config that declares no collection has no pages\n * of its own, so the base is then `cwd`.\n */\nexport function documentBase(\n config: GraphConfig,\n options: Pick<DocumentSetOptions, \"paths\"> = {},\n cwd = process.cwd(),\n): string {\n const typed = (options.paths ?? []).length > 0;\n return typed || config.collections.length === 0 ? cwd : config.configDir;\n}\n\n/**\n * The configured route mappings, each `root` rebased from the config file's\n * directory onto `base`. A route then resolves to the label its page carries,\n * whichever directory the labels are relative to.\n */\nexport function routesFrom(config: GraphConfig, base: string): RouteMapping[] {\n return config.routes.map((m) => ({\n ...m,\n root: relative(base, resolve(config.configDir, m.root)).replace(/\\\\/g, \"/\"),\n }));\n}\n\n/** The patterns a run asked about, for the empty-match message. */\nexport function documentSetPatterns(\n config: GraphConfig,\n options: DocumentSetOptions = {},\n): string[] {\n const paths = options.paths ?? [];\n if (paths.length > 0) return paths;\n return selectCollections(\n config.collections,\n options.collection ?? [],\n config.configSource ?? DEFAULT_CONFIG_FILENAME,\n (message) => new GraphError(message),\n ).flatMap((c) => c.paths);\n}\n","/**\n * The ordering primitive behind the determinism contract. Every sort that\n * reaches output — the file list, emitted subjects/predicates/objects, query\n * results — must go through this comparator so ordering never depends on\n * locale, ICU version, or platform, the way `String.prototype.localeCompare`\n * and `Array.prototype.sort`'s default string coercion do.\n */\n\n/** Locale-independent code-unit comparison for stable sorting. */\nexport function byCodeUnit(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n","/**\n * A page's metadata as `manni meta validate` reads it: its frontmatter, plus\n * every key an external-metadata manifest of one of its collections owns\n * (proposals 0037, 0041, 0047, 0058 and 0068).\n *\n * A corpus that keeps `owner`, `last-updated` or `meta-provenance` in a\n * `{page}.meta.yaml` beside each page would otherwise read to graph as a set\n * of pages that declare none of them. So graph reads through meta's merge,\n * not a loader of its own: the join, ownership and keyless-manifest rules are\n * the ones `meta validate` applies, and so are its refusals, which reach the\n * user in meta's words and exit 2.\n *\n * The config is meta's section of the file the run is under, the same one\n * graph already reads the output marks from (proposal 0074). `--no-config`\n * declares no collection, so no manifest is read, exactly as meta reads none.\n * A page read from stdin belongs to no collection, so no manifest supplies it.\n *\n * Encrypted values (proposal 0045) are merged as the manifest holds them.\n * graph never decrypts, so the graph carries the `~…` token.\n */\nimport { resolve } from \"node:path\";\nimport { metaPageView, type MetaPageView } from \"../../meta/internal.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { GraphError, type DocModel } from \"../types.js\";\nimport type { DocFormat } from \"./analyze.js\";\nimport { STDIN_PATH } from \"./iri.js\";\n\n/** Which config a run reads meta's section of, as its flags said. */\nexport interface MetaViewSource {\n /** `-c/--config`. */\n configPath?: string;\n /** `--no-config`. */\n noConfig?: boolean;\n}\n\n/**\n * Meta's view of the run's pages. `paths` are the run's documents relative\n * to `base` (`documentBase`), and the view's labels are too. `-c` stays\n * relative to `cwd`, where it was typed. A `{page}` manifest is read for\n * exactly these. A manifest meta refuses is refused here in meta's sentence,\n * as an operational error.\n */\nexport async function openMetaView(\n source: MetaViewSource,\n cwd: string,\n paths: readonly string[],\n base = cwd,\n): Promise<MetaPageView> {\n try {\n return await metaPageView({\n cwd: base,\n ...(source.configPath === undefined\n ? {}\n : { configPath: resolve(cwd, source.configPath) }),\n ...(source.noConfig === undefined ? {} : { noConfig: source.noConfig }),\n pages: paths.filter((p) => p !== STDIN_PATH).map((p) => resolve(base, p)),\n });\n } catch (e) {\n throw new GraphError(errorMessage(e));\n }\n}\n\n/** A page's own metadata and what its manifests add to it. */\nexport interface MergedPage {\n /** The page's metadata with every manifest-supplied key in place. */\n data: Record<string, unknown>;\n /** The top-level keys a manifest supplied, with their merged values. */\n supplied: Record<string, unknown>;\n}\n\n/** The `/key` pointer of a top-level key, RFC 6901 escaped. */\nfunction pointerOf(key: string): string {\n return `/${key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\")}`;\n}\n\n/**\n * Merge one page's frontmatter with its manifests. `present` is whether the\n * page has a frontmatter block at all, and `format` is what graph parsed it as.\n */\nexport async function mergePage(\n view: MetaPageView,\n path: string,\n frontmatter: Record<string, unknown>,\n present: boolean,\n format: DocFormat,\n): Promise<MergedPage> {\n let merged;\n try {\n merged = await view.merge(path, {\n data: frontmatter,\n present,\n format,\n lineFor: () => undefined,\n });\n } catch (e) {\n throw new GraphError(errorMessage(e));\n }\n const data = merged.extracted.data;\n const supplied: Record<string, unknown> = {};\n for (const key of Object.keys(data)) {\n if (merged.locate(pointerOf(key)) !== undefined) supplied[key] = data[key];\n }\n return { data, supplied };\n}\n\n/** `docs`, each with its manifests' values merged into its frontmatter. */\nexport async function withExternalMetadata(\n docs: readonly DocModel[],\n view: MetaPageView,\n): Promise<DocModel[]> {\n const out: DocModel[] = [];\n for (const doc of docs) {\n const { data } = await mergePage(\n view,\n doc.path,\n doc.frontmatter,\n doc.frontmatterPresent,\n doc.format,\n );\n // A run with no manifest hands the page's own object back, so the common\n // case allocates nothing.\n out.push(data === doc.frontmatter ? doc : { ...doc, frontmatter: data });\n }\n return out;\n}\n","/**\n * The localization manifest (ADR 01038) — `graph/localizations.json`, the index of\n * indexes.\n *\n * Retrieval artifacts fan out per language: one `search.<lang>.json` and one\n * `vectors.<lang>.bin` each, because a single flat index over every locale\n * ranks across the boundary it exists to respect, and because one embedding\n * model cannot serve every language. The manifest is what makes that navigable\n * — a browser fetches this one small file, learns which localizations exist and\n * what each costs, and downloads only the pair it needs.\n *\n * Written by `manni graph export search`; `manni graph embed` fills in the\n * `vectors` block as it produces each sidecar, so a manifest entry without one\n * means exactly \"this language has no vectors yet\".\n *\n * No `node:` imports: the CLI writes it and the browser runtime reads it.\n */\nimport { byCodeUnit } from \"./sort.js\";\n\n/** Conventional filename, written beside the graph. */\nexport const LOCALIZATIONS_FILENAME = \"localizations.json\";\n\n/**\n * BCP-47's tag for undetermined, used as the bucket for documents that declare\n * no language. A real tag rather than a dockg invention, so a consumer that\n * knows BCP-47 already knows what it means — and so the bucket sorts, filters,\n * and names a file like any other language.\n */\nexport const UNDETERMINED = \"und\";\n\n/**\n * BCP-47's common shape: language(2-3) + optional script(4) + optional\n * region(2 alpha or 3 digit) + variants. Accepts de, de-DE, zh-Hans,\n * zh-Hans-CN, pt-BR and und; rejects English and de_DE.\n *\n * The same grammar appears in `config-schema.json` (for `routes[].language` and\n * `embed.byLanguage`) and in `shapes/graph/shapes-1.1.0.ttl` (for `dcterms:language`).\n * This copy exists because a tag also becomes a **filename**, and the shapes\n * only run under `manni graph check` — an unvalidated literal from the graph would\n * otherwise reach `writeFileSync` as a path segment. `test/unit/schema-sync.test.ts`\n * pins all three to each other.\n */\nexport const LANGUAGE_TAG =\n /^[A-Za-z]{2,3}(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*$/;\n\n/** Whether a string is usable as a language tag — and so as a filename segment. */\nexport function isLanguageTag(value: string): boolean {\n return LANGUAGE_TAG.test(value);\n}\n\n/**\n * The canonical spelling of a BCP-47 tag: `en-us` and `EN-US` both become\n * `en-US`. Tags are case-insensitive, so without this one locale splits into\n * two indexes and a filter matches only the spelling its author happened to\n * type. A string `Intl` refuses comes back as written, so the tag check that\n * guards filenames still sees, and reports, what the author wrote.\n *\n * `Intl` exists in every browser, so the runtime calls this too.\n */\nexport function canonicalLanguageTag(tag: string): string {\n try {\n return Intl.getCanonicalLocales(tag)[0] ?? tag;\n } catch {\n return tag;\n }\n}\n\n/** Where one language's lexical index lives, and what it holds. */\nexport interface SearchArtifact {\n /** Filename, relative to the manifest. */\n path: string;\n /** Indexed nodes. */\n entries: number;\n /** `sha256:…` of the file, so a consumer can detect a stale pair. */\n digest: string;\n}\n\n/** Where one language's vector sidecar lives, and what produced it. */\nexport interface VectorArtifact {\n path: string;\n /** The embedding model this language was embedded with. */\n model: string;\n dtype: string;\n dims: number;\n count: number;\n}\n\nexport interface LocalizationEntry {\n /** BCP-47 tag, or `und` for the undeclared bucket. */\n language: string;\n /** Documents in this language (sections excluded). */\n documents: number;\n search: SearchArtifact;\n /** Absent until `manni graph embed` has run for this language. */\n vectors?: VectorArtifact;\n}\n\nexport interface LocalizationsDoc {\n version: 1;\n /** One entry per language present, sorted by tag. */\n languages: LocalizationEntry[];\n}\n\n/** `search.de.json` — the lexical index for one language. */\nexport function searchIndexFilename(language: string): string {\n return `search.${language}.json`;\n}\n\n/** `vectors.de.bin` — the vector sidecar for one language. */\nexport function vectorIndexFilename(language: string): string {\n return `vectors.${language}.bin`;\n}\n\n/**\n * Serialize the manifest: sorted by language, two-space indent, trailing\n * newline — byte-stable like every other dockg artifact.\n */\nexport function emitLocalizations(doc: LocalizationsDoc): string {\n const languages = [...doc.languages].sort((a, b) =>\n byCodeUnit(a.language, b.language),\n );\n return `${JSON.stringify({ version: doc.version, languages }, null, 2)}\\n`;\n}\n\n/**\n * Parse and shape-check a manifest. Returns undefined for anything else.\n *\n * Every entry is checked, not just the envelope: callers reach straight for\n * `entry.search.path`, and a truncated or hand-edited file would otherwise\n * dereference `undefined` and surface as a raw TypeError with exit 1 rather\n * than the operational error (exit 2) an unreadable artifact owes.\n */\n/** A plain JSON object — not `null`, not an array. */\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nexport function parseLocalizations(text: string): LocalizationsDoc | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return undefined;\n }\n // Checked as `unknown`. Casting to `LocalizationsDoc` first would hand the\n // compiler the answer to the question this function exists to ask, and every\n // guard below would then read as a test that cannot fail.\n if (!isRecord(parsed)) return undefined;\n if (parsed[\"version\"] !== 1 || !Array.isArray(parsed[\"languages\"])) {\n return undefined;\n }\n for (const entry of parsed[\"languages\"] as unknown[]) {\n if (!isRecord(entry)) return undefined;\n const language = entry[\"language\"];\n const search = entry[\"search\"];\n if (\n typeof language !== \"string\" ||\n !isLanguageTag(language) ||\n typeof entry[\"documents\"] !== \"number\" ||\n !isRecord(search) ||\n typeof search[\"path\"] !== \"string\" ||\n typeof search[\"entries\"] !== \"number\" ||\n typeof search[\"digest\"] !== \"string\" ||\n !ownsFilename(search[\"path\"], searchIndexFilename(language))\n ) {\n return undefined;\n }\n const v = entry[\"vectors\"];\n if (v !== undefined) {\n if (\n !isRecord(v) ||\n typeof v[\"path\"] !== \"string\" ||\n typeof v[\"model\"] !== \"string\" ||\n typeof v[\"dtype\"] !== \"string\" ||\n typeof v[\"dims\"] !== \"number\" ||\n typeof v[\"count\"] !== \"number\" ||\n // Same constraint `search.path` gets: the last segment must be the\n // filename this language's sidecar would be given. Without it,\n // `isSafeRelativePath` alone leaves `vectors.path` far more reachable\n // than `search.path` — and `search --mode vector` opens it.\n !ownsFilename(v[\"path\"], vectorIndexFilename(language))\n ) {\n return undefined;\n }\n }\n }\n return parsed as unknown as LocalizationsDoc;\n}\n\n/**\n * A path from the manifest is joined onto a directory and opened, so it is\n * checked like any other untrusted path segment.\n *\n * `export` refuses to *write* a filename it built from a bad language tag; this\n * is the same hole on the read side, reached through a manifest instead of\n * through frontmatter. A hand-edited `\"path\": \"../../etc/passwd\"` would\n * otherwise be joined and read by `embed` and `search`.\n *\n * Rejects an absolute path, a Windows drive letter, a backslash, and any `.`\n * or empty segment. `..` is allowed **only as a prefix**, so `a/../../x` — an\n * escape wearing a normal first segment — is refused while `../vecs/x.bin`,\n * the layout `embed -o` produces, is not.\n *\n * How far up a leading run may climb is deliberately *not* capped. It was,\n * briefly, and the cap rejected manifests `embed -o` itself writes: a sidecar\n * directory two levels from the index directory produced an artifact set dockg\n * could not read back. The bound that matters is `ownsFilename` — a crafted\n * manifest can only ever name a file already called `search.<lang>.json` or\n * `vectors.<lang>.bin`, which is a long way from arbitrary-file read, and no\n * number of `..` segments widens it.\n */\nexport function isSafeRelativePath(path: string): boolean {\n if (path === \"\" || path.startsWith(\"/\") || /^[A-Za-z]:/.test(path)) {\n return false;\n }\n if (path.includes(\"\\\\\")) return false;\n const segments = path.split(\"/\");\n let leading = true;\n for (const segment of segments) {\n if (segment === \"\" || segment === \".\") return false;\n if (segment === \"..\") {\n if (!leading) return false;\n continue;\n }\n leading = false;\n }\n return true;\n}\n\n/**\n * The path is relative-safe *and* its last segment is the filename this\n * language's artifact would be given.\n *\n * The filename check is the constraint that actually narrows what a crafted\n * manifest can reach: `isSafeRelativePath` bounds the directory it can point\n * into, this bounds the file.\n */\nfunction ownsFilename(path: string, expected: string): boolean {\n if (!isSafeRelativePath(path)) return false;\n return path.slice(path.lastIndexOf(\"/\") + 1) === expected;\n}\n","/**\n * A page's `sample-questions`, read into one shape (manni:ai-context:1.1.0,\n * proposal 0087). An item is a string, or an object whose `answers` pin the\n * body lines that answer it. `build` derives only the question text; `check`\n * reads the pins and the review state, which never reach the graph.\n *\n * Reading is lenient: `meta validate` owns the schema, so an item it would\n * refuse is skipped here, and a malformed pin is dropped, rather than failing\n * a build or a check over a shape another command already reports.\n */\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport { isNode, isSeq, LineCounter, parseDocument } from \"yaml\";\nimport { parseLines, type PageLines } from \"../../shared/pin.js\";\nimport { GraphError } from \"../types.js\";\nimport questionsSchema from \"./questions-schema.json\" with { type: \"json\" };\n\n/** One pinned answer: body lines of the page, and the pin over them. */\nexport interface AnswerPin {\n lines: PageLines;\n integrity?: string;\n /** `false` only when the pin says so; absent means confirmed. */\n reviewed: boolean;\n}\n\nexport interface SampleQuestion {\n question: string;\n /** Empty for an unpinned question, which must find the page itself. */\n answers: AnswerPin[];\n /** `false` only when the item says so; absent means confirmed. */\n reviewed: boolean;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction readPin(value: unknown): AnswerPin | undefined {\n if (!isRecord(value)) return undefined;\n const spec = value.lines;\n const lines =\n typeof spec === \"number\" || typeof spec === \"string\" ? parseLines(spec) : undefined;\n if (lines === undefined) return undefined;\n const integrity = value.integrity;\n return {\n lines,\n ...(typeof integrity === \"string\" ? { integrity } : {}),\n reviewed: value.reviewed !== false,\n };\n}\n\nfunction readItem(item: unknown): SampleQuestion | undefined {\n if (typeof item === \"string\") {\n return item === \"\" ? undefined : { question: item, answers: [], reviewed: true };\n }\n if (!isRecord(item) || typeof item.question !== \"string\") return undefined;\n const question = item.question;\n if (question === \"\") return undefined;\n const answers = Array.isArray(item.answers)\n ? item.answers.flatMap((a) => readPin(a) ?? [])\n : [];\n return { question, answers, reviewed: item.reviewed !== false };\n}\n\n/** The questions a `sample-questions` value holds: one item, or a list of them. */\nexport function readSampleQuestions(value: unknown): SampleQuestion[] {\n const items: unknown[] = Array.isArray(value) ? value : value === undefined ? [] : [value];\n return items.flatMap((item) => readItem(item) ?? []);\n}\n\n/** One answer in a golden-set file: a pin on the page `file` names. */\nexport interface FileAnswerPin extends AnswerPin {\n /** The page, relative to the config file, as the item names it. */\n file: string;\n}\n\n/** One question in a golden-set file (proposal 0087). */\nexport interface FileQuestion {\n question: string;\n /** Empty for a known gap, a question the docs don't answer. */\n answers: FileAnswerPin[];\n reviewed: boolean;\n /** The item's own `language`, when it names one. */\n language?: string;\n /** The file line the item starts on, 1-based. */\n line: number;\n}\n\nlet validateFile: ReturnType<Ajv2020[\"compile\"]> | undefined;\n\n/**\n * The questions of one golden-set file. `abs` is where it is read from, and\n * `label` is how messages name it. A missing file, a YAML error and a schema\n * failure are each a `GraphError`, an operational error: a golden set that\n * cannot be read gates nothing.\n */\nexport function readQuestionFile(abs: string, label: string, text?: string): FileQuestion[] {\n if (text === undefined && !existsSync(abs)) {\n throw new GraphError(`graph.questionFiles names ${label}, which does not exist.`);\n }\n const counter = new LineCounter();\n const doc = parseDocument(text ?? readFileSync(abs, \"utf8\"), { lineCounter: counter });\n const [error] = doc.errors;\n if (error) throw new GraphError(`${label}: ${error.message}`);\n const value: unknown = doc.toJS() ?? [];\n validateFile ??= new Ajv2020({ allowUnionTypes: true }).compile(questionsSchema);\n if (!validateFile(value) || !Array.isArray(value)) {\n const [first] = validateFile.errors ?? [];\n const where = [first?.instancePath, first?.message ?? \"is invalid\"].filter(Boolean).join(\" \");\n throw new GraphError(`${label}: ${where}.`);\n }\n const nodes = isSeq(doc.contents) ? doc.contents.items : [];\n return value.flatMap((item: unknown, n): FileQuestion[] => {\n if (!isRecord(item) || typeof item.question !== \"string\") return [];\n const node = nodes[n];\n const offset = isNode(node) ? node.range[0] : undefined;\n const answers = Array.isArray(item.answers)\n ? item.answers.flatMap((a: unknown): FileAnswerPin[] => {\n const pin = readPin(a);\n return pin && isRecord(a) && typeof a.file === \"string\" ? [{ ...pin, file: a.file }] : [];\n })\n : [];\n return [\n {\n question: item.question,\n answers,\n reviewed: item.reviewed !== false,\n ...(typeof item.language === \"string\" ? { language: item.language } : {}),\n line: offset === undefined ? 1 : counter.linePos(offset).line,\n },\n ];\n });\n}\n\n/**\n * A question as duplicates are compared: lowercased, punctuation dropped,\n * and runs of spaces folded to one.\n */\nexport function questionKey(question: string): string {\n return question\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]/gu, \"\")\n .replace(/\\s+/gu, \" \")\n .trim();\n}\n\n/** The share of a question its answer already says, past which it copies. */\nexport const COPIED_SHARE = 0.5;\n\n/**\n * How many of the question's adjacent word pairs, lowercased, the text of its\n * answers also holds. Undefined under two words, where there is no pair to measure.\n */\nexport function copiedPairs(\n question: string,\n ...answers: string[]\n): { copied: number; of: number } | undefined {\n const words = (text: string): string[] => text.toLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? [];\n const pairs = (list: string[]): string[] => list.slice(1).map((w, i) => `${list[i] ?? \"\"} ${w}`);\n const asked = pairs(words(question));\n if (asked.length === 0) return undefined;\n // Each answer on its own, so no pair spans two of them.\n const said = new Set(answers.flatMap((a) => pairs(words(a))));\n return { copied: asked.filter((p) => said.has(p)).length, of: asked.length };\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"manni:graph:questions\",\n \"title\": \"manni graph golden-set file\",\n \"description\": \"A list of reader questions that span pages or that the docs don't answer (proposal 0087). Each item is a page sample question's object form, plus `answers[].file` and `language`. `graph.questionFiles` names the files, and `manni graph check` asks their questions.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"question\", \"answers\"],\n \"properties\": {\n \"question\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The question, as a reader would ask it.\"\n },\n \"answers\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"file\", \"lines\"],\n \"properties\": {\n \"file\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The page that holds this answer, relative to the config file.\"\n },\n \"lines\": {\n \"oneOf\": [\n { \"type\": \"integer\", \"minimum\": 1 },\n { \"type\": \"string\", \"pattern\": \"^[1-9][0-9]*-[1-9][0-9]*$\" }\n ],\n \"description\": \"Body lines of that page, counted as for a citation's claim.\"\n },\n \"integrity\": {\n \"type\": \"string\",\n \"pattern\": \"^sha256-[0-9a-f]{64}$\",\n \"description\": \"The pin over those lines, under cite's hashing rule. Without it, the lines are not checked for change.\"\n },\n \"reviewed\": {\n \"type\": \"boolean\",\n \"description\": \"`false` marks a pin nobody has confirmed. Absent means `true`.\"\n }\n }\n },\n \"description\": \"The lines that answer the question, on one page or several. An empty list marks a known gap: a question the docs don't answer.\"\n },\n \"language\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Za-z]{2,3}(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*$\",\n \"description\": \"The question's language, as a BCP-47 tag. Absent, it is the first answer's page language.\"\n },\n \"generated-by\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The model that drafted the question or any of its pins, as `provider/model`.\"\n },\n \"confidence\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1,\n \"description\": \"The drafting model's confidence, 0..1.\"\n },\n \"reviewed\": {\n \"type\": \"boolean\",\n \"description\": \"`false` marks a drafted question, and its pins are drafts with it. Absent means `true`.\"\n },\n \"reviewed-by\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Who confirmed the question. An optional record.\"\n }\n }\n }\n}\n"],"mappings":"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","names":["resolved","anchor","extname","resolve","resolve","extname","resolve","resolve","Ajv2020","isRecord","Ajv2020"]}
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
askSampleQuestions,
|
|
3
4
|
bundledShapesPath,
|
|
4
5
|
compactIri,
|
|
6
|
+
compareFindings,
|
|
5
7
|
loadGraph,
|
|
6
8
|
parseGraph,
|
|
9
|
+
renderQuestionSummary,
|
|
7
10
|
validateGraph
|
|
8
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ANPIIYRH.js";
|
|
9
12
|
import {
|
|
13
|
+
documentBase,
|
|
10
14
|
loadRunConfig
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2UJZXVHR.js";
|
|
12
16
|
import {
|
|
13
17
|
escapeWorkflowCommandMessage,
|
|
14
18
|
escapeWorkflowCommandProperty
|
|
15
19
|
} from "./chunk-MNH7QO4Z.js";
|
|
16
20
|
|
|
17
21
|
// src/graph/commands/check.ts
|
|
18
|
-
import { resolve } from "node:path";
|
|
22
|
+
import { dirname, resolve } from "node:path";
|
|
19
23
|
|
|
20
24
|
// src/graph/reporters/github.ts
|
|
21
25
|
function renderCheckGithub(report) {
|
|
@@ -41,10 +45,28 @@ async function runCheck(opts = {}) {
|
|
|
41
45
|
},
|
|
42
46
|
cwd
|
|
43
47
|
);
|
|
44
|
-
const
|
|
48
|
+
const graphPath = resolve(cwd, opts.graph ?? config.out);
|
|
49
|
+
const store = opts.turtle === void 0 ? loadGraph(graphPath) : parseGraph(opts.turtle, "the built graph");
|
|
45
50
|
const shapesInput = opts.shapes && opts.shapes.length > 0 ? opts.shapes : config.check.shapes;
|
|
46
51
|
const shapes = shapesInput.length > 0 ? shapesInput.map((p) => resolve(cwd, p)) : [bundledShapesPath(import.meta.url)];
|
|
47
|
-
const
|
|
52
|
+
const asked = await askSampleQuestions(
|
|
53
|
+
store,
|
|
54
|
+
config.check.questions,
|
|
55
|
+
documentBase(config, {}, cwd),
|
|
56
|
+
dirname(graphPath),
|
|
57
|
+
{
|
|
58
|
+
source: {
|
|
59
|
+
...opts.config === void 0 ? {} : { configPath: opts.config },
|
|
60
|
+
...opts.noConfig === void 0 ? {} : { noConfig: opts.noConfig }
|
|
61
|
+
},
|
|
62
|
+
cwd
|
|
63
|
+
},
|
|
64
|
+
config.questionFiles,
|
|
65
|
+
config.configDir
|
|
66
|
+
);
|
|
67
|
+
const findings = [...await validateGraph(store, shapes), ...asked.findings].sort(
|
|
68
|
+
compareFindings
|
|
69
|
+
);
|
|
48
70
|
const count = (severity) => findings.filter((f) => f.severity === severity).length;
|
|
49
71
|
const errors = count("error");
|
|
50
72
|
return {
|
|
@@ -53,6 +75,7 @@ async function runCheck(opts = {}) {
|
|
|
53
75
|
warnings: count("warning"),
|
|
54
76
|
notices: count("notice"),
|
|
55
77
|
shapes,
|
|
78
|
+
...asked.summary ? { questions: asked.summary } : {},
|
|
56
79
|
// Only an `error` fails the run; a warning and a notice are reported and
|
|
57
80
|
// pass, as they were when they were called violations and warnings.
|
|
58
81
|
exitCode: errors > 0 ? 1 : 0
|
|
@@ -66,7 +89,12 @@ function renderCheck(report, format) {
|
|
|
66
89
|
const { exitCode: _exitCode, ...rest } = report;
|
|
67
90
|
return JSON.stringify(rest, null, 2);
|
|
68
91
|
}
|
|
69
|
-
|
|
92
|
+
const summary = report.questions ? renderQuestionSummary(report.questions) : [];
|
|
93
|
+
if (format === "github") {
|
|
94
|
+
const annotations = renderCheckGithub(report);
|
|
95
|
+
if (summary.length === 0) return annotations;
|
|
96
|
+
return [...annotations === "" ? [] : [annotations, ""], ...summary].join("\n");
|
|
97
|
+
}
|
|
70
98
|
const lines = [];
|
|
71
99
|
for (const f of report.findings) {
|
|
72
100
|
const where = f.docs.length > 0 ? ` [${f.docs.join(", ")}]` : "";
|
|
@@ -75,6 +103,7 @@ function renderCheck(report, format) {
|
|
|
75
103
|
);
|
|
76
104
|
}
|
|
77
105
|
if (report.findings.length > 0) lines.push("");
|
|
106
|
+
if (summary.length > 0) lines.push(...summary, "");
|
|
78
107
|
lines.push(
|
|
79
108
|
`${plural(report.errors, "error")}, ${plural(report.warnings, "warning")}, ${plural(report.notices, "notice")}`
|
|
80
109
|
);
|
|
@@ -85,4 +114,4 @@ export {
|
|
|
85
114
|
runCheck,
|
|
86
115
|
renderCheck
|
|
87
116
|
};
|
|
88
|
-
//# sourceMappingURL=chunk-
|
|
117
|
+
//# sourceMappingURL=chunk-3BRJCQPY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graph/commands/check.ts","../src/graph/reporters/github.ts"],"sourcesContent":["/**\n * `manni graph check` — graph-level validation: run the published SHACL shapes\n * (plus the TS-side SKOS integrity checks) over the built graph and report\n * findings with the doc paths responsible. Each page's sample questions are\n * asked too (proposal 0086 §7), with each golden-set file's, and the question\n * set's health is summed up after the findings (proposal 0087). Errors exit 1; warnings and notices are\n * reported but pass.\n */\nimport { dirname, resolve } from \"node:path\";\nimport type { Severity } from \"../../shared/severity.js\";\nimport { loadRunConfig } from \"../core/config.js\";\nimport { loadGraph, compactIri, parseGraph } from \"../core/load.js\";\nimport { documentBase } from \"../core/discover.js\";\nimport { bundledShapesPath } from \"../core/pkg.js\";\nimport {\n compareFindings,\n validateGraph,\n type CheckFinding,\n} from \"../core/shacl.js\";\nimport {\n askSampleQuestions,\n renderQuestionSummary,\n type QuestionSummary,\n} from \"./questions.js\";\nimport { renderCheckGithub } from \"../reporters/github.js\";\nimport type { CheckFormat } from \"../reporters/index.js\";\n\nexport interface CheckOptions {\n config?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Graph .ttl path (default: config `out`). */\n graph?: string;\n /** Shapes .ttl paths (default: config `check.shapes`, then bundled). */\n shapes?: string[];\n cwd?: string;\n /**\n * The graph as Turtle, in place of reading `graph`: what `buildGraph`\n * returns, so `manni check` checks a build it never wrote.\n */\n turtle?: string;\n}\n\nexport interface CheckReport {\n findings: CheckFinding[];\n /** Counts on the family's scale, not SHACL's (proposal 0051 §2). */\n errors: number;\n warnings: number;\n notices: number;\n /** Shapes files used, as given (for reporting). */\n shapes: string[];\n /** The question set's health (proposal 0087); absent when no question exists. */\n questions?: QuestionSummary;\n exitCode: 0 | 1;\n}\n\nexport async function runCheck(opts: CheckOptions = {}): Promise<CheckReport> {\n const cwd = opts.cwd ?? process.cwd();\n const config = loadRunConfig(\n {\n ...(opts.config === undefined ? {} : { configPath: opts.config }),\n ...(opts.noConfig === undefined ? {} : { noConfig: opts.noConfig }),\n },\n cwd,\n );\n const graphPath = resolve(cwd, opts.graph ?? config.out);\n const store =\n opts.turtle === undefined\n ? loadGraph(graphPath)\n : parseGraph(opts.turtle, \"the built graph\");\n\n // CLI flag over config over the bundled contract — same precedence as\n // every other knob.\n const shapesInput =\n opts.shapes && opts.shapes.length > 0 ? opts.shapes : config.check.shapes;\n const shapes =\n shapesInput.length > 0\n ? shapesInput.map((p) => resolve(cwd, p))\n : [bundledShapesPath(import.meta.url)];\n\n // Pages read from where `build` labels them, and a vector sidecar from\n // beside the graph, as `export search` and `search` read them. Golden-set\n // files resolve from the config file's directory.\n const asked = await askSampleQuestions(\n store,\n config.check.questions,\n documentBase(config, {}, cwd),\n dirname(graphPath),\n {\n source: {\n ...(opts.config === undefined ? {} : { configPath: opts.config }),\n ...(opts.noConfig === undefined ? {} : { noConfig: opts.noConfig }),\n },\n cwd,\n },\n config.questionFiles,\n config.configDir,\n );\n const findings = [...(await validateGraph(store, shapes)), ...asked.findings].sort(\n compareFindings,\n );\n const count = (severity: Severity): number =>\n findings.filter((f) => f.severity === severity).length;\n const errors = count(\"error\");\n\n return {\n findings,\n errors,\n warnings: count(\"warning\"),\n notices: count(\"notice\"),\n shapes,\n ...(asked.summary ? { questions: asked.summary } : {}),\n // Only an `error` fails the run; a warning and a notice are reported and\n // pass, as they were when they were called violations and warnings.\n exitCode: errors > 0 ? 1 : 0,\n };\n}\n\n/** `2 errors`, `1 warning`, `0 notices` — each count pluralized on its own. */\nfunction plural(n: number, word: string): string {\n return `${String(n)} ${word}${n === 1 ? \"\" : \"s\"}`;\n}\n\nexport function renderCheck(report: CheckReport, format: CheckFormat): string {\n if (format === \"json\") {\n const { exitCode: _exitCode, ...rest } = report;\n return JSON.stringify(rest, null, 2);\n }\n const summary = report.questions ? renderQuestionSummary(report.questions) : [];\n if (format === \"github\") {\n // The summary is plain text after the annotations, which GitHub logs as is.\n const annotations = renderCheckGithub(report);\n if (summary.length === 0) return annotations;\n return [...(annotations === \"\" ? [] : [annotations, \"\"]), ...summary].join(\"\\n\");\n }\n const lines: string[] = [];\n for (const f of report.findings) {\n const where = f.docs.length > 0 ? ` [${f.docs.join(\", \")}]` : \"\";\n lines.push(\n `${f.severity}: ${compactIri(f.focusNode)}${\n f.path ? ` ${compactIri(f.path)}` : \"\"\n } — ${f.message}${where}`,\n );\n }\n if (report.findings.length > 0) lines.push(\"\");\n if (summary.length > 0) lines.push(...summary, \"\");\n lines.push(\n `${plural(report.errors, \"error\")}, ${plural(report.warnings, \"warning\")}, ${plural(report.notices, \"notice\")}`,\n );\n return lines.join(\"\\n\");\n}\n","/**\n * `--format github`: one workflow-command annotation per `check` finding.\n *\n * `::error file=<first blamed doc>::<message> (<focus node>)`, with\n * `::warning` and `::notice` for the lower levels — the family scale is\n * GitHub's, so the level is the severity, exactly as a11y's and cite's\n * reporters have it.\n *\n * A SHACL finding carries no line number (stress test 5 of proposal 0051 says\n * why SARIF and JUnit are not here), and a finding about a shared node — a\n * concept, an agent, the scheme — may trace back to no document at all. Then\n * there is nothing to anchor to and the annotation goes out without `file=`,\n * which GitHub shows against the workflow run rather than dropping.\n *\n * Empty when the run is clean, so a clean CI step logs nothing.\n */\nimport {\n escapeWorkflowCommandMessage,\n escapeWorkflowCommandProperty,\n} from \"../../shared/github.js\";\nimport type { CheckReport } from \"../commands/check.js\";\nimport { compactIri } from \"../core/load.js\";\n\nexport function renderCheckGithub(report: CheckReport): string {\n const lines: string[] = [];\n for (const f of report.findings) {\n // The first, not all of them: one annotation lands on one file, and the\n // docs are sorted, so which one is stable across runs.\n const file = f.docs[0];\n const where =\n file === undefined ? \"\" : ` file=${escapeWorkflowCommandProperty(file)}`;\n const message = escapeWorkflowCommandMessage(\n `${f.message} (${compactIri(f.focusNode)})`,\n );\n lines.push(`::${f.severity}${where}::${message}`);\n }\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
|
|
@@ -19,29 +19,29 @@ import {
|
|
|
19
19
|
} from "./chunk-SE4JN5XN.js";
|
|
20
20
|
import {
|
|
21
21
|
declaredAt
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-JSSM7VVV.js";
|
|
23
23
|
import {
|
|
24
24
|
metaProvenanceEntries
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-2OZF2VUB.js";
|
|
26
26
|
import {
|
|
27
27
|
familyMarks,
|
|
28
28
|
loadExternalMetadata,
|
|
29
29
|
memberOf,
|
|
30
30
|
mergeWithMarks,
|
|
31
31
|
provenanceEntries
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-SMHAYK6I.js";
|
|
33
33
|
import {
|
|
34
34
|
__default,
|
|
35
35
|
classifyRef,
|
|
36
36
|
extractFrontmatter
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-RGLFV4KO.js";
|
|
38
38
|
import {
|
|
39
39
|
findConfigFileSync,
|
|
40
40
|
ownsKey,
|
|
41
41
|
parseCollections,
|
|
42
42
|
readConfigFileSync,
|
|
43
43
|
selectCollections
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-OTJOBZJ5.js";
|
|
45
45
|
import {
|
|
46
46
|
warn
|
|
47
47
|
} from "./chunk-HX44GB4Z.js";
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
assertKnownProvider,
|
|
51
51
|
parseDuration,
|
|
52
52
|
parseProviders
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-VM7VAFJW.js";
|
|
54
54
|
import {
|
|
55
55
|
errorMessage
|
|
56
56
|
} from "./chunk-G3T47CFV.js";
|
|
@@ -2960,4 +2960,4 @@ export {
|
|
|
2960
2960
|
applySelection,
|
|
2961
2961
|
runEvals
|
|
2962
2962
|
};
|
|
2963
|
-
//# sourceMappingURL=chunk-
|
|
2963
|
+
//# sourceMappingURL=chunk-42VFJOAF.js.map
|