@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
|
@@ -657,6 +657,7 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
657
657
|
output: receipt.output?.state === "final" ? receipt.output.text : "",
|
|
658
658
|
succeeded: stepSucceeded,
|
|
659
659
|
integrityValid,
|
|
660
|
+
...(receipt.decisionRefs !== undefined ? { decisionRefs: receipt.decisionRefs } : {}),
|
|
660
661
|
...(failureReason !== undefined ? { failureReason } : {}),
|
|
661
662
|
...(gatePathHash !== undefined ? { gatePathHash } : {}),
|
|
662
663
|
...(delegationPlanHash !== undefined ? { delegationPlanHash } : {}),
|
|
@@ -5,6 +5,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
5
5
|
import { PATH_BOUNDARY_MAX_ENTRIES, pathBoundaryCovers, resolvePathBoundary } from "../../core/path-boundary.js";
|
|
6
6
|
import { withStateFileLockSync } from "../../core/state-file-lock.js";
|
|
7
7
|
import { clioStateDir } from "../../core/xdg.js";
|
|
8
|
+
import { judgeNumericTexts, judgePerfTexts } from "../../tools/verify/scripts.js";
|
|
8
9
|
import { FLEET_COMMAND_BASE_ENV, type FleetCommand } from "../agents/fleet-commands.js";
|
|
9
10
|
import { runCodeStep } from "./code-step.js";
|
|
10
11
|
import type { DispatchRequest } from "./contract.js";
|
|
@@ -12,7 +13,7 @@ import type { RunHostVerification, RunHostVerificationAttribution, RunHostVerifi
|
|
|
12
13
|
import { captureWorkspaceSnapshot } from "./write-boundary.js";
|
|
13
14
|
|
|
14
15
|
const OUTPUT_TAIL_BYTES = 2_048;
|
|
15
|
-
const MEMO_VERSION =
|
|
16
|
+
const MEMO_VERSION = 2;
|
|
16
17
|
|
|
17
18
|
type ResolvedCheck = NonNullable<DispatchRequest["resolvedVerification"]>[number];
|
|
18
19
|
|
|
@@ -37,7 +38,7 @@ interface MemoEntry {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
interface MemoFile {
|
|
40
|
-
version:
|
|
41
|
+
version: typeof MEMO_VERSION;
|
|
41
42
|
entries: MemoEntry[];
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -108,10 +109,10 @@ function storeMemoEntry(stateDir: string, entry: MemoEntry): void {
|
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
function memoKey(command: FleetCommand, fingerprint: string, env: NodeJS.ProcessEnv): string {
|
|
112
|
+
function memoKey(command: FleetCommand, judgment: string, fingerprint: string, env: NodeJS.ProcessEnv): string {
|
|
112
113
|
const names = [...FLEET_COMMAND_BASE_ENV, ...command.env];
|
|
113
114
|
const values = Object.fromEntries(names.map((name) => [name, env[name] ?? null]));
|
|
114
|
-
return sha256(JSON.stringify({ fingerprint,
|
|
115
|
+
return sha256(JSON.stringify({ fingerprint, judgment, env: values }));
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
export function hostVerificationRejection(
|
|
@@ -124,10 +125,63 @@ export function hostVerificationRejection(
|
|
|
124
125
|
detail:
|
|
125
126
|
failedCheck === undefined
|
|
126
127
|
? "host verification rejected"
|
|
127
|
-
:
|
|
128
|
+
: failedCheck.report !== undefined
|
|
129
|
+
? `host verification check '${failedCheck.check}' rejected: ${failedCheck.report.summary}`
|
|
130
|
+
: `host verification check '${failedCheck.check}' rejected with exit code ${failedCheck.exitCode}`,
|
|
128
131
|
};
|
|
129
132
|
}
|
|
130
133
|
|
|
134
|
+
function readSealedFile(absolutePath: string): string | undefined {
|
|
135
|
+
try {
|
|
136
|
+
return readFileSync(absolutePath, "utf8");
|
|
137
|
+
} catch {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The kind-specific verdict for a resolved check that already ran. A command
|
|
144
|
+
* check keeps its exit code. A numeric-compare check judges captured stdout
|
|
145
|
+
* against the sealed reference; a perf-budget check judges the measured
|
|
146
|
+
* duration against the sealed budget or baseline. Either judgement turns a
|
|
147
|
+
* clean exit into exit 1 when it fails, and a judgement that cannot be made
|
|
148
|
+
* (missing reference, unparseable output) fails with the reason in the tail.
|
|
149
|
+
*/
|
|
150
|
+
function judgeResolvedCheck(
|
|
151
|
+
resolvedCheck: ResolvedCheck,
|
|
152
|
+
exitCode: number,
|
|
153
|
+
durationMs: number,
|
|
154
|
+
stdout: string,
|
|
155
|
+
): { exitCode: number; report?: RunHostVerificationCheck["report"]; outputTail?: string } {
|
|
156
|
+
if (resolvedCheck.kind === undefined || resolvedCheck.kind === "command" || exitCode !== 0) return { exitCode };
|
|
157
|
+
if (resolvedCheck.kind === "numeric-compare" && resolvedCheck.numeric !== undefined) {
|
|
158
|
+
const referenceText = readSealedFile(resolvedCheck.numeric.reference);
|
|
159
|
+
if (referenceText === undefined) {
|
|
160
|
+
return { exitCode: 1, outputTail: `numeric-compare: reference '${resolvedCheck.numeric.reference}' cannot be read` };
|
|
161
|
+
}
|
|
162
|
+
const report = judgeNumericTexts(
|
|
163
|
+
stdout,
|
|
164
|
+
referenceText,
|
|
165
|
+
resolvedCheck.numeric.tolerance,
|
|
166
|
+
`reference '${resolvedCheck.numeric.reference}'`,
|
|
167
|
+
);
|
|
168
|
+
if (report instanceof Error) return { exitCode: 1, outputTail: `numeric-compare: ${report.message}` };
|
|
169
|
+
return { exitCode: report.passed ? 0 : 1, report, outputTail: outputTail(report.summary) };
|
|
170
|
+
}
|
|
171
|
+
if (resolvedCheck.kind === "perf-budget" && resolvedCheck.perf !== undefined) {
|
|
172
|
+
const baselinePath = resolvedCheck.perf.baseline;
|
|
173
|
+
const report = judgePerfTexts(
|
|
174
|
+
durationMs,
|
|
175
|
+
resolvedCheck.perf,
|
|
176
|
+
baselinePath === undefined ? undefined : readSealedFile(baselinePath),
|
|
177
|
+
`baseline '${baselinePath ?? ""}'`,
|
|
178
|
+
);
|
|
179
|
+
if (report instanceof Error) return { exitCode: 1, outputTail: `perf-budget: ${report.message}` };
|
|
180
|
+
return { exitCode: report.passed ? 0 : 1, report, outputTail: outputTail(report.summary) };
|
|
181
|
+
}
|
|
182
|
+
return { exitCode: 1, outputTail: `${resolvedCheck.kind}: sealed check carries no parameters` };
|
|
183
|
+
}
|
|
184
|
+
|
|
131
185
|
async function runResolvedCheck(input: {
|
|
132
186
|
runId: string;
|
|
133
187
|
index: number;
|
|
@@ -145,9 +199,9 @@ async function runResolvedCheck(input: {
|
|
|
145
199
|
env: [],
|
|
146
200
|
description: `Host verification check ${resolvedCheck.check}.`,
|
|
147
201
|
};
|
|
202
|
+
const judgmentKey = checkDedupeKey(resolvedCheck);
|
|
148
203
|
const fingerprint = workspaceFingerprint(resolvedCheck.cwd);
|
|
149
|
-
const key =
|
|
150
|
-
fingerprint === null ? null : memoKey({ ...command, cwd: resolve(resolvedCheck.cwd) }, fingerprint, input.env);
|
|
204
|
+
const key = fingerprint === null ? null : memoKey(command, judgmentKey, fingerprint, input.env);
|
|
151
205
|
const hit =
|
|
152
206
|
key === null
|
|
153
207
|
? undefined
|
|
@@ -168,17 +222,24 @@ async function runResolvedCheck(input: {
|
|
|
168
222
|
env: input.env,
|
|
169
223
|
});
|
|
170
224
|
const artifactPath = outcome.record.artifactPaths[0];
|
|
225
|
+
const judgement = judgeResolvedCheck(
|
|
226
|
+
resolvedCheck,
|
|
227
|
+
outcome.record.exitCode,
|
|
228
|
+
outcome.record.durationMs,
|
|
229
|
+
outcome.stdout,
|
|
230
|
+
);
|
|
171
231
|
const check: RunHostVerificationCheck = {
|
|
172
232
|
check: resolvedCheck.check,
|
|
173
233
|
argv: [...outcome.record.argv],
|
|
174
234
|
cwd: outcome.record.cwd,
|
|
175
|
-
exitCode:
|
|
235
|
+
exitCode: judgement.exitCode,
|
|
176
236
|
durationMs: outcome.record.durationMs,
|
|
177
237
|
memo: false,
|
|
178
|
-
outputTail: outputTail(outcome.report.outputExcerpt),
|
|
238
|
+
outputTail: judgement.outputTail ?? outputTail(outcome.report.outputExcerpt),
|
|
179
239
|
...(artifactPath !== undefined ? { artifactPath } : {}),
|
|
240
|
+
...(judgement.report !== undefined ? { report: judgement.report } : {}),
|
|
180
241
|
};
|
|
181
|
-
if (check.exitCode === 0 && key !== null) {
|
|
242
|
+
if (check.exitCode === 0 && key !== null && checkDedupeKey(resolvedCheck) === judgmentKey) {
|
|
182
243
|
try {
|
|
183
244
|
storeMemoEntry(input.stateDir, { key, runId: input.runId, check });
|
|
184
245
|
} catch (error) {
|
|
@@ -229,14 +290,45 @@ function implicatedPaths(outputExcerpt: string, checkCwd: string): string[] {
|
|
|
229
290
|
return [...paths].sort();
|
|
230
291
|
}
|
|
231
292
|
|
|
232
|
-
/** Identity
|
|
293
|
+
/** Identity shared by memo reuse and batch deduplication, including the declared judgment and its input files. */
|
|
233
294
|
function checkDedupeKey(resolvedCheck: ResolvedCheck): string {
|
|
295
|
+
const numeric = resolvedCheck.numeric;
|
|
296
|
+
const perf = resolvedCheck.perf;
|
|
234
297
|
return sha256(
|
|
235
298
|
JSON.stringify({
|
|
236
299
|
check: resolvedCheck.check,
|
|
237
300
|
argv: [...resolvedCheck.argv],
|
|
238
301
|
cwd: resolve(resolvedCheck.cwd),
|
|
239
302
|
timeoutMs: resolvedCheck.timeoutMs,
|
|
303
|
+
kind: resolvedCheck.kind ?? "command",
|
|
304
|
+
numeric:
|
|
305
|
+
numeric === undefined
|
|
306
|
+
? undefined
|
|
307
|
+
: {
|
|
308
|
+
reference: numeric.reference,
|
|
309
|
+
referenceDigest: sha256(JSON.stringify(readSealedFile(numeric.reference) ?? null)),
|
|
310
|
+
tolerance: {
|
|
311
|
+
absolute: numeric.tolerance.absolute,
|
|
312
|
+
relative: numeric.tolerance.relative,
|
|
313
|
+
ulp: numeric.tolerance.ulp,
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
perf:
|
|
317
|
+
perf === undefined
|
|
318
|
+
? undefined
|
|
319
|
+
: {
|
|
320
|
+
budget:
|
|
321
|
+
perf.budget === undefined
|
|
322
|
+
? undefined
|
|
323
|
+
: {
|
|
324
|
+
wallTimeMs: perf.budget.wallTimeMs,
|
|
325
|
+
tolerance: perf.budget.tolerance,
|
|
326
|
+
},
|
|
327
|
+
baseline: perf.baseline,
|
|
328
|
+
baselineDigest:
|
|
329
|
+
perf.baseline === undefined ? undefined : sha256(JSON.stringify(readSealedFile(perf.baseline) ?? null)),
|
|
330
|
+
tolerance: perf.tolerance,
|
|
331
|
+
},
|
|
240
332
|
}),
|
|
241
333
|
);
|
|
242
334
|
}
|
|
@@ -304,6 +396,12 @@ function memberBoundary(participant: BatchVerificationParticipant): string[] {
|
|
|
304
396
|
* the tree. `basis` is the weakest evidence behind the charge set, never the
|
|
305
397
|
* strongest, so `write_roots` on a receipt means every charged run has a named
|
|
306
398
|
* path inside its own declared boundary.
|
|
399
|
+
*
|
|
400
|
+
* A `worktree: true` member's write roots resolve against its own checkout
|
|
401
|
+
* (`request.cwd`) while the shared check ran in the parent frame, so none of
|
|
402
|
+
* its roots can cover a path the check named: attribution cannot exculpate
|
|
403
|
+
* anyone on its account and every declarer is charged, the conservative
|
|
404
|
+
* fallback those receipts sealed before batch settlement existed.
|
|
307
405
|
*/
|
|
308
406
|
function attributeFailure(input: {
|
|
309
407
|
implicated: ReadonlyArray<string>;
|
|
@@ -421,9 +519,11 @@ export function createBatchVerificationGate(
|
|
|
421
519
|
string,
|
|
422
520
|
{ resolvedCheck: ResolvedCheck; owner: BatchVerificationParticipant; index: number }
|
|
423
521
|
>();
|
|
522
|
+
const checkKeys = new Map<ResolvedCheck, string>();
|
|
424
523
|
for (const member of contributors) {
|
|
425
524
|
for (const resolvedCheck of member.request.resolvedVerification ?? []) {
|
|
426
525
|
const key = checkDedupeKey(resolvedCheck);
|
|
526
|
+
checkKeys.set(resolvedCheck, key);
|
|
427
527
|
if (!distinct.has(key)) distinct.set(key, { resolvedCheck, owner: member, index: distinct.size });
|
|
428
528
|
}
|
|
429
529
|
}
|
|
@@ -448,7 +548,7 @@ export function createBatchVerificationGate(
|
|
|
448
548
|
for (const [key, entry] of ran) {
|
|
449
549
|
if (entry.check.exitCode === 0) continue;
|
|
450
550
|
const declarers = contributors.filter((member) =>
|
|
451
|
-
(member.request.resolvedVerification ?? []).some((candidate) =>
|
|
551
|
+
(member.request.resolvedVerification ?? []).some((candidate) => checkKeys.get(candidate) === key),
|
|
452
552
|
);
|
|
453
553
|
const implicated = implicatedPaths(entry.outputExcerpt, entry.check.cwd);
|
|
454
554
|
const verdict = attributeFailure({ implicated, declarers, wave: members });
|
|
@@ -478,7 +578,8 @@ export function createBatchVerificationGate(
|
|
|
478
578
|
let rejected = false;
|
|
479
579
|
let unimplicated = false;
|
|
480
580
|
for (const resolvedCheck of member.request.resolvedVerification ?? []) {
|
|
481
|
-
const key =
|
|
581
|
+
const key = checkKeys.get(resolvedCheck);
|
|
582
|
+
if (key === undefined) throw new Error("host verification: declared check has no batch identity");
|
|
482
583
|
const shared = ran.get(key);
|
|
483
584
|
if (shared === undefined) continue;
|
|
484
585
|
own.push(
|
|
@@ -271,13 +271,34 @@ export function normalizeDispatchIntent(
|
|
|
271
271
|
if (!Array.isArray(writeRoots)) return writeRoots;
|
|
272
272
|
const relevantPaths = normalizePathList(raw.relevant_paths, "intent.relevant_paths");
|
|
273
273
|
if (!Array.isArray(relevantPaths)) return relevantPaths;
|
|
274
|
-
const expectedOutputs =
|
|
275
|
-
raw.expected_outputs,
|
|
276
|
-
"intent.expected_outputs",
|
|
277
|
-
normalizeExpectedOutputEntry,
|
|
278
|
-
);
|
|
274
|
+
const expectedOutputs = normalizeIntentExpectedOutputs(raw.expected_outputs);
|
|
279
275
|
if (!Array.isArray(expectedOutputs)) return expectedOutputs;
|
|
280
|
-
const
|
|
276
|
+
const verification = normalizeIntentVerification(raw.verification, checks);
|
|
277
|
+
if (!Array.isArray(verification)) return verification;
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
ok: true,
|
|
281
|
+
intent: {
|
|
282
|
+
version: 2,
|
|
283
|
+
readRoots,
|
|
284
|
+
writeRoots,
|
|
285
|
+
relevantPaths,
|
|
286
|
+
pathProvenance: declaredIntentPathProvenance({ readRoots, writeRoots, relevantPaths }),
|
|
287
|
+
expectedOutputs,
|
|
288
|
+
verification,
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function normalizeIntentExpectedOutputs(raw: unknown): string[] | DispatchIntentNormalizationResult {
|
|
294
|
+
return normalizePathList(raw, "intent.expected_outputs", normalizeExpectedOutputEntry);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export function normalizeIntentVerification(
|
|
298
|
+
raw: unknown,
|
|
299
|
+
checks: ReadonlyMap<string, DispatchIntentCheckBound>,
|
|
300
|
+
): DispatchIntentVerification[] | DispatchIntentNormalizationResult {
|
|
301
|
+
const rawVerification = raw ?? [];
|
|
281
302
|
if (!Array.isArray(rawVerification)) {
|
|
282
303
|
return fail("verification_malformed", "intent.verification must be an array");
|
|
283
304
|
}
|
|
@@ -321,16 +342,5 @@ export function normalizeDispatchIntent(
|
|
|
321
342
|
timeoutMs: Math.min(declared.timeoutMs, Math.max(DISPATCH_INTENT_TIMEOUT_MIN_MS, requested)),
|
|
322
343
|
});
|
|
323
344
|
}
|
|
324
|
-
return
|
|
325
|
-
ok: true,
|
|
326
|
-
intent: {
|
|
327
|
-
version: 2,
|
|
328
|
-
readRoots,
|
|
329
|
-
writeRoots,
|
|
330
|
-
relevantPaths,
|
|
331
|
-
pathProvenance: declaredIntentPathProvenance({ readRoots, writeRoots, relevantPaths }),
|
|
332
|
-
expectedOutputs,
|
|
333
|
-
verification,
|
|
334
|
-
},
|
|
335
|
-
};
|
|
345
|
+
return verification;
|
|
336
346
|
}
|
|
@@ -49,6 +49,7 @@ function receiptsDir(): string {
|
|
|
49
49
|
*/
|
|
50
50
|
function envelopeFromReceipt(receipt: RunReceipt, status: RunStatus, receiptPath: string): RunEnvelope {
|
|
51
51
|
const envelope: RunEnvelope = {
|
|
52
|
+
version: 1,
|
|
52
53
|
id: receipt.runId,
|
|
53
54
|
agentId: receipt.agentId,
|
|
54
55
|
executionRole: receipt.executionRole,
|
|
@@ -97,6 +98,7 @@ function envelopeFromReceipt(receipt: RunReceipt, status: RunStatus, receiptPath
|
|
|
97
98
|
if (receipt.gate !== undefined) envelope.gate = receipt.gate;
|
|
98
99
|
if (receipt.plan !== undefined) envelope.plan = receipt.plan;
|
|
99
100
|
if (receipt.personaOverride !== undefined) envelope.personaOverride = receipt.personaOverride;
|
|
101
|
+
if (receipt.decisionRefs !== undefined) envelope.decisionRefs = receipt.decisionRefs;
|
|
100
102
|
return envelope;
|
|
101
103
|
}
|
|
102
104
|
|
|
@@ -99,6 +99,9 @@ export const RECEIPT_INTEGRITY_FIELD_COVERAGE = {
|
|
|
99
99
|
plan: true,
|
|
100
100
|
fleetGate: true,
|
|
101
101
|
personaOverride: true,
|
|
102
|
+
// Absent unless the parent board held decisions, so older receipts and
|
|
103
|
+
// decision-free runs digest exactly as before.
|
|
104
|
+
decisionRefs: true,
|
|
102
105
|
projectContext: true,
|
|
103
106
|
// Always set on receipts written after #104 landed; absent only on older
|
|
104
107
|
// receipts, which omit these fields from canonical serialization.
|
|
@@ -193,6 +196,7 @@ function ledgerDigestFields(envelope: RunEnvelope): Record<string, unknown> {
|
|
|
193
196
|
executionRole: envelope.executionRole,
|
|
194
197
|
task: envelope.task,
|
|
195
198
|
...(envelope.budget !== undefined ? { budget: envelope.budget } : {}),
|
|
199
|
+
...(envelope.decisionRefs !== undefined ? { decisionRefs: envelope.decisionRefs } : {}),
|
|
196
200
|
targetId: envelope.targetId,
|
|
197
201
|
wireModelId: envelope.wireModelId,
|
|
198
202
|
runtimeId: envelope.runtimeId,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { withStateFileLockSync } from "../../core/state-file-lock.js";
|
|
2
|
+
import { withStateFileLock, withStateFileLockSync } from "../../core/state-file-lock.js";
|
|
3
3
|
import { endpointLabel } from "../providers/endpoint-capacity.js";
|
|
4
4
|
import {
|
|
5
5
|
acquireCapacityLease,
|
|
@@ -361,8 +361,10 @@ export function rebindDispatchReservationMember(input: {
|
|
|
361
361
|
costUpperBoundUsd: number;
|
|
362
362
|
capacity: ReservationCapacitySnapshot;
|
|
363
363
|
nowMs?: number;
|
|
364
|
-
}): DispatchReservationRecord {
|
|
365
|
-
|
|
364
|
+
}): Promise<DispatchReservationRecord> {
|
|
365
|
+
// Retry admission runs inside the async dispatch attempt, so it can yield
|
|
366
|
+
// while waiting for the cross-process lock instead of blocking the event loop.
|
|
367
|
+
return withStateFileLock(capacityStateLockPath(), () => {
|
|
366
368
|
const nowMs = input.nowMs ?? Date.now();
|
|
367
369
|
const records = expireRecords(readStore(), nowMs, false);
|
|
368
370
|
const record = records.find((entry) => entry.ownerId === input.ownerId);
|
|
@@ -52,6 +52,7 @@ export interface LedgerOptions {
|
|
|
52
52
|
|
|
53
53
|
export type CreateRunInput = Omit<
|
|
54
54
|
RunEnvelope,
|
|
55
|
+
| "version"
|
|
55
56
|
| "id"
|
|
56
57
|
| "startedAt"
|
|
57
58
|
| "endedAt"
|
|
@@ -143,6 +144,10 @@ export function listFleetRuns(limit = MAX_FLEET_RUN_SCAN): FleetRunRecord[] {
|
|
|
143
144
|
return records.slice(0, Math.max(0, limit));
|
|
144
145
|
}
|
|
145
146
|
|
|
147
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
148
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
149
|
+
}
|
|
150
|
+
|
|
146
151
|
// `RunEnvelope.heartbeatAt` deliberately persists only the absolute wall-clock
|
|
147
152
|
// anchor used for operator display and crash recovery. The monotonic heartbeat
|
|
148
153
|
// stamp belongs to the live transport in this process; serializing it would
|
|
@@ -152,9 +157,16 @@ function readRuns(): RunEnvelope[] {
|
|
|
152
157
|
if (!existsSync(path)) return [];
|
|
153
158
|
const raw = readFileSync(path, "utf8").trim();
|
|
154
159
|
if (raw.length === 0) return [];
|
|
155
|
-
const parsed = JSON.parse(raw) as
|
|
160
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
156
161
|
if (!Array.isArray(parsed)) return [];
|
|
157
|
-
|
|
162
|
+
const envelopes: RunEnvelope[] = [];
|
|
163
|
+
for (const entry of parsed) {
|
|
164
|
+
if (!isRecord(entry)) continue;
|
|
165
|
+
const version = entry.version === undefined ? 1 : entry.version;
|
|
166
|
+
if (version !== 1) continue;
|
|
167
|
+
envelopes.push({ ...(entry as unknown as RunEnvelope), version: 1 });
|
|
168
|
+
}
|
|
169
|
+
return envelopes;
|
|
158
170
|
}
|
|
159
171
|
|
|
160
172
|
function resolveMaxRuns(opt?: number | undefined): number {
|
|
@@ -241,6 +253,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
|
|
|
241
253
|
return {
|
|
242
254
|
create(input: CreateRunInput): RunEnvelope {
|
|
243
255
|
const envelope: RunEnvelope = {
|
|
256
|
+
version: 1,
|
|
244
257
|
id: input.id ?? newRunId(),
|
|
245
258
|
agentId: input.agentId,
|
|
246
259
|
executionRole: input.executionRole,
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* are pure data: no class methods, no engine refs.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { GatewayRoutingObservation } from "../../core/gateway-routing.js";
|
|
9
10
|
import type { ResponseModelIdObservation } from "../../core/response-model-id.js";
|
|
10
11
|
import type { SkillActivation } from "../../core/skill-activation.js";
|
|
11
12
|
import type { ToolProfileName } from "../../tools/profiles.js";
|
|
13
|
+
import type { DeclaredCheckReport } from "../../tools/verify/scripts.js";
|
|
12
14
|
import type { AgentAudience } from "../agents/spec.js";
|
|
13
15
|
import type { EvidenceTag } from "../evidence/index.js";
|
|
14
16
|
import type { CostProvenance, RuntimeTargetSnapshot } from "../providers/index.js";
|
|
@@ -441,6 +443,7 @@ export interface RunReceiptFindingsSummary {
|
|
|
441
443
|
}
|
|
442
444
|
|
|
443
445
|
export interface RunEnvelope {
|
|
446
|
+
version: 1;
|
|
444
447
|
id: string;
|
|
445
448
|
agentId: string;
|
|
446
449
|
/** Semantic role this attempt's route statistics belong to. */
|
|
@@ -482,6 +485,8 @@ export interface RunEnvelope {
|
|
|
482
485
|
plan?: RunPlanProvenance;
|
|
483
486
|
/** Ad-hoc specialist provenance; present only when a persona override composed the stable prompt. */
|
|
484
487
|
personaOverride?: RunPersonaOverride;
|
|
488
|
+
/** Decision refs active on the parent decision board at dispatch; absent when the board was empty. */
|
|
489
|
+
decisionRefs?: ReadonlyArray<string>;
|
|
485
490
|
exitCode: number | null;
|
|
486
491
|
pid: number | null;
|
|
487
492
|
heartbeatAt: string | null;
|
|
@@ -652,6 +657,8 @@ export interface RunReceiptUpstreamResponse {
|
|
|
652
657
|
responseModelIdObservation: ResponseModelIdObservation;
|
|
653
658
|
differingResponseModelId: string | null;
|
|
654
659
|
providerResponseId: string | null;
|
|
660
|
+
/** Physical route and proxy attempts reported by LiteLLM, when this call used that gateway. */
|
|
661
|
+
gatewayRouting?: GatewayRoutingObservation;
|
|
655
662
|
}
|
|
656
663
|
|
|
657
664
|
/**
|
|
@@ -707,11 +714,14 @@ export interface RunHostVerificationCheck {
|
|
|
707
714
|
check: string;
|
|
708
715
|
argv: string[];
|
|
709
716
|
cwd: string;
|
|
717
|
+
/** For a numeric-compare or perf-budget check, 1 when the judgement failed even though the command exited 0. */
|
|
710
718
|
exitCode: number;
|
|
711
719
|
durationMs: number;
|
|
712
720
|
memo: boolean;
|
|
713
721
|
outputTail: string;
|
|
714
722
|
artifactPath?: string;
|
|
723
|
+
/** Structured verdict of a numeric-compare or perf-budget check; absent for a command check. Covered by the receipt digest through `hostVerification`. */
|
|
724
|
+
report?: DeclaredCheckReport;
|
|
715
725
|
/** Run that owns the evidence when it did not come from this run: a memo hit, or the batch member the shared check ran under. */
|
|
716
726
|
evidenceRunId?: string;
|
|
717
727
|
}
|
|
@@ -808,8 +818,14 @@ export interface RunReceipt {
|
|
|
808
818
|
node?: RunNodeIdentity;
|
|
809
819
|
/**
|
|
810
820
|
* Route and node identity attested by the worker process that executed the
|
|
811
|
-
* run.
|
|
812
|
-
*
|
|
821
|
+
* run. Every native and remote worker transport attests, so a receipt from
|
|
822
|
+
* the worker path carries this field. It is legitimately absent on receipts
|
|
823
|
+
* that no worker process produced: the print-mode main-agent receipt
|
|
824
|
+
* (src/cli/modes/print.ts), which runs in the orchestrator process, and ACP
|
|
825
|
+
* delegation receipts, whose external agent never sends an announce frame.
|
|
826
|
+
* The eval process invariants (src/domains/eval/metrics/invariants.ts) rely
|
|
827
|
+
* on that absence to skip the main-agent path when counting orphaned
|
|
828
|
+
* workers. Contract tests that stub the spawn also leave it absent.
|
|
813
829
|
*/
|
|
814
830
|
attestation?: RunReceiptAttestation;
|
|
815
831
|
/** Dead-node failover hops, oldest first; absent when the run was never rerouted. */
|
|
@@ -825,6 +841,8 @@ export interface RunReceipt {
|
|
|
825
841
|
fleetGate?: { path: string; pathHash: string };
|
|
826
842
|
/** Ad-hoc specialist provenance; present only when a persona override composed the stable prompt. */
|
|
827
843
|
personaOverride?: RunPersonaOverride;
|
|
844
|
+
/** Decision refs active on the parent decision board at dispatch; absent when the board was empty. */
|
|
845
|
+
decisionRefs?: ReadonlyArray<string>;
|
|
828
846
|
/** Effective project-context tier for this run; absent on receipts written before this field landed. */
|
|
829
847
|
projectContext?: RunProjectContextProvenance;
|
|
830
848
|
/**
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ProvidersContract } from "../providers/contract.js";
|
|
2
|
+
|
|
3
|
+
/** Preparation owns its wait; a late HTTP body cannot start an expired worker. */
|
|
4
|
+
export async function prepareWorkerModelMetadata(
|
|
5
|
+
providers: ProvidersContract,
|
|
6
|
+
targetId: string,
|
|
7
|
+
deadlineAt: number,
|
|
8
|
+
signal?: AbortSignal,
|
|
9
|
+
now: () => number = Date.now,
|
|
10
|
+
): Promise<void> {
|
|
11
|
+
signal?.throwIfAborted();
|
|
12
|
+
const status = providers.list().find((entry) => entry.target.id === targetId);
|
|
13
|
+
if (status?.target.runtime !== "litellm" || status.health.lastCheckAt !== null) return;
|
|
14
|
+
const remainingMs = deadlineAt - now();
|
|
15
|
+
const deadlineError = new Error("dispatch: admission deadline expired during worker model metadata preparation");
|
|
16
|
+
if (remainingMs <= 0) throw deadlineError;
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const abort = (): void => controller.abort(signal?.reason);
|
|
19
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
20
|
+
const timer = setTimeout(() => controller.abort(deadlineError), Math.min(remainingMs, 2_147_483_647));
|
|
21
|
+
let rejectAborted!: (reason: unknown) => void;
|
|
22
|
+
const aborted = new Promise<never>((_resolve, reject) => {
|
|
23
|
+
rejectAborted = reject;
|
|
24
|
+
});
|
|
25
|
+
const onAbort = (): void => rejectAborted(controller.signal.reason);
|
|
26
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
27
|
+
try {
|
|
28
|
+
// The provider also fences publication after each await. Promise.race
|
|
29
|
+
// observes the probe's eventual rejection if an HTTP body settles late.
|
|
30
|
+
await Promise.race([providers.probeTarget(targetId, { reasoning: false, signal: controller.signal }), aborted]);
|
|
31
|
+
controller.signal.throwIfAborted();
|
|
32
|
+
if (now() >= deadlineAt) throw deadlineError;
|
|
33
|
+
} finally {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
signal?.removeEventListener("abort", abort);
|
|
36
|
+
controller.signal.removeEventListener("abort", onAbort);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -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 {
|