@iowarp/clio-coder 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (595) hide show
  1. package/CHANGELOG.md +90 -2
  2. package/CONTRIBUTING.md +23 -23
  3. package/README.md +284 -613
  4. package/dist/{acp-FPR54DGL.js → acp-BIYHVZIM.js} +43 -53
  5. package/dist/{agents-OGPIHPJH.js → agents-YT6SSRIT.js} +43 -26
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
  8. package/dist/{chunk-PV4JUBVJ.js → chunk-2EHAIA3X.js} +40 -21
  9. package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
  10. package/dist/chunk-2SFS6XQE.js +122 -0
  11. package/dist/chunk-2VTFPG5O.js +48 -0
  12. package/dist/{chunk-MAR7Y6HW.js → chunk-3ZXDFGR5.js} +23 -16
  13. package/dist/chunk-4BJ5BYCE.js +61 -0
  14. package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
  15. package/dist/chunk-4KLWL3UC.js +18 -0
  16. package/dist/chunk-4VP4KH3K.js +962 -0
  17. package/dist/chunk-4ZG3XFUR.js +77 -0
  18. package/dist/chunk-5B2AEOW5.js +5407 -0
  19. package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
  20. package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
  21. package/dist/chunk-65DEGPJ6.js +52 -0
  22. package/dist/chunk-6EJMN2Y3.js +17 -0
  23. package/dist/chunk-6EJV5X2W.js +16405 -0
  24. package/dist/chunk-6N5PTWMY.js +136 -0
  25. package/dist/chunk-6XLNIQDB.js +27 -0
  26. package/dist/{chunk-TEKV33Q5.js → chunk-77VKQEHF.js} +65 -33
  27. package/dist/chunk-7CR24IG7.js +242 -0
  28. package/dist/{chunk-M5T5VO65.js → chunk-7EYHLWU7.js} +837 -635
  29. package/dist/chunk-7MNJORFF.js +22 -0
  30. package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
  31. package/dist/chunk-AGYYIBLL.js +1069 -0
  32. package/dist/chunk-AO4RKG4M.js +277 -0
  33. package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
  34. package/dist/chunk-ARBGF5F7.js +174 -0
  35. package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
  36. package/dist/chunk-CBCAPZAA.js +229 -0
  37. package/dist/chunk-CMZWFGD2.js +352 -0
  38. package/dist/chunk-ECH6PKUQ.js +39 -0
  39. package/dist/chunk-ED4KHGC3.js +143 -0
  40. package/dist/chunk-EKMEHE4H.js +340 -0
  41. package/dist/{chunk-RPTR2H26.js → chunk-EPVUXGXG.js} +21 -15
  42. package/dist/chunk-FCSXB6T2.js +338 -0
  43. package/dist/chunk-FJ3H4MN5.js +48 -0
  44. package/dist/chunk-FQ4SKYE4.js +29 -0
  45. package/dist/chunk-G2DE3C7R.js +644 -0
  46. package/dist/chunk-G4BMMOKF.js +182 -0
  47. package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
  48. package/dist/chunk-HC4CLZ2Y.js +68 -0
  49. package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
  50. package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
  51. package/dist/chunk-I4HZDVNP.js +73 -0
  52. package/dist/{chunk-4QKXUHSR.js → chunk-IGLFWIYI.js} +70 -20
  53. package/dist/chunk-IKCO5N3L.js +162 -0
  54. package/dist/chunk-IR4CFBFN.js +56 -0
  55. package/dist/{chunk-PFEFKVGL.js → chunk-J5HN4RYU.js} +13 -11
  56. package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
  57. package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
  58. package/dist/chunk-KJ5LWLOE.js +1077 -0
  59. package/dist/chunk-LBMZMYH2.js +285 -0
  60. package/dist/{chunk-G34LV2PF.js → chunk-LBNRH5WM.js} +84 -170
  61. package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
  62. package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
  63. package/dist/chunk-MAW544W2.js +1882 -0
  64. package/dist/chunk-MBS4V7ZP.js +217 -0
  65. package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
  66. package/dist/chunk-MNA4JGU4.js +255 -0
  67. package/dist/chunk-MQSRRFWA.js +3428 -0
  68. package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
  69. package/dist/chunk-OAO4GE4M.js +619 -0
  70. package/dist/chunk-OHHN2SO4.js +5135 -0
  71. package/dist/chunk-OKGUZO2U.js +34 -0
  72. package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
  73. package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
  74. package/dist/chunk-OQE5J4C6.js +73 -0
  75. package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
  76. package/dist/chunk-POHLU5DW.js +1186 -0
  77. package/dist/chunk-QKMUKYO7.js +4961 -0
  78. package/dist/{chunk-ASND7OZK.js → chunk-QTYWRVRA.js} +13 -13
  79. package/dist/{chunk-EYOKLTMF.js → chunk-SRF2PJNW.js} +17 -3
  80. package/dist/chunk-SST6Z5JA.js +80 -0
  81. package/dist/chunk-STBPMHSX.js +2456 -0
  82. package/dist/chunk-T6YILFSB.js +80 -0
  83. package/dist/chunk-TZTZS7QK.js +227 -0
  84. package/dist/chunk-UOV2BYIW.js +107 -0
  85. package/dist/{chunk-Q3RUPKEJ.js → chunk-V4RXGQ5Q.js} +58 -189
  86. package/dist/chunk-VAKQQHWR.js +434 -0
  87. package/dist/chunk-VG7TBQIY.js +128 -0
  88. package/dist/chunk-VJWL6YS5.js +244 -0
  89. package/dist/chunk-WEH5XRJQ.js +32 -0
  90. package/dist/chunk-WMSVI4G2.js +2095 -0
  91. package/dist/chunk-WVO7V2QY.js +797 -0
  92. package/dist/chunk-X4RCMKVQ.js +641 -0
  93. package/dist/chunk-X75S7HFS.js +374 -0
  94. package/dist/chunk-XN3L4EYL.js +46 -0
  95. package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
  96. package/dist/chunk-YHZX5GEU.js +193 -0
  97. package/dist/chunk-YXLYO42X.js +91 -0
  98. package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
  99. package/dist/chunk-ZI647VB5.js +37 -0
  100. package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
  101. package/dist/cli/index.js +62 -54
  102. package/dist/clio-4LY5K2AC.js +25 -0
  103. package/dist/code-nav-7AX6FYE6.js +600 -0
  104. package/dist/codewiki/build-worker.js +66 -0
  105. package/dist/compile-cache-CVJMMODC.js +18 -0
  106. package/dist/{components-DMAOEKFB.js → components-KELWS457.js} +11 -6
  107. package/dist/{config-IRUQ7SE4.js → config-GTLUW2PR.js} +92 -55
  108. package/dist/configure-R6A64DHX.js +42 -0
  109. package/dist/context-5VKGUVJJ.js +866 -0
  110. package/dist/{context-3KWFLHJG.js → context-JFZEJ7W5.js} +15 -13
  111. package/dist/{context-5RADCKTR.js → context-RW5HC47S.js} +71 -35
  112. package/dist/{context-clear-7TSNPAAI.js → context-clear-6ZHBAZZT.js} +54 -28
  113. package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
  114. package/dist/dispatch-runner-VKBRCWQC.js +1997 -0
  115. package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
  116. package/dist/{doctor-UC5NAJYQ.js → doctor-KI767GSN.js} +27 -17
  117. package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
  118. package/dist/{evidence-YEGUW4L3.js → evidence-UA6AWDQQ.js} +46 -26
  119. package/dist/{evolve-TXARCTPG.js → evolve-QNTFGV6Z.js} +45 -25
  120. package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
  121. package/dist/{fleet-6G3DHNYE.js → fleet-Q7UOMUSG.js} +163 -54
  122. package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
  123. package/dist/{init-KZ5QTF6M.js → init-WBB65ZHQ.js} +69 -32
  124. package/dist/{memory-73ESV5YC.js → memory-MD3O64RI.js} +48 -27
  125. package/dist/{models-A4PVNWJK.js → models-BZU34YWD.js} +39 -25
  126. package/dist/monitor-MEQA5C3I.js +661 -0
  127. package/dist/{chunk-FCIH3BIZ.js → orchestrator-CGFKEP27.js} +11832 -8687
  128. package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
  129. package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
  130. package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
  131. package/dist/{run-YTPEYQOH.js → run-IV4Q6RLN.js} +101 -61
  132. package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
  133. package/dist/{skills-2V6RA3OQ.js → skills-LQEKRDTN.js} +34 -14
  134. package/dist/{skills-eval-S2TVJO4F.js → skills-eval-3DC4HEWS.js} +70 -34
  135. package/dist/steer-GGWFUJUD.js +77 -0
  136. package/dist/{targets-TYXLPB23.js → targets-C4SSGQOB.js} +43 -27
  137. package/dist/terminal-lease-IT5JW2NR.js +395 -0
  138. package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
  139. package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
  140. package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
  141. package/dist/{upgrade-33G2LMM5.js → upgrade-7TT7SQ3G.js} +45 -25
  142. package/dist/{usage-ZAFSXKKG.js → usage-GV4PKT3M.js} +62 -31
  143. package/dist/verify-G6V4D2G7.js +716 -0
  144. package/dist/web-fetch-2YHJ3KTG.js +638 -0
  145. package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-DQF6Z66B.js} +74 -34
  146. package/dist/worker/entry.js +221 -36
  147. package/dist/workspace-G4ZWUIPR.js +22 -0
  148. package/docs/README.md +22 -17
  149. package/docs/acp.md +168 -16
  150. package/docs/alcf-provider.md +1 -1
  151. package/docs/architecture.md +136 -7
  152. package/docs/artifact-versions.md +1 -1
  153. package/docs/built-in-agents.md +1 -1
  154. package/docs/capacity-and-scheduling.md +1 -1
  155. package/docs/commands-and-modes.md +114 -71
  156. package/docs/config-knobs-audit.md +1 -3
  157. package/docs/configuration-and-targets.md +174 -46
  158. package/docs/context-engine.md +29 -6
  159. package/docs/development-pipeline.md +26 -1
  160. package/docs/dispatch-architecture-rationale.md +1 -1
  161. package/docs/documentation-coverage.md +2 -2
  162. package/docs/documentation-guide.md +1 -1
  163. package/docs/environment-variables.md +13 -5
  164. package/docs/eval-runner.md +1 -1
  165. package/docs/evals-internal.md +1 -1
  166. package/docs/evidence-and-memory.md +6 -2
  167. package/docs/evolution.md +2 -2
  168. package/docs/exit-codes-and-output.md +15 -9
  169. package/docs/extensions-and-sharing.md +9 -9
  170. package/docs/fleet-dispatch.md +7 -5
  171. package/docs/git-commit-provenance.md +120 -0
  172. package/docs/glossary.md +1 -1
  173. package/docs/installation-and-lifecycle.md +34 -27
  174. package/docs/middleware-and-components.md +1 -1
  175. package/docs/model-catalog.md +45 -14
  176. package/docs/observability.md +8 -5
  177. package/docs/performance-methodology.md +491 -0
  178. package/docs/pi-boundary.md +72 -0
  179. package/docs/proactive-memory.md +3 -3
  180. package/docs/prompt-envelope-and-tools.md +24 -3
  181. package/docs/provider-adapter-cookbook.md +57 -4
  182. package/docs/release-cut-checklist.md +129 -115
  183. package/docs/safety-model.md +9 -5
  184. package/docs/scientific-validation.md +3 -3
  185. package/docs/session-lifecycle.md +55 -12
  186. package/docs/skills-marketplace.md +12 -8
  187. package/docs/time-conventions.md +1 -1
  188. package/docs/tool-usage.md +3 -3
  189. package/docs/trace-store.md +1 -1
  190. package/docs/troubleshooting.md +10 -7
  191. package/docs/tui-design.md +47 -10
  192. package/docs/worker-dispatch-mechanics.md +1 -1
  193. package/package.json +19 -22
  194. package/skills/coding/ast-grep/SKILL.md +136 -0
  195. package/skills/coding/ast-grep/evals.md +56 -0
  196. package/skills/coding/ast-grep/references/rule_reference.md +297 -0
  197. package/skills/coding/coding-standards/SKILL.md +113 -0
  198. package/skills/coding/coding-standards/evals.md +34 -0
  199. package/skills/coding/prototype/SKILL.md +86 -0
  200. package/skills/coding/prototype/evals.md +42 -0
  201. package/skills/coding/prototype/references/LOGIC.md +67 -0
  202. package/skills/coding/prototype/references/UI.md +112 -0
  203. package/skills/coding/tdd/SKILL.md +101 -0
  204. package/skills/coding/tdd/evals.md +41 -0
  205. package/skills/coding/tdd/references/mocking.md +59 -0
  206. package/skills/coding/tdd/references/tests.md +77 -0
  207. package/skills/context/context-handoff/SKILL.md +126 -0
  208. package/skills/context/context-handoff/evals.md +57 -0
  209. package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
  210. package/skills/context/context-prime/SKILL.md +95 -0
  211. package/skills/context/context-prime/evals.md +54 -0
  212. package/skills/meta/clio-dev/SKILL.md +91 -0
  213. package/skills/meta/clio-dev/evals.md +45 -0
  214. package/skills/meta/clio-test/SKILL.md +130 -0
  215. package/skills/meta/clio-test/evals.md +43 -0
  216. package/skills/meta/clio-test/references/harness.md +97 -0
  217. package/skills/meta/clio-test/references/test-map.md +59 -0
  218. package/skills/meta/credentials/SKILL.md +125 -0
  219. package/skills/meta/credentials/evals.md +104 -0
  220. package/skills/meta/find-skills/SKILL.md +72 -0
  221. package/skills/meta/find-skills/evals.md +47 -0
  222. package/skills/meta/herdr/SKILL.md +127 -0
  223. package/skills/meta/herdr/evals.md +38 -0
  224. package/skills/meta/skill-craft/SKILL.md +102 -0
  225. package/skills/meta/skill-craft/evals.md +41 -0
  226. package/skills/planning/architecture/SKILL.md +129 -0
  227. package/skills/planning/architecture/evals.md +36 -0
  228. package/skills/planning/backlog/SKILL.md +90 -0
  229. package/skills/planning/backlog/evals.md +43 -0
  230. package/skills/planning/prd/SKILL.md +82 -0
  231. package/skills/planning/prd/evals.md +49 -0
  232. package/skills/planning/product-intent/SKILL.md +112 -0
  233. package/skills/planning/product-intent/evals.md +36 -0
  234. package/skills/planning/tech-spec/SKILL.md +115 -0
  235. package/skills/planning/tech-spec/evals.md +47 -0
  236. package/skills/registry.yaml +136 -0
  237. package/skills/research/arxiv-literature/SKILL.md +104 -0
  238. package/skills/research/arxiv-literature/evals.md +58 -0
  239. package/skills/research/experiment-protocol/SKILL.md +122 -0
  240. package/skills/research/experiment-protocol/evals.md +91 -0
  241. package/skills/research/scientific-debugging/SKILL.md +119 -0
  242. package/skills/research/scientific-debugging/evals.md +138 -0
  243. package/skills/research/scientific-modernization/SKILL.md +138 -0
  244. package/skills/research/scientific-modernization/evals.md +84 -0
  245. package/skills/workflow/design-council/SKILL.md +139 -0
  246. package/skills/workflow/design-council/evals.md +97 -0
  247. package/skills/workflow/grill-me/SKILL.md +186 -0
  248. package/skills/workflow/grill-me/evals.md +78 -0
  249. package/skills/workflow/workflow-distiller/SKILL.md +136 -0
  250. package/skills/workflow/workflow-distiller/evals.md +107 -0
  251. package/src/cli/acp.ts +31 -4
  252. package/src/cli/clio.ts +68 -6
  253. package/src/cli/config-inspect.ts +28 -22
  254. package/src/cli/configure.ts +47 -9
  255. package/src/cli/context-clear.ts +2 -2
  256. package/src/cli/context-index.ts +21 -23
  257. package/src/cli/context.ts +13 -8
  258. package/src/cli/default-target.ts +9 -17
  259. package/src/cli/docs.ts +11 -5
  260. package/src/cli/evidence.ts +4 -1
  261. package/src/cli/extensions.ts +10 -1
  262. package/src/cli/fleet.ts +47 -6
  263. package/src/cli/index.ts +55 -26
  264. package/src/cli/memory.ts +3 -1
  265. package/src/cli/models.ts +1 -1
  266. package/src/cli/modes/json-stream.ts +37 -1
  267. package/src/cli/modes/print.ts +24 -9
  268. package/src/cli/run.ts +2 -2
  269. package/src/cli/skills-eval.ts +23 -8
  270. package/src/cli/skills.ts +19 -4
  271. package/src/cli/targets.ts +4 -0
  272. package/src/cli/text-layout.ts +15 -5
  273. package/src/cli/trace.ts +62 -14
  274. package/src/cli/upgrade.ts +18 -2
  275. package/src/cli/usage.ts +10 -3
  276. package/src/cli/wiki-generate.ts +2 -1
  277. package/src/core/agent-environment.ts +7 -0
  278. package/src/core/bash-exec.ts +72 -1
  279. package/src/core/boot-trace.ts +9 -4
  280. package/src/core/bus-events.ts +20 -4
  281. package/src/core/commit-attribution.ts +157 -0
  282. package/src/core/compile-cache.ts +159 -0
  283. package/src/core/config.ts +131 -2
  284. package/src/core/defaults.ts +39 -5
  285. package/src/core/domain-loader.ts +12 -5
  286. package/src/core/git-commit-attribution.ts +362 -0
  287. package/src/core/incomplete-installation.ts +45 -0
  288. package/src/core/response-schema.ts +1 -1
  289. package/src/core/safe-exec.ts +13 -1
  290. package/src/core/settings-layers.ts +155 -21
  291. package/src/core/skill-activation.ts +1 -1
  292. package/src/core/startup-timer.ts +3 -3
  293. package/src/core/state-file-lock.ts +13 -1
  294. package/src/core/termination.ts +78 -5
  295. package/src/domains/config/classify.ts +15 -3
  296. package/src/domains/config/extension.ts +19 -13
  297. package/src/domains/config/index.ts +10 -0
  298. package/src/domains/config/keybindings.ts +42 -6
  299. package/src/domains/context/bootstrap-prompt.ts +1 -1
  300. package/src/domains/context/bootstrap.ts +111 -18
  301. package/src/domains/context/clear.ts +16 -11
  302. package/src/domains/context/clio-md.ts +111 -9
  303. package/src/domains/context/codewiki/artifact.ts +400 -0
  304. package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
  305. package/src/domains/context/codewiki/build-worker.ts +54 -0
  306. package/src/domains/context/codewiki/coordinator.ts +182 -0
  307. package/src/domains/context/codewiki/indexer.ts +59 -144
  308. package/src/domains/context/codewiki/paths.ts +67 -0
  309. package/src/domains/context/codewiki/schema.ts +80 -0
  310. package/src/domains/context/codewiki/tree-sitter.ts +1 -1
  311. package/src/domains/context/contract.ts +11 -5
  312. package/src/domains/context/extension.ts +94 -143
  313. package/src/domains/context/fingerprint.ts +3 -1
  314. package/src/domains/context/index.ts +12 -22
  315. package/src/domains/context/project-metadata.ts +19 -0
  316. package/src/domains/context/prompt-context.ts +9 -10
  317. package/src/domains/context/refresh.ts +29 -21
  318. package/src/domains/context/runtime.ts +17 -0
  319. package/src/domains/context/wiki/generate.ts +39 -34
  320. package/src/domains/context/wiki/plan.ts +1 -1
  321. package/src/domains/context/wiki/prompts.ts +21 -8
  322. package/src/domains/dispatch/code-step.ts +20 -1
  323. package/src/domains/dispatch/extension.ts +158 -21
  324. package/src/domains/dispatch/failure-classification.ts +6 -0
  325. package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
  326. package/src/domains/dispatch/orphan-recovery.ts +50 -8
  327. package/src/domains/dispatch/receipt-integrity.ts +5 -0
  328. package/src/domains/dispatch/state.ts +31 -6
  329. package/src/domains/dispatch/transport.ts +2 -1
  330. package/src/domains/dispatch/types.ts +14 -0
  331. package/src/domains/dispatch/worker-spawn.ts +21 -2
  332. package/src/domains/eval/metrics/context.ts +1 -1
  333. package/src/domains/eval/types.ts +0 -1
  334. package/src/domains/evidence/build.ts +41 -1
  335. package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
  336. package/src/domains/lifecycle/migrations/index.ts +24 -4
  337. package/src/domains/middleware/hooks-io.ts +12 -0
  338. package/src/domains/middleware/skills-reminder.ts +30 -15
  339. package/src/domains/prompts/compiler.ts +142 -84
  340. package/src/domains/prompts/contract.ts +18 -2
  341. package/src/domains/prompts/extension.ts +39 -7
  342. package/src/domains/prompts/fragment-loader.ts +0 -1
  343. package/src/domains/prompts/fragments/identity/clio.md +2 -4
  344. package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
  345. package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
  346. package/src/domains/prompts/fragments/operating/contract.md +4 -50
  347. package/src/domains/prompts/fragments/operating/delegation.md +42 -0
  348. package/src/domains/prompts/fragments/operating/skills.md +26 -0
  349. package/src/domains/prompts/fragments/operating/worker.md +16 -0
  350. package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
  351. package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
  352. package/src/domains/prompts/fragments/safety/read-only.md +4 -4
  353. package/src/domains/prompts/fragments/safety/suggest.md +2 -2
  354. package/src/domains/prompts/fragments/wiki/page.md +10 -0
  355. package/src/domains/prompts/fragments/wiki/plan.md +10 -0
  356. package/src/domains/prompts/preload.ts +3 -3
  357. package/src/domains/providers/auth/api-key.ts +1 -1
  358. package/src/domains/providers/auth/backend-file.ts +20 -10
  359. package/src/domains/providers/auth/backend-memory.ts +59 -4
  360. package/src/domains/providers/auth/boot-status.ts +65 -0
  361. package/src/domains/providers/auth/oauth.ts +2 -1
  362. package/src/domains/providers/auth/storage.ts +97 -38
  363. package/src/domains/providers/capabilities.ts +12 -4
  364. package/src/domains/providers/contract.ts +15 -4
  365. package/src/domains/providers/extension.ts +18 -6
  366. package/src/domains/providers/model-runtime-capabilities.ts +15 -4
  367. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
  368. package/src/domains/providers/plugins.ts +5 -3
  369. package/src/domains/providers/probe/fingerprint.ts +25 -5
  370. package/src/domains/providers/registry.ts +31 -10
  371. package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
  372. package/src/domains/providers/runtimes/builtins.ts +2 -2
  373. package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
  374. package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
  375. package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
  376. package/src/domains/providers/support.ts +6 -3
  377. package/src/domains/providers/types/local-model-quirks.ts +7 -9
  378. package/src/domains/providers/types/runtime-descriptor.ts +12 -1
  379. package/src/domains/providers/types/target-descriptor.ts +22 -0
  380. package/src/domains/resources/contract.ts +0 -1
  381. package/src/domains/resources/extension.ts +1 -3
  382. package/src/domains/resources/loader.ts +3 -4
  383. package/src/domains/resources/prompts/loader.ts +16 -2
  384. package/src/domains/resources/prompts/substitute.ts +1 -65
  385. package/src/domains/resources/skills/content-hash.ts +2 -0
  386. package/src/domains/resources/skills/install.ts +17 -0
  387. package/src/domains/resources/skills/loader.ts +17 -10
  388. package/src/domains/resources/skills/marketplace.ts +55 -9
  389. package/src/domains/safety/action-classifier.ts +4 -2
  390. package/src/domains/safety/audit.ts +8 -2
  391. package/src/domains/safety/extension.ts +1 -1
  392. package/src/domains/session/compaction/branch-summary.ts +3 -2
  393. package/src/domains/session/compaction/cut-point.ts +2 -1
  394. package/src/domains/session/compaction/tokens.ts +2 -1
  395. package/src/domains/session/context-ledger.ts +14 -0
  396. package/src/domains/session/contract.ts +15 -0
  397. package/src/domains/session/decision-board.ts +190 -0
  398. package/src/domains/session/entries.ts +66 -3
  399. package/src/domains/session/extension.ts +93 -12
  400. package/src/domains/session/retry.ts +10 -18
  401. package/src/domains/session/session-artifacts.ts +107 -0
  402. package/src/domains/session/task-board.ts +207 -13
  403. package/src/domains/session/tree/active-path.ts +44 -5
  404. package/src/domains/session/tree/fork.ts +26 -27
  405. package/src/domains/session/tree/preview.ts +2 -2
  406. package/src/domains/session/workspace/git-probe.ts +17 -11
  407. package/src/domains/user-tasks/store.ts +297 -0
  408. package/src/engine/acp/errors.ts +96 -0
  409. package/src/engine/acp/server.ts +1728 -146
  410. package/src/engine/acp/transport.ts +135 -14
  411. package/src/engine/acp/types.ts +26 -0
  412. package/src/engine/agent.ts +3 -3
  413. package/src/engine/ai.ts +32 -27
  414. package/src/engine/alcf-oauth.ts +26 -19
  415. package/src/engine/api-registry.ts +223 -0
  416. package/src/engine/apis/index.ts +3 -7
  417. package/src/engine/apis/llamacpp-residency.ts +49 -9
  418. package/src/engine/apis/lmstudio-residency.ts +5 -21
  419. package/src/engine/apis/lmstudio.ts +243 -0
  420. package/src/engine/apis/ollama-native.ts +24 -3
  421. package/src/engine/apis/openai-completions.ts +170 -91
  422. package/src/engine/apis/residency.ts +139 -3
  423. package/src/engine/apis/types.ts +16 -0
  424. package/src/engine/env-api-keys.ts +98 -0
  425. package/src/engine/gemma-channel-filter.ts +223 -0
  426. package/src/engine/instrumented-tui.ts +192 -0
  427. package/src/engine/messages.ts +14 -0
  428. package/src/engine/models.ts +42 -0
  429. package/src/engine/oauth.ts +16 -12
  430. package/src/engine/prompt-templates.ts +1 -0
  431. package/src/engine/provider-payload.ts +16 -59
  432. package/src/engine/strip-tokenizer-sentinels.ts +1 -1
  433. package/src/engine/truncate.ts +9 -0
  434. package/src/engine/tui.ts +17 -9
  435. package/src/engine/types.ts +3 -6
  436. package/src/engine/worker-runtime-capabilities.ts +5 -0
  437. package/src/engine/worker-runtime.ts +1 -1
  438. package/src/engine/worker-tools.ts +9 -4
  439. package/src/entry/boot-options.ts +50 -0
  440. package/src/entry/orchestrator.ts +288 -150
  441. package/src/interactive/application-controller.ts +89 -2
  442. package/src/interactive/chat-loop.ts +266 -41
  443. package/src/interactive/chat-panel.ts +173 -47
  444. package/src/interactive/chat-renderer.ts +262 -72
  445. package/src/interactive/clio-editor.ts +3 -8
  446. package/src/interactive/command-fallbacks.ts +2 -2
  447. package/src/interactive/context-overlay.ts +27 -1
  448. package/src/interactive/editor-submit.ts +228 -24
  449. package/src/interactive/export-html/ansi-to-html.ts +161 -0
  450. package/src/interactive/export-html/index.ts +51 -0
  451. package/src/interactive/export-html/template.ts +45 -0
  452. package/src/interactive/export-html/tool-renderer.ts +54 -0
  453. package/src/interactive/footer/dashboard.ts +4 -0
  454. package/src/interactive/footer/notifications.ts +1 -1
  455. package/src/interactive/footer/widgets.ts +20 -2
  456. package/src/interactive/footer-panel.ts +2 -2
  457. package/src/interactive/format-time.ts +14 -2
  458. package/src/interactive/interactive-application.ts +201 -17
  459. package/src/interactive/interactive-event-projection.ts +6 -1
  460. package/src/interactive/interactive-input-runtime.ts +50 -4
  461. package/src/interactive/interactive-presentation.ts +151 -19
  462. package/src/interactive/interactive-shell.ts +268 -14
  463. package/src/interactive/interactive-slash-runtime.ts +176 -114
  464. package/src/interactive/interactive-tickers.ts +38 -7
  465. package/src/interactive/keybinding-manager.ts +1 -1
  466. package/src/interactive/layout.ts +40 -3
  467. package/src/interactive/overlay-frame.ts +1 -1
  468. package/src/interactive/overlay-general-openers.ts +58 -1
  469. package/src/interactive/overlay-key-routing.ts +3 -0
  470. package/src/interactive/overlay-lifecycle.ts +13 -0
  471. package/src/interactive/overlay-permission-lifecycle.ts +2 -1
  472. package/src/interactive/overlay-session-lifecycle.ts +69 -12
  473. package/src/interactive/overlays/decisions.ts +300 -0
  474. package/src/interactive/overlays/help-reference.ts +15 -10
  475. package/src/interactive/overlays/model-selector.ts +34 -16
  476. package/src/interactive/overlays/session-selector.ts +18 -0
  477. package/src/interactive/overlays/settings.ts +105 -17
  478. package/src/interactive/overlays/skills-hub.ts +4 -4
  479. package/src/interactive/overlays/tree-selector.ts +41 -6
  480. package/src/interactive/render-trace.ts +499 -90
  481. package/src/interactive/renderers/compaction-summary.ts +2 -2
  482. package/src/interactive/renderers/diff.ts +115 -104
  483. package/src/interactive/renderers/mermaid.ts +53 -0
  484. package/src/interactive/renderers/tool-execution.ts +386 -133
  485. package/src/interactive/renderers/worker-entry.ts +20 -4
  486. package/src/interactive/session-switch-settlement.ts +10 -0
  487. package/src/interactive/slash-autocomplete.ts +6 -114
  488. package/src/interactive/slash-commands.ts +135 -47
  489. package/src/interactive/slash-spec.ts +9 -38
  490. package/src/interactive/status/controller.ts +5 -1
  491. package/src/interactive/stdout-backpressure.ts +99 -0
  492. package/src/interactive/stream-pacer.ts +530 -0
  493. package/src/interactive/stream-pacing-policy.ts +66 -0
  494. package/src/interactive/tasks-overlay.ts +368 -14
  495. package/src/interactive/terminal-lease.ts +485 -0
  496. package/src/interactive/theme/tokens.ts +1 -1
  497. package/src/interactive/turn-context.ts +4 -3
  498. package/src/interactive/turn-persistence.ts +30 -13
  499. package/src/interactive/turn-queues.ts +12 -0
  500. package/src/interactive/turn-recovery.ts +25 -8
  501. package/src/interactive/turn-runtime.ts +79 -12
  502. package/src/interactive/turn-state.ts +10 -0
  503. package/src/interactive/view/artifacts.ts +114 -4
  504. package/src/interactive/view/view-overlay.ts +3 -0
  505. package/src/interactive/welcome-dashboard.ts +17 -16
  506. package/src/interactive/worker-receipts.ts +52 -3
  507. package/src/interactive/worker-stream.ts +5 -1
  508. package/src/tools/agent-tools.ts +23 -3
  509. package/src/tools/artifact.ts +2 -2
  510. package/src/tools/ask-user.ts +23 -13
  511. package/src/tools/bash.ts +30 -2
  512. package/src/tools/bootstrap.ts +34 -431
  513. package/src/tools/builtin-tool-catalog.ts +265 -0
  514. package/src/tools/codewiki/code-nav-surface.ts +29 -0
  515. package/src/tools/codewiki/code-nav.ts +8 -22
  516. package/src/tools/codewiki/shared.ts +41 -38
  517. package/src/tools/context/docs-engine.ts +14 -3
  518. package/src/tools/context/index.ts +107 -28
  519. package/src/tools/context/surface.ts +19 -0
  520. package/src/tools/core-bootstrap.ts +168 -0
  521. package/src/tools/credential-present.ts +5 -5
  522. package/src/tools/dispatch-admission.ts +533 -0
  523. package/src/tools/dispatch-background.ts +54 -0
  524. package/src/tools/dispatch-event-text.ts +6 -0
  525. package/src/tools/dispatch-plan.ts +9 -4
  526. package/src/tools/dispatch-run-events.ts +238 -0
  527. package/src/tools/dispatch-runner.ts +2370 -0
  528. package/src/tools/dispatch-scout-admission.ts +295 -0
  529. package/src/tools/dispatch-types.ts +77 -0
  530. package/src/tools/dispatch.ts +67 -3161
  531. package/src/tools/find.ts +4 -2
  532. package/src/tools/grep.ts +2 -2
  533. package/src/tools/lazy-tool.ts +60 -0
  534. package/src/tools/ledger.ts +3 -3
  535. package/src/tools/monitor-surface.ts +36 -0
  536. package/src/tools/monitor.ts +2 -32
  537. package/src/tools/observers.ts +2 -2
  538. package/src/tools/registry.ts +39 -27
  539. package/src/tools/safe-exec.ts +2 -2
  540. package/src/tools/steer-surface.ts +17 -0
  541. package/src/tools/steer.ts +2 -13
  542. package/src/tools/tasks.ts +108 -11
  543. package/src/tools/truncate.ts +25 -184
  544. package/src/tools/verify/frontend.ts +3 -1
  545. package/src/tools/verify/index.ts +3 -38
  546. package/src/tools/verify/surface.ts +46 -0
  547. package/src/tools/web-fetch-surface.ts +23 -0
  548. package/src/tools/web-fetch.ts +2 -20
  549. package/src/tools/write.ts +7 -2
  550. package/src/worker/entry.ts +39 -2
  551. package/src/worker/spec-contract.ts +26 -5
  552. package/dist/chunk-7SS2CTV2.js +0 -61361
  553. package/dist/chunk-DKGKUHFA.js +0 -924
  554. package/dist/chunk-GEP36Y4X.js +0 -12796
  555. package/dist/chunk-XYWBQRDM.js +0 -137
  556. package/dist/clio-BZVGEUFJ.js +0 -58
  557. package/dist/configure-S7S6F6CL.js +0 -32
  558. package/docs/html/agents_blueprint.html +0 -936
  559. package/docs/html/alcf_blueprint.html +0 -324
  560. package/docs/html/architecture_blueprint.html +0 -850
  561. package/docs/html/commands_blueprint.html +0 -939
  562. package/docs/html/config_knobs_audit_blueprint.html +0 -178
  563. package/docs/html/configuration_blueprint.html +0 -1080
  564. package/docs/html/context_blueprint.html +0 -603
  565. package/docs/html/documentation_blueprint.html +0 -832
  566. package/docs/html/environment_blueprint.html +0 -404
  567. package/docs/html/eval_blueprint.html +0 -743
  568. package/docs/html/evals_internal_blueprint.html +0 -190
  569. package/docs/html/evolution_blueprint.html +0 -674
  570. package/docs/html/extensions_blueprint.html +0 -2065
  571. package/docs/html/fleet_dispatch_blueprint.html +0 -286
  572. package/docs/html/index.html +0 -919
  573. package/docs/html/lifecycle_blueprint.html +0 -723
  574. package/docs/html/memory_blueprint.html +0 -699
  575. package/docs/html/middleware_blueprint.html +0 -664
  576. package/docs/html/models_blueprint.html +0 -2366
  577. package/docs/html/observability_blueprint.html +0 -683
  578. package/docs/html/provider_adapter_blueprint.html +0 -245
  579. package/docs/html/safety_blueprint.html +0 -1386
  580. package/docs/html/shared.css +0 -571
  581. package/docs/html/shared.js +0 -143
  582. package/docs/html/skills_blueprint.html +0 -671
  583. package/docs/html/soak_blueprint.html +0 -182
  584. package/docs/html/tool_usage_blueprint.html +0 -350
  585. package/docs/html/tools_blueprint.html +0 -2249
  586. package/docs/html/trace_blueprint.html +0 -235
  587. package/docs/html/tui_design_blueprint.html +0 -374
  588. package/docs/html/validation_blueprint.html +0 -961
  589. package/docs/html/worker_dispatch_blueprint.html +0 -231
  590. package/src/core/release.ts +0 -2
  591. package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
  592. package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
  593. package/src/engine/apis/lmstudio-native.ts +0 -1438
  594. package/src/engine/apis/thinking-replay.ts +0 -11
  595. package/src/tools/string-enum.ts +0 -15
@@ -40,8 +40,8 @@ import { createEngineAgent } from "../engine/agent.js";
40
40
  import { resolveReservedOutputTokens } from "../engine/apis/output-budget.js";
41
41
  import type { AgentEvent, AgentMessage, ImageContent } from "../engine/types.js";
42
42
  import { resolveSessionTools } from "../tools/agent-tools.js";
43
- import { finalizeAskUserInterview } from "../tools/ask-user.js";
44
- import type { ToolInvokeOptions, ToolRegistry } from "../tools/registry.js";
43
+ import { finalizeAskUserInterviewForHost } from "../tools/ask-user.js";
44
+ import type { AskUserToolPolicy, ToolInvokeOptions, ToolRegistry } from "../tools/registry.js";
45
45
  import {
46
46
  createAskUserToolPolicy,
47
47
  createPendingSkillToolPolicy,
@@ -53,17 +53,29 @@ import {
53
53
  toolSignatureFromState,
54
54
  } from "./chat-loop-messages.js";
55
55
  import { normalizeRetrySettings } from "./chat-loop-policy.js";
56
+ import type { ApprovalRequestView } from "./permission-overlay.js";
56
57
  import type { AgentStatusEvent } from "./status/types.js";
57
58
  import { createTurnContext } from "./turn-context.js";
58
59
  import { createTurnMiddleware } from "./turn-middleware.js";
59
60
  import { createTurnPersistence } from "./turn-persistence.js";
60
- import { createTurnQueues, type QueuedChatMessage, type QueuedMessagesSnapshot } from "./turn-queues.js";
61
- import { createTurnRecovery, type RetryStatusEvent, reclassifyStallAbort } from "./turn-recovery.js";
62
- import { type AssistantDeltaEvent, createTurnRuntime } from "./turn-runtime.js";
61
+ import {
62
+ createTurnQueues,
63
+ DEFAULT_STEERING_MODE,
64
+ type QueuedChatMessage,
65
+ type QueuedMessagesSnapshot,
66
+ type SteeringMode,
67
+ } from "./turn-queues.js";
68
+ import {
69
+ createTurnRecovery,
70
+ type RetryStatusEvent,
71
+ reclassifyStallAbort,
72
+ rewriteStallAbortMessage,
73
+ } from "./turn-recovery.js";
74
+ import { type AssistantDeltaEvent, createTurnRuntime, TurnAdmissionError } from "./turn-runtime.js";
63
75
  import { type AgentRuntime, type ChatLoopRunSnapshot, createTurnState } from "./turn-state.js";
64
76
  import { isWorkerShareNote } from "./worker-share.js";
65
77
 
66
- export type { QueuedChatMessage, QueuedMessageKind, QueuedMessagesSnapshot } from "./turn-queues.js";
78
+ export type { QueuedChatMessage, QueuedMessageKind, QueuedMessagesSnapshot, SteeringMode } from "./turn-queues.js";
67
79
  export type { RetryStatusEvent, RetryStatusPayload, RetryStatusPhase } from "./turn-recovery.js";
68
80
  export type { AssistantDeltaEvent } from "./turn-runtime.js";
69
81
  export type { ChatLoopRunSnapshot } from "./turn-state.js";
@@ -83,7 +95,8 @@ export interface QueueUpdateEvent {
83
95
  export interface QueuedUserTurnEvent {
84
96
  type: "queued_user_turn";
85
97
  text: string;
86
- kind: QueuedChatMessage["kind"];
98
+ /** `interrupt` marks a message that cancelled the run and was submitted as a fresh prompt. */
99
+ kind: QueuedChatMessage["kind"] | "interrupt";
87
100
  }
88
101
 
89
102
  /**
@@ -100,6 +113,13 @@ export interface ChatNoticeEvent {
100
113
  surface: "footer" | "transcript";
101
114
  text: string;
102
115
  key?: string;
116
+ /**
117
+ * Present only on a notice that reports a turn Clio refused to start. The
118
+ * `reason` is a closed-set code, not prose: protocol surfaces (the ACP
119
+ * server) fail the turn with it instead of returning an empty success, and
120
+ * every other surface renders the notice exactly as before.
121
+ */
122
+ admission?: { reason: string };
103
123
  }
104
124
 
105
125
  /**
@@ -112,11 +132,24 @@ export interface ChatNoticeEvent {
112
132
  * state here: the parked promise resolves blocked and the segment settles
113
133
  * through its ordinary `tool_execution_end`.
114
134
  */
115
- export interface ToolApprovalStateEvent {
116
- type: "tool_approval_state";
117
- toolCallId: string;
118
- state: "awaiting-approval" | "resumed";
119
- }
135
+ export type ToolApprovalStateEvent =
136
+ | {
137
+ type: "tool_approval_state";
138
+ toolCallId: string;
139
+ state: "awaiting-approval";
140
+ /**
141
+ * Already-redacted facts shown by the permission overlay. This payload
142
+ * exists only on the live event and is never written to the session
143
+ * ledger; the transcript renderer must not reconstruct safety facts
144
+ * from raw tool arguments.
145
+ */
146
+ view: ApprovalRequestView;
147
+ }
148
+ | {
149
+ type: "tool_approval_state";
150
+ toolCallId: string;
151
+ state: "resumed";
152
+ };
120
153
 
121
154
  export type ChatLoopEvent =
122
155
  | AgentEvent
@@ -136,14 +169,39 @@ export interface ChatSubmitOptions {
136
169
  pendingSkillRequests?: ReadonlyArray<PendingSkillRequest>;
137
170
  /** Internal middleware resubmit; does not reset the per-user-prompt stalled-turn nudge cap. */
138
171
  requestContinuation?: boolean;
172
+ /**
173
+ * Delivery mode when a run is active; ignored when idle. Defaults to
174
+ * `next-slot`. `interrupt` cancels the run, waits for it to settle, and
175
+ * submits the text as a fresh prompt; see {@link ChatLoop.interruptRefusal}
176
+ * for the two states in which it degrades to `next-slot` instead.
177
+ */
178
+ steering?: SteeringMode;
179
+ /**
180
+ * Fires once this submit owns the live turn (`isStreaming()` is true) and
181
+ * the next queued submit may use streaming queue routing. Stage 0 replay
182
+ * awaits it; the loop's own admission gate releases on it.
183
+ */
184
+ onAdmitted?: () => void;
185
+ }
186
+
187
+ /** Closing notice an operator interrupt leaves in the transcript and the ledger. */
188
+ const INTERRUPT_CANCEL_REASON = "[Clio Coder] run interrupted by operator; delivering the new message now.";
189
+ const ENGINE_ACTIVE_PROMPT_ERROR =
190
+ "Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.";
191
+ const ACTIVE_PROMPT_NOTICE =
192
+ "[Clio Coder] another response was already active, so this response could not start. Wait for it to finish, then submit again.";
193
+
194
+ function operatorFacingEngineError(message: string): string {
195
+ return message.includes(ENGINE_ACTIVE_PROMPT_ERROR) ? ACTIVE_PROMPT_NOTICE : message;
139
196
  }
140
197
 
141
198
  /**
142
199
  * Options for {@link ChatLoop.cancel}. A bare cancel is an operator Esc/Ctrl+C
143
200
  * that ends the in-flight turn as an empty aborted message. Passing a `reason`
144
- * marks the cancel as a system-initiated interrupt (the loop guard): the chat
145
- * loop persists a durable, visible assistant turn carrying that reason in place
146
- * of the empty aborted turn, and tags the audit trail with `source`.
201
+ * marks the cancel as an explained interrupt (the loop guard, or an operator
202
+ * interrupt-with-message): the chat loop persists a durable, visible assistant
203
+ * turn carrying that reason in place of the empty aborted turn, and tags the
204
+ * audit trail with `source`.
147
205
  */
148
206
  export interface ChatCancelOptions {
149
207
  /** Operator-facing explanation for a system-initiated stop. */
@@ -158,6 +216,15 @@ export interface ChatLoop {
158
216
  submit(text: string, options?: ChatSubmitOptions): Promise<void>;
159
217
  steer(text: string): boolean;
160
218
  queueFollowUp(text: string): boolean;
219
+ /**
220
+ * Why an interrupt would be refused right now, or null when it would
221
+ * cancel the run. An attached dispatch is refused because the parent's abort
222
+ * kills the worker's run and discards its work with no receipt; a parked
223
+ * permission ask is refused because it is already waiting on the operator.
224
+ * In both cases `submit(text, { steering: "interrupt" })` says so and
225
+ * queues the text for the next slot instead.
226
+ */
227
+ interruptRefusal(): string | null;
161
228
  clearQueuedFollowUps(): string[];
162
229
  queuedMessages(): QueuedMessagesSnapshot;
163
230
  cancel(options?: ChatCancelOptions): void;
@@ -176,11 +243,11 @@ export interface ChatLoop {
176
243
  /**
177
244
  * Force-run the compaction flow for the current session, swap the agent's
178
245
  * in-memory `state.messages` for a single bridge message carrying the
179
- * summary, and emit the standard summary notice. Used by the `/compact`
246
+ * summary, and emit the standard summary notice. Used by `/context compact`
180
247
  * slash command so the next user turn ships only the bridge plus the new
181
248
  * text to the provider (slice 12.5b bug 4). Silent no-op when no session
182
249
  * or no compaction deps are wired; in both cases emits a user-visible
183
- * notice so the `/compact` handler does not have to mirror the logic.
250
+ * notice so the `/context compact` handler does not have to mirror the logic.
184
251
  */
185
252
  compact(instructions?: string): Promise<void>;
186
253
  /**
@@ -302,6 +369,17 @@ export interface CreateChatLoopDeps {
302
369
  * composition; the loop owns the buffer the reminder lands in.
303
370
  */
304
371
  registerDeferredReminderSink?: (sink: (message: string) => void) => void;
372
+ /**
373
+ * Host-finalizer seam for branch-anchored interview snapshots. Called once,
374
+ * after the ask-user host finalizer has settled the policy and its transcript.
375
+ */
376
+ onAskUserFinalized?: (policy: AskUserToolPolicy) => void;
377
+ /**
378
+ * True while an attached `dispatch` call is running. An interrupt is refused
379
+ * in that state; the composition root wires this from the dispatch
380
+ * background registry, which holds exactly the attached calls.
381
+ */
382
+ hasAttachedDispatch?: () => boolean;
305
383
  }
306
384
 
307
385
  export function reloadProtectedArtifactsForSession(
@@ -347,6 +425,29 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
347
425
  emit({ type: "notice", level, surface: "transcript", text, ...(key === undefined ? {} : { key }) });
348
426
  };
349
427
 
428
+ /**
429
+ * The same transcript notice every admission exit already emitted, carrying
430
+ * the reason the turn never started. Text, level, and surface are unchanged,
431
+ * so the TUI and headless paths render exactly what they rendered before.
432
+ */
433
+ const emitAdmissionNotice = (text: string, reason: string): void => {
434
+ emit({ type: "notice", level: "info", surface: "transcript", text, admission: { reason } });
435
+ };
436
+
437
+ /**
438
+ * Which of the two settings is actually missing when the runtime resolves to
439
+ * null. Both halves produce the same operator-facing notice, but a machine
440
+ * consumer of the reason (the ACP server reports it as `data.reason`) needs
441
+ * to tell "no orchestrator at all" from "a target that names no model", and
442
+ * collapsing them sent a client with a configured target to the wrong fix.
443
+ */
444
+ const nullRuntimeAdmissionReason = (): string => {
445
+ const orchestrator = deps.getSettings().orchestrator;
446
+ const target = orchestrator.target?.trim() ?? "";
447
+ const model = orchestrator.model?.trim() ?? "";
448
+ return target.length > 0 && model.length === 0 ? "model-not-configured" : "orchestrator-not-configured";
449
+ };
450
+
350
451
  const retrySettings = (): RetrySettings => normalizeRetrySettings(deps.getSettings().retry);
351
452
 
352
453
  const currentToolInvokeOptions = (): Partial<ToolInvokeOptions> => {
@@ -367,7 +468,10 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
367
468
  emitQueueUpdateEvent: (messages) => emit({ type: "queue_update", messages }),
368
469
  emitQueuedUserTurn: (entry) => emit({ type: "queued_user_turn", text: entry.text, kind: entry.kind }),
369
470
  emitNotice,
370
- submit: (text, options) => api.submit(text, options),
471
+ // The loop's own resubmits (stranded steers, continuation requests) run
472
+ // from submit's finally and bypass the admission gate: an interrupt that
473
+ // holds the gate while awaiting that same run would otherwise deadlock.
474
+ submit: (text, options) => submitTracked(text, options),
371
475
  });
372
476
 
373
477
  const middleware = createTurnMiddleware({
@@ -424,6 +528,10 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
424
528
  emitFailureMessage: (message) => emit({ type: "message_end", message }),
425
529
  emitNotice,
426
530
  });
531
+ const emitRuntimeEvent = (event: AgentEvent | AssistantDeltaEvent): void => {
532
+ if (event.type === "message_end") rewriteStallAbortMessage(state, event.message);
533
+ emit(event as ChatLoopEvent);
534
+ };
427
535
 
428
536
  const turnRuntime = createTurnRuntime({
429
537
  state,
@@ -437,7 +545,7 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
437
545
  context,
438
546
  middleware,
439
547
  retrySettings,
440
- emit,
548
+ emit: emitRuntimeEvent,
441
549
  emitNotice,
442
550
  toolStartTimes,
443
551
  });
@@ -462,30 +570,78 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
462
570
  // --- the state machine --------------------------------------------------
463
571
 
464
572
  // Settlement tracking for whenSettled(): the latest submit's promise,
465
- // coerced to never reject so shutdown ordering cannot throw.
573
+ // coerced to never reject so shutdown ordering cannot throw. `priorSubmit`
574
+ // is the promise `activeSubmit` held before the latest submit replaced it,
575
+ // which is the run an interrupt has to wait out.
466
576
  let activeSubmit: Promise<void> = Promise.resolve();
577
+ let priorSubmit: Promise<void> = Promise.resolve();
578
+
579
+ const interruptRefusalReason = (): string | null => {
580
+ if (deps.hasAttachedDispatch?.() === true) {
581
+ return "an attached dispatch is running and the interrupt would kill the worker's run with no receipt; use @<agent> to steer it or Esc to cancel it";
582
+ }
583
+ if (deps.toolRegistry?.hasParkedCalls() === true) {
584
+ return "a permission ask is parked and already waiting on you; answer it or press Esc";
585
+ }
586
+ return null;
587
+ };
467
588
 
468
589
  const api: ChatLoop = {
469
590
  steer: (text) => queues.steer(text),
470
591
  queueFollowUp: (text) => queues.queueFollowUp(text),
592
+ interruptRefusal: () => (state.streaming ? interruptRefusalReason() : null),
471
593
  clearQueuedFollowUps: () => queues.clearQueuedMirror().map((entry) => entry.text),
472
594
  queuedMessages: () => queues.queuedMessages(),
473
595
 
474
596
  async submit(text: string, options: ChatSubmitOptions = {}): Promise<void> {
597
+ let interrupted = false;
475
598
  if (state.streaming) {
476
- const hasImages = options.images !== undefined && options.images.length > 0;
599
+ let mode: SteeringMode = options.steering ?? DEFAULT_STEERING_MODE;
477
600
  const trimmed = text.trim();
478
- if (!hasImages && trimmed.length > 0 && state.runtime) {
479
- // Enter while streaming means "correct it now": the engine
480
- // steering queue drains after every tool batch, so the text
481
- // lands as a user message before the next model turn.
482
- // alt+enter (queueFollowUp) keeps the after-this-run intent.
483
- if (isWorkerShareNote(trimmed)) state.turnSharedWorkerNote = true;
484
- queues.steer(trimmed);
601
+ if (mode === "interrupt" && trimmed.length > 0) {
602
+ const refusal = interruptRefusalReason();
603
+ if (refusal !== null) {
604
+ emitNotice(`[Clio Coder] interrupt refused: ${refusal}. Queued for the next slot instead.`, "warning");
605
+ mode = "next-slot";
606
+ } else {
607
+ // Cancel, then wait for the cancelled run to settle (its in-flight
608
+ // tool results and closing ledger turn), then fall through to the
609
+ // fresh-prompt path below. `priorSubmit` is the run being cancelled;
610
+ // `activeSubmit` already points at this call.
611
+ const prior = priorSubmit;
612
+ api.cancel({
613
+ reason: INTERRUPT_CANCEL_REASON,
614
+ auditReason: "operator interrupted the run with a message",
615
+ });
616
+ await prior;
617
+ if (!state.streaming) {
618
+ interrupted = true;
619
+ } else {
620
+ // Something restarted a run while the cancel settled (a
621
+ // continuation resubmit); do not fight it, deliver at the next slot.
622
+ emitNotice(
623
+ "[Clio Coder] a run restarted before the interrupt landed. Queued for the next slot instead.",
624
+ "warning",
625
+ );
626
+ mode = "next-slot";
627
+ }
628
+ }
629
+ }
630
+ if (!interrupted) {
631
+ const hasImages = options.images !== undefined && options.images.length > 0;
632
+ if (!hasImages && trimmed.length > 0 && state.runtime) {
633
+ // Enter while streaming means "correct it now": the engine
634
+ // steering queue drains after every tool batch, so the text
635
+ // lands as a user message before the next model turn.
636
+ // alt+enter (queueFollowUp) keeps the after-this-run intent.
637
+ if (isWorkerShareNote(trimmed)) state.turnSharedWorkerNote = true;
638
+ if (mode === "end-of-turn") queues.queueFollowUp(trimmed);
639
+ else queues.steer(trimmed);
640
+ return;
641
+ }
642
+ emitNotice("[Clio Coder] response already in progress. Press Esc to cancel the active run.");
485
643
  return;
486
644
  }
487
- emitNotice("[Clio Coder] response already in progress. Press Esc to cancel the active run.");
488
- return;
489
645
  }
490
646
 
491
647
  state.lastRunSnapshot = null;
@@ -494,11 +650,14 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
494
650
  await turnRuntime.ensureLiveCapabilitiesForSelectedModel();
495
651
  agentRuntime = turnRuntime.ensureRuntime();
496
652
  } catch (err) {
497
- emitNotice(err instanceof Error ? err.message : String(err));
653
+ emitAdmissionNotice(
654
+ err instanceof Error ? err.message : String(err),
655
+ err instanceof TurnAdmissionError ? err.reason : "admission-failed",
656
+ );
498
657
  return;
499
658
  }
500
659
  if (!agentRuntime) {
501
- emitNotice(notConfiguredNotice());
660
+ emitAdmissionNotice(notConfiguredNotice(), nullRuntimeAdmissionReason());
502
661
  return;
503
662
  }
504
663
 
@@ -613,6 +772,10 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
613
772
  options.requestContinuation === true,
614
773
  text,
615
774
  );
775
+ // An interrupt was submitted while a run was active, so no caller drew
776
+ // it in the transcript; render it here, after the cancel notice and the
777
+ // cancelled run's leftovers, which is the order the ledger has.
778
+ if (interrupted) emit({ type: "queued_user_turn", text, kind: "interrupt" });
616
779
  context.logPromptCompileIfPending();
617
780
  turnSnapshot = { ...turnSnapshot, turnId: userTurnId ?? "unknown" };
618
781
  context.setCurrentSnapshot(turnSnapshot);
@@ -620,6 +783,7 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
620
783
  const promptHash = compiledPrompt?.systemPromptHash ?? null;
621
784
  state.lastRunSnapshot = {
622
785
  targetId: agentRuntime.targetId,
786
+ targetUrl: agentRuntime.runtimeResolution.target.url ?? null,
623
787
  runtimeId: agentRuntime.runtimeId,
624
788
  runtimeKind: agentRuntime.runtimeResolution.runtimeKind,
625
789
  wireModelId: agentRuntime.wireModelId,
@@ -638,12 +802,18 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
638
802
  state.toolProseAbortReason = null;
639
803
  state.toolProseAssessedChars = 0;
640
804
  state.activeInterruptReason = null;
805
+ state.interruptedUsage = null;
641
806
 
642
807
  // 6. Cache-disturbance honesty (T3.3)
643
808
  context.consumeExpectedColdReasons(agentRuntime.runtimeId);
644
809
 
645
810
  // 7. Run the prompt, then route the settled state through recovery.
646
811
  state.streaming = true;
812
+ try {
813
+ options.onAdmitted?.();
814
+ } catch {
815
+ // Admission observers are bookkeeping only and cannot affect the turn.
816
+ }
647
817
  const runtimePromptText = submittedText;
648
818
  const priorPendingSkillPolicy = state.currentPendingSkillPolicy;
649
819
  const priorAskUserPolicy = state.currentAskUserPolicy;
@@ -697,13 +867,26 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
697
867
  });
698
868
  return;
699
869
  }
700
- emitNotice(err instanceof Error ? err.message : String(err));
870
+ emitNotice(operatorFacingEngineError(message));
701
871
  return;
702
872
  }
703
873
  await recovery.runCompactAndRetry(agentRuntime, runtimePromptText, overflow, images);
704
874
  } finally {
705
875
  if (askUserPolicy) {
706
- await finalizeAskUserInterview(askUserPolicy, "turn_finished", currentToolInvokeOptions());
876
+ try {
877
+ await finalizeAskUserInterviewForHost(
878
+ askUserPolicy,
879
+ "turn_finished",
880
+ currentToolInvokeOptions(),
881
+ deps.onAskUserFinalized,
882
+ );
883
+ } catch (error) {
884
+ emitNotice(
885
+ `[Clio Coder] interview decisions could not be persisted: ${error instanceof Error ? error.message : String(error)}`,
886
+ "warning",
887
+ `decision-ledger:${askUserPolicy.id}`,
888
+ );
889
+ }
707
890
  }
708
891
  state.streaming = false;
709
892
  if (state.activeInterruptReason !== null) {
@@ -711,8 +894,16 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
711
894
  // the durable closing turn only now, after the aborted run's
712
895
  // in-flight tool results have all landed, so the ledger replays
713
896
  // as tool_calls → tool_results → closing text.
714
- persistence.appendAssistantTurn(noticeMessage(state.activeInterruptReason));
897
+ // A thinking-only abort never reaches the ledger, so its estimated
898
+ // spend rides on the closing turn; persistence computes nothing
899
+ // further for a message that already reports positive usage.
900
+ const closing = noticeMessage(state.activeInterruptReason);
901
+ if (state.interruptedUsage !== null) {
902
+ (closing as { usage?: unknown }).usage = state.interruptedUsage;
903
+ }
904
+ persistence.appendAssistantTurn(closing);
715
905
  state.activeInterruptReason = null;
906
+ state.interruptedUsage = null;
716
907
  }
717
908
  state.currentPendingSkillPolicy = priorPendingSkillPolicy;
718
909
  state.currentAskUserPolicy = priorAskUserPolicy;
@@ -826,7 +1017,7 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
826
1017
  // current session" message rather than the "not configured"
827
1018
  // banner.
828
1019
  if (!deps.session?.current()) {
829
- emitNotice("[/compact] no current session to compact; start one with /new or /resume first");
1020
+ emitNotice("[/context compact] no current session to compact; start one with /new or /resume first");
830
1021
  return;
831
1022
  }
832
1023
  let agentRuntime: AgentRuntime | null;
@@ -834,32 +1025,66 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
834
1025
  await turnRuntime.ensureLiveCapabilitiesForSelectedModel();
835
1026
  agentRuntime = turnRuntime.ensureRuntime();
836
1027
  } catch (err) {
837
- emitNotice(`[/compact] ${err instanceof Error ? err.message : String(err)}`);
1028
+ emitNotice(`[/context compact] ${err instanceof Error ? err.message : String(err)}`);
838
1029
  return;
839
1030
  }
840
1031
  if (!agentRuntime) {
841
- emitNotice(`[/compact] ${notConfiguredNotice()}`);
1032
+ emitNotice(`[/context compact] ${notConfiguredNotice()}`);
842
1033
  return;
843
1034
  }
844
1035
  let compacted = false;
845
1036
  try {
846
1037
  compacted = await context.runAutoCompact(agentRuntime, true, instructions, "force");
847
1038
  } catch (err) {
848
- emitNotice(`[/compact] ${err instanceof Error ? err.message : String(err)}`);
1039
+ emitNotice(`[/context compact] ${err instanceof Error ? err.message : String(err)}`);
849
1040
  return;
850
1041
  }
851
1042
  if (!compacted) {
852
- emitNotice("[/compact] nothing to compact; session is empty or no cut crossed");
1043
+ emitNotice("[/context compact] nothing to compact; session is empty or no cut crossed");
853
1044
  }
854
1045
  },
855
1046
  };
856
1047
 
857
1048
  const submitInner = api.submit.bind(api);
858
- api.submit = (text, options) => {
1049
+ const submitTracked: ChatLoop["submit"] = (text, options) => {
1050
+ priorSubmit = activeSubmit;
859
1051
  const run = submitInner(text, options);
860
1052
  activeSubmit = run.catch(() => {});
861
1053
  return run;
862
1054
  };
863
1055
 
1056
+ // FIFO admission gate. Between entry and `state.streaming = true` a fresh
1057
+ // submit awaits the target probe, auto-compaction, and the session prompt
1058
+ // compile; a second submit arriving in that window used to run the same
1059
+ // pipeline concurrently, skip the probe the first one was still awaiting,
1060
+ // append its user turn first, and leave the first to fail on the engine's
1061
+ // active-prompt invariant after its turn was already in the ledger. Each
1062
+ // submit now waits for the previous one to either own the stream or return,
1063
+ // then re-evaluates `state.streaming`, so a prompt typed during boot lands
1064
+ // as the next steer or follow-up in the order it was typed. The gate is
1065
+ // released at admission, not settlement, so steering stays immediate.
1066
+ let admissionTail: Promise<void> | null = null;
1067
+ api.submit = (text, options = {}) => {
1068
+ const previous = admissionTail;
1069
+ let release: () => void = () => {};
1070
+ const ticket = new Promise<void>((resolve) => {
1071
+ release = resolve;
1072
+ });
1073
+ admissionTail = ticket;
1074
+ const releaseTicket = (): void => {
1075
+ release();
1076
+ if (admissionTail === ticket) admissionTail = null;
1077
+ };
1078
+ const start = (): Promise<void> =>
1079
+ submitTracked(text, {
1080
+ ...options,
1081
+ onAdmitted: () => {
1082
+ releaseTicket();
1083
+ options.onAdmitted?.();
1084
+ },
1085
+ }).finally(releaseTicket);
1086
+ return previous ? previous.then(start) : start();
1087
+ };
1088
+
864
1089
  return api;
865
1090
  }