@iowarp/clio-coder 0.3.1 → 0.3.3

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 (601) hide show
  1. package/CHANGELOG.md +233 -373
  2. package/CONTRIBUTING.md +23 -23
  3. package/README.md +284 -613
  4. package/dist/{acp-FPR54DGL.js → acp-P2AQILE2.js} +43 -53
  5. package/dist/{agents-OGPIHPJH.js → agents-72W3BI7I.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-2DJ2KNFG.js +2095 -0
  9. package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
  10. package/dist/chunk-2SFS6XQE.js +122 -0
  11. package/dist/{chunk-PV4JUBVJ.js → chunk-2TLUCQVG.js} +40 -21
  12. package/dist/chunk-2VTFPG5O.js +48 -0
  13. package/dist/chunk-4BJ5BYCE.js +61 -0
  14. package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
  15. package/dist/chunk-4VP4KH3K.js +962 -0
  16. package/dist/chunk-4XUGQOHA.js +797 -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-4QKXUHSR.js → chunk-5UFT4SUX.js} +70 -20
  21. package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
  22. package/dist/chunk-65DEGPJ6.js +52 -0
  23. package/dist/chunk-6EJMN2Y3.js +17 -0
  24. package/dist/chunk-6N5PTWMY.js +136 -0
  25. package/dist/chunk-6SGHMWE3.js +277 -0
  26. package/dist/chunk-6XLNIQDB.js +27 -0
  27. package/dist/chunk-7CR24IG7.js +242 -0
  28. package/dist/chunk-7MNJORFF.js +22 -0
  29. package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
  30. package/dist/chunk-AGYYIBLL.js +1069 -0
  31. package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
  32. package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
  33. package/dist/chunk-CBCAPZAA.js +229 -0
  34. package/dist/chunk-CMZWFGD2.js +352 -0
  35. package/dist/chunk-COU2UHX6.js +400 -0
  36. package/dist/chunk-DSELYM6W.js +1077 -0
  37. package/dist/chunk-DUYJ5IO6.js +644 -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-FCSXB6T2.js +338 -0
  42. package/dist/chunk-FJ3H4MN5.js +48 -0
  43. package/dist/{chunk-RPTR2H26.js → chunk-FNTMWMX5.js} +21 -15
  44. package/dist/chunk-FQ4SKYE4.js +29 -0
  45. package/dist/chunk-G4BMMOKF.js +182 -0
  46. package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
  47. package/dist/chunk-HC4CLZ2Y.js +68 -0
  48. package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
  49. package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
  50. package/dist/chunk-I4HZDVNP.js +73 -0
  51. package/dist/chunk-IKCO5N3L.js +162 -0
  52. package/dist/chunk-IR4CFBFN.js +56 -0
  53. package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
  54. package/dist/chunk-J7CWMCQD.js +255 -0
  55. package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
  56. package/dist/chunk-KZWTDYJF.js +217 -0
  57. package/dist/chunk-LBMZMYH2.js +285 -0
  58. package/dist/{chunk-G34LV2PF.js → chunk-LM5TQCJZ.js} +84 -170
  59. package/dist/chunk-LW6DSM3M.js +5135 -0
  60. package/dist/chunk-LWLEKMDQ.js +3482 -0
  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-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
  64. package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
  65. package/dist/chunk-OAO4GE4M.js +619 -0
  66. package/dist/{chunk-Q3RUPKEJ.js → chunk-OC7FIQPC.js} +58 -189
  67. package/dist/chunk-OKGUZO2U.js +34 -0
  68. package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
  69. package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
  70. package/dist/chunk-OQE5J4C6.js +73 -0
  71. package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
  72. package/dist/{chunk-MAR7Y6HW.js → chunk-PAJK6MAQ.js} +23 -16
  73. package/dist/{chunk-M5T5VO65.js → chunk-PIWWS5BL.js} +837 -635
  74. package/dist/chunk-POHLU5DW.js +1186 -0
  75. package/dist/chunk-QKMUKYO7.js +4961 -0
  76. package/dist/chunk-SRDMMSEP.js +16405 -0
  77. package/dist/chunk-SST6Z5JA.js +80 -0
  78. package/dist/chunk-STBPMHSX.js +2456 -0
  79. package/dist/chunk-T6YILFSB.js +80 -0
  80. package/dist/chunk-TZK7PACC.js +174 -0
  81. package/dist/chunk-TZTZS7QK.js +227 -0
  82. package/dist/{chunk-ASND7OZK.js → chunk-UFIIWP2H.js} +13 -13
  83. package/dist/chunk-UOV2BYIW.js +107 -0
  84. package/dist/{chunk-PFEFKVGL.js → chunk-V6RTAOC2.js} +13 -11
  85. package/dist/chunk-VAKQQHWR.js +434 -0
  86. package/dist/chunk-VG7TBQIY.js +128 -0
  87. package/dist/chunk-VJWL6YS5.js +244 -0
  88. package/dist/{chunk-EYOKLTMF.js → chunk-VPAYEGVX.js} +17 -3
  89. package/dist/chunk-WEH5XRJQ.js +32 -0
  90. package/dist/chunk-X4RCMKVQ.js +641 -0
  91. package/dist/{chunk-TEKV33Q5.js → chunk-X6IAEBZR.js} +65 -33
  92. package/dist/chunk-XBXAASKX.js +18 -0
  93. package/dist/chunk-XN3L4EYL.js +46 -0
  94. package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
  95. package/dist/chunk-YHZX5GEU.js +193 -0
  96. package/dist/chunk-YXLYO42X.js +91 -0
  97. package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
  98. package/dist/chunk-ZI647VB5.js +37 -0
  99. package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
  100. package/dist/chunk-ZWMF7253.js +1882 -0
  101. package/dist/cli/index.js +62 -54
  102. package/dist/clio-JOU4FXVA.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-XCDVKR23.js} +92 -55
  108. package/dist/configure-4GAP54ZW.js +42 -0
  109. package/dist/{context-5RADCKTR.js → context-4UOGGLQ5.js} +71 -35
  110. package/dist/context-5VKGUVJJ.js +866 -0
  111. package/dist/{context-3KWFLHJG.js → context-77FM5DV5.js} +15 -13
  112. package/dist/{context-clear-7TSNPAAI.js → context-clear-XXJRLCJJ.js} +54 -28
  113. package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
  114. package/dist/dispatch-runner-QPRDDBDX.js +1997 -0
  115. package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
  116. package/dist/{doctor-UC5NAJYQ.js → doctor-HR46URBJ.js} +27 -17
  117. package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
  118. package/dist/{evidence-YEGUW4L3.js → evidence-6HG2PY2B.js} +46 -26
  119. package/dist/{evolve-TXARCTPG.js → evolve-K7YU3NCY.js} +45 -25
  120. package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
  121. package/dist/{fleet-6G3DHNYE.js → fleet-VY3HHKN6.js} +163 -54
  122. package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
  123. package/dist/{init-KZ5QTF6M.js → init-JYGXI3FK.js} +69 -32
  124. package/dist/{memory-73ESV5YC.js → memory-WFZMGYHX.js} +48 -27
  125. package/dist/{models-A4PVNWJK.js → models-I5QWSEOM.js} +39 -25
  126. package/dist/monitor-GE4ID3IA.js +661 -0
  127. package/dist/{chunk-FCIH3BIZ.js → orchestrator-EM5MC3HM.js} +15979 -12407
  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-ZU3QMZPZ.js} +101 -61
  132. package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
  133. package/dist/{skills-2V6RA3OQ.js → skills-X5VXCRNQ.js} +34 -14
  134. package/dist/{skills-eval-S2TVJO4F.js → skills-eval-WKIHWTHR.js} +70 -34
  135. package/dist/steer-GGWFUJUD.js +77 -0
  136. package/dist/{targets-TYXLPB23.js → targets-SNCPI2NR.js} +43 -27
  137. package/dist/terminal-lease-BNAHVHBS.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-JQHHPQ4K.js} +45 -25
  142. package/dist/{usage-ZAFSXKKG.js → usage-OR4O5SMZ.js} +62 -31
  143. package/dist/verify-375KUB3Y.js +716 -0
  144. package/dist/web-fetch-2YHJ3KTG.js +638 -0
  145. package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-UEXP2ARI.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 +387 -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 +45 -9
  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 +715 -278
  444. package/src/interactive/chat-renderer.ts +306 -85
  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 +253 -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 +42 -22
  456. package/src/interactive/footer-panel.ts +8 -3
  457. package/src/interactive/format-time.ts +14 -2
  458. package/src/interactive/interactive-application.ts +203 -17
  459. package/src/interactive/interactive-event-projection.ts +18 -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 +184 -117
  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/ask-user.ts +146 -24
  474. package/src/interactive/overlays/decisions.ts +300 -0
  475. package/src/interactive/overlays/help-reference.ts +15 -10
  476. package/src/interactive/overlays/model-selector.ts +34 -16
  477. package/src/interactive/overlays/session-selector.ts +18 -0
  478. package/src/interactive/overlays/settings.ts +105 -17
  479. package/src/interactive/overlays/skills-hub.ts +4 -4
  480. package/src/interactive/overlays/tree-selector.ts +41 -6
  481. package/src/interactive/render-trace.ts +499 -90
  482. package/src/interactive/renderers/compaction-summary.ts +2 -2
  483. package/src/interactive/renderers/diff.ts +115 -104
  484. package/src/interactive/renderers/mermaid.ts +53 -0
  485. package/src/interactive/renderers/tool-execution.ts +516 -168
  486. package/src/interactive/renderers/worker-entry.ts +20 -4
  487. package/src/interactive/session-switch-settlement.ts +10 -0
  488. package/src/interactive/slash-autocomplete.ts +6 -114
  489. package/src/interactive/slash-commands.ts +135 -47
  490. package/src/interactive/slash-spec.ts +9 -38
  491. package/src/interactive/status/controller.ts +5 -1
  492. package/src/interactive/status/index.ts +12 -1
  493. package/src/interactive/status/reasoning.ts +87 -0
  494. package/src/interactive/status/summary.ts +13 -2
  495. package/src/interactive/stdout-backpressure.ts +99 -0
  496. package/src/interactive/stream-pacer.ts +530 -0
  497. package/src/interactive/stream-pacing-policy.ts +66 -0
  498. package/src/interactive/tasks-overlay.ts +368 -14
  499. package/src/interactive/terminal-lease.ts +485 -0
  500. package/src/interactive/theme/tokens.ts +1 -1
  501. package/src/interactive/transcript-detail.ts +120 -0
  502. package/src/interactive/turn-context.ts +4 -3
  503. package/src/interactive/turn-persistence.ts +30 -13
  504. package/src/interactive/turn-queues.ts +12 -0
  505. package/src/interactive/turn-recovery.ts +25 -8
  506. package/src/interactive/turn-runtime.ts +79 -12
  507. package/src/interactive/turn-state.ts +10 -0
  508. package/src/interactive/view/artifacts.ts +114 -4
  509. package/src/interactive/view/view-overlay.ts +3 -0
  510. package/src/interactive/welcome-dashboard.ts +17 -16
  511. package/src/interactive/worker-receipts.ts +52 -3
  512. package/src/interactive/worker-stream.ts +5 -1
  513. package/src/tools/agent-tools.ts +23 -3
  514. package/src/tools/artifact.ts +2 -2
  515. package/src/tools/ask-user.ts +23 -13
  516. package/src/tools/bash.ts +30 -2
  517. package/src/tools/bootstrap.ts +34 -431
  518. package/src/tools/builtin-tool-catalog.ts +271 -0
  519. package/src/tools/codewiki/code-nav-surface.ts +29 -0
  520. package/src/tools/codewiki/code-nav.ts +8 -22
  521. package/src/tools/codewiki/shared.ts +41 -38
  522. package/src/tools/context/docs-engine.ts +14 -3
  523. package/src/tools/context/index.ts +107 -28
  524. package/src/tools/context/surface.ts +19 -0
  525. package/src/tools/core-bootstrap.ts +168 -0
  526. package/src/tools/credential-present.ts +5 -5
  527. package/src/tools/dispatch-admission.ts +533 -0
  528. package/src/tools/dispatch-background.ts +54 -0
  529. package/src/tools/dispatch-event-text.ts +6 -0
  530. package/src/tools/dispatch-plan.ts +9 -4
  531. package/src/tools/dispatch-run-events.ts +238 -0
  532. package/src/tools/dispatch-runner.ts +2370 -0
  533. package/src/tools/dispatch-scout-admission.ts +295 -0
  534. package/src/tools/dispatch-types.ts +77 -0
  535. package/src/tools/dispatch.ts +67 -3161
  536. package/src/tools/find.ts +4 -2
  537. package/src/tools/grep.ts +2 -2
  538. package/src/tools/lazy-tool.ts +60 -0
  539. package/src/tools/ledger.ts +3 -3
  540. package/src/tools/monitor-surface.ts +36 -0
  541. package/src/tools/monitor.ts +2 -32
  542. package/src/tools/observers.ts +2 -2
  543. package/src/tools/presentation.ts +107 -0
  544. package/src/tools/registry.ts +45 -27
  545. package/src/tools/safe-exec.ts +2 -2
  546. package/src/tools/steer-surface.ts +17 -0
  547. package/src/tools/steer.ts +2 -13
  548. package/src/tools/tasks.ts +108 -11
  549. package/src/tools/truncate.ts +25 -184
  550. package/src/tools/verify/frontend.ts +3 -1
  551. package/src/tools/verify/index.ts +3 -38
  552. package/src/tools/verify/surface.ts +46 -0
  553. package/src/tools/web-fetch-surface.ts +23 -0
  554. package/src/tools/web-fetch.ts +2 -20
  555. package/src/tools/write.ts +7 -2
  556. package/src/worker/entry.ts +39 -2
  557. package/src/worker/spec-contract.ts +26 -5
  558. package/dist/chunk-7SS2CTV2.js +0 -61361
  559. package/dist/chunk-DKGKUHFA.js +0 -924
  560. package/dist/chunk-GEP36Y4X.js +0 -12796
  561. package/dist/chunk-XYWBQRDM.js +0 -137
  562. package/dist/clio-BZVGEUFJ.js +0 -58
  563. package/dist/configure-S7S6F6CL.js +0 -32
  564. package/docs/html/agents_blueprint.html +0 -936
  565. package/docs/html/alcf_blueprint.html +0 -324
  566. package/docs/html/architecture_blueprint.html +0 -850
  567. package/docs/html/commands_blueprint.html +0 -939
  568. package/docs/html/config_knobs_audit_blueprint.html +0 -178
  569. package/docs/html/configuration_blueprint.html +0 -1080
  570. package/docs/html/context_blueprint.html +0 -603
  571. package/docs/html/documentation_blueprint.html +0 -832
  572. package/docs/html/environment_blueprint.html +0 -404
  573. package/docs/html/eval_blueprint.html +0 -743
  574. package/docs/html/evals_internal_blueprint.html +0 -190
  575. package/docs/html/evolution_blueprint.html +0 -674
  576. package/docs/html/extensions_blueprint.html +0 -2065
  577. package/docs/html/fleet_dispatch_blueprint.html +0 -286
  578. package/docs/html/index.html +0 -919
  579. package/docs/html/lifecycle_blueprint.html +0 -723
  580. package/docs/html/memory_blueprint.html +0 -699
  581. package/docs/html/middleware_blueprint.html +0 -664
  582. package/docs/html/models_blueprint.html +0 -2366
  583. package/docs/html/observability_blueprint.html +0 -683
  584. package/docs/html/provider_adapter_blueprint.html +0 -245
  585. package/docs/html/safety_blueprint.html +0 -1386
  586. package/docs/html/shared.css +0 -571
  587. package/docs/html/shared.js +0 -143
  588. package/docs/html/skills_blueprint.html +0 -671
  589. package/docs/html/soak_blueprint.html +0 -182
  590. package/docs/html/tool_usage_blueprint.html +0 -350
  591. package/docs/html/tools_blueprint.html +0 -2249
  592. package/docs/html/trace_blueprint.html +0 -235
  593. package/docs/html/tui_design_blueprint.html +0 -374
  594. package/docs/html/validation_blueprint.html +0 -961
  595. package/docs/html/worker_dispatch_blueprint.html +0 -231
  596. package/src/core/release.ts +0 -2
  597. package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
  598. package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
  599. package/src/engine/apis/lmstudio-native.ts +0 -1438
  600. package/src/engine/apis/thinking-replay.ts +0 -11
  601. package/src/tools/string-enum.ts +0 -15
@@ -17,8 +17,10 @@ import {
17
17
  } from "../domains/providers/index.js";
18
18
  import type { ResourcesContract } from "../domains/resources/index.js";
19
19
  import { installSkill } from "../domains/resources/skills/marketplace.js";
20
- import type { SessionEntry } from "../domains/session/index.js";
20
+ import type { SessionContract, SessionEntry } from "../domains/session/index.js";
21
21
  import type { ShareContract } from "../domains/share/index.js";
22
+ import type { UserTasksStore } from "../domains/user-tasks/store.js";
23
+ import { stripTerminalSequences } from "../engine/tui.js";
22
24
  import type { ImageContent } from "../engine/types.js";
23
25
  import type { AskUserHandler } from "../tools/ask-user.js";
24
26
  import type { ChatLoop } from "./chat-loop.js";
@@ -26,6 +28,7 @@ import { type ChatPanel, createChatPanel } from "./chat-panel.js";
26
28
  import { rehydrateChatPanelFromTurns } from "./chat-renderer.js";
27
29
  import { runCompactWithNotice } from "./command-fallbacks.js";
28
30
  import { appendNotice, appendOperatorCommand } from "./command-output.js";
31
+ import { renderSessionHtml } from "./export-html/index.js";
29
32
  import { dateLocal } from "./format-time.js";
30
33
  import type { SettingsCenterRowId, SettingsSectionId } from "./overlays/settings.js";
31
34
  import {
@@ -35,18 +38,13 @@ import {
35
38
  parseSlashCommand,
36
39
  type RunIo,
37
40
  type SlashCommandContext,
41
+ type SlashCommandDispatchResult,
38
42
  type TaskMemorySeedCommandResult,
39
43
  } from "./slash-commands.js";
40
44
  import { verifyReceiptFile } from "./view/artifacts.js";
41
45
  import type { WorkerEntryState } from "./worker-stream.js";
42
46
 
43
47
  const EXPORT_RENDER_WIDTH = 100;
44
- // biome-ignore lint/suspicious/noControlCharactersInRegex: the ESC control character is the ANSI escape introducer this pattern exists to strip
45
- const ANSI_PATTERN = /\u001b\[[0-9;?]*[A-Za-z]/g;
46
-
47
- function stripAnsiForExport(line: string): string {
48
- return line.replace(ANSI_PATTERN, "");
49
- }
50
48
 
51
49
  export interface InteractiveSlashSubmitExpansion {
52
50
  text: string;
@@ -56,7 +54,7 @@ export interface InteractiveSlashSubmitExpansion {
56
54
  }
57
55
 
58
56
  type SlashChat = Pick<ChatLoop, "getSessionId" | "isStreaming" | "submit">;
59
- type SlashChatPanel = Pick<ChatPanel, "appendReplayBlock" | "appendUser">;
57
+ type SlashChatPanel = Pick<ChatPanel, "appendReplayBlock" | "appendUser" | "clearFoldOverrides">;
60
58
  type SlashResources = Pick<ResourcesContract, "prompts" | "expandPromptTemplate" | "reload">;
61
59
  type SlashExtensions = Pick<ExtensionsContract, "list">;
62
60
  type SlashAgents = Pick<AgentsContract, "getSpec" | "listSpecs">;
@@ -74,6 +72,7 @@ export interface InteractiveSlashRuntimeDeps {
74
72
  interop?: SlashCommandContext["interop"];
75
73
  agents?: SlashAgents;
76
74
  share?: SlashShare;
75
+ userTasks?: UserTasksStore;
77
76
  getSettings?: () => Readonly<ClioSettings>;
78
77
  writeSettings?: (next: ClioSettings) => void;
79
78
  /**
@@ -91,16 +90,25 @@ export interface InteractiveSlashRuntimeDeps {
91
90
  stateDir: string;
92
91
  shutdown: () => void | Promise<void>;
93
92
  requestRender: () => void;
93
+ beforeSemanticSubmit?: () => void;
94
+ settleVisibleFrame?: (reason: string) => Promise<void>;
94
95
  refreshFooter: () => void;
95
96
  dismissContextBootstrapNotices: () => void;
96
97
  recordSubmittedTurn: () => void;
97
98
  readStructuredEntries: (sessionId: string) => ReadonlyArray<SessionEntry>;
99
+ /**
100
+ * Leaf lookup for `/export`, so the export follows the branch the session
101
+ * is actually on. current.jsonl still holds the abandoned turns after a
102
+ * `/tree` pin, and an unscoped rehydrate reproduced them (issue #109).
103
+ */
104
+ session?: Pick<SessionContract, "tree">;
98
105
  expandSubmit: (text: string) => Promise<InteractiveSlashSubmitExpansion>;
99
106
  openAskUser: AskUserHandler;
100
107
  openSkillsHub: () => void;
101
108
  openCost: () => void;
102
109
  openContextView: () => void;
103
110
  openTasks: () => void;
111
+ openDecisions: () => void;
104
112
  openMemory: () => void;
105
113
  seedTaskMemory?: () => TaskMemorySeedCommandResult;
106
114
  openView: (filter?: string) => void;
@@ -128,7 +136,9 @@ export interface InteractiveSlashRuntimeDeps {
128
136
  export interface InteractiveSlashRuntime {
129
137
  context: SlashCommandContext;
130
138
  notice: SlashCommandContext["notice"];
131
- dispatchCommand(text: string): void;
139
+ dispatchCommand(text: string): SlashCommandDispatchResult;
140
+ /** Admit captured Stage 0 input without waiting for the model turn to finish. */
141
+ admitCommand(text: string, signal?: AbortSignal): Promise<void>;
132
142
  }
133
143
 
134
144
  /** Owns slash-command context construction and its asynchronous command state. */
@@ -166,8 +176,11 @@ export function resolveAvailableThinkingLevels(
166
176
 
167
177
  export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps): InteractiveSlashRuntime {
168
178
  let activeContextInit = false;
179
+ let latestAdmission: Promise<void> = Promise.resolve();
180
+ let activeAdmissionSignal: AbortSignal | undefined;
169
181
  const cwd = (): string => deps.getCwd?.() ?? process.cwd();
170
182
  const resources = deps.resources;
183
+ const userTasks = deps.userTasks;
171
184
 
172
185
  const appendCommandNotice: SlashCommandContext["notice"] = (level, text) => {
173
186
  appendNotice(level, text, {
@@ -177,31 +190,107 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
177
190
  };
178
191
 
179
192
  /** One expanded operator turn into the chat loop: record it, paint it, submit it. */
180
- const submitExpanded = (sub: InteractiveSlashSubmitExpansion): void => {
181
- void (async () => {
182
- try {
183
- // Enter while streaming becomes a steer inside chat.submit. The
184
- // queue panel shows it until the engine injects it, and the
185
- // injection emits queued_user_turn, which is when the transcript
186
- // renders it. Appending here too showed the text twice and at
187
- // the wrong point in the turn's order.
188
- const willQueue = deps.chat.isStreaming();
189
- deps.recordSubmittedTurn();
190
- deps.refreshFooter();
191
- if (!willQueue) deps.chatPanel.appendUser(sub.text);
192
- deps.requestRender();
193
- await deps.chat.submit(sub.text, {
194
- ...(sub.images.length > 0 ? { images: sub.images } : {}),
195
- ...(sub.workingContextPaths.length > 0 ? { workingContextPaths: sub.workingContextPaths } : {}),
196
- ...(sub.pendingSkillRequests.length > 0 ? { pendingSkillRequests: sub.pendingSkillRequests } : {}),
197
- });
198
- } catch (err) {
199
- const msg = err instanceof Error ? err.message : String(err);
200
- deps.io.stderr(`[interactive] chat failed: ${msg}\n`);
201
- } finally {
202
- deps.requestRender();
193
+ const submitExpanded = (sub: InteractiveSlashSubmitExpansion, awaitAdmission = false): Promise<void> => {
194
+ try {
195
+ // Enter while streaming becomes a steer inside chat.submit. The
196
+ // queue panel shows it until the engine injects it, and the
197
+ // injection emits queued_user_turn, which is when the transcript
198
+ // renders it. Appending here too showed the text twice and at
199
+ // the wrong point in the turn's order.
200
+ const willQueue = deps.chat.isStreaming();
201
+ deps.recordSubmittedTurn();
202
+ deps.refreshFooter();
203
+ if (!willQueue) deps.chatPanel.appendUser(sub.text);
204
+ deps.requestRender();
205
+ deps.beforeSemanticSubmit?.();
206
+ let acknowledgeAdmission = (): void => {};
207
+ const admitted = new Promise<void>((resolve) => {
208
+ acknowledgeAdmission = resolve;
209
+ });
210
+ const turn = deps.chat.submit(sub.text, {
211
+ ...(sub.images.length > 0 ? { images: sub.images } : {}),
212
+ ...(sub.workingContextPaths.length > 0 ? { workingContextPaths: sub.workingContextPaths } : {}),
213
+ ...(sub.pendingSkillRequests.length > 0 ? { pendingSkillRequests: sub.pendingSkillRequests } : {}),
214
+ ...(awaitAdmission && willQueue ? { steering: "end-of-turn" as const } : {}),
215
+ ...(awaitAdmission ? { onAdmitted: acknowledgeAdmission } : {}),
216
+ });
217
+ const settlement = turn
218
+ .then(() => deps.settleVisibleFrame?.("submit-return"))
219
+ .catch((err) => {
220
+ const msg = err instanceof Error ? err.message : String(err);
221
+ deps.io.stderr(`[interactive] chat failed: ${msg}\n`);
222
+ })
223
+ .finally(deps.requestRender);
224
+ return awaitAdmission ? Promise.race([admitted, settlement]) : settlement;
225
+ } catch (err) {
226
+ const msg = err instanceof Error ? err.message : String(err);
227
+ deps.io.stderr(`[interactive] chat failed: ${msg}\n`);
228
+ deps.requestRender();
229
+ return Promise.resolve();
230
+ }
231
+ };
232
+
233
+ const admitChat = async (text: string, signal?: AbortSignal): Promise<void> => {
234
+ try {
235
+ signal?.throwIfAborted();
236
+ const submitted = await deps.expandSubmit(text);
237
+ signal?.throwIfAborted();
238
+ const uninstalled = submitted.pendingSkillRequests.find((request) => !request.installed);
239
+ if (uninstalled && !uninstalled.marketplaceRef) {
240
+ deps.io.stderr(`Skill "${uninstalled.name}" is not installed and no local marketplace entry is available.\n`);
241
+ return;
203
242
  }
204
- })();
243
+ if (uninstalled) {
244
+ void deps
245
+ .openAskUser([
246
+ {
247
+ question: `Skill "${uninstalled.name}" is not installed. Would you like to install it?`,
248
+ options: [
249
+ { label: "Install and run", description: `Install from ${uninstalled.marketplaceRef}` },
250
+ { label: "Cancel", description: "Do not install." },
251
+ ],
252
+ },
253
+ ])
254
+ .then((res) => {
255
+ if (res.cancelled || res.answers[0]?.answer !== "Install and run") {
256
+ deps.io.stderr("Installation cancelled.\n");
257
+ return;
258
+ }
259
+ void (async () => {
260
+ try {
261
+ deps.io.stdout(`Installing skill "${uninstalled.name}"...\n`);
262
+ let configDir: string | undefined;
263
+ try {
264
+ configDir = (deps.getConfigDir ?? clioConfigDir)();
265
+ } catch (configErr) {
266
+ deps.io.stderr(
267
+ `Skill install: config dir unavailable (${configErr instanceof Error ? configErr.message : String(configErr)}); continuing without it.\n`,
268
+ );
269
+ }
270
+ (deps.installSkill ?? installSkill)({
271
+ source: uninstalled.name,
272
+ cwd: cwd(),
273
+ ...(configDir ? { configDir } : {}),
274
+ });
275
+ deps.io.stdout(`Successfully installed "${uninstalled.name}"!\n`);
276
+ await deps.resources?.reload();
277
+ const postInstallSubmitted = await deps.expandSubmit(text);
278
+ submitExpanded(postInstallSubmitted);
279
+ } catch (err) {
280
+ deps.io.stderr(
281
+ `Failed to install skill "${uninstalled.name}": ${err instanceof Error ? err.message : String(err)}\n`,
282
+ );
283
+ }
284
+ })();
285
+ });
286
+ return;
287
+ }
288
+ await submitExpanded(submitted, true);
289
+ } catch (err) {
290
+ const msg = err instanceof Error ? err.message : String(err);
291
+ deps.io.stderr(`[interactive] chat failed: ${msg}\n`);
292
+ deps.requestRender();
293
+ }
205
294
  };
206
295
  const context: SlashCommandContext = {
207
296
  io: deps.io,
@@ -251,6 +340,17 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
251
340
  openCost: deps.openCost,
252
341
  openContextView: deps.openContextView,
253
342
  openTasks: deps.openTasks,
343
+ openDecisions: deps.openDecisions,
344
+ ...(userTasks
345
+ ? {
346
+ userTasks: {
347
+ add: (title: string) => userTasks.add(title),
348
+ hand: (id: string) => userTasks.hand(id, deps.chat.getSessionId() ?? undefined),
349
+ done: (id: string) => userTasks.done(id),
350
+ drop: (id: string) => userTasks.drop(id),
351
+ },
352
+ }
353
+ : {}),
254
354
  openMemory: deps.openMemory,
255
355
  seedTaskMemory: () => {
256
356
  const result = deps.seedTaskMemory?.() ?? { status: "not-found" as const };
@@ -298,6 +398,11 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
298
398
  // alone. Saving it as the default is what Settings → Terminal is for.
299
399
  if (deps.commitSetting) deps.commitSetting("terminal.outputVerbosity", next, "session");
300
400
  else deps.writeSettings?.(next);
401
+ // `/output` is also the explicit reset action for transcript folds. Do
402
+ // this even when the requested level already matches the current one;
403
+ // the render-time change detector cannot observe a same-value command.
404
+ deps.chatPanel.clearFoldOverrides();
405
+ deps.refreshFooter();
301
406
  return { status: "applied", verbosity: match };
302
407
  },
303
408
  openModel: deps.openModel,
@@ -333,32 +438,43 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
333
438
  }
334
439
  try {
335
440
  const turns = deps.readStructuredEntries(sessionId);
336
- // Same pure render pipeline as the live panel and /resume replay:
337
- // a throwaway panel rehydrated from the ledger, every tool segment
338
- // expanded, rendered at a fixed width, ANSI stripped. Unlike the
339
- // live view, export renders full tool bodies (no middle-elision or
340
- // char truncation) so the transcript reproduces the complete output.
341
- const exportPanel = createChatPanel({ unboundedToolBodies: true });
342
- rehydrateChatPanelFromTurns(exportPanel, turns, { unboundedToolBodies: true });
343
- exportPanel.toggleAllToolsExpanded();
344
- const lines = exportPanel.render(EXPORT_RENDER_WIDTH).map(stripAnsiForExport);
441
+ // Same pure render pipeline as the live panel and /resume replay: a
442
+ // throwaway panel is rehydrated from the ledger under the verbose
443
+ // transcript detail policy (every body open, full receipts) with no
444
+ // operator overrides, and rendered at a stable width. HTML converts
445
+ // the resulting ANSI presentation to inline styles; Markdown keeps the
446
+ // prior plain-text fenced transcript.
447
+ const exportPanel = createChatPanel({ unboundedToolBodies: true, getOutputVerbosity: () => "verbose" });
448
+ // Scoped to the leaf the session is on, the same way /resume replays
449
+ // (issue #107): with a /tree pin persisted and not yet extended, the
450
+ // file still holds the abandoned branch after the pin, and an unscoped
451
+ // rehydrate exported it as ordinary history (issue #109). No session
452
+ // contract means no pin can exist for this reader, so the file replays whole.
453
+ const leafTurnId = deps.session?.tree(sessionId).leafId ?? null;
454
+ rehydrateChatPanelFromTurns(exportPanel, turns, {
455
+ unboundedToolBodies: true,
456
+ ...(leafTurnId ? { activeLeafTurnId: leafTurnId } : {}),
457
+ });
458
+ const ansiLines = exportPanel.render(EXPORT_RENDER_WIDTH);
345
459
  // The operator names this file by the day they ran the export, so the
346
460
  // date in it is their calendar date. The header below keeps the ISO
347
461
  // instant, which is the machine-readable half of the same fact.
348
- const date = dateLocal(deps.now?.() ?? new Date());
462
+ const exportedAt = deps.now?.() ?? new Date();
463
+ const date = dateLocal(exportedAt);
464
+ const requestedPath = pathArg?.trim() ?? "";
465
+ const markdown = requestedPath.toLowerCase().endsWith(".md");
349
466
  const target = resolve(
350
- pathArg && pathArg.trim().length > 0 ? pathArg.trim() : join(".clio-coder", "exports", `${sessionId}-${date}.md`),
467
+ requestedPath.length > 0 ? requestedPath : join(".clio-coder", "exports", `${sessionId}-${date}.html`),
351
468
  );
352
469
  mkdirSync(resolve(target, ".."), { recursive: true });
353
- const header = [
354
- `# Clio session ${sessionId}`,
355
- "",
356
- `Exported ${(deps.now?.() ?? new Date()).toISOString()}`,
357
- "",
358
- "```text",
359
- ];
360
- writeFileSync(target, `${[...header, ...lines, "```", ""].join("\n")}`, "utf8");
361
- appendCommandNotice("success", `[/export] wrote ${lines.length} lines to ${target}`);
470
+ if (markdown) {
471
+ const lines = ansiLines.map(stripTerminalSequences);
472
+ const header = [`# Clio session ${sessionId}`, "", `Exported ${exportedAt.toISOString()}`, "", "```text"];
473
+ writeFileSync(target, `${[...header, ...lines, "```", ""].join("\n")}`, "utf8");
474
+ } else {
475
+ writeFileSync(target, renderSessionHtml({ sessionId, exportedAt: exportedAt.toISOString(), ansiLines }), "utf8");
476
+ }
477
+ appendCommandNotice("success", `[/export] wrote ${ansiLines.length} lines to ${target}`);
362
478
  } catch (err) {
363
479
  appendCommandNotice("error", `[/export] ${err instanceof Error ? err.message : String(err)}`);
364
480
  }
@@ -416,70 +532,8 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
416
532
  // worker's output name a file the operator never mentioned.
417
533
  submitOperatorNote: (text) => submitExpanded({ text, images: [], workingContextPaths: [], pendingSkillRequests: [] }),
418
534
  submitChat: (text) => {
419
- void (async () => {
420
- try {
421
- const submitted = await deps.expandSubmit(text);
422
- const uninstalled = submitted.pendingSkillRequests.find((request) => !request.installed);
423
- if (uninstalled && !uninstalled.marketplaceRef) {
424
- deps.io.stderr(`Skill "${uninstalled.name}" is not installed and no local marketplace entry is available.\n`);
425
- return;
426
- }
427
- if (uninstalled) {
428
- void deps
429
- .openAskUser([
430
- {
431
- question: `Skill "${uninstalled.name}" is not installed. Would you like to install it?`,
432
- options: [
433
- {
434
- label: "Install and run",
435
- description: `Install from ${uninstalled.marketplaceRef}`,
436
- },
437
- { label: "Cancel", description: "Do not install." },
438
- ],
439
- },
440
- ])
441
- .then((res) => {
442
- if (res.cancelled || res.answers[0]?.answer !== "Install and run") {
443
- deps.io.stderr("Installation cancelled.\n");
444
- return;
445
- }
446
- void (async () => {
447
- try {
448
- deps.io.stdout(`Installing skill "${uninstalled.name}"...\n`);
449
- let configDir: string | undefined;
450
- try {
451
- configDir = (deps.getConfigDir ?? clioConfigDir)();
452
- } catch (configErr) {
453
- deps.io.stderr(
454
- `Skill install: config dir unavailable (${configErr instanceof Error ? configErr.message : String(configErr)}); continuing without it.\n`,
455
- );
456
- }
457
- (deps.installSkill ?? installSkill)({
458
- source: uninstalled.name,
459
- cwd: cwd(),
460
- ...(configDir ? { configDir } : {}),
461
- });
462
- deps.io.stdout(`Successfully installed "${uninstalled.name}"!\n`);
463
- await deps.resources?.reload();
464
- const postInstallSubmitted = await deps.expandSubmit(text);
465
- submitExpanded(postInstallSubmitted);
466
- } catch (err) {
467
- deps.io.stderr(
468
- `Failed to install skill "${uninstalled.name}": ${err instanceof Error ? err.message : String(err)}\n`,
469
- );
470
- }
471
- })();
472
- });
473
- return;
474
- }
475
-
476
- submitExpanded(submitted);
477
- } catch (err) {
478
- const msg = err instanceof Error ? err.message : String(err);
479
- deps.io.stderr(`[interactive] chat failed: ${msg}\n`);
480
- deps.requestRender();
481
- }
482
- })();
535
+ latestAdmission = admitChat(text, activeAdmissionSignal);
536
+ void latestAdmission;
483
537
  },
484
538
  render: deps.requestRender,
485
539
  };
@@ -488,5 +542,18 @@ export function createInteractiveSlashRuntime(deps: InteractiveSlashRuntimeDeps)
488
542
  context,
489
543
  notice: appendCommandNotice,
490
544
  dispatchCommand: (text) => dispatchSlashCommand(parseSlashCommand(text), context),
545
+ admitCommand: async (text, signal) => {
546
+ signal?.throwIfAborted();
547
+ const command = parseSlashCommand(text);
548
+ const before = latestAdmission;
549
+ const previousSignal = activeAdmissionSignal;
550
+ activeAdmissionSignal = signal;
551
+ try {
552
+ dispatchSlashCommand(command, context);
553
+ } finally {
554
+ activeAdmissionSignal = previousSignal;
555
+ }
556
+ if (latestAdmission !== before) await latestAdmission;
557
+ },
491
558
  };
492
559
  }
@@ -1,10 +1,12 @@
1
+ import { type TaskBoardSnapshot, type TaskBoardStore, taskBoardCounts } from "../domains/session/task-board.js";
1
2
  import { Text, type TUI, visibleWidth } from "../engine/tui.js";
2
3
  import {
3
4
  CONTEXT_ISLAND_WIDTH,
4
5
  type ContextActivitySnapshot,
5
6
  formatContextActivityIslandLines,
6
7
  } from "./context-activity.js";
7
- import { type DispatchBoardRow, formatTaskIslandLines } from "./dispatch-board.js";
8
+ import { type DispatchBoardRow, formatTaskIslandLines, TASK_ISLAND_WIDTH } from "./dispatch-board.js";
9
+ import { clioTheme, frame, GLYPH } from "./theme/index.js";
8
10
 
9
11
  export interface InteractiveTickerHandle {
10
12
  unref?(): void;
@@ -26,10 +28,30 @@ export interface InteractiveTickersDeps {
26
28
  contextActivityStore: InteractiveContextActivityStore;
27
29
  getOverlayState: () => string;
28
30
  isFooterExpanded: () => boolean;
31
+ /** Bound to TaskBoardStore.cachedSnapshot; repaint must never fold the session ledger. */
32
+ getTaskBoard?: TaskBoardStore["cachedSnapshot"];
29
33
  scheduleInterval?: (callback: () => void, intervalMs: number) => InteractiveTickerHandle;
30
34
  clearScheduledInterval?: (handle: InteractiveTickerHandle) => void;
31
35
  }
32
36
 
37
+ export function formatTaskBoardIslandLines(board: TaskBoardSnapshot): string[] {
38
+ const theme = clioTheme();
39
+ const counts = taskBoardCounts(board);
40
+ const active = board.tasks.find((task) => task.status === "active");
41
+ const next = active ?? board.tasks.find((task) => task.status === "pending");
42
+ const chips = [
43
+ `${counts.completed}/${counts.total} done`,
44
+ ...(counts.active > 0 ? [`${counts.active} active`] : []),
45
+ ...(counts.blocked > 0 ? [`${counts.blocked} blocked`] : []),
46
+ ].join(" · ");
47
+ const body = [theme.fg("accent", board.title), theme.fg("dim", chips)];
48
+ if (next) {
49
+ const glyph = active ? theme.fg("accent", GLYPH.running) : theme.fg("dim", GLYPH.queued);
50
+ body.push(`${glyph} ${theme.fg("dim", next.id)} ${theme.fg("muted", next.title)}`);
51
+ }
52
+ return frame(theme, "Tasks", body, TASK_ISLAND_WIDTH + 4);
53
+ }
54
+
33
55
  export interface InteractiveTickers {
34
56
  renderTaskIsland(): void;
35
57
  renderContextIsland(): void;
@@ -71,19 +93,28 @@ export function createInteractiveTickers(deps: InteractiveTickersDeps): Interact
71
93
 
72
94
  let taskIslandHidden = true;
73
95
 
74
- const renderTaskIsland = (): void => {
96
+ const renderTaskIsland = (): boolean => {
75
97
  const rows = deps.dispatchBoardStore.activeRows();
98
+ const board = rows.length === 0 ? (deps.getTaskBoard?.() ?? null) : null;
99
+ const boardHasOpenTasks = board !== null && taskBoardCounts(board).open > 0;
76
100
  const contextActive = deps.contextActivityStore.active();
77
- const hidden = deps.getOverlayState() !== "closed" || deps.isFooterExpanded() || contextActive || rows.length === 0;
101
+ const hidden =
102
+ deps.getOverlayState() !== "closed" ||
103
+ deps.isFooterExpanded() ||
104
+ contextActive ||
105
+ (rows.length === 0 && !boardHasOpenTasks);
106
+ const visibilityChanged = taskIslandHidden !== hidden;
78
107
  taskIslandHandle.setHidden(hidden);
79
108
  // A hidden island with nothing to show still ran the frame builder and two
80
109
  // truncateToWidth calls four times a second, forever, to produce lines no
81
110
  // one could see. Formatting the empty case is pure waste; staying hidden
82
111
  // leaves the last text in place, which is unreachable while hidden.
83
- if (hidden && taskIslandHidden && rows.length === 0) return;
112
+ if (hidden && taskIslandHidden && rows.length === 0 && !boardHasOpenTasks) return visibilityChanged;
84
113
  taskIslandHidden = hidden;
85
- taskIsland.setText(formatTaskIslandLines(rows).join("\n"));
114
+ if (rows.length > 0) taskIsland.setText(formatTaskIslandLines(rows).join("\n"));
115
+ else if (board) taskIsland.setText(formatTaskBoardIslandLines(board).join("\n"));
86
116
  taskIsland.invalidate();
117
+ return visibilityChanged || !hidden;
87
118
  };
88
119
 
89
120
  const renderContextIsland = (): void => {
@@ -124,9 +155,9 @@ export function createInteractiveTickers(deps: InteractiveTickersDeps): Interact
124
155
  stopContextIslandTicker();
125
156
  contextIslandTicker = scheduleInterval(() => {
126
157
  deps.dispatchBoardStore.reconcile();
127
- renderTaskIsland();
158
+ const taskNeedsRender = renderTaskIsland();
128
159
  const fleetActive = deps.dispatchBoardStore.activeRows().length > 0;
129
- if (!deps.contextActivityStore.active() && !contextIslandVisible && !fleetActive) return;
160
+ if (!deps.contextActivityStore.active() && !contextIslandVisible && !fleetActive && !taskNeedsRender) return;
130
161
  renderContextIsland();
131
162
  deps.tui.requestRender();
132
163
  }, 250);
@@ -68,7 +68,7 @@ export interface LeaderTarget {
68
68
  }
69
69
 
70
70
  export interface ClioKeybindingManager {
71
- matches(data: string, id: ClioKeybinding): boolean;
71
+ matches(data: string, id: Keybinding): boolean;
72
72
  getKeys(id: Keybinding): ReadonlyArray<KeyId>;
73
73
  getDescription(id: ClioKeybinding): string;
74
74
  getConflicts(): ReadonlyArray<KeybindingConflict>;
@@ -1,5 +1,6 @@
1
- import type { Component } from "../engine/tui.js";
2
- import { Container } from "../engine/tui.js";
1
+ import type { Component, ScrollViewScrollbar, TuiMode } from "../engine/tui.js";
2
+ import { Container, ScrollView, VStack } from "../engine/tui.js";
3
+ import { clioTheme, GLYPH } from "./theme/index.js";
3
4
 
4
5
  export interface LayoutParts {
5
6
  banner: Component;
@@ -9,7 +10,43 @@ export interface LayoutParts {
9
10
  footer: Component;
10
11
  }
11
12
 
12
- export function buildLayout(parts: LayoutParts): Container {
13
+ export interface LayoutOptions {
14
+ mode?: TuiMode;
15
+ fullscreenScrollbar?: ScrollViewScrollbar;
16
+ }
17
+
18
+ export interface FullscreenLayout {
19
+ root: VStack;
20
+ transcript: ScrollView;
21
+ }
22
+
23
+ export function buildFullscreenLayout(
24
+ parts: LayoutParts,
25
+ options: Pick<LayoutOptions, "fullscreenScrollbar"> = {},
26
+ ): FullscreenLayout {
27
+ const document = new Container();
28
+ document.addChild(parts.banner);
29
+ document.addChild(parts.chat);
30
+ const theme = clioTheme();
31
+ const transcript = new ScrollView(document, {
32
+ follow: "end",
33
+ primary: true,
34
+ overscroll: "chain",
35
+ scrollbar: options.fullscreenScrollbar ?? "auto",
36
+ scrollbarStyle: () => theme.fg("frameStrong", GLYPH.barFull),
37
+ });
38
+ const dock = new VStack();
39
+ if (parts.pending) dock.addChild(parts.pending, { shrink: 1, minSize: 0 });
40
+ dock.addChild(parts.editor, { shrink: 1, minSize: 3 });
41
+ dock.addChild(parts.footer, { shrink: 1, minSize: 1 });
42
+ const root = new VStack();
43
+ root.addChild(transcript, { basis: 0, grow: 1, shrink: 1, minSize: 1 });
44
+ root.addChild(dock, { basis: "auto", grow: 0, shrink: 1, minSize: 1 });
45
+ return { root, transcript };
46
+ }
47
+
48
+ export function buildLayout(parts: LayoutParts, options: LayoutOptions = {}): Component {
49
+ if (options.mode === "fullscreen") return buildFullscreenLayout(parts, options).root;
13
50
  const root = new Container();
14
51
  root.addChild(parts.banner);
15
52
  root.addChild(parts.chat);
@@ -182,7 +182,7 @@ export function fitHintEntries(entries: ReadonlyArray<HintEntry>, maxWidth: numb
182
182
  }
183
183
 
184
184
  /**
185
- * The one word for narrowing a list by typing. `/help` said `filter`, `/models`
185
+ * The one word for narrowing a list by typing. `/help` said `filter`, `/model`
186
186
  * and `/resume` said `search`, and they are the same gesture, so a reader who
187
187
  * learned one had to relearn it in the next overlay.
188
188
  */