@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
@@ -27,6 +27,14 @@ export interface PromptTemplate {
27
27
  sourceInfo: ResourceSourceInfo;
28
28
  /** False for a project compatibility root until the operator opts in; such a template refuses to expand. */
29
29
  trusted: boolean;
30
+ /**
31
+ * Why this template cannot be expanded, when a load-time failure left it
32
+ * with no usable body. It is loaded anyway, so the namespaced command is
33
+ * recognized and invoking it reports this reason instead of "not a command"
34
+ * (issue #245). `content` is empty on such a template and nothing may send
35
+ * it to a model.
36
+ */
37
+ unavailable?: string;
30
38
  argumentHint?: string;
31
39
  }
32
40
 
@@ -154,24 +162,28 @@ function contained(root: string, candidate: string): boolean {
154
162
  return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative));
155
163
  }
156
164
 
157
- /** Resolve only existing paths contained by the declaring extension package. */
158
- function resolveExtensionReferences(
159
- body: string,
160
- root: PromptTemplateRoot,
161
- filePath: string,
162
- diagnostics: ResourceDiagnostic[],
163
- ): string | null {
164
- if (root.rootPath === undefined || !body.includes(EXTENSION_ROOT_TOKEN)) return body;
165
+ /**
166
+ * The outcome of a step that may leave the template with no usable body.
167
+ * `reason` is the one sentence that becomes both the diagnostic the `/prompts`
168
+ * overlay renders and the refusal the operator gets when they invoke the
169
+ * command, so the two can never disagree.
170
+ */
171
+ type BodyResolution = { body: string } | { reason: string };
172
+
173
+ /**
174
+ * Resolve only existing paths contained by the declaring extension package.
175
+ *
176
+ * The safety half is unchanged: a missing or escaping reference never expands
177
+ * and never reads outside the package. What changed is what the caller does
178
+ * with the failure, which used to be dropping the template entirely.
179
+ */
180
+ function resolveExtensionReferences(body: string, root: PromptTemplateRoot): BodyResolution {
181
+ if (root.rootPath === undefined || !body.includes(EXTENSION_ROOT_TOKEN)) return { body };
165
182
  let canonicalRoot: string;
166
183
  try {
167
184
  canonicalRoot = realpathSync(root.rootPath);
168
185
  } catch (error) {
169
- diagnostics.push({
170
- type: "warning",
171
- message: `extension root could not be resolved: ${error instanceof Error ? error.message : String(error)}`,
172
- path: filePath,
173
- });
174
- return null;
186
+ return { reason: `extension root could not be resolved: ${error instanceof Error ? error.message : String(error)}` };
175
187
  }
176
188
  let invalid: string | null = null;
177
189
  const resolved = body.replace(EXTENSION_ROOT_REFERENCE, (reference, suffix: string | undefined) => {
@@ -185,14 +197,44 @@ function resolveExtensionReferences(
185
197
  return candidate;
186
198
  });
187
199
  if (invalid !== null) {
188
- diagnostics.push({
189
- type: "warning",
190
- message: `prompt template has an unresolved or escaping extension reference: ${invalid}`,
191
- path: filePath,
192
- });
193
- return null;
200
+ return { reason: `prompt template has an unresolved or escaping extension reference: ${invalid}` };
194
201
  }
195
- return resolved;
202
+ return { body: resolved };
203
+ }
204
+
205
+ /**
206
+ * A template that exists and cannot run.
207
+ *
208
+ * Dropping it made the operator's namespaced command answer "not a command",
209
+ * so an extension author's single bad `${extensionRoot}` path read to their
210
+ * users as "the prompt was never installed" (issue #245). The template is
211
+ * loaded with an empty body and the reason attached instead, which is the same
212
+ * shape an untrusted project template already had, so the existing refusal
213
+ * path carries it to the operator with no new machinery.
214
+ */
215
+ function unavailableTemplate(
216
+ name: string,
217
+ filePath: string,
218
+ root: PromptTemplateRoot,
219
+ reason: string,
220
+ diagnostics: ResourceDiagnostic[],
221
+ description?: string,
222
+ ): ResourceCandidate<PromptTemplate> {
223
+ diagnostics.push({ type: "warning", message: reason, path: filePath });
224
+ const sourceInfo: ResourceSourceInfo = sourceInfoForRoot(root, filePath);
225
+ return {
226
+ name,
227
+ value: {
228
+ name,
229
+ description: description ?? "Prompt template (unavailable)",
230
+ content: "",
231
+ filePath,
232
+ sourceInfo,
233
+ trusted: root.trusted !== false,
234
+ unavailable: `${reason} (${filePath})`,
235
+ },
236
+ source: sourceInfo,
237
+ };
196
238
  }
197
239
 
198
240
  function loadPromptFile(
@@ -202,15 +244,9 @@ function loadPromptFile(
202
244
  ): ResourceCandidate<PromptTemplate> | null {
203
245
  const ext = path.extname(filePath).toLowerCase();
204
246
  if (ext !== ".md") return null;
205
- let raw: string;
206
- try {
207
- raw = readFileSync(filePath, "utf8");
208
- } catch (err) {
209
- const reason = err instanceof Error ? err.message : String(err);
210
- diagnostics.push({ type: "warning", message: `prompt template could not be read: ${reason}`, path: filePath });
211
- return null;
212
- }
213
247
 
248
+ // The name comes before the read, so a file that exists but cannot be read
249
+ // still has a command the operator can invoke and be told why.
214
250
  const relativePath = path.relative(root.path, filePath);
215
251
  if (
216
252
  relativePath === "" ||
@@ -218,21 +254,35 @@ function loadPromptFile(
218
254
  relativePath.startsWith(`..${path.sep}`) ||
219
255
  path.isAbsolute(relativePath)
220
256
  ) {
257
+ // The one failure that stays a drop: the path is outside the discovery
258
+ // root, so there is no name here to offer a command under.
221
259
  diagnostics.push({ type: "warning", message: "prompt template escaped its discovery root", path: filePath });
222
260
  return null;
223
261
  }
224
262
  const name = relativePath.slice(0, -ext.length).split(path.sep).join(":");
225
263
  if (name.trim().length === 0) return null;
264
+
265
+ let raw: string;
266
+ try {
267
+ raw = readFileSync(filePath, "utf8");
268
+ } catch (err) {
269
+ const reason = err instanceof Error ? err.message : String(err);
270
+ return unavailableTemplate(name, filePath, root, `prompt template could not be read: ${reason}`, diagnostics);
271
+ }
272
+
226
273
  const { frontmatter, body } = splitOptionalFrontmatter(raw, filePath, diagnostics);
227
- const resolvedBody = resolveExtensionReferences(body, root, filePath, diagnostics);
228
- if (resolvedBody === null) return null;
229
- const description = stringField(frontmatter, "description") ?? fallbackDescription(resolvedBody);
274
+ const declaredDescription = stringField(frontmatter, "description");
275
+ const resolution = resolveExtensionReferences(body, root);
276
+ if ("reason" in resolution) {
277
+ return unavailableTemplate(name, filePath, root, resolution.reason, diagnostics, declaredDescription ?? undefined);
278
+ }
279
+ const description = declaredDescription ?? fallbackDescription(resolution.body);
230
280
  const argumentHint = stringField(frontmatter, "argument-hint") ?? stringField(frontmatter, "argumentHint");
231
281
  const sourceInfo: ResourceSourceInfo = sourceInfoForRoot(root, filePath);
232
282
  const template: PromptTemplate = {
233
283
  name,
234
284
  description,
235
- content: resolvedBody.trim(),
285
+ content: resolution.body.trim(),
236
286
  filePath,
237
287
  sourceInfo,
238
288
  trusted: root.trusted !== false,
@@ -330,6 +380,18 @@ export function expandPromptTemplateInput(input: string, templates: PromptTempla
330
380
  if (!command) return { expanded: false, text: input, args: [], diagnostics: templates.diagnostics };
331
381
  const template = templates.items.find((entry) => entry.name === command.name);
332
382
  if (!template) return { expanded: false, text: input, args: [], diagnostics: templates.diagnostics };
383
+ // A load-time failure refuses before anything else, and before the trust
384
+ // check, because there is no body here to be trusted or untrusted.
385
+ if (template.unavailable !== undefined) {
386
+ const message = `prompt template /${template.name} cannot run: ${template.unavailable}`;
387
+ return {
388
+ expanded: false,
389
+ text: input,
390
+ args: [],
391
+ diagnostics: templates.diagnostics,
392
+ refusal: { template, message },
393
+ };
394
+ }
333
395
  if (!template.trusted) {
334
396
  const message = `prompt template ${template.name} comes from an untrusted project root; set skills.trustProjectCompatRoots to use it`;
335
397
  return {
@@ -893,6 +893,39 @@ export function modelVisibleSkills(skills: ReadonlyArray<Skill>): Skill[] {
893
893
  return skills.filter((skill) => skill.trusted && !skill.disableModelInvocation);
894
894
  }
895
895
 
896
+ /** Why a loaded skill catalog is not valid. Ordered by which failure to report first. */
897
+ export type SkillCatalogInvalidReason = "load-error" | "collision" | "unloadable-file" | "no-skills";
898
+
899
+ export interface SkillCatalogValidity {
900
+ ok: boolean;
901
+ reason: SkillCatalogInvalidReason | null;
902
+ }
903
+
904
+ /**
905
+ * The rule `clio-coder skills validate` applies, in one place.
906
+ *
907
+ * A scanned file that produced no loaded skill is malformed, and a collision
908
+ * drops a skill: both make the catalog invalid, as does any hard error. Benign
909
+ * warnings (name/path mismatch, name format, description length) attach to a
910
+ * file that still loaded, so their path is among the loaded skills and they do
911
+ * not fail validation.
912
+ *
913
+ * Lives here rather than in the CLI because two callers now need the same
914
+ * answer, and a verdict that drifts between the terminal and a GUI is worse
915
+ * than no verdict at all.
916
+ */
917
+ export function skillCatalogValidity(list: SkillList): SkillCatalogValidity {
918
+ if (list.diagnostics.some((diag) => diag.type === "error")) return { ok: false, reason: "load-error" };
919
+ if (list.diagnostics.some((diag) => diag.type === "collision")) return { ok: false, reason: "collision" };
920
+ const loadedPaths = new Set(list.items.map((skill) => skill.filePath));
921
+ const unloadable = list.diagnostics.some(
922
+ (diag) => diag.type === "warning" && diag.path !== undefined && !loadedPaths.has(diag.path),
923
+ );
924
+ if (unloadable) return { ok: false, reason: "unloadable-file" };
925
+ if (list.items.length === 0) return { ok: false, reason: "no-skills" };
926
+ return { ok: true, reason: null };
927
+ }
928
+
896
929
  export function parseSkillCommand(input: string): { name: string; args: string } | null {
897
930
  const trimmed = input.trim();
898
931
  if (!trimmed.startsWith("/skill ")) return null;
@@ -104,6 +104,12 @@ function baseClassify(tool: string): ActionClass | null {
104
104
  // local mirror. Neither touches the workspace, so it is never gated
105
105
  // behind a confirmation.
106
106
  case ToolNames.Ledger:
107
+ // panes focuses, opens, and closes terminal panes Clio itself created, in
108
+ // a pane host that lives outside the workspace. Nothing it does writes a
109
+ // file, runs a model-supplied command (its schema exposes presets only),
110
+ // or survives the session, so it is reversible, local, and never gated
111
+ // behind a confirmation.
112
+ case ToolNames.Panes:
107
113
  return "read";
108
114
  case ToolNames.Write:
109
115
  case ToolNames.Edit:
@@ -31,6 +31,58 @@ function oneLine(value: string): string {
31
31
  return value.replace(/\s+/g, " ").trim();
32
32
  }
33
33
 
34
+ /** Columns one tab occupies when a multi-line surface expands it. */
35
+ const DISPLAY_TAB_WIDTH = 4;
36
+
37
+ /** Stands in for a control byte that was neutralized, so the cut is visible. */
38
+ const CONTROL_BYTE_PLACEHOLDER = "·";
39
+
40
+ export interface SanitizedDisplayText {
41
+ text: string;
42
+ /** A control byte or escape sequence was neutralized. */
43
+ neutralized: boolean;
44
+ /** A tab was expanded, so column positions are display positions. */
45
+ tabsExpanded: boolean;
46
+ }
47
+
48
+ /**
49
+ * Neutralize escape sequences and control bytes while keeping line structure.
50
+ * {@link sanitizeCallTargetText} is the one-line form for a card; this is the
51
+ * form a multi-line operator surface needs, where the newlines are the content
52
+ * rather than whitespace to collapse. Tabs become spaces because a bordered
53
+ * frame measures visible width and a literal tab makes that measurement a lie.
54
+ * Every other C0 byte and DEL becomes a visible placeholder, so a payload
55
+ * cannot style, reposition, or spoof the surface that is approving it.
56
+ */
57
+ export function sanitizeMultilineDisplayText(value: string): SanitizedDisplayText {
58
+ const escapesStripped = value.replace(OSC_PATTERN, "").replace(CSI_PATTERN, "");
59
+ let neutralized = escapesStripped.length !== value.length;
60
+ // CRLF is line structure, not an injection, so it normalizes rather than
61
+ // showing a placeholder at the end of every line of a Windows-authored file.
62
+ const stripped = escapesStripped.replace(/\r\n/g, "\n");
63
+ let tabsExpanded = false;
64
+ let out = "";
65
+ for (const ch of stripped) {
66
+ if (ch === "\n") {
67
+ out += ch;
68
+ continue;
69
+ }
70
+ if (ch === "\t") {
71
+ out += " ".repeat(DISPLAY_TAB_WIDTH);
72
+ tabsExpanded = true;
73
+ continue;
74
+ }
75
+ const code = ch.codePointAt(0) ?? 0;
76
+ if (code < 0x20 || code === 0x7f) {
77
+ out += CONTROL_BYTE_PLACEHOLDER;
78
+ neutralized = true;
79
+ continue;
80
+ }
81
+ out += ch;
82
+ }
83
+ return { text: out, neutralized, tabsExpanded };
84
+ }
85
+
34
86
  /**
35
87
  * Neutralize escape sequences and control bytes in a pre-composed target
36
88
  * string and collapse it to one line. Used where a description crosses a
@@ -76,6 +76,23 @@ export interface RunEffects {
76
76
  * run there is no path left in the checkout that the record can clear.
77
77
  */
78
78
  writeRecordComplete: boolean;
79
+ /**
80
+ * Successful opaque calls that made the write record incomplete. The call id
81
+ * and tool name are retained so a later write-boundary verdict can explain
82
+ * exactly why attribution was downgraded instead of exposing only a boolean.
83
+ */
84
+ writeRecordDowngrades: ReadonlyArray<WriteRecordDowngrade>;
85
+ }
86
+
87
+ export interface WriteRecordDowngrade {
88
+ reason: "opaque_tool_succeeded";
89
+ tool: string;
90
+ toolCallId: string;
91
+ }
92
+
93
+ export interface RunEffectsRecorderOptions {
94
+ /** Fires once, when the first successful opaque call opens the record. */
95
+ onWriteRecordDowngraded?(downgrade: WriteRecordDowngrade): void;
79
96
  }
80
97
 
81
98
  export interface RunEffectsRecorder {
@@ -87,6 +104,8 @@ export interface RunEffectsRecorder {
87
104
  }
88
105
 
89
106
  interface PendingEffects {
107
+ tool: string;
108
+ toolCallId: string;
90
109
  paths: ReadonlyArray<string>;
91
110
  validationCommand: string | null;
92
111
  verificationCommand: string | null;
@@ -204,13 +223,13 @@ function validationCommandOf(
204
223
  * when its result comes back clean: a blocked write and a red command are not
205
224
  * evidence that the workspace changed or that a check passed.
206
225
  */
207
- export function createRunEffectsRecorder(cwd: string): RunEffectsRecorder {
226
+ export function createRunEffectsRecorder(cwd: string, options: RunEffectsRecorderOptions = {}): RunEffectsRecorder {
208
227
  const pending = new Map<string, PendingEffects>();
209
228
  const mutatedPaths = new Set<string>();
210
229
  const failedMutationPaths = new Set<string>();
211
230
  const validationCommands = new Set<string>();
212
231
  const verificationCommands = new Set<string>();
213
- let opaqueWriteObserved = false;
232
+ const writeRecordDowngrades = new Map<string, WriteRecordDowngrade>();
214
233
  return {
215
234
  start(toolCallId, toolName, args) {
216
235
  const paths = mutationTargets(toolName, args);
@@ -223,6 +242,8 @@ export function createRunEffectsRecorder(cwd: string): RunEffectsRecorder {
223
242
  // A bash call may re-base its relative paths with its own cwd argument.
224
243
  const base = typeof args?.cwd === "string" && args.cwd.length > 0 ? path.resolve(cwd, args.cwd) : cwd;
225
244
  pending.set(toolCallId, {
245
+ tool: toolName,
246
+ toolCallId,
226
247
  paths: paths.map((target) => path.resolve(base, target)),
227
248
  validationCommand,
228
249
  verificationCommand,
@@ -240,7 +261,16 @@ export function createRunEffectsRecorder(cwd: string): RunEffectsRecorder {
240
261
  // Success-gated on purpose. A shell command the safety policy blocked,
241
262
  // or one that came back an error, never reached the filesystem, so it
242
263
  // leaves the record closed.
243
- if (effects.opaque) opaqueWriteObserved = true;
264
+ if (effects.opaque) {
265
+ const downgrade: WriteRecordDowngrade = {
266
+ reason: "opaque_tool_succeeded",
267
+ tool: effects.tool,
268
+ toolCallId: effects.toolCallId,
269
+ };
270
+ const recordWasComplete = writeRecordDowngrades.size === 0;
271
+ writeRecordDowngrades.set(effects.toolCallId, downgrade);
272
+ if (recordWasComplete) options.onWriteRecordDowngraded?.({ ...downgrade });
273
+ }
244
274
  for (const target of effects.paths) mutatedPaths.add(target);
245
275
  if (effects.validationCommand !== null) validationCommands.add(effects.validationCommand);
246
276
  if (effects.verificationCommand !== null) verificationCommands.add(effects.verificationCommand);
@@ -253,7 +283,8 @@ export function createRunEffectsRecorder(cwd: string): RunEffectsRecorder {
253
283
  failedMutationPaths: new Set([...failedMutationPaths].filter((target) => !mutatedPaths.has(target))),
254
284
  validationCommands: new Set(validationCommands),
255
285
  verificationCommands: new Set(verificationCommands),
256
- writeRecordComplete: !opaqueWriteObserved,
286
+ writeRecordComplete: writeRecordDowngrades.size === 0,
287
+ writeRecordDowngrades: [...writeRecordDowngrades.values()].map((entry) => ({ ...entry })),
257
288
  };
258
289
  },
259
290
  };
@@ -72,6 +72,19 @@ export interface ContextSnapshot {
72
72
  splits: Record<string, "estimated" | "exact" | "reconciled">;
73
73
  };
74
74
 
75
+ /**
76
+ * Divergence record. `estimatedTokens` is the chars/4 prompt-side total this
77
+ * snapshot was captured with and is never rewritten by a reconcile, so the
78
+ * two figures stay comparable. `reconciledTokens` is the provider's own
79
+ * prompt token count for the call this snapshot was reconciled against
80
+ * (cached prompt tokens folded back in), and `divergenceRatio` is
81
+ * `reconciledTokens / estimatedTokens`. A ratio above 1 is the estimator
82
+ * under-counting, which is what issue #227 recorded as a provider overflow.
83
+ */
84
+ estimatedTokens?: number | undefined;
85
+ reconciledTokens?: number | undefined;
86
+ divergenceRatio?: number | undefined;
87
+
75
88
  promptHash?: string | undefined;
76
89
  toolSignature?: string | undefined;
77
90
  messageRange?: { start: number; end: number } | undefined;
@@ -332,6 +345,31 @@ export function getLatestContextSnapshot(meta: SessionMeta): ContextSnapshot | n
332
345
  return list.at(-1) ?? null;
333
346
  }
334
347
 
348
+ /**
349
+ * The window a previous process measured this session's prompts against, when
350
+ * the backend itself reported it as the one it had open (issue #227).
351
+ *
352
+ * A resumed session re-resolves its target before discovery has reported a
353
+ * loaded window, so the first turn budgets against the probed server-wide
354
+ * figure, which on a multi-slot backend is a multiple of what the model is
355
+ * actually serving. The snapshot ledger already recorded the number the
356
+ * backend named, so the resume carries it forward instead of re-probing.
357
+ * Scoped to the same target and model: a different selection has no claim on
358
+ * that measurement, and a live loaded window always outranks this one, so a
359
+ * model reloaded at a new size corrects on the next resolution.
360
+ */
361
+ export function lastLoadedContextWindow(meta: SessionMeta, providerId: string, modelId: string): number | null {
362
+ const snapshots = getContextSnapshots(meta);
363
+ for (let i = snapshots.length - 1; i >= 0; i -= 1) {
364
+ const snapshot = snapshots[i];
365
+ if (snapshot?.contextWindowSource !== "loaded") continue;
366
+ if (snapshot.providerId !== providerId || snapshot.modelId !== modelId) continue;
367
+ const window = snapshot.effectiveContextWindow;
368
+ if (typeof window === "number" && Number.isFinite(window) && window > 0) return window;
369
+ }
370
+ return null;
371
+ }
372
+
335
373
  export function buildSnapshotCategories(inputs: {
336
374
  systemPrompt?: string | undefined;
337
375
  promptSegments?: ReadonlyArray<{ id: string; tokenEstimate: number }> | undefined;
@@ -456,6 +494,7 @@ export function captureContextSnapshot(input: CaptureContextSnapshotInput): Cont
456
494
  compactionThreshold: input.compactionThreshold,
457
495
  });
458
496
  return {
497
+ estimatedTokens: sumSplitTokens(categories),
459
498
  snapshotId: nextSnapshotId(),
460
499
  sessionId: input.sessionId,
461
500
  turnId: input.turnId,
@@ -480,9 +519,13 @@ export function captureContextSnapshot(input: CaptureContextSnapshotInput): Cont
480
519
  };
481
520
  }
482
521
 
522
+ function sumSplitTokens(categories: ContextSnapshot["categories"]): number {
523
+ return SNAPSHOT_SPLIT_KEYS.reduce((sum, key) => sum + (categories[key] ?? 0), 0);
524
+ }
525
+
483
526
  /** Sum of the prompt-side categories (everything except reserve/free/streaming). */
484
527
  export function snapshotInputTokens(snapshot: ContextSnapshot): number {
485
- return SNAPSHOT_SPLIT_KEYS.reduce((sum, key) => sum + (snapshot.categories[key] ?? 0), 0);
528
+ return sumSplitTokens(snapshot.categories);
486
529
  }
487
530
 
488
531
  export function reconcileSnapshot(snapshot: ContextSnapshot, usage: Usage): ContextSnapshot {
@@ -572,9 +615,17 @@ export function reconcileSnapshot(snapshot: ContextSnapshot, usage: Usage): Cont
572
615
  {} as Record<string, "estimated" | "exact" | "reconciled">,
573
616
  );
574
617
 
618
+ // The estimate this snapshot was captured with, kept whole across repeated
619
+ // reconciles so the recorded divergence always compares the provider count
620
+ // against chars/4 rather than against a previously normalized total.
621
+ const estimatedTokens = snapshot.estimatedTokens ?? sumSplitTokens(snapshot.categories);
622
+
575
623
  return {
576
624
  ...snapshot,
577
625
  categories: updatedCategories,
626
+ estimatedTokens,
627
+ reconciledTokens: exactInput,
628
+ divergenceRatio: estimatedTokens > 0 ? Math.round((exactInput / estimatedTokens) * 1000) / 1000 : undefined,
578
629
  sources: {
579
630
  total: "reconciled",
580
631
  splits: splitsSources,
@@ -16,6 +16,7 @@
16
16
  * proportional reconciliation the footer bar already performs.
17
17
  */
18
18
 
19
+ import type { BackendCacheVerdict, BackendCompletionTimings } from "../../core/cache-telemetry.js";
19
20
  import type { ContextWindowSlots, ContextWindowSource } from "../providers/index.js";
20
21
  import { DEFAULT_COMPACTION_THRESHOLD } from "./compaction/auto.js";
21
22
 
@@ -100,6 +101,22 @@ export interface BuildContextLedgerInput {
100
101
  } | null;
101
102
  /** Prompt-cache honesty line; null until a turn has compiled and settled. */
102
103
  promptCache?: PromptCacheStats | null;
104
+ /** Last pre-warm since the previous settled run; null when none has run. */
105
+ prewarm?: PrewarmStats | null;
106
+ }
107
+
108
+ /**
109
+ * One pre-warm's result. It is deliberately not a token category: the pre-warm
110
+ * spends no window space and adds no message, it only says the backend has
111
+ * already prefilled the prefix the next turn will send.
112
+ */
113
+ export interface PrewarmStats {
114
+ /** Prompt tokens the backend processed; null when it reported no counts. */
115
+ tokens: number | null;
116
+ /** Wall clock the round took. */
117
+ ms: number;
118
+ /** True when the operator submitted before the round settled. */
119
+ aborted: boolean;
103
120
  }
104
121
 
105
122
  /**
@@ -117,13 +134,17 @@ export interface PromptCacheStats {
117
134
  cacheWriteTokens: number | null;
118
135
  /** Provider-reported uncached input tokens for the last run. */
119
136
  uncachedInputTokens: number | null;
137
+ /** Serving-backend timings for the run's last API call; null when none were captured. */
138
+ backend: BackendCompletionTimings | null;
139
+ /** Backend prompt tokens not served from cache, derived only when cache reads were reported. */
140
+ uncachedPrefillTokens: number | null;
120
141
  /**
121
- * Cache verdict of the run's first API call, classified from the
122
- * provider-reported usage by `backendCacheVerdict`. Null before any
123
- * settled run. "Shell reused but backend cold" is the dishonest
124
- * combination the overlay renders as a warning.
142
+ * Cache verdict of the run's first API call, classified by
143
+ * `backendCacheVerdict` from normalized provider usage and captured serving
144
+ * backend timings when available. Null before any settled run. "Shell reused
145
+ * but backend cold" is the dishonest combination the overlay warns about.
125
146
  */
126
- backendVerdict: "hot" | "partial" | "cold" | "small" | null;
147
+ backendVerdict: BackendCacheVerdict | null;
127
148
  /** Cache disturbances Clio expected before the last settled run. */
128
149
  expectedColdReasons?: ReadonlyArray<string>;
129
150
  }
@@ -185,6 +206,8 @@ export interface ContextLedger {
185
206
  trigger: string;
186
207
  } | null;
187
208
  promptCache: PromptCacheStats | null;
209
+ /** Last pre-warm since the previous settled run; null when none has run. */
210
+ prewarm: PrewarmStats | null;
188
211
  }
189
212
 
190
213
  /** Maps a prompt segment id to the ledger bucket it belongs to. */
@@ -332,14 +355,6 @@ export function buildContextLedger(input: BuildContextLedgerInput): ContextLedge
332
355
  }
333
356
 
334
357
  const meter: ContextLedgerGroup[] = [...groups];
335
- if (reserveTokens > 0) {
336
- meter.push({
337
- category: "reserve",
338
- label: CONTEXT_CATEGORY_LABEL.reserve,
339
- tokens: reserveTokens,
340
- percent: percentOf(reserveTokens, window),
341
- });
342
- }
343
358
  if (window > 0) {
344
359
  meter.push({
345
360
  category: "free",
@@ -348,6 +363,14 @@ export function buildContextLedger(input: BuildContextLedgerInput): ContextLedge
348
363
  percent: percentOf(freeTokens, window),
349
364
  });
350
365
  }
366
+ if (reserveTokens > 0) {
367
+ meter.push({
368
+ category: "reserve",
369
+ label: CONTEXT_CATEGORY_LABEL.reserve,
370
+ tokens: reserveTokens,
371
+ percent: percentOf(reserveTokens, window),
372
+ });
373
+ }
351
374
 
352
375
  return {
353
376
  provider: input.provider ?? null,
@@ -369,5 +392,6 @@ export function buildContextLedger(input: BuildContextLedgerInput): ContextLedge
369
392
  meter,
370
393
  lastCompaction: input.lastCompaction ?? null,
371
394
  promptCache: input.promptCache ?? null,
395
+ prewarm: input.prewarm ?? null,
372
396
  };
373
397
  }
@@ -61,6 +61,12 @@ export type {
61
61
  export { isSessionEntry, isSessionHeader, SESSION_ENTRY_KINDS } from "./entries.js";
62
62
  export { SessionManifest } from "./manifest.js";
63
63
  export { CURRENT_SESSION_FORMAT_VERSION, runMigrations } from "./migrations/index.js";
64
+ export type { ExpectedColdReasonCount, PromptCacheTelemetry } from "./prompt-cache.js";
65
+ export {
66
+ foldPromptCacheTelemetry,
67
+ hasPromptCacheTelemetry,
68
+ topExpectedColdReason,
69
+ } from "./prompt-cache.js";
64
70
  export {
65
71
  protectedArtifactEntryFromArtifact,
66
72
  protectedArtifactFromSessionEntry,