@iowarp/clio-coder 0.3.8 → 0.4.0

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 (552) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/NOTICE +33 -0
  3. package/README.md +12 -3
  4. package/dist/{acp-U67UHUK2.js → acp-G5WJBNCT.js} +13 -12
  5. package/dist/{agents-YU6SGALZ.js → agents-FMV2Q5G4.js} +41 -36
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-5ZPJOIVG.js → auth-3IDSJEIK.js} +18 -18
  8. package/dist/{builtins-C6JMZVV6.js → builtins-XCZWXSC7.js} +5 -5
  9. package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
  10. package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
  11. package/dist/{chunk-XWSF374K.js → chunk-2OQE55CK.js} +3 -3
  12. package/dist/{chunk-5H3GB5BO.js → chunk-32KWKNSF.js} +8 -384
  13. package/dist/{chunk-KTYTFRMB.js → chunk-36EJLSQQ.js} +34 -36
  14. package/dist/{chunk-FHJEP5SW.js → chunk-3BT2XMV4.js} +19 -13
  15. package/dist/chunk-3DPEIQKN.js +113 -0
  16. package/dist/{chunk-GU2UIAFZ.js → chunk-3URVFKWK.js} +7 -7
  17. package/dist/{chunk-WEH5XRJQ.js → chunk-3XML7CDN.js} +3 -3
  18. package/dist/chunk-42FMPA75.js +101 -0
  19. package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
  20. package/dist/{chunk-VCBR6CU7.js → chunk-5PSMVOLM.js} +2 -2
  21. package/dist/{chunk-NMPKI6XL.js → chunk-6DB53AJS.js} +203 -25
  22. package/dist/{chunk-3BINW3FP.js → chunk-76ONBSIA.js} +2 -2
  23. package/dist/{chunk-26LEYJZH.js → chunk-7MCTRUCE.js} +2 -2
  24. package/dist/{chunk-TYPGUK6W.js → chunk-AB44T6BB.js} +111 -5
  25. package/dist/{chunk-K4XHGFR5.js → chunk-B7OBL7PK.js} +317 -721
  26. package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
  27. package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
  28. package/dist/{chunk-ZVJ5BLO2.js → chunk-BKFJHQCA.js} +154 -16
  29. package/dist/chunk-BKFM6EJV.js +462 -0
  30. package/dist/chunk-BMS5RKQY.js +27 -0
  31. package/dist/{chunk-ZNLWCMVZ.js → chunk-BPKCPIL7.js} +2 -2
  32. package/dist/{chunk-TLQJPP24.js → chunk-BUMFYQFY.js} +1394 -1349
  33. package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
  34. package/dist/chunk-C2LTL2W6.js +2447 -0
  35. package/dist/{chunk-ME6CCNFO.js → chunk-CODPRO7Q.js} +8 -8
  36. package/dist/{chunk-E77JEWSD.js → chunk-CTJ4RNAA.js} +7 -37
  37. package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
  38. package/dist/{chunk-7RFXX52T.js → chunk-DQITNCXG.js} +642 -172
  39. package/dist/{chunk-TTHACPOM.js → chunk-DYJP44XW.js} +578 -117
  40. package/dist/{chunk-2HFZQUHL.js → chunk-F4CKPOEQ.js} +18 -8
  41. package/dist/{chunk-DGSYXYMX.js → chunk-FEFIFZTL.js} +3 -3
  42. package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
  43. package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
  44. package/dist/chunk-GKF55TAZ.js +391 -0
  45. package/dist/{chunk-VWZOAB7K.js → chunk-GR5G2PVF.js} +9 -8
  46. package/dist/{chunk-4DGYLA73.js → chunk-GXNLGKAB.js} +80 -9
  47. package/dist/chunk-HHV2GANA.js +88 -0
  48. package/dist/{chunk-IIZWH4XA.js → chunk-HI63TFOG.js} +5 -4
  49. package/dist/{chunk-WLFILSD5.js → chunk-HJJTYUHX.js} +113 -83
  50. package/dist/{chunk-TT36MB5S.js → chunk-HLW2MRKE.js} +3 -1
  51. package/dist/{chunk-PMDBGQSJ.js → chunk-HWHKMHUA.js} +7 -7
  52. package/dist/chunk-HZHHCK24.js +1631 -0
  53. package/dist/{chunk-WSB3FPX7.js → chunk-I5VEOC6I.js} +39 -143
  54. package/dist/chunk-IBEBSCYA.js +564 -0
  55. package/dist/chunk-IQ7KR472.js +362 -0
  56. package/dist/{chunk-A3WNZD3P.js → chunk-J4W7KFM7.js} +949 -972
  57. package/dist/{chunk-TB5666IT.js → chunk-JDG2WCRO.js} +5 -5
  58. package/dist/{chunk-N22QMJKY.js → chunk-K5C3NCBD.js} +4 -4
  59. package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
  60. package/dist/{chunk-5C3AQNDW.js → chunk-KFZI4NIL.js} +216 -38
  61. package/dist/chunk-KMVISBZR.js +132 -0
  62. package/dist/{chunk-WXY7KU3G.js → chunk-LDQ2ZF2M.js} +2 -2
  63. package/dist/{chunk-XN3L4EYL.js → chunk-LQ3DZAMX.js} +3 -3
  64. package/dist/{chunk-U6MBIEMB.js → chunk-LY4S7GJC.js} +173 -144
  65. package/dist/{chunk-4SPRNWDE.js → chunk-MLKNTWH2.js} +19 -19
  66. package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
  67. package/dist/chunk-NEKRRTYW.js +56 -0
  68. package/dist/{chunk-SPULKLCF.js → chunk-NHCZP4K7.js} +3 -3
  69. package/dist/chunk-NHLBIGRH.js +1506 -0
  70. package/dist/chunk-NQQH3YT7.js +302 -0
  71. package/dist/chunk-NYS75XW5.js +15 -0
  72. package/dist/{chunk-GN57SG4G.js → chunk-O4XIVISU.js} +10 -8
  73. package/dist/{chunk-EMYUUSFG.js → chunk-O6TL7WWY.js} +6 -6
  74. package/dist/chunk-OQBA45DZ.js +97 -0
  75. package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
  76. package/dist/chunk-PMZCIOCJ.js +25 -0
  77. package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
  78. package/dist/{chunk-J3YUBZWY.js → chunk-QBJA7R7N.js} +62 -6
  79. package/dist/chunk-QDC3K2U3.js +262 -0
  80. package/dist/{chunk-2HEJ2F35.js → chunk-QLFS5GO2.js} +22 -10
  81. package/dist/{chunk-7RGZWPB6.js → chunk-QLL7ILRG.js} +95 -32
  82. package/dist/{chunk-YS5VLNH5.js → chunk-QREDIESB.js} +6 -6
  83. package/dist/chunk-QSNYB6ZV.js +195 -0
  84. package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
  85. package/dist/chunk-RKKLTLYB.js +45 -0
  86. package/dist/{chunk-P43ETTHK.js → chunk-SJ5ZKQ4S.js} +2 -2
  87. package/dist/{chunk-GPIEI3LY.js → chunk-SP2RXXYO.js} +6 -54
  88. package/dist/chunk-SUCTJL45.js +45 -0
  89. package/dist/{chunk-DYIM5TJT.js → chunk-SUW5DORT.js} +263 -7
  90. package/dist/chunk-T56WDKA5.js +183 -0
  91. package/dist/chunk-TVHHYFHE.js +255 -0
  92. package/dist/{chunk-FJ3H4MN5.js → chunk-TZ3SGWZZ.js} +3 -3
  93. package/dist/{chunk-MXKJU4JB.js → chunk-U77AMWDL.js} +91 -10
  94. package/dist/{chunk-5DHKRSMQ.js → chunk-ULC6OTWO.js} +11 -7
  95. package/dist/{chunk-RWSI4YD7.js → chunk-UM7N4G5A.js} +33 -12
  96. package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
  97. package/dist/{chunk-IGWKHNIQ.js → chunk-UXMFQ54G.js} +44 -37
  98. package/dist/{chunk-HFSBBKSQ.js → chunk-V5DHCITQ.js} +171 -3
  99. package/dist/{chunk-5WIGXA4T.js → chunk-VAZSBTKF.js} +111 -4
  100. package/dist/{chunk-VHN4MY6O.js → chunk-VEO4AP2K.js} +2 -2
  101. package/dist/{chunk-IJ7RPIYJ.js → chunk-VFA6GDY5.js} +65 -4
  102. package/dist/{chunk-PT7HYKEM.js → chunk-VO2LKSTM.js} +2 -2
  103. package/dist/chunk-VO67MWHC.js +75 -0
  104. package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
  105. package/dist/{chunk-TANS5ZJS.js → chunk-VYMXRQI6.js} +36 -22
  106. package/dist/{chunk-WWCZ5F23.js → chunk-W5VSYASO.js} +77 -16
  107. package/dist/{chunk-WNIJTQQK.js → chunk-WZR7K7ZX.js} +72 -116
  108. package/dist/{chunk-5Q2VVUKB.js → chunk-X3YGUTOB.js} +4 -4
  109. package/dist/chunk-X75E3D2N.js +686 -0
  110. package/dist/{chunk-VAWNZU7Z.js → chunk-YDFRH54B.js} +4 -4
  111. package/dist/chunk-YJX4SHTD.js +40 -0
  112. package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
  113. package/dist/chunk-Z2RR6MAK.js +127 -0
  114. package/dist/{chunk-FBVTI2TJ.js → chunk-Z4TXYIEG.js} +12 -131
  115. package/dist/cli/index.js +47 -36
  116. package/dist/{clio-QVTYJ57A.js → clio-2JXHBBY5.js} +7 -7
  117. package/dist/{code-nav-FGGFIE7L.js → code-nav-3YYRMYNF.js} +8 -8
  118. package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
  119. package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
  120. package/dist/{config-LW5IJFQN.js → config-QZPCMYSO.js} +99 -63
  121. package/dist/{configure-7XIZCOU4.js → configure-TEGEBYCA.js} +23 -22
  122. package/dist/{context-Y6Y7QPR6.js → context-AV7OEZ4D.js} +12 -12
  123. package/dist/{context-L3WL3X7K.js → context-E6H5RNMC.js} +56 -47
  124. package/dist/{context-N52ZA626.js → context-GSXUE4CT.js} +29 -27
  125. package/dist/{context-clear-MBQRLSDQ.js → context-clear-SHIBYK6T.js} +55 -46
  126. package/dist/{context-index-HVMFQHK3.js → context-index-HNG3MOME.js} +2 -2
  127. package/dist/{context-working-set-GS6DSO7F.js → context-working-set-5ZGKPGZQ.js} +13 -13
  128. package/dist/{dispatch-runner-22ZCNOM3.js → dispatch-runner-EFMJT4LD.js} +93 -64
  129. package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
  130. package/dist/doctor-QOA5FNY5.js +313 -0
  131. package/dist/{eval-BEC2WHDA.js → eval-TFBYQH4H.js} +2032 -156
  132. package/dist/eval-inventory-SXH7PDKX.js +316 -0
  133. package/dist/{evidence-REJUMSKM.js → evidence-ERGESKGN.js} +203 -48
  134. package/dist/{evolve-PY5ZBA5K.js → evolve-VDXTSYCJ.js} +52 -43
  135. package/dist/{extensions-HVKU65YU.js → extensions-7BGBHN57.js} +13 -7
  136. package/dist/{fleet-7WZEWRFA.js → fleet-2RRVDF2V.js} +228 -108
  137. package/dist/{fleet-commands-UVHWM76J.js → fleet-commands-VJ726XIA.js} +11 -11
  138. package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
  139. package/dist/{fleet-graph-6ULH7PES.js → fleet-graph-JF5QOATM.js} +18 -15
  140. package/dist/fleet-inspect-VLY4S7QM.js +442 -0
  141. package/dist/{fleet-preflight-J53T6CCE.js → fleet-preflight-AIZUEJOY.js} +5 -5
  142. package/dist/{fleet-validate-72PC4SLA.js → fleet-validate-AJRPDMDV.js} +22 -19
  143. package/dist/fleet-verify-JFEL2L3H.js +175 -0
  144. package/dist/fleet-view-ZCON35AG.js +102 -0
  145. package/dist/{init-OG3TPGQG.js → init-DN2WWLFE.js} +72 -62
  146. package/dist/install-XGLBQY5E.js +13 -0
  147. package/dist/interop-OZBKXAYL.js +114 -0
  148. package/dist/{library-CNTMPLRF.js → library-YWZG7IMW.js} +21 -18
  149. package/dist/{memory-6IS7F275.js → memory-I4C4HMLW.js} +54 -45
  150. package/dist/{models-ENRJDA5W.js → models-CEYXJBO6.js} +33 -30
  151. package/dist/{monitor-XLDVO7TN.js → monitor-NZ6GCI3P.js} +59 -52
  152. package/dist/{orchestrator-6KSPYRHA.js → orchestrator-GCGQ4N5I.js} +7827 -7328
  153. package/dist/panes-HMABYVO4.js +58 -0
  154. package/dist/panes-KY6W3V2E.js +103 -0
  155. package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
  156. package/dist/{reset-RZ4ER727.js → reset-DQ6FGCSH.js} +13 -11
  157. package/dist/resources-BB3MVJMD.js +111 -0
  158. package/dist/{run-Y2CNK5RU.js → run-H2GQDUER.js} +119 -87
  159. package/dist/{share-A55GYP6Z.js → share-GTJN6A5O.js} +20 -17
  160. package/dist/{skills-ALC5J6AT.js → skills-L55TEW6R.js} +33 -24
  161. package/dist/{skills-eval-JPBEBYQU.js → skills-eval-XVXPH2JI.js} +67 -56
  162. package/dist/skills-inventory-S4MXPJFV.js +126 -0
  163. package/dist/slash-commands-ZSGASKJC.js +77 -0
  164. package/dist/{steer-GGWFUJUD.js → steer-RZGSCY4R.js} +4 -4
  165. package/dist/{support-MIETYA5E.js → support-PKEUNNQL.js} +6 -6
  166. package/dist/{targets-VGNXIR3S.js → targets-NCPZ644J.js} +68 -40
  167. package/dist/{terminal-lease-WOBR64YA.js → terminal-lease-44SV3YCN.js} +6 -4
  168. package/dist/tools-DAF3DI3C.js +27 -0
  169. package/dist/{trace-PNCASAXC.js → trace-FYVW2MQA.js} +207 -10
  170. package/dist/tui-primitives-2AKXQNZK.js +13 -0
  171. package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
  172. package/dist/{upgrade-FUSUAGHR.js → upgrade-3XPP6OQL.js} +27 -24
  173. package/dist/{usage-N4MKVHKD.js → usage-3NLHGTU2.js} +114 -62
  174. package/dist/{verifiers-YAWOJ3H2.js → verifiers-SSQONKRT.js} +172 -13
  175. package/dist/{verify-LTDHYBGY.js → verify-3U6J7FZI.js} +10 -10
  176. package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
  177. package/dist/{wiki-generate-6M7GHTBJ.js → wiki-generate-CEHYGPGQ.js} +75 -65
  178. package/dist/with-panes-MKB46MPQ.js +782 -0
  179. package/dist/worker/entry.js +106 -75
  180. package/docs/README.md +3 -2
  181. package/docs/acp.md +24 -3
  182. package/docs/alcf-provider.md +1 -1
  183. package/docs/architecture.md +2 -2
  184. package/docs/artifact-versions.md +9 -1
  185. package/docs/built-in-agents.md +1 -1
  186. package/docs/capacity-and-scheduling.md +62 -3
  187. package/docs/commands-and-modes.md +31 -2
  188. package/docs/configuration-and-targets.md +69 -12
  189. package/docs/context-engine.md +63 -4
  190. package/docs/development-pipeline.md +19 -0
  191. package/docs/dispatch-typed-intent.md +385 -0
  192. package/docs/documentation-coverage.md +5 -5
  193. package/docs/documentation-guide.md +1 -1
  194. package/docs/environment-variables.md +3 -0
  195. package/docs/eval-runner.md +262 -11
  196. package/docs/evals-internal.md +72 -2
  197. package/docs/evidence-and-memory.md +12 -11
  198. package/docs/evolution.md +1 -1
  199. package/docs/exit-codes-and-output.md +1 -1
  200. package/docs/extensions-and-sharing.md +27 -1
  201. package/docs/fleet-dispatch.md +25 -4
  202. package/docs/installation-and-lifecycle.md +15 -2
  203. package/docs/middleware-and-components.md +1 -1
  204. package/docs/model-catalog.md +10 -1
  205. package/docs/observability.md +55 -4
  206. package/docs/proactive-memory.md +127 -14
  207. package/docs/prompt-envelope-and-tools.md +19 -1
  208. package/docs/provider-adapter-cookbook.md +1 -1
  209. package/docs/release-cut-checklist.md +19 -3
  210. package/docs/safety-model.md +2 -2
  211. package/docs/scientific-validation.md +3 -3
  212. package/docs/session-lifecycle.md +1 -1
  213. package/docs/skills-marketplace.md +1 -1
  214. package/docs/tool-usage.md +18 -8
  215. package/docs/trace-store.md +1 -1
  216. package/docs/troubleshooting.md +88 -1
  217. package/docs/tui-design.md +1 -1
  218. package/docs/worker-dispatch-mechanics.md +1 -1
  219. package/package.json +5 -2
  220. package/src/cli/acp.ts +6 -2
  221. package/src/cli/agents.ts +1 -1
  222. package/src/cli/argv.ts +25 -0
  223. package/src/cli/config-inspect.ts +33 -6
  224. package/src/cli/config.ts +1 -1
  225. package/src/cli/configure.ts +23 -21
  226. package/src/cli/doctor-panes.ts +124 -0
  227. package/src/cli/doctor-state-size.ts +82 -0
  228. package/src/cli/doctor-toolchain.ts +57 -0
  229. package/src/cli/doctor.ts +22 -1
  230. package/src/cli/eval-inventory.ts +436 -0
  231. package/src/cli/eval.ts +93 -16
  232. package/src/cli/evidence-detail.ts +88 -0
  233. package/src/cli/evidence-inventory.ts +183 -0
  234. package/src/cli/evidence.ts +30 -5
  235. package/src/cli/extensions.ts +5 -1
  236. package/src/cli/fleet-decisions.ts +69 -0
  237. package/src/cli/fleet-inspect.ts +334 -0
  238. package/src/cli/fleet-verify.ts +133 -0
  239. package/src/cli/fleet-view.ts +810 -0
  240. package/src/cli/fleet.ts +179 -39
  241. package/src/cli/index.ts +14 -2
  242. package/src/cli/interop-inspect.ts +128 -0
  243. package/src/cli/interop.ts +34 -0
  244. package/src/cli/panes.ts +35 -0
  245. package/src/cli/reset.ts +5 -2
  246. package/src/cli/run.ts +58 -0
  247. package/src/cli/skills-inventory.ts +185 -0
  248. package/src/cli/skills.ts +16 -13
  249. package/src/cli/targets.ts +44 -13
  250. package/src/cli/tools.ts +321 -0
  251. package/src/cli/trace-inspect.ts +252 -0
  252. package/src/cli/trace.ts +85 -5
  253. package/src/cli/usage.ts +63 -14
  254. package/src/cli/verifiers-inspect.ts +347 -0
  255. package/src/cli/verifiers.ts +9 -0
  256. package/src/core/bus-events.ts +33 -1
  257. package/src/core/cache-telemetry.ts +42 -0
  258. package/src/core/config.ts +67 -0
  259. package/src/core/defaults.ts +124 -8
  260. package/src/core/endpoint-key.ts +27 -0
  261. package/src/core/residency-target-key.ts +25 -0
  262. package/src/core/response-schema.ts +80 -6
  263. package/src/core/theme-token-hex.ts +43 -0
  264. package/src/core/tool-names.ts +2 -1
  265. package/src/core/xdg.ts +1 -1
  266. package/src/domains/agents/fleets/build-review.md +0 -3
  267. package/src/domains/agents/fleets/build-test.md +0 -3
  268. package/src/domains/agents/result-contract-filesystem.ts +32 -0
  269. package/src/domains/agents/result-contract.ts +164 -35
  270. package/src/domains/config/classify.ts +6 -0
  271. package/src/domains/context/codewiki/coordinator.ts +12 -4
  272. package/src/domains/dispatch/admission-error.ts +9 -0
  273. package/src/domains/dispatch/admission.ts +52 -14
  274. package/src/domains/dispatch/capacity-lease.ts +118 -9
  275. package/src/domains/dispatch/contract.ts +11 -0
  276. package/src/domains/dispatch/council-topology.ts +398 -0
  277. package/src/domains/dispatch/execution-plan.ts +44 -4
  278. package/src/domains/dispatch/extension.ts +378 -82
  279. package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
  280. package/src/domains/dispatch/fleet-plan.ts +7 -2
  281. package/src/domains/dispatch/fleet-run.ts +87 -4
  282. package/src/domains/dispatch/gate-decisions.ts +11 -1
  283. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  284. package/src/domains/dispatch/gate-topology.ts +289 -0
  285. package/src/domains/dispatch/heartbeat.ts +32 -8
  286. package/src/domains/dispatch/index.ts +22 -0
  287. package/src/domains/dispatch/intent-compatibility.ts +330 -0
  288. package/src/domains/dispatch/intent.ts +85 -1
  289. package/src/domains/dispatch/orphan-recovery.ts +5 -0
  290. package/src/domains/dispatch/reservation-store.ts +139 -11
  291. package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
  292. package/src/domains/dispatch/run-event-journal.ts +598 -0
  293. package/src/domains/dispatch/state.ts +49 -1
  294. package/src/domains/dispatch/types.ts +13 -0
  295. package/src/domains/dispatch/validation.ts +33 -8
  296. package/src/domains/dispatch/worker-spawn.ts +25 -11
  297. package/src/domains/dispatch/write-boundary-enforcer.ts +20 -3
  298. package/src/domains/dispatch/write-boundary.ts +62 -1
  299. package/src/domains/eval/artifacts/store.ts +62 -0
  300. package/src/domains/eval/compare/behavioral.ts +224 -0
  301. package/src/domains/eval/compare/compare.ts +342 -2
  302. package/src/domains/eval/compare/envelope.ts +128 -0
  303. package/src/domains/eval/compare/gates.ts +24 -6
  304. package/src/domains/eval/compare/thresholds.ts +30 -3
  305. package/src/domains/eval/execution-provenance.ts +240 -0
  306. package/src/domains/eval/inventory.ts +113 -0
  307. package/src/domains/eval/metrics/aggregate.ts +136 -0
  308. package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
  309. package/src/domains/eval/metrics/tracked.ts +413 -0
  310. package/src/domains/eval/provenance.ts +117 -0
  311. package/src/domains/eval/reports/comparison.ts +128 -0
  312. package/src/domains/eval/reports/junit.ts +17 -3
  313. package/src/domains/eval/reports/markdown.ts +3 -3
  314. package/src/domains/eval/reports/text.ts +14 -0
  315. package/src/domains/eval/run-compare.ts +20 -0
  316. package/src/domains/eval/runners/clio-run.ts +127 -0
  317. package/src/domains/eval/runners/external-command.ts +28 -3
  318. package/src/domains/eval/schema/adapter.ts +111 -0
  319. package/src/domains/eval/schema/artifact.ts +20 -0
  320. package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
  321. package/src/domains/eval/schema/behavioral.ts +520 -0
  322. package/src/domains/eval/schema/execution-envelope.ts +194 -0
  323. package/src/domains/eval/schema/serving.ts +105 -0
  324. package/src/domains/eval/schema/suite.ts +38 -8
  325. package/src/domains/eval/schema/validate.ts +58 -3
  326. package/src/domains/eval/schema/verdict.ts +237 -0
  327. package/src/domains/eval/suites/resolve.ts +2 -0
  328. package/src/domains/eval/suites/run.ts +264 -33
  329. package/src/domains/eval/verifiers/command.ts +2 -1
  330. package/src/domains/eval/workspaces/temp-copy.ts +145 -13
  331. package/src/domains/evidence/build.ts +2 -13
  332. package/src/domains/evidence/eval.ts +2 -12
  333. package/src/domains/evidence/findings-markdown.ts +33 -0
  334. package/src/domains/evidence/run-trust.ts +7 -113
  335. package/src/domains/evidence/store.ts +6 -0
  336. package/src/domains/evidence/trust-projection.ts +2 -2
  337. package/src/domains/extensions/compatibility.ts +285 -0
  338. package/src/domains/extensions/discovery.ts +38 -3
  339. package/src/domains/extensions/resources.ts +1 -1
  340. package/src/domains/extensions/state.ts +12 -3
  341. package/src/domains/extensions/types.ts +2 -0
  342. package/src/domains/lifecycle/doctor.ts +69 -1
  343. package/src/domains/memory/index.ts +14 -1
  344. package/src/domains/memory/task-bank-promotion.ts +64 -0
  345. package/src/domains/memory/task-memory-policy.ts +82 -17
  346. package/src/domains/memory/task-memory-spend.ts +131 -0
  347. package/src/domains/memory/task-memory-status.ts +7 -0
  348. package/src/domains/memory/task-memory-telemetry.ts +3 -0
  349. package/src/domains/middleware/index.ts +1 -0
  350. package/src/domains/middleware/memory-intervention.ts +97 -21
  351. package/src/domains/middleware/memory-step-endpoint.ts +71 -0
  352. package/src/domains/mux/contract.ts +434 -0
  353. package/src/domains/mux/detect.ts +158 -0
  354. package/src/domains/mux/extension.ts +47 -0
  355. package/src/domains/mux/index.ts +96 -0
  356. package/src/domains/mux/manifest.ts +6 -0
  357. package/src/domains/mux/operations.ts +164 -0
  358. package/src/domains/mux/pane-registry.ts +90 -0
  359. package/src/domains/mux/protocol.ts +49 -0
  360. package/src/domains/mux/socket-client.ts +816 -0
  361. package/src/domains/mux/types.ts +222 -0
  362. package/src/domains/mux/viewer-command.ts +59 -0
  363. package/src/domains/mux/yazi/assets/init.lua +2 -0
  364. package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
  365. package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
  366. package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
  367. package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
  368. package/src/domains/mux/yazi/assets/yazi.toml +17 -0
  369. package/src/domains/mux/yazi/event-stream.ts +180 -0
  370. package/src/domains/mux/yazi/profile.ts +299 -0
  371. package/src/domains/mux/yazi/session.ts +228 -0
  372. package/src/domains/mux/yazi/theme.ts +30 -0
  373. package/src/domains/observability/background-memory-usage.ts +140 -0
  374. package/src/domains/observability/cost.ts +22 -1
  375. package/src/domains/observability/index.ts +9 -0
  376. package/src/domains/observability/out-of-turn-usage.ts +51 -2
  377. package/src/domains/observability/trace-store.ts +234 -2
  378. package/src/domains/prompts/compiler.ts +100 -13
  379. package/src/domains/providers/endpoint-capacity.ts +228 -0
  380. package/src/domains/providers/endpoint-slots-store.ts +189 -0
  381. package/src/domains/providers/extension.ts +20 -3
  382. package/src/domains/providers/index.ts +32 -0
  383. package/src/domains/providers/model-runtime-capabilities.ts +32 -0
  384. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
  385. package/src/domains/providers/runtime-resolution.ts +8 -1
  386. package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
  387. package/src/domains/providers/runtimes/builtins.ts +2 -0
  388. package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
  389. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
  390. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
  391. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
  392. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
  393. package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
  394. package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
  395. package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
  396. package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
  397. package/src/domains/providers/support.ts +1 -0
  398. package/src/domains/providers/target-model-cache.ts +124 -0
  399. package/src/domains/providers/types/capability-flags.ts +2 -0
  400. package/src/domains/providers/types/target-descriptor.ts +2 -0
  401. package/src/domains/resources/index.ts +3 -0
  402. package/src/domains/resources/prompts/loader.ts +95 -33
  403. package/src/domains/resources/skills/loader.ts +33 -0
  404. package/src/domains/safety/action-classifier.ts +6 -0
  405. package/src/domains/safety/call-target.ts +52 -0
  406. package/src/domains/safety/run-effects.ts +35 -4
  407. package/src/domains/session/context-accounting.ts +52 -1
  408. package/src/domains/session/context-ledger.ts +37 -13
  409. package/src/domains/session/index.ts +6 -0
  410. package/src/domains/session/prompt-cache.ts +140 -0
  411. package/src/domains/session/prompt-manifest.ts +42 -0
  412. package/src/domains/toolchain/archive.ts +175 -0
  413. package/src/domains/toolchain/contract.ts +28 -0
  414. package/src/domains/toolchain/extension.ts +47 -0
  415. package/src/domains/toolchain/index.ts +39 -0
  416. package/src/domains/toolchain/install.ts +327 -0
  417. package/src/domains/toolchain/manifest.ts +8 -0
  418. package/src/domains/toolchain/paths.ts +34 -0
  419. package/src/domains/toolchain/registry.ts +265 -0
  420. package/src/domains/toolchain/remove.ts +218 -0
  421. package/src/domains/toolchain/resolve.ts +182 -0
  422. package/src/domains/toolchain/types.ts +113 -0
  423. package/src/domains/toolchain/version.ts +88 -0
  424. package/src/engine/acp/adapter.ts +18 -3
  425. package/src/engine/acp/server.ts +413 -70
  426. package/src/engine/acp/types.ts +19 -1
  427. package/src/engine/ai.ts +35 -0
  428. package/src/engine/apis/llamacpp-residency.ts +55 -3
  429. package/src/engine/apis/lmstudio.ts +25 -5
  430. package/src/engine/apis/ollama-native.ts +2 -1
  431. package/src/engine/apis/openai-completions.ts +80 -17
  432. package/src/engine/apis/residency-lock.ts +3 -1
  433. package/src/engine/apis/residency.ts +34 -1
  434. package/src/engine/claude/sdk-module.ts +98 -0
  435. package/src/engine/claude/sdk-runtime.ts +19 -11
  436. package/src/engine/provider-payload.ts +29 -1
  437. package/src/engine/tui-primitives.ts +21 -0
  438. package/src/engine/tui.ts +1 -0
  439. package/src/engine/worker-runtime.ts +2 -13
  440. package/src/entry/boot-options.ts +2 -0
  441. package/src/entry/orchestrator.ts +279 -35
  442. package/src/entry/panes-activation.ts +31 -0
  443. package/src/entry/with-panes.ts +20 -0
  444. package/src/interactive/chat-loop-messages.ts +26 -7
  445. package/src/interactive/chat-loop.ts +318 -41
  446. package/src/interactive/chat-panel.ts +62 -8
  447. package/src/interactive/clio-editor.ts +45 -8
  448. package/src/interactive/context-activity.ts +5 -1
  449. package/src/interactive/context-meter.ts +1 -1
  450. package/src/interactive/context-overlay.ts +41 -10
  451. package/src/interactive/cost-overlay.ts +66 -6
  452. package/src/interactive/council-grid.ts +1 -3
  453. package/src/interactive/council.ts +11 -0
  454. package/src/interactive/dispatch-board.ts +102 -20
  455. package/src/interactive/fleet-run-preview.ts +41 -15
  456. package/src/interactive/handoff-round.ts +41 -2
  457. package/src/interactive/interactive-application.ts +177 -7
  458. package/src/interactive/interactive-input-runtime.ts +15 -0
  459. package/src/interactive/interactive-presentation.ts +4 -0
  460. package/src/interactive/interactive-shell.ts +20 -17
  461. package/src/interactive/interactive-slash-runtime.ts +63 -10
  462. package/src/interactive/memory-overlay.ts +9 -0
  463. package/src/interactive/modal-marker.ts +170 -0
  464. package/src/interactive/mutation-preview.ts +295 -0
  465. package/src/interactive/mux-bridge.ts +214 -0
  466. package/src/interactive/overlay-frame.ts +58 -2
  467. package/src/interactive/overlay-general-openers.ts +17 -0
  468. package/src/interactive/overlay-key-routing.ts +52 -3
  469. package/src/interactive/overlay-lifecycle.ts +56 -7
  470. package/src/interactive/overlay-model-selectors.ts +40 -3
  471. package/src/interactive/overlay-permission-lifecycle.ts +112 -24
  472. package/src/interactive/overlay-session-lifecycle.ts +73 -9
  473. package/src/interactive/overlay-transitions.ts +18 -4
  474. package/src/interactive/overlays/agents.ts +1 -0
  475. package/src/interactive/overlays/ask-user.ts +227 -49
  476. package/src/interactive/overlays/auth-dialog.ts +1 -0
  477. package/src/interactive/overlays/context-reset.ts +1 -0
  478. package/src/interactive/overlays/cwd-fallback.ts +1 -0
  479. package/src/interactive/overlays/decisions.ts +11 -11
  480. package/src/interactive/overlays/extensions.ts +1 -0
  481. package/src/interactive/overlays/fleet-run-approval.ts +1 -0
  482. package/src/interactive/overlays/handoff-review.ts +1 -0
  483. package/src/interactive/overlays/help-reference.ts +6 -0
  484. package/src/interactive/overlays/interop.ts +1 -0
  485. package/src/interactive/overlays/library-install-confirm.ts +1 -0
  486. package/src/interactive/overlays/library-tabs.ts +28 -0
  487. package/src/interactive/overlays/list-overlay.ts +10 -1
  488. package/src/interactive/overlays/message-picker.ts +1 -0
  489. package/src/interactive/overlays/model-scope.ts +86 -0
  490. package/src/interactive/overlays/model-selector.ts +1 -0
  491. package/src/interactive/overlays/prompts.ts +12 -1
  492. package/src/interactive/overlays/session-selector.ts +1 -0
  493. package/src/interactive/overlays/settings-sections.ts +30 -0
  494. package/src/interactive/overlays/settings.ts +614 -45
  495. package/src/interactive/overlays/side-question.ts +1 -0
  496. package/src/interactive/overlays/skills-hub.ts +3 -11
  497. package/src/interactive/overlays/tree-selector.ts +1 -0
  498. package/src/interactive/pane-policy.ts +46 -0
  499. package/src/interactive/panes-runtime.ts +292 -0
  500. package/src/interactive/permission-hint.ts +34 -2
  501. package/src/interactive/permission-overlay.ts +159 -9
  502. package/src/interactive/prewarm.ts +197 -0
  503. package/src/interactive/render-trace.ts +162 -15
  504. package/src/interactive/renderers/compaction-summary.ts +29 -0
  505. package/src/interactive/renderers/tool-execution.ts +4 -0
  506. package/src/interactive/renderers/worker-entry.ts +122 -14
  507. package/src/interactive/side-question.ts +58 -1
  508. package/src/interactive/slash-commands.ts +251 -15
  509. package/src/interactive/status/controller.ts +11 -0
  510. package/src/interactive/status/state-machine.ts +54 -2
  511. package/src/interactive/status/types.ts +7 -0
  512. package/src/interactive/tasks-overlay.ts +1 -0
  513. package/src/interactive/terminal-lease.ts +2 -0
  514. package/src/interactive/theme/tokens.ts +3 -14
  515. package/src/interactive/turn-context.ts +346 -33
  516. package/src/interactive/turn-persistence.ts +14 -4
  517. package/src/interactive/turn-prewarm.ts +364 -0
  518. package/src/interactive/turn-queues.ts +7 -4
  519. package/src/interactive/turn-runtime.ts +8 -1
  520. package/src/interactive/turn-state.ts +23 -0
  521. package/src/interactive/view/artifacts.ts +109 -1
  522. package/src/interactive/view/view-overlay.ts +29 -3
  523. package/src/interactive/watch-pane.ts +152 -0
  524. package/src/interactive/worker-progress.ts +7 -1
  525. package/src/interactive/worker-receipts.ts +19 -1
  526. package/src/interactive/worker-stream.ts +5 -0
  527. package/src/interactive/yazi-bridge.ts +444 -0
  528. package/src/tools/ask-user.ts +43 -2
  529. package/src/tools/bootstrap.ts +26 -2
  530. package/src/tools/builtin-tool-catalog.ts +15 -0
  531. package/src/tools/compete-worktrees.ts +83 -2
  532. package/src/tools/core-bootstrap.ts +2 -1
  533. package/src/tools/dispatch-admission.ts +14 -3
  534. package/src/tools/dispatch-arguments.ts +20 -20
  535. package/src/tools/dispatch-plan.ts +17 -9
  536. package/src/tools/dispatch-run-events.ts +134 -19
  537. package/src/tools/dispatch-runner.ts +29 -7
  538. package/src/tools/dispatch-scout.ts +1 -1
  539. package/src/tools/dispatch-types.ts +15 -3
  540. package/src/tools/dispatch.ts +1 -1
  541. package/src/tools/executables.ts +17 -14
  542. package/src/tools/observation.ts +54 -4
  543. package/src/tools/panes-surface.ts +38 -0
  544. package/src/tools/panes.ts +112 -0
  545. package/src/tools/policy.ts +10 -1
  546. package/src/tools/presentation.ts +1 -0
  547. package/src/tools/registry.ts +16 -0
  548. package/dist/chunk-AOCYTWAV.js +0 -449
  549. package/dist/chunk-HLE42MG7.js +0 -37
  550. package/dist/chunk-HWUFFB6L.js +0 -83
  551. package/dist/chunk-JOZYP4GM.js +0 -279
  552. package/dist/doctor-M7YEDGAE.js +0 -91
@@ -21,10 +21,16 @@
21
21
  * Pure: no I/O, no module-level mutable state beyond the shared theme handle.
22
22
  */
23
23
 
24
+ import { parseJsonObjectPayload } from "../../core/json-payload.js";
24
25
  import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../../engine/tui.js";
25
26
  import { formatFooterTokens } from "../footer-panel.js";
26
27
  import { type ClioToken, clioTheme, fitUnits, formatCompactMs, GLYPH } from "../theme/index.js";
27
- import { type WorkerEntryState, type WorkerReceiptSummary, workerAskedByModel } from "../worker-stream.js";
28
+ import {
29
+ type WorkerEntryState,
30
+ type WorkerPresentedResultContract,
31
+ type WorkerReceiptSummary,
32
+ workerAskedByModel,
33
+ } from "../worker-stream.js";
28
34
 
29
35
  const theme = clioTheme();
30
36
  const dim = (text: string): string => theme.fg("dim", text);
@@ -110,7 +116,7 @@ function isPending(entry: WorkerEntryState): boolean {
110
116
  * rendered as zero: an ACP peer reports no tokens at all, so its footer names
111
117
  * the tool calls it mediated instead of claiming it spent nothing.
112
118
  */
113
- function footerUnits(receipt: WorkerReceiptSummary): string[] {
119
+ function footerUnits(entry: WorkerEntryState, receipt: WorkerReceiptSummary): string[] {
114
120
  const units = [outcomeUnit(receipt, true)];
115
121
  if (receipt.exitCode !== undefined && receipt.exitCode !== 0) {
116
122
  units.push(theme.fg("error", `exit=${receipt.exitCode}`));
@@ -122,6 +128,8 @@ function footerUnits(receipt: WorkerReceiptSummary): string[] {
122
128
  }
123
129
  if (receipt.durationMs !== undefined) units.push(dim(formatCompactMs(receipt.durationMs)));
124
130
  if (receipt.contract !== undefined) units.push(dim(`contract ${receipt.contract}`));
131
+ const presentation = presentedContractAnswer(entry);
132
+ if (presentation?.footer !== undefined) units.push(dim(presentation.footer));
125
133
  if (receipt.abandonedDetail !== undefined) units.push(theme.fg("warning", receipt.abandonedDetail));
126
134
  else if (receipt.receiptUnavailable === true) units.push(theme.fg("warning", "receipt unavailable"));
127
135
  return units;
@@ -133,23 +141,120 @@ function railLines(text: string, token: ClioToken, width: number): string[] {
133
141
  return wrapTextWithAnsi(text, contentWidth).map((row) => `${dim(RAIL)}${theme.fg(token, row)}`);
134
142
  }
135
143
 
136
- /** A worker's terminal answer when it is one JSON object, as a structured result contract asks for. */
144
+ /** A worker's terminal JSON payload, using the same tolerant reader as its result contract. */
137
145
  function structuredAnswer(text: string): Record<string, unknown> | null {
138
- const trimmed = text.trim();
139
- if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return null;
140
- try {
141
- const parsed: unknown = JSON.parse(trimmed);
142
- return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)
143
- ? (parsed as Record<string, unknown>)
144
- : null;
145
- } catch {
146
- return null;
147
- }
146
+ const parsed = parseJsonObjectPayload(text);
147
+ return parsed.ok ? parsed.value : null;
148
148
  }
149
149
 
150
150
  const isStringArray = (value: unknown): value is string[] =>
151
151
  Array.isArray(value) && value.every((entry) => typeof entry === "string");
152
152
 
153
+ function reportString(value: unknown): string | null {
154
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
155
+ }
156
+
157
+ interface PresentedContractAnswer {
158
+ lines: string[];
159
+ footer?: string;
160
+ }
161
+
162
+ function debuggerReport(value: Record<string, unknown>): PresentedContractAnswer | null {
163
+ const diagnosis = reportString(value.diagnosis);
164
+ const reproduction = value.reproduction;
165
+ if (
166
+ diagnosis === null ||
167
+ (reproduction !== "reproduced" && reproduction !== "not-reproduced" && reproduction !== "unknown") ||
168
+ !isStringArray(value.evidence)
169
+ ) {
170
+ return null;
171
+ }
172
+ return {
173
+ lines: [
174
+ diagnosis,
175
+ ...(value.evidence.length === 0 ? ["Evidence: none"] : ["Evidence:", ...value.evidence.map((item) => `- ${item}`)]),
176
+ ],
177
+ footer: `reproduction ${reproduction}`,
178
+ };
179
+ }
180
+
181
+ function verifierReport(value: Record<string, unknown>): PresentedContractAnswer | null {
182
+ if ((value.verdict !== "pass" && value.verdict !== "fail") || !Array.isArray(value.checks)) return null;
183
+ const lines: string[] = [];
184
+ for (const raw of value.checks) {
185
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
186
+ const check = raw as Record<string, unknown>;
187
+ const name = reportString(check.name);
188
+ const evidence = reportString(check.evidence);
189
+ if (name === null || evidence === null || typeof check.passed !== "boolean") return null;
190
+ lines.push(`${check.passed ? GLYPH.ok : GLYPH.error} ${name}: ${evidence}`);
191
+ }
192
+ return { lines: lines.length === 0 ? ["No checks reported."] : lines, footer: `verdict ${value.verdict}` };
193
+ }
194
+
195
+ function researchReport(value: Record<string, unknown>): PresentedContractAnswer | null {
196
+ if ((value.source !== "local" && value.source !== "external") || !Array.isArray(value.findings)) return null;
197
+ const lines: string[] = [];
198
+ for (const raw of value.findings) {
199
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
200
+ const finding = raw as Record<string, unknown>;
201
+ const claim = reportString(finding.claim);
202
+ const evidence = reportString(finding.evidence);
203
+ if (claim === null || evidence === null) return null;
204
+ lines.push(`- ${claim}`, ` citation: ${evidence}`);
205
+ }
206
+ return { lines: lines.length === 0 ? ["No findings reported."] : lines, footer: `source ${value.source}` };
207
+ }
208
+
209
+ function scoutReport(value: Record<string, unknown>): PresentedContractAnswer | null {
210
+ if (!Array.isArray(value.findings) || typeof value.needsSplit !== "boolean") return null;
211
+ const lines: string[] = [];
212
+ for (const raw of value.findings) {
213
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
214
+ const finding = raw as Record<string, unknown>;
215
+ const claim = reportString(finding.claim);
216
+ if (claim === null) return null;
217
+ const path = reportString(finding.path);
218
+ const line = typeof finding.line === "number" && Number.isSafeInteger(finding.line) ? finding.line : null;
219
+ lines.push(path !== null && line !== null ? `- ${claim} — ${path}:${line}` : `- ${claim} (ungrounded lead)`);
220
+ }
221
+ if (value.needsSplit) {
222
+ if (!Array.isArray(value.proposedSubtasks)) return null;
223
+ lines.push("Split recommended:");
224
+ for (const raw of value.proposedSubtasks) {
225
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
226
+ const subtask = raw as Record<string, unknown>;
227
+ const task = reportString(subtask.task);
228
+ const id = reportString(subtask.id);
229
+ if (task === null || id === null) return null;
230
+ lines.push(`- ${id}: ${task}`);
231
+ }
232
+ }
233
+ return {
234
+ lines: lines.length === 0 ? ["No findings reported."] : lines,
235
+ footer: value.needsSplit ? "split needed" : "no split needed",
236
+ };
237
+ }
238
+
239
+ function presentedContractAnswer(entry: WorkerEntryState): PresentedContractAnswer | null {
240
+ if (entry.receipt?.contract !== "pass" || entry.receipt.contractKind === undefined || entry.droppedLines !== 0) {
241
+ return null;
242
+ }
243
+ const value = structuredAnswer(entry.text);
244
+ if (value === null) return null;
245
+ const kind: WorkerPresentedResultContract = entry.receipt.contractKind;
246
+ switch (kind) {
247
+ case "debugger-report":
248
+ return debuggerReport(value);
249
+ case "verifier-report":
250
+ return verifierReport(value);
251
+ case "research-report":
252
+ return researchReport(value);
253
+ case "scout-report":
254
+ return scoutReport(value);
255
+ }
256
+ }
257
+
153
258
  /**
154
259
  * A mutation report as prose: the paths it changed, each validation with its
155
260
  * verdict and evidence, then the summary and commit line. Null when the object
@@ -184,6 +289,8 @@ function mutationReportLines(value: Record<string, unknown>): string[] | null {
184
289
  function bodySourceLines(entry: WorkerEntryState): string[] {
185
290
  const structured = entry.droppedLines === 0 ? structuredAnswer(entry.text) : null;
186
291
  if (structured === null) return entry.text.split("\n");
292
+ const presented = presentedContractAnswer(entry);
293
+ if (presented !== null) return presented.lines;
187
294
  return mutationReportLines(structured) ?? JSON.stringify(structured, null, 2).split("\n");
188
295
  }
189
296
 
@@ -236,7 +343,8 @@ function failureLines(entry: WorkerEntryState, width: number): string[] {
236
343
 
237
344
  /** The receipt line, whole units only; a unit that would not fit is dropped behind a dim ellipsis. */
238
345
  function footerLine(entry: WorkerEntryState, width: number): string {
239
- const units = isPending(entry) || entry.receipt === undefined ? [pendingUnit(entry)] : footerUnits(entry.receipt);
346
+ const units =
347
+ isPending(entry) || entry.receipt === undefined ? [pendingUnit(entry)] : footerUnits(entry, entry.receipt);
240
348
  return fitUnits(theme, dim(FOOTER), units, width);
241
349
  }
242
350
 
@@ -13,7 +13,13 @@
13
13
  * machine without adding an engine seam of its own. Tools are never sent.
14
14
  */
15
15
 
16
+ import {
17
+ isResponseSchemaRejection,
18
+ type ResponseSchemaDialect,
19
+ responseSchemaDialectFor,
20
+ } from "../core/response-schema.js";
16
21
  import { stream } from "../engine/ai.js";
22
+ import { patchResponseSchemaPayloadForDialect } from "../engine/provider-payload.js";
17
23
  import type { AgentMessage, EngineModel, Usage } from "../engine/types.js";
18
24
 
19
25
  /**
@@ -67,6 +73,18 @@ export interface OutOfTurnRoundInput extends Omit<SideQuestionInput, "question">
67
73
  systemPrompt: string;
68
74
  /** The one message appended to the read-only copy of the history. */
69
75
  userText: string;
76
+ /**
77
+ * Bind the answer to a JSON schema on the wire, where the runtime takes one.
78
+ *
79
+ * A round that asked for a schema in prose and bound nothing is what made
80
+ * `/handoff` refuse on local targets: the model answered with prose around
81
+ * the object, or with no object at all, and the parser had nothing to work
82
+ * with (issue #223). Absent, or on a runtime with no dialect, the request
83
+ * goes out exactly as before and the prompt-level instruction carries it.
84
+ */
85
+ responseSchema?: { name: string; schema: Record<string, unknown> };
86
+ /** Resolved runtime id, which is what decides the wire dialect. */
87
+ runtimeId?: string;
70
88
  }
71
89
 
72
90
  export interface SideQuestionResult {
@@ -80,7 +98,12 @@ function positive(value: unknown): number {
80
98
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
81
99
  }
82
100
 
83
- function sideQuestionUsage(raw: unknown): SideQuestionUsage | null {
101
+ /**
102
+ * Normalize one provider usage object into the shape `/cost` and the
103
+ * out-of-turn usage store take. Shared with the session pre-warm, which is
104
+ * another call billed beside the session rather than inside it.
105
+ */
106
+ export function sideQuestionUsage(raw: unknown): SideQuestionUsage | null {
84
107
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
85
108
  const usage = raw as Partial<Usage> & { reasoning?: number };
86
109
  const input = positive(usage.input);
@@ -128,11 +151,45 @@ export async function runSideQuestion(input: SideQuestionInput): Promise<SideQue
128
151
  return runOutOfTurnRound({ ...rest, systemPrompt: SIDE_QUESTION_SYSTEM_PROMPT, userText: question });
129
152
  }
130
153
 
154
+ interface SchemaBinding {
155
+ dialect: ResponseSchemaDialect;
156
+ name: string;
157
+ schema: Record<string, unknown>;
158
+ }
159
+
160
+ /** The schema binding for this round, or null when nothing can be bound on the wire. */
161
+ function schemaBindingFor(input: OutOfTurnRoundInput): SchemaBinding | null {
162
+ if (input.responseSchema === undefined || input.runtimeId === undefined) return null;
163
+ const dialect = responseSchemaDialectFor(input.runtimeId);
164
+ return dialect === null ? null : { dialect, ...input.responseSchema };
165
+ }
166
+
131
167
  /** The shared round. See {@link OutOfTurnRoundInput}. */
132
168
  export async function runOutOfTurnRound(input: OutOfTurnRoundInput): Promise<SideQuestionResult> {
169
+ const binding = schemaBindingFor(input);
170
+ if (binding === null) return runRound(input, null);
171
+ try {
172
+ return await runRound(input, binding);
173
+ } catch (error) {
174
+ // Native enforcement is an optimization here, never a precondition. A
175
+ // server that refuses the constrained request answers with the same 400
176
+ // the worker seam already recognizes, and the round is worth more
177
+ // unconstrained than not at all. Anything else is a real failure and
178
+ // rejects, so a broken target still costs exactly one round.
179
+ if (input.signal?.aborted === true) throw error;
180
+ if (!isResponseSchemaRejection(error instanceof Error ? error.message : String(error))) throw error;
181
+ return runRound(input, null);
182
+ }
183
+ }
184
+
185
+ async function runRound(input: OutOfTurnRoundInput, binding: SchemaBinding | null): Promise<SideQuestionResult> {
133
186
  const options: Record<string, unknown> = { maxTokens: input.maxTokens ?? SIDE_QUESTION_MAX_TOKENS };
134
187
  if (input.apiKey !== undefined) options.apiKey = input.apiKey;
135
188
  if (input.signal !== undefined) options.signal = input.signal;
189
+ if (binding !== null) {
190
+ options.onPayload = (payload: unknown): unknown | undefined =>
191
+ patchResponseSchemaPayloadForDialect(payload, binding.dialect, binding.schema, binding.name);
192
+ }
136
193
 
137
194
  const context = {
138
195
  systemPrompt: input.systemPrompt,
@@ -4,6 +4,7 @@ import type { SafeEventBus } from "../core/event-bus.js";
4
4
  import { parseCouncilReport, parseOracleResult } from "../domains/agents/index.js";
5
5
  import type { AgentSpec } from "../domains/agents/spec.js";
6
6
  import type { ContextInitOptions } from "../domains/context/init-options.js";
7
+ import { AdmissionCanceledError } from "../domains/dispatch/admission-error.js";
7
8
  import type { DispatchContract, DispatchRequest } from "../domains/dispatch/contract.js";
8
9
  import { type AgentRoleFactsResolver, requestExecutionRole } from "../domains/dispatch/execution-role.js";
9
10
  import type { RunReceipt } from "../domains/dispatch/types.js";
@@ -11,6 +12,14 @@ import type { JobThinkingLevel } from "../domains/dispatch/validation.js";
11
12
  import type { ReceiptIntegrityOutcome } from "../domains/evidence/trust-status.js";
12
13
  import type { InstalledExtension } from "../domains/extensions/index.js";
13
14
  import type { InteropAgentId, InteropProposal, InteropReport } from "../domains/interop/index.js";
15
+ import {
16
+ isPanesPresetId,
17
+ PANES_PRESET_IDS,
18
+ PANES_PRESETS,
19
+ type PanesOperations,
20
+ type PanesPresetId,
21
+ type PanesStatus,
22
+ } from "../domains/mux/operations.js";
14
23
  import type { ProvidersContract, ResolvedModelRef } from "../domains/providers/index.js";
15
24
  import { resolveModelReference } from "../domains/providers/index.js";
16
25
  import type {
@@ -27,13 +36,13 @@ import type { NoticeLevel } from "./command-output.js";
27
36
  import {
28
37
  buildCouncilDispatchArgs,
29
38
  COUNCIL_MAX_ROUNDS,
39
+ COUNCIL_SYNTHESIS_LABEL,
30
40
  COUNCIL_SYNTHESIS_MODES,
31
41
  type CouncilCommandOptions,
32
42
  type CouncilRosters,
33
43
  isCouncilSynthesisMode,
34
44
  resolveCouncilRoster,
35
45
  } from "./council.js";
36
- import { COUNCIL_SYNTHESIS_LABEL } from "./council-grid.js";
37
46
  import {
38
47
  formatOracleAnswer,
39
48
  ORACLE_AGENT_ID,
@@ -41,8 +50,9 @@ import {
41
50
  type OracleDigestSources,
42
51
  packOracleDigest,
43
52
  } from "./oracle.js";
44
- import { SETTINGS_SECTIONS, type SettingsCenterRowId, type SettingsSectionId } from "./overlays/settings.js";
45
- import { isLibraryTab, LIBRARY_TABS } from "./overlays/skills-hub.js";
53
+ import { isLibraryTab, LIBRARY_TABS } from "./overlays/library-tabs.js";
54
+ import type { SettingsCenterRowId } from "./overlays/settings.js";
55
+ import { SETTINGS_SECTIONS, type SettingsSectionId } from "./overlays/settings-sections.js";
46
56
  import type { CommandArgsSpec, CommandPositionalSpec, ParsedArgs } from "./slash-spec.js";
47
57
  import { matchFromSpec, usageLine } from "./slash-spec.js";
48
58
  import {
@@ -60,6 +70,25 @@ import type { WorkerEntryState } from "./worker-stream.js";
60
70
  * one user-facing slash command: how it parses, which SlashCommand kinds it
61
71
  * produces, and how those kinds execute. Adding a new command is one entry
62
72
  * rather than extending two parallel switches.
73
+ *
74
+ * This module is a CLI seam, which constrains what it may import.
75
+ * `src/cli/run.ts` reaches `parseSlashCommand` here so a headless
76
+ * `clio-coder run "/typo"` refuses the token by the same shape test and the same
77
+ * registry membership the editor uses; a second copy of the parser would drift
78
+ * from this one on the first command added. That makes the CLI a reacher of
79
+ * everything this file statically imports, so nothing here may reach the
80
+ * interactive render graph: no theme, no overlay frame, no overlay module, no
81
+ * `../engine/tui.js`. Those modules share one bundle chunk with the instant
82
+ * shell's Stage 0 closure, and a second, disjoint reacher makes esbuild split
83
+ * it, which is a startup-latency regression rather than a style problem. The
84
+ * parse-time data tables the registry needs live in leaves for that reason:
85
+ * `./overlays/settings-sections.js`, `./overlays/library-tabs.js`, and
86
+ * `COUNCIL_SYNTHESIS_LABEL` in `./council.js`. Import from those, not from the
87
+ * overlays that re-export them.
88
+ *
89
+ * Boundaries rule6 in `tests/boundaries/check-boundaries.ts` refuses a violation
90
+ * at lint time; `tests/contracts/instant-shell-import-graph.test.ts` is the
91
+ * measurement it protects.
63
92
  */
64
93
 
65
94
  type ShareCommandVariant =
@@ -116,6 +145,13 @@ type SlashCommandVariant =
116
145
  | { kind: "view"; filter?: string }
117
146
  | { kind: "view-verify"; runId: string }
118
147
  | { kind: "view-usage" }
148
+ /** `/panes`: mode, health, pane inventory, effective settings. */
149
+ | { kind: "panes" }
150
+ | { kind: "panes-show"; target: string }
151
+ /** A preset the model may also ask for, or operator-only argv. Never both. */
152
+ | { kind: "panes-open"; preset?: PanesPresetId; argv?: ReadonlyArray<string>; once?: boolean }
153
+ | { kind: "panes-close"; target: string }
154
+ | { kind: "panes-usage"; reason?: string }
119
155
  | { kind: "thinking-set"; level: string }
120
156
  | { kind: "output-set"; verbosity: string }
121
157
  | { kind: "model" }
@@ -258,14 +294,20 @@ async function runAttributed(
258
294
  progressBus?.emit(BusChannels.DispatchProgress, { runId: handle.runId, agentId: request.agentId, event });
259
295
  }
260
296
  const receipt = await handle.finalPromise;
261
- if (receipt.exitCode !== 0 || receipt.failureMessage) {
297
+ if (receipt.outcome === "canceled") {
298
+ notice("warn", `${command} aborted: ${receipt.outcomeDetail ?? "operator abort"}`);
299
+ } else if (receipt.exitCode !== 0 || receipt.failureMessage) {
262
300
  const failure = receipt.failureMessage ? ` ${receipt.failureMessage}` : "";
263
301
  notice("error", `${command} failed: exit=${receipt.exitCode}${failure}`);
264
302
  }
265
303
  if (share) shareReceipt(request.agentId, receipt, deps);
266
304
  } catch (err) {
267
305
  const msg = err instanceof Error ? err.message : String(err);
268
- notice("error", `${command} failed: ${msg}`);
306
+ if (err instanceof AdmissionCanceledError) {
307
+ notice("warn", `${command} aborted: ${msg.replace(/^dispatch:\s*/u, "")}`);
308
+ } else {
309
+ notice("error", `${command} failed: ${msg}`);
310
+ }
269
311
  }
270
312
  }
271
313
 
@@ -629,6 +671,14 @@ export interface SlashCommandContext {
629
671
  seedTaskMemory?: () => TaskMemorySeedCommandResult;
630
672
  /** Open `/view`, the full observability artifact viewer. */
631
673
  openView: (filter?: string) => void;
674
+ /**
675
+ * The pane layer's operator surface. It remains present when mux resolves to
676
+ * `none` because the Yazi preset can borrow the terminal for one selection;
677
+ * absent only when the host did not compose pane operations at all.
678
+ */
679
+ panes?: PanesOperations;
680
+ /** Serialize a local async command so the next admitted slash command observes its committed state. */
681
+ runLocalOperation?: (operation: () => Promise<void>) => void;
632
682
  /**
633
683
  * Apply a thinking level named on the command line. Returns why it was
634
684
  * refused so the caller can say so, because the level the operator typed may
@@ -640,8 +690,12 @@ export interface SlashCommandContext {
640
690
  openModel: () => void;
641
691
  /** Live providers contract used by `/model <pattern>` to resolve directly. */
642
692
  providers: ProvidersContract;
643
- /** Apply a resolved model reference to settings (and optionally thinking level). */
644
- applyModelRef: (ref: ResolvedModelRef) => void;
693
+ /**
694
+ * Apply a resolved model reference, or hand it to the scope dialog. "pending"
695
+ * means the operator has yet to choose session or global and nothing has
696
+ * changed; the dialog reports the outcome itself.
697
+ */
698
+ applyModelRef: (ref: ResolvedModelRef) => "applied" | "pending";
645
699
  openSettings: (section?: SettingsSectionId, rowId?: SettingsCenterRowId) => void;
646
700
  openResume: () => void;
647
701
  startNewSession: () => void;
@@ -662,10 +716,16 @@ export interface SlashCommandContext {
662
716
  runCompact: (instructions: string | undefined) => void;
663
717
  /**
664
718
  * Escape hatch for the `view verify` entry: verify a receipt file on disk
665
- * and emit a single status line. Kept on the context so the registry does
719
+ * and emit an actionable verification block. Kept on the context so the registry does
666
720
  * not import the overlay module.
667
721
  */
668
- verifyReceipt: (runId: string) => ReceiptIntegrityOutcome;
722
+ verifyReceipt: (runId: string) => ReceiptIntegrityOutcome & {
723
+ receiptPath?: string;
724
+ sealedDigest?: string | null;
725
+ trustSummary?: string | null;
726
+ compromised?: boolean;
727
+ checks?: ReadonlyArray<{ name: string; ok: boolean; evidence: string }>;
728
+ };
669
729
  /**
670
730
  * Handles the "unknown" case: append the text to the chat panel as a user
671
731
  * turn, submit to the chat loop, and schedule a re-render. Handlers for
@@ -677,6 +737,24 @@ export interface SlashCommandContext {
677
737
  render: () => void;
678
738
  }
679
739
 
740
+ type SlashReceiptVerification = ReturnType<SlashCommandContext["verifyReceipt"]>;
741
+
742
+ /** Compact multiline receipt verification for the composer notice surface. */
743
+ export function formatReceiptVerificationBlock(runId: string, result: SlashReceiptVerification): string {
744
+ const status = result.ok ? (result.compromised ? "compromised" : "ok") : result.retired ? "retired" : "fail";
745
+ const lines = [
746
+ `verify ${status} ${runId}`,
747
+ `receipt ${result.receiptPath ?? "unavailable"}`,
748
+ `digest ${result.sealedDigest ?? "unavailable"}`,
749
+ `evidence ${result.trustSummary ?? (!result.ok ? result.reason : "trust status unavailable")}`,
750
+ ];
751
+ if (result.checks && result.checks.length > 0) {
752
+ lines.push("checks");
753
+ for (const check of result.checks) lines.push(` ${check.ok ? "✓" : "✗"} ${check.name}: ${check.evidence}`);
754
+ }
755
+ return lines.join("\n");
756
+ }
757
+
680
758
  /** The one operator-authored turn used by slash and overlay handoff paths. */
681
759
  export function formatUserTaskHandoff(task: Pick<UserTask, "id" | "title" | "note">): string {
682
760
  const note = task.note ? ` ${task.note}.` : "";
@@ -765,6 +843,35 @@ function usageNotice(entry: BuiltinSlashCommand, subcommand?: string): string {
765
843
  return usageLine(entry, subcommand).trim();
766
844
  }
767
845
 
846
+ /**
847
+ * `/panes` output, as plain lines. Pure so the contract test asserts the text
848
+ * an operator reads rather than the object behind it, and so the registry keeps
849
+ * its promise not to reach a renderer.
850
+ */
851
+ export function formatPanesStatus(status: PanesStatus): ReadonlyArray<string> {
852
+ const server = status.server ? `pane host ${status.server.version}, protocol ${status.server.protocol}` : "no server";
853
+ const lines = [
854
+ `panes: mode=${status.mode} ${status.available ? "available" : "unavailable"} (${server})`,
855
+ ` ${status.reason}`,
856
+ ...(status.socketPath ? [` socket ${status.socketPath}`] : []),
857
+ ` settings: enabled=${status.settings.enabled} notifications=${status.settings.notifications} journal=${status.settings.journal}`,
858
+ ` files: enabled=${status.settings.yazi.enabled} mode=${status.settings.yazi.mode} profile=${status.settings.yazi.profile} followCwd=${status.settings.yazi.followCwd}`,
859
+ ` file pane: mode=${status.yazi.mode} pane=${status.yazi.paneId ?? "none"} cwd=${status.yazi.paneCwd ?? "unknown"} lastLine=${status.yazi.lastLineAt === null ? "never" : new Date(status.yazi.lastLineAt).toISOString()} dropped=${status.yazi.droppedLines}`,
860
+ ];
861
+ if (status.panes.length === 0) {
862
+ lines.push(" no Clio-owned panes");
863
+ } else {
864
+ lines.push(` ${status.panes.length} Clio-owned pane(s):`);
865
+ for (const pane of status.panes) {
866
+ const adopted = pane.adopted ? " adopted" : "";
867
+ const pending = pane.pending ? " opening" : "";
868
+ lines.push(` ${pane.paneId} ${pane.purpose} ${pane.label}${adopted}${pending}`);
869
+ }
870
+ }
871
+ lines.push(` presets: ${PANES_PRESETS.map((preset) => `${preset.id} (${preset.summary})`).join(", ")}`);
872
+ return lines;
873
+ }
874
+
768
875
  export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
769
876
  {
770
877
  name: "quit",
@@ -1505,16 +1612,141 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
1505
1612
  }
1506
1613
  if (command.kind !== "view-verify") return;
1507
1614
  const result = ctx.verifyReceipt(command.runId);
1615
+ const block = formatReceiptVerificationBlock(command.runId, result);
1508
1616
  if (result.ok) {
1509
- ctx.notice("success", `verify ok ${command.runId}`);
1617
+ ctx.notice(result.compromised ? "warn" : "success", block);
1510
1618
  } else if (result.retired !== undefined) {
1511
1619
  // A retired seal is the expected state of a run from the previous
1512
1620
  // release, so it is a warning that names the versions, never the
1513
1621
  // failure a tampered receipt gets.
1514
- ctx.notice("warn", `verify retired ${command.runId} ${result.reason}`);
1622
+ ctx.notice("warn", block);
1515
1623
  } else {
1516
- ctx.notice("error", `verify fail ${command.runId} ${result.reason}`);
1624
+ ctx.notice("error", block);
1625
+ }
1626
+ },
1627
+ },
1628
+ {
1629
+ name: "panes",
1630
+ description: "Inspect the pane layer, watch a live run in a pane, or open a utility pane",
1631
+ group: "Inspect",
1632
+ kinds: ["panes", "panes-show", "panes-open", "panes-close", "panes-usage"],
1633
+ args: {
1634
+ subcommands: {
1635
+ show: { positionals: [{ name: "run-or-agent", required: true }] },
1636
+ // A rest positional, so an argv pane keeps its own flags: the parser
1637
+ // would otherwise refuse `--follow` as an unknown flag of `/panes`.
1638
+ open: { positionals: [{ name: "preset-or-argv", required: true, rest: true }] },
1639
+ close: { positionals: [{ name: "target", required: false }] },
1640
+ },
1641
+ },
1642
+ subcommandDescriptions: {
1643
+ show: "watch a live run or agent in the watch pane",
1644
+ open: `open a utility pane (${PANES_PRESET_IDS.join(", ")}, or a command)`,
1645
+ close: "close a Clio-owned pane, or all of them",
1646
+ },
1647
+ fromArgs(parsed) {
1648
+ if (parsed.error) return { kind: "panes-usage", reason: parsed.error };
1649
+ if (parsed.subcommand === "show") {
1650
+ return { kind: "panes-show", target: parsed.positionals[0] ?? "" };
1651
+ }
1652
+ if (parsed.subcommand === "open") {
1653
+ const rest = (parsed.rest ?? "").trim();
1654
+ if (rest.length === 0) return { kind: "panes-usage", reason: "Missing required argument: preset-or-argv" };
1655
+ const argv = rest.split(/\s+/).filter((token) => token.length > 0);
1656
+ const first = argv[0] ?? "";
1657
+ // A bare preset name is a preset; anything else is operator argv,
1658
+ // which the tool surface deliberately cannot ask for.
1659
+ if (argv.length === 1 && isPanesPresetId(first)) return { kind: "panes-open", preset: first };
1660
+ if (argv.length === 2 && first === "yazi" && argv[1] === "--once") {
1661
+ return { kind: "panes-open", preset: "yazi", once: true };
1662
+ }
1663
+ return { kind: "panes-open", argv };
1664
+ }
1665
+ if (parsed.subcommand === "close") {
1666
+ return { kind: "panes-close", target: parsed.positionals[0] ?? "all" };
1667
+ }
1668
+ if (parsed.positionals.length > 0) {
1669
+ return { kind: "panes-usage", reason: `Unexpected argument: ${parsed.positionals[0]}` };
1670
+ }
1671
+ return { kind: "panes" };
1672
+ },
1673
+ handle(command, ctx) {
1674
+ const entry = BUILTIN_SLASH_COMMANDS.find((candidate) => candidate.name === "panes");
1675
+ if (command.kind === "panes-usage") {
1676
+ // usageNotice trims the leading newline usageLine carries, so the reason
1677
+ // and the usage line need their own separator or they run together as
1678
+ // `Missing required argument: run-or-agentusage: /panes show ...`.
1679
+ if (entry) ctx.notice("info", command.reason ? `${command.reason}\n${usageNotice(entry)}` : usageNotice(entry));
1680
+ return;
1681
+ }
1682
+ const panes = ctx.panes;
1683
+ if (!panes) {
1684
+ // Inactive by choice, not unavailable: the operations object exists in
1685
+ // every `--with-panes` session, even one where no pane host answered.
1686
+ ctx.notice(
1687
+ "info",
1688
+ "panes are inactive: this session started without them. Restart with `clio-coder --with-panes`, or set panes.enabled=auto",
1689
+ );
1690
+ return;
1691
+ }
1692
+ const runLocal = ctx.runLocalOperation ?? ((operation: () => Promise<void>) => void operation());
1693
+ if (command.kind === "panes") {
1694
+ runLocal(async () => {
1695
+ for (const line of formatPanesStatus(panes.status())) ctx.io.stdout(`${line}\n`);
1696
+ ctx.render();
1697
+ });
1698
+ return;
1699
+ }
1700
+ if (command.kind === "panes-show") {
1701
+ runLocal(async () => {
1702
+ const result = await panes.show(command.target);
1703
+ if (result.status === "watching") {
1704
+ ctx.notice("success", `watching ${result.agentId} (${result.runId})${result.opened ? " in a new pane" : ""}`);
1705
+ } else if (result.status === "not-found") {
1706
+ const known = result.candidates.length > 0 ? `; live runs: ${result.candidates.join(", ")}` : "";
1707
+ ctx.notice("warn", `no live run matches ${result.target}${known}`);
1708
+ } else {
1709
+ ctx.notice("warn", result.reason);
1710
+ }
1711
+ });
1712
+ return;
1517
1713
  }
1714
+ if (command.kind === "panes-open") {
1715
+ runLocal(async () => {
1716
+ const result = await panes.open({
1717
+ ...(command.preset ? { preset: command.preset } : {}),
1718
+ ...(command.argv ? { argv: command.argv } : {}),
1719
+ ...(command.once ? { once: true } : {}),
1720
+ });
1721
+ if (result.status === "opened") {
1722
+ // The in-terminal chooser has already restored the TUI by the
1723
+ // time this resolves. A pick emitted its composer notice; an empty
1724
+ // chooser was cancellation and deliberately stays silent.
1725
+ if (result.paneId !== null) ctx.notice("success", `opened pane ${result.label} (${result.paneId})`);
1726
+ } else if (result.status === "missing-binary") {
1727
+ // This is a synchronous slash-surface line, not a transient pane-host
1728
+ // notification. It remains visible when no pane was ever created and
1729
+ // reuses the exact doctor/tools diagnostic including the install hint.
1730
+ ctx.io.stdout(`${result.detail}\n`);
1731
+ ctx.render();
1732
+ } else {
1733
+ ctx.notice("warn", result.reason);
1734
+ }
1735
+ });
1736
+ return;
1737
+ }
1738
+ if (command.kind !== "panes-close") return;
1739
+ runLocal(async () => {
1740
+ const result = await panes.close(command.target);
1741
+ if (result.status === "closed") {
1742
+ const what = result.labels.length > 0 ? `: ${result.labels.join(", ")}` : "";
1743
+ ctx.notice(result.closed > 0 ? "success" : "info", `closed ${result.closed} pane(s)${what}`);
1744
+ } else if (result.status === "not-found") {
1745
+ ctx.notice("warn", `no Clio-owned pane matches ${result.target}`);
1746
+ } else {
1747
+ ctx.notice("warn", result.reason);
1748
+ }
1749
+ });
1518
1750
  },
1519
1751
  },
1520
1752
  {
@@ -1604,9 +1836,13 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
1604
1836
  return;
1605
1837
  }
1606
1838
  if (result.warning) ctx.notice("warn", result.warning);
1607
- ctx.applyModelRef(result.ref);
1608
- const suffix = result.ref.thinkingLevel ? ` thinking=${result.ref.thinkingLevel}` : "";
1609
- ctx.notice("success", `active: ${result.ref.target}/${result.ref.model}${suffix}`);
1839
+ // "pending" means the scope dialog is up: it says what landed and
1840
+ // where, so announcing a swap here would be announcing a choice the
1841
+ // operator has not made yet.
1842
+ if (ctx.applyModelRef(result.ref) === "applied") {
1843
+ const suffix = result.ref.thinkingLevel ? ` thinking=${result.ref.thinkingLevel}` : "";
1844
+ ctx.notice("success", `active this session: ${result.ref.target}/${result.ref.model}${suffix}`);
1845
+ }
1610
1846
  ctx.render();
1611
1847
  })();
1612
1848
  },