@hawkeyexl/manni 4.5.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/README.md +1 -1
  2. package/dist/batch-U6S2JUUN.js +41 -0
  3. package/dist/build-4RN6WBCP.js +32 -0
  4. package/dist/calibrate-6VIZYR4L.js +36 -0
  5. package/dist/capture-DP3NXAZE.js +34 -0
  6. package/dist/{check-RQIIIURI.js → check-ERVNGKLC.js} +13 -14
  7. package/dist/check-IWHUPAZM.js +886 -0
  8. package/dist/check-IWHUPAZM.js.map +1 -0
  9. package/dist/{check-ESNS7ZBC.js → check-OAJWC3WD.js} +7 -5
  10. package/dist/check-STHXZIZO.js +26 -0
  11. package/dist/{chunk-TA42STP7.js → chunk-2ZWTSRE5.js} +4 -4
  12. package/dist/{chunk-F2OVHJNC.js → chunk-4Z2MN5FR.js} +11 -11
  13. package/dist/{chunk-HVFR66GQ.js → chunk-5UB47BEV.js} +3280 -283
  14. package/dist/chunk-5UB47BEV.js.map +1 -0
  15. package/dist/{chunk-TCC737IS.js → chunk-5VWDIWOH.js} +4 -4
  16. package/dist/{chunk-B7XUEQF3.js → chunk-6KKZXB2O.js} +7 -5
  17. package/dist/{chunk-B7XUEQF3.js.map → chunk-6KKZXB2O.js.map} +1 -1
  18. package/dist/{chunk-ELZ2IIOF.js → chunk-6URSCTTX.js} +2 -2
  19. package/dist/{chunk-K3U5F2QT.js → chunk-6VDBP5UV.js} +12 -12
  20. package/dist/chunk-7EL5LLKD.js +233 -0
  21. package/dist/chunk-7EL5LLKD.js.map +1 -0
  22. package/dist/{chunk-C3KI45RF.js → chunk-7XZ6INKO.js} +4 -4
  23. package/dist/{chunk-ZX43SRZR.js → chunk-AMEILOVV.js} +8 -6
  24. package/dist/{chunk-ZX43SRZR.js.map → chunk-AMEILOVV.js.map} +1 -1
  25. package/dist/{chunk-SNEHX4VE.js → chunk-B5CMM57M.js} +2 -2
  26. package/dist/chunk-BWCWTHYS.js +146 -0
  27. package/dist/chunk-BWCWTHYS.js.map +1 -0
  28. package/dist/{chunk-QLUMKWQQ.js → chunk-C2TJG5KV.js} +10 -6
  29. package/dist/{chunk-QLUMKWQQ.js.map → chunk-C2TJG5KV.js.map} +1 -1
  30. package/dist/{chunk-GAZFKZHM.js → chunk-CEVU3GFF.js} +6 -6
  31. package/dist/chunk-CI55ABCK.js +502 -0
  32. package/dist/chunk-CI55ABCK.js.map +1 -0
  33. package/dist/{chunk-QCBICNKC.js → chunk-CR3HZERW.js} +202 -54
  34. package/dist/chunk-CR3HZERW.js.map +1 -0
  35. package/dist/chunk-CU57HT2E.js +116 -0
  36. package/dist/chunk-CU57HT2E.js.map +1 -0
  37. package/dist/chunk-CWXZ2MRT.js +222 -0
  38. package/dist/chunk-CWXZ2MRT.js.map +1 -0
  39. package/dist/chunk-D2LBN44V.js +134 -0
  40. package/dist/chunk-D2LBN44V.js.map +1 -0
  41. package/dist/chunk-D6RO54QD.js +674 -0
  42. package/dist/chunk-D6RO54QD.js.map +1 -0
  43. package/dist/{chunk-52PDIZKV.js → chunk-ECVQNGTH.js} +3 -3
  44. package/dist/chunk-FQGLRJGX.js +174 -0
  45. package/dist/chunk-FQGLRJGX.js.map +1 -0
  46. package/dist/{chunk-NGK3N6F2.js → chunk-GCC52YZD.js} +3 -3
  47. package/dist/chunk-HX44GB4Z.js +30 -0
  48. package/dist/chunk-HX44GB4Z.js.map +1 -0
  49. package/dist/{chunk-NN4ASVTY.js → chunk-IIFADWWI.js} +4 -4
  50. package/dist/{chunk-OIZ3XMKB.js → chunk-IOL74S4J.js} +4 -4
  51. package/dist/{chunk-UK2I3ACY.js → chunk-IZBBXKMJ.js} +4 -4
  52. package/dist/{chunk-YA63PVWI.js → chunk-K52CS4KT.js} +12 -10
  53. package/dist/{chunk-YA63PVWI.js.map → chunk-K52CS4KT.js.map} +1 -1
  54. package/dist/{chunk-7OQAU4EA.js → chunk-LDKIIZDW.js} +16 -12
  55. package/dist/{chunk-7OQAU4EA.js.map → chunk-LDKIIZDW.js.map} +1 -1
  56. package/dist/{chunk-QY3DOZMS.js → chunk-LONRQBGV.js} +4 -4
  57. package/dist/{chunk-EL2BZTDL.js → chunk-LXJEAV2V.js} +13 -11
  58. package/dist/{chunk-EL2BZTDL.js.map → chunk-LXJEAV2V.js.map} +1 -1
  59. package/dist/{chunk-XWFNO5PO.js → chunk-MIBWI5H7.js} +3 -3
  60. package/dist/{chunk-527HHQPS.js → chunk-MSMB6XOS.js} +6 -4
  61. package/dist/{chunk-527HHQPS.js.map → chunk-MSMB6XOS.js.map} +1 -1
  62. package/dist/{chunk-C6HZ6C5T.js → chunk-NIFEEIGQ.js} +2 -2
  63. package/dist/{chunk-JQU7FHYH.js → chunk-NZ6TNSCU.js} +10 -10
  64. package/dist/{chunk-3R5Y3XOL.js → chunk-OOEMKOX6.js} +29 -591
  65. package/dist/chunk-OOEMKOX6.js.map +1 -0
  66. package/dist/{chunk-MZC62HPZ.js → chunk-PAOVVHQX.js} +2 -2
  67. package/dist/chunk-PNX43DYW.js +849 -0
  68. package/dist/chunk-PNX43DYW.js.map +1 -0
  69. package/dist/chunk-QCHVR4ZM.js +286 -0
  70. package/dist/chunk-QCHVR4ZM.js.map +1 -0
  71. package/dist/{chunk-SJO2FTPG.js → chunk-QP5X66TO.js} +73 -1304
  72. package/dist/chunk-QP5X66TO.js.map +1 -0
  73. package/dist/{chunk-HQFVJDEN.js → chunk-QQNPVW3J.js} +19 -19
  74. package/dist/chunk-TPVOOTMN.js +532 -0
  75. package/dist/chunk-TPVOOTMN.js.map +1 -0
  76. package/dist/{chunk-IA7BMIPE.js → chunk-UZKQSWHJ.js} +2 -2
  77. package/dist/chunk-WQWKYAAK.js +86 -0
  78. package/dist/chunk-WQWKYAAK.js.map +1 -0
  79. package/dist/{chunk-CP4ZM43V.js → chunk-WTEILBKC.js} +2 -2
  80. package/dist/{chunk-LJ2RDH3F.js → chunk-XG6PVB5S.js} +1 -23
  81. package/dist/chunk-XG6PVB5S.js.map +1 -0
  82. package/dist/{chunk-Q35YIDBV.js → chunk-XKBEHKWO.js} +29 -264
  83. package/dist/chunk-XKBEHKWO.js.map +1 -0
  84. package/dist/{chunk-BOIF2XGG.js → chunk-XXDXIIQ4.js} +2 -2
  85. package/dist/{chunk-6XTQDFGP.js → chunk-YSCZL4U5.js} +3 -3
  86. package/dist/{chunk-6XTQDFGP.js.map → chunk-YSCZL4U5.js.map} +1 -1
  87. package/dist/{chunk-7ZUCEMCY.js → chunk-ZEXGGGLW.js} +9 -11
  88. package/dist/{chunk-7ZUCEMCY.js.map → chunk-ZEXGGGLW.js.map} +1 -1
  89. package/dist/{chunk-DX32P2DT.js → chunk-ZKAKA54B.js} +2 -2
  90. package/dist/{chunk-TVIX653Q.js → chunk-ZKCNPKUO.js} +4 -4
  91. package/dist/{chunk-DE7JSWXV.js → chunk-ZNE25EAR.js} +8 -6
  92. package/dist/{chunk-DE7JSWXV.js.map → chunk-ZNE25EAR.js.map} +1 -1
  93. package/dist/{chunk-FLF6AECQ.js → chunk-ZPP75QWG.js} +17 -15
  94. package/dist/{chunk-FLF6AECQ.js.map → chunk-ZPP75QWG.js.map} +1 -1
  95. package/dist/{cli-PRZHQ3QB.js → cli-37SRAYNE.js} +14 -15
  96. package/dist/{cli-PRZHQ3QB.js.map → cli-37SRAYNE.js.map} +1 -1
  97. package/dist/{cli-TYGOHJOJ.js → cli-HXWYUKGJ.js} +225 -58
  98. package/dist/cli-HXWYUKGJ.js.map +1 -0
  99. package/dist/{cli-HUIMNJT6.js → cli-IRHPPUFJ.js} +19 -20
  100. package/dist/{cli-HUIMNJT6.js.map → cli-IRHPPUFJ.js.map} +1 -1
  101. package/dist/{cli-6PGVHP7Y.js → cli-KIID535Y.js} +17 -19
  102. package/dist/{cli-6PGVHP7Y.js.map → cli-KIID535Y.js.map} +1 -1
  103. package/dist/{cli-AAG3N4NB.js → cli-MTDGQIIV.js} +17 -18
  104. package/dist/{cli-AAG3N4NB.js.map → cli-MTDGQIIV.js.map} +1 -1
  105. package/dist/{cli-E3H6ZP4I.js → cli-NM6FZ54R.js} +5 -3
  106. package/dist/{cli-E3H6ZP4I.js.map → cli-NM6FZ54R.js.map} +1 -1
  107. package/dist/{cli-MHTYPVOD.js → cli-XIODOEUG.js} +113 -20
  108. package/dist/{cli-MHTYPVOD.js.map → cli-XIODOEUG.js.map} +1 -1
  109. package/dist/{cli-YW6VWBHX.js → cli-YL3IDR52.js} +10 -10
  110. package/dist/{cli-QKIJOXGW.js → cli-ZQUJYQBA.js} +17 -17
  111. package/dist/cli.js +11 -11
  112. package/dist/config-O6UBGEDK.js +26 -0
  113. package/dist/conformance-ALLPNGEQ.js +18 -0
  114. package/dist/docmeta.js +9 -9
  115. package/dist/github-UCYLM3DR.js +26 -0
  116. package/dist/github-VEJFO6JJ.js +31 -0
  117. package/dist/host-6GURH5HE.js +23 -0
  118. package/dist/index.d.ts +72 -4
  119. package/dist/index.js +176 -166
  120. package/dist/index.js.map +1 -1
  121. package/dist/{json-4DCKDGUV.js → json-6F52FSXZ.js} +12 -13
  122. package/dist/lint-X2GNINK6.js +29 -0
  123. package/dist/list-DP3O3CWB.js +30 -0
  124. package/dist/list-P77RZFZF.js +28 -0
  125. package/dist/{page-QEDB7EVU.js → page-WQCMBNRD.js} +11 -12
  126. package/dist/prepare-52QOK7M4.js +155 -0
  127. package/dist/prepare-52QOK7M4.js.map +1 -0
  128. package/dist/{pretty-SQX33UM2.js → pretty-5MMMNSWF.js} +13 -14
  129. package/dist/{pretty-5DGEBZSV.js → pretty-H4DQREMW.js} +12 -13
  130. package/dist/provider-AMGRDY6V.js +34 -0
  131. package/dist/release-CTYRHZL4.js +36 -0
  132. package/dist/release-CTYRHZL4.js.map +1 -0
  133. package/dist/{reporters-YELDDYJD.js → reporters-SU3VUKKX.js} +7 -5
  134. package/dist/{reporters-OHSI3RMV.js → reporters-WIHBEMPG.js} +11 -12
  135. package/dist/reporters-WIHBEMPG.js.map +1 -0
  136. package/dist/run-L2DWJ26K.js +32 -0
  137. package/dist/run-L2DWJ26K.js.map +1 -0
  138. package/dist/{term-2WMDZ4PY.js → term-PJIJQZNF.js} +16 -17
  139. package/dist/{term-2WMDZ4PY.js.map → term-PJIJQZNF.js.map} +1 -1
  140. package/dist/validate-XCDSPURG.js +17 -0
  141. package/dist/validate-XCDSPURG.js.map +1 -0
  142. package/package.json +2 -2
  143. package/plugin/manni/.claude-plugin/plugin.json +1 -1
  144. package/plugin/manni/hooks/hooks.json +47 -0
  145. package/dist/batch-GOE3UXOD.js +0 -36
  146. package/dist/build-M7BMEHL2.js +0 -33
  147. package/dist/calibrate-6RRAILUY.js +0 -31
  148. package/dist/capture-RJPQ6B4N.js +0 -32
  149. package/dist/check-BQD64X3N.js +0 -27
  150. package/dist/chunk-3R5Y3XOL.js.map +0 -1
  151. package/dist/chunk-3YHAYXBC.js +0 -164
  152. package/dist/chunk-3YHAYXBC.js.map +0 -1
  153. package/dist/chunk-HVFR66GQ.js.map +0 -1
  154. package/dist/chunk-LJ2RDH3F.js.map +0 -1
  155. package/dist/chunk-NAZRLJAK.js +0 -3090
  156. package/dist/chunk-NAZRLJAK.js.map +0 -1
  157. package/dist/chunk-Q35YIDBV.js.map +0 -1
  158. package/dist/chunk-QCBICNKC.js.map +0 -1
  159. package/dist/chunk-SJO2FTPG.js.map +0 -1
  160. package/dist/chunk-TU2WUBVZ.js +0 -2
  161. package/dist/cli-TYGOHJOJ.js.map +0 -1
  162. package/dist/github-3WMSTNTK.js +0 -32
  163. package/dist/github-OXSJQ4PS.js +0 -27
  164. package/dist/lint-YDHVVZHT.js +0 -30
  165. package/dist/list-3ZO2NIYO.js +0 -31
  166. package/dist/list-EJH6VAOW.js +0 -29
  167. package/dist/run-IP6NZHAG.js +0 -33
  168. package/dist/validate-G6HH3YXL.js +0 -16
  169. /package/dist/{batch-GOE3UXOD.js.map → batch-U6S2JUUN.js.map} +0 -0
  170. /package/dist/{build-M7BMEHL2.js.map → build-4RN6WBCP.js.map} +0 -0
  171. /package/dist/{calibrate-6RRAILUY.js.map → calibrate-6VIZYR4L.js.map} +0 -0
  172. /package/dist/{capture-RJPQ6B4N.js.map → capture-DP3NXAZE.js.map} +0 -0
  173. /package/dist/{check-BQD64X3N.js.map → check-ERVNGKLC.js.map} +0 -0
  174. /package/dist/{check-ESNS7ZBC.js.map → check-OAJWC3WD.js.map} +0 -0
  175. /package/dist/{check-RQIIIURI.js.map → check-STHXZIZO.js.map} +0 -0
  176. /package/dist/{chunk-TA42STP7.js.map → chunk-2ZWTSRE5.js.map} +0 -0
  177. /package/dist/{chunk-F2OVHJNC.js.map → chunk-4Z2MN5FR.js.map} +0 -0
  178. /package/dist/{chunk-TCC737IS.js.map → chunk-5VWDIWOH.js.map} +0 -0
  179. /package/dist/{chunk-ELZ2IIOF.js.map → chunk-6URSCTTX.js.map} +0 -0
  180. /package/dist/{chunk-K3U5F2QT.js.map → chunk-6VDBP5UV.js.map} +0 -0
  181. /package/dist/{chunk-C3KI45RF.js.map → chunk-7XZ6INKO.js.map} +0 -0
  182. /package/dist/{chunk-SNEHX4VE.js.map → chunk-B5CMM57M.js.map} +0 -0
  183. /package/dist/{chunk-GAZFKZHM.js.map → chunk-CEVU3GFF.js.map} +0 -0
  184. /package/dist/{chunk-52PDIZKV.js.map → chunk-ECVQNGTH.js.map} +0 -0
  185. /package/dist/{chunk-NGK3N6F2.js.map → chunk-GCC52YZD.js.map} +0 -0
  186. /package/dist/{chunk-NN4ASVTY.js.map → chunk-IIFADWWI.js.map} +0 -0
  187. /package/dist/{chunk-OIZ3XMKB.js.map → chunk-IOL74S4J.js.map} +0 -0
  188. /package/dist/{chunk-UK2I3ACY.js.map → chunk-IZBBXKMJ.js.map} +0 -0
  189. /package/dist/{chunk-QY3DOZMS.js.map → chunk-LONRQBGV.js.map} +0 -0
  190. /package/dist/{chunk-XWFNO5PO.js.map → chunk-MIBWI5H7.js.map} +0 -0
  191. /package/dist/{chunk-C6HZ6C5T.js.map → chunk-NIFEEIGQ.js.map} +0 -0
  192. /package/dist/{chunk-JQU7FHYH.js.map → chunk-NZ6TNSCU.js.map} +0 -0
  193. /package/dist/{chunk-MZC62HPZ.js.map → chunk-PAOVVHQX.js.map} +0 -0
  194. /package/dist/{chunk-HQFVJDEN.js.map → chunk-QQNPVW3J.js.map} +0 -0
  195. /package/dist/{chunk-IA7BMIPE.js.map → chunk-UZKQSWHJ.js.map} +0 -0
  196. /package/dist/{chunk-CP4ZM43V.js.map → chunk-WTEILBKC.js.map} +0 -0
  197. /package/dist/{chunk-BOIF2XGG.js.map → chunk-XXDXIIQ4.js.map} +0 -0
  198. /package/dist/{chunk-DX32P2DT.js.map → chunk-ZKAKA54B.js.map} +0 -0
  199. /package/dist/{chunk-TVIX653Q.js.map → chunk-ZKCNPKUO.js.map} +0 -0
  200. /package/dist/{chunk-TU2WUBVZ.js.map → cli-YL3IDR52.js.map} +0 -0
  201. /package/dist/{cli-QKIJOXGW.js.map → cli-ZQUJYQBA.js.map} +0 -0
  202. /package/dist/{cli-YW6VWBHX.js.map → config-O6UBGEDK.js.map} +0 -0
  203. /package/dist/{github-3WMSTNTK.js.map → conformance-ALLPNGEQ.js.map} +0 -0
  204. /package/dist/{github-OXSJQ4PS.js.map → github-UCYLM3DR.js.map} +0 -0
  205. /package/dist/{json-4DCKDGUV.js.map → github-VEJFO6JJ.js.map} +0 -0
  206. /package/dist/{lint-YDHVVZHT.js.map → host-6GURH5HE.js.map} +0 -0
  207. /package/dist/{list-3ZO2NIYO.js.map → json-6F52FSXZ.js.map} +0 -0
  208. /package/dist/{list-EJH6VAOW.js.map → lint-X2GNINK6.js.map} +0 -0
  209. /package/dist/{page-QEDB7EVU.js.map → list-DP3O3CWB.js.map} +0 -0
  210. /package/dist/{pretty-5DGEBZSV.js.map → list-P77RZFZF.js.map} +0 -0
  211. /package/dist/{pretty-SQX33UM2.js.map → page-WQCMBNRD.js.map} +0 -0
  212. /package/dist/{reporters-OHSI3RMV.js.map → pretty-5MMMNSWF.js.map} +0 -0
  213. /package/dist/{reporters-YELDDYJD.js.map → pretty-H4DQREMW.js.map} +0 -0
  214. /package/dist/{run-IP6NZHAG.js.map → provider-AMGRDY6V.js.map} +0 -0
  215. /package/dist/{validate-G6HH3YXL.js.map → reporters-SU3VUKKX.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/docevals/core/config.ts","../src/docevals/core/config-schema.json","../src/docevals/core/split.ts","../src/docevals/core/discover.ts","../src/docevals/core/external.ts","../src/docevals/core/resolve.ts","../src/docevals/schema.ts","../src/docevals/graders/command.ts","../src/docevals/graders/options.ts","../src/docevals/core/target.ts","../src/docevals/graders/native/regex.ts","../src/docevals/graders/registry.ts","../src/docevals/core/feasibility.ts","../src/docevals/core/baseline.ts","../src/docevals/core/since.ts","../src/docevals/core/newer-than.ts","../src/docevals/graders/types.ts","../src/docevals/judge/cache.ts","../src/docevals/judge/prompt.ts","../src/docevals/judge/self-preference.ts","../src/docevals/core/engine.ts"],"sourcesContent":["/**\n * Loads and validates `manni.config.yaml`. The file is shared by the manni\n * family of documentation tools: manni docevals reads its own `docevals:`\n * namespace and leaves every sibling key alone. It carries provider and judge\n * settings plus the central library of named evals and suites that page\n * frontmatter references. Validation is JSON Schema (2020-12) via Ajv; defaults\n * are applied in code afterward so the resolved shape is fully typed.\n */\nimport { resolve, dirname } from \"node:path\";\nimport {\n findConfigFileSync,\n readConfigFileSync,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport { parseCollections, type CollectionConfig } from \"../../shared/collections.js\";\nimport { parse as parseYaml } from \"yaml\";\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport configSchema from \"./config-schema.json\" with { type: \"json\" };\nimport { DocevalsError, type EvalType, type Severity } from \"../types.js\";\n// Type-only, so the cycle with target.ts (which needs ResolvedPagePlan) is\n// erased at compile time rather than existing at runtime.\nimport type { EvalTarget } from \"./target.js\";\nimport { DEFAULT_CHUNK_CHARS } from \"./split.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport {\n PROVIDERS_KEY,\n assertKnownProvider,\n parseProviders,\n type ProvidersConfig,\n} from \"../../shared/providers.js\";\nimport type { ProviderSelector } from \"@hawkeyexl/inference\";\nimport {\n configuredGrants,\n EXECUTION_GRANTS,\n isExecutionGrant,\n unknownGrantsMessage,\n type ExecutionGrant,\n} from \"../../shared/execution.js\";\n\n/** A provider `docevals.provider` or `--provider` may name, `auto` included. */\nexport type ProviderName = ProviderSelector;\n\n/** One capability the operator can grant; the values are the family's. */\nexport type { ExecutionGrant } from \"../../shared/execution.js\";\n\n/**\n * One eval definition, as the rest of the codebase sees it.\n *\n * An eval entry spells these keys in kebab-case wherever it is written, in the\n * config's `evals:` and in page frontmatter alike, because that is the\n * vocabulary the metadata tool publishes and a field should mean one thing\n * wherever it is written. TypeScript keeps camelCase, because that is what\n * TypeScript reads like. `normalizeEvalDef` is the single boundary between\n * the two; nothing downstream should ever see a kebab key. The config's own\n * section keys (`judge.ensembleRuns`) are camelCase, as every manni tool's\n * are, and need no boundary.\n */\nexport interface EvalDef {\n assertion?: string;\n type?: EvalType;\n grader?: string;\n /** Provider or agent judging an `ai` eval; omit for the config default. */\n provider?: string;\n evidence?: string;\n /** Anchor examples. One or several each — a bare string normalizes to a list. */\n examples?: { pass?: string[]; fail?: string[] };\n command?: string[];\n successExitCodes?: number[];\n timeoutMs?: number;\n /** sha256 of the assertion when the check script was generated. */\n generatedAssertionHash?: string;\n options?: Record<string, unknown>;\n severity?: Severity;\n /** Relative contribution to the suite pass rate. Never changes the outcome. */\n weight?: number;\n /** Which bytes the grader receives. Defaults to the page body. */\n target?: EvalTarget;\n /** Judge model for this eval; a CLI --model still wins. */\n model?: string;\n /** Ensemble runs for this eval; a CLI --runs still wins. */\n runs?: number;\n}\n\n/** The file-side spelling of an eval definition. Kebab, exactly as authored. */\nexport interface RawEvalDef {\n assertion?: string;\n type?: EvalType;\n grader?: string;\n provider?: string;\n evidence?: string;\n examples?: { pass?: string | string[]; fail?: string | string[] };\n command?: string[];\n \"success-exit-codes\"?: number[];\n \"timeout-ms\"?: number;\n \"generated-assertion-hash\"?: string;\n options?: Record<string, unknown>;\n severity?: Severity;\n target?: EvalTarget;\n model?: string;\n runs?: number;\n // One word, so kebab and camel are the same string — it still passes through\n // normalizeEvalDef, because that is the only boundary between the two\n // spellings and a field that skips it is a field the next reader has to\n // check for.\n weight?: number;\n}\n\n/** One anchor example, or several, as a list. */\nfunction anchorList(v: string | string[] | undefined): string[] | undefined {\n if (v === undefined) return undefined;\n return Array.isArray(v) ? v : [v];\n}\n\n/**\n * Kebab file keys in, camelCase `EvalDef` out. Used for config-defined evals\n * and for page inline evals, so both reach the engine in one shape.\n */\nexport function normalizeEvalDef(raw: RawEvalDef): EvalDef {\n const examples =\n raw.examples === undefined\n ? undefined\n : {\n ...(anchorList(raw.examples.pass) !== undefined && {\n pass: anchorList(raw.examples.pass),\n }),\n ...(anchorList(raw.examples.fail) !== undefined && {\n fail: anchorList(raw.examples.fail),\n }),\n };\n return {\n assertion: raw.assertion,\n type: raw.type,\n grader: raw.grader,\n provider: raw.provider,\n evidence: raw.evidence,\n examples,\n command: raw.command,\n successExitCodes: raw[\"success-exit-codes\"],\n timeoutMs: raw[\"timeout-ms\"],\n generatedAssertionHash: raw[\"generated-assertion-hash\"],\n options: raw.options,\n severity: raw.severity,\n weight: raw.weight,\n target: raw.target,\n model: raw.model,\n runs: raw.runs,\n };\n}\n\nexport interface SuiteDef {\n targetPassRate: number;\n evals: string[];\n /** Criteria scored in this suite, alongside `evals`. */\n criteria: string[];\n}\n\n/**\n * Several evals scored as one unit.\n *\n * The grouping lives here rather than in page frontmatter because the page\n * vocabulary is the metadata tool's and this is our scoring model — a criterion is a\n * statement about how a corpus is graded, not a fact about a page.\n */\nexport interface CriterionDef {\n evals: string[];\n combine: \"all\" | \"any\";\n weight: number;\n}\n\nexport interface DocevalsConfig {\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 defaults: { suite: string | null; failFast: boolean; concurrency: number };\n /**\n * `docevals.provider`, or `null` when unset: the family's\n * `providers.provider` decides then, and `auto` (detect) after it.\n */\n provider: ProviderName | 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.\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 /** Findings baseline path, resolved against the config's directory (ADR 01017). */\n baseline: string | null;\n judge: {\n ensembleRuns: number;\n /** Judge-stage parallelism. Falls back to `defaults.concurrency` (ADR 01039). */\n concurrency: number;\n temperature: number;\n zones: { autoPass: number; autoFail: number };\n falsePositiveAlert: number;\n cacheDir: string;\n maxTurns: number | null;\n chunkChars: number;\n };\n scripts: {\n dir: string;\n configDir: string;\n timeoutMs: number;\n };\n /**\n * What content-authored code this run may execute. Every grant unless the\n * operator narrows it (proposal 0075); `[]` runs nothing.\n *\n * A page reaches a shell through a `command` eval declared in its\n * frontmatter, or through `options.command` argv it hands a grader.\n */\n execution: { allow: ExecutionGrant[] };\n fill: {\n confidenceThreshold: number;\n maxEvalsPerPage: number;\n temperature: number;\n cacheDir: string;\n maxTurns: number | null;\n chunkChars: number;\n };\n evals: Record<string, EvalDef>;\n criteria: Record<string, CriterionDef>;\n suites: Record<string, SuiteDef>;\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/** Top-level key manni docevals owns inside the shared manni config. */\nconst NAMESPACE = \"docevals\";\n\nexport const DEFAULT_CONFIG_FILENAME = \"manni.config.yaml\";\n\n/**\n * Root keys that only a pre-rename config has. A manni config namespaces every\n * tool, so finding these at the root means the file was never migrated.\n */\nconst PRE_RENAME_ROOT_KEYS = [\n \"version\",\n \"files\",\n \"defaults\",\n \"provider\",\n \"judge\",\n \"scripts\",\n \"fill\",\n \"evals\",\n \"suites\",\n];\n\n// `verbose` puts the parent schema on each error, so an unknown key can be\n// checked against the keys its section does have.\nconst ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true, verbose: true });\nconst validateConfig = ajv.compile(configSchema);\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\n * is what lets `parseConfig` read the file without an `any` — and an `any` here\n * would be the worst place for one, since every default in the tool flows\n * through this function.\n */\ninterface RawDocevalsConfig {\n defaults?: {\n suite?: string | null;\n failFast?: boolean;\n concurrency?: number;\n };\n provider?: string;\n model?: string;\n baseline?: string | null;\n judge?: {\n ensembleRuns?: number;\n concurrency?: number;\n temperature?: number;\n zones?: { autoPass?: number; autoFail?: number };\n falsePositiveAlert?: number;\n cacheDir?: string;\n maxTurns?: number | null;\n chunkChars?: number;\n };\n execution?: { allow?: ExecutionGrant[] };\n scripts?: {\n dir?: string;\n configDir?: string;\n timeoutMs?: number;\n };\n fill?: {\n confidenceThreshold?: number;\n maxEvalsPerPage?: number;\n temperature?: number;\n cacheDir?: string;\n maxTurns?: number | null;\n chunkChars?: number;\n };\n evals?: Record<string, RawEvalDef>;\n criteria?: Record<string, RawCriterionDef>;\n suites?: Record<string, RawSuiteDef>;\n}\n\ninterface RawCriterionDef {\n evals?: string[];\n combine?: \"all\" | \"any\";\n weight?: number;\n}\n\ninterface RawSuiteDef {\n \"target-pass-rate\"?: number;\n evals?: string[];\n criteria?: string[];\n}\n\n/** The 0.1 `generated: {assertionHash}` wrapper, as opposed to any other key of that name. */\nfunction isAssertionHashWrapper(value: unknown): boolean {\n return (\n value != null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n \"assertionHash\" in value\n );\n}\n\n/** Walk `node`, reporting every camelCase key with the kebab it should be. */\nfunction findPreKebabKeys(\n node: unknown,\n path: string,\n): { at: string; becomes: string }[] {\n if (node == null || typeof node !== \"object\" || Array.isArray(node)) return [];\n const found: { at: string; becomes: string }[] = [];\n for (const [key, value] of Object.entries(node as Record<string, unknown>)) {\n if (/[a-z0-9][A-Z]/.test(key)) {\n found.push({\n at: `${path}.${key}`,\n becomes: key.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase(),\n });\n }\n // `generated: {assertionHash}` flattened rather than renamed, so the\n // generic rule above would suggest the wrong thing for the wrapper itself.\n //\n // Matched on shape, not on the name alone: `options` is a grader’s open\n // runtime contract, so a key called `generated` there is legal config and\n // an error naming `generated-assertion-hash` would be advice nobody can\n // follow. Only the 0.1 wrapper — an object carrying `assertionHash` — is\n // the thing this rule is about.\n if (key === \"generated\" && isAssertionHashWrapper(value)) {\n found.push({ at: `${path}.generated`, becomes: \"generated-assertion-hash\" });\n continue;\n }\n found.push(...findPreKebabKeys(value, `${path}.${key}`));\n }\n return found;\n}\n\n/** The section keys whose entries are the frontmatter vocabulary's, in kebab-case. */\nconst ENTRY_SECTIONS = [\"evals\", \"criteria\", \"suites\"] as const;\n\n/**\n * `; did you mean \"failFast\"?` when `key` is the kebab spelling of a key its\n * section has. Only the exact counterpart: a guess at a near miss is advice\n * that can be wrong, and the kebab spelling is the one mistake a reader of\n * the frontmatter vocabulary is likely to make here.\n */\nfunction camelCaseHint(key: string, parentSchema: unknown): string {\n const camel = key.replace(/-([a-z0-9])/g, (_, c: string) => c.toUpperCase());\n if (camel === key || parentSchema === null || typeof parentSchema !== \"object\") return \"\";\n const properties = (parentSchema as { properties?: unknown }).properties;\n return properties !== null && typeof properties === \"object\" && Object.hasOwn(properties, camel)\n ? `; did you mean \"${camel}\"?`\n : \"\";\n}\n\n/**\n * The hint on an old `provider:` object. The key used to hold a `default` and\n * a section per provider; it is now the provider's name, as `fill.provider` is\n * in the metadata tool, and the connection settings moved to the family's\n * top-level `providers:` map, which every tool reads.\n * Ajv's own message names the key and says it must be a string, which is true\n * and leaves the reader to find out where the settings went.\n */\nfunction movedProviderHint(instancePath: string, keyword: string): string {\n return instancePath === `/${NAMESPACE}/provider` && keyword === \"type\"\n ? `; \"provider\" is now a provider name; per-provider settings moved to the top-level providers: map`\n : \"\";\n}\n\n/** Parse and validate config YAML text. `configPath` is used for messages and path resolution. */\nexport function parseConfig(text: string, configPath: string): DocevalsConfig {\n let raw: unknown;\n try {\n raw = parseYaml(text);\n } catch (e) {\n throw new DocevalsError(\n `Invalid YAML in ${configPath}: ${errorMessage(e)}`,\n );\n }\n if (raw == null || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new DocevalsError(`Invalid config in ${configPath}: root must be an object`);\n }\n const doc = raw as Record<string, unknown>;\n const wrapped = NAMESPACE in doc;\n const toError = (message: string): Error => new DocevalsError(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(doc[PROVIDERS_KEY], configPath, dirname(resolve(configPath)), toError)\n : {};\n return parseConfigSection(wrapped ? doc[NAMESPACE] : doc, configPath, wrapped, {\n source: configPath,\n collections,\n providers,\n });\n}\n\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 cite's and meta's `config.ts` carry, repeated because those\n * modules are theirs.\n */\nconst CONFIG_REF = \"https://hawkeyexl.github.io/manni/meta/reference/configuration/\";\n\n/**\n * The key proposal 0041 moved out of `docevals:` and up to the family level.\n * Refused rather than aliased, as meta and cite refuse theirs: an alias would\n * be a second place to declare a document set that is meant to be declared\n * once. Checked before Ajv, which would call it an unknown key.\n */\nconst MOVED_KEY = \"files\";\n\n/**\n * The key the family's top-level `providers:` map replaced. Refused rather\n * than aliased, for the reason `files` is: the settings are declared once, for\n * every tool, and a second place to declare them is a second answer to which\n * one wins. Checked before Ajv, which would call it an unknown key.\n */\nconst MOVED_PROVIDERS_KEY = \"providers\";\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 * Validate the tool's section. `value` is what sat under `docevals:` when\n * `wrapped`, and the whole document otherwise (a legacy file, or an explicit\n * path with no wrapper key). Messages name `configPath`; relative paths in\n * the config resolve against its directory. `file` carries the family keys;\n * absent, the section is its own source and declares no collections.\n */\nexport function parseConfigSection(\n value: unknown,\n configPath: string,\n wrapped: boolean,\n file: ConfigFileContext = { source: configPath, collections: [] },\n): DocevalsConfig {\n // The rest of this function reads `raw` as the document shape the checks\n // below were written against: a mapping with the section under NAMESPACE.\n // An empty `docevals:` is a section with nothing set, so every default\n // applies. It has no required key to write in it.\n const raw: Record<string, unknown> = wrapped\n ? { [NAMESPACE]: value ?? {} }\n : (value as Record<string, unknown> | null) ?? {};\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new DocevalsError(`Invalid config in ${configPath}: root must be an object`);\n }\n\n // `--config <path>` reaches here without passing loadConfig's filename check,\n // so a pre-rename file named anything at all would otherwise parse to pure\n // defaults — no evals, no suites, exit 0. Catch it by shape instead.\n if (!(NAMESPACE in raw)) {\n const stray = PRE_RENAME_ROOT_KEYS.filter((k) => k in raw);\n if (stray.length > 0) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: found ${stray.join(\", \")} at the root, ` +\n `but no \"${NAMESPACE}:\" key.\\n` +\n `manni.config.yaml is shared across the manni family, so every docevals ` +\n `setting belongs under a top-level \"${NAMESPACE}:\" key. Indent the file's ` +\n `contents one level and add that key.`,\n );\n }\n }\n const section = raw[NAMESPACE];\n if (\n section !== null &&\n typeof section === \"object\" &&\n !Array.isArray(section) &&\n Object.hasOwn(section, MOVED_KEY)\n ) {\n throw new DocevalsError(\n `${file.source}: \"${MOVED_KEY}\" is no longer a docevals key. Document sets are declared once for every tool, under a top-level collections: list. See ${CONFIG_REF}#collections`,\n );\n }\n if (\n section !== null &&\n typeof section === \"object\" &&\n !Array.isArray(section) &&\n Object.hasOwn(section, MOVED_PROVIDERS_KEY)\n ) {\n throw new DocevalsError(\n `${file.source}: \"${MOVED_PROVIDERS_KEY}\" is no longer a docevals key. Provider settings are declared once for every tool, under a top-level providers: map. See ${CONFIG_REF}#providers`,\n );\n }\n\n // Eval, criterion and suite entries are kebab-case, the spelling a page\n // uses for the same entries. Ajv would reject a camelCase spelling there as\n // \"must NOT have additional properties\", which names the parent object and\n // leaves the reader to guess which key. Name the key and its kebab spelling\n // instead. The section's own keys are camelCase and are not walked: a kebab\n // spelling of one is an unknown key, and the Ajv message below names the\n // camelCase key it meant.\n const preKebab = ENTRY_SECTIONS.flatMap((name) =>\n section !== null && typeof section === \"object\" && !Array.isArray(section)\n ? findPreKebabKeys((section as Record<string, unknown>)[name], `${NAMESPACE}.${name}`)\n : [],\n );\n if (preKebab.length > 0) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: camelCase keys are not read in eval, criterion or suite entries.\\n` +\n preKebab.map((p) => ` ${p.at} -> ${p.becomes}`).join(\"\\n\") +\n `\\nThose entries are kebab-case, matching the frontmatter vocabulary.`,\n );\n }\n\n // The removed key would otherwise surface as \"must NOT have additional\n // properties\" against `scripts`, which names the parent and leaves the\n // reader to find the child — the same failure the camelCase check above\n // exists to avoid.\n const ns = raw[NAMESPACE];\n const scriptsSection =\n ns && typeof ns === \"object\"\n ? (ns as Record<string, unknown>).scripts\n : undefined;\n if (\n scriptsSection &&\n typeof scriptsSection === \"object\" &&\n \"allow-frontmatter-commands\" in scriptsSection\n ) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: scripts.allow-frontmatter-commands has been replaced by ` +\n `execution.allow.\n` +\n ` Command evals run unless it narrows them; write ` +\n `\\`execution: { allow: [] }\\` to stop them.`,\n );\n }\n\n // Ajv's enum error names neither the value nor the ones allowed, and a\n // grant is the key where a silent misreading costs the most.\n const unknownGrants = configuredGrants(ns).filter((g) => !isExecutionGrant(g));\n if (unknownGrants.length > 0) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: ${unknownGrantsMessage(unknownGrants)}`,\n );\n }\n\n if (!validateConfig(raw)) {\n const details = (validateConfig.errors ?? [])\n .map((e) => {\n // Ajv reports an unknown key against the *parent* object, so the bare\n // message (\"must NOT have additional properties\") leaves the reader to\n // diff their file against the schema to find which key it meant. Name\n // it, for the same reason findPreKebabKeys above names a camelCase\n // spelling: the common case is a removed key in an unmigrated config\n // -- `judge.max-cost-usd` after ADR 01019, say -- and a migration\n // error that makes you guess is one people work around.\n const extra =\n e.keyword === \"additionalProperties\"\n ? (e.params as { additionalProperty?: string }).additionalProperty\n : undefined;\n if (extra !== undefined) {\n return ` ${e.instancePath || \"/\"}: unknown key \"${extra}\"${camelCaseHint(extra, e.parentSchema)}`;\n }\n return ` ${e.instancePath || \"/\"}: ${e.message ?? \"is invalid\"}${movedProviderHint(e.instancePath, e.keyword)}`;\n })\n .join(\"\\n\");\n throw new DocevalsError(`Invalid config in ${configPath}:\\n${details}`);\n }\n\n // Sibling tools own the other root keys; this reads only its own namespace.\n // A file that configures no docevals at all leaves every default in place.\n const r = (raw[NAMESPACE] ??\n {}) as RawDocevalsConfig;\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 ones that reach 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 = r.provider ?? null;\n if (provider !== null) assertKnownProvider(provider, (message) => new DocevalsError(message));\n\n const suites: Record<string, SuiteDef> = {};\n for (const [name, def] of Object.entries(r.suites ?? {})) {\n suites[name] = {\n targetPassRate: def[\"target-pass-rate\"] ?? 1.0,\n evals: def.evals ?? [],\n criteria: def.criteria ?? [],\n };\n }\n\n const criteria: Record<string, CriterionDef> = {};\n for (const [name, def] of Object.entries(r.criteria ?? {})) {\n criteria[name] = {\n evals: def.evals ?? [],\n combine: def.combine ?? \"all\",\n weight: def.weight ?? 1,\n };\n }\n\n const config: DocevalsConfig = {\n collections: file.collections,\n configSource: file.source,\n defaults: {\n suite: r.defaults?.suite ?? null,\n failFast: r.defaults?.failFast ?? false,\n concurrency: r.defaults?.concurrency ?? 4,\n },\n provider,\n model: r.model ?? null,\n providers: file.providers ?? {},\n baseline: r.baseline ?? null,\n judge: {\n ensembleRuns: r.judge?.ensembleRuns ?? 3,\n // Falls back to the corpus-wide setting, so an unset value behaves\n // exactly as it did before this knob existed. It is separable because\n // the judge's right parallelism is not the deterministic graders': a\n // local in-process model serves one context at a time (ADR 01039).\n concurrency: r.judge?.concurrency ?? r.defaults?.concurrency ?? 4,\n temperature: r.judge?.temperature ?? 0,\n zones: {\n autoPass: r.judge?.zones?.autoPass ?? 0.8,\n autoFail: r.judge?.zones?.autoFail ?? 0.8,\n },\n falsePositiveAlert: r.judge?.falsePositiveAlert ?? 0.15,\n cacheDir: r.judge?.cacheDir ?? \".manni/docevals/cache\",\n maxTurns: r.judge?.maxTurns ?? null,\n chunkChars: r.judge?.chunkChars ?? DEFAULT_CHUNK_CHARS,\n },\n scripts: {\n dir: r.scripts?.dir ?? \"{docDir}/manni-docevals\",\n configDir: r.scripts?.configDir ?? \"manni-docevals-scripts\",\n timeoutMs: r.scripts?.timeoutMs ?? 30000,\n },\n execution: { allow: [...(r.execution?.allow ?? EXECUTION_GRANTS)] },\n fill: {\n confidenceThreshold: r.fill?.confidenceThreshold ?? 0.7,\n maxEvalsPerPage: r.fill?.maxEvalsPerPage ?? 3,\n temperature: r.fill?.temperature ?? 0,\n cacheDir: r.fill?.cacheDir ?? \".manni/docevals/cache/fill\",\n maxTurns: r.fill?.maxTurns ?? null,\n chunkChars: r.fill?.chunkChars ?? DEFAULT_CHUNK_CHARS,\n },\n evals: Object.fromEntries(\n Object.entries(r.evals ?? {}).map(([name, def]) => [\n name,\n normalizeEvalDef(def),\n ]),\n ),\n criteria,\n suites,\n configPath: abs,\n configDir: dir,\n };\n\n // Referential integrity: suites may only reference defined evals.\n for (const [suiteName, suite] of Object.entries(config.suites)) {\n for (const evalName of suite.evals) {\n if (!(evalName in config.evals)) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: suite \"${suiteName}\" references undefined eval \"${evalName}\"`,\n );\n }\n }\n }\n for (const [critName, crit] of Object.entries(config.criteria)) {\n for (const evalName of crit.evals) {\n if (!(evalName in config.evals)) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: criterion \"${critName}\" references undefined eval \"${evalName}\"`,\n );\n }\n }\n }\n for (const [suiteName, suite] of Object.entries(config.suites)) {\n for (const critName of suite.criteria) {\n if (!(critName in config.criteria)) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: suite \"${suiteName}\" references undefined criterion \"${critName}\"`,\n );\n }\n }\n }\n if (config.defaults.suite && !(config.defaults.suite in config.suites)) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: defaults.suite \"${config.defaults.suite}\" is not a defined suite`,\n );\n }\n return config;\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`: the family file,\n * read at its `docevals:` key). With no config file present, built-in\n * defaults apply (no named evals or suites).\n */\nexport function loadConfig(path?: string, cwd = process.cwd()): DocevalsConfig {\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, file.wrapped, {\n source: file.source,\n collections: file.collections,\n providers: file.providers ?? {},\n });\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()): DocevalsConfig {\n return {\n ...parseConfigSection(null, resolve(cwd, DEFAULT_CONFIG_FILENAME), false),\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. The missing-config refusal is\n * `discoverPages`', which every command reaches next.\n */\nexport function loadRunConfig(opts: RunConfigOptions, cwd = process.cwd()): DocevalsConfig {\n assertCollectionWithoutPaths(opts.collection, opts.paths);\n return opts.noConfig ? defaultConfig(cwd) : loadConfig(opts.configPath, cwd);\n}\n\n/** The message meta and cite give, in docevals' 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 DocevalsError(\n \"--collection selects a configured collection; it cannot be combined with paths.\",\n );\n }\n}\n\nconst CONFIG_FILE: ConfigFileOptions = {\n section: NAMESPACE,\n // docevals never shipped a file of its own under manni, so, like cite and\n // a11y, it has no pre-family name to read.\n legacyNames: [],\n toError: (message) => new DocevalsError(message),\n};\n\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"manni:config:docevals\",\n \"title\": \"manni docevals configuration\",\n \"description\": \"The docevals: section of manni.config.yaml. Every manni tool reads its own top-level key; keys that belong to sibling tools are ignored here. Section keys are camelCase, as every manni tool's are. The entries under evals, criteria and suites keep the kebab-case spelling of the frontmatter vocabulary, because they are the same entries a page carries.\",\n \"type\": \"object\",\n \"properties\": {\n \"docevals\": {\n \"$ref\": \"#/$defs/docevalsConfig\"\n }\n },\n \"additionalProperties\": true,\n \"$defs\": {\n \"docevalsConfig\": {\n \"type\": \"object\",\n \"properties\": {\n \"baseline\": {\n \"type\": [\n \"string\",\n \"null\"\n ],\n \"description\": \"Path to the findings baseline, relative to this config file. A baseline records today's findings so a run fails only on new ones (ADR 01017). Null (the default) means no baseline. `--baseline`/`--no-baseline` override this; a bare `--write-baseline` records into *this* path, so a repo that points it somewhere custom cannot accidentally record into a file nothing reads.\"\n },\n \"defaults\": {\n \"type\": \"object\",\n \"properties\": {\n \"suite\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"failFast\": {\n \"type\": \"boolean\"\n },\n \"concurrency\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"additionalProperties\": false\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Which provider judges, generates, fills and promotes: 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 an ai eval's own provider wins over it for that eval. 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 provider from --provider, an eval or providers.provider that differs from this one 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.\"\n },\n \"judge\": {\n \"type\": \"object\",\n \"properties\": {\n \"ensembleRuns\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"concurrency\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"temperature\": {\n \"type\": \"number\",\n \"minimum\": 0\n },\n \"zones\": {\n \"type\": \"object\",\n \"properties\": {\n \"autoPass\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"autoFail\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n }\n },\n \"additionalProperties\": false\n },\n \"falsePositiveAlert\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"cacheDir\": {\n \"type\": \"string\"\n },\n \"maxTurns\": {\n \"$ref\": \"#/$defs/maxTurns\"\n },\n \"chunkChars\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"default\": 12000,\n \"description\": \"Characters of page content per judge call. A page longer than this is graded by gathering evidence from each part and judging the collected evidence once.\"\n }\n },\n \"additionalProperties\": false\n },\n \"scripts\": {\n \"type\": \"object\",\n \"properties\": {\n \"dir\": {\n \"type\": \"string\"\n },\n \"configDir\": {\n \"type\": \"string\"\n },\n \"timeoutMs\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"additionalProperties\": false\n },\n \"execution\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"allow\": {\n \"type\": \"array\",\n \"items\": {\n \"enum\": [\n \"frontmatter-commands\"\n ]\n },\n \"default\": [\"frontmatter-commands\"],\n \"description\": \"Which content-authored code this corpus may execute. Absent, every grant holds; list fewer to narrow it, or write [] to run none. frontmatter-commands lets `command` evals declared in page frontmatter run. That is code a page author controls, so a run over an untrusted pull request passes --no-execution.\"\n }\n },\n \"description\": \"Operator grant for executing content-authored code.\"\n },\n \"fill\": {\n \"type\": \"object\",\n \"properties\": {\n \"confidenceThreshold\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"maxEvalsPerPage\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"temperature\": {\n \"type\": \"number\",\n \"minimum\": 0\n },\n \"cacheDir\": {\n \"type\": \"string\"\n },\n \"maxTurns\": {\n \"$ref\": \"#/$defs/maxTurns\"\n },\n \"chunkChars\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"default\": 12000,\n \"description\": \"Characters of page content per fill call. A longer page is proposed against in parts and the proposals merged by id, keeping the highest confidence.\"\n }\n },\n \"additionalProperties\": false\n },\n \"evals\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/evalDef\"\n },\n \"description\": \"The central library of named evals. The map key is the eval's id — the same id a page's `use:` reference names.\"\n },\n \"criteria\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/criterionDef\"\n },\n \"description\": \"Named groups of evals scored as one unit. A criterion contributes a single weighted outcome to its suite and its members contribute none, so writing three checks as a group does not let them outvote three standalone evals.\"\n },\n \"suites\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/suiteDef\"\n }\n }\n },\n \"additionalProperties\": false\n },\n \"maxTurns\": {\n \"type\": [\n \"integer\",\n \"null\"\n ],\n \"minimum\": 1,\n \"description\": \"Stop after this many turns. Counts work, not pages. Under `judge` a turn is one ensemble run, so a judged eval spends `judge.ensembleRuns` of them; a run may make a second provider call when the first response fails schema validation, so this is a floor on calls rather than an exact count. Under `fill` a turn is exactly one call. A cached result spends none. Null (the default) is unbounded. Replaces the `max-cost-usd` ceiling, which could not be honored exactly under concurrency — see ADR 01019.\"\n },\n \"evalDef\": {\n \"type\": \"object\",\n \"properties\": {\n \"assertion\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"type\": {\n \"enum\": [\n \"capability\",\n \"regression\"\n ]\n },\n \"grader\": {\n \"type\": \"string\",\n \"pattern\": \"^(ai|command|human|tool:[a-z0-9][a-z0-9-]*)$\"\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"model\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Model judging this ai eval, within provider. A CLI --model still wins over it. Meaningful only on ai evals.\"\n },\n \"runs\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 50,\n \"description\": \"Ensemble runs for this eval, overriding judge.ensembleRuns. A CLI --runs still wins over it. Capped because it multiplies judge cost directly. Meaningful only on ai evals.\"\n },\n \"evidence\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"target\": {\n \"oneOf\": [\n {\n \"enum\": [\n \"body\",\n \"raw\",\n \"frontmatter\"\n ]\n },\n {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"source\",\n \"path\"\n ],\n \"properties\": {\n \"source\": {\n \"const\": \"file\"\n },\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n }\n ],\n \"default\": \"body\",\n \"description\": \"Which bytes the grader receives: the page body with frontmatter stripped (body), the file verbatim (raw), the parsed frontmatter alone (frontmatter), or a companion file beside the page. Distinct from evidence, which hints where to look within what is graded.\"\n },\n \"examples\": {\n \"type\": \"object\",\n \"properties\": {\n \"pass\": {\n \"$ref\": \"#/$defs/anchorList\"\n },\n \"fail\": {\n \"$ref\": \"#/$defs/anchorList\"\n }\n },\n \"additionalProperties\": false\n },\n \"command\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"minItems\": 1\n },\n \"success-exit-codes\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\"\n }\n },\n \"timeout-ms\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"generated-assertion-hash\": {\n \"type\": \"string\"\n },\n \"options\": {\n \"type\": \"object\"\n },\n \"severity\": {\n \"enum\": [\n \"notice\",\n \"warning\",\n \"error\"\n ]\n },\n \"weight\": {\n \"type\": \"number\",\n \"exclusiveMinimum\": 0,\n \"default\": 1,\n \"description\": \"Relative contribution to its suite's pass rate. Does not change this eval's own pass/fail: the eval still passes or fails on its own terms, and weight only decides how much that outcome moves the suite total against target-pass-rate. Zero is excluded deliberately - a weightless eval is a silent disable, and skip already means that, loudly.\"\n }\n },\n \"additionalProperties\": false,\n \"dependentRequired\": {\n \"generated-assertion-hash\": [\n \"command\"\n ]\n },\n \"allOf\": [\n {\n \"if\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"ai\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n },\n \"then\": {\n \"required\": [\n \"assertion\"\n ]\n }\n },\n {\n \"if\": {\n \"not\": {\n \"required\": [\n \"grader\"\n ]\n }\n },\n \"then\": {\n \"required\": [\n \"assertion\"\n ]\n }\n },\n {\n \"if\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"command\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n },\n \"then\": {\n \"anyOf\": [\n {\n \"required\": [\n \"assertion\"\n ]\n },\n {\n \"required\": [\n \"command\"\n ]\n }\n ]\n }\n },\n {\n \"if\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"human\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n },\n \"then\": {\n \"required\": [\n \"assertion\"\n ]\n }\n },\n {\n \"if\": {\n \"required\": [\n \"command\"\n ]\n },\n \"then\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"command\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n }\n },\n {\n \"if\": {\n \"anyOf\": [\n {\n \"required\": [\n \"success-exit-codes\"\n ]\n },\n {\n \"required\": [\n \"timeout-ms\"\n ]\n }\n ]\n },\n \"then\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"command\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n }\n }\n ]\n },\n \"anchorList\": {\n \"if\": {\n \"type\": \"array\"\n },\n \"then\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"else\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"suiteDef\": {\n \"type\": \"object\",\n \"properties\": {\n \"target-pass-rate\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"evals\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"criteria\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"description\": \"Criteria scored in this suite, alongside `evals`.\"\n }\n },\n \"additionalProperties\": false\n },\n \"criterionDef\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"evals\"\n ],\n \"properties\": {\n \"evals\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"description\": \"Ids of the evals this criterion is made of.\"\n },\n \"combine\": {\n \"enum\": [\n \"all\",\n \"any\"\n ],\n \"default\": \"all\",\n \"description\": \"all: every member must pass. any: one passing member is enough.\"\n },\n \"weight\": {\n \"type\": \"number\",\n \"exclusiveMinimum\": 0,\n \"default\": 1,\n \"description\": \"The criterion's contribution to its suite's pass rate.\"\n }\n }\n }\n }\n}\n","/**\n * Splitting long content for inference, instead of truncating it.\n *\n * Three code paths used to `slice(0, 6000)` and append \"…(truncated)\": `fill`,\n * `scriptgen`, and nothing at all in the judge, which sent whole pages. A page\n * over the cap was therefore filled and script-generated from its first half,\n * silently — the model never saw the rest and had no way to say so.\n *\n * Ported from the metadata tool's `fill`, which solved this first (`splitBody` /\n * `mergeProposals`). The contract, in full:\n *\n * - chunks are greedy and cut at the last newline before the boundary, so a\n * line is never split mid-sentence;\n * - there is no overlap — a merge step, not redundancy, is what stops a\n * boundary from losing something;\n * - content that fits comes back as a single chunk, so the common path is\n * byte-identical to not splitting at all;\n * - a model complaining about context length halves the budget and retries\n * once, because the right chunk size depends on the model, not on us.\n *\n * The chunk budget belongs in every cache key that covers chunked output.\n * The metadata tool documents why at its own call site: halve-and-retry makes two runs\n * at different budgets produce genuinely different results, and without the\n * budget in the key the second silently replays the first.\n */\n\n/** Characters of content per inference call. Matches the metadata tool's default. */\nexport const DEFAULT_CHUNK_CHARS = 12000;\n\n/**\n * Split `body` into chunks of at most `chunkChars`, cutting at line\n * boundaries. Returns `[body]` unchanged when it already fits.\n */\nexport function splitBody(body: string, chunkChars: number): string[] {\n if (body.length <= chunkChars) return [body];\n const chunks: string[] = [];\n let at = 0;\n while (at < body.length) {\n const end = Math.min(at + chunkChars, body.length);\n let cut = end;\n if (end < body.length) {\n const nl = body.lastIndexOf(\"\\n\", end - 1);\n if (nl > at) cut = nl + 1;\n }\n chunks.push(body.slice(at, cut));\n at = cut;\n }\n return chunks;\n}\n\n/**\n * Whether a provider error reads as \"that was too much context\".\n *\n * Deliberately a message match: providers do not agree on a code for this, and\n * the cost of a false positive is one retry at half the budget.\n */\nexport function looksLikeOverflow(message: string): boolean {\n return /context|too long|too large|token limit|maximum.*tokens|exceeds/i.test(\n message,\n );\n}\n\n/** How a part is announced to the model, when there is more than one. */\nexport function partLabel(index: number, total: number): string {\n return `part ${String(index + 1)} of ${String(total)}`;\n}\n","/**\n * Page discovery: resolve the run's document set (positional paths, or the\n * family `collections:`), read each file, and extract frontmatter using\n * the metadata tool's shared extractor (identical fence handling and JSON-Pointer ->\n * line maps as `manni meta validate`).\n */\nimport { readFileSync, statSync } from \"node:fs\";\nimport { resolve, relative, extname } from \"node:path\";\nimport fg from \"fast-glob\";\nimport { extractFrontmatter, type ExtractedMetadata } from \"../../meta/index.js\";\nimport { selectCollections } from \"../../shared/collections.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { DocevalsError } from \"../types.js\";\nimport type { PageExternal } from \"./external.js\";\nimport {\n assertCollectionWithoutPaths,\n DEFAULT_CONFIG_FILENAME,\n type DocevalsConfig,\n type RunConfigOptions,\n} from \"./config.js\";\n\nexport interface PageFile {\n /** Path relative to the discovery root, forward slashes. */\n file: string;\n absPath: string;\n /** Full file content. */\n content: string;\n /** Content with the leading frontmatter block removed (judge input). */\n body: string;\n /**\n * The page's metadata, with every key an owning manifest supplies already\n * merged in (`core/external.ts`). Identical to the frontmatter block when no\n * collection of this page's declares a manifest, which is the common case.\n */\n frontmatter: ExtractedMetadata;\n /**\n * Where a merged value lives, when a manifest supplied it. Absent when the\n * run read no manifest, and its `locate` answers `undefined` for every key\n * the page itself carries.\n */\n external?: PageExternal;\n /** Set when frontmatter extraction failed; the page is reported as errored. */\n extractError?: string;\n}\n\nexport type FrontmatterFormat = \"yaml\" | \"toml\" | \"json\";\n\nconst FENCES: {\n format: FrontmatterFormat;\n open: RegExp;\n isClose: (l: string) => boolean;\n}[] = [\n { format: \"yaml\", open: /^---\\r?\\n/, isClose: (l) => l === \"---\" || l === \"...\" },\n { format: \"toml\", open: /^\\+\\+\\+\\r?\\n/, isClose: (l) => l === \"+++\" },\n { format: \"json\", open: /^;;;\\r?\\n/, isClose: (l) => l === \";;;\" },\n];\n\n/** The frontmatter format a page opens with, or undefined if it has none. */\nexport function leadingFrontmatterFormat(\n content: string,\n): FrontmatterFormat | undefined {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n return FENCES.find((f) => f.open.test(body))?.format;\n}\n\n/**\n * Remove a leading fenced frontmatter block, mirroring the metadata tool's fence rules.\n *\n * The body is sliced out of the page rather than rebuilt from its lines, so it\n * keeps the page's own line endings. `target: raw` reads the file as written,\n * and `target: body` has to read the same bytes past the fence; a CRLF page\n * whose body came back LF would show a regex eval two different pages.\n */\nexport function stripFrontmatterBlock(content: string): string {\n const body =\n content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n const fence = FENCES.find((f) => f.open.test(body));\n if (!fence) return body;\n // Split after each newline, so every line keeps its own ending. The fence\n // test above guarantees an opening line.\n const [openLine = \"\", ...rest] = body.split(/(?<=\\n)/);\n let offset = openLine.length;\n for (const line of rest) {\n offset += line.length;\n if (fence.isClose(line.replace(/\\r?\\n$/, \"\"))) return body.slice(offset);\n }\n return body;\n}\n\nfunction formatForExtension(ext: string): string {\n switch (ext.toLowerCase()) {\n case \".md\":\n case \".markdown\":\n return \"markdown\";\n case \".mdx\":\n return \"mdx\";\n default:\n return \"markdown\";\n }\n}\n\n/** Read and extract a single page. Extraction errors are captured, not thrown. */\nexport function readPage(absPath: string, root: string): PageFile {\n const content = readFileSync(absPath, \"utf8\");\n const file = relative(root, absPath).replace(/\\\\/g, \"/\");\n const format = formatForExtension(extname(absPath));\n try {\n const frontmatter = extractFrontmatter(content, format);\n return {\n file,\n absPath,\n content,\n body: stripFrontmatterBlock(content),\n frontmatter,\n };\n } catch (e) {\n return {\n file,\n absPath,\n content,\n body: stripFrontmatterBlock(content),\n frontmatter: {\n data: {},\n present: false,\n format,\n lineFor: () => undefined,\n },\n extractError: errorMessage(e),\n };\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 and cite's source index ignore; it replaced\n * docevals' own `files.exclude` default (proposal 0041).\n */\nconst FAMILY_EXCLUDE = [\"**/node_modules/**\", \"**/.git/**\"];\n\n/** The word the empty-input message uses for what the command would do. */\nexport type DocumentVerb = \"evaluate\" | \"list\" | \"fill\" | \"read\";\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 /** Defaults to `evaluate`. */\n verb?: DocumentVerb;\n}\n\n/**\n * The document-set options every command that reads pages takes beside its\n * positional paths: `-c`, `--no-config`, `--collection` and `--exclude`.\n */\nexport interface DocumentInputOptions\n extends Pick<DocumentSetOptions, \"collection\" | \"exclude\"> {\n /** `-c/--config`. */\n config?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n}\n\n/** A command's inputs as `loadRunConfig` reads them. */\nexport function runConfigOptions(\n paths: string[],\n options: DocumentInputOptions,\n): RunConfigOptions {\n return {\n paths,\n ...(options.config === undefined ? {} : { configPath: options.config }),\n ...(options.noConfig === undefined ? {} : { noConfig: options.noConfig }),\n ...(options.collection === undefined ? {} : { collection: options.collection }),\n };\n}\n\n/** A command's inputs as `discoverPages` reads them. */\nexport function documentSet(\n paths: string[],\n options: DocumentInputOptions,\n verb: DocumentVerb,\n): DocumentSetOptions {\n return {\n paths,\n verb,\n ...(options.collection === undefined ? {} : { collection: options.collection }),\n ...(options.exclude === undefined ? {} : { exclude: options.exclude }),\n };\n}\n\n/**\n * One input as fast-glob patterns: a glob as written, an existing file as its\n * escaped literal, and an existing directory as everything beneath it. Only\n * the glob is left for fast-glob to interpret, so a literal path with `(` or\n * `[` in its name still means itself.\n */\nfunction toPatterns(input: string, base: string): string[] {\n if (fg.isDynamicPattern(input)) return [input.replace(/\\\\/g, \"/\")];\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 empty-match\n // error below names it.\n return [input.replace(/\\\\/g, \"/\")];\n }\n const literal = fg.convertPathToPattern(input);\n return [isDirectory ? `${literal.replace(/\\/$/, \"\")}/**/*` : literal];\n}\n\n/** Every supported page `patterns` match beneath `base`, as absolute paths. */\nfunction glob(patterns: string[], base: string, ignore: string[]): string[] {\n return fg.sync(patterns.flatMap((p) => toPatterns(p, base)), {\n cwd: base,\n ignore,\n absolute: true,\n dot: false,\n onlyFiles: true,\n });\n}\n\nconst SUPPORTED_EXTENSIONS = new Set([\".md\", \".markdown\", \".mdx\"]);\n\n/**\n * Discover pages (proposal 0041). Positional `paths` are what the operator\n * typed, resolved from `root` (the working directory). Without them the run\n * reads the selected collections, each collection's `paths:` resolved from the\n * config file's directory and narrowed by its own `exclude:`. The family-wide\n * exclusions and `--exclude` apply to both. Page labels stay relative to\n * `root` either way.\n */\nexport function discoverPages(\n config: DocevalsConfig,\n options: DocumentSetOptions = {},\n root = process.cwd(),\n): PageFile[] {\n const paths = options.paths ?? [];\n const wanted = options.collection ?? [];\n assertCollectionWithoutPaths(wanted, paths);\n if (wanted.length > 0 && config.configSource === null) {\n throw new DocevalsError(\"--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 DocevalsError(message),\n );\n\n const exclude = [...FAMILY_EXCLUDE, ...(options.exclude ?? [])];\n let entries: string[];\n let patterns: string[];\n if (paths.length > 0) {\n patterns = paths;\n entries = glob(paths, root, exclude);\n } else {\n // A collection's `exclude:` shapes that collection only, so each is walked\n // with its own and the results are joined: a file excluded from one\n // collection is still read when another collection holds it.\n patterns = collections.flatMap((c) => c.paths);\n if (patterns.length === 0) {\n throw new DocevalsError(\n `No files to ${options.verb ?? \"evaluate\"}. Pass paths/globs, or declare a collection under \\`collections:\\` in manni.config.yaml.`,\n );\n }\n entries = collections.flatMap((c) =>\n glob(c.paths, config.configDir, [...exclude, ...c.exclude]),\n );\n }\n\n const files = [\n ...new Set(entries.filter((p) => SUPPORTED_EXTENSIONS.has(extname(p).toLowerCase()))),\n ];\n if (files.length === 0) {\n throw new DocevalsError(\n `No documentation pages found (patterns: ${patterns.join(\", \")})`,\n );\n }\n return files.sort().map((p) => readPage(resolve(p), root));\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 * (proposal 0041).\n *\n * The evals vocabulary marks `evals`, `eval-suite` and `eval-skip`\n * `x-manni-location: external` in `manni:evals:1.0.0`, and ai-context marks\n * `provenance` and `meta-provenance`. A corpus that took `manni meta\n * relocate` up on that keeps those values in a manifest, and a tool that read\n * frontmatter alone would report every page as declaring nothing.\n *\n * Reading is meta's merge, not a second loader, exactly as `cite`'s sidecars\n * are. `loadExternalMetadata` reads each manifest once per run, behind the\n * shared per-process parse cache, and `mergeExternalMetadata` decides per page\n * what a manifest supplies. So the join rules, the ownership rules and the\n * per-item lines are the ones `meta validate` already applies, and the merged\n * result is handed back as the page's own `frontmatter`: every reader\n * downstream — resolution, the self-preference check, `target: frontmatter` —\n * sees the values where their location puts them, without knowing a manifest\n * exists.\n *\n * Two things are docevals' own, because docevals *writes* eval keys where\n * meta only reads them:\n *\n * - **Membership is decided by every declared collection**, not by the ones\n * `--collection` or the positional paths selected. A page named by path is\n * still a member of the collection that contains it, and its evals are\n * still in that collection's manifest.\n * - **A URL manifest may not own an eval key** (exit 2), and neither may two\n * of one page's collections. Both are refusals rather than tiebreaks, for\n * the reason 0020 gives: there is no right answer to pick.\n *\n * `--no-config` never reaches here: with no config there are no collections,\n * so a page's evals are its frontmatter's.\n */\nimport { resolve } from \"node:path\";\nimport { ownsKey } from \"../../shared/collections.js\";\nimport { familyMarks, mergeWithMarks, type PageMarks } from \"../../meta/internal.js\";\nimport {\n classifyRef,\n loadExternalMetadata,\n memberOf,\n type CollectionConfig,\n type ExternalMetadataCollision,\n type ExternalMetadataConfig,\n type ExternalMetadataIndex,\n type SourceLocation,\n} from \"../../meta/index.js\";\nimport { DocevalsError } from \"../types.js\";\nimport type { DocevalsConfig } from \"./config.js\";\nimport type { PageFile } from \"./discover.js\";\n\n/**\n * The three page keys the evals vocabulary claims, and the only ones these\n * refusals govern. A manifest owning `provenance` is nobody's problem here:\n * docevals reads it and never writes it.\n */\nexport const EVAL_KEYS = [\"evals\", \"eval-suite\", \"eval-skip\"] as const;\n\n/**\n * Every key docevals reads that a manifest may own, and so the only manifests\n * this tool loads: the evals vocabulary's three and ai-context's machine\n * attribution (proposal 0046).\n *\n * A manifest owning none of them is a sibling tool's business. Loading it\n * anyway would make a corpus fail on a manifest docevals has no use for, and\n * would fetch a URL manifest on every run to read nothing out of it. `cite`\n * scopes its own load the same way, to its one key.\n */\nexport const EXTERNAL_KEYS: readonly string[] = [\n ...EVAL_KEYS,\n \"provenance\",\n \"meta-provenance\",\n];\n\n/** Where a value a manifest supplied lives, and what the page duplicates. */\nexport interface PageExternal {\n /**\n * The manifest file and line behind a merged JSON Pointer, or `undefined`\n * for everything the page itself carries — which is what `lineFor` answers.\n */\n locate: (pointer: string) => SourceLocation | undefined;\n /** Eval keys the page carries that an owning manifest also holds. */\n collisions: readonly ExternalMetadataCollision[];\n /**\n * Every manifest file that supplied one of the page's eval keys, as an\n * absolute path. A change to any of them changes what the page is graded\n * on, so `--since` selects the page when one changed. A URL manifest never\n * appears: it may not own an eval key.\n */\n evalManifests: readonly string[];\n}\n\n/** `manni.config.yaml: collection site: evals cannot come from a URL manifest, because docevals writes them.` */\nexport function urlManifestRefusal(\n source: string,\n collection: string,\n key: string,\n): string {\n return `${source}: collection ${collection}: ${key} cannot come from a URL manifest, because docevals writes them.`;\n}\n\n/** `docs/install.md is in collections site and guides, and both keep evals in a manifest.` */\nexport function twoManifestsRefusal(\n label: string,\n a: string,\n b: string,\n key: string,\n): string {\n return `${label} is in collections ${a} and ${b}, and both keep ${key} in a manifest.`;\n}\n\n/**\n * What the vocabularies docevals reads mark `x-manni-location: external`:\n * every key in `EXTERNAL_KEYS`. A manifest with no `keys` (proposal 0068)\n * may own these, less the ones a sibling manifest of its collection names,\n * which is what decides the manifests a run loads and the refusals. The merge\n * itself reads each page's own marks, as meta's does.\n */\nconst MARKED: ReadonlySet<string> = new Set(EXTERNAL_KEYS);\n\n/** Whether one manifest declaration of `collection` owns `key`. */\nfunction owns(\n collection: Pick<CollectionConfig, \"externalMetadata\">,\n manifest: ExternalMetadataConfig,\n key: string,\n): boolean {\n return ownsKey(collection, manifest, key, MARKED);\n}\n\n/** The eval keys one manifest declaration owns, in vocabulary order. */\nfunction evalKeysOf(\n collection: Pick<CollectionConfig, \"externalMetadata\">,\n manifest: ExternalMetadataConfig,\n): string[] {\n return EVAL_KEYS.filter((k) => owns(collection, manifest, k));\n}\n\n/** The pages of a run, with every manifest-supplied key merged into each. */\nexport interface ExternalMetadataReader {\n /** The page as its metadata reads once the manifests are applied. */\n forPage(page: PageFile): Promise<PageFile>;\n}\n\n/**\n * Load every manifest of every declared collection, or `null` when the run has\n * no config, no collections, or none of them declares a manifest — which is\n * every corpus that keeps its metadata in its pages, and costs nothing.\n *\n * The URL refusal is decided from the config alone, before a byte is fetched.\n *\n * `pages` are the run's documents as absolute paths. A collection that keeps\n * its evals in one manifest per page (proposal 0058) has one file to read per\n * page, and meta reads those only for the pages it is given.\n */\nexport async function loadExternalReader(\n config: DocevalsConfig,\n base: string,\n pages?: readonly string[],\n): Promise<ExternalMetadataReader | null> {\n const collections: CollectionConfig[] = [];\n const source = config.configSource ?? config.configPath;\n for (const collection of config.collections) {\n const owning = collection.externalMetadata.filter((m) =>\n EXTERNAL_KEYS.some((k) => owns(collection, m, k)),\n );\n if (owning.length === 0) continue;\n for (const manifest of owning) {\n if (classifyRef(manifest.file).kind !== \"url\") continue;\n const [owned] = evalKeysOf(collection, manifest);\n if (owned !== undefined) {\n throw new DocevalsError(\n urlManifestRefusal(source, collection.name, owned),\n );\n }\n }\n collections.push({ ...collection, externalMetadata: owning });\n }\n if (collections.length === 0) return null;\n\n const index = await loadExternalMetadata(collections, {\n configDir: config.configDir,\n base,\n // A `{page}` entry names one manifest per page (proposal 0058), so it\n // reads a file only for the pages it is handed. Without them it reads\n // nothing, and every value the corpus keeps beside its pages goes missing\n // while the ownership that hides the page's own copy stays.\n ...(pages === undefined ? {} : { pages }),\n });\n if (index === null) return null;\n return reader(index, collections, config.configDir, base, marksFor(config, base));\n}\n\n/**\n * What a page's schemas mark external, for a keyless manifest (proposal\n * 0068): read from meta's section of the same file, the way `cite` reads\n * them, or over meta's default set when that file has none for meta. The\n * default set carries the evals vocabulary, so the eval keys are marked\n * either way. Built once, on the first page that has a keyless manifest.\n */\nfunction marksFor(config: DocevalsConfig, base: string): () => Promise<PageMarks> {\n // A family file whose other sections meta cannot read as its own is still\n // docevals' file; the default set decides the marks then.\n return familyMarks({ configPath: config.configPath, configDir: config.configDir, cwd: base });\n}\n\n/**\n * Which collections of `members` keep `key` in a manifest. Ownership, not\n * supply: a writer has to know which file to write to before either manifest\n * has an entry, so two owners is a refusal even while both are empty.\n */\nfunction ownersOf(\n collections: readonly CollectionConfig[],\n members: readonly string[],\n key: string,\n): string[] {\n return collections\n .filter(\n (c) =>\n members.includes(c.name) &&\n c.externalMetadata.some((m) => owns(c, m, key)),\n )\n .map((c) => c.name);\n}\n\nfunction reader(\n index: ExternalMetadataIndex,\n collections: readonly CollectionConfig[],\n configDir: string,\n base: string,\n marks: () => Promise<PageMarks>,\n): ExternalMetadataReader {\n return {\n async forPage(page: PageFile): Promise<PageFile> {\n if (page.extractError !== undefined) return page;\n const members = memberOf(collections, configDir, base, page.file);\n if (members.length === 0) return page;\n\n for (const key of EVAL_KEYS) {\n const [a, b] = ownersOf(collections, members, key);\n if (a !== undefined && b !== undefined) {\n throw new DocevalsError(twoManifestsRefusal(page.file, a, b, key));\n }\n }\n\n const merged = await mergeWithMarks(\n page.file,\n page.frontmatter,\n index,\n members,\n base,\n { marks: await marks() },\n );\n return {\n ...page,\n frontmatter: merged.extracted,\n external: {\n locate: merged.locate,\n // Only the keys this tool reads and writes. A manifest owning a\n // sibling tool's key that the page also carries is `meta validate`'s\n // finding, and saying it twice would make the same fix look like two.\n collisions: merged.collisions.filter((c) =>\n (EVAL_KEYS as readonly string[]).includes(c.key),\n ),\n evalManifests: suppliers(merged.locate, base),\n },\n };\n },\n };\n}\n\n/**\n * The manifests that supplied the page's eval keys, absolute and deduplicated.\n * `locate` answers only for a key a manifest supplied, so a key the page\n * carries itself names no manifest. A manifest's reported path is relative to\n * `base`, the run's discovery root.\n */\nfunction suppliers(\n locate: PageExternal[\"locate\"],\n base: string,\n): string[] {\n const files = new Set<string>();\n for (const key of EVAL_KEYS) {\n const at = locate(`/${key}`);\n // `at.file` is a path relative to `base`, never a URL: the reader refuses\n // a URL manifest that owns an eval key before any page is read.\n if (at !== undefined) files.add(resolve(base, at.file));\n }\n return [...files];\n}\n\n/**\n * Every page of a run, read the way `meta validate` reads it. The manifests\n * are loaded once, whatever the corpus size, and a run with no manifest gets\n * its pages back untouched.\n *\n * `base` is the run's discovery root, so `page.file` and a manifest's reported\n * path are spelled against the same directory.\n */\nexport async function withExternalMetadata(\n pages: PageFile[],\n config: DocevalsConfig,\n base: string,\n): Promise<PageFile[]> {\n const merge = await loadExternalReader(\n config,\n base,\n pages.map((p) => p.absPath),\n );\n if (merge === null) return pages;\n return Promise.all(pages.map((p) => merge.forPage(p)));\n}\n","/**\n * Resolution: merge a page's eval frontmatter with the central config into a\n * concrete per-page plan. Suites contribute named evals; page entries reference\n * them (with overrides) or define inline evals. Page entries win on id\n * collision.\n *\n * The page vocabulary is `manni:evals:1.0.0` — three flat\n * page-level keys (`evals`, `eval-suite`, `eval-skip`) and a reserved `eval-`\n * prefix, rather than the closed `evals:` object 0.1 used. The\n * whole frontmatter object is validated, not a synthetic `{evals}`: the prefix\n * reservation is a claim about the page root, and it cannot be enforced from a\n * fragment.\n *\n * `page.frontmatter` is the page's metadata *after* `core/external.ts` merged\n * in whatever an owning manifest supplies, so a page whose `evals` live in a\n * manifest resolves the plan it declares rather than none. What the page\n * itself carries and what a manifest supplied are told apart only when a\n * problem or an eval's location has to name a place: `locationOf` and\n * `declaredLocation` below, both through meta's `declaredAt`.\n */\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport type { ErrorObject } from \"ajv\";\nimport { frontmatterSchema } from \"../schema.js\";\nimport type { EvalType, GraderKind, Severity } from \"../types.js\";\nimport {\n normalizeEvalDef,\n type DocevalsConfig,\n type EvalDef,\n type RawEvalDef,\n} from \"./config.js\";\nimport type { PageFile } from \"./discover.js\";\nimport type { EvalTarget } from \"./target.js\";\nimport { warn } from \"../../shared/warn.js\";\nimport { declaredAt } from \"../../meta/internal.js\";\nimport { isRegisteredGrader } from \"../graders/registry.js\";\n\nexport interface ResolvedEval {\n /** Kebab-case id, unique per page. */\n name: string;\n /** Suite this eval reports under (\"default\" when none applies). */\n suite: string;\n assertion?: string;\n type: EvalType;\n grader: GraderKind;\n /** Per-eval provider/agent override for `ai` evals. */\n provider?: string;\n evidence?: string;\n examples?: { pass?: string[]; fail?: string[] };\n command?: string[];\n successExitCodes: number[];\n timeoutMs?: number;\n generatedAssertionHash?: string;\n options: Record<string, unknown>;\n severity: Severity;\n /**\n * Relative contribution to its suite's pass rate. Defaults to 1, which is\n * what makes weighting inert until someone asks for it: a suite of\n * unweighted evals computes exactly the rate it always did.\n */\n weight: number;\n /** Which bytes the grader receives. Absent means the page body. */\n target?: EvalTarget;\n /** Judge model for this eval; a CLI --model still wins. */\n model?: string;\n /** Ensemble runs for this eval; a CLI --runs still wins. */\n runs?: number;\n /** Where the eval definition came from. */\n source: \"config\" | \"page\";\n skip: boolean;\n /**\n * Where the page declares the eval: the item of its `evals` key that names\n * it, in the page or in the manifest that supplied the key. A suite eval\n * the page never names is attached by its `eval-suite` key, so it points\n * there, or at the page alone when the suite is the config's default. The\n * file is spelled like the page's, and `line` is absent when nothing\n * records one.\n */\n location: EvalLocation;\n}\n\n/** A file, and the 1-based line in it when one is known. */\nexport interface EvalLocation {\n file: string;\n line?: number;\n}\n\nexport interface PageProblem {\n message: string;\n level: \"error\" | \"warning\";\n line?: number;\n /**\n * The manifest that supplied the value this problem is about, when one did\n * (`external-metadata`, proposal 0037). Absent for everything the page\n * carries, which the run then reports against the page as it always has.\n */\n file?: string;\n}\n\nexport interface ResolvedPagePlan {\n page: PageFile;\n /** Page-level skip (`eval-skip: true`). */\n skip: boolean;\n suite: string | null;\n evals: ResolvedEval[];\n problems: PageProblem[];\n}\n\n// `strict: false`, as `src/cite/core/page.ts` compiles its own schema: the\n// vocabulary annotates its three keys with `x-manni-location: external`, and\n// Ajv's strict mode throws on a keyword it does not know rather than ignoring\n// the annotation.\nconst ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true, strict: false });\n// The vocabulary as shipped: its severity is the family scale, so nothing is\n// patched in memory.\nconst validateFrontmatter = ajv.compile(frontmatterSchema);\n\ninterface FrontmatterEvalRef {\n use: string;\n type?: EvalType;\n skip?: boolean;\n severity?: Severity;\n /**\n * How much this check counts *for this page*. The reference form is how\n * most pages join a suite at all, so a weight the schema accepts and the\n * merge drops would score the page at the corpus default without saying so.\n */\n weight?: number;\n options?: Record<string, unknown>;\n}\n\ntype FrontmatterEvalEntry =\n | string\n | FrontmatterEvalRef\n | (RawEvalDef & { id: string; skip?: boolean });\n\n/** The three page keys this vocabulary claims. */\ninterface EvalFrontmatter {\n evals?: string | FrontmatterEvalEntry[];\n \"eval-suite\"?: string;\n \"eval-skip\"?: boolean;\n}\n\n/**\n * `evals` is one assertion string or a list of entries. Normalize to the list;\n * a bare string is an ai-judged assertion at error severity, and it has no id\n * of its own — the string shorthand is the legitimately id-less form.\n */\nfunction evalEntries(raw: EvalFrontmatter[\"evals\"]): FrontmatterEvalEntry[] {\n if (raw === undefined) return [];\n return typeof raw === \"string\" ? [raw] : raw;\n}\n\nfunction fromDef(\n name: string,\n suite: string,\n def: EvalDef,\n source: \"config\" | \"page\",\n location: EvalLocation,\n): ResolvedEval {\n return {\n location,\n name,\n suite,\n assertion: def.assertion,\n type: def.type ?? \"regression\",\n grader: (def.grader ?? \"ai\") as GraderKind,\n provider: def.provider,\n evidence: def.evidence,\n examples: def.examples,\n command: def.command,\n successExitCodes: def.successExitCodes ?? [0],\n timeoutMs: def.timeoutMs,\n generatedAssertionHash: def.generatedAssertionHash,\n options: def.options ?? {},\n severity: def.severity ?? \"error\",\n weight: def.weight ?? 1,\n target: def.target,\n model: def.model,\n runs: def.runs,\n source,\n skip: false,\n };\n}\n\n/**\n * A name for a string-shorthand eval, derived from its position.\n *\n * Position-derived names orphan cached verdicts when entries move, which is\n * why object entries must carry an explicit `id`. The shorthand has no id by\n * design, so it accepts that cost in exchange for being one line.\n *\n * `taken` is every name already claimed on this page. Without it a derived\n * name can collide with an explicit `id` of the same spelling, and the Map\n * write silently drops one of two evals the author declared — a page checking\n * less than it says while the run stays green.\n */\nfunction shorthandName(index: number, taken: ReadonlySet<string>): string {\n const base = `assertion-${index + 1}`;\n if (!taken.has(base)) return base;\n for (let n = 2; ; n++) {\n const candidate = `${base}-${n}`;\n if (!taken.has(candidate)) return candidate;\n }\n}\n\n/** The page-level keys this vocabulary claims, for the reservation message. */\nconst RESERVED_KEYS = [\"eval-suite\", \"eval-skip\"] as const;\n\n/**\n * A schema error, in words.\n *\n * The `eval-` prefix reservation is expressed as a `patternProperties` entry\n * whose subschema is `false`, and Ajv reports that as \"boolean schema is\n * false\" — which names neither the key nor the fix. The reservation exists\n * precisely to make a typo loud, so it gets a sentence rather than Ajv's\n * internals.\n */\nfunction describeError(e: ErrorObject): string {\n if (e.keyword === \"false schema\" && e.instancePath.startsWith(\"/eval-\")) {\n const key = e.instancePath.slice(1);\n return (\n `unknown key \"${key}\". The \"eval-\" prefix is reserved, and the only ` +\n `settings under it are ${RESERVED_KEYS.join(\", \")} — so a typo is an ` +\n `error here rather than a key nothing reads.`\n );\n }\n return e.message ?? \"is invalid\";\n}\n\n/**\n * Where a problem about `pointer` should point: the manifest that supplied the\n * value, or the page's own line for it.\n *\n * A manifest line without a file would read as a line of the page, which is\n * the one place the value is not. So the two travel together or not at all.\n */\nfunction locationOf(\n page: PageFile,\n pointer: string,\n): Pick<PageProblem, \"file\" | \"line\"> {\n const at = declaredAt(page.file, pointer, metadataOf(page));\n // A manifest's spelling is never the page's, and a problem about the page\n // always has a line: the block's first when nothing nearer is recorded.\n return at.file === page.file ? { line: at.line ?? 1 } : at;\n}\n\n/** The page's merged metadata, as `declaredAt` reads it. */\nfunction metadataOf(page: PageFile): Parameters<typeof declaredAt>[2] {\n return {\n extracted: page.frontmatter,\n ...(page.external === undefined ? {} : { locate: page.external.locate }),\n };\n}\n\n/**\n * Where the page declares a key it carries, in the page or its manifest. A\n * key the page does not carry has no line: `lineFor` would answer the block's\n * first line for it, which is not where anything is declared.\n */\nfunction declaredLocation(page: PageFile, pointer: string, key: string): EvalLocation {\n if (!(key in page.frontmatter.data)) return { file: page.file };\n return declaredAt(page.file, pointer, metadataOf(page));\n}\n\n/** Resolve one page's plan. Never throws; problems are collected per page. */\nexport function resolvePage(\n page: PageFile,\n config: DocevalsConfig,\n): ResolvedPagePlan {\n const problems: PageProblem[] = [];\n const empty = {\n page,\n skip: false,\n suite: null,\n evals: [],\n problems,\n };\n if (page.extractError) {\n problems.push({ message: page.extractError, level: \"error\", line: 1 });\n return empty;\n }\n\n // A key a manifest owns and the page carries anyway. Meta files this as\n // `external:owned` on the document; docevals says the same sentence, at\n // error level, because there are then two declarations of what to check and\n // grading either one would be a guess.\n for (const c of page.external?.collisions ?? []) {\n problems.push({\n message: `\"${c.key}\" is owned by manifest ${c.file} (collection ${c.collection}); remove it from the document`,\n level: \"error\",\n line: page.frontmatter.lineFor(`/${c.key}`) ?? 1,\n });\n }\n\n const data = page.frontmatter.data;\n // The whole object, not just the eval keys: `eval-` prefix reservation is a\n // statement about the page root. Sibling tools' keys stay legal — the schema\n // root is open — but a typo'd `eval-*` setting is caught here instead of\n // being silently ignored, which is what the closed 0.1 block used to buy.\n if (!validateFrontmatter(data)) {\n for (const e of validateFrontmatter.errors ?? []) {\n problems.push({\n message: `frontmatter${e.instancePath}: ${describeError(e)}`,\n level: \"error\",\n ...locationOf(page, e.instancePath),\n });\n }\n return empty;\n }\n\n const fm = data as EvalFrontmatter;\n const pageSkip = fm[\"eval-skip\"] ?? false;\n\n const declaredSuite = fm[\"eval-suite\"];\n const suiteName = declaredSuite ?? config.defaults.suite;\n if (declaredSuite && !(declaredSuite in config.suites)) {\n problems.push({\n message: `Unknown suite \"${declaredSuite}\" (not defined in ${config.configPath})`,\n level: \"error\",\n ...locationOf(page, \"/eval-suite\"),\n });\n return { ...empty, skip: pageSkip };\n }\n\n const resolved = new Map<string, ResolvedEval>();\n\n // 1. Suite evals from the central config. The page attaches them by naming\n // the suite, so that is where they are declared for this page.\n if (suiteName) {\n const suite = config.suites[suiteName];\n const attached = declaredLocation(page, \"/eval-suite\", \"eval-suite\");\n for (const name of suite?.evals ?? []) {\n const def = config.evals[name];\n if (def) resolved.set(name, fromDef(name, suiteName, def, \"config\", attached));\n }\n }\n\n // 2. Page entries: references (with overrides) and inline evals.\n const reportSuite = suiteName ?? \"default\";\n // Every name an author wrote, collected before any shorthand is numbered.\n // Order matters: a shorthand at index 0 must yield to an explicit\n // `assertion-1` further down the list, not overwrite it.\n const claimed = new Set<string>(resolved.keys());\n for (const entry of evalEntries(fm.evals)) {\n if (typeof entry === \"string\") continue;\n claimed.add(\"use\" in entry ? entry.use : entry.id);\n }\n for (const [i, entry] of evalEntries(fm.evals).entries()) {\n const linePtr = `/evals/${String(i)}`;\n // A string block is one entry at index 0, and the pointer walks up to the\n // block's own line.\n const entryAt = declaredLocation(page, linePtr, \"evals\");\n if (typeof entry === \"string\") {\n // String shorthand: an ai-judged assertion at error severity.\n //\n // In 0.1 a bare string was a *reference* to a config-defined eval, so a\n // page that still says `- no-todo-markers` silently stops running the\n // regex grader and sends the words \"no-todo-markers\" to the judge\n // instead. Nothing errors; the eval simply disappears. Guessing the\n // author's intent would make a second, invisible spelling of `use:`, so\n // name the shape of the mistake and let them fix the page.\n if (entry in config.evals) {\n problems.push({\n message:\n `String shorthand \"${entry}\" matches an eval defined in ${config.configPath}, ` +\n `but a string is an assertion now, not a reference. ` +\n `Write \"use: ${entry}\" to run that eval.`,\n level: \"warning\",\n ...locationOf(page, linePtr),\n });\n }\n const name = shorthandName(i, claimed);\n claimed.add(name);\n resolved.set(\n name,\n fromDef(name, reportSuite, { assertion: entry }, \"page\", entryAt),\n );\n continue;\n }\n if (\"use\" in entry) {\n const ref = entry;\n const def = config.evals[ref.use];\n if (!def) {\n problems.push({\n message: `Unknown eval \"${ref.use}\" (not defined in ${config.configPath})`,\n level: \"error\",\n ...locationOf(page, linePtr),\n });\n continue;\n }\n const base =\n resolved.get(ref.use) ?? fromDef(ref.use, reportSuite, def, \"config\", entryAt);\n resolved.set(ref.use, {\n ...base,\n location: entryAt,\n type: ref.type ?? base.type,\n severity: ref.severity ?? base.severity,\n weight: ref.weight ?? base.weight,\n options: { ...base.options, ...(ref.options ?? {}) },\n skip: ref.skip ?? base.skip,\n });\n continue;\n }\n\n const inline = entry;\n if (resolved.has(inline.id) && resolved.get(inline.id)?.source === \"page\") {\n // Overriding a *suite* eval by id is the documented precedence rule and\n // stays a silent, intended win. Two page-level entries sharing an id is\n // different: one of them is dropped, so the page checks less than it\n // declares — an error, not a warning that lets the run pass.\n problems.push({\n message: `Duplicate eval id \"${inline.id}\" on page — the later entry replaces the earlier one`,\n level: \"error\",\n ...locationOf(page, linePtr),\n });\n }\n const ev = fromDef(inline.id, reportSuite, normalizeEvalDef(inline), \"page\", entryAt);\n ev.skip = inline.skip ?? false;\n resolved.set(inline.id, ev);\n // The shared vocabulary still allows `severity-map`, so a page carrying\n // one is valid. It mapped a wrapped tool's own scale, and no registered\n // grader has one, so the key is read by nothing. Said once per eval:\n // `warn` deduplicates on the text, which names the page and the eval.\n // An eval naming an unregistered grader is a usage error a moment\n // later, so the warning would only bury it.\n if (\"severity-map\" in inline && isRegisteredGrader(ev.grader)) {\n warn(\n `${page.file}: eval \"${inline.id}\" sets severity-map, which no registered ` +\n `grader reads; it has no effect.`,\n );\n }\n if (ev.grader === \"ai\" && !inline.examples) {\n problems.push({\n message: `Eval \"${inline.id}\": ai-graded evals work best with examples.pass/examples.fail`,\n level: \"warning\",\n ...locationOf(page, linePtr),\n });\n }\n }\n\n return {\n page,\n skip: pageSkip,\n suite: suiteName,\n evals: [...resolved.values()],\n problems,\n };\n}\n\n/** Resolve all pages. */\nexport function resolvePages(\n pages: PageFile[],\n config: DocevalsConfig,\n): ResolvedPagePlan[] {\n return pages.map((p) => resolvePage(p, config));\n}\n","/**\n * The page vocabulary manni docevals implements: `manni:evals:1.0.0`, the\n * built-in schema the metadata tool publishes under `src/meta/schemas/`.\n * Pages are validated against that schema itself, imported and bundled into\n * the build, so docevals and `manni meta validate` read the same bytes.\n *\n * docevals ships no copy of the schema. A copy is a second artifact to keep in\n * step, and the copies it used to publish drifted from the draft they copied:\n * they kept `eval-provenance` and the `info` severity after proposal 0046\n * removed both. A consumer who wants to validate pages names\n * `manni:evals:1.0.0` to `manni meta validate`, or validates programmatically\n * against the object below.\n */\nimport schema from \"../meta/schemas/evals/1.0.0.json\" with { type: \"json\" };\n\n/** The evals vocabulary, for validators that accept an inline schema. */\nexport const frontmatterSchema = schema as Record<string, unknown>;\n\n/** The vocabulary's `$id`: `manni:evals:1.0.0`. */\nexport const FRONTMATTER_SCHEMA_ID: string = schema.$id;\n","/**\n * Command grader: runs a user-supplied (or manni docevals-generated) CLI command per\n * page. Exit code membership in `successExitCodes` (default [0]) decides\n * pass/fail; the output tail becomes the finding message.\n *\n * Working directory: page-sourced commands run from the page's directory (so\n * generated script paths like \"manni-docevals/page.eval.mjs\" resolve naturally);\n * config-sourced commands run from the config file's directory.\n */\nimport { dirname } from \"node:path\";\nimport type { Finding } from \"../types.js\";\nimport { outputTail } from \"../../shared/exec.js\";\nimport type { Grader, GraderContext, GraderTarget } from \"./types.js\";\n\nfunction substitute(cmd: string[], file: string): string[] {\n return cmd.map((part) => part.replaceAll(\"{file}\", file));\n}\n\nasync function gradeOne(\n ctx: GraderContext,\n target: GraderTarget,\n): Promise<Finding[]> {\n const { plan, eval: ev } = target;\n if (!ev.command) {\n return [\n {\n evalName: ev.name,\n file: plan.page.file,\n message:\n \"No command to run (script not yet generated — run `manni docevals generate` or `manni docevals run` with a provider configured)\",\n severity: ev.severity,\n diagnostic: true,\n },\n ];\n }\n const cwd =\n ev.source === \"page\" ? dirname(plan.page.absPath) : ctx.config.configDir;\n const result = await ctx.exec(substitute(ev.command, plan.page.absPath), {\n cwd,\n timeoutMs: ev.timeoutMs ?? ctx.config.scripts.timeoutMs,\n env: { MANNI_DOCEVALS_FILE: plan.page.absPath },\n });\n\n if (result.spawnError) {\n return [\n {\n evalName: ev.name,\n file: plan.page.file,\n message: `Failed to run command \"${ev.command[0] ?? \"(empty)\"}\": ${result.spawnError}`,\n severity: ev.severity,\n diagnostic: true,\n },\n ];\n }\n if (result.timedOut) {\n return [\n {\n evalName: ev.name,\n file: plan.page.file,\n message: `Command timed out after ${ev.timeoutMs ?? ctx.config.scripts.timeoutMs}ms`,\n severity: ev.severity,\n diagnostic: true,\n },\n ];\n }\n if (result.code != null && ev.successExitCodes.includes(result.code)) {\n return [];\n }\n const tail = outputTail(result);\n return [\n {\n evalName: ev.name,\n file: plan.page.file,\n // \"Exit code N\" is the message users and docs already know; only the\n // null case — killed by a signal, which is what a timeout produces —\n // needs different words, because \"Exit code null\" describes nothing.\n message:\n (result.code === null\n ? \"Killed before exiting\"\n : `Exit code ${result.code}`) + (tail ? `: ${tail}` : \"\"),\n severity: ev.severity,\n },\n ];\n}\n\nexport const commandGrader: Grader = {\n kind: \"command\",\n mode: \"per-file\",\n async grade(ctx) {\n const findings: Finding[] = [];\n for (const target of ctx.targets) {\n findings.push(...(await gradeOne(ctx, target)));\n }\n return findings;\n },\n};\n","/**\n * Grader option validation.\n *\n * `options` is deliberately open in the published vocabulary — proposal 0023\n * describes it as \"grader-specific options; validated by the grader at run\n * time\", because a grader's options evolve on the grader's schedule and a\n * closed schema would version on every one. The cost of that openness is that\n * nothing catches a typo: `max-age-day: 30` used to fall straight through to\n * the default of 365, and the eval quietly checked something its author never\n * wrote. This module is the \"validated by the grader\" half actually happening.\n *\n * Ported from moose-tracevals' `src/graders/util.ts`, which solved it first —\n * the same reason `src/docevals/core/baseline.ts` was ported from the metadata tool. Combinators\n * rather than a JSON Schema per grader: they give messages that name the key,\n * and they express the cross-field constraints (ordered bounds, a criterion\n * that can never pass) that JSON Schema states badly.\n */\n\n/** An option-validation outcome: a message when invalid, undefined when fine. */\nexport type OptionCheck = string | undefined;\n\nexport type Options = Record<string, unknown>;\n\n/** First failing check, so callers read as a flat list of constraints. */\nexport function firstError(...checks: OptionCheck[]): OptionCheck {\n return checks.find((check) => check !== undefined);\n}\n\n/**\n * Rejects any key the grader does not know.\n *\n * This is the check the whole module exists for: every other constraint here\n * assumes the author spelled the key right in the first place.\n */\nexport function knownKeys(options: Options, allowed: readonly string[]): OptionCheck {\n const unknown = Object.keys(options).filter((k) => !allowed.includes(k));\n if (unknown.length === 0) return undefined;\n const listed = [...allowed].sort().join(\", \");\n return `unknown option${unknown.length > 1 ? \"s\" : \"\"} ${unknown\n .map((k) => `\"${k}\"`)\n .join(\", \")} — this grader accepts: ${listed}`;\n}\n\nexport function requiredString(options: Options, key: string): OptionCheck {\n const value = options[key];\n if (typeof value !== \"string\" || value.length === 0) {\n return `options.${key} is required`;\n }\n return undefined;\n}\n\nexport function optionalString(options: Options, key: string): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n if (typeof value !== \"string\" || value.length === 0) {\n return `options.${key} must be a non-empty string`;\n }\n return undefined;\n}\n\nexport function optionalEnum(\n options: Options,\n key: string,\n allowed: readonly string[],\n): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n if (typeof value !== \"string\" || !allowed.includes(value)) {\n return `options.${key} must be one of: ${allowed.join(\", \")}`;\n }\n return undefined;\n}\n\nexport function optionalNumber(\n options: Options,\n key: string,\n bounds: { min?: number; max?: number; integer?: boolean } = {},\n): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n // Number.isFinite also rejects NaN and both infinities.\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return `options.${key} must be a finite number`;\n }\n if (bounds.integer === true && !Number.isInteger(value)) {\n return `options.${key} must be a whole number`;\n }\n if (bounds.min !== undefined && value < bounds.min) {\n return `options.${key} must be at least ${bounds.min}`;\n }\n if (bounds.max !== undefined && value > bounds.max) {\n return `options.${key} must be at most ${bounds.max}`;\n }\n return undefined;\n}\n\nexport function optionalBoolean(options: Options, key: string): OptionCheck {\n if (options[key] !== undefined && typeof options[key] !== \"boolean\") {\n return `options.${key} must be a boolean`;\n }\n return undefined;\n}\n\nexport function optionalStringArray(options: Options, key: string): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n if (\n !Array.isArray(value) ||\n value.some((v) => typeof v !== \"string\" || v.length === 0)\n ) {\n return `options.${key} must be a list of non-empty strings`;\n }\n return undefined;\n}\n","/**\n * `target` — which bytes a grader receives.\n *\n * Distinct from `evidence`, which only hints where to look *within* what is\n * graded. `evidence` is prose for the judge; `target` decides what the judge\n * (or a deterministic grader) is handed in the first place, which is why\n * deterministic graders honour it too and why it is named `target` rather than\n * `focus` — a regex grader has no focus.\n *\n * A target that cannot be served is an explicit failure, never a silent\n * substitution: grading the page body when the author asked for a companion\n * file would report a verdict about the wrong bytes, which is worse than no\n * verdict at all (ADR 01022).\n */\nimport { readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport type { ResolvedPagePlan } from \"./resolve.js\";\n\n/** The `body` | `raw` | `frontmatter` | companion-file selector. */\nexport type EvalTarget =\n | \"body\"\n | \"raw\"\n | \"frontmatter\"\n | { source: \"file\"; path: string };\n\nexport const DEFAULT_TARGET: EvalTarget = \"body\";\n\nexport type TargetResult =\n | { ok: true; text: string; label: string }\n | { ok: false; reason: string };\n\n/** Human-readable name for a target, for messages and report lines. */\nexport function describeTarget(target: EvalTarget | undefined): string {\n const t = target ?? DEFAULT_TARGET;\n return typeof t === \"string\" ? t : `file ${t.path}`;\n}\n\n/**\n * Read what `target` selects for `plan`.\n *\n * A companion path is resolved against the page's own directory and must stay\n * inside it. An absolute path or one that climbs out is refused by name rather\n * than read: a page is content, and content naming an arbitrary path on the\n * machine that runs the eval is the same class of hazard as a frontmatter\n * command.\n */\nexport function readTarget(\n target: EvalTarget | undefined,\n plan: ResolvedPagePlan,\n): TargetResult {\n const t = target ?? DEFAULT_TARGET;\n if (t === \"body\") return { ok: true, text: plan.page.body, label: \"body\" };\n if (t === \"raw\") return { ok: true, text: plan.page.content, label: \"raw\" };\n if (t === \"frontmatter\") {\n const data = plan.page.frontmatter.data as unknown;\n // An empty or absent frontmatter block yields \"{}\\n\" from the YAML\n // stringifier, which reads as \"there was nothing\" rather than as a bug.\n return {\n ok: true,\n text: stringifyYaml(data ?? {}),\n label: \"frontmatter\",\n };\n }\n\n const pageDir = dirname(plan.page.absPath);\n if (isAbsolute(t.path)) {\n return {\n ok: false,\n reason: `target file \"${t.path}\" is an absolute path; name it relative to the page`,\n };\n }\n const abs = resolve(pageDir, t.path);\n const rel = relative(pageDir, abs);\n // The segment has to *end* at the dots. `startsWith(\"..\")` alone rejects a\n // legitimate sibling whose name merely begins with them — `..notes.ts`,\n // `..rc` — which is a refusal the author cannot act on, since the file is\n // inside the root and named exactly what they wrote. `isAbsolute` covers the\n // Windows case where the target sits on another drive and `relative` cannot\n // express the step at all.\n if (rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {\n return {\n ok: false,\n reason: `target file \"${t.path}\" resolves outside the page's directory`,\n };\n }\n try {\n return { ok: true, text: readFileSync(abs, \"utf8\"), label: `file ${t.path}` };\n } catch (err) {\n // `useUnknownInCatchVariables` is on, so the cast has to be earned: a\n // thrown value that is not an Error has no `code` to read, and asserting\n // one would put `undefined` where the message promises a reason.\n const code =\n err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\n return {\n ok: false,\n reason: `target file \"${t.path}\" could not be read (${code ?? \"unknown error\"})`,\n };\n }\n}\n","/**\n * Native regex check over whatever `target` selects.\n *\n * The cheap rung the grader hierarchy was missing. An assertion like \"the page\n * names the current package\" is a verifiable fact, and putting it to an LLM\n * judge three times is both slower and less trustworthy than matching it —\n * \"use an ai grader only when a deterministic one cannot express it\" is only\n * advice you can follow if a deterministic one exists.\n *\n * `match` covers the three shapes worth having: `contains` (the default),\n * `not-contains`, and `count:N` for \"exactly N times\", which is what catches a\n * heading duplicated by a bad merge.\n */\nimport type { Finding } from \"../../types.js\";\nimport type { Grader } from \"./../types.js\";\nimport {\n firstError,\n knownKeys,\n optionalString,\n requiredString,\n type OptionCheck,\n type Options,\n} from \"../options.js\";\nimport { readTarget, type EvalTarget } from \"../../core/target.js\";\nimport type { PageFile } from \"../../core/discover.js\";\nimport { errorMessage } from \"../../../shared/errors.js\";\n\ninterface RegexOptions {\n pattern?: string;\n flags?: string;\n match?: string;\n}\n\nconst MATCH_RE = /^(contains|not-contains|count:\\d+)$/;\nconst FLAGS_RE = /^[dgimsuvy]*$/;\n\n/** 1-based line of `index` within `text`. */\nfunction lineAt(text: string, index: number): number {\n let line = 1;\n for (let i = 0; i < index && i < text.length; i++) {\n if (text[i] === \"\\n\") line++;\n }\n return line;\n}\n\n/**\n * Lines of the file above the text `target` selects, so a finding names the\n * line in the file rather than in the selection. The github format writes\n * `line=` from it.\n *\n * The body is the file with its frontmatter block cut off the front, so it\n * starts that block's height down. `raw` is the file itself. The serialized\n * frontmatter and a companion file have no place in the page to count from,\n * so their lines stay their own.\n */\nfunction linesAbove(target: EvalTarget | undefined, page: PageFile): number {\n if (target !== undefined && target !== \"body\") return 0;\n if (!page.content.endsWith(page.body)) return 0;\n return lineAt(page.content, page.content.length - page.body.length) - 1;\n}\n\nexport const regexGrader: Grader = {\n kind: \"tool:regex\",\n // It calls `readTarget` directly, so it serves the whole vocabulary — the\n // one deterministic grader that does. Declaring it here is what exempts it\n // from the engine's body-only guard (ADR 01033).\n targets: [\"body\", \"raw\", \"frontmatter\", \"file\"] as const,\n validateOptions(options: Options): OptionCheck {\n const match = options.match;\n return firstError(\n knownKeys(options, [\"pattern\", \"flags\", \"match\"]),\n requiredString(options, \"pattern\"),\n optionalString(options, \"flags\"),\n typeof options.flags === \"string\" && !FLAGS_RE.test(options.flags)\n ? \"options.flags must be JS RegExp flags (d g i m s u v y)\"\n : undefined,\n match !== undefined && (typeof match !== \"string\" || !MATCH_RE.test(match))\n ? \"options.match must be contains, not-contains, or count:N\"\n : undefined,\n // A pattern that will not compile is a typo, not a finding: reporting it\n // as a failed assertion would blame the page for the eval's own bug.\n (() => {\n if (typeof options.pattern !== \"string\") return undefined;\n try {\n new RegExp(options.pattern, (options.flags as string | undefined) ?? \"\");\n return undefined;\n } catch (err) {\n return `options.pattern is not a valid regular expression (${errorMessage(err)})`;\n }\n })(),\n );\n },\n mode: \"per-file\",\n grade(ctx) {\n // Synchronous work behind an async contract: `.then` keeps a throw a\n // rejection, as it was when this method was `async`.\n return Promise.resolve().then(() => {\n const findings: Finding[] = [];\n for (const { plan, eval: ev } of ctx.targets) {\n const opts = ev.options as RegexOptions;\n const pattern = opts.pattern ?? \"\";\n const flags = opts.flags ?? \"\";\n const match = opts.match ?? \"contains\";\n\n const selected = readTarget(ev.target, plan);\n if (!selected.ok) {\n findings.push({\n evalName: ev.name,\n file: plan.page.file,\n ruleId: \"regex/unreadable-target\",\n message: selected.reason,\n severity: ev.severity,\n line: 1,\n });\n continue;\n }\n\n const text = selected.text;\n const offset = linesAbove(ev.target, plan.page);\n // Always count with /g so `count:N` is a count and not a boolean, then\n // read the first match's offset for the line number.\n const all = [...text.matchAll(new RegExp(pattern, flags.includes(\"g\") ? flags : `${flags}g`))];\n const first = all[0];\n\n if (match === \"contains\" && all.length === 0) {\n findings.push({\n evalName: ev.name,\n file: plan.page.file,\n ruleId: \"regex/not-found\",\n message: `Pattern /${pattern}/${flags} not found in ${selected.label}`,\n severity: ev.severity,\n line: 1,\n });\n } else if (match === \"not-contains\" && first !== undefined) {\n findings.push({\n evalName: ev.name,\n file: plan.page.file,\n ruleId: \"regex/found\",\n message: `Pattern /${pattern}/${flags} found in ${selected.label}, expected absent`,\n severity: ev.severity,\n line: offset + lineAt(text, first.index),\n });\n } else if (match.startsWith(\"count:\")) {\n const want = Number(match.slice(\"count:\".length));\n if (all.length !== want) {\n findings.push({\n evalName: ev.name,\n file: plan.page.file,\n ruleId: \"regex/count\",\n message: `Pattern /${pattern}/${flags} matched ${String(all.length)} time(s) in ${selected.label}, expected ${String(want)}`,\n severity: ev.severity,\n line: first === undefined ? 1 : offset + lineAt(text, first.index),\n });\n }\n }\n }\n return findings;\n });\n },\n};\n","/**\n * Grader registry: maps grader kinds to implementations. Same pattern as\n * the metadata tool's schema registry — a static map, one entry per built-in.\n *\n * Only the deterministic graders have an implementation here. `ai` is graded\n * by the judge stage and `human` by review, so `graderFor` answers\n * `undefined` for both. They are registered kinds all the same:\n * `listGraderKinds` names them, and an eval may name either.\n */\nimport type { Grader } from \"./types.js\";\nimport { commandGrader } from \"./command.js\";\nimport { regexGrader } from \"./native/regex.js\";\n\nconst GRADERS = new Map<string, Grader>(\n [commandGrader, regexGrader].map((g) => [g.kind, g]),\n);\n\n/** Kinds graded outside this map: `ai` by the judge, `human` by review. */\nconst UNMAPPED_KINDS: readonly string[] = [\"ai\", \"human\"];\n\n/** The built-in kinds, in the order a message lists them. */\nconst BUILT_IN_ORDER: readonly string[] = [\"ai\", \"command\", \"human\", \"tool:regex\"];\n\nexport function graderFor(kind: string): Grader | undefined {\n return GRADERS.get(kind);\n}\n\n/** Every registered kind: the built-ins first, then any registered later. */\nexport function listGraderKinds(): string[] {\n return [...new Set<string>([...BUILT_IN_ORDER, ...GRADERS.keys()])];\n}\n\n/** Whether an eval naming `kind` has anything to grade it. */\nexport function isRegisteredGrader(kind: string): boolean {\n return UNMAPPED_KINDS.includes(kind) || GRADERS.has(kind);\n}\n\n/** Register an additional grader (used by later phases and tests). */\nexport function registerGrader(grader: Grader): void {\n GRADERS.set(grader.kind, grader);\n}\n","/**\n * Pre-run feasibility: evals that cannot reach a verdict as configured.\n *\n * ADRs 01020 and 01022 already make an eval that reached no verdict a failure\n * rather than a pass — but they do it at grade time, which for an `ai` eval is\n * after the judge has been paid. Everything here is knowable from the resolved\n * config and page alone, so it is knowable before a single call goes out.\n *\n * `claude plugin eval` computes the same class of thing and prints it up\n * front, on the reasoning that an infeasible check scores zero in every arm\n * and reads as \"the tool found nothing\" rather than as \"you configured this\n * wrong\". That is exactly the confusion worth spending a cheap static pass to\n * avoid.\n *\n * Scope is deliberately narrow: only what *configuration* makes impossible,\n * and only where nothing already answers it. Whether a command is on PATH is\n * a runtime fact ADR 01020 covers, and an `ai` eval with no assertion is\n * already rejected by both schemas at parse time, with a better message than\n * this could give. A second answer to a settled question is worse than none.\n *\n * An eval naming a grader nothing registered is not a feasibility problem but\n * a usage error: `assertRegisteredGraders` below refuses the whole command.\n */\nimport { graderFor, isRegisteredGrader, listGraderKinds } from \"../graders/registry.js\";\nimport { DocevalsError } from \"../types.js\";\nimport type { DocevalsConfig } from \"./config.js\";\nimport type { RunProblem } from \"./engine.js\";\nimport type { ResolvedPagePlan } from \"./resolve.js\";\n\nfunction unregistered(where: string, name: string, grader: string): DocevalsError {\n return new DocevalsError(\n `${where}: eval \"${name}\" names grader \"${grader}\", which is not registered. ` +\n `Registered graders: ${listGraderKinds().join(\", \")}.`,\n );\n}\n\n/**\n * Refuse an eval whose grader nothing registered, naming the file that\n * declared it: the config for a config eval, the page for an inline one.\n *\n * A usage error, exit 2, for `run`, `list`, `generate` and `promote`\n * alike. The configuration's bug is not the page's fault (ADR 01029), so a\n * per-eval error result, which blamed every page carrying the eval, was the\n * wrong report. Every config eval is checked, used or not, and every inline\n * eval on every page, skipped or not: a skip is not a reason to keep a typo.\n * A grader added through `registerGrader` passes.\n */\nexport function assertRegisteredGraders(\n plans: ResolvedPagePlan[],\n config: DocevalsConfig,\n): void {\n const configFile = config.configSource ?? config.configPath;\n for (const [name, def] of Object.entries(config.evals)) {\n const grader = def.grader ?? \"ai\";\n if (!isRegisteredGrader(grader)) throw unregistered(configFile, name, grader);\n }\n for (const plan of plans) {\n for (const ev of plan.evals) {\n // A config eval was checked by the loop above, so only a page's own\n // inline evals are left to check here.\n if (ev.source === \"page\" && !isRegisteredGrader(ev.grader)) {\n throw unregistered(plan.page.file, ev.name, ev.grader);\n }\n }\n }\n}\n\nexport interface FeasibilityOptions {\n /** Whether frontmatter-declared commands may run in this invocation. */\n allowFrontmatterCommands: boolean;\n /** Whether script generation can supply a missing command. */\n canGenerate: boolean;\n /** `--deterministic-only`: ai evals are not run, so not checked. */\n deterministicOnly?: boolean;\n /** `--ai-only`: deterministic evals are not run, so not checked. */\n aiOnly?: boolean;\n}\n\nexport function checkFeasibility(\n plans: ResolvedPagePlan[],\n options: FeasibilityOptions,\n): RunProblem[] {\n const problems: RunProblem[] = [];\n for (const plan of plans) {\n if (plan.skip) continue;\n for (const ev of plan.evals) {\n if (ev.skip) continue;\n // Only what this run would actually execute. A filtered run reporting a\n // configuration error about work it never attempted is the shape ADR\n // 01018 guards against: numbers about one thing, a verdict about another.\n const isAi = ev.grader === \"ai\";\n if (isAi && options.deterministicOnly === true) continue;\n if (!isAi && ev.grader !== \"human\" && options.aiOnly === true) continue;\n const where = `Eval \"${ev.name}\"`;\n\n // Grader options. The published vocabulary leaves `options` open and\n // says the grader validates it; this is where that happens for every\n // grader at once, before any of them run.\n const grader = graderFor(ev.grader);\n const invalid = grader?.validateOptions?.(ev.options);\n if (invalid !== undefined) {\n problems.push({\n file: plan.page.file,\n level: \"error\",\n message: `${where}: ${ev.grader} ${invalid}`,\n });\n }\n\n // A page-declared command that may not run, and cannot be generated\n // either, can only ever be skipped — so it is a gate that checks\n // nothing, which is the failure mode worth naming out loud.\n if (\n ev.grader === \"command\" &&\n ev.source === \"page\" &&\n !options.allowFrontmatterCommands &&\n !ev.command &&\n !options.canGenerate\n ) {\n problems.push({\n file: plan.page.file,\n level: \"error\",\n message:\n `${where}: a page-declared command eval with no command, while ` +\n `frontmatter commands are not granted (execution.allow: ` +\n `[frontmatter-commands]) and generation is off — it can only ever ` +\n `be skipped`,\n });\n }\n }\n }\n return problems;\n}\n","/**\n * The findings baseline — a ratchet (ADR 01017).\n *\n * A baseline records today's findings so a run can fail on *new* ones only.\n * That is what lets a team turn an eval on this Monday instead of after a\n * 500-page cleanup: the standard tightens immediately, the backlog is recorded,\n * and nothing regresses past the recorded state.\n *\n * Ported from the metadata tool's `src/meta/core/baseline.ts`, which solved this first.\n * `manni.config.yaml` is shared by the family (ADR 01008), so the two tools\n * spell the idea the same way. What differs is the fingerprint: the metadata tool has a\n * JSON Pointer into structured metadata, and we grade prose. See `fingerprint`.\n *\n * Scope: **findings**, which means deterministic graders. An ai-graded eval's\n * verdict carries no rule identity to fingerprint, and a judge verdict is not\n * the kind of thing a backlog file should freeze — the human-review queue is\n * the mechanism for those.\n */\nimport { createHash } from \"node:crypto\";\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport { DocevalsError, type EvalResult, type Finding } from \"../types.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\n\n/** Where `--baseline` / `--write-baseline` / `baseline:` point when unspecified. */\nexport const DEFAULT_BASELINE_PATH = \".manni-docevals-baseline.json\";\n\n/** The only file format this version understands. */\nexport const BASELINE_VERSION = 1;\n\n/** Exactly what `fingerprint` emits: 16 lowercase hex characters. */\nconst FINGERPRINT_RE = /^[0-9a-f]{16}$/;\n\nexport interface Baseline {\n version: number;\n /** manni docevals version that produced the file, for diagnosis only. */\n generatedWith: string;\n /** File path (as reported in results) -> sorted finding fingerprints. */\n entries: Record<string, string[]>;\n}\n\n/** The parts of a finding a fingerprint is built from. */\nexport type Fingerprintable = Pick<Finding, \"evalName\" | \"ruleId\">;\n\n/** What file labels are made relative to, so a baseline reads the same anywhere. */\nexport interface FingerprintContext {\n /** Directory canonical paths are expressed relative to: the config's. */\n base: string;\n /** Directory a result's `file` label is relative to. Defaults to `base`. */\n runBase?: string;\n}\n\n/**\n * The key a file's entry is stored under.\n *\n * Result labels are relative to whatever the run resolved against, so the same\n * page is `docs/legacy.md` from the repo root and `legacy.md` from inside\n * `docs/`. A baseline is committed and shared, so its keys have to name the\n * file the same way from anywhere — otherwise the lookup misses and every\n * baselined finding reads as new, without a fingerprint ever being compared.\n */\nexport function canonicalFilePath(file: string, ctx?: FingerprintContext): string {\n if (!ctx) return file;\n const from = ctx.runBase ?? ctx.base;\n return relative(ctx.base, resolve(from, file)).replace(/\\\\/g, \"/\");\n}\n\n/**\n * A finding's stable identity: 16 hex characters of\n * `sha256(evalName NUL ruleId)`.\n *\n * `ruleId` is the grader's own rule (`regex/found`, `regex/count`).\n * Unlike `ruleIdFor` in the SARIF reporter it is *not* defaulted to the eval\n * name when absent — `evalName` is already the first component, so an empty\n * second one is unambiguous, and a grader that leaves `ruleId` undefined (the\n * `command` grader does) would otherwise hash its eval name twice.\n *\n * Deliberately excludes:\n *\n * - **the line number** — adding one line shifts every finding below it, and a\n * fingerprint that moved with it would present a pure reordering as a wall of\n * new findings;\n * - **the message prose** — a command or a registered grader writes it, so an upstream\n * reword would invalidate every affected entry in every consuming repo at\n * once, presenting as \"manni docevals broke our build\";\n * - **the file path** — it is already the entry key.\n *\n * The consequence, and it is a real one: identity is per rule per file, **not\n * per occurrence**. A file baselined for three `regex/found` findings will not fail\n * when a fourth appears. Prose has no stable per-occurrence anchor — a text\n * snippet churns on every edit, an ordinal renumbers on every insertion, which\n * is the line-number problem again.\n *\n * The NUL separator is what keeps `(\"ab\", undefined)` and `(\"a\", \"b\")` apart.\n */\nexport function fingerprint(f: Fingerprintable): string {\n const parts = [f.evalName, f.ruleId ?? \"\"];\n return createHash(\"sha256\").update(parts.join(\"\\0\")).digest(\"hex\").slice(0, 16);\n}\n\n/** Sorted keys and sorted fingerprints, so the file diffs and merges legibly. */\nexport function serializeBaseline(baseline: Baseline): string {\n // Null-prototype for the same reason `parseBaseline` uses one: a file key of\n // `__proto__` assigned into a plain object literal would set the prototype\n // and drop the entry, so a parse/serialize round-trip would lose it silently.\n const entries = Object.create(null) as Record<string, string[]>;\n for (const file of Object.keys(baseline.entries).sort()) {\n entries[file] = [...(baseline.entries[file] ?? [])].sort();\n }\n return `${JSON.stringify(\n { version: baseline.version, generatedWith: baseline.generatedWith, entries },\n null,\n 2,\n )}\\n`;\n}\n\nfunction bad(source: string, detail: string): never {\n throw new DocevalsError(`Baseline \"${source}\": ${detail}`);\n}\n\n/** Parse baseline JSON. `source` is the path as the user would type it. */\nexport function parseBaseline(text: string, source: string): Baseline {\n let raw: unknown;\n try {\n // A committed file an editor may have re-saved. Nothing hashes it, so this\n // is purely a parsing concession.\n raw = JSON.parse(text.replace(/^/, \"\"));\n } catch (err) {\n bad(source, `invalid JSON: ${errorMessage(err)}`);\n }\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n bad(source, \"top level must be an object.\");\n }\n const obj = raw as Record<string, unknown>;\n\n if (obj.version !== BASELINE_VERSION) {\n bad(\n source,\n `unsupported version ${JSON.stringify(obj.version)} (this manni docevals writes version ${BASELINE_VERSION}). Re-record it with \\`manni docevals run --write-baseline\\`.`,\n );\n }\n\n const rawEntries = obj.entries;\n if (\n typeof rawEntries !== \"object\" ||\n rawEntries === null ||\n Array.isArray(rawEntries)\n ) {\n bad(source, '\"entries\" must be an object mapping file paths to fingerprints.');\n }\n\n // Null-prototype, so a file key of `__proto__` is stored as an ordinary entry\n // rather than triggering the inherited setter — which would replace this\n // object's prototype and silently drop the entry. Every other malformation\n // here is rejected loudly; that one would not even be visible.\n const entries = Object.create(null) as Record<string, string[]>;\n for (const [file, value] of Object.entries(rawEntries as Record<string, unknown>)) {\n if (!Array.isArray(value) || value.some((v) => typeof v !== \"string\")) {\n bad(source, `entries[\"${file}\"] must be a list of fingerprint strings.`);\n }\n // A fingerprint that is not the shape this code writes can never match a\n // real finding, so a typo in a hand-edited baseline would otherwise present\n // as \"that finding came back\" with nothing to explain it. Reject it where\n // the user can still see which entry is wrong.\n const malformed = (value as string[]).find((v) => !FINGERPRINT_RE.test(v));\n if (malformed !== undefined) {\n bad(\n source,\n `entries[\"${file}\"] contains ${JSON.stringify(malformed)}, which is not a fingerprint (16 lowercase hex characters).`,\n );\n }\n entries[file] = value as string[];\n }\n\n return {\n version: BASELINE_VERSION,\n generatedWith: typeof obj.generatedWith === \"string\" ? obj.generatedWith : \"\",\n entries,\n };\n}\n\n/** Read a baseline from disk. Returns null when the file does not exist. */\nexport function readBaseline(absPath: string, source: string): Baseline | null {\n let text: string;\n try {\n text = readFileSync(absPath, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw new DocevalsError(\n `Baseline \"${source}\" could not be read: ${errorMessage(err)}`,\n );\n }\n return parseBaseline(text, source);\n}\n\n/**\n * Write the baseline atomically.\n *\n * It is a committed artifact the whole team's gate reads, and a truncated write\n * is not merely lost work: the next run cannot parse it and exits 2 until\n * someone re-records.\n */\nexport function writeBaselineFile(\n absPath: string,\n baseline: Baseline,\n source: string,\n): void {\n try {\n mkdirSync(dirname(absPath), { recursive: true });\n const tmp = `${absPath}.tmp`;\n writeFileSync(tmp, serializeBaseline(baseline));\n renameSync(tmp, absPath);\n } catch (err) {\n throw new DocevalsError(\n `Baseline \"${source}\" could not be written: ${errorMessage(err)}`,\n );\n }\n}\n\n/** Record every finding in `results` as a baseline. Clean files are omitted. */\nexport function buildBaseline(\n results: EvalResult[],\n generatedWith: string,\n ctx?: FingerprintContext,\n): Baseline {\n // Null-prototype, and here it prevents a crash rather than a lost entry.\n // `__proto__` is the famous collision but not the reachable one; `toString`\n // is a legal filename. A *clean* file gets no entry, so `applyBaseline`'s\n // lookup would find the inherited method instead of `undefined`, pass the\n // `!known` guard because a function is truthy, and then die in `new Set(known)`.\n const entries = Object.create(null) as Record<string, string[]>;\n for (const r of results) {\n // Keyed by `r.file`, matching `applyBaseline`'s lookup. `groupFindings`\n // currently guarantees `f.file === r.file`, so keying by the finding was\n // not a live bug — but the asymmetry is a trap: a grader that resolved a\n // path differently would build entries the lookup could never match, and\n // every baselined finding would reappear as new with nothing to explain it.\n const key = canonicalFilePath(r.file, ctx);\n for (const f of r.findings ?? []) {\n // A diagnostic is never recorded. It is not a finding *about the page* —\n // it is the grader reporting that it could not reach a verdict, and ADR\n // 01022 says that fails the eval at any severity. Recording it lets the\n // next run suppress it, which empties `fresh` entirely and makes the\n // recompute below yield `pass`: \"the grader could not run\" becomes a\n // permanent green that no later run can dislodge. The severity-plus-\n // diagnostic predicate in `applyBaseline` only covers *partial*\n // suppression; this is what covers the whole-set case.\n if (f.diagnostic === true) continue;\n const list = entries[key] ?? [];\n const print = fingerprint(f);\n // Two identical findings in one file are one fingerprint; storing the\n // duplicate would only make the count meaningless.\n if (!list.includes(print)) list.push(print);\n entries[key] = list;\n }\n }\n return { version: BASELINE_VERSION, generatedWith, entries };\n}\n\nexport interface AppliedBaseline {\n /** Results with baselined findings removed and outcomes recomputed. */\n results: EvalResult[];\n /** Fingerprints the baseline holds **for the files this run checked**. */\n recorded: number;\n /** Findings suppressed because the baseline already had them. */\n suppressed: number;\n /** Recorded fingerprints for checked files that no longer occur. */\n stale: number;\n}\n\n/**\n * Subtract a baseline from a run's results.\n *\n * `recorded` and `stale` count only the files this run actually checked. The\n * alternative — counting the whole file — would make a single-page run announce\n * that hundreds of entries \"no longer occur\", and the advice that follows\n * (re-record to prune) would then destroy them.\n */\nexport function applyBaseline(\n results: EvalResult[],\n baseline: Baseline,\n ctx?: FingerprintContext,\n): AppliedBaseline {\n let suppressed = 0;\n const seenByFile = new Map<string, Set<string>>();\n const touched = new Set<string>();\n\n const applied = results.map((r) => {\n // \"Touched\" means this run actually graded the file, which is not the same\n // as having produced a result for it. A clean pass must count, because a\n // file whose findings were all fixed is exactly what `stale` exists to\n // surface. A `skipped` or `error` result must NOT: the eval never ran, so\n // its recorded findings are not gone, they are unmeasured — and reporting\n // them as \"no longer occur\" invites the re-record that deletes them.\n const key = canonicalFilePath(r.file, ctx);\n if (r.outcome === \"pass\" || r.outcome === \"fail\") touched.add(key);\n const findings = r.findings;\n if (!findings || findings.length === 0) return r;\n const known = baseline.entries[key];\n if (!known) return r; // no entry: a new or renamed file, everything is new\n\n const recordedHere = new Set(known);\n const seen = seenByFile.get(key) ?? new Set<string>();\n const fresh: Finding[] = [];\n for (const f of findings) {\n const print = fingerprint(f);\n if (recordedHere.has(print)) {\n seen.add(print);\n suppressed += 1;\n } else {\n fresh.push(f);\n }\n }\n seenByFile.set(key, seen);\n\n if (fresh.length === findings.length) return r;\n // Outcome is recomputed rather than preserved: a deterministic eval fails\n // only on an error-severity finding, so suppressing the last of them makes\n // the eval pass. Leaving `outcome` alone would baseline the finding and\n // still fail the run.\n // `diagnostic` is part of the failing condition, not just severity. A\n // diagnostic finding means the grader reached no verdict, and ADR 01022\n // says that fails the eval at any severity — the engine enforces exactly\n // that when it first computes the outcome. Recomputing on severity alone\n // let a baseline turn \"the grader could not run\" into `pass`, which is the\n // one thing a baseline must never forgive: it suppresses *known* findings,\n // never the absence of a verdict.\n const hasError = fresh.some(\n (f) => f.severity === \"error\" || f.diagnostic === true,\n );\n return {\n ...r,\n outcome: hasError ? (\"fail\" as const) : (\"pass\" as const),\n ...(fresh.length > 0 ? { findings: fresh } : { findings: undefined }),\n baselined: findings.length - fresh.length,\n };\n });\n\n let recorded = 0;\n let stale = 0;\n for (const key of touched) {\n const known = baseline.entries[key];\n if (!known) continue;\n const recordedHere = new Set(known);\n recorded += recordedHere.size;\n stale += recordedHere.size - (seenByFile.get(key)?.size ?? 0);\n }\n\n return { results: applied, recorded, suppressed, stale };\n}\n\n/**\n * Count fingerprints added and dropped between two baselines.\n *\n * The `removed` half is the load-bearing one: an accidental `--write-baseline`\n * on a narrowed glob or a mistyped exclude silently forgives everything it did\n * not see, and this number is the only thing that makes that visible in a CI log.\n */\nexport function diffBaselines(\n previous: Baseline | null,\n next: Baseline,\n): { added: number; removed: number } {\n const flatten = (b: Baseline | null): Set<string> => {\n const out = new Set<string>();\n if (!b) return out;\n for (const [file, prints] of Object.entries(b.entries)) {\n for (const p of prints) out.add(`${file}\\0${p}`);\n }\n return out;\n };\n const before = flatten(previous);\n const after = flatten(next);\n let added = 0;\n let removed = 0;\n for (const k of after) if (!before.has(k)) added += 1;\n for (const k of before) if (!after.has(k)) removed += 1;\n return { added, removed };\n}\n\n/** Total fingerprints held in a baseline, across every file. */\nexport function countFingerprints(baseline: Baseline): number {\n let n = 0;\n for (const prints of Object.values(baseline.entries)) n += prints.length;\n return n;\n}\n","/**\n * `--since <ref>`: which pages changed, in absolute-path terms the engine can\n * compare against a discovered `PageFile` (ADR 01040).\n *\n * Two invocations, both through the injected `ExecFn` so the suite never runs\n * git. `rev-parse --show-toplevel` doubles as the is-this-a-repo check and\n * supplies the anchor the diff's paths are relative to.\n *\n * The anchor is the whole point. `git diff --name-only` prints paths relative\n * to the repository top level, while `PageFile.file` is relative to the\n * *discovery* root — the two differ whenever the config lives in a\n * subdirectory. Comparing them directly does not throw; it simply matches\n * nothing, so every page reads as unchanged and the run exits 0 having\n * evaluated nothing. Reconciling in absolute space is what makes that\n * impossible rather than merely unlikely.\n */\nimport { resolve } from \"node:path\";\nimport { DocevalsError } from \"../types.js\";\nimport { outputTail } from \"../../shared/exec.js\";\nimport type { ExecFn, ExecResult } from \"../graders/types.js\";\n\n/** git can be slow on a cold index, but not this slow. */\nconst GIT_TIMEOUT_MS = 30_000;\n\n/**\n * The comparison key for one absolute path.\n *\n * Lowercased on win32, and that is load-bearing rather than defensive: git\n * reports the case recorded in its index, fast-glob reports the case on disk,\n * and the two sources can also disagree about the drive letter. None of those\n * differences is a different file on Windows, but every one of them is a\n * different string.\n *\n * Keyed on the platform rather than on case-insensitivity in general, because\n * the latter cannot be detected reliably — a case-insensitive APFS or a\n * case-sensitive Windows volume both exist. This is the Windows-specific\n * behaviour the code actually implements, not a claim about every such\n * filesystem.\n */\nexport function changedKey(absPath: string): string {\n const abs = resolve(absPath);\n return process.platform === \"win32\" ? abs.toLowerCase() : abs;\n}\n\n/** `outputTail` caps at 400 chars; git stderr on a broken repo is unbounded. */\nfunction stderrOf(result: ExecResult): string {\n return outputTail(result) || \"(no output)\";\n}\n\n/**\n * Run one git invocation, raising the two failures whose repair is the same\n * whichever command produced them. A non-zero exit is left to the caller,\n * because *that* repair differs: a bad repository and a bad ref send the\n * reader to different places.\n */\nasync function git(\n exec: ExecFn,\n args: string[],\n root: string,\n): Promise<ExecResult> {\n const result = await exec(args, { cwd: root, timeoutMs: GIT_TIMEOUT_MS });\n if (result.spawnError) {\n throw new DocevalsError(\n `--since needs git on PATH: could not run git (${result.spawnError}). ` +\n `Install git, or drop --since to evaluate the whole corpus.`,\n );\n }\n if (result.timedOut) {\n throw new DocevalsError(\n `--since timed out: \\`${args.join(\" \")}\\` took longer than ` +\n `${GIT_TIMEOUT_MS / 1000}s in ${root}.`,\n );\n }\n return result;\n}\n\n/**\n * Absolute-path keys for every file that differs between `ref` and `HEAD`.\n *\n * `ref...HEAD` (three dots) diffs against the merge base, which is what a pull\n * request means by \"changed\": commits that landed on the base branch after this\n * one forked are not this branch's changes. It also means **uncommitted\n * working-tree edits are not included** — correct for CI, surprising locally.\n */\nexport async function changedFilesSince(\n ref: string,\n root: string,\n exec: ExecFn,\n): Promise<Set<string>> {\n // A ref that parses as a git option is not a ref. `--output=x` sends the diff\n // to a file and leaves stdout empty, so the changed set comes back empty and\n // the run exits 0 having scoped everything out — the silent green this flag\n // must never produce. `--` does not help: the left side of `A...B` is parsed\n // before any separator, so the shape has to be rejected outright.\n if (ref.startsWith(\"-\")) {\n throw new DocevalsError(\n `--since \"${ref}\" is not a ref: a value starting with \"-\" is read by git as ` +\n `an option, which would silently produce an empty diff.`,\n );\n }\n // Git reads an omitted left side of `A...B` as HEAD, so a blank ref diffs\n // HEAD against HEAD — exit 0, empty diff, every eval scoped out, exit 0. The\n // blank arrives by accident: `--since \"${{ github.base_ref }}\"` renders empty\n // on a push event, and an unset shell variable expands to nothing.\n if (ref.trim() === \"\") {\n throw new DocevalsError(\n `--since was given an empty ref. Git would read that as HEAD and scope the ` +\n `run to nothing, which exits 0 having checked nothing. If this came from a ` +\n `CI expression, the variable is unset on this event.`,\n );\n }\n const top = await git(exec, [\"git\", \"rev-parse\", \"--show-toplevel\"], root);\n if (top.code !== 0) {\n throw new DocevalsError(\n `--since requires a git repository, and ${root} is not a git repository ` +\n `(or git cannot read it). git said: ${stderrOf(top)}`,\n );\n }\n const topLevel = top.stdout.trim();\n\n // `-z` is mandatory. Without it, `core.quotePath` C-escapes any path with a\n // non-ASCII byte — `\"docs/caf\\303\\251.md\"` — and the escaped form matches no\n // discovered page. Nothing errors; the page is simply never evaluated.\n const diff = await git(\n exec,\n [\"git\", \"--no-pager\", \"diff\", \"--name-only\", \"-z\", `${ref}...HEAD`],\n root,\n );\n if (diff.code !== 0) {\n throw new DocevalsError(\n `--since ${ref}: git could not resolve \"${ref}...HEAD\". ` +\n `In CI this is usually a shallow clone — actions/checkout defaults to ` +\n `fetch-depth: 1, which fetches no other branch, so set fetch-depth: 0 ` +\n `(or fetch ${ref} explicitly) before using --since. ` +\n `git said: ${stderrOf(diff)}`,\n );\n }\n\n const changed = new Set<string>();\n // NUL-*terminated*, not NUL-separated: the last entry is followed by a\n // separator, so the split ends in an empty string.\n for (const rel of diff.stdout.split(\"\\0\")) {\n if (rel === \"\") continue;\n changed.add(changedKey(resolve(topLevel, rel)));\n }\n return changed;\n}\n","/**\n * `--newer-than <duration>`: which pages changed inside a window of time back\n * from now.\n *\n * A page's age is **detected, not switched**. A page git tracks, with no\n * uncommitted change in the page or in any manifest that supplied its evals,\n * takes the committer date of the last commit touching any of those files.\n * Every other page (untracked, modified, or outside a repository) takes the\n * newest mtime among them.\n *\n * The committed case is the reason this is not simply mtime. A fresh clone,\n * which is what CI runs on, stamps every file with the clone's time, so mtime\n * alone would read as \"every page just changed\". The modified case is the\n * reason it is not simply the commit date: an edit not yet committed is the\n * newest change there is, and the commit date predates it.\n *\n * Every git call goes through the injected `ExecFn`, so the suite never runs\n * git. A machine without git, or a directory outside a repository, is not an\n * error: every page is then \"any other page\" and takes its mtime.\n */\nimport { statSync } from \"node:fs\";\nimport { relative, resolve } from \"node:path\";\nimport { DocevalsError } from \"../types.js\";\nimport type { ExecFn, ExecResult } from \"../graders/types.js\";\nimport { changedKey } from \"./since.js\";\n\n/** git can be slow on a cold index, but not this slow. */\nconst GIT_TIMEOUT_MS = 30_000;\n\n/** The files that decide one page's age: the page, then its eval manifests. */\nexport interface PageAgeInput {\n /** Absolute path of the page file. */\n page: string;\n /** Absolute paths (or URLs) of the manifests that supplied its eval keys. */\n manifests: readonly string[];\n}\n\n/** What git says about the working tree, or `null` outside a repository. */\ninterface RepoState {\n topLevel: string;\n /** `changedKey`s of every file git tracks. */\n tracked: Set<string>;\n /** `changedKey`s of tracked files that differ from HEAD. */\n modified: Set<string>;\n}\n\nasync function git(\n exec: ExecFn,\n args: string[],\n cwd: string,\n): Promise<ExecResult> {\n const result = await exec(args, { cwd, timeoutMs: GIT_TIMEOUT_MS });\n if (result.timedOut) {\n throw new DocevalsError(\n `--newer-than timed out: \\`${args.join(\" \")}\\` took longer than ` +\n `${String(GIT_TIMEOUT_MS / 1000)}s in ${cwd}.`,\n );\n }\n return result;\n}\n\n/** NUL-terminated repo-relative paths to `changedKey`s. */\nfunction keysOf(stdout: string, topLevel: string): Set<string> {\n const keys = new Set<string>();\n for (const rel of stdout.split(\"\\0\")) {\n if (rel !== \"\") keys.add(changedKey(resolve(topLevel, rel)));\n }\n return keys;\n}\n\nasync function repoState(root: string, exec: ExecFn): Promise<RepoState | null> {\n const top = await git(exec, [\"git\", \"rev-parse\", \"--show-toplevel\"], root);\n // No git on PATH, or not a repository: every page takes its mtime.\n if (top.spawnError !== undefined || top.code !== 0) return null;\n const topLevel = top.stdout.trim();\n if (topLevel === \"\") return null;\n\n // `--full-name` so the paths are relative to the top level whatever the\n // working directory, and `-z` so `core.quotePath` cannot C-escape them.\n const tracked = await git(exec, [\"git\", \"ls-files\", \"-z\", \"--full-name\"], topLevel);\n if (tracked.code !== 0) return null;\n\n // Staged and unstaged edits alike. A repository with no commit has no HEAD,\n // and then every tracked file is uncommitted: the mtime rule applies.\n const diff = await git(\n exec,\n [\"git\", \"--no-pager\", \"diff\", \"--name-only\", \"-z\", \"HEAD\"],\n topLevel,\n );\n const trackedKeys = keysOf(tracked.stdout, topLevel);\n return {\n topLevel,\n tracked: trackedKeys,\n modified: diff.code === 0 ? keysOf(diff.stdout, topLevel) : trackedKeys,\n };\n}\n\n/** The newest mtime among `files`, skipping any that cannot be read (a URL). */\nfunction newestMtime(files: readonly string[]): number {\n let newest = Number.NEGATIVE_INFINITY;\n for (const file of files) {\n try {\n newest = Math.max(newest, statSync(file).mtimeMs);\n } catch {\n // A URL manifest, or a file removed mid-run, has no mtime to offer.\n }\n }\n return newest;\n}\n\n/** Epoch milliseconds of the last commit touching any of `files`, if one did. */\nasync function lastCommit(\n files: readonly string[],\n repo: RepoState,\n exec: ExecFn,\n): Promise<number | undefined> {\n const paths = files.map((f) => relative(repo.topLevel, f).replace(/\\\\/g, \"/\"));\n const log = await git(\n exec,\n [\"git\", \"--no-pager\", \"log\", \"-1\", \"--format=%ct\", \"--\", ...paths],\n repo.topLevel,\n );\n const seconds = Number.parseInt(log.stdout.trim(), 10);\n return log.code === 0 && Number.isFinite(seconds) ? seconds * 1000 : undefined;\n}\n\n/**\n * The epoch milliseconds each page last changed, in input order, by the rule\n * in this module's header.\n */\nexport async function pageAges(\n pages: readonly PageAgeInput[],\n root: string,\n exec: ExecFn,\n): Promise<number[]> {\n const repo = await repoState(root, exec);\n const ages: number[] = [];\n for (const { page, manifests } of pages) {\n const files = [page, ...manifests];\n const committed =\n repo !== null &&\n files.every((f) => {\n const key = changedKey(f);\n return repo.tracked.has(key) && !repo.modified.has(key);\n });\n const fromGit = committed ? await lastCommit(files, repo, exec) : undefined;\n ages.push(fromGit ?? newestMtime(files));\n }\n return ages;\n}\n","/**\n * Grader contract for deterministically graded evals (command and tool:*).\n * A grader receives every (page, eval) target that resolved to its kind and\n * returns normalized findings. AI grading lives in src/judge, not here.\n */\nimport type { ExecFn } from \"@hawkeyexl/inference\";\nimport type { Finding } from \"../types.js\";\nimport type { DocevalsConfig } from \"../core/config.js\";\nimport type { OptionCheck, Options } from \"./options.js\";\nimport type { ResolvedEval, ResolvedPagePlan } from \"../core/resolve.js\";\n\n/** One (page, eval) pair a grader must grade. */\nexport interface GraderTarget {\n plan: ResolvedPagePlan;\n eval: ResolvedEval;\n}\n\n// The exec seam is shared with the inference layer's subprocess provider, so\n// these types live there now. Re-exported so grader code keeps importing them\n// from one place.\nexport type { ExecFn, ExecOptions, ExecResult } from \"@hawkeyexl/inference\";\n\nexport interface GraderContext {\n targets: GraderTarget[];\n config: DocevalsConfig;\n /** Discovery root; page paths are relative to it. */\n root: string;\n exec: ExecFn;\n}\n\nexport interface Grader {\n /** Registry kind, e.g. \"command\", \"tool:regex\". */\n kind: string;\n /**\n * Reject option sets this grader cannot honour, before anything runs.\n *\n * The published vocabulary leaves `options` open on purpose, so this is the\n * \"validated by the grader at run time\" half of that contract. Without it a\n * misspelled key falls through to a default and the eval silently checks\n * something its author never wrote. Returns a message, or undefined when the\n * options are fine.\n */\n validateOptions?(options: Options): OptionCheck;\n /**\n * Targets other than `body` this grader can actually read.\n *\n * Declared by the grader rather than listed in the engine, so adding a\n * grader that reads `target` is a change in one file. Absent means \"body\n * only\", which is every grader that predates `target` — and the engine\n * turns any other request into an error rather than letting the grader\n * quietly measure the whole page (ADR 01033).\n */\n targets?: readonly string[];\n /**\n * batch: one external invocation covers all targets;\n * per-file: one invocation per target.\n */\n mode: \"batch\" | \"per-file\";\n grade(ctx: GraderContext): Promise<Finding[]>;\n}\n\n/**\n * Split targets into groups that share an eval configuration. A batch\n * grader runs one invocation per group so that (a) two same-kind evals\n * on one page each get their own run and correct finding attribution, and\n * (b) per-page option overrides are honored instead of the first target's\n * options being applied to everyone.\n */\n/**\n * A plain object with its keys in sorted order, recursively, so that\n * `JSON.stringify` describes the value rather than the order it was written\n * in. `undefined` passes through so an absent option stays absent in the key.\n */\nfunction sortedForKey(value: unknown): unknown {\n if (value === undefined || value === null) return value;\n if (Array.isArray(value)) return value.map(sortedForKey);\n if (typeof value !== \"object\") return value;\n const entries = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(entries).sort()) {\n out[k] = sortedForKey(entries[k]);\n }\n return out;\n}\n\nexport function groupTargetsByEval(targets: GraderTarget[]): GraderTarget[][] {\n const groups = new Map<string, GraderTarget[]>();\n for (const t of targets) {\n const key = JSON.stringify([\n t.eval.name,\n // Key order, not just content: `resolve.ts` rebuilds `options` per page\n // by spread, so insertion order follows each page's own YAML. Two pages\n // declaring the same options in a different order used to hash\n // differently and land in separate groups, so a batch grader made one\n // invocation per page instead of one per configuration. Sorting makes\n // the key describe the configuration rather than how it was typed.\n sortedForKey(t.eval.options),\n t.eval.timeoutMs ?? null,\n t.eval.severity,\n ]);\n const list = groups.get(key) ?? [];\n list.push(t);\n groups.set(key, list);\n }\n return [...groups.values()];\n}\n","/**\n * Judge cache key composition. The cache itself is the inference library's\n * `JsonCache`; what stays here is what only manni docevals can decide — what\n * invalidates an entry: provider, model, prompt version, run count,\n * temperature, the page body, and the resolved eval.\n */\nimport { buildCacheKey, JsonCache, sha256 } from \"@hawkeyexl/inference\";\nimport type { JudgeRun } from \"../types.js\";\nimport type { ResolvedEval } from \"../core/resolve.js\";\nimport { PROMPT_VERSION } from \"./prompt.js\";\n\nexport { sha256 };\n\ndeclare const judgeCacheBodyBrand: unique symbol;\n\n/**\n * The output of `judgeCacheBody`, and the only thing `cacheKey` accepts as a\n * body. A brand rather than a wrapper object: it costs nothing at runtime and\n * the value is still an ordinary string everywhere else.\n */\nexport type JudgeCacheBody = string & { readonly [judgeCacheBodyBrand]: true };\n\n/**\n * A judge cache that refuses to persist an ensemble containing an errored run.\n *\n * The library's `runEnsemble` caches unconditionally — it has no way to know\n * whether an error is a property of the request or of the moment. Here we do:\n * an error is an infrastructure failure (VRAM exhausted, rate limited,\n * connection dropped), never a verdict about the page. Writing one to the cache\n * turns a transient outage into a permanent answer, and `--no-cache` becomes\n * the only way out of a state nothing explains.\n *\n * That is worst for a committed cache, whose whole purpose is to let CI replay\n * real verdicts with no provider reachable. Caching an error there commits the\n * outage: every future run replays it, the evals sit in human-review forever,\n * and the fixtures look valid the entire time. This was not hypothetical — a\n * local run at concurrency 4 exhausted VRAM and wrote 65 errored ensembles into\n * `docs/.manni-docevals-cache/` (ADR 01038).\n *\n * Subclassed rather than wrapped because `JsonCache` has private fields, so a\n * structurally-identical object does not satisfy its type.\n */\nexport class VerdictCache extends JsonCache<JudgeRun[]> {\n /** An ensemble is cacheable only if every run produced a verdict. */\n private static usable(runs: JudgeRun[]): boolean {\n return runs.every((r) => r.error === undefined && r.verdict !== undefined);\n }\n\n override set(key: string, value: JudgeRun[]): void {\n if (!VerdictCache.usable(value)) return;\n super.set(key, value);\n }\n\n /**\n * Reading applies the same predicate, which is what makes the property\n * total rather than merely forward-looking.\n *\n * Guarding only the write cannot heal an entry this class did not write —\n * and those exist: the 65 errored ensembles that prompted ADR 01038 were on\n * disk before it, and had to be deleted by hand. A committed cache is\n * exactly the population at risk, because CI replays it with no provider\n * reachable, so a poisoned entry there is a verdict no future run can\n * dislodge. Treating it as a miss costs one re-judge and converges;\n * inheriting `get` unchanged never does.\n *\n * The predicate also matches the library's own definition rather than ours:\n * `computeConsensus` counts a run with no `verdict` as an error vote, so an\n * entry with neither `verdict` nor `error` — reachable through a truncated\n * write to these hand-editable JSON files — would otherwise replay as a\n * permanent human-review with nothing explaining why.\n */\n override get(key: string): JudgeRun[] | undefined {\n const hit = super.get(key);\n if (hit === undefined) return undefined;\n return VerdictCache.usable(hit) ? hit : undefined;\n }\n}\n\n/**\n * The exact body string the judge keys on: the chunk budget, then the selected\n * text.\n *\n * Exported because anything that wants to know whether a verdict is cached has\n * to reproduce this byte for byte, and reproducing it by hand is how the\n * cache-completeness script silently computed keys that matched nothing —\n * `scripts/check-docs-cache.mjs` passed the raw page body while the judge had\n * started prefixing the budget. A helper both call is the only version of this\n * that cannot drift.\n *\n * The return type is branded, and `cacheKey` takes only that brand, so a\n * caller that hands over a raw page body no longer compiles. Reproducing the\n * composition by hand used to be a silent cache miss; now it is a type error,\n * which is the whole point of having one helper.\n */\nexport function judgeCacheBody(chunkChars: number, text: string): JudgeCacheBody {\n return `chunk${String(chunkChars)}\\n${text}` as JudgeCacheBody;\n}\n\nexport function cacheKey(\n provider: string,\n model: string,\n runs: number,\n temperature: number,\n body: JudgeCacheBody,\n ev: ResolvedEval,\n): string {\n const evalFingerprint = JSON.stringify({\n assertion: ev.assertion,\n evidence: ev.evidence,\n examples: ev.examples,\n type: ev.type,\n });\n return buildCacheKey([\n provider,\n model,\n `v${PROMPT_VERSION}`,\n `r${runs}`,\n `t${temperature}`,\n // Pre-hashed: page bodies are large and key parts should stay short.\n sha256(body),\n sha256(evalFingerprint),\n ]);\n}\n","/**\n * Judge prompt construction. The system prompt sets a binary rubric with an\n * explicit `partial` escape valve; the user content carries the assertion,\n * evidence hint, pass/fail example anchors, and the page body with\n * frontmatter and MDX noise stripped.\n *\n * PROMPT_VERSION is part of every cache key — bump it whenever the prompt\n * changes so stale cached verdicts never survive a prompt revision.\n */\nimport type { ResolvedEval } from \"../core/resolve.js\";\nimport { partLabel } from \"../core/split.js\";\n\nexport const PROMPT_VERSION = 4;\n\nexport const JUDGE_SYSTEM_PROMPT = [\n \"You are a meticulous technical documentation judge. You evaluate whether a\",\n \"documentation page satisfies a specific assertion.\",\n \"\",\n \"Rules:\",\n \"- Judge ONLY the stated assertion against the supplied page content. Do not\",\n \" invent requirements the assertion does not state.\",\n '- \"match\" is \"pass\" only when the assertion is fully satisfied by the page.',\n '- Use \"partial\" when the page partially satisfies the assertion.',\n '- Use \"fail\" when the page does not satisfy the assertion.',\n \"- Quote the specific page text you relied on in \\\"observed\\\". If the page\",\n \" lacks relevant content, say so explicitly.\",\n \"- Be conservative with confidence: reserve values above 0.9 for verdicts a\",\n \" careful human reviewer would certainly agree with.\",\n \"Respond with a JSON object matching the provided schema.\",\n].join(\"\\n\");\n\n/**\n * Strip MDX imports/exports and comments; keep JSX text content and markdown.\n * Fence-aware: lines inside ``` / ~~~ code blocks are page content the judge\n * must see verbatim (a code sample's `import` line is evidence, not MDX noise).\n */\nexport function cleanBody(body: string): string {\n const out: string[] = [];\n let fence: string | null = null;\n for (const line of body.split(\"\\n\")) {\n const marker = /^(\\s*)(```+|~~~+)/.exec(line)?.[2];\n if (fence) {\n out.push(line);\n if (marker?.startsWith(fence)) fence = null;\n continue;\n }\n if (marker !== undefined) {\n fence = marker;\n out.push(line);\n continue;\n }\n out.push(\n line\n .replace(/\\{\\/\\*[\\s\\S]*?\\*\\/\\}/g, \"\")\n .replace(/<!--[\\s\\S]*?-->/g, \"\")\n .replace(/^(import|export)\\s.*$/, \"\"),\n );\n }\n // Comments spanning multiple lines are left in place — stray comment text\n // is harmless noise, whereas a post-join strip would reach into fences.\n return out.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\").trim();\n}\n\nexport function buildUserContent(\n ev: ResolvedEval,\n body: string,\n targetLabel = \"body\",\n): string {\n const parts: string[] = [\n `# Assertion`,\n ev.assertion ?? \"\",\n ];\n if (ev.evidence) {\n parts.push(\"\", `# Where to look`, ev.evidence);\n }\n if (ev.examples?.pass || ev.examples?.fail) {\n parts.push(\"\", \"# Anchors\");\n // Anchors widened to lists with the manni:evals vocabulary. Interpolating\n // the array would join it with commas and present several distinct\n // examples to the judge as one run-on sentence.\n for (const anchor of ev.examples.pass ?? []) {\n parts.push(`A passing page: ${anchor}`);\n }\n for (const anchor of ev.examples.fail ?? []) {\n parts.push(`A failing page: ${anchor}`);\n }\n }\n // Name what the judge is looking at. Told only \"page content\" while being\n // handed a frontmatter block or a companion file, a judge reasons about the\n // wrong thing and says so confidently.\n //\n // Only the page body carries MDX noise worth stripping. Running `cleanBody`\n // over a companion source file would delete its `import`/`export` lines —\n // the judge would then be asked whether code exports something it can no\n // longer see.\n const isBody = targetLabel === \"body\";\n parts.push(\n \"\",\n isBody ? \"# Page content\" : `# Page content (${targetLabel})`,\n \"\",\n isBody ? cleanBody(body) : body,\n );\n return parts.join(\"\\n\");\n}\n\n/**\n * Gathering evidence from one part of a page too long to judge in one call.\n *\n * Why a two-stage shape rather than judging each part and merging verdicts:\n * merging is unsound. \"The page documents the --force flag\" is satisfied if\n * *any* part documents it; \"the page never promises unreleased features\" is\n * violated if *any* part promises one. One needs OR across parts, the other\n * AND, and nothing in an assertion's text reliably says which — so a merge\n * rule has to guess, and guesses wrong quietly.\n *\n * Gathering evidence sidesteps the quantifier entirely. Each part contributes\n * what it saw; one judge then answers the original question against the whole\n * collection, exactly as it would have with the page in front of it. The\n * verdict contract is unchanged — still one `JudgeVerdict` per run — so\n * consensus, zones, the response cache, human review and `calibrate` need to\n * know nothing about any of this.\n */\nexport const EVIDENCE_SYSTEM_PROMPT = [\n \"You are gathering evidence from one part of a documentation page so that a\",\n \"judge can later evaluate an assertion about the whole page.\",\n \"\",\n \"Rules:\",\n \"- Do NOT decide whether the assertion holds. You are seeing one part; the\",\n \" part that settles it may be elsewhere.\",\n \"- Quote page text verbatim. Quote anything that supports the assertion and\",\n \" anything that contradicts it.\",\n \"- Quote only what bears on this assertion. An empty list is the right\",\n \" answer for a part that says nothing about it.\",\n \"Respond with a JSON object matching the provided schema.\",\n].join(\"\\n\");\n\nexport const EVIDENCE_SCHEMA = {\n type: \"object\",\n required: [\"supports\", \"contradicts\"],\n properties: {\n supports: { type: \"array\", items: { type: \"string\" } },\n contradicts: { type: \"array\", items: { type: \"string\" } },\n },\n additionalProperties: false,\n} as const;\n\nexport interface PartEvidence {\n supports: string[];\n contradicts: string[];\n}\n\nexport function buildEvidenceUser(\n ev: ResolvedEval,\n chunk: string,\n part: { index: number; total: number },\n): string {\n return [\n \"# Assertion (do not judge it — only gather evidence)\",\n ev.assertion ?? \"\",\n ...(ev.evidence ? [\"\", \"# Where to look\", ev.evidence] : []),\n \"\",\n `# Page content (${partLabel(part.index, part.total)})`,\n \"\",\n chunk,\n ].join(\"\\n\");\n}\n\n/**\n * Render gathered evidence as the \"page content\" a judge sees.\n *\n * The judge is told plainly that it is reading extracts rather than the page,\n * because a judge that believes it saw everything will happily report that\n * something is absent when it was merely in a part that contributed nothing.\n */\nexport function renderEvidence(parts: PartEvidence[], total: number): string {\n const supports = parts.flatMap((p) => p.supports);\n const contradicts = parts.flatMap((p) => p.contradicts);\n const lines = [\n `The page was too long to read in one pass, so it was read in ${String(total)} parts`,\n \"and the passages bearing on this assertion were collected below. Judge the\",\n \"assertion against this evidence. Absence of a quotation is weak evidence of\",\n \"absence in the page: parts that bore on nothing contributed nothing.\",\n \"\",\n \"## Passages supporting the assertion\",\n ...(supports.length > 0 ? supports.map((q) => `- ${q}`) : [\"(none)\"]),\n \"\",\n \"## Passages contradicting the assertion\",\n ...(contradicts.length > 0 ? contradicts.map((q) => `- ${q}`) : [\"(none)\"]),\n ];\n return lines.join(\"\\n\");\n}\n","/**\n * Safeguard layer 1: a model judging its own output shows self-preference\n * bias (proposal 0046, § The self-preference-bias check).\n *\n * Two axes, reported apart because the remedy differs.\n *\n * - **Content.** The judge is among the machines attributed for what the\n * eval's `target` reads: `provenance` for `body` (the default), the `fields`\n * of `meta-provenance` for `frontmatter`, both for `raw`, and none for a\n * companion file, which carries its own record if it is a page. The check\n * covers the whole body, because `target` has no form that names lines.\n * - **Criterion.** A `meta-provenance` entry for the judge lists this eval's\n * id under `evals`: the judge proposed the assertion it is now grading.\n *\n * Content wins when both hold. Neither is a failure: bias skews a verdict, it\n * does not prevent one forming, so ADR 01022's \"no verdict fails\" rule does\n * not apply, and erroring would punish a single-model corpus with no second\n * provider to reach for.\n */\nimport { metaProvenanceEntries, provenanceEntries } from \"../../meta/internal.js\";\nimport type { ResolvedEval, ResolvedPagePlan } from \"../core/resolve.js\";\nimport { DEFAULT_TARGET } from \"../core/target.js\";\nimport type { EvalResult } from \"../types.js\";\n\nexport type SelfPreference = NonNullable<EvalResult[\"selfPreference\"]>;\n\n/** A self-preference mark, and the sentence that explains it. */\nexport interface SelfPreferenceFinding extends SelfPreference {\n /** Without the file: the warning prefixes it, a problem carries it. */\n message: string;\n}\n\nconst remedy = (evalId: string): string =>\n `, and it is also the judge. Self-judging favors the author; give \"${evalId}\" a model: of its own.`;\n\n/** Whether the eval's judge, `model`, produced what the eval grades or the eval itself. */\nexport function selfPreferenceOf(\n plan: ResolvedPagePlan,\n ev: ResolvedEval,\n model: string,\n): SelfPreferenceFinding | undefined {\n const data = plan.page.frontmatter.data;\n const meta = metaProvenanceEntries(data[\"meta-provenance\"]).filter(\n (e) => e[\"generated-by\"] === model,\n );\n const target = ev.target ?? DEFAULT_TARGET;\n const readsBody = target === \"body\" || target === \"raw\";\n const readsFields = target === \"frontmatter\" || target === \"raw\";\n\n if (readsBody && provenanceEntries(data.provenance).some((e) => e[\"generated-by\"] === model)) {\n return {\n axis: \"content\",\n model,\n message: `provenance names ${model} for the body this eval grades${remedy(ev.name)}`,\n };\n }\n if (readsFields && meta.some((e) => e.fields.length > 0)) {\n return {\n axis: \"content\",\n model,\n message: `meta-provenance names ${model} for the fields this eval grades${remedy(ev.name)}`,\n };\n }\n if (meta.some((e) => e.evals.includes(ev.name))) {\n return {\n axis: \"criterion\",\n model,\n message: `meta-provenance says ${model} proposed \"${ev.name}\"${remedy(ev.name)}`,\n };\n }\n return undefined;\n}\n","/**\n * Pipeline orchestration: discover → resolve → deterministic graders (cheap\n * first, the book's hybrid pattern) → AI judge → aggregate → report.\n *\n * The judge is injected (`options.judge`) so the deterministic pipeline and\n * tests run without any provider configured.\n */\nimport { DocevalsError } from \"../types.js\";\nimport type {\n EvalResult,\n Finding,\n RunReport,\n SuiteSummary,\n} from \"../types.js\";\nimport { loadRunConfig, type DocevalsConfig } from \"./config.js\";\nimport {\n grantsFor,\n NOT_GRANTED_REASON,\n type ExecutionGrant,\n} from \"../../shared/execution.js\";\nimport { discoverPages } from \"./discover.js\";\nimport { withExternalMetadata } from \"./external.js\";\nimport { resolvePages, type EvalLocation, type ResolvedPagePlan } from \"./resolve.js\";\nimport {\n applyBaseline,\n buildBaseline,\n countFingerprints,\n diffBaselines,\n readBaseline,\n writeBaselineFile,\n DEFAULT_BASELINE_PATH,\n type Baseline,\n type FingerprintContext,\n} from \"./baseline.js\";\nimport { changedFilesSince, changedKey } from \"./since.js\";\nimport { pageAges } from \"./newer-than.js\";\nimport { parseDuration } from \"../../shared/duration.js\";\nimport { graderFor } from \"../graders/registry.js\";\nimport { assertRegisteredGraders, checkFeasibility } from \"./feasibility.js\";\nimport { realExec } from \"../../shared/exec.js\";\nimport { groupTargetsByEval, type ExecFn, type GraderTarget } from \"../graders/types.js\";\nimport { sha256 } from \"../judge/cache.js\";\nimport { isTurnBudgetSkip } from \"../judge/budget.js\";\nimport { selfPreferenceOf } from \"../judge/self-preference.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { resolve } from \"node:path\";\n\nexport interface RunProblem {\n file: string;\n message: string;\n level: \"error\" | \"warning\";\n line?: number;\n}\n\n/** RunReport plus resolution problems (kept off the core type for reporters). */\nexport interface EngineReport extends RunReport {\n problems: RunProblem[];\n /** Present only when a baseline was read or written (ADR 01017). */\n baseline?: BaselineOutcome[\"summary\"];\n /**\n * Present only under `--since` (ADR 01040). `pagesTotal` is the whole\n * discovered corpus — `pages` above stays that number too — and\n * `pagesSelected` is the count of pages that **changed since the ref**,\n * which are the only pages this run graded. Consumers reading this from\n * `--format json` should treat it as the size of the change set, matching\n * what the reporters print.\n */\n since?: { ref: string; pagesSelected: number; pagesTotal: number };\n /**\n * Present only under `--newer-than`. `pagesSelected` is the count of pages\n * this run graded: those that changed inside the window and, when `--since`\n * is given too, since the ref as well. Both blocks then carry that one count.\n */\n newerThan?: { duration: string; pagesSelected: number; pagesTotal: number };\n}\n\nexport interface JudgeOptions {\n provider?: string;\n model?: string;\n /** Run inference on this machine, with llama-cpp, over any configured or eval-level provider. */\n local?: boolean;\n runs?: number;\n noCache?: boolean;\n /** Stop after this many uncached inference calls (ADR 01019). */\n maxTurns?: number | null;\n /** Characters of content per judge call; longer content is read in parts. */\n chunkChars?: number;\n}\n\n/** Injected AI judging stage; absent → ai-graded evals are skipped. */\nexport type JudgeFn = (\n targets: GraderTarget[],\n config: DocevalsConfig,\n options: JudgeOptions,\n) => Promise<EvalResult[]>;\n\n/** Injected script-generation stage (Phase 4); absent → missing commands error. */\n/** Why a command eval with no command was not generated for: no provider. */\nconst GENERATION_UNAVAILABLE =\n \"no command and script generation unavailable (configure a provider or run `manni docevals generate`)\";\n\n/** One eval generation could not persist a command for, and why. */\nexport interface GenerationRefusal {\n file: string;\n evalName: string;\n message: string;\n}\n\nexport type GenerateFn = (\n targets: GraderTarget[],\n config: DocevalsConfig,\n options: JudgeOptions,\n) => Promise<{\n generatedPaths: string[];\n /** Why no provider could be had, when generation needed one and got none. */\n unavailable?: string;\n /**\n * Evals whose command reference had nowhere to go (proposal 0047): the\n * manifest that owns the page's evals joins on a field the page lacks. The\n * engine reports each as an errored result in the writer's own sentence,\n * rather than as a generation that failed.\n */\n refusals?: GenerationRefusal[];\n}>;\n\nexport interface RunOptions {\n configPath?: string;\n /** Preloaded config; skips loading/validating configPath a second time. */\n config?: DocevalsConfig;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Files, directories and globs, cwd-relative; empty means the collections. */\n paths?: string[];\n /** `--collection <name>`, repeatable (proposal 0041). */\n collection?: string[];\n /** `--exclude <glob>`, repeatable. */\n exclude?: string[];\n cwd?: string;\n deterministicOnly?: boolean;\n aiOnly?: boolean;\n /**\n * Run only these grants, of those the config holds. Absent keeps them all;\n * `[]` runs nothing. Never widens past `execution.allow`.\n */\n allowExecution?: ExecutionGrant[];\n /** `false` clears every grant for this run. */\n execution?: boolean;\n /** Run only these evals by name. Empty match is a usage error (ADR 01018). */\n evalNames?: string[];\n /** Run only evals belonging to this suite. */\n suite?: string;\n /**\n * Evaluate only pages that differ between this ref and HEAD. Unlike\n * `evalNames`, an empty match is *not* a usage error (ADR 01040).\n */\n since?: string;\n /**\n * Evaluate only pages whose file or eval manifest changed within this\n * duration back from now, such as `7d`. A committed page's age is its last\n * commit's date; any other page's is its mtime. With `since`, a page must\n * satisfy both. Like `since`, an empty match is not a usage error.\n */\n newerThan?: string;\n /**\n * Baseline in four states, like the metadata tool's: `undefined` leaves the config in\n * charge, a string names a file, `true` means \"use the resolved path even if\n * the config names none\", and `false` disables it outright.\n */\n baseline?: string | boolean;\n /** Record the run's findings as the new baseline. `true` uses the resolved path. */\n writeBaseline?: string | boolean;\n /**\n * Stamped into a written baseline's `generatedWith`, for diagnosis only. The\n * engine is a library entry point and cannot read its own package.json in a\n * bundle, so the CLI supplies it rather than the engine guessing.\n */\n toolVersion?: string;\n generate?: boolean;\n failOnReview?: boolean;\n judgeOptions?: JudgeOptions;\n exec?: ExecFn;\n judge?: JudgeFn;\n generateScripts?: GenerateFn;\n}\n\n/**\n * Why this eval's `target` cannot be served, or `undefined` when it can.\n *\n * `body` is what every deterministic grader already reads, so naming it\n * explicitly is a no-op rather than an error.\n */\nfunction unsupportedTarget(\n ev: ResolvedPagePlan[\"evals\"][number],\n): string | undefined {\n const target = ev.target;\n if (target === undefined || target === \"body\") return undefined;\n const grader = graderFor(ev.grader);\n const named = typeof target === \"string\" ? target : target.path;\n if (grader?.targets?.includes(typeof target === \"string\" ? target : \"file\")) {\n return undefined;\n }\n return (\n `grader ${ev.grader} cannot read target \"${named}\" — it grades the page ` +\n `body. Use the ai grader for this target, or drop the target.`\n );\n}\n\nfunction skippedResult(\n plan: ResolvedPagePlan,\n ev: ResolvedPagePlan[\"evals\"][number],\n reason: string,\n): EvalResult {\n return {\n evalName: ev.name,\n type: ev.type,\n grader: ev.grader,\n file: plan.page.file,\n outcome: \"skipped\",\n skipReason: reason,\n durationMs: 0,\n };\n}\n\n/**\n * Collision-proof composite key for (file, eval) maps — file paths may\n * contain any character, so field boundaries must be unambiguous.\n */\nfunction resultKey(file: string, evalName: string): string {\n return JSON.stringify([file, evalName]);\n}\n\nfunction groupFindings(findings: Finding[]): Map<string, Finding[]> {\n const map = new Map<string, Finding[]>();\n for (const f of findings) {\n const key = resultKey(f.file, f.evalName);\n const list = map.get(key) ?? [];\n list.push(f);\n map.set(key, list);\n }\n return map;\n}\n\n/**\n * Record each result's suite on the result itself.\n *\n * The mapping is already computed here for the summaries; without stamping it,\n * a reporter that wants to group by suite (JUnit) has no way to, and a\n * consumer of `--format json` sees pass rates per suite with no way to tell\n * which results produced them.\n */\nfunction stampSuites(\n results: EvalResult[],\n plans: ResolvedPagePlan[],\n): void {\n const suiteOf = new Map<string, string>();\n const weightOf = new Map<string, number>();\n const locationOf = new Map<string, EvalLocation>();\n for (const plan of plans) {\n for (const ev of plan.evals) {\n const key = resultKey(plan.page.file, ev.name);\n suiteOf.set(key, ev.suite);\n weightOf.set(key, ev.weight);\n locationOf.set(key, ev.location);\n }\n }\n for (const r of results) {\n const key = resultKey(r.file, r.evalName);\n r.suite = suiteOf.get(key) ?? \"default\";\n // A result with no matching plan entry cannot be weighted from one, so it\n // counts as 1 rather than 0 — dropping it out of the denominator would let\n // an unresolvable eval quietly raise a suite's rate.\n r.weight = weightOf.get(key) ?? 1;\n // A result with no plan entry has no declaring entry to point at, so it\n // names its page alone, as every result did before locations.\n r.location = locationOf.get(key) ?? { file: r.file };\n }\n}\n\nexport interface BaselineOutcome {\n results: EvalResult[];\n /** Present only when a baseline was read or written. */\n summary?: {\n path: string;\n recorded: number;\n suppressed: number;\n stale: number;\n written?: { added: number; removed: number; total: number };\n };\n}\n\n/**\n * Read, apply, and optionally re-record the findings baseline (ADR 01017).\n *\n * The path is resolved once, here, and both reading and writing use it. That is\n * deliberate: a bare `--write-baseline` must record into the *configured* path,\n * because a repo that points `baseline:` somewhere custom would otherwise\n * record into a file nothing ever reads — and the ratchet would silently do\n * nothing at all. The metadata tool names this exact trap.\n */\nfunction resolveBaseline(\n results: EvalResult[],\n config: DocevalsConfig,\n options: RunOptions,\n cwd: string,\n problems: RunProblem[],\n): BaselineOutcome {\n const wants = options.writeBaseline !== undefined && options.writeBaseline !== false;\n if (options.baseline === false && !wants) return { results };\n\n // Read and write paths resolve separately. Sharing one made\n // `--baseline old.json --write-baseline new.json` read old.json and then\n // overwrite it, never creating new.json.\n //\n // A bare `--baseline` falls back to the configured path and then the\n // default. `--write-baseline` does NOT force that fallback on the *read*\n // side: `--write-baseline snapshot.json` in a repo with no `baseline:` key\n // should not silently subtract a file the user never named.\n const readFallback =\n config.baseline ?? (options.baseline === true ? DEFAULT_BASELINE_PATH : null);\n const applyFrom =\n options.baseline === false\n ? null\n : typeof options.baseline === \"string\"\n ? options.baseline\n : readFallback;\n const writeTo = !wants\n ? null\n : typeof options.writeBaseline === \"string\"\n ? options.writeBaseline\n : (config.baseline ?? DEFAULT_BASELINE_PATH);\n const configured = writeTo ?? applyFrom;\n if (configured === null) return { results };\n\n // Relative to the config's directory, not the working directory: the file is\n // committed beside the config, and a run from a subdirectory has to find the\n // same one.\n const ctx: FingerprintContext = { base: config.configDir, runBase: cwd };\n // A baseline that cannot be parsed must not block the one command documented\n // to repair it. Reading unconditionally made `--write-baseline` throw the\n // very error whose message recommends running it.\n const read = (from: string): Baseline | null => {\n try {\n return readBaseline(resolve(config.configDir, from), from);\n } catch (e) {\n if (!wants) throw e;\n problems.push({\n file: from,\n message: `${errorMessage(e)} — re-recording over it.`,\n level: \"warning\",\n });\n return null;\n }\n };\n\n // What gets subtracted from this run's findings. Null under --no-baseline.\n const previous = applyFrom === null ? null : read(applyFrom);\n // What is about to be overwritten. This is what `removed` must be measured\n // against — not `previous`, which may be a different file or, under\n // --no-baseline, deliberately unread. Measuring the diff against the wrong\n // prior silently reported `-0` for a re-record that dropped everything.\n const overwriting =\n writeTo === null ? null : writeTo === applyFrom ? previous : read(writeTo);\n\n let out = results;\n let recorded = 0;\n let suppressed = 0;\n let stale = 0;\n if (previous && options.baseline !== false) {\n const applied = applyBaseline(results, previous, ctx);\n out = applied.results;\n recorded = applied.recorded;\n suppressed = applied.suppressed;\n stale = applied.stale;\n }\n\n // `writeTo` is null exactly when nothing is being recorded.\n if (!wants || writeTo === null) {\n return {\n results: out,\n summary: { path: configured, recorded, suppressed, stale },\n };\n }\n\n // Recorded from the *unsuppressed* results: a re-record describes what the\n // corpus contains now, not what this run happened to still be complaining\n // about after the previous baseline was subtracted.\n const next = buildBaseline(results, options.toolVersion ?? \"unknown\", ctx);\n writeBaselineFile(resolve(config.configDir, writeTo), next, writeTo);\n const { added, removed } = diffBaselines(overwriting, next);\n // Apply the baseline this run just wrote, not the one it replaced. Recording\n // today's findings *is* declaring them the accepted state, so a recording run\n // has nothing new left to fail on. Reporting them as failures anyway would\n // make `--write-baseline` a command you always have to `|| true`, which is a\n // reliable way to lose the exit code that matters on the next run.\n const accepted = applyBaseline(results, next, ctx);\n // Writing a baseline nothing will read is the same silent-nothing-happens\n // failure as recording into the wrong path: the command succeeds, the file\n // appears, and the next run ignores it. Say so where the user is looking.\n // Fires whenever an ordinary run would not read back what was just written:\n // no `baseline:` at all, or a `--write-baseline <path>` pointing somewhere\n // the config does not name.\n if (config.baseline !== writeTo) {\n problems.push({\n file: writeTo,\n message:\n `Recorded ${writeTo}, but \\`baseline:\\` in ${config.configPath} is ` +\n `${config.baseline === null ? \"not set\" : `\"${config.baseline}\"`}. ` +\n `An ordinary run will not read this file — point the key at it, or pass --baseline ${writeTo}.`,\n level: \"warning\",\n });\n }\n return {\n results: accepted.results,\n summary: {\n path: configured,\n recorded,\n suppressed,\n stale,\n written: { added, removed, total: countFingerprints(next) },\n },\n };\n}\n\n/**\n * Narrow each plan's evals to the requested names and/or suite, in place.\n *\n * Returns whether a filter was applied, which is what suspends suite\n * enforcement downstream. A filter matching nothing is a usage error rather\n * than a green run over zero evals — the same contract `discoverPages` already\n * enforces for an empty input set (ADR 01018).\n */\nexport function applySelection(\n plans: ResolvedPagePlan[],\n config: DocevalsConfig,\n options: { evalNames?: string[]; suite?: string },\n /**\n * Whether a match must be something the run would actually grade.\n *\n * True for `run`, where a filter matching only skipped work would exit 0\n * having executed nothing. False for `list`, which executes nothing by\n * design — showing that an eval resolves but is skipped is the answer it\n * exists to give, and throwing there breaks the command the run's own error\n * message points at.\n */\n requireRunnable = true,\n): boolean {\n const names = options.evalNames?.filter((n) => n.trim() !== \"\") ?? [];\n const suite = options.suite;\n if (names.length === 0 && suite === undefined) return false;\n\n if (suite !== undefined && !(suite in config.suites)) {\n throw new DocevalsError(\n `--suite \"${suite}\" is not a defined suite. Defined: ${\n Object.keys(config.suites).sort().join(\", \") || \"(none)\"\n }`,\n );\n }\n const wanted = new Set(names);\n\n // Counts only evals that will actually be graded. Counting evals on a\n // skipped page made `--eval x` exit 0 over a run that executed nothing,\n // which is the outcome ADR 01018 makes a usage error one typo away.\n let matched = 0;\n for (const plan of plans) {\n const runnable = !plan.skip && !plan.problems.some((p) => p.level === \"error\");\n plan.evals = plan.evals.filter((ev) => {\n const byName = wanted.size === 0 || wanted.has(ev.name);\n // Match the suite an eval *reports under*, not the membership list in\n // `config.suites[x].evals`. A page inherits its suite from `eval-suite`\n // or `defaults.suite` and stamps it on every eval it carries, including\n // page-inline ones the membership list never mentions — so filtering on\n // the list would select evals that report under a different suite than\n // the one asked for, and miss ones that report under it.\n const bySuite = suite === undefined || ev.suite === suite;\n const keep = byName && bySuite;\n if (keep && (!requireRunnable || (runnable && !ev.skip))) matched += 1;\n return keep;\n });\n }\n\n if (matched === 0) {\n const asked = [\n names.length > 0 ? `--eval ${names.join(\", \")}` : \"\",\n suite === undefined ? \"\" : `--suite ${suite}`,\n ]\n .filter(Boolean)\n .join(\" and \");\n throw new DocevalsError(\n `${asked} matched no evals that would run on the pages selected. Nothing ` +\n `would have been checked — the name may be wrong, or every page carrying ` +\n `it may be skipped. Run \\`manni docevals list\\` with the same filter to ` +\n `see the resolved plan.`,\n );\n }\n return true;\n}\n\n/**\n * Narrow each plan to the pages that changed, in place (ADR 01040).\n *\n * A page changed when its own file did, or when a manifest that supplied one\n * of its eval keys did. A corpus that keeps its evals in manifests edits an\n * eval without touching the page, and keying on the page file alone would\n * scope that edit out and grade nothing.\n *\n * An unchanged page keeps no eval. Every grader grades one page at a time or\n * one group of pages per call, so dropping a page's targets shrinks the check\n * rather than changing what it means. An eval naming an unregistered grader\n * never reaches here: `assertRegisteredGraders` refuses the run first, so a\n * typo cannot surface on a changed page and vanish on an unchanged one.\n *\n * An empty result is **not** a usage error, which is where this parts company\n * with `applySelection`. \"No page changed\" is a correct answer to a correct\n * question; \"`--eval` matched nothing\" is a typo.\n */\nexport function applySinceScope(\n plans: ResolvedPagePlan[],\n changed: Set<string>,\n): { pagesSelected: number } {\n return applyScope(plans, (plan) => sinceSelects(plan, changed));\n}\n\n/**\n * The files whose change counts as the page's: its own, then every manifest\n * that supplied one of its eval keys. `external` is absent when the run loaded\n * no manifest at all (`withExternalMetadata` returns such pages untouched).\n */\nfunction scopeManifests(plan: ResolvedPagePlan): readonly string[] {\n return plan.page.external?.evalManifests ?? [];\n}\n\nfunction sinceSelects(plan: ResolvedPagePlan, changed: Set<string>): boolean {\n return [plan.page.absPath, ...scopeManifests(plan)].some((f) =>\n changed.has(changedKey(f)),\n );\n}\n\n/**\n * Empty `plan.evals` on every page `keep` rejects, in place, and count the\n * rest. `--since` and `--newer-than` both narrow through it, so a page under\n * both keeps its evals only when both select it.\n */\nfunction applyScope(\n plans: ResolvedPagePlan[],\n keep: (plan: ResolvedPagePlan) => boolean,\n): { pagesSelected: number } {\n let pagesSelected = 0;\n for (const plan of plans) {\n if (keep(plan)) {\n pagesSelected += 1;\n continue;\n }\n plan.evals = [];\n }\n return { pagesSelected };\n}\n\n/** The plans whose page or eval manifest changed inside the last `windowMs`. */\nasync function recentPages(\n plans: ResolvedPagePlan[],\n windowMs: number,\n cwd: string,\n exec: ExecFn,\n): Promise<Set<ResolvedPagePlan>> {\n const floor = Date.now() - windowMs;\n const ages = await pageAges(\n plans.map((p) => ({ page: p.page.absPath, manifests: scopeManifests(p) })),\n cwd,\n exec,\n );\n return new Set(plans.filter((_, i) => (ages[i] ?? Number.NEGATIVE_INFINITY) >= floor));\n}\n\n/**\n * Per-suite aggregates. Reads the suite `stampSuites` recorded on each result\n * rather than rebuilding the plan-to-suite map a second time — two copies of\n * one derivation are two things to keep in agreement.\n */\nfunction summarizeSuites(\n results: EvalResult[],\n config: DocevalsConfig,\n partial = false,\n): SuiteSummary[] {\n const bySuite = new Map<string, EvalResult[]>();\n for (const r of results) {\n const suite = r.suite ?? \"default\";\n const list = bySuite.get(suite) ?? [];\n list.push(r);\n bySuite.set(suite, list);\n }\n const summaries: SuiteSummary[] = [];\n for (const [suite, rs] of [...bySuite.entries()].sort()) {\n const passed = rs.filter((r) => r.outcome === \"pass\").length;\n const failed = rs.filter((r) => r.outcome === \"fail\").length;\n const errored = rs.filter((r) => r.outcome === \"error\").length;\n const needsReview = rs.filter((r) => r.outcome === \"needs-review\").length;\n const skipped = rs.filter((r) => r.outcome === \"skipped\").length;\n // Counts stay unweighted and per-eval: they report how many evals did\n // what, and a reader comparing \"1 failed\" against a rate of 0.33 is\n // reading two different questions, both answered honestly.\n //\n // The rate is weighted over the same membership as before — the graded\n // set, pass + fail + error. `needs-review` and `skipped` stay out of both\n // halves, so a page awaiting review neither helps nor hurts.\n const graded = (r: EvalResult): boolean =>\n r.outcome === \"pass\" || r.outcome === \"fail\" || r.outcome === \"error\";\n const suiteCriteria = config.suites[suite]?.criteria ?? [];\n\n const contributions: { weight: number; passed: boolean }[] = [];\n\n // Criteria first, because which evals a criterion actually absorbs is only\n // known once it is evaluated. A group scored once is the whole point —\n // three checks written as a criterion must not outvote three standalone\n // evals just for being grouped.\n let critPassed = 0;\n let critFailed = 0;\n let critSuspended = 0;\n /** \"<file> <evalName>\" of members a *scored* criterion speaks for. */\n const absorbed = new Set<string>();\n // Indexed once for the whole suite. The loop below is criterion x page x\n // member, and a `filter`/`find` inside it rescans every result each time —\n // quadratic in a corpus's result count, on the one code path that runs\n // after everything else has finished.\n const byKey = new Map<string, EvalResult>();\n const filesByEval = new Map<string, Set<string>>();\n for (const r of rs) {\n byKey.set(resultKey(r.file, r.evalName), r);\n const files = filesByEval.get(r.evalName) ?? new Set<string>();\n files.add(r.file);\n filesByEval.set(r.evalName, files);\n }\n for (const critName of suiteCriteria) {\n const def = config.criteria[critName];\n if (!def) continue;\n const pages = new Set<string>();\n for (const name of def.evals) {\n for (const file of filesByEval.get(name) ?? []) pages.add(file);\n }\n for (const file of pages) {\n const members = def.evals.map((name) =>\n byKey.get(resultKey(file, name)),\n );\n // Every member must have been graded for the group to mean anything.\n // A missing or ungraded member suspends it rather than failing it.\n if (members.some((m) => m === undefined || !graded(m))) {\n critSuspended++;\n // Deliberately does NOT absorb its members. A suspended criterion\n // contributes nothing, so absorbing them too would delete their\n // outcomes from the rate entirely — a failing member would move the\n // total by nothing and silently inflate the suite.\n continue;\n }\n const passes = members.map((m) => m?.outcome === \"pass\");\n const passed =\n def.combine === \"any\" ? passes.some(Boolean) : passes.every(Boolean);\n if (passed) critPassed++;\n else critFailed++;\n contributions.push({ weight: def.weight, passed });\n for (const m of members) {\n if (m) absorbed.add(resultKey(m.file, m.evalName));\n }\n }\n }\n\n // Standalone evals: everything a scored criterion did not speak for.\n for (const r of rs) {\n if (!graded(r) || absorbed.has(resultKey(r.file, r.evalName))) continue;\n contributions.push({ weight: r.weight ?? 1, passed: r.outcome === \"pass\" });\n }\n\n const totalWeight = contributions.reduce((sum, c) => sum + c.weight, 0);\n const passRate =\n totalWeight > 0\n ? contributions\n .filter((c) => c.passed)\n .reduce((sum, c) => sum + c.weight, 0) / totalWeight\n : 1;\n const targetPassRate = config.suites[suite]?.targetPassRate ?? 1.0;\n summaries.push({\n suite,\n total: rs.length,\n passed,\n failed,\n needsReview,\n skipped,\n errored,\n passRate,\n targetPassRate,\n // A suite target is a claim about a body of checks. A filtered run\n // measured part of it, so it reports the numbers and withholds the\n // verdict — erring toward false confidence is what gets a gate removed\n // rather than fixed (ADR 01018).\n meetsTarget: partial ? false : passRate >= targetPassRate,\n ...(partial ? { partial: true } : {}),\n ...(suiteCriteria.length > 0\n ? {\n criteria: {\n total: critPassed + critFailed + critSuspended,\n passed: critPassed,\n failed: critFailed,\n suspended: critSuspended,\n },\n }\n : {}),\n });\n }\n return summaries;\n}\n\nexport async function runEvals(options: RunOptions = {}): Promise<EngineReport> {\n const cwd = options.cwd ?? process.cwd();\n const paths = options.paths ?? [];\n const config =\n options.config ??\n loadRunConfig(\n {\n paths,\n ...(options.configPath === undefined ? {} : { configPath: options.configPath }),\n ...(options.noConfig === undefined ? {} : { noConfig: options.noConfig }),\n ...(options.collection === undefined ? {} : { collection: options.collection }),\n },\n cwd,\n );\n const exec = options.exec ?? realExec;\n // Read the way `meta validate` reads: the frontmatter block, plus whatever\n // an owning manifest of one of the page's collections supplies. A corpus\n // that relocated its evals resolves the same plan it did before the move.\n const pages = await withExternalMetadata(\n discoverPages(\n config,\n {\n paths,\n verb: \"evaluate\",\n ...(options.collection === undefined ? {} : { collection: options.collection }),\n ...(options.exclude === undefined ? {} : { exclude: options.exclude }),\n },\n cwd,\n ),\n config,\n cwd,\n );\n // Refused up front, not at the end: a re-record rebuilds the file from this\n // run's findings, so recording from a filtered run would drop every\n // fingerprint the filter excluded. Deciding it here costs nothing; deciding\n // it after `resolveBaseline` meant the generation pass had already written\n // scripts and rewritten frontmatter, and the judge had already been paid.\n //\n // `--since` is refused here for the same reason and, being *before* the git\n // call below, a usage error never spawns a subprocess.\n if (\n options.writeBaseline !== undefined &&\n options.writeBaseline !== false &&\n ((options.evalNames?.some((n) => n.trim() !== \"\") ?? false) ||\n options.suite !== undefined ||\n options.since !== undefined ||\n options.newerThan !== undefined)\n ) {\n throw new DocevalsError(\n \"--write-baseline records the whole corpus, so it cannot be combined with \" +\n \"--eval, --suite, --since or --newer-than: the re-record would drop every \" +\n \"finding the narrowing excluded. Re-run without it to record.\",\n );\n }\n\n // Before `resolvePages`, so an unresolvable ref fails the run without paying\n // for resolution — but applied after `applySelection` below, because\n // `PageFile.absPath` only exists post-discovery and resolution problems must\n // surface for every page, scoped or not (ADR 01018's driver).\n // Blank and option-shaped refs are rejected inside `changedFilesSince`, at\n // the seam, so a library caller gets the same guard the CLI does.\n const sinceRef = options.since;\n // Parsed before git is asked anything, so a bad duration is a usage error\n // that spawns no subprocess.\n const newerThan = options.newerThan;\n const windowMs =\n newerThan === undefined\n ? undefined\n : parseDuration(newerThan, (message) => new DocevalsError(message));\n const changed =\n sinceRef === undefined ? null : await changedFilesSince(sinceRef, cwd, exec);\n\n const plans = resolvePages(pages, config);\n // A grader nothing registered is the configuration's bug, so it is a usage\n // error before anything else is said about the plan.\n assertRegisteredGraders(plans, config);\n // A run that resolved no evals at all checked nothing, and exited 0 saying\n // so in about seventeen bytes. The identical condition reached through\n // `--eval no-such-eval` is already exit 2 with a careful message\n // (ADR 01018); reaching it through configuration must not be silence\n // (ADR 01041).\n //\n // Read off the *resolved* plan, deliberately before every narrowing:\n // `applySelection` owns its own empty-match error and names what was asked\n // for, and `--since` deliberately answers \"no page changed\" with exit 0 and\n // a sentence (ADR 01040). The plan being empty is a different claim from a\n // scope being empty.\n //\n // Suppressed when resolution errored, because then there *is* something to\n // report: the run exits 1 naming the bad key, which is a better diagnosis\n // than telling the reader to configure a suite they may already have.\n //\n // And read over the pages the author did **not** skip. A page carrying\n // `eval-skip: true` and no suite resolves *zero* evals rather than evals\n // that are then skipped, so counting over every page turned a deliberate,\n // documented skip into a usage error — `test/docevals/fixtures/pages/index.mdx`\n // is exactly that page, and `docs/src/content/docs/docevals/evals/index.mdx` runs it\n // expecting exit 0. \"Nothing is configured to check the pages you asked\n // about\" is the claim; a skipped page is not one of those pages.\n const unskipped = plans.filter((p) => !p.skip);\n if (\n unskipped.length > 0 &&\n unskipped.every((p) => p.evals.length === 0) &&\n !plans.some((p) => p.problems.some((pr) => pr.level === \"error\"))\n ) {\n throw new DocevalsError(\n `No evals resolved for any of the ${unskipped.length} page(s) this run would check. ` +\n `Nothing would have been checked, so this run would have reported ` +\n `success without checking anything.\\n` +\n `Point \\`defaults.suite\\` at a suite in ${config.configPath}, or give ` +\n `the pages an \\`eval-suite\\` or \\`evals\\` frontmatter key. Run ` +\n `\\`manni docevals list\\` to see the resolved plan.`,\n \"nothing-resolved\",\n );\n }\n const filtered = applySelection(plans, config, options);\n // Declared here, applied *after* the feasibility pass below. `--since` scopes\n // what is graded, never what is diagnosed — and `applySinceScope` empties\n // `plan.evals` on unchanged pages, so scoping first would hand\n // `checkFeasibility` nothing to look at. A pull request that edits only\n // `manni.config.yaml` changes no page, so under `--since` every plan would be\n // empty and the config's own validity — a malformed grader option, an unknown\n // key — would go unchecked, exiting 0. The one flag meant for CI would make a\n // config-only change the least examined kind of change there is.\n let scope: { pagesSelected: number; pagesTotal: number } | null = null;\n const judgeOptions = options.judgeOptions ?? {};\n\n const problems: RunProblem[] = plans.flatMap((p) =>\n p.problems.map((pr) => ({\n // A value a manifest supplied is reported against that manifest, at its\n // line there: the page has nothing at that pointer to fix.\n file: pr.file ?? p.page.file,\n message: pr.message,\n level: pr.level,\n line: pr.line,\n })),\n );\n\n const results: EvalResult[] = [];\n const deterministicTargets: GraderTarget[] = [];\n const aiTargets: GraderTarget[] = [];\n const generationTargets: GraderTarget[] = [];\n const generatedPaths: string[] = [];\n /** \"<file> <evalName>\" keys whose check script this run generated. */\n const generatedThisRun = new Set<string>();\n\n // Everything available runs unless the operator narrows it (proposal 0075).\n // The config holds every grant unless `execution.allow` lists fewer;\n // `--allow-execution` keeps only the named ones it already holds, and\n // `--no-execution` clears them all for one run. Nothing here widens.\n const granted = grantsFor(config.execution.allow, {\n ...(options.allowExecution === undefined\n ? {}\n : { allowExecution: options.allowExecution }),\n ...(options.execution === undefined ? {} : { execution: options.execution }),\n });\n const allowFrontmatterCommands = granted.has(\"frontmatter-commands\");\n\n // Before anything is dispatched: an eval that cannot reach a verdict as\n // configured is a configuration error, and saying so now costs nothing where\n // discovering it at grade time costs a judge call.\n problems.push(\n ...checkFeasibility(plans, {\n allowFrontmatterCommands,\n canGenerate: options.generate !== false && options.generateScripts != null,\n ...(options.deterministicOnly === true ? { deterministicOnly: true } : {}),\n ...(options.aiOnly === true ? { aiOnly: true } : {}),\n }),\n );\n\n // Now that every page has been diagnosed, narrow what will actually be\n // graded. See the declaration above for why this cannot move earlier.\n if (changed !== null || windowMs !== undefined) {\n // Ages are read only when asked for, and after every page was diagnosed.\n const recent =\n windowMs === undefined ? null : await recentPages(plans, windowMs, cwd, exec);\n scope = {\n pagesTotal: plans.length,\n ...applyScope(\n plans,\n (plan) =>\n (changed === null || sinceSelects(plan, changed)) &&\n (recent === null || recent.has(plan)),\n ),\n };\n }\n\n for (const plan of plans) {\n if (plan.problems.some((p) => p.level === \"error\")) continue;\n for (const ev of plan.evals) {\n if (plan.skip) {\n results.push(skippedResult(plan, ev, \"page skipped (evals.skip)\"));\n continue;\n }\n if (ev.skip) {\n results.push(skippedResult(plan, ev, \"eval skipped\"));\n continue;\n }\n if (ev.grader === \"human\") {\n results.push({\n evalName: ev.name,\n type: ev.type,\n grader: ev.grader,\n file: plan.page.file,\n outcome: \"needs-review\",\n durationMs: 0,\n });\n continue;\n }\n if (ev.grader === \"ai\") {\n if (options.deterministicOnly) {\n results.push(skippedResult(plan, ev, \"judge skipped (--deterministic-only)\"));\n } else if (!options.judge) {\n results.push(skippedResult(plan, ev, \"judge unavailable (no provider)\"));\n } else {\n aiTargets.push({ plan, eval: ev });\n }\n continue;\n }\n // command / tool:* — deterministic.\n if (options.aiOnly) {\n results.push(skippedResult(plan, ev, \"deterministic evals skipped (--ai-only)\"));\n continue;\n }\n // Page-authored argv, whatever grader carries it. `command` evals name\n // it in `command`; a registered grader may also accept an\n // `options.command` override and hand it to the same `exec`. Gating\n // only the grader left a second spelling of \"run this\" that reached a\n // shell ungated, which made the grant decorative — a page that cannot\n // say `grader: command` could name such a grader with the same argv.\n // Config-authored argv is the operator's own and is not content, so the\n // gate is on `source === \"page\"` rather than on the key's presence.\n const pageAuthoredArgv =\n ev.source === \"page\" &&\n (ev.grader === \"command\" || Array.isArray(ev.options.command));\n if (pageAuthoredArgv && !allowFrontmatterCommands) {\n results.push(\n skippedResult(\n plan,\n ev,\n NOT_GRANTED_REASON,\n ),\n );\n continue;\n }\n if (ev.grader === \"command\" && !ev.command) {\n generationTargets.push({ plan, eval: ev });\n continue;\n }\n // Stale generated script: the assertion changed since generation.\n if (\n ev.grader === \"command\" &&\n ev.command &&\n ev.generatedAssertionHash &&\n ev.assertion &&\n ev.generatedAssertionHash !== sha256(ev.assertion)\n ) {\n if (options.generate !== false && options.generateScripts) {\n generationTargets.push({ plan, eval: ev });\n continue;\n }\n problems.push({\n file: plan.page.file,\n message: `Eval \"${ev.name}\": assertion changed since its script was generated — run \\`manni docevals generate\\` to regenerate`,\n level: \"warning\",\n });\n }\n // ADR 01033: a grader that cannot serve a requested target says so,\n // rather than grading something else and reporting a verdict about\n // bytes nobody asked about. An *error* and not a skip, because a skip\n // keeps the run green and an eval that measured the wrong thing would\n // then read as coverage.\n const unsupported = unsupportedTarget(ev);\n if (unsupported !== undefined) {\n results.push({\n evalName: ev.name,\n type: ev.type,\n grader: ev.grader,\n file: plan.page.file,\n outcome: \"error\",\n skipReason: unsupported,\n durationMs: 0,\n });\n continue;\n }\n deterministicTargets.push({ plan, eval: ev });\n }\n }\n\n // Script generation for command evals with no command yet.\n if (generationTargets.length > 0) {\n if (options.generate !== false && options.generateScripts) {\n const gen = await options.generateScripts(\n generationTargets,\n config,\n judgeOptions,\n );\n generatedPaths.push(...gen.generatedPaths);\n const refusedBy = new Map<string, string>(\n (gen.refusals ?? []).map((r) => [resultKey(r.file, r.evalName), r.message]),\n );\n // Re-read the targets' evals: generateScripts mutates eval.command in place.\n for (const t of generationTargets) {\n const refused = refusedBy.get(resultKey(t.plan.page.file, t.eval.name));\n if (!t.eval.command && refused !== undefined) {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: refused,\n durationMs: 0,\n });\n } else if (!t.eval.command && gen.unavailable !== undefined) {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: `${GENERATION_UNAVAILABLE}: ${gen.unavailable}`,\n durationMs: 0,\n });\n } else if (t.eval.command) {\n deterministicTargets.push(t);\n // Surfaced by the reporters as \"(generated)\" on this run's result.\n generatedThisRun.add(resultKey(t.plan.page.file, t.eval.name));\n } else {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: \"script generation failed\",\n generated: false,\n durationMs: 0,\n });\n }\n }\n } else {\n for (const t of generationTargets) {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: GENERATION_UNAVAILABLE,\n durationMs: 0,\n });\n }\n }\n }\n\n // Deterministic graders, grouped by kind.\n const byKind = new Map<string, GraderTarget[]>();\n for (const t of deterministicTargets) {\n const list = byKind.get(t.eval.grader) ?? [];\n list.push(t);\n byKind.set(t.eval.grader, list);\n }\n\n for (const [kind, targets] of byKind) {\n const grader = graderFor(kind);\n // `assertRegisteredGraders` already refused an unregistered kind. Kept so\n // that a gap between the two checks reads as an error, never a pass.\n if (!grader) {\n for (const t of targets) {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: `Unknown grader kind \"${kind}\"`,\n durationMs: 0,\n });\n }\n continue;\n }\n // One invocation per eval *configuration*, not one per grader kind — the\n // engine drives the same partition the batch adapters use internally, so\n // the try/catch below can only ever reach one eval's targets (ADR 01042).\n //\n // The bug this closes: batch graders loop `groupTargetsByEval` *inside*\n // `grade()`, so a throw on the second group unwound the whole function and\n // discarded the first group's already-computed findings. One broken eval\n // erased every sibling eval of the same kind, and every one of them\n // reported the broken eval's message.\n //\n // `groupTargetsByEval` is a pure partition and idempotent, so the adapters\n // keep calling it too: each stays correct when invoked directly, and the\n // isolation boundary is not something a new adapter has to remember.\n for (const group of groupTargetsByEval(targets)) {\n const start = Date.now();\n // A grader is effectively third-party code: tool adapters shell out, and\n // `runValidate` raises on a schema path it cannot read — which\n // `options.schemas` being hand-written makes the likeliest route in.\n // Letting that rejection escape drops every remaining eval on every\n // remaining page with no result and no exit-code signal that anything\n // was skipped. Error its own targets and carry on, the way a failed\n // script generation already does above.\n let findings: Finding[];\n try {\n findings = await grader.grade({ targets: group, config, root: cwd, exec });\n } catch (e) {\n const reason = errorMessage(e);\n for (const target of group) {\n results.push({\n evalName: target.eval.name,\n suite: target.eval.suite,\n type: target.eval.type,\n grader: target.eval.grader,\n file: target.plan.page.file,\n outcome: \"error\",\n // Names the eval, not just the kind. With one catch per kind the\n // message described whichever eval happened to throw while sitting\n // on every eval's result, so the name in the result and the name\n // in the message disagreed.\n skipReason: `grader ${kind} failed for eval \"${target.eval.name}\": ${reason}`,\n durationMs: Date.now() - start,\n });\n }\n continue;\n }\n const durationMs = Date.now() - start;\n const grouped = groupFindings(findings);\n for (const t of group) {\n const key = resultKey(t.plan.page.file, t.eval.name);\n const own = grouped.get(key) ?? [];\n // A diagnostic finding fails the eval regardless of severity: it means\n // the grader could not reach a verdict, and \"no verdict\" must never\n // read as \"pass\". Enforced here rather than per-adapter, so a new\n // adapter gets it by default instead of having to remember (ADR 01022).\n const hasError = own.some(\n (f) => f.severity === \"error\" || f.diagnostic === true,\n );\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: hasError ? \"fail\" : \"pass\",\n findings: own.length > 0 ? own : undefined,\n generated: generatedThisRun.has(key) ? true : undefined,\n durationMs: Math.round(durationMs / group.length),\n });\n }\n }\n }\n\n // failFast: a page with an error-severity deterministic failure skips its ai evals.\n let effectiveAiTargets = aiTargets;\n if (config.defaults.failFast) {\n const failedPages = new Set(\n results\n .filter((r) => r.outcome === \"fail\" || r.outcome === \"error\")\n .map((r) => r.file),\n );\n effectiveAiTargets = [];\n for (const t of aiTargets) {\n if (failedPages.has(t.plan.page.file)) {\n results.push(\n skippedResult(t.plan, t.eval, \"deterministic-precondition-failed\"),\n );\n } else {\n effectiveAiTargets.push(t);\n }\n }\n }\n\n // AI judge stage.\n if (effectiveAiTargets.length > 0 && options.judge) {\n results.push(\n ...(await options.judge(effectiveAiTargets, config, judgeOptions)),\n );\n }\n\n // A run that ran out of turns has *reduced coverage*, and skipped evals are\n // excluded from the suite pass rate below — so without this it exits 0\n // having judged less than it was asked to, which is the silent-green shape\n // this corpus gate exists to prevent. Warning, not error: the cap was asked\n // for, so tripping it is expected; going quiet about it is not (ADR 01019).\n const budgetSkipped = results.filter((r) => isTurnBudgetSkip(r.skipReason));\n const firstBudgetSkipped = budgetSkipped[0];\n if (firstBudgetSkipped !== undefined) {\n problems.push({\n file: firstBudgetSkipped.file,\n message:\n `${budgetSkipped.length} eval(s) were not judged: the turn budget ran out. ` +\n `This run covered less than it was asked to — raise --max-turns or narrow the run.`,\n level: \"warning\",\n });\n }\n\n // Nothing reached a verdict. Deliberately a warning and not an error:\n // `eval-skip` is a feature, `--deterministic-only` is a standing CI\n // invocation, and a scoped run over a clean tree is a correct answer\n // (ADR 01040). What was missing is anyone saying that the run therefore\n // established nothing — the same omission the turn-budget warning above\n // exists to fill (ADR 01019, ADR 01041).\n //\n // No exception for `--since`, which narrates its own empty scope a few lines\n // later in every reporter. Two lines, one explaining the other, is a better\n // trade than a carve-out: a carve-out is how this class of bug returns.\n //\n // `needs-review` is excluded on purpose: a human-graded eval is work the run\n // produced, not silence, and the reporters already point at `review`.\n //\n // Anchored on the config rather than a page: no single page is at fault, and\n // the config is the run-level file a reader can act on.\n if (!results.some((r) => r.outcome !== \"skipped\")) {\n problems.push({\n file: config.configPath,\n message:\n `This run graded nothing — no eval reached a verdict, so it established ` +\n `nothing about the corpus. ` +\n (results.length > 0\n ? `All ${results.length} resolved eval(s) were skipped; check the skip ` +\n `reasons above — a page-level \\`eval-skip\\`, a grader-class flag, or ` +\n `a missing provider.`\n : // With zero results the cause is not always the same, and naming the\n // wrong one sends the reader to the wrong file. An error-level\n // resolution problem makes the plan loop skip that page entirely and\n // also suppresses the empty-plan throw above, so \"skipped or scoped\n // out\" would contradict the errors printed right beside it.\n problems.some((p) => p.level === \"error\")\n ? `Every discovered page was dropped by an error-level resolution ` +\n `problem — fix those first; they are listed above.`\n : `Every discovered page was skipped or scoped out of the run.`),\n level: \"warning\",\n });\n }\n\n const baselineOutcome = resolveBaseline(results, config, options, cwd, problems);\n // Copy before clearing: when no baseline applies, `resolveBaseline` hands\n // back the very array it was given, and emptying it first would leave the\n // spread with nothing to read — a run reporting zero results, green.\n const baselinedResults = [...baselineOutcome.results];\n results.length = 0;\n results.push(...baselinedResults);\n\n stampSuites(results, plans);\n\n // Self-preference reaches the reporters as a problem, not just as a field on\n // the result: a run whose verdicts were formed by the model that wrote what\n // they grade should say so where anyone reads it. One per affected eval, in\n // the judge's own sentence, which is recomputed from the plan because the\n // result carries only the axis and the model.\n for (const r of results) {\n if (!r.selfPreference) continue;\n const plan = plans.find((p) => p.page.file === r.file);\n const ev = plan?.evals.find((e) => e.name === r.evalName);\n const finding =\n plan && ev ? selfPreferenceOf(plan, ev, r.selfPreference.model) : undefined;\n if (!finding) continue;\n problems.push({ file: r.file, level: \"warning\", message: finding.message });\n }\n\n // A scoped run measured part of the corpus, which is the same claim-from-a-\n // sample problem `--eval` has — so it reuses ADR 01018's mechanism rather\n // than growing a second, differently-behaved one.\n //\n // `partial` means coverage was actually lost, not that a narrowing flag was\n // present. Deriving it from the flag disabled suite-target enforcement on a\n // `--since` run that happened to touch every page — and since ADR 01040\n // intends `--since` as the CI invocation, that turned the aggregate gate off\n // permanently for anyone who adopted it. `pagesSelected` is already the exact\n // count, so the predicate is free.\n const scopeLostCoverage = scope !== null && scope.pagesSelected < plans.length;\n const suites = summarizeSuites(results, config, filtered || scopeLostCoverage);\n const judged = results.filter((r) => r.consensus != null);\n const totalTokens = judged.reduce(\n (n, r) =>\n n +\n (r.consensus?.runs.reduce(\n (m, run) =>\n m + (run.usage ? run.usage.inputTokens + run.usage.outputTokens : 0),\n 0,\n ) ?? 0),\n 0,\n );\n\n const hasFailure =\n results.some((r) => r.outcome === \"fail\" || r.outcome === \"error\") ||\n suites.some((s) => s.partial !== true && !s.meetsTarget) ||\n problems.some((p) => p.level === \"error\") ||\n (options.failOnReview === true &&\n results.some((r) => r.outcome === \"needs-review\"));\n\n return {\n pages: plans.length,\n evalResults: results,\n suites,\n usage: {\n totalTokens,\n cachedEvals: judged.filter(\n (r) => r.consensus?.runs.every((run) => run.cached) === true,\n ).length,\n judgedEvals: judged.length,\n },\n generated: generatedPaths,\n exitCode: hasFailure ? 1 : 0,\n problems,\n ...(baselineOutcome.summary ? { baseline: baselineOutcome.summary } : {}),\n ...(scope && sinceRef !== undefined ? { since: { ref: sinceRef, ...scope } } : {}),\n ...(scope && newerThan !== undefined\n ? { newerThan: { duration: newerThan, ...scope } }\n : {}),\n };\n}\n"],"mappings":"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","names":["resolve","resolve","resolve","resolve","Ajv2020","dirname","dirname","readFileSync","dirname","relative","resolve","dirname","resolve","relative","readFileSync","ajv","Ajv2020","readFileSync","dirname","relative","resolve","relative","resolve","readFileSync","dirname","resolve","resolve","statSync","relative","resolve","GIT_TIMEOUT_MS","git","resolve","statSync","relative","resolve","locationOf","passed"]}
1
+ {"version":3,"sources":["../src/docevals/core/config.ts","../src/docevals/core/config-schema.json","../src/docevals/core/split.ts","../src/docevals/core/discover.ts","../src/docevals/core/external.ts","../src/docevals/core/resolve.ts","../src/docevals/schema.ts","../src/docevals/graders/command.ts","../src/docevals/graders/options.ts","../src/docevals/core/target.ts","../src/docevals/graders/native/regex.ts","../src/docevals/graders/registry.ts","../src/docevals/core/feasibility.ts","../src/docevals/core/baseline.ts","../src/docevals/core/since.ts","../src/docevals/core/newer-than.ts","../src/docevals/graders/types.ts","../src/docevals/judge/cache.ts","../src/docevals/judge/prompt.ts","../src/docevals/judge/self-preference.ts","../src/docevals/core/engine.ts"],"sourcesContent":["/**\n * Loads and validates `manni.config.yaml`. The file is shared by the manni\n * family of documentation tools: manni docevals reads its own `docevals:`\n * namespace and leaves every sibling key alone. It carries provider and judge\n * settings plus the central library of named evals and suites that page\n * frontmatter references. Validation is JSON Schema (2020-12) via Ajv; defaults\n * are applied in code afterward so the resolved shape is fully typed.\n */\nimport { resolve, dirname } from \"node:path\";\nimport {\n findConfigFileSync,\n readConfigFileSync,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport { parseCollections, type CollectionConfig } from \"../../shared/collections.js\";\nimport { parse as parseYaml } from \"yaml\";\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport configSchema from \"./config-schema.json\" with { type: \"json\" };\nimport { DocevalsError, type EvalType, type Severity } from \"../types.js\";\n// Type-only, so the cycle with target.ts (which needs ResolvedPagePlan) is\n// erased at compile time rather than existing at runtime.\nimport type { EvalTarget } from \"./target.js\";\nimport { DEFAULT_CHUNK_CHARS } from \"./split.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport {\n PROVIDERS_KEY,\n assertKnownProvider,\n parseProviders,\n type ProvidersConfig,\n} from \"../../shared/providers.js\";\nimport type { ProviderSelector } from \"@hawkeyexl/inference\";\nimport {\n configuredGrants,\n EXECUTION_GRANTS,\n isExecutionGrant,\n unknownGrantsMessage,\n type ExecutionGrant,\n} from \"../../shared/execution.js\";\n\n/** A provider `docevals.provider` or `--provider` may name, `auto` included. */\nexport type ProviderName = ProviderSelector;\n\n/** One capability the operator can grant; the values are the family's. */\nexport type { ExecutionGrant } from \"../../shared/execution.js\";\n\n/**\n * One eval definition, as the rest of the codebase sees it.\n *\n * An eval entry spells these keys in kebab-case wherever it is written, in the\n * config's `evals:` and in page frontmatter alike, because that is the\n * vocabulary the metadata tool publishes and a field should mean one thing\n * wherever it is written. TypeScript keeps camelCase, because that is what\n * TypeScript reads like. `normalizeEvalDef` is the single boundary between\n * the two; nothing downstream should ever see a kebab key. The config's own\n * section keys (`judge.ensembleRuns`) are camelCase, as every manni tool's\n * are, and need no boundary.\n */\nexport interface EvalDef {\n assertion?: string;\n type?: EvalType;\n grader?: string;\n /** Provider or agent judging an `ai` eval; omit for the config default. */\n provider?: string;\n evidence?: string;\n /** Anchor examples. One or several each — a bare string normalizes to a list. */\n examples?: { pass?: string[]; fail?: string[] };\n command?: string[];\n successExitCodes?: number[];\n timeoutMs?: number;\n /** sha256 of the assertion when the check script was generated. */\n generatedAssertionHash?: string;\n options?: Record<string, unknown>;\n severity?: Severity;\n /** Relative contribution to the suite pass rate. Never changes the outcome. */\n weight?: number;\n /** Which bytes the grader receives. Defaults to the page body. */\n target?: EvalTarget;\n /** Judge model for this eval; a CLI --model still wins. */\n model?: string;\n /** Ensemble runs for this eval; a CLI --runs still wins. */\n runs?: number;\n}\n\n/** The file-side spelling of an eval definition. Kebab, exactly as authored. */\nexport interface RawEvalDef {\n assertion?: string;\n type?: EvalType;\n grader?: string;\n provider?: string;\n evidence?: string;\n examples?: { pass?: string | string[]; fail?: string | string[] };\n command?: string[];\n \"success-exit-codes\"?: number[];\n \"timeout-ms\"?: number;\n \"generated-assertion-hash\"?: string;\n options?: Record<string, unknown>;\n severity?: Severity;\n target?: EvalTarget;\n model?: string;\n runs?: number;\n // One word, so kebab and camel are the same string — it still passes through\n // normalizeEvalDef, because that is the only boundary between the two\n // spellings and a field that skips it is a field the next reader has to\n // check for.\n weight?: number;\n}\n\n/** One anchor example, or several, as a list. */\nfunction anchorList(v: string | string[] | undefined): string[] | undefined {\n if (v === undefined) return undefined;\n return Array.isArray(v) ? v : [v];\n}\n\n/**\n * Kebab file keys in, camelCase `EvalDef` out. Used for config-defined evals\n * and for page inline evals, so both reach the engine in one shape.\n */\nexport function normalizeEvalDef(raw: RawEvalDef): EvalDef {\n const examples =\n raw.examples === undefined\n ? undefined\n : {\n ...(anchorList(raw.examples.pass) !== undefined && {\n pass: anchorList(raw.examples.pass),\n }),\n ...(anchorList(raw.examples.fail) !== undefined && {\n fail: anchorList(raw.examples.fail),\n }),\n };\n return {\n assertion: raw.assertion,\n type: raw.type,\n grader: raw.grader,\n provider: raw.provider,\n evidence: raw.evidence,\n examples,\n command: raw.command,\n successExitCodes: raw[\"success-exit-codes\"],\n timeoutMs: raw[\"timeout-ms\"],\n generatedAssertionHash: raw[\"generated-assertion-hash\"],\n options: raw.options,\n severity: raw.severity,\n weight: raw.weight,\n target: raw.target,\n model: raw.model,\n runs: raw.runs,\n };\n}\n\nexport interface SuiteDef {\n targetPassRate: number;\n evals: string[];\n /** Criteria scored in this suite, alongside `evals`. */\n criteria: string[];\n}\n\n/**\n * Several evals scored as one unit.\n *\n * The grouping lives here rather than in page frontmatter because the page\n * vocabulary is the metadata tool's and this is our scoring model — a criterion is a\n * statement about how a corpus is graded, not a fact about a page.\n */\nexport interface CriterionDef {\n evals: string[];\n combine: \"all\" | \"any\";\n weight: number;\n}\n\nexport interface DocevalsConfig {\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 defaults: { suite: string | null; failFast: boolean; concurrency: number };\n /**\n * `docevals.provider`, or `null` when unset: the family's\n * `providers.provider` decides then, and `auto` (detect) after it.\n */\n provider: ProviderName | 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.\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 /** Findings baseline path, resolved against the config's directory (ADR 01017). */\n baseline: string | null;\n judge: {\n ensembleRuns: number;\n /** Judge-stage parallelism. Falls back to `defaults.concurrency` (ADR 01039). */\n concurrency: number;\n temperature: number;\n zones: { autoPass: number; autoFail: number };\n falsePositiveAlert: number;\n cacheDir: string;\n maxTurns: number | null;\n chunkChars: number;\n };\n scripts: {\n dir: string;\n configDir: string;\n timeoutMs: number;\n };\n /**\n * What content-authored code this run may execute. Every grant unless the\n * operator narrows it (proposal 0075); `[]` runs nothing.\n *\n * A page reaches a shell through a `command` eval declared in its\n * frontmatter, or through `options.command` argv it hands a grader.\n */\n execution: { allow: ExecutionGrant[] };\n fill: {\n confidenceThreshold: number;\n maxEvalsPerPage: number;\n temperature: number;\n cacheDir: string;\n maxTurns: number | null;\n chunkChars: number;\n };\n evals: Record<string, EvalDef>;\n criteria: Record<string, CriterionDef>;\n suites: Record<string, SuiteDef>;\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/** Top-level key manni docevals owns inside the shared manni config. */\nconst NAMESPACE = \"docevals\";\n\nexport const DEFAULT_CONFIG_FILENAME = \"manni.config.yaml\";\n\n/**\n * Root keys that only a pre-rename config has. A manni config namespaces every\n * tool, so finding these at the root means the file was never migrated.\n */\nconst PRE_RENAME_ROOT_KEYS = [\n \"version\",\n \"files\",\n \"defaults\",\n \"provider\",\n \"judge\",\n \"scripts\",\n \"fill\",\n \"evals\",\n \"suites\",\n];\n\n// `verbose` puts the parent schema on each error, so an unknown key can be\n// checked against the keys its section does have.\nconst ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true, verbose: true });\nconst validateConfig = ajv.compile(configSchema);\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\n * is what lets `parseConfig` read the file without an `any` — and an `any` here\n * would be the worst place for one, since every default in the tool flows\n * through this function.\n */\ninterface RawDocevalsConfig {\n defaults?: {\n suite?: string | null;\n failFast?: boolean;\n concurrency?: number;\n };\n provider?: string;\n model?: string;\n baseline?: string | null;\n judge?: {\n ensembleRuns?: number;\n concurrency?: number;\n temperature?: number;\n zones?: { autoPass?: number; autoFail?: number };\n falsePositiveAlert?: number;\n cacheDir?: string;\n maxTurns?: number | null;\n chunkChars?: number;\n };\n execution?: { allow?: ExecutionGrant[] };\n scripts?: {\n dir?: string;\n configDir?: string;\n timeoutMs?: number;\n };\n fill?: {\n confidenceThreshold?: number;\n maxEvalsPerPage?: number;\n temperature?: number;\n cacheDir?: string;\n maxTurns?: number | null;\n chunkChars?: number;\n };\n evals?: Record<string, RawEvalDef>;\n criteria?: Record<string, RawCriterionDef>;\n suites?: Record<string, RawSuiteDef>;\n}\n\ninterface RawCriterionDef {\n evals?: string[];\n combine?: \"all\" | \"any\";\n weight?: number;\n}\n\ninterface RawSuiteDef {\n \"target-pass-rate\"?: number;\n evals?: string[];\n criteria?: string[];\n}\n\n/** The 0.1 `generated: {assertionHash}` wrapper, as opposed to any other key of that name. */\nfunction isAssertionHashWrapper(value: unknown): boolean {\n return (\n value != null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n \"assertionHash\" in value\n );\n}\n\n/** Walk `node`, reporting every camelCase key with the kebab it should be. */\nfunction findPreKebabKeys(\n node: unknown,\n path: string,\n): { at: string; becomes: string }[] {\n if (node == null || typeof node !== \"object\" || Array.isArray(node)) return [];\n const found: { at: string; becomes: string }[] = [];\n for (const [key, value] of Object.entries(node as Record<string, unknown>)) {\n if (/[a-z0-9][A-Z]/.test(key)) {\n found.push({\n at: `${path}.${key}`,\n becomes: key.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase(),\n });\n }\n // `generated: {assertionHash}` flattened rather than renamed, so the\n // generic rule above would suggest the wrong thing for the wrapper itself.\n //\n // Matched on shape, not on the name alone: `options` is a grader’s open\n // runtime contract, so a key called `generated` there is legal config and\n // an error naming `generated-assertion-hash` would be advice nobody can\n // follow. Only the 0.1 wrapper — an object carrying `assertionHash` — is\n // the thing this rule is about.\n if (key === \"generated\" && isAssertionHashWrapper(value)) {\n found.push({ at: `${path}.generated`, becomes: \"generated-assertion-hash\" });\n continue;\n }\n found.push(...findPreKebabKeys(value, `${path}.${key}`));\n }\n return found;\n}\n\n/** The section keys whose entries are the frontmatter vocabulary's, in kebab-case. */\nconst ENTRY_SECTIONS = [\"evals\", \"criteria\", \"suites\"] as const;\n\n/**\n * `; did you mean \"failFast\"?` when `key` is the kebab spelling of a key its\n * section has. Only the exact counterpart: a guess at a near miss is advice\n * that can be wrong, and the kebab spelling is the one mistake a reader of\n * the frontmatter vocabulary is likely to make here.\n */\nfunction camelCaseHint(key: string, parentSchema: unknown): string {\n const camel = key.replace(/-([a-z0-9])/g, (_, c: string) => c.toUpperCase());\n if (camel === key || parentSchema === null || typeof parentSchema !== \"object\") return \"\";\n const properties = (parentSchema as { properties?: unknown }).properties;\n return properties !== null && typeof properties === \"object\" && Object.hasOwn(properties, camel)\n ? `; did you mean \"${camel}\"?`\n : \"\";\n}\n\n/**\n * The hint on an old `provider:` object. The key used to hold a `default` and\n * a section per provider; it is now the provider's name, as `fill.provider` is\n * in the metadata tool, and the connection settings moved to the family's\n * top-level `providers:` map, which every tool reads.\n * Ajv's own message names the key and says it must be a string, which is true\n * and leaves the reader to find out where the settings went.\n */\nfunction movedProviderHint(instancePath: string, keyword: string): string {\n return instancePath === `/${NAMESPACE}/provider` && keyword === \"type\"\n ? `; \"provider\" is now a provider name; per-provider settings moved to the top-level providers: map`\n : \"\";\n}\n\n/** Parse and validate config YAML text. `configPath` is used for messages and path resolution. */\nexport function parseConfig(text: string, configPath: string): DocevalsConfig {\n let raw: unknown;\n try {\n raw = parseYaml(text);\n } catch (e) {\n throw new DocevalsError(\n `Invalid YAML in ${configPath}: ${errorMessage(e)}`,\n );\n }\n if (raw == null || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new DocevalsError(`Invalid config in ${configPath}: root must be an object`);\n }\n const doc = raw as Record<string, unknown>;\n const wrapped = NAMESPACE in doc;\n const toError = (message: string): Error => new DocevalsError(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(doc[PROVIDERS_KEY], configPath, dirname(resolve(configPath)), toError)\n : {};\n return parseConfigSection(wrapped ? doc[NAMESPACE] : doc, configPath, wrapped, {\n source: configPath,\n collections,\n providers,\n });\n}\n\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 cite's and meta's `config.ts` carry, repeated because those\n * modules are theirs.\n */\nconst CONFIG_REF = \"https://hawkeyexl.github.io/manni/meta/reference/configuration/\";\n\n/**\n * The key proposal 0041 moved out of `docevals:` and up to the family level.\n * Refused rather than aliased, as meta and cite refuse theirs: an alias would\n * be a second place to declare a document set that is meant to be declared\n * once. Checked before Ajv, which would call it an unknown key.\n */\nconst MOVED_KEY = \"files\";\n\n/**\n * The key the family's top-level `providers:` map replaced. Refused rather\n * than aliased, for the reason `files` is: the settings are declared once, for\n * every tool, and a second place to declare them is a second answer to which\n * one wins. Checked before Ajv, which would call it an unknown key.\n */\nconst MOVED_PROVIDERS_KEY = \"providers\";\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 * Validate the tool's section. `value` is what sat under `docevals:` when\n * `wrapped`, and the whole document otherwise (a legacy file, or an explicit\n * path with no wrapper key). Messages name `configPath`; relative paths in\n * the config resolve against its directory. `file` carries the family keys;\n * absent, the section is its own source and declares no collections.\n */\nexport function parseConfigSection(\n value: unknown,\n configPath: string,\n wrapped: boolean,\n file: ConfigFileContext = { source: configPath, collections: [] },\n): DocevalsConfig {\n // The rest of this function reads `raw` as the document shape the checks\n // below were written against: a mapping with the section under NAMESPACE.\n // An empty `docevals:` is a section with nothing set, so every default\n // applies. It has no required key to write in it.\n const raw: Record<string, unknown> = wrapped\n ? { [NAMESPACE]: value ?? {} }\n : (value as Record<string, unknown> | null) ?? {};\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new DocevalsError(`Invalid config in ${configPath}: root must be an object`);\n }\n\n // `--config <path>` reaches here without passing loadConfig's filename check,\n // so a pre-rename file named anything at all would otherwise parse to pure\n // defaults — no evals, no suites, exit 0. Catch it by shape instead.\n if (!(NAMESPACE in raw)) {\n const stray = PRE_RENAME_ROOT_KEYS.filter((k) => k in raw);\n if (stray.length > 0) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: found ${stray.join(\", \")} at the root, ` +\n `but no \"${NAMESPACE}:\" key.\\n` +\n `manni.config.yaml is shared across the manni family, so every docevals ` +\n `setting belongs under a top-level \"${NAMESPACE}:\" key. Indent the file's ` +\n `contents one level and add that key.`,\n );\n }\n }\n const section = raw[NAMESPACE];\n if (\n section !== null &&\n typeof section === \"object\" &&\n !Array.isArray(section) &&\n Object.hasOwn(section, MOVED_KEY)\n ) {\n throw new DocevalsError(\n `${file.source}: \"${MOVED_KEY}\" is no longer a docevals key. Document sets are declared once for every tool, under a top-level collections: list. See ${CONFIG_REF}#collections`,\n );\n }\n if (\n section !== null &&\n typeof section === \"object\" &&\n !Array.isArray(section) &&\n Object.hasOwn(section, MOVED_PROVIDERS_KEY)\n ) {\n throw new DocevalsError(\n `${file.source}: \"${MOVED_PROVIDERS_KEY}\" is no longer a docevals key. Provider settings are declared once for every tool, under a top-level providers: map. See ${CONFIG_REF}#providers`,\n );\n }\n\n // Eval, criterion and suite entries are kebab-case, the spelling a page\n // uses for the same entries. Ajv would reject a camelCase spelling there as\n // \"must NOT have additional properties\", which names the parent object and\n // leaves the reader to guess which key. Name the key and its kebab spelling\n // instead. The section's own keys are camelCase and are not walked: a kebab\n // spelling of one is an unknown key, and the Ajv message below names the\n // camelCase key it meant.\n const preKebab = ENTRY_SECTIONS.flatMap((name) =>\n section !== null && typeof section === \"object\" && !Array.isArray(section)\n ? findPreKebabKeys((section as Record<string, unknown>)[name], `${NAMESPACE}.${name}`)\n : [],\n );\n if (preKebab.length > 0) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: camelCase keys are not read in eval, criterion or suite entries.\\n` +\n preKebab.map((p) => ` ${p.at} -> ${p.becomes}`).join(\"\\n\") +\n `\\nThose entries are kebab-case, matching the frontmatter vocabulary.`,\n );\n }\n\n // The removed key would otherwise surface as \"must NOT have additional\n // properties\" against `scripts`, which names the parent and leaves the\n // reader to find the child — the same failure the camelCase check above\n // exists to avoid.\n const ns = raw[NAMESPACE];\n const scriptsSection =\n ns && typeof ns === \"object\"\n ? (ns as Record<string, unknown>).scripts\n : undefined;\n if (\n scriptsSection &&\n typeof scriptsSection === \"object\" &&\n \"allow-frontmatter-commands\" in scriptsSection\n ) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: scripts.allow-frontmatter-commands has been replaced by ` +\n `execution.allow.\n` +\n ` Command evals run unless it narrows them; write ` +\n `\\`execution: { allow: [] }\\` to stop them.`,\n );\n }\n\n // Ajv's enum error names neither the value nor the ones allowed, and a\n // grant is the key where a silent misreading costs the most.\n const unknownGrants = configuredGrants(ns).filter((g) => !isExecutionGrant(g));\n if (unknownGrants.length > 0) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: ${unknownGrantsMessage(unknownGrants)}`,\n );\n }\n\n if (!validateConfig(raw)) {\n const details = (validateConfig.errors ?? [])\n .map((e) => {\n // Ajv reports an unknown key against the *parent* object, so the bare\n // message (\"must NOT have additional properties\") leaves the reader to\n // diff their file against the schema to find which key it meant. Name\n // it, for the same reason findPreKebabKeys above names a camelCase\n // spelling: the common case is a removed key in an unmigrated config\n // -- `judge.max-cost-usd` after ADR 01019, say -- and a migration\n // error that makes you guess is one people work around.\n const extra =\n e.keyword === \"additionalProperties\"\n ? (e.params as { additionalProperty?: string }).additionalProperty\n : undefined;\n if (extra !== undefined) {\n return ` ${e.instancePath || \"/\"}: unknown key \"${extra}\"${camelCaseHint(extra, e.parentSchema)}`;\n }\n return ` ${e.instancePath || \"/\"}: ${e.message ?? \"is invalid\"}${movedProviderHint(e.instancePath, e.keyword)}`;\n })\n .join(\"\\n\");\n throw new DocevalsError(`Invalid config in ${configPath}:\\n${details}`);\n }\n\n // Sibling tools own the other root keys; this reads only its own namespace.\n // A file that configures no docevals at all leaves every default in place.\n const r = (raw[NAMESPACE] ??\n {}) as RawDocevalsConfig;\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 ones that reach 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 = r.provider ?? null;\n if (provider !== null) assertKnownProvider(provider, (message) => new DocevalsError(message));\n\n const suites: Record<string, SuiteDef> = {};\n for (const [name, def] of Object.entries(r.suites ?? {})) {\n suites[name] = {\n targetPassRate: def[\"target-pass-rate\"] ?? 1.0,\n evals: def.evals ?? [],\n criteria: def.criteria ?? [],\n };\n }\n\n const criteria: Record<string, CriterionDef> = {};\n for (const [name, def] of Object.entries(r.criteria ?? {})) {\n criteria[name] = {\n evals: def.evals ?? [],\n combine: def.combine ?? \"all\",\n weight: def.weight ?? 1,\n };\n }\n\n const config: DocevalsConfig = {\n collections: file.collections,\n configSource: file.source,\n defaults: {\n suite: r.defaults?.suite ?? null,\n failFast: r.defaults?.failFast ?? false,\n concurrency: r.defaults?.concurrency ?? 4,\n },\n provider,\n model: r.model ?? null,\n providers: file.providers ?? {},\n baseline: r.baseline ?? null,\n judge: {\n ensembleRuns: r.judge?.ensembleRuns ?? 3,\n // Falls back to the corpus-wide setting, so an unset value behaves\n // exactly as it did before this knob existed. It is separable because\n // the judge's right parallelism is not the deterministic graders': a\n // local in-process model serves one context at a time (ADR 01039).\n concurrency: r.judge?.concurrency ?? r.defaults?.concurrency ?? 4,\n temperature: r.judge?.temperature ?? 0,\n zones: {\n autoPass: r.judge?.zones?.autoPass ?? 0.8,\n autoFail: r.judge?.zones?.autoFail ?? 0.8,\n },\n falsePositiveAlert: r.judge?.falsePositiveAlert ?? 0.15,\n cacheDir: r.judge?.cacheDir ?? \".manni/docevals/cache\",\n maxTurns: r.judge?.maxTurns ?? null,\n chunkChars: r.judge?.chunkChars ?? DEFAULT_CHUNK_CHARS,\n },\n scripts: {\n dir: r.scripts?.dir ?? \"{docDir}/manni-docevals\",\n configDir: r.scripts?.configDir ?? \"manni-docevals-scripts\",\n timeoutMs: r.scripts?.timeoutMs ?? 30000,\n },\n execution: { allow: [...(r.execution?.allow ?? EXECUTION_GRANTS)] },\n fill: {\n confidenceThreshold: r.fill?.confidenceThreshold ?? 0.7,\n maxEvalsPerPage: r.fill?.maxEvalsPerPage ?? 3,\n temperature: r.fill?.temperature ?? 0,\n cacheDir: r.fill?.cacheDir ?? \".manni/docevals/cache/fill\",\n maxTurns: r.fill?.maxTurns ?? null,\n chunkChars: r.fill?.chunkChars ?? DEFAULT_CHUNK_CHARS,\n },\n evals: Object.fromEntries(\n Object.entries(r.evals ?? {}).map(([name, def]) => [\n name,\n normalizeEvalDef(def),\n ]),\n ),\n criteria,\n suites,\n configPath: abs,\n configDir: dir,\n };\n\n // Referential integrity: suites may only reference defined evals.\n for (const [suiteName, suite] of Object.entries(config.suites)) {\n for (const evalName of suite.evals) {\n if (!(evalName in config.evals)) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: suite \"${suiteName}\" references undefined eval \"${evalName}\"`,\n );\n }\n }\n }\n for (const [critName, crit] of Object.entries(config.criteria)) {\n for (const evalName of crit.evals) {\n if (!(evalName in config.evals)) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: criterion \"${critName}\" references undefined eval \"${evalName}\"`,\n );\n }\n }\n }\n for (const [suiteName, suite] of Object.entries(config.suites)) {\n for (const critName of suite.criteria) {\n if (!(critName in config.criteria)) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: suite \"${suiteName}\" references undefined criterion \"${critName}\"`,\n );\n }\n }\n }\n if (config.defaults.suite && !(config.defaults.suite in config.suites)) {\n throw new DocevalsError(\n `Invalid config in ${configPath}: defaults.suite \"${config.defaults.suite}\" is not a defined suite`,\n );\n }\n return config;\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`: the family file,\n * read at its `docevals:` key). With no config file present, built-in\n * defaults apply (no named evals or suites).\n */\nexport function loadConfig(path?: string, cwd = process.cwd()): DocevalsConfig {\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, file.wrapped, {\n source: file.source,\n collections: file.collections,\n providers: file.providers ?? {},\n });\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()): DocevalsConfig {\n return {\n ...parseConfigSection(null, resolve(cwd, DEFAULT_CONFIG_FILENAME), false),\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. The missing-config refusal is\n * `discoverPages`', which every command reaches next.\n */\nexport function loadRunConfig(opts: RunConfigOptions, cwd = process.cwd()): DocevalsConfig {\n assertCollectionWithoutPaths(opts.collection, opts.paths);\n return opts.noConfig ? defaultConfig(cwd) : loadConfig(opts.configPath, cwd);\n}\n\n/** The message meta and cite give, in docevals' 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 DocevalsError(\n \"--collection selects a configured collection; it cannot be combined with paths.\",\n );\n }\n}\n\nconst CONFIG_FILE: ConfigFileOptions = {\n section: NAMESPACE,\n // docevals never shipped a file of its own under manni, so, like cite and\n // a11y, it has no pre-family name to read.\n legacyNames: [],\n toError: (message) => new DocevalsError(message),\n};\n\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"manni:config:docevals\",\n \"title\": \"manni docevals configuration\",\n \"description\": \"The docevals: section of manni.config.yaml. Every manni tool reads its own top-level key; keys that belong to sibling tools are ignored here. Section keys are camelCase, as every manni tool's are. The entries under evals, criteria and suites keep the kebab-case spelling of the frontmatter vocabulary, because they are the same entries a page carries.\",\n \"type\": \"object\",\n \"properties\": {\n \"docevals\": {\n \"$ref\": \"#/$defs/docevalsConfig\"\n }\n },\n \"additionalProperties\": true,\n \"$defs\": {\n \"docevalsConfig\": {\n \"type\": \"object\",\n \"properties\": {\n \"baseline\": {\n \"type\": [\n \"string\",\n \"null\"\n ],\n \"description\": \"Path to the findings baseline, relative to this config file. A baseline records today's findings so a run fails only on new ones (ADR 01017). Null (the default) means no baseline. `--baseline`/`--no-baseline` override this; a bare `--write-baseline` records into *this* path, so a repo that points it somewhere custom cannot accidentally record into a file nothing reads.\"\n },\n \"defaults\": {\n \"type\": \"object\",\n \"properties\": {\n \"suite\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"failFast\": {\n \"type\": \"boolean\"\n },\n \"concurrency\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"additionalProperties\": false\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Which provider judges, generates, fills and promotes: 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 an ai eval's own provider wins over it for that eval. 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 provider from --provider, an eval or providers.provider that differs from this one 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.\"\n },\n \"judge\": {\n \"type\": \"object\",\n \"properties\": {\n \"ensembleRuns\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"concurrency\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"temperature\": {\n \"type\": \"number\",\n \"minimum\": 0\n },\n \"zones\": {\n \"type\": \"object\",\n \"properties\": {\n \"autoPass\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"autoFail\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n }\n },\n \"additionalProperties\": false\n },\n \"falsePositiveAlert\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"cacheDir\": {\n \"type\": \"string\"\n },\n \"maxTurns\": {\n \"$ref\": \"#/$defs/maxTurns\"\n },\n \"chunkChars\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"default\": 12000,\n \"description\": \"Characters of page content per judge call. A page longer than this is graded by gathering evidence from each part and judging the collected evidence once.\"\n }\n },\n \"additionalProperties\": false\n },\n \"scripts\": {\n \"type\": \"object\",\n \"properties\": {\n \"dir\": {\n \"type\": \"string\"\n },\n \"configDir\": {\n \"type\": \"string\"\n },\n \"timeoutMs\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"additionalProperties\": false\n },\n \"execution\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"allow\": {\n \"type\": \"array\",\n \"items\": {\n \"enum\": [\n \"frontmatter-commands\"\n ]\n },\n \"default\": [\"frontmatter-commands\"],\n \"description\": \"Which content-authored code this corpus may execute. Absent, every grant holds; list fewer to narrow it, or write [] to run none. frontmatter-commands lets `command` evals declared in page frontmatter run. That is code a page author controls, so a run over an untrusted pull request passes --no-execution.\"\n }\n },\n \"description\": \"Operator grant for executing content-authored code.\"\n },\n \"fill\": {\n \"type\": \"object\",\n \"properties\": {\n \"confidenceThreshold\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"maxEvalsPerPage\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"temperature\": {\n \"type\": \"number\",\n \"minimum\": 0\n },\n \"cacheDir\": {\n \"type\": \"string\"\n },\n \"maxTurns\": {\n \"$ref\": \"#/$defs/maxTurns\"\n },\n \"chunkChars\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"default\": 12000,\n \"description\": \"Characters of page content per fill call. A longer page is proposed against in parts and the proposals merged by id, keeping the highest confidence.\"\n }\n },\n \"additionalProperties\": false\n },\n \"evals\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/evalDef\"\n },\n \"description\": \"The central library of named evals. The map key is the eval's id — the same id a page's `use:` reference names.\"\n },\n \"criteria\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/criterionDef\"\n },\n \"description\": \"Named groups of evals scored as one unit. A criterion contributes a single weighted outcome to its suite and its members contribute none, so writing three checks as a group does not let them outvote three standalone evals.\"\n },\n \"suites\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/suiteDef\"\n }\n }\n },\n \"additionalProperties\": false\n },\n \"maxTurns\": {\n \"type\": [\n \"integer\",\n \"null\"\n ],\n \"minimum\": 1,\n \"description\": \"Stop after this many turns. Counts work, not pages. Under `judge` a turn is one ensemble run, so a judged eval spends `judge.ensembleRuns` of them; a run may make a second provider call when the first response fails schema validation, so this is a floor on calls rather than an exact count. Under `fill` a turn is exactly one call. A cached result spends none. Null (the default) is unbounded. Replaces the `max-cost-usd` ceiling, which could not be honored exactly under concurrency — see ADR 01019.\"\n },\n \"evalDef\": {\n \"type\": \"object\",\n \"properties\": {\n \"assertion\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"type\": {\n \"enum\": [\n \"capability\",\n \"regression\"\n ]\n },\n \"grader\": {\n \"type\": \"string\",\n \"pattern\": \"^(ai|command|human|tool:[a-z0-9][a-z0-9-]*)$\"\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"model\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Model judging this ai eval, within provider. A CLI --model still wins over it. Meaningful only on ai evals.\"\n },\n \"runs\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 50,\n \"description\": \"Ensemble runs for this eval, overriding judge.ensembleRuns. A CLI --runs still wins over it. Capped because it multiplies judge cost directly. Meaningful only on ai evals.\"\n },\n \"evidence\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"target\": {\n \"oneOf\": [\n {\n \"enum\": [\n \"body\",\n \"raw\",\n \"frontmatter\"\n ]\n },\n {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"source\",\n \"path\"\n ],\n \"properties\": {\n \"source\": {\n \"const\": \"file\"\n },\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n }\n ],\n \"default\": \"body\",\n \"description\": \"Which bytes the grader receives: the page body with frontmatter stripped (body), the file verbatim (raw), the parsed frontmatter alone (frontmatter), or a companion file beside the page. Distinct from evidence, which hints where to look within what is graded.\"\n },\n \"examples\": {\n \"type\": \"object\",\n \"properties\": {\n \"pass\": {\n \"$ref\": \"#/$defs/anchorList\"\n },\n \"fail\": {\n \"$ref\": \"#/$defs/anchorList\"\n }\n },\n \"additionalProperties\": false\n },\n \"command\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"minItems\": 1\n },\n \"success-exit-codes\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\"\n }\n },\n \"timeout-ms\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"generated-assertion-hash\": {\n \"type\": \"string\"\n },\n \"options\": {\n \"type\": \"object\"\n },\n \"severity\": {\n \"enum\": [\n \"notice\",\n \"warning\",\n \"error\"\n ]\n },\n \"weight\": {\n \"type\": \"number\",\n \"exclusiveMinimum\": 0,\n \"default\": 1,\n \"description\": \"Relative contribution to its suite's pass rate. Does not change this eval's own pass/fail: the eval still passes or fails on its own terms, and weight only decides how much that outcome moves the suite total against target-pass-rate. Zero is excluded deliberately - a weightless eval is a silent disable, and skip already means that, loudly.\"\n }\n },\n \"additionalProperties\": false,\n \"dependentRequired\": {\n \"generated-assertion-hash\": [\n \"command\"\n ]\n },\n \"allOf\": [\n {\n \"if\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"ai\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n },\n \"then\": {\n \"required\": [\n \"assertion\"\n ]\n }\n },\n {\n \"if\": {\n \"not\": {\n \"required\": [\n \"grader\"\n ]\n }\n },\n \"then\": {\n \"required\": [\n \"assertion\"\n ]\n }\n },\n {\n \"if\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"command\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n },\n \"then\": {\n \"anyOf\": [\n {\n \"required\": [\n \"assertion\"\n ]\n },\n {\n \"required\": [\n \"command\"\n ]\n }\n ]\n }\n },\n {\n \"if\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"human\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n },\n \"then\": {\n \"required\": [\n \"assertion\"\n ]\n }\n },\n {\n \"if\": {\n \"required\": [\n \"command\"\n ]\n },\n \"then\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"command\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n }\n },\n {\n \"if\": {\n \"anyOf\": [\n {\n \"required\": [\n \"success-exit-codes\"\n ]\n },\n {\n \"required\": [\n \"timeout-ms\"\n ]\n }\n ]\n },\n \"then\": {\n \"properties\": {\n \"grader\": {\n \"const\": \"command\"\n }\n },\n \"required\": [\n \"grader\"\n ]\n }\n }\n ]\n },\n \"anchorList\": {\n \"if\": {\n \"type\": \"array\"\n },\n \"then\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"else\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"suiteDef\": {\n \"type\": \"object\",\n \"properties\": {\n \"target-pass-rate\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"evals\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"criteria\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"description\": \"Criteria scored in this suite, alongside `evals`.\"\n }\n },\n \"additionalProperties\": false\n },\n \"criterionDef\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"evals\"\n ],\n \"properties\": {\n \"evals\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\"\n },\n \"description\": \"Ids of the evals this criterion is made of.\"\n },\n \"combine\": {\n \"enum\": [\n \"all\",\n \"any\"\n ],\n \"default\": \"all\",\n \"description\": \"all: every member must pass. any: one passing member is enough.\"\n },\n \"weight\": {\n \"type\": \"number\",\n \"exclusiveMinimum\": 0,\n \"default\": 1,\n \"description\": \"The criterion's contribution to its suite's pass rate.\"\n }\n }\n }\n }\n}\n","/**\n * Splitting long content for inference, instead of truncating it.\n *\n * Three code paths used to `slice(0, 6000)` and append \"…(truncated)\": `fill`,\n * `scriptgen`, and nothing at all in the judge, which sent whole pages. A page\n * over the cap was therefore filled and script-generated from its first half,\n * silently — the model never saw the rest and had no way to say so.\n *\n * Ported from the metadata tool's `fill`, which solved this first (`splitBody` /\n * `mergeProposals`). The contract, in full:\n *\n * - chunks are greedy and cut at the last newline before the boundary, so a\n * line is never split mid-sentence;\n * - there is no overlap — a merge step, not redundancy, is what stops a\n * boundary from losing something;\n * - content that fits comes back as a single chunk, so the common path is\n * byte-identical to not splitting at all;\n * - a model complaining about context length halves the budget and retries\n * once, because the right chunk size depends on the model, not on us.\n *\n * The chunk budget belongs in every cache key that covers chunked output.\n * The metadata tool documents why at its own call site: halve-and-retry makes two runs\n * at different budgets produce genuinely different results, and without the\n * budget in the key the second silently replays the first.\n */\n\n/** Characters of content per inference call. Matches the metadata tool's default. */\nexport const DEFAULT_CHUNK_CHARS = 12000;\n\n/**\n * Split `body` into chunks of at most `chunkChars`, cutting at line\n * boundaries. Returns `[body]` unchanged when it already fits.\n */\nexport function splitBody(body: string, chunkChars: number): string[] {\n if (body.length <= chunkChars) return [body];\n const chunks: string[] = [];\n let at = 0;\n while (at < body.length) {\n const end = Math.min(at + chunkChars, body.length);\n let cut = end;\n if (end < body.length) {\n const nl = body.lastIndexOf(\"\\n\", end - 1);\n if (nl > at) cut = nl + 1;\n }\n chunks.push(body.slice(at, cut));\n at = cut;\n }\n return chunks;\n}\n\n/**\n * Whether a provider error reads as \"that was too much context\".\n *\n * Deliberately a message match: providers do not agree on a code for this, and\n * the cost of a false positive is one retry at half the budget.\n */\nexport function looksLikeOverflow(message: string): boolean {\n return /context|too long|too large|token limit|maximum.*tokens|exceeds/i.test(\n message,\n );\n}\n\n/** How a part is announced to the model, when there is more than one. */\nexport function partLabel(index: number, total: number): string {\n return `part ${String(index + 1)} of ${String(total)}`;\n}\n","/**\n * Page discovery: resolve the run's document set (positional paths, or the\n * family `collections:`), read each file, and extract frontmatter using\n * the metadata tool's shared extractor (identical fence handling and JSON-Pointer ->\n * line maps as `manni meta validate`).\n */\nimport { readFileSync, statSync } from \"node:fs\";\nimport { resolve, relative, extname } from \"node:path\";\nimport fg from \"fast-glob\";\nimport { extractFrontmatter, type ExtractedMetadata } from \"../../meta/index.js\";\nimport { selectCollections } from \"../../shared/collections.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { DocevalsError } from \"../types.js\";\nimport type { PageExternal } from \"./external.js\";\nimport {\n assertCollectionWithoutPaths,\n DEFAULT_CONFIG_FILENAME,\n type DocevalsConfig,\n type RunConfigOptions,\n} from \"./config.js\";\n\nexport interface PageFile {\n /** Path relative to the discovery root, forward slashes. */\n file: string;\n absPath: string;\n /** Full file content. */\n content: string;\n /** Content with the leading frontmatter block removed (judge input). */\n body: string;\n /**\n * The page's metadata, with every key an owning manifest supplies already\n * merged in (`core/external.ts`). Identical to the frontmatter block when no\n * collection of this page's declares a manifest, which is the common case.\n */\n frontmatter: ExtractedMetadata;\n /**\n * Where a merged value lives, when a manifest supplied it. Absent when the\n * run read no manifest, and its `locate` answers `undefined` for every key\n * the page itself carries.\n */\n external?: PageExternal;\n /** Set when frontmatter extraction failed; the page is reported as errored. */\n extractError?: string;\n}\n\nexport type FrontmatterFormat = \"yaml\" | \"toml\" | \"json\";\n\nconst FENCES: {\n format: FrontmatterFormat;\n open: RegExp;\n isClose: (l: string) => boolean;\n}[] = [\n { format: \"yaml\", open: /^---\\r?\\n/, isClose: (l) => l === \"---\" || l === \"...\" },\n { format: \"toml\", open: /^\\+\\+\\+\\r?\\n/, isClose: (l) => l === \"+++\" },\n { format: \"json\", open: /^;;;\\r?\\n/, isClose: (l) => l === \";;;\" },\n];\n\n/** The frontmatter format a page opens with, or undefined if it has none. */\nexport function leadingFrontmatterFormat(\n content: string,\n): FrontmatterFormat | undefined {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n return FENCES.find((f) => f.open.test(body))?.format;\n}\n\n/**\n * Remove a leading fenced frontmatter block, mirroring the metadata tool's fence rules.\n *\n * The body is sliced out of the page rather than rebuilt from its lines, so it\n * keeps the page's own line endings. `target: raw` reads the file as written,\n * and `target: body` has to read the same bytes past the fence; a CRLF page\n * whose body came back LF would show a regex eval two different pages.\n */\nexport function stripFrontmatterBlock(content: string): string {\n const body =\n content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n const fence = FENCES.find((f) => f.open.test(body));\n if (!fence) return body;\n // Split after each newline, so every line keeps its own ending. The fence\n // test above guarantees an opening line.\n const [openLine = \"\", ...rest] = body.split(/(?<=\\n)/);\n let offset = openLine.length;\n for (const line of rest) {\n offset += line.length;\n if (fence.isClose(line.replace(/\\r?\\n$/, \"\"))) return body.slice(offset);\n }\n return body;\n}\n\nfunction formatForExtension(ext: string): string {\n switch (ext.toLowerCase()) {\n case \".md\":\n case \".markdown\":\n return \"markdown\";\n case \".mdx\":\n return \"mdx\";\n default:\n return \"markdown\";\n }\n}\n\n/** Read and extract a single page. Extraction errors are captured, not thrown. */\nexport function readPage(absPath: string, root: string): PageFile {\n const content = readFileSync(absPath, \"utf8\");\n const file = relative(root, absPath).replace(/\\\\/g, \"/\");\n const format = formatForExtension(extname(absPath));\n try {\n const frontmatter = extractFrontmatter(content, format);\n return {\n file,\n absPath,\n content,\n body: stripFrontmatterBlock(content),\n frontmatter,\n };\n } catch (e) {\n return {\n file,\n absPath,\n content,\n body: stripFrontmatterBlock(content),\n frontmatter: {\n data: {},\n present: false,\n format,\n lineFor: () => undefined,\n },\n extractError: errorMessage(e),\n };\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 and cite's source index ignore; it replaced\n * docevals' own `files.exclude` default (proposal 0041).\n */\nconst FAMILY_EXCLUDE = [\"**/node_modules/**\", \"**/.git/**\"];\n\n/** The word the empty-input message uses for what the command would do. */\nexport type DocumentVerb = \"evaluate\" | \"list\" | \"fill\" | \"read\";\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 /** Defaults to `evaluate`. */\n verb?: DocumentVerb;\n}\n\n/**\n * The document-set options every command that reads pages takes beside its\n * positional paths: `-c`, `--no-config`, `--collection` and `--exclude`.\n */\nexport interface DocumentInputOptions\n extends Pick<DocumentSetOptions, \"collection\" | \"exclude\"> {\n /** `-c/--config`. */\n config?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n}\n\n/** A command's inputs as `loadRunConfig` reads them. */\nexport function runConfigOptions(\n paths: string[],\n options: DocumentInputOptions,\n): RunConfigOptions {\n return {\n paths,\n ...(options.config === undefined ? {} : { configPath: options.config }),\n ...(options.noConfig === undefined ? {} : { noConfig: options.noConfig }),\n ...(options.collection === undefined ? {} : { collection: options.collection }),\n };\n}\n\n/** A command's inputs as `discoverPages` reads them. */\nexport function documentSet(\n paths: string[],\n options: DocumentInputOptions,\n verb: DocumentVerb,\n): DocumentSetOptions {\n return {\n paths,\n verb,\n ...(options.collection === undefined ? {} : { collection: options.collection }),\n ...(options.exclude === undefined ? {} : { exclude: options.exclude }),\n };\n}\n\n/**\n * One input as fast-glob patterns: a glob as written, an existing file as its\n * escaped literal, and an existing directory as everything beneath it. Only\n * the glob is left for fast-glob to interpret, so a literal path with `(` or\n * `[` in its name still means itself.\n */\nfunction toPatterns(input: string, base: string): string[] {\n if (fg.isDynamicPattern(input)) return [input.replace(/\\\\/g, \"/\")];\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 empty-match\n // error below names it.\n return [input.replace(/\\\\/g, \"/\")];\n }\n const literal = fg.convertPathToPattern(input);\n return [isDirectory ? `${literal.replace(/\\/$/, \"\")}/**/*` : literal];\n}\n\n/** Every supported page `patterns` match beneath `base`, as absolute paths. */\nfunction glob(patterns: string[], base: string, ignore: string[]): string[] {\n return fg.sync(patterns.flatMap((p) => toPatterns(p, base)), {\n cwd: base,\n ignore,\n absolute: true,\n dot: false,\n onlyFiles: true,\n });\n}\n\nconst SUPPORTED_EXTENSIONS = new Set([\".md\", \".markdown\", \".mdx\"]);\n\n/**\n * Discover pages (proposal 0041). Positional `paths` are what the operator\n * typed, resolved from `root` (the working directory). Without them the run\n * reads the selected collections, each collection's `paths:` resolved from the\n * config file's directory and narrowed by its own `exclude:`. The family-wide\n * exclusions and `--exclude` apply to both. Page labels stay relative to\n * `root` either way.\n */\nexport function discoverPages(\n config: DocevalsConfig,\n options: DocumentSetOptions = {},\n root = process.cwd(),\n): PageFile[] {\n const paths = options.paths ?? [];\n const wanted = options.collection ?? [];\n assertCollectionWithoutPaths(wanted, paths);\n if (wanted.length > 0 && config.configSource === null) {\n throw new DocevalsError(\"--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 DocevalsError(message),\n );\n\n const exclude = [...FAMILY_EXCLUDE, ...(options.exclude ?? [])];\n let entries: string[];\n let patterns: string[];\n if (paths.length > 0) {\n patterns = paths;\n entries = glob(paths, root, exclude);\n } else {\n // A collection's `exclude:` shapes that collection only, so each is walked\n // with its own and the results are joined: a file excluded from one\n // collection is still read when another collection holds it.\n patterns = collections.flatMap((c) => c.paths);\n if (patterns.length === 0) {\n throw new DocevalsError(\n `No files to ${options.verb ?? \"evaluate\"}. Pass paths/globs, or declare a collection under \\`collections:\\` in manni.config.yaml.`,\n );\n }\n entries = collections.flatMap((c) =>\n glob(c.paths, config.configDir, [...exclude, ...c.exclude]),\n );\n }\n\n const files = [\n ...new Set(entries.filter((p) => SUPPORTED_EXTENSIONS.has(extname(p).toLowerCase()))),\n ];\n if (files.length === 0) {\n throw new DocevalsError(\n `No documentation pages found (patterns: ${patterns.join(\", \")})`,\n );\n }\n return files.sort().map((p) => readPage(resolve(p), root));\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 * (proposal 0041).\n *\n * The evals vocabulary marks `evals`, `eval-suite` and `eval-skip`\n * `x-manni-location: external` in `manni:evals:1.0.0`, and ai-context marks\n * `provenance` and `meta-provenance`. A corpus that took `manni meta\n * relocate` up on that keeps those values in a manifest, and a tool that read\n * frontmatter alone would report every page as declaring nothing.\n *\n * Reading is meta's merge, not a second loader, exactly as `cite`'s sidecars\n * are. `loadExternalMetadata` reads each manifest once per run, behind the\n * shared per-process parse cache, and `mergeExternalMetadata` decides per page\n * what a manifest supplies. So the join rules, the ownership rules and the\n * per-item lines are the ones `meta validate` already applies, and the merged\n * result is handed back as the page's own `frontmatter`: every reader\n * downstream — resolution, the self-preference check, `target: frontmatter` —\n * sees the values where their location puts them, without knowing a manifest\n * exists.\n *\n * Two things are docevals' own, because docevals *writes* eval keys where\n * meta only reads them:\n *\n * - **Membership is decided by every declared collection**, not by the ones\n * `--collection` or the positional paths selected. A page named by path is\n * still a member of the collection that contains it, and its evals are\n * still in that collection's manifest.\n * - **A URL manifest may not own an eval key** (exit 2), and neither may two\n * of one page's collections. Both are refusals rather than tiebreaks, for\n * the reason 0020 gives: there is no right answer to pick.\n *\n * `--no-config` never reaches here: with no config there are no collections,\n * so a page's evals are its frontmatter's.\n */\nimport { resolve } from \"node:path\";\nimport { ownsKey } from \"../../shared/collections.js\";\nimport { familyMarks, mergeWithMarks, type PageMarks } from \"../../meta/internal.js\";\nimport {\n classifyRef,\n loadExternalMetadata,\n memberOf,\n type CollectionConfig,\n type ExternalMetadataCollision,\n type ExternalMetadataConfig,\n type ExternalMetadataIndex,\n type SourceLocation,\n} from \"../../meta/index.js\";\nimport { DocevalsError } from \"../types.js\";\nimport type { DocevalsConfig } from \"./config.js\";\nimport type { PageFile } from \"./discover.js\";\n\n/**\n * The three page keys the evals vocabulary claims, and the only ones these\n * refusals govern. A manifest owning `provenance` is nobody's problem here:\n * docevals reads it and never writes it.\n */\nexport const EVAL_KEYS = [\"evals\", \"eval-suite\", \"eval-skip\"] as const;\n\n/**\n * Every key docevals reads that a manifest may own, and so the only manifests\n * this tool loads: the evals vocabulary's three and ai-context's machine\n * attribution (proposal 0046).\n *\n * A manifest owning none of them is a sibling tool's business. Loading it\n * anyway would make a corpus fail on a manifest docevals has no use for, and\n * would fetch a URL manifest on every run to read nothing out of it. `cite`\n * scopes its own load the same way, to its one key.\n */\nexport const EXTERNAL_KEYS: readonly string[] = [\n ...EVAL_KEYS,\n \"provenance\",\n \"meta-provenance\",\n];\n\n/** Where a value a manifest supplied lives, and what the page duplicates. */\nexport interface PageExternal {\n /**\n * The manifest file and line behind a merged JSON Pointer, or `undefined`\n * for everything the page itself carries — which is what `lineFor` answers.\n */\n locate: (pointer: string) => SourceLocation | undefined;\n /** Eval keys the page carries that an owning manifest also holds. */\n collisions: readonly ExternalMetadataCollision[];\n /**\n * Every manifest file that supplied one of the page's eval keys, as an\n * absolute path. A change to any of them changes what the page is graded\n * on, so `--since` selects the page when one changed. A URL manifest never\n * appears: it may not own an eval key.\n */\n evalManifests: readonly string[];\n}\n\n/** `manni.config.yaml: collection site: evals cannot come from a URL manifest, because docevals writes them.` */\nexport function urlManifestRefusal(\n source: string,\n collection: string,\n key: string,\n): string {\n return `${source}: collection ${collection}: ${key} cannot come from a URL manifest, because docevals writes them.`;\n}\n\n/** `docs/install.md is in collections site and guides, and both keep evals in a manifest.` */\nexport function twoManifestsRefusal(\n label: string,\n a: string,\n b: string,\n key: string,\n): string {\n return `${label} is in collections ${a} and ${b}, and both keep ${key} in a manifest.`;\n}\n\n/**\n * What the vocabularies docevals reads mark `x-manni-location: external`:\n * every key in `EXTERNAL_KEYS`. A manifest with no `keys` (proposal 0068)\n * may own these, less the ones a sibling manifest of its collection names,\n * which is what decides the manifests a run loads and the refusals. The merge\n * itself reads each page's own marks, as meta's does.\n */\nconst MARKED: ReadonlySet<string> = new Set(EXTERNAL_KEYS);\n\n/** Whether one manifest declaration of `collection` owns `key`. */\nfunction owns(\n collection: Pick<CollectionConfig, \"externalMetadata\">,\n manifest: ExternalMetadataConfig,\n key: string,\n): boolean {\n return ownsKey(collection, manifest, key, MARKED);\n}\n\n/** The eval keys one manifest declaration owns, in vocabulary order. */\nfunction evalKeysOf(\n collection: Pick<CollectionConfig, \"externalMetadata\">,\n manifest: ExternalMetadataConfig,\n): string[] {\n return EVAL_KEYS.filter((k) => owns(collection, manifest, k));\n}\n\n/** The pages of a run, with every manifest-supplied key merged into each. */\nexport interface ExternalMetadataReader {\n /** The page as its metadata reads once the manifests are applied. */\n forPage(page: PageFile): Promise<PageFile>;\n}\n\n/**\n * Load every manifest of every declared collection, or `null` when the run has\n * no config, no collections, or none of them declares a manifest — which is\n * every corpus that keeps its metadata in its pages, and costs nothing.\n *\n * The URL refusal is decided from the config alone, before a byte is fetched.\n *\n * `pages` are the run's documents as absolute paths. A collection that keeps\n * its evals in one manifest per page (proposal 0058) has one file to read per\n * page, and meta reads those only for the pages it is given.\n */\nexport async function loadExternalReader(\n config: DocevalsConfig,\n base: string,\n pages?: readonly string[],\n): Promise<ExternalMetadataReader | null> {\n const collections: CollectionConfig[] = [];\n const source = config.configSource ?? config.configPath;\n for (const collection of config.collections) {\n const owning = collection.externalMetadata.filter((m) =>\n EXTERNAL_KEYS.some((k) => owns(collection, m, k)),\n );\n if (owning.length === 0) continue;\n for (const manifest of owning) {\n if (classifyRef(manifest.file).kind !== \"url\") continue;\n const [owned] = evalKeysOf(collection, manifest);\n if (owned !== undefined) {\n throw new DocevalsError(\n urlManifestRefusal(source, collection.name, owned),\n );\n }\n }\n collections.push({ ...collection, externalMetadata: owning });\n }\n if (collections.length === 0) return null;\n\n const index = await loadExternalMetadata(collections, {\n configDir: config.configDir,\n base,\n // A `{page}` entry names one manifest per page (proposal 0058), so it\n // reads a file only for the pages it is handed. Without them it reads\n // nothing, and every value the corpus keeps beside its pages goes missing\n // while the ownership that hides the page's own copy stays.\n ...(pages === undefined ? {} : { pages }),\n });\n if (index === null) return null;\n return reader(index, collections, config.configDir, base, marksFor(config, base));\n}\n\n/**\n * What a page's schemas mark external, for a keyless manifest (proposal\n * 0068): read from meta's section of the same file, the way `cite` reads\n * them, or over meta's default set when that file has none for meta. The\n * default set carries the evals vocabulary, so the eval keys are marked\n * either way. Built once, on the first page that has a keyless manifest.\n */\nfunction marksFor(config: DocevalsConfig, base: string): () => Promise<PageMarks> {\n // A family file whose other sections meta cannot read as its own is still\n // docevals' file; the default set decides the marks then.\n return familyMarks({ configPath: config.configPath, configDir: config.configDir, cwd: base });\n}\n\n/**\n * Which collections of `members` keep `key` in a manifest. Ownership, not\n * supply: a writer has to know which file to write to before either manifest\n * has an entry, so two owners is a refusal even while both are empty.\n */\nfunction ownersOf(\n collections: readonly CollectionConfig[],\n members: readonly string[],\n key: string,\n): string[] {\n return collections\n .filter(\n (c) =>\n members.includes(c.name) &&\n c.externalMetadata.some((m) => owns(c, m, key)),\n )\n .map((c) => c.name);\n}\n\nfunction reader(\n index: ExternalMetadataIndex,\n collections: readonly CollectionConfig[],\n configDir: string,\n base: string,\n marks: () => Promise<PageMarks>,\n): ExternalMetadataReader {\n return {\n async forPage(page: PageFile): Promise<PageFile> {\n if (page.extractError !== undefined) return page;\n const members = memberOf(collections, configDir, base, page.file);\n if (members.length === 0) return page;\n\n for (const key of EVAL_KEYS) {\n const [a, b] = ownersOf(collections, members, key);\n if (a !== undefined && b !== undefined) {\n throw new DocevalsError(twoManifestsRefusal(page.file, a, b, key));\n }\n }\n\n const merged = await mergeWithMarks(\n page.file,\n page.frontmatter,\n index,\n members,\n base,\n { marks: await marks() },\n );\n return {\n ...page,\n frontmatter: merged.extracted,\n external: {\n locate: merged.locate,\n // Only the keys this tool reads and writes. A manifest owning a\n // sibling tool's key that the page also carries is `meta validate`'s\n // finding, and saying it twice would make the same fix look like two.\n collisions: merged.collisions.filter((c) =>\n (EVAL_KEYS as readonly string[]).includes(c.key),\n ),\n evalManifests: suppliers(merged.locate, base),\n },\n };\n },\n };\n}\n\n/**\n * The manifests that supplied the page's eval keys, absolute and deduplicated.\n * `locate` answers only for a key a manifest supplied, so a key the page\n * carries itself names no manifest. A manifest's reported path is relative to\n * `base`, the run's discovery root.\n */\nfunction suppliers(\n locate: PageExternal[\"locate\"],\n base: string,\n): string[] {\n const files = new Set<string>();\n for (const key of EVAL_KEYS) {\n const at = locate(`/${key}`);\n // `at.file` is a path relative to `base`, never a URL: the reader refuses\n // a URL manifest that owns an eval key before any page is read.\n if (at !== undefined) files.add(resolve(base, at.file));\n }\n return [...files];\n}\n\n/**\n * Every page of a run, read the way `meta validate` reads it. The manifests\n * are loaded once, whatever the corpus size, and a run with no manifest gets\n * its pages back untouched.\n *\n * `base` is the run's discovery root, so `page.file` and a manifest's reported\n * path are spelled against the same directory.\n */\nexport async function withExternalMetadata(\n pages: PageFile[],\n config: DocevalsConfig,\n base: string,\n): Promise<PageFile[]> {\n const merge = await loadExternalReader(\n config,\n base,\n pages.map((p) => p.absPath),\n );\n if (merge === null) return pages;\n return Promise.all(pages.map((p) => merge.forPage(p)));\n}\n","/**\n * Resolution: merge a page's eval frontmatter with the central config into a\n * concrete per-page plan. Suites contribute named evals; page entries reference\n * them (with overrides) or define inline evals. Page entries win on id\n * collision.\n *\n * The page vocabulary is `manni:evals:1.0.0` — three flat\n * page-level keys (`evals`, `eval-suite`, `eval-skip`) and a reserved `eval-`\n * prefix, rather than the closed `evals:` object 0.1 used. The\n * whole frontmatter object is validated, not a synthetic `{evals}`: the prefix\n * reservation is a claim about the page root, and it cannot be enforced from a\n * fragment.\n *\n * `page.frontmatter` is the page's metadata *after* `core/external.ts` merged\n * in whatever an owning manifest supplies, so a page whose `evals` live in a\n * manifest resolves the plan it declares rather than none. What the page\n * itself carries and what a manifest supplied are told apart only when a\n * problem or an eval's location has to name a place: `locationOf` and\n * `declaredLocation` below, both through meta's `declaredAt`.\n */\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport type { ErrorObject } from \"ajv\";\nimport { frontmatterSchema } from \"../schema.js\";\nimport type { EvalType, GraderKind, Severity } from \"../types.js\";\nimport {\n normalizeEvalDef,\n type DocevalsConfig,\n type EvalDef,\n type RawEvalDef,\n} from \"./config.js\";\nimport type { PageFile } from \"./discover.js\";\nimport type { EvalTarget } from \"./target.js\";\nimport { warn } from \"../../shared/warn.js\";\nimport { declaredAt } from \"../../meta/internal.js\";\nimport { isRegisteredGrader } from \"../graders/registry.js\";\n\nexport interface ResolvedEval {\n /** Kebab-case id, unique per page. */\n name: string;\n /** Suite this eval reports under (\"default\" when none applies). */\n suite: string;\n assertion?: string;\n type: EvalType;\n grader: GraderKind;\n /** Per-eval provider/agent override for `ai` evals. */\n provider?: string;\n evidence?: string;\n examples?: { pass?: string[]; fail?: string[] };\n command?: string[];\n successExitCodes: number[];\n timeoutMs?: number;\n generatedAssertionHash?: string;\n options: Record<string, unknown>;\n severity: Severity;\n /**\n * Relative contribution to its suite's pass rate. Defaults to 1, which is\n * what makes weighting inert until someone asks for it: a suite of\n * unweighted evals computes exactly the rate it always did.\n */\n weight: number;\n /** Which bytes the grader receives. Absent means the page body. */\n target?: EvalTarget;\n /** Judge model for this eval; a CLI --model still wins. */\n model?: string;\n /** Ensemble runs for this eval; a CLI --runs still wins. */\n runs?: number;\n /** Where the eval definition came from. */\n source: \"config\" | \"page\";\n skip: boolean;\n /**\n * Where the page declares the eval: the item of its `evals` key that names\n * it, in the page or in the manifest that supplied the key. A suite eval\n * the page never names is attached by its `eval-suite` key, so it points\n * there, or at the page alone when the suite is the config's default. The\n * file is spelled like the page's, and `line` is absent when nothing\n * records one.\n */\n location: EvalLocation;\n}\n\n/** A file, and the 1-based line in it when one is known. */\nexport interface EvalLocation {\n file: string;\n line?: number;\n}\n\nexport interface PageProblem {\n message: string;\n level: \"error\" | \"warning\";\n line?: number;\n /**\n * The manifest that supplied the value this problem is about, when one did\n * (`external-metadata`, proposal 0037). Absent for everything the page\n * carries, which the run then reports against the page as it always has.\n */\n file?: string;\n}\n\nexport interface ResolvedPagePlan {\n page: PageFile;\n /** Page-level skip (`eval-skip: true`). */\n skip: boolean;\n suite: string | null;\n evals: ResolvedEval[];\n problems: PageProblem[];\n}\n\n// `strict: false`, as `src/cite/core/page.ts` compiles its own schema: the\n// vocabulary annotates its three keys with `x-manni-location: external`, and\n// Ajv's strict mode throws on a keyword it does not know rather than ignoring\n// the annotation.\nconst ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true, strict: false });\n// The vocabulary as shipped: its severity is the family scale, so nothing is\n// patched in memory.\nconst validateFrontmatter = ajv.compile(frontmatterSchema);\n\ninterface FrontmatterEvalRef {\n use: string;\n type?: EvalType;\n skip?: boolean;\n severity?: Severity;\n /**\n * How much this check counts *for this page*. The reference form is how\n * most pages join a suite at all, so a weight the schema accepts and the\n * merge drops would score the page at the corpus default without saying so.\n */\n weight?: number;\n options?: Record<string, unknown>;\n}\n\ntype FrontmatterEvalEntry =\n | string\n | FrontmatterEvalRef\n | (RawEvalDef & { id: string; skip?: boolean });\n\n/** The three page keys this vocabulary claims. */\ninterface EvalFrontmatter {\n evals?: string | FrontmatterEvalEntry[];\n \"eval-suite\"?: string;\n \"eval-skip\"?: boolean;\n}\n\n/**\n * `evals` is one assertion string or a list of entries. Normalize to the list;\n * a bare string is an ai-judged assertion at error severity, and it has no id\n * of its own — the string shorthand is the legitimately id-less form.\n */\nfunction evalEntries(raw: EvalFrontmatter[\"evals\"]): FrontmatterEvalEntry[] {\n if (raw === undefined) return [];\n return typeof raw === \"string\" ? [raw] : raw;\n}\n\nfunction fromDef(\n name: string,\n suite: string,\n def: EvalDef,\n source: \"config\" | \"page\",\n location: EvalLocation,\n): ResolvedEval {\n return {\n location,\n name,\n suite,\n assertion: def.assertion,\n type: def.type ?? \"regression\",\n grader: (def.grader ?? \"ai\") as GraderKind,\n provider: def.provider,\n evidence: def.evidence,\n examples: def.examples,\n command: def.command,\n successExitCodes: def.successExitCodes ?? [0],\n timeoutMs: def.timeoutMs,\n generatedAssertionHash: def.generatedAssertionHash,\n options: def.options ?? {},\n severity: def.severity ?? \"error\",\n weight: def.weight ?? 1,\n target: def.target,\n model: def.model,\n runs: def.runs,\n source,\n skip: false,\n };\n}\n\n/**\n * A name for a string-shorthand eval, derived from its position.\n *\n * Position-derived names orphan cached verdicts when entries move, which is\n * why object entries must carry an explicit `id`. The shorthand has no id by\n * design, so it accepts that cost in exchange for being one line.\n *\n * `taken` is every name already claimed on this page. Without it a derived\n * name can collide with an explicit `id` of the same spelling, and the Map\n * write silently drops one of two evals the author declared — a page checking\n * less than it says while the run stays green.\n */\nfunction shorthandName(index: number, taken: ReadonlySet<string>): string {\n const base = `assertion-${index + 1}`;\n if (!taken.has(base)) return base;\n for (let n = 2; ; n++) {\n const candidate = `${base}-${n}`;\n if (!taken.has(candidate)) return candidate;\n }\n}\n\n/** The page-level keys this vocabulary claims, for the reservation message. */\nconst RESERVED_KEYS = [\"eval-suite\", \"eval-skip\"] as const;\n\n/**\n * A schema error, in words.\n *\n * The `eval-` prefix reservation is expressed as a `patternProperties` entry\n * whose subschema is `false`, and Ajv reports that as \"boolean schema is\n * false\" — which names neither the key nor the fix. The reservation exists\n * precisely to make a typo loud, so it gets a sentence rather than Ajv's\n * internals.\n */\nfunction describeError(e: ErrorObject): string {\n if (e.keyword === \"false schema\" && e.instancePath.startsWith(\"/eval-\")) {\n const key = e.instancePath.slice(1);\n return (\n `unknown key \"${key}\". The \"eval-\" prefix is reserved, and the only ` +\n `settings under it are ${RESERVED_KEYS.join(\", \")} — so a typo is an ` +\n `error here rather than a key nothing reads.`\n );\n }\n return e.message ?? \"is invalid\";\n}\n\n/**\n * Where a problem about `pointer` should point: the manifest that supplied the\n * value, or the page's own line for it.\n *\n * A manifest line without a file would read as a line of the page, which is\n * the one place the value is not. So the two travel together or not at all.\n */\nfunction locationOf(\n page: PageFile,\n pointer: string,\n): Pick<PageProblem, \"file\" | \"line\"> {\n const at = declaredAt(page.file, pointer, metadataOf(page));\n // A manifest's spelling is never the page's, and a problem about the page\n // always has a line: the block's first when nothing nearer is recorded.\n return at.file === page.file ? { line: at.line ?? 1 } : at;\n}\n\n/** The page's merged metadata, as `declaredAt` reads it. */\nfunction metadataOf(page: PageFile): Parameters<typeof declaredAt>[2] {\n return {\n extracted: page.frontmatter,\n ...(page.external === undefined ? {} : { locate: page.external.locate }),\n };\n}\n\n/**\n * Where the page declares a key it carries, in the page or its manifest. A\n * key the page does not carry has no line: `lineFor` would answer the block's\n * first line for it, which is not where anything is declared.\n */\nfunction declaredLocation(page: PageFile, pointer: string, key: string): EvalLocation {\n if (!(key in page.frontmatter.data)) return { file: page.file };\n return declaredAt(page.file, pointer, metadataOf(page));\n}\n\n/** Resolve one page's plan. Never throws; problems are collected per page. */\nexport function resolvePage(\n page: PageFile,\n config: DocevalsConfig,\n): ResolvedPagePlan {\n const problems: PageProblem[] = [];\n const empty = {\n page,\n skip: false,\n suite: null,\n evals: [],\n problems,\n };\n if (page.extractError) {\n problems.push({ message: page.extractError, level: \"error\", line: 1 });\n return empty;\n }\n\n // A key a manifest owns and the page carries anyway. Meta files this as\n // `external:owned` on the document; docevals says the same sentence, at\n // error level, because there are then two declarations of what to check and\n // grading either one would be a guess.\n for (const c of page.external?.collisions ?? []) {\n problems.push({\n message: `\"${c.key}\" is owned by manifest ${c.file} (collection ${c.collection}); remove it from the document`,\n level: \"error\",\n line: page.frontmatter.lineFor(`/${c.key}`) ?? 1,\n });\n }\n\n const data = page.frontmatter.data;\n // The whole object, not just the eval keys: `eval-` prefix reservation is a\n // statement about the page root. Sibling tools' keys stay legal — the schema\n // root is open — but a typo'd `eval-*` setting is caught here instead of\n // being silently ignored, which is what the closed 0.1 block used to buy.\n if (!validateFrontmatter(data)) {\n for (const e of validateFrontmatter.errors ?? []) {\n problems.push({\n message: `frontmatter${e.instancePath}: ${describeError(e)}`,\n level: \"error\",\n ...locationOf(page, e.instancePath),\n });\n }\n return empty;\n }\n\n const fm = data as EvalFrontmatter;\n const pageSkip = fm[\"eval-skip\"] ?? false;\n\n const declaredSuite = fm[\"eval-suite\"];\n const suiteName = declaredSuite ?? config.defaults.suite;\n if (declaredSuite && !(declaredSuite in config.suites)) {\n problems.push({\n message: `Unknown suite \"${declaredSuite}\" (not defined in ${config.configPath})`,\n level: \"error\",\n ...locationOf(page, \"/eval-suite\"),\n });\n return { ...empty, skip: pageSkip };\n }\n\n const resolved = new Map<string, ResolvedEval>();\n\n // 1. Suite evals from the central config. The page attaches them by naming\n // the suite, so that is where they are declared for this page.\n if (suiteName) {\n const suite = config.suites[suiteName];\n const attached = declaredLocation(page, \"/eval-suite\", \"eval-suite\");\n for (const name of suite?.evals ?? []) {\n const def = config.evals[name];\n if (def) resolved.set(name, fromDef(name, suiteName, def, \"config\", attached));\n }\n }\n\n // 2. Page entries: references (with overrides) and inline evals.\n const reportSuite = suiteName ?? \"default\";\n // Every name an author wrote, collected before any shorthand is numbered.\n // Order matters: a shorthand at index 0 must yield to an explicit\n // `assertion-1` further down the list, not overwrite it.\n const claimed = new Set<string>(resolved.keys());\n for (const entry of evalEntries(fm.evals)) {\n if (typeof entry === \"string\") continue;\n claimed.add(\"use\" in entry ? entry.use : entry.id);\n }\n for (const [i, entry] of evalEntries(fm.evals).entries()) {\n const linePtr = `/evals/${String(i)}`;\n // A string block is one entry at index 0, and the pointer walks up to the\n // block's own line.\n const entryAt = declaredLocation(page, linePtr, \"evals\");\n if (typeof entry === \"string\") {\n // String shorthand: an ai-judged assertion at error severity.\n //\n // In 0.1 a bare string was a *reference* to a config-defined eval, so a\n // page that still says `- no-todo-markers` silently stops running the\n // regex grader and sends the words \"no-todo-markers\" to the judge\n // instead. Nothing errors; the eval simply disappears. Guessing the\n // author's intent would make a second, invisible spelling of `use:`, so\n // name the shape of the mistake and let them fix the page.\n if (entry in config.evals) {\n problems.push({\n message:\n `String shorthand \"${entry}\" matches an eval defined in ${config.configPath}, ` +\n `but a string is an assertion now, not a reference. ` +\n `Write \"use: ${entry}\" to run that eval.`,\n level: \"warning\",\n ...locationOf(page, linePtr),\n });\n }\n const name = shorthandName(i, claimed);\n claimed.add(name);\n resolved.set(\n name,\n fromDef(name, reportSuite, { assertion: entry }, \"page\", entryAt),\n );\n continue;\n }\n if (\"use\" in entry) {\n const ref = entry;\n const def = config.evals[ref.use];\n if (!def) {\n problems.push({\n message: `Unknown eval \"${ref.use}\" (not defined in ${config.configPath})`,\n level: \"error\",\n ...locationOf(page, linePtr),\n });\n continue;\n }\n const base =\n resolved.get(ref.use) ?? fromDef(ref.use, reportSuite, def, \"config\", entryAt);\n resolved.set(ref.use, {\n ...base,\n location: entryAt,\n type: ref.type ?? base.type,\n severity: ref.severity ?? base.severity,\n weight: ref.weight ?? base.weight,\n options: { ...base.options, ...(ref.options ?? {}) },\n skip: ref.skip ?? base.skip,\n });\n continue;\n }\n\n const inline = entry;\n if (resolved.has(inline.id) && resolved.get(inline.id)?.source === \"page\") {\n // Overriding a *suite* eval by id is the documented precedence rule and\n // stays a silent, intended win. Two page-level entries sharing an id is\n // different: one of them is dropped, so the page checks less than it\n // declares — an error, not a warning that lets the run pass.\n problems.push({\n message: `Duplicate eval id \"${inline.id}\" on page — the later entry replaces the earlier one`,\n level: \"error\",\n ...locationOf(page, linePtr),\n });\n }\n const ev = fromDef(inline.id, reportSuite, normalizeEvalDef(inline), \"page\", entryAt);\n ev.skip = inline.skip ?? false;\n resolved.set(inline.id, ev);\n // The shared vocabulary still allows `severity-map`, so a page carrying\n // one is valid. It mapped a wrapped tool's own scale, and no registered\n // grader has one, so the key is read by nothing. Said once per eval:\n // `warn` deduplicates on the text, which names the page and the eval.\n // An eval naming an unregistered grader is a usage error a moment\n // later, so the warning would only bury it.\n if (\"severity-map\" in inline && isRegisteredGrader(ev.grader)) {\n warn(\n `${page.file}: eval \"${inline.id}\" sets severity-map, which no registered ` +\n `grader reads; it has no effect.`,\n );\n }\n if (ev.grader === \"ai\" && !inline.examples) {\n problems.push({\n message: `Eval \"${inline.id}\": ai-graded evals work best with examples.pass/examples.fail`,\n level: \"warning\",\n ...locationOf(page, linePtr),\n });\n }\n }\n\n return {\n page,\n skip: pageSkip,\n suite: suiteName,\n evals: [...resolved.values()],\n problems,\n };\n}\n\n/** Resolve all pages. */\nexport function resolvePages(\n pages: PageFile[],\n config: DocevalsConfig,\n): ResolvedPagePlan[] {\n return pages.map((p) => resolvePage(p, config));\n}\n","/**\n * The page vocabulary manni docevals implements: `manni:evals:1.0.0`, the\n * built-in schema the metadata tool publishes under `src/meta/schemas/`.\n * Pages are validated against that schema itself, imported and bundled into\n * the build, so docevals and `manni meta validate` read the same bytes.\n *\n * docevals ships no copy of the schema. A copy is a second artifact to keep in\n * step, and the copies it used to publish drifted from the draft they copied:\n * they kept `eval-provenance` and the `info` severity after proposal 0046\n * removed both. A consumer who wants to validate pages names\n * `manni:evals:1.0.0` to `manni meta validate`, or validates programmatically\n * against the object below.\n */\nimport schema from \"../meta/schemas/evals/1.0.0.json\" with { type: \"json\" };\n\n/** The evals vocabulary, for validators that accept an inline schema. */\nexport const frontmatterSchema = schema as Record<string, unknown>;\n\n/** The vocabulary's `$id`: `manni:evals:1.0.0`. */\nexport const FRONTMATTER_SCHEMA_ID: string = schema.$id;\n","/**\n * Command grader: runs a user-supplied (or manni docevals-generated) CLI command per\n * page. Exit code membership in `successExitCodes` (default [0]) decides\n * pass/fail; the output tail becomes the finding message.\n *\n * Working directory: page-sourced commands run from the page's directory (so\n * generated script paths like \"manni-docevals/page.eval.mjs\" resolve naturally);\n * config-sourced commands run from the config file's directory.\n */\nimport { dirname } from \"node:path\";\nimport type { Finding } from \"../types.js\";\nimport { outputTail } from \"../../shared/exec.js\";\nimport type { Grader, GraderContext, GraderTarget } from \"./types.js\";\n\nfunction substitute(cmd: string[], file: string): string[] {\n return cmd.map((part) => part.replaceAll(\"{file}\", file));\n}\n\nasync function gradeOne(\n ctx: GraderContext,\n target: GraderTarget,\n): Promise<Finding[]> {\n const { plan, eval: ev } = target;\n if (!ev.command) {\n return [\n {\n evalName: ev.name,\n file: plan.page.file,\n message:\n \"No command to run (script not yet generated — run `manni docevals generate` or `manni docevals run` with a provider configured)\",\n severity: ev.severity,\n diagnostic: true,\n },\n ];\n }\n const cwd =\n ev.source === \"page\" ? dirname(plan.page.absPath) : ctx.config.configDir;\n const result = await ctx.exec(substitute(ev.command, plan.page.absPath), {\n cwd,\n timeoutMs: ev.timeoutMs ?? ctx.config.scripts.timeoutMs,\n env: { MANNI_DOCEVALS_FILE: plan.page.absPath },\n });\n\n if (result.spawnError) {\n return [\n {\n evalName: ev.name,\n file: plan.page.file,\n message: `Failed to run command \"${ev.command[0] ?? \"(empty)\"}\": ${result.spawnError}`,\n severity: ev.severity,\n diagnostic: true,\n },\n ];\n }\n if (result.timedOut) {\n return [\n {\n evalName: ev.name,\n file: plan.page.file,\n message: `Command timed out after ${ev.timeoutMs ?? ctx.config.scripts.timeoutMs}ms`,\n severity: ev.severity,\n diagnostic: true,\n },\n ];\n }\n if (result.code != null && ev.successExitCodes.includes(result.code)) {\n return [];\n }\n const tail = outputTail(result);\n return [\n {\n evalName: ev.name,\n file: plan.page.file,\n // \"Exit code N\" is the message users and docs already know; only the\n // null case — killed by a signal, which is what a timeout produces —\n // needs different words, because \"Exit code null\" describes nothing.\n message:\n (result.code === null\n ? \"Killed before exiting\"\n : `Exit code ${result.code}`) + (tail ? `: ${tail}` : \"\"),\n severity: ev.severity,\n },\n ];\n}\n\nexport const commandGrader: Grader = {\n kind: \"command\",\n mode: \"per-file\",\n async grade(ctx) {\n const findings: Finding[] = [];\n for (const target of ctx.targets) {\n findings.push(...(await gradeOne(ctx, target)));\n }\n return findings;\n },\n};\n","/**\n * Grader option validation.\n *\n * `options` is deliberately open in the published vocabulary — proposal 0023\n * describes it as \"grader-specific options; validated by the grader at run\n * time\", because a grader's options evolve on the grader's schedule and a\n * closed schema would version on every one. The cost of that openness is that\n * nothing catches a typo: `max-age-day: 30` used to fall straight through to\n * the default of 365, and the eval quietly checked something its author never\n * wrote. This module is the \"validated by the grader\" half actually happening.\n *\n * Ported from moose-tracevals' `src/graders/util.ts`, which solved it first —\n * the same reason `src/docevals/core/baseline.ts` was ported from the metadata tool. Combinators\n * rather than a JSON Schema per grader: they give messages that name the key,\n * and they express the cross-field constraints (ordered bounds, a criterion\n * that can never pass) that JSON Schema states badly.\n */\n\n/** An option-validation outcome: a message when invalid, undefined when fine. */\nexport type OptionCheck = string | undefined;\n\nexport type Options = Record<string, unknown>;\n\n/** First failing check, so callers read as a flat list of constraints. */\nexport function firstError(...checks: OptionCheck[]): OptionCheck {\n return checks.find((check) => check !== undefined);\n}\n\n/**\n * Rejects any key the grader does not know.\n *\n * This is the check the whole module exists for: every other constraint here\n * assumes the author spelled the key right in the first place.\n */\nexport function knownKeys(options: Options, allowed: readonly string[]): OptionCheck {\n const unknown = Object.keys(options).filter((k) => !allowed.includes(k));\n if (unknown.length === 0) return undefined;\n const listed = [...allowed].sort().join(\", \");\n return `unknown option${unknown.length > 1 ? \"s\" : \"\"} ${unknown\n .map((k) => `\"${k}\"`)\n .join(\", \")} — this grader accepts: ${listed}`;\n}\n\nexport function requiredString(options: Options, key: string): OptionCheck {\n const value = options[key];\n if (typeof value !== \"string\" || value.length === 0) {\n return `options.${key} is required`;\n }\n return undefined;\n}\n\nexport function optionalString(options: Options, key: string): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n if (typeof value !== \"string\" || value.length === 0) {\n return `options.${key} must be a non-empty string`;\n }\n return undefined;\n}\n\nexport function optionalEnum(\n options: Options,\n key: string,\n allowed: readonly string[],\n): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n if (typeof value !== \"string\" || !allowed.includes(value)) {\n return `options.${key} must be one of: ${allowed.join(\", \")}`;\n }\n return undefined;\n}\n\nexport function optionalNumber(\n options: Options,\n key: string,\n bounds: { min?: number; max?: number; integer?: boolean } = {},\n): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n // Number.isFinite also rejects NaN and both infinities.\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return `options.${key} must be a finite number`;\n }\n if (bounds.integer === true && !Number.isInteger(value)) {\n return `options.${key} must be a whole number`;\n }\n if (bounds.min !== undefined && value < bounds.min) {\n return `options.${key} must be at least ${bounds.min}`;\n }\n if (bounds.max !== undefined && value > bounds.max) {\n return `options.${key} must be at most ${bounds.max}`;\n }\n return undefined;\n}\n\nexport function optionalBoolean(options: Options, key: string): OptionCheck {\n if (options[key] !== undefined && typeof options[key] !== \"boolean\") {\n return `options.${key} must be a boolean`;\n }\n return undefined;\n}\n\nexport function optionalStringArray(options: Options, key: string): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n if (\n !Array.isArray(value) ||\n value.some((v) => typeof v !== \"string\" || v.length === 0)\n ) {\n return `options.${key} must be a list of non-empty strings`;\n }\n return undefined;\n}\n","/**\n * `target` — which bytes a grader receives.\n *\n * Distinct from `evidence`, which only hints where to look *within* what is\n * graded. `evidence` is prose for the judge; `target` decides what the judge\n * (or a deterministic grader) is handed in the first place, which is why\n * deterministic graders honour it too and why it is named `target` rather than\n * `focus` — a regex grader has no focus.\n *\n * A target that cannot be served is an explicit failure, never a silent\n * substitution: grading the page body when the author asked for a companion\n * file would report a verdict about the wrong bytes, which is worse than no\n * verdict at all (ADR 01022).\n */\nimport { readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport type { ResolvedPagePlan } from \"./resolve.js\";\n\n/** The `body` | `raw` | `frontmatter` | companion-file selector. */\nexport type EvalTarget =\n | \"body\"\n | \"raw\"\n | \"frontmatter\"\n | { source: \"file\"; path: string };\n\nexport const DEFAULT_TARGET: EvalTarget = \"body\";\n\nexport type TargetResult =\n | { ok: true; text: string; label: string }\n | { ok: false; reason: string };\n\n/** Human-readable name for a target, for messages and report lines. */\nexport function describeTarget(target: EvalTarget | undefined): string {\n const t = target ?? DEFAULT_TARGET;\n return typeof t === \"string\" ? t : `file ${t.path}`;\n}\n\n/**\n * Read what `target` selects for `plan`.\n *\n * A companion path is resolved against the page's own directory and must stay\n * inside it. An absolute path or one that climbs out is refused by name rather\n * than read: a page is content, and content naming an arbitrary path on the\n * machine that runs the eval is the same class of hazard as a frontmatter\n * command.\n */\nexport function readTarget(\n target: EvalTarget | undefined,\n plan: ResolvedPagePlan,\n): TargetResult {\n const t = target ?? DEFAULT_TARGET;\n if (t === \"body\") return { ok: true, text: plan.page.body, label: \"body\" };\n if (t === \"raw\") return { ok: true, text: plan.page.content, label: \"raw\" };\n if (t === \"frontmatter\") {\n const data = plan.page.frontmatter.data as unknown;\n // An empty or absent frontmatter block yields \"{}\\n\" from the YAML\n // stringifier, which reads as \"there was nothing\" rather than as a bug.\n return {\n ok: true,\n text: stringifyYaml(data ?? {}),\n label: \"frontmatter\",\n };\n }\n\n const pageDir = dirname(plan.page.absPath);\n if (isAbsolute(t.path)) {\n return {\n ok: false,\n reason: `target file \"${t.path}\" is an absolute path; name it relative to the page`,\n };\n }\n const abs = resolve(pageDir, t.path);\n const rel = relative(pageDir, abs);\n // The segment has to *end* at the dots. `startsWith(\"..\")` alone rejects a\n // legitimate sibling whose name merely begins with them — `..notes.ts`,\n // `..rc` — which is a refusal the author cannot act on, since the file is\n // inside the root and named exactly what they wrote. `isAbsolute` covers the\n // Windows case where the target sits on another drive and `relative` cannot\n // express the step at all.\n if (rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {\n return {\n ok: false,\n reason: `target file \"${t.path}\" resolves outside the page's directory`,\n };\n }\n try {\n return { ok: true, text: readFileSync(abs, \"utf8\"), label: `file ${t.path}` };\n } catch (err) {\n // `useUnknownInCatchVariables` is on, so the cast has to be earned: a\n // thrown value that is not an Error has no `code` to read, and asserting\n // one would put `undefined` where the message promises a reason.\n const code =\n err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\n return {\n ok: false,\n reason: `target file \"${t.path}\" could not be read (${code ?? \"unknown error\"})`,\n };\n }\n}\n","/**\n * Native regex check over whatever `target` selects.\n *\n * The cheap rung the grader hierarchy was missing. An assertion like \"the page\n * names the current package\" is a verifiable fact, and putting it to an LLM\n * judge three times is both slower and less trustworthy than matching it —\n * \"use an ai grader only when a deterministic one cannot express it\" is only\n * advice you can follow if a deterministic one exists.\n *\n * `match` covers the three shapes worth having: `contains` (the default),\n * `not-contains`, and `count:N` for \"exactly N times\", which is what catches a\n * heading duplicated by a bad merge.\n */\nimport type { Finding } from \"../../types.js\";\nimport type { Grader } from \"./../types.js\";\nimport {\n firstError,\n knownKeys,\n optionalString,\n requiredString,\n type OptionCheck,\n type Options,\n} from \"../options.js\";\nimport { readTarget, type EvalTarget } from \"../../core/target.js\";\nimport type { PageFile } from \"../../core/discover.js\";\nimport { errorMessage } from \"../../../shared/errors.js\";\n\ninterface RegexOptions {\n pattern?: string;\n flags?: string;\n match?: string;\n}\n\nconst MATCH_RE = /^(contains|not-contains|count:\\d+)$/;\nconst FLAGS_RE = /^[dgimsuvy]*$/;\n\n/** 1-based line of `index` within `text`. */\nfunction lineAt(text: string, index: number): number {\n let line = 1;\n for (let i = 0; i < index && i < text.length; i++) {\n if (text[i] === \"\\n\") line++;\n }\n return line;\n}\n\n/**\n * Lines of the file above the text `target` selects, so a finding names the\n * line in the file rather than in the selection. The github format writes\n * `line=` from it.\n *\n * The body is the file with its frontmatter block cut off the front, so it\n * starts that block's height down. `raw` is the file itself. The serialized\n * frontmatter and a companion file have no place in the page to count from,\n * so their lines stay their own.\n */\nfunction linesAbove(target: EvalTarget | undefined, page: PageFile): number {\n if (target !== undefined && target !== \"body\") return 0;\n if (!page.content.endsWith(page.body)) return 0;\n return lineAt(page.content, page.content.length - page.body.length) - 1;\n}\n\nexport const regexGrader: Grader = {\n kind: \"tool:regex\",\n // It calls `readTarget` directly, so it serves the whole vocabulary — the\n // one deterministic grader that does. Declaring it here is what exempts it\n // from the engine's body-only guard (ADR 01033).\n targets: [\"body\", \"raw\", \"frontmatter\", \"file\"] as const,\n validateOptions(options: Options): OptionCheck {\n const match = options.match;\n return firstError(\n knownKeys(options, [\"pattern\", \"flags\", \"match\"]),\n requiredString(options, \"pattern\"),\n optionalString(options, \"flags\"),\n typeof options.flags === \"string\" && !FLAGS_RE.test(options.flags)\n ? \"options.flags must be JS RegExp flags (d g i m s u v y)\"\n : undefined,\n match !== undefined && (typeof match !== \"string\" || !MATCH_RE.test(match))\n ? \"options.match must be contains, not-contains, or count:N\"\n : undefined,\n // A pattern that will not compile is a typo, not a finding: reporting it\n // as a failed assertion would blame the page for the eval's own bug.\n (() => {\n if (typeof options.pattern !== \"string\") return undefined;\n try {\n new RegExp(options.pattern, (options.flags as string | undefined) ?? \"\");\n return undefined;\n } catch (err) {\n return `options.pattern is not a valid regular expression (${errorMessage(err)})`;\n }\n })(),\n );\n },\n mode: \"per-file\",\n grade(ctx) {\n // Synchronous work behind an async contract: `.then` keeps a throw a\n // rejection, as it was when this method was `async`.\n return Promise.resolve().then(() => {\n const findings: Finding[] = [];\n for (const { plan, eval: ev } of ctx.targets) {\n const opts = ev.options as RegexOptions;\n const pattern = opts.pattern ?? \"\";\n const flags = opts.flags ?? \"\";\n const match = opts.match ?? \"contains\";\n\n const selected = readTarget(ev.target, plan);\n if (!selected.ok) {\n findings.push({\n evalName: ev.name,\n file: plan.page.file,\n ruleId: \"regex/unreadable-target\",\n message: selected.reason,\n severity: ev.severity,\n line: 1,\n });\n continue;\n }\n\n const text = selected.text;\n const offset = linesAbove(ev.target, plan.page);\n // Always count with /g so `count:N` is a count and not a boolean, then\n // read the first match's offset for the line number.\n const all = [...text.matchAll(new RegExp(pattern, flags.includes(\"g\") ? flags : `${flags}g`))];\n const first = all[0];\n\n if (match === \"contains\" && all.length === 0) {\n findings.push({\n evalName: ev.name,\n file: plan.page.file,\n ruleId: \"regex/not-found\",\n message: `Pattern /${pattern}/${flags} not found in ${selected.label}`,\n severity: ev.severity,\n line: 1,\n });\n } else if (match === \"not-contains\" && first !== undefined) {\n findings.push({\n evalName: ev.name,\n file: plan.page.file,\n ruleId: \"regex/found\",\n message: `Pattern /${pattern}/${flags} found in ${selected.label}, expected absent`,\n severity: ev.severity,\n line: offset + lineAt(text, first.index),\n });\n } else if (match.startsWith(\"count:\")) {\n const want = Number(match.slice(\"count:\".length));\n if (all.length !== want) {\n findings.push({\n evalName: ev.name,\n file: plan.page.file,\n ruleId: \"regex/count\",\n message: `Pattern /${pattern}/${flags} matched ${String(all.length)} time(s) in ${selected.label}, expected ${String(want)}`,\n severity: ev.severity,\n line: first === undefined ? 1 : offset + lineAt(text, first.index),\n });\n }\n }\n }\n return findings;\n });\n },\n};\n","/**\n * Grader registry: maps grader kinds to implementations. Same pattern as\n * the metadata tool's schema registry — a static map, one entry per built-in.\n *\n * Only the deterministic graders have an implementation here. `ai` is graded\n * by the judge stage and `human` by review, so `graderFor` answers\n * `undefined` for both. They are registered kinds all the same:\n * `listGraderKinds` names them, and an eval may name either.\n */\nimport type { Grader } from \"./types.js\";\nimport { commandGrader } from \"./command.js\";\nimport { regexGrader } from \"./native/regex.js\";\n\nconst GRADERS = new Map<string, Grader>(\n [commandGrader, regexGrader].map((g) => [g.kind, g]),\n);\n\n/** Kinds graded outside this map: `ai` by the judge, `human` by review. */\nconst UNMAPPED_KINDS: readonly string[] = [\"ai\", \"human\"];\n\n/** The built-in kinds, in the order a message lists them. */\nconst BUILT_IN_ORDER: readonly string[] = [\"ai\", \"command\", \"human\", \"tool:regex\"];\n\nexport function graderFor(kind: string): Grader | undefined {\n return GRADERS.get(kind);\n}\n\n/** Every registered kind: the built-ins first, then any registered later. */\nexport function listGraderKinds(): string[] {\n return [...new Set<string>([...BUILT_IN_ORDER, ...GRADERS.keys()])];\n}\n\n/** Whether an eval naming `kind` has anything to grade it. */\nexport function isRegisteredGrader(kind: string): boolean {\n return UNMAPPED_KINDS.includes(kind) || GRADERS.has(kind);\n}\n\n/** Register an additional grader (used by later phases and tests). */\nexport function registerGrader(grader: Grader): void {\n GRADERS.set(grader.kind, grader);\n}\n","/**\n * Pre-run feasibility: evals that cannot reach a verdict as configured.\n *\n * ADRs 01020 and 01022 already make an eval that reached no verdict a failure\n * rather than a pass — but they do it at grade time, which for an `ai` eval is\n * after the judge has been paid. Everything here is knowable from the resolved\n * config and page alone, so it is knowable before a single call goes out.\n *\n * `claude plugin eval` computes the same class of thing and prints it up\n * front, on the reasoning that an infeasible check scores zero in every arm\n * and reads as \"the tool found nothing\" rather than as \"you configured this\n * wrong\". That is exactly the confusion worth spending a cheap static pass to\n * avoid.\n *\n * Scope is deliberately narrow: only what *configuration* makes impossible,\n * and only where nothing already answers it. Whether a command is on PATH is\n * a runtime fact ADR 01020 covers, and an `ai` eval with no assertion is\n * already rejected by both schemas at parse time, with a better message than\n * this could give. A second answer to a settled question is worse than none.\n *\n * An eval naming a grader nothing registered is not a feasibility problem but\n * a usage error: `assertRegisteredGraders` below refuses the whole command.\n */\nimport { graderFor, isRegisteredGrader, listGraderKinds } from \"../graders/registry.js\";\nimport { DocevalsError } from \"../types.js\";\nimport type { DocevalsConfig } from \"./config.js\";\nimport type { RunProblem } from \"./engine.js\";\nimport type { ResolvedPagePlan } from \"./resolve.js\";\n\nfunction unregistered(where: string, name: string, grader: string): DocevalsError {\n return new DocevalsError(\n `${where}: eval \"${name}\" names grader \"${grader}\", which is not registered. ` +\n `Registered graders: ${listGraderKinds().join(\", \")}.`,\n );\n}\n\n/**\n * Refuse an eval whose grader nothing registered, naming the file that\n * declared it: the config for a config eval, the page for an inline one.\n *\n * A usage error, exit 2, for `run`, `list`, `generate` and `promote`\n * alike. The configuration's bug is not the page's fault (ADR 01029), so a\n * per-eval error result, which blamed every page carrying the eval, was the\n * wrong report. Every config eval is checked, used or not, and every inline\n * eval on every page, skipped or not: a skip is not a reason to keep a typo.\n * A grader added through `registerGrader` passes.\n */\nexport function assertRegisteredGraders(\n plans: ResolvedPagePlan[],\n config: DocevalsConfig,\n): void {\n const configFile = config.configSource ?? config.configPath;\n for (const [name, def] of Object.entries(config.evals)) {\n const grader = def.grader ?? \"ai\";\n if (!isRegisteredGrader(grader)) throw unregistered(configFile, name, grader);\n }\n for (const plan of plans) {\n for (const ev of plan.evals) {\n // A config eval was checked by the loop above, so only a page's own\n // inline evals are left to check here.\n if (ev.source === \"page\" && !isRegisteredGrader(ev.grader)) {\n throw unregistered(plan.page.file, ev.name, ev.grader);\n }\n }\n }\n}\n\nexport interface FeasibilityOptions {\n /** Whether frontmatter-declared commands may run in this invocation. */\n allowFrontmatterCommands: boolean;\n /** Whether script generation can supply a missing command. */\n canGenerate: boolean;\n /** `--deterministic-only`: ai evals are not run, so not checked. */\n deterministicOnly?: boolean;\n /** `--ai-only`: deterministic evals are not run, so not checked. */\n aiOnly?: boolean;\n}\n\nexport function checkFeasibility(\n plans: ResolvedPagePlan[],\n options: FeasibilityOptions,\n): RunProblem[] {\n const problems: RunProblem[] = [];\n for (const plan of plans) {\n if (plan.skip) continue;\n for (const ev of plan.evals) {\n if (ev.skip) continue;\n // Only what this run would actually execute. A filtered run reporting a\n // configuration error about work it never attempted is the shape ADR\n // 01018 guards against: numbers about one thing, a verdict about another.\n const isAi = ev.grader === \"ai\";\n if (isAi && options.deterministicOnly === true) continue;\n if (!isAi && ev.grader !== \"human\" && options.aiOnly === true) continue;\n const where = `Eval \"${ev.name}\"`;\n\n // Grader options. The published vocabulary leaves `options` open and\n // says the grader validates it; this is where that happens for every\n // grader at once, before any of them run.\n const grader = graderFor(ev.grader);\n const invalid = grader?.validateOptions?.(ev.options);\n if (invalid !== undefined) {\n problems.push({\n file: plan.page.file,\n level: \"error\",\n message: `${where}: ${ev.grader} ${invalid}`,\n });\n }\n\n // A page-declared command that may not run, and cannot be generated\n // either, can only ever be skipped — so it is a gate that checks\n // nothing, which is the failure mode worth naming out loud.\n if (\n ev.grader === \"command\" &&\n ev.source === \"page\" &&\n !options.allowFrontmatterCommands &&\n !ev.command &&\n !options.canGenerate\n ) {\n problems.push({\n file: plan.page.file,\n level: \"error\",\n message:\n `${where}: a page-declared command eval with no command, while ` +\n `frontmatter commands are not granted (execution.allow: ` +\n `[frontmatter-commands]) and generation is off — it can only ever ` +\n `be skipped`,\n });\n }\n }\n }\n return problems;\n}\n","/**\n * The findings baseline — a ratchet (ADR 01017).\n *\n * A baseline records today's findings so a run can fail on *new* ones only.\n * That is what lets a team turn an eval on this Monday instead of after a\n * 500-page cleanup: the standard tightens immediately, the backlog is recorded,\n * and nothing regresses past the recorded state.\n *\n * Ported from the metadata tool's `src/meta/core/baseline.ts`, which solved this first.\n * `manni.config.yaml` is shared by the family (ADR 01008), so the two tools\n * spell the idea the same way. What differs is the fingerprint: the metadata tool has a\n * JSON Pointer into structured metadata, and we grade prose. See `fingerprint`.\n *\n * Scope: **findings**, which means deterministic graders. An ai-graded eval's\n * verdict carries no rule identity to fingerprint, and a judge verdict is not\n * the kind of thing a backlog file should freeze — the human-review queue is\n * the mechanism for those.\n */\nimport { createHash } from \"node:crypto\";\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport { DocevalsError, type EvalResult, type Finding } from \"../types.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\n\n/** Where `--baseline` / `--write-baseline` / `baseline:` point when unspecified. */\nexport const DEFAULT_BASELINE_PATH = \".manni-docevals-baseline.json\";\n\n/** The only file format this version understands. */\nexport const BASELINE_VERSION = 1;\n\n/** Exactly what `fingerprint` emits: 16 lowercase hex characters. */\nconst FINGERPRINT_RE = /^[0-9a-f]{16}$/;\n\nexport interface Baseline {\n version: number;\n /** manni docevals version that produced the file, for diagnosis only. */\n generatedWith: string;\n /** File path (as reported in results) -> sorted finding fingerprints. */\n entries: Record<string, string[]>;\n}\n\n/** The parts of a finding a fingerprint is built from. */\nexport type Fingerprintable = Pick<Finding, \"evalName\" | \"ruleId\">;\n\n/** What file labels are made relative to, so a baseline reads the same anywhere. */\nexport interface FingerprintContext {\n /** Directory canonical paths are expressed relative to: the config's. */\n base: string;\n /** Directory a result's `file` label is relative to. Defaults to `base`. */\n runBase?: string;\n}\n\n/**\n * The key a file's entry is stored under.\n *\n * Result labels are relative to whatever the run resolved against, so the same\n * page is `docs/legacy.md` from the repo root and `legacy.md` from inside\n * `docs/`. A baseline is committed and shared, so its keys have to name the\n * file the same way from anywhere — otherwise the lookup misses and every\n * baselined finding reads as new, without a fingerprint ever being compared.\n */\nexport function canonicalFilePath(file: string, ctx?: FingerprintContext): string {\n if (!ctx) return file;\n const from = ctx.runBase ?? ctx.base;\n return relative(ctx.base, resolve(from, file)).replace(/\\\\/g, \"/\");\n}\n\n/**\n * A finding's stable identity: 16 hex characters of\n * `sha256(evalName NUL ruleId)`.\n *\n * `ruleId` is the grader's own rule (`regex/found`, `regex/count`).\n * Unlike `ruleIdFor` in the SARIF reporter it is *not* defaulted to the eval\n * name when absent — `evalName` is already the first component, so an empty\n * second one is unambiguous, and a grader that leaves `ruleId` undefined (the\n * `command` grader does) would otherwise hash its eval name twice.\n *\n * Deliberately excludes:\n *\n * - **the line number** — adding one line shifts every finding below it, and a\n * fingerprint that moved with it would present a pure reordering as a wall of\n * new findings;\n * - **the message prose** — a command or a registered grader writes it, so an upstream\n * reword would invalidate every affected entry in every consuming repo at\n * once, presenting as \"manni docevals broke our build\";\n * - **the file path** — it is already the entry key.\n *\n * The consequence, and it is a real one: identity is per rule per file, **not\n * per occurrence**. A file baselined for three `regex/found` findings will not fail\n * when a fourth appears. Prose has no stable per-occurrence anchor — a text\n * snippet churns on every edit, an ordinal renumbers on every insertion, which\n * is the line-number problem again.\n *\n * The NUL separator is what keeps `(\"ab\", undefined)` and `(\"a\", \"b\")` apart.\n */\nexport function fingerprint(f: Fingerprintable): string {\n const parts = [f.evalName, f.ruleId ?? \"\"];\n return createHash(\"sha256\").update(parts.join(\"\\0\")).digest(\"hex\").slice(0, 16);\n}\n\n/** Sorted keys and sorted fingerprints, so the file diffs and merges legibly. */\nexport function serializeBaseline(baseline: Baseline): string {\n // Null-prototype for the same reason `parseBaseline` uses one: a file key of\n // `__proto__` assigned into a plain object literal would set the prototype\n // and drop the entry, so a parse/serialize round-trip would lose it silently.\n const entries = Object.create(null) as Record<string, string[]>;\n for (const file of Object.keys(baseline.entries).sort()) {\n entries[file] = [...(baseline.entries[file] ?? [])].sort();\n }\n return `${JSON.stringify(\n { version: baseline.version, generatedWith: baseline.generatedWith, entries },\n null,\n 2,\n )}\\n`;\n}\n\nfunction bad(source: string, detail: string): never {\n throw new DocevalsError(`Baseline \"${source}\": ${detail}`);\n}\n\n/** Parse baseline JSON. `source` is the path as the user would type it. */\nexport function parseBaseline(text: string, source: string): Baseline {\n let raw: unknown;\n try {\n // A committed file an editor may have re-saved. Nothing hashes it, so this\n // is purely a parsing concession.\n raw = JSON.parse(text.replace(/^/, \"\"));\n } catch (err) {\n bad(source, `invalid JSON: ${errorMessage(err)}`);\n }\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n bad(source, \"top level must be an object.\");\n }\n const obj = raw as Record<string, unknown>;\n\n if (obj.version !== BASELINE_VERSION) {\n bad(\n source,\n `unsupported version ${JSON.stringify(obj.version)} (this manni docevals writes version ${BASELINE_VERSION}). Re-record it with \\`manni docevals run --write-baseline\\`.`,\n );\n }\n\n const rawEntries = obj.entries;\n if (\n typeof rawEntries !== \"object\" ||\n rawEntries === null ||\n Array.isArray(rawEntries)\n ) {\n bad(source, '\"entries\" must be an object mapping file paths to fingerprints.');\n }\n\n // Null-prototype, so a file key of `__proto__` is stored as an ordinary entry\n // rather than triggering the inherited setter — which would replace this\n // object's prototype and silently drop the entry. Every other malformation\n // here is rejected loudly; that one would not even be visible.\n const entries = Object.create(null) as Record<string, string[]>;\n for (const [file, value] of Object.entries(rawEntries as Record<string, unknown>)) {\n if (!Array.isArray(value) || value.some((v) => typeof v !== \"string\")) {\n bad(source, `entries[\"${file}\"] must be a list of fingerprint strings.`);\n }\n // A fingerprint that is not the shape this code writes can never match a\n // real finding, so a typo in a hand-edited baseline would otherwise present\n // as \"that finding came back\" with nothing to explain it. Reject it where\n // the user can still see which entry is wrong.\n const malformed = (value as string[]).find((v) => !FINGERPRINT_RE.test(v));\n if (malformed !== undefined) {\n bad(\n source,\n `entries[\"${file}\"] contains ${JSON.stringify(malformed)}, which is not a fingerprint (16 lowercase hex characters).`,\n );\n }\n entries[file] = value as string[];\n }\n\n return {\n version: BASELINE_VERSION,\n generatedWith: typeof obj.generatedWith === \"string\" ? obj.generatedWith : \"\",\n entries,\n };\n}\n\n/** Read a baseline from disk. Returns null when the file does not exist. */\nexport function readBaseline(absPath: string, source: string): Baseline | null {\n let text: string;\n try {\n text = readFileSync(absPath, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw new DocevalsError(\n `Baseline \"${source}\" could not be read: ${errorMessage(err)}`,\n );\n }\n return parseBaseline(text, source);\n}\n\n/**\n * Write the baseline atomically.\n *\n * It is a committed artifact the whole team's gate reads, and a truncated write\n * is not merely lost work: the next run cannot parse it and exits 2 until\n * someone re-records.\n */\nexport function writeBaselineFile(\n absPath: string,\n baseline: Baseline,\n source: string,\n): void {\n try {\n mkdirSync(dirname(absPath), { recursive: true });\n const tmp = `${absPath}.tmp`;\n writeFileSync(tmp, serializeBaseline(baseline));\n renameSync(tmp, absPath);\n } catch (err) {\n throw new DocevalsError(\n `Baseline \"${source}\" could not be written: ${errorMessage(err)}`,\n );\n }\n}\n\n/** Record every finding in `results` as a baseline. Clean files are omitted. */\nexport function buildBaseline(\n results: EvalResult[],\n generatedWith: string,\n ctx?: FingerprintContext,\n): Baseline {\n // Null-prototype, and here it prevents a crash rather than a lost entry.\n // `__proto__` is the famous collision but not the reachable one; `toString`\n // is a legal filename. A *clean* file gets no entry, so `applyBaseline`'s\n // lookup would find the inherited method instead of `undefined`, pass the\n // `!known` guard because a function is truthy, and then die in `new Set(known)`.\n const entries = Object.create(null) as Record<string, string[]>;\n for (const r of results) {\n // Keyed by `r.file`, matching `applyBaseline`'s lookup. `groupFindings`\n // currently guarantees `f.file === r.file`, so keying by the finding was\n // not a live bug — but the asymmetry is a trap: a grader that resolved a\n // path differently would build entries the lookup could never match, and\n // every baselined finding would reappear as new with nothing to explain it.\n const key = canonicalFilePath(r.file, ctx);\n for (const f of r.findings ?? []) {\n // A diagnostic is never recorded. It is not a finding *about the page* —\n // it is the grader reporting that it could not reach a verdict, and ADR\n // 01022 says that fails the eval at any severity. Recording it lets the\n // next run suppress it, which empties `fresh` entirely and makes the\n // recompute below yield `pass`: \"the grader could not run\" becomes a\n // permanent green that no later run can dislodge. The severity-plus-\n // diagnostic predicate in `applyBaseline` only covers *partial*\n // suppression; this is what covers the whole-set case.\n if (f.diagnostic === true) continue;\n const list = entries[key] ?? [];\n const print = fingerprint(f);\n // Two identical findings in one file are one fingerprint; storing the\n // duplicate would only make the count meaningless.\n if (!list.includes(print)) list.push(print);\n entries[key] = list;\n }\n }\n return { version: BASELINE_VERSION, generatedWith, entries };\n}\n\nexport interface AppliedBaseline {\n /** Results with baselined findings removed and outcomes recomputed. */\n results: EvalResult[];\n /** Fingerprints the baseline holds **for the files this run checked**. */\n recorded: number;\n /** Findings suppressed because the baseline already had them. */\n suppressed: number;\n /** Recorded fingerprints for checked files that no longer occur. */\n stale: number;\n}\n\n/**\n * Subtract a baseline from a run's results.\n *\n * `recorded` and `stale` count only the files this run actually checked. The\n * alternative — counting the whole file — would make a single-page run announce\n * that hundreds of entries \"no longer occur\", and the advice that follows\n * (re-record to prune) would then destroy them.\n */\nexport function applyBaseline(\n results: EvalResult[],\n baseline: Baseline,\n ctx?: FingerprintContext,\n): AppliedBaseline {\n let suppressed = 0;\n const seenByFile = new Map<string, Set<string>>();\n const touched = new Set<string>();\n\n const applied = results.map((r) => {\n // \"Touched\" means this run actually graded the file, which is not the same\n // as having produced a result for it. A clean pass must count, because a\n // file whose findings were all fixed is exactly what `stale` exists to\n // surface. A `skipped` or `error` result must NOT: the eval never ran, so\n // its recorded findings are not gone, they are unmeasured — and reporting\n // them as \"no longer occur\" invites the re-record that deletes them.\n const key = canonicalFilePath(r.file, ctx);\n if (r.outcome === \"pass\" || r.outcome === \"fail\") touched.add(key);\n const findings = r.findings;\n if (!findings || findings.length === 0) return r;\n const known = baseline.entries[key];\n if (!known) return r; // no entry: a new or renamed file, everything is new\n\n const recordedHere = new Set(known);\n const seen = seenByFile.get(key) ?? new Set<string>();\n const fresh: Finding[] = [];\n for (const f of findings) {\n const print = fingerprint(f);\n if (recordedHere.has(print)) {\n seen.add(print);\n suppressed += 1;\n } else {\n fresh.push(f);\n }\n }\n seenByFile.set(key, seen);\n\n if (fresh.length === findings.length) return r;\n // Outcome is recomputed rather than preserved: a deterministic eval fails\n // only on an error-severity finding, so suppressing the last of them makes\n // the eval pass. Leaving `outcome` alone would baseline the finding and\n // still fail the run.\n // `diagnostic` is part of the failing condition, not just severity. A\n // diagnostic finding means the grader reached no verdict, and ADR 01022\n // says that fails the eval at any severity — the engine enforces exactly\n // that when it first computes the outcome. Recomputing on severity alone\n // let a baseline turn \"the grader could not run\" into `pass`, which is the\n // one thing a baseline must never forgive: it suppresses *known* findings,\n // never the absence of a verdict.\n const hasError = fresh.some(\n (f) => f.severity === \"error\" || f.diagnostic === true,\n );\n return {\n ...r,\n outcome: hasError ? (\"fail\" as const) : (\"pass\" as const),\n ...(fresh.length > 0 ? { findings: fresh } : { findings: undefined }),\n baselined: findings.length - fresh.length,\n };\n });\n\n let recorded = 0;\n let stale = 0;\n for (const key of touched) {\n const known = baseline.entries[key];\n if (!known) continue;\n const recordedHere = new Set(known);\n recorded += recordedHere.size;\n stale += recordedHere.size - (seenByFile.get(key)?.size ?? 0);\n }\n\n return { results: applied, recorded, suppressed, stale };\n}\n\n/**\n * Count fingerprints added and dropped between two baselines.\n *\n * The `removed` half is the load-bearing one: an accidental `--write-baseline`\n * on a narrowed glob or a mistyped exclude silently forgives everything it did\n * not see, and this number is the only thing that makes that visible in a CI log.\n */\nexport function diffBaselines(\n previous: Baseline | null,\n next: Baseline,\n): { added: number; removed: number } {\n const flatten = (b: Baseline | null): Set<string> => {\n const out = new Set<string>();\n if (!b) return out;\n for (const [file, prints] of Object.entries(b.entries)) {\n for (const p of prints) out.add(`${file}\\0${p}`);\n }\n return out;\n };\n const before = flatten(previous);\n const after = flatten(next);\n let added = 0;\n let removed = 0;\n for (const k of after) if (!before.has(k)) added += 1;\n for (const k of before) if (!after.has(k)) removed += 1;\n return { added, removed };\n}\n\n/** Total fingerprints held in a baseline, across every file. */\nexport function countFingerprints(baseline: Baseline): number {\n let n = 0;\n for (const prints of Object.values(baseline.entries)) n += prints.length;\n return n;\n}\n","/**\n * `--since <ref>`: which pages changed, in absolute-path terms the engine can\n * compare against a discovered `PageFile` (ADR 01040).\n *\n * Two invocations, both through the injected `ExecFn` so the suite never runs\n * git. `rev-parse --show-toplevel` doubles as the is-this-a-repo check and\n * supplies the anchor the diff's paths are relative to.\n *\n * The anchor is the whole point. `git diff --name-only` prints paths relative\n * to the repository top level, while `PageFile.file` is relative to the\n * *discovery* root — the two differ whenever the config lives in a\n * subdirectory. Comparing them directly does not throw; it simply matches\n * nothing, so every page reads as unchanged and the run exits 0 having\n * evaluated nothing. Reconciling in absolute space is what makes that\n * impossible rather than merely unlikely.\n */\nimport { resolve } from \"node:path\";\nimport { DocevalsError } from \"../types.js\";\nimport { outputTail } from \"../../shared/exec.js\";\nimport type { ExecFn, ExecResult } from \"../graders/types.js\";\n\n/** git can be slow on a cold index, but not this slow. */\nconst GIT_TIMEOUT_MS = 30_000;\n\n/**\n * The comparison key for one absolute path.\n *\n * Lowercased on win32, and that is load-bearing rather than defensive: git\n * reports the case recorded in its index, fast-glob reports the case on disk,\n * and the two sources can also disagree about the drive letter. None of those\n * differences is a different file on Windows, but every one of them is a\n * different string.\n *\n * Keyed on the platform rather than on case-insensitivity in general, because\n * the latter cannot be detected reliably — a case-insensitive APFS or a\n * case-sensitive Windows volume both exist. This is the Windows-specific\n * behaviour the code actually implements, not a claim about every such\n * filesystem.\n */\nexport function changedKey(absPath: string): string {\n const abs = resolve(absPath);\n return process.platform === \"win32\" ? abs.toLowerCase() : abs;\n}\n\n/** `outputTail` caps at 400 chars; git stderr on a broken repo is unbounded. */\nfunction stderrOf(result: ExecResult): string {\n return outputTail(result) || \"(no output)\";\n}\n\n/**\n * Run one git invocation, raising the two failures whose repair is the same\n * whichever command produced them. A non-zero exit is left to the caller,\n * because *that* repair differs: a bad repository and a bad ref send the\n * reader to different places.\n */\nasync function git(\n exec: ExecFn,\n args: string[],\n root: string,\n): Promise<ExecResult> {\n const result = await exec(args, { cwd: root, timeoutMs: GIT_TIMEOUT_MS });\n if (result.spawnError) {\n throw new DocevalsError(\n `--since needs git on PATH: could not run git (${result.spawnError}). ` +\n `Install git, or drop --since to evaluate the whole corpus.`,\n );\n }\n if (result.timedOut) {\n throw new DocevalsError(\n `--since timed out: \\`${args.join(\" \")}\\` took longer than ` +\n `${GIT_TIMEOUT_MS / 1000}s in ${root}.`,\n );\n }\n return result;\n}\n\n/**\n * Absolute-path keys for every file that differs between `ref` and `HEAD`.\n *\n * `ref...HEAD` (three dots) diffs against the merge base, which is what a pull\n * request means by \"changed\": commits that landed on the base branch after this\n * one forked are not this branch's changes. It also means **uncommitted\n * working-tree edits are not included** — correct for CI, surprising locally.\n */\nexport async function changedFilesSince(\n ref: string,\n root: string,\n exec: ExecFn,\n): Promise<Set<string>> {\n // A ref that parses as a git option is not a ref. `--output=x` sends the diff\n // to a file and leaves stdout empty, so the changed set comes back empty and\n // the run exits 0 having scoped everything out — the silent green this flag\n // must never produce. `--` does not help: the left side of `A...B` is parsed\n // before any separator, so the shape has to be rejected outright.\n if (ref.startsWith(\"-\")) {\n throw new DocevalsError(\n `--since \"${ref}\" is not a ref: a value starting with \"-\" is read by git as ` +\n `an option, which would silently produce an empty diff.`,\n );\n }\n // Git reads an omitted left side of `A...B` as HEAD, so a blank ref diffs\n // HEAD against HEAD — exit 0, empty diff, every eval scoped out, exit 0. The\n // blank arrives by accident: `--since \"${{ github.base_ref }}\"` renders empty\n // on a push event, and an unset shell variable expands to nothing.\n if (ref.trim() === \"\") {\n throw new DocevalsError(\n `--since was given an empty ref. Git would read that as HEAD and scope the ` +\n `run to nothing, which exits 0 having checked nothing. If this came from a ` +\n `CI expression, the variable is unset on this event.`,\n );\n }\n const top = await git(exec, [\"git\", \"rev-parse\", \"--show-toplevel\"], root);\n if (top.code !== 0) {\n throw new DocevalsError(\n `--since requires a git repository, and ${root} is not a git repository ` +\n `(or git cannot read it). git said: ${stderrOf(top)}`,\n );\n }\n const topLevel = top.stdout.trim();\n\n // `-z` is mandatory. Without it, `core.quotePath` C-escapes any path with a\n // non-ASCII byte — `\"docs/caf\\303\\251.md\"` — and the escaped form matches no\n // discovered page. Nothing errors; the page is simply never evaluated.\n const diff = await git(\n exec,\n [\"git\", \"--no-pager\", \"diff\", \"--name-only\", \"-z\", `${ref}...HEAD`],\n root,\n );\n if (diff.code !== 0) {\n throw new DocevalsError(\n `--since ${ref}: git could not resolve \"${ref}...HEAD\". ` +\n `In CI this is usually a shallow clone — actions/checkout defaults to ` +\n `fetch-depth: 1, which fetches no other branch, so set fetch-depth: 0 ` +\n `(or fetch ${ref} explicitly) before using --since. ` +\n `git said: ${stderrOf(diff)}`,\n );\n }\n\n const changed = new Set<string>();\n // NUL-*terminated*, not NUL-separated: the last entry is followed by a\n // separator, so the split ends in an empty string.\n for (const rel of diff.stdout.split(\"\\0\")) {\n if (rel === \"\") continue;\n changed.add(changedKey(resolve(topLevel, rel)));\n }\n return changed;\n}\n","/**\n * `--newer-than <duration>`: which pages changed inside a window of time back\n * from now.\n *\n * A page's age is **detected, not switched**. A page git tracks, with no\n * uncommitted change in the page or in any manifest that supplied its evals,\n * takes the committer date of the last commit touching any of those files.\n * Every other page (untracked, modified, or outside a repository) takes the\n * newest mtime among them.\n *\n * The committed case is the reason this is not simply mtime. A fresh clone,\n * which is what CI runs on, stamps every file with the clone's time, so mtime\n * alone would read as \"every page just changed\". The modified case is the\n * reason it is not simply the commit date: an edit not yet committed is the\n * newest change there is, and the commit date predates it.\n *\n * Every git call goes through the injected `ExecFn`, so the suite never runs\n * git. A machine without git, or a directory outside a repository, is not an\n * error: every page is then \"any other page\" and takes its mtime.\n */\nimport { statSync } from \"node:fs\";\nimport { relative, resolve } from \"node:path\";\nimport { DocevalsError } from \"../types.js\";\nimport type { ExecFn, ExecResult } from \"../graders/types.js\";\nimport { changedKey } from \"./since.js\";\n\n/** git can be slow on a cold index, but not this slow. */\nconst GIT_TIMEOUT_MS = 30_000;\n\n/** The files that decide one page's age: the page, then its eval manifests. */\nexport interface PageAgeInput {\n /** Absolute path of the page file. */\n page: string;\n /** Absolute paths (or URLs) of the manifests that supplied its eval keys. */\n manifests: readonly string[];\n}\n\n/** What git says about the working tree, or `null` outside a repository. */\ninterface RepoState {\n topLevel: string;\n /** `changedKey`s of every file git tracks. */\n tracked: Set<string>;\n /** `changedKey`s of tracked files that differ from HEAD. */\n modified: Set<string>;\n}\n\nasync function git(\n exec: ExecFn,\n args: string[],\n cwd: string,\n): Promise<ExecResult> {\n const result = await exec(args, { cwd, timeoutMs: GIT_TIMEOUT_MS });\n if (result.timedOut) {\n throw new DocevalsError(\n `--newer-than timed out: \\`${args.join(\" \")}\\` took longer than ` +\n `${String(GIT_TIMEOUT_MS / 1000)}s in ${cwd}.`,\n );\n }\n return result;\n}\n\n/** NUL-terminated repo-relative paths to `changedKey`s. */\nfunction keysOf(stdout: string, topLevel: string): Set<string> {\n const keys = new Set<string>();\n for (const rel of stdout.split(\"\\0\")) {\n if (rel !== \"\") keys.add(changedKey(resolve(topLevel, rel)));\n }\n return keys;\n}\n\nasync function repoState(root: string, exec: ExecFn): Promise<RepoState | null> {\n const top = await git(exec, [\"git\", \"rev-parse\", \"--show-toplevel\"], root);\n // No git on PATH, or not a repository: every page takes its mtime.\n if (top.spawnError !== undefined || top.code !== 0) return null;\n const topLevel = top.stdout.trim();\n if (topLevel === \"\") return null;\n\n // `--full-name` so the paths are relative to the top level whatever the\n // working directory, and `-z` so `core.quotePath` cannot C-escape them.\n const tracked = await git(exec, [\"git\", \"ls-files\", \"-z\", \"--full-name\"], topLevel);\n if (tracked.code !== 0) return null;\n\n // Staged and unstaged edits alike. A repository with no commit has no HEAD,\n // and then every tracked file is uncommitted: the mtime rule applies.\n const diff = await git(\n exec,\n [\"git\", \"--no-pager\", \"diff\", \"--name-only\", \"-z\", \"HEAD\"],\n topLevel,\n );\n const trackedKeys = keysOf(tracked.stdout, topLevel);\n return {\n topLevel,\n tracked: trackedKeys,\n modified: diff.code === 0 ? keysOf(diff.stdout, topLevel) : trackedKeys,\n };\n}\n\n/** The newest mtime among `files`, skipping any that cannot be read (a URL). */\nfunction newestMtime(files: readonly string[]): number {\n let newest = Number.NEGATIVE_INFINITY;\n for (const file of files) {\n try {\n newest = Math.max(newest, statSync(file).mtimeMs);\n } catch {\n // A URL manifest, or a file removed mid-run, has no mtime to offer.\n }\n }\n return newest;\n}\n\n/** Epoch milliseconds of the last commit touching any of `files`, if one did. */\nasync function lastCommit(\n files: readonly string[],\n repo: RepoState,\n exec: ExecFn,\n): Promise<number | undefined> {\n const paths = files.map((f) => relative(repo.topLevel, f).replace(/\\\\/g, \"/\"));\n const log = await git(\n exec,\n [\"git\", \"--no-pager\", \"log\", \"-1\", \"--format=%ct\", \"--\", ...paths],\n repo.topLevel,\n );\n const seconds = Number.parseInt(log.stdout.trim(), 10);\n return log.code === 0 && Number.isFinite(seconds) ? seconds * 1000 : undefined;\n}\n\n/**\n * The epoch milliseconds each page last changed, in input order, by the rule\n * in this module's header.\n */\nexport async function pageAges(\n pages: readonly PageAgeInput[],\n root: string,\n exec: ExecFn,\n): Promise<number[]> {\n const repo = await repoState(root, exec);\n const ages: number[] = [];\n for (const { page, manifests } of pages) {\n const files = [page, ...manifests];\n const committed =\n repo !== null &&\n files.every((f) => {\n const key = changedKey(f);\n return repo.tracked.has(key) && !repo.modified.has(key);\n });\n const fromGit = committed ? await lastCommit(files, repo, exec) : undefined;\n ages.push(fromGit ?? newestMtime(files));\n }\n return ages;\n}\n","/**\n * Grader contract for deterministically graded evals (command and tool:*).\n * A grader receives every (page, eval) target that resolved to its kind and\n * returns normalized findings. AI grading lives in src/judge, not here.\n */\nimport type { ExecFn } from \"@hawkeyexl/inference\";\nimport type { Finding } from \"../types.js\";\nimport type { DocevalsConfig } from \"../core/config.js\";\nimport type { OptionCheck, Options } from \"./options.js\";\nimport type { ResolvedEval, ResolvedPagePlan } from \"../core/resolve.js\";\n\n/** One (page, eval) pair a grader must grade. */\nexport interface GraderTarget {\n plan: ResolvedPagePlan;\n eval: ResolvedEval;\n}\n\n// The exec seam is shared with the inference layer's subprocess provider, so\n// these types live there now. Re-exported so grader code keeps importing them\n// from one place.\nexport type { ExecFn, ExecOptions, ExecResult } from \"@hawkeyexl/inference\";\n\nexport interface GraderContext {\n targets: GraderTarget[];\n config: DocevalsConfig;\n /** Discovery root; page paths are relative to it. */\n root: string;\n exec: ExecFn;\n}\n\nexport interface Grader {\n /** Registry kind, e.g. \"command\", \"tool:regex\". */\n kind: string;\n /**\n * Reject option sets this grader cannot honour, before anything runs.\n *\n * The published vocabulary leaves `options` open on purpose, so this is the\n * \"validated by the grader at run time\" half of that contract. Without it a\n * misspelled key falls through to a default and the eval silently checks\n * something its author never wrote. Returns a message, or undefined when the\n * options are fine.\n */\n validateOptions?(options: Options): OptionCheck;\n /**\n * Targets other than `body` this grader can actually read.\n *\n * Declared by the grader rather than listed in the engine, so adding a\n * grader that reads `target` is a change in one file. Absent means \"body\n * only\", which is every grader that predates `target` — and the engine\n * turns any other request into an error rather than letting the grader\n * quietly measure the whole page (ADR 01033).\n */\n targets?: readonly string[];\n /**\n * batch: one external invocation covers all targets;\n * per-file: one invocation per target.\n */\n mode: \"batch\" | \"per-file\";\n grade(ctx: GraderContext): Promise<Finding[]>;\n}\n\n/**\n * Split targets into groups that share an eval configuration. A batch\n * grader runs one invocation per group so that (a) two same-kind evals\n * on one page each get their own run and correct finding attribution, and\n * (b) per-page option overrides are honored instead of the first target's\n * options being applied to everyone.\n */\n/**\n * A plain object with its keys in sorted order, recursively, so that\n * `JSON.stringify` describes the value rather than the order it was written\n * in. `undefined` passes through so an absent option stays absent in the key.\n */\nfunction sortedForKey(value: unknown): unknown {\n if (value === undefined || value === null) return value;\n if (Array.isArray(value)) return value.map(sortedForKey);\n if (typeof value !== \"object\") return value;\n const entries = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(entries).sort()) {\n out[k] = sortedForKey(entries[k]);\n }\n return out;\n}\n\nexport function groupTargetsByEval(targets: GraderTarget[]): GraderTarget[][] {\n const groups = new Map<string, GraderTarget[]>();\n for (const t of targets) {\n const key = JSON.stringify([\n t.eval.name,\n // Key order, not just content: `resolve.ts` rebuilds `options` per page\n // by spread, so insertion order follows each page's own YAML. Two pages\n // declaring the same options in a different order used to hash\n // differently and land in separate groups, so a batch grader made one\n // invocation per page instead of one per configuration. Sorting makes\n // the key describe the configuration rather than how it was typed.\n sortedForKey(t.eval.options),\n t.eval.timeoutMs ?? null,\n t.eval.severity,\n ]);\n const list = groups.get(key) ?? [];\n list.push(t);\n groups.set(key, list);\n }\n return [...groups.values()];\n}\n","/**\n * Judge cache key composition. The cache itself is the inference library's\n * `JsonCache`; what stays here is what only manni docevals can decide — what\n * invalidates an entry: provider, model, prompt version, run count,\n * temperature, the page body, and the resolved eval.\n */\nimport { buildCacheKey, JsonCache, sha256 } from \"@hawkeyexl/inference\";\nimport type { JudgeRun } from \"../types.js\";\nimport type { ResolvedEval } from \"../core/resolve.js\";\nimport { PROMPT_VERSION } from \"./prompt.js\";\n\nexport { sha256 };\n\ndeclare const judgeCacheBodyBrand: unique symbol;\n\n/**\n * The output of `judgeCacheBody`, and the only thing `cacheKey` accepts as a\n * body. A brand rather than a wrapper object: it costs nothing at runtime and\n * the value is still an ordinary string everywhere else.\n */\nexport type JudgeCacheBody = string & { readonly [judgeCacheBodyBrand]: true };\n\n/**\n * A judge cache that refuses to persist an ensemble containing an errored run.\n *\n * The library's `runEnsemble` caches unconditionally — it has no way to know\n * whether an error is a property of the request or of the moment. Here we do:\n * an error is an infrastructure failure (VRAM exhausted, rate limited,\n * connection dropped), never a verdict about the page. Writing one to the cache\n * turns a transient outage into a permanent answer, and `--no-cache` becomes\n * the only way out of a state nothing explains.\n *\n * That is worst for a committed cache, whose whole purpose is to let CI replay\n * real verdicts with no provider reachable. Caching an error there commits the\n * outage: every future run replays it, the evals sit in human-review forever,\n * and the fixtures look valid the entire time. This was not hypothetical — a\n * local run at concurrency 4 exhausted VRAM and wrote 65 errored ensembles into\n * `docs/.manni-docevals-cache/` (ADR 01038).\n *\n * Subclassed rather than wrapped because `JsonCache` has private fields, so a\n * structurally-identical object does not satisfy its type.\n */\nexport class VerdictCache extends JsonCache<JudgeRun[]> {\n /** An ensemble is cacheable only if every run produced a verdict. */\n private static usable(runs: JudgeRun[]): boolean {\n return runs.every((r) => r.error === undefined && r.verdict !== undefined);\n }\n\n override set(key: string, value: JudgeRun[]): void {\n if (!VerdictCache.usable(value)) return;\n super.set(key, value);\n }\n\n /**\n * Reading applies the same predicate, which is what makes the property\n * total rather than merely forward-looking.\n *\n * Guarding only the write cannot heal an entry this class did not write —\n * and those exist: the 65 errored ensembles that prompted ADR 01038 were on\n * disk before it, and had to be deleted by hand. A committed cache is\n * exactly the population at risk, because CI replays it with no provider\n * reachable, so a poisoned entry there is a verdict no future run can\n * dislodge. Treating it as a miss costs one re-judge and converges;\n * inheriting `get` unchanged never does.\n *\n * The predicate also matches the library's own definition rather than ours:\n * `computeConsensus` counts a run with no `verdict` as an error vote, so an\n * entry with neither `verdict` nor `error` — reachable through a truncated\n * write to these hand-editable JSON files — would otherwise replay as a\n * permanent human-review with nothing explaining why.\n */\n override get(key: string): JudgeRun[] | undefined {\n const hit = super.get(key);\n if (hit === undefined) return undefined;\n return VerdictCache.usable(hit) ? hit : undefined;\n }\n}\n\n/**\n * The exact body string the judge keys on: the chunk budget, then the selected\n * text.\n *\n * Exported because anything that wants to know whether a verdict is cached has\n * to reproduce this byte for byte, and reproducing it by hand is how the\n * cache-completeness script silently computed keys that matched nothing —\n * `scripts/check-docs-cache.mjs` passed the raw page body while the judge had\n * started prefixing the budget. A helper both call is the only version of this\n * that cannot drift.\n *\n * The return type is branded, and `cacheKey` takes only that brand, so a\n * caller that hands over a raw page body no longer compiles. Reproducing the\n * composition by hand used to be a silent cache miss; now it is a type error,\n * which is the whole point of having one helper.\n */\nexport function judgeCacheBody(chunkChars: number, text: string): JudgeCacheBody {\n return `chunk${String(chunkChars)}\\n${text}` as JudgeCacheBody;\n}\n\nexport function cacheKey(\n provider: string,\n model: string,\n runs: number,\n temperature: number,\n body: JudgeCacheBody,\n ev: ResolvedEval,\n): string {\n const evalFingerprint = JSON.stringify({\n assertion: ev.assertion,\n evidence: ev.evidence,\n examples: ev.examples,\n type: ev.type,\n });\n return buildCacheKey([\n provider,\n model,\n `v${PROMPT_VERSION}`,\n `r${runs}`,\n `t${temperature}`,\n // Pre-hashed: page bodies are large and key parts should stay short.\n sha256(body),\n sha256(evalFingerprint),\n ]);\n}\n","/**\n * Judge prompt construction. The system prompt sets a binary rubric with an\n * explicit `partial` escape valve; the user content carries the assertion,\n * evidence hint, pass/fail example anchors, and the page body with\n * frontmatter and MDX noise stripped.\n *\n * PROMPT_VERSION is part of every cache key — bump it whenever the prompt\n * changes so stale cached verdicts never survive a prompt revision.\n */\nimport type { ResolvedEval } from \"../core/resolve.js\";\nimport { partLabel } from \"../core/split.js\";\n\nexport const PROMPT_VERSION = 4;\n\nexport const JUDGE_SYSTEM_PROMPT = [\n \"You are a meticulous technical documentation judge. You evaluate whether a\",\n \"documentation page satisfies a specific assertion.\",\n \"\",\n \"Rules:\",\n \"- Judge ONLY the stated assertion against the supplied page content. Do not\",\n \" invent requirements the assertion does not state.\",\n '- \"match\" is \"pass\" only when the assertion is fully satisfied by the page.',\n '- Use \"partial\" when the page partially satisfies the assertion.',\n '- Use \"fail\" when the page does not satisfy the assertion.',\n \"- Quote the specific page text you relied on in \\\"observed\\\". If the page\",\n \" lacks relevant content, say so explicitly.\",\n \"- Be conservative with confidence: reserve values above 0.9 for verdicts a\",\n \" careful human reviewer would certainly agree with.\",\n \"Respond with a JSON object matching the provided schema.\",\n].join(\"\\n\");\n\n/**\n * Strip MDX imports/exports and comments; keep JSX text content and markdown.\n * Fence-aware: lines inside ``` / ~~~ code blocks are page content the judge\n * must see verbatim (a code sample's `import` line is evidence, not MDX noise).\n */\nexport function cleanBody(body: string): string {\n const out: string[] = [];\n let fence: string | null = null;\n for (const line of body.split(\"\\n\")) {\n const marker = /^(\\s*)(```+|~~~+)/.exec(line)?.[2];\n if (fence) {\n out.push(line);\n if (marker?.startsWith(fence)) fence = null;\n continue;\n }\n if (marker !== undefined) {\n fence = marker;\n out.push(line);\n continue;\n }\n out.push(\n line\n .replace(/\\{\\/\\*[\\s\\S]*?\\*\\/\\}/g, \"\")\n .replace(/<!--[\\s\\S]*?-->/g, \"\")\n .replace(/^(import|export)\\s.*$/, \"\"),\n );\n }\n // Comments spanning multiple lines are left in place — stray comment text\n // is harmless noise, whereas a post-join strip would reach into fences.\n return out.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\").trim();\n}\n\nexport function buildUserContent(\n ev: ResolvedEval,\n body: string,\n targetLabel = \"body\",\n): string {\n const parts: string[] = [\n `# Assertion`,\n ev.assertion ?? \"\",\n ];\n if (ev.evidence) {\n parts.push(\"\", `# Where to look`, ev.evidence);\n }\n if (ev.examples?.pass || ev.examples?.fail) {\n parts.push(\"\", \"# Anchors\");\n // Anchors widened to lists with the manni:evals vocabulary. Interpolating\n // the array would join it with commas and present several distinct\n // examples to the judge as one run-on sentence.\n for (const anchor of ev.examples.pass ?? []) {\n parts.push(`A passing page: ${anchor}`);\n }\n for (const anchor of ev.examples.fail ?? []) {\n parts.push(`A failing page: ${anchor}`);\n }\n }\n // Name what the judge is looking at. Told only \"page content\" while being\n // handed a frontmatter block or a companion file, a judge reasons about the\n // wrong thing and says so confidently.\n //\n // Only the page body carries MDX noise worth stripping. Running `cleanBody`\n // over a companion source file would delete its `import`/`export` lines —\n // the judge would then be asked whether code exports something it can no\n // longer see.\n const isBody = targetLabel === \"body\";\n parts.push(\n \"\",\n isBody ? \"# Page content\" : `# Page content (${targetLabel})`,\n \"\",\n isBody ? cleanBody(body) : body,\n );\n return parts.join(\"\\n\");\n}\n\n/**\n * Gathering evidence from one part of a page too long to judge in one call.\n *\n * Why a two-stage shape rather than judging each part and merging verdicts:\n * merging is unsound. \"The page documents the --force flag\" is satisfied if\n * *any* part documents it; \"the page never promises unreleased features\" is\n * violated if *any* part promises one. One needs OR across parts, the other\n * AND, and nothing in an assertion's text reliably says which — so a merge\n * rule has to guess, and guesses wrong quietly.\n *\n * Gathering evidence sidesteps the quantifier entirely. Each part contributes\n * what it saw; one judge then answers the original question against the whole\n * collection, exactly as it would have with the page in front of it. The\n * verdict contract is unchanged — still one `JudgeVerdict` per run — so\n * consensus, zones, the response cache, human review and `calibrate` need to\n * know nothing about any of this.\n */\nexport const EVIDENCE_SYSTEM_PROMPT = [\n \"You are gathering evidence from one part of a documentation page so that a\",\n \"judge can later evaluate an assertion about the whole page.\",\n \"\",\n \"Rules:\",\n \"- Do NOT decide whether the assertion holds. You are seeing one part; the\",\n \" part that settles it may be elsewhere.\",\n \"- Quote page text verbatim. Quote anything that supports the assertion and\",\n \" anything that contradicts it.\",\n \"- Quote only what bears on this assertion. An empty list is the right\",\n \" answer for a part that says nothing about it.\",\n \"Respond with a JSON object matching the provided schema.\",\n].join(\"\\n\");\n\nexport const EVIDENCE_SCHEMA = {\n type: \"object\",\n required: [\"supports\", \"contradicts\"],\n properties: {\n supports: { type: \"array\", items: { type: \"string\" } },\n contradicts: { type: \"array\", items: { type: \"string\" } },\n },\n additionalProperties: false,\n} as const;\n\nexport interface PartEvidence {\n supports: string[];\n contradicts: string[];\n}\n\nexport function buildEvidenceUser(\n ev: ResolvedEval,\n chunk: string,\n part: { index: number; total: number },\n): string {\n return [\n \"# Assertion (do not judge it — only gather evidence)\",\n ev.assertion ?? \"\",\n ...(ev.evidence ? [\"\", \"# Where to look\", ev.evidence] : []),\n \"\",\n `# Page content (${partLabel(part.index, part.total)})`,\n \"\",\n chunk,\n ].join(\"\\n\");\n}\n\n/**\n * Render gathered evidence as the \"page content\" a judge sees.\n *\n * The judge is told plainly that it is reading extracts rather than the page,\n * because a judge that believes it saw everything will happily report that\n * something is absent when it was merely in a part that contributed nothing.\n */\nexport function renderEvidence(parts: PartEvidence[], total: number): string {\n const supports = parts.flatMap((p) => p.supports);\n const contradicts = parts.flatMap((p) => p.contradicts);\n const lines = [\n `The page was too long to read in one pass, so it was read in ${String(total)} parts`,\n \"and the passages bearing on this assertion were collected below. Judge the\",\n \"assertion against this evidence. Absence of a quotation is weak evidence of\",\n \"absence in the page: parts that bore on nothing contributed nothing.\",\n \"\",\n \"## Passages supporting the assertion\",\n ...(supports.length > 0 ? supports.map((q) => `- ${q}`) : [\"(none)\"]),\n \"\",\n \"## Passages contradicting the assertion\",\n ...(contradicts.length > 0 ? contradicts.map((q) => `- ${q}`) : [\"(none)\"]),\n ];\n return lines.join(\"\\n\");\n}\n","/**\n * Safeguard layer 1: a model judging its own output shows self-preference\n * bias (proposal 0046, § The self-preference-bias check).\n *\n * Two axes, reported apart because the remedy differs.\n *\n * - **Content.** The judge is among the machines attributed for what the\n * eval's `target` reads: `provenance` for `body` (the default), the `fields`\n * of `meta-provenance` for `frontmatter`, both for `raw`, and none for a\n * companion file, which carries its own record if it is a page. The check\n * covers the whole body, because `target` has no form that names lines.\n * - **Criterion.** A `meta-provenance` entry for the judge lists this eval's\n * id under `evals`: the judge proposed the assertion it is now grading.\n *\n * Content wins when both hold. Neither is a failure: bias skews a verdict, it\n * does not prevent one forming, so ADR 01022's \"no verdict fails\" rule does\n * not apply, and erroring would punish a single-model corpus with no second\n * provider to reach for.\n */\nimport { metaProvenanceEntries, provenanceEntries } from \"../../meta/internal.js\";\nimport type { ResolvedEval, ResolvedPagePlan } from \"../core/resolve.js\";\nimport { DEFAULT_TARGET } from \"../core/target.js\";\nimport type { EvalResult } from \"../types.js\";\n\nexport type SelfPreference = NonNullable<EvalResult[\"selfPreference\"]>;\n\n/** A self-preference mark, and the sentence that explains it. */\nexport interface SelfPreferenceFinding extends SelfPreference {\n /** Without the file: the warning prefixes it, a problem carries it. */\n message: string;\n}\n\nconst remedy = (evalId: string): string =>\n `, and it is also the judge. Self-judging favors the author; give \"${evalId}\" a model: of its own.`;\n\n/** Whether the eval's judge, `model`, produced what the eval grades or the eval itself. */\nexport function selfPreferenceOf(\n plan: ResolvedPagePlan,\n ev: ResolvedEval,\n model: string,\n): SelfPreferenceFinding | undefined {\n const data = plan.page.frontmatter.data;\n const meta = metaProvenanceEntries(data[\"meta-provenance\"]).filter(\n (e) => e[\"generated-by\"] === model,\n );\n const target = ev.target ?? DEFAULT_TARGET;\n const readsBody = target === \"body\" || target === \"raw\";\n const readsFields = target === \"frontmatter\" || target === \"raw\";\n\n if (readsBody && provenanceEntries(data.provenance).some((e) => e[\"generated-by\"] === model)) {\n return {\n axis: \"content\",\n model,\n message: `provenance names ${model} for the body this eval grades${remedy(ev.name)}`,\n };\n }\n if (readsFields && meta.some((e) => e.fields.length > 0)) {\n return {\n axis: \"content\",\n model,\n message: `meta-provenance names ${model} for the fields this eval grades${remedy(ev.name)}`,\n };\n }\n if (meta.some((e) => e.evals.includes(ev.name))) {\n return {\n axis: \"criterion\",\n model,\n message: `meta-provenance says ${model} proposed \"${ev.name}\"${remedy(ev.name)}`,\n };\n }\n return undefined;\n}\n","/**\n * Pipeline orchestration: discover → resolve → deterministic graders (cheap\n * first, the book's hybrid pattern) → AI judge → aggregate → report.\n *\n * The judge is injected (`options.judge`) so the deterministic pipeline and\n * tests run without any provider configured.\n */\nimport { DocevalsError } from \"../types.js\";\nimport type {\n EvalResult,\n Finding,\n RunReport,\n SuiteSummary,\n} from \"../types.js\";\nimport { loadRunConfig, type DocevalsConfig } from \"./config.js\";\nimport {\n grantsFor,\n NOT_GRANTED_REASON,\n type ExecutionGrant,\n} from \"../../shared/execution.js\";\nimport { discoverPages } from \"./discover.js\";\nimport { withExternalMetadata } from \"./external.js\";\nimport { resolvePages, type EvalLocation, type ResolvedPagePlan } from \"./resolve.js\";\nimport {\n applyBaseline,\n buildBaseline,\n countFingerprints,\n diffBaselines,\n readBaseline,\n writeBaselineFile,\n DEFAULT_BASELINE_PATH,\n type Baseline,\n type FingerprintContext,\n} from \"./baseline.js\";\nimport { changedFilesSince, changedKey } from \"./since.js\";\nimport { pageAges } from \"./newer-than.js\";\nimport { parseDuration } from \"../../shared/duration.js\";\nimport { graderFor } from \"../graders/registry.js\";\nimport { assertRegisteredGraders, checkFeasibility } from \"./feasibility.js\";\nimport { realExec } from \"../../shared/exec.js\";\nimport { groupTargetsByEval, type ExecFn, type GraderTarget } from \"../graders/types.js\";\nimport { sha256 } from \"../judge/cache.js\";\nimport { isTurnBudgetSkip } from \"../judge/budget.js\";\nimport { selfPreferenceOf } from \"../judge/self-preference.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { resolve } from \"node:path\";\n\nexport interface RunProblem {\n file: string;\n message: string;\n level: \"error\" | \"warning\";\n line?: number;\n}\n\n/** RunReport plus resolution problems (kept off the core type for reporters). */\nexport interface EngineReport extends RunReport {\n problems: RunProblem[];\n /** Present only when a baseline was read or written (ADR 01017). */\n baseline?: BaselineOutcome[\"summary\"];\n /**\n * Present only under `--since` (ADR 01040). `pagesTotal` is the whole\n * discovered corpus — `pages` above stays that number too — and\n * `pagesSelected` is the count of pages that **changed since the ref**,\n * which are the only pages this run graded. Consumers reading this from\n * `--format json` should treat it as the size of the change set, matching\n * what the reporters print.\n */\n since?: { ref: string; pagesSelected: number; pagesTotal: number };\n /**\n * Present only under `--newer-than`. `pagesSelected` is the count of pages\n * this run graded: those that changed inside the window and, when `--since`\n * is given too, since the ref as well. Both blocks then carry that one count.\n */\n newerThan?: { duration: string; pagesSelected: number; pagesTotal: number };\n}\n\nexport interface JudgeOptions {\n provider?: string;\n model?: string;\n /** Run inference on this machine, with llama-cpp, over any configured or eval-level provider. */\n local?: boolean;\n runs?: number;\n noCache?: boolean;\n /** Stop after this many uncached inference calls (ADR 01019). */\n maxTurns?: number | null;\n /** Characters of content per judge call; longer content is read in parts. */\n chunkChars?: number;\n}\n\n/** Injected AI judging stage; absent → ai-graded evals are skipped. */\nexport type JudgeFn = (\n targets: GraderTarget[],\n config: DocevalsConfig,\n options: JudgeOptions,\n) => Promise<EvalResult[]>;\n\n/** Injected script-generation stage (Phase 4); absent → missing commands error. */\n/** Why a command eval with no command was not generated for: no provider. */\nconst GENERATION_UNAVAILABLE =\n \"no command and script generation unavailable (configure a provider or run `manni docevals generate`)\";\n\n/** One eval generation could not persist a command for, and why. */\nexport interface GenerationRefusal {\n file: string;\n evalName: string;\n message: string;\n}\n\nexport type GenerateFn = (\n targets: GraderTarget[],\n config: DocevalsConfig,\n options: JudgeOptions,\n) => Promise<{\n generatedPaths: string[];\n /** Why no provider could be had, when generation needed one and got none. */\n unavailable?: string;\n /**\n * Evals whose command reference had nowhere to go (proposal 0047): the\n * manifest that owns the page's evals joins on a field the page lacks. The\n * engine reports each as an errored result in the writer's own sentence,\n * rather than as a generation that failed.\n */\n refusals?: GenerationRefusal[];\n}>;\n\nexport interface RunOptions {\n configPath?: string;\n /** Preloaded config; skips loading/validating configPath a second time. */\n config?: DocevalsConfig;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Files, directories and globs, cwd-relative; empty means the collections. */\n paths?: string[];\n /** `--collection <name>`, repeatable (proposal 0041). */\n collection?: string[];\n /** `--exclude <glob>`, repeatable. */\n exclude?: string[];\n cwd?: string;\n deterministicOnly?: boolean;\n aiOnly?: boolean;\n /**\n * Run only these grants, of those the config holds. Absent keeps them all;\n * `[]` runs nothing. Never widens past `execution.allow`.\n */\n allowExecution?: ExecutionGrant[];\n /** `false` clears every grant for this run. */\n execution?: boolean;\n /** Run only these evals by name. Empty match is a usage error (ADR 01018). */\n evalNames?: string[];\n /** Run only evals belonging to this suite. */\n suite?: string;\n /**\n * Evaluate only pages that differ between this ref and HEAD. Unlike\n * `evalNames`, an empty match is *not* a usage error (ADR 01040).\n */\n since?: string;\n /**\n * Evaluate only pages whose file or eval manifest changed within this\n * duration back from now, such as `7d`. A committed page's age is its last\n * commit's date; any other page's is its mtime. With `since`, a page must\n * satisfy both. Like `since`, an empty match is not a usage error.\n */\n newerThan?: string;\n /**\n * Baseline in four states, like the metadata tool's: `undefined` leaves the config in\n * charge, a string names a file, `true` means \"use the resolved path even if\n * the config names none\", and `false` disables it outright.\n */\n baseline?: string | boolean;\n /** Record the run's findings as the new baseline. `true` uses the resolved path. */\n writeBaseline?: string | boolean;\n /**\n * Stamped into a written baseline's `generatedWith`, for diagnosis only. The\n * engine is a library entry point and cannot read its own package.json in a\n * bundle, so the CLI supplies it rather than the engine guessing.\n */\n toolVersion?: string;\n generate?: boolean;\n failOnReview?: boolean;\n judgeOptions?: JudgeOptions;\n exec?: ExecFn;\n judge?: JudgeFn;\n generateScripts?: GenerateFn;\n}\n\n/**\n * Why this eval's `target` cannot be served, or `undefined` when it can.\n *\n * `body` is what every deterministic grader already reads, so naming it\n * explicitly is a no-op rather than an error.\n */\nfunction unsupportedTarget(\n ev: ResolvedPagePlan[\"evals\"][number],\n): string | undefined {\n const target = ev.target;\n if (target === undefined || target === \"body\") return undefined;\n const grader = graderFor(ev.grader);\n const named = typeof target === \"string\" ? target : target.path;\n if (grader?.targets?.includes(typeof target === \"string\" ? target : \"file\")) {\n return undefined;\n }\n return (\n `grader ${ev.grader} cannot read target \"${named}\" — it grades the page ` +\n `body. Use the ai grader for this target, or drop the target.`\n );\n}\n\nfunction skippedResult(\n plan: ResolvedPagePlan,\n ev: ResolvedPagePlan[\"evals\"][number],\n reason: string,\n): EvalResult {\n return {\n evalName: ev.name,\n type: ev.type,\n grader: ev.grader,\n file: plan.page.file,\n outcome: \"skipped\",\n skipReason: reason,\n durationMs: 0,\n };\n}\n\n/**\n * Collision-proof composite key for (file, eval) maps — file paths may\n * contain any character, so field boundaries must be unambiguous.\n */\nfunction resultKey(file: string, evalName: string): string {\n return JSON.stringify([file, evalName]);\n}\n\nfunction groupFindings(findings: Finding[]): Map<string, Finding[]> {\n const map = new Map<string, Finding[]>();\n for (const f of findings) {\n const key = resultKey(f.file, f.evalName);\n const list = map.get(key) ?? [];\n list.push(f);\n map.set(key, list);\n }\n return map;\n}\n\n/**\n * Record each result's suite on the result itself.\n *\n * The mapping is already computed here for the summaries; without stamping it,\n * a reporter that wants to group by suite (JUnit) has no way to, and a\n * consumer of `--format json` sees pass rates per suite with no way to tell\n * which results produced them.\n */\nfunction stampSuites(\n results: EvalResult[],\n plans: ResolvedPagePlan[],\n): void {\n const suiteOf = new Map<string, string>();\n const weightOf = new Map<string, number>();\n const locationOf = new Map<string, EvalLocation>();\n for (const plan of plans) {\n for (const ev of plan.evals) {\n const key = resultKey(plan.page.file, ev.name);\n suiteOf.set(key, ev.suite);\n weightOf.set(key, ev.weight);\n locationOf.set(key, ev.location);\n }\n }\n for (const r of results) {\n const key = resultKey(r.file, r.evalName);\n r.suite = suiteOf.get(key) ?? \"default\";\n // A result with no matching plan entry cannot be weighted from one, so it\n // counts as 1 rather than 0 — dropping it out of the denominator would let\n // an unresolvable eval quietly raise a suite's rate.\n r.weight = weightOf.get(key) ?? 1;\n // A result with no plan entry has no declaring entry to point at, so it\n // names its page alone, as every result did before locations.\n r.location = locationOf.get(key) ?? { file: r.file };\n }\n}\n\nexport interface BaselineOutcome {\n results: EvalResult[];\n /** Present only when a baseline was read or written. */\n summary?: {\n path: string;\n recorded: number;\n suppressed: number;\n stale: number;\n written?: { added: number; removed: number; total: number };\n };\n}\n\n/**\n * Read, apply, and optionally re-record the findings baseline (ADR 01017).\n *\n * The path is resolved once, here, and both reading and writing use it. That is\n * deliberate: a bare `--write-baseline` must record into the *configured* path,\n * because a repo that points `baseline:` somewhere custom would otherwise\n * record into a file nothing ever reads — and the ratchet would silently do\n * nothing at all. The metadata tool names this exact trap.\n */\nfunction resolveBaseline(\n results: EvalResult[],\n config: DocevalsConfig,\n options: RunOptions,\n cwd: string,\n problems: RunProblem[],\n): BaselineOutcome {\n const wants = options.writeBaseline !== undefined && options.writeBaseline !== false;\n if (options.baseline === false && !wants) return { results };\n\n // Read and write paths resolve separately. Sharing one made\n // `--baseline old.json --write-baseline new.json` read old.json and then\n // overwrite it, never creating new.json.\n //\n // A bare `--baseline` falls back to the configured path and then the\n // default. `--write-baseline` does NOT force that fallback on the *read*\n // side: `--write-baseline snapshot.json` in a repo with no `baseline:` key\n // should not silently subtract a file the user never named.\n const readFallback =\n config.baseline ?? (options.baseline === true ? DEFAULT_BASELINE_PATH : null);\n const applyFrom =\n options.baseline === false\n ? null\n : typeof options.baseline === \"string\"\n ? options.baseline\n : readFallback;\n const writeTo = !wants\n ? null\n : typeof options.writeBaseline === \"string\"\n ? options.writeBaseline\n : (config.baseline ?? DEFAULT_BASELINE_PATH);\n const configured = writeTo ?? applyFrom;\n if (configured === null) return { results };\n\n // Relative to the config's directory, not the working directory: the file is\n // committed beside the config, and a run from a subdirectory has to find the\n // same one.\n const ctx: FingerprintContext = { base: config.configDir, runBase: cwd };\n // A baseline that cannot be parsed must not block the one command documented\n // to repair it. Reading unconditionally made `--write-baseline` throw the\n // very error whose message recommends running it.\n const read = (from: string): Baseline | null => {\n try {\n return readBaseline(resolve(config.configDir, from), from);\n } catch (e) {\n if (!wants) throw e;\n problems.push({\n file: from,\n message: `${errorMessage(e)} — re-recording over it.`,\n level: \"warning\",\n });\n return null;\n }\n };\n\n // What gets subtracted from this run's findings. Null under --no-baseline.\n const previous = applyFrom === null ? null : read(applyFrom);\n // What is about to be overwritten. This is what `removed` must be measured\n // against — not `previous`, which may be a different file or, under\n // --no-baseline, deliberately unread. Measuring the diff against the wrong\n // prior silently reported `-0` for a re-record that dropped everything.\n const overwriting =\n writeTo === null ? null : writeTo === applyFrom ? previous : read(writeTo);\n\n let out = results;\n let recorded = 0;\n let suppressed = 0;\n let stale = 0;\n if (previous && options.baseline !== false) {\n const applied = applyBaseline(results, previous, ctx);\n out = applied.results;\n recorded = applied.recorded;\n suppressed = applied.suppressed;\n stale = applied.stale;\n }\n\n // `writeTo` is null exactly when nothing is being recorded.\n if (!wants || writeTo === null) {\n return {\n results: out,\n summary: { path: configured, recorded, suppressed, stale },\n };\n }\n\n // Recorded from the *unsuppressed* results: a re-record describes what the\n // corpus contains now, not what this run happened to still be complaining\n // about after the previous baseline was subtracted.\n const next = buildBaseline(results, options.toolVersion ?? \"unknown\", ctx);\n writeBaselineFile(resolve(config.configDir, writeTo), next, writeTo);\n const { added, removed } = diffBaselines(overwriting, next);\n // Apply the baseline this run just wrote, not the one it replaced. Recording\n // today's findings *is* declaring them the accepted state, so a recording run\n // has nothing new left to fail on. Reporting them as failures anyway would\n // make `--write-baseline` a command you always have to `|| true`, which is a\n // reliable way to lose the exit code that matters on the next run.\n const accepted = applyBaseline(results, next, ctx);\n // Writing a baseline nothing will read is the same silent-nothing-happens\n // failure as recording into the wrong path: the command succeeds, the file\n // appears, and the next run ignores it. Say so where the user is looking.\n // Fires whenever an ordinary run would not read back what was just written:\n // no `baseline:` at all, or a `--write-baseline <path>` pointing somewhere\n // the config does not name.\n if (config.baseline !== writeTo) {\n problems.push({\n file: writeTo,\n message:\n `Recorded ${writeTo}, but \\`baseline:\\` in ${config.configPath} is ` +\n `${config.baseline === null ? \"not set\" : `\"${config.baseline}\"`}. ` +\n `An ordinary run will not read this file — point the key at it, or pass --baseline ${writeTo}.`,\n level: \"warning\",\n });\n }\n return {\n results: accepted.results,\n summary: {\n path: configured,\n recorded,\n suppressed,\n stale,\n written: { added, removed, total: countFingerprints(next) },\n },\n };\n}\n\n/**\n * Narrow each plan's evals to the requested names and/or suite, in place.\n *\n * Returns whether a filter was applied, which is what suspends suite\n * enforcement downstream. A filter matching nothing is a usage error rather\n * than a green run over zero evals — the same contract `discoverPages` already\n * enforces for an empty input set (ADR 01018).\n */\nexport function applySelection(\n plans: ResolvedPagePlan[],\n config: DocevalsConfig,\n options: { evalNames?: string[]; suite?: string },\n /**\n * Whether a match must be something the run would actually grade.\n *\n * True for `run`, where a filter matching only skipped work would exit 0\n * having executed nothing. False for `list`, which executes nothing by\n * design — showing that an eval resolves but is skipped is the answer it\n * exists to give, and throwing there breaks the command the run's own error\n * message points at.\n */\n requireRunnable = true,\n): boolean {\n const names = options.evalNames?.filter((n) => n.trim() !== \"\") ?? [];\n const suite = options.suite;\n if (names.length === 0 && suite === undefined) return false;\n\n if (suite !== undefined && !(suite in config.suites)) {\n throw new DocevalsError(\n `--suite \"${suite}\" is not a defined suite. Defined: ${\n Object.keys(config.suites).sort().join(\", \") || \"(none)\"\n }`,\n );\n }\n const wanted = new Set(names);\n\n // Counts only evals that will actually be graded. Counting evals on a\n // skipped page made `--eval x` exit 0 over a run that executed nothing,\n // which is the outcome ADR 01018 makes a usage error one typo away.\n let matched = 0;\n for (const plan of plans) {\n const runnable = !plan.skip && !plan.problems.some((p) => p.level === \"error\");\n plan.evals = plan.evals.filter((ev) => {\n const byName = wanted.size === 0 || wanted.has(ev.name);\n // Match the suite an eval *reports under*, not the membership list in\n // `config.suites[x].evals`. A page inherits its suite from `eval-suite`\n // or `defaults.suite` and stamps it on every eval it carries, including\n // page-inline ones the membership list never mentions — so filtering on\n // the list would select evals that report under a different suite than\n // the one asked for, and miss ones that report under it.\n const bySuite = suite === undefined || ev.suite === suite;\n const keep = byName && bySuite;\n if (keep && (!requireRunnable || (runnable && !ev.skip))) matched += 1;\n return keep;\n });\n }\n\n if (matched === 0) {\n const asked = [\n names.length > 0 ? `--eval ${names.join(\", \")}` : \"\",\n suite === undefined ? \"\" : `--suite ${suite}`,\n ]\n .filter(Boolean)\n .join(\" and \");\n throw new DocevalsError(\n `${asked} matched no evals that would run on the pages selected. Nothing ` +\n `would have been checked — the name may be wrong, or every page carrying ` +\n `it may be skipped. Run \\`manni docevals list\\` with the same filter to ` +\n `see the resolved plan.`,\n );\n }\n return true;\n}\n\n/**\n * Narrow each plan to the pages that changed, in place (ADR 01040).\n *\n * A page changed when its own file did, or when a manifest that supplied one\n * of its eval keys did. A corpus that keeps its evals in manifests edits an\n * eval without touching the page, and keying on the page file alone would\n * scope that edit out and grade nothing.\n *\n * An unchanged page keeps no eval. Every grader grades one page at a time or\n * one group of pages per call, so dropping a page's targets shrinks the check\n * rather than changing what it means. An eval naming an unregistered grader\n * never reaches here: `assertRegisteredGraders` refuses the run first, so a\n * typo cannot surface on a changed page and vanish on an unchanged one.\n *\n * An empty result is **not** a usage error, which is where this parts company\n * with `applySelection`. \"No page changed\" is a correct answer to a correct\n * question; \"`--eval` matched nothing\" is a typo.\n */\nexport function applySinceScope(\n plans: ResolvedPagePlan[],\n changed: Set<string>,\n): { pagesSelected: number } {\n return applyScope(plans, (plan) => sinceSelects(plan, changed));\n}\n\n/**\n * The files whose change counts as the page's: its own, then every manifest\n * that supplied one of its eval keys. `external` is absent when the run loaded\n * no manifest at all (`withExternalMetadata` returns such pages untouched).\n */\nfunction scopeManifests(plan: ResolvedPagePlan): readonly string[] {\n return plan.page.external?.evalManifests ?? [];\n}\n\nfunction sinceSelects(plan: ResolvedPagePlan, changed: Set<string>): boolean {\n return [plan.page.absPath, ...scopeManifests(plan)].some((f) =>\n changed.has(changedKey(f)),\n );\n}\n\n/**\n * Empty `plan.evals` on every page `keep` rejects, in place, and count the\n * rest. `--since` and `--newer-than` both narrow through it, so a page under\n * both keeps its evals only when both select it.\n */\nfunction applyScope(\n plans: ResolvedPagePlan[],\n keep: (plan: ResolvedPagePlan) => boolean,\n): { pagesSelected: number } {\n let pagesSelected = 0;\n for (const plan of plans) {\n if (keep(plan)) {\n pagesSelected += 1;\n continue;\n }\n plan.evals = [];\n }\n return { pagesSelected };\n}\n\n/** The plans whose page or eval manifest changed inside the last `windowMs`. */\nasync function recentPages(\n plans: ResolvedPagePlan[],\n windowMs: number,\n cwd: string,\n exec: ExecFn,\n): Promise<Set<ResolvedPagePlan>> {\n const floor = Date.now() - windowMs;\n const ages = await pageAges(\n plans.map((p) => ({ page: p.page.absPath, manifests: scopeManifests(p) })),\n cwd,\n exec,\n );\n return new Set(plans.filter((_, i) => (ages[i] ?? Number.NEGATIVE_INFINITY) >= floor));\n}\n\n/**\n * Per-suite aggregates. Reads the suite `stampSuites` recorded on each result\n * rather than rebuilding the plan-to-suite map a second time — two copies of\n * one derivation are two things to keep in agreement.\n */\nfunction summarizeSuites(\n results: EvalResult[],\n config: DocevalsConfig,\n partial = false,\n): SuiteSummary[] {\n const bySuite = new Map<string, EvalResult[]>();\n for (const r of results) {\n const suite = r.suite ?? \"default\";\n const list = bySuite.get(suite) ?? [];\n list.push(r);\n bySuite.set(suite, list);\n }\n const summaries: SuiteSummary[] = [];\n for (const [suite, rs] of [...bySuite.entries()].sort()) {\n const passed = rs.filter((r) => r.outcome === \"pass\").length;\n const failed = rs.filter((r) => r.outcome === \"fail\").length;\n const errored = rs.filter((r) => r.outcome === \"error\").length;\n const needsReview = rs.filter((r) => r.outcome === \"needs-review\").length;\n const skipped = rs.filter((r) => r.outcome === \"skipped\").length;\n // Counts stay unweighted and per-eval: they report how many evals did\n // what, and a reader comparing \"1 failed\" against a rate of 0.33 is\n // reading two different questions, both answered honestly.\n //\n // The rate is weighted over the same membership as before — the graded\n // set, pass + fail + error. `needs-review` and `skipped` stay out of both\n // halves, so a page awaiting review neither helps nor hurts.\n const graded = (r: EvalResult): boolean =>\n r.outcome === \"pass\" || r.outcome === \"fail\" || r.outcome === \"error\";\n const suiteCriteria = config.suites[suite]?.criteria ?? [];\n\n const contributions: { weight: number; passed: boolean }[] = [];\n\n // Criteria first, because which evals a criterion actually absorbs is only\n // known once it is evaluated. A group scored once is the whole point —\n // three checks written as a criterion must not outvote three standalone\n // evals just for being grouped.\n let critPassed = 0;\n let critFailed = 0;\n let critSuspended = 0;\n /** \"<file> <evalName>\" of members a *scored* criterion speaks for. */\n const absorbed = new Set<string>();\n // Indexed once for the whole suite. The loop below is criterion x page x\n // member, and a `filter`/`find` inside it rescans every result each time —\n // quadratic in a corpus's result count, on the one code path that runs\n // after everything else has finished.\n const byKey = new Map<string, EvalResult>();\n const filesByEval = new Map<string, Set<string>>();\n for (const r of rs) {\n byKey.set(resultKey(r.file, r.evalName), r);\n const files = filesByEval.get(r.evalName) ?? new Set<string>();\n files.add(r.file);\n filesByEval.set(r.evalName, files);\n }\n for (const critName of suiteCriteria) {\n const def = config.criteria[critName];\n if (!def) continue;\n const pages = new Set<string>();\n for (const name of def.evals) {\n for (const file of filesByEval.get(name) ?? []) pages.add(file);\n }\n for (const file of pages) {\n const members = def.evals.map((name) =>\n byKey.get(resultKey(file, name)),\n );\n // Every member must have been graded for the group to mean anything.\n // A missing or ungraded member suspends it rather than failing it.\n if (members.some((m) => m === undefined || !graded(m))) {\n critSuspended++;\n // Deliberately does NOT absorb its members. A suspended criterion\n // contributes nothing, so absorbing them too would delete their\n // outcomes from the rate entirely — a failing member would move the\n // total by nothing and silently inflate the suite.\n continue;\n }\n const passes = members.map((m) => m?.outcome === \"pass\");\n const passed =\n def.combine === \"any\" ? passes.some(Boolean) : passes.every(Boolean);\n if (passed) critPassed++;\n else critFailed++;\n contributions.push({ weight: def.weight, passed });\n for (const m of members) {\n if (m) absorbed.add(resultKey(m.file, m.evalName));\n }\n }\n }\n\n // Standalone evals: everything a scored criterion did not speak for.\n for (const r of rs) {\n if (!graded(r) || absorbed.has(resultKey(r.file, r.evalName))) continue;\n contributions.push({ weight: r.weight ?? 1, passed: r.outcome === \"pass\" });\n }\n\n const totalWeight = contributions.reduce((sum, c) => sum + c.weight, 0);\n const passRate =\n totalWeight > 0\n ? contributions\n .filter((c) => c.passed)\n .reduce((sum, c) => sum + c.weight, 0) / totalWeight\n : 1;\n const targetPassRate = config.suites[suite]?.targetPassRate ?? 1.0;\n summaries.push({\n suite,\n total: rs.length,\n passed,\n failed,\n needsReview,\n skipped,\n errored,\n passRate,\n targetPassRate,\n // A suite target is a claim about a body of checks. A filtered run\n // measured part of it, so it reports the numbers and withholds the\n // verdict — erring toward false confidence is what gets a gate removed\n // rather than fixed (ADR 01018).\n meetsTarget: partial ? false : passRate >= targetPassRate,\n ...(partial ? { partial: true } : {}),\n ...(suiteCriteria.length > 0\n ? {\n criteria: {\n total: critPassed + critFailed + critSuspended,\n passed: critPassed,\n failed: critFailed,\n suspended: critSuspended,\n },\n }\n : {}),\n });\n }\n return summaries;\n}\n\nexport async function runEvals(options: RunOptions = {}): Promise<EngineReport> {\n const cwd = options.cwd ?? process.cwd();\n const paths = options.paths ?? [];\n const config =\n options.config ??\n loadRunConfig(\n {\n paths,\n ...(options.configPath === undefined ? {} : { configPath: options.configPath }),\n ...(options.noConfig === undefined ? {} : { noConfig: options.noConfig }),\n ...(options.collection === undefined ? {} : { collection: options.collection }),\n },\n cwd,\n );\n const exec = options.exec ?? realExec;\n // Read the way `meta validate` reads: the frontmatter block, plus whatever\n // an owning manifest of one of the page's collections supplies. A corpus\n // that relocated its evals resolves the same plan it did before the move.\n const pages = await withExternalMetadata(\n discoverPages(\n config,\n {\n paths,\n verb: \"evaluate\",\n ...(options.collection === undefined ? {} : { collection: options.collection }),\n ...(options.exclude === undefined ? {} : { exclude: options.exclude }),\n },\n cwd,\n ),\n config,\n cwd,\n );\n // Refused up front, not at the end: a re-record rebuilds the file from this\n // run's findings, so recording from a filtered run would drop every\n // fingerprint the filter excluded. Deciding it here costs nothing; deciding\n // it after `resolveBaseline` meant the generation pass had already written\n // scripts and rewritten frontmatter, and the judge had already been paid.\n //\n // `--since` is refused here for the same reason and, being *before* the git\n // call below, a usage error never spawns a subprocess.\n if (\n options.writeBaseline !== undefined &&\n options.writeBaseline !== false &&\n ((options.evalNames?.some((n) => n.trim() !== \"\") ?? false) ||\n options.suite !== undefined ||\n options.since !== undefined ||\n options.newerThan !== undefined)\n ) {\n throw new DocevalsError(\n \"--write-baseline records the whole corpus, so it cannot be combined with \" +\n \"--eval, --suite, --since or --newer-than: the re-record would drop every \" +\n \"finding the narrowing excluded. Re-run without it to record.\",\n );\n }\n\n // Before `resolvePages`, so an unresolvable ref fails the run without paying\n // for resolution — but applied after `applySelection` below, because\n // `PageFile.absPath` only exists post-discovery and resolution problems must\n // surface for every page, scoped or not (ADR 01018's driver).\n // Blank and option-shaped refs are rejected inside `changedFilesSince`, at\n // the seam, so a library caller gets the same guard the CLI does.\n const sinceRef = options.since;\n // Parsed before git is asked anything, so a bad duration is a usage error\n // that spawns no subprocess.\n const newerThan = options.newerThan;\n const windowMs =\n newerThan === undefined\n ? undefined\n : parseDuration(newerThan, (message) => new DocevalsError(message));\n const changed =\n sinceRef === undefined ? null : await changedFilesSince(sinceRef, cwd, exec);\n\n const plans = resolvePages(pages, config);\n // A grader nothing registered is the configuration's bug, so it is a usage\n // error before anything else is said about the plan.\n assertRegisteredGraders(plans, config);\n // A run that resolved no evals at all checked nothing, and exited 0 saying\n // so in about seventeen bytes. The identical condition reached through\n // `--eval no-such-eval` is already exit 2 with a careful message\n // (ADR 01018); reaching it through configuration must not be silence\n // (ADR 01041).\n //\n // Read off the *resolved* plan, deliberately before every narrowing:\n // `applySelection` owns its own empty-match error and names what was asked\n // for, and `--since` deliberately answers \"no page changed\" with exit 0 and\n // a sentence (ADR 01040). The plan being empty is a different claim from a\n // scope being empty.\n //\n // Suppressed when resolution errored, because then there *is* something to\n // report: the run exits 1 naming the bad key, which is a better diagnosis\n // than telling the reader to configure a suite they may already have.\n //\n // And read over the pages the author did **not** skip. A page carrying\n // `eval-skip: true` and no suite resolves *zero* evals rather than evals\n // that are then skipped, so counting over every page turned a deliberate,\n // documented skip into a usage error — `test/docevals/fixtures/pages/index.mdx`\n // is exactly that page, and `docs/src/content/docs/docevals/evals/index.mdx` runs it\n // expecting exit 0. \"Nothing is configured to check the pages you asked\n // about\" is the claim; a skipped page is not one of those pages.\n const unskipped = plans.filter((p) => !p.skip);\n if (\n unskipped.length > 0 &&\n unskipped.every((p) => p.evals.length === 0) &&\n !plans.some((p) => p.problems.some((pr) => pr.level === \"error\"))\n ) {\n throw new DocevalsError(\n `No evals resolved for any of the ${unskipped.length} page(s) this run would check. ` +\n `Nothing would have been checked, so this run would have reported ` +\n `success without checking anything.\\n` +\n `Point \\`defaults.suite\\` at a suite in ${config.configPath}, or give ` +\n `the pages an \\`eval-suite\\` or \\`evals\\` frontmatter key. Run ` +\n `\\`manni docevals list\\` to see the resolved plan.`,\n \"nothing-resolved\",\n );\n }\n const filtered = applySelection(plans, config, options);\n // Declared here, applied *after* the feasibility pass below. `--since` scopes\n // what is graded, never what is diagnosed — and `applySinceScope` empties\n // `plan.evals` on unchanged pages, so scoping first would hand\n // `checkFeasibility` nothing to look at. A pull request that edits only\n // `manni.config.yaml` changes no page, so under `--since` every plan would be\n // empty and the config's own validity — a malformed grader option, an unknown\n // key — would go unchecked, exiting 0. The one flag meant for CI would make a\n // config-only change the least examined kind of change there is.\n let scope: { pagesSelected: number; pagesTotal: number } | null = null;\n const judgeOptions = options.judgeOptions ?? {};\n\n const problems: RunProblem[] = plans.flatMap((p) =>\n p.problems.map((pr) => ({\n // A value a manifest supplied is reported against that manifest, at its\n // line there: the page has nothing at that pointer to fix.\n file: pr.file ?? p.page.file,\n message: pr.message,\n level: pr.level,\n line: pr.line,\n })),\n );\n\n const results: EvalResult[] = [];\n const deterministicTargets: GraderTarget[] = [];\n const aiTargets: GraderTarget[] = [];\n const generationTargets: GraderTarget[] = [];\n const generatedPaths: string[] = [];\n /** \"<file> <evalName>\" keys whose check script this run generated. */\n const generatedThisRun = new Set<string>();\n\n // Everything available runs unless the operator narrows it (proposal 0075).\n // The config holds every grant unless `execution.allow` lists fewer;\n // `--allow-execution` keeps only the named ones it already holds, and\n // `--no-execution` clears them all for one run. Nothing here widens.\n const granted = grantsFor(config.execution.allow, {\n ...(options.allowExecution === undefined\n ? {}\n : { allowExecution: options.allowExecution }),\n ...(options.execution === undefined ? {} : { execution: options.execution }),\n });\n const allowFrontmatterCommands = granted.has(\"frontmatter-commands\");\n\n // Before anything is dispatched: an eval that cannot reach a verdict as\n // configured is a configuration error, and saying so now costs nothing where\n // discovering it at grade time costs a judge call.\n problems.push(\n ...checkFeasibility(plans, {\n allowFrontmatterCommands,\n canGenerate: options.generate !== false && options.generateScripts != null,\n ...(options.deterministicOnly === true ? { deterministicOnly: true } : {}),\n ...(options.aiOnly === true ? { aiOnly: true } : {}),\n }),\n );\n\n // Now that every page has been diagnosed, narrow what will actually be\n // graded. See the declaration above for why this cannot move earlier.\n if (changed !== null || windowMs !== undefined) {\n // Ages are read only when asked for, and after every page was diagnosed.\n const recent =\n windowMs === undefined ? null : await recentPages(plans, windowMs, cwd, exec);\n scope = {\n pagesTotal: plans.length,\n ...applyScope(\n plans,\n (plan) =>\n (changed === null || sinceSelects(plan, changed)) &&\n (recent === null || recent.has(plan)),\n ),\n };\n }\n\n for (const plan of plans) {\n if (plan.problems.some((p) => p.level === \"error\")) continue;\n for (const ev of plan.evals) {\n if (plan.skip) {\n results.push(skippedResult(plan, ev, \"page skipped (evals.skip)\"));\n continue;\n }\n if (ev.skip) {\n results.push(skippedResult(plan, ev, \"eval skipped\"));\n continue;\n }\n if (ev.grader === \"human\") {\n results.push({\n evalName: ev.name,\n type: ev.type,\n grader: ev.grader,\n file: plan.page.file,\n outcome: \"needs-review\",\n durationMs: 0,\n });\n continue;\n }\n if (ev.grader === \"ai\") {\n if (options.deterministicOnly) {\n results.push(skippedResult(plan, ev, \"judge skipped (--deterministic-only)\"));\n } else if (!options.judge) {\n results.push(skippedResult(plan, ev, \"judge unavailable (no provider)\"));\n } else {\n aiTargets.push({ plan, eval: ev });\n }\n continue;\n }\n // command / tool:* — deterministic.\n if (options.aiOnly) {\n results.push(skippedResult(plan, ev, \"deterministic evals skipped (--ai-only)\"));\n continue;\n }\n // Page-authored argv, whatever grader carries it. `command` evals name\n // it in `command`; a registered grader may also accept an\n // `options.command` override and hand it to the same `exec`. Gating\n // only the grader left a second spelling of \"run this\" that reached a\n // shell ungated, which made the grant decorative — a page that cannot\n // say `grader: command` could name such a grader with the same argv.\n // Config-authored argv is the operator's own and is not content, so the\n // gate is on `source === \"page\"` rather than on the key's presence.\n const pageAuthoredArgv =\n ev.source === \"page\" &&\n (ev.grader === \"command\" || Array.isArray(ev.options.command));\n if (pageAuthoredArgv && !allowFrontmatterCommands) {\n results.push(\n skippedResult(\n plan,\n ev,\n NOT_GRANTED_REASON,\n ),\n );\n continue;\n }\n if (ev.grader === \"command\" && !ev.command) {\n generationTargets.push({ plan, eval: ev });\n continue;\n }\n // Stale generated script: the assertion changed since generation.\n if (\n ev.grader === \"command\" &&\n ev.command &&\n ev.generatedAssertionHash &&\n ev.assertion &&\n ev.generatedAssertionHash !== sha256(ev.assertion)\n ) {\n if (options.generate !== false && options.generateScripts) {\n generationTargets.push({ plan, eval: ev });\n continue;\n }\n problems.push({\n file: plan.page.file,\n message: `Eval \"${ev.name}\": assertion changed since its script was generated — run \\`manni docevals generate\\` to regenerate`,\n level: \"warning\",\n });\n }\n // ADR 01033: a grader that cannot serve a requested target says so,\n // rather than grading something else and reporting a verdict about\n // bytes nobody asked about. An *error* and not a skip, because a skip\n // keeps the run green and an eval that measured the wrong thing would\n // then read as coverage.\n const unsupported = unsupportedTarget(ev);\n if (unsupported !== undefined) {\n results.push({\n evalName: ev.name,\n type: ev.type,\n grader: ev.grader,\n file: plan.page.file,\n outcome: \"error\",\n skipReason: unsupported,\n durationMs: 0,\n });\n continue;\n }\n deterministicTargets.push({ plan, eval: ev });\n }\n }\n\n // Script generation for command evals with no command yet.\n if (generationTargets.length > 0) {\n if (options.generate !== false && options.generateScripts) {\n const gen = await options.generateScripts(\n generationTargets,\n config,\n judgeOptions,\n );\n generatedPaths.push(...gen.generatedPaths);\n const refusedBy = new Map<string, string>(\n (gen.refusals ?? []).map((r) => [resultKey(r.file, r.evalName), r.message]),\n );\n // Re-read the targets' evals: generateScripts mutates eval.command in place.\n for (const t of generationTargets) {\n const refused = refusedBy.get(resultKey(t.plan.page.file, t.eval.name));\n if (!t.eval.command && refused !== undefined) {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: refused,\n durationMs: 0,\n });\n } else if (!t.eval.command && gen.unavailable !== undefined) {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: `${GENERATION_UNAVAILABLE}: ${gen.unavailable}`,\n durationMs: 0,\n });\n } else if (t.eval.command) {\n deterministicTargets.push(t);\n // Surfaced by the reporters as \"(generated)\" on this run's result.\n generatedThisRun.add(resultKey(t.plan.page.file, t.eval.name));\n } else {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: \"script generation failed\",\n generated: false,\n durationMs: 0,\n });\n }\n }\n } else {\n for (const t of generationTargets) {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: GENERATION_UNAVAILABLE,\n durationMs: 0,\n });\n }\n }\n }\n\n // Deterministic graders, grouped by kind.\n const byKind = new Map<string, GraderTarget[]>();\n for (const t of deterministicTargets) {\n const list = byKind.get(t.eval.grader) ?? [];\n list.push(t);\n byKind.set(t.eval.grader, list);\n }\n\n for (const [kind, targets] of byKind) {\n const grader = graderFor(kind);\n // `assertRegisteredGraders` already refused an unregistered kind. Kept so\n // that a gap between the two checks reads as an error, never a pass.\n if (!grader) {\n for (const t of targets) {\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: \"error\",\n skipReason: `Unknown grader kind \"${kind}\"`,\n durationMs: 0,\n });\n }\n continue;\n }\n // One invocation per eval *configuration*, not one per grader kind — the\n // engine drives the same partition the batch adapters use internally, so\n // the try/catch below can only ever reach one eval's targets (ADR 01042).\n //\n // The bug this closes: batch graders loop `groupTargetsByEval` *inside*\n // `grade()`, so a throw on the second group unwound the whole function and\n // discarded the first group's already-computed findings. One broken eval\n // erased every sibling eval of the same kind, and every one of them\n // reported the broken eval's message.\n //\n // `groupTargetsByEval` is a pure partition and idempotent, so the adapters\n // keep calling it too: each stays correct when invoked directly, and the\n // isolation boundary is not something a new adapter has to remember.\n for (const group of groupTargetsByEval(targets)) {\n const start = Date.now();\n // A grader is effectively third-party code: tool adapters shell out, and\n // `runValidate` raises on a schema path it cannot read — which\n // `options.schemas` being hand-written makes the likeliest route in.\n // Letting that rejection escape drops every remaining eval on every\n // remaining page with no result and no exit-code signal that anything\n // was skipped. Error its own targets and carry on, the way a failed\n // script generation already does above.\n let findings: Finding[];\n try {\n findings = await grader.grade({ targets: group, config, root: cwd, exec });\n } catch (e) {\n const reason = errorMessage(e);\n for (const target of group) {\n results.push({\n evalName: target.eval.name,\n suite: target.eval.suite,\n type: target.eval.type,\n grader: target.eval.grader,\n file: target.plan.page.file,\n outcome: \"error\",\n // Names the eval, not just the kind. With one catch per kind the\n // message described whichever eval happened to throw while sitting\n // on every eval's result, so the name in the result and the name\n // in the message disagreed.\n skipReason: `grader ${kind} failed for eval \"${target.eval.name}\": ${reason}`,\n durationMs: Date.now() - start,\n });\n }\n continue;\n }\n const durationMs = Date.now() - start;\n const grouped = groupFindings(findings);\n for (const t of group) {\n const key = resultKey(t.plan.page.file, t.eval.name);\n const own = grouped.get(key) ?? [];\n // A diagnostic finding fails the eval regardless of severity: it means\n // the grader could not reach a verdict, and \"no verdict\" must never\n // read as \"pass\". Enforced here rather than per-adapter, so a new\n // adapter gets it by default instead of having to remember (ADR 01022).\n const hasError = own.some(\n (f) => f.severity === \"error\" || f.diagnostic === true,\n );\n results.push({\n evalName: t.eval.name,\n type: t.eval.type,\n grader: t.eval.grader,\n file: t.plan.page.file,\n outcome: hasError ? \"fail\" : \"pass\",\n findings: own.length > 0 ? own : undefined,\n generated: generatedThisRun.has(key) ? true : undefined,\n durationMs: Math.round(durationMs / group.length),\n });\n }\n }\n }\n\n // failFast: a page with an error-severity deterministic failure skips its ai evals.\n let effectiveAiTargets = aiTargets;\n if (config.defaults.failFast) {\n const failedPages = new Set(\n results\n .filter((r) => r.outcome === \"fail\" || r.outcome === \"error\")\n .map((r) => r.file),\n );\n effectiveAiTargets = [];\n for (const t of aiTargets) {\n if (failedPages.has(t.plan.page.file)) {\n results.push(\n skippedResult(t.plan, t.eval, \"deterministic-precondition-failed\"),\n );\n } else {\n effectiveAiTargets.push(t);\n }\n }\n }\n\n // AI judge stage.\n if (effectiveAiTargets.length > 0 && options.judge) {\n results.push(\n ...(await options.judge(effectiveAiTargets, config, judgeOptions)),\n );\n }\n\n // A run that ran out of turns has *reduced coverage*, and skipped evals are\n // excluded from the suite pass rate below — so without this it exits 0\n // having judged less than it was asked to, which is the silent-green shape\n // this corpus gate exists to prevent. Warning, not error: the cap was asked\n // for, so tripping it is expected; going quiet about it is not (ADR 01019).\n const budgetSkipped = results.filter((r) => isTurnBudgetSkip(r.skipReason));\n const firstBudgetSkipped = budgetSkipped[0];\n if (firstBudgetSkipped !== undefined) {\n problems.push({\n file: firstBudgetSkipped.file,\n message:\n `${budgetSkipped.length} eval(s) were not judged: the turn budget ran out. ` +\n `This run covered less than it was asked to — raise --max-turns or narrow the run.`,\n level: \"warning\",\n });\n }\n\n // Nothing reached a verdict. Deliberately a warning and not an error:\n // `eval-skip` is a feature, `--deterministic-only` is a standing CI\n // invocation, and a scoped run over a clean tree is a correct answer\n // (ADR 01040). What was missing is anyone saying that the run therefore\n // established nothing — the same omission the turn-budget warning above\n // exists to fill (ADR 01019, ADR 01041).\n //\n // No exception for `--since`, which narrates its own empty scope a few lines\n // later in every reporter. Two lines, one explaining the other, is a better\n // trade than a carve-out: a carve-out is how this class of bug returns.\n //\n // `needs-review` is excluded on purpose: a human-graded eval is work the run\n // produced, not silence, and the reporters already point at `review`.\n //\n // Anchored on the config rather than a page: no single page is at fault, and\n // the config is the run-level file a reader can act on.\n if (!results.some((r) => r.outcome !== \"skipped\")) {\n problems.push({\n file: config.configPath,\n message:\n `This run graded nothing — no eval reached a verdict, so it established ` +\n `nothing about the corpus. ` +\n (results.length > 0\n ? `All ${results.length} resolved eval(s) were skipped; check the skip ` +\n `reasons above — a page-level \\`eval-skip\\`, a grader-class flag, or ` +\n `a missing provider.`\n : // With zero results the cause is not always the same, and naming the\n // wrong one sends the reader to the wrong file. An error-level\n // resolution problem makes the plan loop skip that page entirely and\n // also suppresses the empty-plan throw above, so \"skipped or scoped\n // out\" would contradict the errors printed right beside it.\n problems.some((p) => p.level === \"error\")\n ? `Every discovered page was dropped by an error-level resolution ` +\n `problem — fix those first; they are listed above.`\n : `Every discovered page was skipped or scoped out of the run.`),\n level: \"warning\",\n });\n }\n\n const baselineOutcome = resolveBaseline(results, config, options, cwd, problems);\n // Copy before clearing: when no baseline applies, `resolveBaseline` hands\n // back the very array it was given, and emptying it first would leave the\n // spread with nothing to read — a run reporting zero results, green.\n const baselinedResults = [...baselineOutcome.results];\n results.length = 0;\n results.push(...baselinedResults);\n\n stampSuites(results, plans);\n\n // Self-preference reaches the reporters as a problem, not just as a field on\n // the result: a run whose verdicts were formed by the model that wrote what\n // they grade should say so where anyone reads it. One per affected eval, in\n // the judge's own sentence, which is recomputed from the plan because the\n // result carries only the axis and the model.\n for (const r of results) {\n if (!r.selfPreference) continue;\n const plan = plans.find((p) => p.page.file === r.file);\n const ev = plan?.evals.find((e) => e.name === r.evalName);\n const finding =\n plan && ev ? selfPreferenceOf(plan, ev, r.selfPreference.model) : undefined;\n if (!finding) continue;\n problems.push({ file: r.file, level: \"warning\", message: finding.message });\n }\n\n // A scoped run measured part of the corpus, which is the same claim-from-a-\n // sample problem `--eval` has — so it reuses ADR 01018's mechanism rather\n // than growing a second, differently-behaved one.\n //\n // `partial` means coverage was actually lost, not that a narrowing flag was\n // present. Deriving it from the flag disabled suite-target enforcement on a\n // `--since` run that happened to touch every page — and since ADR 01040\n // intends `--since` as the CI invocation, that turned the aggregate gate off\n // permanently for anyone who adopted it. `pagesSelected` is already the exact\n // count, so the predicate is free.\n const scopeLostCoverage = scope !== null && scope.pagesSelected < plans.length;\n const suites = summarizeSuites(results, config, filtered || scopeLostCoverage);\n const judged = results.filter((r) => r.consensus != null);\n const totalTokens = judged.reduce(\n (n, r) =>\n n +\n (r.consensus?.runs.reduce(\n (m, run) =>\n m + (run.usage ? run.usage.inputTokens + run.usage.outputTokens : 0),\n 0,\n ) ?? 0),\n 0,\n );\n\n const hasFailure =\n results.some((r) => r.outcome === \"fail\" || r.outcome === \"error\") ||\n suites.some((s) => s.partial !== true && !s.meetsTarget) ||\n problems.some((p) => p.level === \"error\") ||\n (options.failOnReview === true &&\n results.some((r) => r.outcome === \"needs-review\"));\n\n return {\n pages: plans.length,\n evalResults: results,\n suites,\n usage: {\n totalTokens,\n cachedEvals: judged.filter(\n (r) => r.consensus?.runs.every((run) => run.cached) === true,\n ).length,\n judgedEvals: judged.length,\n },\n generated: generatedPaths,\n exitCode: hasFailure ? 1 : 0,\n problems,\n ...(baselineOutcome.summary ? { baseline: baselineOutcome.summary } : {}),\n ...(scope && sinceRef !== undefined ? { since: { ref: sinceRef, ...scope } } : {}),\n ...(scope && newerThan !== undefined\n ? { newerThan: { duration: newerThan, ...scope } }\n : {}),\n };\n}\n"],"mappings":"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","names":["resolve","resolve","resolve","resolve","Ajv2020","dirname","dirname","readFileSync","dirname","relative","resolve","dirname","resolve","relative","readFileSync","ajv","Ajv2020","readFileSync","dirname","relative","resolve","relative","resolve","readFileSync","dirname","resolve","resolve","statSync","relative","resolve","GIT_TIMEOUT_MS","git","resolve","statSync","relative","resolve","locationOf","passed"]}