@iowarp/clio-coder 0.4.2 → 0.4.4
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 +98 -0
- package/CONTRIBUTING.md +86 -19
- package/README.md +35 -6
- package/dist/{acp-TMDQZDIG.js → acp-WNAYYF4F.js} +12 -13
- package/dist/{agents-5N5NG3XG.js → agents-3OKXHLOI.js} +60 -57
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-Z5CCBXKQ.js → auth-VKNNMGPU.js} +21 -19
- package/dist/{builtins-K6TNDT24.js → builtins-WGALA46I.js} +9 -4
- package/dist/{chunk-XE3PCIXH.js → chunk-23L32XTI.js} +12 -9
- package/dist/{chunk-I64IFBLB.js → chunk-25QBEXRS.js} +18 -11
- package/dist/{chunk-CDNVLKUX.js → chunk-26QSH3EJ.js} +13 -7
- package/dist/{chunk-QQLGQY2A.js → chunk-2ASED4PZ.js} +22 -22
- package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
- package/dist/chunk-2DSOYNFC.js +108 -0
- package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
- package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
- package/dist/{chunk-O3YUNJZ2.js → chunk-2ZSONWVL.js} +82 -25
- package/dist/{chunk-2NHR3NAY.js → chunk-36CT5VVL.js} +331 -42
- package/dist/{chunk-2X4RYJTJ.js → chunk-3GY4F45V.js} +3 -3
- package/dist/{chunk-ZW55JB7N.js → chunk-3ODX73FK.js} +4 -6
- package/dist/{chunk-PBP4B7XR.js → chunk-3UNOLWNZ.js} +3 -3
- package/dist/{chunk-4JDLP6ZS.js → chunk-3UUXNFEX.js} +14 -10
- package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
- package/dist/{chunk-ZW4HH5JJ.js → chunk-4M6Z5QVF.js} +6 -6
- package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
- package/dist/{chunk-M2DAX4F6.js → chunk-4WR7VSYB.js} +2 -2
- package/dist/{chunk-FSP7CMNU.js → chunk-54X7T7DK.js} +61 -6
- package/dist/{chunk-54ODD65L.js → chunk-5636DCO5.js} +4 -4
- package/dist/chunk-57XXR6DR.js +3763 -0
- package/dist/{chunk-3KIPBMUA.js → chunk-5ICU3EUH.js} +2 -2
- package/dist/{chunk-77QIVUZB.js → chunk-5MEZN6CB.js} +4 -4
- package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
- package/dist/{chunk-YJISEZKC.js → chunk-5TUB6SLS.js} +6 -6
- package/dist/{chunk-IMXMHHMQ.js → chunk-6OSVSQL5.js} +341 -57
- package/dist/{chunk-Q4XWMHX6.js → chunk-6PAZTBPA.js} +14 -2
- package/dist/{chunk-FVDGR2ZL.js → chunk-6Q3CYFD3.js} +112 -39
- package/dist/{chunk-IDNA72AH.js → chunk-6QOTUPRG.js} +155 -36
- package/dist/{chunk-X7IARSHT.js → chunk-6UINWWS6.js} +16 -10
- package/dist/{chunk-CYZW7JHJ.js → chunk-72YIHOZQ.js} +9 -9
- package/dist/{chunk-IKSLQ4XV.js → chunk-75W7L2E2.js} +752 -861
- package/dist/{chunk-CRFOIAX3.js → chunk-7UGL4MB5.js} +6 -6
- package/dist/{chunk-HIICAHCJ.js → chunk-AUPNRN7C.js} +2 -2
- package/dist/{chunk-7BHIY2MW.js → chunk-BJVFZO5U.js} +8 -50
- package/dist/{chunk-B74PXLU7.js → chunk-CUSRQKPU.js} +65 -3
- package/dist/chunk-DQOVN6KV.js +386 -0
- package/dist/{chunk-E7GT7O5N.js → chunk-DT3LWJOB.js} +7 -4
- package/dist/chunk-DXKJURES.js +671 -0
- package/dist/{chunk-JBCS7CRR.js → chunk-EL24TAU4.js} +10 -10
- package/dist/{chunk-TPEQIQIE.js → chunk-ELWDPP3Y.js} +8 -8
- package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
- package/dist/chunk-EXLD33WO.js +381 -0
- package/dist/chunk-FEAXX7B6.js +101 -0
- package/dist/{chunk-RLYRBIYQ.js → chunk-FFUPXJC4.js} +90 -331
- package/dist/{chunk-5PFYMY2V.js → chunk-FTMGRKEF.js} +2 -2
- package/dist/{chunk-34BHNEE3.js → chunk-GHS5EBTQ.js} +58 -7
- package/dist/{chunk-DYHAXKHD.js → chunk-GWZNEVM2.js} +12 -8
- package/dist/chunk-GX5WYQO4.js +59 -0
- package/dist/chunk-GYV6VZOC.js +26 -0
- package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
- package/dist/chunk-I2DWJ4GM.js +390 -0
- package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
- package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
- package/dist/{chunk-XQRY4DTA.js → chunk-IGLP3ODT.js} +10 -10
- package/dist/chunk-IRXAATOX.js +539 -0
- package/dist/chunk-IXIY2H4R.js +44 -0
- package/dist/{chunk-SSEYRH53.js → chunk-IZXGRF7P.js} +92 -147
- package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
- package/dist/{chunk-JWJGP5DQ.js → chunk-JEIYHLOR.js} +7 -7
- package/dist/{chunk-F2I26BDK.js → chunk-JQLNNIKT.js} +4 -4
- package/dist/{chunk-BYMNWQ7O.js → chunk-JSD46VO2.js} +315 -63
- package/dist/{chunk-AK5XEFVZ.js → chunk-JT2RFCC5.js} +64 -14
- package/dist/{chunk-MCMZMDAC.js → chunk-K6T2ZAMZ.js} +168 -6
- package/dist/{chunk-PGF63K6I.js → chunk-KFV5L5SK.js} +73 -4
- package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
- package/dist/{chunk-PJX3WQUQ.js → chunk-LLXSDWXS.js} +3 -3
- package/dist/{chunk-DZAW46HP.js → chunk-LTIKRKFL.js} +3 -3
- package/dist/{chunk-DZEK6CJN.js → chunk-N56KALIC.js} +21 -21
- package/dist/{chunk-B7HM5Z7T.js → chunk-NAI6ZFCY.js} +9 -5
- package/dist/{chunk-I66ZTYNP.js → chunk-NRO2BJRH.js} +2656 -2213
- package/dist/{chunk-ZGNYYXQ6.js → chunk-NXIMQY5W.js} +3 -3
- package/dist/{chunk-IKOZFYBN.js → chunk-NXYCB2VD.js} +149 -106
- package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
- package/dist/{chunk-462T4EGZ.js → chunk-O5CVSAG5.js} +2 -2
- package/dist/chunk-ODGTEFFI.js +50 -0
- package/dist/{chunk-3F7VUY77.js → chunk-OEJSLEPW.js} +2 -2
- package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
- package/dist/{chunk-5KW52TEP.js → chunk-Q4WO54TA.js} +132 -77
- package/dist/{chunk-W6NIE6OW.js → chunk-QUFRYSWI.js} +13 -7
- package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
- package/dist/chunk-R6Q67RJH.js +134 -0
- package/dist/{chunk-W4YEMFBX.js → chunk-RAY4OVGZ.js} +3 -3
- package/dist/{chunk-ZNT2M6TG.js → chunk-RQCKCSRL.js} +17 -17
- package/dist/{chunk-LJID3DYZ.js → chunk-RXTN6AKH.js} +3 -3
- package/dist/{chunk-P75RZCJW.js → chunk-RZDWV63N.js} +3 -3
- package/dist/{chunk-UH632ZYL.js → chunk-S6PYF2XF.js} +2 -2
- package/dist/{chunk-HJWWJ6IL.js → chunk-TOIVGRUX.js} +17 -5
- package/dist/{chunk-HLAFFSEK.js → chunk-TQAHXW6Y.js} +2 -2
- package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
- package/dist/{chunk-2HFQNRV3.js → chunk-UEPWCCTY.js} +12 -12
- package/dist/chunk-UOIZ7DA4.js +41 -0
- package/dist/{chunk-UH347SHR.js → chunk-USR47QNF.js} +11 -11
- package/dist/{chunk-AZ4WMN4W.js → chunk-V6HJFQZE.js} +2 -2
- package/dist/chunk-V76WTFTW.js +318 -0
- package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
- package/dist/{chunk-KPXDY6QF.js → chunk-XRZT5WY5.js} +2 -2
- package/dist/{chunk-UBRFI4HS.js → chunk-XULDXHTN.js} +142 -50
- package/dist/chunk-XXYSBZIQ.js +283 -0
- package/dist/{chunk-HKMD33FO.js → chunk-Y55JBDO5.js} +405 -122
- package/dist/{chunk-XOXV5GKE.js → chunk-YD5GIKET.js} +17 -8
- package/dist/{chunk-XGDPUNND.js → chunk-YECAMM3D.js} +2 -2
- package/dist/{chunk-BO7Y52RY.js → chunk-YNFKXPEC.js} +7 -7
- package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
- package/dist/{chunk-M2WXEHER.js → chunk-ZA4VCIGV.js} +2 -2
- package/dist/cli/index.js +42 -40
- package/dist/{clio-7VB377CC.js → clio-QLICPCF5.js} +7 -7
- package/dist/{code-nav-YVLCYA7V.js → code-nav-IJR2DBPR.js} +9 -9
- package/dist/{components-UBWCQSRW.js → components-2TGAI2RC.js} +5 -6
- package/dist/{config-4HVOS65E.js → config-IUA6OYNS.js} +88 -81
- package/dist/{configure-PIWO7B24.js → configure-VEPX4NMX.js} +26 -25
- package/dist/{context-KQYIWPWT.js → context-2DKHWH2T.js} +60 -45
- package/dist/{context-IYEHL3WQ.js → context-4MPR7WKB.js} +78 -69
- package/dist/{context-N6ZE3LGJ.js → context-BOYF5EJM.js} +15 -11
- package/dist/{context-clear-G4OGZJDS.js → context-clear-S4ZJCQUX.js} +73 -65
- package/dist/context-map-COB37XXN.js +505 -0
- package/dist/{context-working-set-BWLF6LJP.js → context-working-set-3I3FYX6Y.js} +18 -17
- package/dist/detail-A7JAVSIG.js +98 -0
- package/dist/{dispatch-runner-2QQAITS3.js → dispatch-runner-RJ5I2F2O.js} +99 -75
- package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
- package/dist/{doctor-LHBD36VU.js → doctor-DKICC2SN.js} +71 -48
- package/dist/{eval-C45FYRJ6.js → eval-OQOQUDHK.js} +308 -146
- package/dist/{eval-inventory-6DEJPLBF.js → eval-inventory-Y6QRFOH5.js} +4 -4
- package/dist/{evidence-6SHONYAF.js → evidence-4DQ25GUQ.js} +79 -175
- package/dist/evidence-4F5USFKH.js +208 -0
- package/dist/{evolve-KRKMV72X.js → evolve-GSS52E5J.js} +71 -67
- package/dist/{extensions-KPZ2UHBB.js → extensions-G7MFLYHT.js} +8 -9
- package/dist/{fleet-IVTCKDHT.js → fleet-Q37YHHAQ.js} +126 -118
- package/dist/{fleet-commands-EDWL3IT7.js → fleet-commands-G7E4N7SM.js} +16 -13
- package/dist/{fleet-decisions-YP3YEFGK.js → fleet-decisions-O7M6QBA2.js} +9 -8
- package/dist/{fleet-graph-ZFWKHY2M.js → fleet-graph-TOUBW6OW.js} +21 -20
- package/dist/{fleet-inspect-FVUNCBML.js → fleet-inspect-SW33JJNI.js} +65 -60
- package/dist/{fleet-preflight-UN5XED4R.js → fleet-preflight-CV2655TW.js} +4 -5
- package/dist/{fleet-validate-XOWC4HSX.js → fleet-validate-KESZX2YH.js} +25 -24
- package/dist/{fleet-verify-UN3SODEL.js → fleet-verify-UQPMTVE3.js} +66 -61
- package/dist/{fleet-view-TWHJKCN6.js → fleet-view-MN2VG4MR.js} +65 -60
- package/dist/{init-T2QORQ3Y.js → init-PXEXQSBF.js} +90 -82
- package/dist/{interop-IN5I2A66.js → interop-ZG5T62U3.js} +12 -13
- package/dist/inventory-C26CFDRR.js +101 -0
- package/dist/{library-LSCATDLZ.js → library-B2W4N74O.js} +29 -29
- package/dist/{memory-HYOKAGGJ.js → memory-YCANYS5A.js} +73 -69
- package/dist/{models-2GPMFYCM.js → models-GERTU3YI.js} +51 -47
- package/dist/{monitor-E4ASVUJH.js → monitor-CPNIUULB.js} +74 -67
- package/dist/{orchestrator-DDMPR3PY.js → orchestrator-J4BSH4WQ.js} +1288 -1606
- package/dist/{panes-E3RUXOW5.js → panes-BOHAEGYC.js} +4 -4
- package/dist/{panes-IXKLOKA2.js → panes-NXSLDQZ2.js} +10 -11
- package/dist/{paths-L7LGY6RN.js → paths-VSUWNC22.js} +6 -7
- package/dist/reset-TNWTB5LU.js +343 -0
- package/dist/{resources-OTRSN34L.js → resources-4PXNMD5G.js} +29 -22
- package/dist/{run-5DEYH5QK.js → run-D6XJ34CN.js} +132 -132
- package/dist/{share-IHWTLO3M.js → share-2NWMJJEE.js} +27 -27
- package/dist/{skills-IYMXMKW4.js → skills-KR7WON5G.js} +40 -33
- package/dist/{skills-eval-DROHSJAR.js → skills-eval-O2ZNOLDS.js} +81 -77
- package/dist/{skills-inventory-D7X4L4ZX.js → skills-inventory-ZZOUBK7O.js} +23 -22
- package/dist/{slash-commands-QBM7UZ3B.js → slash-commands-ZXPJD64J.js} +47 -37
- package/dist/{steer-Z5DO23FJ.js → steer-XA25PSCS.js} +4 -4
- package/dist/{support-U7QOWY26.js → support-7EMVWYG2.js} +6 -6
- package/dist/{targets-P2FUC4IL.js → targets-OMH2XCSN.js} +50 -49
- package/dist/tasks-IPAGMEIX.js +36 -0
- package/dist/{terminal-lease-YREJ3JX2.js → terminal-lease-C2J3JYRE.js} +4 -4
- package/dist/{tools-5B7RO6MV.js → tools-EFFEAIDP.js} +8 -9
- package/dist/{trace-YMGMUM6A.js → trace-FXMXUZUF.js} +7 -7
- package/dist/uninstall-HALS6BLF.js +407 -0
- package/dist/upgrade-MS72RJEP.js +306 -0
- package/dist/{usage-ME5MPXGX.js → usage-NHG6MCJM.js} +162 -108
- package/dist/{verifiers-BVZ7IWOO.js → verifiers-7AUNVXDY.js} +155 -22
- package/dist/{verify-5K7ZKQFC.js → verify-FWYGPKMR.js} +14 -12
- package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
- package/dist/{wiki-generate-F5W5QTYY.js → wiki-generate-743CIGJW.js} +99 -90
- package/dist/{with-panes-BYOJCLAM.js → with-panes-BDQEWBRT.js} +10 -10
- package/dist/worker/entry.js +72 -68
- package/docs/README.md +3 -2
- package/docs/architecture/acp.md +17 -0
- package/docs/architecture/artifact-placement.md +1 -0
- package/docs/architecture/artifact-versions.md +2 -2
- package/docs/architecture/context-engine.md +4 -0
- package/docs/architecture/dispatch-typed-intent.md +1 -1
- package/docs/architecture/evidence-and-memory.md +1 -1
- package/docs/architecture/middleware-and-components.md +1 -1
- package/docs/architecture/model-catalog.md +21 -10
- package/docs/architecture/observability.md +19 -2
- package/docs/architecture/prompt-envelope-and-tools.md +17 -5
- package/docs/architecture/provider-adapter-cookbook.md +63 -0
- package/docs/architecture/safety-model.md +25 -22
- package/docs/architecture/tui-design.md +1 -1
- package/docs/guide/built-in-agents.md +25 -11
- package/docs/guide/commands-and-modes.md +18 -3
- package/docs/guide/configuration-and-targets.md +100 -10
- package/docs/guide/configuration-reference.md +17 -7
- package/docs/guide/environment-variables.md +4 -2
- package/docs/guide/installation-and-lifecycle.md +37 -4
- package/docs/guide/proactive-memory.md +66 -55
- package/docs/guide/skills-marketplace.md +18 -0
- package/docs/guide/tool-usage.md +78 -3
- package/docs/history/config-knobs-audit.md +2 -2
- package/docs/process/development-pipeline.md +40 -2
- package/docs/process/eval-runner.md +67 -3
- package/docs/process/git-commit-provenance.md +15 -0
- package/docs/process/release-cut-checklist.md +207 -0
- package/docs/process/scientific-validation.md +18 -17
- package/evals/behavioral-machinery-support.ts +1 -0
- package/evals/behavioral-machinery.yaml +1 -1
- package/evals/behavioral-model.yaml +3 -2
- package/package.json +2 -2
- package/skills/README.md +7 -5
- package/skills/coding/ast-grep/SKILL.md +101 -30
- package/skills/coding/ast-grep/evals.md +26 -0
- package/skills/coding/coding-standards/SKILL.md +47 -2
- package/skills/coding/coding-standards/evals.md +23 -0
- package/skills/coding/prototype/SKILL.md +87 -28
- package/skills/coding/prototype/evals.md +19 -0
- package/skills/coding/tdd/SKILL.md +80 -53
- package/skills/coding/tdd/evals.md +20 -0
- package/skills/context/context-handoff/SKILL.md +43 -2
- package/skills/context/context-handoff/evals.md +44 -0
- package/skills/context/context-prime/SKILL.md +45 -15
- package/skills/context/context-prime/evals.md +45 -0
- package/skills/git/branch-closeout/SKILL.md +132 -0
- package/skills/git/branch-closeout/evals.md +133 -0
- package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
- package/skills/git/file-ticket/SKILL.md +77 -63
- package/skills/git/file-ticket/assets/issue-template.md +22 -0
- package/skills/git/file-ticket/evals.md +31 -26
- package/skills/git/file-ticket/references/issue-discovery.md +49 -0
- package/skills/git/fix-issue/SKILL.md +87 -64
- package/skills/git/fix-issue/evals.md +35 -31
- package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
- package/skills/git/resolve-merge-conflicts/SKILL.md +100 -51
- package/skills/git/resolve-merge-conflicts/evals.md +52 -25
- package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
- package/skills/git/ship/SKILL.md +103 -67
- package/skills/git/ship/assets/pr-template.md +21 -0
- package/skills/git/ship/evals.md +44 -28
- package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
- package/skills/git/worktree-create/SKILL.md +80 -50
- package/skills/git/worktree-create/evals.md +40 -33
- package/skills/git/worktree-create/references/worktree-setup.md +62 -66
- package/skills/git/worktree-merge/SKILL.md +112 -65
- package/skills/git/worktree-merge/evals.md +42 -34
- package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
- package/skills/planning/archify/SKILL.md +196 -0
- package/skills/planning/archify/evals.md +65 -0
- package/skills/planning/architecture/SKILL.md +61 -12
- package/skills/planning/architecture/evals.md +65 -0
- package/skills/planning/backlog/SKILL.md +130 -14
- package/skills/planning/backlog/evals.md +142 -0
- package/skills/planning/prd/SKILL.md +47 -6
- package/skills/planning/prd/evals.md +54 -0
- package/skills/planning/product-intent/SKILL.md +57 -2
- package/skills/planning/product-intent/evals.md +70 -0
- package/skills/planning/tech-spec/SKILL.md +53 -2
- package/skills/planning/tech-spec/evals.md +73 -0
- package/skills/registry.yaml +58 -50
- package/skills/remote.yaml +13 -0
- package/skills/research/arxiv-literature/SKILL.md +76 -18
- package/skills/research/arxiv-literature/evals.md +50 -0
- package/skills/research/experiment-protocol/SKILL.md +20 -1
- package/skills/research/experiment-protocol/evals.md +23 -0
- package/skills/research/scientific-debugging/SKILL.md +24 -1
- package/skills/research/scientific-debugging/evals.md +18 -0
- package/skills/research/scientific-modernization/SKILL.md +26 -1
- package/skills/research/scientific-modernization/evals.md +27 -0
- package/skills/skill-marketplace.json +63 -28
- package/skills/workflow/cut-it/SKILL.md +64 -5
- package/skills/workflow/cut-it/evals.md +101 -0
- package/skills/workflow/design-council/SKILL.md +112 -27
- package/skills/workflow/design-council/evals.md +161 -0
- package/skills/workflow/grill-me/SKILL.md +85 -10
- package/skills/workflow/grill-me/evals.md +153 -0
- package/skills/workflow/workflow-distiller/SKILL.md +76 -17
- package/skills/workflow/workflow-distiller/evals.md +118 -0
- package/src/cli/args.ts +0 -8
- package/src/cli/configure-interop.ts +105 -13
- package/src/cli/configure-oauth.ts +57 -0
- package/src/cli/configure-onboarding.ts +980 -0
- package/src/cli/configure-target.ts +594 -0
- package/src/cli/configure.ts +1084 -529
- package/src/cli/context-map.ts +114 -0
- package/src/cli/context.ts +4 -0
- package/src/cli/doctor-state-size.ts +1 -12
- package/src/cli/doctor-validation-contract.ts +28 -0
- package/src/cli/doctor.ts +5 -0
- package/src/cli/evidence-detail.ts +1 -75
- package/src/cli/evidence-inventory.ts +1 -167
- package/src/cli/index.ts +3 -0
- package/src/cli/lifecycle-presenter.ts +436 -0
- package/src/cli/models.ts +10 -2
- package/src/cli/modes/print.ts +5 -1
- package/src/cli/reset.ts +228 -106
- package/src/cli/run.ts +7 -4
- package/src/cli/select.ts +664 -0
- package/src/cli/skills.ts +9 -2
- package/src/cli/targets.ts +3 -0
- package/src/cli/tasks.ts +84 -0
- package/src/cli/uninstall.ts +233 -165
- package/src/cli/upgrade.ts +210 -150
- package/src/cli/usage.ts +92 -27
- package/src/cli/validate-model.ts +3 -3
- package/src/cli/verifiers.ts +147 -1
- package/src/cli/wiki-generate.ts +1 -0
- package/src/core/commit-attribution.ts +41 -1
- package/src/core/config.ts +56 -0
- package/src/core/external-diagnostic.ts +44 -0
- package/src/core/gateway-routing.ts +157 -0
- package/src/core/git-commit-attribution.ts +46 -3
- package/src/core/run-overrides.ts +0 -5
- package/src/core/safe-exec.ts +17 -2
- package/src/core/skill-activation.ts +92 -2
- package/src/core/tool-names.ts +5 -2
- package/src/domains/agents/builtins/architect.md +1 -1
- package/src/domains/agents/builtins/coder.md +1 -1
- package/src/domains/agents/builtins/documenter.md +1 -1
- package/src/domains/agents/builtins/git-master.md +1 -1
- package/src/domains/agents/builtins/provenance.md +7 -7
- package/src/domains/agents/builtins/tester.md +1 -1
- package/src/domains/agents/builtins/verifier.md +2 -2
- package/src/domains/agents/builtins/wiki-writer.md +4 -3
- package/src/domains/agents/builtins/world-knowledge.md +31 -0
- package/src/domains/agents/catalog.ts +1 -1
- package/src/domains/agents/result-contract.ts +70 -0
- package/src/domains/context/extension.ts +31 -7
- package/src/domains/context/refresh.ts +3 -0
- package/src/domains/context/wiki/frontmatter.ts +5 -2
- package/src/domains/context/wiki/generate.ts +6 -0
- package/src/domains/context/wiki/map-seed.ts +589 -0
- package/src/domains/context/wiki/plan.ts +2 -2
- package/src/domains/context/wiki/prompts.ts +43 -0
- package/src/domains/dispatch/active-route-planner.ts +4 -0
- package/src/domains/dispatch/admission.ts +29 -0
- package/src/domains/dispatch/agent-candidates.ts +10 -0
- package/src/domains/dispatch/budget-envelope.ts +86 -1
- package/src/domains/dispatch/capability-match.ts +1 -0
- package/src/domains/dispatch/capacity-lease.ts +17 -0
- package/src/domains/dispatch/code-step.ts +11 -4
- package/src/domains/dispatch/contract.ts +42 -8
- package/src/domains/dispatch/execution-scheduler.ts +2 -0
- package/src/domains/dispatch/extension.ts +184 -56
- package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
- package/src/domains/dispatch/fleet-run.ts +1 -0
- package/src/domains/dispatch/host-verification.ts +114 -13
- package/src/domains/dispatch/intent.ts +28 -18
- package/src/domains/dispatch/orphan-recovery.ts +2 -0
- package/src/domains/dispatch/receipt-integrity.ts +4 -0
- package/src/domains/dispatch/reservation-store.ts +5 -3
- package/src/domains/dispatch/state.ts +15 -2
- package/src/domains/dispatch/types.ts +20 -2
- package/src/domains/dispatch/worker-model-metadata.ts +38 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
- package/src/domains/eval/metrics/token-stream.ts +201 -31
- package/src/domains/eval/metrics/tracked.ts +40 -4
- package/src/domains/eval/runners/clio-run.ts +17 -11
- package/src/domains/eval/runners/context-index.ts +2 -7
- package/src/domains/eval/runners/context-init.ts +3 -6
- package/src/domains/eval/runners/external-command.ts +29 -11
- package/src/domains/eval/schema/suite.ts +28 -0
- package/src/domains/eval/schema/verdict.ts +2 -2
- package/src/domains/eval/suites/resolve.ts +13 -1
- package/src/domains/eval/suites/run.ts +24 -3
- package/src/domains/evidence/build.ts +102 -15
- package/src/domains/evidence/detail.ts +69 -0
- package/src/domains/evidence/eval.ts +13 -1
- package/src/domains/evidence/finish-contract-map.ts +5 -1
- package/src/domains/evidence/inventory.ts +167 -0
- package/src/domains/evidence/store.ts +16 -0
- package/src/domains/evidence/types.ts +12 -0
- package/src/domains/extensions/resources.ts +7 -0
- package/src/domains/interop/registry.ts +6 -2
- package/src/domains/interop/types.ts +4 -0
- package/src/domains/lifecycle/migrations/index.ts +4 -0
- package/src/domains/memory/task-memory-policy.ts +70 -26
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/index.ts +0 -1
- package/src/domains/middleware/marketplace-offer.ts +22 -35
- package/src/domains/middleware/memory-intervention.ts +127 -32
- package/src/domains/middleware/memory-step-endpoint.ts +3 -2
- package/src/domains/middleware/runtime.ts +7 -3
- package/src/domains/middleware/skills-reminder.ts +31 -2
- package/src/domains/mux/detect.ts +3 -6
- package/src/domains/observability/accountability.ts +15 -1
- package/src/domains/observability/compaction-usage.ts +118 -0
- package/src/domains/observability/contract.ts +52 -7
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/evidence-index.ts +10 -0
- package/src/domains/observability/extension.ts +15 -6
- package/src/domains/observability/out-of-turn-usage.ts +52 -21
- package/src/domains/observability/projection.ts +394 -45
- package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
- package/src/domains/prompts/fragments/operating/contract.md +2 -0
- package/src/domains/prompts/fragments/wiki/page.md +8 -0
- package/src/domains/providers/contract.ts +4 -1
- package/src/domains/providers/extension.ts +40 -9
- package/src/domains/providers/model-capabilities.ts +9 -0
- package/src/domains/providers/model-discovery.ts +3 -4
- package/src/domains/providers/model-runtime-capabilities.ts +15 -5
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +48 -26
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
- package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
- package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
- package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
- package/src/domains/providers/support.ts +11 -5
- package/src/domains/providers/target-model-cache.ts +25 -2
- package/src/domains/providers/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/runtime-descriptor.ts +20 -1
- package/src/domains/providers/types/target-descriptor.ts +19 -0
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/skills/install.ts +72 -7
- package/src/domains/resources/skills/loader.ts +7 -0
- package/src/domains/resources/skills/marketplace.ts +63 -11
- package/src/domains/safety/action-classifier.ts +7 -0
- package/src/domains/safety/autonomy.ts +15 -0
- package/src/domains/safety/default-path-policy.ts +2 -0
- package/src/domains/safety/finish-contract-registration.ts +29 -14
- package/src/domains/safety/finish-contract.ts +252 -40
- package/src/domains/safety/index.ts +21 -1
- package/src/domains/safety/path-policy.ts +1 -1
- package/src/domains/safety/policy-engine.ts +60 -17
- package/src/domains/safety/protected-artifacts.ts +191 -88
- package/src/domains/safety/rigor.ts +53 -39
- package/src/domains/safety/run-effects.ts +2 -22
- package/src/domains/safety/skill-authority.ts +55 -0
- package/src/domains/safety/validation-contract.ts +388 -0
- package/src/domains/session/archive-readers.ts +10 -1
- package/src/domains/session/compaction/compact.ts +72 -22
- package/src/domains/session/decision-board.ts +101 -2
- package/src/domains/session/entries.ts +50 -7
- package/src/domains/session/extension.ts +4 -4
- package/src/domains/session/handoff.ts +2 -1
- package/src/domains/session/manager.ts +2 -3
- package/src/domains/session/task-board.ts +14 -1
- package/src/domains/session/tree/fork.ts +1 -2
- package/src/domains/session/tree/navigator.ts +1 -1
- package/src/domains/session/usage.ts +3 -3
- package/src/domains/user-tasks/acceptance.ts +56 -0
- package/src/domains/user-tasks/active-acceptance.ts +40 -0
- package/src/domains/user-tasks/store.ts +34 -3
- package/src/engine/acp/adapter.ts +24 -6
- package/src/engine/acp/server.ts +21 -4
- package/src/engine/acp/transport.ts +53 -8
- package/src/engine/acp/types.ts +4 -0
- package/src/engine/agent.ts +13 -3
- package/src/engine/ai.ts +26 -8
- package/src/engine/antigravity/subprocess-runtime.ts +386 -120
- package/src/engine/api-registry.ts +3 -0
- package/src/engine/apis/ollama-native.ts +15 -0
- package/src/engine/apis/openai-completions.ts +117 -14
- package/src/engine/claude/subprocess-runtime.ts +107 -60
- package/src/engine/external-subprocess.ts +122 -6
- package/src/entry/background-model-metadata.ts +18 -0
- package/src/entry/compaction-prompt.ts +57 -0
- package/src/entry/orchestrator.ts +416 -218
- package/src/entry/task-memory-lifecycle.ts +35 -0
- package/src/interactive/chat-loop-messages.ts +13 -4
- package/src/interactive/chat-loop.ts +65 -2
- package/src/interactive/chat-renderer.ts +1 -0
- package/src/interactive/cost-overlay.ts +26 -2
- package/src/interactive/dispatch-board.ts +46 -717
- package/src/interactive/fleet-run-preview.ts +2 -1
- package/src/interactive/interactive-application.ts +3 -2
- package/src/interactive/interactive-presentation.ts +55 -12
- package/src/interactive/interactive-slash-runtime.ts +4 -2
- package/src/interactive/oracle.ts +5 -2
- package/src/interactive/overlays/fleet-run-approval.ts +3 -2
- package/src/interactive/overlays/message-picker.ts +2 -2
- package/src/interactive/overlays/settings.ts +2 -2
- package/src/interactive/overlays/tree-selector.ts +2 -2
- package/src/interactive/renderers/branch-summary.ts +1 -1
- package/src/interactive/renderers/worker-entry.ts +32 -0
- package/src/interactive/slash-autocomplete.ts +4 -6
- package/src/interactive/slash-commands.ts +49 -45
- package/src/interactive/slash-spec.ts +28 -0
- package/src/interactive/theme/labels.ts +19 -13
- package/src/interactive/turn-context.ts +9 -5
- package/src/interactive/turn-recovery.ts +8 -0
- package/src/interactive/turn-runtime.ts +27 -11
- package/src/interactive/turn-state.ts +7 -0
- package/src/interactive/view/artifacts.ts +2 -0
- package/src/interactive/worker-receipts.ts +1 -0
- package/src/interactive/worker-stream.ts +13 -4
- package/src/tools/bootstrap.ts +4 -0
- package/src/tools/builtin-tool-catalog.ts +31 -0
- package/src/tools/compete-worktrees.ts +7 -1
- package/src/tools/context/index.ts +30 -9
- package/src/tools/core-bootstrap.ts +16 -0
- package/src/tools/decide.ts +136 -0
- package/src/tools/dispatch-admission.ts +21 -0
- package/src/tools/dispatch-arguments.ts +1 -0
- package/src/tools/dispatch-event-text.ts +10 -0
- package/src/tools/dispatch-plan.ts +6 -2
- package/src/tools/dispatch-runner.ts +27 -1
- package/src/tools/dispatch-types.ts +6 -0
- package/src/tools/evidence.ts +96 -0
- package/src/tools/limitation.ts +76 -0
- package/src/tools/policy.ts +9 -0
- package/src/tools/presentation.ts +3 -0
- package/src/tools/registry.ts +11 -5
- package/src/tools/result-shaping.ts +17 -5
- package/src/tools/task-worktree.ts +13 -3
- package/src/tools/tasks.ts +10 -1
- package/src/tools/verify/authoring.ts +170 -83
- package/src/tools/verify/catalog.ts +122 -5
- package/src/tools/verify/index.ts +2 -1
- package/src/tools/verify/numeric.ts +298 -0
- package/src/tools/verify/perf.ts +143 -0
- package/src/tools/verify/scripts.ts +229 -2
- package/src/tools/worker-evidence.ts +3 -1
- package/src/worker/spec-contract.ts +4 -0
- package/dist/chunk-2Z2IKEXI.js +0 -1554
- package/dist/chunk-RVG5JXAL.js +0 -41
- package/dist/chunk-T56WDKA5.js +0 -183
- package/dist/chunk-VN3SHNBN.js +0 -313
- package/dist/chunk-VPKWYKEY.js +0 -169
- package/dist/reset-OAQP3W4O.js +0 -230
- package/dist/uninstall-N34PCTGJ.js +0 -331
- package/dist/upgrade-PXK3S2YM.js +0 -325
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import { extractReasoningTokens } from "../../session/context-accounting.js";
|
|
1
2
|
import type { EvalTokenMetricsV4 } from "../schema/artifact.js";
|
|
2
3
|
|
|
3
4
|
export interface EvalTokenStreamUsage {
|
|
4
5
|
/**
|
|
5
6
|
* True when the stream carried at least one completed assistant message
|
|
6
|
-
* with
|
|
7
|
+
* with observed token facts. False means this runner observed no token
|
|
7
8
|
* accounting at all, which is not the same as a run that cost nothing.
|
|
8
9
|
*/
|
|
9
10
|
measured: boolean;
|
|
11
|
+
/** Known token subtotals; missing failed-call coverage is reported separately. */
|
|
10
12
|
tokens: EvalTokenMetricsV4;
|
|
11
13
|
costUsd: number;
|
|
14
|
+
provider: EvalProviderObservation;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export interface EvalTokenUsageFold {
|
|
@@ -21,6 +24,7 @@ export const UNMEASURED_TOKEN_USAGE: EvalTokenStreamUsage = {
|
|
|
21
24
|
measured: false,
|
|
22
25
|
tokens: { input: 0, output: 0, total: 0, cacheRead: 0, cacheWrite: 0 },
|
|
23
26
|
costUsd: 0,
|
|
27
|
+
provider: emptyProviderObservation(),
|
|
24
28
|
};
|
|
25
29
|
|
|
26
30
|
/**
|
|
@@ -30,8 +34,12 @@ export const UNMEASURED_TOKEN_USAGE: EvalTokenStreamUsage = {
|
|
|
30
34
|
* carrying a completed message's usage exactly once; `turn_end` republishes
|
|
31
35
|
* the same assistant message and `agent_end` republishes its segment's
|
|
32
36
|
* summary, so counting those too would multiply a run's reported cost. Every
|
|
33
|
-
*
|
|
34
|
-
*
|
|
37
|
+
* reported call counts, including known errored-call spend: a headless turn
|
|
38
|
+
* spans several segments and its cost is their sum. Provider facts and the
|
|
39
|
+
* errored known share are folded here too, from the same events before truncation.
|
|
40
|
+
* Failed all-zero usage is ambiguous (adapters synthesize it), so it cannot
|
|
41
|
+
* establish measured usage. Unknown failed spend is retained as missing coverage,
|
|
42
|
+
* never subtracted from inclusive totals or used to change task pass policy.
|
|
35
43
|
*
|
|
36
44
|
* Folding as the stream arrives is what makes the count trustworthy: the
|
|
37
45
|
* operator-facing stdout artifact keeps only a bounded head and tail, so a
|
|
@@ -42,6 +50,7 @@ export function createTokenUsageFold(): EvalTokenUsageFold {
|
|
|
42
50
|
let costUsd = 0;
|
|
43
51
|
let measured = false;
|
|
44
52
|
let pending = "";
|
|
53
|
+
const provider = emptyProviderObservation();
|
|
45
54
|
|
|
46
55
|
const consume = (line: string): void => {
|
|
47
56
|
if (line.trim().length === 0) return;
|
|
@@ -51,23 +60,16 @@ export function createTokenUsageFold(): EvalTokenUsageFold {
|
|
|
51
60
|
} catch {
|
|
52
61
|
return;
|
|
53
62
|
}
|
|
54
|
-
if (!isRecord(event)
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
const usage =
|
|
58
|
-
if (usage ===
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const totalTokens = numberField(usage, "totalTokens");
|
|
65
|
-
tokens.input += input;
|
|
66
|
-
tokens.output += output;
|
|
67
|
-
tokens.cacheRead += cacheRead;
|
|
68
|
-
tokens.cacheWrite += cacheWrite;
|
|
69
|
-
tokens.total += totalTokens > 0 ? totalTokens : input + output + cacheRead + cacheWrite;
|
|
70
|
-
if (isRecord(usage.cost)) costUsd += numberField(usage.cost, "total");
|
|
63
|
+
if (!isRecord(event)) return;
|
|
64
|
+
observeProviderEvent(provider, event);
|
|
65
|
+
if (event.type !== "message_end" || !isRecord(event.message) || event.message.role !== "assistant") return;
|
|
66
|
+
const usage = readMessageUsage(event.message);
|
|
67
|
+
if (usage === null) return;
|
|
68
|
+
if (Object.keys(usage.tokens).length > 0) {
|
|
69
|
+
measured = true;
|
|
70
|
+
for (const field of TOKEN_FIELDS) tokens[field] += usage.tokens[field] ?? 0;
|
|
71
|
+
}
|
|
72
|
+
costUsd += usage.costUsd ?? 0;
|
|
71
73
|
};
|
|
72
74
|
|
|
73
75
|
return {
|
|
@@ -85,7 +87,7 @@ export function createTokenUsageFold(): EvalTokenUsageFold {
|
|
|
85
87
|
consume(pending.replace(/\r$/u, ""));
|
|
86
88
|
pending = "";
|
|
87
89
|
}
|
|
88
|
-
return { measured, tokens: { ...tokens }, costUsd };
|
|
90
|
+
return { measured, tokens: { ...tokens }, costUsd, provider: structuredClone(provider) };
|
|
89
91
|
},
|
|
90
92
|
};
|
|
91
93
|
}
|
|
@@ -101,6 +103,7 @@ export function addTokenStreamUsage(left: EvalTokenStreamUsage, right: EvalToken
|
|
|
101
103
|
cacheWrite: left.tokens.cacheWrite + right.tokens.cacheWrite,
|
|
102
104
|
},
|
|
103
105
|
costUsd: left.costUsd + right.costUsd,
|
|
106
|
+
provider: addProviderObservations(left.provider, right.provider),
|
|
104
107
|
};
|
|
105
108
|
}
|
|
106
109
|
|
|
@@ -110,21 +113,188 @@ export function addTokenStreamUsage(left: EvalTokenStreamUsage, right: EvalToken
|
|
|
110
113
|
* read an absence as a zero-cost run.
|
|
111
114
|
*/
|
|
112
115
|
export function tokenMetricEntries(usage: EvalTokenStreamUsage): Record<string, number | boolean> {
|
|
113
|
-
if (!usage.measured) return { "tokens.measured": false };
|
|
114
116
|
return {
|
|
115
|
-
|
|
116
|
-
"tokens.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
...providerMetricEntries(usage.provider),
|
|
118
|
+
"tokens.measured": usage.measured,
|
|
119
|
+
...(usage.measured
|
|
120
|
+
? {
|
|
121
|
+
"tokens.input": usage.tokens.input,
|
|
122
|
+
"tokens.output": usage.tokens.output,
|
|
123
|
+
"tokens.total": usage.tokens.total,
|
|
124
|
+
"tokens.cacheRead": usage.tokens.cacheRead,
|
|
125
|
+
"tokens.cacheWrite": usage.tokens.cacheWrite,
|
|
126
|
+
}
|
|
127
|
+
: {}),
|
|
121
128
|
...(usage.costUsd > 0 ? { "cost.usd": usage.costUsd } : {}),
|
|
122
129
|
};
|
|
123
130
|
}
|
|
124
131
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
const TOKEN_FIELDS = ["input", "output", "total", "cacheRead", "cacheWrite"] as const;
|
|
133
|
+
const STOP_REASONS = ["stop", "toolUse", "length", "error", "aborted", "other"] as const;
|
|
134
|
+
const RETRY_PHASES = {
|
|
135
|
+
scheduled: "retryScheduled",
|
|
136
|
+
retrying: "retryStarted",
|
|
137
|
+
cancelled: "retryCancelled",
|
|
138
|
+
exhausted: "retryExhausted",
|
|
139
|
+
recovered: "retryRecovered",
|
|
140
|
+
} as const;
|
|
141
|
+
type StopReason = (typeof STOP_REASONS)[number];
|
|
142
|
+
type RetryPhase = keyof typeof RETRY_PHASES;
|
|
143
|
+
|
|
144
|
+
interface EvalProviderObservation {
|
|
145
|
+
measured: boolean;
|
|
146
|
+
stops: Record<StopReason, number>;
|
|
147
|
+
retries: Record<RetryPhase, number>;
|
|
148
|
+
errorUsageObservedCalls: number;
|
|
149
|
+
errorUsageUnobservedCalls: number;
|
|
150
|
+
errorUsageIncompleteCalls: number;
|
|
151
|
+
errorCostUnobservedCalls: number;
|
|
152
|
+
errorReasoningUnobservedCalls: number;
|
|
153
|
+
errorReasoningTokens: number | null;
|
|
154
|
+
errorTokens: Partial<EvalTokenMetricsV4>;
|
|
155
|
+
errorCostUsd: number | null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
interface MessageUsageObservation {
|
|
159
|
+
reasoningTokens: number | null;
|
|
160
|
+
tokens: Partial<EvalTokenMetricsV4>;
|
|
161
|
+
costUsd: number | null;
|
|
162
|
+
completeTokens: boolean;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function emptyProviderObservation(): EvalProviderObservation {
|
|
166
|
+
return {
|
|
167
|
+
measured: false,
|
|
168
|
+
stops: { stop: 0, toolUse: 0, length: 0, error: 0, aborted: 0, other: 0 },
|
|
169
|
+
retries: { scheduled: 0, retrying: 0, cancelled: 0, exhausted: 0, recovered: 0 },
|
|
170
|
+
errorUsageObservedCalls: 0,
|
|
171
|
+
errorUsageUnobservedCalls: 0,
|
|
172
|
+
errorUsageIncompleteCalls: 0,
|
|
173
|
+
errorCostUnobservedCalls: 0,
|
|
174
|
+
errorReasoningUnobservedCalls: 0,
|
|
175
|
+
errorReasoningTokens: null,
|
|
176
|
+
errorTokens: {},
|
|
177
|
+
errorCostUsd: null,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Same usage interpretation for inclusive totals and their known errored share. */
|
|
182
|
+
function readMessageUsage(message: Record<string, unknown>): MessageUsageObservation | null {
|
|
183
|
+
if (!isRecord(message.usage)) return null;
|
|
184
|
+
const usage = message.usage;
|
|
185
|
+
const failed = message.stopReason === "error" || message.stopReason === "aborted";
|
|
186
|
+
const raw: Partial<EvalTokenMetricsV4> = {};
|
|
187
|
+
for (const field of TOKEN_FIELDS) {
|
|
188
|
+
const value = nonNegativeNumber(usage[field === "total" ? "totalTokens" : field]);
|
|
189
|
+
// Failed adapter objects can initialize each absent field to zero even
|
|
190
|
+
// when another field is reported. Keep only attributable positive facts.
|
|
191
|
+
if (value !== null && (!failed || value > 0)) raw[field] = value;
|
|
192
|
+
}
|
|
193
|
+
const cost = isRecord(usage.cost) ? nonNegativeNumber(usage.cost.total) : null;
|
|
194
|
+
// Zero prices are also initialized by adapters without pricing evidence.
|
|
195
|
+
const costUsd = cost !== null && cost > 0 ? cost : null;
|
|
196
|
+
|
|
197
|
+
// The compat adapter can synthesize the root reasoningTokens alias from
|
|
198
|
+
// thinking text without marking it estimated. Preserve explicit provider
|
|
199
|
+
// detail through the shared reader, but never promote that ambiguous alias.
|
|
200
|
+
// Normalized zero reasoning can also mean omitted provider detail.
|
|
201
|
+
const reportedReasoning = extractReasoningTokens({ ...usage, reasoningTokens: undefined });
|
|
202
|
+
const reasoningTokens = reportedReasoning !== null && reportedReasoning > 0 ? reportedReasoning : null;
|
|
203
|
+
const tokens = raw;
|
|
204
|
+
if (Object.keys(tokens).length === 0 && costUsd === null && reasoningTokens === null) return null;
|
|
205
|
+
const completeTokens = Object.keys(tokens).length === TOKEN_FIELDS.length;
|
|
206
|
+
if (Object.keys(tokens).length > 0 && !(tokens.total !== undefined && tokens.total > 0)) {
|
|
207
|
+
// This is a known subtotal when fields are missing; coverage stays incomplete.
|
|
208
|
+
tokens.total = (tokens.input ?? 0) + (tokens.output ?? 0) + (tokens.cacheRead ?? 0) + (tokens.cacheWrite ?? 0);
|
|
209
|
+
}
|
|
210
|
+
return { tokens, costUsd, completeTokens, reasoningTokens };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function observeProviderEvent(provider: EvalProviderObservation, event: Record<string, unknown>): void {
|
|
214
|
+
if (event.type === "retry_status" && isRecord(event.status)) {
|
|
215
|
+
const phase = event.status.phase;
|
|
216
|
+
if (typeof phase === "string" && Object.hasOwn(RETRY_PHASES, phase)) {
|
|
217
|
+
provider.measured = true;
|
|
218
|
+
provider.retries[phase as RetryPhase] += 1;
|
|
219
|
+
}
|
|
220
|
+
// Waiting frames are countdown ticks, not attempts. Attempt numbers may
|
|
221
|
+
// restart in another chain, so neither frames nor attempts are deduplicated.
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (event.type !== "message_end" || !isRecord(event.message) || event.message.role !== "assistant") return;
|
|
225
|
+
const reason = event.message.stopReason;
|
|
226
|
+
if (typeof reason !== "string" || reason.length === 0 || reason === "pending") return;
|
|
227
|
+
provider.measured = true;
|
|
228
|
+
const stop = STOP_REASONS.includes(reason as StopReason) ? (reason as StopReason) : "other";
|
|
229
|
+
provider.stops[stop] += 1;
|
|
230
|
+
if (reason !== "error") return;
|
|
231
|
+
const usage = readMessageUsage(event.message);
|
|
232
|
+
if (usage === null) provider.errorUsageUnobservedCalls += 1;
|
|
233
|
+
else {
|
|
234
|
+
provider.errorUsageObservedCalls += 1;
|
|
235
|
+
for (const field of TOKEN_FIELDS) {
|
|
236
|
+
const value = usage.tokens[field];
|
|
237
|
+
if (value !== undefined) provider.errorTokens[field] = (provider.errorTokens[field] ?? 0) + value;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (usage?.completeTokens !== true) provider.errorUsageIncompleteCalls += 1;
|
|
241
|
+
if (usage?.costUsd === undefined || usage.costUsd === null) provider.errorCostUnobservedCalls += 1;
|
|
242
|
+
else provider.errorCostUsd = (provider.errorCostUsd ?? 0) + usage.costUsd;
|
|
243
|
+
if (usage?.reasoningTokens === undefined || usage.reasoningTokens === null)
|
|
244
|
+
provider.errorReasoningUnobservedCalls += 1;
|
|
245
|
+
else provider.errorReasoningTokens = (provider.errorReasoningTokens ?? 0) + usage.reasoningTokens;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function addProviderObservations(
|
|
249
|
+
left: EvalProviderObservation,
|
|
250
|
+
right: EvalProviderObservation,
|
|
251
|
+
): EvalProviderObservation {
|
|
252
|
+
const result = emptyProviderObservation();
|
|
253
|
+
result.measured = left.measured || right.measured;
|
|
254
|
+
for (const reason of STOP_REASONS) result.stops[reason] = left.stops[reason] + right.stops[reason];
|
|
255
|
+
for (const phase of Object.keys(RETRY_PHASES) as RetryPhase[])
|
|
256
|
+
result.retries[phase] = left.retries[phase] + right.retries[phase];
|
|
257
|
+
result.errorUsageObservedCalls = left.errorUsageObservedCalls + right.errorUsageObservedCalls;
|
|
258
|
+
result.errorUsageUnobservedCalls = left.errorUsageUnobservedCalls + right.errorUsageUnobservedCalls;
|
|
259
|
+
result.errorUsageIncompleteCalls = left.errorUsageIncompleteCalls + right.errorUsageIncompleteCalls;
|
|
260
|
+
result.errorCostUnobservedCalls = left.errorCostUnobservedCalls + right.errorCostUnobservedCalls;
|
|
261
|
+
result.errorReasoningUnobservedCalls = left.errorReasoningUnobservedCalls + right.errorReasoningUnobservedCalls;
|
|
262
|
+
if (left.errorReasoningTokens !== null || right.errorReasoningTokens !== null)
|
|
263
|
+
result.errorReasoningTokens = (left.errorReasoningTokens ?? 0) + (right.errorReasoningTokens ?? 0);
|
|
264
|
+
for (const field of TOKEN_FIELDS) {
|
|
265
|
+
if (left.errorTokens[field] !== undefined || right.errorTokens[field] !== undefined) {
|
|
266
|
+
result.errorTokens[field] = (left.errorTokens[field] ?? 0) + (right.errorTokens[field] ?? 0);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (left.errorCostUsd !== null || right.errorCostUsd !== null)
|
|
270
|
+
result.errorCostUsd = (left.errorCostUsd ?? 0) + (right.errorCostUsd ?? 0);
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Provider observations are independent of task success and receipt billing. */
|
|
275
|
+
function providerMetricEntries(provider: EvalProviderObservation): Record<string, number | boolean> {
|
|
276
|
+
if (!provider.measured) return { "provider.measured": false };
|
|
277
|
+
const metrics: Record<string, number | boolean> = { "provider.measured": true };
|
|
278
|
+
for (const reason of STOP_REASONS) metrics[`provider.stopReason.${reason}`] = provider.stops[reason];
|
|
279
|
+
for (const phase of Object.keys(RETRY_PHASES) as RetryPhase[])
|
|
280
|
+
metrics[`provider.${RETRY_PHASES[phase]}`] = provider.retries[phase];
|
|
281
|
+
if (provider.stops.error === 0) return metrics;
|
|
282
|
+
metrics["provider.errorUsageObservedCalls"] = provider.errorUsageObservedCalls;
|
|
283
|
+
metrics["provider.errorUsageUnobservedCalls"] = provider.errorUsageUnobservedCalls;
|
|
284
|
+
metrics["provider.errorUsageIncompleteCalls"] = provider.errorUsageIncompleteCalls;
|
|
285
|
+
metrics["provider.errorCostUnobservedCalls"] = provider.errorCostUnobservedCalls;
|
|
286
|
+
metrics["provider.errorReasoningUnobservedCalls"] = provider.errorReasoningUnobservedCalls;
|
|
287
|
+
if (provider.errorReasoningTokens !== null) metrics["provider.errorReasoningTokens"] = provider.errorReasoningTokens;
|
|
288
|
+
for (const field of TOKEN_FIELDS) {
|
|
289
|
+
const value = provider.errorTokens[field];
|
|
290
|
+
if (value !== undefined) metrics[`provider.errorTokens.${field}`] = value;
|
|
291
|
+
}
|
|
292
|
+
if (provider.errorCostUsd !== null) metrics["provider.errorCostUsd"] = provider.errorCostUsd;
|
|
293
|
+
return metrics;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function nonNegativeNumber(value: unknown): number | null {
|
|
297
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
128
298
|
}
|
|
129
299
|
|
|
130
300
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
@@ -47,6 +47,7 @@ export interface BuildEvalTrackedMetricsInput {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
interface AssistantCall {
|
|
50
|
+
timestamp: string | null;
|
|
50
51
|
payload: Record<string, unknown>;
|
|
51
52
|
promptCache: Record<string, unknown> | null;
|
|
52
53
|
backend: Record<string, unknown> | null;
|
|
@@ -59,6 +60,28 @@ interface NumericReading {
|
|
|
59
60
|
source: EvalMetricSource;
|
|
60
61
|
}
|
|
61
62
|
|
|
63
|
+
/**
|
|
64
|
+
* The session ledger and stdout fold observe the same assistant calls on the
|
|
65
|
+
* native runner. Prefer the durable calls (including their richer timing and
|
|
66
|
+
* cache facts), with stdout as a fallback only when no durable calls exist.
|
|
67
|
+
* Keep non-call entries in either case: compaction is billed but not streamed.
|
|
68
|
+
* Counts are observations, NOT identities or evidence of matching coverage;
|
|
69
|
+
* partial/mixed ledgers cannot be unioned without a shared call identity.
|
|
70
|
+
*/
|
|
71
|
+
export function selectEvalLedgerEntries(
|
|
72
|
+
durable: ReadonlyArray<SessionEntry>,
|
|
73
|
+
stream: ReadonlyArray<SessionEntry>,
|
|
74
|
+
): { entries: ReadonlyArray<SessionEntry>; source: "session" | "stream"; sessionCalls: number; streamCalls: number } {
|
|
75
|
+
const sessionCalls = assistantCalls(durable).length;
|
|
76
|
+
const streamCalls = assistantCalls(stream).length;
|
|
77
|
+
return {
|
|
78
|
+
entries: sessionCalls > 0 ? durable : [...durable, ...stream],
|
|
79
|
+
source: sessionCalls > 0 ? "session" : "stream",
|
|
80
|
+
sessionCalls,
|
|
81
|
+
streamCalls,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
62
85
|
/** Read every isolated session ledger and its prompt manifest before cleanup. */
|
|
63
86
|
export async function readEvalLedgerSnapshot(stateDir: string): Promise<EvalLedgerSnapshot> {
|
|
64
87
|
const refs = await listSessionLedgerRefs(stateDir);
|
|
@@ -175,7 +198,7 @@ export function emptyEvalTrackedMetrics(source: EvalMetricSource = "estimated"):
|
|
|
175
198
|
reasoningTokens: { value: null, source },
|
|
176
199
|
toolCalls: zero(),
|
|
177
200
|
toolErrors: zero(),
|
|
178
|
-
ttftMsFirstCall:
|
|
201
|
+
ttftMsFirstCall: { value: null, source: "estimated" },
|
|
179
202
|
wallClockMs: zero(),
|
|
180
203
|
contextTokensAtEnd: zero(),
|
|
181
204
|
compactions: zero(),
|
|
@@ -192,6 +215,7 @@ function assistantCalls(entries: ReadonlyArray<SessionEntry>): AssistantCall[] {
|
|
|
192
215
|
if (promptCache === null && timing === null && usage === null) return [];
|
|
193
216
|
return [
|
|
194
217
|
{
|
|
218
|
+
timestamp: entry.payload.timestampEstimated === true ? null : entry.timestamp,
|
|
195
219
|
payload: entry.payload,
|
|
196
220
|
promptCache,
|
|
197
221
|
backend: promptCache === null ? null : recordField(promptCache, "backend"),
|
|
@@ -260,10 +284,22 @@ function reasoningMetric(
|
|
|
260
284
|
return measured ? { value: total, source: "ledger" } : { value: null, source: "estimated" };
|
|
261
285
|
}
|
|
262
286
|
|
|
263
|
-
function firstCallTtft(calls: ReadonlyArray<AssistantCall>):
|
|
264
|
-
|
|
287
|
+
function firstCallTtft(calls: ReadonlyArray<AssistantCall>): EvalSourcedNullableNumber {
|
|
288
|
+
// Session directories are read by name, not by call time. Select without
|
|
289
|
+
// reordering the evidence or borrowing a later call's available timing.
|
|
290
|
+
let first: AssistantCall | undefined;
|
|
291
|
+
let firstAt = Number.POSITIVE_INFINITY;
|
|
292
|
+
for (const call of calls) {
|
|
293
|
+
if (call.timestamp === null) return { value: null, source: "estimated" };
|
|
294
|
+
const at = Date.parse(call.timestamp);
|
|
295
|
+
if (!Number.isFinite(at)) return { value: null, source: "estimated" };
|
|
296
|
+
if (at < firstAt) {
|
|
297
|
+
first = call;
|
|
298
|
+
firstAt = at;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
265
301
|
const value = first?.timing === null || first?.timing === undefined ? null : nonNegativeNumber(first.timing.ttftMs);
|
|
266
|
-
return value === null ? { value:
|
|
302
|
+
return value === null ? { value: null, source: "estimated" } : { value, source: "ledger" };
|
|
267
303
|
}
|
|
268
304
|
|
|
269
305
|
function wallClockMetric(receipt: RunReceipt | null, fallback: number): EvalSourcedNumber {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
2
2
|
import { normalizeClioCoderEventRecord } from "../../../core/naming-events.js";
|
|
3
|
-
import { shellQuote } from "../../../core/shell-quote.js";
|
|
4
3
|
import { clioStateDir } from "../../../core/xdg.js";
|
|
5
4
|
import {
|
|
6
5
|
evidenceMetricsFromReceipt,
|
|
@@ -22,19 +21,23 @@ export async function runClioRunRunner(
|
|
|
22
21
|
readObservation?: { allowedPaths: string[]; decoyPaths: string[] },
|
|
23
22
|
): Promise<EvalRunnerOutput> {
|
|
24
23
|
const prompt = runner.prompt ?? "";
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
// Spawned as an argv, not a shell line: the task timeout has to reach the
|
|
25
|
+
// Clio process itself so the receipt it seals and the exit code this
|
|
26
|
+
// runner reports describe the same ending. See runShellCommand.
|
|
27
|
+
const args: [string, ...string[]] = [
|
|
28
|
+
process.execPath,
|
|
29
|
+
clioEntry,
|
|
27
30
|
"run",
|
|
28
31
|
"--json",
|
|
29
|
-
...(runner.agent === undefined ? [] : ["--agent",
|
|
32
|
+
...(runner.agent === undefined ? [] : ["--agent", runner.agent]),
|
|
30
33
|
"--target",
|
|
31
|
-
|
|
32
|
-
...(target.model === undefined ? [] : ["--model",
|
|
33
|
-
...(target.thinking === undefined ? [] : ["--thinking",
|
|
34
|
+
target.id,
|
|
35
|
+
...(target.model === undefined ? [] : ["--model", target.model]),
|
|
36
|
+
...(target.thinking === undefined ? [] : ["--thinking", target.thinking]),
|
|
34
37
|
...(runner.autonomy === undefined ? [] : ["--autonomy", runner.autonomy]),
|
|
35
|
-
|
|
38
|
+
prompt,
|
|
36
39
|
];
|
|
37
|
-
const result = await runShellCommand(
|
|
40
|
+
const result = await runShellCommand(args, cwd, runner.timeoutMs ?? timeoutMs, env);
|
|
38
41
|
// Usage is folded from the live stream, not from the bounded stdout
|
|
39
42
|
// artifact: a verbose run's `message_end` events do not survive truncation.
|
|
40
43
|
const tokens = result.usage;
|
|
@@ -149,7 +152,7 @@ interface BehavioralToolTerminal {
|
|
|
149
152
|
* bounded counters against the suite's explicit public allowlist and decoy
|
|
150
153
|
* list; they never become behavioral fact values or evidence excerpts.
|
|
151
154
|
*/
|
|
152
|
-
function toolBehaviorMetricEntriesFromJsonl(
|
|
155
|
+
export function toolBehaviorMetricEntriesFromJsonl(
|
|
153
156
|
stdout: string,
|
|
154
157
|
cwd: string,
|
|
155
158
|
readObservation?: { allowedPaths: string[]; decoyPaths: string[] },
|
|
@@ -201,16 +204,19 @@ function toolBehaviorMetricEntriesFromJsonl(
|
|
|
201
204
|
|
|
202
205
|
const terminals = canonicalFinishes.length > 0 ? canonicalFinishes : executionEnds;
|
|
203
206
|
const calls = new Map<string, number>();
|
|
207
|
+
const succeeded = new Map<string, number>();
|
|
204
208
|
const blocked = new Map<string, number>();
|
|
205
209
|
for (const terminal of terminals) {
|
|
206
210
|
const tool = metricToolName(terminal.tool);
|
|
207
211
|
calls.set(tool, (calls.get(tool) ?? 0) + 1);
|
|
212
|
+
if (terminal.outcome === "ok") succeeded.set(tool, (succeeded.get(tool) ?? 0) + 1);
|
|
208
213
|
if (terminal.outcome === "blocked") blocked.set(tool, (blocked.get(tool) ?? 0) + 1);
|
|
209
214
|
}
|
|
210
|
-
const namedTools = new Set(["bash", "dispatch", "read", ...calls.keys(), ...blocked.keys()]);
|
|
215
|
+
const namedTools = new Set(["bash", "dispatch", "read", ...calls.keys(), ...succeeded.keys(), ...blocked.keys()]);
|
|
211
216
|
const entries: Record<string, number> = { "tools.read.distinctPaths": readPaths.size };
|
|
212
217
|
for (const tool of [...namedTools].sort()) {
|
|
213
218
|
entries[`tools.calls.${tool}`] = calls.get(tool) ?? 0;
|
|
219
|
+
entries[`tools.succeeded.${tool}`] = succeeded.get(tool) ?? 0;
|
|
214
220
|
entries[`tools.blocked.${tool}`] = blocked.get(tool) ?? 0;
|
|
215
221
|
}
|
|
216
222
|
if (readObservation !== undefined) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { shellQuote } from "../../../core/shell-quote.js";
|
|
2
1
|
import type { EvalSuiteTargetV2 } from "../schema/suite.js";
|
|
3
2
|
import { type EvalRunnerOutput, runShellCommand } from "./external-command.js";
|
|
4
3
|
|
|
@@ -9,12 +8,8 @@ export async function runContextIndexRunner(
|
|
|
9
8
|
target: EvalSuiteTargetV2,
|
|
10
9
|
env?: NodeJS.ProcessEnv,
|
|
11
10
|
): Promise<EvalRunnerOutput> {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
cwd,
|
|
15
|
-
timeoutMs,
|
|
16
|
-
env,
|
|
17
|
-
);
|
|
11
|
+
const args: [string, ...string[]] = [process.execPath, clioEntry, "context", "index", "--json"];
|
|
12
|
+
const result = await runShellCommand(args, cwd, timeoutMs, env);
|
|
18
13
|
const parsed = parseContextIndexOutput(result.stdout);
|
|
19
14
|
return {
|
|
20
15
|
assignmentId: null,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { existsSync, statSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { shellQuote } from "../../../core/shell-quote.js";
|
|
4
3
|
import type { EvalRunnerV2, EvalSuiteTargetV2 } from "../schema/suite.js";
|
|
5
4
|
import { type EvalRunnerOutput, runShellCommand } from "./external-command.js";
|
|
6
5
|
|
|
@@ -13,7 +12,7 @@ export async function runContextInitRunner(
|
|
|
13
12
|
env?: NodeJS.ProcessEnv,
|
|
14
13
|
): Promise<EvalRunnerOutput> {
|
|
15
14
|
const extraArgs = runner.args ?? [];
|
|
16
|
-
const
|
|
15
|
+
const args: [string, ...string[]] = [
|
|
17
16
|
process.execPath,
|
|
18
17
|
clioEntry,
|
|
19
18
|
"context",
|
|
@@ -25,10 +24,8 @@ export async function runContextInitRunner(
|
|
|
25
24
|
...(target.model === undefined ? [] : ["--model", target.model]),
|
|
26
25
|
...(target.thinking === undefined ? [] : ["--thinking", target.thinking]),
|
|
27
26
|
...extraArgs,
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
.join(" ");
|
|
31
|
-
const result = await runShellCommand(command, cwd, runner.timeoutMs ?? timeoutMs, env);
|
|
27
|
+
];
|
|
28
|
+
const result = await runShellCommand(args, cwd, runner.timeoutMs ?? timeoutMs, env);
|
|
32
29
|
const payload = parseInitPayload(result.stdout);
|
|
33
30
|
const candidateGeneration = recordField(payload, "generation");
|
|
34
31
|
const generation = isValidGenerationPayload(payload, candidateGeneration) ? candidateGeneration : null;
|
|
@@ -65,6 +65,11 @@ const OUTPUT_HEAD_LIMIT = 20_000;
|
|
|
65
65
|
const OUTPUT_TRUNCATION_MARKER = "\n[output middle truncated; tail preserved]\n";
|
|
66
66
|
const METRIC_JSONL_LIMIT = 256_000;
|
|
67
67
|
const METRIC_JSONL_LINE_LIMIT = 64_000;
|
|
68
|
+
// After the deadline's SIGTERM, how long a run gets to end on its own terms
|
|
69
|
+
// before SIGKILL. Clio seals the interrupted run's receipt inside its
|
|
70
|
+
// coordinated shutdown, which budgets 500ms per hook across several hooks; a
|
|
71
|
+
// one-second grace killed it mid-seal and the timed-out run left no receipt.
|
|
72
|
+
const TIMEOUT_KILL_GRACE_MS = 5_000;
|
|
68
73
|
|
|
69
74
|
export async function runExternalCommandRunner(
|
|
70
75
|
runner: EvalRunnerV2,
|
|
@@ -133,8 +138,23 @@ export async function runExternalCommandRunner(
|
|
|
133
138
|
};
|
|
134
139
|
}
|
|
135
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Run one eval subprocess to completion or to the timeout.
|
|
143
|
+
*
|
|
144
|
+
* A string runs through the shell, which is what an operator's
|
|
145
|
+
* `external-command` line and the verifier commands are. An argv array spawns
|
|
146
|
+
* the program directly, with no shell between the runner and the process
|
|
147
|
+
* whose exit code it reports. That distinction matters on the timeout path:
|
|
148
|
+
* `/bin/sh -c` on dash keeps the shell as the parent, so SIGTERM to the shell
|
|
149
|
+
* stops the shell alone while the program runs on to completion. A
|
|
150
|
+
* `clio-coder run` spawned that way finished its turn after the deadline,
|
|
151
|
+
* sealed a succeeded receipt with exit 0, and exited 0, and this runner
|
|
152
|
+
* reported the shell's signal death as exit 124 (issue #275). With an argv the
|
|
153
|
+
* signal reaches Clio itself, which seals the run as canceled with the exit
|
|
154
|
+
* status it then reports, so the receipt and the exit code agree either way.
|
|
155
|
+
*/
|
|
136
156
|
export function runShellCommand(
|
|
137
|
-
command: string,
|
|
157
|
+
command: string | readonly [string, ...string[]],
|
|
138
158
|
cwd: string,
|
|
139
159
|
timeoutMs: number,
|
|
140
160
|
env?: NodeJS.ProcessEnv,
|
|
@@ -153,14 +173,12 @@ export function runShellCommand(
|
|
|
153
173
|
const callLedgerFold = createEvalCallLedgerFold();
|
|
154
174
|
let timedOut = false;
|
|
155
175
|
let settled = false;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
env: env === undefined ? process.env : { ...process.env, ...env },
|
|
163
|
-
});
|
|
176
|
+
// The overlay is additive: an eval item pins where Clio writes its
|
|
177
|
+
// journal, and inherits everything else the operator's shell provides.
|
|
178
|
+
const spawnEnv = env === undefined ? process.env : { ...process.env, ...env };
|
|
179
|
+
const [file, args, shell] = typeof command === "string" ? [command, [], true] : [command[0], command.slice(1), false];
|
|
180
|
+
const child = spawn(file, args, { cwd, shell, stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
|
|
181
|
+
const commandLine = typeof command === "string" ? command : command.join(" ");
|
|
164
182
|
child.stdout.setEncoding("utf8");
|
|
165
183
|
child.stderr.setEncoding("utf8");
|
|
166
184
|
child.stdout.on("data", (chunk: string) => {
|
|
@@ -177,14 +195,14 @@ export function runShellCommand(
|
|
|
177
195
|
const timer = setTimeout(() => {
|
|
178
196
|
timedOut = true;
|
|
179
197
|
child.kill("SIGTERM");
|
|
180
|
-
setTimeout(() => child.kill("SIGKILL"),
|
|
198
|
+
setTimeout(() => child.kill("SIGKILL"), TIMEOUT_KILL_GRACE_MS);
|
|
181
199
|
}, timeoutMs);
|
|
182
200
|
const finish = (exitCode: number): void => {
|
|
183
201
|
if (settled) return;
|
|
184
202
|
settled = true;
|
|
185
203
|
clearTimeout(timer);
|
|
186
204
|
resolve({
|
|
187
|
-
command,
|
|
205
|
+
command: commandLine,
|
|
188
206
|
exitCode,
|
|
189
207
|
stdout,
|
|
190
208
|
metricJsonl: metricCapture.finish(),
|
|
@@ -13,6 +13,33 @@ export const CANONICAL_METRICS = [
|
|
|
13
13
|
// are absent in that case rather than zero, so a gate on cost can require
|
|
14
14
|
// measurement instead of reading silence as free.
|
|
15
15
|
"tokens.measured",
|
|
16
|
+
// Observed stdout terminal/retry facts, independent of task success. Opaque
|
|
17
|
+
// runs carry measured:false and no counters. Errored usage stays in inclusive
|
|
18
|
+
// tokens.* totals; errorTokens/errorCostUsd are known subtotals with coverage.
|
|
19
|
+
"provider.measured",
|
|
20
|
+
"provider.stopReason.stop",
|
|
21
|
+
"provider.stopReason.toolUse",
|
|
22
|
+
"provider.stopReason.length",
|
|
23
|
+
"provider.stopReason.error",
|
|
24
|
+
"provider.stopReason.aborted",
|
|
25
|
+
"provider.stopReason.other",
|
|
26
|
+
"provider.retryScheduled",
|
|
27
|
+
"provider.retryStarted",
|
|
28
|
+
"provider.retryCancelled",
|
|
29
|
+
"provider.retryExhausted",
|
|
30
|
+
"provider.retryRecovered",
|
|
31
|
+
"provider.errorUsageObservedCalls",
|
|
32
|
+
"provider.errorUsageUnobservedCalls",
|
|
33
|
+
"provider.errorUsageIncompleteCalls",
|
|
34
|
+
"provider.errorCostUnobservedCalls",
|
|
35
|
+
"provider.errorReasoningUnobservedCalls",
|
|
36
|
+
"provider.errorReasoningTokens",
|
|
37
|
+
"provider.errorTokens.input",
|
|
38
|
+
"provider.errorTokens.output",
|
|
39
|
+
"provider.errorTokens.total",
|
|
40
|
+
"provider.errorTokens.cacheRead",
|
|
41
|
+
"provider.errorTokens.cacheWrite",
|
|
42
|
+
"provider.errorCostUsd",
|
|
16
43
|
"latency.wallMs",
|
|
17
44
|
"latency.modelMs",
|
|
18
45
|
"tools.totalCalls",
|
|
@@ -22,6 +49,7 @@ export const CANONICAL_METRICS = [
|
|
|
22
49
|
"tools.read.outsideAllowed",
|
|
23
50
|
"tools.read.decoyHits",
|
|
24
51
|
"tools.calls.dispatch",
|
|
52
|
+
"tools.succeeded.dispatch",
|
|
25
53
|
"tools.blocked.bash",
|
|
26
54
|
"claims.unsupported",
|
|
27
55
|
"completion.reported",
|
|
@@ -39,7 +39,7 @@ export interface EvalTrackedMetricsV1 {
|
|
|
39
39
|
reasoningTokens: EvalSourcedNullableNumber;
|
|
40
40
|
toolCalls: EvalSourcedNumber;
|
|
41
41
|
toolErrors: EvalSourcedNumber;
|
|
42
|
-
ttftMsFirstCall:
|
|
42
|
+
ttftMsFirstCall: EvalSourcedNullableNumber;
|
|
43
43
|
wallClockMs: EvalSourcedNumber;
|
|
44
44
|
contextTokensAtEnd: EvalSourcedNumber;
|
|
45
45
|
compactions: EvalSourcedNumber;
|
|
@@ -125,7 +125,7 @@ function parseTrackedMetrics(value: unknown, source: string): EvalTrackedMetrics
|
|
|
125
125
|
reasoningTokens: readSourcedNullableNumber(record.reasoningTokens, `${source}.reasoningTokens`),
|
|
126
126
|
toolCalls: readSourcedNumber(record.toolCalls, `${source}.toolCalls`),
|
|
127
127
|
toolErrors: readSourcedNumber(record.toolErrors, `${source}.toolErrors`),
|
|
128
|
-
ttftMsFirstCall:
|
|
128
|
+
ttftMsFirstCall: readSourcedNullableNumber(record.ttftMsFirstCall, `${source}.ttftMsFirstCall`),
|
|
129
129
|
wallClockMs: readSourcedNumber(record.wallClockMs, `${source}.wallClockMs`),
|
|
130
130
|
contextTokensAtEnd: readSourcedNumber(record.contextTokensAtEnd, `${source}.contextTokensAtEnd`),
|
|
131
131
|
compactions: readSourcedNumber(record.compactions, `${source}.compactions`),
|
|
@@ -38,7 +38,19 @@ function resolveTargets(targets: ReadonlyArray<EvalSuiteTargetV2>, options: Reso
|
|
|
38
38
|
const filtered =
|
|
39
39
|
options.target === undefined ? [...targets] : targets.filter((target) => target.id === options.target);
|
|
40
40
|
const selected =
|
|
41
|
-
filtered.length > 0
|
|
41
|
+
filtered.length > 0
|
|
42
|
+
? filtered
|
|
43
|
+
: options.target === undefined
|
|
44
|
+
? [...targets]
|
|
45
|
+
: [
|
|
46
|
+
{
|
|
47
|
+
id: options.target,
|
|
48
|
+
// A one-row suite still owns its thinking dimension when the CLI
|
|
49
|
+
// substitutes the target/model pair. Dropping it silently changes
|
|
50
|
+
// an off baseline into the target's configured default.
|
|
51
|
+
...(targets.length === 1 && targets[0]?.thinking !== undefined ? { thinking: targets[0].thinking } : {}),
|
|
52
|
+
},
|
|
53
|
+
];
|
|
42
54
|
return selected.map((target) => ({
|
|
43
55
|
...target,
|
|
44
56
|
...(options.model === undefined ? {} : { model: options.model }),
|