@iowarp/clio-coder 0.4.1 → 0.4.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 (437) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/CONTRIBUTING.md +59 -36
  3. package/README.md +404 -472
  4. package/SECURITY.md +2 -1
  5. package/dist/{acp-ZILU3AUO.js → acp-TMDQZDIG.js} +7 -7
  6. package/dist/{agents-HYWGBGQR.js → agents-5N5NG3XG.js} +28 -28
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/{auth-N3QT7CBO.js → auth-Z5CCBXKQ.js} +8 -9
  9. package/dist/{builtins-UJLMOVOV.js → builtins-K6TNDT24.js} +4 -4
  10. package/dist/{chunk-GVQJ5CCZ.js → chunk-2HFQNRV3.js} +7 -7
  11. package/dist/{chunk-QMXC4JB7.js → chunk-2NHR3NAY.js} +163 -1401
  12. package/dist/chunk-2X4RYJTJ.js +39 -0
  13. package/dist/{chunk-Y45G3AXC.js → chunk-2Z2IKEXI.js} +6 -10
  14. package/dist/{chunk-EIMVLWB3.js → chunk-34BHNEE3.js} +7 -3
  15. package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
  16. package/dist/chunk-3EBYEESD.js +314 -0
  17. package/dist/{chunk-CTJ4RNAA.js → chunk-3F7VUY77.js} +2 -2
  18. package/dist/{chunk-AP73CFDC.js → chunk-3KIPBMUA.js} +2 -2
  19. package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
  20. package/dist/{chunk-VEGN6WIQ.js → chunk-462T4EGZ.js} +2 -2
  21. package/dist/{chunk-AFKWHWXF.js → chunk-4JDLP6ZS.js} +33 -16
  22. package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
  23. package/dist/{chunk-AKB4GYDL.js → chunk-54ODD65L.js} +5 -5
  24. package/dist/{chunk-BBTJOK6Y.js → chunk-5KW52TEP.js} +3 -3
  25. package/dist/{chunk-6CCS4G3W.js → chunk-5PFYMY2V.js} +2 -2
  26. package/dist/chunk-77QIVUZB.js +1334 -0
  27. package/dist/{chunk-7OBGU7UB.js → chunk-7BHIY2MW.js} +7 -13
  28. package/dist/{chunk-3QSOM6PA.js → chunk-AZ4WMN4W.js} +2 -2
  29. package/dist/{chunk-6NJQITNH.js → chunk-B74PXLU7.js} +6 -3
  30. package/dist/{chunk-R23Z6K6I.js → chunk-B7HM5Z7T.js} +15 -15
  31. package/dist/{chunk-R32CLGZ6.js → chunk-BO7Y52RY.js} +81 -20
  32. package/dist/{chunk-UEDMSP56.js → chunk-BYMNWQ7O.js} +123 -148
  33. package/dist/{chunk-ZJLUDYFY.js → chunk-CRFOIAX3.js} +4 -4
  34. package/dist/{chunk-2NM363SV.js → chunk-CYZW7JHJ.js} +7 -7
  35. package/dist/{chunk-6HMJX2VU.js → chunk-DYHAXKHD.js} +38 -10
  36. package/dist/{chunk-THYWACCR.js → chunk-DZAW46HP.js} +3 -3
  37. package/dist/{chunk-FYUN5KZ3.js → chunk-DZEK6CJN.js} +17 -17
  38. package/dist/{chunk-3I5NY75V.js → chunk-E7GT7O5N.js} +5 -5
  39. package/dist/{chunk-VKFQTNDV.js → chunk-F2I26BDK.js} +4 -4
  40. package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
  41. package/dist/{chunk-IXJT6DCX.js → chunk-FVDGR2ZL.js} +3 -3
  42. package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
  43. package/dist/{chunk-7EPLI7VL.js → chunk-HIICAHCJ.js} +2 -2
  44. package/dist/{chunk-E67WX76H.js → chunk-HKMD33FO.js} +29 -80
  45. package/dist/chunk-HLAFFSEK.js +360 -0
  46. package/dist/{chunk-UAPGZHYC.js → chunk-I64IFBLB.js} +9 -2
  47. package/dist/{chunk-XKA2ICR3.js → chunk-I66ZTYNP.js} +440 -175
  48. package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
  49. package/dist/{chunk-PVAMAVBB.js → chunk-IDNA72AH.js} +102 -2
  50. package/dist/{chunk-GCSMB2KY.js → chunk-IKOZFYBN.js} +1 -1
  51. package/dist/{chunk-2VG7KLYV.js → chunk-IKSLQ4XV.js} +5460 -3241
  52. package/dist/{chunk-QKIFBZKT.js → chunk-IMXMHHMQ.js} +166 -25
  53. package/dist/{chunk-74YWRRU5.js → chunk-JBCS7CRR.js} +2 -2
  54. package/dist/{chunk-BDPT6GTK.js → chunk-JWJGP5DQ.js} +2 -2
  55. package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
  56. package/dist/chunk-KPXDY6QF.js +47 -0
  57. package/dist/{chunk-ABLSQ6JX.js → chunk-LJID3DYZ.js} +7 -1
  58. package/dist/{chunk-VKRH2TCS.js → chunk-M2DAX4F6.js} +2 -2
  59. package/dist/{chunk-6I5ILFOF.js → chunk-M2WXEHER.js} +2 -2
  60. package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
  61. package/dist/{chunk-N5UK64DP.js → chunk-MCMZMDAC.js} +2 -2
  62. package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
  63. package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
  64. package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
  65. package/dist/{chunk-HUAS7ITX.js → chunk-O3YUNJZ2.js} +13 -21
  66. package/dist/{chunk-MA3H6DM5.js → chunk-P75RZCJW.js} +25 -3
  67. package/dist/{chunk-IG7BCQBA.js → chunk-PGF63K6I.js} +2 -2
  68. package/dist/chunk-PJX3WQUQ.js +42 -0
  69. package/dist/{chunk-6DWBAZ5U.js → chunk-Q4XWMHX6.js} +4 -6
  70. package/dist/{chunk-OJTRZGR3.js → chunk-QQLGQY2A.js} +8 -8
  71. package/dist/{chunk-J4HBWF6Y.js → chunk-RLYRBIYQ.js} +115 -20
  72. package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
  73. package/dist/{chunk-C537JADH.js → chunk-SSEYRH53.js} +6 -7
  74. package/dist/chunk-SZAA6XDG.js +30 -0
  75. package/dist/{chunk-MOPSG2X7.js → chunk-TPEQIQIE.js} +6 -6
  76. package/dist/{chunk-JA5QWE4Z.js → chunk-UBRFI4HS.js} +1879 -1650
  77. package/dist/{chunk-BTGG6BG2.js → chunk-UH347SHR.js} +154 -15
  78. package/dist/{chunk-5YHDIDBP.js → chunk-UH632ZYL.js} +2 -2
  79. package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
  80. package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
  81. package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
  82. package/dist/{chunk-UXN6JT4W.js → chunk-W4YEMFBX.js} +2 -2
  83. package/dist/{chunk-TD3PGPQA.js → chunk-W6NIE6OW.js} +2 -2
  84. package/dist/{chunk-TVH4ONAM.js → chunk-X7IARSHT.js} +3 -3
  85. package/dist/{chunk-PJJ6MY27.js → chunk-XE3PCIXH.js} +3 -3
  86. package/dist/{chunk-FEFIFZTL.js → chunk-XGDPUNND.js} +2 -2
  87. package/dist/{chunk-SCYB3HA4.js → chunk-XOXV5GKE.js} +51 -16
  88. package/dist/{chunk-QTFGO774.js → chunk-XQRY4DTA.js} +24 -11
  89. package/dist/{chunk-BJGUKIG4.js → chunk-YJISEZKC.js} +2 -2
  90. package/dist/{chunk-GPPB3JBE.js → chunk-ZGNYYXQ6.js} +2 -2
  91. package/dist/{chunk-SINK3QR6.js → chunk-ZNT2M6TG.js} +7 -7
  92. package/dist/{chunk-7RY5VZPH.js → chunk-ZW4HH5JJ.js} +6 -6
  93. package/dist/cli/index.js +33 -32
  94. package/dist/{clio-IT3G3VQH.js → clio-7VB377CC.js} +7 -7
  95. package/dist/{code-nav-RK6S7F6E.js → code-nav-YVLCYA7V.js} +85 -17
  96. package/dist/{config-3QZRWZJF.js → config-4HVOS65E.js} +88 -43
  97. package/dist/{configure-FL7Y3KJF.js → configure-PIWO7B24.js} +10 -10
  98. package/dist/{context-5HE7ODYK.js → context-IYEHL3WQ.js} +33 -31
  99. package/dist/{context-XNHL75JV.js → context-KQYIWPWT.js} +47 -34
  100. package/dist/{context-KYQFRVDC.js → context-N6ZE3LGJ.js} +11 -11
  101. package/dist/{context-clear-N545L53A.js → context-clear-G4OGZJDS.js} +33 -31
  102. package/dist/{context-working-set-QHKXSV2F.js → context-working-set-BWLF6LJP.js} +7 -7
  103. package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-2QQAITS3.js} +38 -38
  104. package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
  105. package/dist/{doctor-ZGPEGHIP.js → doctor-LHBD36VU.js} +23 -22
  106. package/dist/{eval-GXLL44RD.js → eval-C45FYRJ6.js} +21 -20
  107. package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-6DEJPLBF.js} +2 -2
  108. package/dist/{evidence-HWLBRH3Q.js → evidence-6SHONYAF.js} +30 -28
  109. package/dist/{evolve-FTZBMNVW.js → evolve-KRKMV72X.js} +30 -28
  110. package/dist/{extensions-VHRBEID7.js → extensions-KPZ2UHBB.js} +5 -3
  111. package/dist/{fleet-CKZHJWZJ.js → fleet-IVTCKDHT.js} +62 -61
  112. package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-EDWL3IT7.js} +5 -5
  113. package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-YP3YEFGK.js} +4 -4
  114. package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-ZFWKHY2M.js} +16 -14
  115. package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-FVUNCBML.js} +31 -29
  116. package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-UN5XED4R.js} +2 -2
  117. package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-XOWC4HSX.js} +17 -15
  118. package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-UN3SODEL.js} +30 -28
  119. package/dist/{fleet-view-WAMJYNDT.js → fleet-view-TWHJKCN6.js} +31 -29
  120. package/dist/{init-5XQRBOFV.js → init-T2QORQ3Y.js} +50 -49
  121. package/dist/{interop-34TVO25M.js → interop-IN5I2A66.js} +5 -5
  122. package/dist/{library-3QY6KF57.js → library-LSCATDLZ.js} +15 -13
  123. package/dist/{memory-L4UTIIIW.js → memory-HYOKAGGJ.js} +31 -29
  124. package/dist/{models-ZVX3QOWE.js → models-2GPMFYCM.js} +22 -21
  125. package/dist/{monitor-CEKVSYTS.js → monitor-E4ASVUJH.js} +34 -32
  126. package/dist/{orchestrator-77BAP6BC.js → orchestrator-DDMPR3PY.js} +984 -583
  127. package/dist/{panes-7STHOAUJ.js → panes-E3RUXOW5.js} +4 -4
  128. package/dist/{panes-SHAUIRXY.js → panes-IXKLOKA2.js} +23 -8
  129. package/dist/{reset-EOLM7GVE.js → reset-OAQP3W4O.js} +4 -4
  130. package/dist/{resources-74GKTLSF.js → resources-OTRSN34L.js} +15 -13
  131. package/dist/{run-HBAUJNNZ.js → run-5DEYH5QK.js} +60 -59
  132. package/dist/{share-G3APVLVP.js → share-IHWTLO3M.js} +19 -15
  133. package/dist/{skills-35HHUKCR.js → skills-IYMXMKW4.js} +17 -15
  134. package/dist/{skills-eval-QN4HSHDC.js → skills-eval-DROHSJAR.js} +36 -36
  135. package/dist/{skills-inventory-J357J34F.js → skills-inventory-D7X4L4ZX.js} +15 -13
  136. package/dist/{slash-commands-JZZCQA32.js → slash-commands-QBM7UZ3B.js} +21 -18
  137. package/dist/{steer-XAVHJM22.js → steer-Z5DO23FJ.js} +2 -2
  138. package/dist/{targets-DSM6CY3M.js → targets-P2FUC4IL.js} +25 -28
  139. package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-YREJ3JX2.js} +5 -5
  140. package/dist/{tools-MKNWVPBH.js → tools-5B7RO6MV.js} +4 -4
  141. package/dist/{trace-ECQ7TIYZ.js → trace-YMGMUM6A.js} +55 -7
  142. package/dist/{upgrade-H7TOM7YL.js → upgrade-PXK3S2YM.js} +11 -9
  143. package/dist/{usage-X52N3IDJ.js → usage-ME5MPXGX.js} +36 -34
  144. package/dist/{verifiers-EJTVVSMA.js → verifiers-BVZ7IWOO.js} +5 -5
  145. package/dist/{verify-YJL6XET2.js → verify-5K7ZKQFC.js} +4 -4
  146. package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
  147. package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-F5W5QTYY.js} +48 -47
  148. package/dist/{with-panes-OBOBFIIR.js → with-panes-BYOJCLAM.js} +51 -255
  149. package/dist/worker/entry.js +45 -30
  150. package/docs/README.md +176 -81
  151. package/docs/{acp.md → architecture/acp.md} +36 -20
  152. package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
  153. package/docs/{architecture.md → architecture/architecture.md} +43 -22
  154. package/docs/{artifact-placement.md → architecture/artifact-placement.md} +26 -23
  155. package/docs/architecture/artifact-versions.md +90 -0
  156. package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
  157. package/docs/{context-engine.md → architecture/context-engine.md} +25 -25
  158. package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
  159. package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
  160. package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
  161. package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
  162. package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
  163. package/docs/{model-catalog.md → architecture/model-catalog.md} +40 -17
  164. package/docs/{observability.md → architecture/observability.md} +26 -13
  165. package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
  166. package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +55 -20
  167. package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +35 -24
  168. package/docs/{safety-model.md → architecture/safety-model.md} +20 -15
  169. package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
  170. package/docs/architecture/time-conventions.md +125 -0
  171. package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
  172. package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
  173. package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
  174. package/docs/{built-in-agents.md → guide/built-in-agents.md} +50 -34
  175. package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +65 -60
  176. package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +227 -289
  177. package/docs/guide/configuration-reference.md +1158 -0
  178. package/docs/{environment-variables.md → guide/environment-variables.md} +31 -28
  179. package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
  180. package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
  181. package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
  182. package/docs/{glossary.md → guide/glossary.md} +14 -11
  183. package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +44 -13
  184. package/docs/guide/panes-and-files.md +290 -0
  185. package/docs/{proactive-memory.md → guide/proactive-memory.md} +79 -66
  186. package/docs/{resource-library.md → guide/resource-library.md} +13 -4
  187. package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +7 -3
  188. package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
  189. package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
  190. package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
  191. package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
  192. package/docs/{development-pipeline.md → process/development-pipeline.md} +24 -26
  193. package/docs/process/documentation-coverage.md +100 -0
  194. package/docs/process/documentation-guide.md +187 -0
  195. package/docs/{eval-runner.md → process/eval-runner.md} +41 -50
  196. package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
  197. package/docs/{evolution.md → process/evolution.md} +2 -2
  198. package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
  199. package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
  200. package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
  201. package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
  202. package/evals/README.md +2 -2
  203. package/package.json +9 -7
  204. package/skills/README.md +46 -37
  205. package/skills/coding/ast-grep/SKILL.md +2 -2
  206. package/skills/coding/coding-standards/SKILL.md +2 -2
  207. package/skills/coding/prototype/SKILL.md +2 -2
  208. package/skills/coding/tdd/SKILL.md +2 -2
  209. package/skills/context/context-handoff/SKILL.md +2 -2
  210. package/skills/context/context-prime/SKILL.md +2 -2
  211. package/skills/git/file-ticket/SKILL.md +2 -2
  212. package/skills/git/fix-issue/SKILL.md +3 -3
  213. package/skills/git/resolve-merge-conflicts/SKILL.md +2 -2
  214. package/skills/git/ship/SKILL.md +2 -2
  215. package/skills/git/worktree-create/SKILL.md +2 -2
  216. package/skills/git/worktree-merge/SKILL.md +2 -2
  217. package/skills/meta/clio-coder-dev/SKILL.md +9 -5
  218. package/skills/meta/clio-coder-dev/evals.md +3 -2
  219. package/skills/meta/clio-coder-test/SKILL.md +102 -95
  220. package/skills/meta/clio-coder-test/evals.md +9 -4
  221. package/skills/meta/clio-coder-test/references/harness.md +100 -124
  222. package/skills/meta/clio-coder-test/references/test-map.md +77 -50
  223. package/skills/meta/credentials/SKILL.md +2 -2
  224. package/skills/meta/find-skills/SKILL.md +2 -2
  225. package/skills/meta/herdr/SKILL.md +2 -2
  226. package/skills/meta/skill-craft/SKILL.md +22 -16
  227. package/skills/planning/architecture/SKILL.md +2 -2
  228. package/skills/planning/backlog/SKILL.md +2 -2
  229. package/skills/planning/prd/SKILL.md +2 -2
  230. package/skills/planning/product-intent/SKILL.md +2 -2
  231. package/skills/planning/tech-spec/SKILL.md +2 -2
  232. package/skills/registry.yaml +62 -62
  233. package/skills/research/arxiv-literature/SKILL.md +2 -2
  234. package/skills/research/experiment-protocol/SKILL.md +2 -2
  235. package/skills/research/scientific-debugging/SKILL.md +2 -2
  236. package/skills/research/scientific-modernization/SKILL.md +2 -2
  237. package/skills/skill-marketplace.json +62 -62
  238. package/skills/workflow/cut-it/SKILL.md +2 -2
  239. package/skills/workflow/design-council/SKILL.md +2 -2
  240. package/skills/workflow/grill-me/SKILL.md +2 -2
  241. package/skills/workflow/workflow-distiller/SKILL.md +2 -2
  242. package/src/cli/args.ts +2 -2
  243. package/src/cli/bootstrap-generate.ts +1 -1
  244. package/src/cli/config-inspect.ts +65 -12
  245. package/src/cli/configure.ts +0 -4
  246. package/src/cli/docs.ts +22 -14
  247. package/src/cli/doctor-naming.ts +5 -5
  248. package/src/cli/doctor-toolchain.ts +3 -3
  249. package/src/cli/eval.ts +1 -2
  250. package/src/cli/extensions.ts +2 -1
  251. package/src/cli/fleet.ts +1 -1
  252. package/src/cli/index.ts +2 -1
  253. package/src/cli/internal-dispatch.ts +3 -4
  254. package/src/cli/panes.ts +19 -5
  255. package/src/cli/run.ts +2 -2
  256. package/src/cli/share.ts +5 -1
  257. package/src/cli/skills-eval.ts +3 -3
  258. package/src/cli/targets.ts +2 -6
  259. package/src/cli/trace.ts +55 -4
  260. package/src/cli/wiki-generate.ts +1 -1
  261. package/src/core/artifact-paths.ts +1 -1
  262. package/src/core/bash-exec.ts +131 -86
  263. package/src/core/bus-events.ts +51 -6
  264. package/src/core/config.ts +5 -1
  265. package/src/core/defaults.ts +7 -4
  266. package/src/core/dispatch-outcome.ts +16 -0
  267. package/src/core/guardrails.ts +10 -49
  268. package/src/core/prompt-hint.ts +9 -0
  269. package/src/domains/agents/builtins/architect.md +2 -3
  270. package/src/domains/agents/builtins/coder.md +3 -2
  271. package/src/domains/agents/builtins/debugger.md +2 -2
  272. package/src/domains/agents/builtins/documenter.md +2 -2
  273. package/src/domains/agents/builtins/git-master.md +1 -1
  274. package/src/domains/agents/builtins/oracle.md +1 -1
  275. package/src/domains/agents/builtins/provenance.md +1 -1
  276. package/src/domains/agents/builtins/researcher.md +1 -1
  277. package/src/domains/agents/builtins/scout.md +1 -1
  278. package/src/domains/agents/builtins/tester.md +2 -2
  279. package/src/domains/agents/builtins/verifier.md +2 -2
  280. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  281. package/src/domains/agents/catalog.ts +12 -14
  282. package/src/domains/agents/contract.ts +2 -0
  283. package/src/domains/agents/extension.ts +23 -1
  284. package/src/domains/config/keybindings.ts +8 -0
  285. package/src/domains/context/extension.ts +0 -3
  286. package/src/domains/context/working-set/path-index.ts +1 -0
  287. package/src/domains/dispatch/capability-match.ts +10 -0
  288. package/src/domains/dispatch/extension.ts +105 -22
  289. package/src/domains/dispatch/host-verification.ts +435 -39
  290. package/src/domains/dispatch/intent-requirements.ts +10 -0
  291. package/src/domains/dispatch/intent.ts +18 -1
  292. package/src/domains/dispatch/path-scope.ts +235 -24
  293. package/src/domains/dispatch/run-event-journal.ts +4 -15
  294. package/src/domains/dispatch/state.ts +2 -3
  295. package/src/domains/dispatch/transport.ts +45 -21
  296. package/src/domains/dispatch/types.ts +55 -3
  297. package/src/domains/eval/artifacts/store.ts +5 -0
  298. package/src/domains/eval/store.ts +8 -1
  299. package/src/domains/evidence/trust-status.ts +10 -1
  300. package/src/domains/extensions/contract.ts +15 -1
  301. package/src/domains/extensions/discovery.ts +238 -41
  302. package/src/domains/extensions/extension.ts +105 -6
  303. package/src/domains/extensions/index.ts +24 -0
  304. package/src/domains/extensions/integrity.ts +189 -0
  305. package/src/domains/extensions/manager.ts +17 -1
  306. package/src/domains/extensions/resource-path.ts +27 -0
  307. package/src/domains/extensions/resources.ts +18 -38
  308. package/src/domains/extensions/snapshot-store.ts +39 -0
  309. package/src/domains/extensions/snapshot.ts +180 -0
  310. package/src/domains/extensions/state.ts +385 -57
  311. package/src/domains/extensions/types.ts +118 -1
  312. package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
  313. package/src/domains/lifecycle/migrations/index.ts +2 -0
  314. package/src/domains/lifecycle/naming-resources.ts +19 -4
  315. package/src/domains/lifecycle/naming-yazi.ts +10 -5
  316. package/src/domains/middleware/contract.ts +26 -0
  317. package/src/domains/middleware/extension.ts +24 -24
  318. package/src/domains/middleware/hook-receipts.ts +27 -4
  319. package/src/domains/middleware/hooks-io.ts +65 -32
  320. package/src/domains/middleware/hooks.ts +64 -0
  321. package/src/domains/middleware/index.ts +28 -4
  322. package/src/domains/middleware/registrations.ts +326 -0
  323. package/src/domains/middleware/runtime.ts +28 -0
  324. package/src/domains/middleware/snapshot.ts +20 -7
  325. package/src/domains/mux/contract.ts +38 -0
  326. package/src/domains/mux/detect.ts +6 -13
  327. package/src/domains/mux/index.ts +1 -1
  328. package/src/domains/mux/operations.ts +44 -5
  329. package/src/domains/mux/yazi/assets/yazi.toml +2 -2
  330. package/src/domains/mux/yazi/session.ts +53 -4
  331. package/src/domains/mux/yazi/theme.ts +117 -17
  332. package/src/domains/observability/contract.ts +10 -11
  333. package/src/domains/observability/extension.ts +11 -3
  334. package/src/domains/observability/projection.ts +14 -90
  335. package/src/domains/observability/trace-store.ts +43 -7
  336. package/src/domains/prompts/compiler.ts +73 -53
  337. package/src/domains/prompts/contract.ts +15 -3
  338. package/src/domains/prompts/extension.ts +97 -9
  339. package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
  340. package/src/domains/prompts/fragments/identity/clio.md +6 -12
  341. package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
  342. package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
  343. package/src/domains/prompts/fragments/operating/contract.md +7 -15
  344. package/src/domains/prompts/fragments/operating/delegation.md +32 -34
  345. package/src/domains/prompts/fragments/operating/skills.md +10 -24
  346. package/src/domains/prompts/fragments/operating/worker.md +1 -8
  347. package/src/domains/providers/index.ts +1 -1
  348. package/src/domains/providers/model-runtime-capabilities.ts +85 -21
  349. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +669 -104
  350. package/src/domains/providers/runtime-resolution.ts +31 -0
  351. package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
  352. package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
  353. package/src/domains/providers/types/cost-provenance.ts +19 -0
  354. package/src/domains/providers/types/local-model-quirks.ts +85 -37
  355. package/src/domains/resources/skills/loader.ts +16 -19
  356. package/src/domains/safety/call-target.ts +1 -1
  357. package/src/domains/safety/loop-detector.ts +7 -4
  358. package/src/domains/session/task-board.ts +10 -9
  359. package/src/domains/share/archive.ts +164 -7
  360. package/src/engine/acp/server.ts +62 -9
  361. package/src/engine/apis/llamacpp-residency.ts +3 -4
  362. package/src/engine/apis/lmstudio.ts +3 -3
  363. package/src/engine/apis/ollama-native.ts +6 -6
  364. package/src/engine/apis/openai-completions.ts +28 -25
  365. package/src/engine/apis/output-budget.ts +8 -18
  366. package/src/engine/apis/residency.ts +8 -27
  367. package/src/engine/gemma-channel-filter.ts +19 -0
  368. package/src/engine/loop-guard.ts +92 -12
  369. package/src/engine/worker-runtime.ts +40 -11
  370. package/src/engine/worker-tools.ts +3 -1
  371. package/src/entry/extension-hook-sources.ts +28 -0
  372. package/src/entry/extension-reload.ts +309 -0
  373. package/src/entry/orchestrator.ts +59 -35
  374. package/src/interactive/application-controller.ts +2 -1
  375. package/src/interactive/bus-notices.ts +8 -1
  376. package/src/interactive/chat-loop-messages.ts +3 -13
  377. package/src/interactive/chat-loop.ts +10 -1
  378. package/src/interactive/chat-panel.ts +36 -13
  379. package/src/interactive/chat-renderer.ts +71 -7
  380. package/src/interactive/dispatch-board.ts +6 -11
  381. package/src/interactive/footer/widgets.ts +13 -0
  382. package/src/interactive/interactive-application.ts +39 -4
  383. package/src/interactive/interactive-input-runtime.ts +4 -0
  384. package/src/interactive/interactive-presentation.ts +2 -2
  385. package/src/interactive/interactive-slash-runtime.ts +2 -0
  386. package/src/interactive/overlays/extensions.ts +9 -1
  387. package/src/interactive/overlays/help-reference.ts +13 -0
  388. package/src/interactive/overlays/settings.ts +27 -16
  389. package/src/interactive/panes-runtime.ts +111 -35
  390. package/src/interactive/prompt-cache-identity.ts +88 -0
  391. package/src/interactive/slash-commands.ts +129 -14
  392. package/src/interactive/stream-pacing-policy.ts +0 -23
  393. package/src/interactive/turn-context.ts +30 -15
  394. package/src/interactive/yazi-bridge.ts +60 -6
  395. package/src/tools/agent-tools.ts +30 -1
  396. package/src/tools/artifact.ts +2 -2
  397. package/src/tools/ask-user.ts +3 -3
  398. package/src/tools/bash.ts +1 -1
  399. package/src/tools/bootstrap.ts +4 -0
  400. package/src/tools/builtin-tool-catalog.ts +52 -22
  401. package/src/tools/codewiki/code-nav-surface.ts +6 -0
  402. package/src/tools/codewiki/code-nav.ts +99 -13
  403. package/src/tools/context/docs-engine.ts +20 -7
  404. package/src/tools/context/index.ts +29 -12
  405. package/src/tools/core-bootstrap.ts +28 -6
  406. package/src/tools/credential-present.ts +1 -2
  407. package/src/tools/dispatch-arguments.ts +5 -1
  408. package/src/tools/dispatch-plan.ts +48 -4
  409. package/src/tools/dispatch-run-events.ts +1 -1
  410. package/src/tools/dispatch-schema.ts +338 -0
  411. package/src/tools/dispatch-types.ts +3 -0
  412. package/src/tools/dispatch.ts +9 -254
  413. package/src/tools/ledger.ts +3 -5
  414. package/src/tools/monitor-surface.ts +5 -13
  415. package/src/tools/observation.ts +4 -5
  416. package/src/tools/panes-surface.ts +4 -11
  417. package/src/tools/panes.ts +4 -2
  418. package/src/tools/policy.ts +15 -2
  419. package/src/tools/read.ts +5 -6
  420. package/src/tools/registry.ts +30 -7
  421. package/src/tools/result-shaping.ts +18 -14
  422. package/src/tools/steer-surface.ts +1 -1
  423. package/src/tools/tasks.ts +1 -1
  424. package/src/tools/truncate.ts +6 -5
  425. package/src/tools/verify/surface.ts +6 -12
  426. package/src/tools/web-fetch-surface.ts +1 -3
  427. package/dist/chunk-5QIAJV2D.js +0 -48
  428. package/dist/chunk-JZWT5J3Y.js +0 -814
  429. package/dist/chunk-K7VKOLQQ.js +0 -15
  430. package/dist/chunk-PMZCIOCJ.js +0 -25
  431. package/dist/chunk-SUW5DORT.js +0 -819
  432. package/dist/chunk-UOV2BYIW.js +0 -107
  433. package/dist/chunk-WR6U3OVP.js +0 -45
  434. package/docs/artifact-versions.md +0 -67
  435. package/docs/documentation-coverage.md +0 -46
  436. package/docs/documentation-guide.md +0 -167
  437. package/docs/time-conventions.md +0 -101
@@ -27,6 +27,19 @@ export interface ExtensionDiagnostic {
27
27
  path?: string;
28
28
  }
29
29
 
30
+ export interface ExtensionProvenance {
31
+ id: string;
32
+ scope: ExtensionScope;
33
+ /** Path recorded in install state, when known. */
34
+ sourcePath?: string;
35
+ /** Canonical filesystem identity of the installed package root. */
36
+ canonicalRoot: string;
37
+ /** SHA-256 of the manifest bytes covered by the installed-tree digest. */
38
+ manifestDigest: string;
39
+ /** Installed-tree digest recorded at install and reverified on this load. */
40
+ contentDigest: string;
41
+ }
42
+
30
43
  export interface InstalledExtension {
31
44
  id: string;
32
45
  name: string;
@@ -36,14 +49,28 @@ export interface InstalledExtension {
36
49
  rootPath: string;
37
50
  manifestPath: string;
38
51
  enabled: boolean;
52
+ /** Whether the complete manifest and declared resource tree are valid. */
53
+ valid: boolean;
39
54
  /** Whether this package admits the running Clio version. */
40
55
  compatible: boolean;
41
56
  effective: boolean;
57
+ /** The single admission decision for extension-owned resources and hooks. */
58
+ loadable: boolean;
59
+ /** Present exactly when the installed tree and manifest bytes were reverified. */
60
+ provenance?: ExtensionProvenance;
61
+ /** Digest observed while checking installed content on this load. */
62
+ observedContentDigest?: string;
42
63
  resources: ExtensionManifestResources;
43
64
  overriddenBy?: ExtensionScope;
44
65
  diagnostics: ExtensionDiagnostic[];
45
66
  }
46
67
 
68
+ export type LoadableExtension = InstalledExtension & { loadable: true; provenance: ExtensionProvenance };
69
+
70
+ export function isLoadableExtension(entry: InstalledExtension): entry is LoadableExtension {
71
+ return entry.loadable && entry.provenance !== undefined;
72
+ }
73
+
47
74
  export interface ExtensionCandidate {
48
75
  path: string;
49
76
  manifestPath?: string;
@@ -58,8 +85,88 @@ export interface ExtensionResourceRoot {
58
85
  path: string;
59
86
  rootPath: string;
60
87
  source: string;
88
+ provenance: ExtensionProvenance;
89
+ /** Zero denotes an ephemeral, uncommitted projection. */
90
+ generation: number;
91
+ }
92
+
93
+ export interface ExtensionHookSource {
94
+ provenance: ExtensionProvenance;
95
+ /** SHA-256 of the captured hooks.yaml bytes. */
96
+ declarationsDigest: string;
97
+ /** Parsed captured YAML, or an empty list when parsing failed. */
98
+ declarations: unknown;
99
+ parseError?: string;
61
100
  }
62
101
 
102
+ export interface ExtensionSnapshotDiagnostics {
103
+ entries: ReadonlyArray<ExtensionDiagnostic & { extensionId?: string }>;
104
+ truncated: number;
105
+ }
106
+
107
+ export interface ExtensionSnapshot {
108
+ version: 1;
109
+ generation: number;
110
+ cwd: string;
111
+ builtAt: string;
112
+ /** Content identity; generation, timestamp, and diagnostic text are excluded. */
113
+ digest: string;
114
+ packages: ReadonlyArray<InstalledExtension>;
115
+ resourceRoots: Readonly<Record<ExtensionResourceKind, ReadonlyArray<ExtensionResourceRoot>>>;
116
+ hookSources: ReadonlyArray<ExtensionHookSource>;
117
+ diagnostics: ExtensionSnapshotDiagnostics;
118
+ }
119
+
120
+ export type ExtensionReloadRejectionReason = "build-failed" | "reentrant" | "stale" | "workspace-changed";
121
+
122
+ export interface ExtensionReloadRejection {
123
+ status: "rejected";
124
+ reason: ExtensionReloadRejectionReason;
125
+ /** Generation that remains committed. */
126
+ generation: number;
127
+ diagnostics: ExtensionSnapshotDiagnostics;
128
+ }
129
+
130
+ /**
131
+ * A fully built and validated generation that has not been published. The
132
+ * bundle holds at most one candidate at a time. `publish` is one reference
133
+ * assignment that never validates, refuses, throws, or calls out; the caller
134
+ * checks `current()` on the same stack immediately before it. `discard`
135
+ * releases the candidate without any visible change.
136
+ */
137
+ export interface ExtensionReloadCandidate {
138
+ generation: number;
139
+ previousGeneration: number;
140
+ snapshot: ExtensionSnapshot;
141
+ /** False when the candidate digest equals the committed digest. */
142
+ changed: boolean;
143
+ added: ReadonlyArray<string>;
144
+ removed: ReadonlyArray<string>;
145
+ modified: ReadonlyArray<string>;
146
+ /** True while this is the in-flight candidate and the committed snapshot it was diffed against is still live. */
147
+ current(): boolean;
148
+ publish(): void;
149
+ discard(): void;
150
+ }
151
+
152
+ export type ExtensionReloadPrepareResult =
153
+ | { status: "prepared"; candidate: ExtensionReloadCandidate }
154
+ | ExtensionReloadRejection;
155
+
156
+ export interface ExtensionReloadCommitted {
157
+ status: "committed";
158
+ generation: number;
159
+ previousGeneration: number;
160
+ changed: boolean;
161
+ digest: string;
162
+ added: ReadonlyArray<string>;
163
+ removed: ReadonlyArray<string>;
164
+ modified: ReadonlyArray<string>;
165
+ diagnostics: ExtensionSnapshotDiagnostics;
166
+ }
167
+
168
+ export type ExtensionReloadResult = ExtensionReloadCommitted | ExtensionReloadRejection;
169
+
63
170
  export interface ExtensionListOptions {
64
171
  scope?: ExtensionScope;
65
172
  cwd?: string;
@@ -72,17 +179,27 @@ export interface ExtensionInstallOptions extends ExtensionListOptions {
72
179
 
73
180
  export interface ExtensionInstallResult {
74
181
  extension?: InstalledExtension;
182
+ recovery?: { stateBackup?: string; packageBackup?: string };
75
183
  diagnostics: ExtensionDiagnostic[];
76
184
  }
77
185
 
78
186
  export interface ExtensionMutationResult {
79
187
  extension?: InstalledExtension;
80
188
  removed?: { id: string; scope: ExtensionScope; path: string };
189
+ recovery?: { stateBackup?: string; packageBackup?: string };
81
190
  diagnostics: ExtensionDiagnostic[];
82
191
  }
83
192
 
193
+ export interface ExtensionStateUpgradeReport {
194
+ scope: ExtensionScope;
195
+ statePath: string;
196
+ backupPath?: string;
197
+ upgraded: string[];
198
+ refused: Array<{ id: string; reason: string }>;
199
+ }
200
+
84
201
  export interface ExtensionState {
85
202
  version: 1;
86
203
  disabled: string[];
87
- installed: Record<string, { installedAt: string; source?: string }>;
204
+ installed: Record<string, { installedAt: string; source?: string; contentDigest?: string }>;
88
205
  }
@@ -0,0 +1,27 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { safeResourceWrite } from "../../../core/safe-resource-write.js";
4
+ import { upgradeLegacyExtensionInstallState } from "../../extensions/state.js";
5
+ import type { Migration } from "./index.js";
6
+
7
+ export const EXTENSION_INSTALL_DIGESTS_MIGRATION_ID = "2026-09-01-extension-install-digests";
8
+
9
+ function migrateExtensionInstallDigests(stateDir: string, cwd = process.cwd()): void {
10
+ const scopes = upgradeLegacyExtensionInstallState(cwd);
11
+ const reportDir = join(stateDir, "migration-reports");
12
+ mkdirSync(reportDir, { recursive: true });
13
+ safeResourceWrite(
14
+ join(reportDir, `${EXTENSION_INSTALL_DIGESTS_MIGRATION_ID}.json`),
15
+ `${JSON.stringify({ migration: EXTENSION_INSTALL_DIGESTS_MIGRATION_ID, scopes }, null, 2)}\n`,
16
+ { encoding: "utf8", mode: 0o644 },
17
+ );
18
+ }
19
+
20
+ const migration: Migration = {
21
+ id: EXTENSION_INSTALL_DIGESTS_MIGRATION_ID,
22
+ async up(stateDir: string): Promise<void> {
23
+ migrateExtensionInstallDigests(stateDir);
24
+ },
25
+ };
26
+
27
+ export default migration;
@@ -34,6 +34,7 @@ import { join } from "node:path";
34
34
 
35
35
  import lmStudioRuntimeId from "./2026-08-18-lmstudio-runtime-id.js";
36
36
  import clioCoderNaming from "./2026-09-01-clio-coder-naming.js";
37
+ import extensionInstallDigests from "./2026-09-01-extension-install-digests.js";
37
38
  import retirePanesKnobs from "./2026-09-01-retire-panes-knobs.js";
38
39
  import settingsV2 from "./2026-09-01-settings-v2.js";
39
40
 
@@ -61,6 +62,7 @@ export interface MigrationRunResult {
61
62
  // migration independently and for manifest continuity; it is a no-op on v2.
62
63
  const REGISTRY: ReadonlyArray<Migration> = Object.freeze([
63
64
  settingsV2,
65
+ extensionInstallDigests,
64
66
  clioCoderNaming,
65
67
  retirePanesKnobs,
66
68
  lmStudioRuntimeId,
@@ -9,12 +9,14 @@ import {
9
9
  statSync,
10
10
  writeFileSync,
11
11
  } from "node:fs";
12
+ import { homedir } from "node:os";
12
13
  import path from "node:path";
13
14
 
14
15
  import { parse as parseYaml } from "yaml";
15
16
  import { resolvePackageRoot } from "../../core/package-root.js";
16
17
  import { fsyncDirectory } from "../../core/safe-resource-write.js";
17
18
  import { resolveClioDirs } from "../../core/xdg.js";
19
+ import { INTEROP_AGENT_KINDS } from "../interop/registry.js";
18
20
  import { normalizedSkillHash, stripProvenanceFrontmatter } from "../resources/skills/content-hash.js";
19
21
 
20
22
  const LEGACY_SKILL_NAMES = [
@@ -35,6 +37,8 @@ export interface NamingResourceReport {
35
37
  export interface NamingResourceOptions {
36
38
  cwd?: string;
37
39
  configDir?: string;
40
+ /** Home directory whose interop skill roots are inspected; defaults to the OS home. */
41
+ home?: string;
38
42
  packageRoot?: string;
39
43
  fix?: boolean;
40
44
  }
@@ -206,14 +210,25 @@ function collectSkillFiles(root: string, current = root): string[] {
206
210
  return out;
207
211
  }
208
212
 
209
- /** Read-only inventory of released skill metadata keys in selected Clio Coder roots. */
213
+ /**
214
+ * Read-only inventory of released skill metadata keys in every root the skill
215
+ * loader reads: the Clio user and project roots plus each interop agent's
216
+ * user and project compatibility roots (`.claude/skills`, `.agents/skills`,
217
+ * ...). The loader warns for a legacy key in any of them, so the doctor has to
218
+ * look where the loader looks or it reports "canonical" while boot warns.
219
+ */
210
220
  export function inspectSkillMetadataNaming(
211
- options: Pick<NamingResourceOptions, "cwd" | "configDir"> = {},
221
+ options: Pick<NamingResourceOptions, "cwd" | "configDir" | "home"> = {},
212
222
  ): SkillMetadataNamingInspection[] {
213
223
  const cwd = options.cwd ?? process.cwd();
214
224
  const configDir = options.configDir ?? resolveClioDirs().config;
215
- const roots = [path.join(configDir, "skills"), path.join(cwd, ".clio-coder", "skills")];
216
- return roots.flatMap((root) =>
225
+ const home = options.home ?? homedir();
226
+ const roots = new Set<string>([path.join(configDir, "skills"), path.join(cwd, ".clio-coder", "skills")]);
227
+ for (const kind of INTEROP_AGENT_KINDS) {
228
+ if (kind.userSkillRoot !== undefined) roots.add(path.join(home, kind.userSkillRoot));
229
+ if (kind.projectSkillRoot !== undefined) roots.add(path.join(cwd, kind.projectSkillRoot));
230
+ }
231
+ return [...roots].flatMap((root) =>
217
232
  collectSkillFiles(root).map((file) => ({
218
233
  path: file,
219
234
  legacyMetadataKey: /^clio:\s*(?:#.*)?$/mu.test(readFileSync(file, "utf8")),
@@ -54,10 +54,14 @@ export function regenerateYaziNamingProfile(options: YaziNamingOptions = {}): Ya
54
54
  const cacheDir = options.cacheDir ?? resolveClioDirs().cache;
55
55
  const before = inspectYaziNaming(cacheDir);
56
56
  if (!before.present) {
57
- return { ...before, status: "absent", detail: "managed Yazi profile is absent; next open writes canonical names" };
57
+ return {
58
+ ...before,
59
+ status: "absent",
60
+ detail: "managed files pane profile is absent; next open writes canonical names",
61
+ };
58
62
  }
59
63
  if (before.legacyEvents === 0 && before.legacyEnvironmentNames === 0) {
60
- return { ...before, status: "canonical", detail: "managed Yazi profile already uses canonical names" };
64
+ return { ...before, status: "canonical", detail: "managed files pane profile already uses canonical names" };
61
65
  }
62
66
  const yaziPath = options.yaziPath === undefined ? resolveToolBinary("yazi").binaryPath : options.yaziPath;
63
67
  const yaPath = options.yaPath === undefined ? resolveToolBinary("ya").binaryPath : options.yaPath;
@@ -66,7 +70,8 @@ export function regenerateYaziNamingProfile(options: YaziNamingOptions = {}): Ya
66
70
  return {
67
71
  ...before,
68
72
  status: "removed-unresolved",
69
- detail: "legacy managed profile removed; Yazi/ya is unresolved, so the next managed open will regenerate it",
73
+ detail:
74
+ "legacy managed profile removed; the files pane engine is unresolved, so the next managed open will regenerate it",
70
75
  };
71
76
  }
72
77
  const profile = ensureYaziProfile({ yaziPath, yaPath, profileDir: before.profileDir });
@@ -74,8 +79,8 @@ export function regenerateYaziNamingProfile(options: YaziNamingOptions = {}): Ya
74
79
  return {
75
80
  ...before,
76
81
  status: "regeneration-failed",
77
- detail: "legacy managed profile removed, but current Yazi rejected the regenerated profile",
82
+ detail: "legacy managed profile removed, but the files pane engine rejected the regenerated profile",
78
83
  };
79
84
  }
80
- return { ...before, status: "regenerated", detail: "managed Yazi profile regenerated with canonical names" };
85
+ return { ...before, status: "regenerated", detail: "managed files pane profile regenerated with canonical names" };
81
86
  }
@@ -1,3 +1,8 @@
1
+ import type {
2
+ MiddlewareRegistrationOwner,
3
+ PrepareRegistrationReplacementResult,
4
+ ReplaceRegistrationsReport,
5
+ } from "./registrations.js";
1
6
  import type { MiddlewareDiagnosticSink, MiddlewareHookRegistration } from "./runtime.js";
2
7
  import type {
3
8
  MiddlewareEffect,
@@ -32,4 +37,25 @@ export interface MiddlewareContract {
32
37
  * stderr writer default.
33
38
  */
34
39
  setDiagnosticSink(sink: MiddlewareDiagnosticSink): void;
40
+ /**
41
+ * Validate an owner's replacement registration set against the current
42
+ * builtin and host ids and build its evaluation list without publishing.
43
+ * Rejected when `generation` is not strictly greater than the owner's
44
+ * active generation. The returned replacement publishes with one reference
45
+ * assignment that cannot refuse or call out, so a composition root can publish it
46
+ * back-to-back with another domain's generation on the same stack.
47
+ */
48
+ prepareRegistrationReplacement(
49
+ owner: MiddlewareRegistrationOwner,
50
+ generation: number,
51
+ registrations: ReadonlyArray<MiddlewareHookRegistration>,
52
+ ): PrepareRegistrationReplacementResult;
53
+ /** Prepare, check currentness, publish, then emit any conflict diagnostics. */
54
+ replaceRegistrations(
55
+ owner: MiddlewareRegistrationOwner,
56
+ generation: number,
57
+ registrations: ReadonlyArray<MiddlewareHookRegistration>,
58
+ ): ReplaceRegistrationsReport;
59
+ /** Active generation for an owner; 0 when nothing was ever applied. */
60
+ ownedGeneration(owner: MiddlewareRegistrationOwner): number;
35
61
  }
@@ -6,6 +6,7 @@ import {
6
6
  resolveHookBudgetTunablesFromEnv,
7
7
  } from "./budget.js";
8
8
  import type { MiddlewareContract } from "./contract.js";
9
+ import { createMiddlewareRegistrationTable } from "./registrations.js";
9
10
  import { cloneMiddlewareRule, listMiddlewareRuleDefinitions } from "./rules.js";
10
11
  import {
11
12
  type MiddlewareDiagnosticSink,
@@ -14,6 +15,7 @@ import {
14
15
  registrationFromRuleDefinition,
15
16
  runMiddlewareAsyncRegistrations,
16
17
  runMiddlewareRegistrations,
18
+ writeMiddlewareDiagnosticToStderr,
17
19
  } from "./runtime.js";
18
20
  import { createMiddlewareSnapshot } from "./snapshot.js";
19
21
 
@@ -54,18 +56,28 @@ export interface MiddlewareBundleOptions {
54
56
 
55
57
  export function createMiddlewareBundle(options: MiddlewareBundleOptions = {}): DomainBundle<MiddlewareContract> {
56
58
  const ruleDefinitions = combineRuleDefinitions(listMiddlewareRuleDefinitions(), options.ruleDefinitions ?? []);
57
- const registrations = combineRegistrations(ruleDefinitions, options.registrations ?? []);
58
- const registeredIds = new Set(registrations.map((registration) => registration.id));
59
59
  let diagnosticSink = options.onDiagnostic;
60
+ // Declarative rules are the fixed tier; construction-time coded
61
+ // registrations are the first host entries, deduplicated first-wins across
62
+ // the shared id namespace exactly as before.
63
+ const table = createMiddlewareRegistrationTable({
64
+ fixed: ruleDefinitions.map(registrationFromRuleDefinition),
65
+ diagnosticSink: () => diagnosticSink ?? writeMiddlewareDiagnosticToStderr,
66
+ });
67
+ for (const registration of options.registrations ?? []) table.registerHook(registration);
60
68
  const budgetTracker = options.budgetTracker ?? createEnvHookBudgetTracker();
61
69
  const contract: MiddlewareContract = {
62
70
  runHook(input) {
71
+ // Capture the list once; a replacement published mid-evaluation
72
+ // takes effect for the next evaluation, never this one.
73
+ const registrations = table.list();
63
74
  return runMiddlewareRegistrations(input, registrations, {
64
75
  budgetTracker,
65
76
  ...(diagnosticSink !== undefined ? { onDiagnostic: diagnosticSink } : {}),
66
77
  });
67
78
  },
68
79
  runAsyncHook(input, priorEffects = []) {
80
+ const registrations = table.list();
69
81
  return runMiddlewareAsyncRegistrations(input, registrations, priorEffects, {
70
82
  ...(diagnosticSink !== undefined ? { onDiagnostic: diagnosticSink } : {}),
71
83
  });
@@ -77,13 +89,20 @@ export function createMiddlewareBundle(options: MiddlewareBundleOptions = {}): D
77
89
  return createMiddlewareSnapshot(ruleDefinitions.map((definition) => definition.rule));
78
90
  },
79
91
  registerHook(registration) {
80
- if (registeredIds.has(registration.id)) return;
81
- registeredIds.add(registration.id);
82
- registrations.push(registration);
92
+ table.registerHook(registration);
83
93
  },
84
94
  setDiagnosticSink(sink) {
85
95
  diagnosticSink = sink;
86
96
  },
97
+ prepareRegistrationReplacement(owner, generation, registrations) {
98
+ return table.prepareReplacement(owner, generation, registrations);
99
+ },
100
+ replaceRegistrations(owner, generation, registrations) {
101
+ return table.replaceRegistrations(owner, generation, registrations);
102
+ },
103
+ ownedGeneration(owner) {
104
+ return table.ownedGeneration(owner);
105
+ },
87
106
  };
88
107
  return {
89
108
  extension: {
@@ -108,22 +127,3 @@ function combineRuleDefinitions(
108
127
  }
109
128
  return combined;
110
129
  }
111
-
112
- /**
113
- * One ordered evaluation list: declarative rules first (builtin, then
114
- * composition-root), then coded registrations, deduplicated across the shared
115
- * id namespace with the earlier entry winning.
116
- */
117
- function combineRegistrations(
118
- ruleDefinitions: ReadonlyArray<MiddlewareRuleDefinition>,
119
- coded: ReadonlyArray<MiddlewareHookRegistration>,
120
- ): MiddlewareHookRegistration[] {
121
- const seen = new Set<string>(ruleDefinitions.map((definition) => definition.rule.id));
122
- const combined: MiddlewareHookRegistration[] = ruleDefinitions.map(registrationFromRuleDefinition);
123
- for (const registration of coded) {
124
- if (seen.has(registration.id)) continue;
125
- seen.add(registration.id);
126
- combined.push(registration);
127
- }
128
- return combined;
129
- }
@@ -1,11 +1,14 @@
1
1
  /**
2
2
  * Durable receipt log for user-defined middleware hooks. Every hook execution
3
- * emits a {@link HookReceipt}; this log keeps a bounded in-memory ring (the live
4
- * surface `clio-coder config inspect` reads) and persists it atomically through
5
- * safeResourceWrite. Writes are throttled so a per-tool-call cadence never turns
6
- * into per-call disk I/O; `flush()` forces a final write at shutdown.
3
+ * emits a {@link HookReceipt}; this log keeps a bounded in-memory ring and
4
+ * persists it atomically through safeResourceWrite. Writes are throttled so a
5
+ * per-tool-call cadence never turns into per-call disk I/O; `flush()` forces a
6
+ * final write at shutdown. `clio-coder config inspect` reads the persisted
7
+ * snapshot back with {@link readPersistedHookReceipts}, since it runs as its
8
+ * own process and has no access to a running session's in-memory ring.
7
9
  */
8
10
 
11
+ import { readFileSync } from "node:fs";
9
12
  import { safeResourceWrite } from "../../core/safe-resource-write.js";
10
13
  import type { HookReceipt } from "./hooks.js";
11
14
 
@@ -68,3 +71,23 @@ export function createHookReceiptLog(options: HookReceiptLogOptions = {}): HookR
68
71
  },
69
72
  };
70
73
  }
74
+
75
+ /**
76
+ * Read a log's persisted snapshot back, for a process that never held the
77
+ * live log (`config inspect` runs as its own invocation). A log that has
78
+ * never persisted yet reads as empty, not an error.
79
+ */
80
+ export function readPersistedHookReceipts(persistPath: string): HookReceipt[] {
81
+ let raw: string;
82
+ try {
83
+ raw = readFileSync(persistPath, "utf8");
84
+ } catch (error) {
85
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return [];
86
+ throw error;
87
+ }
88
+ const parsed = JSON.parse(raw) as Partial<PersistedReceipts>;
89
+ if (parsed.version !== 1 || !Array.isArray(parsed.receipts)) {
90
+ throw new Error(`${persistPath}: unrecognized hook receipt log shape`);
91
+ }
92
+ return parsed.receipts;
93
+ }
@@ -1,12 +1,19 @@
1
1
  /**
2
- * Filesystem loading for user-defined middleware hooks and the production
3
- * command runner. Hooks live in dedicated, secrets-free files so they stay out
4
- * of the strict settings schema:
2
+ * Loading for user-defined middleware hooks and the production command
3
+ * runner. Hooks live in dedicated, secrets-free files so they stay out of the
4
+ * strict settings schema:
5
5
  *
6
6
  * - `.clio-coder/hooks.yaml` committed project hooks (origin "project"),
7
7
  * - `.clio-coder/hooks.local.yaml` gitignored local hooks (origin "project.local"),
8
8
  * - `<extensionRoot>/hooks.yaml` hooks shipped by an installed extension.
9
9
  *
10
+ * Project files are read from disk here. Extension declarations are never
11
+ * read here: they arrive already parsed as a captured source set that the
12
+ * composition root adapts from the extension snapshot, which captured the
13
+ * bytes during install-digest verification, so a hooks.yaml rewritten after
14
+ * verification cannot be admitted until the next generation re-verifies the
15
+ * tree. Middleware never sees extension-domain types.
16
+ *
10
17
  * Reads are best-effort: a missing file is skipped silently, and a malformed
11
18
  * file is reported as an issue without aborting anything.
12
19
  */
@@ -26,6 +33,7 @@ import {
26
33
  type UserHookCommandRunner,
27
34
  type UserHookDeclarationBatch,
28
35
  type UserHookLoadResult,
36
+ type UserHookPackageProvenance,
29
37
  type UserHookSource,
30
38
  userHookToRegistration,
31
39
  } from "./hooks.js";
@@ -43,15 +51,27 @@ export interface ReadHookSourcesResult {
43
51
  fileIssues: HookFileIssue[];
44
52
  }
45
53
 
46
- export interface ExtensionHookRoot {
47
- id: string;
48
- rootPath: string;
54
+ /** One package's hook declarations, captured by the supplier from verified bytes. */
55
+ export interface CapturedHookDeclarations {
56
+ provenance: UserHookPackageProvenance;
57
+ /** SHA-256 of the captured hooks.yaml bytes. */
58
+ declarationsDigest: string;
59
+ /** Parsed declarations, or an empty list when parsing failed. */
60
+ declarations: unknown;
61
+ parseError?: string;
62
+ }
63
+
64
+ /** The captured declarations of one supplier generation. */
65
+ export interface CapturedHookSourceSet {
66
+ /** 0 for an ephemeral (uncommitted) build. */
67
+ generation: number;
68
+ sources: ReadonlyArray<CapturedHookDeclarations>;
49
69
  }
50
70
 
51
71
  export interface ReadHookSourcesOptions {
52
72
  cwd: string;
53
- /** Installed extension roots, in dependency order. */
54
- extensions?: ReadonlyArray<ExtensionHookRoot>;
73
+ /** Captured extension declarations; absent means no extension hooks. */
74
+ capturedSources?: CapturedHookSourceSet;
55
75
  }
56
76
 
57
77
  function readBatch(
@@ -86,14 +106,23 @@ export function readHookSources(options: ReadHookSourcesOptions): ReadHookSource
86
106
  const fileIssues: HookFileIssue[] = [];
87
107
  const batches: UserHookDeclarationBatch[] = [];
88
108
 
89
- for (const extension of options.extensions ?? []) {
109
+ const captured = options.capturedSources;
110
+ for (const entry of captured?.sources ?? []) {
90
111
  const source: UserHookSource = {
91
112
  origin: "extension",
92
- sourcePath: `${extension.id}:hooks.yaml`,
93
- sourceId: extension.id,
113
+ sourcePath: `${entry.provenance.id}:hooks.yaml`,
114
+ sourceId: entry.provenance.id,
115
+ extension: {
116
+ provenance: entry.provenance,
117
+ generation: captured?.generation ?? 0,
118
+ declarationsDigest: entry.declarationsDigest,
119
+ },
94
120
  };
95
- const batch = readBatch(source, join(extension.rootPath, "hooks.yaml"), fileIssues);
96
- if (batch) batches.push(batch);
121
+ if (entry.parseError !== undefined) {
122
+ fileIssues.push({ source, message: `failed to parse ${source.sourcePath}: ${entry.parseError}` });
123
+ continue;
124
+ }
125
+ batches.push({ source, declarations: entry.declarations });
97
126
  }
98
127
 
99
128
  const projectBatch = readBatch(
@@ -113,44 +142,48 @@ export function readHookSources(options: ReadHookSourcesOptions): ReadHookSource
113
142
  return { batches, fileIssues };
114
143
  }
115
144
 
116
- export interface InstallUserHooksOptions {
145
+ export interface BuildUserHookRegistrationsOptions {
117
146
  cwd: string;
118
147
  /** Absolute workspace root a command `cwd` must resolve under; defaults to `cwd`. */
119
148
  workspaceRoot?: string;
120
- extensions?: ReadonlyArray<ExtensionHookRoot>;
121
- registerHook: (registration: MiddlewareHookRegistration) => void;
149
+ capturedSources?: CapturedHookSourceSet;
122
150
  recordReceipt: HookReceiptSink;
123
151
  /** Injected for tests; defaults to the spawnSync runner. */
124
152
  runCommand?: UserHookCommandRunner;
125
153
  now?: () => number;
126
154
  }
127
155
 
128
- export interface InstallUserHooksResult extends UserHookLoadResult {
156
+ export interface BuildUserHookRegistrationsResult extends UserHookLoadResult {
129
157
  fileIssues: HookFileIssue[];
158
+ /** One registration per admitted hook, in merged precedence order. Nothing is registered here. */
159
+ registrations: MiddlewareHookRegistration[];
130
160
  }
131
161
 
132
162
  /**
133
- * Read, normalize, and register every user hook on the middleware contract. The
134
- * returned hooks and issues feed `clio-coder config inspect`. Best-effort throughout:
135
- * a malformed file or hook is reported, never thrown.
163
+ * Read project files, merge them with the captured extension declarations,
164
+ * normalize, and build one registration per admitted hook. Pure with respect
165
+ * to the middleware contract: the caller decides when the set is published,
166
+ * which is what lets extension and hook state publish on one stack. The
167
+ * returned hooks and issues feed `clio-coder config inspect`. Best-effort
168
+ * throughout: a malformed file or hook is reported, never thrown.
136
169
  */
137
- export function installUserHooks(options: InstallUserHooksOptions): InstallUserHooksResult {
170
+ export function buildUserHookRegistrations(
171
+ options: BuildUserHookRegistrationsOptions,
172
+ ): BuildUserHookRegistrationsResult {
138
173
  const workspaceRoot = options.workspaceRoot ?? options.cwd;
139
174
  const readOptions: ReadHookSourcesOptions = { cwd: options.cwd };
140
- if (options.extensions !== undefined) readOptions.extensions = options.extensions;
175
+ if (options.capturedSources !== undefined) readOptions.capturedSources = options.capturedSources;
141
176
  const { batches, fileIssues } = readHookSources(readOptions);
142
177
  const loaded = loadUserHooks(batches, { workspaceRoot });
143
178
  const runCommand = options.runCommand ?? spawnSyncCommandRunner();
144
- for (const hook of loaded.hooks) {
145
- options.registerHook(
146
- userHookToRegistration(hook, {
147
- recordReceipt: options.recordReceipt,
148
- runCommand,
149
- ...(options.now !== undefined ? { now: options.now } : {}),
150
- }),
151
- );
152
- }
153
- return { ...loaded, fileIssues };
179
+ const registrations = loaded.hooks.map((hook) =>
180
+ userHookToRegistration(hook, {
181
+ recordReceipt: options.recordReceipt,
182
+ runCommand,
183
+ ...(options.now !== undefined ? { now: options.now } : {}),
184
+ }),
185
+ );
186
+ return { ...loaded, fileIssues, registrations };
154
187
  }
155
188
 
156
189
  /**