@iowarp/clio-coder 0.4.1 → 0.4.2

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 (437) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/CONTRIBUTING.md +59 -36
  3. package/README.md +404 -472
  4. package/SECURITY.md +2 -1
  5. package/dist/{acp-ZILU3AUO.js → acp-TMDQZDIG.js} +7 -7
  6. package/dist/{agents-HYWGBGQR.js → agents-5N5NG3XG.js} +28 -28
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/{auth-N3QT7CBO.js → auth-Z5CCBXKQ.js} +8 -9
  9. package/dist/{builtins-UJLMOVOV.js → builtins-K6TNDT24.js} +4 -4
  10. package/dist/{chunk-GVQJ5CCZ.js → chunk-2HFQNRV3.js} +7 -7
  11. package/dist/{chunk-QMXC4JB7.js → chunk-2NHR3NAY.js} +163 -1401
  12. package/dist/chunk-2X4RYJTJ.js +39 -0
  13. package/dist/{chunk-Y45G3AXC.js → chunk-2Z2IKEXI.js} +6 -10
  14. package/dist/{chunk-EIMVLWB3.js → chunk-34BHNEE3.js} +7 -3
  15. package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
  16. package/dist/chunk-3EBYEESD.js +314 -0
  17. package/dist/{chunk-CTJ4RNAA.js → chunk-3F7VUY77.js} +2 -2
  18. package/dist/{chunk-AP73CFDC.js → chunk-3KIPBMUA.js} +2 -2
  19. package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
  20. package/dist/{chunk-VEGN6WIQ.js → chunk-462T4EGZ.js} +2 -2
  21. package/dist/{chunk-AFKWHWXF.js → chunk-4JDLP6ZS.js} +33 -16
  22. package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
  23. package/dist/{chunk-AKB4GYDL.js → chunk-54ODD65L.js} +5 -5
  24. package/dist/{chunk-BBTJOK6Y.js → chunk-5KW52TEP.js} +3 -3
  25. package/dist/{chunk-6CCS4G3W.js → chunk-5PFYMY2V.js} +2 -2
  26. package/dist/chunk-77QIVUZB.js +1334 -0
  27. package/dist/{chunk-7OBGU7UB.js → chunk-7BHIY2MW.js} +7 -13
  28. package/dist/{chunk-3QSOM6PA.js → chunk-AZ4WMN4W.js} +2 -2
  29. package/dist/{chunk-6NJQITNH.js → chunk-B74PXLU7.js} +6 -3
  30. package/dist/{chunk-R23Z6K6I.js → chunk-B7HM5Z7T.js} +15 -15
  31. package/dist/{chunk-R32CLGZ6.js → chunk-BO7Y52RY.js} +81 -20
  32. package/dist/{chunk-UEDMSP56.js → chunk-BYMNWQ7O.js} +123 -148
  33. package/dist/{chunk-ZJLUDYFY.js → chunk-CRFOIAX3.js} +4 -4
  34. package/dist/{chunk-2NM363SV.js → chunk-CYZW7JHJ.js} +7 -7
  35. package/dist/{chunk-6HMJX2VU.js → chunk-DYHAXKHD.js} +38 -10
  36. package/dist/{chunk-THYWACCR.js → chunk-DZAW46HP.js} +3 -3
  37. package/dist/{chunk-FYUN5KZ3.js → chunk-DZEK6CJN.js} +17 -17
  38. package/dist/{chunk-3I5NY75V.js → chunk-E7GT7O5N.js} +5 -5
  39. package/dist/{chunk-VKFQTNDV.js → chunk-F2I26BDK.js} +4 -4
  40. package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
  41. package/dist/{chunk-IXJT6DCX.js → chunk-FVDGR2ZL.js} +3 -3
  42. package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
  43. package/dist/{chunk-7EPLI7VL.js → chunk-HIICAHCJ.js} +2 -2
  44. package/dist/{chunk-E67WX76H.js → chunk-HKMD33FO.js} +29 -80
  45. package/dist/chunk-HLAFFSEK.js +360 -0
  46. package/dist/{chunk-UAPGZHYC.js → chunk-I64IFBLB.js} +9 -2
  47. package/dist/{chunk-XKA2ICR3.js → chunk-I66ZTYNP.js} +440 -175
  48. package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
  49. package/dist/{chunk-PVAMAVBB.js → chunk-IDNA72AH.js} +102 -2
  50. package/dist/{chunk-GCSMB2KY.js → chunk-IKOZFYBN.js} +1 -1
  51. package/dist/{chunk-2VG7KLYV.js → chunk-IKSLQ4XV.js} +5460 -3241
  52. package/dist/{chunk-QKIFBZKT.js → chunk-IMXMHHMQ.js} +166 -25
  53. package/dist/{chunk-74YWRRU5.js → chunk-JBCS7CRR.js} +2 -2
  54. package/dist/{chunk-BDPT6GTK.js → chunk-JWJGP5DQ.js} +2 -2
  55. package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
  56. package/dist/chunk-KPXDY6QF.js +47 -0
  57. package/dist/{chunk-ABLSQ6JX.js → chunk-LJID3DYZ.js} +7 -1
  58. package/dist/{chunk-VKRH2TCS.js → chunk-M2DAX4F6.js} +2 -2
  59. package/dist/{chunk-6I5ILFOF.js → chunk-M2WXEHER.js} +2 -2
  60. package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
  61. package/dist/{chunk-N5UK64DP.js → chunk-MCMZMDAC.js} +2 -2
  62. package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
  63. package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
  64. package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
  65. package/dist/{chunk-HUAS7ITX.js → chunk-O3YUNJZ2.js} +13 -21
  66. package/dist/{chunk-MA3H6DM5.js → chunk-P75RZCJW.js} +25 -3
  67. package/dist/{chunk-IG7BCQBA.js → chunk-PGF63K6I.js} +2 -2
  68. package/dist/chunk-PJX3WQUQ.js +42 -0
  69. package/dist/{chunk-6DWBAZ5U.js → chunk-Q4XWMHX6.js} +4 -6
  70. package/dist/{chunk-OJTRZGR3.js → chunk-QQLGQY2A.js} +8 -8
  71. package/dist/{chunk-J4HBWF6Y.js → chunk-RLYRBIYQ.js} +115 -20
  72. package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
  73. package/dist/{chunk-C537JADH.js → chunk-SSEYRH53.js} +6 -7
  74. package/dist/chunk-SZAA6XDG.js +30 -0
  75. package/dist/{chunk-MOPSG2X7.js → chunk-TPEQIQIE.js} +6 -6
  76. package/dist/{chunk-JA5QWE4Z.js → chunk-UBRFI4HS.js} +1879 -1650
  77. package/dist/{chunk-BTGG6BG2.js → chunk-UH347SHR.js} +154 -15
  78. package/dist/{chunk-5YHDIDBP.js → chunk-UH632ZYL.js} +2 -2
  79. package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
  80. package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
  81. package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
  82. package/dist/{chunk-UXN6JT4W.js → chunk-W4YEMFBX.js} +2 -2
  83. package/dist/{chunk-TD3PGPQA.js → chunk-W6NIE6OW.js} +2 -2
  84. package/dist/{chunk-TVH4ONAM.js → chunk-X7IARSHT.js} +3 -3
  85. package/dist/{chunk-PJJ6MY27.js → chunk-XE3PCIXH.js} +3 -3
  86. package/dist/{chunk-FEFIFZTL.js → chunk-XGDPUNND.js} +2 -2
  87. package/dist/{chunk-SCYB3HA4.js → chunk-XOXV5GKE.js} +51 -16
  88. package/dist/{chunk-QTFGO774.js → chunk-XQRY4DTA.js} +24 -11
  89. package/dist/{chunk-BJGUKIG4.js → chunk-YJISEZKC.js} +2 -2
  90. package/dist/{chunk-GPPB3JBE.js → chunk-ZGNYYXQ6.js} +2 -2
  91. package/dist/{chunk-SINK3QR6.js → chunk-ZNT2M6TG.js} +7 -7
  92. package/dist/{chunk-7RY5VZPH.js → chunk-ZW4HH5JJ.js} +6 -6
  93. package/dist/cli/index.js +33 -32
  94. package/dist/{clio-IT3G3VQH.js → clio-7VB377CC.js} +7 -7
  95. package/dist/{code-nav-RK6S7F6E.js → code-nav-YVLCYA7V.js} +85 -17
  96. package/dist/{config-3QZRWZJF.js → config-4HVOS65E.js} +88 -43
  97. package/dist/{configure-FL7Y3KJF.js → configure-PIWO7B24.js} +10 -10
  98. package/dist/{context-5HE7ODYK.js → context-IYEHL3WQ.js} +33 -31
  99. package/dist/{context-XNHL75JV.js → context-KQYIWPWT.js} +47 -34
  100. package/dist/{context-KYQFRVDC.js → context-N6ZE3LGJ.js} +11 -11
  101. package/dist/{context-clear-N545L53A.js → context-clear-G4OGZJDS.js} +33 -31
  102. package/dist/{context-working-set-QHKXSV2F.js → context-working-set-BWLF6LJP.js} +7 -7
  103. package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-2QQAITS3.js} +38 -38
  104. package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
  105. package/dist/{doctor-ZGPEGHIP.js → doctor-LHBD36VU.js} +23 -22
  106. package/dist/{eval-GXLL44RD.js → eval-C45FYRJ6.js} +21 -20
  107. package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-6DEJPLBF.js} +2 -2
  108. package/dist/{evidence-HWLBRH3Q.js → evidence-6SHONYAF.js} +30 -28
  109. package/dist/{evolve-FTZBMNVW.js → evolve-KRKMV72X.js} +30 -28
  110. package/dist/{extensions-VHRBEID7.js → extensions-KPZ2UHBB.js} +5 -3
  111. package/dist/{fleet-CKZHJWZJ.js → fleet-IVTCKDHT.js} +62 -61
  112. package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-EDWL3IT7.js} +5 -5
  113. package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-YP3YEFGK.js} +4 -4
  114. package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-ZFWKHY2M.js} +16 -14
  115. package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-FVUNCBML.js} +31 -29
  116. package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-UN5XED4R.js} +2 -2
  117. package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-XOWC4HSX.js} +17 -15
  118. package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-UN3SODEL.js} +30 -28
  119. package/dist/{fleet-view-WAMJYNDT.js → fleet-view-TWHJKCN6.js} +31 -29
  120. package/dist/{init-5XQRBOFV.js → init-T2QORQ3Y.js} +50 -49
  121. package/dist/{interop-34TVO25M.js → interop-IN5I2A66.js} +5 -5
  122. package/dist/{library-3QY6KF57.js → library-LSCATDLZ.js} +15 -13
  123. package/dist/{memory-L4UTIIIW.js → memory-HYOKAGGJ.js} +31 -29
  124. package/dist/{models-ZVX3QOWE.js → models-2GPMFYCM.js} +22 -21
  125. package/dist/{monitor-CEKVSYTS.js → monitor-E4ASVUJH.js} +34 -32
  126. package/dist/{orchestrator-77BAP6BC.js → orchestrator-DDMPR3PY.js} +984 -583
  127. package/dist/{panes-7STHOAUJ.js → panes-E3RUXOW5.js} +4 -4
  128. package/dist/{panes-SHAUIRXY.js → panes-IXKLOKA2.js} +23 -8
  129. package/dist/{reset-EOLM7GVE.js → reset-OAQP3W4O.js} +4 -4
  130. package/dist/{resources-74GKTLSF.js → resources-OTRSN34L.js} +15 -13
  131. package/dist/{run-HBAUJNNZ.js → run-5DEYH5QK.js} +60 -59
  132. package/dist/{share-G3APVLVP.js → share-IHWTLO3M.js} +19 -15
  133. package/dist/{skills-35HHUKCR.js → skills-IYMXMKW4.js} +17 -15
  134. package/dist/{skills-eval-QN4HSHDC.js → skills-eval-DROHSJAR.js} +36 -36
  135. package/dist/{skills-inventory-J357J34F.js → skills-inventory-D7X4L4ZX.js} +15 -13
  136. package/dist/{slash-commands-JZZCQA32.js → slash-commands-QBM7UZ3B.js} +21 -18
  137. package/dist/{steer-XAVHJM22.js → steer-Z5DO23FJ.js} +2 -2
  138. package/dist/{targets-DSM6CY3M.js → targets-P2FUC4IL.js} +25 -28
  139. package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-YREJ3JX2.js} +5 -5
  140. package/dist/{tools-MKNWVPBH.js → tools-5B7RO6MV.js} +4 -4
  141. package/dist/{trace-ECQ7TIYZ.js → trace-YMGMUM6A.js} +55 -7
  142. package/dist/{upgrade-H7TOM7YL.js → upgrade-PXK3S2YM.js} +11 -9
  143. package/dist/{usage-X52N3IDJ.js → usage-ME5MPXGX.js} +36 -34
  144. package/dist/{verifiers-EJTVVSMA.js → verifiers-BVZ7IWOO.js} +5 -5
  145. package/dist/{verify-YJL6XET2.js → verify-5K7ZKQFC.js} +4 -4
  146. package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
  147. package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-F5W5QTYY.js} +48 -47
  148. package/dist/{with-panes-OBOBFIIR.js → with-panes-BYOJCLAM.js} +51 -255
  149. package/dist/worker/entry.js +45 -30
  150. package/docs/README.md +176 -81
  151. package/docs/{acp.md → architecture/acp.md} +36 -20
  152. package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
  153. package/docs/{architecture.md → architecture/architecture.md} +43 -22
  154. package/docs/{artifact-placement.md → architecture/artifact-placement.md} +26 -23
  155. package/docs/architecture/artifact-versions.md +90 -0
  156. package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
  157. package/docs/{context-engine.md → architecture/context-engine.md} +25 -25
  158. package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
  159. package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
  160. package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
  161. package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
  162. package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
  163. package/docs/{model-catalog.md → architecture/model-catalog.md} +40 -17
  164. package/docs/{observability.md → architecture/observability.md} +26 -13
  165. package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
  166. package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +55 -20
  167. package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +35 -24
  168. package/docs/{safety-model.md → architecture/safety-model.md} +20 -15
  169. package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
  170. package/docs/architecture/time-conventions.md +125 -0
  171. package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
  172. package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
  173. package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
  174. package/docs/{built-in-agents.md → guide/built-in-agents.md} +50 -34
  175. package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +65 -60
  176. package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +227 -289
  177. package/docs/guide/configuration-reference.md +1158 -0
  178. package/docs/{environment-variables.md → guide/environment-variables.md} +31 -28
  179. package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
  180. package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
  181. package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
  182. package/docs/{glossary.md → guide/glossary.md} +14 -11
  183. package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +44 -13
  184. package/docs/guide/panes-and-files.md +290 -0
  185. package/docs/{proactive-memory.md → guide/proactive-memory.md} +79 -66
  186. package/docs/{resource-library.md → guide/resource-library.md} +13 -4
  187. package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +7 -3
  188. package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
  189. package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
  190. package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
  191. package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
  192. package/docs/{development-pipeline.md → process/development-pipeline.md} +24 -26
  193. package/docs/process/documentation-coverage.md +100 -0
  194. package/docs/process/documentation-guide.md +187 -0
  195. package/docs/{eval-runner.md → process/eval-runner.md} +41 -50
  196. package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
  197. package/docs/{evolution.md → process/evolution.md} +2 -2
  198. package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
  199. package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
  200. package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
  201. package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
  202. package/evals/README.md +2 -2
  203. package/package.json +9 -7
  204. package/skills/README.md +46 -37
  205. package/skills/coding/ast-grep/SKILL.md +2 -2
  206. package/skills/coding/coding-standards/SKILL.md +2 -2
  207. package/skills/coding/prototype/SKILL.md +2 -2
  208. package/skills/coding/tdd/SKILL.md +2 -2
  209. package/skills/context/context-handoff/SKILL.md +2 -2
  210. package/skills/context/context-prime/SKILL.md +2 -2
  211. package/skills/git/file-ticket/SKILL.md +2 -2
  212. package/skills/git/fix-issue/SKILL.md +3 -3
  213. package/skills/git/resolve-merge-conflicts/SKILL.md +2 -2
  214. package/skills/git/ship/SKILL.md +2 -2
  215. package/skills/git/worktree-create/SKILL.md +2 -2
  216. package/skills/git/worktree-merge/SKILL.md +2 -2
  217. package/skills/meta/clio-coder-dev/SKILL.md +9 -5
  218. package/skills/meta/clio-coder-dev/evals.md +3 -2
  219. package/skills/meta/clio-coder-test/SKILL.md +102 -95
  220. package/skills/meta/clio-coder-test/evals.md +9 -4
  221. package/skills/meta/clio-coder-test/references/harness.md +100 -124
  222. package/skills/meta/clio-coder-test/references/test-map.md +77 -50
  223. package/skills/meta/credentials/SKILL.md +2 -2
  224. package/skills/meta/find-skills/SKILL.md +2 -2
  225. package/skills/meta/herdr/SKILL.md +2 -2
  226. package/skills/meta/skill-craft/SKILL.md +22 -16
  227. package/skills/planning/architecture/SKILL.md +2 -2
  228. package/skills/planning/backlog/SKILL.md +2 -2
  229. package/skills/planning/prd/SKILL.md +2 -2
  230. package/skills/planning/product-intent/SKILL.md +2 -2
  231. package/skills/planning/tech-spec/SKILL.md +2 -2
  232. package/skills/registry.yaml +62 -62
  233. package/skills/research/arxiv-literature/SKILL.md +2 -2
  234. package/skills/research/experiment-protocol/SKILL.md +2 -2
  235. package/skills/research/scientific-debugging/SKILL.md +2 -2
  236. package/skills/research/scientific-modernization/SKILL.md +2 -2
  237. package/skills/skill-marketplace.json +62 -62
  238. package/skills/workflow/cut-it/SKILL.md +2 -2
  239. package/skills/workflow/design-council/SKILL.md +2 -2
  240. package/skills/workflow/grill-me/SKILL.md +2 -2
  241. package/skills/workflow/workflow-distiller/SKILL.md +2 -2
  242. package/src/cli/args.ts +2 -2
  243. package/src/cli/bootstrap-generate.ts +1 -1
  244. package/src/cli/config-inspect.ts +65 -12
  245. package/src/cli/configure.ts +0 -4
  246. package/src/cli/docs.ts +22 -14
  247. package/src/cli/doctor-naming.ts +5 -5
  248. package/src/cli/doctor-toolchain.ts +3 -3
  249. package/src/cli/eval.ts +1 -2
  250. package/src/cli/extensions.ts +2 -1
  251. package/src/cli/fleet.ts +1 -1
  252. package/src/cli/index.ts +2 -1
  253. package/src/cli/internal-dispatch.ts +3 -4
  254. package/src/cli/panes.ts +19 -5
  255. package/src/cli/run.ts +2 -2
  256. package/src/cli/share.ts +5 -1
  257. package/src/cli/skills-eval.ts +3 -3
  258. package/src/cli/targets.ts +2 -6
  259. package/src/cli/trace.ts +55 -4
  260. package/src/cli/wiki-generate.ts +1 -1
  261. package/src/core/artifact-paths.ts +1 -1
  262. package/src/core/bash-exec.ts +131 -86
  263. package/src/core/bus-events.ts +51 -6
  264. package/src/core/config.ts +5 -1
  265. package/src/core/defaults.ts +7 -4
  266. package/src/core/dispatch-outcome.ts +16 -0
  267. package/src/core/guardrails.ts +10 -49
  268. package/src/core/prompt-hint.ts +9 -0
  269. package/src/domains/agents/builtins/architect.md +2 -3
  270. package/src/domains/agents/builtins/coder.md +3 -2
  271. package/src/domains/agents/builtins/debugger.md +2 -2
  272. package/src/domains/agents/builtins/documenter.md +2 -2
  273. package/src/domains/agents/builtins/git-master.md +1 -1
  274. package/src/domains/agents/builtins/oracle.md +1 -1
  275. package/src/domains/agents/builtins/provenance.md +1 -1
  276. package/src/domains/agents/builtins/researcher.md +1 -1
  277. package/src/domains/agents/builtins/scout.md +1 -1
  278. package/src/domains/agents/builtins/tester.md +2 -2
  279. package/src/domains/agents/builtins/verifier.md +2 -2
  280. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  281. package/src/domains/agents/catalog.ts +12 -14
  282. package/src/domains/agents/contract.ts +2 -0
  283. package/src/domains/agents/extension.ts +23 -1
  284. package/src/domains/config/keybindings.ts +8 -0
  285. package/src/domains/context/extension.ts +0 -3
  286. package/src/domains/context/working-set/path-index.ts +1 -0
  287. package/src/domains/dispatch/capability-match.ts +10 -0
  288. package/src/domains/dispatch/extension.ts +105 -22
  289. package/src/domains/dispatch/host-verification.ts +435 -39
  290. package/src/domains/dispatch/intent-requirements.ts +10 -0
  291. package/src/domains/dispatch/intent.ts +18 -1
  292. package/src/domains/dispatch/path-scope.ts +235 -24
  293. package/src/domains/dispatch/run-event-journal.ts +4 -15
  294. package/src/domains/dispatch/state.ts +2 -3
  295. package/src/domains/dispatch/transport.ts +45 -21
  296. package/src/domains/dispatch/types.ts +55 -3
  297. package/src/domains/eval/artifacts/store.ts +5 -0
  298. package/src/domains/eval/store.ts +8 -1
  299. package/src/domains/evidence/trust-status.ts +10 -1
  300. package/src/domains/extensions/contract.ts +15 -1
  301. package/src/domains/extensions/discovery.ts +238 -41
  302. package/src/domains/extensions/extension.ts +105 -6
  303. package/src/domains/extensions/index.ts +24 -0
  304. package/src/domains/extensions/integrity.ts +189 -0
  305. package/src/domains/extensions/manager.ts +17 -1
  306. package/src/domains/extensions/resource-path.ts +27 -0
  307. package/src/domains/extensions/resources.ts +18 -38
  308. package/src/domains/extensions/snapshot-store.ts +39 -0
  309. package/src/domains/extensions/snapshot.ts +180 -0
  310. package/src/domains/extensions/state.ts +385 -57
  311. package/src/domains/extensions/types.ts +118 -1
  312. package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
  313. package/src/domains/lifecycle/migrations/index.ts +2 -0
  314. package/src/domains/lifecycle/naming-resources.ts +19 -4
  315. package/src/domains/lifecycle/naming-yazi.ts +10 -5
  316. package/src/domains/middleware/contract.ts +26 -0
  317. package/src/domains/middleware/extension.ts +24 -24
  318. package/src/domains/middleware/hook-receipts.ts +27 -4
  319. package/src/domains/middleware/hooks-io.ts +65 -32
  320. package/src/domains/middleware/hooks.ts +64 -0
  321. package/src/domains/middleware/index.ts +28 -4
  322. package/src/domains/middleware/registrations.ts +326 -0
  323. package/src/domains/middleware/runtime.ts +28 -0
  324. package/src/domains/middleware/snapshot.ts +20 -7
  325. package/src/domains/mux/contract.ts +38 -0
  326. package/src/domains/mux/detect.ts +6 -13
  327. package/src/domains/mux/index.ts +1 -1
  328. package/src/domains/mux/operations.ts +44 -5
  329. package/src/domains/mux/yazi/assets/yazi.toml +2 -2
  330. package/src/domains/mux/yazi/session.ts +53 -4
  331. package/src/domains/mux/yazi/theme.ts +117 -17
  332. package/src/domains/observability/contract.ts +10 -11
  333. package/src/domains/observability/extension.ts +11 -3
  334. package/src/domains/observability/projection.ts +14 -90
  335. package/src/domains/observability/trace-store.ts +43 -7
  336. package/src/domains/prompts/compiler.ts +73 -53
  337. package/src/domains/prompts/contract.ts +15 -3
  338. package/src/domains/prompts/extension.ts +97 -9
  339. package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
  340. package/src/domains/prompts/fragments/identity/clio.md +6 -12
  341. package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
  342. package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
  343. package/src/domains/prompts/fragments/operating/contract.md +7 -15
  344. package/src/domains/prompts/fragments/operating/delegation.md +32 -34
  345. package/src/domains/prompts/fragments/operating/skills.md +10 -24
  346. package/src/domains/prompts/fragments/operating/worker.md +1 -8
  347. package/src/domains/providers/index.ts +1 -1
  348. package/src/domains/providers/model-runtime-capabilities.ts +85 -21
  349. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +669 -104
  350. package/src/domains/providers/runtime-resolution.ts +31 -0
  351. package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
  352. package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
  353. package/src/domains/providers/types/cost-provenance.ts +19 -0
  354. package/src/domains/providers/types/local-model-quirks.ts +85 -37
  355. package/src/domains/resources/skills/loader.ts +16 -19
  356. package/src/domains/safety/call-target.ts +1 -1
  357. package/src/domains/safety/loop-detector.ts +7 -4
  358. package/src/domains/session/task-board.ts +10 -9
  359. package/src/domains/share/archive.ts +164 -7
  360. package/src/engine/acp/server.ts +62 -9
  361. package/src/engine/apis/llamacpp-residency.ts +3 -4
  362. package/src/engine/apis/lmstudio.ts +3 -3
  363. package/src/engine/apis/ollama-native.ts +6 -6
  364. package/src/engine/apis/openai-completions.ts +28 -25
  365. package/src/engine/apis/output-budget.ts +8 -18
  366. package/src/engine/apis/residency.ts +8 -27
  367. package/src/engine/gemma-channel-filter.ts +19 -0
  368. package/src/engine/loop-guard.ts +92 -12
  369. package/src/engine/worker-runtime.ts +40 -11
  370. package/src/engine/worker-tools.ts +3 -1
  371. package/src/entry/extension-hook-sources.ts +28 -0
  372. package/src/entry/extension-reload.ts +309 -0
  373. package/src/entry/orchestrator.ts +59 -35
  374. package/src/interactive/application-controller.ts +2 -1
  375. package/src/interactive/bus-notices.ts +8 -1
  376. package/src/interactive/chat-loop-messages.ts +3 -13
  377. package/src/interactive/chat-loop.ts +10 -1
  378. package/src/interactive/chat-panel.ts +36 -13
  379. package/src/interactive/chat-renderer.ts +71 -7
  380. package/src/interactive/dispatch-board.ts +6 -11
  381. package/src/interactive/footer/widgets.ts +13 -0
  382. package/src/interactive/interactive-application.ts +39 -4
  383. package/src/interactive/interactive-input-runtime.ts +4 -0
  384. package/src/interactive/interactive-presentation.ts +2 -2
  385. package/src/interactive/interactive-slash-runtime.ts +2 -0
  386. package/src/interactive/overlays/extensions.ts +9 -1
  387. package/src/interactive/overlays/help-reference.ts +13 -0
  388. package/src/interactive/overlays/settings.ts +27 -16
  389. package/src/interactive/panes-runtime.ts +111 -35
  390. package/src/interactive/prompt-cache-identity.ts +88 -0
  391. package/src/interactive/slash-commands.ts +129 -14
  392. package/src/interactive/stream-pacing-policy.ts +0 -23
  393. package/src/interactive/turn-context.ts +30 -15
  394. package/src/interactive/yazi-bridge.ts +60 -6
  395. package/src/tools/agent-tools.ts +30 -1
  396. package/src/tools/artifact.ts +2 -2
  397. package/src/tools/ask-user.ts +3 -3
  398. package/src/tools/bash.ts +1 -1
  399. package/src/tools/bootstrap.ts +4 -0
  400. package/src/tools/builtin-tool-catalog.ts +52 -22
  401. package/src/tools/codewiki/code-nav-surface.ts +6 -0
  402. package/src/tools/codewiki/code-nav.ts +99 -13
  403. package/src/tools/context/docs-engine.ts +20 -7
  404. package/src/tools/context/index.ts +29 -12
  405. package/src/tools/core-bootstrap.ts +28 -6
  406. package/src/tools/credential-present.ts +1 -2
  407. package/src/tools/dispatch-arguments.ts +5 -1
  408. package/src/tools/dispatch-plan.ts +48 -4
  409. package/src/tools/dispatch-run-events.ts +1 -1
  410. package/src/tools/dispatch-schema.ts +338 -0
  411. package/src/tools/dispatch-types.ts +3 -0
  412. package/src/tools/dispatch.ts +9 -254
  413. package/src/tools/ledger.ts +3 -5
  414. package/src/tools/monitor-surface.ts +5 -13
  415. package/src/tools/observation.ts +4 -5
  416. package/src/tools/panes-surface.ts +4 -11
  417. package/src/tools/panes.ts +4 -2
  418. package/src/tools/policy.ts +15 -2
  419. package/src/tools/read.ts +5 -6
  420. package/src/tools/registry.ts +30 -7
  421. package/src/tools/result-shaping.ts +18 -14
  422. package/src/tools/steer-surface.ts +1 -1
  423. package/src/tools/tasks.ts +1 -1
  424. package/src/tools/truncate.ts +6 -5
  425. package/src/tools/verify/surface.ts +6 -12
  426. package/src/tools/web-fetch-surface.ts +1 -3
  427. package/dist/chunk-5QIAJV2D.js +0 -48
  428. package/dist/chunk-JZWT5J3Y.js +0 -814
  429. package/dist/chunk-K7VKOLQQ.js +0 -15
  430. package/dist/chunk-PMZCIOCJ.js +0 -25
  431. package/dist/chunk-SUW5DORT.js +0 -819
  432. package/dist/chunk-UOV2BYIW.js +0 -107
  433. package/dist/chunk-WR6U3OVP.js +0 -45
  434. package/docs/artifact-versions.md +0 -67
  435. package/docs/documentation-coverage.md +0 -46
  436. package/docs/documentation-guide.md +0 -167
  437. package/docs/time-conventions.md +0 -101
@@ -603,30 +603,53 @@ function hasStreamingText(entry: Extract<TranscriptEntry, { role: "assistant" }>
603
603
  }
604
604
 
605
605
  /**
606
- * Split a reply that opens with the skill-suggestion protocol line into that
607
- * line and the answer beneath it.
606
+ * Locate the skill-suggestion protocol line inside a reply.
608
607
  *
609
- * The prompt asks the model to *begin its reply* with the suggestion, so the
610
- * usual shape is one segment holding both. Classifying that whole segment as
611
- * advisory left the turn with no voice glyph at all: the suggestion did not
612
- * claim it and the answer never got the chance. Returns null when the segment
613
- * is only a suggestion, which stays advisory in full.
608
+ * The prompt asks the model to begin its reply with the line, but a model
609
+ * that narrates its work first puts the line at the end of the final message
610
+ * about half the time (round-4 skill batches: 1/2 and 0/2 opened, 2/2 fired).
611
+ * The line is recognized at the start of any line, provided it is complete
612
+ * (a newline follows it, or the segment is finalized), so a partially
613
+ * streamed line stays ordinary prose until it is whole. Returns the line's
614
+ * byte range or null.
615
+ */
616
+ function findSkillSuggestionLine(seg: TextSegment): { start: number; end: number } | null {
617
+ const text = seg.text;
618
+ let at = text.startsWith(SKILL_SUGGESTION_PREFIX) ? 0 : text.indexOf(`\n${SKILL_SUGGESTION_PREFIX}`);
619
+ if (at < 0) return null;
620
+ if (at > 0) at += 1;
621
+ const lineEnd = text.indexOf("\n", at);
622
+ if (lineEnd < 0) return seg.finalized ? { start: at, end: text.length } : null;
623
+ return { start: at, end: lineEnd };
624
+ }
625
+
626
+ /**
627
+ * Split a reply that carries the skill-suggestion protocol line into that
628
+ * line and the answer around it.
629
+ *
630
+ * The usual shape is one segment holding both. Classifying that whole segment
631
+ * as advisory left the turn with no voice glyph at all: the suggestion did not
632
+ * claim it and the answer never got the chance. The suggestion renders first
633
+ * wherever the model put it, and the answer is the rest of the segment with
634
+ * that line removed. Returns null when the segment is only a suggestion,
635
+ * which stays advisory in full.
614
636
  */
615
637
  function skillSuggestionSplit(seg: TextSegment): { suggestion: string; answer: TextSegment } | null {
616
- if (!seg.text.startsWith(SKILL_SUGGESTION_PREFIX)) return null;
617
- const breakIndex = seg.text.indexOf("\n");
618
- if (breakIndex < 0) return null;
638
+ const found = findSkillSuggestionLine(seg);
639
+ if (!found) return null;
640
+ const before = seg.text.slice(0, found.start).replace(/\n+$/, "");
641
+ const after = seg.text.slice(found.end + 1).replace(/^\n+/, "");
619
642
  // A model that puts a blank line between the suggestion and the answer left
620
643
  // the remainder opening with a newline, so the first rendered row was empty
621
644
  // and took the glyph the answer's own text row was owed.
622
- const answerText = seg.text.slice(breakIndex + 1).replace(/^\n+/, "");
645
+ const answerText = before.length > 0 && after.length > 0 ? `${before}\n${after}` : before + after;
623
646
  if (answerText.trim().length === 0) return null;
624
647
  const split = seg.suggestionSplit ?? {
625
648
  suggestion: "",
626
649
  answer: { kind: "text", text: answerText, finalized: seg.finalized } as TextSegment,
627
650
  };
628
651
  seg.suggestionSplit = split;
629
- split.suggestion = seg.text.slice(0, breakIndex);
652
+ split.suggestion = seg.text.slice(found.start, found.end).replace(/\r$/, "");
630
653
  const answer = split.answer;
631
654
  if (answer.text === answerText && answer.finalized === seg.finalized) return split;
632
655
  // The answer half follows the same cache rules as any other segment: the
@@ -1113,7 +1136,7 @@ function renderEntryLines(
1113
1136
  const rendered =
1114
1137
  seg.kind === "text" ? renderTextSegmentLines(seg, proseWidth) : renderErrorSegmentLines(seg, proseWidth);
1115
1138
  if (rendered.length === 0) continue;
1116
- const isSkillSuggestion = seg.kind === "text" && seg.text.startsWith(SKILL_SUGGESTION_PREFIX);
1139
+ const isSkillSuggestion = seg.kind === "text" && findSkillSuggestionLine(seg) !== null;
1117
1140
  if (!labeled && !isSkillSuggestion) {
1118
1141
  lines.push(...hangProseLines(rendered, clioPrefix));
1119
1142
  labeled = true;
@@ -460,15 +460,73 @@ function richMessageFromEntry(entry: MessageEntry, maxTextChars?: number): Agent
460
460
  return message as unknown as AgentMessage;
461
461
  }
462
462
 
463
- function recordToolCallsFromMessage(message: AgentMessage, seen: Set<string>): void {
463
+ function toolCallIdsFromMessage(message: AgentMessage): string[] {
464
464
  const content = (message as { content?: unknown }).content;
465
- if (!Array.isArray(content)) return;
465
+ if (!Array.isArray(content)) return [];
466
+ const ids: string[] = [];
466
467
  for (const block of content) {
467
468
  if (!block || typeof block !== "object") continue;
468
469
  const b = block as Record<string, unknown>;
469
470
  if (b.type !== "toolCall") continue;
470
- if (typeof b.id === "string" && b.id.length > 0) seen.add(b.id);
471
+ if (typeof b.id === "string" && b.id.length > 0) ids.push(b.id);
471
472
  }
473
+ return ids;
474
+ }
475
+
476
+ function recordToolCallsFromMessage(message: AgentMessage, seen: Set<string>): void {
477
+ for (const id of toolCallIdsFromMessage(message)) seen.add(id);
478
+ }
479
+
480
+ /**
481
+ * Replay sink that hands tool results to the model in the order the assistant
482
+ * issued the calls.
483
+ *
484
+ * The ledger appends a tool result when its tool finishes, while the live loop
485
+ * appends a parallel batch's results by call index (pi executes the batch and
486
+ * pushes results in the assistant's order). A two-call turn whose second call
487
+ * finished first is therefore recorded as [b, a] and was sent as [a, b]. A
488
+ * resume that replayed the ledger order sent different bytes from that point
489
+ * on, and the provider's prefix cache missed for the rest of the session.
490
+ * Results are staged until the next non-result message and released in call
491
+ * order; an id the staged assistant turn never issued keeps its ledger order
492
+ * after the known ones.
493
+ */
494
+ function createOrderedReplaySink(): {
495
+ messages: AgentMessage[];
496
+ push(message: AgentMessage): void;
497
+ stageToolResult(message: AgentMessage): void;
498
+ flush(): void;
499
+ } {
500
+ const messages: AgentMessage[] = [];
501
+ let callOrder: string[] = [];
502
+ let staged: AgentMessage[] = [];
503
+ const rank = (message: AgentMessage): number => {
504
+ const id = (message as { toolCallId?: unknown }).toolCallId;
505
+ const index = typeof id === "string" ? callOrder.indexOf(id) : -1;
506
+ return index < 0 ? Number.MAX_SAFE_INTEGER : index;
507
+ };
508
+ const flush = (): void => {
509
+ if (staged.length === 0) return;
510
+ staged.sort((a, b) => rank(a) - rank(b));
511
+ messages.push(...staged);
512
+ staged = [];
513
+ callOrder = [];
514
+ };
515
+ return {
516
+ messages,
517
+ flush,
518
+ push(message) {
519
+ flush();
520
+ messages.push(message);
521
+ // Consecutive assistant messages (one legacy standalone tool_call entry
522
+ // per call) share one batch; anything else starts a new one.
523
+ if (message.role === "assistant") callOrder.push(...toolCallIdsFromMessage(message));
524
+ else callOrder = [];
525
+ },
526
+ stageToolResult(message) {
527
+ staged.push(message);
528
+ },
529
+ };
472
530
  }
473
531
 
474
532
  function toolCallMessageFromEntry(entry: MessageEntry): AgentMessage {
@@ -998,7 +1056,12 @@ function bashContextText(entry: BashExecutionEntry): string {
998
1056
  return bashExecutionToText(message);
999
1057
  }
1000
1058
 
1001
- function appendContextMessage(out: AgentMessage[], role: "user" | "assistant", text: string, timestamp: string): void {
1059
+ function appendContextMessage(
1060
+ out: { push(message: AgentMessage): void },
1061
+ role: "user" | "assistant",
1062
+ text: string,
1063
+ timestamp: string,
1064
+ ): void {
1002
1065
  const trimmed = text.trim();
1003
1066
  if (trimmed.length === 0) return;
1004
1067
  out.push(makeTextMessage(role, truncateReplayText(trimmed), timestamp));
@@ -1014,7 +1077,7 @@ export function buildReplayAgentMessagesFromTurns(
1014
1077
  turns: ReadonlyArray<SessionEntry>,
1015
1078
  options: RehydrateChatPanelOptions = {},
1016
1079
  ): AgentMessage[] {
1017
- const out: AgentMessage[] = [];
1080
+ const out = createOrderedReplaySink();
1018
1081
  const seenToolCalls = new Set<string>();
1019
1082
  for (const entry of selectReplayEntries(turns, options)) {
1020
1083
  switch (entry.kind) {
@@ -1035,7 +1098,7 @@ export function buildReplayAgentMessagesFromTurns(
1035
1098
  recordToolCallsFromMessage(message, seenToolCalls);
1036
1099
  }
1037
1100
  } else if (entry.role === "tool_result") {
1038
- out.push(toolResultMessageFromEntry(entry));
1101
+ out.stageToolResult(toolResultMessageFromEntry(entry));
1039
1102
  } else if (entry.role === "system") {
1040
1103
  appendContextMessage(out, "user", `System note: ${text}`, entry.timestamp);
1041
1104
  }
@@ -1082,7 +1145,8 @@ export function buildReplayAgentMessagesFromTurns(
1082
1145
  break;
1083
1146
  }
1084
1147
  }
1085
- return out;
1148
+ out.flush();
1149
+ return out.messages;
1086
1150
  }
1087
1151
 
1088
1152
  /**
@@ -6,6 +6,7 @@ import {
6
6
  type DispatchProgressPayload,
7
7
  type DispatchRunIdentity,
8
8
  } from "../core/bus-events.js";
9
+ import { resolveDispatchFailureStatus } from "../core/dispatch-outcome.js";
9
10
  import type { SafeEventBus } from "../core/event-bus.js";
10
11
  import { rawDurationMs } from "../core/timers.js";
11
12
  import type { AgentAudience } from "../domains/agents/spec.js";
@@ -37,7 +38,7 @@ import {
37
38
  type ObservabilityNotice,
38
39
  type ObservabilitySnapshot,
39
40
  } from "../domains/observability/index.js";
40
- import { type CostProvenance, foregroundStreamUsage } from "../domains/providers/index.js";
41
+ import { type CostProvenance, foregroundStreamUsage, resolveCostProvenance } from "../domains/providers/index.js";
41
42
  import { sanitizeCallTargetText } from "../domains/safety/call-target.js";
42
43
  import { type Component, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../engine/tui.js";
43
44
  import { formatWorkerContextMeter } from "./context-meter.js";
@@ -121,7 +122,7 @@ export interface DispatchBoardRow {
121
122
  gate?: { role: string; cycle: number };
122
123
  council?: { group: string; label: string; color?: string; round: number };
123
124
  /** Orchestrator-executed declared verification status. */
124
- hostVerification?: "verified" | "rejected" | "skipped";
125
+ hostVerification?: "verified" | "rejected" | "skipped" | "not_implicated";
125
126
  /**
126
127
  * The canonical trust projection of the sealed receipt, read back from
127
128
  * disk and authenticated against the ledger row. Absent while the run is
@@ -1285,12 +1286,6 @@ function resolveAgentEndStatus(rawMessages: unknown): DispatchBoardStatus | null
1285
1286
  return null;
1286
1287
  }
1287
1288
 
1288
- function resolveFailedStatus(reason: unknown): DispatchBoardStatus {
1289
- if (reason === "dead" || reason === "stalled") return "dead";
1290
- if (reason === "interrupted" || reason === "canceled") return "aborted";
1291
- return "failed";
1292
- }
1293
-
1294
1289
  function resolveFailureDetail(
1295
1290
  payload: Partial<DispatchFailedPayload>,
1296
1291
  fallback: string | null | undefined,
@@ -1601,7 +1596,7 @@ export function createDispatchBoardStore(
1601
1596
  entry.durationMs = parseFiniteNumber(payload.durationMs, Math.max(0, rawDurationMs(entry.startedAtMs, now)));
1602
1597
  entry.tokenCount = parseFiniteNumber(payload.tokenCount, entry.tokenCount);
1603
1598
  entry.costUsd = parseFiniteNumber(payload.costUsd, entry.costUsd);
1604
- entry.costProvenance = payload.costProvenance ?? "unknown";
1599
+ entry.costProvenance = resolveCostProvenance(payload.costProvenance, entry.costProvenance ?? "unknown");
1605
1600
  entry.outcomeDetail = null;
1606
1601
  if (payload.hostVerification !== undefined) entry.hostVerification = payload.hostVerification;
1607
1602
  settleFromReceipt(entry);
@@ -1621,7 +1616,7 @@ export function createDispatchBoardStore(
1621
1616
  const payload: Partial<DispatchFailedPayload> = raw ?? {};
1622
1617
  const runId = parseRunId(payload.runId);
1623
1618
  const previousStatus = runId !== null ? entries.get(runId)?.status : undefined;
1624
- const resolvedStatus = resolveFailedStatus(payload.reason);
1619
+ const resolvedStatus = resolveDispatchFailureStatus(payload.reason);
1625
1620
  const status = previousStatus === "dead" && resolvedStatus === "failed" ? "dead" : resolvedStatus;
1626
1621
  const entry = upsertBase(payload, status, now);
1627
1622
  if (!entry) return;
@@ -1630,7 +1625,7 @@ export function createDispatchBoardStore(
1630
1625
  entry.durationMs = parseFiniteNumber(payload.durationMs, Math.max(0, rawDurationMs(entry.startedAtMs, now)));
1631
1626
  entry.tokenCount = parseFiniteNumber(payload.tokenCount, entry.tokenCount);
1632
1627
  entry.costUsd = parseFiniteNumber(payload.costUsd, entry.costUsd);
1633
- entry.costProvenance = payload.costProvenance ?? "unknown";
1628
+ entry.costProvenance = resolveCostProvenance(payload.costProvenance, entry.costProvenance ?? "unknown");
1634
1629
  entry.outcomeDetail = resolveFailureDetail(payload, entry.outcomeDetail);
1635
1630
  if (payload.hostVerification !== undefined) entry.hostVerification = payload.hostVerification;
1636
1631
  settleFromReceipt(entry);
@@ -368,6 +368,13 @@ function contextComposition(context: ContextEngineFacts): {
368
368
  };
369
369
  }
370
370
 
371
+ /** The live window after the percent; null when unknown or the row is too narrow to carry it. */
372
+ export function compactContextWindowLabel(context: ContextEngineFacts, width: number): string | null {
373
+ if (width < 72) return null;
374
+ const window = finiteNonNegative(context.ledger?.contextWindow ?? context.contextWindow);
375
+ return window > 0 ? formatFooterTokens(window) : null;
376
+ }
377
+
371
378
  export function compactSecondaryLine(
372
379
  context: ContextEngineFacts,
373
380
  agent: AgentWorkFacts,
@@ -403,6 +410,12 @@ export function compactSecondaryLine(
403
410
  } else {
404
411
  left = buildSegmentedContextBar(theme, barCells, context.contextWindow ?? 0, contextBreakdownForBar(context));
405
412
  }
413
+ // A percentage alone does not say whether the window is 128k or 1M, so at
414
+ // widths that can afford it the live window follows the percent. It comes
415
+ // from the ledger when one is bound (the layer that answered the window is
416
+ // also the layer that produced the percent) and from the facts otherwise.
417
+ const windowLabel = compactContextWindowLabel(context, safeWidth);
418
+ if (windowLabel) left = `${left} ${theme.fg("dim", "of")} ${theme.fg("muted", windowLabel)}`;
406
419
  const maxRightWidth = Math.max(0, safeWidth - visibleWidth(left) - 1);
407
420
  const right = buildMetricStrip(
408
421
  theme,
@@ -46,6 +46,7 @@ import type { createMuxBridge } from "./mux-bridge.js";
46
46
  import { createOverlayLifecycle, type OverlayLifecycleController, type OverlayState } from "./overlay-lifecycle.js";
47
47
  import { interopOverlaySurface } from "./overlays/interop.js";
48
48
  import { paneWatchDecision } from "./pane-policy.js";
49
+ import { describePanesLeftBehind } from "./panes-runtime.js";
49
50
  import { writeInputWedgeDump } from "./render-trace.js";
50
51
  import { settleChatBeforeSessionSwitch } from "./session-switch-settlement.js";
51
52
  import { createSessionTranscript } from "./session-transcript.js";
@@ -54,9 +55,10 @@ import type {
54
55
  InitCommandOptions,
55
56
  RunIo,
56
57
  SettingsAreaId,
58
+ SlashCommandContext,
57
59
  TaskMemorySeedCommandResult,
58
60
  } from "./slash-commands.js";
59
- import { processAutoPacingAllowed, resolveSmoothStreamingMode } from "./stream-pacing-policy.js";
61
+ import { processAutoPacingAllowed } from "./stream-pacing-policy.js";
60
62
  import type { TerminalLease } from "./terminal-lease.js";
61
63
  import type { createWatchPaneController } from "./watch-pane.js";
62
64
  import { createWorkspaceFacts } from "./workspace-facts.js";
@@ -121,6 +123,8 @@ export interface InteractiveDeps {
121
123
  initialNotices?: ReadonlyArray<string>;
122
124
  resources?: ResourcesContract;
123
125
  extensions?: ExtensionsContract;
126
+ /** `/resources extensions reload` seam; the composition root supplies the coordinator. */
127
+ reloadExtensions?: SlashCommandContext["reloadExtensions"];
124
128
  interop?: InteropContract;
125
129
  share?: ShareContract;
126
130
  /**
@@ -311,6 +315,8 @@ export interface KeyBindingDeps {
311
315
  requestShutdown: () => void;
312
316
  toggleStatus: () => void;
313
317
  toggleDispatchBoard: () => void;
318
+ /** `/files` as a key: open the files pane when closed, close it when open. */
319
+ toggleFilesPane: () => void;
314
320
  openTasks: () => void;
315
321
  openDecisions: () => void;
316
322
  backgroundDispatch: () => void;
@@ -396,6 +402,9 @@ function dispatchInteractiveAction(id: ClioKeybinding, deps: KeyBindingDeps): bo
396
402
  case "clio-coder.dispatchBoard.toggle":
397
403
  deps.toggleDispatchBoard();
398
404
  return true;
405
+ case "clio-coder.files.toggle":
406
+ deps.toggleFilesPane();
407
+ return true;
399
408
  case "clio-coder.tasks.open":
400
409
  deps.openTasks();
401
410
  return true;
@@ -430,6 +439,7 @@ export function routeInteractiveKey(data: string, deps: KeyBindingDeps): boolean
430
439
  "clio-coder.thinking.cycle",
431
440
  "clio-coder.session.tree",
432
441
  "clio-coder.dispatchBoard.toggle",
442
+ "clio-coder.files.toggle",
433
443
  "clio-coder.tasks.open",
434
444
  "clio-coder.decisions.open",
435
445
  "clio-coder.dispatch.background",
@@ -448,7 +458,7 @@ export function routeInteractiveKey(data: string, deps: KeyBindingDeps): boolean
448
458
  }
449
459
 
450
460
  export async function createInteractiveApplication(deps: InteractiveDeps): Promise<number> {
451
- const initialSmoothStreaming = resolveSmoothStreamingMode(deps.getSettings?.().interface.smoothStreaming ?? "off");
461
+ const initialSmoothStreaming = deps.getSettings?.().interface.smoothStreaming ?? "off";
452
462
  const initialAutoPacingAllowed = processAutoPacingAllowed(false);
453
463
  const lease = deps.terminalLease;
454
464
  const shell =
@@ -606,7 +616,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
606
616
  getDraft: () => editor.getText(),
607
617
  setDraft: (text) => editor.setText(text),
608
618
  requestRender: () => tui.requestRender(),
609
- notice: (level, text) => notify(level, text, `yazi:${level}`),
619
+ notice: (level, text) => notify(level, text, `files:${level}`),
610
620
  getCwd: () => process.cwd(),
611
621
  getSettings: () =>
612
622
  deps.getSettings?.().interface.panes.files ?? {
@@ -672,7 +682,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
672
682
  appendTranscriptNotice: (level, text) => appendNotice(level, text, busNoticeSink),
673
683
  refreshSettingsOverlay: () => overlayLifecycle.refreshSettingsOverlay(),
674
684
  onConfigHotReload: (settings) => {
675
- const mode = resolveSmoothStreamingMode(settings.interface.smoothStreaming);
685
+ const mode = settings.interface.smoothStreaming;
676
686
  const autoAllowed = processAutoPacingAllowed(shell.hasObservedBackpressure());
677
687
  chatRenderer.setSmoothStreamingMode(mode);
678
688
  shell.setStreamPacingActive(mode === "on" || (mode === "auto" && autoAllowed));
@@ -702,6 +712,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
702
712
  settleVisibleFrame: (reason) => chatRenderer.flushAndCommit(reason),
703
713
  ...(deps.resources ? { resources: deps.resources } : {}),
704
714
  ...(deps.extensions ? { extensions: deps.extensions } : {}),
715
+ ...(deps.reloadExtensions ? { reloadExtensions: deps.reloadExtensions } : {}),
705
716
  ...(interopSurface ? { interop: interopSurface } : {}),
706
717
  ...(deps.agents ? { agents: deps.agents } : {}),
707
718
  ...(deps.share ? { share: deps.share } : {}),
@@ -1056,6 +1067,25 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
1056
1067
  if (deps.onCycleScopedModelBackward?.() === false) announceEmptyScopedSet();
1057
1068
  },
1058
1069
  backgroundActiveDispatch,
1070
+ toggleFilesPane: () => {
1071
+ const panes = deps.panes;
1072
+ if (!panes) {
1073
+ notify(
1074
+ "info",
1075
+ "the files pane is inactive: this session started without panes. Restart with `clio-coder --with-panes`, or set interface.panes.enabled=auto",
1076
+ "files:info",
1077
+ );
1078
+ return;
1079
+ }
1080
+ void panes.files("toggle").then((result) => {
1081
+ if (result.status === "opened") {
1082
+ if (result.paneId !== null)
1083
+ notify("success", `files pane ${result.existing ? "focused" : "opened"}`, "files:open");
1084
+ } else if (result.status === "closed") notify("info", "files pane closed", "files:close");
1085
+ else if (result.status === "missing-binary") notify("warning", result.detail, "files:missing");
1086
+ else notify("warning", result.reason, "files:refused");
1087
+ });
1088
+ },
1059
1089
  },
1060
1090
  overlay: overlayLifecycle,
1061
1091
  refreshFooter: () => footer.refresh(),
@@ -1137,6 +1167,11 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
1137
1167
  },
1138
1168
  cancelParkedCalls: (reason) => deps.toolRegistry?.cancelParkedCalls(reason),
1139
1169
  onShutdown: async () => {
1170
+ // The terminal is already stopped here and the domains have not, so this
1171
+ // is the one moment a plain line about the pane host can both be read
1172
+ // and still see the registry that shutdown is about to forget.
1173
+ const leftBehind = mux && mux.mode !== "none" && mux.available() ? describePanesLeftBehind(mux) : null;
1174
+ if (leftBehind !== null) process.stderr.write(`${leftBehind}\n`);
1140
1175
  try {
1141
1176
  if (dumpInputWedgeOnTerminate) process.off("SIGTERM", dumpInputWedgeOnTerminate);
1142
1177
  await deps.onShutdown();
@@ -21,6 +21,7 @@ export interface InteractiveInputKeyActionDeps {
21
21
  requestShutdown: () => void;
22
22
  toggleStatus: () => void;
23
23
  toggleDispatchBoard: () => void;
24
+ toggleFilesPane: () => void;
24
25
  openTasks: () => void;
25
26
  openDecisions: () => void;
26
27
  backgroundDispatch: () => void;
@@ -54,6 +55,8 @@ export interface InteractiveInputRuntimeDeps {
54
55
  cycleScopedModelBackward(): void;
55
56
  /** Convert the newest attached dispatch into a detached batch and notice the outcome. */
56
57
  backgroundActiveDispatch(): void;
58
+ /** Toggle the files pane; the application decides what "inactive" says. */
59
+ toggleFilesPane(): void;
57
60
  };
58
61
  overlay: {
59
62
  getState(): OverlayState;
@@ -154,6 +157,7 @@ export function createInteractiveInputRuntime(deps: InteractiveInputRuntimeDeps)
154
157
  openTasks: deps.overlay.openTasksOverlayState,
155
158
  openDecisions: deps.overlay.openDecisionsOverlayState,
156
159
  backgroundDispatch: deps.actions.backgroundActiveDispatch,
160
+ toggleFilesPane: deps.actions.toggleFilesPane,
157
161
  openModelSelector: deps.overlay.openModelOverlayState,
158
162
  openTree: deps.overlay.openTreeOverlayState,
159
163
  cycleScopedModelForward: () => {
@@ -37,7 +37,7 @@ import { createSlashCommandAutocompleteProvider } from "./slash-autocomplete.js"
37
37
  import { parseSlashCommand, type RunIo } from "./slash-commands.js";
38
38
  import { createStatusController, type StatusController, type TurnSummary } from "./status/index.js";
39
39
  import type { SmoothStreamingMode } from "./stream-pacer.js";
40
- import { processAutoPacingAllowed, resolveSmoothStreamingMode } from "./stream-pacing-policy.js";
40
+ import { processAutoPacingAllowed } from "./stream-pacing-policy.js";
41
41
  import { formatTargetLabel } from "./theme/index.js";
42
42
  import { createWelcomeDashboard, type WelcomeDashboardComponent } from "./welcome-dashboard.js";
43
43
  import { readWorkerReceiptFacts } from "./worker-receipts.js";
@@ -452,7 +452,7 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
452
452
  ? {
453
453
  streamIngress: deps.resolveStreamIngress,
454
454
  getSmoothStreamingMode: () => {
455
- const mode = resolveSmoothStreamingMode(deps.getSettings?.().interface.smoothStreaming ?? "off");
455
+ const mode = deps.getSettings?.().interface.smoothStreaming ?? "off";
456
456
  const autoAllowed = processAutoPacingAllowed(deps.hasObservedBackpressure?.() ?? false);
457
457
  deps.onSmoothStreamingMode?.(mode, mode === "on" || (mode === "auto" && autoAllowed));
458
458
  return mode;
@@ -79,6 +79,7 @@ export interface InteractiveSlashRuntimeDeps {
79
79
  chatPanel: SlashChatPanel;
80
80
  resources?: SlashResources;
81
81
  extensions?: SlashExtensions;
82
+ reloadExtensions?: SlashCommandContext["reloadExtensions"];
82
83
  interop?: SlashCommandContext["interop"];
83
84
  agents?: SlashAgents;
84
85
  share?: SlashShare;
@@ -566,6 +567,7 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
566
567
  openAgents: deps.openAgents,
567
568
  openPrompts: deps.openPrompts,
568
569
  openExtensions: deps.openExtensions,
570
+ ...(deps.reloadExtensions ? { reloadExtensions: deps.reloadExtensions } : {}),
569
571
  ...(deps.openInterop ? { openInterop: deps.openInterop } : {}),
570
572
  ...(deps.interop ? { interop: deps.interop } : {}),
571
573
  setEditorText: (text) => {
@@ -10,7 +10,15 @@ export const EXTENSIONS_EMPTY =
10
10
  export function openExtensionsOverlay(tui: TUI, ctx: SlashCommandContext, onClose: () => void): OverlayHandle {
11
11
  const list = ctx.listExtensions?.() ?? [];
12
12
  const items: ListOverlayItem[] = list.map((ext) => {
13
- const state = !ext.enabled ? "disabled" : ext.effective ? "active" : `shadowed:${ext.overriddenBy ?? "higher"}`;
13
+ const state = !ext.valid
14
+ ? "invalid"
15
+ : !ext.compatible
16
+ ? "incompatible"
17
+ : !ext.enabled
18
+ ? "disabled"
19
+ : ext.loadable
20
+ ? "active"
21
+ : `shadowed:${ext.overriddenBy ?? "higher"}`;
14
22
 
15
23
  let meta = state;
16
24
  if (state === "active") {
@@ -101,6 +101,19 @@ export function openHelpOverlay(
101
101
  "**Tasks versus runs**: `/tasks` shows the agent's plan steps. Fleet runs are concrete delegated worker executions and remain in this board as recent terminal history.",
102
102
  ],
103
103
  },
104
+ {
105
+ id: "topic-files-pane",
106
+ label: `${"panes & files".padEnd(30)}The files pane, the logs and shell panes, and what closes them`,
107
+ group: "Topics",
108
+ detail: () => [
109
+ "# Panes & files",
110
+ "**Where it works**: a session started inside a herdr pane with `clio-coder --with-panes` (or `interface.panes.enabled: auto`). Outside herdr `/files` still works as a full-screen pick that returns to the composer; `/panes open logs|shell` do not.",
111
+ "**Files pane**: `/files` or the Files toggle key (Alt+E by default) opens the file view below the session and moves the keyboard into it; the same key or command closes it. `/files pick` borrows it for one selection. It is off until `interface.panes.files.enabled` is `true`.",
112
+ "**Picking**: navigate, select with Space for several, then Ctrl+Y (or Enter in pick mode). The paths land in the composer as `@file` mentions and the keyboard returns to the composer.",
113
+ "**Logs and shell**: `/panes open logs` follows the newest dispatched run's journal; `/panes open shell` opens a shell in the workspace. A second open focuses the pane that is already there. `/panes close <name|all>` closes them; `/quit` closes the docks it manages (files, workers), leaves a shell or logs pane you opened, and prints which panes it left and how to close them.",
114
+ "**Engine**: the files pane runs a vendored file manager installed with `clio-coder tools install yazi`; `clio-coder doctor` and `/panes` say whether it resolved.",
115
+ ],
116
+ },
104
117
  {
105
118
  id: "topic-steering-modes",
106
119
  label: `${"steering modes".padEnd(30)}Interrupt, next slot, or end of turn: when a message lands mid-run`,
@@ -200,7 +200,7 @@ export const SETTINGS_LABELS_BY_ID = {
200
200
  "panes.journal": "Run event journal",
201
201
  "panes.yazi.enabled": "Files pane",
202
202
  "panes.yazi.mode": "Files pane mode",
203
- "panes.yazi.profile": "Yazi profile",
203
+ "panes.yazi.profile": "Files pane profile",
204
204
  "panes.yazi.followCwd": "Follow conversation cwd",
205
205
  "panes.yazi.ratio": "Files dock share",
206
206
  scope: "Model cycle set",
@@ -208,6 +208,7 @@ export const SETTINGS_LABELS_BY_ID = {
208
208
  "modelSelector.favorites": "Pinned favorites",
209
209
  "budget.sessionCeilingUsd": "Session ceiling (USD)",
210
210
  "defaults.maxTokens": "Output budget (tokens)",
211
+ "context.toolResultMaxBytes": "Tool result cap (bytes)",
211
212
  "budget.concurrency": "Fleet concurrency",
212
213
  "guardrails.turnToolCallBudget": "Turn tool-call budget",
213
214
  "guardrails.workerToolCallCap": "Worker tool-call cap",
@@ -326,6 +327,7 @@ export const SETTINGS_SECTION_ROWS = {
326
327
  budget: [
327
328
  "budget.sessionCeilingUsd",
328
329
  "defaults.maxTokens",
330
+ "context.toolResultMaxBytes",
329
331
  "budget.concurrency",
330
332
  "guardrails.turnToolCallBudget",
331
333
  "guardrails.workerToolCallCap",
@@ -414,9 +416,10 @@ const SETTINGS_DESCRIPTIONS_BY_ID = {
414
416
  "panes.layout": "What composes itself at interactive boot: nothing, the workers dock, or workers plus files.",
415
417
  "panes.workers.ratio": "Share of the width the workers dock takes, at most half.",
416
418
  "panes.journal": "Whether every dispatched run's event tail is written to disk for `clio-coder fleet view`.",
417
- "panes.yazi.enabled": "Whether `/panes open yazi` may open the files pane or one-shot chooser.",
418
- "panes.yazi.mode": "Keep Yazi beside the conversation, or close it after one selection.",
419
- "panes.yazi.profile": "Use Clio's managed pick profile or leave the operator's Yazi profile untouched.",
419
+ "panes.yazi.enabled":
420
+ "Whether `/files`, its key, and `/panes open files` may open the files pane or the one-shot pick.",
421
+ "panes.yazi.mode": "Keep the files pane beside the conversation, or close it after one selection.",
422
+ "panes.yazi.profile": "Use Clio's managed, themed engine profile or the operator's own file-manager configuration.",
420
423
  "panes.yazi.followCwd": "Push the conversation directory into an already-open companion pane.",
421
424
  "panes.yazi.ratio": "Share of the height the files dock takes, at most half.",
422
425
  scope: "Alt+J and Alt+K model cycle set.",
@@ -424,6 +427,7 @@ const SETTINGS_DESCRIPTIONS_BY_ID = {
424
427
  "modelSelector.favorites": "Exact target/model refs pinned in /model.",
425
428
  "budget.sessionCeilingUsd": "Per-session cost cap.",
426
429
  "defaults.maxTokens": "Output tokens requested per turn, applied to every target.",
430
+ "context.toolResultMaxBytes": "Maximum bytes returned from one tool result before the full text spills to scratch.",
427
431
  "budget.concurrency": "Parallel workers allowed during dispatch.",
428
432
  "guardrails.turnToolCallBudget": "Soft per-turn tool-call budget for this chat loop.",
429
433
  "guardrails.workerToolCallCap": "Lifetime ceiling on tool calls one dispatched worker may execute.",
@@ -475,6 +479,8 @@ const SETTINGS_HELP_BY_ID: Partial<Record<EditableSettingId, string>> = {
475
479
  "read-only observes; suggest parks non-read calls; auto-edit edits, dispatches, and runs recognized commands; full-auto runs except command substitution and system-level changes. A confirmation marked exposure=outward parks for you at suggest and auto-edit.",
476
480
  "defaults.maxTokens":
477
481
  "Clamped down to each model's max-output cap and the remaining context window. Set 0 to use per-model caps only.",
482
+ "context.toolResultMaxBytes":
483
+ "The 192KB per-turn observation pool remains authoritative. Three full 64KB results consume it, so a fourth finds it filled. Whole number of at least 4096 bytes · default: 65536 (64KB).",
478
484
  "compaction.threshold":
479
485
  "pressure = estimated tokens ÷ context window. Higher keeps more history but risks overflow before a summary runs.",
480
486
  "context.workingSet.enabled":
@@ -487,17 +493,17 @@ const SETTINGS_HELP_BY_ID: Partial<Record<EditableSettingId, string>> = {
487
493
  "context.workingSet.minEvictableTokens":
488
494
  "The floor sweep put marker break-even near 50 tokens; 200 is the churn guard. Whole number, 0 evicts anything · default: 200.",
489
495
  "guardrails.turnToolCallBudget":
490
- "Crossing it blocks further calls in the turn with a stop-and-summarize directive, and the hard interrupt ceiling sits a fixed margin above. A backstop against a model spraying unproductive calls, not a routine ceiling: a repo-wide audit legitimately runs dozens. Whole number of at least 1 · default: 60. Env override CLIO_CODER_TURN_TOOL_CALL_BUDGET beats this value.",
496
+ "Crossing it blocks further calls in the turn with a stop-and-summarize directive, and the hard interrupt ceiling sits a fixed margin above. A backstop against a model spraying unproductive calls, not a routine ceiling: a repo-wide audit legitimately runs dozens. Whole number of at least 1 · default: 60.",
491
497
  "guardrails.workerToolCallCap":
492
- "Bounds admitted calls, not attempts: a call the harness refuses never ran and never spends the cap. Dispatch takes the smaller of this and the agent recipe's own budget, so the recipe normally binds. Whole number of at least 1 · default: 150. Env override CLIO_CODER_WORKER_TOOL_CALL_CAP beats this value.",
498
+ "Bounds admitted calls, not attempts: a call the harness refuses never ran and never spends the cap. Dispatch takes the smaller of this and the agent recipe's own budget, so the recipe normally binds. Whole number of at least 1 · default: 150.",
493
499
  "guardrails.maxDispatchRuns":
494
- "Runs leaving the ring also lose their event journal directory. Whole number of at least 1 · default: 1000. Env override CLIO_CODER_MAX_DISPATCH_RUNS beats this value.",
500
+ "Runs leaving the ring also lose their event journal directory. Whole number of at least 1 · default: 1000.",
495
501
  "guardrails.readMaxBytes":
496
- "Clamped up to a 1KB floor at use. Whole number of bytes, at least 1 · default: 51200 (50KB). Env override CLIO_CODER_READ_MAX_BYTES beats this value.",
502
+ "Clamped up to a 1KB floor at use. Whole number of bytes, at least 1 · default: 51200 (50KB).",
497
503
  "guardrails.observationTurnBudgetBytes":
498
- "One pool shared by every observation-producing tool in a turn, so a single verbose tool cannot starve the rest. Whole number of bytes, at least 1 · default: 196608 (192KB). Env override CLIO_CODER_OBSERVATION_TURN_BUDGET_BYTES beats this value.",
504
+ "One pool shared by every observation-producing tool in a turn, so a single verbose tool cannot starve the rest. Whole number of bytes, at least 1 · default: 196608 (192KB).",
499
505
  "guardrails.internalDispatchTimeoutMs":
500
- "Covers the wiki documenter and the bootstrap scout. Continuous output satisfies the heartbeat watchdog and a run mid-generation spends no tool calls, so this is the only guard that ends a degenerate generator. Healthy runs finish in minutes. Whole milliseconds of at least 1 · default: 900000 (15 minutes). Env override CLIO_CODER_INTERNAL_DISPATCH_TIMEOUT_MS beats this value.",
506
+ "Covers the wiki documenter and the bootstrap scout. Continuous output satisfies the heartbeat watchdog and a run mid-generation spends no tool calls, so this is the only guard that ends a degenerate generator. Healthy runs finish in minutes. Whole milliseconds of at least 1 · default: 900000 (15 minutes).",
501
507
  "retry.streamStallMs":
502
508
  "Measured from the last token received, not from the request, so a slow-but-alive stream is never aborted. The retry then follows the same enabled/maxRetries/delay settings above. Whole milliseconds · default: 180000 (three minutes).",
503
509
  "library.catalog":
@@ -593,14 +599,11 @@ const SETTINGS_VALUE_HELP_BY_ID: Partial<Record<EditableSettingId, Record<string
593
599
  true: "compact automatically before a turn crosses the threshold",
594
600
  false: "context is only compacted when you run /context compact",
595
601
  },
596
- // `embedded` is a declared rung with no implementation behind it, and a row
597
- // that offered it beside two working values read as a third working value.
598
- // It stays selectable, because refusing it outright would break a settings
599
- // file that names it, but nothing here lets an operator pick it believing
600
- // they will get panes.
602
+ // `embedded` is a declared rung with no implementation behind it yet; it
603
+ // runs as `auto` until Clio can own a pane host, and the hint says so.
601
604
  "panes.enabled": {
602
605
  auto: "detect a herdr session and join it as a guest; no pane host, no panes",
603
- embedded: "NOT IMPLEMENTED (ships in phase 5): this session gets no panes at all, guest mode included",
606
+ embedded: "not implemented yet; behaves as auto (guest mode inside herdr) until Clio can own a pane host",
604
607
  off: "never detect or open a pane",
605
608
  },
606
609
  "retry.enabled": {
@@ -1838,6 +1841,9 @@ function buildSettingItems(settings: Readonly<ClioSettings>, options?: BuildSett
1838
1841
  settingItem("defaults.maxTokens", String(settings.chat.maxOutputTokens), {
1839
1842
  values: ["0", "4096", "8192", "16384", "32768", "65536", "131072"],
1840
1843
  }),
1844
+ settingItem("context.toolResultMaxBytes", String(settings.context.toolResultMaxBytes), {
1845
+ values: ["4096", "8192", "16384", "32768", "65536", "131072"],
1846
+ }),
1841
1847
  settingItem("budget.concurrency", String(settings.fleet.concurrency), {
1842
1848
  values: ["auto", "1", "2", "4", "8"],
1843
1849
  }),
@@ -2707,6 +2713,11 @@ function applySettingChange(settings: ClioSettings, id: string, value: string):
2707
2713
  else settings.fleet.limits.internalRunTimeoutMs = next;
2708
2714
  });
2709
2715
  return;
2716
+ case "context.toolResultMaxBytes":
2717
+ applyNonNegativeInteger(value, (next) => {
2718
+ if (next >= 4096) settings.context.toolResultMaxBytes = next;
2719
+ });
2720
+ return;
2710
2721
  case "context.workingSet.enabled":
2711
2722
  if (value === "true" || value === "false") settings.context.workingSet.enabled = value === "true";
2712
2723
  return;