@iowarp/clio-coder 0.4.8 → 0.4.9

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 (513) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +7 -6
  3. package/dist/{acp-JWPQZM2D.js → acp-ZWZCPS2A.js} +13 -13
  4. package/dist/{agents-4GCDIRVX.js → agents-LYSOWZUE.js} +53 -52
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-SYAKTDQE.js → auth-WBQGKWQ5.js} +27 -27
  7. package/dist/{background-OW67WMYR.js → background-BUMOBAQN.js} +4 -4
  8. package/dist/{builtins-TKS63VNV.js → builtins-ODRJOEDI.js} +7 -7
  9. package/dist/{chunk-JLBVCROW.js → chunk-2DRRZ57Q.js} +33 -24
  10. package/dist/chunk-2JBZYUPY.js +105 -0
  11. package/dist/chunk-2KUBKL63.js +336 -0
  12. package/dist/{chunk-K45LHSCI.js → chunk-2VBWFXYE.js} +7 -3
  13. package/dist/{chunk-XTLJDC2X.js → chunk-2X2R3UTH.js} +23 -18
  14. package/dist/{chunk-5HULHKT2.js → chunk-37LW32LZ.js} +5 -5
  15. package/dist/{chunk-W7KNI3F5.js → chunk-3AND2EFU.js} +5 -5
  16. package/dist/{chunk-36XSBPXL.js → chunk-3RDHGNU7.js} +95 -27
  17. package/dist/{chunk-BIY22UUK.js → chunk-3SUDBGEI.js} +11 -10
  18. package/dist/{chunk-3IQOZRQ6.js → chunk-3TQN67I2.js} +7 -7
  19. package/dist/{chunk-KWJXCL2X.js → chunk-3U4BL2EV.js} +3 -3
  20. package/dist/{chunk-RBES4TCZ.js → chunk-3UQADNG2.js} +3 -3
  21. package/dist/{chunk-V4ZKOKRB.js → chunk-434LRQ6Z.js} +61 -53
  22. package/dist/{chunk-MWMW53WW.js → chunk-4ATBOFRP.js} +649 -193
  23. package/dist/{chunk-QGIC5SX5.js → chunk-4DNL43EZ.js} +3 -3
  24. package/dist/{chunk-GVU4CXPJ.js → chunk-4HFJKRGZ.js} +113 -54
  25. package/dist/{chunk-5A6XR3RJ.js → chunk-555E2WVV.js} +16 -2
  26. package/dist/{chunk-LZDLYSUN.js → chunk-5RTEFNBP.js} +3 -3
  27. package/dist/{chunk-HMGAKB7E.js → chunk-64XJW7NT.js} +15 -15
  28. package/dist/{chunk-EXKUF426.js → chunk-7FBCRWVT.js} +280 -280
  29. package/dist/{chunk-K3W6BF5C.js → chunk-7JSOSVLP.js} +2 -2
  30. package/dist/{chunk-WFTSK7N3.js → chunk-7N3OLLSL.js} +4 -4
  31. package/dist/{chunk-JRA6OBHY.js → chunk-A6DULIMH.js} +17 -5
  32. package/dist/{chunk-R5NRX5N4.js → chunk-AB3QXXBC.js} +2 -2
  33. package/dist/chunk-ACCECAH4.js +49 -0
  34. package/dist/{chunk-GJBJHJNY.js → chunk-AM6CEP2K.js} +5 -5
  35. package/dist/{chunk-MUXNDNMZ.js → chunk-AY4XE6GN.js} +19 -13
  36. package/dist/{chunk-MATCRH3M.js → chunk-BBA2TAWV.js} +9 -9
  37. package/dist/{chunk-PMUUAABD.js → chunk-BMNVVKEW.js} +9 -9
  38. package/dist/{chunk-TOPICHGR.js → chunk-CTGZCEI6.js} +2 -2
  39. package/dist/{chunk-L75H5B3B.js → chunk-DIAJYJYG.js} +2 -2
  40. package/dist/{chunk-JIMWEYWO.js → chunk-EHZRAB4U.js} +2 -2
  41. package/dist/{chunk-YXANQGCX.js → chunk-EM2DIQAJ.js} +6 -6
  42. package/dist/{chunk-JCVIL6TY.js → chunk-ETF4ROKH.js} +4 -4
  43. package/dist/{chunk-5W4FRA5Q.js → chunk-F2YM3JY4.js} +483 -253
  44. package/dist/{chunk-YGIV24MF.js → chunk-FEBQWHJT.js} +21 -16
  45. package/dist/{chunk-PGEFOTJB.js → chunk-FPS4R2RN.js} +5 -4
  46. package/dist/{chunk-XC5POIL4.js → chunk-G5R53COU.js} +1 -1
  47. package/dist/chunk-GHXGMFQ5.js +40 -0
  48. package/dist/{chunk-QLKCCC2J.js → chunk-GJDRMBDI.js} +14 -14
  49. package/dist/{chunk-2ZWLMA3T.js → chunk-GREYLTZ5.js} +7 -7
  50. package/dist/{chunk-YXFKLMX2.js → chunk-H2WSCZZT.js} +22 -6
  51. package/dist/{chunk-FNVPQQYT.js → chunk-H6IUCY6Q.js} +2 -2
  52. package/dist/{chunk-5C2OQHLR.js → chunk-H72DCH3E.js} +92 -203
  53. package/dist/{chunk-JYKUMHCQ.js → chunk-H7TXJR23.js} +21 -21
  54. package/dist/chunk-HBJQQTKM.js +40 -0
  55. package/dist/chunk-HCVKSGNZ.js +990 -0
  56. package/dist/{chunk-ARRUMZ7X.js → chunk-I47EJPYL.js} +3 -3
  57. package/dist/{chunk-YKIIWURD.js → chunk-IALGWTLO.js} +3 -3
  58. package/dist/{chunk-FB3KTE2J.js → chunk-IALZJE37.js} +4 -4
  59. package/dist/{chunk-RAUOKUZV.js → chunk-IC7JXLOM.js} +15 -10
  60. package/dist/{chunk-LLCGGVSW.js → chunk-IOSVTTCD.js} +7 -7
  61. package/dist/{chunk-DBREN25X.js → chunk-IPTPMLA6.js} +8 -3
  62. package/dist/{chunk-V552WL53.js → chunk-IZZI3SKQ.js} +3 -67
  63. package/dist/{chunk-UDAK6GR2.js → chunk-JIYWMQZ5.js} +2 -2
  64. package/dist/{chunk-O3HSB2YL.js → chunk-JKU34ACI.js} +2 -2
  65. package/dist/{chunk-6X7VOCDY.js → chunk-JTR3VSV3.js} +3 -3
  66. package/dist/{chunk-O2QJDRWP.js → chunk-JU6MAMRJ.js} +4 -4
  67. package/dist/chunk-JURMQWVJ.js +15 -0
  68. package/dist/{chunk-STC6CWUZ.js → chunk-K3XN4LZ4.js} +5 -5
  69. package/dist/{chunk-ATB3Q7YO.js → chunk-KIVFXGBM.js} +27 -2
  70. package/dist/{chunk-WJWNZXRM.js → chunk-KOAHT3N2.js} +2 -2
  71. package/dist/chunk-KP5BPXR3.js +73 -0
  72. package/dist/{chunk-K53E2PTW.js → chunk-KRJQG47M.js} +3 -3
  73. package/dist/{chunk-IILXVWJY.js → chunk-KW6OJ7IY.js} +19 -21
  74. package/dist/{chunk-A46ILRS2.js → chunk-L3NBWLSN.js} +4 -4
  75. package/dist/{chunk-2U2U5POA.js → chunk-L4RUTLRL.js} +5 -5
  76. package/dist/{chunk-QYSAZMSH.js → chunk-LGTVWPRN.js} +2 -2
  77. package/dist/{chunk-KGP3UQGJ.js → chunk-LSQW6KZO.js} +5 -5
  78. package/dist/{chunk-P4JS3MH5.js → chunk-LWJYOHT3.js} +8 -8
  79. package/dist/{chunk-U3TPUXOQ.js → chunk-M6YLF66Z.js} +74 -40
  80. package/dist/{chunk-5D2FNBMG.js → chunk-MJ4QEJVT.js} +2 -2
  81. package/dist/{chunk-RM3XJX7P.js → chunk-MO65K5CH.js} +5 -5
  82. package/dist/{chunk-H5DPSUBB.js → chunk-MTOZEQHL.js} +3 -3
  83. package/dist/{chunk-6R5MBXBJ.js → chunk-NBPA5QM6.js} +2 -2
  84. package/dist/{chunk-H77XBUBM.js → chunk-NMBEW4PP.js} +3 -3
  85. package/dist/{chunk-QWUSS2QP.js → chunk-NPLLK3HO.js} +67 -87
  86. package/dist/{chunk-K5UJD6MM.js → chunk-NSYGPIVW.js} +5 -5
  87. package/dist/{context-EZZPT2ZV.js → chunk-NXTV5OI5.js} +30 -84
  88. package/dist/{chunk-F7Y6QTPL.js → chunk-NYDG4QP4.js} +4 -4
  89. package/dist/{chunk-PFZJMXIY.js → chunk-OA2GDACN.js} +2 -2
  90. package/dist/{chunk-Q32C6AWI.js → chunk-PJI57EC6.js} +4 -4
  91. package/dist/{chunk-EFXMQYI6.js → chunk-PJJBUGMR.js} +52 -52
  92. package/dist/{chunk-ICYIUNO4.js → chunk-PNJE7JPS.js} +18 -3
  93. package/dist/chunk-PP23PZEV.js +1347 -0
  94. package/dist/chunk-PPIFDSBK.js +409 -0
  95. package/dist/{chunk-RFULVPBX.js → chunk-PTFISXQO.js} +6 -5
  96. package/dist/{chunk-JV25I7ID.js → chunk-QB33Z5S7.js} +5 -5
  97. package/dist/{chunk-D55WO5J7.js → chunk-QGNII5VC.js} +8 -8
  98. package/dist/{chunk-RKFNU5UA.js → chunk-QI72X67S.js} +104 -27
  99. package/dist/chunk-QKHZZFKH.js +98 -0
  100. package/dist/{chunk-5UG6EZI3.js → chunk-RDKX2PME.js} +4 -4
  101. package/dist/{chunk-B5ZTR6KZ.js → chunk-RL7LJYN4.js} +1 -1
  102. package/dist/{chunk-BE4I3UJ2.js → chunk-RQROVOV3.js} +15 -13
  103. package/dist/{chunk-TEHVMHOK.js → chunk-S34A7BSP.js} +3 -3
  104. package/dist/{chunk-4P6M2TTE.js → chunk-SJETVJHX.js} +2 -2
  105. package/dist/{chunk-OPC4DQD6.js → chunk-SJMNU4ZS.js} +2 -2
  106. package/dist/{chunk-2JSCCEKO.js → chunk-SLLG2G44.js} +2 -2
  107. package/dist/{chunk-EPYATQMG.js → chunk-SQAZN2V3.js} +42 -16
  108. package/dist/{chunk-E2NSPYLC.js → chunk-SQBT46OF.js} +5 -5
  109. package/dist/{chunk-WTZVSMQZ.js → chunk-TCUOGIL2.js} +5 -5
  110. package/dist/{chunk-RRZFRIJP.js → chunk-TIWPKCVO.js} +5 -5
  111. package/dist/{chunk-QLAGXTTV.js → chunk-UIU7MGZ3.js} +5 -1
  112. package/dist/{chunk-WLHX3MM5.js → chunk-V4XJWDHR.js} +21 -11
  113. package/dist/{chunk-PJ5H5B7A.js → chunk-VPWGADBG.js} +18 -18
  114. package/dist/{chunk-GEYX2NZ5.js → chunk-VWFCAK34.js} +6 -6
  115. package/dist/{chunk-44U2OUSM.js → chunk-W72LLZAV.js} +2 -2
  116. package/dist/{chunk-ORRNGQDV.js → chunk-WGRDABW7.js} +4 -4
  117. package/dist/{chunk-RNLAPBJL.js → chunk-XFLSL7BT.js} +2 -2
  118. package/dist/{chunk-2SXGG2IV.js → chunk-XJZEDCNT.js} +6 -6
  119. package/dist/{chunk-UB33F3YW.js → chunk-XLLEL3K7.js} +5 -5
  120. package/dist/{chunk-2GPGAE5W.js → chunk-XNIZBOFV.js} +15 -1
  121. package/dist/{chunk-WS4FOGLY.js → chunk-XNZWWDC3.js} +2 -2
  122. package/dist/{chunk-P7GTE4FX.js → chunk-XRECG65F.js} +2 -2
  123. package/dist/chunk-XTQ7MEJG.js +457 -0
  124. package/dist/{chunk-GEVQNST4.js → chunk-XZWSP67B.js} +2 -2
  125. package/dist/{chunk-OEMFEL26.js → chunk-Y3M2T5RO.js} +3 -3
  126. package/dist/{chunk-HP7KJ5O2.js → chunk-YPQOPFP7.js} +6 -6
  127. package/dist/{chunk-MEHBW2SP.js → chunk-YQYINEJI.js} +6 -6
  128. package/dist/{chunk-RXI7K4J5.js → chunk-ZF6CV4WZ.js} +1338 -217
  129. package/dist/{chunk-3XE4NRLF.js → chunk-ZKJU55MX.js} +4 -2
  130. package/dist/{chunk-526ABLHD.js → chunk-ZKQ63XZ5.js} +12 -35
  131. package/dist/{chunk-PAQVETLA.js → chunk-ZKVMDNAN.js} +5 -5
  132. package/dist/cli/index.js +47 -37
  133. package/dist/{clio-BPBAPZGA.js → clio-JUDCLNHC.js} +7 -7
  134. package/dist/clio-context-tools-FT672MNZ.js +136 -0
  135. package/dist/{code-nav-KBQ3RIFK.js → code-nav-7OVCTP2Z.js} +28 -26
  136. package/dist/{components-6DKAXWFN.js → components-OZXZMDWU.js} +5 -5
  137. package/dist/{config-FWL5JK2H.js → config-P3ZQVF63.js} +80 -75
  138. package/dist/{config-graph-ACDB26L2.js → config-graph-GKAOBAS5.js} +74 -70
  139. package/dist/{configure-ZIZ4YV62.js → configure-25LRYZJG.js} +45 -44
  140. package/dist/context-72VQV7JX.js +73 -0
  141. package/dist/{context-VIL5MFRH.js → context-COWRWXP3.js} +74 -70
  142. package/dist/{context-Z3GOBHDK.js → context-WB3D474G.js} +12 -12
  143. package/dist/{context-clear-ZPB3L7MN.js → context-clear-Y4LYMWC6.js} +70 -66
  144. package/dist/{context-working-set-2GLBVF7L.js → context-working-set-TMZYVC7A.js} +15 -14
  145. package/dist/data-tool-KMBWKKWR.js +2987 -0
  146. package/dist/{detail-VSBWYSGZ.js → detail-4GLROGY5.js} +71 -67
  147. package/dist/{dispatch-runner-EEEHGKX4.js → dispatch-runner-TR3LBP5P.js} +92 -88
  148. package/dist/{docs-VMMWFVHL.js → docs-ZK777W2G.js} +3 -3
  149. package/dist/{doctor-V5L4IQGP.js → doctor-WC4OV2OB.js} +61 -59
  150. package/dist/{eval-VJYJ2BV3.js → eval-FUNWJNUJ.js} +45 -45
  151. package/dist/{evals-J2H5V6DD.js → evals-L73EBHSU.js} +4 -4
  152. package/dist/{evidence-Y35YSXH6.js → evidence-AVJ2RTHX.js} +80 -76
  153. package/dist/{evidence-POWAEBEW.js → evidence-P4NZOAK7.js} +70 -66
  154. package/dist/{evidence-XCCCLS36.js → evidence-Y55WKYHH.js} +79 -75
  155. package/dist/{evolve-GPG72VB6.js → evolve-MAWKRYWF.js} +75 -71
  156. package/dist/{extensions-YIZ7W3DA.js → extensions-PYQH3H47.js} +8 -8
  157. package/dist/{fleet-2MDCQ2VK.js → fleet-M4H2QBWT.js} +84 -80
  158. package/dist/{fleet-W2AF3TOJ.js → fleet-ULBXXRDR.js} +123 -119
  159. package/dist/{fleet-commands-WS56G26H.js → fleet-commands-7NNC4JZU.js} +17 -16
  160. package/dist/{fleet-decisions-MYGZ3JW7.js → fleet-decisions-EHEY7KPU.js} +9 -9
  161. package/dist/{fleet-graph-ELTBXBAV.js → fleet-graph-LQ2AHZT3.js} +15 -15
  162. package/dist/{fleet-inspect-45IK73L4.js → fleet-inspect-5IGBIIYZ.js} +76 -72
  163. package/dist/{fleet-preflight-T5NCZKHE.js → fleet-preflight-UTTNOKMG.js} +7 -2
  164. package/dist/{fleet-validate-VG4JBLA4.js → fleet-validate-YGILJKA6.js} +20 -20
  165. package/dist/{fleet-verify-VTSABAYO.js → fleet-verify-AUWTCDKR.js} +70 -66
  166. package/dist/{fleet-view-XC7WMKSS.js → fleet-view-TGUFCY5A.js} +73 -69
  167. package/dist/{init-VTJNNTIP.js → init-GFN2Z7NF.js} +94 -90
  168. package/dist/{interop-IU6BNA7C.js → interop-EF5JUWWK.js} +21 -21
  169. package/dist/{inventory-QPQUTUUZ.js → inventory-I6VJDDYF.js} +73 -69
  170. package/dist/{library-Q3NWL5CM.js → library-3J5IO2OJ.js} +13 -13
  171. package/dist/{library-LF7DLU6S.js → library-IJTOFTDS.js} +16 -15
  172. package/dist/{library-HUTAS57T.js → library-Z3KZSHPE.js} +27 -27
  173. package/dist/{library-import-PPW4YUC5.js → library-import-IMKFLDHX.js} +21 -21
  174. package/dist/{library-inventory-DIRVFRZU.js → library-inventory-CQP5D6GU.js} +13 -13
  175. package/dist/{library-validation-XHUZ3INE.js → library-validation-33UTX7AI.js} +11 -11
  176. package/dist/mcp-5FWZKUS6.js +26 -0
  177. package/dist/{memory-Z2LSKNV6.js → memory-36CWN67Y.js} +75 -71
  178. package/dist/{models-3FTREYPY.js → models-KQ6PQJJQ.js} +49 -49
  179. package/dist/{monitor-HF2MQRB3.js → monitor-XX6ZD6KC.js} +83 -79
  180. package/dist/{orchestrator-UYPA6W4S.js → orchestrator-SK6HDAOP.js} +1337 -772
  181. package/dist/{panes-736XB73K.js → panes-L27QRXUH.js} +12 -12
  182. package/dist/{panes-C4P3PIWT.js → panes-LXZIWNOZ.js} +4 -4
  183. package/dist/{paths-JQ4QYIYB.js → paths-7DJDU4P4.js} +5 -5
  184. package/dist/{preload-XSLRYH3Y.js → preload-K2TDYI4Y.js} +70 -66
  185. package/dist/{reset-V7QSPZYE.js → reset-73VU3XNT.js} +10 -10
  186. package/dist/{resources-OJGDFHYT.js → resources-3BYJYVYL.js} +16 -16
  187. package/dist/{run-T354SMDW.js → run-AR7PY6GW.js} +132 -128
  188. package/dist/run-script-H2KUDIII.js +41 -0
  189. package/dist/{settings-MWZXO6RV.js → settings-3VMBMWID.js} +4 -4
  190. package/dist/{share-Y5ZKJPND.js → share-HVWH4FPF.js} +21 -21
  191. package/dist/{skills-4GLZC4LN.js → skills-5TYEY75Q.js} +22 -22
  192. package/dist/{skills-eval-L5T7GODM.js → skills-eval-CK3MD63Z.js} +96 -87
  193. package/dist/{skills-inventory-LASKXEZI.js → skills-inventory-KSFYG3I6.js} +16 -16
  194. package/dist/{slash-commands-OIMRU36D.js → slash-commands-DMVHML7P.js} +47 -44
  195. package/dist/{steer-KMAM2Y2C.js → steer-XCD6V3EW.js} +4 -4
  196. package/dist/{support-AWC3XKPX.js → support-JAZL6VBR.js} +7 -7
  197. package/dist/{system-CD75NYBU.js → system-3TDQRMZZ.js} +26 -26
  198. package/dist/{targets-VSZX2J2S.js → targets-EZKHAYRN.js} +66 -65
  199. package/dist/{tasks-AN567LYH.js → tasks-SNEFHWYW.js} +12 -12
  200. package/dist/{terminal-lease-6KTWNHVY.js → terminal-lease-BNLFA4OF.js} +8 -7
  201. package/dist/{tools-AGRK3V5J.js → tools-7IM6BDCE.js} +12 -12
  202. package/dist/{trace-P4MQZD33.js → trace-C3MBGD4S.js} +8 -8
  203. package/dist/{tui-primitives-A6MUW32V.js → tui-primitives-36BY2774.js} +2 -2
  204. package/dist/{uninstall-BRUTEPIC.js → uninstall-WWLOSZ42.js} +10 -10
  205. package/dist/{upgrade-SBCGHQGJ.js → upgrade-ETK2JNSJ.js} +37 -47
  206. package/dist/{usage-BIDVTO6V.js → usage-S2HOB7BZ.js} +93 -89
  207. package/dist/{verifiers-LTGCAMXS.js → verifiers-QDTEVH7R.js} +24 -22
  208. package/dist/{verify-OZU4LLNP.js → verify-SUKUK6XM.js} +15 -14
  209. package/dist/web/client/assets/{abnfDiagram-VCTEODGH-C5wfoHm3.js → abnfDiagram-VCTEODGH-BznNOe_I.js} +1 -1
  210. package/dist/web/client/assets/{arc-oH91sfLl.js → arc-Pry-7G1_.js} +1 -1
  211. package/dist/web/client/assets/architecture-7GRP2DOG-BQO9DL_y.js +1 -0
  212. package/dist/web/client/assets/architectureDiagram-5GKGNRK7-CKPbdvyx.js +36 -0
  213. package/dist/web/client/assets/{blockDiagram-I7D4REHJ-wi0_CYHL.js → blockDiagram-I7D4REHJ-prINbpbM.js} +1 -1
  214. package/dist/web/client/assets/{c4Diagram-7LVT6UL2-DV7NYc2W.js → c4Diagram-7LVT6UL2-DkVRKtyU.js} +1 -1
  215. package/dist/web/client/assets/channel-c4EeUUqA.js +1 -0
  216. package/dist/web/client/assets/{chunk-4HAMMTFA-Bhsegh3F.js → chunk-4HAMMTFA-CV0Z1ApC.js} +1 -1
  217. package/dist/web/client/assets/{chunk-75Z2AOVW-RQCckcQG.js → chunk-75Z2AOVW-D34Nohxq.js} +1 -1
  218. package/dist/web/client/assets/chunk-DU6HZSFF-Das_cS-O.js +125 -0
  219. package/dist/web/client/assets/{chunk-F27PBJKO-BcNqv2x1.js → chunk-F27PBJKO-CmRojxkG.js} +1 -1
  220. package/dist/web/client/assets/{chunk-GMAD6QVW-Bq8JWiZT.js → chunk-GMAD6QVW-ClYZmc73.js} +1 -1
  221. package/dist/web/client/assets/{chunk-GVQU2GXP-DbchrAeJ.js → chunk-GVQU2GXP-B2BiHFt-.js} +1 -1
  222. package/dist/web/client/assets/{chunk-IMKFNOWR-DrpvjocK.js → chunk-IMKFNOWR-BGApZ8nP.js} +1 -1
  223. package/dist/web/client/assets/{chunk-L3NEJ4N5-DHLmTnCe.js → chunk-L3NEJ4N5-DIzCgpkY.js} +1 -1
  224. package/dist/web/client/assets/{chunk-OSK3NFVY-CsRbtN9n.js → chunk-OSK3NFVY-BPT-yePv.js} +1 -1
  225. package/dist/web/client/assets/{chunk-P2QGCYS3-aqPbxoMh.js → chunk-P2QGCYS3-BC1WTc2t.js} +1 -1
  226. package/dist/web/client/assets/{chunk-POPQ4Y6H-Dl5vw0h0.js → chunk-POPQ4Y6H-BSjzBmZU.js} +1 -1
  227. package/dist/web/client/assets/{chunk-PWAF6VOD-D7OBRSdO.js → chunk-PWAF6VOD-BIjLs86Z.js} +1 -1
  228. package/dist/web/client/assets/{chunk-SHT3W25Y-CdKCIwuB.js → chunk-SHT3W25Y-CduDz2cm.js} +1 -1
  229. package/dist/web/client/assets/{chunk-SVP7TREG-B94Nu_1-.js → chunk-SVP7TREG-XUn4pPAP.js} +1 -1
  230. package/dist/web/client/assets/{chunk-TICWLB2K-jjRQI_hk.js → chunk-TICWLB2K-DcBy2DKy.js} +1 -1
  231. package/dist/web/client/assets/{chunk-XXDRQBXY-azkbKE37.js → chunk-XXDRQBXY-DqAYeljN.js} +1 -1
  232. package/dist/web/client/assets/classDiagram-ZZMXUADV-C0HR7YKN.js +1 -0
  233. package/dist/web/client/assets/classDiagram-v2-VYDZK3BY-C0HR7YKN.js +1 -0
  234. package/dist/web/client/assets/cose-bilkent-JH36ORCC-CVh1icwb.js +1 -0
  235. package/dist/web/client/assets/{cynefin-OW5HDTMX--i9RDU5f.js → cynefin-OW5HDTMX-BecPbyM6.js} +1 -1
  236. package/dist/web/client/assets/{cynefinDiagram-5FMLGOSQ-cRcvyBdp.js → cynefinDiagram-5FMLGOSQ-BzMzFwyT.js} +1 -1
  237. package/dist/web/client/assets/{dagre-GXQ25YYZ-C9mZmAPe.js → dagre-GXQ25YYZ-CAWJmRMG.js} +1 -1
  238. package/dist/web/client/assets/{diagram-S7CK7UJ4-Oj_zlLDY.js → diagram-S7CK7UJ4--lp0ALmn.js} +1 -1
  239. package/dist/web/client/assets/{diagram-UQ7AKVKN-BWKbbfcR.js → diagram-UQ7AKVKN-gKUnsjcj.js} +1 -1
  240. package/dist/web/client/assets/{diagram-VSXAHHWV-C3N3f7DO.js → diagram-VSXAHHWV-BoN5D1Gh.js} +1 -1
  241. package/dist/web/client/assets/{diagram-VX7I27RA-CtDKDAWe.js → diagram-VX7I27RA-BMtuswQ6.js} +1 -1
  242. package/dist/web/client/assets/{diagram-Z3DM3KII-B8bkBRCz.js → diagram-Z3DM3KII-DtU8LXrA.js} +1 -1
  243. package/dist/web/client/assets/dist-v5Q1xZ2K.js +1 -0
  244. package/dist/web/client/assets/{ebnfDiagram-PWID7BFC-CskW-Whx.js → ebnfDiagram-PWID7BFC-DDcnv9BH.js} +1 -1
  245. package/dist/web/client/assets/{erDiagram-RLTQ6QDP-C-83cgCW.js → erDiagram-RLTQ6QDP-DvRb4iDL.js} +1 -1
  246. package/dist/web/client/assets/eventmodeling-NTZA5JFV-01h4SbTc.js +1 -0
  247. package/dist/web/client/assets/flowDiagram-HODETNUW-Bll_YZ6T.js +1 -0
  248. package/dist/web/client/assets/framework-YGoR34M4.js +9 -0
  249. package/dist/web/client/assets/ganttDiagram-EL5Y4UJY-DdFZ9hvH.js +292 -0
  250. package/dist/web/client/assets/{gitGraph-4MIJSDKK-B40cQtBE.js → gitGraph-4MIJSDKK-DjD_AAMj.js} +1 -1
  251. package/dist/web/client/assets/{gitGraphDiagram-WWUBYQGX-CH-7P7Di.js → gitGraphDiagram-WWUBYQGX-CDyN9n2u.js} +1 -1
  252. package/dist/web/client/assets/index-CVcy0FAn.js +75 -0
  253. package/dist/web/client/assets/{info-A6RAGUB7-eCCE9D_Q.js → info-A6RAGUB7-C_XK8Hq0.js} +1 -1
  254. package/dist/web/client/assets/{infoDiagram-27XIBGKW-DRnvqMjM.js → infoDiagram-27XIBGKW-DIe4tJ1i.js} +1 -1
  255. package/dist/web/client/assets/{ishikawaDiagram-5VMMS53U-DBA_55wp.js → ishikawaDiagram-5VMMS53U-CVl5unKI.js} +1 -1
  256. package/dist/web/client/assets/{journeyDiagram-3NMN7TZE-C-ewpNl7.js → journeyDiagram-3NMN7TZE-CPEB1Vt8.js} +1 -1
  257. package/dist/web/client/assets/{kanban-definition-UXKFOSKX-B1taGsu0.js → kanban-definition-UXKFOSKX-j-9WXjYQ.js} +1 -1
  258. package/dist/web/client/assets/{line-lZ0kyxDI.js → line-BIDAcEtX.js} +1 -1
  259. package/dist/web/client/assets/{linear-DIc8FgZj.js → linear-SzVmGSw4.js} +1 -1
  260. package/dist/web/client/assets/{mermaid-parser.core-SXolxpXw.js → mermaid-parser.core-Ux4vssh0.js} +3 -3
  261. package/dist/web/client/assets/{mermaid.core-DXgQtkNg.js → mermaid.core-CDuwVKeh.js} +4 -4
  262. package/dist/web/client/assets/{mindmap-definition-YA3MSWOX-DXJas9K7.js → mindmap-definition-YA3MSWOX-5MlQEeQ6.js} +1 -1
  263. package/dist/web/client/assets/{packet-AYTQ26CC-OqVl_07o.js → packet-AYTQ26CC-DRO66c9Q.js} +1 -1
  264. package/dist/web/client/assets/{pegDiagram-XKGWAZYB-CPE_zdfN.js → pegDiagram-XKGWAZYB-BakZnSjM.js} +1 -1
  265. package/dist/web/client/assets/{pie-WAS4IAKB-DAxnMBLe.js → pie-WAS4IAKB-BEzcmhz8.js} +1 -1
  266. package/dist/web/client/assets/{pieDiagram-E7YTZNPT-Uwjpufxv.js → pieDiagram-E7YTZNPT-DpmqgoPt.js} +1 -1
  267. package/dist/web/client/assets/prism-core-BtsZdCS6.js +1 -0
  268. package/dist/web/client/assets/{quadrantDiagram-AXDQQJYC-Bjs4yjgs.js → quadrantDiagram-AXDQQJYC-DuMPwwV2.js} +1 -1
  269. package/dist/web/client/assets/{radar-RG4KPBEZ-CuCKjHM3.js → radar-RG4KPBEZ-Djm3oXl5.js} +1 -1
  270. package/dist/web/client/assets/{railroad-74A4TZTK-CnQK-Cc1.js → railroad-74A4TZTK-Cpvkwsao.js} +1 -1
  271. package/dist/web/client/assets/railroad-abnf-HS5TGJTU-CpRQ3ruG.js +1 -0
  272. package/dist/web/client/assets/railroad-ebnf-LZEXJU2U-1Rm5a5eJ.js +1 -0
  273. package/dist/web/client/assets/railroad-peg-WCYAUIDC-C8344cTh.js +1 -0
  274. package/dist/web/client/assets/{railroadDiagram-O6MQD6OU-BDDIPNLL.js → railroadDiagram-O6MQD6OU-CgMS4B6R.js} +1 -1
  275. package/dist/web/client/assets/{requirementDiagram-BXWQKSXE-B5Ydyxc1.js → requirementDiagram-BXWQKSXE-CX5eoNdN.js} +1 -1
  276. package/dist/web/client/assets/rolldown-runtime-hePW80VL.js +1 -0
  277. package/dist/web/client/assets/{sankeyDiagram-P5KCCOFB-Bw2Qym75.js → sankeyDiagram-P5KCCOFB-CODBX2N3.js} +1 -1
  278. package/dist/web/client/assets/{sequenceDiagram-WJ2MYXX4-BZf36nO0.js → sequenceDiagram-WJ2MYXX4-eUhhF8OR.js} +1 -1
  279. package/dist/web/client/assets/src-B6xuSHsQ.js +1 -0
  280. package/dist/web/client/assets/{stateDiagram-D77RDMKH-DnH6JRkp.js → stateDiagram-D77RDMKH-vR6l0NC2.js} +1 -1
  281. package/dist/web/client/assets/stateDiagram-v2-MP3YSRHH-BYUm8jLY.js +1 -0
  282. package/dist/web/client/assets/{swimlanes-42K2YHIH-D9PZmtZg.js → swimlanes-42K2YHIH-v9Tw_zX7.js} +1 -1
  283. package/dist/web/client/assets/swimlanesDiagram-VR7AAH4N-B2jdCvhD.js +8 -0
  284. package/dist/web/client/assets/{timeline-definition-24CTP7MA-CrkZZBo7.js → timeline-definition-24CTP7MA-DxianbhU.js} +1 -1
  285. package/dist/web/client/assets/{treeView-Q6P3EWNA-C9zDShoC.js → treeView-Q6P3EWNA-DLxnZb9R.js} +1 -1
  286. package/dist/web/client/assets/{treemap-WGGIJYW6-B-plj9yK.js → treemap-WGGIJYW6-I7UnZ6xJ.js} +1 -1
  287. package/dist/web/client/assets/{vennDiagram-4TSXK5OY-VeOdaphN.js → vennDiagram-4TSXK5OY-Ar7M8Mrj.js} +1 -1
  288. package/dist/web/client/assets/{wardley-WFR3VGLG-Wl1P_m6L.js → wardley-WFR3VGLG-B8ZSHeDu.js} +1 -1
  289. package/dist/web/client/assets/{wardleyDiagram-VM6X3IG4-B85-R9t2.js → wardleyDiagram-VM6X3IG4-Qks2FmIn.js} +1 -1
  290. package/dist/web/client/assets/{xychartDiagram-S5SC5T6Z-BrD8OW8m.js → xychartDiagram-S5SC5T6Z-BBBjRtiE.js} +1 -1
  291. package/dist/web/client/index.html +3 -1
  292. package/dist/web/reads-worker.js +17 -17
  293. package/dist/web/server.js +25 -25
  294. package/dist/{web-EU6ATJWA.js → web-EMGUGGEI.js} +3 -3
  295. package/dist/{web-fetch-U22Q7HV4.js → web-fetch-6BRRVQON.js} +22 -5
  296. package/dist/{wiki-generate-LZRLFG6I.js → wiki-generate-XHSJTDOP.js} +104 -100
  297. package/dist/{with-panes-X5CZOGML.js → with-panes-Z6BTEHMZ.js} +11 -11
  298. package/dist/worker/entry.js +101 -87
  299. package/docs/README.md +1 -1
  300. package/docs/architecture/artifact-placement.md +12 -1
  301. package/docs/architecture/library.md +1 -1
  302. package/docs/architecture/prompt-envelope-and-tools.md +37 -27
  303. package/docs/architecture/safety-model.md +19 -6
  304. package/docs/architecture/session-lifecycle.md +10 -4
  305. package/docs/architecture/tui-design.md +37 -14
  306. package/docs/guide/commands-and-modes.md +39 -19
  307. package/docs/guide/configuration-and-targets.md +7 -5
  308. package/docs/guide/configuration-reference.md +116 -13
  309. package/docs/guide/environment-variables.md +2 -5
  310. package/docs/guide/fleet-dispatch.md +3 -2
  311. package/docs/guide/glossary.md +1 -1
  312. package/docs/guide/installation-and-lifecycle.md +2 -2
  313. package/docs/guide/resource-library.md +1 -1
  314. package/docs/guide/tool-usage.md +166 -64
  315. package/docs/guide/troubleshooting.md +1 -1
  316. package/docs/process/documentation-guide.md +1 -0
  317. package/docs/process/fleet-demo-runbook.md +6 -6
  318. package/docs/process/scientific-validation.md +22 -2
  319. package/docs/process/tool-audit-v0.4.9.md +357 -0
  320. package/package.json +1 -1
  321. package/src/cli/argv.ts +31 -0
  322. package/src/cli/clio.ts +17 -13
  323. package/src/cli/config.ts +4 -0
  324. package/src/cli/doctor-panes.ts +1 -1
  325. package/src/cli/doctor.ts +3 -1
  326. package/src/cli/index.ts +14 -1
  327. package/src/cli/mcp.ts +106 -0
  328. package/src/cli/skills-eval.ts +8 -2
  329. package/src/cli/upgrade.ts +34 -38
  330. package/src/cli/verifiers.ts +1 -1
  331. package/src/core/bash-exec.ts +27 -4
  332. package/src/core/config.ts +2 -1
  333. package/src/core/defaults.ts +10 -1
  334. package/src/core/event-bus.ts +1 -1
  335. package/src/core/run-records.ts +438 -0
  336. package/src/core/safe-exec.ts +506 -56
  337. package/src/core/skill-activation.ts +5 -3
  338. package/src/core/termination.ts +3 -3
  339. package/src/core/tool-names.ts +33 -12
  340. package/src/domains/context/clio-md.ts +1 -1
  341. package/src/domains/context/worker/pressure.ts +6 -2
  342. package/src/domains/context/working-set/path-index.ts +7 -2
  343. package/src/domains/dispatch/code-step.ts +7 -2
  344. package/src/domains/dispatch/contract.ts +7 -0
  345. package/src/domains/dispatch/execution-role.ts +3 -3
  346. package/src/domains/dispatch/execution-scheduler.ts +204 -79
  347. package/src/domains/dispatch/extension.ts +131 -14
  348. package/src/domains/dispatch/fleet-preflight.ts +18 -3
  349. package/src/domains/dispatch/fleet-run.ts +1 -0
  350. package/src/domains/dispatch/gate-decisions.ts +3 -3
  351. package/src/domains/dispatch/heartbeat.ts +1 -1
  352. package/src/domains/dispatch/host-verification.ts +16 -14
  353. package/src/domains/dispatch/receipt-findings.ts +3 -4
  354. package/src/domains/dispatch/reservation-store.ts +7 -9
  355. package/src/domains/dispatch/route-facts.ts +1 -1
  356. package/src/domains/dispatch/state.ts +3 -3
  357. package/src/domains/dispatch/types.ts +1 -1
  358. package/src/domains/evidence/build.ts +35 -7
  359. package/src/domains/gateway/mcp/client.ts +923 -0
  360. package/src/domains/gateway/mcp/config.ts +456 -0
  361. package/src/domains/gateway/mcp/index.ts +88 -0
  362. package/src/domains/gateway/mcp/protocol.ts +273 -0
  363. package/src/domains/gateway/mcp/trust.ts +263 -0
  364. package/src/domains/lifecycle/doctor.ts +17 -3
  365. package/src/domains/mux/contract.ts +5 -9
  366. package/src/domains/mux/detect.ts +1 -1
  367. package/src/domains/mux/extension.ts +1 -1
  368. package/src/domains/mux/protocol.ts +5 -7
  369. package/src/domains/mux/socket-client.ts +3 -3
  370. package/src/domains/observability/accountability.ts +2 -2
  371. package/src/domains/observability/contract.ts +7 -3
  372. package/src/domains/observability/evidence-index.ts +2 -2
  373. package/src/domains/observability/projection.ts +10 -0
  374. package/src/domains/prompts/compiler.ts +41 -23
  375. package/src/domains/prompts/fragments/identity/docs-routing.md +2 -2
  376. package/src/domains/prompts/fragments/operating/skills.md +12 -10
  377. package/src/domains/providers/index.ts +5 -1
  378. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +42 -10
  379. package/src/domains/providers/probe/http.ts +44 -59
  380. package/src/domains/providers/probe/reasoning.ts +2 -0
  381. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +20 -31
  382. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +9 -4
  383. package/src/domains/safety/action-classifier.ts +17 -1
  384. package/src/domains/safety/call-target.ts +14 -0
  385. package/src/domains/safety/contract.ts +1 -1
  386. package/src/domains/safety/finish-contract.ts +9 -3
  387. package/src/domains/safety/loop-detector.ts +1 -1
  388. package/src/domains/safety/policy-engine.ts +7 -0
  389. package/src/domains/safety/protected-artifacts.ts +3 -4
  390. package/src/domains/safety/rejection-feedback.ts +1 -1
  391. package/src/domains/safety/scope.ts +2 -3
  392. package/src/domains/safety/validation-contract.ts +3 -2
  393. package/src/domains/scheduling/budget.ts +5 -3
  394. package/src/domains/scheduling/contract.ts +2 -1
  395. package/src/domains/scheduling/extension.ts +3 -3
  396. package/src/domains/session/compaction/branch-summary.ts +1 -1
  397. package/src/domains/session/compaction/compact.ts +25 -2
  398. package/src/domains/session/compaction/cut-point.ts +1 -1
  399. package/src/domains/session/compaction/tokens.ts +5 -10
  400. package/src/domains/session/contract.ts +1 -1
  401. package/src/domains/session/cwd-fallback.ts +2 -2
  402. package/src/domains/session/handoff.ts +5 -1
  403. package/src/domains/session/history.ts +6 -0
  404. package/src/domains/session/manager.ts +14 -7
  405. package/src/domains/session/retry.ts +2 -1
  406. package/src/domains/session/session-artifacts.ts +12 -7
  407. package/src/domains/session/task-board.ts +2 -3
  408. package/src/engine/apis/openai-completions.ts +8 -0
  409. package/src/engine/loop-guard.ts +7 -0
  410. package/src/engine/provider-error-body.ts +65 -0
  411. package/src/engine/session.ts +118 -29
  412. package/src/engine/worker-runtime.ts +3 -0
  413. package/src/entry/boot-options.ts +2 -0
  414. package/src/entry/orchestrator.ts +18 -2
  415. package/src/interactive/chat-loop-policy.ts +1 -0
  416. package/src/interactive/chat-loop.ts +8 -4
  417. package/src/interactive/chat-panel.ts +23 -9
  418. package/src/interactive/chat-renderer.ts +33 -11
  419. package/src/interactive/clio-editor.ts +13 -5
  420. package/src/interactive/dispatch-board.ts +70 -30
  421. package/src/interactive/editor-submit.ts +30 -25
  422. package/src/interactive/footer/widgets.ts +12 -9
  423. package/src/interactive/interactive-presentation.ts +2 -3
  424. package/src/interactive/mux-bridge.ts +3 -7
  425. package/src/interactive/overlay-general-openers.ts +14 -7
  426. package/src/interactive/overlays/cwd-fallback.ts +1 -1
  427. package/src/interactive/overlays/library-model.ts +114 -35
  428. package/src/interactive/overlays/library.ts +52 -5
  429. package/src/interactive/overlays/list-overlay.ts +4 -1
  430. package/src/interactive/overlays/session-selector.ts +28 -23
  431. package/src/interactive/overlays/settings.ts +20 -1
  432. package/src/interactive/overlays/tree-selector.ts +47 -10
  433. package/src/interactive/panes-runtime.ts +1 -1
  434. package/src/interactive/renderers/compaction-summary.ts +1 -1
  435. package/src/interactive/renderers/provider-error.ts +118 -0
  436. package/src/interactive/renderers/retry-status.ts +59 -23
  437. package/src/interactive/renderers/tool-execution.ts +67 -7
  438. package/src/interactive/renderers/worker-answer.ts +198 -0
  439. package/src/interactive/renderers/worker-entry.ts +57 -163
  440. package/src/interactive/slash-commands.ts +26 -1
  441. package/src/interactive/slash-spec.ts +2 -2
  442. package/src/interactive/theme/labels.ts +66 -30
  443. package/src/interactive/turn-persistence.ts +6 -1
  444. package/src/interactive/turn-recovery.ts +2 -1
  445. package/src/interactive/turn-runtime.ts +22 -5
  446. package/src/interactive/view/artifacts.ts +3 -2
  447. package/src/interactive/view/view-overlay.ts +96 -20
  448. package/src/tools/agent-tools.ts +21 -7
  449. package/src/tools/artifact.ts +16 -8
  450. package/src/tools/bash.ts +90 -11
  451. package/src/tools/bootstrap.ts +42 -4
  452. package/src/tools/builtin-tool-catalog.ts +72 -7
  453. package/src/tools/context/index.ts +27 -31
  454. package/src/tools/context/library.ts +3 -1
  455. package/src/tools/context/surface.ts +12 -26
  456. package/src/tools/core-bootstrap.ts +72 -1
  457. package/src/tools/data/csv.ts +1189 -0
  458. package/src/tools/data/index.ts +308 -0
  459. package/src/tools/data/json.ts +1799 -0
  460. package/src/tools/data/jsonl.ts +561 -0
  461. package/src/tools/data/shared.ts +452 -0
  462. package/src/tools/edit-diff.ts +0 -7
  463. package/src/tools/edit.ts +115 -18
  464. package/src/tools/file-mutation-queue.ts +114 -4
  465. package/src/tools/find.ts +108 -29
  466. package/src/tools/gateway/caps.ts +11 -0
  467. package/src/tools/gateway/clio-context-surface.ts +41 -0
  468. package/src/tools/gateway/clio-context-tools.ts +77 -0
  469. package/src/tools/gateway/data-surface.ts +138 -0
  470. package/src/tools/gateway/data-tool.ts +201 -0
  471. package/src/tools/gateway/index.ts +342 -0
  472. package/src/tools/gateway/mcp-capabilities.ts +469 -0
  473. package/src/tools/grep.ts +88 -33
  474. package/src/tools/harness-extensions.ts +3 -0
  475. package/src/tools/ignore-policy.ts +7 -5
  476. package/src/tools/ls.ts +111 -20
  477. package/src/tools/policy.ts +35 -13
  478. package/src/tools/presentation.ts +6 -0
  479. package/src/tools/read.ts +634 -156
  480. package/src/tools/registry.ts +94 -6
  481. package/src/tools/run-script.ts +997 -0
  482. package/src/tools/spawn-hygiene.ts +157 -5
  483. package/src/tools/surface.ts +163 -0
  484. package/src/tools/verify/authoring.ts +8 -3
  485. package/src/tools/verify/catalog.ts +14 -1
  486. package/src/tools/verify/numeric.ts +367 -59
  487. package/src/tools/verify/perf.ts +171 -9
  488. package/src/tools/verify/scripts.ts +178 -26
  489. package/src/tools/web-fetch-surface.ts +22 -0
  490. package/src/tools/web-fetch.ts +26 -1
  491. package/src/tools/write.ts +45 -19
  492. package/dist/chunk-B6UM3OZC.js +0 -15
  493. package/dist/chunk-GJ24ODAX.js +0 -196
  494. package/dist/chunk-LZCCBLRC.js +0 -57
  495. package/dist/web/client/assets/architecture-7GRP2DOG-EGozsYEO.js +0 -1
  496. package/dist/web/client/assets/architectureDiagram-5GKGNRK7-z9FokbJl.js +0 -36
  497. package/dist/web/client/assets/channel-CiUWbHN9.js +0 -1
  498. package/dist/web/client/assets/chunk-DU6HZSFF-C5USiOAy.js +0 -125
  499. package/dist/web/client/assets/classDiagram-ZZMXUADV-CMODalmo.js +0 -1
  500. package/dist/web/client/assets/classDiagram-v2-VYDZK3BY-CMODalmo.js +0 -1
  501. package/dist/web/client/assets/cose-bilkent-JH36ORCC-RbQL23qS.js +0 -1
  502. package/dist/web/client/assets/dist-D0_q-A2b.js +0 -1
  503. package/dist/web/client/assets/eventmodeling-NTZA5JFV-DjVq8wKU.js +0 -1
  504. package/dist/web/client/assets/flowDiagram-HODETNUW-BUiCBGXt.js +0 -1
  505. package/dist/web/client/assets/ganttDiagram-EL5Y4UJY-B2lb8lvF.js +0 -292
  506. package/dist/web/client/assets/index-FSIC94pi.js +0 -83
  507. package/dist/web/client/assets/prism-core-BngLtbUd.js +0 -1
  508. package/dist/web/client/assets/railroad-abnf-HS5TGJTU-BcW01NZG.js +0 -1
  509. package/dist/web/client/assets/railroad-ebnf-LZEXJU2U-B7YCEDDd.js +0 -1
  510. package/dist/web/client/assets/railroad-peg-WCYAUIDC-DjNZbSTZ.js +0 -1
  511. package/dist/web/client/assets/src-yeptRXpt.js +0 -1
  512. package/dist/web/client/assets/stateDiagram-v2-MP3YSRHH-C7QtHeK4.js +0 -1
  513. package/dist/web/client/assets/swimlanesDiagram-VR7AAH4N-CBZlPFky.js +0 -8
@@ -2,20 +2,73 @@
2
2
  * Pure budget math for `kind: perf-budget` verifier checks. The harness
3
3
  * measures the command's wall time; this module decides pass or fail against
4
4
  * a declared budget or a recorded baseline and writes the structured report.
5
- * It reads no file and runs nothing.
5
+ * It reads no file and runs nothing; the one impure function here,
6
+ * {@link capturePerfEnvironment}, reads the host description so a baseline
7
+ * can say where it was measured.
8
+ *
9
+ * A wall-time verdict is a statement about this machine at this moment. The
10
+ * report carries the baseline's recorded environment beside the current one
11
+ * and names every field that differs, because a baseline recorded on a
12
+ * different CPU says little about a regression here. The comparison is
13
+ * informational: it never changes pass or fail.
6
14
  */
7
15
 
16
+ import { arch, cpus, hostname, platform, totalmem } from "node:os";
17
+
8
18
  export interface PerfBudgetSpec {
9
19
  wallTimeMs: number;
10
20
  tolerance?: { relative?: number };
11
21
  }
12
22
 
23
+ /** The host a baseline was recorded on, as far as Node can describe it. */
24
+ export interface PerfEnvironment {
25
+ hostname: string;
26
+ platform: string;
27
+ arch: string;
28
+ cpuModel: string;
29
+ cpuCount: number;
30
+ totalMemoryBytes: number;
31
+ nodeVersion: string;
32
+ }
33
+
34
+ export type PerfEnvironmentField = keyof PerfEnvironment;
35
+
36
+ const PERF_ENVIRONMENT_FIELDS: ReadonlyArray<PerfEnvironmentField> = [
37
+ "hostname",
38
+ "platform",
39
+ "arch",
40
+ "cpuModel",
41
+ "cpuCount",
42
+ "totalMemoryBytes",
43
+ "nodeVersion",
44
+ ];
45
+
13
46
  export interface PerfBaseline {
14
47
  wallTimeMs: number;
15
48
  /** ISO time the baseline was recorded; informational. */
16
49
  recordedAt?: string;
17
50
  /** Check id the baseline was recorded for; informational. */
18
51
  check?: string;
52
+ /** Host the baseline was recorded on; absent on version 1 files. */
53
+ environment?: PerfEnvironment;
54
+ }
55
+
56
+ /** Identity of the baseline file a judgement read. */
57
+ export interface PerfBaselineProvenance {
58
+ path: string;
59
+ /** SHA-256 of the exact baseline text. */
60
+ sha256: string;
61
+ bytes: number;
62
+ recordedAt?: string;
63
+ check?: string;
64
+ }
65
+
66
+ /** Baseline host beside the judging host, with the fields that differ named. */
67
+ export interface PerfEnvironmentComparison {
68
+ /** Null when the baseline file recorded no environment (a version 1 file). */
69
+ baseline: PerfEnvironment | null;
70
+ current: PerfEnvironment;
71
+ differing: PerfEnvironmentField[];
19
72
  }
20
73
 
21
74
  export interface PerfBudgetReport {
@@ -31,9 +84,15 @@ export interface PerfBudgetReport {
31
84
  referenceMs: number;
32
85
  relative: number;
33
86
  summary: string;
87
+ /** Present for a baseline judgement when the judging host was captured. Informational only. */
88
+ environment?: PerfEnvironmentComparison;
89
+ /** Present when the judgement read a baseline file. */
90
+ baseline?: PerfBaselineProvenance;
34
91
  }
35
92
 
36
- export const PERF_BASELINE_VERSION = 1;
93
+ /** The version this build writes. Version 1 files, which record no environment, still load. */
94
+ export const PERF_BASELINE_VERSION = 2;
95
+ const SUPPORTED_BASELINE_VERSIONS: ReadonlyArray<number> = [1, PERF_BASELINE_VERSION];
37
96
 
38
97
  export function normalizePerfBudget(value: unknown): PerfBudgetSpec | Error {
39
98
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
@@ -68,7 +127,56 @@ export function normalizePerfTolerance(value: unknown, location: string): { rela
68
127
  return { relative: record.relative };
69
128
  }
70
129
 
71
- /** Parse a baseline file written by `clio-coder verifiers baseline <id>`. */
130
+ /** Describe the host this process runs on. */
131
+ export function capturePerfEnvironment(): PerfEnvironment {
132
+ const processors = cpus();
133
+ return {
134
+ hostname: hostname(),
135
+ platform: platform(),
136
+ arch: arch(),
137
+ cpuModel: processors[0]?.model.trim() ?? "unknown",
138
+ cpuCount: processors.length,
139
+ totalMemoryBytes: totalmem(),
140
+ nodeVersion: process.version,
141
+ };
142
+ }
143
+
144
+ function parsePerfEnvironment(value: unknown, label: string): PerfEnvironment | Error {
145
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
146
+ return new Error(`${label} must be an object describing the recording host`);
147
+ }
148
+ const record = value as Record<string, unknown>;
149
+ const unknown = Object.keys(record).filter((key) => !(PERF_ENVIRONMENT_FIELDS as ReadonlyArray<string>).includes(key));
150
+ if (unknown.length > 0) return new Error(`${label} has unknown field(s): ${unknown.sort().join(", ")}`);
151
+ for (const field of ["hostname", "platform", "arch", "cpuModel", "nodeVersion"] as const) {
152
+ if (typeof record[field] !== "string") return new Error(`${label}.${field} must be a string`);
153
+ }
154
+ if (typeof record.cpuCount !== "number" || !Number.isInteger(record.cpuCount) || record.cpuCount < 0) {
155
+ return new Error(`${label}.cpuCount must be a non-negative integer`);
156
+ }
157
+ if (
158
+ typeof record.totalMemoryBytes !== "number" ||
159
+ !Number.isFinite(record.totalMemoryBytes) ||
160
+ record.totalMemoryBytes < 0
161
+ ) {
162
+ return new Error(`${label}.totalMemoryBytes must be a non-negative number`);
163
+ }
164
+ return {
165
+ hostname: record.hostname as string,
166
+ platform: record.platform as string,
167
+ arch: record.arch as string,
168
+ cpuModel: record.cpuModel as string,
169
+ cpuCount: record.cpuCount,
170
+ totalMemoryBytes: record.totalMemoryBytes,
171
+ nodeVersion: record.nodeVersion as string,
172
+ };
173
+ }
174
+
175
+ /**
176
+ * Parse a baseline file written by `clio-coder verifiers baseline <id>`. A
177
+ * version 1 file (or one without a version) carries no environment; a version
178
+ * 2 file carries the recording host.
179
+ */
72
180
  export function parsePerfBaseline(text: string, label: string): PerfBaseline | Error {
73
181
  let parsed: unknown;
74
182
  try {
@@ -80,38 +188,81 @@ export function parsePerfBaseline(text: string, label: string): PerfBaseline | E
80
188
  return new Error(`${label} must be a JSON object with wallTimeMs`);
81
189
  }
82
190
  const record = parsed as Record<string, unknown>;
191
+ if (Object.hasOwn(record, "version")) {
192
+ if (typeof record.version !== "number" || !SUPPORTED_BASELINE_VERSIONS.includes(record.version)) {
193
+ return new Error(`${label}.version must be one of ${SUPPORTED_BASELINE_VERSIONS.join(", ")}`);
194
+ }
195
+ }
83
196
  if (typeof record.wallTimeMs !== "number" || !Number.isFinite(record.wallTimeMs) || record.wallTimeMs <= 0) {
84
197
  return new Error(`${label}.wallTimeMs must be a positive number of milliseconds`);
85
198
  }
86
199
  const baseline: PerfBaseline = { wallTimeMs: record.wallTimeMs };
87
200
  if (typeof record.recordedAt === "string") baseline.recordedAt = record.recordedAt;
88
201
  if (typeof record.check === "string") baseline.check = record.check;
202
+ if (Object.hasOwn(record, "environment") && record.environment !== undefined) {
203
+ const environment = parsePerfEnvironment(record.environment, `${label}.environment`);
204
+ if (environment instanceof Error) return environment;
205
+ baseline.environment = environment;
206
+ }
89
207
  return baseline;
90
208
  }
91
209
 
92
210
  /** The JSON text a baseline file holds; stable key order so a re-record is a clean diff. */
93
- export function renderPerfBaseline(input: { wallTimeMs: number; check: string; recordedAt: string }): string {
211
+ export function renderPerfBaseline(input: {
212
+ wallTimeMs: number;
213
+ check: string;
214
+ recordedAt: string;
215
+ environment: PerfEnvironment;
216
+ }): string {
94
217
  return `${JSON.stringify(
95
- { version: PERF_BASELINE_VERSION, check: input.check, wallTimeMs: input.wallTimeMs, recordedAt: input.recordedAt },
218
+ {
219
+ version: PERF_BASELINE_VERSION,
220
+ check: input.check,
221
+ wallTimeMs: input.wallTimeMs,
222
+ recordedAt: input.recordedAt,
223
+ environment: {
224
+ hostname: input.environment.hostname,
225
+ platform: input.environment.platform,
226
+ arch: input.environment.arch,
227
+ cpuModel: input.environment.cpuModel,
228
+ cpuCount: input.environment.cpuCount,
229
+ totalMemoryBytes: input.environment.totalMemoryBytes,
230
+ nodeVersion: input.environment.nodeVersion,
231
+ },
232
+ },
96
233
  null,
97
234
  2,
98
235
  )}\n`;
99
236
  }
100
237
 
238
+ /** Name every field on which the judging host differs from the recording host. */
239
+ export function comparePerfEnvironments(
240
+ baseline: PerfEnvironment | undefined,
241
+ current: PerfEnvironment,
242
+ ): PerfEnvironmentComparison {
243
+ if (baseline === undefined) return { baseline: null, current, differing: [] };
244
+ const differing = PERF_ENVIRONMENT_FIELDS.filter((field) => baseline[field] !== current[field]);
245
+ return { baseline, current, differing };
246
+ }
247
+
101
248
  /**
102
249
  * Judge a measurement. A declared budget bounds the time at
103
250
  * `wallTimeMs * (1 + tolerance.relative)`; a baseline bounds it at
104
251
  * `baseline.wallTimeMs * (1 + relative)`. Measured time above the bound fails.
252
+ * When `environment` names the judging host and the judgement uses a
253
+ * baseline, the report compares the two hosts; a difference is reported and
254
+ * never changes the verdict.
105
255
  */
106
256
  export function evaluatePerfBudget(
107
257
  measuredMs: number,
108
- spec: { budget?: PerfBudgetSpec; baseline?: PerfBaseline; relative?: number },
258
+ spec: { budget?: PerfBudgetSpec; baseline?: PerfBaseline; relative?: number; environment?: PerfEnvironment },
109
259
  ): PerfBudgetReport | Error {
110
260
  if (!Number.isFinite(measuredMs) || measuredMs < 0)
111
261
  return new Error("measured wall time must be a non-negative number");
112
262
  let source: PerfBudgetReport["source"];
113
263
  let referenceMs: number;
114
264
  let relative: number;
265
+ let comparison: PerfEnvironmentComparison | undefined;
115
266
  if (spec.budget !== undefined) {
116
267
  source = "budget";
117
268
  referenceMs = spec.budget.wallTimeMs;
@@ -120,6 +271,7 @@ export function evaluatePerfBudget(
120
271
  source = "baseline";
121
272
  referenceMs = spec.baseline.wallTimeMs;
122
273
  relative = spec.relative ?? 0;
274
+ if (spec.environment !== undefined) comparison = comparePerfEnvironments(spec.baseline.environment, spec.environment);
123
275
  } else {
124
276
  return new Error("perf-budget needs a budget or a recorded baseline");
125
277
  }
@@ -127,6 +279,17 @@ export function evaluatePerfBudget(
127
279
  const ratio = Math.round((measuredMs / budgetMs) * 1000) / 1000;
128
280
  const passed = measuredMs <= budgetMs;
129
281
  const bound = `${Math.round(budgetMs)}ms (${source} ${Math.round(referenceMs)}ms${relative > 0 ? ` +${Math.round(relative * 100)}%` : ""})`;
282
+ const verdict = passed
283
+ ? `perf-budget passed: measured ${Math.round(measuredMs)}ms within ${bound}, ratio ${ratio}`
284
+ : `perf-budget failed: measured ${Math.round(measuredMs)}ms exceeds ${bound}, ratio ${ratio}`;
285
+ const environmentNote =
286
+ comparison === undefined
287
+ ? ""
288
+ : comparison.baseline === null
289
+ ? "; baseline records no environment"
290
+ : comparison.differing.length > 0
291
+ ? `; environment differs: ${comparison.differing.join(", ")}`
292
+ : "";
130
293
  return {
131
294
  kind: "perf-budget",
132
295
  passed,
@@ -136,8 +299,7 @@ export function evaluatePerfBudget(
136
299
  source,
137
300
  referenceMs,
138
301
  relative,
139
- summary: passed
140
- ? `perf-budget passed: measured ${Math.round(measuredMs)}ms within ${bound}, ratio ${ratio}`
141
- : `perf-budget failed: measured ${Math.round(measuredMs)}ms exceeds ${bound}, ratio ${ratio}`,
302
+ summary: `${verdict}${environmentNote}`,
303
+ ...(comparison !== undefined ? { environment: comparison } : {}),
142
304
  };
143
305
  }
@@ -1,4 +1,5 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
2
3
  import path from "node:path";
3
4
  import { resolveSafeCwd, runCommandVector, type SafeCommandResult } from "../../core/safe-exec.js";
4
5
  import { declaredVerificationScripts, VERIFICATION_SCRIPT_FAMILY_HINT } from "../../core/verification-scripts.js";
@@ -16,9 +17,11 @@ import {
16
17
  } from "./catalog.js";
17
18
  import { compareNumeric, type NumericCompareReport, parseNumericPayload, renderNumericReport } from "./numeric.js";
18
19
  import {
20
+ capturePerfEnvironment,
19
21
  evaluatePerfBudget,
20
22
  type PerfBaseline,
21
23
  type PerfBudgetReport,
24
+ type PerfEnvironment,
22
25
  parsePerfBaseline,
23
26
  renderPerfBaseline,
24
27
  } from "./perf.js";
@@ -26,6 +29,52 @@ import {
26
29
  /** The structured verdict a numeric-compare or perf-budget check records beside the command facts. */
27
30
  export type DeclaredCheckReport = NumericCompareReport | PerfBudgetReport;
28
31
 
32
+ /**
33
+ * Output ceiling for a judged check's command. A numeric payload may carry up
34
+ * to NUMERIC_PAYLOAD_CAPS.elements numbers, which as printed JSON can exceed
35
+ * the safe-exec default of 600 KB by a wide margin, so the judged path has its
36
+ * own bound. The runner retains the whole capture in memory as a string until
37
+ * judgement, so this constant is also the memory bound one judged check may
38
+ * hold; output past it ends the command before judgement. Baseline recording
39
+ * runs the same command under the same ceiling, and a reference or baseline
40
+ * file is refused past it before being read, so no judged input exceeds it.
41
+ */
42
+ export const JUDGED_CHECK_MAX_OUTPUT_BYTES = 32 * 1024 * 1024;
43
+
44
+ export type CheckExecutionOutcome = "succeeded" | "failed" | "timed-out" | "aborted" | "output-capped";
45
+
46
+ /**
47
+ * A verifier result answers three separate questions, and a reader must not
48
+ * fold them into one. Execution says whether the command ran to completion.
49
+ * Validation says what the declared judgement concluded: a tolerance or budget
50
+ * verdict for a judged check, the exit code itself for a command check, or
51
+ * `not-run` when execution ended before any judgement. Scientific validity is
52
+ * never established by a check: a payload within tolerance of its reference
53
+ * says nothing about whether the reference is right.
54
+ */
55
+ export interface CheckJudgement {
56
+ execution: CheckExecutionOutcome;
57
+ validation: "passed" | "failed" | "exit-code" | "not-run";
58
+ scientificValidity: typeof SCIENTIFIC_VALIDITY_NOT_ESTABLISHED;
59
+ }
60
+
61
+ export const SCIENTIFIC_VALIDITY_NOT_ESTABLISHED = "not established by this check";
62
+
63
+ function sha256(text: string): string {
64
+ return createHash("sha256").update(text).digest("hex");
65
+ }
66
+
67
+ function executionOutcome(result: Pick<SafeCommandResult, "aborted" | "timedOut" | "outputCapped" | "exitCode">) {
68
+ if (result.aborted) return "aborted" as const;
69
+ if (result.timedOut) return "timed-out" as const;
70
+ if (result.outputCapped) return "output-capped" as const;
71
+ return result.exitCode === 0 ? ("succeeded" as const) : ("failed" as const);
72
+ }
73
+
74
+ function judgement(execution: CheckExecutionOutcome, validation: CheckJudgement["validation"]): CheckJudgement {
75
+ return { execution, validation, scientificValidity: SCIENTIFIC_VALIDITY_NOT_ESTABLISHED };
76
+ }
77
+
29
78
  /**
30
79
  * Package scripts and the project catalog meet here as one canonical check
31
80
  * projection. Project checks retain their admitted argv/cwd/timeout exactly;
@@ -203,11 +252,34 @@ export function listChecks(cwdArg: string | undefined): ToolResult {
203
252
  };
204
253
  }
205
254
 
255
+ /**
256
+ * Attach the judgement facts to a `command` check's result, whose whole
257
+ * verdict is its exit code: a package script or a catalog `command` check.
258
+ * Judged checks attach their own facts before reaching here and keep them; a
259
+ * result without exec facts (a refusal before anything ran) gets none.
260
+ */
261
+ function withCommandJudgement(result: ToolResult): ToolResult {
262
+ const details = result.details ?? {};
263
+ if (details.judgement !== undefined) return result;
264
+ // The exec record always names exitCode (a number, or null for a signal
265
+ // death) once the command ran; a refusal before spawning carries none.
266
+ if (!Object.hasOwn(details, "exitCode")) return result;
267
+ const execution = executionOutcome({
268
+ aborted: details.aborted === true,
269
+ timedOut: details.timedOut === true,
270
+ outputCapped: details.outputCapped === true,
271
+ exitCode: typeof details.exitCode === "number" ? details.exitCode : null,
272
+ });
273
+ const validation = execution === "succeeded" || execution === "failed" ? "exit-code" : "not-run";
274
+ return { ...result, details: { ...details, judgement: judgement(execution, validation) } };
275
+ }
276
+
206
277
  function withDeclaredEvidence(result: ToolResult, check: DeclaredCheck): ToolResult {
278
+ const judged = check.kind === "command" ? withCommandJudgement(result) : result;
207
279
  return {
208
- ...result,
280
+ ...judged,
209
281
  details: {
210
- ...result.details,
282
+ ...judged.details,
211
283
  action: "verify",
212
284
  check: check.id,
213
285
  kind: check.kind,
@@ -239,7 +311,12 @@ export function extractNumericPayloadText(output: string): string {
239
311
  }
240
312
  }
241
313
 
242
- /** Read a repository-relative check file inside the workspace root, as text. */
314
+ /**
315
+ * Read a repository-relative check file inside the workspace root, as text.
316
+ * The file is bounded by JUDGED_CHECK_MAX_OUTPUT_BYTES, the same ceiling as
317
+ * the command output it is judged beside, and the size is checked before any
318
+ * byte is read so an oversized file costs nothing but a stat.
319
+ */
243
320
  function readCheckFile(workspaceRoot: string, relative: string, label: string): string | Error {
244
321
  let resolved: string;
245
322
  try {
@@ -249,24 +326,45 @@ function readCheckFile(workspaceRoot: string, relative: string, label: string):
249
326
  }
250
327
  if (!existsSync(resolved)) return new Error(`${label} '${relative}' does not exist`);
251
328
  try {
329
+ const { size } = statSync(resolved);
330
+ if (size > JUDGED_CHECK_MAX_OUTPUT_BYTES) {
331
+ return new Error(`${label} '${relative}' exceeds the ${JUDGED_CHECK_MAX_OUTPUT_BYTES}-byte cap (${size} bytes)`);
332
+ }
252
333
  return readFileSync(resolved, "utf8");
253
334
  } catch (error) {
254
335
  return new Error(`${label} '${relative}' cannot be read (${error instanceof Error ? error.message : String(error)})`);
255
336
  }
256
337
  }
257
338
 
258
- /** Judge a numeric-compare command's stdout against reference text already read from disk. Pure. */
339
+ /**
340
+ * Judge a numeric-compare command's stdout against reference text already
341
+ * read from disk. Pure. The report records the identity of both texts it
342
+ * judged: the reference's digest and size beside the caller's label (and its
343
+ * path when the caller names one), and the digest and size of the payload
344
+ * text extracted from stdout.
345
+ */
259
346
  export function judgeNumericTexts(
260
347
  stdout: string,
261
348
  referenceText: string,
262
349
  tolerance: DeclaredNumericCompare["tolerance"],
263
350
  referenceLabel: string,
351
+ referencePath?: string,
264
352
  ): NumericCompareReport | Error {
265
353
  const reference = parseNumericPayload(referenceText, referenceLabel);
266
354
  if (reference instanceof Error) return reference;
267
- const actual = parseNumericPayload(extractNumericPayloadText(stdout), "command output");
355
+ const payloadText = extractNumericPayloadText(stdout);
356
+ const actual = parseNumericPayload(payloadText, "command output");
268
357
  if (actual instanceof Error) return actual;
269
- return compareNumeric(actual, reference, tolerance);
358
+ return {
359
+ ...compareNumeric(actual, reference, tolerance),
360
+ reference: {
361
+ source: referenceLabel,
362
+ ...(referencePath !== undefined ? { path: referencePath } : {}),
363
+ sha256: sha256(referenceText),
364
+ bytes: Buffer.byteLength(referenceText, "utf8"),
365
+ },
366
+ actual: { sha256: sha256(payloadText), bytes: Buffer.byteLength(payloadText, "utf8") },
367
+ };
270
368
  }
271
369
 
272
370
  /** Judge a numeric-compare command's stdout against the declared reference under the workspace root. */
@@ -277,17 +375,35 @@ function judgeNumericCompare(
277
375
  ): NumericCompareReport | Error {
278
376
  const referenceText = readCheckFile(workspaceRoot, numeric.reference, "reference");
279
377
  if (referenceText instanceof Error) return referenceText;
280
- return judgeNumericTexts(stdout, referenceText, numeric.tolerance, `reference '${numeric.reference}'`);
378
+ return judgeNumericTexts(
379
+ stdout,
380
+ referenceText,
381
+ numeric.tolerance,
382
+ `reference '${numeric.reference}'`,
383
+ numeric.reference,
384
+ );
385
+ }
386
+
387
+ export interface JudgePerfOptions {
388
+ /** The judging host; captured from this process when omitted. Tests inject one for determinism. */
389
+ environment?: PerfEnvironment;
281
390
  }
282
391
 
283
- /** Judge a measured wall time against a budget, or against baseline text already read from disk. Pure. */
392
+ /**
393
+ * Judge a measured wall time against a budget, or against baseline text
394
+ * already read from disk. Pure given `options.environment`. A baseline
395
+ * judgement records the baseline file's identity and compares its recorded
396
+ * host against the judging host; that comparison is reported, never enforced.
397
+ */
284
398
  export function judgePerfTexts(
285
399
  measuredMs: number,
286
400
  perf: DeclaredPerfBudget,
287
401
  baselineText: string | undefined,
288
402
  baselineLabel: string,
403
+ options: JudgePerfOptions = {},
289
404
  ): PerfBudgetReport | Error {
290
405
  let baseline: PerfBaseline | undefined;
406
+ let provenance: PerfBudgetReport["baseline"];
291
407
  if (perf.baseline !== undefined) {
292
408
  if (baselineText === undefined) {
293
409
  return new Error(`${baselineLabel} is missing; record it with \`clio-coder verifiers baseline <id>\``);
@@ -295,12 +411,21 @@ export function judgePerfTexts(
295
411
  const parsed = parsePerfBaseline(baselineText, baselineLabel);
296
412
  if (parsed instanceof Error) return parsed;
297
413
  baseline = parsed;
414
+ provenance = {
415
+ path: perf.baseline,
416
+ sha256: sha256(baselineText),
417
+ bytes: Buffer.byteLength(baselineText, "utf8"),
418
+ ...(parsed.recordedAt !== undefined ? { recordedAt: parsed.recordedAt } : {}),
419
+ ...(parsed.check !== undefined ? { check: parsed.check } : {}),
420
+ };
298
421
  }
299
- return evaluatePerfBudget(measuredMs, {
422
+ const report = evaluatePerfBudget(measuredMs, {
300
423
  ...(perf.budget !== undefined ? { budget: perf.budget } : {}),
301
- ...(baseline !== undefined ? { baseline } : {}),
424
+ ...(baseline !== undefined ? { baseline, environment: options.environment ?? capturePerfEnvironment() } : {}),
302
425
  ...(perf.tolerance?.relative !== undefined ? { relative: perf.tolerance.relative } : {}),
303
426
  });
427
+ if (report instanceof Error || provenance === undefined) return report;
428
+ return { ...report, baseline: provenance };
304
429
  }
305
430
 
306
431
  /** Judge a measured wall time against the declared budget or the recorded baseline under the workspace root. */
@@ -336,8 +461,11 @@ function commandFacts(result: SafeCommandResult): Record<string, unknown> {
336
461
  /**
337
462
  * Run a numeric-compare or perf-budget check: the command through the same
338
463
  * safe-exec spine as a command check, then the pure judgement. A command that
339
- * exits non-zero, times out, or is aborted fails before any comparison, so a
340
- * crashed validator never reads as a tolerance verdict.
464
+ * exits non-zero, times out, is aborted, or overruns the output ceiling fails
465
+ * before any comparison, so a crashed or truncated validator never reads as a
466
+ * tolerance verdict. Every result carries the three-part judgement so a
467
+ * reader can tell execution failure, validation failure, and the unanswered
468
+ * question of scientific validity apart.
341
469
  */
342
470
  async function runJudgedCheck(
343
471
  check: DeclaredCheck,
@@ -351,16 +479,25 @@ async function runJudgedCheck(
351
479
  result = await runCommandVector(file, vector, {
352
480
  cwd,
353
481
  timeoutMs: check.timeoutMs,
482
+ maxOutputBytes: JUDGED_CHECK_MAX_OUTPUT_BYTES,
354
483
  ...(options?.signal !== undefined ? { signal: options.signal } : {}),
355
484
  });
356
485
  } catch (error) {
357
486
  return { kind: "error", message: `verify: ${error instanceof Error ? error.message : String(error)}` };
358
487
  }
359
- const facts = commandFacts(result);
360
- const tail = `${result.stdout}${result.stderr}`.trim().slice(-2_000);
488
+ const execution = executionOutcome(result);
489
+ const facts = { ...commandFacts(result), judgement: judgement(execution, "not-run") };
361
490
  if (result.aborted) return { kind: "error", message: "verify: aborted", details: facts };
362
491
  if (result.timedOut) return { kind: "error", message: `verify: timed out after ${check.timeoutMs}ms`, details: facts };
492
+ if (result.outputCapped) {
493
+ return {
494
+ kind: "error",
495
+ message: `verify: ${check.kind} command output exceeded ${JUDGED_CHECK_MAX_OUTPUT_BYTES} bytes before judgement`,
496
+ details: facts,
497
+ };
498
+ }
363
499
  if (result.exitCode !== 0) {
500
+ const tail = `${result.stdout}${result.stderr}`.trim().slice(-2_000);
364
501
  return {
365
502
  kind: "error",
366
503
  message: `verify: ${check.kind} command exited with code ${result.exitCode ?? "?"} before judgement: ${tail}`,
@@ -375,7 +512,7 @@ async function runJudgedCheck(
375
512
  : new Error(`declared check '${check.id}' has kind ${check.kind} without its parameters`);
376
513
  if (report instanceof Error) return { kind: "error", message: `verify: ${report.message}`, details: facts };
377
514
  const rendered = report.kind === "numeric-compare" ? renderNumericReport(report) : report.summary;
378
- const details = { ...facts, report };
515
+ const details = { ...facts, report, judgement: judgement(execution, report.passed ? "passed" : "failed") };
379
516
  if (!report.passed) return { kind: "error", message: `verify: ${rendered}`, details };
380
517
  return { kind: "ok", output: `${rendered}\n`, details };
381
518
  }
@@ -394,12 +531,15 @@ export async function runProjectCheck(check: DeclaredCheck, options?: { signal?:
394
531
 
395
532
  /**
396
533
  * Run a perf-budget check once and write its wall time as the baseline the
397
- * check's `baseline` path names. The command must exit cleanly; a failed run
398
- * records nothing, so a baseline never encodes a broken command's timing.
534
+ * check's `baseline` path names. The command runs under the judged check's
535
+ * output ceiling, so the recording run and the judged run are the same run.
536
+ * The command must exit cleanly; a failed, timed-out, aborted, or
537
+ * output-capped run records nothing, so a baseline never encodes a broken
538
+ * command's timing.
399
539
  */
400
540
  export async function recordPerfBaseline(
401
541
  check: DeclaredCheck,
402
- options?: { signal?: AbortSignal; now?: () => Date },
542
+ options?: { signal?: AbortSignal; now?: () => Date; environment?: PerfEnvironment },
403
543
  ): Promise<{ ok: true; path: string; wallTimeMs: number } | { ok: false; message: string }> {
404
544
  if (check.kind !== "perf-budget" || check.perf?.baseline === undefined) {
405
545
  return { ok: false, message: `check '${check.id}' is not a perf-budget check with a baseline path` };
@@ -413,16 +553,23 @@ export async function recordPerfBaseline(
413
553
  result = await runCommandVector(file, vector, {
414
554
  cwd,
415
555
  timeoutMs: check.timeoutMs,
556
+ maxOutputBytes: JUDGED_CHECK_MAX_OUTPUT_BYTES,
416
557
  ...(options?.signal !== undefined ? { signal: options.signal } : {}),
417
558
  });
418
559
  } catch (error) {
419
560
  return { ok: false, message: error instanceof Error ? error.message : String(error) };
420
561
  }
421
- if (result.aborted || result.timedOut || result.exitCode !== 0) {
422
- return {
423
- ok: false,
424
- message: `command ${result.timedOut ? "timed out" : result.aborted ? "was aborted" : `exited with code ${result.exitCode ?? "?"}`}; no baseline recorded`,
425
- };
562
+ const execution = executionOutcome(result);
563
+ if (execution !== "succeeded") {
564
+ const ended =
565
+ execution === "aborted"
566
+ ? "was aborted"
567
+ : execution === "timed-out"
568
+ ? "timed out"
569
+ : execution === "output-capped"
570
+ ? `output exceeded ${JUDGED_CHECK_MAX_OUTPUT_BYTES} bytes`
571
+ : `exited with code ${result.exitCode ?? "?"}`;
572
+ return { ok: false, message: `command ${ended}; no baseline recorded` };
426
573
  }
427
574
  let target: string;
428
575
  try {
@@ -431,9 +578,14 @@ export async function recordPerfBaseline(
431
578
  return { ok: false, message: `baseline ${error instanceof Error ? error.message : String(error)}` };
432
579
  }
433
580
  const recordedAt = (options?.now?.() ?? new Date()).toISOString();
581
+ const environment = options?.environment ?? capturePerfEnvironment();
434
582
  try {
435
583
  mkdirSync(path.dirname(target), { recursive: true });
436
- writeFileSync(target, renderPerfBaseline({ wallTimeMs: result.durationMs, check: check.id, recordedAt }), "utf8");
584
+ writeFileSync(
585
+ target,
586
+ renderPerfBaseline({ wallTimeMs: result.durationMs, check: check.id, recordedAt, environment }),
587
+ "utf8",
588
+ );
437
589
  } catch (error) {
438
590
  return {
439
591
  ok: false,
@@ -471,7 +623,7 @@ export async function runScriptCheck(
471
623
  : [];
472
624
  const vector = ["run", check];
473
625
  if (extraArgs.length > 0) vector.push("--", ...extraArgs);
474
- return runVectorTool("verify", "npm", vector, { ...args, cwd }, options);
626
+ return withCommandJudgement(await runVectorTool("verify", "npm", vector, { ...args, cwd }, options));
475
627
  }
476
628
 
477
629
  export { VERIFICATION_SCRIPT_FAMILY_HINT };
@@ -20,3 +20,25 @@ export const webFetchToolSurface = {
20
20
  baseActionClass: "read",
21
21
  executionMode: "parallel",
22
22
  } satisfies ToolSurface;
23
+
24
+ /**
25
+ * The read half of the web split. It shares web_fetch's implementation and
26
+ * accepts no method, headers, or body, so no argument can turn it into an
27
+ * outward action: it is read class unconditionally and never asks for an
28
+ * outward approval.
29
+ */
30
+ export const webReadToolSurface = {
31
+ name: ToolNames.WebRead,
32
+ description:
33
+ "Read an http(s) URL with a GET request; HTML is cleaned and converted to Markdown, arXiv and repository-tree URLs are summarized. Sends nothing outward: no method, headers, or body. Non-2xx responses are errors; private networks require operator opt-in.",
34
+ parameters: Type.Object({
35
+ url: Type.String({ description: "Fully-qualified http(s) URL." }),
36
+ timeout_ms: Type.Optional(Type.Number({ description: "Timeout ms (default 30000)." })),
37
+ max_bytes: Type.Optional(Type.Number({ description: "Max bytes returned (default 600000)." })),
38
+ format: Type.Optional(
39
+ Type.String({ description: "auto (default) converts HTML to Markdown; raw returns the body unconverted." }),
40
+ ),
41
+ }),
42
+ baseActionClass: "read",
43
+ executionMode: "parallel",
44
+ } satisfies ToolSurface;