@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.
Files changed (523) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/CONTRIBUTING.md +86 -19
  3. package/README.md +35 -6
  4. package/dist/{acp-TMDQZDIG.js → acp-WNAYYF4F.js} +12 -13
  5. package/dist/{agents-5N5NG3XG.js → agents-3OKXHLOI.js} +60 -57
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-Z5CCBXKQ.js → auth-VKNNMGPU.js} +21 -19
  8. package/dist/{builtins-K6TNDT24.js → builtins-WGALA46I.js} +9 -4
  9. package/dist/{chunk-XE3PCIXH.js → chunk-23L32XTI.js} +12 -9
  10. package/dist/{chunk-I64IFBLB.js → chunk-25QBEXRS.js} +18 -11
  11. package/dist/{chunk-CDNVLKUX.js → chunk-26QSH3EJ.js} +13 -7
  12. package/dist/{chunk-QQLGQY2A.js → chunk-2ASED4PZ.js} +22 -22
  13. package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
  14. package/dist/chunk-2DSOYNFC.js +108 -0
  15. package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
  16. package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
  17. package/dist/{chunk-O3YUNJZ2.js → chunk-2ZSONWVL.js} +82 -25
  18. package/dist/{chunk-2NHR3NAY.js → chunk-36CT5VVL.js} +331 -42
  19. package/dist/{chunk-2X4RYJTJ.js → chunk-3GY4F45V.js} +3 -3
  20. package/dist/{chunk-ZW55JB7N.js → chunk-3ODX73FK.js} +4 -6
  21. package/dist/{chunk-PBP4B7XR.js → chunk-3UNOLWNZ.js} +3 -3
  22. package/dist/{chunk-4JDLP6ZS.js → chunk-3UUXNFEX.js} +14 -10
  23. package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
  24. package/dist/{chunk-ZW4HH5JJ.js → chunk-4M6Z5QVF.js} +6 -6
  25. package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
  26. package/dist/{chunk-M2DAX4F6.js → chunk-4WR7VSYB.js} +2 -2
  27. package/dist/{chunk-FSP7CMNU.js → chunk-54X7T7DK.js} +61 -6
  28. package/dist/{chunk-54ODD65L.js → chunk-5636DCO5.js} +4 -4
  29. package/dist/chunk-57XXR6DR.js +3763 -0
  30. package/dist/{chunk-3KIPBMUA.js → chunk-5ICU3EUH.js} +2 -2
  31. package/dist/{chunk-77QIVUZB.js → chunk-5MEZN6CB.js} +4 -4
  32. package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
  33. package/dist/{chunk-YJISEZKC.js → chunk-5TUB6SLS.js} +6 -6
  34. package/dist/{chunk-IMXMHHMQ.js → chunk-6OSVSQL5.js} +341 -57
  35. package/dist/{chunk-Q4XWMHX6.js → chunk-6PAZTBPA.js} +14 -2
  36. package/dist/{chunk-FVDGR2ZL.js → chunk-6Q3CYFD3.js} +112 -39
  37. package/dist/{chunk-IDNA72AH.js → chunk-6QOTUPRG.js} +155 -36
  38. package/dist/{chunk-X7IARSHT.js → chunk-6UINWWS6.js} +16 -10
  39. package/dist/{chunk-CYZW7JHJ.js → chunk-72YIHOZQ.js} +9 -9
  40. package/dist/{chunk-IKSLQ4XV.js → chunk-75W7L2E2.js} +752 -861
  41. package/dist/{chunk-CRFOIAX3.js → chunk-7UGL4MB5.js} +6 -6
  42. package/dist/{chunk-HIICAHCJ.js → chunk-AUPNRN7C.js} +2 -2
  43. package/dist/{chunk-7BHIY2MW.js → chunk-BJVFZO5U.js} +8 -50
  44. package/dist/{chunk-B74PXLU7.js → chunk-CUSRQKPU.js} +65 -3
  45. package/dist/chunk-DQOVN6KV.js +386 -0
  46. package/dist/{chunk-E7GT7O5N.js → chunk-DT3LWJOB.js} +7 -4
  47. package/dist/chunk-DXKJURES.js +671 -0
  48. package/dist/{chunk-JBCS7CRR.js → chunk-EL24TAU4.js} +10 -10
  49. package/dist/{chunk-TPEQIQIE.js → chunk-ELWDPP3Y.js} +8 -8
  50. package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
  51. package/dist/chunk-EXLD33WO.js +381 -0
  52. package/dist/chunk-FEAXX7B6.js +101 -0
  53. package/dist/{chunk-RLYRBIYQ.js → chunk-FFUPXJC4.js} +90 -331
  54. package/dist/{chunk-5PFYMY2V.js → chunk-FTMGRKEF.js} +2 -2
  55. package/dist/{chunk-34BHNEE3.js → chunk-GHS5EBTQ.js} +58 -7
  56. package/dist/{chunk-DYHAXKHD.js → chunk-GWZNEVM2.js} +12 -8
  57. package/dist/chunk-GX5WYQO4.js +59 -0
  58. package/dist/chunk-GYV6VZOC.js +26 -0
  59. package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
  60. package/dist/chunk-I2DWJ4GM.js +390 -0
  61. package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
  62. package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
  63. package/dist/{chunk-XQRY4DTA.js → chunk-IGLP3ODT.js} +10 -10
  64. package/dist/chunk-IRXAATOX.js +539 -0
  65. package/dist/chunk-IXIY2H4R.js +44 -0
  66. package/dist/{chunk-SSEYRH53.js → chunk-IZXGRF7P.js} +92 -147
  67. package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
  68. package/dist/{chunk-JWJGP5DQ.js → chunk-JEIYHLOR.js} +7 -7
  69. package/dist/{chunk-F2I26BDK.js → chunk-JQLNNIKT.js} +4 -4
  70. package/dist/{chunk-BYMNWQ7O.js → chunk-JSD46VO2.js} +315 -63
  71. package/dist/{chunk-AK5XEFVZ.js → chunk-JT2RFCC5.js} +64 -14
  72. package/dist/{chunk-MCMZMDAC.js → chunk-K6T2ZAMZ.js} +168 -6
  73. package/dist/{chunk-PGF63K6I.js → chunk-KFV5L5SK.js} +73 -4
  74. package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
  75. package/dist/{chunk-PJX3WQUQ.js → chunk-LLXSDWXS.js} +3 -3
  76. package/dist/{chunk-DZAW46HP.js → chunk-LTIKRKFL.js} +3 -3
  77. package/dist/{chunk-DZEK6CJN.js → chunk-N56KALIC.js} +21 -21
  78. package/dist/{chunk-B7HM5Z7T.js → chunk-NAI6ZFCY.js} +9 -5
  79. package/dist/{chunk-I66ZTYNP.js → chunk-NRO2BJRH.js} +2656 -2213
  80. package/dist/{chunk-ZGNYYXQ6.js → chunk-NXIMQY5W.js} +3 -3
  81. package/dist/{chunk-IKOZFYBN.js → chunk-NXYCB2VD.js} +149 -106
  82. package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
  83. package/dist/{chunk-462T4EGZ.js → chunk-O5CVSAG5.js} +2 -2
  84. package/dist/chunk-ODGTEFFI.js +50 -0
  85. package/dist/{chunk-3F7VUY77.js → chunk-OEJSLEPW.js} +2 -2
  86. package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
  87. package/dist/{chunk-5KW52TEP.js → chunk-Q4WO54TA.js} +132 -77
  88. package/dist/{chunk-W6NIE6OW.js → chunk-QUFRYSWI.js} +13 -7
  89. package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
  90. package/dist/chunk-R6Q67RJH.js +134 -0
  91. package/dist/{chunk-W4YEMFBX.js → chunk-RAY4OVGZ.js} +3 -3
  92. package/dist/{chunk-ZNT2M6TG.js → chunk-RQCKCSRL.js} +17 -17
  93. package/dist/{chunk-LJID3DYZ.js → chunk-RXTN6AKH.js} +3 -3
  94. package/dist/{chunk-P75RZCJW.js → chunk-RZDWV63N.js} +3 -3
  95. package/dist/{chunk-UH632ZYL.js → chunk-S6PYF2XF.js} +2 -2
  96. package/dist/{chunk-HJWWJ6IL.js → chunk-TOIVGRUX.js} +17 -5
  97. package/dist/{chunk-HLAFFSEK.js → chunk-TQAHXW6Y.js} +2 -2
  98. package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
  99. package/dist/{chunk-2HFQNRV3.js → chunk-UEPWCCTY.js} +12 -12
  100. package/dist/chunk-UOIZ7DA4.js +41 -0
  101. package/dist/{chunk-UH347SHR.js → chunk-USR47QNF.js} +11 -11
  102. package/dist/{chunk-AZ4WMN4W.js → chunk-V6HJFQZE.js} +2 -2
  103. package/dist/chunk-V76WTFTW.js +318 -0
  104. package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
  105. package/dist/{chunk-KPXDY6QF.js → chunk-XRZT5WY5.js} +2 -2
  106. package/dist/{chunk-UBRFI4HS.js → chunk-XULDXHTN.js} +142 -50
  107. package/dist/chunk-XXYSBZIQ.js +283 -0
  108. package/dist/{chunk-HKMD33FO.js → chunk-Y55JBDO5.js} +405 -122
  109. package/dist/{chunk-XOXV5GKE.js → chunk-YD5GIKET.js} +17 -8
  110. package/dist/{chunk-XGDPUNND.js → chunk-YECAMM3D.js} +2 -2
  111. package/dist/{chunk-BO7Y52RY.js → chunk-YNFKXPEC.js} +7 -7
  112. package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
  113. package/dist/{chunk-M2WXEHER.js → chunk-ZA4VCIGV.js} +2 -2
  114. package/dist/cli/index.js +42 -40
  115. package/dist/{clio-7VB377CC.js → clio-QLICPCF5.js} +7 -7
  116. package/dist/{code-nav-YVLCYA7V.js → code-nav-IJR2DBPR.js} +9 -9
  117. package/dist/{components-UBWCQSRW.js → components-2TGAI2RC.js} +5 -6
  118. package/dist/{config-4HVOS65E.js → config-IUA6OYNS.js} +88 -81
  119. package/dist/{configure-PIWO7B24.js → configure-VEPX4NMX.js} +26 -25
  120. package/dist/{context-KQYIWPWT.js → context-2DKHWH2T.js} +60 -45
  121. package/dist/{context-IYEHL3WQ.js → context-4MPR7WKB.js} +78 -69
  122. package/dist/{context-N6ZE3LGJ.js → context-BOYF5EJM.js} +15 -11
  123. package/dist/{context-clear-G4OGZJDS.js → context-clear-S4ZJCQUX.js} +73 -65
  124. package/dist/context-map-COB37XXN.js +505 -0
  125. package/dist/{context-working-set-BWLF6LJP.js → context-working-set-3I3FYX6Y.js} +18 -17
  126. package/dist/detail-A7JAVSIG.js +98 -0
  127. package/dist/{dispatch-runner-2QQAITS3.js → dispatch-runner-RJ5I2F2O.js} +99 -75
  128. package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
  129. package/dist/{doctor-LHBD36VU.js → doctor-DKICC2SN.js} +71 -48
  130. package/dist/{eval-C45FYRJ6.js → eval-OQOQUDHK.js} +308 -146
  131. package/dist/{eval-inventory-6DEJPLBF.js → eval-inventory-Y6QRFOH5.js} +4 -4
  132. package/dist/{evidence-6SHONYAF.js → evidence-4DQ25GUQ.js} +79 -175
  133. package/dist/evidence-4F5USFKH.js +208 -0
  134. package/dist/{evolve-KRKMV72X.js → evolve-GSS52E5J.js} +71 -67
  135. package/dist/{extensions-KPZ2UHBB.js → extensions-G7MFLYHT.js} +8 -9
  136. package/dist/{fleet-IVTCKDHT.js → fleet-Q37YHHAQ.js} +126 -118
  137. package/dist/{fleet-commands-EDWL3IT7.js → fleet-commands-G7E4N7SM.js} +16 -13
  138. package/dist/{fleet-decisions-YP3YEFGK.js → fleet-decisions-O7M6QBA2.js} +9 -8
  139. package/dist/{fleet-graph-ZFWKHY2M.js → fleet-graph-TOUBW6OW.js} +21 -20
  140. package/dist/{fleet-inspect-FVUNCBML.js → fleet-inspect-SW33JJNI.js} +65 -60
  141. package/dist/{fleet-preflight-UN5XED4R.js → fleet-preflight-CV2655TW.js} +4 -5
  142. package/dist/{fleet-validate-XOWC4HSX.js → fleet-validate-KESZX2YH.js} +25 -24
  143. package/dist/{fleet-verify-UN3SODEL.js → fleet-verify-UQPMTVE3.js} +66 -61
  144. package/dist/{fleet-view-TWHJKCN6.js → fleet-view-MN2VG4MR.js} +65 -60
  145. package/dist/{init-T2QORQ3Y.js → init-PXEXQSBF.js} +90 -82
  146. package/dist/{interop-IN5I2A66.js → interop-ZG5T62U3.js} +12 -13
  147. package/dist/inventory-C26CFDRR.js +101 -0
  148. package/dist/{library-LSCATDLZ.js → library-B2W4N74O.js} +29 -29
  149. package/dist/{memory-HYOKAGGJ.js → memory-YCANYS5A.js} +73 -69
  150. package/dist/{models-2GPMFYCM.js → models-GERTU3YI.js} +51 -47
  151. package/dist/{monitor-E4ASVUJH.js → monitor-CPNIUULB.js} +74 -67
  152. package/dist/{orchestrator-DDMPR3PY.js → orchestrator-J4BSH4WQ.js} +1288 -1606
  153. package/dist/{panes-E3RUXOW5.js → panes-BOHAEGYC.js} +4 -4
  154. package/dist/{panes-IXKLOKA2.js → panes-NXSLDQZ2.js} +10 -11
  155. package/dist/{paths-L7LGY6RN.js → paths-VSUWNC22.js} +6 -7
  156. package/dist/reset-TNWTB5LU.js +343 -0
  157. package/dist/{resources-OTRSN34L.js → resources-4PXNMD5G.js} +29 -22
  158. package/dist/{run-5DEYH5QK.js → run-D6XJ34CN.js} +132 -132
  159. package/dist/{share-IHWTLO3M.js → share-2NWMJJEE.js} +27 -27
  160. package/dist/{skills-IYMXMKW4.js → skills-KR7WON5G.js} +40 -33
  161. package/dist/{skills-eval-DROHSJAR.js → skills-eval-O2ZNOLDS.js} +81 -77
  162. package/dist/{skills-inventory-D7X4L4ZX.js → skills-inventory-ZZOUBK7O.js} +23 -22
  163. package/dist/{slash-commands-QBM7UZ3B.js → slash-commands-ZXPJD64J.js} +47 -37
  164. package/dist/{steer-Z5DO23FJ.js → steer-XA25PSCS.js} +4 -4
  165. package/dist/{support-U7QOWY26.js → support-7EMVWYG2.js} +6 -6
  166. package/dist/{targets-P2FUC4IL.js → targets-OMH2XCSN.js} +50 -49
  167. package/dist/tasks-IPAGMEIX.js +36 -0
  168. package/dist/{terminal-lease-YREJ3JX2.js → terminal-lease-C2J3JYRE.js} +4 -4
  169. package/dist/{tools-5B7RO6MV.js → tools-EFFEAIDP.js} +8 -9
  170. package/dist/{trace-YMGMUM6A.js → trace-FXMXUZUF.js} +7 -7
  171. package/dist/uninstall-HALS6BLF.js +407 -0
  172. package/dist/upgrade-MS72RJEP.js +306 -0
  173. package/dist/{usage-ME5MPXGX.js → usage-NHG6MCJM.js} +162 -108
  174. package/dist/{verifiers-BVZ7IWOO.js → verifiers-7AUNVXDY.js} +155 -22
  175. package/dist/{verify-5K7ZKQFC.js → verify-FWYGPKMR.js} +14 -12
  176. package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
  177. package/dist/{wiki-generate-F5W5QTYY.js → wiki-generate-743CIGJW.js} +99 -90
  178. package/dist/{with-panes-BYOJCLAM.js → with-panes-BDQEWBRT.js} +10 -10
  179. package/dist/worker/entry.js +72 -68
  180. package/docs/README.md +3 -2
  181. package/docs/architecture/acp.md +17 -0
  182. package/docs/architecture/artifact-placement.md +1 -0
  183. package/docs/architecture/artifact-versions.md +2 -2
  184. package/docs/architecture/context-engine.md +4 -0
  185. package/docs/architecture/dispatch-typed-intent.md +1 -1
  186. package/docs/architecture/evidence-and-memory.md +1 -1
  187. package/docs/architecture/middleware-and-components.md +1 -1
  188. package/docs/architecture/model-catalog.md +21 -10
  189. package/docs/architecture/observability.md +19 -2
  190. package/docs/architecture/prompt-envelope-and-tools.md +17 -5
  191. package/docs/architecture/provider-adapter-cookbook.md +63 -0
  192. package/docs/architecture/safety-model.md +25 -22
  193. package/docs/architecture/tui-design.md +1 -1
  194. package/docs/guide/built-in-agents.md +25 -11
  195. package/docs/guide/commands-and-modes.md +18 -3
  196. package/docs/guide/configuration-and-targets.md +100 -10
  197. package/docs/guide/configuration-reference.md +17 -7
  198. package/docs/guide/environment-variables.md +4 -2
  199. package/docs/guide/installation-and-lifecycle.md +37 -4
  200. package/docs/guide/proactive-memory.md +66 -55
  201. package/docs/guide/skills-marketplace.md +18 -0
  202. package/docs/guide/tool-usage.md +78 -3
  203. package/docs/history/config-knobs-audit.md +2 -2
  204. package/docs/process/development-pipeline.md +40 -2
  205. package/docs/process/eval-runner.md +67 -3
  206. package/docs/process/git-commit-provenance.md +15 -0
  207. package/docs/process/release-cut-checklist.md +207 -0
  208. package/docs/process/scientific-validation.md +18 -17
  209. package/evals/behavioral-machinery-support.ts +1 -0
  210. package/evals/behavioral-machinery.yaml +1 -1
  211. package/evals/behavioral-model.yaml +3 -2
  212. package/package.json +2 -2
  213. package/skills/README.md +7 -5
  214. package/skills/coding/ast-grep/SKILL.md +101 -30
  215. package/skills/coding/ast-grep/evals.md +26 -0
  216. package/skills/coding/coding-standards/SKILL.md +47 -2
  217. package/skills/coding/coding-standards/evals.md +23 -0
  218. package/skills/coding/prototype/SKILL.md +87 -28
  219. package/skills/coding/prototype/evals.md +19 -0
  220. package/skills/coding/tdd/SKILL.md +80 -53
  221. package/skills/coding/tdd/evals.md +20 -0
  222. package/skills/context/context-handoff/SKILL.md +43 -2
  223. package/skills/context/context-handoff/evals.md +44 -0
  224. package/skills/context/context-prime/SKILL.md +45 -15
  225. package/skills/context/context-prime/evals.md +45 -0
  226. package/skills/git/branch-closeout/SKILL.md +132 -0
  227. package/skills/git/branch-closeout/evals.md +133 -0
  228. package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
  229. package/skills/git/file-ticket/SKILL.md +77 -63
  230. package/skills/git/file-ticket/assets/issue-template.md +22 -0
  231. package/skills/git/file-ticket/evals.md +31 -26
  232. package/skills/git/file-ticket/references/issue-discovery.md +49 -0
  233. package/skills/git/fix-issue/SKILL.md +87 -64
  234. package/skills/git/fix-issue/evals.md +35 -31
  235. package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
  236. package/skills/git/resolve-merge-conflicts/SKILL.md +100 -51
  237. package/skills/git/resolve-merge-conflicts/evals.md +52 -25
  238. package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
  239. package/skills/git/ship/SKILL.md +103 -67
  240. package/skills/git/ship/assets/pr-template.md +21 -0
  241. package/skills/git/ship/evals.md +44 -28
  242. package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
  243. package/skills/git/worktree-create/SKILL.md +80 -50
  244. package/skills/git/worktree-create/evals.md +40 -33
  245. package/skills/git/worktree-create/references/worktree-setup.md +62 -66
  246. package/skills/git/worktree-merge/SKILL.md +112 -65
  247. package/skills/git/worktree-merge/evals.md +42 -34
  248. package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
  249. package/skills/planning/archify/SKILL.md +196 -0
  250. package/skills/planning/archify/evals.md +65 -0
  251. package/skills/planning/architecture/SKILL.md +61 -12
  252. package/skills/planning/architecture/evals.md +65 -0
  253. package/skills/planning/backlog/SKILL.md +130 -14
  254. package/skills/planning/backlog/evals.md +142 -0
  255. package/skills/planning/prd/SKILL.md +47 -6
  256. package/skills/planning/prd/evals.md +54 -0
  257. package/skills/planning/product-intent/SKILL.md +57 -2
  258. package/skills/planning/product-intent/evals.md +70 -0
  259. package/skills/planning/tech-spec/SKILL.md +53 -2
  260. package/skills/planning/tech-spec/evals.md +73 -0
  261. package/skills/registry.yaml +58 -50
  262. package/skills/remote.yaml +13 -0
  263. package/skills/research/arxiv-literature/SKILL.md +76 -18
  264. package/skills/research/arxiv-literature/evals.md +50 -0
  265. package/skills/research/experiment-protocol/SKILL.md +20 -1
  266. package/skills/research/experiment-protocol/evals.md +23 -0
  267. package/skills/research/scientific-debugging/SKILL.md +24 -1
  268. package/skills/research/scientific-debugging/evals.md +18 -0
  269. package/skills/research/scientific-modernization/SKILL.md +26 -1
  270. package/skills/research/scientific-modernization/evals.md +27 -0
  271. package/skills/skill-marketplace.json +63 -28
  272. package/skills/workflow/cut-it/SKILL.md +64 -5
  273. package/skills/workflow/cut-it/evals.md +101 -0
  274. package/skills/workflow/design-council/SKILL.md +112 -27
  275. package/skills/workflow/design-council/evals.md +161 -0
  276. package/skills/workflow/grill-me/SKILL.md +85 -10
  277. package/skills/workflow/grill-me/evals.md +153 -0
  278. package/skills/workflow/workflow-distiller/SKILL.md +76 -17
  279. package/skills/workflow/workflow-distiller/evals.md +118 -0
  280. package/src/cli/args.ts +0 -8
  281. package/src/cli/configure-interop.ts +105 -13
  282. package/src/cli/configure-oauth.ts +57 -0
  283. package/src/cli/configure-onboarding.ts +980 -0
  284. package/src/cli/configure-target.ts +594 -0
  285. package/src/cli/configure.ts +1084 -529
  286. package/src/cli/context-map.ts +114 -0
  287. package/src/cli/context.ts +4 -0
  288. package/src/cli/doctor-state-size.ts +1 -12
  289. package/src/cli/doctor-validation-contract.ts +28 -0
  290. package/src/cli/doctor.ts +5 -0
  291. package/src/cli/evidence-detail.ts +1 -75
  292. package/src/cli/evidence-inventory.ts +1 -167
  293. package/src/cli/index.ts +3 -0
  294. package/src/cli/lifecycle-presenter.ts +436 -0
  295. package/src/cli/models.ts +10 -2
  296. package/src/cli/modes/print.ts +5 -1
  297. package/src/cli/reset.ts +228 -106
  298. package/src/cli/run.ts +7 -4
  299. package/src/cli/select.ts +664 -0
  300. package/src/cli/skills.ts +9 -2
  301. package/src/cli/targets.ts +3 -0
  302. package/src/cli/tasks.ts +84 -0
  303. package/src/cli/uninstall.ts +233 -165
  304. package/src/cli/upgrade.ts +210 -150
  305. package/src/cli/usage.ts +92 -27
  306. package/src/cli/validate-model.ts +3 -3
  307. package/src/cli/verifiers.ts +147 -1
  308. package/src/cli/wiki-generate.ts +1 -0
  309. package/src/core/commit-attribution.ts +41 -1
  310. package/src/core/config.ts +56 -0
  311. package/src/core/external-diagnostic.ts +44 -0
  312. package/src/core/gateway-routing.ts +157 -0
  313. package/src/core/git-commit-attribution.ts +46 -3
  314. package/src/core/run-overrides.ts +0 -5
  315. package/src/core/safe-exec.ts +17 -2
  316. package/src/core/skill-activation.ts +92 -2
  317. package/src/core/tool-names.ts +5 -2
  318. package/src/domains/agents/builtins/architect.md +1 -1
  319. package/src/domains/agents/builtins/coder.md +1 -1
  320. package/src/domains/agents/builtins/documenter.md +1 -1
  321. package/src/domains/agents/builtins/git-master.md +1 -1
  322. package/src/domains/agents/builtins/provenance.md +7 -7
  323. package/src/domains/agents/builtins/tester.md +1 -1
  324. package/src/domains/agents/builtins/verifier.md +2 -2
  325. package/src/domains/agents/builtins/wiki-writer.md +4 -3
  326. package/src/domains/agents/builtins/world-knowledge.md +31 -0
  327. package/src/domains/agents/catalog.ts +1 -1
  328. package/src/domains/agents/result-contract.ts +70 -0
  329. package/src/domains/context/extension.ts +31 -7
  330. package/src/domains/context/refresh.ts +3 -0
  331. package/src/domains/context/wiki/frontmatter.ts +5 -2
  332. package/src/domains/context/wiki/generate.ts +6 -0
  333. package/src/domains/context/wiki/map-seed.ts +589 -0
  334. package/src/domains/context/wiki/plan.ts +2 -2
  335. package/src/domains/context/wiki/prompts.ts +43 -0
  336. package/src/domains/dispatch/active-route-planner.ts +4 -0
  337. package/src/domains/dispatch/admission.ts +29 -0
  338. package/src/domains/dispatch/agent-candidates.ts +10 -0
  339. package/src/domains/dispatch/budget-envelope.ts +86 -1
  340. package/src/domains/dispatch/capability-match.ts +1 -0
  341. package/src/domains/dispatch/capacity-lease.ts +17 -0
  342. package/src/domains/dispatch/code-step.ts +11 -4
  343. package/src/domains/dispatch/contract.ts +42 -8
  344. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  345. package/src/domains/dispatch/extension.ts +184 -56
  346. package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
  347. package/src/domains/dispatch/fleet-run.ts +1 -0
  348. package/src/domains/dispatch/host-verification.ts +114 -13
  349. package/src/domains/dispatch/intent.ts +28 -18
  350. package/src/domains/dispatch/orphan-recovery.ts +2 -0
  351. package/src/domains/dispatch/receipt-integrity.ts +4 -0
  352. package/src/domains/dispatch/reservation-store.ts +5 -3
  353. package/src/domains/dispatch/state.ts +15 -2
  354. package/src/domains/dispatch/types.ts +20 -2
  355. package/src/domains/dispatch/worker-model-metadata.ts +38 -0
  356. package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
  357. package/src/domains/eval/metrics/token-stream.ts +201 -31
  358. package/src/domains/eval/metrics/tracked.ts +40 -4
  359. package/src/domains/eval/runners/clio-run.ts +17 -11
  360. package/src/domains/eval/runners/context-index.ts +2 -7
  361. package/src/domains/eval/runners/context-init.ts +3 -6
  362. package/src/domains/eval/runners/external-command.ts +29 -11
  363. package/src/domains/eval/schema/suite.ts +28 -0
  364. package/src/domains/eval/schema/verdict.ts +2 -2
  365. package/src/domains/eval/suites/resolve.ts +13 -1
  366. package/src/domains/eval/suites/run.ts +24 -3
  367. package/src/domains/evidence/build.ts +102 -15
  368. package/src/domains/evidence/detail.ts +69 -0
  369. package/src/domains/evidence/eval.ts +13 -1
  370. package/src/domains/evidence/finish-contract-map.ts +5 -1
  371. package/src/domains/evidence/inventory.ts +167 -0
  372. package/src/domains/evidence/store.ts +16 -0
  373. package/src/domains/evidence/types.ts +12 -0
  374. package/src/domains/extensions/resources.ts +7 -0
  375. package/src/domains/interop/registry.ts +6 -2
  376. package/src/domains/interop/types.ts +4 -0
  377. package/src/domains/lifecycle/migrations/index.ts +4 -0
  378. package/src/domains/memory/task-memory-policy.ts +70 -26
  379. package/src/domains/memory/task-memory-telemetry.ts +1 -0
  380. package/src/domains/middleware/index.ts +0 -1
  381. package/src/domains/middleware/marketplace-offer.ts +22 -35
  382. package/src/domains/middleware/memory-intervention.ts +127 -32
  383. package/src/domains/middleware/memory-step-endpoint.ts +3 -2
  384. package/src/domains/middleware/runtime.ts +7 -3
  385. package/src/domains/middleware/skills-reminder.ts +31 -2
  386. package/src/domains/mux/detect.ts +3 -6
  387. package/src/domains/observability/accountability.ts +15 -1
  388. package/src/domains/observability/compaction-usage.ts +118 -0
  389. package/src/domains/observability/contract.ts +52 -7
  390. package/src/domains/observability/cost.ts +1 -1
  391. package/src/domains/observability/evidence-index.ts +10 -0
  392. package/src/domains/observability/extension.ts +15 -6
  393. package/src/domains/observability/out-of-turn-usage.ts +52 -21
  394. package/src/domains/observability/projection.ts +394 -45
  395. package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
  396. package/src/domains/prompts/fragments/operating/contract.md +2 -0
  397. package/src/domains/prompts/fragments/wiki/page.md +8 -0
  398. package/src/domains/providers/contract.ts +4 -1
  399. package/src/domains/providers/extension.ts +40 -9
  400. package/src/domains/providers/model-capabilities.ts +9 -0
  401. package/src/domains/providers/model-discovery.ts +3 -4
  402. package/src/domains/providers/model-runtime-capabilities.ts +15 -5
  403. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +48 -26
  404. package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
  405. package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
  406. package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
  407. package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
  408. package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
  409. package/src/domains/providers/support.ts +11 -5
  410. package/src/domains/providers/target-model-cache.ts +25 -2
  411. package/src/domains/providers/types/capability-flags.ts +2 -0
  412. package/src/domains/providers/types/runtime-descriptor.ts +20 -1
  413. package/src/domains/providers/types/target-descriptor.ts +19 -0
  414. package/src/domains/resources/index.ts +3 -0
  415. package/src/domains/resources/skills/install.ts +72 -7
  416. package/src/domains/resources/skills/loader.ts +7 -0
  417. package/src/domains/resources/skills/marketplace.ts +63 -11
  418. package/src/domains/safety/action-classifier.ts +7 -0
  419. package/src/domains/safety/autonomy.ts +15 -0
  420. package/src/domains/safety/default-path-policy.ts +2 -0
  421. package/src/domains/safety/finish-contract-registration.ts +29 -14
  422. package/src/domains/safety/finish-contract.ts +252 -40
  423. package/src/domains/safety/index.ts +21 -1
  424. package/src/domains/safety/path-policy.ts +1 -1
  425. package/src/domains/safety/policy-engine.ts +60 -17
  426. package/src/domains/safety/protected-artifacts.ts +191 -88
  427. package/src/domains/safety/rigor.ts +53 -39
  428. package/src/domains/safety/run-effects.ts +2 -22
  429. package/src/domains/safety/skill-authority.ts +55 -0
  430. package/src/domains/safety/validation-contract.ts +388 -0
  431. package/src/domains/session/archive-readers.ts +10 -1
  432. package/src/domains/session/compaction/compact.ts +72 -22
  433. package/src/domains/session/decision-board.ts +101 -2
  434. package/src/domains/session/entries.ts +50 -7
  435. package/src/domains/session/extension.ts +4 -4
  436. package/src/domains/session/handoff.ts +2 -1
  437. package/src/domains/session/manager.ts +2 -3
  438. package/src/domains/session/task-board.ts +14 -1
  439. package/src/domains/session/tree/fork.ts +1 -2
  440. package/src/domains/session/tree/navigator.ts +1 -1
  441. package/src/domains/session/usage.ts +3 -3
  442. package/src/domains/user-tasks/acceptance.ts +56 -0
  443. package/src/domains/user-tasks/active-acceptance.ts +40 -0
  444. package/src/domains/user-tasks/store.ts +34 -3
  445. package/src/engine/acp/adapter.ts +24 -6
  446. package/src/engine/acp/server.ts +21 -4
  447. package/src/engine/acp/transport.ts +53 -8
  448. package/src/engine/acp/types.ts +4 -0
  449. package/src/engine/agent.ts +13 -3
  450. package/src/engine/ai.ts +26 -8
  451. package/src/engine/antigravity/subprocess-runtime.ts +386 -120
  452. package/src/engine/api-registry.ts +3 -0
  453. package/src/engine/apis/ollama-native.ts +15 -0
  454. package/src/engine/apis/openai-completions.ts +117 -14
  455. package/src/engine/claude/subprocess-runtime.ts +107 -60
  456. package/src/engine/external-subprocess.ts +122 -6
  457. package/src/entry/background-model-metadata.ts +18 -0
  458. package/src/entry/compaction-prompt.ts +57 -0
  459. package/src/entry/orchestrator.ts +416 -218
  460. package/src/entry/task-memory-lifecycle.ts +35 -0
  461. package/src/interactive/chat-loop-messages.ts +13 -4
  462. package/src/interactive/chat-loop.ts +65 -2
  463. package/src/interactive/chat-renderer.ts +1 -0
  464. package/src/interactive/cost-overlay.ts +26 -2
  465. package/src/interactive/dispatch-board.ts +46 -717
  466. package/src/interactive/fleet-run-preview.ts +2 -1
  467. package/src/interactive/interactive-application.ts +3 -2
  468. package/src/interactive/interactive-presentation.ts +55 -12
  469. package/src/interactive/interactive-slash-runtime.ts +4 -2
  470. package/src/interactive/oracle.ts +5 -2
  471. package/src/interactive/overlays/fleet-run-approval.ts +3 -2
  472. package/src/interactive/overlays/message-picker.ts +2 -2
  473. package/src/interactive/overlays/settings.ts +2 -2
  474. package/src/interactive/overlays/tree-selector.ts +2 -2
  475. package/src/interactive/renderers/branch-summary.ts +1 -1
  476. package/src/interactive/renderers/worker-entry.ts +32 -0
  477. package/src/interactive/slash-autocomplete.ts +4 -6
  478. package/src/interactive/slash-commands.ts +49 -45
  479. package/src/interactive/slash-spec.ts +28 -0
  480. package/src/interactive/theme/labels.ts +19 -13
  481. package/src/interactive/turn-context.ts +9 -5
  482. package/src/interactive/turn-recovery.ts +8 -0
  483. package/src/interactive/turn-runtime.ts +27 -11
  484. package/src/interactive/turn-state.ts +7 -0
  485. package/src/interactive/view/artifacts.ts +2 -0
  486. package/src/interactive/worker-receipts.ts +1 -0
  487. package/src/interactive/worker-stream.ts +13 -4
  488. package/src/tools/bootstrap.ts +4 -0
  489. package/src/tools/builtin-tool-catalog.ts +31 -0
  490. package/src/tools/compete-worktrees.ts +7 -1
  491. package/src/tools/context/index.ts +30 -9
  492. package/src/tools/core-bootstrap.ts +16 -0
  493. package/src/tools/decide.ts +136 -0
  494. package/src/tools/dispatch-admission.ts +21 -0
  495. package/src/tools/dispatch-arguments.ts +1 -0
  496. package/src/tools/dispatch-event-text.ts +10 -0
  497. package/src/tools/dispatch-plan.ts +6 -2
  498. package/src/tools/dispatch-runner.ts +27 -1
  499. package/src/tools/dispatch-types.ts +6 -0
  500. package/src/tools/evidence.ts +96 -0
  501. package/src/tools/limitation.ts +76 -0
  502. package/src/tools/policy.ts +9 -0
  503. package/src/tools/presentation.ts +3 -0
  504. package/src/tools/registry.ts +11 -5
  505. package/src/tools/result-shaping.ts +17 -5
  506. package/src/tools/task-worktree.ts +13 -3
  507. package/src/tools/tasks.ts +10 -1
  508. package/src/tools/verify/authoring.ts +170 -83
  509. package/src/tools/verify/catalog.ts +122 -5
  510. package/src/tools/verify/index.ts +2 -1
  511. package/src/tools/verify/numeric.ts +298 -0
  512. package/src/tools/verify/perf.ts +143 -0
  513. package/src/tools/verify/scripts.ts +229 -2
  514. package/src/tools/worker-evidence.ts +3 -1
  515. package/src/worker/spec-contract.ts +4 -0
  516. package/dist/chunk-2Z2IKEXI.js +0 -1554
  517. package/dist/chunk-RVG5JXAL.js +0 -41
  518. package/dist/chunk-T56WDKA5.js +0 -183
  519. package/dist/chunk-VN3SHNBN.js +0 -313
  520. package/dist/chunk-VPKWYKEY.js +0 -169
  521. package/dist/reset-OAQP3W4O.js +0 -230
  522. package/dist/uninstall-N34PCTGJ.js +0 -331
  523. package/dist/upgrade-PXK3S2YM.js +0 -325
@@ -1,10 +1,12 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import type { AskUserToolPolicy } from "../../tools/registry.js";
2
3
  import type { AutonomyExposure } from "../safety/autonomy.js";
3
- import type { DecisionLedgerEntry, DecisionRecord } from "./entries.js";
4
+ import { type DecisionLedgerEntry, type DecisionRecord, decisionRef } from "./entries.js";
4
5
 
5
6
  export interface DecisionLedgerEntryFields {
6
7
  kind: "decisionLedger";
7
8
  parentTurnId: string;
9
+ origin?: "interview" | "agent";
8
10
  interviewId: string;
9
11
  interviewStatus: "complete" | "cancelled";
10
12
  startedAt: string;
@@ -28,11 +30,35 @@ export interface DecisionBoardStoreDeps {
28
30
  now?: () => Date;
29
31
  }
30
32
 
33
+ /** One design choice the model records itself through the `decide` tool. */
34
+ export interface AgentDecisionInput {
35
+ key: string;
36
+ value: string;
37
+ alternatives: ReadonlyArray<string>;
38
+ rationale: string;
39
+ label?: string;
40
+ }
41
+
42
+ export interface AgentDecisionOutcome {
43
+ /** The appended agent decision set; `decisionRef(entry.interviewId, key)` cites it. */
44
+ entry: DecisionLedgerEntryFields;
45
+ /** The earlier active record with the same key that this decision superseded, when there was one. */
46
+ superseded: { interviewId: string; key: string } | null;
47
+ }
48
+
31
49
  export interface DecisionBoardStore {
32
50
  /** Latest snapshot per interview, newest interview first. */
33
51
  snapshot(): ReadonlyArray<DecisionLedgerEntry>;
34
52
  /** Persist the one host-finalized snapshot for a settled interview. */
35
53
  recordFinalizedInterview(policy: AskUserToolPolicy): boolean;
54
+ /**
55
+ * Append one agent-recorded decision as its own complete set
56
+ * (`origin: "agent"`, `interviewId: "agent:<uuid>"`, `roundCount: 0`). An
57
+ * earlier active agent decision with the same key is superseded first with
58
+ * the new rationale as its correction. An active operator decision with the
59
+ * same key is never overwritten by the model; that throws.
60
+ */
61
+ recordAgentDecision(input: AgentDecisionInput): AgentDecisionOutcome;
36
62
  /** Append an operator revision snapshot anchored to the active branch leaf. */
37
63
  supersede(interviewId: string, key: string, correction?: string): DecisionLedgerEntryFields;
38
64
  /** Force the next read to refold, including after a same-session tree switch. */
@@ -90,6 +116,24 @@ function finalizedInterviewEntryFields(policy: AskUserToolPolicy): DecisionLedge
90
116
  };
91
117
  }
92
118
 
119
+ /** Most decision refs one dispatch request, envelope, or receipt carries. */
120
+ export const DECISION_REFS_CAP = 32;
121
+
122
+ /**
123
+ * Refs of every active decision on a board snapshot, sorted and capped at
124
+ * {@link DECISION_REFS_CAP}. Dispatch seals this onto each request it builds;
125
+ * an empty board yields an empty list, which callers leave off the request.
126
+ */
127
+ export function activeDecisionRefs(board: ReadonlyArray<DecisionLedgerEntry>): string[] {
128
+ const refs = new Set<string>();
129
+ for (const entry of board) {
130
+ for (const decision of entry.decisions) {
131
+ if (decision.status === "active") refs.add(decisionRef(entry.interviewId, decision.key));
132
+ }
133
+ }
134
+ return [...refs].sort().slice(0, DECISION_REFS_CAP);
135
+ }
136
+
93
137
  function isDecisionLedgerEntry(value: unknown): value is DecisionLedgerEntry {
94
138
  return !!value && typeof value === "object" && (value as { kind?: unknown }).kind === "decisionLedger";
95
139
  }
@@ -143,7 +187,7 @@ export function createDecisionBoardStore(deps: DecisionBoardStoreDeps = {}): Dec
143
187
  dirty = true;
144
188
  };
145
189
 
146
- return {
190
+ const store: DecisionBoardStore = {
147
191
  snapshot(): ReadonlyArray<DecisionLedgerEntry> {
148
192
  syncToSession();
149
193
  return interviews;
@@ -154,6 +198,51 @@ export function createDecisionBoardStore(deps: DecisionBoardStoreDeps = {}): Dec
154
198
  append(entry);
155
199
  return true;
156
200
  },
201
+ recordAgentDecision(input: AgentDecisionInput): AgentDecisionOutcome {
202
+ syncToSession();
203
+ let superseded: AgentDecisionOutcome["superseded"] = null;
204
+ for (const interview of interviews) {
205
+ const prior = interview.decisions.find((decision) => decision.key === input.key && decision.status === "active");
206
+ if (prior === undefined) continue;
207
+ if (interview.origin !== "agent" || prior.source !== "agent") {
208
+ throw new Error(
209
+ `decision board: '${input.key}' is an operator decision (${interview.interviewId}); it can only be revised through ask_user`,
210
+ );
211
+ }
212
+ superseded = { interviewId: interview.interviewId, key: prior.key };
213
+ break;
214
+ }
215
+ if (superseded !== null) store.supersede(superseded.interviewId, superseded.key, input.rationale);
216
+ const now = (deps.now?.() ?? new Date()).toISOString();
217
+ const entries = deps.readEntries?.() ?? [];
218
+ const parentTurnId = deps.getActiveLeafTurnId?.() ?? activeLeafFromEntries(entries);
219
+ if (!parentTurnId) throw new Error("decision board: no active branch leaf is available for the decision");
220
+ const entry: DecisionLedgerEntryFields = {
221
+ kind: "decisionLedger",
222
+ parentTurnId,
223
+ origin: "agent",
224
+ interviewId: `agent:${randomUUID()}`,
225
+ interviewStatus: "complete",
226
+ startedAt: now,
227
+ endedAt: now,
228
+ roundCount: 0,
229
+ exposure: "local",
230
+ decisions: [
231
+ {
232
+ key: input.key,
233
+ value: input.value,
234
+ ...(input.label ? { label: input.label } : {}),
235
+ status: "active",
236
+ decidedAt: now,
237
+ source: "agent",
238
+ alternatives: [...input.alternatives],
239
+ rationale: input.rationale,
240
+ },
241
+ ],
242
+ };
243
+ append(entry);
244
+ return { entry, superseded };
245
+ },
157
246
  supersede(interviewId: string, key: string, correction?: string): DecisionLedgerEntryFields {
158
247
  syncToSession();
159
248
  const interview = interviews.find((candidate) => candidate.interviewId === interviewId);
@@ -191,4 +280,14 @@ export function createDecisionBoardStore(deps: DecisionBoardStoreDeps = {}): Dec
191
280
  dirty = true;
192
281
  },
193
282
  };
283
+ return store;
284
+ }
285
+
286
+ /** Preserve the recorded argument wherever a decision is carried into another prompt. */
287
+ export function decisionRationale(decision: DecisionRecord): string | undefined {
288
+ const parts: string[] = [];
289
+ if (decision.alternatives?.length) parts.push(`Alternatives: ${decision.alternatives.join("; ")}`);
290
+ if (decision.rationale) parts.push(`Rationale: ${decision.rationale}`);
291
+ if (parts.length > 0) return parts.join(". ");
292
+ return decision.source_question ?? decision.correction;
194
293
  }
@@ -5,10 +5,13 @@
5
5
  * carries its `kind` discriminant, a `turnId` (uuid v7 where possible so
6
6
  * entries sort by creation), a parent pointer, and an ISO timestamp.
7
7
  *
8
- * Later slices extend this union:
9
- * - compactionSummary is produced by compaction/compact.ts (slice 12c).
10
- * - branchSummary is produced by the fork path (slice 12b).
11
- * - bashExecution / fileEntry become the wire shape for Phase 14 extensions.
8
+ * Non-message kinds and where they come from:
9
+ * - compactionSummary is produced by compaction/compact.ts.
10
+ * - branchSummary is produced by the fork path.
11
+ * - bashExecution is produced by the editor bash path
12
+ * (interactive/editor-bash.ts).
13
+ * - fileEntry is consumed by the renderer, compaction, handoff, and
14
+ * evidence builders but has no in-tree producer.
12
15
  */
13
16
 
14
17
  import { isSkillActivation, type SkillActivation } from "../../core/skill-activation.js";
@@ -101,6 +104,10 @@ export type CompactionTrigger = "auto" | "force" | "overflow";
101
104
  * `usage` carries and the ledger usage fold reads both from one place.
102
105
  */
103
106
  export interface CompactionUsage {
107
+ /** Executing route; absent on legacy checkpoints that used the active chat model. */
108
+ targetId?: string;
109
+ /** Requested wire model ID, not a verified physical backend identity. */
110
+ modelId?: string;
104
111
  input: number;
105
112
  output: number;
106
113
  cacheRead: number;
@@ -209,6 +216,14 @@ export interface TaskLedgerEntry extends BaseSessionEntry {
209
216
 
210
217
  export type DecisionStatus = "active" | "superseded";
211
218
 
219
+ /**
220
+ * Who settled a decision. `operator` is an answer the operator gave in an
221
+ * `ask_user` interview. `agent` is a design choice the model recorded itself
222
+ * through the `decide` tool, with the alternatives it rejected and why. Absent
223
+ * on entries written before agent decisions existed, which were all operator.
224
+ */
225
+ export type DecisionSource = "operator" | "agent";
226
+
212
227
  export interface DecisionRecord {
213
228
  key: string;
214
229
  value: string;
@@ -218,11 +233,33 @@ export interface DecisionRecord {
218
233
  decidedAt: string;
219
234
  revisedAt?: string;
220
235
  correction?: string;
236
+ source?: DecisionSource;
237
+ /** Options considered and not taken. Only agent decisions carry these. */
238
+ alternatives?: string[];
239
+ /** Why `value` won over `alternatives`. Only agent decisions carry this. */
240
+ rationale?: string;
241
+ }
242
+
243
+ /**
244
+ * Stable reference to one decision: `<interviewId>/<key>`. Both halves are
245
+ * already unique on the active path, so the pair needs no third id. Run
246
+ * envelopes, receipts, and commit trailers cite decisions by this string.
247
+ */
248
+ export type DecisionRef = string;
249
+
250
+ export function decisionRef(interviewId: string, key: string): DecisionRef {
251
+ return `${interviewId}/${key}`;
221
252
  }
222
253
 
223
- /** One complete, branch-anchored snapshot of a settled operator interview. */
254
+ /**
255
+ * One complete, branch-anchored snapshot of a settled decision set. An
256
+ * `interview` origin is an operator `ask_user` round; an `agent` origin is a
257
+ * set the model recorded with the `decide` tool, where `interviewId` is the
258
+ * agent decision set id and `roundCount` is 0. Absent origin means interview.
259
+ */
224
260
  export interface DecisionLedgerEntry extends BaseSessionEntry {
225
261
  kind: "decisionLedger";
262
+ origin?: "interview" | "agent";
226
263
  interviewId: string;
227
264
  interviewStatus: "complete" | "cancelled";
228
265
  startedAt: string;
@@ -499,11 +536,14 @@ function isTaskLedgerEvidence(value: unknown): value is TaskLedgerValidationEvid
499
536
  );
500
537
  }
501
538
 
502
- function isDecisionRecord(value: unknown): value is DecisionRecord {
539
+ export function isDecisionRecord(value: unknown): value is DecisionRecord {
503
540
  if (!isRecord(value)) return false;
504
- if (!isString(value.key) || !/^[a-z0-9]+(?:_[a-z0-9]+)*$/.test(value.key)) return false;
541
+ if (!isString(value.key) || !/^[a-z0-9]+(?:[_-][a-z0-9]+)*$/.test(value.key)) return false;
505
542
  if (!isString(value.value) || !isOneOf(value.status, DECISION_STATUSES) || !isString(value.decidedAt)) return false;
506
543
  if (!isOptionalString(value.label) || !isOptionalString(value.source_question)) return false;
544
+ if (value.source !== undefined && !isOneOf(value.source, ["operator", "agent"])) return false;
545
+ if (value.alternatives !== undefined && !isStringArray(value.alternatives)) return false;
546
+ if (!isOptionalString(value.rationale)) return false;
507
547
  if (!isOptionalString(value.revisedAt) || !isOptionalString(value.correction)) return false;
508
548
  return value.status === "superseded"
509
549
  ? isString(value.revisedAt)
@@ -515,6 +555,8 @@ function isOptionalCompactionUsage(value: unknown): boolean {
515
555
  if (!isRecord(value)) return false;
516
556
  const cost = value.cost;
517
557
  return (
558
+ isOptionalString(value.targetId) &&
559
+ isOptionalString(value.modelId) &&
518
560
  isNumber(value.input) &&
519
561
  isNumber(value.output) &&
520
562
  isNumber(value.cacheRead) &&
@@ -636,6 +678,7 @@ export function isSessionEntry(value: unknown): value is SessionEntry {
636
678
  );
637
679
  case "decisionLedger":
638
680
  return (
681
+ (v.origin === undefined || isOneOf(v.origin, ["interview", "agent"])) &&
639
682
  isString(v.interviewId) &&
640
683
  isOneOf(v.interviewStatus, DECISION_INTERVIEW_STATUSES) &&
641
684
  isString(v.startedAt) &&
@@ -282,10 +282,10 @@ export function createSessionBundle(context: DomainContext): DomainBundle<Sessio
282
282
  return snapshotFor(id);
283
283
  },
284
284
  switchBranch(sessionId) {
285
- // /tree-driven branch switch currently delegates to resume. Kept as a
286
- // distinct contract method so later slices can layer telemetry or
287
- // chat-loop rewiring without changing resume's semantics. Same
288
- // open-before-close ordering as resume() above and for the same reason.
285
+ // /tree-driven branch switch delegates to resume. Kept as a distinct
286
+ // contract method so telemetry or chat-loop rewiring can be layered on
287
+ // without changing resume's semantics. Same open-before-close ordering
288
+ // as resume() above and for the same reason.
289
289
  if (state?.meta.id === sessionId) return state.meta;
290
290
  const resumed = resumeSessionState(sessionId);
291
291
  if (state) {
@@ -22,6 +22,7 @@
22
22
  */
23
23
 
24
24
  import { isAbsolute, normalize, relative, resolve } from "node:path";
25
+ import { decisionRationale } from "./decision-board.js";
25
26
  import type { DecisionLedgerEntry, SessionEntry } from "./entries.js";
26
27
  import { filterEntriesToActivePath } from "./tree/active-path.js";
27
28
 
@@ -480,7 +481,7 @@ export function mergeHandoffDecisions(
480
481
  if (decision.status !== "active") continue;
481
482
  const name = decision.label ?? decision.key;
482
483
  const summary = boundHandoffString(`${name}: ${decision.value}`).text;
483
- const rationale = decision.source_question ?? decision.correction;
484
+ const rationale = decisionRationale(decision);
484
485
  settled.push({
485
486
  summary,
486
487
  ...(rationale ? { rationale: boundHandoffString(rationale).text } : {}),
@@ -111,9 +111,8 @@ export function appendTurn(state: SessionManagerState, input: TurnInput): ClioTu
111
111
 
112
112
  /**
113
113
  * Append a rich SessionEntry via the engine writer. Non-message kinds are
114
- * written as JSON lines to current.jsonl; they do not project into tree.json
115
- * in slice 12a. Slice 12b extends the tree model so /fork can pick non-message
116
- * branch points too.
114
+ * written as JSON lines to current.jsonl and do not project into tree.json;
115
+ * the /fork picker offers assistant message turns only.
117
116
  */
118
117
  export function appendEntry(state: SessionManagerState, input: SessionEntryInput): SessionEntry {
119
118
  const turnId = input.turnId ?? newTurnId();
@@ -29,6 +29,7 @@ export interface TaskBoardTask {
29
29
  status: TaskLedgerStatus;
30
30
  origin?: "agent" | "user";
31
31
  userTaskId?: string;
32
+ requiredValidationEvidence?: TaskLedgerValidationEvidence[];
32
33
  /** Block or drop reason; empty for pending/active/completed tasks. */
33
34
  reason?: string;
34
35
  /** Evidence note recorded when the task was completed. */
@@ -64,7 +65,7 @@ export interface TaskBoardCounts {
64
65
  export type TaskBoardMutation =
65
66
  | { op: "plan"; title: string; tasks: ReadonlyArray<string> }
66
67
  | { op: "add"; tasks: ReadonlyArray<string> }
67
- | { op: "pick"; title: string; userTaskId: string }
68
+ | { op: "pick"; title: string; userTaskId: string; verification?: ReadonlyArray<{ check: string; timeoutMs: number }> }
68
69
  | { op: "start"; id: string }
69
70
  | { op: "done"; id: string; evidence: string }
70
71
  | { op: "block"; id: string; reason: string }
@@ -179,6 +180,7 @@ function boardStatus(tasks: ReadonlyArray<TaskBoardTask>): TaskLedgerStatus {
179
180
  export function toTaskLedgerEntryFields(board: TaskBoardSnapshot, now: Date): TaskLedgerEntryFields {
180
181
  const evidence: TaskLedgerValidationEvidence[] = [];
181
182
  const subgoals: TaskLedgerGoal[] = board.tasks.map((task) => {
183
+ evidence.push(...(task.requiredValidationEvidence ?? []).map((item) => ({ ...item })));
182
184
  if (task.status === "completed" && task.evidence) {
183
185
  evidence.push({
184
186
  id: `${task.id}.evidence`,
@@ -308,6 +310,8 @@ function toEntryView(entry: {
308
310
  origin: goal.origin ?? "agent",
309
311
  };
310
312
  if (goal.userTaskId) task.userTaskId = goal.userTaskId;
313
+ const required = entry.requiredValidationEvidence.filter((item) => item.id.startsWith(`${goal.id}.acceptance.`));
314
+ if (required.length > 0) task.requiredValidationEvidence = required.map((item) => ({ ...item }));
311
315
  if (goal.description) task.reason = goal.description;
312
316
  const evidence = evidenceByTask.get(goal.id);
313
317
  if (evidence) task.evidence = evidence;
@@ -390,6 +394,15 @@ function applyMutation(
390
394
  origin: "user",
391
395
  userTaskId: mutation.userTaskId,
392
396
  };
397
+ if (mutation.verification && mutation.verification.length > 0) {
398
+ picked.requiredValidationEvidence = mutation.verification.map((item, index) => ({
399
+ id: `${picked.id}.acceptance.${index}`,
400
+ description: `Operator acceptance: ${item.check}`,
401
+ command: item.check,
402
+ status: "pending",
403
+ notes: `timeoutMs=${item.timeoutMs}`,
404
+ }));
405
+ }
393
406
  return {
394
407
  board: {
395
408
  boardId: board?.boardId ?? "",
@@ -14,8 +14,7 @@ import { entryBelongsToPath } from "./active-path.js";
14
14
  * install it as current.
15
15
  *
16
16
  * Used by SessionContract.fork (current session) and the /fork message
17
- * picker path that lands in slice 12b-3. Kept out of extension.ts so the
18
- * bundle wiring stays thin.
17
+ * picker overlay. Kept out of extension.ts so the bundle wiring stays thin.
19
18
  */
20
19
  export interface ForkInput {
21
20
  /** The state we are forking from. Must carry a live writer. */
@@ -6,7 +6,7 @@ import type { ResolvedLabel } from "./manager.js";
6
6
  * Purely functional tree-walk helpers. Given the raw SessionTreeNode[] that
7
7
  * the engine persists plus a label map and a leaf pointer, produce a
8
8
  * render-friendly snapshot. No I/O. Used by SessionContract.tree() to
9
- * deliver a serializable structure to overlay renderers in slice 12b-2.
9
+ * deliver a serializable structure to the /tree overlay renderer.
10
10
  */
11
11
 
12
12
  /**
@@ -101,9 +101,9 @@ export function ledgerUsageCalls(
101
101
  const usage = entry.usage;
102
102
  if (!usage || usage.totalTokens <= 0) continue;
103
103
  calls.push({
104
- providerId: currentTarget ?? "unknown",
105
- attributedModelId: currentModel ?? "unknown",
106
- requestedModelId: currentModel ?? "unknown",
104
+ providerId: usage.targetId ?? currentTarget ?? "unknown",
105
+ attributedModelId: usage.modelId ?? currentModel ?? "unknown",
106
+ requestedModelId: usage.modelId ?? currentModel ?? "unknown",
107
107
  responseModelIdObservation: { state: "not-observed" },
108
108
  input: usage.input,
109
109
  output: usage.output,
@@ -0,0 +1,56 @@
1
+ import {
2
+ DISPATCH_INTENT_TIMEOUT_MIN_MS,
3
+ type DispatchIntentCheckBound,
4
+ type DispatchIntentVerification,
5
+ normalizeIntentExpectedOutputs,
6
+ normalizeIntentVerification,
7
+ } from "../dispatch/intent.js";
8
+
9
+ export interface UserTaskAcceptance {
10
+ expectedOutputs: string[];
11
+ verification: DispatchIntentVerification[];
12
+ }
13
+
14
+ /** Validate stored acceptance without consulting a catalog that may have changed. */
15
+ export function normalizeUserTaskAcceptance(raw: unknown): UserTaskAcceptance {
16
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
17
+ throw new Error("acceptance must be an object");
18
+ }
19
+ const value = raw as Record<string, unknown>;
20
+ if (Object.keys(value).some((key) => key !== "expectedOutputs" && key !== "verification")) {
21
+ throw new Error("acceptance contains an unknown field");
22
+ }
23
+ if (!Array.isArray(value.expectedOutputs) || !Array.isArray(value.verification)) {
24
+ throw new Error("acceptance requires expectedOutputs and verification arrays");
25
+ }
26
+ const checks = new Map<string, DispatchIntentCheckBound>();
27
+ const rawVerification = value.verification.map((entry: unknown) => {
28
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
29
+ throw new Error("acceptance verification must contain check and timeoutMs");
30
+ }
31
+ const item = entry as Record<string, unknown>;
32
+ if (Object.keys(item).some((key) => key !== "check" && key !== "timeoutMs")) {
33
+ throw new Error("acceptance verification contains an unknown field");
34
+ }
35
+ if (
36
+ typeof item.check !== "string" ||
37
+ typeof item.timeoutMs !== "number" ||
38
+ !Number.isSafeInteger(item.timeoutMs) ||
39
+ item.timeoutMs <= 0
40
+ ) {
41
+ throw new Error("acceptance verification requires a check and a positive integer timeoutMs");
42
+ }
43
+ checks.set(item.check.trim(), {
44
+ id: item.check.trim(),
45
+ timeoutMs: Math.max(DISPATCH_INTENT_TIMEOUT_MIN_MS, item.timeoutMs, checks.get(item.check.trim())?.timeoutMs ?? 0),
46
+ });
47
+ return { check: item.check, timeout_ms: item.timeoutMs };
48
+ });
49
+ const expectedOutputs = normalizeIntentExpectedOutputs(value.expectedOutputs);
50
+ if (!Array.isArray(expectedOutputs))
51
+ throw new Error(expectedOutputs.ok ? "invalid acceptance outputs" : expectedOutputs.message);
52
+ const verification = normalizeIntentVerification(rawVerification, checks);
53
+ if (!Array.isArray(verification))
54
+ throw new Error(verification.ok ? "invalid acceptance verification" : verification.message);
55
+ return { expectedOutputs, verification };
56
+ }
@@ -0,0 +1,40 @@
1
+ import { isSessionEntry } from "../session/entries.js";
2
+ import type { TaskBoardSnapshot } from "../session/task-board.js";
3
+ import type { UserTaskAcceptance } from "./acceptance.js";
4
+ import type { UserTask } from "./store.js";
5
+
6
+ /** Keep a task's acceptance through the turn that finishes or blocks its board row. */
7
+ export function activeUserTaskAcceptance(
8
+ tasks: ReadonlyArray<UserTask>,
9
+ board: TaskBoardSnapshot | null,
10
+ sessionId: string | null,
11
+ window: ReadonlyArray<unknown>,
12
+ ): UserTaskAcceptance | undefined {
13
+ if (!board || !sessionId) return undefined;
14
+ const touched = new Set<string>();
15
+ for (const entry of window) {
16
+ if (!isSessionEntry(entry) || entry.kind !== "message" || entry.role !== "tool_call") continue;
17
+ if (!entry.payload || typeof entry.payload !== "object") continue;
18
+ const payload = entry.payload as { name?: string; toolName?: string; args?: { action?: string; id?: string } };
19
+ if (
20
+ (payload.name ?? payload.toolName) === "tasks" &&
21
+ payload.args?.id &&
22
+ ["done", "block", "drop"].includes(payload.args.action ?? "")
23
+ )
24
+ touched.add(payload.args.id);
25
+ }
26
+ const linked = new Set(
27
+ board.tasks
28
+ .filter((task) => task.status === "pending" || task.status === "active" || touched.has(task.id))
29
+ .map((task) => task.userTaskId),
30
+ );
31
+ const acceptance = tasks
32
+ .filter((task) => task.handedSessionId === sessionId && linked.has(task.id))
33
+ .flatMap((task) => (task.acceptance ? [task.acceptance] : []));
34
+ return acceptance.length > 0
35
+ ? {
36
+ expectedOutputs: [...new Set(acceptance.flatMap((item) => item.expectedOutputs))],
37
+ verification: acceptance.flatMap((item) => item.verification),
38
+ }
39
+ : undefined;
40
+ }
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { CLIO_PROJECT_DIR } from "../../core/artifact-paths.js";
4
4
  import { atomicWrite } from "../../engine/session.js";
5
+ import { normalizeUserTaskAcceptance, type UserTaskAcceptance } from "./acceptance.js";
5
6
 
6
7
  export const USER_TASKS_FILE_VERSION = 1 as const;
7
8
  export const USER_TASKS_RELATIVE_PATH = `${CLIO_PROJECT_DIR}/user-tasks.json`;
@@ -12,6 +13,7 @@ export interface UserTask {
12
13
  id: string;
13
14
  title: string;
14
15
  note?: string;
16
+ acceptance?: UserTaskAcceptance;
15
17
  status: UserTaskStatus;
16
18
  createdAt: string;
17
19
  updatedAt: string;
@@ -37,7 +39,8 @@ export interface UserTasksStore {
37
39
  readonly path: string;
38
40
  snapshot(): ReadonlyArray<UserTask>;
39
41
  get(id: string): UserTask | null;
40
- add(title: string, note?: string): UserTask;
42
+ add(title: string, note?: string, acceptance?: UserTaskAcceptance): UserTask;
43
+ setAcceptance(id: string, acceptance: UserTaskAcceptance): UserTask;
41
44
  hand(id: string, sessionId?: string): UserTask;
42
45
  done(id: string): UserTask;
43
46
  drop(id: string): UserTask;
@@ -65,6 +68,7 @@ const TASK_KEYS = new Set([
65
68
  "id",
66
69
  "title",
67
70
  "note",
71
+ "acceptance",
68
72
  "status",
69
73
  "createdAt",
70
74
  "updatedAt",
@@ -86,6 +90,13 @@ function isOptionalString(value: unknown): boolean {
86
90
 
87
91
  function isUserTask(value: unknown): value is UserTask {
88
92
  if (!isRecord(value) || !hasOnlyKeys(value, TASK_KEYS)) return false;
93
+ if (value.acceptance !== undefined) {
94
+ try {
95
+ normalizeUserTaskAcceptance(value.acceptance);
96
+ } catch {
97
+ return false;
98
+ }
99
+ }
89
100
  return (
90
101
  typeof value.id === "string" &&
91
102
  /^u[1-9]\d*$/.test(value.id) &&
@@ -138,7 +149,7 @@ function parseFile(body: string, path: string): UserTasksFile {
138
149
  }
139
150
 
140
151
  function copyTask(task: UserTask): UserTask {
141
- return { ...task };
152
+ return { ...task, ...(task.acceptance ? { acceptance: normalizeUserTaskAcceptance(task.acceptance) } : {}) };
142
153
  }
143
154
 
144
155
  function initialFile(): UserTasksFile {
@@ -219,7 +230,8 @@ export function createUserTasksStore(deps: UserTasksStoreDeps): UserTasksStore {
219
230
  const task = load().tasks.find((candidate) => candidate.id === id);
220
231
  return task ? copyTask(task) : null;
221
232
  },
222
- add(title: string, note?: string): UserTask {
233
+ add(title: string, note?: string, acceptance?: UserTaskAcceptance): UserTask {
234
+ const normalizedAcceptance = acceptance === undefined ? undefined : normalizeAcceptance(acceptance);
223
235
  const normalizedTitle = title.trim();
224
236
  if (normalizedTitle.length === 0) throw new UserTasksStoreError("operator task title cannot be empty");
225
237
  const normalizedNote = note?.trim();
@@ -229,6 +241,7 @@ export function createUserTasksStore(deps: UserTasksStoreDeps): UserTasksStore {
229
241
  id: `u${file.nextId}`,
230
242
  title: normalizedTitle,
231
243
  ...(normalizedNote ? { note: normalizedNote } : {}),
244
+ ...(normalizedAcceptance ? { acceptance: normalizedAcceptance } : {}),
232
245
  status: "open",
233
246
  createdAt: timestamp,
234
247
  updatedAt: timestamp,
@@ -238,6 +251,16 @@ export function createUserTasksStore(deps: UserTasksStoreDeps): UserTasksStore {
238
251
  save(file);
239
252
  return copyTask(task);
240
253
  },
254
+ setAcceptance(id: string, acceptance: UserTaskAcceptance): UserTask {
255
+ const normalized = normalizeAcceptance(acceptance);
256
+ const file = load();
257
+ const task = file.tasks.find((item) => item.id === id);
258
+ if (!task) throw new UserTasksStoreError(`operator task ${id} was not found`);
259
+ task.acceptance = normalized;
260
+ task.updatedAt = now();
261
+ save(file);
262
+ return copyTask(task);
263
+ },
241
264
  hand(id: string, sessionId?: string): UserTask {
242
265
  return mutate(id, ["open"], "handed", sessionId);
243
266
  },
@@ -295,3 +318,11 @@ export function createUserTasksStore(deps: UserTasksStoreDeps): UserTasksStore {
295
318
  },
296
319
  };
297
320
  }
321
+
322
+ function normalizeAcceptance(raw: unknown): UserTaskAcceptance {
323
+ try {
324
+ return normalizeUserTaskAcceptance(raw);
325
+ } catch (error) {
326
+ throw new UserTasksStoreError(error instanceof Error ? error.message : String(error), { cause: error });
327
+ }
328
+ }
@@ -134,13 +134,15 @@ function flattenPrompt(input: AcpDelegationRunInput): string {
134
134
  return parts.join("\n\n");
135
135
  }
136
136
 
137
- function emptyUsage(): AcpDelegationUsage {
137
+ export function emptyUsage(): AcpDelegationUsage {
138
138
  return {
139
139
  inputTokens: 0,
140
140
  outputTokens: 0,
141
141
  cacheReadTokens: 0,
142
142
  cacheWriteTokens: 0,
143
143
  reasoningTokens: 0,
144
+ totalTokens: 0,
145
+ costUsd: 0,
144
146
  };
145
147
  }
146
148
 
@@ -148,13 +150,29 @@ function finite(value: unknown): number {
148
150
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
149
151
  }
150
152
 
151
- function mergeUsage(into: AcpDelegationUsage, raw: unknown): void {
153
+ /** Same field the ACP server side and `sumRunUsage` read for a dollar figure; cost is never re-derived here. */
154
+ function costTotal(raw: Record<string, unknown>): number {
155
+ const cost = raw.cost;
156
+ return isRecord(cost) ? finite(cost.total) : 0;
157
+ }
158
+
159
+ export function mergeUsage(into: AcpDelegationUsage, raw: unknown): void {
152
160
  if (!isRecord(raw)) return;
153
- into.inputTokens += finite(raw.input) + finite(raw.inputTokens) + finite(raw.input_tokens);
154
- into.outputTokens += finite(raw.output) + finite(raw.outputTokens) + finite(raw.output_tokens);
155
- into.cacheReadTokens += finite(raw.cacheRead) + finite(raw.cacheReadTokens) + finite(raw.cache_read_tokens);
156
- into.cacheWriteTokens += finite(raw.cacheWrite) + finite(raw.cacheWriteTokens) + finite(raw.cache_write_tokens);
161
+ const input = finite(raw.input) + finite(raw.inputTokens) + finite(raw.input_tokens);
162
+ const output = finite(raw.output) + finite(raw.outputTokens) + finite(raw.output_tokens);
163
+ const cacheRead = finite(raw.cacheRead) + finite(raw.cacheReadTokens) + finite(raw.cache_read_tokens);
164
+ const cacheWrite = finite(raw.cacheWrite) + finite(raw.cacheWriteTokens) + finite(raw.cache_write_tokens);
165
+ into.inputTokens += input;
166
+ into.outputTokens += output;
167
+ into.cacheReadTokens += cacheRead;
168
+ into.cacheWriteTokens += cacheWrite;
157
169
  into.reasoningTokens += finite(raw.reasoning) + finite(raw.reasoningTokens) + finite(raw.reasoning_tokens);
170
+ // Same rule as the ACP server accumulator: prefer the peer's explicit total,
171
+ // otherwise sum the four billed categories (reasoning excluded, since a peer
172
+ // that reports it separately still counts it inside output).
173
+ const explicitTotal = finite(raw.totalTokens) + finite(raw.total_tokens);
174
+ into.totalTokens += explicitTotal > 0 ? explicitTotal : input + output + cacheRead + cacheWrite;
175
+ into.costUsd += costTotal(raw);
158
176
  }
159
177
 
160
178
  function errorMessage(value: unknown): string {