@iowarp/clio-coder 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (604) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/CONTRIBUTING.md +142 -52
  3. package/README.md +434 -473
  4. package/SECURITY.md +2 -1
  5. package/dist/{acp-ZILU3AUO.js → acp-H2NGRPWO.js} +12 -12
  6. package/dist/{agents-HYWGBGQR.js → agents-TL5LLUQP.js} +56 -55
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/{auth-N3QT7CBO.js → auth-E5SW4HMS.js} +23 -21
  9. package/dist/builtins-IA7V7FUC.js +22 -0
  10. package/dist/{chunk-7RY5VZPH.js → chunk-2APPQIER.js} +8 -8
  11. package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
  12. package/dist/{chunk-JA5QWE4Z.js → chunk-2UG5F4C5.js} +1973 -1664
  13. package/dist/{chunk-5YHDIDBP.js → chunk-2UH2KFUP.js} +2 -2
  14. package/dist/{chunk-CTJ4RNAA.js → chunk-2VIKGWFZ.js} +2 -2
  15. package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
  16. package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
  17. package/dist/chunk-3EBYEESD.js +314 -0
  18. package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
  19. package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
  20. package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
  21. package/dist/chunk-4UVU7BJ5.js +39 -0
  22. package/dist/{chunk-VKRH2TCS.js → chunk-4WR7VSYB.js} +2 -2
  23. package/dist/{chunk-BBTJOK6Y.js → chunk-54CBCGIR.js} +5 -5
  24. package/dist/{chunk-AP73CFDC.js → chunk-5ICU3EUH.js} +2 -2
  25. package/dist/chunk-5MEZN6CB.js +1334 -0
  26. package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
  27. package/dist/{chunk-ABLSQ6JX.js → chunk-64I3JVYM.js} +8 -2
  28. package/dist/{chunk-AFKWHWXF.js → chunk-6PTFB5VS.js} +39 -22
  29. package/dist/{chunk-VN3SHNBN.js → chunk-7DICMOS6.js} +2 -2
  30. package/dist/chunk-7DRAWPTZ.js +360 -0
  31. package/dist/chunk-7E7I3WLS.js +3762 -0
  32. package/dist/{chunk-BJGUKIG4.js → chunk-7ZYNNDKC.js} +7 -7
  33. package/dist/{chunk-XKA2ICR3.js → chunk-AF4YM7Z4.js} +652 -252
  34. package/dist/{chunk-GVQJ5CCZ.js → chunk-AX2THNSA.js} +12 -12
  35. package/dist/{chunk-IG7BCQBA.js → chunk-B4OAX3SI.js} +65 -3
  36. package/dist/{chunk-TD3PGPQA.js → chunk-B4VEBZKF.js} +3 -3
  37. package/dist/{chunk-74YWRRU5.js → chunk-BEPZRGGU.js} +10 -10
  38. package/dist/{chunk-FEFIFZTL.js → chunk-CE5AX47J.js} +2 -2
  39. package/dist/{chunk-UAPGZHYC.js → chunk-DWUOQKRU.js} +25 -11
  40. package/dist/{chunk-THYWACCR.js → chunk-E3TPLWFX.js} +3 -3
  41. package/dist/{chunk-7EPLI7VL.js → chunk-EKCHAPYA.js} +2 -2
  42. package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
  43. package/dist/{chunk-PJJ6MY27.js → chunk-F5JHEYZM.js} +7 -7
  44. package/dist/{chunk-6CCS4G3W.js → chunk-FTMGRKEF.js} +3 -3
  45. package/dist/{chunk-SINK3QR6.js → chunk-G76U63X4.js} +17 -17
  46. package/dist/{chunk-EIMVLWB3.js → chunk-GHS5EBTQ.js} +64 -9
  47. package/dist/{chunk-QMXC4JB7.js → chunk-GI7YYQ3F.js} +187 -1419
  48. package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
  49. package/dist/{chunk-6HMJX2VU.js → chunk-GWZNEVM2.js} +44 -12
  50. package/dist/chunk-GYV6VZOC.js +26 -0
  51. package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
  52. package/dist/{chunk-UXN6JT4W.js → chunk-HEQY7ZFI.js} +3 -3
  53. package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
  54. package/dist/{chunk-GCSMB2KY.js → chunk-I7ZPNEJM.js} +145 -102
  55. package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
  56. package/dist/{chunk-QTFGO774.js → chunk-IGLP3ODT.js} +29 -16
  57. package/dist/chunk-IJNZMHLA.js +101 -0
  58. package/dist/{chunk-BDPT6GTK.js → chunk-INY6HTFL.js} +7 -7
  59. package/dist/{chunk-PBP4B7XR.js → chunk-IUE3Y34X.js} +2 -2
  60. package/dist/{chunk-6NJQITNH.js → chunk-IWT4SF4R.js} +6 -3
  61. package/dist/{chunk-R23Z6K6I.js → chunk-JDAY6FIL.js} +19 -19
  62. package/dist/chunk-JEQ3XTHC.js +42 -0
  63. package/dist/{chunk-FSP7CMNU.js → chunk-JGRC33J2.js} +50 -4
  64. package/dist/{chunk-TVH4ONAM.js → chunk-JKKCYP3C.js} +10 -10
  65. package/dist/{chunk-HJWWJ6IL.js → chunk-JSC3U7TI.js} +16 -4
  66. package/dist/{chunk-C537JADH.js → chunk-KK4JZPBQ.js} +19 -141
  67. package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
  68. package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
  69. package/dist/{chunk-6DWBAZ5U.js → chunk-L47TF46W.js} +5 -7
  70. package/dist/{chunk-HUAS7ITX.js → chunk-LDJG7DW3.js} +91 -42
  71. package/dist/{chunk-CDNVLKUX.js → chunk-LLDJM5XK.js} +13 -7
  72. package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
  73. package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
  74. package/dist/{chunk-VKFQTNDV.js → chunk-MUW2BDDH.js} +4 -4
  75. package/dist/{chunk-E67WX76H.js → chunk-MWUZBSAQ.js} +104 -152
  76. package/dist/{chunk-OJTRZGR3.js → chunk-N2Z7HLVY.js} +21 -21
  77. package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
  78. package/dist/{chunk-FYUN5KZ3.js → chunk-NIQJ66N4.js} +21 -21
  79. package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
  80. package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
  81. package/dist/{chunk-VEGN6WIQ.js → chunk-O5CVSAG5.js} +3 -3
  82. package/dist/{chunk-MOPSG2X7.js → chunk-OML5D5V5.js} +8 -8
  83. package/dist/{chunk-2VG7KLYV.js → chunk-PAJQJ7BS.js} +5816 -3255
  84. package/dist/{chunk-ZW55JB7N.js → chunk-PUVDKJ2Y.js} +2 -2
  85. package/dist/{chunk-BTGG6BG2.js → chunk-QWGDJJYJ.js} +158 -19
  86. package/dist/chunk-R6Q67RJH.js +134 -0
  87. package/dist/{chunk-ZJLUDYFY.js → chunk-RRNP2ANY.js} +6 -6
  88. package/dist/{chunk-PVAMAVBB.js → chunk-RSJ25QSL.js} +102 -2
  89. package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
  90. package/dist/chunk-SKHCAU7K.js +385 -0
  91. package/dist/chunk-SZAA6XDG.js +30 -0
  92. package/dist/{chunk-J4HBWF6Y.js → chunk-TM6LQDI3.js} +131 -28
  93. package/dist/chunk-UOIZ7DA4.js +41 -0
  94. package/dist/{chunk-MA3H6DM5.js → chunk-UPZU6GE4.js} +25 -3
  95. package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
  96. package/dist/{chunk-N5UK64DP.js → chunk-V2ANDPVT.js} +4 -4
  97. package/dist/{chunk-AK5XEFVZ.js → chunk-VA5FNYMT.js} +26 -13
  98. package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
  99. package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
  100. package/dist/{chunk-QKIFBZKT.js → chunk-VW6DOEDG.js} +497 -81
  101. package/dist/{chunk-SCYB3HA4.js → chunk-W6RRQCPQ.js} +63 -19
  102. package/dist/{chunk-2NM363SV.js → chunk-WBKFA554.js} +10 -10
  103. package/dist/{chunk-R32CLGZ6.js → chunk-WCXUNS7U.js} +82 -21
  104. package/dist/{chunk-GPPB3JBE.js → chunk-WRBAGUNF.js} +3 -3
  105. package/dist/{chunk-IXJT6DCX.js → chunk-XIVNBFZS.js} +85 -30
  106. package/dist/{chunk-UEDMSP56.js → chunk-XPWWI35G.js} +417 -201
  107. package/dist/chunk-XRZT5WY5.js +47 -0
  108. package/dist/{chunk-3QSOM6PA.js → chunk-Y3CBHOR6.js} +2 -2
  109. package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
  110. package/dist/{chunk-AKB4GYDL.js → chunk-YQWYVTMC.js} +5 -5
  111. package/dist/{chunk-6I5ILFOF.js → chunk-ZA4VCIGV.js} +3 -3
  112. package/dist/{chunk-7OBGU7UB.js → chunk-ZDN3Y73Y.js} +12 -18
  113. package/dist/{chunk-3I5NY75V.js → chunk-ZWPRK62N.js} +8 -5
  114. package/dist/cli/index.js +41 -39
  115. package/dist/{clio-IT3G3VQH.js → clio-CMMK4KRR.js} +9 -9
  116. package/dist/{code-nav-RK6S7F6E.js → code-nav-MDZNQS33.js} +89 -21
  117. package/dist/{components-UBWCQSRW.js → components-UCUQ4QXW.js} +4 -4
  118. package/dist/{config-3QZRWZJF.js → config-SVM5P5YI.js} +131 -84
  119. package/dist/{configure-FL7Y3KJF.js → configure-LE3IK2TJ.js} +28 -26
  120. package/dist/{context-5HE7ODYK.js → context-2OHRKS42.js} +69 -64
  121. package/dist/{context-KYQFRVDC.js → context-E3VC7RX5.js} +15 -11
  122. package/dist/{context-XNHL75JV.js → context-VNCR7KAG.js} +93 -65
  123. package/dist/{context-clear-N545L53A.js → context-clear-BW4O37TG.js} +64 -60
  124. package/dist/context-map-COB37XXN.js +505 -0
  125. package/dist/{context-working-set-QHKXSV2F.js → context-working-set-VDS25HXZ.js} +19 -18
  126. package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-5AHT53RF.js} +93 -82
  127. package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
  128. package/dist/{doctor-ZGPEGHIP.js → doctor-WNNVO6FY.js} +48 -47
  129. package/dist/{eval-GXLL44RD.js → eval-7G7SGAYO.js} +287 -115
  130. package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-Y6QRFOH5.js} +4 -4
  131. package/dist/{evidence-HWLBRH3Q.js → evidence-VD6736FQ.js} +67 -64
  132. package/dist/{evolve-FTZBMNVW.js → evolve-AL3NGVRL.js} +65 -62
  133. package/dist/{extensions-VHRBEID7.js → extensions-MOVJ32NM.js} +9 -7
  134. package/dist/{fleet-CKZHJWZJ.js → fleet-QZHUMAGI.js} +114 -111
  135. package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-BAYT5FJZ.js} +10 -10
  136. package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-IREVMRU4.js} +7 -6
  137. package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-YCTT3HTI.js} +22 -19
  138. package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-QVJTDAVB.js} +58 -55
  139. package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-25QAFPK4.js} +4 -4
  140. package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-5O57AAJ7.js} +26 -23
  141. package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-CPH2W2T6.js} +59 -56
  142. package/dist/{fleet-view-WAMJYNDT.js → fleet-view-SWBR3VGQ.js} +58 -55
  143. package/dist/{init-5XQRBOFV.js → init-J477LKZH.js} +82 -79
  144. package/dist/{interop-34TVO25M.js → interop-3FCM6XLG.js} +11 -11
  145. package/dist/{library-3QY6KF57.js → library-QUQEIUG6.js} +30 -27
  146. package/dist/{memory-L4UTIIIW.js → memory-SGGSEP65.js} +67 -64
  147. package/dist/{models-ZVX3QOWE.js → models-HEKUAXXK.js} +53 -46
  148. package/dist/{monitor-CEKVSYTS.js → monitor-HKU57TYQ.js} +63 -60
  149. package/dist/{orchestrator-77BAP6BC.js → orchestrator-VDFAEFAI.js} +1831 -1057
  150. package/dist/{panes-7STHOAUJ.js → panes-DN2SSFOH.js} +5 -5
  151. package/dist/{panes-SHAUIRXY.js → panes-TALGNPZT.js} +29 -14
  152. package/dist/{paths-L7LGY6RN.js → paths-NBMFAIEZ.js} +5 -5
  153. package/dist/reset-EAJFFJVB.js +344 -0
  154. package/dist/{resources-74GKTLSF.js → resources-OVKSEFVE.js} +29 -20
  155. package/dist/{run-HBAUJNNZ.js → run-7DP7ZF2J.js} +120 -115
  156. package/dist/{share-G3APVLVP.js → share-WML67FT3.js} +32 -27
  157. package/dist/{skills-35HHUKCR.js → skills-SG662R2K.js} +41 -31
  158. package/dist/{skills-eval-QN4HSHDC.js → skills-eval-VVZEUU46.js} +78 -77
  159. package/dist/{skills-inventory-J357J34F.js → skills-inventory-I2E23GET.js} +23 -20
  160. package/dist/{slash-commands-JZZCQA32.js → slash-commands-S7MBJDQK.js} +40 -36
  161. package/dist/{steer-XAVHJM22.js → steer-2LQOMCPB.js} +3 -3
  162. package/dist/{support-U7QOWY26.js → support-CC2UJBJ6.js} +6 -6
  163. package/dist/{targets-DSM6CY3M.js → targets-4QC3HIEW.js} +54 -54
  164. package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-TUHIJ6Y2.js} +5 -5
  165. package/dist/{tools-MKNWVPBH.js → tools-TFGJICCU.js} +10 -10
  166. package/dist/{trace-ECQ7TIYZ.js → trace-FXMXUZUF.js} +55 -7
  167. package/dist/uninstall-5PEVOE5B.js +408 -0
  168. package/dist/upgrade-M4WXY6KN.js +303 -0
  169. package/dist/{usage-X52N3IDJ.js → usage-N7ZNVLEM.js} +151 -104
  170. package/dist/{verifiers-EJTVVSMA.js → verifiers-DJTP4XX6.js} +15 -15
  171. package/dist/{verify-YJL6XET2.js → verify-RWE4PPEK.js} +9 -9
  172. package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
  173. package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-C7IQOXSP.js} +89 -86
  174. package/dist/{with-panes-OBOBFIIR.js → with-panes-4GCGSL7J.js} +53 -257
  175. package/dist/worker/entry.js +90 -74
  176. package/docs/README.md +176 -81
  177. package/docs/{acp.md → architecture/acp.md} +36 -20
  178. package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
  179. package/docs/{architecture.md → architecture/architecture.md} +43 -22
  180. package/docs/{artifact-placement.md → architecture/artifact-placement.md} +27 -23
  181. package/docs/architecture/artifact-versions.md +90 -0
  182. package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
  183. package/docs/{context-engine.md → architecture/context-engine.md} +29 -25
  184. package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
  185. package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
  186. package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
  187. package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
  188. package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
  189. package/docs/{model-catalog.md → architecture/model-catalog.md} +61 -27
  190. package/docs/{observability.md → architecture/observability.md} +38 -14
  191. package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
  192. package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +57 -20
  193. package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +99 -25
  194. package/docs/{safety-model.md → architecture/safety-model.md} +35 -20
  195. package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
  196. package/docs/architecture/time-conventions.md +125 -0
  197. package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
  198. package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
  199. package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
  200. package/docs/{built-in-agents.md → guide/built-in-agents.md} +65 -35
  201. package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +66 -61
  202. package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +323 -297
  203. package/docs/guide/configuration-reference.md +1163 -0
  204. package/docs/{environment-variables.md → guide/environment-variables.md} +33 -28
  205. package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
  206. package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
  207. package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
  208. package/docs/{glossary.md → guide/glossary.md} +14 -11
  209. package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +81 -17
  210. package/docs/guide/panes-and-files.md +290 -0
  211. package/docs/{proactive-memory.md → guide/proactive-memory.md} +131 -107
  212. package/docs/{resource-library.md → guide/resource-library.md} +13 -4
  213. package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +25 -3
  214. package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
  215. package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
  216. package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
  217. package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
  218. package/docs/process/development-pipeline.md +152 -0
  219. package/docs/process/documentation-coverage.md +100 -0
  220. package/docs/process/documentation-guide.md +187 -0
  221. package/docs/{eval-runner.md → process/eval-runner.md} +108 -53
  222. package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
  223. package/docs/{evolution.md → process/evolution.md} +2 -2
  224. package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
  225. package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
  226. package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
  227. package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
  228. package/evals/README.md +2 -2
  229. package/evals/behavioral-model.yaml +3 -2
  230. package/package.json +10 -8
  231. package/skills/README.md +52 -41
  232. package/skills/coding/ast-grep/SKILL.md +102 -31
  233. package/skills/coding/ast-grep/evals.md +26 -0
  234. package/skills/coding/coding-standards/SKILL.md +41 -6
  235. package/skills/coding/coding-standards/evals.md +23 -0
  236. package/skills/coding/prototype/SKILL.md +88 -29
  237. package/skills/coding/prototype/evals.md +19 -0
  238. package/skills/coding/tdd/SKILL.md +81 -54
  239. package/skills/coding/tdd/evals.md +20 -0
  240. package/skills/context/context-handoff/SKILL.md +44 -3
  241. package/skills/context/context-handoff/evals.md +44 -0
  242. package/skills/context/context-prime/SKILL.md +46 -16
  243. package/skills/context/context-prime/evals.md +45 -0
  244. package/skills/git/branch-closeout/SKILL.md +132 -0
  245. package/skills/git/branch-closeout/evals.md +133 -0
  246. package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
  247. package/skills/git/file-ticket/SKILL.md +78 -64
  248. package/skills/git/file-ticket/assets/issue-template.md +22 -0
  249. package/skills/git/file-ticket/evals.md +31 -26
  250. package/skills/git/file-ticket/references/issue-discovery.md +49 -0
  251. package/skills/git/fix-issue/SKILL.md +88 -65
  252. package/skills/git/fix-issue/evals.md +35 -31
  253. package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
  254. package/skills/git/resolve-merge-conflicts/SKILL.md +101 -52
  255. package/skills/git/resolve-merge-conflicts/evals.md +52 -25
  256. package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
  257. package/skills/git/ship/SKILL.md +103 -67
  258. package/skills/git/ship/assets/pr-template.md +21 -0
  259. package/skills/git/ship/evals.md +44 -28
  260. package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
  261. package/skills/git/worktree-create/SKILL.md +80 -50
  262. package/skills/git/worktree-create/evals.md +40 -33
  263. package/skills/git/worktree-create/references/worktree-setup.md +62 -66
  264. package/skills/git/worktree-merge/SKILL.md +112 -65
  265. package/skills/git/worktree-merge/evals.md +42 -34
  266. package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
  267. package/skills/meta/clio-coder-dev/SKILL.md +9 -5
  268. package/skills/meta/clio-coder-dev/evals.md +3 -2
  269. package/skills/meta/clio-coder-test/SKILL.md +102 -95
  270. package/skills/meta/clio-coder-test/evals.md +9 -4
  271. package/skills/meta/clio-coder-test/references/harness.md +100 -124
  272. package/skills/meta/clio-coder-test/references/test-map.md +77 -50
  273. package/skills/meta/credentials/SKILL.md +2 -2
  274. package/skills/meta/find-skills/SKILL.md +2 -2
  275. package/skills/meta/herdr/SKILL.md +2 -2
  276. package/skills/meta/skill-craft/SKILL.md +22 -16
  277. package/skills/planning/archify/SKILL.md +196 -0
  278. package/skills/planning/archify/evals.md +65 -0
  279. package/skills/planning/architecture/SKILL.md +62 -13
  280. package/skills/planning/architecture/evals.md +65 -0
  281. package/skills/planning/backlog/SKILL.md +131 -15
  282. package/skills/planning/backlog/evals.md +142 -0
  283. package/skills/planning/prd/SKILL.md +47 -7
  284. package/skills/planning/prd/evals.md +54 -0
  285. package/skills/planning/product-intent/SKILL.md +58 -3
  286. package/skills/planning/product-intent/evals.md +70 -0
  287. package/skills/planning/tech-spec/SKILL.md +54 -3
  288. package/skills/planning/tech-spec/evals.md +73 -0
  289. package/skills/registry.yaml +70 -62
  290. package/skills/remote.yaml +13 -0
  291. package/skills/research/arxiv-literature/SKILL.md +77 -19
  292. package/skills/research/arxiv-literature/evals.md +50 -0
  293. package/skills/research/experiment-protocol/SKILL.md +21 -2
  294. package/skills/research/experiment-protocol/evals.md +23 -0
  295. package/skills/research/scientific-debugging/SKILL.md +24 -2
  296. package/skills/research/scientific-debugging/evals.md +18 -0
  297. package/skills/research/scientific-modernization/SKILL.md +27 -2
  298. package/skills/research/scientific-modernization/evals.md +27 -0
  299. package/skills/skill-marketplace.json +97 -62
  300. package/skills/workflow/cut-it/SKILL.md +66 -6
  301. package/skills/workflow/cut-it/evals.md +101 -0
  302. package/skills/workflow/design-council/SKILL.md +118 -28
  303. package/skills/workflow/design-council/evals.md +161 -0
  304. package/skills/workflow/grill-me/SKILL.md +87 -11
  305. package/skills/workflow/grill-me/evals.md +153 -0
  306. package/skills/workflow/workflow-distiller/SKILL.md +77 -18
  307. package/skills/workflow/workflow-distiller/evals.md +118 -0
  308. package/src/cli/args.ts +2 -2
  309. package/src/cli/bootstrap-generate.ts +1 -1
  310. package/src/cli/config-inspect.ts +65 -12
  311. package/src/cli/configure-interop.ts +105 -13
  312. package/src/cli/configure-oauth.ts +57 -0
  313. package/src/cli/configure-onboarding.ts +980 -0
  314. package/src/cli/configure-target.ts +594 -0
  315. package/src/cli/configure.ts +1082 -532
  316. package/src/cli/context-map.ts +114 -0
  317. package/src/cli/context.ts +4 -0
  318. package/src/cli/docs.ts +22 -14
  319. package/src/cli/doctor-naming.ts +5 -5
  320. package/src/cli/doctor-toolchain.ts +3 -3
  321. package/src/cli/eval.ts +1 -2
  322. package/src/cli/extensions.ts +2 -1
  323. package/src/cli/fleet.ts +1 -1
  324. package/src/cli/index.ts +3 -1
  325. package/src/cli/internal-dispatch.ts +3 -4
  326. package/src/cli/lifecycle-presenter.ts +436 -0
  327. package/src/cli/models.ts +10 -2
  328. package/src/cli/modes/print.ts +5 -1
  329. package/src/cli/panes.ts +19 -5
  330. package/src/cli/reset.ts +228 -106
  331. package/src/cli/run.ts +9 -4
  332. package/src/cli/select.ts +664 -0
  333. package/src/cli/share.ts +5 -1
  334. package/src/cli/skills-eval.ts +3 -3
  335. package/src/cli/skills.ts +9 -2
  336. package/src/cli/targets.ts +5 -6
  337. package/src/cli/trace.ts +55 -4
  338. package/src/cli/uninstall.ts +233 -165
  339. package/src/cli/upgrade.ts +204 -149
  340. package/src/cli/usage.ts +86 -27
  341. package/src/cli/validate-model.ts +3 -3
  342. package/src/cli/wiki-generate.ts +1 -1
  343. package/src/core/artifact-paths.ts +1 -1
  344. package/src/core/bash-exec.ts +131 -86
  345. package/src/core/bus-events.ts +51 -6
  346. package/src/core/config.ts +61 -1
  347. package/src/core/defaults.ts +7 -4
  348. package/src/core/dispatch-outcome.ts +16 -0
  349. package/src/core/external-diagnostic.ts +44 -0
  350. package/src/core/gateway-routing.ts +157 -0
  351. package/src/core/guardrails.ts +10 -49
  352. package/src/core/prompt-hint.ts +9 -0
  353. package/src/core/safe-exec.ts +17 -2
  354. package/src/core/skill-activation.ts +89 -2
  355. package/src/domains/agents/builtins/architect.md +2 -3
  356. package/src/domains/agents/builtins/coder.md +3 -2
  357. package/src/domains/agents/builtins/debugger.md +2 -2
  358. package/src/domains/agents/builtins/documenter.md +2 -2
  359. package/src/domains/agents/builtins/git-master.md +1 -1
  360. package/src/domains/agents/builtins/oracle.md +1 -1
  361. package/src/domains/agents/builtins/provenance.md +1 -1
  362. package/src/domains/agents/builtins/researcher.md +1 -1
  363. package/src/domains/agents/builtins/scout.md +1 -1
  364. package/src/domains/agents/builtins/tester.md +2 -2
  365. package/src/domains/agents/builtins/verifier.md +2 -2
  366. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  367. package/src/domains/agents/builtins/world-knowledge.md +31 -0
  368. package/src/domains/agents/catalog.ts +13 -15
  369. package/src/domains/agents/contract.ts +2 -0
  370. package/src/domains/agents/extension.ts +23 -1
  371. package/src/domains/agents/result-contract.ts +70 -0
  372. package/src/domains/config/keybindings.ts +8 -0
  373. package/src/domains/context/extension.ts +0 -3
  374. package/src/domains/context/wiki/map-seed.ts +589 -0
  375. package/src/domains/context/wiki/plan.ts +2 -2
  376. package/src/domains/context/working-set/path-index.ts +1 -0
  377. package/src/domains/dispatch/admission.ts +29 -0
  378. package/src/domains/dispatch/agent-candidates.ts +10 -0
  379. package/src/domains/dispatch/budget-envelope.ts +86 -1
  380. package/src/domains/dispatch/capability-match.ts +11 -0
  381. package/src/domains/dispatch/capacity-lease.ts +17 -0
  382. package/src/domains/dispatch/contract.ts +11 -1
  383. package/src/domains/dispatch/extension.ts +237 -49
  384. package/src/domains/dispatch/host-verification.ts +435 -39
  385. package/src/domains/dispatch/intent-requirements.ts +10 -0
  386. package/src/domains/dispatch/intent.ts +18 -1
  387. package/src/domains/dispatch/path-scope.ts +235 -24
  388. package/src/domains/dispatch/run-event-journal.ts +4 -15
  389. package/src/domains/dispatch/state.ts +2 -3
  390. package/src/domains/dispatch/transport.ts +45 -21
  391. package/src/domains/dispatch/types.ts +58 -3
  392. package/src/domains/dispatch/worker-model-metadata.ts +38 -0
  393. package/src/domains/eval/artifacts/store.ts +5 -0
  394. package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
  395. package/src/domains/eval/metrics/token-stream.ts +201 -31
  396. package/src/domains/eval/metrics/tracked.ts +40 -4
  397. package/src/domains/eval/runners/clio-run.ts +5 -2
  398. package/src/domains/eval/schema/suite.ts +28 -0
  399. package/src/domains/eval/schema/verdict.ts +2 -2
  400. package/src/domains/eval/store.ts +8 -1
  401. package/src/domains/eval/suites/resolve.ts +13 -1
  402. package/src/domains/eval/suites/run.ts +24 -3
  403. package/src/domains/evidence/trust-status.ts +10 -1
  404. package/src/domains/extensions/contract.ts +15 -1
  405. package/src/domains/extensions/discovery.ts +238 -41
  406. package/src/domains/extensions/extension.ts +105 -6
  407. package/src/domains/extensions/index.ts +24 -0
  408. package/src/domains/extensions/integrity.ts +189 -0
  409. package/src/domains/extensions/manager.ts +17 -1
  410. package/src/domains/extensions/resource-path.ts +27 -0
  411. package/src/domains/extensions/resources.ts +18 -38
  412. package/src/domains/extensions/snapshot-store.ts +39 -0
  413. package/src/domains/extensions/snapshot.ts +180 -0
  414. package/src/domains/extensions/state.ts +385 -57
  415. package/src/domains/extensions/types.ts +118 -1
  416. package/src/domains/interop/registry.ts +6 -2
  417. package/src/domains/interop/types.ts +4 -0
  418. package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
  419. package/src/domains/lifecycle/migrations/index.ts +6 -0
  420. package/src/domains/lifecycle/naming-resources.ts +19 -4
  421. package/src/domains/lifecycle/naming-yazi.ts +10 -5
  422. package/src/domains/memory/task-memory-policy.ts +70 -26
  423. package/src/domains/memory/task-memory-telemetry.ts +1 -0
  424. package/src/domains/middleware/contract.ts +26 -0
  425. package/src/domains/middleware/extension.ts +24 -24
  426. package/src/domains/middleware/hook-receipts.ts +27 -4
  427. package/src/domains/middleware/hooks-io.ts +65 -32
  428. package/src/domains/middleware/hooks.ts +64 -0
  429. package/src/domains/middleware/index.ts +28 -5
  430. package/src/domains/middleware/marketplace-offer.ts +3 -35
  431. package/src/domains/middleware/memory-intervention.ts +127 -32
  432. package/src/domains/middleware/memory-step-endpoint.ts +3 -2
  433. package/src/domains/middleware/registrations.ts +326 -0
  434. package/src/domains/middleware/runtime.ts +28 -0
  435. package/src/domains/middleware/skills-reminder.ts +31 -2
  436. package/src/domains/middleware/snapshot.ts +20 -7
  437. package/src/domains/mux/contract.ts +38 -0
  438. package/src/domains/mux/detect.ts +6 -13
  439. package/src/domains/mux/index.ts +1 -1
  440. package/src/domains/mux/operations.ts +44 -5
  441. package/src/domains/mux/yazi/assets/yazi.toml +2 -2
  442. package/src/domains/mux/yazi/session.ts +53 -4
  443. package/src/domains/mux/yazi/theme.ts +117 -17
  444. package/src/domains/observability/compaction-usage.ts +118 -0
  445. package/src/domains/observability/contract.ts +10 -11
  446. package/src/domains/observability/cost.ts +1 -1
  447. package/src/domains/observability/extension.ts +17 -4
  448. package/src/domains/observability/out-of-turn-usage.ts +52 -21
  449. package/src/domains/observability/projection.ts +14 -90
  450. package/src/domains/observability/trace-store.ts +43 -7
  451. package/src/domains/prompts/compiler.ts +73 -53
  452. package/src/domains/prompts/contract.ts +15 -3
  453. package/src/domains/prompts/extension.ts +97 -9
  454. package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
  455. package/src/domains/prompts/fragments/identity/clio.md +6 -12
  456. package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
  457. package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
  458. package/src/domains/prompts/fragments/operating/contract.md +7 -15
  459. package/src/domains/prompts/fragments/operating/delegation.md +32 -34
  460. package/src/domains/prompts/fragments/operating/skills.md +10 -24
  461. package/src/domains/prompts/fragments/operating/worker.md +1 -8
  462. package/src/domains/providers/contract.ts +4 -1
  463. package/src/domains/providers/extension.ts +40 -9
  464. package/src/domains/providers/index.ts +1 -1
  465. package/src/domains/providers/model-capabilities.ts +9 -0
  466. package/src/domains/providers/model-discovery.ts +2 -0
  467. package/src/domains/providers/model-runtime-capabilities.ts +99 -25
  468. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +699 -114
  469. package/src/domains/providers/runtime-resolution.ts +31 -0
  470. package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
  471. package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
  472. package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
  473. package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
  474. package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
  475. package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
  476. package/src/domains/providers/support.ts +11 -5
  477. package/src/domains/providers/target-model-cache.ts +25 -2
  478. package/src/domains/providers/types/capability-flags.ts +2 -0
  479. package/src/domains/providers/types/cost-provenance.ts +19 -0
  480. package/src/domains/providers/types/local-model-quirks.ts +85 -37
  481. package/src/domains/providers/types/runtime-descriptor.ts +20 -1
  482. package/src/domains/providers/types/target-descriptor.ts +19 -0
  483. package/src/domains/resources/index.ts +3 -0
  484. package/src/domains/resources/skills/install.ts +72 -7
  485. package/src/domains/resources/skills/loader.ts +23 -19
  486. package/src/domains/resources/skills/marketplace.ts +63 -11
  487. package/src/domains/safety/autonomy.ts +15 -0
  488. package/src/domains/safety/call-target.ts +1 -1
  489. package/src/domains/safety/index.ts +1 -0
  490. package/src/domains/safety/loop-detector.ts +7 -4
  491. package/src/domains/safety/path-policy.ts +1 -1
  492. package/src/domains/safety/policy-engine.ts +34 -11
  493. package/src/domains/safety/protected-artifacts.ts +191 -88
  494. package/src/domains/safety/run-effects.ts +2 -22
  495. package/src/domains/safety/skill-authority.ts +55 -0
  496. package/src/domains/session/compaction/compact.ts +72 -22
  497. package/src/domains/session/entries.ts +6 -0
  498. package/src/domains/session/task-board.ts +10 -9
  499. package/src/domains/session/usage.ts +3 -3
  500. package/src/domains/share/archive.ts +164 -7
  501. package/src/engine/acp/server.ts +62 -9
  502. package/src/engine/agent.ts +13 -3
  503. package/src/engine/ai.ts +26 -8
  504. package/src/engine/antigravity/subprocess-runtime.ts +386 -120
  505. package/src/engine/api-registry.ts +3 -0
  506. package/src/engine/apis/llamacpp-residency.ts +3 -4
  507. package/src/engine/apis/lmstudio.ts +3 -3
  508. package/src/engine/apis/ollama-native.ts +6 -6
  509. package/src/engine/apis/openai-completions.ts +145 -39
  510. package/src/engine/apis/output-budget.ts +8 -18
  511. package/src/engine/apis/residency.ts +8 -27
  512. package/src/engine/external-subprocess.ts +114 -6
  513. package/src/engine/gemma-channel-filter.ts +19 -0
  514. package/src/engine/loop-guard.ts +92 -12
  515. package/src/engine/worker-runtime.ts +40 -11
  516. package/src/engine/worker-tools.ts +3 -1
  517. package/src/entry/background-model-metadata.ts +18 -0
  518. package/src/entry/compaction-prompt.ts +57 -0
  519. package/src/entry/extension-hook-sources.ts +28 -0
  520. package/src/entry/extension-reload.ts +309 -0
  521. package/src/entry/orchestrator.ts +464 -251
  522. package/src/entry/task-memory-lifecycle.ts +35 -0
  523. package/src/interactive/application-controller.ts +2 -1
  524. package/src/interactive/bus-notices.ts +8 -1
  525. package/src/interactive/chat-loop-messages.ts +16 -17
  526. package/src/interactive/chat-loop.ts +75 -3
  527. package/src/interactive/chat-panel.ts +36 -13
  528. package/src/interactive/chat-renderer.ts +72 -7
  529. package/src/interactive/cost-overlay.ts +26 -2
  530. package/src/interactive/dispatch-board.ts +6 -11
  531. package/src/interactive/footer/widgets.ts +13 -0
  532. package/src/interactive/interactive-application.ts +39 -4
  533. package/src/interactive/interactive-input-runtime.ts +4 -0
  534. package/src/interactive/interactive-presentation.ts +2 -2
  535. package/src/interactive/interactive-slash-runtime.ts +4 -1
  536. package/src/interactive/overlays/extensions.ts +9 -1
  537. package/src/interactive/overlays/help-reference.ts +13 -0
  538. package/src/interactive/overlays/settings.ts +27 -16
  539. package/src/interactive/panes-runtime.ts +111 -35
  540. package/src/interactive/prompt-cache-identity.ts +88 -0
  541. package/src/interactive/renderers/worker-entry.ts +32 -0
  542. package/src/interactive/slash-commands.ts +153 -20
  543. package/src/interactive/stream-pacing-policy.ts +0 -23
  544. package/src/interactive/theme/labels.ts +19 -13
  545. package/src/interactive/turn-context.ts +39 -20
  546. package/src/interactive/turn-recovery.ts +8 -0
  547. package/src/interactive/turn-runtime.ts +27 -11
  548. package/src/interactive/turn-state.ts +7 -0
  549. package/src/interactive/worker-receipts.ts +1 -0
  550. package/src/interactive/worker-stream.ts +6 -1
  551. package/src/interactive/yazi-bridge.ts +60 -6
  552. package/src/tools/agent-tools.ts +30 -1
  553. package/src/tools/artifact.ts +2 -2
  554. package/src/tools/ask-user.ts +3 -3
  555. package/src/tools/bash.ts +1 -1
  556. package/src/tools/bootstrap.ts +4 -0
  557. package/src/tools/builtin-tool-catalog.ts +52 -22
  558. package/src/tools/codewiki/code-nav-surface.ts +6 -0
  559. package/src/tools/codewiki/code-nav.ts +99 -13
  560. package/src/tools/context/docs-engine.ts +20 -7
  561. package/src/tools/context/index.ts +59 -21
  562. package/src/tools/core-bootstrap.ts +28 -6
  563. package/src/tools/credential-present.ts +1 -2
  564. package/src/tools/dispatch-arguments.ts +6 -1
  565. package/src/tools/dispatch-event-text.ts +10 -0
  566. package/src/tools/dispatch-plan.ts +49 -4
  567. package/src/tools/dispatch-run-events.ts +1 -1
  568. package/src/tools/dispatch-runner.ts +12 -0
  569. package/src/tools/dispatch-schema.ts +338 -0
  570. package/src/tools/dispatch-types.ts +3 -0
  571. package/src/tools/dispatch.ts +9 -254
  572. package/src/tools/ledger.ts +3 -5
  573. package/src/tools/monitor-surface.ts +5 -13
  574. package/src/tools/observation.ts +4 -5
  575. package/src/tools/panes-surface.ts +4 -11
  576. package/src/tools/panes.ts +4 -2
  577. package/src/tools/policy.ts +15 -2
  578. package/src/tools/read.ts +5 -6
  579. package/src/tools/registry.ts +41 -12
  580. package/src/tools/result-shaping.ts +18 -14
  581. package/src/tools/steer-surface.ts +1 -1
  582. package/src/tools/tasks.ts +1 -1
  583. package/src/tools/truncate.ts +6 -5
  584. package/src/tools/verify/surface.ts +6 -12
  585. package/src/tools/web-fetch-surface.ts +1 -3
  586. package/src/tools/worker-evidence.ts +3 -1
  587. package/src/worker/spec-contract.ts +4 -0
  588. package/dist/builtins-UJLMOVOV.js +0 -17
  589. package/dist/chunk-5QIAJV2D.js +0 -48
  590. package/dist/chunk-JZWT5J3Y.js +0 -814
  591. package/dist/chunk-K7VKOLQQ.js +0 -15
  592. package/dist/chunk-PMZCIOCJ.js +0 -25
  593. package/dist/chunk-SUW5DORT.js +0 -819
  594. package/dist/chunk-UOV2BYIW.js +0 -107
  595. package/dist/chunk-WR6U3OVP.js +0 -45
  596. package/dist/chunk-Y45G3AXC.js +0 -1558
  597. package/dist/reset-EOLM7GVE.js +0 -230
  598. package/dist/uninstall-N34PCTGJ.js +0 -331
  599. package/dist/upgrade-H7TOM7YL.js +0 -323
  600. package/docs/artifact-versions.md +0 -67
  601. package/docs/development-pipeline.md +0 -121
  602. package/docs/documentation-coverage.md +0 -46
  603. package/docs/documentation-guide.md +0 -167
  604. package/docs/time-conventions.md +0 -101
@@ -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
+ }
@@ -18,25 +18,24 @@ export interface TokenThroughputSnapshot {
18
18
  }
19
19
 
20
20
  /**
21
- * One bounded, product-facing observability event. Notices are a redacted,
22
- * append-only stream: a runtime eviction, a blocked tool, a hook crash, a
23
- * pruned context window, and so on. They never carry raw worker output or tool
24
- * arguments; `message` is a short rendered line and `ref` links back to the
25
- * subject (a run, a target, an evidence bundle) without embedding its contents.
21
+ * One bounded, product-facing observability event: an evidence build that
22
+ * failed for a run, read by the Dispatch Board to explain why a run has no
23
+ * evidence bundle. This used to also carry runtime/middleware/safety/loop/
24
+ * tool-budget/context/budget notices classified off the same bus channels the
25
+ * interactive layer's own notice pipeline (bus-notices.ts and
26
+ * interactive-event-projection.ts) classifies independently for the toast
27
+ * surface a session actually shows; those seven kinds had no reader of their
28
+ * own here and were removed rather than kept as an unread second opinion.
29
+ * `message` is a short rendered line and `ref` links back to the run.
26
30
  */
27
31
  export interface ObservabilityNotice {
28
32
  id: string;
29
33
  at: number;
30
- kind: "runtime" | "middleware" | "safety" | "loop" | "tool-budget" | "context" | "budget" | "provider" | "evidence";
34
+ kind: "evidence";
31
35
  level: "info" | "warning" | "error";
32
36
  message: string;
33
37
  ref?: {
34
38
  runId?: string;
35
- agentId?: string;
36
- targetId?: string;
37
- modelId?: string;
38
- evidenceId?: string;
39
- tool?: string;
40
39
  };
41
40
  }
42
41
 
@@ -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;
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Observability domain wire-up. Listens to dispatch + safety bus channels and
3
- * folds payloads into telemetry/cost trackers. Emits nothing; other domains
4
- * read the snapshot through the contract.
3
+ * folds payloads into telemetry/cost trackers. Other domains read the snapshot
4
+ * through the contract; the one thing it emits is
5
+ * `accountability.evidenceReady`, once per run whose evidence bundle landed.
5
6
  */
6
7
 
7
8
  import { BusChannels, type DispatchCompletedPayload } from "../../core/bus-events.js";
@@ -36,6 +37,11 @@ type DispatchTerminalLike = {
36
37
  [K in keyof DispatchCompletedPayload]?: DispatchCompletedPayload[K] | undefined;
37
38
  };
38
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
+
39
45
  function recordDispatchCost(
40
46
  telemetry: ReturnType<typeof createTelemetry>,
41
47
  cost: ReturnType<typeof createCostTracker>,
@@ -171,7 +177,14 @@ export function createObservabilityBundle(
171
177
  const trackBuild = (runId: string, succeeded: boolean, attempt: number | undefined): void => {
172
178
  projection.evidenceBuildStarted(runId);
173
179
  const build = buildAndIndexEvidence(runId, succeeded, attempt, {
174
- onReady: (id, evidence) => projection.evidenceBuildSucceeded(id, evidence),
180
+ onReady: (id, evidence) => {
181
+ projection.evidenceBuildSucceeded(id, evidence);
182
+ // The same fact, once, for listeners outside this closure (the ACP
183
+ // server forwards it as the opt-in `accountability.evidenceReady`
184
+ // kind). The payload spreads the evidence object the projection just
185
+ // received rather than rebuilding it, so the two cannot drift.
186
+ context.bus.emit(BusChannels.AccountabilityEvidenceReady, { runId: id, ...evidence });
187
+ },
175
188
  onFailed: (id, message) => projection.evidenceBuildFailed(id, message),
176
189
  });
177
190
  pendingBuilds.add(build);
@@ -214,7 +227,7 @@ export function createObservabilityBundle(
214
227
  recordDispatchCost(telemetry, cost, payload);
215
228
  // A failed run is never a first-pass success; still build the
216
229
  // bundle so its failure-cause tags exist for the index.
217
- if (typeof payload.runId === "string" && payload.runId.length > 0) {
230
+ if (typeof payload.runId === "string" && payload.runId.length > 0 && dispatchHasEvidenceLedger(payload)) {
218
231
  trackBuild(payload.runId, false, payload.lineage?.attempt);
219
232
  }
220
233
  }),
@@ -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 priced out-of-turn call. Never throws: this runs on the same path
119
- * that answers an operator's side question, and a failed bookkeeping write must
120
- * not take the answer down with it.
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(stateDir: string, row: OutOfTurnUsageRow): void {
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
- writeSync(fd, `${JSON.stringify(row)}\n`);
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 (label !== "side-question" && label !== "handoff" && label !== "prewarm" && label !== "background-memory")
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: numberOr0(usage.input),
227
- output: numberOr0(usage.output),
228
- cacheRead: numberOr0(usage.cacheRead),
229
- cacheWrite: numberOr0(usage.cacheWrite),
230
- reasoning: numberOr0(usage.reasoning),
231
- totalTokens: numberOr0(usage.totalTokens),
232
- costUsd: numberOr0(usage.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
  }
@@ -17,8 +17,10 @@
17
17
  */
18
18
 
19
19
  import { BusChannels } from "../../core/bus-events.js";
20
+ import { resolveDispatchFailureStatus } from "../../core/dispatch-outcome.js";
20
21
  import type { SafeEventBus } from "../../core/event-bus.js";
21
22
  import type { TargetStatus } from "../providers/contract.js";
23
+ import { resolveCostProvenance } from "../providers/types/cost-provenance.js";
22
24
  import type { AccountabilitySummary } from "./accountability.js";
23
25
  import type {
24
26
  ObservabilityNotice,
@@ -94,17 +96,6 @@ function resolveHeartbeat(status: unknown): ObservabilityRunSummary["status"] |
94
96
  return null;
95
97
  }
96
98
 
97
- /** Map a DispatchFailed outcome/reason to a summary status, mirroring the board. */
98
- function resolveFailedStatus(reason: unknown): ObservabilityRunSummary["status"] {
99
- if (reason === "dead" || reason === "stalled") return "dead";
100
- if (reason === "interrupted" || reason === "canceled") return "aborted";
101
- return "failed";
102
- }
103
-
104
- function normalizeLevel(value: unknown): ObservabilityNotice["level"] {
105
- return value === "error" || value === "warning" || value === "info" ? value : "info";
106
- }
107
-
108
99
  /** Build a notice ref from candidate parts, dropping anything non-string/empty. */
109
100
  function makeRef(parts: Record<string, unknown>): ObservabilityNotice["ref"] | undefined {
110
101
  const ref: Record<string, string> = {};
@@ -216,22 +207,20 @@ export function createObservabilityProjection(bus: SafeEventBus, deps: Projectio
216
207
  if (typeof id.runtimeKind === "string" && id.runtimeKind.length > 0) summary.runtimeKind = id.runtimeKind;
217
208
  }
218
209
 
210
+ // num()'s Number.isFinite check matters here specifically: a NaN or
211
+ // Infinity costUsd/tokenCount from a payload used to pass the bare
212
+ // `typeof === "number"` check this function had instead, so the projection
213
+ // could corrupt a run's running total on a malformed terminal payload while
214
+ // the dispatch board's parseFiniteNumber (an identical check) rejected it.
219
215
  function applyTerminalTokens(summary: ObservabilityRunSummary, payload: Record<string, unknown>): void {
220
- if (typeof payload.tokenCount === "number") summary.tokens.total = payload.tokenCount;
216
+ summary.tokens.total = num(payload.tokenCount, summary.tokens.total);
221
217
  if (typeof payload.inputTokenCount === "number") {
222
- summary.tokens.input = payload.inputTokenCount + num(payload.cacheReadTokenCount, 0);
223
- }
224
- if (typeof payload.outputTokenCount === "number") summary.tokens.output = payload.outputTokenCount;
225
- if (typeof payload.reasoningTokenCount === "number") summary.tokens.reasoning = payload.reasoningTokenCount;
226
- if (typeof payload.costUsd === "number") summary.costUsd = payload.costUsd;
227
- if (
228
- payload.costProvenance === "known" ||
229
- payload.costProvenance === "known_free" ||
230
- payload.costProvenance === "estimated" ||
231
- payload.costProvenance === "unknown"
232
- ) {
233
- summary.costProvenance = payload.costProvenance;
218
+ summary.tokens.input = num(payload.inputTokenCount, summary.tokens.input) + num(payload.cacheReadTokenCount, 0);
234
219
  }
220
+ summary.tokens.output = num(payload.outputTokenCount, summary.tokens.output);
221
+ summary.tokens.reasoning = num(payload.reasoningTokenCount, summary.tokens.reasoning);
222
+ summary.costUsd = num(payload.costUsd, summary.costUsd);
223
+ summary.costProvenance = resolveCostProvenance(payload.costProvenance, summary.costProvenance);
235
224
  }
236
225
 
237
226
  function pushNotice(
@@ -337,7 +326,7 @@ export function createObservabilityProjection(bus: SafeEventBus, deps: Projectio
337
326
  const now = Date.now();
338
327
  const summary = runs.get(runId) ?? emptyRun(runId, now);
339
328
  applyIdentity(summary, payload);
340
- summary.status = resolveFailedStatus(payload.reason);
329
+ summary.status = resolveDispatchFailureStatus(payload.reason);
341
330
  summary.updatedAtMs = now;
342
331
  summary.finishedAtMs = now;
343
332
  summary.durationMs = num(payload.durationMs, Math.max(0, now - summary.startedAtMs));
@@ -355,71 +344,6 @@ export function createObservabilityProjection(bus: SafeEventBus, deps: Projectio
355
344
  providerHealth.set(payload.id, payload.status as TargetStatus);
356
345
  markChanged();
357
346
  }),
358
- bus.on(BusChannels.RuntimeNotice, (raw: unknown) => {
359
- const payload = (raw ?? {}) as Record<string, unknown>;
360
- pushNotice(
361
- "runtime",
362
- normalizeLevel(payload.level),
363
- str(payload.message, "runtime notice"),
364
- makeRef({ targetId: payload.targetId, modelId: payload.model }),
365
- );
366
- }),
367
- bus.on(BusChannels.MiddlewareHookFailed, (raw: unknown) => {
368
- const payload = (raw ?? {}) as Record<string, unknown>;
369
- const kind = payload.kind;
370
- // Mirror the interactive notice policy: every crashed hook surfaces, but
371
- // a budget overrun only surfaces once it is steady-state slowness.
372
- if (kind === "budget_exceeded" && payload.steadyStateWarn !== true) return;
373
- const hook = str(payload.hook, "hook");
374
- const message =
375
- typeof payload.message === "string" && payload.message.length > 0
376
- ? payload.message
377
- : kind === "budget_exceeded"
378
- ? `middleware hook ${hook} exceeded ${num(payload.budgetMs, 0)}ms budget`
379
- : `middleware hook ${hook} failed`;
380
- pushNotice("middleware", kind === "budget_exceeded" ? "warning" : "error", message);
381
- }),
382
- bus.on(BusChannels.SafetyBlocked, (raw: unknown) => {
383
- const payload = (raw ?? {}) as Record<string, unknown>;
384
- const tool = str(payload.tool, "tool");
385
- const rejection = (payload.rejection ?? {}) as { short?: unknown };
386
- const short = str(rejection.short, `${str(payload.actionClass, "action")} blocked`);
387
- pushNotice("safety", "warning", `${tool}: ${short}`, makeRef({ tool: payload.tool }));
388
- }),
389
- bus.on(BusChannels.LoopBlocked, (raw: unknown) => {
390
- const payload = (raw ?? {}) as Record<string, unknown>;
391
- const tool = str(payload.tool, "tool");
392
- pushNotice(
393
- "loop",
394
- payload.interrupted === true ? "error" : "warning",
395
- `loop guard blocked repeated ${tool} (${num(payload.repeatCount, 0)}x)`,
396
- makeRef({ tool: payload.tool }),
397
- );
398
- }),
399
- bus.on(BusChannels.ToolBudgetExceeded, (raw: unknown) => {
400
- const payload = (raw ?? {}) as Record<string, unknown>;
401
- const tool = str(payload.tool, "tool");
402
- pushNotice(
403
- "tool-budget",
404
- payload.interrupted === true ? "error" : "warning",
405
- `tool-call budget reached on ${tool} (${num(payload.callsThisTurn, 0)} calls)`,
406
- makeRef({ tool: payload.tool }),
407
- );
408
- }),
409
- bus.on(BusChannels.ContextPruned, (raw: unknown) => {
410
- const payload = (raw ?? {}) as Record<string, unknown>;
411
- const reclaimed = Math.max(0, num(payload.tokensBefore, 0) - num(payload.tokensAfter, 0));
412
- pushNotice("context", "info", `context pruned ${reclaimed} tokens (${str(payload.stage, "prune")})`);
413
- }),
414
- bus.on(BusChannels.BudgetAlert, (raw: unknown) => {
415
- const payload = (raw ?? {}) as Record<string, unknown>;
416
- const over = payload.level === "over";
417
- pushNotice(
418
- "budget",
419
- over ? "error" : "warning",
420
- `session cost $${num(payload.currentUsd, 0).toFixed(2)} ${over ? "over" : "at"} $${num(payload.ceilingUsd, 0).toFixed(2)} ceiling`,
421
- );
422
- }),
423
347
  ];
424
348
 
425
349
  return {
@@ -341,6 +341,8 @@ export interface TraceRunRow {
341
341
  ended_at: string | null;
342
342
  total_tokens: number | null;
343
343
  total_cost_usd: number | null;
344
+ /** 'dispatch' for a worker run, 'session' for an interactive chat-loop turn. */
345
+ source: "dispatch" | "session";
344
346
  }
345
347
 
346
348
  export interface TracePhaseRow {
@@ -423,7 +425,8 @@ CREATE TABLE runs (
423
425
  started_at TEXT NOT NULL,
424
426
  ended_at TEXT,
425
427
  total_tokens INTEGER,
426
- total_cost_usd REAL
428
+ total_cost_usd REAL,
429
+ source TEXT NOT NULL DEFAULT 'dispatch' CHECK(source IN ('dispatch','session'))
427
430
  );
428
431
 
429
432
  CREATE TABLE phases (
@@ -524,6 +527,23 @@ function ensureProcessOwnerColumns(db: DatabaseSync): void {
524
527
  db.exec("ALTER TABLE processes ADD COLUMN host TEXT; ALTER TABLE processes ADD COLUMN birth_token TEXT;");
525
528
  }
526
529
 
530
+ /**
531
+ * Additive discriminator between a dispatched run and an interactive session
532
+ * turn; older version-1 databases gain it in place. `runs`/`phases` held both
533
+ * kinds under one undocumented schema before this column existed, distinguishable
534
+ * only by the sentinel `assignment_id = SESSION_TRACE_ASSIGNMENT_ID` a session
535
+ * turn's row carries (recordSessionTurn's startSessionTurn) versus a real
536
+ * dispatch assignment id (upsertRun). The backfill reads that existing
537
+ * sentinel once; every row written after this migration sets `source`
538
+ * directly instead of relying on it.
539
+ */
540
+ function ensureRunSourceColumn(db: DatabaseSync): void {
541
+ const columns = db.prepare("PRAGMA table_info(runs)").all() as { name: string }[];
542
+ if (columns.some((column) => column.name === "source")) return;
543
+ db.exec("ALTER TABLE runs ADD COLUMN source TEXT NOT NULL DEFAULT 'dispatch';");
544
+ db.prepare("UPDATE runs SET source = 'session' WHERE assignment_id = ?").run(SESSION_TRACE_ASSIGNMENT_ID);
545
+ }
546
+
527
547
  /**
528
548
  * Finalize `running` rows whose recorded owner is on this host and provably
529
549
  * dead (pid gone, or alive under a different birth token, i.e. reused). Rows
@@ -570,6 +590,7 @@ export class TraceStore {
570
590
  else if (version !== TRACE_SCHEMA_VERSION) throw new TraceSchemaVersionError(version);
571
591
  this.transaction(() => {
572
592
  ensureProcessOwnerColumns(this.db);
593
+ ensureRunSourceColumn(this.db);
573
594
  reconcileAbandonedRuns(this.db);
574
595
  });
575
596
  }
@@ -673,8 +694,8 @@ export class TraceStore {
673
694
  this.transaction(() => {
674
695
  this.db
675
696
  .prepare(`INSERT INTO runs
676
- (run_id, assignment_id, request, status, agent, target, model, runtime, node, started_at)
677
- VALUES (?, ?, ?, 'queued', ?, ?, ?, ?, ?, ?)
697
+ (run_id, assignment_id, request, status, agent, target, model, runtime, node, started_at, source)
698
+ VALUES (?, ?, ?, 'queued', ?, ?, ?, ?, ?, ?, 'dispatch')
678
699
  ON CONFLICT(run_id) DO UPDATE SET request=excluded.request, agent=excluded.agent,
679
700
  target=excluded.target, model=excluded.model, runtime=excluded.runtime, node=excluded.node`)
680
701
  .run(
@@ -1046,8 +1067,8 @@ export class TraceStore {
1046
1067
  this.transaction(() => {
1047
1068
  this.db
1048
1069
  .prepare(`INSERT INTO runs
1049
- (run_id, assignment_id, request, status, agent, target, model, runtime, node, started_at)
1050
- VALUES (?, ?, ?, 'running', ?, ?, ?, ?, NULL, ?)
1070
+ (run_id, assignment_id, request, status, agent, target, model, runtime, node, started_at, source)
1071
+ VALUES (?, ?, ?, 'running', ?, ?, ?, ?, NULL, ?, 'session')
1051
1072
  ON CONFLICT(run_id) DO NOTHING`)
1052
1073
  .run(
1053
1074
  input.runId,
@@ -1167,6 +1188,15 @@ function traceDatabaseFootprintBytes(path: string): number {
1167
1188
 
1168
1189
  export class TraceReader {
1169
1190
  readonly db: DatabaseSync;
1191
+ /**
1192
+ * `runs.source` is an additive column (see ensureRunSourceColumn) a
1193
+ * TraceStore writer backfills in place. A read-only reader can open a
1194
+ * database no writer has touched since before the column existed — the
1195
+ * trace viewer opening a dormant install's trace.sqlite fresh is the
1196
+ * realistic case — and cannot ALTER TABLE to fix that itself, so it
1197
+ * derives the same value the migration would have written instead.
1198
+ */
1199
+ private readonly runsSourceExpr: string;
1170
1200
 
1171
1201
  constructor(readonly path: string) {
1172
1202
  this.db = new (databaseSyncConstructor())(path, { readOnly: true });
@@ -1177,6 +1207,10 @@ export class TraceReader {
1177
1207
  const mode = this.db.prepare("PRAGMA journal_mode").get() as { journal_mode: string };
1178
1208
  if (mode.journal_mode.toLowerCase() !== "wal")
1179
1209
  throw new Error(`trace database journal mode is ${mode.journal_mode}, expected WAL`);
1210
+ const runColumns = this.db.prepare("PRAGMA table_info(runs)").all() as { name: string }[];
1211
+ this.runsSourceExpr = runColumns.some((column) => column.name === "source")
1212
+ ? "*"
1213
+ : `*, CASE WHEN assignment_id = '${SESSION_TRACE_ASSIGNMENT_ID}' THEN 'session' ELSE 'dispatch' END AS source`;
1180
1214
  }
1181
1215
 
1182
1216
  close(): void {
@@ -1185,13 +1219,15 @@ export class TraceReader {
1185
1219
 
1186
1220
  runs(limit = 50): TraceRunRow[] {
1187
1221
  return this.db
1188
- .prepare("SELECT * FROM runs ORDER BY started_at DESC LIMIT ?")
1222
+ .prepare(`SELECT ${this.runsSourceExpr} FROM runs ORDER BY started_at DESC LIMIT ?`)
1189
1223
  .all(clampInt(limit, 1, 500)) as unknown as TraceRunRow[];
1190
1224
  }
1191
1225
 
1192
1226
  run(runId: string): TraceRunRow | null {
1193
1227
  return (
1194
- (this.db.prepare("SELECT * FROM runs WHERE run_id=?").get(runId) as unknown as TraceRunRow | undefined) ?? null
1228
+ (this.db.prepare(`SELECT ${this.runsSourceExpr} FROM runs WHERE run_id=?`).get(runId) as unknown as
1229
+ | TraceRunRow
1230
+ | undefined) ?? null
1195
1231
  );
1196
1232
  }
1197
1233