@hawkeyexl/manni 4.4.1 → 4.6.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 (226) hide show
  1. package/README.md +1 -1
  2. package/dist/batch-OZOACN4G.js +41 -0
  3. package/dist/build-Z5VOVADH.js +32 -0
  4. package/dist/calibrate-TZYT42DR.js +36 -0
  5. package/dist/capture-SL4MNDDP.js +34 -0
  6. package/dist/check-5OMA42Y6.js +26 -0
  7. package/dist/{check-HYNGXYJV.js → check-OAJWC3WD.js} +7 -5
  8. package/dist/{check-ASPIHA6B.js → check-PKY7KTQE.js} +13 -14
  9. package/dist/check-WB2QDHJQ.js +880 -0
  10. package/dist/check-WB2QDHJQ.js.map +1 -0
  11. package/dist/{chunk-MWJLZMBL.js → chunk-2JFPBZJK.js} +11 -11
  12. package/dist/{chunk-QQUKGCAJ.js → chunk-2KRB3EG7.js} +2 -2
  13. package/dist/{chunk-DXNZS72W.js → chunk-2M6DVNI5.js} +10 -6
  14. package/dist/{chunk-DXNZS72W.js.map → chunk-2M6DVNI5.js.map} +1 -1
  15. package/dist/{chunk-QZ6LRSNV.js → chunk-3NWX34ZI.js} +19 -19
  16. package/dist/{chunk-IDV6HJCB.js → chunk-5G53XATW.js} +4 -4
  17. package/dist/{chunk-M2JCK5F6.js → chunk-6KKZXB2O.js} +19 -6
  18. package/dist/chunk-6KKZXB2O.js.map +1 -0
  19. package/dist/{chunk-PNPQTHBT.js → chunk-733Y2STG.js} +2 -2
  20. package/dist/{chunk-WB3QM6PP.js → chunk-73TC4DYH.js} +332 -2522
  21. package/dist/chunk-73TC4DYH.js.map +1 -0
  22. package/dist/{chunk-EPH54CAY.js → chunk-7WRP5FFP.js} +4 -4
  23. package/dist/{chunk-NXV7WE2D.js → chunk-APKH2T6E.js} +29 -591
  24. package/dist/chunk-APKH2T6E.js.map +1 -0
  25. package/dist/{chunk-I2AH3CJJ.js → chunk-B3TS4WRM.js} +17 -15
  26. package/dist/{chunk-I2AH3CJJ.js.map → chunk-B3TS4WRM.js.map} +1 -1
  27. package/dist/chunk-BWCWTHYS.js +146 -0
  28. package/dist/chunk-BWCWTHYS.js.map +1 -0
  29. package/dist/{chunk-MMTSSTG7.js → chunk-C3B2VJNC.js} +2 -2
  30. package/dist/{chunk-PU6DFJMY.js → chunk-C73RSUIC.js} +4 -4
  31. package/dist/chunk-CU57HT2E.js +116 -0
  32. package/dist/chunk-CU57HT2E.js.map +1 -0
  33. package/dist/chunk-CWXZ2MRT.js +222 -0
  34. package/dist/chunk-CWXZ2MRT.js.map +1 -0
  35. package/dist/{chunk-GCQRPUSB.js → chunk-DC5DDJVE.js} +6 -6
  36. package/dist/{chunk-6OYEI2VV.js → chunk-ECVQNGTH.js} +3 -3
  37. package/dist/chunk-FLAO4ZS3.js +502 -0
  38. package/dist/chunk-FLAO4ZS3.js.map +1 -0
  39. package/dist/chunk-FQGLRJGX.js +174 -0
  40. package/dist/chunk-FQGLRJGX.js.map +1 -0
  41. package/dist/{chunk-7UKO3ASZ.js → chunk-GAJIJKET.js} +3 -3
  42. package/dist/{chunk-6JSSEWBG.js → chunk-GREQKO6M.js} +202 -54
  43. package/dist/chunk-GREQKO6M.js.map +1 -0
  44. package/dist/chunk-HX44GB4Z.js +30 -0
  45. package/dist/chunk-HX44GB4Z.js.map +1 -0
  46. package/dist/{chunk-4IUC2MNL.js → chunk-IY7NYNPZ.js} +9 -11
  47. package/dist/{chunk-4IUC2MNL.js.map → chunk-IY7NYNPZ.js.map} +1 -1
  48. package/dist/{chunk-57NEQRVO.js → chunk-KCOFEWV5.js} +8 -6
  49. package/dist/{chunk-57NEQRVO.js.map → chunk-KCOFEWV5.js.map} +1 -1
  50. package/dist/chunk-M2RLHZ4J.js +849 -0
  51. package/dist/chunk-M2RLHZ4J.js.map +1 -0
  52. package/dist/{chunk-NLXTXE5Y.js → chunk-M6GSS72T.js} +185 -33
  53. package/dist/chunk-M6GSS72T.js.map +1 -0
  54. package/dist/{chunk-YTURO7SI.js → chunk-MHM4QEBV.js} +4 -4
  55. package/dist/{chunk-RL5XWQOL.js → chunk-MOWMCEOJ.js} +143 -54
  56. package/dist/chunk-MOWMCEOJ.js.map +1 -0
  57. package/dist/{chunk-C4SQM22E.js → chunk-MWBJ3KTF.js} +13 -11
  58. package/dist/chunk-MWBJ3KTF.js.map +1 -0
  59. package/dist/chunk-N7JSEDSC.js +233 -0
  60. package/dist/chunk-N7JSEDSC.js.map +1 -0
  61. package/dist/{chunk-JCDXE76J.js → chunk-NBMPHD4I.js} +2 -2
  62. package/dist/{chunk-37LP5HMZ.js → chunk-NHHOPZRA.js} +12 -10
  63. package/dist/{chunk-37LP5HMZ.js.map → chunk-NHHOPZRA.js.map} +1 -1
  64. package/dist/{chunk-YB4IBW3M.js → chunk-NTWW7J76.js} +2 -2
  65. package/dist/{chunk-UJCVAWP7.js → chunk-PCFG7E6B.js} +3 -3
  66. package/dist/{chunk-UJCVAWP7.js.map → chunk-PCFG7E6B.js.map} +1 -1
  67. package/dist/{chunk-FBEQCK47.js → chunk-PL4UAF4S.js} +73 -1304
  68. package/dist/chunk-PL4UAF4S.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-PIKOVN6W.js → chunk-QW77LCOU.js} +10 -10
  72. package/dist/{chunk-2B7ZNTPV.js → chunk-SM6NOMJS.js} +2 -2
  73. package/dist/chunk-SWSTHZBI.js +2464 -0
  74. package/dist/chunk-SWSTHZBI.js.map +1 -0
  75. package/dist/{chunk-JXLTXMJ7.js → chunk-T6SYGLWR.js} +3 -3
  76. package/dist/{chunk-CK7SKVHR.js → chunk-TBAMBLF3.js} +3 -12
  77. package/dist/chunk-TBAMBLF3.js.map +1 -0
  78. package/dist/chunk-TH4JVQPF.js +133 -0
  79. package/dist/chunk-TH4JVQPF.js.map +1 -0
  80. package/dist/{chunk-QRWGPQKO.js → chunk-TLXE7LYK.js} +4 -4
  81. package/dist/{chunk-M3W7J6MU.js → chunk-TUAAR3MM.js} +3280 -283
  82. package/dist/chunk-TUAAR3MM.js.map +1 -0
  83. package/dist/{chunk-SKSDRUUK.js → chunk-UAKNZVCD.js} +4 -4
  84. package/dist/{chunk-YJOGUXGP.js → chunk-UJSGS2Y5.js} +8 -6
  85. package/dist/{chunk-YJOGUXGP.js.map → chunk-UJSGS2Y5.js.map} +1 -1
  86. package/dist/{chunk-UQISLDAV.js → chunk-UWQ2UVHE.js} +8 -6
  87. package/dist/{chunk-UQISLDAV.js.map → chunk-UWQ2UVHE.js.map} +1 -1
  88. package/dist/chunk-WQWKYAAK.js +86 -0
  89. package/dist/chunk-WQWKYAAK.js.map +1 -0
  90. package/dist/{chunk-LJ2RDH3F.js → chunk-XG6PVB5S.js} +1 -23
  91. package/dist/chunk-XG6PVB5S.js.map +1 -0
  92. package/dist/{chunk-Q35YIDBV.js → chunk-XKBEHKWO.js} +29 -264
  93. package/dist/chunk-XKBEHKWO.js.map +1 -0
  94. package/dist/chunk-XPEWUK7J.js +532 -0
  95. package/dist/chunk-XPEWUK7J.js.map +1 -0
  96. package/dist/{chunk-MYMBCTDE.js → chunk-XXDXIIQ4.js} +2 -2
  97. package/dist/chunk-YGFIQ6Y5.js +17 -0
  98. package/dist/chunk-YGFIQ6Y5.js.map +1 -0
  99. package/dist/chunk-YLK2J5YK.js +610 -0
  100. package/dist/chunk-YLK2J5YK.js.map +1 -0
  101. package/dist/{chunk-3VK37OR2.js → chunk-Z4IZGEM3.js} +16 -12
  102. package/dist/{chunk-3VK37OR2.js.map → chunk-Z4IZGEM3.js.map} +1 -1
  103. package/dist/{cli-6HIDIFVT.js → cli-6EWVMEN6.js} +5 -3
  104. package/dist/{cli-6HIDIFVT.js.map → cli-6EWVMEN6.js.map} +1 -1
  105. package/dist/{cli-VI7VHWNZ.js → cli-6H7HVDMQ.js} +113 -20
  106. package/dist/{cli-VI7VHWNZ.js.map → cli-6H7HVDMQ.js.map} +1 -1
  107. package/dist/{cli-RPM5PELX.js → cli-EPVZHAZS.js} +24 -20
  108. package/dist/cli-EPVZHAZS.js.map +1 -0
  109. package/dist/{cli-MN7PYMBI.js → cli-LUCSGTVI.js} +17 -19
  110. package/dist/{cli-MN7PYMBI.js.map → cli-LUCSGTVI.js.map} +1 -1
  111. package/dist/{cli-LFP5ZGYS.js → cli-NIG4N3XM.js} +16 -15
  112. package/dist/{cli-LFP5ZGYS.js.map → cli-NIG4N3XM.js.map} +1 -1
  113. package/dist/{cli-PYPX6O6E.js → cli-PSKNB66T.js} +225 -58
  114. package/dist/cli-PSKNB66T.js.map +1 -0
  115. package/dist/{cli-3BIBYHFK.js → cli-UO4NHIB3.js} +17 -17
  116. package/dist/{cli-6UB5N6CU.js → cli-UQ7A3YA2.js} +17 -18
  117. package/dist/{cli-6UB5N6CU.js.map → cli-UQ7A3YA2.js.map} +1 -1
  118. package/dist/{cli-673OTRGE.js → cli-YHYDLQAF.js} +10 -10
  119. package/dist/cli.js +11 -11
  120. package/dist/config-P4HDNTYD.js +26 -0
  121. package/dist/conformance-ZFCMKM6M.js +18 -0
  122. package/dist/docmeta.js +9 -9
  123. package/dist/github-7ZCH5PSO.js +26 -0
  124. package/dist/github-POT6724K.js +31 -0
  125. package/dist/host-6GURH5HE.js +23 -0
  126. package/dist/index.d.ts +102 -12
  127. package/dist/index.js +185 -171
  128. package/dist/index.js.map +1 -1
  129. package/dist/{json-SY7KLNC7.js → json-KT2K62L5.js} +12 -13
  130. package/dist/lint-5AQ5C2BV.js +29 -0
  131. package/dist/list-5JZKX2NK.js +28 -0
  132. package/dist/list-SWPFXQMU.js +30 -0
  133. package/dist/{page-KSGV5RD4.js → page-UPSXRP75.js} +11 -12
  134. package/dist/prepare-6GNEWCNH.js +155 -0
  135. package/dist/prepare-6GNEWCNH.js.map +1 -0
  136. package/dist/{pretty-CXSDXNAS.js → pretty-Q6FQAOK4.js} +13 -14
  137. package/dist/{pretty-A5EGTN35.js → pretty-SQRPFPSQ.js} +12 -13
  138. package/dist/provider-AMGRDY6V.js +34 -0
  139. package/dist/release-IECYCLTD.js +36 -0
  140. package/dist/release-IECYCLTD.js.map +1 -0
  141. package/dist/{reporters-HUY7UXFS.js → reporters-45MMC2ID.js} +13 -13
  142. package/dist/{reporters-K2VUKSAK.js → reporters-XUV4MM64.js} +7 -5
  143. package/dist/reporters-XUV4MM64.js.map +1 -0
  144. package/dist/run-KMWY2IAN.js +32 -0
  145. package/dist/run-KMWY2IAN.js.map +1 -0
  146. package/dist/{term-BIQUPMOR.js → term-PCJUCWNF.js} +16 -17
  147. package/dist/{term-BIQUPMOR.js.map → term-PCJUCWNF.js.map} +1 -1
  148. package/dist/validate-IMNCZNWG.js +17 -0
  149. package/dist/validate-IMNCZNWG.js.map +1 -0
  150. package/package.json +2 -2
  151. package/plugin/manni/.claude-plugin/plugin.json +1 -1
  152. package/plugin/manni/hooks/hooks.json +47 -0
  153. package/dist/batch-GFNLTGOH.js +0 -36
  154. package/dist/build-COYIQ25L.js +0 -31
  155. package/dist/calibrate-MDBLJKEE.js +0 -31
  156. package/dist/capture-LRML2PKV.js +0 -32
  157. package/dist/check-EDLBYL5N.js +0 -27
  158. package/dist/chunk-6JSSEWBG.js.map +0 -1
  159. package/dist/chunk-A5ULMVHQ.js +0 -164
  160. package/dist/chunk-A5ULMVHQ.js.map +0 -1
  161. package/dist/chunk-C4SQM22E.js.map +0 -1
  162. package/dist/chunk-CK7SKVHR.js.map +0 -1
  163. package/dist/chunk-FBEQCK47.js.map +0 -1
  164. package/dist/chunk-LJ2RDH3F.js.map +0 -1
  165. package/dist/chunk-M2JCK5F6.js.map +0 -1
  166. package/dist/chunk-M3W7J6MU.js.map +0 -1
  167. package/dist/chunk-NLXTXE5Y.js.map +0 -1
  168. package/dist/chunk-NXV7WE2D.js.map +0 -1
  169. package/dist/chunk-Q35YIDBV.js.map +0 -1
  170. package/dist/chunk-RL5XWQOL.js.map +0 -1
  171. package/dist/chunk-TK3FC4RF.js +0 -3090
  172. package/dist/chunk-TK3FC4RF.js.map +0 -1
  173. package/dist/chunk-TU2WUBVZ.js +0 -2
  174. package/dist/chunk-WB3QM6PP.js.map +0 -1
  175. package/dist/cli-PYPX6O6E.js.map +0 -1
  176. package/dist/cli-RPM5PELX.js.map +0 -1
  177. package/dist/github-6QMYOHC3.js +0 -27
  178. package/dist/github-SXPGP5DB.js +0 -32
  179. package/dist/lint-ASMJLLPA.js +0 -28
  180. package/dist/list-KZNVTNVC.js +0 -31
  181. package/dist/list-Q57YTFUQ.js +0 -29
  182. package/dist/run-3DYJNRIG.js +0 -33
  183. package/dist/validate-53RKM2XG.js +0 -16
  184. /package/dist/{batch-GFNLTGOH.js.map → batch-OZOACN4G.js.map} +0 -0
  185. /package/dist/{build-COYIQ25L.js.map → build-Z5VOVADH.js.map} +0 -0
  186. /package/dist/{calibrate-MDBLJKEE.js.map → calibrate-TZYT42DR.js.map} +0 -0
  187. /package/dist/{capture-LRML2PKV.js.map → capture-SL4MNDDP.js.map} +0 -0
  188. /package/dist/{check-ASPIHA6B.js.map → check-5OMA42Y6.js.map} +0 -0
  189. /package/dist/{check-EDLBYL5N.js.map → check-OAJWC3WD.js.map} +0 -0
  190. /package/dist/{check-HYNGXYJV.js.map → check-PKY7KTQE.js.map} +0 -0
  191. /package/dist/{chunk-MWJLZMBL.js.map → chunk-2JFPBZJK.js.map} +0 -0
  192. /package/dist/{chunk-QQUKGCAJ.js.map → chunk-2KRB3EG7.js.map} +0 -0
  193. /package/dist/{chunk-QZ6LRSNV.js.map → chunk-3NWX34ZI.js.map} +0 -0
  194. /package/dist/{chunk-IDV6HJCB.js.map → chunk-5G53XATW.js.map} +0 -0
  195. /package/dist/{chunk-PNPQTHBT.js.map → chunk-733Y2STG.js.map} +0 -0
  196. /package/dist/{chunk-EPH54CAY.js.map → chunk-7WRP5FFP.js.map} +0 -0
  197. /package/dist/{chunk-MMTSSTG7.js.map → chunk-C3B2VJNC.js.map} +0 -0
  198. /package/dist/{chunk-PU6DFJMY.js.map → chunk-C73RSUIC.js.map} +0 -0
  199. /package/dist/{chunk-GCQRPUSB.js.map → chunk-DC5DDJVE.js.map} +0 -0
  200. /package/dist/{chunk-6OYEI2VV.js.map → chunk-ECVQNGTH.js.map} +0 -0
  201. /package/dist/{chunk-7UKO3ASZ.js.map → chunk-GAJIJKET.js.map} +0 -0
  202. /package/dist/{chunk-YTURO7SI.js.map → chunk-MHM4QEBV.js.map} +0 -0
  203. /package/dist/{chunk-JCDXE76J.js.map → chunk-NBMPHD4I.js.map} +0 -0
  204. /package/dist/{chunk-YB4IBW3M.js.map → chunk-NTWW7J76.js.map} +0 -0
  205. /package/dist/{chunk-PIKOVN6W.js.map → chunk-QW77LCOU.js.map} +0 -0
  206. /package/dist/{chunk-2B7ZNTPV.js.map → chunk-SM6NOMJS.js.map} +0 -0
  207. /package/dist/{chunk-JXLTXMJ7.js.map → chunk-T6SYGLWR.js.map} +0 -0
  208. /package/dist/{chunk-QRWGPQKO.js.map → chunk-TLXE7LYK.js.map} +0 -0
  209. /package/dist/{chunk-SKSDRUUK.js.map → chunk-UAKNZVCD.js.map} +0 -0
  210. /package/dist/{chunk-MYMBCTDE.js.map → chunk-XXDXIIQ4.js.map} +0 -0
  211. /package/dist/{cli-3BIBYHFK.js.map → cli-UO4NHIB3.js.map} +0 -0
  212. /package/dist/{chunk-TU2WUBVZ.js.map → cli-YHYDLQAF.js.map} +0 -0
  213. /package/dist/{cli-673OTRGE.js.map → config-P4HDNTYD.js.map} +0 -0
  214. /package/dist/{github-6QMYOHC3.js.map → conformance-ZFCMKM6M.js.map} +0 -0
  215. /package/dist/{github-SXPGP5DB.js.map → github-7ZCH5PSO.js.map} +0 -0
  216. /package/dist/{json-SY7KLNC7.js.map → github-POT6724K.js.map} +0 -0
  217. /package/dist/{lint-ASMJLLPA.js.map → host-6GURH5HE.js.map} +0 -0
  218. /package/dist/{list-KZNVTNVC.js.map → json-KT2K62L5.js.map} +0 -0
  219. /package/dist/{list-Q57YTFUQ.js.map → lint-5AQ5C2BV.js.map} +0 -0
  220. /package/dist/{page-KSGV5RD4.js.map → list-5JZKX2NK.js.map} +0 -0
  221. /package/dist/{pretty-A5EGTN35.js.map → list-SWPFXQMU.js.map} +0 -0
  222. /package/dist/{pretty-CXSDXNAS.js.map → page-UPSXRP75.js.map} +0 -0
  223. /package/dist/{reporters-HUY7UXFS.js.map → pretty-Q6FQAOK4.js.map} +0 -0
  224. /package/dist/{reporters-K2VUKSAK.js.map → pretty-SQRPFPSQ.js.map} +0 -0
  225. /package/dist/{run-3DYJNRIG.js.map → provider-AMGRDY6V.js.map} +0 -0
  226. /package/dist/{validate-53RKM2XG.js.map → reporters-45MMC2ID.js.map} +0 -0
@@ -0,0 +1,880 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ clipTo,
4
+ historyBlock,
5
+ ledgerPath,
6
+ projectPath,
7
+ readLedger,
8
+ recordFacts,
9
+ recordTurn,
10
+ rollup,
11
+ turnFacts,
12
+ writeLedger
13
+ } from "./chunk-N7JSEDSC.js";
14
+ import {
15
+ JUDGE_ENV,
16
+ assertDownloaded,
17
+ conformanceOf,
18
+ extraction,
19
+ firstLine,
20
+ isNetworkProvider,
21
+ localGate,
22
+ markJudgeProcess,
23
+ mockTurnJudge,
24
+ offlineRefusal,
25
+ rulesCacheFor
26
+ } from "./chunk-FLAO4ZS3.js";
27
+ import {
28
+ isTypedPrompt,
29
+ lastTurn,
30
+ resolveTurnSources,
31
+ subagentTurn
32
+ } from "./chunk-YLK2J5YK.js";
33
+ import {
34
+ libraryLocalModels,
35
+ renderCheck
36
+ } from "./chunk-TH4JVQPF.js";
37
+ import {
38
+ QUEUE_WAIT_MS,
39
+ hostHolds,
40
+ hostSetting,
41
+ queued
42
+ } from "./chunk-WQWKYAAK.js";
43
+ import {
44
+ parseTraceFile,
45
+ renderTrace
46
+ } from "./chunk-M2RLHZ4J.js";
47
+ import {
48
+ evaluateWhen
49
+ } from "./chunk-FQGLRJGX.js";
50
+ import {
51
+ materialize
52
+ } from "./chunk-CWXZ2MRT.js";
53
+ import "./chunk-APKH2T6E.js";
54
+ import "./chunk-4TSWU2SU.js";
55
+ import {
56
+ discoverConfig
57
+ } from "./chunk-XPEWUK7J.js";
58
+ import {
59
+ makeRedactor
60
+ } from "./chunk-CU57HT2E.js";
61
+ import {
62
+ constructProvider,
63
+ resolveSelectionIdentity,
64
+ selectHookProvider,
65
+ selectProvider
66
+ } from "./chunk-BWCWTHYS.js";
67
+ import {
68
+ TracevalsError
69
+ } from "./chunk-UKZNLVJW.js";
70
+ import "./chunk-YNHZHSSM.js";
71
+ import "./chunk-TLXE7LYK.js";
72
+ import "./chunk-GREQKO6M.js";
73
+ import "./chunk-TUAAR3MM.js";
74
+ import "./chunk-5G53XATW.js";
75
+ import "./chunk-KCOFEWV5.js";
76
+ import "./chunk-YEUYKR62.js";
77
+ import "./chunk-RNVYGWIC.js";
78
+ import "./chunk-MNH7QO4Z.js";
79
+ import "./chunk-XKBEHKWO.js";
80
+ import {
81
+ warn
82
+ } from "./chunk-HX44GB4Z.js";
83
+ import {
84
+ DECISION_ONLY_PROVIDERS
85
+ } from "./chunk-QCHVR4ZM.js";
86
+ import "./chunk-PCFG7E6B.js";
87
+ import "./chunk-OWBRDNRZ.js";
88
+ import "./chunk-G3T47CFV.js";
89
+ import "./chunk-2H7UOFLK.js";
90
+
91
+ // src/tracevals/commands/check.ts
92
+ import { writeFile } from "node:fs/promises";
93
+ import { basename, resolve } from "node:path";
94
+
95
+ // src/tracevals/rules/judge.ts
96
+ import {
97
+ JsonCache,
98
+ buildCacheKey,
99
+ canDecide,
100
+ completeJSONShared,
101
+ sha256
102
+ } from "@hawkeyexl/inference";
103
+
104
+ // src/tracevals/rules/judge-prompt.ts
105
+ var TURN_JUDGE_PROMPT_VERSION = 7;
106
+ var TURN_JUDGE_SYSTEM_PROMPT = [
107
+ "You check the last turn of an AI coding agent's session against one rule.",
108
+ "The last turn starts at the last prompt the user typed and runs to the end of the transcript.",
109
+ "The transcript shows the user's prompts, the agent's tool calls with their inputs, and its replies.",
110
+ '"Earlier in this session" lists what the session did before the last turn.',
111
+ "",
112
+ "A prompt the user typed overrides any rule. Doing what the user explicitly asked is never a violation.",
113
+ "",
114
+ "Judge only from what the transcript and the earlier turns show. Do not guess.",
115
+ "A rule applies only once the session does the kind of work it covers.",
116
+ "Score it broken only for what the last turn did, or for the last turn saying the work is done without it."
117
+ ].join("\n");
118
+ var TURN_SCORES = ["not-applicable", "followed", "not-followed"];
119
+ var SCORE = { type: "integer", minimum: 0, maximum: 100 };
120
+ var TURN_SCHEMA = {
121
+ type: "object",
122
+ required: ["reasoning", ...TURN_SCORES],
123
+ additionalProperties: false,
124
+ properties: {
125
+ reasoning: { type: "string" },
126
+ "not-applicable": SCORE,
127
+ followed: SCORE,
128
+ "not-followed": SCORE
129
+ }
130
+ };
131
+ var TURN_CRITERIA = {
132
+ followed: "The session does what the rule asks.",
133
+ "not-followed": "The last turn did what the rule forbids, skipped what it requires, or said the work is done without it.",
134
+ "not-applicable": "The rule does not apply yet, or the last turn did nothing it covers."
135
+ };
136
+ function ruleKey(displayPath, id) {
137
+ return `${displayPath}#${id}`;
138
+ }
139
+ function buildTurnShared(turn, earlier = "") {
140
+ return `${earlier !== "" ? `${earlier}
141
+
142
+ ` : ""}# The turn
143
+
144
+ ${turn}
145
+
146
+ `;
147
+ }
148
+ function buildRuleItem(displayPath, rule, history = "") {
149
+ return [
150
+ "# The rule",
151
+ "",
152
+ `${ruleKey(displayPath, rule.id)}: ${rule.text}`,
153
+ "",
154
+ ...history !== "" ? [history, ""] : [],
155
+ "First say in one or two sentences what the session shows about this rule. Then score each as a whole number from 0 to 100: the rule does not apply yet, or the last turn did nothing it covers; the session follows it; the last turn broke it, or the last turn says the work is done without it."
156
+ ].join("\n");
157
+ }
158
+ function buildDecisionState(turn, earlier = "") {
159
+ return `${TURN_JUDGE_SYSTEM_PROMPT}
160
+
161
+ ${buildTurnShared(turn, earlier)}`;
162
+ }
163
+ function questionFor(displayPath, rule) {
164
+ return {
165
+ type: "choice",
166
+ instructions: `Did this turn follow ${ruleKey(displayPath, rule.id)}? The rule: ${rule.text}`,
167
+ criteria: { ...TURN_CRITERIA }
168
+ };
169
+ }
170
+
171
+ // src/tracevals/rules/timeline.ts
172
+ var HEAD = "# Earlier in this session\n\n";
173
+ var RESULT_CHARS = 120;
174
+ var TICK_CHARS = 60;
175
+ var SPAWNS = 10;
176
+ var TASK = /^\s*-\s+\[([ xX])\]\s+(.+?)\s*$/;
177
+ var TASK_ID = /^(?:[A-Z]+(?:-[A-Z]+)*-?\d+(?:\.\d+)*|\d+(?:\.\d+)*)(?=[\s:.)\]]|$)/;
178
+ var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
179
+ function toolResults(trace) {
180
+ const out = /* @__PURE__ */ new Map();
181
+ for (const e of trace.events) {
182
+ if (e.kind !== "tool_result") continue;
183
+ const message = e.raw.message;
184
+ const content = isRecord(message) ? message.content : void 0;
185
+ if (!Array.isArray(content)) continue;
186
+ for (const block of content) {
187
+ if (!isRecord(block) || block.type !== "tool_result" || typeof block.tool_use_id !== "string") continue;
188
+ const body = block.content;
189
+ const text = typeof body === "string" ? body : Array.isArray(body) ? body.flatMap((b) => isRecord(b) && typeof b.text === "string" ? [b.text] : []).join("\n") : "";
190
+ out.set(block.tool_use_id, { text, isError: block.is_error === true });
191
+ }
192
+ }
193
+ return out;
194
+ }
195
+ function callId(trace, index) {
196
+ const id = trace.events.find((e) => e.index === index)?.raw.id;
197
+ return typeof id === "string" ? id : void 0;
198
+ }
199
+ function tasks(text, ticked) {
200
+ return text.split(/\r?\n/).flatMap((line) => {
201
+ const m = TASK.exec(line);
202
+ const box = m?.[1];
203
+ const body = m?.[2];
204
+ if (box === void 0 || body === void 0) return [];
205
+ return box !== " " === ticked ? [body] : [];
206
+ });
207
+ }
208
+ function ticks(oldText, newText) {
209
+ if (typeof oldText !== "string" || typeof newText !== "string") return [];
210
+ const now = new Set(tasks(newText, true));
211
+ return tasks(oldText, false).filter((t) => now.has(t));
212
+ }
213
+ var list = (verb, items) => items.length > 0 ? [`${verb} ${items.join(", ")}`] : [];
214
+ function timelineBlock(trace, before, opts) {
215
+ const scrub = makeRedactor(opts.redact);
216
+ const results = toolResults(trace);
217
+ const starts = trace.events.filter((e) => e.index < before && e.sidechain !== true && isTypedPrompt(e)).map((e) => e.index);
218
+ const lines = starts.flatMap((from, i) => {
219
+ const end = starts[i + 1] ?? before;
220
+ const window = materialize(trace, "turn", "earlier turn", [{ start: from, end }], void 0, /* @__PURE__ */ new Set([void 0]));
221
+ const facts = turnFacts(trace, { window, from, to: end - 1, sessionTurnCount: 0 }, opts.sources, opts);
222
+ const spawns = trace.agentSpawns.filter((a) => a.index >= from && a.index < end).slice(0, SPAWNS).map((a) => {
223
+ const result = results.get(a.toolUseId ?? callId(trace, a.index) ?? "");
224
+ const first = scrub(result?.text ?? "").trim().split(/\r?\n/)[0]?.trim() ?? "";
225
+ return first === "" ? `spawned ${a.subagentType}` : `spawned ${a.subagentType}, which returned ${clipTo(first, RESULT_CHARS)}`;
226
+ });
227
+ const calls = window.toolCalls;
228
+ const asked = calls.some((c) => c.name === "AskUserQuestion") ? ["asked the user"] : [];
229
+ const ticked = calls.flatMap((c) => {
230
+ if (typeof c.input.file_path !== "string") return [];
231
+ const edits = c.name === "Edit" ? [c.input] : c.name === "MultiEdit" && Array.isArray(c.input.edits) ? c.input.edits : [];
232
+ const path = scrub(projectPath(c.input.file_path, opts.cwd, opts.root));
233
+ return edits.flatMap(
234
+ (e) => isRecord(e) ? ticks(e.old_string, e.new_string).map((t) => {
235
+ const safe = scrub(t);
236
+ return `ticked ${TASK_ID.exec(safe)?.[0] ?? clipTo(safe, TICK_CHARS)} in ${path}`;
237
+ }) : []
238
+ );
239
+ });
240
+ const approved = calls.some((c) => {
241
+ if (c.name !== "ExitPlanMode") return false;
242
+ const result = results.get(callId(trace, c.index) ?? "");
243
+ return result !== void 0 && !result.isError;
244
+ }) ? ["had a plan approved"] : [];
245
+ const parts = [
246
+ ...list("ran", facts.commands),
247
+ ...list("wrote", facts.wrote),
248
+ ...list("read", facts.read),
249
+ ...facts.skills.map((s) => `ran skill ${s}`),
250
+ ...spawns,
251
+ ...asked,
252
+ ...[...new Set(ticked)],
253
+ ...approved
254
+ ];
255
+ if (parts.length === 0) return [];
256
+ const out = opts.ledger?.turns.find((t) => t.turn === from)?.inScope === false;
257
+ return [{ turn: from, line: `- turn ${String(from)}: ${parts.join("; ")}${out ? " (no rules in scope)" : ""}` }];
258
+ });
259
+ const max = opts.maxChars ?? Number.POSITIVE_INFINITY;
260
+ const marker = (n) => {
261
+ const a = String(lines[0]?.turn);
262
+ const b = String(lines[n - 1]?.turn);
263
+ return n === 1 ? `- (turn ${a}: 1 line left out)` : `- (turns ${a}\u2013${b}: ${String(n)} lines left out)`;
264
+ };
265
+ let kept = lines.reduce((sum, l) => sum + l.line.length + 1, HEAD.length - 1);
266
+ let dropped = 0;
267
+ const size = () => kept + (dropped > 0 ? marker(dropped).length + 1 : 0);
268
+ while (dropped < lines.length && size() > max) {
269
+ kept -= (lines[dropped]?.line.length ?? 0) + 1;
270
+ dropped += 1;
271
+ }
272
+ if (dropped === lines.length) return "";
273
+ const shown = lines.slice(dropped).map((l) => l.line);
274
+ return `${HEAD}${[...dropped > 0 ? [marker(dropped)] : [], ...shown].join("\n")}`;
275
+ }
276
+
277
+ // src/tracevals/rules/judge.ts
278
+ var DEFAULT_TURN_CACHE_DIR = ".manni/tracevals/cache/turns";
279
+ var CHARS_PER_TOKEN = 3;
280
+ var isRecord2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
281
+ function isScores(v) {
282
+ return isRecord2(v) && TURN_SCORES.every((s) => typeof v[s] === "number");
283
+ }
284
+ var TurnCache = class {
285
+ store;
286
+ constructor(dir = DEFAULT_TURN_CACHE_DIR, enabled = true) {
287
+ this.store = new JsonCache(dir, enabled, "manni-tracevals");
288
+ }
289
+ /** An entry of any other shape, from an older version, is a miss. */
290
+ get(key) {
291
+ const v = this.store.get(key);
292
+ if (!isRecord2(v) || !Array.isArray(v.runs) || v.runs.length === 0) return void 0;
293
+ const runs = v.runs;
294
+ return runs.every(isScores) ? runs : void 0;
295
+ }
296
+ set(key, runs) {
297
+ this.store.set(key, { runs });
298
+ }
299
+ };
300
+ var StateLimits = class {
301
+ store;
302
+ constructor(dir, enabled = true) {
303
+ this.store = new JsonCache(dir, enabled, "manni-tracevals");
304
+ }
305
+ get(id) {
306
+ const v = this.store.get(buildCacheKey([id.provider, id.model]));
307
+ return isRecord2(v) && (v.limit === null || typeof v.limit === "number") ? v.limit : void 0;
308
+ }
309
+ set(id, limit) {
310
+ this.store.set(buildCacheKey([id.provider, id.model]), { limit });
311
+ }
312
+ };
313
+ function applicableRules(rules, window) {
314
+ const applicable = rules.filter(
315
+ (r) => evaluateWhen({ when: r.rule.when }, window).armed
316
+ );
317
+ return { applicable, notApplicable: rules.length - applicable.length };
318
+ }
319
+ var round = (n) => Math.round(n * 100) / 100;
320
+ function decisionOnly(provider) {
321
+ return DECISION_ONLY_PROVIDERS.has(provider.provider()) && canDecide(provider) ? provider : void 0;
322
+ }
323
+ function planTurn(input, id, decisionOnly2, limit) {
324
+ const runs = decisionOnly2 ? 1 : input.runs;
325
+ const { applicable } = applicableRules(input.rules, input.turn.window);
326
+ const warnings = [];
327
+ const hits = /* @__PURE__ */ new Map();
328
+ const sourceIndex = /* @__PURE__ */ new Map();
329
+ for (const r of input.rules) {
330
+ const path = r.source.displayPath;
331
+ if (!sourceIndex.has(path)) sourceIndex.set(path, sourceIndex.size);
332
+ }
333
+ const planned = applicable.map(({ source, rule }) => {
334
+ const history = !decisionOnly2 && input.ledger !== void 0 ? historyBlock(input.ledger, ruleKey(source.displayPath, rule.id), rule.text, input.turn.from) : "";
335
+ return {
336
+ qid: `${String(sourceIndex.get(source.displayPath))}:${rule.id}`,
337
+ source: source.displayPath,
338
+ id: rule.id,
339
+ text: rule.text,
340
+ history,
341
+ item: buildRuleItem(source.displayPath, rule, history)
342
+ };
343
+ });
344
+ if (planned.length === 0) {
345
+ return { planned, turnText: "", earlier: "", warnings, hits, todo: [], keyOf: () => "" };
346
+ }
347
+ const tail = lastMessageLine(input);
348
+ let budget = input.render.maxTotalChars;
349
+ let byLimit = false;
350
+ if (limit !== void 0) {
351
+ const longest = Math.max(
352
+ ...planned.map(
353
+ (p) => decisionOnly2 ? JSON.stringify(questionFor(p.source, p)).length : p.item.length
354
+ )
355
+ );
356
+ const fixed = decisionOnly2 ? buildDecisionState("").length : TURN_JUDGE_SYSTEM_PROMPT.length + buildTurnShared("").length;
357
+ const fit = limit * CHARS_PER_TOKEN - longest - fixed;
358
+ if (fit < budget) {
359
+ budget = fit;
360
+ byLimit = true;
361
+ }
362
+ }
363
+ const sources = [
364
+ ...new Map(
365
+ input.rules.flatMap(
366
+ ({ source: { path, displayPath } }) => (
367
+ // A source with no file (the typed prompts, an inline plan) is never read.
368
+ path !== void 0 && path !== "" ? [[displayPath, { path, displayPath }]] : []
369
+ )
370
+ )
371
+ ).values()
372
+ ];
373
+ const earlier = timelineBlock(input.trace, input.turn.from, {
374
+ cwd: input.project?.cwd ?? input.trace.cwd,
375
+ root: input.project?.root ?? input.trace.cwd,
376
+ redact: input.render.redact,
377
+ sources,
378
+ ...input.ledger !== void 0 ? { ledger: input.ledger } : {},
379
+ maxChars: Math.floor(budget / 4)
380
+ });
381
+ budget -= buildTurnShared("", earlier).length - buildTurnShared("").length;
382
+ const cut = { happened: false };
383
+ const turnText = renderTrace(input.trace, {
384
+ maxBlockChars: input.render.maxBlockChars,
385
+ maxTotalChars: budget - tail.length,
386
+ redact: input.render.redact,
387
+ window: input.turn.window,
388
+ onTruncated: () => {
389
+ cut.happened = true;
390
+ }
391
+ }) + tail;
392
+ if (cut.happened) {
393
+ warnings.push(
394
+ byLimit ? `the turn was cut to fit the state limit of ${String(limit)} tokens of ${id.provider}/${id.model}; the judge saw its head and tail` : `the turn was cut to the render cap of ${String(input.render.maxTotalChars)} characters; the judge saw its head and tail`
395
+ );
396
+ }
397
+ const base = [
398
+ id.provider,
399
+ id.model,
400
+ decisionOnly2 ? "decision" : "generative",
401
+ `r${String(runs)}`,
402
+ `t${String(input.temperature)}`,
403
+ `turn-v${String(TURN_JUDGE_PROMPT_VERSION)}`,
404
+ sha256(turnText),
405
+ sha256(earlier)
406
+ ];
407
+ const keyOf = (p) => buildCacheKey([...base, sha256(JSON.stringify([p.source, p.id, p.text, p.history]))]);
408
+ const todo = [];
409
+ for (const p of planned) {
410
+ const hit = input.cache?.get(keyOf(p));
411
+ if (hit !== void 0) hits.set(p, { runs: hit });
412
+ else todo.push(p);
413
+ }
414
+ return { planned, turnText, earlier, warnings, hits, todo, keyOf };
415
+ }
416
+ function allVerdictsCached(input, id) {
417
+ const limit = input.limits.get(id);
418
+ if (limit === void 0 || DECISION_ONLY_PROVIDERS.has(id.provider)) return false;
419
+ const plan = planTurn(input, id, false, limit ?? void 0);
420
+ return plan.planned.length > 0 && plan.todo.length === 0;
421
+ }
422
+ async function judgeTurn(input) {
423
+ const { provider, zones } = input;
424
+ const decider = decisionOnly(provider);
425
+ const mode = decider !== void 0 ? "decision" : "generative";
426
+ const runs = decider !== void 0 ? 1 : input.runs;
427
+ const id = { provider: provider.provider(), model: provider.modelName() };
428
+ const { applicable, notApplicable } = applicableRules(input.rules, input.turn.window);
429
+ const result = {
430
+ mode,
431
+ runs,
432
+ findings: [],
433
+ verdicts: [],
434
+ judged: applicable.length,
435
+ notApplicable,
436
+ cached: false,
437
+ warnings: []
438
+ };
439
+ if (applicable.length === 0) return result;
440
+ const fresh = async () => {
441
+ const real = canDecide(provider) ? await provider.stateLimit() : null;
442
+ input.limits?.set(id, real);
443
+ return real;
444
+ };
445
+ const remembered = input.limits?.get(id);
446
+ let limit = remembered ?? await fresh();
447
+ let plan = planTurn(input, id, decider !== void 0, limit ?? void 0);
448
+ if (remembered !== void 0 && plan.todo.length > 0) {
449
+ const real = await fresh();
450
+ if (real !== limit) {
451
+ limit = real;
452
+ plan = planTurn(input, id, decider !== void 0, limit ?? void 0);
453
+ }
454
+ }
455
+ const { planned, hits: verdicts, todo, keyOf, turnText, earlier } = plan;
456
+ const warnings = plan.warnings;
457
+ result.warnings = warnings;
458
+ result.cached = todo.length === 0;
459
+ if (todo.length > 0) {
460
+ const scored = decider !== void 0 ? await decide(decider, todo, buildDecisionState(turnText, earlier)) : await score(provider, todo, buildTurnShared(turnText, earlier), runs, input.temperature);
461
+ if (scored.every((v) => v.runs.length === 0)) {
462
+ throw new Error(scored.find((v) => v.error !== void 0)?.error ?? "every judge call errored");
463
+ }
464
+ const errored = scored.filter((v) => v.error !== void 0);
465
+ if (errored.length > 0) {
466
+ warnings.push(
467
+ `the judge errored on ${String(errored.length)} of ${String(todo.length)} rules, so they need review: ${errored[0]?.error ?? ""}`
468
+ );
469
+ }
470
+ todo.forEach((p, i) => {
471
+ const v = scored[i] ?? { runs: [], error: "the judge returned nothing" };
472
+ verdicts.set(p, v);
473
+ if (v.error === void 0) input.cache?.set(keyOf(p), v.runs);
474
+ });
475
+ }
476
+ for (const p of planned) {
477
+ const v = verdicts.get(p) ?? { runs: [], error: "the judge returned nothing" };
478
+ const outcome = outcomeOf(v, runs, zones);
479
+ const reasoning = v.runs.find((r) => typeof r.reasoning === "string")?.reasoning;
480
+ result.verdicts.push({
481
+ source: p.source,
482
+ rule: p.id,
483
+ text: p.text,
484
+ outcome,
485
+ ...reasoning !== void 0 ? { reasoning } : {}
486
+ });
487
+ if (outcome === "not-applicable") result.notApplicable += 1;
488
+ else if (outcome !== "followed") result.findings.push(findingOf(p, outcome, v, runs));
489
+ }
490
+ return result;
491
+ }
492
+ async function decide(decider, todo, state) {
493
+ const response = await decider.decide({
494
+ state,
495
+ questions: Object.fromEntries(todo.map((p) => [p.qid, questionFor(p.source, p)]))
496
+ });
497
+ const answers = response.answers;
498
+ return todo.map((p) => {
499
+ const answer = answers[p.qid];
500
+ if (answer === void 0) return { runs: [], error: "the judge returned no answer for this rule" };
501
+ const pct = (s) => Math.round((answer.probabilities[s] ?? 0) * 100);
502
+ return {
503
+ runs: [
504
+ {
505
+ followed: pct("followed"),
506
+ "not-followed": pct("not-followed"),
507
+ "not-applicable": pct("not-applicable")
508
+ }
509
+ ]
510
+ };
511
+ });
512
+ }
513
+ async function score(provider, todo, shared, runs, temperature) {
514
+ const verdicts = todo.map(() => ({ runs: [] }));
515
+ const errors = todo.map(() => 0);
516
+ for (let run = 0; run < runs; run++) {
517
+ const response = await completeJSONShared(provider, {
518
+ system: TURN_JUDGE_SYSTEM_PROMPT,
519
+ shared,
520
+ items: todo.map((p) => p.item),
521
+ schema: TURN_SCHEMA,
522
+ temperature
523
+ });
524
+ verdicts.forEach((v, i) => {
525
+ const answer = response.answers[i];
526
+ if (answer !== void 0 && "json" in answer && isScores(answer.json)) {
527
+ v.runs.push(answer.json);
528
+ return;
529
+ }
530
+ errors[i] = (errors[i] ?? 0) + 1;
531
+ v.error ??= answer !== void 0 && "error" in answer ? answer.error : "the judge returned nothing";
532
+ });
533
+ }
534
+ return verdicts.map(
535
+ (v, i) => v.error === void 0 || v.runs.length === 0 ? v : { ...v, error: `${String(errors[i] ?? 0)} of ${String(runs)} runs errored: ${v.error}` }
536
+ );
537
+ }
538
+ function classify(s, zones) {
539
+ if (s["not-followed"] / 100 >= zones.autoFail) return "fail";
540
+ if (s["not-applicable"] / 100 >= zones.autoPass) return "not-applicable";
541
+ if (s.followed / 100 >= zones.autoPass) return "followed";
542
+ return "needs-review";
543
+ }
544
+ function outcomeOf(v, runs, zones) {
545
+ if (v.error !== void 0 || v.runs.length < runs) return "needs-review";
546
+ const each = v.runs.map((s) => classify(s, zones));
547
+ if (each.every((c) => c === "fail")) return "fail";
548
+ if (each.every((c) => c === "not-applicable")) return "not-applicable";
549
+ if (each.every((c) => c === "not-applicable" || c === "followed")) return "followed";
550
+ return "needs-review";
551
+ }
552
+ function findingOf(p, outcome, v, runs) {
553
+ const base = { source: p.source, rule: p.id, text: p.text, outcome };
554
+ if (v.runs.length === 0) {
555
+ return {
556
+ ...base,
557
+ observed: `the judge returned no answer for this rule: ${v.error ?? ""}`,
558
+ confidence: 0
559
+ };
560
+ }
561
+ const mean = (s) => Math.round(v.runs.reduce((sum, r) => sum + r[s], 0) / v.runs.length);
562
+ const scores = `not-followed ${String(mean("not-followed"))}, followed ${String(mean("followed"))}, not-applicable ${String(mean("not-applicable"))}`;
563
+ const errored = v.error !== void 0 && runs > 1 ? `; ${v.error}` : "";
564
+ const reasoning = v.runs.find((r) => typeof r.reasoning === "string")?.reasoning;
565
+ return {
566
+ ...base,
567
+ observed: `${scores}${errored}${reasoning !== void 0 ? `. ${reasoning}` : ""}`,
568
+ confidence: round(mean("not-followed") / 100),
569
+ ...reasoning !== void 0 ? { reasoning } : {}
570
+ };
571
+ }
572
+ function lastMessageLine(input) {
573
+ const message = input.lastAssistantMessage?.trim();
574
+ if (message === void 0 || message === "") return "";
575
+ if (input.turn.window.assistantTexts.at(-1)?.trim() === message) return "";
576
+ const safe = makeRedactor(input.render.redact)(message);
577
+ const max = input.render.maxBlockChars;
578
+ const clipped = safe.length <= max ? safe : `${safe.slice(0, max)} [... truncated ${String(safe.length - max)} chars ...]`;
579
+ return `
580
+ [assistant] ${clipped}`;
581
+ }
582
+
583
+ // src/tracevals/commands/check.ts
584
+ var idOf = (p) => ({
585
+ provider: p.provider(),
586
+ model: p.modelName()
587
+ });
588
+ var LEDGER_OUTCOME = {
589
+ fail: "broken",
590
+ followed: "followed",
591
+ "needs-review": "needs-review",
592
+ "not-applicable": "not-applicable"
593
+ };
594
+ async function conform(p) {
595
+ const ledgerFile = ledgerPath(p.projectDir, p.sessionId, p.agentId);
596
+ const ledger = await readLedger(ledgerFile);
597
+ const seen = { sources: [] };
598
+ const outcome = await judgeTurnOf(p, ledger, seen);
599
+ if (p.inLoop) await record(p, ledgerFile, ledger, seen);
600
+ else if (outcome.kind === "report") outcome.report.session = rollup(ledger);
601
+ return outcome;
602
+ }
603
+ async function record(p, file, ledger, seen) {
604
+ const facts = turnFacts(p.trace, p.turn, seen.sources, {
605
+ cwd: p.projectDir,
606
+ root: p.projectRoot ?? p.projectDir,
607
+ redact: p.config.judge.redact
608
+ });
609
+ let next = recordFacts(ledger, facts);
610
+ if (seen.judgement !== void 0) {
611
+ next = recordTurn(
612
+ next,
613
+ p.turn.from,
614
+ seen.judgement.verdicts.map((v) => ({
615
+ key: ruleKey(v.source, v.rule),
616
+ text: v.text,
617
+ outcome: LEDGER_OUTCOME[v.outcome],
618
+ note: v.reasoning ?? ""
619
+ }))
620
+ );
621
+ }
622
+ try {
623
+ await writeLedger(file, next);
624
+ } catch (err) {
625
+ warn(`could not write the session ledger ${file}: ${firstLine(err)}`);
626
+ }
627
+ }
628
+ async function judgeTurnOf(p, ledger, seen) {
629
+ const { config, turn } = p;
630
+ const conformance = conformanceOf(config);
631
+ const local = p.localModels ?? libraryLocalModels(config.providers);
632
+ const report = {
633
+ trace: p.trace.file,
634
+ sessionId: p.sessionId,
635
+ agentId: p.agentId,
636
+ turn: { from: turn.from, to: turn.to },
637
+ judge: null,
638
+ extraction: null,
639
+ sources: [],
640
+ findings: [],
641
+ summary: { sources: 0, rules: 0, notApplicable: 0, fail: 0, needsReview: 0 },
642
+ session: null,
643
+ skipped: null,
644
+ warnings: [...p.trace.warnings],
645
+ exitCode: 0
646
+ };
647
+ const stop = (skipped) => {
648
+ report.skipped = skipped;
649
+ return { kind: "report", report };
650
+ };
651
+ if (turn.window.empty) return stop("empty-turn");
652
+ const resolved = await resolveTurnSources(p.trace, turn, {
653
+ projectDir: p.projectDir,
654
+ ...p.projectRoot !== void 0 ? { projectRoot: p.projectRoot } : {},
655
+ ...p.env !== void 0 ? { env: p.env } : {},
656
+ include: conformance.include,
657
+ exclude: conformance.exclude,
658
+ plans: conformance.plans,
659
+ ...p.agentType !== void 0 ? { agentType: p.agentType } : {}
660
+ });
661
+ report.warnings.push(...resolved.warnings);
662
+ const { sources } = resolved;
663
+ seen.sources = sources;
664
+ report.summary.sources = sources.length;
665
+ if (sources.length === 0) return stop("no-sources");
666
+ const judgeId = p.judge !== void 0 ? idOf(p.judge) : await resolveSelectionIdentity(config, p.judgeSelection);
667
+ const judgeIsLocal = judgeId.provider === "llama-cpp";
668
+ if (p.inLoop && judgeIsLocal) {
669
+ const skip = await localGate(local, judgeId.model, ["downloading"]);
670
+ if (skip !== void 0) return { kind: "gate", skip };
671
+ }
672
+ const host = hostSetting(p.inLoop, p.sessionId, config.providers["llama-cpp"]?.keepAlive);
673
+ const ex = await extraction(config, rulesCacheFor(config, p.configDir, p.noCache), p.extractor, host);
674
+ if (sources.some((s) => ex.needs(s))) {
675
+ report.extraction = { provider: ex.identity.provider, model: ex.identity.model };
676
+ if (p.offline && isNetworkProvider(ex.identity.provider)) {
677
+ throw offlineRefusal("extraction", ex.identity);
678
+ }
679
+ if (ex.identity.provider === "llama-cpp") {
680
+ if (p.inLoop) {
681
+ const skip = await localGate(
682
+ local,
683
+ ex.identity.model,
684
+ ["downloading", "not-downloaded", "memory"],
685
+ () => hostHolds(ex.identity.model, p.hostApi)
686
+ );
687
+ if (skip !== void 0) return { kind: "gate", skip };
688
+ } else {
689
+ await assertDownloaded(local, ex.identity.model);
690
+ }
691
+ }
692
+ }
693
+ const rules = [];
694
+ for (const source of sources) {
695
+ const { rules: found, origin } = await ex.rulesOf(source);
696
+ report.sources.push({
697
+ path: source.displayPath,
698
+ format: source.format,
699
+ ...source.skill !== void 0 ? { skill: source.skill } : {},
700
+ trigger: source.trigger,
701
+ rules: found.length,
702
+ origin
703
+ });
704
+ for (const rule of found) rules.push({ source, rule });
705
+ }
706
+ report.summary.rules = rules.length;
707
+ const { applicable } = applicableRules(rules, turn.window);
708
+ if (applicable.length === 0) {
709
+ report.summary.notApplicable = rules.length;
710
+ return stop("not-applicable");
711
+ }
712
+ if (p.offline && isNetworkProvider(judgeId.provider)) {
713
+ throw offlineRefusal("the judge", judgeId);
714
+ }
715
+ const cacheRoot = resolve(p.configDir, config.judge.cacheDir);
716
+ const limits = new StateLimits(resolve(cacheRoot, "limits"), !p.noCache);
717
+ const plan = {
718
+ trace: p.trace,
719
+ turn,
720
+ rules,
721
+ runs: p.runs,
722
+ temperature: config.judge.temperature,
723
+ zones: config.judge.zones,
724
+ render: {
725
+ maxBlockChars: config.render.maxBlockChars,
726
+ maxTotalChars: config.render.maxTotalChars,
727
+ redact: config.judge.redact
728
+ },
729
+ ...p.lastAssistantMessage !== void 0 ? { lastAssistantMessage: p.lastAssistantMessage } : {},
730
+ ledger,
731
+ project: { cwd: p.projectDir, root: p.projectRoot ?? p.projectDir },
732
+ cache: new TurnCache(resolve(cacheRoot, "turns"), !p.noCache)
733
+ };
734
+ if (judgeIsLocal) {
735
+ if (p.inLoop) {
736
+ const skip = await localGate(
737
+ local,
738
+ judgeId.model,
739
+ ["not-downloaded", "memory"],
740
+ async () => allVerdictsCached({ ...plan, limits }, judgeId) || await hostHolds(judgeId.model, p.hostApi)
741
+ );
742
+ if (skip !== void 0) return { kind: "gate", skip };
743
+ } else {
744
+ await assertDownloaded(local, judgeId.model);
745
+ }
746
+ }
747
+ markJudgeProcess();
748
+ const provider = p.judge ?? (judgeId.provider === "mock" ? mockTurnJudge(judgeId.model) : constructProvider(config, judgeId, { host }));
749
+ let ran;
750
+ try {
751
+ ran = await queued(
752
+ judgeId.model,
753
+ () => judgeTurn({ ...plan, provider, limits })
754
+ );
755
+ } catch (err) {
756
+ if (err instanceof TracevalsError) throw err;
757
+ throw new TracevalsError(`could not judge the last turn: ${firstLine(err)}`);
758
+ }
759
+ if (ran.busy) {
760
+ return {
761
+ kind: "gate",
762
+ skip: {
763
+ gate: "busy",
764
+ message: `tracevals skipped this turn: ${judgeId.model} was busy with other judgements for ${String(QUEUE_WAIT_MS / 6e4)} minutes.`
765
+ }
766
+ };
767
+ }
768
+ const judgement = ran.value;
769
+ seen.judgement = judgement;
770
+ report.judge = {
771
+ provider: judgeId.provider,
772
+ model: judgeId.model,
773
+ mode: judgement.mode,
774
+ runs: judgement.runs
775
+ };
776
+ report.findings = judgement.findings;
777
+ report.summary.notApplicable = judgement.notApplicable;
778
+ report.summary.fail = judgement.findings.filter((f) => f.outcome === "fail").length;
779
+ report.summary.needsReview = judgement.findings.length - report.summary.fail;
780
+ report.warnings.push(...judgement.warnings);
781
+ report.exitCode = report.summary.fail > 0 ? 1 : 0;
782
+ return { kind: "report", report, judgement };
783
+ }
784
+ async function readTrace(path) {
785
+ try {
786
+ return await parseTraceFile(path);
787
+ } catch (err) {
788
+ throw new TracevalsError(`cannot read trace ${path}: ${firstLine(err)}`);
789
+ }
790
+ }
791
+ async function runCheck(options) {
792
+ const { config, dir: configDir } = await discoverConfig(options.configDir ?? process.cwd(), {
793
+ ...options.config === void 0 ? {} : { configPath: options.config },
794
+ ...options.noConfig === void 0 ? {} : { noConfig: options.noConfig }
795
+ });
796
+ const judgeSelection = selectProvider(config, {
797
+ ...options.provider !== void 0 ? { provider: options.provider } : {},
798
+ ...options.model !== void 0 ? { model: options.model } : {},
799
+ ...options.local !== void 0 ? { local: options.local } : {}
800
+ });
801
+ const trace = await readTrace(options.tracePath);
802
+ const outcome = await conform({
803
+ config,
804
+ configDir,
805
+ trace,
806
+ turn: lastTurn(trace),
807
+ sessionId: trace.sessionId ?? basename(trace.file).replace(/\.jsonl$/, ""),
808
+ agentId: null,
809
+ projectDir: options.project ?? trace.cwd,
810
+ ...options.project !== void 0 ? { projectRoot: options.project } : {},
811
+ ...options.env !== void 0 ? { env: options.env } : {},
812
+ judgeSelection,
813
+ runs: options.runs ?? config.judge.ensembleRuns,
814
+ inLoop: false,
815
+ noCache: options.noCache === true,
816
+ offline: options.offline === true,
817
+ ...seamsOf(options)
818
+ });
819
+ if (outcome.kind === "gate") throw new TracevalsError(outcome.skip.message);
820
+ const { report } = outcome;
821
+ const rendered = options.format === "json" ? JSON.stringify(report, null, 2) : renderCheck(report, { color: options.color === true });
822
+ if (options.output !== void 0) await writeFile(options.output, rendered, "utf-8");
823
+ return { report, rendered };
824
+ }
825
+ function seamsOf(s) {
826
+ return {
827
+ ...s.judge !== void 0 ? { judge: s.judge } : {},
828
+ ...s.extractor !== void 0 ? { extractor: s.extractor } : {},
829
+ ...s.localModels !== void 0 ? { localModels: s.localModels } : {},
830
+ ...s.hostApi !== void 0 ? { hostApi: s.hostApi } : {}
831
+ };
832
+ }
833
+ async function checkTurn(input) {
834
+ const { config, dir: configDir } = await discoverConfig(input.cwd);
835
+ if (config.conformance === null) {
836
+ return { skipped: { gate: "not-in-play" }, findings: [], exitCode: 0 };
837
+ }
838
+ const env = input.env ?? process.env;
839
+ if ((env[JUDGE_ENV] ?? "") !== "") {
840
+ return { skipped: { gate: "judge-session" }, findings: [], exitCode: 0 };
841
+ }
842
+ const subagent = input.agentTranscriptPath !== void 0;
843
+ const trace = await readTrace(input.agentTranscriptPath ?? input.transcriptPath);
844
+ const outcome = await conform({
845
+ config,
846
+ configDir,
847
+ trace,
848
+ turn: subagent ? subagentTurn(trace) : lastTurn(trace),
849
+ sessionId: input.sessionId,
850
+ agentId: input.agentId ?? null,
851
+ ...input.agentType !== void 0 ? { agentType: input.agentType } : {},
852
+ projectDir: input.cwd,
853
+ ...input.env !== void 0 ? { env: input.env } : {},
854
+ judgeSelection: selectHookProvider(config),
855
+ runs: config.conformance.hook.runs,
856
+ inLoop: true,
857
+ noCache: false,
858
+ offline: false,
859
+ ...input.lastAssistantMessage !== void 0 ? { lastAssistantMessage: input.lastAssistantMessage } : {},
860
+ ...seamsOf(input)
861
+ });
862
+ if (outcome.kind === "gate") {
863
+ return { skipped: outcome.skip, findings: [], exitCode: 0 };
864
+ }
865
+ const { report, judgement } = outcome;
866
+ if (report.skipped !== null) {
867
+ return { skipped: { gate: report.skipped }, findings: [], report, exitCode: 0 };
868
+ }
869
+ return {
870
+ ...judgement !== void 0 ? { judgement } : {},
871
+ findings: report.findings,
872
+ report,
873
+ exitCode: report.exitCode === 1 ? 1 : 0
874
+ };
875
+ }
876
+ export {
877
+ checkTurn,
878
+ runCheck
879
+ };
880
+ //# sourceMappingURL=check-WB2QDHJQ.js.map