@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
|
@@ -24,7 +24,7 @@ export const SKILLS_REMINDER_REGISTRATION_ID = "observer.skills-reminder";
|
|
|
24
24
|
|
|
25
25
|
export { SKILL_SUGGESTION_ANCHOR };
|
|
26
26
|
|
|
27
|
-
export function skillsReminderMessage(installed: number, installable = 0): string {
|
|
27
|
+
export function skillsReminderMessage(installed: number, installable = 0, modelActivation = false): string {
|
|
28
28
|
// Unconditional imperative, deliberately: the skill-mastery batteries
|
|
29
29
|
// showed literal local models comply with "list and check" but never act
|
|
30
30
|
// on wording that first asks them to classify the task as skill-shaped.
|
|
@@ -37,6 +37,17 @@ export function skillsReminderMessage(installed: number, installable = 0): strin
|
|
|
37
37
|
// operator" as the whole job, spent a 40-second turn deliberating over the
|
|
38
38
|
// suggestion, and ended without one repository read. The suggestion is one
|
|
39
39
|
// line, the task continues in the same turn, and only the operator loads.
|
|
40
|
+
// At auto-edit and full-auto the model activates installed skills itself,
|
|
41
|
+
// so the reminder must not repeat "only the operator loads a skill": the
|
|
42
|
+
// literal models this line exists for act on it over the listing footer.
|
|
43
|
+
if (modelActivation) {
|
|
44
|
+
return (
|
|
45
|
+
`[Skills] ${counts}. Start this task by listing them with context(scope="skills") ` +
|
|
46
|
+
'and checking for a match; if one matches, load it with context(scope="skills", name="<name>") and ' +
|
|
47
|
+
"continue the task in the same turn. A marketplace skill is not installed and is offered for install " +
|
|
48
|
+
"when the operator runs it. If none match, do not mention skills and continue with the task."
|
|
49
|
+
);
|
|
50
|
+
}
|
|
40
51
|
return (
|
|
41
52
|
`[Skills] ${counts}. Start this task by listing them with context(scope="skills") ` +
|
|
42
53
|
"and checking for a match; if one matches, open your reply with the line " +
|
|
@@ -55,6 +66,12 @@ export interface SkillsReminderDeps {
|
|
|
55
66
|
* zero. Either count above zero arms the reminder.
|
|
56
67
|
*/
|
|
57
68
|
countInstallableSkills?(): number;
|
|
69
|
+
/**
|
|
70
|
+
* True when the session's autonomy level lets the model activate an
|
|
71
|
+
* installed skill itself. Absent reads as false, the operator-gated wording
|
|
72
|
+
* every surface taught before the level became the opt-in.
|
|
73
|
+
*/
|
|
74
|
+
modelMayActivateSkills?(): boolean;
|
|
58
75
|
}
|
|
59
76
|
|
|
60
77
|
const NO_EFFECTS: ReadonlyArray<MiddlewareEffect> = [];
|
|
@@ -211,7 +228,19 @@ export function createSkillsReminderRegistration(deps: SkillsReminderDeps): Midd
|
|
|
211
228
|
return NO_EFFECTS;
|
|
212
229
|
}
|
|
213
230
|
if (installed <= 0 && installable <= 0) return NO_EFFECTS;
|
|
214
|
-
|
|
231
|
+
let modelActivation = false;
|
|
232
|
+
try {
|
|
233
|
+
modelActivation = deps.modelMayActivateSkills?.() ?? false;
|
|
234
|
+
} catch {
|
|
235
|
+
// An unreadable autonomy level falls back to the operator-gated wording.
|
|
236
|
+
}
|
|
237
|
+
return [
|
|
238
|
+
{
|
|
239
|
+
kind: "inject_reminder",
|
|
240
|
+
severity: "info",
|
|
241
|
+
message: skillsReminderMessage(installed, installable, modelActivation),
|
|
242
|
+
},
|
|
243
|
+
];
|
|
215
244
|
},
|
|
216
245
|
};
|
|
217
246
|
}
|
|
@@ -126,12 +126,9 @@ export async function detectMux(options: DetectMuxOptions = {}): Promise<MuxDete
|
|
|
126
126
|
return { detection: none("panes are turned off"), client: null };
|
|
127
127
|
}
|
|
128
128
|
if (enabled === "embedded") {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// mode actually runs. When the guest ladder also fails, that failure is
|
|
133
|
-
// reported on its own terms.
|
|
134
|
-
log("info", "interface.panes.enabled=embedded is not implemented yet; detecting a guest pane host instead");
|
|
129
|
+
const reason = "embedded pane hosting is not implemented; use auto or guest";
|
|
130
|
+
log("warning", reason);
|
|
131
|
+
return { detection: none(reason, [], true), client: null };
|
|
135
132
|
}
|
|
136
133
|
if (env.HERDR_ENV !== "1") {
|
|
137
134
|
return { detection: none("HERDR_ENV is not 1, so Clio is not running inside a pane host"), client: null };
|
|
@@ -27,6 +27,8 @@ export interface AccountabilitySummary {
|
|
|
27
27
|
totalRuns: number;
|
|
28
28
|
firstPassRuns: number;
|
|
29
29
|
firstPassRate: number;
|
|
30
|
+
unverifiedSuccesses: number;
|
|
31
|
+
ungroundedClaims: number;
|
|
30
32
|
failureCauses: ReadonlyArray<{ tag: EvidenceTag; count: number }>;
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -38,9 +40,19 @@ export interface AccountabilitySummary {
|
|
|
38
40
|
export function summarizeEvidenceIndex(rows: ReadonlyArray<EvidenceIndexRow>): AccountabilitySummary {
|
|
39
41
|
const totalRuns = rows.length;
|
|
40
42
|
let firstPassRuns = 0;
|
|
43
|
+
let unverifiedSuccesses = 0;
|
|
44
|
+
let ungroundedClaims = 0;
|
|
41
45
|
const counts = new Map<EvidenceTag, number>();
|
|
42
46
|
for (const row of rows) {
|
|
43
47
|
if (row.firstPassSuccess) firstPassRuns += 1;
|
|
48
|
+
if (
|
|
49
|
+
row.succeeded === true &&
|
|
50
|
+
(row.tags.includes("no-validation") ||
|
|
51
|
+
row.tags.includes("proxy-validation") ||
|
|
52
|
+
row.completionEvidenceWarning === true)
|
|
53
|
+
)
|
|
54
|
+
unverifiedSuccesses += 1;
|
|
55
|
+
ungroundedClaims += row.ungroundedClaims ?? 0;
|
|
44
56
|
for (const tag of row.tags) {
|
|
45
57
|
if (!FAILURE_CAUSE_TAGS.has(tag)) continue;
|
|
46
58
|
counts.set(tag, (counts.get(tag) ?? 0) + 1);
|
|
@@ -53,6 +65,8 @@ export function summarizeEvidenceIndex(rows: ReadonlyArray<EvidenceIndexRow>): A
|
|
|
53
65
|
totalRuns,
|
|
54
66
|
firstPassRuns,
|
|
55
67
|
firstPassRate: totalRuns === 0 ? 0 : firstPassRuns / totalRuns,
|
|
68
|
+
unverifiedSuccesses,
|
|
69
|
+
ungroundedClaims,
|
|
56
70
|
failureCauses,
|
|
57
71
|
};
|
|
58
72
|
}
|
|
@@ -60,7 +74,7 @@ export function summarizeEvidenceIndex(rows: ReadonlyArray<EvidenceIndexRow>): A
|
|
|
60
74
|
/**
|
|
61
75
|
* Read the sidecar index from the state dir and summarize it. Tolerant by way of
|
|
62
76
|
* `readEvidenceIndex`: a missing or corrupt index yields the empty summary
|
|
63
|
-
*
|
|
77
|
+
* with zero counters and an empty failure-cause histogram.
|
|
64
78
|
*/
|
|
65
79
|
export function readAccountabilitySummary(stateDir: string): AccountabilitySummary {
|
|
66
80
|
return summarizeEvidenceIndex(readEvidenceIndex(stateDir));
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/** Preserve spending from summary streams that did not produce a checkpoint. */
|
|
2
|
+
|
|
3
|
+
import type { CompactionCallObservation } from "../session/compaction/compact.js";
|
|
4
|
+
import { extractReasoningTokens } from "../session/context-accounting.js";
|
|
5
|
+
import type { BackgroundMemoryUsageSink } from "./background-memory-usage.js";
|
|
6
|
+
import { appendOutOfTurnUsageRow, type OutOfTurnUsage, type OutOfTurnUsageRow } from "./out-of-turn-usage.js";
|
|
7
|
+
|
|
8
|
+
export interface CompactionUsageOrigin {
|
|
9
|
+
stateDir: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
repoIdentity: string;
|
|
12
|
+
target: string;
|
|
13
|
+
model: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Failed adapter zeros cannot distinguish absent usage from a reported zero. */
|
|
17
|
+
function observedUsage(call: CompactionCallObservation): OutOfTurnUsage {
|
|
18
|
+
const raw = isRecord(call.usage) ? call.usage : {};
|
|
19
|
+
const reading = (value: unknown): number | null =>
|
|
20
|
+
typeof value === "number" && Number.isFinite(value) && value >= 0 && (call.outcome === "success" || value > 0)
|
|
21
|
+
? value
|
|
22
|
+
: null;
|
|
23
|
+
const cost = isRecord(raw.cost) ? reading(raw.cost.total) : null;
|
|
24
|
+
// Adapter cost is a price estimate, not independent provider billing evidence.
|
|
25
|
+
const costUsd = cost !== null && cost > 0 ? cost : null;
|
|
26
|
+
const reasoning = extractReasoningTokens({ ...raw, reasoningTokens: undefined });
|
|
27
|
+
return {
|
|
28
|
+
input: reading(raw.input),
|
|
29
|
+
output: reading(raw.output),
|
|
30
|
+
cacheRead: reading(raw.cacheRead),
|
|
31
|
+
cacheWrite: reading(raw.cacheWrite),
|
|
32
|
+
reasoning: reasoning !== null && reasoning > 0 ? reasoning : null,
|
|
33
|
+
totalTokens: reading(raw.totalTokens),
|
|
34
|
+
costUsd,
|
|
35
|
+
costProvenance: costUsd === null ? "unknown" : "estimated",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The checkpoint is the sole accounting source on success. Call this only when
|
|
41
|
+
* no checkpoint exists; each row is one actual stream invocation, not a retry.
|
|
42
|
+
* Missing amounts remain null on disk. Numeric live counters are known subtotals.
|
|
43
|
+
*/
|
|
44
|
+
export function recordFailedCompactionCalls(
|
|
45
|
+
origin: CompactionUsageOrigin,
|
|
46
|
+
calls: ReadonlyArray<CompactionCallObservation>,
|
|
47
|
+
observability?: BackgroundMemoryUsageSink,
|
|
48
|
+
): void {
|
|
49
|
+
for (const call of calls) {
|
|
50
|
+
const usage = observedUsage(call);
|
|
51
|
+
const row: OutOfTurnUsageRow = {
|
|
52
|
+
label: "failed-compaction",
|
|
53
|
+
callOutcome: call.outcome,
|
|
54
|
+
sessionId: origin.sessionId,
|
|
55
|
+
repoIdentity: origin.repoIdentity,
|
|
56
|
+
timestamp: call.timestamp,
|
|
57
|
+
target: origin.target,
|
|
58
|
+
attributedModelId: origin.model,
|
|
59
|
+
usage,
|
|
60
|
+
timing: { durationMs: call.durationMs },
|
|
61
|
+
};
|
|
62
|
+
appendOutOfTurnUsageRow(origin.stateDir, row, { required: true });
|
|
63
|
+
// Do not create a measured-zero live entry for a wholly unobserved call.
|
|
64
|
+
if (!Object.values(usage).some((value) => typeof value === "number" && value > 0)) continue;
|
|
65
|
+
observability?.recordTokens(
|
|
66
|
+
origin.target,
|
|
67
|
+
origin.model,
|
|
68
|
+
usage.totalTokens ?? 0,
|
|
69
|
+
usage.costUsd ?? 0,
|
|
70
|
+
{
|
|
71
|
+
input: usage.input ?? 0,
|
|
72
|
+
output: usage.output ?? 0,
|
|
73
|
+
cacheRead: usage.cacheRead ?? 0,
|
|
74
|
+
cacheWrite: usage.cacheWrite ?? 0,
|
|
75
|
+
reasoningTokens: usage.reasoning ?? 0,
|
|
76
|
+
totalTokens: usage.totalTokens ?? 0,
|
|
77
|
+
apiCalls: 1,
|
|
78
|
+
},
|
|
79
|
+
usage.costProvenance,
|
|
80
|
+
undefined,
|
|
81
|
+
"failed-compaction",
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
87
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const USAGE_FIELDS = ["input", "output", "cacheRead", "cacheWrite", "reasoning", "totalTokens", "costUsd"] as const;
|
|
91
|
+
type UsageField = (typeof USAGE_FIELDS)[number];
|
|
92
|
+
|
|
93
|
+
/** Known subtotals and missing-field coverage; zero missing values are never inferred. */
|
|
94
|
+
export function summarizeFailedCompactionUsage(rows: ReadonlyArray<OutOfTurnUsageRow>) {
|
|
95
|
+
const calls = rows.filter((row) => row.label === "failed-compaction");
|
|
96
|
+
const knownUsage = Object.fromEntries(USAGE_FIELDS.map((field) => [field, null])) as Record<UsageField, number | null>;
|
|
97
|
+
const erroredKnownUsage = { ...knownUsage };
|
|
98
|
+
const unobservedUsageCalls = Object.fromEntries(USAGE_FIELDS.map((field) => [field, 0])) as Record<UsageField, number>;
|
|
99
|
+
for (const row of calls) {
|
|
100
|
+
for (const field of USAGE_FIELDS) {
|
|
101
|
+
const value = row.usage[field];
|
|
102
|
+
if (value === null) unobservedUsageCalls[field] += 1;
|
|
103
|
+
else {
|
|
104
|
+
knownUsage[field] = (knownUsage[field] ?? 0) + value;
|
|
105
|
+
if (row.callOutcome === "error") erroredKnownUsage[field] = (erroredKnownUsage[field] ?? 0) + value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
calls: calls.length,
|
|
111
|
+
successfulCalls: calls.filter((row) => row.callOutcome === "success").length,
|
|
112
|
+
erroredCalls: calls.filter((row) => row.callOutcome === "error").length,
|
|
113
|
+
abortedCalls: calls.filter((row) => row.callOutcome === "aborted").length,
|
|
114
|
+
knownUsage,
|
|
115
|
+
erroredKnownUsage,
|
|
116
|
+
unobservedUsageCalls,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { ResponseModelIdObservationCounts } from "../../core/response-model-id.js";
|
|
2
|
+
import type { AgentAudience } from "../agents/spec.js";
|
|
3
|
+
import type { RunToolBudgetEnvelope } from "../dispatch/budget-envelope.js";
|
|
4
|
+
import type { DispatchSnapshot } from "../dispatch/contract.js";
|
|
5
|
+
import type { DispatchRequestOrigin, RunKind } from "../dispatch/types.js";
|
|
6
|
+
import type { TrustSummaryProjection } from "../evidence/trust-projection.js";
|
|
7
|
+
import type { CanonicalTrustStatus } from "../evidence/trust-status.js";
|
|
2
8
|
import type { TargetStatus } from "../providers/contract.js";
|
|
3
9
|
import type { CostProvenance } from "../providers/index.js";
|
|
4
10
|
import type { AccountabilitySummary } from "./accountability.js";
|
|
@@ -6,6 +12,7 @@ import type { CostAggregate, CostEntry, CostEntryLabel, UsageBreakdown } from ".
|
|
|
6
12
|
import type { MetricsView } from "./metrics.js";
|
|
7
13
|
import type { TelemetrySnapshot } from "./telemetry.js";
|
|
8
14
|
import type { SessionTurnTrace } from "./trace-store.js";
|
|
15
|
+
import type { WorkerProgressSnapshot } from "./worker-progress.js";
|
|
9
16
|
|
|
10
17
|
export interface TokenThroughputSnapshot {
|
|
11
18
|
tokensPerSecond: number;
|
|
@@ -41,9 +48,9 @@ export interface ObservabilityNotice {
|
|
|
41
48
|
|
|
42
49
|
/**
|
|
43
50
|
* Compact lifecycle summary for a recent dispatch run. Projected from the
|
|
44
|
-
* dispatch bus channels;
|
|
45
|
-
*
|
|
46
|
-
* forensic bundle for the run finalizes.
|
|
51
|
+
* dispatch bus channels; raw tool arguments and reasoning are absent. Worker
|
|
52
|
+
* progress is a bounded, redacted presentation of the live stream. `evidence`
|
|
53
|
+
* is populated asynchronously once the forensic bundle for the run finalizes.
|
|
47
54
|
*/
|
|
48
55
|
export interface ObservabilityRunSummary {
|
|
49
56
|
runId: string;
|
|
@@ -51,8 +58,29 @@ export interface ObservabilityRunSummary {
|
|
|
51
58
|
targetId?: string;
|
|
52
59
|
modelId?: string;
|
|
53
60
|
runtimeId?: string;
|
|
54
|
-
runtimeKind?:
|
|
55
|
-
status: "enqueued" | "running" | "completed" | "failed" | "aborted" | "dead" | "stale";
|
|
61
|
+
runtimeKind?: RunKind;
|
|
62
|
+
status: "enqueued" | "running" | "completed" | "failed" | "aborted" | "dead" | "stale" | "cancelling" | "retrying";
|
|
63
|
+
agentAudience?: AgentAudience;
|
|
64
|
+
requestOrigin?: DispatchRequestOrigin;
|
|
65
|
+
endpoint?: { key: string; label: string; limit: number };
|
|
66
|
+
taskSummary?: string;
|
|
67
|
+
budget?: RunToolBudgetEnvelope;
|
|
68
|
+
ttftMs?: number | null;
|
|
69
|
+
node?: string;
|
|
70
|
+
gate?: { role: string; cycle: number };
|
|
71
|
+
council?: { group: string; label: string; color?: string; round: number };
|
|
72
|
+
hostVerification?: "verified" | "rejected" | "skipped" | "not_implicated";
|
|
73
|
+
trust?: TrustSummaryProjection;
|
|
74
|
+
rerouteCount?: number;
|
|
75
|
+
failoverHops?: number;
|
|
76
|
+
contextWindow?: number;
|
|
77
|
+
lastContextTokens?: number;
|
|
78
|
+
progress?: WorkerProgressSnapshot;
|
|
79
|
+
receiptId?: string;
|
|
80
|
+
retry?: { attempt: number; dueAtMs: number; reason: string };
|
|
81
|
+
steerAcknowledgement?: { receivedAtMs: number; chars: number };
|
|
82
|
+
writeRecordDowngrade?: { reason: "opaque_tool_succeeded"; tool: string; toolCallId: string };
|
|
83
|
+
phase?: { wave: number; stepId: string };
|
|
56
84
|
startedAtMs: number;
|
|
57
85
|
updatedAtMs: number;
|
|
58
86
|
finishedAtMs: number | null;
|
|
@@ -101,7 +129,23 @@ export interface ObservabilitySnapshot {
|
|
|
101
129
|
pendingEvidenceBuildRunIds: readonly string[];
|
|
102
130
|
}
|
|
103
131
|
|
|
104
|
-
|
|
132
|
+
/** Runtime readers supplied after dispatch is composed, avoiding a domain dependency cycle. */
|
|
133
|
+
export interface ObservabilityRunReaders {
|
|
134
|
+
dispatchSnapshot?: () => DispatchSnapshot;
|
|
135
|
+
readReceipt?: (runId: string) => { text?: string; trust?: CanonicalTrustStatus } | null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Run projection controls shared by the contract and the in-memory projection. */
|
|
139
|
+
export interface ObservabilityRunProjection {
|
|
140
|
+
/** Bind live dispatch and receipt readers; disposal detaches this binding only. */
|
|
141
|
+
bindRunReaders(readers: ObservabilityRunReaders): () => void;
|
|
142
|
+
/** Fold retry timers and live counters from the dispatch reader. */
|
|
143
|
+
reconcileRuns(): void;
|
|
144
|
+
/** Record an explicit fleet position, including before a run's first event. */
|
|
145
|
+
setFleetPhase(runId: string, phase: NonNullable<ObservabilityRunSummary["phase"]>): void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface ObservabilityContract extends ObservabilityRunProjection {
|
|
105
149
|
/** Raw counter + histogram view. */
|
|
106
150
|
telemetry(): TelemetrySnapshot;
|
|
107
151
|
/** Aggregated view the TUI consumes. */
|
|
@@ -114,7 +158,8 @@ export interface ObservabilityContract {
|
|
|
114
158
|
/** Running session cost log entries. */
|
|
115
159
|
costEntries(): ReadonlyArray<CostEntry>;
|
|
116
160
|
/**
|
|
117
|
-
* Rolling first-pass-success rate
|
|
161
|
+
* Rolling first-pass-success rate, unverified successes, ungrounded claims,
|
|
162
|
+
* and failure-cause histogram, aggregated
|
|
118
163
|
* from the sidecar evidence index on call. Read-only: it folds rows Slice 2
|
|
119
164
|
* already wrote and recomputes no evidence.
|
|
120
165
|
*/
|
|
@@ -137,7 +137,7 @@ export interface UsageBreakdown {
|
|
|
137
137
|
* the usage surfaces separate these out so an operator can see that money was
|
|
138
138
|
* spent beside the session rather than inside it.
|
|
139
139
|
*/
|
|
140
|
-
export type CostEntryLabel = "side-question" | "handoff" | "prewarm" | "background-memory";
|
|
140
|
+
export type CostEntryLabel = "side-question" | "handoff" | "prewarm" | "background-memory" | "failed-compaction";
|
|
141
141
|
|
|
142
142
|
export interface CostEntry {
|
|
143
143
|
providerId: string;
|
|
@@ -42,6 +42,10 @@ export interface EvidenceIndexRow {
|
|
|
42
42
|
tags: EvidenceTag[];
|
|
43
43
|
firstPassSuccess: boolean;
|
|
44
44
|
findingCount: number;
|
|
45
|
+
/** Absent on historical rows; never infer success from firstPassSuccess. */
|
|
46
|
+
succeeded?: boolean;
|
|
47
|
+
completionEvidenceWarning?: boolean;
|
|
48
|
+
ungroundedClaims?: number;
|
|
45
49
|
/** ISO-8601 timestamp the row was written. */
|
|
46
50
|
generatedAt: string;
|
|
47
51
|
}
|
|
@@ -60,6 +64,12 @@ function isEvidenceIndexRow(value: unknown): value is EvidenceIndexRow {
|
|
|
60
64
|
row.tags.every((tag) => typeof tag === "string") &&
|
|
61
65
|
typeof row.firstPassSuccess === "boolean" &&
|
|
62
66
|
typeof row.findingCount === "number" &&
|
|
67
|
+
(row.succeeded === undefined || typeof row.succeeded === "boolean") &&
|
|
68
|
+
(row.completionEvidenceWarning === undefined || typeof row.completionEvidenceWarning === "boolean") &&
|
|
69
|
+
(row.ungroundedClaims === undefined ||
|
|
70
|
+
(typeof row.ungroundedClaims === "number" &&
|
|
71
|
+
Number.isSafeInteger(row.ungroundedClaims) &&
|
|
72
|
+
row.ungroundedClaims >= 0)) &&
|
|
63
73
|
typeof row.generatedAt === "string"
|
|
64
74
|
);
|
|
65
75
|
}
|
|
@@ -37,6 +37,11 @@ type DispatchTerminalLike = {
|
|
|
37
37
|
[K in keyof DispatchCompletedPayload]?: DispatchCompletedPayload[K] | undefined;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
/** Pre-admission failures have an announced run id but never create a run ledger. */
|
|
41
|
+
export function dispatchHasEvidenceLedger(payload: DispatchTerminalLike): boolean {
|
|
42
|
+
return payload.lineage !== undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
function recordDispatchCost(
|
|
41
46
|
telemetry: ReturnType<typeof createTelemetry>,
|
|
42
47
|
cost: ReturnType<typeof createCostTracker>,
|
|
@@ -125,6 +130,11 @@ function evidenceIndexRow(
|
|
|
125
130
|
tags: [...tags],
|
|
126
131
|
firstPassSuccess,
|
|
127
132
|
findingCount: result.findings.length,
|
|
133
|
+
succeeded,
|
|
134
|
+
completionEvidenceWarning: result.findings.some(
|
|
135
|
+
(finding) => finding.tag === "completion-evidence" && finding.severity === "warn",
|
|
136
|
+
),
|
|
137
|
+
ungroundedClaims: result.ungroundedClaims,
|
|
128
138
|
generatedAt: new Date().toISOString(),
|
|
129
139
|
};
|
|
130
140
|
}
|
|
@@ -173,11 +183,7 @@ export function createObservabilityBundle(
|
|
|
173
183
|
projection.evidenceBuildStarted(runId);
|
|
174
184
|
const build = buildAndIndexEvidence(runId, succeeded, attempt, {
|
|
175
185
|
onReady: (id, evidence) => {
|
|
176
|
-
projection
|
|
177
|
-
// The same fact, once, for listeners outside this closure (the ACP
|
|
178
|
-
// server forwards it as the opt-in `accountability.evidenceReady`
|
|
179
|
-
// kind). The payload spreads the evidence object the projection just
|
|
180
|
-
// received rather than rebuilding it, so the two cannot drift.
|
|
186
|
+
// The projection and ACP consume the same evidence-ready event.
|
|
181
187
|
context.bus.emit(BusChannels.AccountabilityEvidenceReady, { runId: id, ...evidence });
|
|
182
188
|
},
|
|
183
189
|
onFailed: (id, message) => projection.evidenceBuildFailed(id, message),
|
|
@@ -222,7 +228,7 @@ export function createObservabilityBundle(
|
|
|
222
228
|
recordDispatchCost(telemetry, cost, payload);
|
|
223
229
|
// A failed run is never a first-pass success; still build the
|
|
224
230
|
// bundle so its failure-cause tags exist for the index.
|
|
225
|
-
if (typeof payload.runId === "string" && payload.runId.length > 0) {
|
|
231
|
+
if (typeof payload.runId === "string" && payload.runId.length > 0 && dispatchHasEvidenceLedger(payload)) {
|
|
226
232
|
trackBuild(payload.runId, false, payload.lineage?.attempt);
|
|
227
233
|
}
|
|
228
234
|
}),
|
|
@@ -281,6 +287,9 @@ export function createObservabilityBundle(
|
|
|
281
287
|
telemetry.record("histogram", "tokens.ttft_ms", snapshot.ttftMs ?? 0);
|
|
282
288
|
projection.refresh();
|
|
283
289
|
},
|
|
290
|
+
bindRunReaders: (readers) => projection.bindRunReaders(readers),
|
|
291
|
+
reconcileRuns: () => projection.reconcileRuns(),
|
|
292
|
+
setFleetPhase: (runId, phase) => projection.setFleetPhase(runId, phase),
|
|
284
293
|
snapshot: () => projection.snapshot(),
|
|
285
294
|
subscribe: (listener) => projection.subscribe(listener),
|
|
286
295
|
};
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* skipped, never fatal.
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import { closeSync, mkdirSync, openSync, readFileSync, writeSync } from "node:fs";
|
|
30
|
+
import { closeSync, fsyncSync, mkdirSync, openSync, readFileSync, writeSync } from "node:fs";
|
|
31
31
|
import { dirname, join } from "node:path";
|
|
32
32
|
import { safeResourceWrite } from "../../core/safe-resource-write.js";
|
|
33
33
|
import { withStateFileLockSync } from "../../core/state-file-lock.js";
|
|
@@ -74,13 +74,13 @@ export interface OutOfTurnPromptCache {
|
|
|
74
74
|
|
|
75
75
|
/** Provider-reported usage for one out-of-turn call. */
|
|
76
76
|
export interface OutOfTurnUsage {
|
|
77
|
-
input: number;
|
|
78
|
-
output: number;
|
|
79
|
-
cacheRead: number;
|
|
80
|
-
cacheWrite: number;
|
|
81
|
-
reasoning: number;
|
|
82
|
-
totalTokens: number;
|
|
83
|
-
costUsd: number;
|
|
77
|
+
input: number | null;
|
|
78
|
+
output: number | null;
|
|
79
|
+
cacheRead: number | null;
|
|
80
|
+
cacheWrite: number | null;
|
|
81
|
+
reasoning: number | null;
|
|
82
|
+
totalTokens: number | null;
|
|
83
|
+
costUsd: number | null;
|
|
84
84
|
costProvenance: CostProvenance;
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -97,6 +97,8 @@ export interface OutOfTurnUsageRow {
|
|
|
97
97
|
target: string;
|
|
98
98
|
attributedModelId: string;
|
|
99
99
|
usage: OutOfTurnUsage;
|
|
100
|
+
/** New failed-compaction rows preserve unknown usage as null. Legacy rows are unchanged. */
|
|
101
|
+
callOutcome?: "success" | "error" | "aborted";
|
|
100
102
|
/** Present when the caller measured the call. */
|
|
101
103
|
timing?: OutOfTurnTiming;
|
|
102
104
|
/** Present when the serving backend reported prefill facts. */
|
|
@@ -115,21 +117,31 @@ export function outOfTurnUsagePath(stateDir: string): string {
|
|
|
115
117
|
let appendsSinceBoundCheck = BOUND_CHECK_INTERVAL;
|
|
116
118
|
|
|
117
119
|
/**
|
|
118
|
-
* Append one
|
|
119
|
-
*
|
|
120
|
-
*
|
|
120
|
+
* Append one out-of-turn call. Optional bookkeeping keeps its existing diagnostic
|
|
121
|
+
* write policy. Required failed-compaction records flush the append and throw on
|
|
122
|
+
* a failed or incomplete write, so their caller cannot report recorded spending.
|
|
121
123
|
*/
|
|
122
|
-
export function appendOutOfTurnUsageRow(
|
|
124
|
+
export function appendOutOfTurnUsageRow(
|
|
125
|
+
stateDir: string,
|
|
126
|
+
row: OutOfTurnUsageRow,
|
|
127
|
+
options: { required?: boolean } = {},
|
|
128
|
+
): void {
|
|
123
129
|
const path = outOfTurnUsagePath(stateDir);
|
|
124
130
|
try {
|
|
125
131
|
mkdirSync(dirname(path), { recursive: true });
|
|
126
132
|
const fd = openSync(path, "a");
|
|
127
133
|
try {
|
|
128
|
-
|
|
134
|
+
const line = `${JSON.stringify(row)}\n`;
|
|
135
|
+
const written = writeSync(fd, line);
|
|
136
|
+
if (options.required) {
|
|
137
|
+
if (written !== Buffer.byteLength(line)) throw new Error("incomplete usage row write");
|
|
138
|
+
fsyncSync(fd);
|
|
139
|
+
}
|
|
129
140
|
} finally {
|
|
130
141
|
closeSync(fd);
|
|
131
142
|
}
|
|
132
143
|
} catch (error) {
|
|
144
|
+
if (options.required) throw new Error(`compaction usage row not written: ${messageOf(error)}`, { cause: error });
|
|
133
145
|
process.stderr.write(`[clio-coder:usage] out-of-turn usage row not written: ${messageOf(error)}\n`);
|
|
134
146
|
return;
|
|
135
147
|
}
|
|
@@ -205,11 +217,25 @@ export function readOutOfTurnUsageRows(stateDir: string): OutOfTurnUsageReadResu
|
|
|
205
217
|
function asOutOfTurnUsageRow(value: unknown): OutOfTurnUsageRow | null {
|
|
206
218
|
if (!isRecord(value)) return null;
|
|
207
219
|
const label = value.label;
|
|
208
|
-
if (
|
|
220
|
+
if (
|
|
221
|
+
label !== "side-question" &&
|
|
222
|
+
label !== "handoff" &&
|
|
223
|
+
label !== "prewarm" &&
|
|
224
|
+
label !== "background-memory" &&
|
|
225
|
+
label !== "failed-compaction"
|
|
226
|
+
)
|
|
209
227
|
return null;
|
|
210
228
|
if (typeof value.timestamp !== "string" || value.timestamp.length === 0) return null;
|
|
211
229
|
if (!isRecord(value.usage)) return null;
|
|
212
230
|
const usage = value.usage;
|
|
231
|
+
if (
|
|
232
|
+
label === "failed-compaction" &&
|
|
233
|
+
value.callOutcome !== "success" &&
|
|
234
|
+
value.callOutcome !== "error" &&
|
|
235
|
+
value.callOutcome !== "aborted"
|
|
236
|
+
)
|
|
237
|
+
return null;
|
|
238
|
+
const reading = label === "failed-compaction" ? nullableNumber : numberOr0;
|
|
213
239
|
const timing = asTiming(value.timing);
|
|
214
240
|
const promptCache = asPromptCache(value.promptCache);
|
|
215
241
|
return {
|
|
@@ -223,15 +249,16 @@ function asOutOfTurnUsageRow(value: unknown): OutOfTurnUsageRow | null {
|
|
|
223
249
|
? value.attributedModelId
|
|
224
250
|
: "unknown",
|
|
225
251
|
usage: {
|
|
226
|
-
input:
|
|
227
|
-
output:
|
|
228
|
-
cacheRead:
|
|
229
|
-
cacheWrite:
|
|
230
|
-
reasoning:
|
|
231
|
-
totalTokens:
|
|
232
|
-
costUsd:
|
|
252
|
+
input: reading(usage.input),
|
|
253
|
+
output: reading(usage.output),
|
|
254
|
+
cacheRead: reading(usage.cacheRead),
|
|
255
|
+
cacheWrite: reading(usage.cacheWrite),
|
|
256
|
+
reasoning: reading(usage.reasoning),
|
|
257
|
+
totalTokens: reading(usage.totalTokens),
|
|
258
|
+
costUsd: reading(usage.costUsd),
|
|
233
259
|
costProvenance: asCostProvenance(usage.costProvenance),
|
|
234
260
|
},
|
|
261
|
+
...(label === "failed-compaction" ? { callOutcome: value.callOutcome as "success" | "error" | "aborted" } : {}),
|
|
235
262
|
...(timing === null ? {} : { timing }),
|
|
236
263
|
...(promptCache === null ? {} : { promptCache }),
|
|
237
264
|
};
|
|
@@ -259,6 +286,10 @@ function asCostProvenance(value: unknown): CostProvenance {
|
|
|
259
286
|
return value === "known" || value === "known_free" || value === "estimated" ? value : "unknown";
|
|
260
287
|
}
|
|
261
288
|
|
|
289
|
+
function nullableNumber(value: unknown): number | null {
|
|
290
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
291
|
+
}
|
|
292
|
+
|
|
262
293
|
function numberOr0(value: unknown): number {
|
|
263
294
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
264
295
|
}
|