@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
@@ -28,6 +28,8 @@ export interface OrphanRecoverySummary {
28
28
  skipped: number;
29
29
  /** Non-terminal rows whose worker process no longer exists, closed as stalled. */
30
30
  abandoned: number;
31
+ /** Non-terminal rows whose worker process is gone but whose own receipt verified, sealed from it. */
32
+ sealed: number;
31
33
  }
32
34
 
33
35
  /**
@@ -128,12 +130,40 @@ function isProcessAlive(pid: number | null): boolean {
128
130
 
129
131
  const NON_TERMINAL_STATUSES: ReadonlySet<string> = new Set(["queued", "running", "stale", "dead"]);
130
132
 
133
+ /**
134
+ * The sealed receipt for a row that never made it to a persisted terminal
135
+ * state, or null when there is no receipt or it does not verify against a
136
+ * reconstructable envelope. A run writes its receipt before it persists the
137
+ * ledger, so this window is exactly where a crash or a clobbered persist leaves
138
+ * the truth on disk in the receipt and a lie in the row.
139
+ */
140
+ function sealedEnvelopeFor(runId: string): RunEnvelope | null {
141
+ const path = join(receiptsDir(), `${runId}.json`);
142
+ if (!existsSync(path)) return null;
143
+ let receipt: RunReceipt;
144
+ try {
145
+ receipt = JSON.parse(readFileSync(path, "utf8")) as RunReceipt;
146
+ } catch {
147
+ return null;
148
+ }
149
+ if (receipt?.runId !== runId) return null;
150
+ if (!isReceiptIntegrity(receipt.integrity)) return null;
151
+ if (receipt.reproducibility?.cwd === undefined) return null;
152
+ return verifyOrphan(receipt, path);
153
+ }
154
+
131
155
  /**
132
156
  * Close abandoned ledger rows: a non-terminal row whose recorded worker pid
133
- * no longer exists belongs to an orchestrator that died mid-run. There is no
134
- * receipt to seal (the run never finalized), so the row is closed in place
135
- * with outcome "stalled" rather than left as a permanent ghost in status
136
- * output.
157
+ * no longer exists belongs to an orchestrator that died mid-run.
158
+ *
159
+ * Such a row may still have a sealed receipt on disk. A run writes its receipt
160
+ * before it persists the settled row, so a crash or a clobbered persist in that
161
+ * window leaves a receipt saying `succeeded`/0 next to a row that still says
162
+ * `running`. Stamping the row dead without looking was how a finished dispatch
163
+ * came to be recorded as a failure, and the receipt pass below could not repair
164
+ * it afterwards because it only adopts receipts with no row at all. So the
165
+ * receipt decides when it verifies, and only a row with nothing to seal is
166
+ * closed as "stalled" rather than left as a permanent ghost in status output.
137
167
  *
138
168
  * `endedAt` is the last instant the run was observed alive, not the instant
139
169
  * recovery noticed it was gone. Stamping recovery time made every phase
@@ -142,8 +172,9 @@ const NON_TERMINAL_STATUSES: ReadonlySet<string> = new Set(["queued", "running",
142
172
  * last heartbeat is the honest bound; a row that never heartbeat has only its
143
173
  * own start, which reads as a zero-length run rather than an invented one.
144
174
  */
145
- function closeAbandonedRows(ledger: Ledger): number {
175
+ function closeAbandonedRows(ledger: Ledger): { closed: number; sealed: number } {
146
176
  let closed = 0;
177
+ let sealed = 0;
147
178
  const localHost = hostname();
148
179
  for (const row of ledger.list()) {
149
180
  if (row.endedAt !== null || !NON_TERMINAL_STATUSES.has(row.status)) continue;
@@ -155,6 +186,15 @@ function closeAbandonedRows(ledger: Ledger): number {
155
186
  // for that host's own recovery pass.
156
187
  if (row.identity !== undefined && row.identity.host !== localHost) continue;
157
188
  if (isProcessAlive(row.pid)) continue;
189
+ const envelope = sealedEnvelopeFor(row.id);
190
+ if (envelope !== null) {
191
+ // Patch rather than replace: the row carries phase timings and lineage
192
+ // the receipt does not, and pid/heartbeatAt are this row's own history.
193
+ const { id: _id, pid: _pid, heartbeatAt: _heartbeatAt, ...settled } = envelope;
194
+ ledger.update(row.id, settled);
195
+ sealed += 1;
196
+ continue;
197
+ }
158
198
  ledger.update(row.id, {
159
199
  status: "dead",
160
200
  outcome: "stalled",
@@ -164,12 +204,14 @@ function closeAbandonedRows(ledger: Ledger): number {
164
204
  });
165
205
  closed += 1;
166
206
  }
167
- return closed;
207
+ return { closed, sealed };
168
208
  }
169
209
 
170
210
  export function recoverOrphanReceipts(ledger: Ledger): OrphanRecoverySummary {
171
- const summary: OrphanRecoverySummary = { recovered: 0, corrupt: 0, skipped: 0, abandoned: 0 };
172
- summary.abandoned = closeAbandonedRows(ledger);
211
+ const summary: OrphanRecoverySummary = { recovered: 0, corrupt: 0, skipped: 0, abandoned: 0, sealed: 0 };
212
+ const abandoned = closeAbandonedRows(ledger);
213
+ summary.abandoned = abandoned.closed;
214
+ summary.sealed = abandoned.sealed;
173
215
  const dir = receiptsDir();
174
216
  if (!existsSync(dir)) return summary;
175
217
  // Retention horizon: the ledger is a bounded ring, so a receipt older than
@@ -94,6 +94,11 @@ export const RECEIPT_INTEGRITY_FIELD_COVERAGE = {
94
94
  plan: true,
95
95
  personaOverride: true,
96
96
  projectContext: true,
97
+ // Always set on receipts written after #104 landed; absent only on older
98
+ // receipts, which digest exactly as they did before these fields existed,
99
+ // so the integrity version stays where it is.
100
+ rulesApplied: true,
101
+ operatorProfileApplied: true,
97
102
  exitCode: true,
98
103
  failureMessage: true,
99
104
  tokenCount: true,
@@ -106,13 +106,23 @@ function cloneEnvelope(envelope: RunEnvelope): RunEnvelope {
106
106
  return structuredClone(envelope);
107
107
  }
108
108
 
109
- function mergeRunsById(disk: RunEnvelope[], memory: RunEnvelope[]): RunEnvelope[] {
110
- // In-memory writes represent newer state (we just updated them in this process),
111
- // so they win on id conflict. Disk-only entries are preserved so sibling
112
- // processes' runs survive this process's persist().
109
+ /**
110
+ * Only a row this process actually wrote is newer than disk. The mirror also
111
+ * holds rows read at open time that belong to sibling processes, and letting
112
+ * those win reverted a sibling's settled run to the snapshot this process
113
+ * happened to read: a dispatch that finished `completed`/0 reappeared as
114
+ * `running` with a null receiptPath, and the next recovery pass then sealed it
115
+ * `dead`/1. So memory wins only for `dirty` ids; every other id takes the disk
116
+ * copy. A non-dirty mirror row absent from disk was evicted by a sibling's ring
117
+ * cap and stays evicted rather than being resurrected on every persist.
118
+ */
119
+ function mergeRunsById(disk: RunEnvelope[], memory: RunEnvelope[], dirty: ReadonlySet<string>): RunEnvelope[] {
113
120
  const merged = new Map<string, RunEnvelope>();
114
121
  for (const r of disk) merged.set(r.id, r);
115
- for (const r of memory) merged.set(r.id, r);
122
+ for (const r of memory) {
123
+ if (!dirty.has(r.id)) continue;
124
+ merged.set(r.id, r);
125
+ }
116
126
  const all = Array.from(merged.values());
117
127
  all.sort((a, b) => (a.startedAt < b.startedAt ? 1 : a.startedAt > b.startedAt ? -1 : 0));
118
128
  return all;
@@ -147,6 +157,10 @@ function capRuns(all: RunEnvelope[], maxRuns: number): RunEnvelope[] {
147
157
  export function openLedger(opts?: LedgerOptions): Ledger {
148
158
  const maxRuns = resolveMaxRuns(opts?.maxRuns);
149
159
  let runs: RunEnvelope[] = readRuns();
160
+ // Ids this process has written since the last successful persist. See
161
+ // mergeRunsById: this is what separates our writes from a sibling's rows we
162
+ // merely read at open time.
163
+ const dirty = new Set<string>();
150
164
 
151
165
  function findIndex(id: string): number {
152
166
  return runs.findIndex((r) => r.id === id);
@@ -187,6 +201,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
187
201
  costUsd: 0,
188
202
  };
189
203
  runs.unshift(envelope);
204
+ dirty.add(envelope.id);
190
205
  return cloneEnvelope(envelope);
191
206
  },
192
207
 
@@ -197,6 +212,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
197
212
  if (!current) return null;
198
213
  const next = applyPatch(current, patch);
199
214
  runs[idx] = next;
215
+ dirty.add(id);
200
216
  return cloneEnvelope(next);
201
217
  },
202
218
 
@@ -244,6 +260,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
244
260
  if (stateRootRemoved()) return receiptWithIntegrity;
245
261
  atomicWrite(target, JSON.stringify(receiptWithIntegrity, null, 2));
246
262
  runs[idx] = { ...current, receiptPath: target };
263
+ dirty.add(id);
247
264
  return receiptWithIntegrity;
248
265
  },
249
266
 
@@ -251,6 +268,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
251
268
  if (findIndex(envelope.id) !== -1) return false;
252
269
  runs.push(cloneEnvelope(envelope));
253
270
  runs.sort((a, b) => (a.startedAt < b.startedAt ? 1 : a.startedAt > b.startedAt ? -1 : 0));
271
+ dirty.add(envelope.id);
254
272
  return true;
255
273
  },
256
274
 
@@ -263,15 +281,22 @@ export function openLedger(opts?: LedgerOptions): Ledger {
263
281
  await withStateFileLock(target, () => {
264
282
  if (stateRootRemoved()) return;
265
283
  const diskRuns = readRuns();
266
- const merged = mergeRunsById(diskRuns, runs);
284
+ const merged = mergeRunsById(diskRuns, runs, dirty);
267
285
  const capped = capRuns(merged, maxRuns);
268
286
  runs = capped;
269
287
  atomicWrite(target, JSON.stringify(capped, null, 2));
288
+ // Everything this process claimed is now on disk, so the mirror holds
289
+ // no newer state until the next write. Clearing here is what stops a
290
+ // long-lived process from re-asserting an old snapshot of its own rows
291
+ // over a sibling's later update to them.
292
+ dirty.clear();
270
293
  });
271
294
  },
272
295
 
273
296
  reload(): void {
274
297
  runs = readRuns();
298
+ // The mirror was just replaced wholesale, so any unpersisted claim is gone.
299
+ dirty.clear();
275
300
  },
276
301
  };
277
302
  }
@@ -22,6 +22,7 @@
22
22
  */
23
23
 
24
24
  import { spawn } from "node:child_process";
25
+ import { AI_AGENT_NAME } from "../../core/agent-environment.js";
25
26
  import { shellQuote } from "../../core/shell-quote.js";
26
27
  import type { WorkerSpec } from "../../worker/spec-contract.js";
27
28
  import type { RunNodeIdentity } from "./types.js";
@@ -122,7 +123,7 @@ function remoteEnvAssignments(node: SshNodeEndpoint): string {
122
123
  // is the group an abort must signal.
123
124
  const labels = (node.labels ?? []).map((label) => label.trim()).filter((label) => label.length > 0);
124
125
  const labelAssignment = labels.length > 0 ? ` CLIO_CODER_WORKER_LABELS=${shellQuote(labels.join(","))}` : "";
125
- return `CLIO_CODER_RESIDENCY=${residency} CLIO_CODER_WORKER_PGID=$$${labelAssignment}`;
126
+ return `AI_AGENT=${AI_AGENT_NAME} CLIO_CODER_RESIDENCY=${residency} CLIO_CODER_WORKER_PGID=$$${labelAssignment}`;
126
127
  }
127
128
 
128
129
  export function buildRemoteWorkerCommand(node: SshNodeEndpoint, cwd: string): string {
@@ -713,6 +713,20 @@ export interface RunReceipt {
713
713
  personaOverride?: RunPersonaOverride;
714
714
  /** Effective project-context tier for this run; absent on receipts written before this field landed. */
715
715
  projectContext?: RunProjectContextProvenance;
716
+ /**
717
+ * Repo-relative `.clio-coder/rules/**` ids selected into this run's worker
718
+ * prompt, in load order; `[]` when the run had none. Always present on
719
+ * receipts written after this field landed (#104); absent on older
720
+ * receipts, which readers must treat as unknown, never as "no rules".
721
+ */
722
+ rulesApplied?: string[];
723
+ /**
724
+ * Whether the operator profile rendered non-empty content into this run's
725
+ * worker prompt. Always present on receipts written after this field
726
+ * landed (#104); absent on older receipts, which readers must treat as
727
+ * unknown, never as false.
728
+ */
729
+ operatorProfileApplied?: boolean;
716
730
  exitCode: number;
717
731
  failureMessage?: string;
718
732
  tokenCount: number;
@@ -26,6 +26,8 @@
26
26
 
27
27
  import { type ChildProcess, spawn } from "node:child_process";
28
28
  import { join } from "node:path";
29
+ import { withClioAgentEnvironment } from "../../core/agent-environment.js";
30
+ import { enableClioCompileCache, workerCompileCacheEnvironment } from "../../core/compile-cache.js";
29
31
  import { resolvePackageRoot } from "../../core/package-root.js";
30
32
  import type { WorkerSpec } from "../../worker/spec-contract.js";
31
33
  import {
@@ -184,7 +186,7 @@ export function spawnWorkerProcess(
184
186
  const child: ChildProcess = spawn(command, [...args], {
185
187
  stdio: ["pipe", "pipe", "pipe"],
186
188
  cwd: opts?.cwd,
187
- env: opts?.env ?? process.env,
189
+ env: withClioAgentEnvironment(opts?.env ?? process.env),
188
190
  // The worker leads its own process group so abort escalation covers the
189
191
  // descendants a runtime spawned, not only the immediate child.
190
192
  detached: true,
@@ -561,6 +563,23 @@ export function spawnNativeWorker(spec: WorkerSpec, opts?: SpawnOptions): Spawne
561
563
  const { workerEntryPath: _entryPath, ...processOptions } = opts ?? {};
562
564
  return spawnWorkerProcess(process.execPath, ["--disable-warning=ExperimentalWarning", workerEntry], spec, {
563
565
  ...processOptions,
564
- env: opts?.env ?? process.env,
566
+ env: withCompileCacheEnvironment(opts?.env ?? process.env),
565
567
  });
566
568
  }
569
+
570
+ /**
571
+ * Hand a native worker the parent's compile-cache directory. The worker's
572
+ * whole static graph resolves before its first application statement, so an
573
+ * in-process enableCompileCache() call there is too late; NODE_COMPILE_CACHE
574
+ * is the only control Node reads early enough. Spawning a worker writes state
575
+ * by definition, so the cache is established here when no boot entrypoint did
576
+ * it earlier (a direct `fleet run` reaches this line with the cache still
577
+ * unsettled); the enable is settle-once, root-gated, and operator-controlled
578
+ * like everywhere else. Operator settings win, stale markers are normalized
579
+ * away, and the worker entry consumes the injected pair from its own
580
+ * process.env right after Node reads it, so the cache serves Clio's own
581
+ * entry graph and never the user's node processes.
582
+ */
583
+ function withCompileCacheEnvironment(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
584
+ return workerCompileCacheEnvironment(env, enableClioCompileCache());
585
+ }
@@ -1,6 +1,6 @@
1
1
  import { enumerateWorkspaceFiles } from "../../../core/workspace-files.js";
2
+ import { readCodewiki, structuralCodewikiHash } from "../../context/codewiki/artifact.js";
2
3
  import { renderCodewikiDigest } from "../../context/codewiki/digest.js";
3
- import { readCodewiki, structuralCodewikiHash } from "../../context/codewiki/indexer.js";
4
4
  import { detectProjectProfile } from "../../session/workspace/project-type.js";
5
5
 
6
6
  export function collectContextMetrics(cwd: string): Record<string, number | string | null> {
@@ -1,5 +1,4 @@
1
1
  export const EVAL_TASK_FILE_VERSION = 1;
2
- export const EVAL_ARTIFACT_VERSION = 1;
3
2
 
4
3
  export type EvalCommandPhase = "setup" | "verifier";
5
4
 
@@ -53,6 +53,7 @@ import {
53
53
  const MAX_TASK_CHARS = 500;
54
54
  const TRANSCRIPT_TEXT_MAX_CHARS = 500;
55
55
  const TOOL_PREVIEW_MAX_CHARS = 240;
56
+ const TASK_LEDGER_ROW_LIMIT = 200;
56
57
 
57
58
  export interface BuildEvidenceOptions {
58
59
  /** Evidence bundles are written under <dataDir>/evidence/. */
@@ -1321,8 +1322,47 @@ function renderSessionTranscriptEntry(linked: LinkedSessionEntry): string[] {
1321
1322
  ];
1322
1323
  }
1323
1324
  if (entry.kind === "taskLedger") {
1325
+ const userLinks = entry.subgoals
1326
+ .filter((goal) => goal.origin === "user" && goal.userTaskId)
1327
+ .map((goal) => `${goal.id}:${goal.userTaskId}`)
1328
+ .join(",");
1329
+ const boardId = entry.boardId ?? "legacy";
1330
+ const provenance = userLinks ? ` userLinks=${userLinks}` : "";
1331
+ const evidenceByTaskId = new Map(
1332
+ entry.requiredValidationEvidence.map((item) => [
1333
+ item.id.endsWith(".evidence") ? item.id.slice(0, -".evidence".length) : item.id,
1334
+ item.description,
1335
+ ]),
1336
+ );
1337
+ const rows = entry.subgoals.slice(0, TASK_LEDGER_ROW_LIMIT).map((goal) => {
1338
+ const userTaskId = goal.userTaskId ?? "none";
1339
+ const reason = goal.description === undefined ? "none" : previewUnknown(goal.description);
1340
+ const evidence = evidenceByTaskId.has(goal.id) ? previewUnknown(evidenceByTaskId.get(goal.id)) : "none";
1341
+ return ` task board=${boardId} id=${goal.id} title=${previewUnknown(goal.title)} status=${goal.status} origin=${goal.origin ?? "agent"} userTaskId=${userTaskId} reason=${reason} evidence=${evidence}`;
1342
+ });
1343
+ if (entry.subgoals.length > TASK_LEDGER_ROW_LIMIT) {
1344
+ rows.push(` task rows omitted=${entry.subgoals.length - TASK_LEDGER_ROW_LIMIT}`);
1345
+ }
1346
+ return [
1347
+ `${prefix} taskLedger goals=${entry.goals.length} subgoals=${entry.subgoals.length} activeRuns=${entry.activeRunIds.length} evidence=${entry.requiredValidationEvidence.length} board=${boardId}${provenance}`,
1348
+ ...rows,
1349
+ ];
1350
+ }
1351
+ if (entry.kind === "decisionLedger") {
1352
+ const summary = entry.summary === undefined ? "" : ` summary=${previewUnknown(entry.summary)}`;
1324
1353
  return [
1325
- `${prefix} taskLedger goals=${entry.goals.length} subgoals=${entry.subgoals.length} activeRuns=${entry.activeRunIds.length} evidence=${entry.requiredValidationEvidence.length}`,
1354
+ `${prefix} decisionLedger anchor=${entry.parentTurnId ?? "none"} interview=${entry.interviewId} status=${entry.interviewStatus} startedAt=${entry.startedAt} endedAt=${entry.endedAt} rounds=${entry.roundCount} decisions=${entry.decisions.length}${summary}`,
1355
+ ...entry.decisions.map((decision) => {
1356
+ const label = decision.label === undefined ? "" : ` label=${previewUnknown(decision.label)}`;
1357
+ const sourceQuestion =
1358
+ decision.source_question === undefined ? "" : ` sourceQuestion=${previewUnknown(decision.source_question)}`;
1359
+ const revision = decision.revisedAt === undefined ? "" : ` revisedAt=${decision.revisedAt} revisionSource=operator`;
1360
+ const correction =
1361
+ decision.correction === undefined
1362
+ ? ""
1363
+ : ` correctionSource=operator correction=${previewUnknown(decision.correction)}`;
1364
+ return ` decision key=${decision.key} status=${decision.status} decidedAt=${decision.decidedAt}${revision}${label}${sourceQuestion} value=${previewUnknown(decision.value)}${correction}`;
1365
+ }),
1326
1366
  ];
1327
1367
  }
1328
1368
  if (entry.kind === "workerRun") {
@@ -0,0 +1,52 @@
1
+ import { existsSync } from "node:fs";
2
+
3
+ import { readSettings, settingsPath, updateSettings } from "../../../core/config.js";
4
+ import { authStoragePath } from "../../providers/auth/backend-file.js";
5
+ import { openAuthStorage } from "../../providers/auth/index.js";
6
+ import type { Migration } from "./index.js";
7
+
8
+ function normalizeLmStudioUrl(url: string | undefined): string | undefined {
9
+ if (!url) return url;
10
+ if (url.startsWith("ws://")) return `http://${url.slice("ws://".length)}`;
11
+ if (url.startsWith("wss://")) return `https://${url.slice("wss://".length)}`;
12
+ return url;
13
+ }
14
+
15
+ const migration: Migration = {
16
+ id: "2026-08-18-lmstudio-runtime-id",
17
+ async up(): Promise<void> {
18
+ let keepLegacyCredential = false;
19
+ if (existsSync(settingsPath())) {
20
+ const current = readSettings();
21
+ keepLegacyCredential = current.targets.some((target) => target.auth?.apiKeyRef === "lmstudio-native");
22
+ const needsSettingsRewrite = current.targets.some(
23
+ (target) =>
24
+ target.runtime === "lmstudio-native" ||
25
+ ((target.runtime === "lmstudio" || target.runtime === "lmstudio-native") &&
26
+ normalizeLmStudioUrl(target.url) !== target.url),
27
+ );
28
+ if (needsSettingsRewrite) {
29
+ updateSettings((settings) => {
30
+ for (const target of settings.targets) {
31
+ if (target.runtime !== "lmstudio-native" && target.runtime !== "lmstudio") continue;
32
+ target.runtime = "lmstudio";
33
+ const url = normalizeLmStudioUrl(target.url);
34
+ if (url !== undefined) target.url = url;
35
+ }
36
+ });
37
+ }
38
+ }
39
+ if (!existsSync(authStoragePath())) return;
40
+ // Only reach for the rename when a legacy credential is actually stored.
41
+ // Most homes this migration runs on never held one, and asking the store
42
+ // to rename nothing is work that can only fail: it takes the credentials
43
+ // lock and, before this guard existed, refused outright on a file the
44
+ // parser could not fully read, which failed every later `clio-coder
45
+ // upgrade` on that machine.
46
+ const storage = openAuthStorage();
47
+ if (!storage.hasStored("lmstudio-native")) return;
48
+ storage.renameProvider("lmstudio-native", "lmstudio", { keepSource: keepLegacyCredential });
49
+ },
50
+ };
51
+
52
+ export default migration;
@@ -25,6 +25,8 @@
25
25
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
26
26
  import { join } from "node:path";
27
27
 
28
+ import lmStudioRuntimeId from "./2026-08-18-lmstudio-runtime-id.js";
29
+
28
30
  export interface Migration {
29
31
  id: string;
30
32
  up(stateDir: string): Promise<void>;
@@ -43,7 +45,7 @@ export interface MigrationRunResult {
43
45
  available: string[];
44
46
  }
45
47
 
46
- const REGISTRY: ReadonlyArray<Migration> = Object.freeze([]);
48
+ const REGISTRY: ReadonlyArray<Migration> = Object.freeze([lmStudioRuntimeId]);
47
49
 
48
50
  export function listMigrations(): ReadonlyArray<Migration> {
49
51
  return REGISTRY;
@@ -72,23 +74,41 @@ function writeManifest(path: string, manifest: MigrationManifest): void {
72
74
  writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\n`, { encoding: "utf8", mode: 0o644 });
73
75
  }
74
76
 
75
- export async function runPending(stateDir: string): Promise<MigrationRunResult> {
77
+ /**
78
+ * Apply every registered migration this state tree has not recorded yet.
79
+ *
80
+ * `migrations` defaults to the compiled registry and exists so the ordering
81
+ * guarantee below can be exercised against a failing migration; production
82
+ * callers pass one argument.
83
+ */
84
+ export async function runPending(
85
+ stateDir: string,
86
+ migrations: ReadonlyArray<Migration> = REGISTRY,
87
+ ): Promise<MigrationRunResult> {
76
88
  mkdirSync(stateDir, { recursive: true });
77
89
  const path = manifestPath(stateDir);
78
90
  const manifest = readManifest(path);
79
91
  const applied = new Set(manifest.applied);
80
92
  const newlyApplied: string[] = [];
81
- for (const m of REGISTRY) {
93
+ // The manifest is written after each `up()` rather than once at the end. A
94
+ // throw from a later migration used to discard the record of the earlier ones
95
+ // that had already succeeded, so they re-ran on the next upgrade against a
96
+ // tree they had already changed. That breaks the at-most-once guarantee this
97
+ // module's contract states.
98
+ for (const m of migrations) {
82
99
  if (applied.has(m.id)) continue;
83
100
  await m.up(stateDir);
84
101
  applied.add(m.id);
85
102
  newlyApplied.push(m.id);
103
+ writeManifest(path, { applied: [...applied] });
86
104
  }
87
105
  const allApplied = [...applied];
106
+ // Nothing pending still rewrites the manifest, so a home whose file was
107
+ // missing or unparseable gains a well-formed one.
88
108
  writeManifest(path, { applied: allApplied });
89
109
  return {
90
110
  applied: newlyApplied,
91
111
  allApplied,
92
- available: REGISTRY.map((m) => m.id),
112
+ available: migrations.map((m) => m.id),
93
113
  };
94
114
  }
@@ -15,6 +15,10 @@ import { spawnSync } from "node:child_process";
15
15
  import { readFileSync } from "node:fs";
16
16
  import { join } from "node:path";
17
17
  import { parse as parseYaml } from "yaml";
18
+ import {
19
+ reportCommitAttributionDiagnostic,
20
+ withManagedGitCommitAttributionEnvironment,
21
+ } from "../../core/git-commit-attribution.js";
18
22
  import {
19
23
  type HookReceiptSink,
20
24
  loadUserHooks,
@@ -156,12 +160,20 @@ export function installUserHooks(options: InstallUserHooksOptions): InstallUserH
156
160
  export function spawnSyncCommandRunner(): UserHookCommandRunner {
157
161
  return (argv, options): UserHookCommandResult => {
158
162
  const [command, ...args] = argv;
163
+ // A user hook is operator automation, not Clio work: the environment is
164
+ // normalized so a nested seam sees consistent state, but no role is claimed.
165
+ const attribution = withManagedGitCommitAttributionEnvironment(process.env, {
166
+ cwd: options.cwd ?? process.cwd(),
167
+ evidence: {},
168
+ });
169
+ reportCommitAttributionDiagnostic(attribution.diagnostic);
159
170
  const result = spawnSync(command ?? "", args, {
160
171
  ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
161
172
  timeout: options.timeoutMs,
162
173
  maxBuffer: COMMAND_OUTPUT_MAX_BYTES,
163
174
  encoding: "utf8",
164
175
  shell: false,
176
+ env: attribution.env,
165
177
  });
166
178
  const timedOut = result.error !== undefined && (result.error as NodeJS.ErrnoException).code === "ETIMEDOUT";
167
179
  return {
@@ -7,35 +7,48 @@ import { type MiddlewareEffect, metadataNumber } from "./types.js";
7
7
  * models read and ignore every ambient prompt channel but comply with the
8
8
  * identical instruction when it is visible user-message text, and
9
9
  * middleware reminders are the sanctioned mechanism for that text. Once
10
- * per session, on the first substantive task turn, when model-visible
11
- * skills exist, this registration injects one compact line teaching the
12
- * same reply protocol as the context(scope="skills") listing footer.
13
- * Reminder text only: loading stays operator-gated (`pendingSkillPolicy`
14
- * untouched), and a turn that already carries a pending skill request gets
15
- * no reminder because the operator has already chosen.
10
+ * per session, on the first substantive task turn, when model-visible or
11
+ * installable skills exist, this registration injects one compact line
12
+ * teaching the same reply protocol as the context(scope="skills") listing
13
+ * footer. Installable skills count because a fresh install has none
14
+ * installed and a marketplace full of them: gating on installed alone meant
15
+ * the one channel these models act on never fired for the operator who
16
+ * needed it most. Reminder text only: loading stays operator-gated
17
+ * (`pendingSkillPolicy` untouched), and a turn that already carries a
18
+ * pending skill request gets no reminder because the operator has already
19
+ * chosen.
16
20
  */
17
21
 
18
22
  export const SKILLS_REMINDER_REGISTRATION_ID = "observer.skills-reminder";
19
23
 
20
24
  export { SKILL_SUGGESTION_ANCHOR };
21
25
 
22
- export function skillsReminderMessage(count: number): string {
26
+ export function skillsReminderMessage(installed: number, installable = 0): string {
23
27
  // Unconditional imperative, deliberately: the skill-mastery batteries
24
28
  // showed literal local models comply with "list and check" but never act
25
29
  // on wording that first asks them to classify the task as skill-shaped.
26
30
  // One listing call on the session's first turn is the accepted price.
31
+ const counts =
32
+ installable > 0
33
+ ? `${installed} installed, ${installable} installable from the marketplace`
34
+ : `${installed} installed`;
27
35
  return (
28
- `[Skills] ${count} installed. Start this task by listing them with context(scope="skills") ` +
36
+ `[Skills] ${counts}. Start this task by listing them with context(scope="skills") ` +
29
37
  "and checking for a match; if one matches, open your reply with the line " +
30
38
  `\`${SKILL_SUGGESTION_ANCHOR}\` (a comma-separated sequence, in order, when several compose) ` +
31
- "and wait for the operator; load only on operator request. If none match, do not mention " +
32
- "skills and continue with the task."
39
+ "and wait for the operator; load only on operator request, and a marketplace skill is offered for " +
40
+ "install when the operator runs it. If none match, do not mention skills and continue with the task."
33
41
  );
34
42
  }
35
43
 
36
44
  export interface SkillsReminderDeps {
37
- /** Count of skills the model may see and suggest; 0 disables the reminder. */
45
+ /** Count of installed skills the model may see and suggest. */
38
46
  countModelVisibleSkills(): number;
47
+ /**
48
+ * Count of marketplace skills not yet installed. Optional; absent reads as
49
+ * zero. Either count above zero arms the reminder.
50
+ */
51
+ countInstallableSkills?(): number;
39
52
  }
40
53
 
41
54
  const NO_EFFECTS: ReadonlyArray<MiddlewareEffect> = [];
@@ -174,14 +187,16 @@ export function createSkillsReminderRegistration(deps: SkillsReminderDeps): Midd
174
187
  // suggesting one would only add noise.
175
188
  const pendingSkillRequests = metadataNumber(input, "pendingSkillRequests");
176
189
  if (pendingSkillRequests !== null && pendingSkillRequests > 0) return NO_EFFECTS;
177
- let count = 0;
190
+ let installed = 0;
191
+ let installable = 0;
178
192
  try {
179
- count = deps.countModelVisibleSkills();
193
+ installed = deps.countModelVisibleSkills();
194
+ installable = deps.countInstallableSkills?.() ?? 0;
180
195
  } catch {
181
196
  return NO_EFFECTS;
182
197
  }
183
- if (count <= 0) return NO_EFFECTS;
184
- return [{ kind: "inject_reminder", severity: "info", message: skillsReminderMessage(count) }];
198
+ if (installed <= 0 && installable <= 0) return NO_EFFECTS;
199
+ return [{ kind: "inject_reminder", severity: "info", message: skillsReminderMessage(installed, installable) }];
185
200
  },
186
201
  };
187
202
  }