@iowarp/clio-coder 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (604) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/CONTRIBUTING.md +142 -52
  3. package/README.md +434 -473
  4. package/SECURITY.md +2 -1
  5. package/dist/{acp-ZILU3AUO.js → acp-H2NGRPWO.js} +12 -12
  6. package/dist/{agents-HYWGBGQR.js → agents-TL5LLUQP.js} +56 -55
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/{auth-N3QT7CBO.js → auth-E5SW4HMS.js} +23 -21
  9. package/dist/builtins-IA7V7FUC.js +22 -0
  10. package/dist/{chunk-7RY5VZPH.js → chunk-2APPQIER.js} +8 -8
  11. package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
  12. package/dist/{chunk-JA5QWE4Z.js → chunk-2UG5F4C5.js} +1973 -1664
  13. package/dist/{chunk-5YHDIDBP.js → chunk-2UH2KFUP.js} +2 -2
  14. package/dist/{chunk-CTJ4RNAA.js → chunk-2VIKGWFZ.js} +2 -2
  15. package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
  16. package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
  17. package/dist/chunk-3EBYEESD.js +314 -0
  18. package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
  19. package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
  20. package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
  21. package/dist/chunk-4UVU7BJ5.js +39 -0
  22. package/dist/{chunk-VKRH2TCS.js → chunk-4WR7VSYB.js} +2 -2
  23. package/dist/{chunk-BBTJOK6Y.js → chunk-54CBCGIR.js} +5 -5
  24. package/dist/{chunk-AP73CFDC.js → chunk-5ICU3EUH.js} +2 -2
  25. package/dist/chunk-5MEZN6CB.js +1334 -0
  26. package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
  27. package/dist/{chunk-ABLSQ6JX.js → chunk-64I3JVYM.js} +8 -2
  28. package/dist/{chunk-AFKWHWXF.js → chunk-6PTFB5VS.js} +39 -22
  29. package/dist/{chunk-VN3SHNBN.js → chunk-7DICMOS6.js} +2 -2
  30. package/dist/chunk-7DRAWPTZ.js +360 -0
  31. package/dist/chunk-7E7I3WLS.js +3762 -0
  32. package/dist/{chunk-BJGUKIG4.js → chunk-7ZYNNDKC.js} +7 -7
  33. package/dist/{chunk-XKA2ICR3.js → chunk-AF4YM7Z4.js} +652 -252
  34. package/dist/{chunk-GVQJ5CCZ.js → chunk-AX2THNSA.js} +12 -12
  35. package/dist/{chunk-IG7BCQBA.js → chunk-B4OAX3SI.js} +65 -3
  36. package/dist/{chunk-TD3PGPQA.js → chunk-B4VEBZKF.js} +3 -3
  37. package/dist/{chunk-74YWRRU5.js → chunk-BEPZRGGU.js} +10 -10
  38. package/dist/{chunk-FEFIFZTL.js → chunk-CE5AX47J.js} +2 -2
  39. package/dist/{chunk-UAPGZHYC.js → chunk-DWUOQKRU.js} +25 -11
  40. package/dist/{chunk-THYWACCR.js → chunk-E3TPLWFX.js} +3 -3
  41. package/dist/{chunk-7EPLI7VL.js → chunk-EKCHAPYA.js} +2 -2
  42. package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
  43. package/dist/{chunk-PJJ6MY27.js → chunk-F5JHEYZM.js} +7 -7
  44. package/dist/{chunk-6CCS4G3W.js → chunk-FTMGRKEF.js} +3 -3
  45. package/dist/{chunk-SINK3QR6.js → chunk-G76U63X4.js} +17 -17
  46. package/dist/{chunk-EIMVLWB3.js → chunk-GHS5EBTQ.js} +64 -9
  47. package/dist/{chunk-QMXC4JB7.js → chunk-GI7YYQ3F.js} +187 -1419
  48. package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
  49. package/dist/{chunk-6HMJX2VU.js → chunk-GWZNEVM2.js} +44 -12
  50. package/dist/chunk-GYV6VZOC.js +26 -0
  51. package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
  52. package/dist/{chunk-UXN6JT4W.js → chunk-HEQY7ZFI.js} +3 -3
  53. package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
  54. package/dist/{chunk-GCSMB2KY.js → chunk-I7ZPNEJM.js} +145 -102
  55. package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
  56. package/dist/{chunk-QTFGO774.js → chunk-IGLP3ODT.js} +29 -16
  57. package/dist/chunk-IJNZMHLA.js +101 -0
  58. package/dist/{chunk-BDPT6GTK.js → chunk-INY6HTFL.js} +7 -7
  59. package/dist/{chunk-PBP4B7XR.js → chunk-IUE3Y34X.js} +2 -2
  60. package/dist/{chunk-6NJQITNH.js → chunk-IWT4SF4R.js} +6 -3
  61. package/dist/{chunk-R23Z6K6I.js → chunk-JDAY6FIL.js} +19 -19
  62. package/dist/chunk-JEQ3XTHC.js +42 -0
  63. package/dist/{chunk-FSP7CMNU.js → chunk-JGRC33J2.js} +50 -4
  64. package/dist/{chunk-TVH4ONAM.js → chunk-JKKCYP3C.js} +10 -10
  65. package/dist/{chunk-HJWWJ6IL.js → chunk-JSC3U7TI.js} +16 -4
  66. package/dist/{chunk-C537JADH.js → chunk-KK4JZPBQ.js} +19 -141
  67. package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
  68. package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
  69. package/dist/{chunk-6DWBAZ5U.js → chunk-L47TF46W.js} +5 -7
  70. package/dist/{chunk-HUAS7ITX.js → chunk-LDJG7DW3.js} +91 -42
  71. package/dist/{chunk-CDNVLKUX.js → chunk-LLDJM5XK.js} +13 -7
  72. package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
  73. package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
  74. package/dist/{chunk-VKFQTNDV.js → chunk-MUW2BDDH.js} +4 -4
  75. package/dist/{chunk-E67WX76H.js → chunk-MWUZBSAQ.js} +104 -152
  76. package/dist/{chunk-OJTRZGR3.js → chunk-N2Z7HLVY.js} +21 -21
  77. package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
  78. package/dist/{chunk-FYUN5KZ3.js → chunk-NIQJ66N4.js} +21 -21
  79. package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
  80. package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
  81. package/dist/{chunk-VEGN6WIQ.js → chunk-O5CVSAG5.js} +3 -3
  82. package/dist/{chunk-MOPSG2X7.js → chunk-OML5D5V5.js} +8 -8
  83. package/dist/{chunk-2VG7KLYV.js → chunk-PAJQJ7BS.js} +5816 -3255
  84. package/dist/{chunk-ZW55JB7N.js → chunk-PUVDKJ2Y.js} +2 -2
  85. package/dist/{chunk-BTGG6BG2.js → chunk-QWGDJJYJ.js} +158 -19
  86. package/dist/chunk-R6Q67RJH.js +134 -0
  87. package/dist/{chunk-ZJLUDYFY.js → chunk-RRNP2ANY.js} +6 -6
  88. package/dist/{chunk-PVAMAVBB.js → chunk-RSJ25QSL.js} +102 -2
  89. package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
  90. package/dist/chunk-SKHCAU7K.js +385 -0
  91. package/dist/chunk-SZAA6XDG.js +30 -0
  92. package/dist/{chunk-J4HBWF6Y.js → chunk-TM6LQDI3.js} +131 -28
  93. package/dist/chunk-UOIZ7DA4.js +41 -0
  94. package/dist/{chunk-MA3H6DM5.js → chunk-UPZU6GE4.js} +25 -3
  95. package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
  96. package/dist/{chunk-N5UK64DP.js → chunk-V2ANDPVT.js} +4 -4
  97. package/dist/{chunk-AK5XEFVZ.js → chunk-VA5FNYMT.js} +26 -13
  98. package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
  99. package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
  100. package/dist/{chunk-QKIFBZKT.js → chunk-VW6DOEDG.js} +497 -81
  101. package/dist/{chunk-SCYB3HA4.js → chunk-W6RRQCPQ.js} +63 -19
  102. package/dist/{chunk-2NM363SV.js → chunk-WBKFA554.js} +10 -10
  103. package/dist/{chunk-R32CLGZ6.js → chunk-WCXUNS7U.js} +82 -21
  104. package/dist/{chunk-GPPB3JBE.js → chunk-WRBAGUNF.js} +3 -3
  105. package/dist/{chunk-IXJT6DCX.js → chunk-XIVNBFZS.js} +85 -30
  106. package/dist/{chunk-UEDMSP56.js → chunk-XPWWI35G.js} +417 -201
  107. package/dist/chunk-XRZT5WY5.js +47 -0
  108. package/dist/{chunk-3QSOM6PA.js → chunk-Y3CBHOR6.js} +2 -2
  109. package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
  110. package/dist/{chunk-AKB4GYDL.js → chunk-YQWYVTMC.js} +5 -5
  111. package/dist/{chunk-6I5ILFOF.js → chunk-ZA4VCIGV.js} +3 -3
  112. package/dist/{chunk-7OBGU7UB.js → chunk-ZDN3Y73Y.js} +12 -18
  113. package/dist/{chunk-3I5NY75V.js → chunk-ZWPRK62N.js} +8 -5
  114. package/dist/cli/index.js +41 -39
  115. package/dist/{clio-IT3G3VQH.js → clio-CMMK4KRR.js} +9 -9
  116. package/dist/{code-nav-RK6S7F6E.js → code-nav-MDZNQS33.js} +89 -21
  117. package/dist/{components-UBWCQSRW.js → components-UCUQ4QXW.js} +4 -4
  118. package/dist/{config-3QZRWZJF.js → config-SVM5P5YI.js} +131 -84
  119. package/dist/{configure-FL7Y3KJF.js → configure-LE3IK2TJ.js} +28 -26
  120. package/dist/{context-5HE7ODYK.js → context-2OHRKS42.js} +69 -64
  121. package/dist/{context-KYQFRVDC.js → context-E3VC7RX5.js} +15 -11
  122. package/dist/{context-XNHL75JV.js → context-VNCR7KAG.js} +93 -65
  123. package/dist/{context-clear-N545L53A.js → context-clear-BW4O37TG.js} +64 -60
  124. package/dist/context-map-COB37XXN.js +505 -0
  125. package/dist/{context-working-set-QHKXSV2F.js → context-working-set-VDS25HXZ.js} +19 -18
  126. package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-5AHT53RF.js} +93 -82
  127. package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
  128. package/dist/{doctor-ZGPEGHIP.js → doctor-WNNVO6FY.js} +48 -47
  129. package/dist/{eval-GXLL44RD.js → eval-7G7SGAYO.js} +287 -115
  130. package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-Y6QRFOH5.js} +4 -4
  131. package/dist/{evidence-HWLBRH3Q.js → evidence-VD6736FQ.js} +67 -64
  132. package/dist/{evolve-FTZBMNVW.js → evolve-AL3NGVRL.js} +65 -62
  133. package/dist/{extensions-VHRBEID7.js → extensions-MOVJ32NM.js} +9 -7
  134. package/dist/{fleet-CKZHJWZJ.js → fleet-QZHUMAGI.js} +114 -111
  135. package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-BAYT5FJZ.js} +10 -10
  136. package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-IREVMRU4.js} +7 -6
  137. package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-YCTT3HTI.js} +22 -19
  138. package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-QVJTDAVB.js} +58 -55
  139. package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-25QAFPK4.js} +4 -4
  140. package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-5O57AAJ7.js} +26 -23
  141. package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-CPH2W2T6.js} +59 -56
  142. package/dist/{fleet-view-WAMJYNDT.js → fleet-view-SWBR3VGQ.js} +58 -55
  143. package/dist/{init-5XQRBOFV.js → init-J477LKZH.js} +82 -79
  144. package/dist/{interop-34TVO25M.js → interop-3FCM6XLG.js} +11 -11
  145. package/dist/{library-3QY6KF57.js → library-QUQEIUG6.js} +30 -27
  146. package/dist/{memory-L4UTIIIW.js → memory-SGGSEP65.js} +67 -64
  147. package/dist/{models-ZVX3QOWE.js → models-HEKUAXXK.js} +53 -46
  148. package/dist/{monitor-CEKVSYTS.js → monitor-HKU57TYQ.js} +63 -60
  149. package/dist/{orchestrator-77BAP6BC.js → orchestrator-VDFAEFAI.js} +1831 -1057
  150. package/dist/{panes-7STHOAUJ.js → panes-DN2SSFOH.js} +5 -5
  151. package/dist/{panes-SHAUIRXY.js → panes-TALGNPZT.js} +29 -14
  152. package/dist/{paths-L7LGY6RN.js → paths-NBMFAIEZ.js} +5 -5
  153. package/dist/reset-EAJFFJVB.js +344 -0
  154. package/dist/{resources-74GKTLSF.js → resources-OVKSEFVE.js} +29 -20
  155. package/dist/{run-HBAUJNNZ.js → run-7DP7ZF2J.js} +120 -115
  156. package/dist/{share-G3APVLVP.js → share-WML67FT3.js} +32 -27
  157. package/dist/{skills-35HHUKCR.js → skills-SG662R2K.js} +41 -31
  158. package/dist/{skills-eval-QN4HSHDC.js → skills-eval-VVZEUU46.js} +78 -77
  159. package/dist/{skills-inventory-J357J34F.js → skills-inventory-I2E23GET.js} +23 -20
  160. package/dist/{slash-commands-JZZCQA32.js → slash-commands-S7MBJDQK.js} +40 -36
  161. package/dist/{steer-XAVHJM22.js → steer-2LQOMCPB.js} +3 -3
  162. package/dist/{support-U7QOWY26.js → support-CC2UJBJ6.js} +6 -6
  163. package/dist/{targets-DSM6CY3M.js → targets-4QC3HIEW.js} +54 -54
  164. package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-TUHIJ6Y2.js} +5 -5
  165. package/dist/{tools-MKNWVPBH.js → tools-TFGJICCU.js} +10 -10
  166. package/dist/{trace-ECQ7TIYZ.js → trace-FXMXUZUF.js} +55 -7
  167. package/dist/uninstall-5PEVOE5B.js +408 -0
  168. package/dist/upgrade-M4WXY6KN.js +303 -0
  169. package/dist/{usage-X52N3IDJ.js → usage-N7ZNVLEM.js} +151 -104
  170. package/dist/{verifiers-EJTVVSMA.js → verifiers-DJTP4XX6.js} +15 -15
  171. package/dist/{verify-YJL6XET2.js → verify-RWE4PPEK.js} +9 -9
  172. package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
  173. package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-C7IQOXSP.js} +89 -86
  174. package/dist/{with-panes-OBOBFIIR.js → with-panes-4GCGSL7J.js} +53 -257
  175. package/dist/worker/entry.js +90 -74
  176. package/docs/README.md +176 -81
  177. package/docs/{acp.md → architecture/acp.md} +36 -20
  178. package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
  179. package/docs/{architecture.md → architecture/architecture.md} +43 -22
  180. package/docs/{artifact-placement.md → architecture/artifact-placement.md} +27 -23
  181. package/docs/architecture/artifact-versions.md +90 -0
  182. package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
  183. package/docs/{context-engine.md → architecture/context-engine.md} +29 -25
  184. package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
  185. package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
  186. package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
  187. package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
  188. package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
  189. package/docs/{model-catalog.md → architecture/model-catalog.md} +61 -27
  190. package/docs/{observability.md → architecture/observability.md} +38 -14
  191. package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
  192. package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +57 -20
  193. package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +99 -25
  194. package/docs/{safety-model.md → architecture/safety-model.md} +35 -20
  195. package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
  196. package/docs/architecture/time-conventions.md +125 -0
  197. package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
  198. package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
  199. package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
  200. package/docs/{built-in-agents.md → guide/built-in-agents.md} +65 -35
  201. package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +66 -61
  202. package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +323 -297
  203. package/docs/guide/configuration-reference.md +1163 -0
  204. package/docs/{environment-variables.md → guide/environment-variables.md} +33 -28
  205. package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
  206. package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
  207. package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
  208. package/docs/{glossary.md → guide/glossary.md} +14 -11
  209. package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +81 -17
  210. package/docs/guide/panes-and-files.md +290 -0
  211. package/docs/{proactive-memory.md → guide/proactive-memory.md} +131 -107
  212. package/docs/{resource-library.md → guide/resource-library.md} +13 -4
  213. package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +25 -3
  214. package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
  215. package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
  216. package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
  217. package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
  218. package/docs/process/development-pipeline.md +152 -0
  219. package/docs/process/documentation-coverage.md +100 -0
  220. package/docs/process/documentation-guide.md +187 -0
  221. package/docs/{eval-runner.md → process/eval-runner.md} +108 -53
  222. package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
  223. package/docs/{evolution.md → process/evolution.md} +2 -2
  224. package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
  225. package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
  226. package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
  227. package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
  228. package/evals/README.md +2 -2
  229. package/evals/behavioral-model.yaml +3 -2
  230. package/package.json +10 -8
  231. package/skills/README.md +52 -41
  232. package/skills/coding/ast-grep/SKILL.md +102 -31
  233. package/skills/coding/ast-grep/evals.md +26 -0
  234. package/skills/coding/coding-standards/SKILL.md +41 -6
  235. package/skills/coding/coding-standards/evals.md +23 -0
  236. package/skills/coding/prototype/SKILL.md +88 -29
  237. package/skills/coding/prototype/evals.md +19 -0
  238. package/skills/coding/tdd/SKILL.md +81 -54
  239. package/skills/coding/tdd/evals.md +20 -0
  240. package/skills/context/context-handoff/SKILL.md +44 -3
  241. package/skills/context/context-handoff/evals.md +44 -0
  242. package/skills/context/context-prime/SKILL.md +46 -16
  243. package/skills/context/context-prime/evals.md +45 -0
  244. package/skills/git/branch-closeout/SKILL.md +132 -0
  245. package/skills/git/branch-closeout/evals.md +133 -0
  246. package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
  247. package/skills/git/file-ticket/SKILL.md +78 -64
  248. package/skills/git/file-ticket/assets/issue-template.md +22 -0
  249. package/skills/git/file-ticket/evals.md +31 -26
  250. package/skills/git/file-ticket/references/issue-discovery.md +49 -0
  251. package/skills/git/fix-issue/SKILL.md +88 -65
  252. package/skills/git/fix-issue/evals.md +35 -31
  253. package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
  254. package/skills/git/resolve-merge-conflicts/SKILL.md +101 -52
  255. package/skills/git/resolve-merge-conflicts/evals.md +52 -25
  256. package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
  257. package/skills/git/ship/SKILL.md +103 -67
  258. package/skills/git/ship/assets/pr-template.md +21 -0
  259. package/skills/git/ship/evals.md +44 -28
  260. package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
  261. package/skills/git/worktree-create/SKILL.md +80 -50
  262. package/skills/git/worktree-create/evals.md +40 -33
  263. package/skills/git/worktree-create/references/worktree-setup.md +62 -66
  264. package/skills/git/worktree-merge/SKILL.md +112 -65
  265. package/skills/git/worktree-merge/evals.md +42 -34
  266. package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
  267. package/skills/meta/clio-coder-dev/SKILL.md +9 -5
  268. package/skills/meta/clio-coder-dev/evals.md +3 -2
  269. package/skills/meta/clio-coder-test/SKILL.md +102 -95
  270. package/skills/meta/clio-coder-test/evals.md +9 -4
  271. package/skills/meta/clio-coder-test/references/harness.md +100 -124
  272. package/skills/meta/clio-coder-test/references/test-map.md +77 -50
  273. package/skills/meta/credentials/SKILL.md +2 -2
  274. package/skills/meta/find-skills/SKILL.md +2 -2
  275. package/skills/meta/herdr/SKILL.md +2 -2
  276. package/skills/meta/skill-craft/SKILL.md +22 -16
  277. package/skills/planning/archify/SKILL.md +196 -0
  278. package/skills/planning/archify/evals.md +65 -0
  279. package/skills/planning/architecture/SKILL.md +62 -13
  280. package/skills/planning/architecture/evals.md +65 -0
  281. package/skills/planning/backlog/SKILL.md +131 -15
  282. package/skills/planning/backlog/evals.md +142 -0
  283. package/skills/planning/prd/SKILL.md +47 -7
  284. package/skills/planning/prd/evals.md +54 -0
  285. package/skills/planning/product-intent/SKILL.md +58 -3
  286. package/skills/planning/product-intent/evals.md +70 -0
  287. package/skills/planning/tech-spec/SKILL.md +54 -3
  288. package/skills/planning/tech-spec/evals.md +73 -0
  289. package/skills/registry.yaml +70 -62
  290. package/skills/remote.yaml +13 -0
  291. package/skills/research/arxiv-literature/SKILL.md +77 -19
  292. package/skills/research/arxiv-literature/evals.md +50 -0
  293. package/skills/research/experiment-protocol/SKILL.md +21 -2
  294. package/skills/research/experiment-protocol/evals.md +23 -0
  295. package/skills/research/scientific-debugging/SKILL.md +24 -2
  296. package/skills/research/scientific-debugging/evals.md +18 -0
  297. package/skills/research/scientific-modernization/SKILL.md +27 -2
  298. package/skills/research/scientific-modernization/evals.md +27 -0
  299. package/skills/skill-marketplace.json +97 -62
  300. package/skills/workflow/cut-it/SKILL.md +66 -6
  301. package/skills/workflow/cut-it/evals.md +101 -0
  302. package/skills/workflow/design-council/SKILL.md +118 -28
  303. package/skills/workflow/design-council/evals.md +161 -0
  304. package/skills/workflow/grill-me/SKILL.md +87 -11
  305. package/skills/workflow/grill-me/evals.md +153 -0
  306. package/skills/workflow/workflow-distiller/SKILL.md +77 -18
  307. package/skills/workflow/workflow-distiller/evals.md +118 -0
  308. package/src/cli/args.ts +2 -2
  309. package/src/cli/bootstrap-generate.ts +1 -1
  310. package/src/cli/config-inspect.ts +65 -12
  311. package/src/cli/configure-interop.ts +105 -13
  312. package/src/cli/configure-oauth.ts +57 -0
  313. package/src/cli/configure-onboarding.ts +980 -0
  314. package/src/cli/configure-target.ts +594 -0
  315. package/src/cli/configure.ts +1082 -532
  316. package/src/cli/context-map.ts +114 -0
  317. package/src/cli/context.ts +4 -0
  318. package/src/cli/docs.ts +22 -14
  319. package/src/cli/doctor-naming.ts +5 -5
  320. package/src/cli/doctor-toolchain.ts +3 -3
  321. package/src/cli/eval.ts +1 -2
  322. package/src/cli/extensions.ts +2 -1
  323. package/src/cli/fleet.ts +1 -1
  324. package/src/cli/index.ts +3 -1
  325. package/src/cli/internal-dispatch.ts +3 -4
  326. package/src/cli/lifecycle-presenter.ts +436 -0
  327. package/src/cli/models.ts +10 -2
  328. package/src/cli/modes/print.ts +5 -1
  329. package/src/cli/panes.ts +19 -5
  330. package/src/cli/reset.ts +228 -106
  331. package/src/cli/run.ts +9 -4
  332. package/src/cli/select.ts +664 -0
  333. package/src/cli/share.ts +5 -1
  334. package/src/cli/skills-eval.ts +3 -3
  335. package/src/cli/skills.ts +9 -2
  336. package/src/cli/targets.ts +5 -6
  337. package/src/cli/trace.ts +55 -4
  338. package/src/cli/uninstall.ts +233 -165
  339. package/src/cli/upgrade.ts +204 -149
  340. package/src/cli/usage.ts +86 -27
  341. package/src/cli/validate-model.ts +3 -3
  342. package/src/cli/wiki-generate.ts +1 -1
  343. package/src/core/artifact-paths.ts +1 -1
  344. package/src/core/bash-exec.ts +131 -86
  345. package/src/core/bus-events.ts +51 -6
  346. package/src/core/config.ts +61 -1
  347. package/src/core/defaults.ts +7 -4
  348. package/src/core/dispatch-outcome.ts +16 -0
  349. package/src/core/external-diagnostic.ts +44 -0
  350. package/src/core/gateway-routing.ts +157 -0
  351. package/src/core/guardrails.ts +10 -49
  352. package/src/core/prompt-hint.ts +9 -0
  353. package/src/core/safe-exec.ts +17 -2
  354. package/src/core/skill-activation.ts +89 -2
  355. package/src/domains/agents/builtins/architect.md +2 -3
  356. package/src/domains/agents/builtins/coder.md +3 -2
  357. package/src/domains/agents/builtins/debugger.md +2 -2
  358. package/src/domains/agents/builtins/documenter.md +2 -2
  359. package/src/domains/agents/builtins/git-master.md +1 -1
  360. package/src/domains/agents/builtins/oracle.md +1 -1
  361. package/src/domains/agents/builtins/provenance.md +1 -1
  362. package/src/domains/agents/builtins/researcher.md +1 -1
  363. package/src/domains/agents/builtins/scout.md +1 -1
  364. package/src/domains/agents/builtins/tester.md +2 -2
  365. package/src/domains/agents/builtins/verifier.md +2 -2
  366. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  367. package/src/domains/agents/builtins/world-knowledge.md +31 -0
  368. package/src/domains/agents/catalog.ts +13 -15
  369. package/src/domains/agents/contract.ts +2 -0
  370. package/src/domains/agents/extension.ts +23 -1
  371. package/src/domains/agents/result-contract.ts +70 -0
  372. package/src/domains/config/keybindings.ts +8 -0
  373. package/src/domains/context/extension.ts +0 -3
  374. package/src/domains/context/wiki/map-seed.ts +589 -0
  375. package/src/domains/context/wiki/plan.ts +2 -2
  376. package/src/domains/context/working-set/path-index.ts +1 -0
  377. package/src/domains/dispatch/admission.ts +29 -0
  378. package/src/domains/dispatch/agent-candidates.ts +10 -0
  379. package/src/domains/dispatch/budget-envelope.ts +86 -1
  380. package/src/domains/dispatch/capability-match.ts +11 -0
  381. package/src/domains/dispatch/capacity-lease.ts +17 -0
  382. package/src/domains/dispatch/contract.ts +11 -1
  383. package/src/domains/dispatch/extension.ts +237 -49
  384. package/src/domains/dispatch/host-verification.ts +435 -39
  385. package/src/domains/dispatch/intent-requirements.ts +10 -0
  386. package/src/domains/dispatch/intent.ts +18 -1
  387. package/src/domains/dispatch/path-scope.ts +235 -24
  388. package/src/domains/dispatch/run-event-journal.ts +4 -15
  389. package/src/domains/dispatch/state.ts +2 -3
  390. package/src/domains/dispatch/transport.ts +45 -21
  391. package/src/domains/dispatch/types.ts +58 -3
  392. package/src/domains/dispatch/worker-model-metadata.ts +38 -0
  393. package/src/domains/eval/artifacts/store.ts +5 -0
  394. package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
  395. package/src/domains/eval/metrics/token-stream.ts +201 -31
  396. package/src/domains/eval/metrics/tracked.ts +40 -4
  397. package/src/domains/eval/runners/clio-run.ts +5 -2
  398. package/src/domains/eval/schema/suite.ts +28 -0
  399. package/src/domains/eval/schema/verdict.ts +2 -2
  400. package/src/domains/eval/store.ts +8 -1
  401. package/src/domains/eval/suites/resolve.ts +13 -1
  402. package/src/domains/eval/suites/run.ts +24 -3
  403. package/src/domains/evidence/trust-status.ts +10 -1
  404. package/src/domains/extensions/contract.ts +15 -1
  405. package/src/domains/extensions/discovery.ts +238 -41
  406. package/src/domains/extensions/extension.ts +105 -6
  407. package/src/domains/extensions/index.ts +24 -0
  408. package/src/domains/extensions/integrity.ts +189 -0
  409. package/src/domains/extensions/manager.ts +17 -1
  410. package/src/domains/extensions/resource-path.ts +27 -0
  411. package/src/domains/extensions/resources.ts +18 -38
  412. package/src/domains/extensions/snapshot-store.ts +39 -0
  413. package/src/domains/extensions/snapshot.ts +180 -0
  414. package/src/domains/extensions/state.ts +385 -57
  415. package/src/domains/extensions/types.ts +118 -1
  416. package/src/domains/interop/registry.ts +6 -2
  417. package/src/domains/interop/types.ts +4 -0
  418. package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
  419. package/src/domains/lifecycle/migrations/index.ts +6 -0
  420. package/src/domains/lifecycle/naming-resources.ts +19 -4
  421. package/src/domains/lifecycle/naming-yazi.ts +10 -5
  422. package/src/domains/memory/task-memory-policy.ts +70 -26
  423. package/src/domains/memory/task-memory-telemetry.ts +1 -0
  424. package/src/domains/middleware/contract.ts +26 -0
  425. package/src/domains/middleware/extension.ts +24 -24
  426. package/src/domains/middleware/hook-receipts.ts +27 -4
  427. package/src/domains/middleware/hooks-io.ts +65 -32
  428. package/src/domains/middleware/hooks.ts +64 -0
  429. package/src/domains/middleware/index.ts +28 -5
  430. package/src/domains/middleware/marketplace-offer.ts +3 -35
  431. package/src/domains/middleware/memory-intervention.ts +127 -32
  432. package/src/domains/middleware/memory-step-endpoint.ts +3 -2
  433. package/src/domains/middleware/registrations.ts +326 -0
  434. package/src/domains/middleware/runtime.ts +28 -0
  435. package/src/domains/middleware/skills-reminder.ts +31 -2
  436. package/src/domains/middleware/snapshot.ts +20 -7
  437. package/src/domains/mux/contract.ts +38 -0
  438. package/src/domains/mux/detect.ts +6 -13
  439. package/src/domains/mux/index.ts +1 -1
  440. package/src/domains/mux/operations.ts +44 -5
  441. package/src/domains/mux/yazi/assets/yazi.toml +2 -2
  442. package/src/domains/mux/yazi/session.ts +53 -4
  443. package/src/domains/mux/yazi/theme.ts +117 -17
  444. package/src/domains/observability/compaction-usage.ts +118 -0
  445. package/src/domains/observability/contract.ts +10 -11
  446. package/src/domains/observability/cost.ts +1 -1
  447. package/src/domains/observability/extension.ts +17 -4
  448. package/src/domains/observability/out-of-turn-usage.ts +52 -21
  449. package/src/domains/observability/projection.ts +14 -90
  450. package/src/domains/observability/trace-store.ts +43 -7
  451. package/src/domains/prompts/compiler.ts +73 -53
  452. package/src/domains/prompts/contract.ts +15 -3
  453. package/src/domains/prompts/extension.ts +97 -9
  454. package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
  455. package/src/domains/prompts/fragments/identity/clio.md +6 -12
  456. package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
  457. package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
  458. package/src/domains/prompts/fragments/operating/contract.md +7 -15
  459. package/src/domains/prompts/fragments/operating/delegation.md +32 -34
  460. package/src/domains/prompts/fragments/operating/skills.md +10 -24
  461. package/src/domains/prompts/fragments/operating/worker.md +1 -8
  462. package/src/domains/providers/contract.ts +4 -1
  463. package/src/domains/providers/extension.ts +40 -9
  464. package/src/domains/providers/index.ts +1 -1
  465. package/src/domains/providers/model-capabilities.ts +9 -0
  466. package/src/domains/providers/model-discovery.ts +2 -0
  467. package/src/domains/providers/model-runtime-capabilities.ts +99 -25
  468. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +699 -114
  469. package/src/domains/providers/runtime-resolution.ts +31 -0
  470. package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
  471. package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
  472. package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
  473. package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
  474. package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
  475. package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
  476. package/src/domains/providers/support.ts +11 -5
  477. package/src/domains/providers/target-model-cache.ts +25 -2
  478. package/src/domains/providers/types/capability-flags.ts +2 -0
  479. package/src/domains/providers/types/cost-provenance.ts +19 -0
  480. package/src/domains/providers/types/local-model-quirks.ts +85 -37
  481. package/src/domains/providers/types/runtime-descriptor.ts +20 -1
  482. package/src/domains/providers/types/target-descriptor.ts +19 -0
  483. package/src/domains/resources/index.ts +3 -0
  484. package/src/domains/resources/skills/install.ts +72 -7
  485. package/src/domains/resources/skills/loader.ts +23 -19
  486. package/src/domains/resources/skills/marketplace.ts +63 -11
  487. package/src/domains/safety/autonomy.ts +15 -0
  488. package/src/domains/safety/call-target.ts +1 -1
  489. package/src/domains/safety/index.ts +1 -0
  490. package/src/domains/safety/loop-detector.ts +7 -4
  491. package/src/domains/safety/path-policy.ts +1 -1
  492. package/src/domains/safety/policy-engine.ts +34 -11
  493. package/src/domains/safety/protected-artifacts.ts +191 -88
  494. package/src/domains/safety/run-effects.ts +2 -22
  495. package/src/domains/safety/skill-authority.ts +55 -0
  496. package/src/domains/session/compaction/compact.ts +72 -22
  497. package/src/domains/session/entries.ts +6 -0
  498. package/src/domains/session/task-board.ts +10 -9
  499. package/src/domains/session/usage.ts +3 -3
  500. package/src/domains/share/archive.ts +164 -7
  501. package/src/engine/acp/server.ts +62 -9
  502. package/src/engine/agent.ts +13 -3
  503. package/src/engine/ai.ts +26 -8
  504. package/src/engine/antigravity/subprocess-runtime.ts +386 -120
  505. package/src/engine/api-registry.ts +3 -0
  506. package/src/engine/apis/llamacpp-residency.ts +3 -4
  507. package/src/engine/apis/lmstudio.ts +3 -3
  508. package/src/engine/apis/ollama-native.ts +6 -6
  509. package/src/engine/apis/openai-completions.ts +145 -39
  510. package/src/engine/apis/output-budget.ts +8 -18
  511. package/src/engine/apis/residency.ts +8 -27
  512. package/src/engine/external-subprocess.ts +114 -6
  513. package/src/engine/gemma-channel-filter.ts +19 -0
  514. package/src/engine/loop-guard.ts +92 -12
  515. package/src/engine/worker-runtime.ts +40 -11
  516. package/src/engine/worker-tools.ts +3 -1
  517. package/src/entry/background-model-metadata.ts +18 -0
  518. package/src/entry/compaction-prompt.ts +57 -0
  519. package/src/entry/extension-hook-sources.ts +28 -0
  520. package/src/entry/extension-reload.ts +309 -0
  521. package/src/entry/orchestrator.ts +464 -251
  522. package/src/entry/task-memory-lifecycle.ts +35 -0
  523. package/src/interactive/application-controller.ts +2 -1
  524. package/src/interactive/bus-notices.ts +8 -1
  525. package/src/interactive/chat-loop-messages.ts +16 -17
  526. package/src/interactive/chat-loop.ts +75 -3
  527. package/src/interactive/chat-panel.ts +36 -13
  528. package/src/interactive/chat-renderer.ts +72 -7
  529. package/src/interactive/cost-overlay.ts +26 -2
  530. package/src/interactive/dispatch-board.ts +6 -11
  531. package/src/interactive/footer/widgets.ts +13 -0
  532. package/src/interactive/interactive-application.ts +39 -4
  533. package/src/interactive/interactive-input-runtime.ts +4 -0
  534. package/src/interactive/interactive-presentation.ts +2 -2
  535. package/src/interactive/interactive-slash-runtime.ts +4 -1
  536. package/src/interactive/overlays/extensions.ts +9 -1
  537. package/src/interactive/overlays/help-reference.ts +13 -0
  538. package/src/interactive/overlays/settings.ts +27 -16
  539. package/src/interactive/panes-runtime.ts +111 -35
  540. package/src/interactive/prompt-cache-identity.ts +88 -0
  541. package/src/interactive/renderers/worker-entry.ts +32 -0
  542. package/src/interactive/slash-commands.ts +153 -20
  543. package/src/interactive/stream-pacing-policy.ts +0 -23
  544. package/src/interactive/theme/labels.ts +19 -13
  545. package/src/interactive/turn-context.ts +39 -20
  546. package/src/interactive/turn-recovery.ts +8 -0
  547. package/src/interactive/turn-runtime.ts +27 -11
  548. package/src/interactive/turn-state.ts +7 -0
  549. package/src/interactive/worker-receipts.ts +1 -0
  550. package/src/interactive/worker-stream.ts +6 -1
  551. package/src/interactive/yazi-bridge.ts +60 -6
  552. package/src/tools/agent-tools.ts +30 -1
  553. package/src/tools/artifact.ts +2 -2
  554. package/src/tools/ask-user.ts +3 -3
  555. package/src/tools/bash.ts +1 -1
  556. package/src/tools/bootstrap.ts +4 -0
  557. package/src/tools/builtin-tool-catalog.ts +52 -22
  558. package/src/tools/codewiki/code-nav-surface.ts +6 -0
  559. package/src/tools/codewiki/code-nav.ts +99 -13
  560. package/src/tools/context/docs-engine.ts +20 -7
  561. package/src/tools/context/index.ts +59 -21
  562. package/src/tools/core-bootstrap.ts +28 -6
  563. package/src/tools/credential-present.ts +1 -2
  564. package/src/tools/dispatch-arguments.ts +6 -1
  565. package/src/tools/dispatch-event-text.ts +10 -0
  566. package/src/tools/dispatch-plan.ts +49 -4
  567. package/src/tools/dispatch-run-events.ts +1 -1
  568. package/src/tools/dispatch-runner.ts +12 -0
  569. package/src/tools/dispatch-schema.ts +338 -0
  570. package/src/tools/dispatch-types.ts +3 -0
  571. package/src/tools/dispatch.ts +9 -254
  572. package/src/tools/ledger.ts +3 -5
  573. package/src/tools/monitor-surface.ts +5 -13
  574. package/src/tools/observation.ts +4 -5
  575. package/src/tools/panes-surface.ts +4 -11
  576. package/src/tools/panes.ts +4 -2
  577. package/src/tools/policy.ts +15 -2
  578. package/src/tools/read.ts +5 -6
  579. package/src/tools/registry.ts +41 -12
  580. package/src/tools/result-shaping.ts +18 -14
  581. package/src/tools/steer-surface.ts +1 -1
  582. package/src/tools/tasks.ts +1 -1
  583. package/src/tools/truncate.ts +6 -5
  584. package/src/tools/verify/surface.ts +6 -12
  585. package/src/tools/web-fetch-surface.ts +1 -3
  586. package/src/tools/worker-evidence.ts +3 -1
  587. package/src/worker/spec-contract.ts +4 -0
  588. package/dist/builtins-UJLMOVOV.js +0 -17
  589. package/dist/chunk-5QIAJV2D.js +0 -48
  590. package/dist/chunk-JZWT5J3Y.js +0 -814
  591. package/dist/chunk-K7VKOLQQ.js +0 -15
  592. package/dist/chunk-PMZCIOCJ.js +0 -25
  593. package/dist/chunk-SUW5DORT.js +0 -819
  594. package/dist/chunk-UOV2BYIW.js +0 -107
  595. package/dist/chunk-WR6U3OVP.js +0 -45
  596. package/dist/chunk-Y45G3AXC.js +0 -1558
  597. package/dist/reset-EOLM7GVE.js +0 -230
  598. package/dist/uninstall-N34PCTGJ.js +0 -331
  599. package/dist/upgrade-H7TOM7YL.js +0 -323
  600. package/docs/artifact-versions.md +0 -67
  601. package/docs/development-pipeline.md +0 -121
  602. package/docs/documentation-coverage.md +0 -46
  603. package/docs/documentation-guide.md +0 -167
  604. package/docs/time-conventions.md +0 -101
@@ -1,21 +1,46 @@
1
- import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync } from "node:fs";
1
+ import { createHash } from "node:crypto";
2
+ import {
3
+ cpSync,
4
+ existsSync,
5
+ lstatSync,
6
+ mkdirSync,
7
+ readdirSync,
8
+ readFileSync,
9
+ realpathSync,
10
+ renameSync,
11
+ rmSync,
12
+ } from "node:fs";
2
13
  import path from "node:path";
3
14
  import { safeResourceWrite } from "../../core/safe-resource-write.js";
4
15
  import { clioConfigDir } from "../../core/xdg.js";
5
16
  import { evaluateClioCompatibility } from "./compatibility.js";
6
17
  import { isRecord, loadManifestFromRoot, trimString } from "./discovery.js";
18
+ import { extensionContentDigest, extensionContentDigestWithCapture } from "./integrity.js";
7
19
  import type {
20
+ ExtensionDiagnostic,
8
21
  ExtensionInstallOptions,
9
22
  ExtensionInstallResult,
10
23
  ExtensionListOptions,
11
24
  ExtensionMutationResult,
12
25
  ExtensionScope,
13
26
  ExtensionState,
27
+ ExtensionStateUpgradeReport,
14
28
  InstalledExtension,
15
29
  } from "./types.js";
16
30
 
17
31
  const DEFAULT_STATE: ExtensionState = { version: 1, disabled: [], installed: {} };
18
32
 
33
+ type StateReadResult =
34
+ | { status: "absent"; state: ExtensionState }
35
+ | { status: "valid"; state: ExtensionState }
36
+ | { status: "corrupt"; state: ExtensionState; message: string };
37
+
38
+ export interface InstalledExtensionRecord {
39
+ entry: InstalledExtension;
40
+ /** Exact file bytes captured by the stable tree-digest read. */
41
+ captured?: ReadonlyMap<string, Buffer>;
42
+ }
43
+
19
44
  export function extensionBaseDir(scope: ExtensionScope, cwd = process.cwd()): string {
20
45
  return scope === "user"
21
46
  ? path.join(clioConfigDir(), "extensions")
@@ -26,32 +51,61 @@ function statePath(scope: ExtensionScope, cwd = process.cwd()): string {
26
51
  return path.join(extensionBaseDir(scope, cwd), "state.json");
27
52
  }
28
53
 
54
+ function recoveryPath(filePath: string, label: string): string {
55
+ return `${filePath}.${label}-${process.pid}-${Date.now()}.bak`;
56
+ }
57
+
58
+ function packageRecoveryPath(root: string, label: string): string {
59
+ return path.join(path.dirname(root), `.${path.basename(root)}.${label}-${process.pid}-${Date.now()}.bak`);
60
+ }
61
+
62
+ function preserveFile(filePath: string, label: string): string | undefined {
63
+ if (!existsSync(filePath)) return undefined;
64
+ const backupPath = recoveryPath(filePath, label);
65
+ safeResourceWrite(backupPath, readFileSync(filePath));
66
+ return backupPath;
67
+ }
68
+
29
69
  export function scopeRank(scope: ExtensionScope): number {
30
70
  return scope === "project" ? 2 : 1;
31
71
  }
32
72
 
33
- function readState(scope: ExtensionScope, cwd = process.cwd()): ExtensionState {
73
+ function readState(scope: ExtensionScope, cwd = process.cwd()): StateReadResult {
34
74
  const filePath = statePath(scope, cwd);
35
- if (!existsSync(filePath)) return structuredClone(DEFAULT_STATE);
75
+ if (!existsSync(filePath)) return { status: "absent", state: structuredClone(DEFAULT_STATE) };
36
76
  try {
37
77
  const parsed = JSON.parse(readFileSync(filePath, "utf8")) as unknown;
38
- if (!isRecord(parsed) || parsed.version !== 1) return structuredClone(DEFAULT_STATE);
39
- const disabled = Array.isArray(parsed.disabled)
40
- ? parsed.disabled.filter((entry): entry is string => typeof entry === "string")
41
- : [];
42
- const installed = isRecord(parsed.installed)
43
- ? Object.fromEntries(
44
- Object.entries(parsed.installed).flatMap(([id, raw]) => {
45
- if (!isRecord(raw)) return [];
46
- const installedAt = trimString(raw.installedAt) ?? new Date(0).toISOString();
47
- const source = trimString(raw.source);
48
- return [[id, { installedAt, ...(source ? { source } : {}) }]];
49
- }),
50
- )
51
- : {};
52
- return { version: 1, disabled, installed };
53
- } catch {
54
- return structuredClone(DEFAULT_STATE);
78
+ if (!isRecord(parsed) || parsed.version !== 1) throw new Error("state must be a version 1 object");
79
+ if (!Array.isArray(parsed.disabled) || !parsed.disabled.every((entry) => typeof entry === "string")) {
80
+ throw new Error("state.disabled must be an array of strings");
81
+ }
82
+ if (!isRecord(parsed.installed)) throw new Error("state.installed must be an object");
83
+ const installed: ExtensionState["installed"] = {};
84
+ for (const [id, raw] of Object.entries(parsed.installed)) {
85
+ if (!isRecord(raw)) throw new Error(`state.installed.${id} must be an object`);
86
+ const installedAt = trimString(raw.installedAt);
87
+ if (!installedAt) throw new Error(`state.installed.${id}.installedAt must be a non-empty string`);
88
+ const source = raw.source === undefined ? undefined : trimString(raw.source);
89
+ if (raw.source !== undefined && !source) {
90
+ throw new Error(`state.installed.${id}.source must be a non-empty string`);
91
+ }
92
+ const contentDigest = raw.contentDigest === undefined ? undefined : trimString(raw.contentDigest);
93
+ if (raw.contentDigest !== undefined && (!contentDigest || !/^[a-f0-9]{64}$/u.test(contentDigest))) {
94
+ throw new Error(`state.installed.${id}.contentDigest must be a SHA-256 digest`);
95
+ }
96
+ installed[id] = {
97
+ installedAt,
98
+ ...(source ? { source } : {}),
99
+ ...(contentDigest ? { contentDigest } : {}),
100
+ };
101
+ }
102
+ return { status: "valid", state: { version: 1, disabled: [...parsed.disabled], installed } };
103
+ } catch (error) {
104
+ return {
105
+ status: "corrupt",
106
+ state: structuredClone(DEFAULT_STATE),
107
+ message: error instanceof Error ? error.message : String(error),
108
+ };
55
109
  }
56
110
  }
57
111
 
@@ -60,68 +114,225 @@ function writeState(scope: ExtensionScope, state: ExtensionState, cwd = process.
60
114
  safeResourceWrite(filePath, `${JSON.stringify(state, null, 2)}\n`, { encoding: "utf8" });
61
115
  }
62
116
 
63
- function installedFromRoot(root: string, scope: ExtensionScope, state: ExtensionState): InstalledExtension | null {
117
+ function installedFromRoot(
118
+ root: string,
119
+ scope: ExtensionScope,
120
+ stateResult: StateReadResult,
121
+ cwd: string,
122
+ fallbackId: string,
123
+ ): InstalledExtensionRecord | null {
64
124
  const candidate = loadManifestFromRoot(root);
65
125
  const manifest = candidate.manifest;
66
- if (!manifest || !candidate.manifestPath) return null;
67
- const clioRange = manifest.compatibility?.clio;
126
+ const diagnostics = [...candidate.diagnostics];
127
+ const id = manifest?.id ?? fallbackId;
128
+ const provenance = stateResult.state.installed[id];
129
+ const expectedDigest = provenance?.contentDigest;
130
+ let observedDigest: string | undefined;
131
+ let captured: ReadonlyMap<string, Buffer> | undefined;
132
+ let contentVerified = false;
133
+ if (stateResult.status === "corrupt") {
134
+ diagnostics.push({
135
+ type: "error",
136
+ message: `extension install state is corrupt: ${stateResult.message}; reinstall with --force or remove the package to preserve the corrupt bytes and recover`,
137
+ path: statePath(scope, cwd),
138
+ });
139
+ } else if (stateResult.status === "absent") {
140
+ diagnostics.push({
141
+ type: "error",
142
+ message: "extension install state is absent; installed content cannot be verified; reinstall with --force",
143
+ path: statePath(scope, cwd),
144
+ });
145
+ } else if (!provenance) {
146
+ diagnostics.push({
147
+ type: "error",
148
+ message: `extension ${id} is not recorded in install state; reinstall with --force`,
149
+ path: statePath(scope, cwd),
150
+ });
151
+ } else if (!expectedDigest) {
152
+ diagnostics.push({
153
+ type: "error",
154
+ message: `extension ${id} install provenance has no content digest; run clio-coder upgrade, then reinstall with --force if it remains unverifiable`,
155
+ path: statePath(scope, cwd),
156
+ });
157
+ } else {
158
+ try {
159
+ const manifestName = candidate.manifestPath ? path.basename(candidate.manifestPath) : undefined;
160
+ const digestResult = extensionContentDigestWithCapture(root, {
161
+ capture: [...(manifestName ? [manifestName] : []), "hooks.yaml"],
162
+ });
163
+ observedDigest = digestResult.digest;
164
+ contentVerified = observedDigest === expectedDigest;
165
+ if (contentVerified) captured = digestResult.captured;
166
+ if (!contentVerified) {
167
+ diagnostics.push({
168
+ type: "error",
169
+ message: `installed extension content drift detected (expected ${expectedDigest}, observed ${observedDigest})`,
170
+ path: root,
171
+ });
172
+ }
173
+ } catch (error) {
174
+ diagnostics.push({
175
+ type: "error",
176
+ message: `installed extension content could not be verified: ${error instanceof Error ? error.message : String(error)}`,
177
+ path: root,
178
+ });
179
+ }
180
+ }
181
+ const clioRange = manifest?.compatibility?.clio;
68
182
  const compatible = clioRange === undefined || evaluateClioCompatibility(clioRange).satisfied;
69
- return {
70
- id: manifest.id,
71
- name: manifest.name,
72
- version: manifest.version,
73
- description: manifest.description,
183
+ const manifestName = candidate.manifestPath ? path.basename(candidate.manifestPath) : undefined;
184
+ const manifestBytes = manifestName ? captured?.get(manifestName) : undefined;
185
+ const extensionProvenance =
186
+ contentVerified && expectedDigest && manifestBytes
187
+ ? {
188
+ id,
189
+ scope,
190
+ ...(provenance?.source ? { sourcePath: provenance.source } : {}),
191
+ canonicalRoot: realpathSync(root),
192
+ manifestDigest: createHash("sha256").update(manifestBytes).digest("hex"),
193
+ contentDigest: expectedDigest,
194
+ }
195
+ : undefined;
196
+ const entry: InstalledExtension = {
197
+ id,
198
+ name: manifest?.name ?? id,
199
+ version: manifest?.version ?? "unknown",
200
+ description: manifest?.description ?? "Installed extension has an invalid manifest.",
74
201
  scope,
75
202
  rootPath: root,
76
- manifestPath: candidate.manifestPath,
77
- enabled: !state.disabled.includes(manifest.id),
203
+ manifestPath: candidate.manifestPath ?? root,
204
+ enabled: !stateResult.state.disabled.includes(id),
205
+ valid: manifest !== undefined && candidate.valid && contentVerified,
78
206
  compatible,
79
207
  effective: false,
80
- resources: manifest.resources,
81
- diagnostics: candidate.diagnostics,
208
+ loadable: false,
209
+ ...(extensionProvenance ? { provenance: extensionProvenance } : {}),
210
+ ...(observedDigest ? { observedContentDigest: observedDigest } : {}),
211
+ resources: manifest?.resources ?? {},
212
+ diagnostics,
82
213
  };
214
+ return { entry, ...(extensionProvenance && captured ? { captured } : {}) };
83
215
  }
84
216
 
85
- function listScope(scope: ExtensionScope, cwd = process.cwd()): InstalledExtension[] {
217
+ function listScope(scope: ExtensionScope, cwd = process.cwd()): InstalledExtensionRecord[] {
86
218
  const base = extensionBaseDir(scope, cwd);
87
219
  if (!existsSync(base)) return [];
88
220
  const state = readState(scope, cwd);
89
- const out: InstalledExtension[] = [];
221
+ const out: InstalledExtensionRecord[] = [];
90
222
  for (const entry of readdirSync(base, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
91
- if (!entry.isDirectory()) continue;
223
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
92
224
  const root = path.join(base, entry.name);
93
- const installed = installedFromRoot(root, scope, state);
225
+ const installed = installedFromRoot(root, scope, state, cwd, entry.name);
94
226
  if (installed) out.push(installed);
95
227
  }
96
228
  return out;
97
229
  }
98
230
 
231
+ /**
232
+ * Add integrity digests to released v1 install records only after the installed
233
+ * tree validates and remains byte-identical through the atomic state rewrite.
234
+ * Refused records remain unchanged and therefore fail closed at load time.
235
+ */
236
+ export function upgradeLegacyExtensionInstallState(
237
+ cwd = process.cwd(),
238
+ scopes: ReadonlyArray<ExtensionScope> = ["user", "project"],
239
+ ): ExtensionStateUpgradeReport[] {
240
+ const reports: ExtensionStateUpgradeReport[] = [];
241
+ for (const scope of scopes) {
242
+ const filePath = statePath(scope, cwd);
243
+ const report: ExtensionStateUpgradeReport = { scope, statePath: filePath, upgraded: [], refused: [] };
244
+ const stateResult = readState(scope, cwd);
245
+ if (stateResult.status === "absent") {
246
+ reports.push(report);
247
+ continue;
248
+ }
249
+ if (stateResult.status === "corrupt") {
250
+ report.refused.push({ id: "<state>", reason: `install state is corrupt: ${stateResult.message}` });
251
+ reports.push(report);
252
+ continue;
253
+ }
254
+ const next = structuredClone(stateResult.state);
255
+ const verified = new Map<string, { root: string; digest: string }>();
256
+ for (const [id, record] of Object.entries(next.installed)) {
257
+ if (record.contentDigest) continue;
258
+ const root = path.join(extensionBaseDir(scope, cwd), id);
259
+ try {
260
+ if (!lstatSync(root).isDirectory()) throw new Error("installed path is not a directory");
261
+ const candidate = loadManifestFromRoot(root);
262
+ if (!candidate.valid || !candidate.manifest) {
263
+ throw new Error(candidate.diagnostics.map((diagnostic) => diagnostic.message).join("; ") || "manifest is invalid");
264
+ }
265
+ if (candidate.manifest.id !== id) {
266
+ throw new Error(`manifest id ${candidate.manifest.id} does not match install record ${id}`);
267
+ }
268
+ const digest = extensionContentDigest(root);
269
+ record.contentDigest = digest;
270
+ verified.set(id, { root, digest });
271
+ report.upgraded.push(id);
272
+ } catch (error) {
273
+ report.refused.push({ id, reason: error instanceof Error ? error.message : String(error) });
274
+ }
275
+ }
276
+ if (report.upgraded.length > 0) {
277
+ const backupPath = `${filePath}.pre-digest.bak`;
278
+ safeResourceWrite(filePath, `${JSON.stringify(next, null, 2)}\n`, {
279
+ encoding: "utf8",
280
+ backup: { path: backupPath },
281
+ beforeRename: () => {
282
+ for (const [id, expected] of verified) {
283
+ const candidate = loadManifestFromRoot(expected.root);
284
+ if (!candidate.valid || candidate.manifest?.id !== id) {
285
+ throw new Error(`extension ${id} became invalid during digest migration`);
286
+ }
287
+ const observed = extensionContentDigest(expected.root);
288
+ if (observed !== expected.digest) throw new Error(`extension ${id} changed during digest migration`);
289
+ }
290
+ },
291
+ });
292
+ report.backupPath = backupPath;
293
+ }
294
+ reports.push(report);
295
+ }
296
+ return reports;
297
+ }
298
+
99
299
  export function listInstalledExtensions(cwd = process.cwd(), options: ExtensionListOptions = {}): InstalledExtension[] {
300
+ return listInstalledExtensionRecords(cwd, options).map((record) => record.entry);
301
+ }
302
+
303
+ export function listInstalledExtensionRecords(
304
+ cwd = process.cwd(),
305
+ options: ExtensionListOptions = {},
306
+ ): InstalledExtensionRecord[] {
100
307
  const scopes: ExtensionScope[] = options.scope ? [options.scope] : ["user", "project"];
101
- const entries = scopes.flatMap((scope) => listScope(scope, cwd));
102
- const byId = new Map<string, InstalledExtension[]>();
103
- for (const entry of entries) {
308
+ const records = scopes.flatMap((scope) => listScope(scope, cwd));
309
+ const byId = new Map<string, InstalledExtensionRecord[]>();
310
+ for (const record of records) {
311
+ const entry = record.entry;
104
312
  const list = byId.get(entry.id) ?? [];
105
- list.push(entry);
313
+ list.push(record);
106
314
  byId.set(entry.id, list);
107
315
  }
108
316
  for (const group of byId.values()) {
109
317
  const winner = group
110
- .filter((entry) => entry.compatible)
111
- .sort((a, b) => scopeRank(a.scope) - scopeRank(b.scope))
318
+ .filter((record) => record.entry.valid && record.entry.compatible)
319
+ .sort((a, b) => scopeRank(a.entry.scope) - scopeRank(b.entry.scope))
112
320
  .at(-1);
113
- for (const entry of group) {
114
- entry.effective = entry === winner;
115
- if (entry.compatible && !entry.effective && winner) entry.overriddenBy = winner.scope;
321
+ for (const record of group) {
322
+ const entry = record.entry;
323
+ entry.effective = record === winner;
324
+ entry.loadable = entry.valid && entry.compatible && entry.enabled && entry.effective;
325
+ if (entry.valid && entry.compatible && !entry.effective && winner) entry.overriddenBy = winner.entry.scope;
116
326
  }
117
327
  }
118
- // Incompatible packages remain visible by default so the load refusal and
119
- // its version diagnostic cannot disappear with the resources it suppresses.
120
- const all = options.all === true ? entries : entries.filter((entry) => entry.effective || !entry.compatible);
328
+ // Invalid and incompatible packages remain visible by default so the load
329
+ // refusal and its diagnostic cannot disappear with the resources it suppresses.
330
+ const all =
331
+ options.all === true ? records : records.filter(({ entry }) => entry.effective || !entry.valid || !entry.compatible);
121
332
  return all.sort((a, b) => {
122
- const id = a.id.localeCompare(b.id);
333
+ const id = a.entry.id.localeCompare(b.entry.id);
123
334
  if (id !== 0) return id;
124
- return scopeRank(a.scope) - scopeRank(b.scope);
335
+ return scopeRank(a.entry.scope) - scopeRank(b.entry.scope);
125
336
  });
126
337
  }
127
338
 
@@ -144,7 +355,11 @@ export function installExtension(sourcePath: string, options: ExtensionInstallOp
144
355
  if (!options.force) {
145
356
  return {
146
357
  diagnostics: [
147
- { type: "error", message: `extension ${candidate.manifest.id} is already installed`, path: targetRoot },
358
+ {
359
+ type: "error",
360
+ message: `extension ${candidate.manifest.id} is already installed; retry with --force to replace it`,
361
+ path: targetRoot,
362
+ },
148
363
  ],
149
364
  };
150
365
  }
@@ -154,9 +369,24 @@ export function installExtension(sourcePath: string, options: ExtensionInstallOp
154
369
  const backupRoot = path.join(parent, `.${candidate.manifest.id}.backup-${process.pid}-${Date.now()}`);
155
370
  let installedReplacement = false;
156
371
  let movedExisting = false;
157
- const state = readState(scope, cwd);
372
+ const stateResult = readState(scope, cwd);
373
+ if (stateResult.status === "corrupt" && !options.force) {
374
+ return {
375
+ diagnostics: [
376
+ {
377
+ type: "error",
378
+ message: `extension install state is corrupt: ${stateResult.message}; retry with --force to back it up and reinstall safely`,
379
+ path: statePath(scope, cwd),
380
+ },
381
+ ],
382
+ };
383
+ }
384
+ const state = stateResult.status === "corrupt" ? structuredClone(DEFAULT_STATE) : stateResult.state;
385
+ let stateBackup: string | undefined;
386
+ let packageBackup: string | undefined;
158
387
  try {
159
388
  mkdirSync(parent, { recursive: true });
389
+ if (stateResult.status === "corrupt") stateBackup = preserveFile(statePath(scope, cwd), "corrupt");
160
390
  rmSync(stagingRoot, { recursive: true, force: true });
161
391
  rmSync(backupRoot, { recursive: true, force: true });
162
392
  cpSync(source, stagingRoot, {
@@ -167,23 +397,40 @@ export function installExtension(sourcePath: string, options: ExtensionInstallOp
167
397
  // template), so exclude only a bookkeeping file at the package root.
168
398
  filter: (src) => path.relative(source, src) !== "state.json",
169
399
  });
400
+ const stagedCandidate = loadManifestFromRoot(stagingRoot);
401
+ if (!stagedCandidate.valid || !stagedCandidate.manifest) {
402
+ const reasons = stagedCandidate.diagnostics.map((diagnostic) => diagnostic.message).join("; ");
403
+ throw new Error(`staged extension content is invalid${reasons ? `: ${reasons}` : ""}`);
404
+ }
405
+ if (stagedCandidate.manifest.id !== candidate.manifest.id) {
406
+ throw new Error(`staged extension id changed from ${candidate.manifest.id} to ${stagedCandidate.manifest.id}`);
407
+ }
408
+ const contentDigest = extensionContentDigest(stagingRoot);
170
409
  if (existsSync(targetRoot)) {
171
410
  renameSync(targetRoot, backupRoot);
172
411
  movedExisting = true;
412
+ packageBackup = backupRoot;
173
413
  }
174
414
  renameSync(stagingRoot, targetRoot);
175
415
  installedReplacement = true;
176
- state.installed[candidate.manifest.id] = { installedAt: new Date().toISOString(), source };
416
+ state.installed[candidate.manifest.id] = {
417
+ installedAt: new Date().toISOString(),
418
+ source,
419
+ contentDigest,
420
+ };
177
421
  state.disabled = state.disabled.filter((entry) => entry !== candidate.manifest?.id);
178
422
  writeState(scope, state, cwd);
179
- rmSync(backupRoot, { recursive: true, force: true });
180
423
  } catch (error) {
181
424
  rmSync(stagingRoot, { recursive: true, force: true });
182
425
  if (installedReplacement) rmSync(targetRoot, { recursive: true, force: true });
183
426
  if (movedExisting && existsSync(backupRoot) && !existsSync(targetRoot)) {
184
427
  renameSync(backupRoot, targetRoot);
428
+ packageBackup = undefined;
185
429
  }
186
430
  return {
431
+ ...(stateBackup || packageBackup
432
+ ? { recovery: { ...(stateBackup ? { stateBackup } : {}), ...(packageBackup ? { packageBackup } : {}) } }
433
+ : {}),
187
434
  diagnostics: [
188
435
  {
189
436
  type: "error",
@@ -193,10 +440,35 @@ export function installExtension(sourcePath: string, options: ExtensionInstallOp
193
440
  ],
194
441
  };
195
442
  }
443
+ const diagnostics = [...candidate.diagnostics];
444
+ if (movedExisting && stateResult.status !== "valid") {
445
+ diagnostics.push({
446
+ type: "warning",
447
+ message: "previous unverifiable extension bytes were preserved during forced reinstall",
448
+ path: backupRoot,
449
+ });
450
+ } else {
451
+ try {
452
+ rmSync(backupRoot, { recursive: true, force: true });
453
+ packageBackup = undefined;
454
+ } catch (error) {
455
+ diagnostics.push({
456
+ type: "warning",
457
+ message: `extension installed, but its backup could not be removed: ${error instanceof Error ? error.message : String(error)}`,
458
+ path: backupRoot,
459
+ });
460
+ }
461
+ }
462
+ if (stateBackup) {
463
+ diagnostics.push({ type: "warning", message: "corrupt extension install state was preserved", path: stateBackup });
464
+ }
196
465
  const installed = findInstalled(candidate.manifest.id, cwd, scope);
197
466
  return {
198
467
  ...(installed ? { extension: installed } : {}),
199
- diagnostics: candidate.diagnostics,
468
+ ...(stateBackup || packageBackup
469
+ ? { recovery: { ...(stateBackup ? { stateBackup } : {}), ...(packageBackup ? { packageBackup } : {}) } }
470
+ : {}),
471
+ diagnostics,
200
472
  };
201
473
  }
202
474
 
@@ -206,7 +478,22 @@ function mutateEnabled(id: string, enabled: boolean, options: ExtensionListOptio
206
478
  if (!target) {
207
479
  return { diagnostics: [{ type: "error", message: `extension ${id} is not installed` }] };
208
480
  }
209
- const state = readState(target.scope, cwd);
481
+ const stateResult = readState(target.scope, cwd);
482
+ if (stateResult.status !== "valid") {
483
+ return {
484
+ diagnostics: [
485
+ {
486
+ type: "error",
487
+ message:
488
+ stateResult.status === "corrupt"
489
+ ? `extension install state is corrupt: ${stateResult.message}`
490
+ : "extension install state is absent",
491
+ path: statePath(target.scope, cwd),
492
+ },
493
+ ],
494
+ };
495
+ }
496
+ const state = stateResult.state;
210
497
  if (enabled) state.disabled = state.disabled.filter((entry) => entry !== id);
211
498
  else if (!state.disabled.includes(id)) state.disabled.push(id);
212
499
  writeState(target.scope, state, cwd);
@@ -228,8 +515,49 @@ export function removeExtension(id: string, options: ExtensionListOptions = {}):
228
515
  if (!target) {
229
516
  return { diagnostics: [{ type: "error", message: `extension ${id} is not installed` }] };
230
517
  }
518
+ const stateResult = readState(target.scope, cwd);
519
+ if (stateResult.status !== "valid") {
520
+ const filePath = statePath(target.scope, cwd);
521
+ const packageBackup = packageRecoveryPath(target.rootPath, "removed-unverifiable");
522
+ let stateBackup: string | undefined;
523
+ try {
524
+ if (stateResult.status === "corrupt") stateBackup = preserveFile(filePath, "corrupt");
525
+ renameSync(target.rootPath, packageBackup);
526
+ try {
527
+ writeState(target.scope, structuredClone(DEFAULT_STATE), cwd);
528
+ } catch (error) {
529
+ renameSync(packageBackup, target.rootPath);
530
+ throw error;
531
+ }
532
+ const diagnostics: ExtensionDiagnostic[] = [
533
+ {
534
+ type: "warning",
535
+ message: "unverifiable extension bytes were preserved while removing the package from the load path",
536
+ path: packageBackup,
537
+ },
538
+ ];
539
+ if (stateBackup) {
540
+ diagnostics.push({ type: "warning", message: "corrupt extension install state was preserved", path: stateBackup });
541
+ }
542
+ return {
543
+ removed: { id, scope: target.scope, path: target.rootPath },
544
+ recovery: { ...(stateBackup ? { stateBackup } : {}), packageBackup },
545
+ diagnostics,
546
+ };
547
+ } catch (error) {
548
+ return {
549
+ diagnostics: [
550
+ {
551
+ type: "error",
552
+ message: `extension ${id} could not be removed safely: ${error instanceof Error ? error.message : String(error)}`,
553
+ path: target.rootPath,
554
+ },
555
+ ],
556
+ };
557
+ }
558
+ }
559
+ const state = stateResult.state;
231
560
  rmSync(target.rootPath, { recursive: true, force: true });
232
- const state = readState(target.scope, cwd);
233
561
  Reflect.deleteProperty(state.installed, id);
234
562
  state.disabled = state.disabled.filter((entry) => entry !== id);
235
563
  writeState(target.scope, state, cwd);