@iowarp/clio-coder 0.4.1 → 0.4.3
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 +127 -0
- package/CONTRIBUTING.md +142 -52
- package/README.md +434 -473
- package/SECURITY.md +2 -1
- package/dist/{acp-ZILU3AUO.js → acp-H2NGRPWO.js} +12 -12
- package/dist/{agents-HYWGBGQR.js → agents-TL5LLUQP.js} +56 -55
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-N3QT7CBO.js → auth-E5SW4HMS.js} +23 -21
- package/dist/builtins-IA7V7FUC.js +22 -0
- package/dist/{chunk-7RY5VZPH.js → chunk-2APPQIER.js} +8 -8
- package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
- package/dist/{chunk-JA5QWE4Z.js → chunk-2UG5F4C5.js} +1973 -1664
- package/dist/{chunk-5YHDIDBP.js → chunk-2UH2KFUP.js} +2 -2
- package/dist/{chunk-CTJ4RNAA.js → chunk-2VIKGWFZ.js} +2 -2
- package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
- package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
- package/dist/chunk-3EBYEESD.js +314 -0
- package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
- package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
- package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
- package/dist/chunk-4UVU7BJ5.js +39 -0
- package/dist/{chunk-VKRH2TCS.js → chunk-4WR7VSYB.js} +2 -2
- package/dist/{chunk-BBTJOK6Y.js → chunk-54CBCGIR.js} +5 -5
- package/dist/{chunk-AP73CFDC.js → chunk-5ICU3EUH.js} +2 -2
- package/dist/chunk-5MEZN6CB.js +1334 -0
- package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
- package/dist/{chunk-ABLSQ6JX.js → chunk-64I3JVYM.js} +8 -2
- package/dist/{chunk-AFKWHWXF.js → chunk-6PTFB5VS.js} +39 -22
- package/dist/{chunk-VN3SHNBN.js → chunk-7DICMOS6.js} +2 -2
- package/dist/chunk-7DRAWPTZ.js +360 -0
- package/dist/chunk-7E7I3WLS.js +3762 -0
- package/dist/{chunk-BJGUKIG4.js → chunk-7ZYNNDKC.js} +7 -7
- package/dist/{chunk-XKA2ICR3.js → chunk-AF4YM7Z4.js} +652 -252
- package/dist/{chunk-GVQJ5CCZ.js → chunk-AX2THNSA.js} +12 -12
- package/dist/{chunk-IG7BCQBA.js → chunk-B4OAX3SI.js} +65 -3
- package/dist/{chunk-TD3PGPQA.js → chunk-B4VEBZKF.js} +3 -3
- package/dist/{chunk-74YWRRU5.js → chunk-BEPZRGGU.js} +10 -10
- package/dist/{chunk-FEFIFZTL.js → chunk-CE5AX47J.js} +2 -2
- package/dist/{chunk-UAPGZHYC.js → chunk-DWUOQKRU.js} +25 -11
- package/dist/{chunk-THYWACCR.js → chunk-E3TPLWFX.js} +3 -3
- package/dist/{chunk-7EPLI7VL.js → chunk-EKCHAPYA.js} +2 -2
- package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
- package/dist/{chunk-PJJ6MY27.js → chunk-F5JHEYZM.js} +7 -7
- package/dist/{chunk-6CCS4G3W.js → chunk-FTMGRKEF.js} +3 -3
- package/dist/{chunk-SINK3QR6.js → chunk-G76U63X4.js} +17 -17
- package/dist/{chunk-EIMVLWB3.js → chunk-GHS5EBTQ.js} +64 -9
- package/dist/{chunk-QMXC4JB7.js → chunk-GI7YYQ3F.js} +187 -1419
- package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
- package/dist/{chunk-6HMJX2VU.js → chunk-GWZNEVM2.js} +44 -12
- package/dist/chunk-GYV6VZOC.js +26 -0
- package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
- package/dist/{chunk-UXN6JT4W.js → chunk-HEQY7ZFI.js} +3 -3
- package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
- package/dist/{chunk-GCSMB2KY.js → chunk-I7ZPNEJM.js} +145 -102
- package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
- package/dist/{chunk-QTFGO774.js → chunk-IGLP3ODT.js} +29 -16
- package/dist/chunk-IJNZMHLA.js +101 -0
- package/dist/{chunk-BDPT6GTK.js → chunk-INY6HTFL.js} +7 -7
- package/dist/{chunk-PBP4B7XR.js → chunk-IUE3Y34X.js} +2 -2
- package/dist/{chunk-6NJQITNH.js → chunk-IWT4SF4R.js} +6 -3
- package/dist/{chunk-R23Z6K6I.js → chunk-JDAY6FIL.js} +19 -19
- package/dist/chunk-JEQ3XTHC.js +42 -0
- package/dist/{chunk-FSP7CMNU.js → chunk-JGRC33J2.js} +50 -4
- package/dist/{chunk-TVH4ONAM.js → chunk-JKKCYP3C.js} +10 -10
- package/dist/{chunk-HJWWJ6IL.js → chunk-JSC3U7TI.js} +16 -4
- package/dist/{chunk-C537JADH.js → chunk-KK4JZPBQ.js} +19 -141
- package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
- package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
- package/dist/{chunk-6DWBAZ5U.js → chunk-L47TF46W.js} +5 -7
- package/dist/{chunk-HUAS7ITX.js → chunk-LDJG7DW3.js} +91 -42
- package/dist/{chunk-CDNVLKUX.js → chunk-LLDJM5XK.js} +13 -7
- package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
- package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
- package/dist/{chunk-VKFQTNDV.js → chunk-MUW2BDDH.js} +4 -4
- package/dist/{chunk-E67WX76H.js → chunk-MWUZBSAQ.js} +104 -152
- package/dist/{chunk-OJTRZGR3.js → chunk-N2Z7HLVY.js} +21 -21
- package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
- package/dist/{chunk-FYUN5KZ3.js → chunk-NIQJ66N4.js} +21 -21
- package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
- package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
- package/dist/{chunk-VEGN6WIQ.js → chunk-O5CVSAG5.js} +3 -3
- package/dist/{chunk-MOPSG2X7.js → chunk-OML5D5V5.js} +8 -8
- package/dist/{chunk-2VG7KLYV.js → chunk-PAJQJ7BS.js} +5816 -3255
- package/dist/{chunk-ZW55JB7N.js → chunk-PUVDKJ2Y.js} +2 -2
- package/dist/{chunk-BTGG6BG2.js → chunk-QWGDJJYJ.js} +158 -19
- package/dist/chunk-R6Q67RJH.js +134 -0
- package/dist/{chunk-ZJLUDYFY.js → chunk-RRNP2ANY.js} +6 -6
- package/dist/{chunk-PVAMAVBB.js → chunk-RSJ25QSL.js} +102 -2
- package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
- package/dist/chunk-SKHCAU7K.js +385 -0
- package/dist/chunk-SZAA6XDG.js +30 -0
- package/dist/{chunk-J4HBWF6Y.js → chunk-TM6LQDI3.js} +131 -28
- package/dist/chunk-UOIZ7DA4.js +41 -0
- package/dist/{chunk-MA3H6DM5.js → chunk-UPZU6GE4.js} +25 -3
- package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
- package/dist/{chunk-N5UK64DP.js → chunk-V2ANDPVT.js} +4 -4
- package/dist/{chunk-AK5XEFVZ.js → chunk-VA5FNYMT.js} +26 -13
- package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
- package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
- package/dist/{chunk-QKIFBZKT.js → chunk-VW6DOEDG.js} +497 -81
- package/dist/{chunk-SCYB3HA4.js → chunk-W6RRQCPQ.js} +63 -19
- package/dist/{chunk-2NM363SV.js → chunk-WBKFA554.js} +10 -10
- package/dist/{chunk-R32CLGZ6.js → chunk-WCXUNS7U.js} +82 -21
- package/dist/{chunk-GPPB3JBE.js → chunk-WRBAGUNF.js} +3 -3
- package/dist/{chunk-IXJT6DCX.js → chunk-XIVNBFZS.js} +85 -30
- package/dist/{chunk-UEDMSP56.js → chunk-XPWWI35G.js} +417 -201
- package/dist/chunk-XRZT5WY5.js +47 -0
- package/dist/{chunk-3QSOM6PA.js → chunk-Y3CBHOR6.js} +2 -2
- package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
- package/dist/{chunk-AKB4GYDL.js → chunk-YQWYVTMC.js} +5 -5
- package/dist/{chunk-6I5ILFOF.js → chunk-ZA4VCIGV.js} +3 -3
- package/dist/{chunk-7OBGU7UB.js → chunk-ZDN3Y73Y.js} +12 -18
- package/dist/{chunk-3I5NY75V.js → chunk-ZWPRK62N.js} +8 -5
- package/dist/cli/index.js +41 -39
- package/dist/{clio-IT3G3VQH.js → clio-CMMK4KRR.js} +9 -9
- package/dist/{code-nav-RK6S7F6E.js → code-nav-MDZNQS33.js} +89 -21
- package/dist/{components-UBWCQSRW.js → components-UCUQ4QXW.js} +4 -4
- package/dist/{config-3QZRWZJF.js → config-SVM5P5YI.js} +131 -84
- package/dist/{configure-FL7Y3KJF.js → configure-LE3IK2TJ.js} +28 -26
- package/dist/{context-5HE7ODYK.js → context-2OHRKS42.js} +69 -64
- package/dist/{context-KYQFRVDC.js → context-E3VC7RX5.js} +15 -11
- package/dist/{context-XNHL75JV.js → context-VNCR7KAG.js} +93 -65
- package/dist/{context-clear-N545L53A.js → context-clear-BW4O37TG.js} +64 -60
- package/dist/context-map-COB37XXN.js +505 -0
- package/dist/{context-working-set-QHKXSV2F.js → context-working-set-VDS25HXZ.js} +19 -18
- package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-5AHT53RF.js} +93 -82
- package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
- package/dist/{doctor-ZGPEGHIP.js → doctor-WNNVO6FY.js} +48 -47
- package/dist/{eval-GXLL44RD.js → eval-7G7SGAYO.js} +287 -115
- package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-Y6QRFOH5.js} +4 -4
- package/dist/{evidence-HWLBRH3Q.js → evidence-VD6736FQ.js} +67 -64
- package/dist/{evolve-FTZBMNVW.js → evolve-AL3NGVRL.js} +65 -62
- package/dist/{extensions-VHRBEID7.js → extensions-MOVJ32NM.js} +9 -7
- package/dist/{fleet-CKZHJWZJ.js → fleet-QZHUMAGI.js} +114 -111
- package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-BAYT5FJZ.js} +10 -10
- package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-IREVMRU4.js} +7 -6
- package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-YCTT3HTI.js} +22 -19
- package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-QVJTDAVB.js} +58 -55
- package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-25QAFPK4.js} +4 -4
- package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-5O57AAJ7.js} +26 -23
- package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-CPH2W2T6.js} +59 -56
- package/dist/{fleet-view-WAMJYNDT.js → fleet-view-SWBR3VGQ.js} +58 -55
- package/dist/{init-5XQRBOFV.js → init-J477LKZH.js} +82 -79
- package/dist/{interop-34TVO25M.js → interop-3FCM6XLG.js} +11 -11
- package/dist/{library-3QY6KF57.js → library-QUQEIUG6.js} +30 -27
- package/dist/{memory-L4UTIIIW.js → memory-SGGSEP65.js} +67 -64
- package/dist/{models-ZVX3QOWE.js → models-HEKUAXXK.js} +53 -46
- package/dist/{monitor-CEKVSYTS.js → monitor-HKU57TYQ.js} +63 -60
- package/dist/{orchestrator-77BAP6BC.js → orchestrator-VDFAEFAI.js} +1831 -1057
- package/dist/{panes-7STHOAUJ.js → panes-DN2SSFOH.js} +5 -5
- package/dist/{panes-SHAUIRXY.js → panes-TALGNPZT.js} +29 -14
- package/dist/{paths-L7LGY6RN.js → paths-NBMFAIEZ.js} +5 -5
- package/dist/reset-EAJFFJVB.js +344 -0
- package/dist/{resources-74GKTLSF.js → resources-OVKSEFVE.js} +29 -20
- package/dist/{run-HBAUJNNZ.js → run-7DP7ZF2J.js} +120 -115
- package/dist/{share-G3APVLVP.js → share-WML67FT3.js} +32 -27
- package/dist/{skills-35HHUKCR.js → skills-SG662R2K.js} +41 -31
- package/dist/{skills-eval-QN4HSHDC.js → skills-eval-VVZEUU46.js} +78 -77
- package/dist/{skills-inventory-J357J34F.js → skills-inventory-I2E23GET.js} +23 -20
- package/dist/{slash-commands-JZZCQA32.js → slash-commands-S7MBJDQK.js} +40 -36
- package/dist/{steer-XAVHJM22.js → steer-2LQOMCPB.js} +3 -3
- package/dist/{support-U7QOWY26.js → support-CC2UJBJ6.js} +6 -6
- package/dist/{targets-DSM6CY3M.js → targets-4QC3HIEW.js} +54 -54
- package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-TUHIJ6Y2.js} +5 -5
- package/dist/{tools-MKNWVPBH.js → tools-TFGJICCU.js} +10 -10
- package/dist/{trace-ECQ7TIYZ.js → trace-FXMXUZUF.js} +55 -7
- package/dist/uninstall-5PEVOE5B.js +408 -0
- package/dist/upgrade-M4WXY6KN.js +303 -0
- package/dist/{usage-X52N3IDJ.js → usage-N7ZNVLEM.js} +151 -104
- package/dist/{verifiers-EJTVVSMA.js → verifiers-DJTP4XX6.js} +15 -15
- package/dist/{verify-YJL6XET2.js → verify-RWE4PPEK.js} +9 -9
- package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
- package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-C7IQOXSP.js} +89 -86
- package/dist/{with-panes-OBOBFIIR.js → with-panes-4GCGSL7J.js} +53 -257
- package/dist/worker/entry.js +90 -74
- package/docs/README.md +176 -81
- package/docs/{acp.md → architecture/acp.md} +36 -20
- package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
- package/docs/{architecture.md → architecture/architecture.md} +43 -22
- package/docs/{artifact-placement.md → architecture/artifact-placement.md} +27 -23
- package/docs/architecture/artifact-versions.md +90 -0
- package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
- package/docs/{context-engine.md → architecture/context-engine.md} +29 -25
- package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
- package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
- package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
- package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
- package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
- package/docs/{model-catalog.md → architecture/model-catalog.md} +61 -27
- package/docs/{observability.md → architecture/observability.md} +38 -14
- package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
- package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +57 -20
- package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +99 -25
- package/docs/{safety-model.md → architecture/safety-model.md} +35 -20
- package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
- package/docs/architecture/time-conventions.md +125 -0
- package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
- package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
- package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
- package/docs/{built-in-agents.md → guide/built-in-agents.md} +65 -35
- package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +66 -61
- package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +323 -297
- package/docs/guide/configuration-reference.md +1163 -0
- package/docs/{environment-variables.md → guide/environment-variables.md} +33 -28
- package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
- package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
- package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
- package/docs/{glossary.md → guide/glossary.md} +14 -11
- package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +81 -17
- package/docs/guide/panes-and-files.md +290 -0
- package/docs/{proactive-memory.md → guide/proactive-memory.md} +131 -107
- package/docs/{resource-library.md → guide/resource-library.md} +13 -4
- package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +25 -3
- package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
- package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
- package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
- package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
- package/docs/process/development-pipeline.md +152 -0
- package/docs/process/documentation-coverage.md +100 -0
- package/docs/process/documentation-guide.md +187 -0
- package/docs/{eval-runner.md → process/eval-runner.md} +108 -53
- package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
- package/docs/{evolution.md → process/evolution.md} +2 -2
- package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
- package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
- package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
- package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
- package/evals/README.md +2 -2
- package/evals/behavioral-model.yaml +3 -2
- package/package.json +10 -8
- package/skills/README.md +52 -41
- package/skills/coding/ast-grep/SKILL.md +102 -31
- package/skills/coding/ast-grep/evals.md +26 -0
- package/skills/coding/coding-standards/SKILL.md +41 -6
- package/skills/coding/coding-standards/evals.md +23 -0
- package/skills/coding/prototype/SKILL.md +88 -29
- package/skills/coding/prototype/evals.md +19 -0
- package/skills/coding/tdd/SKILL.md +81 -54
- package/skills/coding/tdd/evals.md +20 -0
- package/skills/context/context-handoff/SKILL.md +44 -3
- package/skills/context/context-handoff/evals.md +44 -0
- package/skills/context/context-prime/SKILL.md +46 -16
- 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 +78 -64
- 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 +88 -65
- 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 +101 -52
- 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/meta/clio-coder-dev/SKILL.md +9 -5
- package/skills/meta/clio-coder-dev/evals.md +3 -2
- package/skills/meta/clio-coder-test/SKILL.md +102 -95
- package/skills/meta/clio-coder-test/evals.md +9 -4
- package/skills/meta/clio-coder-test/references/harness.md +100 -124
- package/skills/meta/clio-coder-test/references/test-map.md +77 -50
- package/skills/meta/credentials/SKILL.md +2 -2
- package/skills/meta/find-skills/SKILL.md +2 -2
- package/skills/meta/herdr/SKILL.md +2 -2
- package/skills/meta/skill-craft/SKILL.md +22 -16
- package/skills/planning/archify/SKILL.md +196 -0
- package/skills/planning/archify/evals.md +65 -0
- package/skills/planning/architecture/SKILL.md +62 -13
- package/skills/planning/architecture/evals.md +65 -0
- package/skills/planning/backlog/SKILL.md +131 -15
- package/skills/planning/backlog/evals.md +142 -0
- package/skills/planning/prd/SKILL.md +47 -7
- package/skills/planning/prd/evals.md +54 -0
- package/skills/planning/product-intent/SKILL.md +58 -3
- package/skills/planning/product-intent/evals.md +70 -0
- package/skills/planning/tech-spec/SKILL.md +54 -3
- package/skills/planning/tech-spec/evals.md +73 -0
- package/skills/registry.yaml +70 -62
- package/skills/remote.yaml +13 -0
- package/skills/research/arxiv-literature/SKILL.md +77 -19
- package/skills/research/arxiv-literature/evals.md +50 -0
- package/skills/research/experiment-protocol/SKILL.md +21 -2
- package/skills/research/experiment-protocol/evals.md +23 -0
- package/skills/research/scientific-debugging/SKILL.md +24 -2
- package/skills/research/scientific-debugging/evals.md +18 -0
- package/skills/research/scientific-modernization/SKILL.md +27 -2
- package/skills/research/scientific-modernization/evals.md +27 -0
- package/skills/skill-marketplace.json +97 -62
- package/skills/workflow/cut-it/SKILL.md +66 -6
- package/skills/workflow/cut-it/evals.md +101 -0
- package/skills/workflow/design-council/SKILL.md +118 -28
- package/skills/workflow/design-council/evals.md +161 -0
- package/skills/workflow/grill-me/SKILL.md +87 -11
- package/skills/workflow/grill-me/evals.md +153 -0
- package/skills/workflow/workflow-distiller/SKILL.md +77 -18
- package/skills/workflow/workflow-distiller/evals.md +118 -0
- package/src/cli/args.ts +2 -2
- package/src/cli/bootstrap-generate.ts +1 -1
- package/src/cli/config-inspect.ts +65 -12
- 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 +1082 -532
- package/src/cli/context-map.ts +114 -0
- package/src/cli/context.ts +4 -0
- package/src/cli/docs.ts +22 -14
- package/src/cli/doctor-naming.ts +5 -5
- package/src/cli/doctor-toolchain.ts +3 -3
- package/src/cli/eval.ts +1 -2
- package/src/cli/extensions.ts +2 -1
- package/src/cli/fleet.ts +1 -1
- package/src/cli/index.ts +3 -1
- package/src/cli/internal-dispatch.ts +3 -4
- 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/panes.ts +19 -5
- package/src/cli/reset.ts +228 -106
- package/src/cli/run.ts +9 -4
- package/src/cli/select.ts +664 -0
- package/src/cli/share.ts +5 -1
- package/src/cli/skills-eval.ts +3 -3
- package/src/cli/skills.ts +9 -2
- package/src/cli/targets.ts +5 -6
- package/src/cli/trace.ts +55 -4
- package/src/cli/uninstall.ts +233 -165
- package/src/cli/upgrade.ts +204 -149
- package/src/cli/usage.ts +86 -27
- package/src/cli/validate-model.ts +3 -3
- package/src/cli/wiki-generate.ts +1 -1
- package/src/core/artifact-paths.ts +1 -1
- package/src/core/bash-exec.ts +131 -86
- package/src/core/bus-events.ts +51 -6
- package/src/core/config.ts +61 -1
- package/src/core/defaults.ts +7 -4
- package/src/core/dispatch-outcome.ts +16 -0
- package/src/core/external-diagnostic.ts +44 -0
- package/src/core/gateway-routing.ts +157 -0
- package/src/core/guardrails.ts +10 -49
- package/src/core/prompt-hint.ts +9 -0
- package/src/core/safe-exec.ts +17 -2
- package/src/core/skill-activation.ts +89 -2
- package/src/domains/agents/builtins/architect.md +2 -3
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +2 -2
- package/src/domains/agents/builtins/documenter.md +2 -2
- package/src/domains/agents/builtins/git-master.md +1 -1
- package/src/domains/agents/builtins/oracle.md +1 -1
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +2 -2
- package/src/domains/agents/builtins/verifier.md +2 -2
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/builtins/world-knowledge.md +31 -0
- package/src/domains/agents/catalog.ts +13 -15
- package/src/domains/agents/contract.ts +2 -0
- package/src/domains/agents/extension.ts +23 -1
- package/src/domains/agents/result-contract.ts +70 -0
- package/src/domains/config/keybindings.ts +8 -0
- package/src/domains/context/extension.ts +0 -3
- package/src/domains/context/wiki/map-seed.ts +589 -0
- package/src/domains/context/wiki/plan.ts +2 -2
- package/src/domains/context/working-set/path-index.ts +1 -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 +11 -0
- package/src/domains/dispatch/capacity-lease.ts +17 -0
- package/src/domains/dispatch/contract.ts +11 -1
- package/src/domains/dispatch/extension.ts +237 -49
- package/src/domains/dispatch/host-verification.ts +435 -39
- package/src/domains/dispatch/intent-requirements.ts +10 -0
- package/src/domains/dispatch/intent.ts +18 -1
- package/src/domains/dispatch/path-scope.ts +235 -24
- package/src/domains/dispatch/run-event-journal.ts +4 -15
- package/src/domains/dispatch/state.ts +2 -3
- package/src/domains/dispatch/transport.ts +45 -21
- package/src/domains/dispatch/types.ts +58 -3
- package/src/domains/dispatch/worker-model-metadata.ts +38 -0
- package/src/domains/eval/artifacts/store.ts +5 -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 +5 -2
- package/src/domains/eval/schema/suite.ts +28 -0
- package/src/domains/eval/schema/verdict.ts +2 -2
- package/src/domains/eval/store.ts +8 -1
- package/src/domains/eval/suites/resolve.ts +13 -1
- package/src/domains/eval/suites/run.ts +24 -3
- package/src/domains/evidence/trust-status.ts +10 -1
- package/src/domains/extensions/contract.ts +15 -1
- package/src/domains/extensions/discovery.ts +238 -41
- package/src/domains/extensions/extension.ts +105 -6
- package/src/domains/extensions/index.ts +24 -0
- package/src/domains/extensions/integrity.ts +189 -0
- package/src/domains/extensions/manager.ts +17 -1
- package/src/domains/extensions/resource-path.ts +27 -0
- package/src/domains/extensions/resources.ts +18 -38
- package/src/domains/extensions/snapshot-store.ts +39 -0
- package/src/domains/extensions/snapshot.ts +180 -0
- package/src/domains/extensions/state.ts +385 -57
- package/src/domains/extensions/types.ts +118 -1
- package/src/domains/interop/registry.ts +6 -2
- package/src/domains/interop/types.ts +4 -0
- package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
- package/src/domains/lifecycle/migrations/index.ts +6 -0
- package/src/domains/lifecycle/naming-resources.ts +19 -4
- package/src/domains/lifecycle/naming-yazi.ts +10 -5
- package/src/domains/memory/task-memory-policy.ts +70 -26
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/contract.ts +26 -0
- package/src/domains/middleware/extension.ts +24 -24
- package/src/domains/middleware/hook-receipts.ts +27 -4
- package/src/domains/middleware/hooks-io.ts +65 -32
- package/src/domains/middleware/hooks.ts +64 -0
- package/src/domains/middleware/index.ts +28 -5
- package/src/domains/middleware/marketplace-offer.ts +3 -35
- package/src/domains/middleware/memory-intervention.ts +127 -32
- package/src/domains/middleware/memory-step-endpoint.ts +3 -2
- package/src/domains/middleware/registrations.ts +326 -0
- package/src/domains/middleware/runtime.ts +28 -0
- package/src/domains/middleware/skills-reminder.ts +31 -2
- package/src/domains/middleware/snapshot.ts +20 -7
- package/src/domains/mux/contract.ts +38 -0
- package/src/domains/mux/detect.ts +6 -13
- package/src/domains/mux/index.ts +1 -1
- package/src/domains/mux/operations.ts +44 -5
- package/src/domains/mux/yazi/assets/yazi.toml +2 -2
- package/src/domains/mux/yazi/session.ts +53 -4
- package/src/domains/mux/yazi/theme.ts +117 -17
- package/src/domains/observability/compaction-usage.ts +118 -0
- package/src/domains/observability/contract.ts +10 -11
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/extension.ts +17 -4
- package/src/domains/observability/out-of-turn-usage.ts +52 -21
- package/src/domains/observability/projection.ts +14 -90
- package/src/domains/observability/trace-store.ts +43 -7
- package/src/domains/prompts/compiler.ts +73 -53
- package/src/domains/prompts/contract.ts +15 -3
- package/src/domains/prompts/extension.ts +97 -9
- package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
- package/src/domains/prompts/fragments/identity/clio.md +6 -12
- package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
- package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
- package/src/domains/prompts/fragments/operating/contract.md +7 -15
- package/src/domains/prompts/fragments/operating/delegation.md +32 -34
- package/src/domains/prompts/fragments/operating/skills.md +10 -24
- package/src/domains/prompts/fragments/operating/worker.md +1 -8
- package/src/domains/providers/contract.ts +4 -1
- package/src/domains/providers/extension.ts +40 -9
- package/src/domains/providers/index.ts +1 -1
- package/src/domains/providers/model-capabilities.ts +9 -0
- package/src/domains/providers/model-discovery.ts +2 -0
- package/src/domains/providers/model-runtime-capabilities.ts +99 -25
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +699 -114
- package/src/domains/providers/runtime-resolution.ts +31 -0
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
- 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/common/probe-helpers.ts +7 -2
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
- 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/cost-provenance.ts +19 -0
- package/src/domains/providers/types/local-model-quirks.ts +85 -37
- 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 +23 -19
- package/src/domains/resources/skills/marketplace.ts +63 -11
- package/src/domains/safety/autonomy.ts +15 -0
- package/src/domains/safety/call-target.ts +1 -1
- package/src/domains/safety/index.ts +1 -0
- package/src/domains/safety/loop-detector.ts +7 -4
- package/src/domains/safety/path-policy.ts +1 -1
- package/src/domains/safety/policy-engine.ts +34 -11
- package/src/domains/safety/protected-artifacts.ts +191 -88
- package/src/domains/safety/run-effects.ts +2 -22
- package/src/domains/safety/skill-authority.ts +55 -0
- package/src/domains/session/compaction/compact.ts +72 -22
- package/src/domains/session/entries.ts +6 -0
- package/src/domains/session/task-board.ts +10 -9
- package/src/domains/session/usage.ts +3 -3
- package/src/domains/share/archive.ts +164 -7
- package/src/engine/acp/server.ts +62 -9
- 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/llamacpp-residency.ts +3 -4
- package/src/engine/apis/lmstudio.ts +3 -3
- package/src/engine/apis/ollama-native.ts +6 -6
- package/src/engine/apis/openai-completions.ts +145 -39
- package/src/engine/apis/output-budget.ts +8 -18
- package/src/engine/apis/residency.ts +8 -27
- package/src/engine/external-subprocess.ts +114 -6
- package/src/engine/gemma-channel-filter.ts +19 -0
- package/src/engine/loop-guard.ts +92 -12
- package/src/engine/worker-runtime.ts +40 -11
- package/src/engine/worker-tools.ts +3 -1
- package/src/entry/background-model-metadata.ts +18 -0
- package/src/entry/compaction-prompt.ts +57 -0
- package/src/entry/extension-hook-sources.ts +28 -0
- package/src/entry/extension-reload.ts +309 -0
- package/src/entry/orchestrator.ts +464 -251
- package/src/entry/task-memory-lifecycle.ts +35 -0
- package/src/interactive/application-controller.ts +2 -1
- package/src/interactive/bus-notices.ts +8 -1
- package/src/interactive/chat-loop-messages.ts +16 -17
- package/src/interactive/chat-loop.ts +75 -3
- package/src/interactive/chat-panel.ts +36 -13
- package/src/interactive/chat-renderer.ts +72 -7
- package/src/interactive/cost-overlay.ts +26 -2
- package/src/interactive/dispatch-board.ts +6 -11
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/interactive-application.ts +39 -4
- package/src/interactive/interactive-input-runtime.ts +4 -0
- package/src/interactive/interactive-presentation.ts +2 -2
- package/src/interactive/interactive-slash-runtime.ts +4 -1
- package/src/interactive/overlays/extensions.ts +9 -1
- package/src/interactive/overlays/help-reference.ts +13 -0
- package/src/interactive/overlays/settings.ts +27 -16
- package/src/interactive/panes-runtime.ts +111 -35
- package/src/interactive/prompt-cache-identity.ts +88 -0
- package/src/interactive/renderers/worker-entry.ts +32 -0
- package/src/interactive/slash-commands.ts +153 -20
- package/src/interactive/stream-pacing-policy.ts +0 -23
- package/src/interactive/theme/labels.ts +19 -13
- package/src/interactive/turn-context.ts +39 -20
- 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/worker-receipts.ts +1 -0
- package/src/interactive/worker-stream.ts +6 -1
- package/src/interactive/yazi-bridge.ts +60 -6
- package/src/tools/agent-tools.ts +30 -1
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +3 -3
- package/src/tools/bash.ts +1 -1
- package/src/tools/bootstrap.ts +4 -0
- package/src/tools/builtin-tool-catalog.ts +52 -22
- package/src/tools/codewiki/code-nav-surface.ts +6 -0
- package/src/tools/codewiki/code-nav.ts +99 -13
- package/src/tools/context/docs-engine.ts +20 -7
- package/src/tools/context/index.ts +59 -21
- package/src/tools/core-bootstrap.ts +28 -6
- package/src/tools/credential-present.ts +1 -2
- package/src/tools/dispatch-arguments.ts +6 -1
- package/src/tools/dispatch-event-text.ts +10 -0
- package/src/tools/dispatch-plan.ts +49 -4
- package/src/tools/dispatch-run-events.ts +1 -1
- package/src/tools/dispatch-runner.ts +12 -0
- package/src/tools/dispatch-schema.ts +338 -0
- package/src/tools/dispatch-types.ts +3 -0
- package/src/tools/dispatch.ts +9 -254
- package/src/tools/ledger.ts +3 -5
- package/src/tools/monitor-surface.ts +5 -13
- package/src/tools/observation.ts +4 -5
- package/src/tools/panes-surface.ts +4 -11
- package/src/tools/panes.ts +4 -2
- package/src/tools/policy.ts +15 -2
- package/src/tools/read.ts +5 -6
- package/src/tools/registry.ts +41 -12
- package/src/tools/result-shaping.ts +18 -14
- package/src/tools/steer-surface.ts +1 -1
- package/src/tools/tasks.ts +1 -1
- package/src/tools/truncate.ts +6 -5
- package/src/tools/verify/surface.ts +6 -12
- package/src/tools/web-fetch-surface.ts +1 -3
- package/src/tools/worker-evidence.ts +3 -1
- package/src/worker/spec-contract.ts +4 -0
- package/dist/builtins-UJLMOVOV.js +0 -17
- package/dist/chunk-5QIAJV2D.js +0 -48
- package/dist/chunk-JZWT5J3Y.js +0 -814
- package/dist/chunk-K7VKOLQQ.js +0 -15
- package/dist/chunk-PMZCIOCJ.js +0 -25
- package/dist/chunk-SUW5DORT.js +0 -819
- package/dist/chunk-UOV2BYIW.js +0 -107
- package/dist/chunk-WR6U3OVP.js +0 -45
- package/dist/chunk-Y45G3AXC.js +0 -1558
- package/dist/reset-EOLM7GVE.js +0 -230
- package/dist/uninstall-N34PCTGJ.js +0 -331
- package/dist/upgrade-H7TOM7YL.js +0 -323
- package/docs/artifact-versions.md +0 -67
- package/docs/development-pipeline.md +0 -121
- package/docs/documentation-coverage.md +0 -46
- package/docs/documentation-guide.md +0 -167
- package/docs/time-conventions.md +0 -101
|
@@ -11,6 +11,11 @@ import { parseEvalVerdictEnvelopeV1 } from "../schema/verdict.js";
|
|
|
11
11
|
import { evalRoot } from "../store.js";
|
|
12
12
|
import { redactArtifactForStorage } from "./redact.js";
|
|
13
13
|
|
|
14
|
+
// This is the documented location (docs/architecture/artifact-versions.md's
|
|
15
|
+
// Eval Artifact row): <dataDir>/evals/<evalId>.json, flat. The legacy version-1
|
|
16
|
+
// shape skills-eval writes lives at evalRoot()/skills-eval/ instead
|
|
17
|
+
// (store.ts's evalArtifactPath) so the two writers can never resolve to the
|
|
18
|
+
// same file for the same id.
|
|
14
19
|
function evalArtifactPathV4(dataDir: string, evalId: string): string {
|
|
15
20
|
assertSafeId(evalId, "eval");
|
|
16
21
|
return join(evalRoot(dataDir), `${evalId}.json`);
|
|
@@ -6,7 +6,11 @@ export interface EvalCallLedgerFold {
|
|
|
6
6
|
entries(): SessionEntry[];
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Fold stdout assistant completions into a fallback ledger. These spans start
|
|
11
|
+
* at the provider's message_start, which may follow its response-header wait;
|
|
12
|
+
* they are not complete request latency. Native eval prefers session timing.
|
|
13
|
+
*/
|
|
10
14
|
export function createEvalCallLedgerFold(now: () => number = () => performance.now()): EvalCallLedgerFold {
|
|
11
15
|
const entries: SessionEntry[] = [];
|
|
12
16
|
let pending = "";
|
|
@@ -21,7 +25,7 @@ export function createEvalCallLedgerFold(now: () => number = () => performance.n
|
|
|
21
25
|
activeFirstOutputAt = null;
|
|
22
26
|
return;
|
|
23
27
|
}
|
|
24
|
-
if (event
|
|
28
|
+
if (isAssistantOutput(event) && activeStartedAt !== null && activeFirstOutputAt === null) {
|
|
25
29
|
activeFirstOutputAt = now();
|
|
26
30
|
return;
|
|
27
31
|
}
|
|
@@ -42,19 +46,25 @@ export function createEvalCallLedgerFold(now: () => number = () => performance.n
|
|
|
42
46
|
};
|
|
43
47
|
if (isRecord(message.backendTimings)) promptCache.backend = structuredClone(message.backendTimings);
|
|
44
48
|
const previous = entries.at(-1);
|
|
49
|
+
const timestamp = messageTimestamp(message.timestamp);
|
|
45
50
|
entries.push({
|
|
46
51
|
kind: "message",
|
|
47
52
|
role: "assistant",
|
|
48
53
|
turnId: `eval-call-${entries.length + 1}`,
|
|
49
54
|
parentTurnId: previous?.turnId ?? null,
|
|
50
|
-
timestamp:
|
|
55
|
+
timestamp: timestamp ?? new Date(0).toISOString(),
|
|
51
56
|
payload: {
|
|
57
|
+
// Retain the legacy ISO placeholder without treating it as observed
|
|
58
|
+
// chronology. Per-call monotonic timing remains usable on its own.
|
|
59
|
+
...(timestamp === null ? { timestampEstimated: true } : {}),
|
|
52
60
|
promptCache,
|
|
53
|
-
timing:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
timing:
|
|
62
|
+
activeStartedAt === null
|
|
63
|
+
? null
|
|
64
|
+
: {
|
|
65
|
+
ttftMs: activeFirstOutputAt === null ? null : Math.round(Math.max(0, activeFirstOutputAt - activeStartedAt)),
|
|
66
|
+
apiMs: Math.round(Math.max(0, endedAt - activeStartedAt)),
|
|
67
|
+
},
|
|
58
68
|
usage: structuredClone(usage),
|
|
59
69
|
},
|
|
60
70
|
});
|
|
@@ -82,15 +92,28 @@ export function createEvalCallLedgerFold(now: () => number = () => performance.n
|
|
|
82
92
|
};
|
|
83
93
|
}
|
|
84
94
|
|
|
95
|
+
function isAssistantOutput(event: Record<string, unknown>): boolean {
|
|
96
|
+
// Headless chat projects updates to text/thinking deltas; worker stdout
|
|
97
|
+
// retains the nested update. Structural events are not token observations.
|
|
98
|
+
const output = event.type === "message_update" ? event.assistantMessageEvent : event;
|
|
99
|
+
if (!isRecord(output)) return false;
|
|
100
|
+
if (output.type === "toolcall_start") return event.type === "message_update";
|
|
101
|
+
return (
|
|
102
|
+
(output.type === "text_delta" || output.type === "thinking_delta" || output.type === "toolcall_delta") &&
|
|
103
|
+
typeof output.delta === "string" &&
|
|
104
|
+
output.delta.length > 0
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
85
108
|
function isAssistantMessage(value: unknown): value is Record<string, unknown> & { role: "assistant" } {
|
|
86
109
|
return isRecord(value) && value.role === "assistant";
|
|
87
110
|
}
|
|
88
111
|
|
|
89
|
-
function messageTimestamp(value: unknown): string {
|
|
112
|
+
function messageTimestamp(value: unknown): string | null {
|
|
90
113
|
const milliseconds = nonNegativeNumber(value);
|
|
91
|
-
if (milliseconds === null) return
|
|
114
|
+
if (milliseconds === null) return null;
|
|
92
115
|
const date = new Date(milliseconds);
|
|
93
|
-
return Number.isFinite(date.getTime()) ? date.toISOString() :
|
|
116
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : null;
|
|
94
117
|
}
|
|
95
118
|
|
|
96
119
|
function nonNegativeNumber(value: unknown): number | null {
|
|
@@ -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 {
|
|
@@ -149,7 +149,7 @@ interface BehavioralToolTerminal {
|
|
|
149
149
|
* bounded counters against the suite's explicit public allowlist and decoy
|
|
150
150
|
* list; they never become behavioral fact values or evidence excerpts.
|
|
151
151
|
*/
|
|
152
|
-
function toolBehaviorMetricEntriesFromJsonl(
|
|
152
|
+
export function toolBehaviorMetricEntriesFromJsonl(
|
|
153
153
|
stdout: string,
|
|
154
154
|
cwd: string,
|
|
155
155
|
readObservation?: { allowedPaths: string[]; decoyPaths: string[] },
|
|
@@ -201,16 +201,19 @@ function toolBehaviorMetricEntriesFromJsonl(
|
|
|
201
201
|
|
|
202
202
|
const terminals = canonicalFinishes.length > 0 ? canonicalFinishes : executionEnds;
|
|
203
203
|
const calls = new Map<string, number>();
|
|
204
|
+
const succeeded = new Map<string, number>();
|
|
204
205
|
const blocked = new Map<string, number>();
|
|
205
206
|
for (const terminal of terminals) {
|
|
206
207
|
const tool = metricToolName(terminal.tool);
|
|
207
208
|
calls.set(tool, (calls.get(tool) ?? 0) + 1);
|
|
209
|
+
if (terminal.outcome === "ok") succeeded.set(tool, (succeeded.get(tool) ?? 0) + 1);
|
|
208
210
|
if (terminal.outcome === "blocked") blocked.set(tool, (blocked.get(tool) ?? 0) + 1);
|
|
209
211
|
}
|
|
210
|
-
const namedTools = new Set(["bash", "dispatch", "read", ...calls.keys(), ...blocked.keys()]);
|
|
212
|
+
const namedTools = new Set(["bash", "dispatch", "read", ...calls.keys(), ...succeeded.keys(), ...blocked.keys()]);
|
|
211
213
|
const entries: Record<string, number> = { "tools.read.distinctPaths": readPaths.size };
|
|
212
214
|
for (const tool of [...namedTools].sort()) {
|
|
213
215
|
entries[`tools.calls.${tool}`] = calls.get(tool) ?? 0;
|
|
216
|
+
entries[`tools.succeeded.${tool}`] = succeeded.get(tool) ?? 0;
|
|
214
217
|
entries[`tools.blocked.${tool}`] = blocked.get(tool) ?? 0;
|
|
215
218
|
}
|
|
216
219
|
if (readObservation !== undefined) {
|
|
@@ -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`),
|
|
@@ -60,9 +60,16 @@ export function evalRoot(dataDir: string): string {
|
|
|
60
60
|
return join(dataDir, "evals");
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* `skills-eval` is the only writer of this legacy version-1 shape; it nests
|
|
65
|
+
* under its own subdirectory so a legacy id that collides with a `clio-coder
|
|
66
|
+
* eval` run's version-4 id (evalArtifactPathV4, artifacts/store.ts) cannot
|
|
67
|
+
* clobber that artifact, and so `eval inventory`'s top-level readdir of
|
|
68
|
+
* evalRoot() never trips over a shape it does not parse.
|
|
69
|
+
*/
|
|
63
70
|
export function evalArtifactPath(dataDir: string, evalId: string): string {
|
|
64
71
|
assertSafeId(evalId, "eval");
|
|
65
|
-
return join(evalRoot(dataDir), `${evalId}.json`);
|
|
72
|
+
return join(evalRoot(dataDir), "skills-eval", `${evalId}.json`);
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
/**
|
|
@@ -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 }),
|
|
@@ -18,7 +18,12 @@ import {
|
|
|
18
18
|
import { wallTimeMetric } from "../metrics/latency.js";
|
|
19
19
|
import { tokenAccountingFrom } from "../metrics/tokens.js";
|
|
20
20
|
import { zeroToolCallMetrics } from "../metrics/tool-calls.js";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
buildEvalTrackedMetrics,
|
|
23
|
+
emptyEvalTrackedMetrics,
|
|
24
|
+
readEvalLedgerSnapshot,
|
|
25
|
+
selectEvalLedgerEntries,
|
|
26
|
+
} from "../metrics/tracked.js";
|
|
22
27
|
import {
|
|
23
28
|
type EvalServingObservation,
|
|
24
29
|
evalClioProvenance,
|
|
@@ -234,11 +239,27 @@ async function runMatrixItem(
|
|
|
234
239
|
},
|
|
235
240
|
};
|
|
236
241
|
const snapshot = await readEvalLedgerSnapshot(stateDir);
|
|
237
|
-
const
|
|
242
|
+
const selected = selectEvalLedgerEntries(snapshot.entries, runner.ledgerEntries ?? []);
|
|
243
|
+
result.artifacts.trackedMetricSources = JSON.stringify({
|
|
244
|
+
assistantCalls: selected.source,
|
|
245
|
+
sessionCalls: selected.sessionCalls,
|
|
246
|
+
streamCalls: selected.streamCalls,
|
|
247
|
+
compactions: "session",
|
|
248
|
+
});
|
|
249
|
+
if (selected.sessionCalls > 0 && selected.streamCalls > 0) {
|
|
250
|
+
// Preserve the unmerged evidence for opaque runners too. The native
|
|
251
|
+
// runner already publishes this artifact before stdout truncation.
|
|
252
|
+
result.artifacts.callLedger ??= JSON.stringify(runner.ledgerEntries);
|
|
253
|
+
if (selected.sessionCalls !== selected.streamCalls || task.runner.kind === "external-command") {
|
|
254
|
+
result.artifacts.trackedMetricWarning =
|
|
255
|
+
"Session and stream call coverage may differ; tracked metrics use session calls, not a reconciled union. " +
|
|
256
|
+
"Inspect callLedger before treating these counts as complete: no shared call identity proves overlap.";
|
|
257
|
+
}
|
|
258
|
+
}
|
|
238
259
|
result.verdict = adaptSuiteV2ResultToVerdictV1(
|
|
239
260
|
result,
|
|
240
261
|
buildEvalTrackedMetrics({
|
|
241
|
-
ledgerEntries,
|
|
262
|
+
ledgerEntries: selected.entries,
|
|
242
263
|
receipt: receipt ?? null,
|
|
243
264
|
fallbackWallClockMs: runner.wallTimeMs,
|
|
244
265
|
}),
|