@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.
- package/CHANGELOG.md +82 -0
- package/README.md +7 -6
- package/dist/{acp-JWPQZM2D.js → acp-ZWZCPS2A.js} +13 -13
- package/dist/{agents-4GCDIRVX.js → agents-LYSOWZUE.js} +53 -52
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-SYAKTDQE.js → auth-WBQGKWQ5.js} +27 -27
- package/dist/{background-OW67WMYR.js → background-BUMOBAQN.js} +4 -4
- package/dist/{builtins-TKS63VNV.js → builtins-ODRJOEDI.js} +7 -7
- package/dist/{chunk-JLBVCROW.js → chunk-2DRRZ57Q.js} +33 -24
- package/dist/chunk-2JBZYUPY.js +105 -0
- package/dist/chunk-2KUBKL63.js +336 -0
- package/dist/{chunk-K45LHSCI.js → chunk-2VBWFXYE.js} +7 -3
- package/dist/{chunk-XTLJDC2X.js → chunk-2X2R3UTH.js} +23 -18
- package/dist/{chunk-5HULHKT2.js → chunk-37LW32LZ.js} +5 -5
- package/dist/{chunk-W7KNI3F5.js → chunk-3AND2EFU.js} +5 -5
- package/dist/{chunk-36XSBPXL.js → chunk-3RDHGNU7.js} +95 -27
- package/dist/{chunk-BIY22UUK.js → chunk-3SUDBGEI.js} +11 -10
- package/dist/{chunk-3IQOZRQ6.js → chunk-3TQN67I2.js} +7 -7
- package/dist/{chunk-KWJXCL2X.js → chunk-3U4BL2EV.js} +3 -3
- package/dist/{chunk-RBES4TCZ.js → chunk-3UQADNG2.js} +3 -3
- package/dist/{chunk-V4ZKOKRB.js → chunk-434LRQ6Z.js} +61 -53
- package/dist/{chunk-MWMW53WW.js → chunk-4ATBOFRP.js} +649 -193
- package/dist/{chunk-QGIC5SX5.js → chunk-4DNL43EZ.js} +3 -3
- package/dist/{chunk-GVU4CXPJ.js → chunk-4HFJKRGZ.js} +113 -54
- package/dist/{chunk-5A6XR3RJ.js → chunk-555E2WVV.js} +16 -2
- package/dist/{chunk-LZDLYSUN.js → chunk-5RTEFNBP.js} +3 -3
- package/dist/{chunk-HMGAKB7E.js → chunk-64XJW7NT.js} +15 -15
- package/dist/{chunk-EXKUF426.js → chunk-7FBCRWVT.js} +280 -280
- package/dist/{chunk-K3W6BF5C.js → chunk-7JSOSVLP.js} +2 -2
- package/dist/{chunk-WFTSK7N3.js → chunk-7N3OLLSL.js} +4 -4
- package/dist/{chunk-JRA6OBHY.js → chunk-A6DULIMH.js} +17 -5
- package/dist/{chunk-R5NRX5N4.js → chunk-AB3QXXBC.js} +2 -2
- package/dist/chunk-ACCECAH4.js +49 -0
- package/dist/{chunk-GJBJHJNY.js → chunk-AM6CEP2K.js} +5 -5
- package/dist/{chunk-MUXNDNMZ.js → chunk-AY4XE6GN.js} +19 -13
- package/dist/{chunk-MATCRH3M.js → chunk-BBA2TAWV.js} +9 -9
- package/dist/{chunk-PMUUAABD.js → chunk-BMNVVKEW.js} +9 -9
- package/dist/{chunk-TOPICHGR.js → chunk-CTGZCEI6.js} +2 -2
- package/dist/{chunk-L75H5B3B.js → chunk-DIAJYJYG.js} +2 -2
- package/dist/{chunk-JIMWEYWO.js → chunk-EHZRAB4U.js} +2 -2
- package/dist/{chunk-YXANQGCX.js → chunk-EM2DIQAJ.js} +6 -6
- package/dist/{chunk-JCVIL6TY.js → chunk-ETF4ROKH.js} +4 -4
- package/dist/{chunk-5W4FRA5Q.js → chunk-F2YM3JY4.js} +483 -253
- package/dist/{chunk-YGIV24MF.js → chunk-FEBQWHJT.js} +21 -16
- package/dist/{chunk-PGEFOTJB.js → chunk-FPS4R2RN.js} +5 -4
- package/dist/{chunk-XC5POIL4.js → chunk-G5R53COU.js} +1 -1
- package/dist/chunk-GHXGMFQ5.js +40 -0
- package/dist/{chunk-QLKCCC2J.js → chunk-GJDRMBDI.js} +14 -14
- package/dist/{chunk-2ZWLMA3T.js → chunk-GREYLTZ5.js} +7 -7
- package/dist/{chunk-YXFKLMX2.js → chunk-H2WSCZZT.js} +22 -6
- package/dist/{chunk-FNVPQQYT.js → chunk-H6IUCY6Q.js} +2 -2
- package/dist/{chunk-5C2OQHLR.js → chunk-H72DCH3E.js} +92 -203
- package/dist/{chunk-JYKUMHCQ.js → chunk-H7TXJR23.js} +21 -21
- package/dist/chunk-HBJQQTKM.js +40 -0
- package/dist/chunk-HCVKSGNZ.js +990 -0
- package/dist/{chunk-ARRUMZ7X.js → chunk-I47EJPYL.js} +3 -3
- package/dist/{chunk-YKIIWURD.js → chunk-IALGWTLO.js} +3 -3
- package/dist/{chunk-FB3KTE2J.js → chunk-IALZJE37.js} +4 -4
- package/dist/{chunk-RAUOKUZV.js → chunk-IC7JXLOM.js} +15 -10
- package/dist/{chunk-LLCGGVSW.js → chunk-IOSVTTCD.js} +7 -7
- package/dist/{chunk-DBREN25X.js → chunk-IPTPMLA6.js} +8 -3
- package/dist/{chunk-V552WL53.js → chunk-IZZI3SKQ.js} +3 -67
- package/dist/{chunk-UDAK6GR2.js → chunk-JIYWMQZ5.js} +2 -2
- package/dist/{chunk-O3HSB2YL.js → chunk-JKU34ACI.js} +2 -2
- package/dist/{chunk-6X7VOCDY.js → chunk-JTR3VSV3.js} +3 -3
- package/dist/{chunk-O2QJDRWP.js → chunk-JU6MAMRJ.js} +4 -4
- package/dist/chunk-JURMQWVJ.js +15 -0
- package/dist/{chunk-STC6CWUZ.js → chunk-K3XN4LZ4.js} +5 -5
- package/dist/{chunk-ATB3Q7YO.js → chunk-KIVFXGBM.js} +27 -2
- package/dist/{chunk-WJWNZXRM.js → chunk-KOAHT3N2.js} +2 -2
- package/dist/chunk-KP5BPXR3.js +73 -0
- package/dist/{chunk-K53E2PTW.js → chunk-KRJQG47M.js} +3 -3
- package/dist/{chunk-IILXVWJY.js → chunk-KW6OJ7IY.js} +19 -21
- package/dist/{chunk-A46ILRS2.js → chunk-L3NBWLSN.js} +4 -4
- package/dist/{chunk-2U2U5POA.js → chunk-L4RUTLRL.js} +5 -5
- package/dist/{chunk-QYSAZMSH.js → chunk-LGTVWPRN.js} +2 -2
- package/dist/{chunk-KGP3UQGJ.js → chunk-LSQW6KZO.js} +5 -5
- package/dist/{chunk-P4JS3MH5.js → chunk-LWJYOHT3.js} +8 -8
- package/dist/{chunk-U3TPUXOQ.js → chunk-M6YLF66Z.js} +74 -40
- package/dist/{chunk-5D2FNBMG.js → chunk-MJ4QEJVT.js} +2 -2
- package/dist/{chunk-RM3XJX7P.js → chunk-MO65K5CH.js} +5 -5
- package/dist/{chunk-H5DPSUBB.js → chunk-MTOZEQHL.js} +3 -3
- package/dist/{chunk-6R5MBXBJ.js → chunk-NBPA5QM6.js} +2 -2
- package/dist/{chunk-H77XBUBM.js → chunk-NMBEW4PP.js} +3 -3
- package/dist/{chunk-QWUSS2QP.js → chunk-NPLLK3HO.js} +67 -87
- package/dist/{chunk-K5UJD6MM.js → chunk-NSYGPIVW.js} +5 -5
- package/dist/{context-EZZPT2ZV.js → chunk-NXTV5OI5.js} +30 -84
- package/dist/{chunk-F7Y6QTPL.js → chunk-NYDG4QP4.js} +4 -4
- package/dist/{chunk-PFZJMXIY.js → chunk-OA2GDACN.js} +2 -2
- package/dist/{chunk-Q32C6AWI.js → chunk-PJI57EC6.js} +4 -4
- package/dist/{chunk-EFXMQYI6.js → chunk-PJJBUGMR.js} +52 -52
- package/dist/{chunk-ICYIUNO4.js → chunk-PNJE7JPS.js} +18 -3
- package/dist/chunk-PP23PZEV.js +1347 -0
- package/dist/chunk-PPIFDSBK.js +409 -0
- package/dist/{chunk-RFULVPBX.js → chunk-PTFISXQO.js} +6 -5
- package/dist/{chunk-JV25I7ID.js → chunk-QB33Z5S7.js} +5 -5
- package/dist/{chunk-D55WO5J7.js → chunk-QGNII5VC.js} +8 -8
- package/dist/{chunk-RKFNU5UA.js → chunk-QI72X67S.js} +104 -27
- package/dist/chunk-QKHZZFKH.js +98 -0
- package/dist/{chunk-5UG6EZI3.js → chunk-RDKX2PME.js} +4 -4
- package/dist/{chunk-B5ZTR6KZ.js → chunk-RL7LJYN4.js} +1 -1
- package/dist/{chunk-BE4I3UJ2.js → chunk-RQROVOV3.js} +15 -13
- package/dist/{chunk-TEHVMHOK.js → chunk-S34A7BSP.js} +3 -3
- package/dist/{chunk-4P6M2TTE.js → chunk-SJETVJHX.js} +2 -2
- package/dist/{chunk-OPC4DQD6.js → chunk-SJMNU4ZS.js} +2 -2
- package/dist/{chunk-2JSCCEKO.js → chunk-SLLG2G44.js} +2 -2
- package/dist/{chunk-EPYATQMG.js → chunk-SQAZN2V3.js} +42 -16
- package/dist/{chunk-E2NSPYLC.js → chunk-SQBT46OF.js} +5 -5
- package/dist/{chunk-WTZVSMQZ.js → chunk-TCUOGIL2.js} +5 -5
- package/dist/{chunk-RRZFRIJP.js → chunk-TIWPKCVO.js} +5 -5
- package/dist/{chunk-QLAGXTTV.js → chunk-UIU7MGZ3.js} +5 -1
- package/dist/{chunk-WLHX3MM5.js → chunk-V4XJWDHR.js} +21 -11
- package/dist/{chunk-PJ5H5B7A.js → chunk-VPWGADBG.js} +18 -18
- package/dist/{chunk-GEYX2NZ5.js → chunk-VWFCAK34.js} +6 -6
- package/dist/{chunk-44U2OUSM.js → chunk-W72LLZAV.js} +2 -2
- package/dist/{chunk-ORRNGQDV.js → chunk-WGRDABW7.js} +4 -4
- package/dist/{chunk-RNLAPBJL.js → chunk-XFLSL7BT.js} +2 -2
- package/dist/{chunk-2SXGG2IV.js → chunk-XJZEDCNT.js} +6 -6
- package/dist/{chunk-UB33F3YW.js → chunk-XLLEL3K7.js} +5 -5
- package/dist/{chunk-2GPGAE5W.js → chunk-XNIZBOFV.js} +15 -1
- package/dist/{chunk-WS4FOGLY.js → chunk-XNZWWDC3.js} +2 -2
- package/dist/{chunk-P7GTE4FX.js → chunk-XRECG65F.js} +2 -2
- package/dist/chunk-XTQ7MEJG.js +457 -0
- package/dist/{chunk-GEVQNST4.js → chunk-XZWSP67B.js} +2 -2
- package/dist/{chunk-OEMFEL26.js → chunk-Y3M2T5RO.js} +3 -3
- package/dist/{chunk-HP7KJ5O2.js → chunk-YPQOPFP7.js} +6 -6
- package/dist/{chunk-MEHBW2SP.js → chunk-YQYINEJI.js} +6 -6
- package/dist/{chunk-RXI7K4J5.js → chunk-ZF6CV4WZ.js} +1338 -217
- package/dist/{chunk-3XE4NRLF.js → chunk-ZKJU55MX.js} +4 -2
- package/dist/{chunk-526ABLHD.js → chunk-ZKQ63XZ5.js} +12 -35
- package/dist/{chunk-PAQVETLA.js → chunk-ZKVMDNAN.js} +5 -5
- package/dist/cli/index.js +47 -37
- package/dist/{clio-BPBAPZGA.js → clio-JUDCLNHC.js} +7 -7
- package/dist/clio-context-tools-FT672MNZ.js +136 -0
- package/dist/{code-nav-KBQ3RIFK.js → code-nav-7OVCTP2Z.js} +28 -26
- package/dist/{components-6DKAXWFN.js → components-OZXZMDWU.js} +5 -5
- package/dist/{config-FWL5JK2H.js → config-P3ZQVF63.js} +80 -75
- package/dist/{config-graph-ACDB26L2.js → config-graph-GKAOBAS5.js} +74 -70
- package/dist/{configure-ZIZ4YV62.js → configure-25LRYZJG.js} +45 -44
- package/dist/context-72VQV7JX.js +73 -0
- package/dist/{context-VIL5MFRH.js → context-COWRWXP3.js} +74 -70
- package/dist/{context-Z3GOBHDK.js → context-WB3D474G.js} +12 -12
- package/dist/{context-clear-ZPB3L7MN.js → context-clear-Y4LYMWC6.js} +70 -66
- package/dist/{context-working-set-2GLBVF7L.js → context-working-set-TMZYVC7A.js} +15 -14
- package/dist/data-tool-KMBWKKWR.js +2987 -0
- package/dist/{detail-VSBWYSGZ.js → detail-4GLROGY5.js} +71 -67
- package/dist/{dispatch-runner-EEEHGKX4.js → dispatch-runner-TR3LBP5P.js} +92 -88
- package/dist/{docs-VMMWFVHL.js → docs-ZK777W2G.js} +3 -3
- package/dist/{doctor-V5L4IQGP.js → doctor-WC4OV2OB.js} +61 -59
- package/dist/{eval-VJYJ2BV3.js → eval-FUNWJNUJ.js} +45 -45
- package/dist/{evals-J2H5V6DD.js → evals-L73EBHSU.js} +4 -4
- package/dist/{evidence-Y35YSXH6.js → evidence-AVJ2RTHX.js} +80 -76
- package/dist/{evidence-POWAEBEW.js → evidence-P4NZOAK7.js} +70 -66
- package/dist/{evidence-XCCCLS36.js → evidence-Y55WKYHH.js} +79 -75
- package/dist/{evolve-GPG72VB6.js → evolve-MAWKRYWF.js} +75 -71
- package/dist/{extensions-YIZ7W3DA.js → extensions-PYQH3H47.js} +8 -8
- package/dist/{fleet-2MDCQ2VK.js → fleet-M4H2QBWT.js} +84 -80
- package/dist/{fleet-W2AF3TOJ.js → fleet-ULBXXRDR.js} +123 -119
- package/dist/{fleet-commands-WS56G26H.js → fleet-commands-7NNC4JZU.js} +17 -16
- package/dist/{fleet-decisions-MYGZ3JW7.js → fleet-decisions-EHEY7KPU.js} +9 -9
- package/dist/{fleet-graph-ELTBXBAV.js → fleet-graph-LQ2AHZT3.js} +15 -15
- package/dist/{fleet-inspect-45IK73L4.js → fleet-inspect-5IGBIIYZ.js} +76 -72
- package/dist/{fleet-preflight-T5NCZKHE.js → fleet-preflight-UTTNOKMG.js} +7 -2
- package/dist/{fleet-validate-VG4JBLA4.js → fleet-validate-YGILJKA6.js} +20 -20
- package/dist/{fleet-verify-VTSABAYO.js → fleet-verify-AUWTCDKR.js} +70 -66
- package/dist/{fleet-view-XC7WMKSS.js → fleet-view-TGUFCY5A.js} +73 -69
- package/dist/{init-VTJNNTIP.js → init-GFN2Z7NF.js} +94 -90
- package/dist/{interop-IU6BNA7C.js → interop-EF5JUWWK.js} +21 -21
- package/dist/{inventory-QPQUTUUZ.js → inventory-I6VJDDYF.js} +73 -69
- package/dist/{library-Q3NWL5CM.js → library-3J5IO2OJ.js} +13 -13
- package/dist/{library-LF7DLU6S.js → library-IJTOFTDS.js} +16 -15
- package/dist/{library-HUTAS57T.js → library-Z3KZSHPE.js} +27 -27
- package/dist/{library-import-PPW4YUC5.js → library-import-IMKFLDHX.js} +21 -21
- package/dist/{library-inventory-DIRVFRZU.js → library-inventory-CQP5D6GU.js} +13 -13
- package/dist/{library-validation-XHUZ3INE.js → library-validation-33UTX7AI.js} +11 -11
- package/dist/mcp-5FWZKUS6.js +26 -0
- package/dist/{memory-Z2LSKNV6.js → memory-36CWN67Y.js} +75 -71
- package/dist/{models-3FTREYPY.js → models-KQ6PQJJQ.js} +49 -49
- package/dist/{monitor-HF2MQRB3.js → monitor-XX6ZD6KC.js} +83 -79
- package/dist/{orchestrator-UYPA6W4S.js → orchestrator-SK6HDAOP.js} +1337 -772
- package/dist/{panes-736XB73K.js → panes-L27QRXUH.js} +12 -12
- package/dist/{panes-C4P3PIWT.js → panes-LXZIWNOZ.js} +4 -4
- package/dist/{paths-JQ4QYIYB.js → paths-7DJDU4P4.js} +5 -5
- package/dist/{preload-XSLRYH3Y.js → preload-K2TDYI4Y.js} +70 -66
- package/dist/{reset-V7QSPZYE.js → reset-73VU3XNT.js} +10 -10
- package/dist/{resources-OJGDFHYT.js → resources-3BYJYVYL.js} +16 -16
- package/dist/{run-T354SMDW.js → run-AR7PY6GW.js} +132 -128
- package/dist/run-script-H2KUDIII.js +41 -0
- package/dist/{settings-MWZXO6RV.js → settings-3VMBMWID.js} +4 -4
- package/dist/{share-Y5ZKJPND.js → share-HVWH4FPF.js} +21 -21
- package/dist/{skills-4GLZC4LN.js → skills-5TYEY75Q.js} +22 -22
- package/dist/{skills-eval-L5T7GODM.js → skills-eval-CK3MD63Z.js} +96 -87
- package/dist/{skills-inventory-LASKXEZI.js → skills-inventory-KSFYG3I6.js} +16 -16
- package/dist/{slash-commands-OIMRU36D.js → slash-commands-DMVHML7P.js} +47 -44
- package/dist/{steer-KMAM2Y2C.js → steer-XCD6V3EW.js} +4 -4
- package/dist/{support-AWC3XKPX.js → support-JAZL6VBR.js} +7 -7
- package/dist/{system-CD75NYBU.js → system-3TDQRMZZ.js} +26 -26
- package/dist/{targets-VSZX2J2S.js → targets-EZKHAYRN.js} +66 -65
- package/dist/{tasks-AN567LYH.js → tasks-SNEFHWYW.js} +12 -12
- package/dist/{terminal-lease-6KTWNHVY.js → terminal-lease-BNLFA4OF.js} +8 -7
- package/dist/{tools-AGRK3V5J.js → tools-7IM6BDCE.js} +12 -12
- package/dist/{trace-P4MQZD33.js → trace-C3MBGD4S.js} +8 -8
- package/dist/{tui-primitives-A6MUW32V.js → tui-primitives-36BY2774.js} +2 -2
- package/dist/{uninstall-BRUTEPIC.js → uninstall-WWLOSZ42.js} +10 -10
- package/dist/{upgrade-SBCGHQGJ.js → upgrade-ETK2JNSJ.js} +37 -47
- package/dist/{usage-BIDVTO6V.js → usage-S2HOB7BZ.js} +93 -89
- package/dist/{verifiers-LTGCAMXS.js → verifiers-QDTEVH7R.js} +24 -22
- package/dist/{verify-OZU4LLNP.js → verify-SUKUK6XM.js} +15 -14
- package/dist/web/client/assets/{abnfDiagram-VCTEODGH-C5wfoHm3.js → abnfDiagram-VCTEODGH-BznNOe_I.js} +1 -1
- package/dist/web/client/assets/{arc-oH91sfLl.js → arc-Pry-7G1_.js} +1 -1
- package/dist/web/client/assets/architecture-7GRP2DOG-BQO9DL_y.js +1 -0
- package/dist/web/client/assets/architectureDiagram-5GKGNRK7-CKPbdvyx.js +36 -0
- package/dist/web/client/assets/{blockDiagram-I7D4REHJ-wi0_CYHL.js → blockDiagram-I7D4REHJ-prINbpbM.js} +1 -1
- package/dist/web/client/assets/{c4Diagram-7LVT6UL2-DV7NYc2W.js → c4Diagram-7LVT6UL2-DkVRKtyU.js} +1 -1
- package/dist/web/client/assets/channel-c4EeUUqA.js +1 -0
- package/dist/web/client/assets/{chunk-4HAMMTFA-Bhsegh3F.js → chunk-4HAMMTFA-CV0Z1ApC.js} +1 -1
- package/dist/web/client/assets/{chunk-75Z2AOVW-RQCckcQG.js → chunk-75Z2AOVW-D34Nohxq.js} +1 -1
- package/dist/web/client/assets/chunk-DU6HZSFF-Das_cS-O.js +125 -0
- package/dist/web/client/assets/{chunk-F27PBJKO-BcNqv2x1.js → chunk-F27PBJKO-CmRojxkG.js} +1 -1
- package/dist/web/client/assets/{chunk-GMAD6QVW-Bq8JWiZT.js → chunk-GMAD6QVW-ClYZmc73.js} +1 -1
- package/dist/web/client/assets/{chunk-GVQU2GXP-DbchrAeJ.js → chunk-GVQU2GXP-B2BiHFt-.js} +1 -1
- package/dist/web/client/assets/{chunk-IMKFNOWR-DrpvjocK.js → chunk-IMKFNOWR-BGApZ8nP.js} +1 -1
- package/dist/web/client/assets/{chunk-L3NEJ4N5-DHLmTnCe.js → chunk-L3NEJ4N5-DIzCgpkY.js} +1 -1
- package/dist/web/client/assets/{chunk-OSK3NFVY-CsRbtN9n.js → chunk-OSK3NFVY-BPT-yePv.js} +1 -1
- package/dist/web/client/assets/{chunk-P2QGCYS3-aqPbxoMh.js → chunk-P2QGCYS3-BC1WTc2t.js} +1 -1
- package/dist/web/client/assets/{chunk-POPQ4Y6H-Dl5vw0h0.js → chunk-POPQ4Y6H-BSjzBmZU.js} +1 -1
- package/dist/web/client/assets/{chunk-PWAF6VOD-D7OBRSdO.js → chunk-PWAF6VOD-BIjLs86Z.js} +1 -1
- package/dist/web/client/assets/{chunk-SHT3W25Y-CdKCIwuB.js → chunk-SHT3W25Y-CduDz2cm.js} +1 -1
- package/dist/web/client/assets/{chunk-SVP7TREG-B94Nu_1-.js → chunk-SVP7TREG-XUn4pPAP.js} +1 -1
- package/dist/web/client/assets/{chunk-TICWLB2K-jjRQI_hk.js → chunk-TICWLB2K-DcBy2DKy.js} +1 -1
- package/dist/web/client/assets/{chunk-XXDRQBXY-azkbKE37.js → chunk-XXDRQBXY-DqAYeljN.js} +1 -1
- package/dist/web/client/assets/classDiagram-ZZMXUADV-C0HR7YKN.js +1 -0
- package/dist/web/client/assets/classDiagram-v2-VYDZK3BY-C0HR7YKN.js +1 -0
- package/dist/web/client/assets/cose-bilkent-JH36ORCC-CVh1icwb.js +1 -0
- package/dist/web/client/assets/{cynefin-OW5HDTMX--i9RDU5f.js → cynefin-OW5HDTMX-BecPbyM6.js} +1 -1
- package/dist/web/client/assets/{cynefinDiagram-5FMLGOSQ-cRcvyBdp.js → cynefinDiagram-5FMLGOSQ-BzMzFwyT.js} +1 -1
- package/dist/web/client/assets/{dagre-GXQ25YYZ-C9mZmAPe.js → dagre-GXQ25YYZ-CAWJmRMG.js} +1 -1
- package/dist/web/client/assets/{diagram-S7CK7UJ4-Oj_zlLDY.js → diagram-S7CK7UJ4--lp0ALmn.js} +1 -1
- package/dist/web/client/assets/{diagram-UQ7AKVKN-BWKbbfcR.js → diagram-UQ7AKVKN-gKUnsjcj.js} +1 -1
- package/dist/web/client/assets/{diagram-VSXAHHWV-C3N3f7DO.js → diagram-VSXAHHWV-BoN5D1Gh.js} +1 -1
- package/dist/web/client/assets/{diagram-VX7I27RA-CtDKDAWe.js → diagram-VX7I27RA-BMtuswQ6.js} +1 -1
- package/dist/web/client/assets/{diagram-Z3DM3KII-B8bkBRCz.js → diagram-Z3DM3KII-DtU8LXrA.js} +1 -1
- package/dist/web/client/assets/dist-v5Q1xZ2K.js +1 -0
- package/dist/web/client/assets/{ebnfDiagram-PWID7BFC-CskW-Whx.js → ebnfDiagram-PWID7BFC-DDcnv9BH.js} +1 -1
- package/dist/web/client/assets/{erDiagram-RLTQ6QDP-C-83cgCW.js → erDiagram-RLTQ6QDP-DvRb4iDL.js} +1 -1
- package/dist/web/client/assets/eventmodeling-NTZA5JFV-01h4SbTc.js +1 -0
- package/dist/web/client/assets/flowDiagram-HODETNUW-Bll_YZ6T.js +1 -0
- package/dist/web/client/assets/framework-YGoR34M4.js +9 -0
- package/dist/web/client/assets/ganttDiagram-EL5Y4UJY-DdFZ9hvH.js +292 -0
- package/dist/web/client/assets/{gitGraph-4MIJSDKK-B40cQtBE.js → gitGraph-4MIJSDKK-DjD_AAMj.js} +1 -1
- package/dist/web/client/assets/{gitGraphDiagram-WWUBYQGX-CH-7P7Di.js → gitGraphDiagram-WWUBYQGX-CDyN9n2u.js} +1 -1
- package/dist/web/client/assets/index-CVcy0FAn.js +75 -0
- package/dist/web/client/assets/{info-A6RAGUB7-eCCE9D_Q.js → info-A6RAGUB7-C_XK8Hq0.js} +1 -1
- package/dist/web/client/assets/{infoDiagram-27XIBGKW-DRnvqMjM.js → infoDiagram-27XIBGKW-DIe4tJ1i.js} +1 -1
- package/dist/web/client/assets/{ishikawaDiagram-5VMMS53U-DBA_55wp.js → ishikawaDiagram-5VMMS53U-CVl5unKI.js} +1 -1
- package/dist/web/client/assets/{journeyDiagram-3NMN7TZE-C-ewpNl7.js → journeyDiagram-3NMN7TZE-CPEB1Vt8.js} +1 -1
- package/dist/web/client/assets/{kanban-definition-UXKFOSKX-B1taGsu0.js → kanban-definition-UXKFOSKX-j-9WXjYQ.js} +1 -1
- package/dist/web/client/assets/{line-lZ0kyxDI.js → line-BIDAcEtX.js} +1 -1
- package/dist/web/client/assets/{linear-DIc8FgZj.js → linear-SzVmGSw4.js} +1 -1
- package/dist/web/client/assets/{mermaid-parser.core-SXolxpXw.js → mermaid-parser.core-Ux4vssh0.js} +3 -3
- package/dist/web/client/assets/{mermaid.core-DXgQtkNg.js → mermaid.core-CDuwVKeh.js} +4 -4
- package/dist/web/client/assets/{mindmap-definition-YA3MSWOX-DXJas9K7.js → mindmap-definition-YA3MSWOX-5MlQEeQ6.js} +1 -1
- package/dist/web/client/assets/{packet-AYTQ26CC-OqVl_07o.js → packet-AYTQ26CC-DRO66c9Q.js} +1 -1
- package/dist/web/client/assets/{pegDiagram-XKGWAZYB-CPE_zdfN.js → pegDiagram-XKGWAZYB-BakZnSjM.js} +1 -1
- package/dist/web/client/assets/{pie-WAS4IAKB-DAxnMBLe.js → pie-WAS4IAKB-BEzcmhz8.js} +1 -1
- package/dist/web/client/assets/{pieDiagram-E7YTZNPT-Uwjpufxv.js → pieDiagram-E7YTZNPT-DpmqgoPt.js} +1 -1
- package/dist/web/client/assets/prism-core-BtsZdCS6.js +1 -0
- package/dist/web/client/assets/{quadrantDiagram-AXDQQJYC-Bjs4yjgs.js → quadrantDiagram-AXDQQJYC-DuMPwwV2.js} +1 -1
- package/dist/web/client/assets/{radar-RG4KPBEZ-CuCKjHM3.js → radar-RG4KPBEZ-Djm3oXl5.js} +1 -1
- package/dist/web/client/assets/{railroad-74A4TZTK-CnQK-Cc1.js → railroad-74A4TZTK-Cpvkwsao.js} +1 -1
- package/dist/web/client/assets/railroad-abnf-HS5TGJTU-CpRQ3ruG.js +1 -0
- package/dist/web/client/assets/railroad-ebnf-LZEXJU2U-1Rm5a5eJ.js +1 -0
- package/dist/web/client/assets/railroad-peg-WCYAUIDC-C8344cTh.js +1 -0
- package/dist/web/client/assets/{railroadDiagram-O6MQD6OU-BDDIPNLL.js → railroadDiagram-O6MQD6OU-CgMS4B6R.js} +1 -1
- package/dist/web/client/assets/{requirementDiagram-BXWQKSXE-B5Ydyxc1.js → requirementDiagram-BXWQKSXE-CX5eoNdN.js} +1 -1
- package/dist/web/client/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/dist/web/client/assets/{sankeyDiagram-P5KCCOFB-Bw2Qym75.js → sankeyDiagram-P5KCCOFB-CODBX2N3.js} +1 -1
- package/dist/web/client/assets/{sequenceDiagram-WJ2MYXX4-BZf36nO0.js → sequenceDiagram-WJ2MYXX4-eUhhF8OR.js} +1 -1
- package/dist/web/client/assets/src-B6xuSHsQ.js +1 -0
- package/dist/web/client/assets/{stateDiagram-D77RDMKH-DnH6JRkp.js → stateDiagram-D77RDMKH-vR6l0NC2.js} +1 -1
- package/dist/web/client/assets/stateDiagram-v2-MP3YSRHH-BYUm8jLY.js +1 -0
- package/dist/web/client/assets/{swimlanes-42K2YHIH-D9PZmtZg.js → swimlanes-42K2YHIH-v9Tw_zX7.js} +1 -1
- package/dist/web/client/assets/swimlanesDiagram-VR7AAH4N-B2jdCvhD.js +8 -0
- package/dist/web/client/assets/{timeline-definition-24CTP7MA-CrkZZBo7.js → timeline-definition-24CTP7MA-DxianbhU.js} +1 -1
- package/dist/web/client/assets/{treeView-Q6P3EWNA-C9zDShoC.js → treeView-Q6P3EWNA-DLxnZb9R.js} +1 -1
- package/dist/web/client/assets/{treemap-WGGIJYW6-B-plj9yK.js → treemap-WGGIJYW6-I7UnZ6xJ.js} +1 -1
- package/dist/web/client/assets/{vennDiagram-4TSXK5OY-VeOdaphN.js → vennDiagram-4TSXK5OY-Ar7M8Mrj.js} +1 -1
- package/dist/web/client/assets/{wardley-WFR3VGLG-Wl1P_m6L.js → wardley-WFR3VGLG-B8ZSHeDu.js} +1 -1
- package/dist/web/client/assets/{wardleyDiagram-VM6X3IG4-B85-R9t2.js → wardleyDiagram-VM6X3IG4-Qks2FmIn.js} +1 -1
- package/dist/web/client/assets/{xychartDiagram-S5SC5T6Z-BrD8OW8m.js → xychartDiagram-S5SC5T6Z-BBBjRtiE.js} +1 -1
- package/dist/web/client/index.html +3 -1
- package/dist/web/reads-worker.js +17 -17
- package/dist/web/server.js +25 -25
- package/dist/{web-EU6ATJWA.js → web-EMGUGGEI.js} +3 -3
- package/dist/{web-fetch-U22Q7HV4.js → web-fetch-6BRRVQON.js} +22 -5
- package/dist/{wiki-generate-LZRLFG6I.js → wiki-generate-XHSJTDOP.js} +104 -100
- package/dist/{with-panes-X5CZOGML.js → with-panes-Z6BTEHMZ.js} +11 -11
- package/dist/worker/entry.js +101 -87
- package/docs/README.md +1 -1
- package/docs/architecture/artifact-placement.md +12 -1
- package/docs/architecture/library.md +1 -1
- package/docs/architecture/prompt-envelope-and-tools.md +37 -27
- package/docs/architecture/safety-model.md +19 -6
- package/docs/architecture/session-lifecycle.md +10 -4
- package/docs/architecture/tui-design.md +37 -14
- package/docs/guide/commands-and-modes.md +39 -19
- package/docs/guide/configuration-and-targets.md +7 -5
- package/docs/guide/configuration-reference.md +116 -13
- package/docs/guide/environment-variables.md +2 -5
- package/docs/guide/fleet-dispatch.md +3 -2
- package/docs/guide/glossary.md +1 -1
- package/docs/guide/installation-and-lifecycle.md +2 -2
- package/docs/guide/resource-library.md +1 -1
- package/docs/guide/tool-usage.md +166 -64
- package/docs/guide/troubleshooting.md +1 -1
- package/docs/process/documentation-guide.md +1 -0
- package/docs/process/fleet-demo-runbook.md +6 -6
- package/docs/process/scientific-validation.md +22 -2
- package/docs/process/tool-audit-v0.4.9.md +357 -0
- package/package.json +1 -1
- package/src/cli/argv.ts +31 -0
- package/src/cli/clio.ts +17 -13
- package/src/cli/config.ts +4 -0
- package/src/cli/doctor-panes.ts +1 -1
- package/src/cli/doctor.ts +3 -1
- package/src/cli/index.ts +14 -1
- package/src/cli/mcp.ts +106 -0
- package/src/cli/skills-eval.ts +8 -2
- package/src/cli/upgrade.ts +34 -38
- package/src/cli/verifiers.ts +1 -1
- package/src/core/bash-exec.ts +27 -4
- package/src/core/config.ts +2 -1
- package/src/core/defaults.ts +10 -1
- package/src/core/event-bus.ts +1 -1
- package/src/core/run-records.ts +438 -0
- package/src/core/safe-exec.ts +506 -56
- package/src/core/skill-activation.ts +5 -3
- package/src/core/termination.ts +3 -3
- package/src/core/tool-names.ts +33 -12
- package/src/domains/context/clio-md.ts +1 -1
- package/src/domains/context/worker/pressure.ts +6 -2
- package/src/domains/context/working-set/path-index.ts +7 -2
- package/src/domains/dispatch/code-step.ts +7 -2
- package/src/domains/dispatch/contract.ts +7 -0
- package/src/domains/dispatch/execution-role.ts +3 -3
- package/src/domains/dispatch/execution-scheduler.ts +204 -79
- package/src/domains/dispatch/extension.ts +131 -14
- package/src/domains/dispatch/fleet-preflight.ts +18 -3
- package/src/domains/dispatch/fleet-run.ts +1 -0
- package/src/domains/dispatch/gate-decisions.ts +3 -3
- package/src/domains/dispatch/heartbeat.ts +1 -1
- package/src/domains/dispatch/host-verification.ts +16 -14
- package/src/domains/dispatch/receipt-findings.ts +3 -4
- package/src/domains/dispatch/reservation-store.ts +7 -9
- package/src/domains/dispatch/route-facts.ts +1 -1
- package/src/domains/dispatch/state.ts +3 -3
- package/src/domains/dispatch/types.ts +1 -1
- package/src/domains/evidence/build.ts +35 -7
- package/src/domains/gateway/mcp/client.ts +923 -0
- package/src/domains/gateway/mcp/config.ts +456 -0
- package/src/domains/gateway/mcp/index.ts +88 -0
- package/src/domains/gateway/mcp/protocol.ts +273 -0
- package/src/domains/gateway/mcp/trust.ts +263 -0
- package/src/domains/lifecycle/doctor.ts +17 -3
- package/src/domains/mux/contract.ts +5 -9
- package/src/domains/mux/detect.ts +1 -1
- package/src/domains/mux/extension.ts +1 -1
- package/src/domains/mux/protocol.ts +5 -7
- package/src/domains/mux/socket-client.ts +3 -3
- package/src/domains/observability/accountability.ts +2 -2
- package/src/domains/observability/contract.ts +7 -3
- package/src/domains/observability/evidence-index.ts +2 -2
- package/src/domains/observability/projection.ts +10 -0
- package/src/domains/prompts/compiler.ts +41 -23
- package/src/domains/prompts/fragments/identity/docs-routing.md +2 -2
- package/src/domains/prompts/fragments/operating/skills.md +12 -10
- package/src/domains/providers/index.ts +5 -1
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +42 -10
- package/src/domains/providers/probe/http.ts +44 -59
- package/src/domains/providers/probe/reasoning.ts +2 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +20 -31
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +9 -4
- package/src/domains/safety/action-classifier.ts +17 -1
- package/src/domains/safety/call-target.ts +14 -0
- package/src/domains/safety/contract.ts +1 -1
- package/src/domains/safety/finish-contract.ts +9 -3
- package/src/domains/safety/loop-detector.ts +1 -1
- package/src/domains/safety/policy-engine.ts +7 -0
- package/src/domains/safety/protected-artifacts.ts +3 -4
- package/src/domains/safety/rejection-feedback.ts +1 -1
- package/src/domains/safety/scope.ts +2 -3
- package/src/domains/safety/validation-contract.ts +3 -2
- package/src/domains/scheduling/budget.ts +5 -3
- package/src/domains/scheduling/contract.ts +2 -1
- package/src/domains/scheduling/extension.ts +3 -3
- package/src/domains/session/compaction/branch-summary.ts +1 -1
- package/src/domains/session/compaction/compact.ts +25 -2
- package/src/domains/session/compaction/cut-point.ts +1 -1
- package/src/domains/session/compaction/tokens.ts +5 -10
- package/src/domains/session/contract.ts +1 -1
- package/src/domains/session/cwd-fallback.ts +2 -2
- package/src/domains/session/handoff.ts +5 -1
- package/src/domains/session/history.ts +6 -0
- package/src/domains/session/manager.ts +14 -7
- package/src/domains/session/retry.ts +2 -1
- package/src/domains/session/session-artifacts.ts +12 -7
- package/src/domains/session/task-board.ts +2 -3
- package/src/engine/apis/openai-completions.ts +8 -0
- package/src/engine/loop-guard.ts +7 -0
- package/src/engine/provider-error-body.ts +65 -0
- package/src/engine/session.ts +118 -29
- package/src/engine/worker-runtime.ts +3 -0
- package/src/entry/boot-options.ts +2 -0
- package/src/entry/orchestrator.ts +18 -2
- package/src/interactive/chat-loop-policy.ts +1 -0
- package/src/interactive/chat-loop.ts +8 -4
- package/src/interactive/chat-panel.ts +23 -9
- package/src/interactive/chat-renderer.ts +33 -11
- package/src/interactive/clio-editor.ts +13 -5
- package/src/interactive/dispatch-board.ts +70 -30
- package/src/interactive/editor-submit.ts +30 -25
- package/src/interactive/footer/widgets.ts +12 -9
- package/src/interactive/interactive-presentation.ts +2 -3
- package/src/interactive/mux-bridge.ts +3 -7
- package/src/interactive/overlay-general-openers.ts +14 -7
- package/src/interactive/overlays/cwd-fallback.ts +1 -1
- package/src/interactive/overlays/library-model.ts +114 -35
- package/src/interactive/overlays/library.ts +52 -5
- package/src/interactive/overlays/list-overlay.ts +4 -1
- package/src/interactive/overlays/session-selector.ts +28 -23
- package/src/interactive/overlays/settings.ts +20 -1
- package/src/interactive/overlays/tree-selector.ts +47 -10
- package/src/interactive/panes-runtime.ts +1 -1
- package/src/interactive/renderers/compaction-summary.ts +1 -1
- package/src/interactive/renderers/provider-error.ts +118 -0
- package/src/interactive/renderers/retry-status.ts +59 -23
- package/src/interactive/renderers/tool-execution.ts +67 -7
- package/src/interactive/renderers/worker-answer.ts +198 -0
- package/src/interactive/renderers/worker-entry.ts +57 -163
- package/src/interactive/slash-commands.ts +26 -1
- package/src/interactive/slash-spec.ts +2 -2
- package/src/interactive/theme/labels.ts +66 -30
- package/src/interactive/turn-persistence.ts +6 -1
- package/src/interactive/turn-recovery.ts +2 -1
- package/src/interactive/turn-runtime.ts +22 -5
- package/src/interactive/view/artifacts.ts +3 -2
- package/src/interactive/view/view-overlay.ts +96 -20
- package/src/tools/agent-tools.ts +21 -7
- package/src/tools/artifact.ts +16 -8
- package/src/tools/bash.ts +90 -11
- package/src/tools/bootstrap.ts +42 -4
- package/src/tools/builtin-tool-catalog.ts +72 -7
- package/src/tools/context/index.ts +27 -31
- package/src/tools/context/library.ts +3 -1
- package/src/tools/context/surface.ts +12 -26
- package/src/tools/core-bootstrap.ts +72 -1
- package/src/tools/data/csv.ts +1189 -0
- package/src/tools/data/index.ts +308 -0
- package/src/tools/data/json.ts +1799 -0
- package/src/tools/data/jsonl.ts +561 -0
- package/src/tools/data/shared.ts +452 -0
- package/src/tools/edit-diff.ts +0 -7
- package/src/tools/edit.ts +115 -18
- package/src/tools/file-mutation-queue.ts +114 -4
- package/src/tools/find.ts +108 -29
- package/src/tools/gateway/caps.ts +11 -0
- package/src/tools/gateway/clio-context-surface.ts +41 -0
- package/src/tools/gateway/clio-context-tools.ts +77 -0
- package/src/tools/gateway/data-surface.ts +138 -0
- package/src/tools/gateway/data-tool.ts +201 -0
- package/src/tools/gateway/index.ts +342 -0
- package/src/tools/gateway/mcp-capabilities.ts +469 -0
- package/src/tools/grep.ts +88 -33
- package/src/tools/harness-extensions.ts +3 -0
- package/src/tools/ignore-policy.ts +7 -5
- package/src/tools/ls.ts +111 -20
- package/src/tools/policy.ts +35 -13
- package/src/tools/presentation.ts +6 -0
- package/src/tools/read.ts +634 -156
- package/src/tools/registry.ts +94 -6
- package/src/tools/run-script.ts +997 -0
- package/src/tools/spawn-hygiene.ts +157 -5
- package/src/tools/surface.ts +163 -0
- package/src/tools/verify/authoring.ts +8 -3
- package/src/tools/verify/catalog.ts +14 -1
- package/src/tools/verify/numeric.ts +367 -59
- package/src/tools/verify/perf.ts +171 -9
- package/src/tools/verify/scripts.ts +178 -26
- package/src/tools/web-fetch-surface.ts +22 -0
- package/src/tools/web-fetch.ts +26 -1
- package/src/tools/write.ts +45 -19
- package/dist/chunk-B6UM3OZC.js +0 -15
- package/dist/chunk-GJ24ODAX.js +0 -196
- package/dist/chunk-LZCCBLRC.js +0 -57
- package/dist/web/client/assets/architecture-7GRP2DOG-EGozsYEO.js +0 -1
- package/dist/web/client/assets/architectureDiagram-5GKGNRK7-z9FokbJl.js +0 -36
- package/dist/web/client/assets/channel-CiUWbHN9.js +0 -1
- package/dist/web/client/assets/chunk-DU6HZSFF-C5USiOAy.js +0 -125
- package/dist/web/client/assets/classDiagram-ZZMXUADV-CMODalmo.js +0 -1
- package/dist/web/client/assets/classDiagram-v2-VYDZK3BY-CMODalmo.js +0 -1
- package/dist/web/client/assets/cose-bilkent-JH36ORCC-RbQL23qS.js +0 -1
- package/dist/web/client/assets/dist-D0_q-A2b.js +0 -1
- package/dist/web/client/assets/eventmodeling-NTZA5JFV-DjVq8wKU.js +0 -1
- package/dist/web/client/assets/flowDiagram-HODETNUW-BUiCBGXt.js +0 -1
- package/dist/web/client/assets/ganttDiagram-EL5Y4UJY-B2lb8lvF.js +0 -292
- package/dist/web/client/assets/index-FSIC94pi.js +0 -83
- package/dist/web/client/assets/prism-core-BngLtbUd.js +0 -1
- package/dist/web/client/assets/railroad-abnf-HS5TGJTU-BcW01NZG.js +0 -1
- package/dist/web/client/assets/railroad-ebnf-LZEXJU2U-B7YCEDDd.js +0 -1
- package/dist/web/client/assets/railroad-peg-WCYAUIDC-DjNZbSTZ.js +0 -1
- package/dist/web/client/assets/src-yeptRXpt.js +0 -1
- package/dist/web/client/assets/stateDiagram-v2-MP3YSRHH-C7QtHeK4.js +0 -1
- package/dist/web/client/assets/swimlanesDiagram-VR7AAH4N-CBZlPFky.js +0 -8
package/src/tools/verify/perf.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
/**
|
|
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: {
|
|
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
|
-
{
|
|
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:
|
|
140
|
-
|
|
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 {
|
|
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
|
-
...
|
|
280
|
+
...judged,
|
|
209
281
|
details: {
|
|
210
|
-
...
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
355
|
+
const payloadText = extractNumericPayloadText(stdout);
|
|
356
|
+
const actual = parseNumericPayload(payloadText, "command output");
|
|
268
357
|
if (actual instanceof Error) return actual;
|
|
269
|
-
return
|
|
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(
|
|
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
|
-
/**
|
|
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
|
-
|
|
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,
|
|
340
|
-
* crashed validator never reads as a
|
|
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
|
|
360
|
-
const
|
|
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
|
|
398
|
-
*
|
|
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
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
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(
|
|
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;
|