@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
@@ -0,0 +1,197 @@
1
+ /**
2
+ * The session pre-warm round: the request the next turn would send, minus the
3
+ * operator's text, issued as soon as the prefix is known.
4
+ *
5
+ * On a local server prefill is the cost. A fresh session's first turn prefills
6
+ * the whole compiled prompt plus the tool schemas before the model emits a
7
+ * token, and a resumed session's first turn prefills the entire replayed
8
+ * history. Both are paid after the operator presses Enter, and both are fully
9
+ * determined before they type anything. llama.cpp picks the slot with the
10
+ * longest common prefix and re-evaluates only the suffix, so sending the prefix
11
+ * early leaves the processed KV in the slot for the real turn to land on.
12
+ *
13
+ * The payload is not hand-assembled. It goes through `streamSimple`, the same
14
+ * dispatcher `createEngineAgent` hands pi-agent-core as its `streamFn`, with the
15
+ * same system prompt, the same tool schemas, the same replayed messages, and the
16
+ * same thinking level, so `withSamplingOverrides`, the thinking composition, and
17
+ * `cache_prompt` resolve exactly as they do for a turn. Any byte that differs
18
+ * ahead of the user turn would defeat the purpose.
19
+ */
20
+
21
+ import type { BackendCompletionTimings } from "../core/cache-telemetry.js";
22
+ import { streamSimple } from "../engine/ai.js";
23
+ import type { AgentMessage, AgentTool, EngineModel, Usage } from "../engine/types.js";
24
+
25
+ /**
26
+ * The one user message appended so the chat template renders the prefix up to
27
+ * the user turn. One character: it has to exist for the template to close the
28
+ * prefix, and everything after the last shared byte is re-evaluated by the real
29
+ * turn anyway.
30
+ */
31
+ export const PREWARM_USER_TEXT = ".";
32
+
33
+ /** Output budget for the round. The tokens the model produces are not the point. */
34
+ export const PREWARM_MAX_TOKENS = 1;
35
+
36
+ /** Which trigger asked for the pre-warm. Recorded on the ledger entry. */
37
+ export type PrewarmTrigger = "session-start" | "resume" | "compaction";
38
+
39
+ export interface PrewarmContext {
40
+ systemPrompt: string;
41
+ messages: ReadonlyArray<AgentMessage>;
42
+ tools: ReadonlyArray<AgentTool>;
43
+ }
44
+
45
+ /**
46
+ * The roles pi-agent-core's default `convertToLlm` keeps when it turns the
47
+ * agent's message list into provider messages. The pre-warm applies the same
48
+ * filter so its message array is the one a turn would send, not the agent's
49
+ * internal list.
50
+ */
51
+ const LLM_MESSAGE_ROLES: ReadonlySet<string> = new Set(["user", "assistant", "toolResult"]);
52
+
53
+ /**
54
+ * The prefix of the next turn's request: system prompt, tool schemas, and the
55
+ * replayed conversation, with no user turn yet.
56
+ */
57
+ function prewarmPrefix(state: {
58
+ systemPrompt: string;
59
+ messages: ReadonlyArray<AgentMessage>;
60
+ tools: ReadonlyArray<AgentTool>;
61
+ }): PrewarmContext {
62
+ return {
63
+ systemPrompt: state.systemPrompt,
64
+ messages: state.messages.filter((message) => LLM_MESSAGE_ROLES.has((message as { role?: string }).role ?? "")),
65
+ tools: [...state.tools],
66
+ };
67
+ }
68
+
69
+ export interface PrewarmRoundInput {
70
+ model: EngineModel;
71
+ /** Live agent state the next turn would send. Read-only; the round copies it. */
72
+ state: {
73
+ systemPrompt: string;
74
+ messages: ReadonlyArray<AgentMessage>;
75
+ tools: ReadonlyArray<AgentTool>;
76
+ thinkingLevel: string;
77
+ };
78
+ apiKey?: string;
79
+ signal?: AbortSignal;
80
+ /** Test seam. Production uses the engine dispatcher a turn runs on. */
81
+ streamFn?: typeof streamSimple;
82
+ }
83
+
84
+ export interface PrewarmRoundResult {
85
+ /** True when the operator submitted (or the session moved) before the round settled. */
86
+ aborted: boolean;
87
+ /** Provider usage for the round; null when the backend reported none. */
88
+ usage: Usage | null;
89
+ /** Backend prefill and prediction timings when the server reported them. */
90
+ backend: BackendCompletionTimings | null;
91
+ /** Wall clock the round spent, in the shape a turn's assistant entry uses. */
92
+ timing: { ttftMs: number | null; apiMs: number };
93
+ /** Provider error text when the round failed outright. */
94
+ errorMessage: string | null;
95
+ }
96
+
97
+ function usageOf(message: unknown): Usage | null {
98
+ if (message === null || typeof message !== "object") return null;
99
+ const usage = (message as { usage?: unknown }).usage;
100
+ return usage !== null && typeof usage === "object" ? (usage as Usage) : null;
101
+ }
102
+
103
+ function backendOf(message: unknown): BackendCompletionTimings | null {
104
+ if (message === null || typeof message !== "object") return null;
105
+ const backend = (message as { backendTimings?: unknown }).backendTimings;
106
+ return backend !== null && typeof backend === "object" ? (backend as BackendCompletionTimings) : null;
107
+ }
108
+
109
+ /**
110
+ * Prompt tokens the backend actually processed for one pre-warm. The server's
111
+ * own prompt count is authoritative when it reported one; otherwise the
112
+ * provider usage prompt side, cached tokens folded in, is the honest figure.
113
+ * Null when neither exists, which is different from a measured zero.
114
+ */
115
+ export function prewarmPromptTokens(result: Pick<PrewarmRoundResult, "usage" | "backend">): number | null {
116
+ if (result.backend) return result.backend.promptTokens;
117
+ const usage = result.usage;
118
+ if (!usage) return null;
119
+ const total = (usage.input || 0) + (usage.cacheRead || 0) + (usage.cacheWrite || 0);
120
+ return total > 0 ? total : null;
121
+ }
122
+
123
+ /**
124
+ * Send the prefix and wait for the backend to acknowledge it. Resolves rather
125
+ * than rejects on a provider failure: a pre-warm is an optimization, and a
126
+ * backend that refuses it must not be able to break the session it was warming.
127
+ */
128
+ export async function runPrewarmRound(input: PrewarmRoundInput): Promise<PrewarmRoundResult> {
129
+ const prefix = prewarmPrefix(input.state);
130
+ const context = {
131
+ systemPrompt: prefix.systemPrompt,
132
+ messages: [
133
+ ...prefix.messages,
134
+ { role: "user", content: [{ type: "text", text: PREWARM_USER_TEXT }], timestamp: Date.now() },
135
+ ],
136
+ tools: prefix.tools,
137
+ };
138
+ // pi-agent-core maps `thinkingLevel: "off"` onto an absent `reasoning`; the
139
+ // pre-warm has to make the same mapping or the thinking composition resolves
140
+ // against a different level and the rendered template moves.
141
+ const options: Record<string, unknown> = { maxTokens: PREWARM_MAX_TOKENS };
142
+ if (input.state.thinkingLevel !== "off") options.reasoning = input.state.thinkingLevel;
143
+ if (input.apiKey !== undefined) options.apiKey = input.apiKey;
144
+ if (input.signal !== undefined) options.signal = input.signal;
145
+
146
+ const send = input.streamFn ?? streamSimple;
147
+ const startedAt = performance.now();
148
+ let firstDeltaAt: number | null = null;
149
+ const elapsed = (): number => Math.round(Math.max(0, performance.now() - startedAt));
150
+ const ttft = (): number | null => (firstDeltaAt === null ? null : Math.round(Math.max(0, firstDeltaAt - startedAt)));
151
+
152
+ try {
153
+ const events = send(
154
+ input.model,
155
+ context as unknown as Parameters<typeof streamSimple>[1],
156
+ options as unknown as Parameters<typeof streamSimple>[2],
157
+ );
158
+ for await (const event of events) {
159
+ if (firstDeltaAt === null && event.type !== "start") firstDeltaAt = performance.now();
160
+ if (event.type === "done") {
161
+ return {
162
+ aborted: false,
163
+ usage: usageOf(event.message),
164
+ backend: backendOf(event.message),
165
+ timing: { ttftMs: ttft(), apiMs: elapsed() },
166
+ errorMessage: null,
167
+ };
168
+ }
169
+ if (event.type === "error") {
170
+ const failed = event.error as { stopReason?: unknown; errorMessage?: unknown };
171
+ const aborted = event.reason === "aborted" || failed.stopReason === "aborted" || input.signal?.aborted === true;
172
+ return {
173
+ aborted,
174
+ usage: usageOf(event.error),
175
+ backend: backendOf(event.error),
176
+ timing: { ttftMs: ttft(), apiMs: elapsed() },
177
+ errorMessage: aborted ? null : typeof failed.errorMessage === "string" ? failed.errorMessage : "pre-warm failed",
178
+ };
179
+ }
180
+ }
181
+ } catch (error) {
182
+ return {
183
+ aborted: input.signal?.aborted === true,
184
+ usage: null,
185
+ backend: null,
186
+ timing: { ttftMs: ttft(), apiMs: elapsed() },
187
+ errorMessage: input.signal?.aborted === true ? null : error instanceof Error ? error.message : String(error),
188
+ };
189
+ }
190
+ return {
191
+ aborted: input.signal?.aborted === true,
192
+ usage: null,
193
+ backend: null,
194
+ timing: { ttftMs: ttft(), apiMs: elapsed() },
195
+ errorMessage: null,
196
+ };
197
+ }
@@ -1,6 +1,6 @@
1
- import { mkdirSync, writeFileSync } from "node:fs";
1
+ import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { appendFile } from "node:fs/promises";
3
- import { dirname } from "node:path";
3
+ import { dirname, join } from "node:path";
4
4
  import type { TuiRenderObserver, TuiRenderPhase } from "../engine/tui.js";
5
5
 
6
6
  /** The trace format is append-only JSONL so partial sessions remain readable. */
@@ -106,6 +106,106 @@ export type RenderTraceRecord =
106
106
  }
107
107
  | { type: "trace_drop"; version: typeof RENDER_TRACE_VERSION; at: number; records: number };
108
108
 
109
+ /** One byte-level delivery from the stdin reader to the application listener. */
110
+ export type RenderTraceInputIngressRecord = Extract<RenderTraceRecord, { type: "input_ingress" }>;
111
+
112
+ /**
113
+ * How many `input_ingress` records and how many committed frame records the
114
+ * always-on ring keeps, each. 256 keystrokes and 256 committed frames cover the
115
+ * last stretch of interaction an operator would still be describing when they
116
+ * kill a wedged pane, and cost about 200 KB of process memory in the worst case
117
+ * (a frame record carries its terminal-write commits).
118
+ */
119
+ export const INPUT_WEDGE_RING_CAPACITY = 256;
120
+
121
+ /** Subdirectory of the state directory that holds SIGTERM wedge dumps. */
122
+ export const INPUT_WEDGE_DUMP_DIRNAME = "input-wedge";
123
+
124
+ /** Dumps kept in that directory; older ones are removed as new ones land. */
125
+ export const INPUT_WEDGE_DUMP_RETAINED = 5;
126
+
127
+ /**
128
+ * Which half of the input pipeline was still moving when the dump was taken.
129
+ *
130
+ * `input-not-committed` is the consumer's failure: bytes reached the
131
+ * application listener and no frame that carries them ever reached stdout.
132
+ * `no-input-recorded` is the reader's: nothing was delivered at all, so an
133
+ * operator who was typing was typing into a reader that had stopped.
134
+ * `input-committed` says neither half of this pipeline was stuck.
135
+ */
136
+ export type InputWedgeClassification = "no-input-recorded" | "input-not-committed" | "input-committed";
137
+
138
+ export interface InputWedgeSnapshot {
139
+ version: typeof RENDER_TRACE_VERSION;
140
+ capacity: number;
141
+ pid: number;
142
+ /** Wall clock at trace open, so a record's relative `at` maps onto real time. */
143
+ openedAtEpochMs: number;
144
+ atEpochMs: number;
145
+ /** Milliseconds since trace open, the same clock every record's `at` uses. */
146
+ at: number;
147
+ classification: InputWedgeClassification;
148
+ msSinceLastInputIngress: number | null;
149
+ msSinceLastCommittedFrame: number | null;
150
+ inputIngress: RenderTraceInputIngressRecord[];
151
+ frames: RenderTraceFrameRecord[];
152
+ }
153
+
154
+ /** Bounded FIFO that overwrites its oldest entry rather than growing. */
155
+ function createRing<T>(capacity: number): { push(value: T): void; toArray(): T[] } {
156
+ const slots: T[] = [];
157
+ let next = 0;
158
+ return {
159
+ push(value): void {
160
+ if (slots.length < capacity) slots.push(value);
161
+ else slots[next] = value;
162
+ next = (next + 1) % capacity;
163
+ },
164
+ toArray(): T[] {
165
+ if (slots.length < capacity) return [...slots];
166
+ return [...slots.slice(next), ...slots.slice(0, next)];
167
+ },
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Read the two rings the way the ticket asks the wedge to be read: the newest
173
+ * input the operator should have seen, against the newest frame that reached
174
+ * stdout carrying it.
175
+ */
176
+ function classifyInputWedge(
177
+ inputIngress: ReadonlyArray<RenderTraceInputIngressRecord>,
178
+ frames: ReadonlyArray<RenderTraceFrameRecord>,
179
+ ): InputWedgeClassification {
180
+ const newest = [...inputIngress].reverse().find((record) => record.visualExpected) ?? inputIngress.at(-1);
181
+ if (newest === undefined) return "no-input-recorded";
182
+ return frames.some((frame) => frame.inputHighWater >= newest.inputSeq) ? "input-committed" : "input-not-committed";
183
+ }
184
+
185
+ /**
186
+ * Write one snapshot under `<stateDir>/input-wedge/`, newest-first by name, and
187
+ * drop everything past the retention bound. Synchronous on purpose: the caller
188
+ * is a signal handler on a process that is about to end.
189
+ */
190
+ export function writeInputWedgeDump(stateDir: string, snapshot: InputWedgeSnapshot): string {
191
+ const directory = join(stateDir, INPUT_WEDGE_DUMP_DIRNAME);
192
+ mkdirSync(directory, { recursive: true });
193
+ const stamp = new Date(snapshot.atEpochMs).toISOString().replace(/[:.]/gu, "-");
194
+ const path = join(directory, `${stamp}-${snapshot.pid}.json`);
195
+ writeFileSync(path, `${JSON.stringify(snapshot, null, 2)}\n`, "utf8");
196
+ try {
197
+ const existing = readdirSync(directory)
198
+ .filter((name) => name.endsWith(".json"))
199
+ .sort();
200
+ for (const name of existing.slice(0, Math.max(0, existing.length - INPUT_WEDGE_DUMP_RETAINED))) {
201
+ rmSync(join(directory, name), { force: true });
202
+ }
203
+ } catch {
204
+ // Retention is housekeeping; a dump that landed is worth more than a tidy directory.
205
+ }
206
+ return path;
207
+ }
208
+
109
209
  interface TraceWriter {
110
210
  enqueue(record: RenderTraceRecord): void;
111
211
  close(): Promise<void>;
@@ -236,6 +336,8 @@ export interface RenderTrace extends TuiRenderObserver {
236
336
  recordTerminalDrain(writeId: number): void;
237
337
  currentFrameId(): number | null;
238
338
  onFirstFrameCommit(listener: (frameId: number) => void): void;
339
+ /** The always-on ring as it stands, classified. Allocates; call it once, on the way out. */
340
+ snapshotInputWedge(): InputWedgeSnapshot;
239
341
  close(): Promise<void>;
240
342
  }
241
343
 
@@ -255,17 +357,32 @@ export function renderTracePath(env: NodeJS.ProcessEnv = process.env): string |
255
357
  return raw && raw.length > 0 ? raw : null;
256
358
  }
257
359
 
360
+ /**
361
+ * One tracer, two sinks. The JSONL file is the armed sink: it exists only when
362
+ * `CLIO_CODER_RENDER_TRACE` named a path, and it keeps every record. The
363
+ * bounded in-memory ring is the always-on sink: it keeps the last
364
+ * {@link INPUT_WEDGE_RING_CAPACITY} `input_ingress` records and the same number
365
+ * of committed frames, so the SIGTERM that recovers a wedged pane can still say
366
+ * which half of the input pipeline stopped (#224). A null `path` is the
367
+ * ring-only mode, and there the recorders that only ever fed the file keep
368
+ * their counters and skip building a record nothing would read.
369
+ */
258
370
  export function createRenderTrace(
259
- path: string,
371
+ path: string | null,
260
372
  now: () => number = () => performance.now(),
261
373
  writerOptions: AsyncTraceWriterOptions = {},
262
374
  ): RenderTrace {
263
375
  // Initialization happens before the terminal/TUI starts, never in a frame.
264
- mkdirSync(dirname(path), { recursive: true });
265
- writeFileSync(path, "", "utf8");
376
+ if (path !== null) {
377
+ mkdirSync(dirname(path), { recursive: true });
378
+ writeFileSync(path, "", "utf8");
379
+ }
266
380
  const openedAt = now();
381
+ const openedAtEpochMs = Date.now();
267
382
  const at = (): number => rounded(now() - openedAt);
268
- const writer = createAsyncTraceWriter(path, { ...writerOptions, recordTime: at });
383
+ const writer = path === null ? null : createAsyncTraceWriter(path, { ...writerOptions, recordTime: at });
384
+ const inputRing = createRing<RenderTraceInputIngressRecord>(INPUT_WEDGE_RING_CAPACITY);
385
+ const frameRing = createRing<RenderTraceFrameRecord>(INPUT_WEDGE_RING_CAPACITY);
269
386
  let frameSeq = 0;
270
387
  let writeSeq = 0;
271
388
  let eventSeq = 0;
@@ -282,7 +399,7 @@ export function createRenderTrace(
282
399
  const ranges = new Map<string, { codeUnits: number; graphemes: number }>();
283
400
  const pendingDrains = new Map<number, { frameId: number | null; at: number }>();
284
401
 
285
- writer.enqueue({ type: "trace_start", version: RENDER_TRACE_VERSION, at: 0 });
402
+ writer?.enqueue({ type: "trace_start", version: RENDER_TRACE_VERSION, at: 0 });
286
403
 
287
404
  const trace: RenderTrace = {
288
405
  recordPanelRender(metrics): void {
@@ -294,12 +411,15 @@ export function createRenderTrace(
294
411
  },
295
412
  recordVisibleEvent(fields): number {
296
413
  eventSeq += 1;
414
+ // The ring keeps no provider deltas, so ring-only mode does not pay for
415
+ // grapheme segmentation on every token of every stream.
416
+ if (writer === null) return eventSeq;
297
417
  const key = `${generation}:${fields.kind}:${fields.contentIndex}`;
298
418
  const previous = ranges.get(key) ?? { codeUnits: 0, graphemes: 0 };
299
419
  const graphemes = graphemeCount(fields.delta);
300
420
  const next = { codeUnits: previous.codeUnits + fields.delta.length, graphemes: previous.graphemes + graphemes };
301
421
  ranges.set(key, next);
302
- writer.enqueue({
422
+ writer?.enqueue({
303
423
  type: "event_ingress",
304
424
  version: RENDER_TRACE_VERSION,
305
425
  eventSeq,
@@ -317,7 +437,7 @@ export function createRenderTrace(
317
437
  },
318
438
  recordQueue(sequence, action): void {
319
439
  queueDepth = Math.max(0, queueDepth + (action === "admit" ? 1 : -1));
320
- writer.enqueue({
440
+ writer?.enqueue({
321
441
  type: "queue",
322
442
  version: RENDER_TRACE_VERSION,
323
443
  eventSeq: sequence,
@@ -328,7 +448,7 @@ export function createRenderTrace(
328
448
  },
329
449
  recordPanelApplied(sequence): void {
330
450
  panelHighWater = Math.max(panelHighWater, sequence);
331
- writer.enqueue({
451
+ writer?.enqueue({
332
452
  type: "panel",
333
453
  version: RENDER_TRACE_VERSION,
334
454
  eventSeq: sequence,
@@ -339,7 +459,7 @@ export function createRenderTrace(
339
459
  recordInputIngress(action, bytes, visualExpected = action !== "no-visual-change"): number {
340
460
  inputSeq += 1;
341
461
  if (visualExpected) inputHighWater = inputSeq;
342
- writer.enqueue({
462
+ const record: RenderTraceInputIngressRecord = {
343
463
  type: "input_ingress",
344
464
  version: RENDER_TRACE_VERSION,
345
465
  inputSeq,
@@ -347,7 +467,9 @@ export function createRenderTrace(
347
467
  at: at(),
348
468
  bytes,
349
469
  visualExpected,
350
- });
470
+ };
471
+ inputRing.push(record);
472
+ writer?.enqueue(record);
351
473
  return inputSeq;
352
474
  },
353
475
  beginFrame(fields): FrameState {
@@ -403,8 +525,11 @@ export function createRenderTrace(
403
525
  },
404
526
  commits: frame.commits,
405
527
  };
406
- writer.enqueue(record);
528
+ writer?.enqueue(record);
407
529
  if (frame.commits.length > 0) {
530
+ // Only a frame that reached stdout answers the question the ring exists
531
+ // for, which is whether the consumer half is still painting.
532
+ frameRing.push(record);
408
533
  lastCommitAt = frame.commits.at(-1)?.at ?? endAt;
409
534
  if (!firstCommitDelivered) {
410
535
  firstCommitDelivered = true;
@@ -439,6 +564,7 @@ export function createRenderTrace(
439
564
  backpressured: !fields.returned,
440
565
  };
441
566
  currentFrame?.commits.push(commit);
567
+ if (writer === null) return writeSeq;
442
568
  writer.enqueue({ type: "terminal_write", version: RENDER_TRACE_VERSION, frameId, ...commit });
443
569
  if (!fields.returned) pendingDrains.set(writeSeq, { frameId, at: commit.at });
444
570
  return writeSeq;
@@ -448,7 +574,7 @@ export function createRenderTrace(
448
574
  if (!pending) return;
449
575
  pendingDrains.delete(writeId);
450
576
  const drainAt = at();
451
- writer.enqueue({
577
+ writer?.enqueue({
452
578
  type: "terminal_drain",
453
579
  version: RENDER_TRACE_VERSION,
454
580
  writeId,
@@ -461,7 +587,28 @@ export function createRenderTrace(
461
587
  onFirstFrameCommit(listener): void {
462
588
  firstCommitListener = listener;
463
589
  },
464
- close: () => writer.close(),
590
+ snapshotInputWedge(): InputWedgeSnapshot {
591
+ const inputIngress = inputRing.toArray();
592
+ const frames = frameRing.toArray();
593
+ const nowAt = at();
594
+ const lastIngressAt = inputIngress.at(-1)?.at;
595
+ const lastFrame = frames.at(-1);
596
+ const lastFrameCommitAt = lastFrame?.commits.at(-1)?.at ?? lastFrame?.endAt;
597
+ return {
598
+ version: RENDER_TRACE_VERSION,
599
+ capacity: INPUT_WEDGE_RING_CAPACITY,
600
+ pid: process.pid,
601
+ openedAtEpochMs,
602
+ atEpochMs: Date.now(),
603
+ at: nowAt,
604
+ classification: classifyInputWedge(inputIngress, frames),
605
+ msSinceLastInputIngress: lastIngressAt === undefined ? null : rounded(nowAt - lastIngressAt),
606
+ msSinceLastCommittedFrame: lastFrameCommitAt === undefined ? null : rounded(nowAt - lastFrameCommitAt),
607
+ inputIngress,
608
+ frames,
609
+ };
610
+ },
611
+ close: () => writer?.close() ?? Promise.resolve(),
465
612
  };
466
613
  return trace;
467
614
  }
@@ -49,6 +49,35 @@ export function renderCompactionSummaryLine(input: CompactionSummaryLineInput):
49
49
  return `[context engine] llm_summary: ${input.messagesSummarized} messages summarized to ${input.summaryChars} chars; ~${input.tokensBefore} tokens before${tail}`;
50
50
  }
51
51
 
52
+ /** Why the non-destructive stage had nothing to do before a summary ran. */
53
+ export type EvictionSkipReason = "all-protected" | "nothing-evictable" | "disabled";
54
+
55
+ export interface EvictionSkipLineInput {
56
+ reason: EvictionSkipReason;
57
+ /** Turn starts in the visible slice the policy was offered. */
58
+ turns: number;
59
+ protectLastTurns: number;
60
+ policyId: string;
61
+ }
62
+
63
+ /**
64
+ * One line saying the working-set stage was considered and declined, in the
65
+ * same `[context engine] working set:` voice its eviction notice uses. Without
66
+ * it a short session falls from the pressure threshold straight into the
67
+ * destructive summary with nothing in the transcript explaining why the cheap
68
+ * stage did not run (smoke pass 2, G1).
69
+ */
70
+ export function renderEvictionSkipLine(input: EvictionSkipLineInput): string {
71
+ const turnWord = input.turns === 1 ? "turn" : "turns";
72
+ const cause =
73
+ input.reason === "disabled"
74
+ ? "eviction is off (context.workingSet.enabled false)"
75
+ : input.reason === "all-protected"
76
+ ? `nothing evictable, all ${input.turns} ${turnWord} are inside the protected window (protectLastTurns ${input.protectLastTurns})`
77
+ : `nothing evictable by ${input.policyId} above the protected window (protectLastTurns ${input.protectLastTurns})`;
78
+ return `[context engine] working set: ${cause}; llm_summary runs instead`;
79
+ }
80
+
52
81
  export interface RenderCompactionSummaryOptions {
53
82
  /** Override the default markdown theme. Defaults to the local theme above. */
54
83
  theme?: MarkdownTheme;
@@ -18,6 +18,7 @@ import { formatSize } from "../../engine/truncate.js";
18
18
  import { visibleWidth, wrapTextWithAnsi } from "../../engine/tui.js";
19
19
  import { classifyResourceRead, toolPresentationPolicy } from "../../tools/presentation.js";
20
20
  import { toolResultPresentationPolicy, toolResultPresentationText } from "../../tools/result-disposition.js";
21
+ import { mutationFactsLine } from "../mutation-preview.js";
21
22
  import type { ApprovalRequestView } from "../permission-overlay.js";
22
23
  import { clioTheme, formatCompactMs, GLYPH } from "../theme/index.js";
23
24
  import { renderDiffLines } from "./diff.js";
@@ -490,6 +491,9 @@ export function renderToolAwaitingApproval(
490
491
  ["action", view.actionClass],
491
492
  ["axis", axis],
492
493
  ...(view.target !== undefined && view.target.length > 0 ? [["target", view.target]] : []),
494
+ // Size and digest, never the mutation text: this row is the transcript,
495
+ // which is written, replayed, and shared (issue #254).
496
+ ...(view.mutation !== undefined ? [["mutation", mutationFactsLine(view.mutation)]] : []),
493
497
  ] as const;
494
498
  for (const [label, value] of facts) {
495
499
  lines.push(...indentAndWrap(`${dim(`${label} ·`)} ${value}`, width, false));