@skaile/workspaces 5.11.0 → 5.13.0

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 (472) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/README.md +4 -4
  3. package/dist/{asset-feeds-CXGQIDFR.js → asset-feeds-ALMTHLPV.js} +26 -23
  4. package/dist/asset-feeds-ALMTHLPV.js.map +1 -0
  5. package/dist/asset-manager/catalog-deployer.js +10 -10
  6. package/dist/asset-manager/fragments.js +1 -1
  7. package/dist/asset-manager/index.js +18 -18
  8. package/dist/asset-manager/installer.js +13 -13
  9. package/dist/asset-manager/renderers.js +11 -11
  10. package/dist/asset-manager/src/fragments.d.ts +5 -0
  11. package/dist/asset-manager/src/fragments.d.ts.map +1 -1
  12. package/dist/asset-manager/src/index.d.ts +140 -12
  13. package/dist/asset-manager/src/index.d.ts.map +1 -1
  14. package/dist/asset-manager/src/install-agent.d.ts +9 -1
  15. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  16. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  17. package/dist/asset-manager/src/renderers.d.ts +5 -0
  18. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  19. package/dist/bridge/drivers/claude-sdk.js +21 -16
  20. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  21. package/dist/bridge/drivers/codex.js +101 -29
  22. package/dist/bridge/drivers/codex.js.map +1 -1
  23. package/dist/bridge/drivers/continue.js +12 -12
  24. package/dist/bridge/drivers/echo.js +2 -2
  25. package/dist/bridge/drivers/gemini.js +7 -7
  26. package/dist/bridge/drivers/goose.js +12 -12
  27. package/dist/bridge/drivers/omp.js +135 -33
  28. package/dist/bridge/drivers/omp.js.map +1 -1
  29. package/dist/bridge/drivers/opencode.js +12 -12
  30. package/dist/bridge/drivers/qwen.js +7 -7
  31. package/dist/bridge/index.js +14 -14
  32. package/dist/bridge/src/codex/config-toml.d.ts +16 -3
  33. package/dist/bridge/src/codex/config-toml.d.ts.map +1 -1
  34. package/dist/bridge/src/codex/managed-driver.d.ts.map +1 -1
  35. package/dist/bridge/src/drivers/claude-sdk.d.ts +1 -1
  36. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  37. package/dist/bridge/src/drivers/codex.d.ts +6 -0
  38. package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
  39. package/dist/bridge/src/drivers/omp-models-yml.d.ts +32 -0
  40. package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +1 -1
  41. package/dist/bridge/src/drivers/omp.d.ts +29 -6
  42. package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
  43. package/dist/bridge/src/provider-materialize/credential-env.d.ts +15 -0
  44. package/dist/bridge/src/provider-materialize/credential-env.d.ts.map +1 -1
  45. package/dist/{chunk-T42WRQ4O.js → chunk-2BIESC6S.js} +3 -3
  46. package/dist/{chunk-T42WRQ4O.js.map → chunk-2BIESC6S.js.map} +1 -1
  47. package/dist/{chunk-CPWLNZGJ.js → chunk-4DLQESIY.js} +3 -3
  48. package/dist/{chunk-CPWLNZGJ.js.map → chunk-4DLQESIY.js.map} +1 -1
  49. package/dist/{chunk-HZXUXHIV.js → chunk-4L4R5LV3.js} +89 -12
  50. package/dist/chunk-4L4R5LV3.js.map +1 -0
  51. package/dist/{chunk-CAHB6MHA.js → chunk-4NJ3QQHZ.js} +5 -5
  52. package/dist/{chunk-CAHB6MHA.js.map → chunk-4NJ3QQHZ.js.map} +1 -1
  53. package/dist/{chunk-ZCAJZ4B2.js → chunk-57SF6W6E.js} +147 -4
  54. package/dist/chunk-57SF6W6E.js.map +1 -0
  55. package/dist/{chunk-FH7W6TJ4.js → chunk-5FYOM4RF.js} +106 -25
  56. package/dist/chunk-5FYOM4RF.js.map +1 -0
  57. package/dist/{chunk-R7NHYEJF.js → chunk-5SKVCMRC.js} +15 -7
  58. package/dist/chunk-5SKVCMRC.js.map +1 -0
  59. package/dist/{chunk-CJERAGFY.js → chunk-6GICC4RJ.js} +44 -13
  60. package/dist/chunk-6GICC4RJ.js.map +1 -0
  61. package/dist/{chunk-G4FFOV3N.js → chunk-6JKIOPT3.js} +4 -4
  62. package/dist/{chunk-G4FFOV3N.js.map → chunk-6JKIOPT3.js.map} +1 -1
  63. package/dist/{chunk-T7CTHHG7.js → chunk-6NQDDCIL.js} +3 -3
  64. package/dist/{chunk-T7CTHHG7.js.map → chunk-6NQDDCIL.js.map} +1 -1
  65. package/dist/{chunk-XUSALIEI.js → chunk-7SMP4GNW.js} +6 -6
  66. package/dist/{chunk-XUSALIEI.js.map → chunk-7SMP4GNW.js.map} +1 -1
  67. package/dist/{chunk-Y3HTGHJC.js → chunk-AHCI4V5L.js} +3 -3
  68. package/dist/{chunk-Y3HTGHJC.js.map → chunk-AHCI4V5L.js.map} +1 -1
  69. package/dist/{chunk-M3B6EIJD.js → chunk-B7CZYFB2.js} +4 -4
  70. package/dist/{chunk-M3B6EIJD.js.map → chunk-B7CZYFB2.js.map} +1 -1
  71. package/dist/{chunk-PBBPZYVG.js → chunk-BF422IDP.js} +112 -46
  72. package/dist/chunk-BF422IDP.js.map +1 -0
  73. package/dist/{chunk-47U4GZ4M.js → chunk-BVJU2GKE.js} +20 -3
  74. package/dist/chunk-BVJU2GKE.js.map +1 -0
  75. package/dist/{chunk-PMECEZK3.js → chunk-D54T2F54.js} +5 -4
  76. package/dist/chunk-D54T2F54.js.map +1 -0
  77. package/dist/{chunk-2F5AWQX5.js → chunk-DKGEV6SQ.js} +192 -42
  78. package/dist/chunk-DKGEV6SQ.js.map +1 -0
  79. package/dist/{chunk-DALV4HHP.js → chunk-DKXNKFKP.js} +3 -2
  80. package/dist/{chunk-DALV4HHP.js.map → chunk-DKXNKFKP.js.map} +1 -1
  81. package/dist/chunk-FB3NREF7.js +649 -0
  82. package/dist/chunk-FB3NREF7.js.map +1 -0
  83. package/dist/{chunk-QZNJOHN6.js → chunk-FHDK3BFD.js} +3 -3
  84. package/dist/{chunk-QZNJOHN6.js.map → chunk-FHDK3BFD.js.map} +1 -1
  85. package/dist/{chunk-3SM2DL2T.js → chunk-GMDSRSGI.js} +21 -11
  86. package/dist/chunk-GMDSRSGI.js.map +1 -0
  87. package/dist/chunk-H5U7LNTJ.js +122 -0
  88. package/dist/chunk-H5U7LNTJ.js.map +1 -0
  89. package/dist/{chunk-VLTQGE2E.js → chunk-HBZD3MIW.js} +269 -81
  90. package/dist/chunk-HBZD3MIW.js.map +1 -0
  91. package/dist/{chunk-S3O3GKB7.js → chunk-HWGYJMME.js} +4 -4
  92. package/dist/{chunk-S3O3GKB7.js.map → chunk-HWGYJMME.js.map} +1 -1
  93. package/dist/{chunk-CPSIPIX7.js → chunk-IG5LZ3WU.js} +8 -6
  94. package/dist/chunk-IG5LZ3WU.js.map +1 -0
  95. package/dist/{chunk-ZPWTOUTK.js → chunk-IY5E7Y5W.js} +61 -8
  96. package/dist/chunk-IY5E7Y5W.js.map +1 -0
  97. package/dist/{chunk-6O2X3GPW.js → chunk-J4DB5G36.js} +7 -5
  98. package/dist/chunk-J4DB5G36.js.map +1 -0
  99. package/dist/{chunk-BNMZVPYA.js → chunk-J4OYIYFQ.js} +2 -2
  100. package/dist/{chunk-BNMZVPYA.js.map → chunk-J4OYIYFQ.js.map} +1 -1
  101. package/dist/{chunk-ALEYHUC5.js → chunk-L3ZGYSWY.js} +182 -41
  102. package/dist/chunk-L3ZGYSWY.js.map +1 -0
  103. package/dist/{chunk-SBSA3IQA.js → chunk-M3P4BYRK.js} +49 -14
  104. package/dist/chunk-M3P4BYRK.js.map +1 -0
  105. package/dist/{chunk-IER3KIPH.js → chunk-NDUYFYJB.js} +5 -5
  106. package/dist/{chunk-IER3KIPH.js.map → chunk-NDUYFYJB.js.map} +1 -1
  107. package/dist/{chunk-CGYEHQOX.js → chunk-NOA6EJXE.js} +11 -2
  108. package/dist/chunk-NOA6EJXE.js.map +1 -0
  109. package/dist/{chunk-J4RBUFGM.js → chunk-NVO6WECE.js} +9 -8
  110. package/dist/chunk-NVO6WECE.js.map +1 -0
  111. package/dist/{chunk-OBYKJB4U.js → chunk-O2SYFJWP.js} +79 -5
  112. package/dist/chunk-O2SYFJWP.js.map +1 -0
  113. package/dist/{chunk-5LKOAX7I.js → chunk-OQ5MKDS3.js} +21 -5
  114. package/dist/chunk-OQ5MKDS3.js.map +1 -0
  115. package/dist/{chunk-NWDSLXOX.js → chunk-PHRNUTSG.js} +118 -118
  116. package/dist/chunk-PHRNUTSG.js.map +1 -0
  117. package/dist/chunk-PN44DOGP.js +345 -0
  118. package/dist/chunk-PN44DOGP.js.map +1 -0
  119. package/dist/{chunk-COH6FQAG.js → chunk-PXDWTJ3P.js} +5 -5
  120. package/dist/{chunk-COH6FQAG.js.map → chunk-PXDWTJ3P.js.map} +1 -1
  121. package/dist/{chunk-GV4DZ6MT.js → chunk-PYTTF754.js} +22 -6
  122. package/dist/chunk-PYTTF754.js.map +1 -0
  123. package/dist/chunk-PZOO7L26.js +64 -0
  124. package/dist/chunk-PZOO7L26.js.map +1 -0
  125. package/dist/{chunk-EDYHEMJA.js → chunk-QO7CR3KB.js} +10 -5
  126. package/dist/chunk-QO7CR3KB.js.map +1 -0
  127. package/dist/{chunk-XDKH7XSA.js → chunk-R6QHJEHE.js} +5 -5
  128. package/dist/{chunk-XDKH7XSA.js.map → chunk-R6QHJEHE.js.map} +1 -1
  129. package/dist/chunk-U27JRO5L.js +13 -0
  130. package/dist/chunk-U27JRO5L.js.map +1 -0
  131. package/dist/{chunk-X77SUM4P.js → chunk-USHB5KEY.js} +3 -3
  132. package/dist/{chunk-X77SUM4P.js.map → chunk-USHB5KEY.js.map} +1 -1
  133. package/dist/{chunk-QVFAS5IO.js → chunk-V5JHD4I2.js} +3 -3
  134. package/dist/{chunk-QVFAS5IO.js.map → chunk-V5JHD4I2.js.map} +1 -1
  135. package/dist/{chunk-PQFHMQHQ.js → chunk-VLBIME5L.js} +6 -6
  136. package/dist/{chunk-PQFHMQHQ.js.map → chunk-VLBIME5L.js.map} +1 -1
  137. package/dist/{chunk-D3B36CYC.js → chunk-X3RMRJNR.js} +4 -3
  138. package/dist/chunk-X3RMRJNR.js.map +1 -0
  139. package/dist/{chunk-TCHRMVTO.js → chunk-XBYSURMK.js} +4 -4
  140. package/dist/{chunk-TCHRMVTO.js.map → chunk-XBYSURMK.js.map} +1 -1
  141. package/dist/{chunk-MZG34MBZ.js → chunk-XJYBCDY2.js} +3 -3
  142. package/dist/{chunk-MZG34MBZ.js.map → chunk-XJYBCDY2.js.map} +1 -1
  143. package/dist/{chunk-4A4OD24G.js → chunk-Y4Z7LGSH.js} +9 -9
  144. package/dist/{chunk-4A4OD24G.js.map → chunk-Y4Z7LGSH.js.map} +1 -1
  145. package/dist/{chunk-DZMNFCWB.js → chunk-Y7WKXPWS.js} +816 -143
  146. package/dist/chunk-Y7WKXPWS.js.map +1 -0
  147. package/dist/{chunk-HCEVNYSH.js → chunk-YTZFSKWL.js} +3 -3
  148. package/dist/{chunk-HCEVNYSH.js.map → chunk-YTZFSKWL.js.map} +1 -1
  149. package/dist/{chunk-WSBKB4CJ.js → chunk-ZSMMX3JD.js} +167 -25
  150. package/dist/chunk-ZSMMX3JD.js.map +1 -0
  151. package/dist/{chunk-GCHPUTA3.js → chunk-ZU24LWBI.js} +3 -3
  152. package/dist/{chunk-GCHPUTA3.js.map → chunk-ZU24LWBI.js.map} +1 -1
  153. package/dist/cli/index.js +1427 -605
  154. package/dist/cli/index.js.map +1 -1
  155. package/dist/cli/src/agent-checks.d.ts +40 -0
  156. package/dist/cli/src/agent-checks.d.ts.map +1 -0
  157. package/dist/cli/src/asset-feeds.d.ts.map +1 -1
  158. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  159. package/dist/cli/src/commands/catalog-cmd.d.ts.map +1 -1
  160. package/dist/cli/src/commands/catalog.d.ts +26 -0
  161. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  162. package/dist/cli/src/commands/config.d.ts.map +1 -1
  163. package/dist/cli/src/commands/diff.d.ts +1 -1
  164. package/dist/cli/src/commands/diff.d.ts.map +1 -1
  165. package/dist/cli/src/commands/integration.d.ts.map +1 -1
  166. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  167. package/dist/cli/src/commands/library-index.d.ts +10 -0
  168. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  169. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  170. package/dist/cli/src/commands/mcp-server.d.ts +1 -1
  171. package/dist/cli/src/commands/migrate-assets.d.ts +2 -1
  172. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  173. package/dist/cli/src/commands/migrate.d.ts.map +1 -1
  174. package/dist/cli/src/commands/plugin/claude-code.d.ts +1 -1
  175. package/dist/cli/src/commands/plugin/claude-code.d.ts.map +1 -1
  176. package/dist/cli/src/commands/plugin/types.d.ts +3 -1
  177. package/dist/cli/src/commands/plugin/types.d.ts.map +1 -1
  178. package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
  179. package/dist/cli/src/commands/preset-apply.d.ts.map +1 -1
  180. package/dist/cli/src/commands/project.d.ts +8 -0
  181. package/dist/cli/src/commands/project.d.ts.map +1 -1
  182. package/dist/cli/src/commands/publish-core.d.ts +5 -0
  183. package/dist/cli/src/commands/publish-core.d.ts.map +1 -1
  184. package/dist/cli/src/commands/run.d.ts +11 -1
  185. package/dist/cli/src/commands/run.d.ts.map +1 -1
  186. package/dist/cli/src/commands/serve-preflight.d.ts +23 -0
  187. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -0
  188. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  189. package/dist/cli/src/commands/source-manifest-publish.d.ts.map +1 -1
  190. package/dist/cli/src/commands/source-manifest.d.ts +1 -0
  191. package/dist/cli/src/commands/source-manifest.d.ts.map +1 -1
  192. package/dist/cli/src/commands/source.d.ts +9 -1
  193. package/dist/cli/src/commands/source.d.ts.map +1 -1
  194. package/dist/cli/src/commands/store.d.ts.map +1 -1
  195. package/dist/cli/src/commands/tree.d.ts.map +1 -1
  196. package/dist/cli/src/commands/update.d.ts.map +1 -1
  197. package/dist/cli/src/commands/validate-instances.d.ts.map +1 -1
  198. package/dist/cli/src/commands/validate.d.ts +3 -2
  199. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  200. package/dist/cli/src/commands/why.d.ts.map +1 -1
  201. package/dist/cli/src/curated-manifests.d.ts +21 -0
  202. package/dist/cli/src/curated-manifests.d.ts.map +1 -0
  203. package/dist/cli/src/driver-error.d.ts +7 -0
  204. package/dist/cli/src/driver-error.d.ts.map +1 -1
  205. package/dist/cli/src/helpers.d.ts +6 -0
  206. package/dist/cli/src/helpers.d.ts.map +1 -1
  207. package/dist/cli/src/index-busy.d.ts +8 -0
  208. package/dist/cli/src/index-busy.d.ts.map +1 -0
  209. package/dist/cli/src/plugin-store/index.d.ts +1 -1
  210. package/dist/cli/src/plugin-store/index.d.ts.map +1 -1
  211. package/dist/cli/src/plugin-store/paths.d.ts +7 -3
  212. package/dist/cli/src/plugin-store/paths.d.ts.map +1 -1
  213. package/dist/cli/src/plugin-store/reconcile.d.ts +24 -4
  214. package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -1
  215. package/dist/cli/src/skill-checks.d.ts +27 -3
  216. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  217. package/dist/cli/src/store-addable.d.ts +17 -0
  218. package/dist/cli/src/store-addable.d.ts.map +1 -0
  219. package/dist/connectors/config.js +6 -6
  220. package/dist/connectors/index.js +18 -18
  221. package/dist/connectors/src/config.d.ts.map +1 -1
  222. package/dist/{connectors-4QWAKPHB.js → connectors-GFKMKAXV.js} +21 -21
  223. package/dist/{connectors-4QWAKPHB.js.map → connectors-GFKMKAXV.js.map} +1 -1
  224. package/dist/core/driver-targets.js +1 -1
  225. package/dist/core/index.js +9 -9
  226. package/dist/core/logging.js +1 -1
  227. package/dist/core/manifest.js +2 -2
  228. package/dist/core/models.js +1 -1
  229. package/dist/core/publish-manifest.js +4 -2
  230. package/dist/core/ref.js +1 -1
  231. package/dist/core/runtime-assets.js +6 -6
  232. package/dist/core/src/agent-instances.d.ts +5 -0
  233. package/dist/core/src/agent-instances.d.ts.map +1 -1
  234. package/dist/core/src/driver-targets.d.ts.map +1 -1
  235. package/dist/core/src/index.d.ts +6 -5
  236. package/dist/core/src/index.d.ts.map +1 -1
  237. package/dist/core/src/lock.d.ts +15 -5
  238. package/dist/core/src/lock.d.ts.map +1 -1
  239. package/dist/core/src/logging/sinks/sqlite-sink.d.ts.map +1 -1
  240. package/dist/core/src/manifest.d.ts +14 -3
  241. package/dist/core/src/manifest.d.ts.map +1 -1
  242. package/dist/core/src/models.d.ts +11 -3
  243. package/dist/core/src/models.d.ts.map +1 -1
  244. package/dist/core/src/package-manager.d.ts +19 -0
  245. package/dist/core/src/package-manager.d.ts.map +1 -0
  246. package/dist/core/src/publish-manifest.d.ts +38 -1
  247. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  248. package/dist/core/src/repo-manager.d.ts +19 -3
  249. package/dist/core/src/repo-manager.d.ts.map +1 -1
  250. package/dist/core/src/runtime-assets.d.ts.map +1 -1
  251. package/dist/core/src/settings.d.ts +26 -6
  252. package/dist/core/src/settings.d.ts.map +1 -1
  253. package/dist/core/src/store.d.ts +4 -0
  254. package/dist/core/src/store.d.ts.map +1 -1
  255. package/dist/core/src/walker.d.ts +8 -1
  256. package/dist/core/src/walker.d.ts.map +1 -1
  257. package/dist/core/src/workspace-config.d.ts +24 -2
  258. package/dist/core/src/workspace-config.d.ts.map +1 -1
  259. package/dist/core/store.js +2 -2
  260. package/dist/core/workspace-config.js +5 -5
  261. package/dist/deploy/index.js +9 -9
  262. package/dist/discovery/index.js +5 -5
  263. package/dist/discovery/src/parse-manifest.d.ts.map +1 -1
  264. package/dist/discovery/src/source-config.d.ts +5 -3
  265. package/dist/discovery/src/source-config.d.ts.map +1 -1
  266. package/dist/{ensure-sources-2RONZKCU.js → ensure-sources-VUKHL65L.js} +21 -21
  267. package/dist/{ensure-sources-2RONZKCU.js.map → ensure-sources-VUKHL65L.js.map} +1 -1
  268. package/dist/factory-assets/README.md +1 -1
  269. package/dist/factory-assets/connectors/box.js +18 -18
  270. package/dist/factory-assets/connectors/deploy.js +18 -18
  271. package/dist/factory-assets/connectors/devserver.js +18 -18
  272. package/dist/factory-assets/connectors/flow/adapter.js +18 -18
  273. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
  274. package/dist/factory-assets/connectors/flow/contract.js +1 -1
  275. package/dist/factory-assets/connectors/flow/engine.js +11 -11
  276. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  277. package/dist/factory-assets/connectors/flow/run-flow.js +20 -20
  278. package/dist/factory-assets/connectors/flow.js +18 -18
  279. package/dist/factory-assets/connectors/git.js +18 -18
  280. package/dist/factory-assets/connectors/gmail.js +18 -18
  281. package/dist/factory-assets/connectors/googledrive.js +18 -18
  282. package/dist/factory-assets/connectors/local.js +18 -18
  283. package/dist/factory-assets/connectors/mattermost.js +18 -18
  284. package/dist/factory-assets/connectors/memory.js +18 -18
  285. package/dist/factory-assets/connectors/minio.js +18 -18
  286. package/dist/factory-assets/connectors/postgres.js +18 -18
  287. package/dist/factory-assets/connectors/s3.js +18 -18
  288. package/dist/factory-assets/connectors/sharepoint.js +18 -18
  289. package/dist/factory-assets/connectors/sqlite.js +18 -18
  290. package/dist/factory-assets/connectors/static-server.js +18 -18
  291. package/dist/factory-assets/connectors/tunnel.js +18 -18
  292. package/dist/factory-assets/connectors/webdav.js +18 -18
  293. package/dist/factory-assets/connectors/xstate-store.js +18 -18
  294. package/dist/factory-assets/connectors/xstate.js +18 -18
  295. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +10 -8
  296. package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +15 -11
  297. package/dist/factory-assets/skills/authoring-skaile-manifests/references/dependency-standard.md +12 -9
  298. package/dist/factory-assets/skills/skaile-author-asset/SKILL.md +2 -2
  299. package/dist/flows-A4YALSZY.js +26 -0
  300. package/dist/{flows-EQF2CH4U.js.map → flows-A4YALSZY.js.map} +1 -1
  301. package/dist/helpers-53XZW7KF.js +34 -0
  302. package/dist/{helpers-CFK6YP6R.js.map → helpers-53XZW7KF.js.map} +1 -1
  303. package/dist/library/index.js +14 -14
  304. package/dist/library/install.js +6 -4
  305. package/dist/library/src/index.d.ts +2 -2
  306. package/dist/library/src/index.d.ts.map +1 -1
  307. package/dist/library/src/install/source-fetch-github.d.ts.map +1 -1
  308. package/dist/library/src/local/db.d.ts +2 -0
  309. package/dist/library/src/local/db.d.ts.map +1 -1
  310. package/dist/library/src/local/library-manager.d.ts +5 -0
  311. package/dist/library/src/local/library-manager.d.ts.map +1 -1
  312. package/dist/library/src/local/library.d.ts +5 -3
  313. package/dist/library/src/local/library.d.ts.map +1 -1
  314. package/dist/library/src/local/local-catalog-source.d.ts +6 -0
  315. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  316. package/dist/library/src/local/store-paths.d.ts +9 -0
  317. package/dist/library/src/local/store-paths.d.ts.map +1 -1
  318. package/dist/library/src/manifest-writer.d.ts +1 -1
  319. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  320. package/dist/library/src/remote/index.d.ts +1 -1
  321. package/dist/library/src/remote/index.d.ts.map +1 -1
  322. package/dist/library/src/remote/remote-catalog-source.d.ts +17 -0
  323. package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
  324. package/dist/library/src/sync/git-driver.d.ts.map +1 -1
  325. package/dist/library/src/user-library.d.ts +2 -0
  326. package/dist/library/src/user-library.d.ts.map +1 -1
  327. package/dist/{library-publish-53UTB3MB.js → library-publish-FFIPWIRM.js} +50 -39
  328. package/dist/library-publish-FFIPWIRM.js.map +1 -0
  329. package/dist/open-library-PZAT3TJA.js +40 -0
  330. package/dist/{open-library-BOSPJVID.js.map → open-library-PZAT3TJA.js.map} +1 -1
  331. package/dist/open-registry-W46UXZ3I.js +32 -0
  332. package/dist/{open-registry-4FI7HKET.js.map → open-registry-W46UXZ3I.js.map} +1 -1
  333. package/dist/paths-KKY3NSBZ.js +22 -0
  334. package/dist/{paths-SUS4S4YT.js.map → paths-KKY3NSBZ.js.map} +1 -1
  335. package/dist/plugin-store-CK7YWRIC.js +227 -0
  336. package/dist/plugin-store-CK7YWRIC.js.map +1 -0
  337. package/dist/plugins/src/catalog-source.d.ts +6 -0
  338. package/dist/plugins/src/catalog-source.d.ts.map +1 -1
  339. package/dist/project-EZUH7PUJ.js +79 -0
  340. package/dist/{project-I55A4O2T.js.map → project-EZUH7PUJ.js.map} +1 -1
  341. package/dist/resolver/index.js +10 -10
  342. package/dist/runner/index.js +35 -35
  343. package/dist/runner/src/agent.d.ts.map +1 -1
  344. package/dist/runner/src/agents/in-process-host.d.ts.map +1 -1
  345. package/dist/runner/src/composition/index.d.ts +2 -1
  346. package/dist/runner/src/composition/index.d.ts.map +1 -1
  347. package/dist/runner/src/composition/prompt-sections.d.ts +20 -5
  348. package/dist/runner/src/composition/prompt-sections.d.ts.map +1 -1
  349. package/dist/runner/src/composition/resolve.d.ts +10 -1
  350. package/dist/runner/src/composition/resolve.d.ts.map +1 -1
  351. package/dist/runner/src/composition/verify.d.ts +29 -0
  352. package/dist/runner/src/composition/verify.d.ts.map +1 -0
  353. package/dist/runner/src/credential-notice.d.ts +14 -0
  354. package/dist/runner/src/credential-notice.d.ts.map +1 -0
  355. package/dist/runner/src/environment.d.ts.map +1 -1
  356. package/dist/runner/src/final-text.d.ts +17 -0
  357. package/dist/runner/src/final-text.d.ts.map +1 -0
  358. package/dist/runner/src/index.d.ts +2 -0
  359. package/dist/runner/src/index.d.ts.map +1 -1
  360. package/dist/runner/src/resource-handler.d.ts.map +1 -1
  361. package/dist/runner/src/serve.d.ts +13 -0
  362. package/dist/runner/src/serve.d.ts.map +1 -1
  363. package/dist/runner/src/session-builder.d.ts.map +1 -1
  364. package/dist/runner/src/session.d.ts +2 -0
  365. package/dist/runner/src/session.d.ts.map +1 -1
  366. package/dist/runner/src/ws-auth-warning.d.ts +17 -0
  367. package/dist/runner/src/ws-auth-warning.d.ts.map +1 -0
  368. package/dist/sdk/asset-manager.js +18 -18
  369. package/dist/sdk/bridge.js +14 -14
  370. package/dist/sdk/core.js +9 -9
  371. package/dist/sdk/flow.js +11 -11
  372. package/dist/sdk/index.js +38 -36
  373. package/dist/sdk/index.js.map +1 -1
  374. package/dist/sdk/resolver.js +10 -10
  375. package/dist/sdk/runner.js +35 -35
  376. package/dist/sdk/src/local-runtime.d.ts.map +1 -1
  377. package/dist/sdk/transport/ws/client.js +1 -1
  378. package/dist/sdk/transport/ws/server.js +1 -1
  379. package/dist/sdk/transport/ws.js +2 -2
  380. package/dist/sdk/transport.js +2 -2
  381. package/dist/serve-preflight-F7MYF747.js +64 -0
  382. package/dist/serve-preflight-F7MYF747.js.map +1 -0
  383. package/dist/{setup-7DQJKHUI.js → setup-L632QIHV.js} +26 -26
  384. package/dist/{setup-7DQJKHUI.js.map → setup-L632QIHV.js.map} +1 -1
  385. package/dist/skills-OY3Y5GKA.js +26 -0
  386. package/dist/{skills-NUEN5NDX.js.map → skills-OY3Y5GKA.js.map} +1 -1
  387. package/dist/source-36FHMN5V.js +42 -0
  388. package/dist/{source-G2LV5LVD.js.map → source-36FHMN5V.js.map} +1 -1
  389. package/dist/source-fetch-github-PIO6EMMF.js +4 -0
  390. package/dist/{source-fetch-github-QN4LLTL5.js.map → source-fetch-github-PIO6EMMF.js.map} +1 -1
  391. package/dist/{source-manifest-publish-6RM7SWLZ.js → source-manifest-publish-NIXJSJ22.js} +30 -28
  392. package/dist/source-manifest-publish-NIXJSJ22.js.map +1 -0
  393. package/dist/transport/index.js +2 -2
  394. package/dist/transport/src/ws/client.d.ts +6 -0
  395. package/dist/transport/src/ws/client.d.ts.map +1 -1
  396. package/dist/transport/src/ws/server.d.ts +4 -0
  397. package/dist/transport/src/ws/server.d.ts.map +1 -1
  398. package/dist/transport/ws/client.js +1 -1
  399. package/dist/transport/ws/server.js +1 -1
  400. package/dist/transport/ws.js +2 -2
  401. package/dist/tui/index.js +77 -50
  402. package/dist/tui/index.js.map +1 -1
  403. package/dist/tui/src/repl-session.d.ts +1 -1
  404. package/dist/tui/src/repl-session.d.ts.map +1 -1
  405. package/dist/tui/src/repl.d.ts +3 -0
  406. package/dist/tui/src/repl.d.ts.map +1 -1
  407. package/dist/types/manifests.js +1 -1
  408. package/dist/types/src/lifecycle.d.ts +2 -1
  409. package/dist/types/src/lifecycle.d.ts.map +1 -1
  410. package/dist/types/src/manifests/agent-composition.d.ts +20 -0
  411. package/dist/types/src/manifests/agent-composition.d.ts.map +1 -1
  412. package/dist/types/src/manifests/agent.d.ts.map +1 -1
  413. package/dist/types/src/manifests/cron.d.ts +15 -0
  414. package/dist/types/src/manifests/cron.d.ts.map +1 -0
  415. package/dist/types/src/manifests/index.d.ts +3 -2
  416. package/dist/types/src/manifests/index.d.ts.map +1 -1
  417. package/dist/types/src/manifests/preset.d.ts +6 -1
  418. package/dist/types/src/manifests/preset.d.ts.map +1 -1
  419. package/dist/workspace-plugin/adapters/mcp.js +25 -25
  420. package/dist/workspace-plugin/adapters/omp.js +106 -51
  421. package/dist/workspace-plugin/adapters/omp.js.map +1 -1
  422. package/dist/workspace-plugin/index.js +2 -2
  423. package/dist/workspace-plugin/src/adapters/claude-code.d.ts.map +1 -1
  424. package/dist/workspace-plugin/src/adapters/omp.d.ts +11 -2
  425. package/dist/workspace-plugin/src/adapters/omp.d.ts.map +1 -1
  426. package/package.json +1 -1
  427. package/dist/asset-feeds-CXGQIDFR.js.map +0 -1
  428. package/dist/chunk-2F5AWQX5.js.map +0 -1
  429. package/dist/chunk-3SM2DL2T.js.map +0 -1
  430. package/dist/chunk-47U4GZ4M.js.map +0 -1
  431. package/dist/chunk-5LKOAX7I.js.map +0 -1
  432. package/dist/chunk-6O2X3GPW.js.map +0 -1
  433. package/dist/chunk-ALEYHUC5.js.map +0 -1
  434. package/dist/chunk-CGYEHQOX.js.map +0 -1
  435. package/dist/chunk-CJERAGFY.js.map +0 -1
  436. package/dist/chunk-CPSIPIX7.js.map +0 -1
  437. package/dist/chunk-D3B36CYC.js.map +0 -1
  438. package/dist/chunk-DZMNFCWB.js.map +0 -1
  439. package/dist/chunk-EDYHEMJA.js.map +0 -1
  440. package/dist/chunk-FH7W6TJ4.js.map +0 -1
  441. package/dist/chunk-GV4DZ6MT.js.map +0 -1
  442. package/dist/chunk-HZXUXHIV.js.map +0 -1
  443. package/dist/chunk-J4RBUFGM.js.map +0 -1
  444. package/dist/chunk-NWDSLXOX.js.map +0 -1
  445. package/dist/chunk-OBYKJB4U.js.map +0 -1
  446. package/dist/chunk-PBBPZYVG.js.map +0 -1
  447. package/dist/chunk-PMECEZK3.js.map +0 -1
  448. package/dist/chunk-R7FOF242.js +0 -59
  449. package/dist/chunk-R7FOF242.js.map +0 -1
  450. package/dist/chunk-R7NHYEJF.js.map +0 -1
  451. package/dist/chunk-RYYLMBA2.js +0 -392
  452. package/dist/chunk-RYYLMBA2.js.map +0 -1
  453. package/dist/chunk-SBSA3IQA.js.map +0 -1
  454. package/dist/chunk-VLTQGE2E.js.map +0 -1
  455. package/dist/chunk-WSBKB4CJ.js.map +0 -1
  456. package/dist/chunk-YOH2L76X.js +0 -505
  457. package/dist/chunk-YOH2L76X.js.map +0 -1
  458. package/dist/chunk-ZCAJZ4B2.js.map +0 -1
  459. package/dist/chunk-ZPWTOUTK.js.map +0 -1
  460. package/dist/flows-EQF2CH4U.js +0 -26
  461. package/dist/helpers-CFK6YP6R.js +0 -34
  462. package/dist/library-publish-53UTB3MB.js.map +0 -1
  463. package/dist/open-library-BOSPJVID.js +0 -40
  464. package/dist/open-registry-4FI7HKET.js +0 -32
  465. package/dist/paths-SUS4S4YT.js +0 -22
  466. package/dist/plugin-store-AGQDMING.js +0 -149
  467. package/dist/plugin-store-AGQDMING.js.map +0 -1
  468. package/dist/project-I55A4O2T.js +0 -41
  469. package/dist/skills-NUEN5NDX.js +0 -26
  470. package/dist/source-G2LV5LVD.js +0 -41
  471. package/dist/source-fetch-github-QN4LLTL5.js +0 -4
  472. package/dist/source-manifest-publish-6RM7SWLZ.js.map +0 -1
package/dist/cli/index.js CHANGED
@@ -1,98 +1,101 @@
1
1
  #!/usr/bin/env node
2
- import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-XDKH7XSA.js';
3
- import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-WSBKB4CJ.js';
4
- import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportReplaced, reportRelocked, reportMoved, REF_HINT, reportInstalledSoftDeps } from '../chunk-CJERAGFY.js';
2
+ import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-R6QHJEHE.js';
3
+ import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportReplaced, reportRelocked, reportMoved, editedConventionFiles, REF_HINT, reportInstalledSoftDeps } from '../chunk-6GICC4RJ.js';
5
4
  import { createSpinner } from '../chunk-NESV47MF.js';
6
- import { AI_RESOURCES } from '../chunk-S3O3GKB7.js';
7
- import { unresolvedManifestDependencies, warnIgnoredDomainFiles, warnLegacyBundleFiles, removedDomainOption, rejectRemovedDomainOption, resolveLibraryPublisherDetailed, warnLibraryNameFallback, indexLibrary, requireValidPublisherOrExit, exitOnManifestPublisherProblems, registerLibraryAsset, DOMAIN_REMOVED_HINT, manifestPublisherProblems, manifestRequiresProblems, findAssetManifestFile, declaredVersion, checkAssetFile, duplicateAssetMessage, readAssetBody, checkAsset, invalidSemverText } from '../chunk-YOH2L76X.js';
8
- import { getStoreConfig, storeFetch, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, isStoreAuthenticated, getStoreToken, getStoreIdentity, assetEntryRef, manifestVersionMismatchMessage } from '../chunk-RYYLMBA2.js';
9
- import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-PQFHMQHQ.js';
10
- import { logErr, S, logOk, logInfo, logWarn, TARGET_DEFAULT_HINT, requireProjectConfig, deferredWarnings, warnLegacyClaudeCopies, kindColorPad, kindColor, colorRef, formatSoftDepSection, bareSoftDepName, formatSoftDepHint, formatRelativeTime, formatSoftDepRemovePreview, formatSoftDepAddPreview, fitWidth, KIND_COL_WIDTH } from '../chunk-GV4DZ6MT.js';
11
- import { getKindRegistry, getKnownKinds } from '../chunk-CAHB6MHA.js';
5
+ import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-ZSMMX3JD.js';
6
+ import { AI_RESOURCES } from '../chunk-HWGYJMME.js';
7
+ import { checkAsset, agentComposeRefAdvisories, findAssetManifestFile, declaredVersion, checkAssetFile, duplicateAssetMessage, readAssetBody, checkAgentFiles, invalidSemverText } from '../chunk-PN44DOGP.js';
8
+ import { getStoreConfig, storeFetch, isStoreAuthenticated, getStoreToken } from '../chunk-PZOO7L26.js';
9
+ import { unresolvedManifestDependencies, warnIgnoredDomainFiles, warnLegacyBundleFiles, removedDomainOption, rejectRemovedDomainOption, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, resolveLibraryPublisherDetailed, getStoreIdentity, warnLibraryNameFallback, indexLibrary, requireValidPublisherOrExit, exitOnManifestPublisherProblems, registerLibraryAsset, DOMAIN_REMOVED_HINT, reportLibrarySymlinks, assetEntryRef, manifestPublisherProblems, manifestRequiresProblems, manifestVersionMismatchMessage, exitOnLibrarySymlinks } from '../chunk-FB3NREF7.js';
10
+ import { storeNotInstallableReason } from '../chunk-U27JRO5L.js';
11
+ import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-VLBIME5L.js';
12
+ import { logErr, S, logOk, logInfo, logWarn, TARGET_DEFAULT_HINT, requireProjectConfig, deferredWarnings, logNoProject, warnLegacyClaudeCopies, kindColorPad, kindColor, colorRef, formatSoftDepSection, bareSoftDepName, formatSoftDepHint, formatRelativeTime, formatSoftDepRemovePreview, formatSoftDepAddPreview, fitWidth, KIND_COL_WIDTH } from '../chunk-PYTTF754.js';
13
+ import { getKindRegistry, getKnownKinds } from '../chunk-4NJ3QQHZ.js';
12
14
  import { LocalSecretsProvider } from '../chunk-ILFGVSTJ.js';
13
- import { runAgentChat, isCompositionError, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, hashAgentFiles, createCompositionContentSource, compileComposition, instanceForSession, resolveAgentInstance, describeComposition, MarkdownStreamer } from '../chunk-VLTQGE2E.js';
14
- import { buildClaudePluginFiles } from '../chunk-6O2X3GPW.js';
15
- import '../chunk-IER3KIPH.js';
16
- import '../chunk-QVFAS5IO.js';
15
+ import { runAgentChat, isCompositionError, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, hashAgentFiles, createCompositionContentSource, compileComposition, instanceForSession, resolveAgentInstance, describeComposition, MarkdownStreamer, createFinalTextFallback, resolveBinding, UnknownCompositionKindError } from '../chunk-HBZD3MIW.js';
16
+ import { buildClaudePluginFiles } from '../chunk-J4DB5G36.js';
17
+ import '../chunk-NDUYFYJB.js';
18
+ import '../chunk-V5JHD4I2.js';
17
19
  import '../chunk-R6O6YWU7.js';
18
- import '../chunk-G4FFOV3N.js';
19
- import '../chunk-T42WRQ4O.js';
20
+ import '../chunk-6JKIOPT3.js';
21
+ import '../chunk-2BIESC6S.js';
20
22
  import '../chunk-4ZTPYIBE.js';
21
- import '../chunk-MZG34MBZ.js';
23
+ import '../chunk-XJYBCDY2.js';
22
24
  import '../chunk-X5YPJV4N.js';
23
25
  import '../chunk-O7SG5PC2.js';
24
26
  import '../chunk-7QBNJTTQ.js';
25
- import '../chunk-OBYKJB4U.js';
26
- import '../chunk-5LKOAX7I.js';
27
+ import '../chunk-O2SYFJWP.js';
28
+ import '../chunk-OQ5MKDS3.js';
27
29
  import '../chunk-32NA4TVC.js';
28
30
  import '../chunk-W3UDISS2.js';
29
- import '../chunk-NWDSLXOX.js';
30
- import { runFlow, resumeFlow } from '../chunk-3SM2DL2T.js';
31
+ import '../chunk-PHRNUTSG.js';
32
+ import { runFlow, resumeFlow } from '../chunk-GMDSRSGI.js';
31
33
  import '../chunk-4R6DROGN.js';
32
- import { validateFlowVersions } from '../chunk-X77SUM4P.js';
33
- import '../chunk-GCHPUTA3.js';
34
+ import { parseSkillRequirements, validateRequirements, validateFlowVersions } from '../chunk-USHB5KEY.js';
35
+ import '../chunk-ZU24LWBI.js';
34
36
  import '../chunk-ISHJITXJ.js';
35
- import '../chunk-4A4OD24G.js';
37
+ import '../chunk-Y4Z7LGSH.js';
36
38
  import '../chunk-X4BAYGMT.js';
37
- import '../chunk-R7NHYEJF.js';
38
- import '../chunk-T7CTHHG7.js';
39
- import '../chunk-HCEVNYSH.js';
39
+ import '../chunk-5SKVCMRC.js';
40
+ import '../chunk-6NQDDCIL.js';
41
+ import '../chunk-YTZFSKWL.js';
40
42
  import '../chunk-LOO5CB5M.js';
41
43
  import '../chunk-2H73V6XR.js';
42
- import '../chunk-M3B6EIJD.js';
44
+ import '../chunk-B7CZYFB2.js';
43
45
  import '../chunk-B4X2N7JQ.js';
44
46
  import '../chunk-YROR332M.js';
45
- import { getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-47U4GZ4M.js';
47
+ import { listDrivers, getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-BVJU2GKE.js';
46
48
  import '../chunk-6E6PKKAD.js';
47
49
  import '../chunk-IFGTRL2I.js';
48
- import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-TCHRMVTO.js';
50
+ import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-XBYSURMK.js';
49
51
  import '../chunk-LNFKL23K.js';
50
- import '../chunk-D3B36CYC.js';
52
+ import '../chunk-X3RMRJNR.js';
51
53
  import '../chunk-M3WPBTGJ.js';
52
54
  import { nodeLabel, nodeSkillAsset, nodeIsInert, nodeIsOptional, nodeRunKind, flowSkillVersionPins } from '../chunk-7RGTAEG6.js';
53
55
  import '../chunk-NUELZWCF.js';
54
56
  import '../chunk-F4NJDSR7.js';
55
- import { AssetManager, MissingManifestError, parseRefTolerant, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-DZMNFCWB.js';
56
- import { libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, ensureGitRepo, conflictingAssetRoot, setManifestPublisher, LIBRARY_OWNERSHIPS, isGitRepo, assertManifestEditable, installLibraryAsset, missingRootAssets, assertValidLibraryName, syncManifestWithDisk, getStoreManifestsDir, getDefaultValue, isSecretPlaceholder } from '../chunk-2F5AWQX5.js';
57
- import { parseManifestFile, SEMVER_RE } from '../chunk-J4RBUFGM.js';
58
- import '../chunk-COH6FQAG.js';
59
- import '../chunk-R7FOF242.js';
57
+ import { AssetManager, parseRefTolerant, MissingManifestError, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-Y7WKXPWS.js';
58
+ import { libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, isGitRepo, ensureGitRepo, conflictingAssetRoot, setManifestPublisher, LIBRARY_OWNERSHIPS, assertManifestEditable, installLibraryAsset, missingRootAssets, getStoreManifestsDir, assertValidLibraryName, syncManifestWithDisk, getDefaultValue, isSecretPlaceholder } from '../chunk-DKGEV6SQ.js';
59
+ import { parseManifestFile, SEMVER_RE } from '../chunk-NVO6WECE.js';
60
+ import '../chunk-PXDWTJ3P.js';
61
+ import '../chunk-H5U7LNTJ.js';
60
62
  import '../chunk-3TXEJN4W.js';
61
- import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-FH7W6TJ4.js';
62
- import '../chunk-CGYEHQOX.js';
63
+ import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-5FYOM4RF.js';
64
+ import '../chunk-NOA6EJXE.js';
63
65
  import '../chunk-KTBKW2FI.js';
64
66
  import '../chunk-UQ6LFBPZ.js';
65
- import '../chunk-HZXUXHIV.js';
66
- import { effectiveComposes, validatePreset, composeSlotDiagnostics, agentDeprecationDiagnostics, validateAgent, SLOT_ID_PATTERN } from '../chunk-ZCAJZ4B2.js';
67
- import { resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, readLock, aiResourceRoots, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile } from '../chunk-PBBPZYVG.js';
67
+ import '../chunk-4L4R5LV3.js';
68
+ import { effectiveComposes, validatePreset, composeSlotDiagnostics, agentDeprecationDiagnostics, validateAgent, SLOT_ID_PATTERN } from '../chunk-57SF6W6E.js';
69
+ import { resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, resolveSettingsWithSources, readLock, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, aiResourceRoots, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile } from '../chunk-BF422IDP.js';
68
70
  import '../chunk-4GY63JU6.js';
69
- import { factoryAssetRoots } from '../chunk-EDYHEMJA.js';
70
- import '../chunk-PMECEZK3.js';
71
+ import { resolveRuntimeAssets, factoryAssetRoots } from '../chunk-QO7CR3KB.js';
72
+ import { deployedDir } from '../chunk-D54T2F54.js';
71
73
  import { DEFAULT_DRIVER_ID, DRIVER_DEFAULTS } from '../chunk-5BEFNLOR.js';
72
74
  import { findKindDirs } from '../chunk-A2ULN3KX.js';
73
- import { SourceEntryError, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, resolveSkWorkspaceConfig, matchPin, coerceVersion, loadSkWorkspaceConfig, normalizeAgentInstances, agentInstanceDiagnostics, storeManifestSlug, isWorkspaceConfigFilename } from '../chunk-ALEYHUC5.js';
75
+ import { SourceEntryError, resolveSkWorkspaceConfig, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, decodeSkaileYaml, matchPin, coerceVersion, loadSkWorkspaceConfig, normalizeAgentInstances, agentBlockKeyDiagnostics, agentInstanceDiagnostics, storeManifestSlug, isWorkspaceConfigFilename } from '../chunk-L3ZGYSWY.js';
74
76
  import { globalCacheRoot, globalSkaileDir, userConfigPath } from '../chunk-L5VSIPQD.js';
75
- import { SUPPORTED_DRIVER_TARGETS, driverTargetForDriver } from '../chunk-CPSIPIX7.js';
76
- import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, encodeSkaileManifest } from '../chunk-ZPWTOUTK.js';
77
+ import { SUPPORTED_DRIVER_TARGETS, driverTargetForDriver } from '../chunk-IG5LZ3WU.js';
78
+ import { SKAILE_MANIFEST_FILENAME, loadSkPublishManifest, decodeSkaileManifest, isNonAssetPath, isNonAssetDir, encodeSkaileManifest } from '../chunk-IY5E7Y5W.js';
77
79
  import { pluginTitle } from '../chunk-RVRB27AN.js';
78
- import { dedupeRequirements, parseFrontmatter, scanDirectory } from '../chunk-SBSA3IQA.js';
79
- import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, slugifyAssetName, parseAssetRefLoose, assetRefToStr } from '../chunk-BNMZVPYA.js';
80
+ import { dedupeRequirements, parseFrontmatter, scanDirectory, parseRequires } from '../chunk-M3P4BYRK.js';
81
+ import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, depToStr, slugifyAssetName, parseAssetRefLoose, assetRefToStr } from '../chunk-J4OYIYFQ.js';
80
82
  import { portableSpawn, portableSpawnSync } from '../chunk-ICSCSM5D.js';
81
- import { openSqlite } from '../chunk-DALV4HHP.js';
83
+ import { openSqlite } from '../chunk-DKXNKFKP.js';
82
84
  import { parseModelRef, resolveEntryBaseUrl } from '../chunk-MJHSLODD.js';
83
85
  import '../chunk-C3CAXQMA.js';
84
- import '../chunk-BOFL7GIF.js';
86
+ import { registerLogStore, LogStore, StdoutSink } from '../chunk-BOFL7GIF.js';
85
87
  import '../chunk-NSBPE2FW.js';
86
- import * as fs8 from 'fs';
87
- import fs8__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
88
- import * as path18 from 'path';
89
- import path18__default, { resolve, join } from 'path';
88
+ import * as fs9 from 'fs';
89
+ import fs9__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
90
+ import * as path22 from 'path';
91
+ import path22__default, { resolve, join } from 'path';
90
92
  import { fileURLToPath } from 'url';
91
93
  import { Help, Command, Option } from 'commander';
92
94
  import { rcompare } from 'semver';
95
+ import * as os from 'os';
96
+ import { homedir } from 'os';
93
97
  import * as p4 from '@clack/prompts';
94
98
  import pc5 from 'picocolors';
95
- import * as os from 'os';
96
99
  import { parse, stringify, parseDocument, isMap, isScalar, isSeq } from 'yaml';
97
100
  import * as readline from 'readline';
98
101
  import { createInterface } from 'readline';
@@ -128,6 +131,45 @@ function filterCatalogAssets(assets, query) {
128
131
  (a) => a.name.toLowerCase().includes(q) || (a.description?.toLowerCase().includes(q) ?? false) || a.publisher.toLowerCase().includes(q)
129
132
  );
130
133
  }
134
+ var STORE_TEST_NAME_RE = /^(test|demo)(-|$)/;
135
+ var STORE_ROW_LIMIT = 20;
136
+ function selectStoreRows(matches, query, all) {
137
+ const q = query?.toLowerCase();
138
+ const rank = (a) => {
139
+ if (!q) return 3;
140
+ const n = a.name.toLowerCase();
141
+ if (n === q) return 0;
142
+ if (n.startsWith(q)) return 1;
143
+ if (n.includes(q)) return 2;
144
+ return 3;
145
+ };
146
+ const ranked = [...matches].sort(
147
+ (a, b) => rank(a) - rank(b) || a.name.localeCompare(b.name) || a.version.localeCompare(b.version)
148
+ );
149
+ if (all) return { shown: ranked, hidden: 0, cut: 0 };
150
+ const keep = ranked.filter(
151
+ (a) => storeNotInstallableReason(a) === void 0 && !a.demo && !STORE_TEST_NAME_RE.test(a.name)
152
+ );
153
+ return {
154
+ shown: keep.slice(0, STORE_ROW_LIMIT),
155
+ hidden: ranked.length - keep.length,
156
+ cut: Math.max(0, keep.length - STORE_ROW_LIMIT)
157
+ };
158
+ }
159
+ function storeSelectionNotes(sel, indent) {
160
+ const notes = [];
161
+ if (sel.cut > 0) {
162
+ notes.push(
163
+ `${indent}${S.dim(`\u2026 ${sel.cut} more store match(es); narrow the query, or pass --all to list every one`)}`
164
+ );
165
+ }
166
+ if (sel.hidden > 0) {
167
+ notes.push(
168
+ `${indent}${S.dim(`${sel.hidden} store entr${sel.hidden === 1 ? "y" : "ies"} hidden: names that are not valid refs, demo/internal entries; --all lists them`)}`
169
+ );
170
+ }
171
+ return notes;
172
+ }
131
173
  function nearAssetKind(word) {
132
174
  const w = word.toLowerCase();
133
175
  let best;
@@ -175,7 +217,7 @@ async function runSearch(kind, query, opts) {
175
217
  const showLocal = !opts.store;
176
218
  const showStore = !opts.local;
177
219
  const { resolveConfig } = await import('../library/index.js');
178
- const airGapped = resolveConfig({ projectDir: path18__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
220
+ const airGapped = resolveConfig({ projectDir: path22__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
179
221
  if (showLocal) {
180
222
  await searchLocal(query, kind, opts, showStore, airGapped);
181
223
  }
@@ -184,7 +226,7 @@ async function runSearch(kind, query, opts) {
184
226
  }
185
227
  }
186
228
  async function searchIndex(query, kind) {
187
- const { openLibrary: openLibrary2 } = await import('../open-library-BOSPJVID.js');
229
+ const { openLibrary: openLibrary2 } = await import('../open-library-PZAT3TJA.js');
188
230
  const library = await openLibrary2();
189
231
  try {
190
232
  const { libraryDirMissing: libraryDirMissing2 } = await import('../library/index.js');
@@ -221,7 +263,7 @@ async function searchIndex(query, kind) {
221
263
  }
222
264
  }
223
265
  async function searchFactory(projectDir, query, kind) {
224
- const prefixes = factoryAssetRoots().map((r) => r.endsWith(path18__default.sep) ? r : r + path18__default.sep);
266
+ const prefixes = factoryAssetRoots().map((r) => r.endsWith(path22__default.sep) ? r : r + path22__default.sep);
225
267
  const isFactoryPath = (p6) => prefixes.some((fp) => p6 === fp.slice(0, -1) || p6.startsWith(fp));
226
268
  try {
227
269
  const entries = await new AssetManager({ registry: getKindRegistry(), projectDir }).search(
@@ -331,11 +373,11 @@ async function expandCompetingOrigins(entries, projectDir) {
331
373
  return out;
332
374
  }
333
375
  async function searchLocal(query, kind, opts, showStore, airGapped) {
334
- const projectDir = path18__default.resolve(opts.projectDir);
376
+ const projectDir = path22__default.resolve(opts.projectDir);
335
377
  const factory = await searchFactory(projectDir, query, kind);
336
378
  let entries = unionEntries(await searchIndex(query, kind), factory);
337
379
  if (entries.length === 0 && !query && !kind && !airGapped) {
338
- const { autoSyncForSearch } = await import('../source-G2LV5LVD.js');
380
+ const { autoSyncForSearch } = await import('../source-36FHMN5V.js');
339
381
  if (await autoSyncForSearch(projectDir)) {
340
382
  entries = unionEntries(await searchIndex(query, kind), factory);
341
383
  }
@@ -445,34 +487,30 @@ function formatStoreRows(assets, indent, width = terminalWidth()) {
445
487
  });
446
488
  }
447
489
  async function searchStore(query, kind, opts, airGapped) {
448
- if (airGapped) {
449
- if (opts.store) {
450
- logErr(
451
- "air-gapped (catalog.cache_ttl: 0) \u2014 store search is disabled. Set catalog.cache_ttl > 0 to query the store."
452
- );
453
- process.exit(1);
454
- }
490
+ if (airGapped && !opts.store) {
455
491
  logInfo("air-gapped (cache_ttl: 0) \u2014 local sources only");
456
492
  return;
457
493
  }
458
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-BOSPJVID.js');
494
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-PZAT3TJA.js');
459
495
  try {
460
- const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
496
+ const remote = await openCatalogSource2({ projectDir: path22__default.resolve(opts.projectDir) });
461
497
  const assets = await remote.listAssets(kind ? { kind } : {});
462
- const results = filterCatalogAssets(assets, query);
463
- if (results.length > 0) {
498
+ const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
499
+ if (sel.shown.length > 0) {
464
500
  console.log(`
465
501
  ${S.heading("Store:")}`);
466
- for (const row of formatStoreRows(results, " ")) console.log(row);
502
+ for (const row of formatStoreRows(sel.shown, " ")) console.log(row);
467
503
  } else if (opts.store) {
468
504
  logInfo("No results in store");
469
505
  }
506
+ for (const note of storeSelectionNotes(sel, " ")) console.log(note);
470
507
  } catch (e) {
471
508
  const local = e instanceof LocalCatalogDisabledError2;
472
509
  if (opts.store) {
473
510
  logErr(
474
- local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${e.message}`
511
+ local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${await describeStoreFailure(e, path22__default.resolve(opts.projectDir))}`
475
512
  );
513
+ process.exit(1);
476
514
  } else {
477
515
  logInfo(
478
516
  local ? "remote catalog disabled (catalog.url: local) \u2014 showing local results only" : "store unavailable \u2014 showing local results only (run with --store to see the error)"
@@ -480,8 +518,17 @@ async function searchStore(query, kind, opts, airGapped) {
480
518
  }
481
519
  }
482
520
  }
521
+ async function describeStoreFailure(err2, projectDir) {
522
+ const { resolveConfig, describeCatalogError, CatalogHttpError } = await import('../library/index.js');
523
+ const { catalog } = resolveConfig({ projectDir });
524
+ const framingHint = catalog.framing === "rest" && err2 instanceof CatalogHttpError && (err2.status === 404 || err2.status === 405) ? ` catalog.framing is rest; if this host serves tRPC, set it with \`skaile config set catalog.framing trpc\`.` : "";
525
+ return `${describeCatalogError(err2, catalog.url)}.${framingHint} Check the catalog with \`skaile catalog test\`.`;
526
+ }
483
527
  function makeSearchCommand() {
484
- return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind (a single non-kind argument is the query)").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").action(async (kind, query, opts) => {
528
+ return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind (a single non-kind argument is the query)").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").option(
529
+ "--all",
530
+ `Store leg: list every match (default: ${STORE_ROW_LIMIT} rows, only what add can install)`
531
+ ).action(async (kind, query, opts) => {
485
532
  await runSearch(kind, query, opts);
486
533
  });
487
534
  }
@@ -572,7 +619,10 @@ function makeAddCommand() {
572
619
  ).option(
573
620
  "--with-soft-deps",
574
621
  "also add the asset's report-only soft (body-link) deps, without prompting"
575
- ).option("--no-soft-deps", "skip the soft-dep prompt entirely (don't add, don't report)").action(async (ref, opts) => {
622
+ ).option("--no-soft-deps", "skip the soft-dep prompt entirely (don't add, don't report)").option(
623
+ "--force",
624
+ "overwrite a deployed folder that no lock entry owns (a hand-made skill of the same name)"
625
+ ).action(async (ref, opts) => {
576
626
  if (opts.withSoftDeps && opts.softDeps === false) {
577
627
  logErr("--with-soft-deps and --no-soft-deps are mutually exclusive.");
578
628
  process.exit(1);
@@ -580,13 +630,17 @@ function makeAddCommand() {
580
630
  const harnesses = parseHarnessFilter(opts.harness);
581
631
  if (!opts.global && harnesses === void 0) requireProjectConfig(opts.projectDir);
582
632
  const warnings = deferredWarnings();
633
+ const collisionKeys = [];
583
634
  const am2 = new AssetManager({
584
635
  registry: getKindRegistry(),
585
- projectDir: path18__default.resolve(opts.projectDir),
636
+ projectDir: path22__default.resolve(opts.projectDir),
586
637
  global: opts.global || harnesses !== void 0,
587
638
  harnesses,
588
639
  driverTarget: opts.target,
589
- onLibraryCollision: warnings.push
640
+ onLibraryCollision: (msg) => {
641
+ collisionKeys.push(msg.split(" exists in ")[0]);
642
+ warnings.push(msg);
643
+ }
590
644
  });
591
645
  const spinner = createSpinner();
592
646
  spinner.start(`Adding ${ref}`);
@@ -597,6 +651,7 @@ function makeAddCommand() {
597
651
  const skippedEnv = /* @__PURE__ */ new Set();
598
652
  const added = await am2.add(ref, {
599
653
  link: opts.link,
654
+ force: opts.force,
600
655
  onLibraryOrigin: (deployedRef, library) => libraryOf.set(deployedRef, library),
601
656
  onLibraryMoved: (m) => warnings.push(`${m.ref} moved from ${m.from} to ${m.to}`),
602
657
  onPresets: (expanded) => {
@@ -644,9 +699,27 @@ function makeAddCommand() {
644
699
  const library = libraryOf.get(a);
645
700
  logOk(library ? `${a} (library ${library})` : a);
646
701
  }
702
+ if (am2.global) {
703
+ for (const a of added) {
704
+ const { kind, name } = parseAssetRef(a);
705
+ const component = installTargetOf(getKindRegistry(), kind);
706
+ if (!component) continue;
707
+ for (const harness of am2.deployTargets()) {
708
+ const dir = deployedDir(component, name, harness, true);
709
+ if (existsSync(dir)) logInfo(S.dim(`${harness}: ${dir.replace(homedir(), "~")}`));
710
+ }
711
+ }
712
+ }
713
+ if (added.length > 1) {
714
+ logInfo(S.dim(`${added.length} assets deployed (${ref} and ${added.length - 1} more)`));
715
+ }
647
716
  }
648
717
  const addOrigins = await competingOriginsOf(am2, ref);
649
- if (addOrigins) {
718
+ const asked = parseRefTolerant(ref);
719
+ const alreadyWarned = collisionKeys.some(
720
+ (key) => key.startsWith(`${asked?.kind}:`) && key.endsWith(`/${asked?.name}`)
721
+ );
722
+ if (addOrigins && !alreadyWarned) {
650
723
  const [first, ...rest] = addOrigins;
651
724
  logInfo(
652
725
  S.dim(
@@ -673,7 +746,7 @@ function makeRemoveCommand() {
673
746
  requireProjectConfig(opts.projectDir, { allowMissing: true });
674
747
  const am2 = new AssetManager({
675
748
  registry: getKindRegistry(),
676
- projectDir: path18__default.resolve(opts.projectDir),
749
+ projectDir: path22__default.resolve(opts.projectDir),
677
750
  global: opts.global || harnesses !== void 0,
678
751
  harnesses,
679
752
  driverTarget: opts.target
@@ -735,15 +808,14 @@ function makeListCommand() {
735
808
  }
736
809
  const am2 = new AssetManager({
737
810
  registry: getKindRegistry(),
738
- projectDir: path18__default.resolve(opts.projectDir),
811
+ projectDir: path22__default.resolve(opts.projectDir),
739
812
  driverTarget: opts.target
740
813
  });
741
814
  let declared;
742
815
  try {
743
816
  declared = await am2.listDeclared(kind);
744
817
  } catch (err2) {
745
- if (err2 instanceof MissingManifestError)
746
- logErr(`No ${S.cmd("skaile.yaml")} found. Run ${S.cmd("skaile init")} to create one.`);
818
+ if (err2 instanceof MissingManifestError) logNoProject(opts.projectDir);
747
819
  else logErr(err2 instanceof Error ? err2.message : String(err2));
748
820
  process.exit(1);
749
821
  }
@@ -783,7 +855,7 @@ function makeListCommand() {
783
855
  function runGlobalList(kind, opts, harnesses) {
784
856
  const am2 = new AssetManager({
785
857
  registry: getKindRegistry(),
786
- projectDir: path18__default.resolve(opts.projectDir),
858
+ projectDir: path22__default.resolve(opts.projectDir),
787
859
  global: true,
788
860
  harnesses
789
861
  });
@@ -856,7 +928,7 @@ async function resolveInfoEntry(am2, ref, opts) {
856
928
  return { entry: match ?? deployed };
857
929
  }
858
930
  const lookup = opts.storeLookup ?? (async (filter) => {
859
- const { resolveCatalogSource } = await import('../open-library-BOSPJVID.js');
931
+ const { resolveCatalogSource } = await import('../open-library-PZAT3TJA.js');
860
932
  const { source, close } = await resolveCatalogSource({ projectDir: opts.projectDir });
861
933
  try {
862
934
  return await source.listAssets(filter);
@@ -872,7 +944,7 @@ async function resolveInfoEntry(am2, ref, opts) {
872
944
  );
873
945
  return { entry: hit ? catalogAssetToEntry(hit) : null };
874
946
  } catch (err2) {
875
- const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-BOSPJVID.js');
947
+ const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-PZAT3TJA.js');
876
948
  const storeNote = err2 instanceof Error ? err2.message : String(err2);
877
949
  const disabled = err2 instanceof LocalCatalogDisabledError2 || /catalog\.url/i.test(storeNote);
878
950
  return { entry: null, storeNote, ...disabled ? { storeDisabled: true } : {} };
@@ -888,7 +960,8 @@ function infoNotFoundHint(ref, lookup) {
888
960
  }
889
961
  function makeInfoCommand() {
890
962
  return new Command("info").description("Show asset metadata, deps, deploy status").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
891
- const projectDir = path18__default.resolve(opts.projectDir);
963
+ const projectDir = path22__default.resolve(opts.projectDir);
964
+ requireProjectConfig(projectDir, { allowMissing: true });
892
965
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
893
966
  const lookup = await resolveInfoEntry(am2, ref, { projectDir });
894
967
  const entry = lookup.entry;
@@ -937,7 +1010,7 @@ function makeCreateCommand() {
937
1010
  new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...SCAFFOLD_KINDS])
938
1011
  ).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
939
1012
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
940
- const destDir = opts.dir ? path18__default.resolve(opts.dir) : process.cwd();
1013
+ const destDir = opts.dir ? path22__default.resolve(opts.dir) : process.cwd();
941
1014
  const result = am2.create(name, opts.kind, destDir);
942
1015
  if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
943
1016
  else {
@@ -951,14 +1024,16 @@ function makeDoctorCommand() {
951
1024
  requireProjectConfig(opts.projectDir);
952
1025
  const am2 = new AssetManager({
953
1026
  registry: getKindRegistry(),
954
- projectDir: path18__default.resolve(opts.projectDir)
1027
+ projectDir: path22__default.resolve(opts.projectDir)
955
1028
  });
956
1029
  const { gaps } = await am2.projectState();
957
- if (gaps.length === 0) {
1030
+ const edited = await editedConventionFiles(path22__default.resolve(opts.projectDir));
1031
+ if (gaps.length === 0 && edited.length === 0) {
958
1032
  logOk("No missing dependencies.");
959
1033
  return;
960
1034
  }
961
1035
  process.exitCode = 1;
1036
+ for (const e of edited) logErr(e);
962
1037
  for (const g of gaps) if (g.type !== "requires") logErr(g.message);
963
1038
  const missing = gaps.filter((g) => g.type === "requires" && g.asset !== void 0);
964
1039
  if (missing.length === 0) return;
@@ -983,21 +1058,21 @@ function claudeSkillRoots() {
983
1058
  const roots = [];
984
1059
  const override = process.env.SKAILE_CLAUDE_SKILLS_DIR;
985
1060
  if (override) roots.push(override);
986
- roots.push(path18.join(os.homedir(), ".claude", "skills"));
1061
+ roots.push(path22.join(os.homedir(), ".claude", "skills"));
987
1062
  return roots;
988
1063
  }
989
1064
  function resolveImportSource(nameOrPath) {
990
- const asPath = path18.resolve(nameOrPath);
991
- if (fs8.existsSync(asPath)) {
992
- const dir = fs8.statSync(asPath).isDirectory() ? asPath : path18.dirname(asPath);
993
- const skillFile = path18.join(dir, "SKILL.md");
994
- if (fs8.existsSync(skillFile)) return { dir, skillFile, via: "path" };
1065
+ const asPath = path22.resolve(nameOrPath);
1066
+ if (fs9.existsSync(asPath)) {
1067
+ const dir = fs9.statSync(asPath).isDirectory() ? asPath : path22.dirname(asPath);
1068
+ const skillFile = path22.join(dir, "SKILL.md");
1069
+ if (fs9.existsSync(skillFile)) return { dir, skillFile, via: "path" };
995
1070
  }
996
- if (!nameOrPath.includes(path18.sep) && !nameOrPath.startsWith(".")) {
1071
+ if (!nameOrPath.includes(path22.sep) && !nameOrPath.startsWith(".")) {
997
1072
  for (const root of claudeSkillRoots()) {
998
- const dir = path18.join(root, nameOrPath);
999
- const skillFile = path18.join(dir, "SKILL.md");
1000
- if (fs8.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
1073
+ const dir = path22.join(root, nameOrPath);
1074
+ const skillFile = path22.join(dir, "SKILL.md");
1075
+ if (fs9.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
1001
1076
  }
1002
1077
  }
1003
1078
  return null;
@@ -1052,6 +1127,12 @@ ${body}
1052
1127
  }
1053
1128
 
1054
1129
  // cli/src/commands/asset-cmd.ts
1130
+ function copyFilter(root) {
1131
+ return (src) => {
1132
+ const rel = path22.relative(root, src).split(path22.sep).join("/");
1133
+ return rel === "" || !(isNonAssetPath(rel) || isNonAssetDir(path22.basename(src)));
1134
+ };
1135
+ }
1055
1136
  async function resolveDefByRef(library, ref, opts) {
1056
1137
  let parsed;
1057
1138
  try {
@@ -1124,19 +1205,25 @@ function makeAssetCommand() {
1124
1205
  process.exit(1);
1125
1206
  }
1126
1207
  exitOnManifestPublisherProblems(target.path, target.name);
1127
- const rawSkill = fs8.readFileSync(src.skillFile, "utf8");
1208
+ if (reportLibrarySymlinks(src.dir, { rootIsAsset: true }) > 0) {
1209
+ logErr(
1210
+ `Not imported: ${src.dir} holds symlinks (listed above). Replace each with a copy of what it points at, or remove it, and run the import again.`
1211
+ );
1212
+ process.exit(1);
1213
+ }
1214
+ const rawSkill = fs9.readFileSync(src.skillFile, "utf8");
1128
1215
  const norm = opts.normalize ? normalizeSkillContent(rawSkill, {
1129
- fallbackName: path18.basename(src.dir),
1216
+ fallbackName: path22.basename(src.dir),
1130
1217
  version: opts.version,
1131
1218
  stage: opts.stage
1132
- }) : { content: rawSkill, name: path18.basename(src.dir), changed: false, notes: [] };
1219
+ }) : { content: rawSkill, name: path22.basename(src.dir), changed: false, notes: [] };
1133
1220
  if (!opts.normalize && !isValidAssetName(norm.name)) {
1134
1221
  logWarn(
1135
1222
  `Name "${norm.name}" is not canonical (kebab-case); \`skaile validate\` will reject this manifest entry. Drop --no-normalize to slugify it.`
1136
1223
  );
1137
1224
  }
1138
- const destDir = path18.join(target.path, norm.name);
1139
- if (fs8.existsSync(destDir)) {
1225
+ const destDir = path22.join(target.path, norm.name);
1226
+ if (fs9.existsSync(destDir)) {
1140
1227
  logErr(`Destination already exists: ${destDir}`);
1141
1228
  process.exit(1);
1142
1229
  }
@@ -1147,8 +1234,27 @@ function makeAssetCommand() {
1147
1234
  );
1148
1235
  process.exit(1);
1149
1236
  }
1150
- fs8.cpSync(src.dir, destDir, { recursive: true });
1151
- fs8.writeFileSync(path18.join(destDir, "SKILL.md"), norm.content, "utf8");
1237
+ const importedFm = parseFrontmatter(norm.content);
1238
+ const checked = checkAsset(
1239
+ "skill",
1240
+ importedFm.data,
1241
+ importedFm.body,
1242
+ norm.name,
1243
+ getKindRegistry(),
1244
+ norm.content
1245
+ );
1246
+ if (checked.errors.length > 0) {
1247
+ for (const f of checked.errors) logErr(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
1248
+ logErr(
1249
+ `Not imported: ${checked.errors.length} problem(s) in SKILL.md. Fix them in ${src.skillFile} (or drop --no-normalize) and run the import again.`
1250
+ );
1251
+ process.exit(1);
1252
+ }
1253
+ for (const f of checked.advisories) {
1254
+ logWarn(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
1255
+ }
1256
+ fs9.cpSync(src.dir, destDir, { recursive: true, filter: copyFilter(src.dir) });
1257
+ fs9.writeFileSync(path22.join(destDir, "SKILL.md"), norm.content, "utf8");
1152
1258
  for (const note of norm.notes) logInfo(` \u2022 ${note}`);
1153
1259
  const fm = parseFrontmatter(norm.content).data;
1154
1260
  for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
@@ -1188,7 +1294,7 @@ function makeAssetCommand() {
1188
1294
  logErr(`Invalid --mode "${opts.mode}". Expected: copy | move | link.`);
1189
1295
  process.exit(1);
1190
1296
  }
1191
- if (!fs8.existsSync(srcPath)) {
1297
+ if (!fs9.existsSync(srcPath)) {
1192
1298
  logErr(`Source path does not exist: ${srcPath}`);
1193
1299
  process.exit(1);
1194
1300
  }
@@ -1214,23 +1320,29 @@ function makeAssetCommand() {
1214
1320
  );
1215
1321
  process.exit(1);
1216
1322
  }
1217
- const basename3 = path18.basename(srcPath);
1323
+ const basename3 = path22.basename(srcPath);
1218
1324
  const destDir = target.path;
1219
- fs8.mkdirSync(destDir, { recursive: true });
1220
- const destPath = path18.join(destDir, basename3);
1221
- if (fs8.existsSync(destPath)) {
1325
+ fs9.mkdirSync(destDir, { recursive: true });
1326
+ const destPath = path22.join(destDir, basename3);
1327
+ if (fs9.existsSync(destPath)) {
1222
1328
  logErr(`Destination already exists: ${destPath}`);
1223
1329
  process.exit(1);
1224
1330
  }
1331
+ if (opts.mode === "copy" && reportLibrarySymlinks(srcPath, { rootIsAsset: true }) > 0) {
1332
+ logErr(
1333
+ `Not migrated: ${srcPath} holds symlinks (listed above). Replace each with a copy of what it points at, or remove it, and run the migrate again.`
1334
+ );
1335
+ process.exit(1);
1336
+ }
1225
1337
  switch (opts.mode) {
1226
1338
  case "copy":
1227
- fs8.cpSync(srcPath, destPath, { recursive: true });
1339
+ fs9.cpSync(srcPath, destPath, { recursive: true, filter: copyFilter(srcPath) });
1228
1340
  break;
1229
1341
  case "move":
1230
- fs8.renameSync(srcPath, destPath);
1342
+ fs9.renameSync(srcPath, destPath);
1231
1343
  break;
1232
1344
  case "link":
1233
- fs8.symlinkSync(path18.resolve(srcPath), destPath);
1345
+ fs9.symlinkSync(path22.resolve(srcPath), destPath);
1234
1346
  break;
1235
1347
  }
1236
1348
  if (target.backend === "git" && opts.commit) {
@@ -1245,6 +1357,11 @@ function makeAssetCommand() {
1245
1357
  }
1246
1358
  }
1247
1359
  logOk(`Migrated ${basename3} \u2192 ${target.name} (${opts.mode})`);
1360
+ const publisher = loadSkPublishManifest(target.path)?.publisher ?? "<publisher>";
1361
+ const migratedKind = fs9.existsSync(path22.join(destPath, "SKILL.md")) ? "skill" : "<kind>";
1362
+ logInfo(
1363
+ `Not addable yet: run ${S.cmd(`skaile library index ${target.name}`)}, then ${S.cmd(`skaile add ${migratedKind}:@${publisher.replace(/^@/, "")}/${basename3}`)}`
1364
+ );
1248
1365
  if (opts.mode === "move") {
1249
1366
  logInfo("Source moved into the library \u2014 future edits modify the library copy.");
1250
1367
  } else if (opts.mode === "copy") {
@@ -1360,14 +1477,14 @@ function makeAuthCommand() {
1360
1477
  }
1361
1478
  function collectCacheTargets(scope) {
1362
1479
  const out = [];
1363
- out.push(path18__default.join(scope.projectDir, ".skaile", "cache"));
1364
- out.push(path18__default.join(scope.projectDir, ".skaile", "store-cache"));
1365
- out.push(path18__default.join(scope.projectDir, ".skaile", "repos"));
1480
+ out.push(path22__default.join(scope.projectDir, ".skaile", "cache"));
1481
+ out.push(path22__default.join(scope.projectDir, ".skaile", "store-cache"));
1482
+ out.push(path22__default.join(scope.projectDir, ".skaile", "repos"));
1366
1483
  if (scope.global) {
1367
1484
  out.push(globalCacheRoot());
1368
1485
  const home = globalSkaileDir();
1369
- out.push(path18__default.join(home, "repos"));
1370
- out.push(path18__default.join(home, "catalog-cache"));
1486
+ out.push(path22__default.join(home, "repos"));
1487
+ out.push(path22__default.join(home, "catalog-cache"));
1371
1488
  }
1372
1489
  return out;
1373
1490
  }
@@ -1381,7 +1498,7 @@ function dirSize(target) {
1381
1498
  function dirSizeOfDir(dir) {
1382
1499
  let total = 0;
1383
1500
  for (const ent of readdirSync(dir, { withFileTypes: true })) {
1384
- const child = path18__default.join(dir, ent.name);
1501
+ const child = path22__default.join(dir, ent.name);
1385
1502
  if (ent.isSymbolicLink()) continue;
1386
1503
  if (ent.isDirectory()) total += dirSizeOfDir(child);
1387
1504
  else if (ent.isFile()) total += statSync(child).size;
@@ -1407,7 +1524,7 @@ function makeCacheCommand() {
1407
1524
  const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
1408
1525
  cmd.command("clean").description("Remove the project cache (.skaile/cache); --global also clears ~/.skaile/cache").option("--global", "Also clear the global cache (sources + catalog) and legacy dirs").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
1409
1526
  const targets = collectCacheTargets({
1410
- projectDir: path18__default.resolve(opts.projectDir),
1527
+ projectDir: path22__default.resolve(opts.projectDir),
1411
1528
  global: opts.global
1412
1529
  }).filter((t) => existsSync(t));
1413
1530
  if (targets.length === 0) {
@@ -1437,12 +1554,12 @@ function makeCacheCommand() {
1437
1554
  for (const r of removed) logOk(`Removed ${r}`);
1438
1555
  });
1439
1556
  cmd.command("dir").description("Print the resolved cache roots").option("--global", "Include the global cache root").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
1440
- console.log(path18__default.join(path18__default.resolve(opts.projectDir), ".skaile", "cache"));
1557
+ console.log(path22__default.join(path22__default.resolve(opts.projectDir), ".skaile", "cache"));
1441
1558
  if (opts.global) console.log(globalCacheRoot());
1442
1559
  });
1443
1560
  cmd.command("size").description("Show cache disk usage per directory").option("--global", "Include the global cache").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
1444
1561
  const targets = collectCacheTargets({
1445
- projectDir: path18__default.resolve(opts.projectDir),
1562
+ projectDir: path22__default.resolve(opts.projectDir),
1446
1563
  global: opts.global
1447
1564
  });
1448
1565
  console.log();
@@ -1458,7 +1575,7 @@ function makeCatalogCommand() {
1458
1575
  const catalog = new Command("catalog").description("Catalog source health and configuration");
1459
1576
  catalog.command("test").description("Probe the configured catalog source and report status").option("--project-dir <path>", "Project directory (for project-level config overlay)").option("--url <url>", "Override the catalog URL for this probe").option("--force", "Probe the network even in air-gapped mode (cache_ttl: 0)").action(async (opts) => {
1460
1577
  const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
1461
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : void 0;
1578
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : void 0;
1462
1579
  const cfg = resolveConfig({ projectDir });
1463
1580
  const baseUrl = opts.url ?? cfg.catalog.url;
1464
1581
  if (isLocalCatalogUrl(baseUrl)) {
@@ -1472,11 +1589,15 @@ function makeCatalogCommand() {
1472
1589
  );
1473
1590
  return;
1474
1591
  }
1475
- await runRemoteCatalogProbe(baseUrl, trpcGetUrl(baseUrl, "catalog.listKinds", void 0));
1592
+ await runRemoteCatalogProbe(
1593
+ baseUrl,
1594
+ cfg.catalog.framing,
1595
+ trpcGetUrl(baseUrl, "catalog.listKinds", void 0)
1596
+ );
1476
1597
  });
1477
1598
  catalog.command("info").description("Print the resolved catalog configuration (url, framing, cacheTtlMs)").option("--project-dir <path>", "Project directory (for project-level config overlay)").action(async (opts) => {
1478
1599
  const { resolveConfig } = await import('../library/index.js');
1479
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : void 0;
1600
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : void 0;
1480
1601
  const cfg = resolveConfig({ projectDir });
1481
1602
  console.log(`url: ${cfg.catalog.url}`);
1482
1603
  console.log(`framing: ${cfg.catalog.framing}`);
@@ -1485,14 +1606,16 @@ function makeCatalogCommand() {
1485
1606
  return catalog;
1486
1607
  }
1487
1608
  async function runLocalCatalogTest(projectDir) {
1488
- const { resolveCatalogSource } = await import('../open-library-BOSPJVID.js');
1609
+ const { resolveCatalogSource } = await import('../open-library-PZAT3TJA.js');
1489
1610
  let resolved;
1490
1611
  try {
1491
1612
  resolved = await resolveCatalogSource({ projectDir });
1492
1613
  const sources = await resolved.source.listSources();
1493
1614
  logOk("Catalog mode: local");
1494
1615
  if (sources.length === 0) {
1495
- logInfo("No local sources registered. Run `skaile source add <path>` first.");
1616
+ logInfo(
1617
+ "No local sources registered. Run `skaile library init <name> --path <dir>` first (a git repo: `skaile source add <git-url>`)."
1618
+ );
1496
1619
  } else {
1497
1620
  for (const s of sources) {
1498
1621
  console.log(` ${S.dim("\u2022")} ${s.type} ${S.heading(s.url)}`);
@@ -1513,7 +1636,8 @@ function isTrpcEnvelope(text) {
1513
1636
  return false;
1514
1637
  }
1515
1638
  }
1516
- async function runRemoteCatalogProbe(baseUrl, probeUrl) {
1639
+ async function runRemoteCatalogProbe(baseUrl, framing, trpcProbeUrl) {
1640
+ const probeUrl = framing === "rest" ? `${baseUrl.replace(/\/+$/, "")}/api/catalog/list` : trpcProbeUrl;
1517
1641
  const controller = new AbortController();
1518
1642
  const timeout = setTimeout(() => controller.abort(), 5e3);
1519
1643
  try {
@@ -1524,10 +1648,24 @@ async function runRemoteCatalogProbe(baseUrl, probeUrl) {
1524
1648
  });
1525
1649
  const ms = Date.now() - started;
1526
1650
  if (!res.ok) {
1651
+ if (framing === "rest" && (res.status === 404 || res.status === 405)) {
1652
+ const trpc = await fetch(trpcProbeUrl, {
1653
+ signal: controller.signal,
1654
+ headers: { accept: "application/json" }
1655
+ }).catch(() => null);
1656
+ if (trpc?.ok && isTrpcEnvelope((await trpc.text()).trim())) {
1657
+ logErr(
1658
+ `${baseUrl} serves the tRPC catalog, but catalog.framing is rest (${probeUrl} answered ${res.status}).`
1659
+ );
1660
+ logInfo(`Set it with: skaile config set catalog.framing trpc`);
1661
+ process.exitCode = 1;
1662
+ return;
1663
+ }
1664
+ }
1527
1665
  logErr(`${probeUrl} responded ${res.status} ${res.statusText} (${ms}ms)`);
1528
1666
  if (res.status === 404) {
1529
1667
  logInfo(
1530
- `Got 404 from catalog.listKinds. Check the URL prefix in ${userConfigPath()} \u2014 Skaile mirrors must expose \`/trpc/catalog.*\` at the configured baseUrl.`
1668
+ framing === "rest" ? `Got 404 from /api/catalog/list (catalog.framing is rest). Check the URL prefix in ${userConfigPath()}.` : `Got 404 from catalog.listKinds. Check the URL prefix in ${userConfigPath()} \u2014 Skaile mirrors must expose \`/trpc/catalog.*\` at the configured baseUrl.`
1531
1669
  );
1532
1670
  } else {
1533
1671
  logInfo(
@@ -1538,17 +1676,27 @@ async function runRemoteCatalogProbe(baseUrl, probeUrl) {
1538
1676
  return;
1539
1677
  }
1540
1678
  const text = (await res.text()).trim();
1541
- if (!isTrpcEnvelope(text)) {
1542
- logWarn(
1543
- `Catalog reachable at ${baseUrl} (${ms}ms) but the response is not a valid tRPC envelope.`
1544
- );
1545
- logInfo(
1546
- "The host responded 200 but the body is not Skaile's catalog router shape. Check that `catalog.listKinds` is mounted at the configured baseUrl."
1547
- );
1548
- process.exitCode = 1;
1549
- return;
1679
+ if (framing === "trpc") {
1680
+ if (!isTrpcEnvelope(text)) {
1681
+ logWarn(
1682
+ `Catalog reachable at ${baseUrl} (${ms}ms) but the response is not a valid tRPC envelope.`
1683
+ );
1684
+ logInfo(
1685
+ "The host responded 200 but the body is not Skaile's catalog router shape. Check that `catalog.listKinds` is mounted at the configured baseUrl."
1686
+ );
1687
+ process.exitCode = 1;
1688
+ return;
1689
+ }
1690
+ } else {
1691
+ try {
1692
+ JSON.parse(text);
1693
+ } catch {
1694
+ logWarn(`Catalog reachable at ${baseUrl} (${ms}ms) but /api/catalog/list is not JSON.`);
1695
+ process.exitCode = 1;
1696
+ return;
1697
+ }
1550
1698
  }
1551
- logOk(`Catalog reachable at ${S.heading(baseUrl)} (${ms}ms)`);
1699
+ logOk(`Catalog reachable at ${S.heading(baseUrl)} (${ms}ms, framing ${framing})`);
1552
1700
  } catch (err2) {
1553
1701
  if (err2 instanceof Error && err2.name === "AbortError") {
1554
1702
  logErr(`Timeout reaching ${probeUrl} after 5s`);
@@ -1628,7 +1776,7 @@ async function scanLibraryFlowEntries() {
1628
1776
  const { LocalIndex, resolveIndexPath, scanAuthoringLibraries } = await import('../library/index.js');
1629
1777
  const indexPath = resolveIndexPath();
1630
1778
  if (!existsSync(indexPath)) return entries;
1631
- const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-4FI7HKET.js');
1779
+ const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-W46UXZ3I.js');
1632
1780
  const index = new LocalIndex({ indexPath });
1633
1781
  try {
1634
1782
  for (const { assets } of await scanAuthoringLibraries(index, getKindRegistry2())) {
@@ -1678,11 +1826,11 @@ function findSkills() {
1678
1826
  return deduped;
1679
1827
  }
1680
1828
  function walkSkills(dir, out) {
1681
- for (const entry of fs8__default.readdirSync(dir, { withFileTypes: true })) {
1682
- const full = path18__default.join(dir, entry.name);
1829
+ for (const entry of fs9__default.readdirSync(dir, { withFileTypes: true })) {
1830
+ const full = path22__default.join(dir, entry.name);
1683
1831
  if (entry.isDirectory()) {
1684
- const skillMd = path18__default.join(full, "SKILL.md");
1685
- if (fs8__default.existsSync(skillMd)) {
1832
+ const skillMd = path22__default.join(full, "SKILL.md");
1833
+ if (fs9__default.existsSync(skillMd)) {
1686
1834
  out.push({ name: entry.name, path: full, skillPath: skillMd });
1687
1835
  } else {
1688
1836
  walkSkills(full, out);
@@ -1703,10 +1851,10 @@ function resolveFlowIds() {
1703
1851
  }
1704
1852
  }
1705
1853
  function resolveSessionIds(projectDir) {
1706
- const sessionsDir = path18__default.join(projectDir, ".skaile", "sessions");
1707
- if (!fs8__default.existsSync(sessionsDir)) return [];
1854
+ const sessionsDir = path22__default.join(projectDir, ".skaile", "sessions");
1855
+ if (!fs9__default.existsSync(sessionsDir)) return [];
1708
1856
  try {
1709
- return fs8__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
1857
+ return fs9__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
1710
1858
  } catch {
1711
1859
  return [];
1712
1860
  }
@@ -1759,6 +1907,33 @@ function resolveDynamic(words, cword) {
1759
1907
  return null;
1760
1908
  }
1761
1909
  var PERSONAL_KEYS = /* @__PURE__ */ new Set(["driver", "model"]);
1910
+ var CATALOG_KEYS = /* @__PURE__ */ new Set(["catalog.url", "catalog.cache_ttl", "catalog.framing"]);
1911
+ async function setCatalogKey(key, raw) {
1912
+ const { CatalogConfigSchema, saveConfig } = await import('../library/index.js');
1913
+ const { parse: parseYaml5 } = await import('yaml');
1914
+ const field = key.slice("catalog.".length);
1915
+ const value = field === "cache_ttl" ? /^\d+$/.test(raw.trim()) ? Number(raw) : raw : raw;
1916
+ const checked = CatalogConfigSchema.safeParse({ [field]: value });
1917
+ if (!checked.success) {
1918
+ const hint = field === "url" ? 'a http(s) URL, or "local" to turn the remote catalog off' : field === "cache_ttl" ? "a whole number of seconds (0 = air-gapped)" : '"trpc" or "rest"';
1919
+ logErr(`'${key}' must be ${hint}; got "${raw}".`);
1920
+ process.exit(1);
1921
+ }
1922
+ const filePath = userConfigPath();
1923
+ const fs14 = await import('fs');
1924
+ let existing = {};
1925
+ if (fs14.existsSync(filePath)) {
1926
+ const parsed = parseYaml5(fs14.readFileSync(filePath, "utf-8"));
1927
+ if (parsed && typeof parsed === "object") existing = parsed;
1928
+ }
1929
+ const catalog = {
1930
+ ...existing.catalog ?? {},
1931
+ [field]: checked.data[field]
1932
+ };
1933
+ saveConfig(filePath, { ...existing, catalog });
1934
+ logOk(`Set ${pc5.bold(key)} = ${String(checked.data[field])}`);
1935
+ console.log(S.dim(` \u2192 ${filePath}`));
1936
+ }
1762
1937
  var API_KEY_PREFIX = "apiKey.";
1763
1938
  function collectWorkspaceDefaults(projectDir) {
1764
1939
  const wsDefaults = {};
@@ -1774,14 +1949,17 @@ function collectWorkspaceDefaults(projectDir) {
1774
1949
  }
1775
1950
  return wsDefaults;
1776
1951
  }
1777
- function printEffectiveSection(config) {
1952
+ function printEffectiveSection(config, sources) {
1778
1953
  console.log();
1779
1954
  console.log(S.heading(" Effective Config"));
1780
1955
  console.log(` ${S.rule(40)}`);
1781
1956
  for (const key of ["driver", "model"]) {
1782
1957
  const value = config[key];
1783
1958
  if (value !== void 0) {
1784
- console.log(` ${S.label(`${key}:`.padEnd(16))} ${value}`);
1959
+ const origin = sources[key];
1960
+ console.log(
1961
+ ` ${S.label(`${key}:`.padEnd(16))} ${value}${origin ? ` ${S.dim(`(${origin})`)}` : ""}`
1962
+ );
1785
1963
  }
1786
1964
  }
1787
1965
  }
@@ -1845,17 +2023,18 @@ function printResolvedPathsSection(config) {
1845
2023
  console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
1846
2024
  }
1847
2025
  async function showConfig(opts) {
1848
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2026
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
1849
2027
  let config;
2028
+ let sources;
1850
2029
  let wsDefaults;
1851
2030
  try {
1852
- config = await resolveSettings(projectDir);
2031
+ ({ settings: config, sources } = await resolveSettingsWithSources(projectDir));
1853
2032
  wsDefaults = collectWorkspaceDefaults(projectDir);
1854
2033
  } catch (error) {
1855
2034
  logErr(error instanceof Error ? error.message : String(error));
1856
2035
  process.exit(1);
1857
2036
  }
1858
- printEffectiveSection(config);
2037
+ printEffectiveSection(config, sources);
1859
2038
  printWorkspaceDefaultsSection(wsDefaults);
1860
2039
  printModelSelectionSection(config, projectDir);
1861
2040
  printResolvedPathsSection(config);
@@ -1890,13 +2069,25 @@ function makeConfigCommand() {
1890
2069
  const cmd = new Command("config").description("Manage personal config (.skaile/settings.json)");
1891
2070
  cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
1892
2071
  cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").action(async (key, opts) => {
1893
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2072
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
2073
+ if (CATALOG_KEYS.has(key)) {
2074
+ const { resolveConfig } = await import('../library/index.js');
2075
+ const field = key.slice("catalog.".length);
2076
+ console.log(resolveConfig({ projectDir }).catalog[field]);
2077
+ return;
2078
+ }
1894
2079
  const config = await resolveSettings(projectDir);
1895
2080
  const value = config[key];
1896
2081
  console.log(value ?? S.dim("(not set)"));
1897
2082
  });
1898
- cmd.command("set <key> <value>").description("Set a personal config value (driver, model, apiKey.<provider>)").option("--project-dir <path>", "Project directory").option("--global", "Write to ~/.skaile/settings.json instead of project-local").action(async (key, value, opts) => {
1899
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2083
+ cmd.command("set <key> <value>").description(
2084
+ "Set a personal config value (driver, model, apiKey.<provider>) or a catalog setting (catalog.url, catalog.cache_ttl, catalog.framing)"
2085
+ ).option("--project-dir <path>", "Project directory").option("--global", "Write to ~/.skaile/settings.json instead of project-local").action(async (key, value, opts) => {
2086
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
2087
+ if (CATALOG_KEYS.has(key)) {
2088
+ await setCatalogKey(key, value);
2089
+ return;
2090
+ }
1900
2091
  if (key === "provider" || key === "cloud" || key === "cloudConfig") {
1901
2092
  logErr(
1902
2093
  `'${key}' is no longer a setting \u2014 an endpoint is an AI provider registry entry and a session selects one with a model reference.
@@ -1923,6 +2114,14 @@ function makeConfigCommand() {
1923
2114
  await saveSettings({ ...existing, [key]: value }, filePath);
1924
2115
  logOk(`Set ${pc5.bold(key)} = ${value}`);
1925
2116
  console.log(S.dim(` \u2192 ${filePath}`));
2117
+ if (key === "driver") {
2118
+ const projectDriver = resolveSkWorkspaceConfig(projectDir).agent_config?.default?.driver;
2119
+ if (projectDriver && projectDriver !== value) {
2120
+ logWarn(
2121
+ `skaile.yaml sets driver ${projectDriver}; a personal driver does not override the project harness. Change agent-config.default.driver in skaile.yaml to move the project.`
2122
+ );
2123
+ }
2124
+ }
1926
2125
  if (key === "model") {
1927
2126
  const view = loadRegistryView({ projectDir });
1928
2127
  const resolved = parseModelRef(value, view.merged);
@@ -2236,8 +2435,8 @@ function makeConnectorCommand() {
2236
2435
  async (driver, opts) => {
2237
2436
  const { installNpmPackages } = await import('../connectors/index.js');
2238
2437
  const { scanDirectory: scanDirectory2, factoryAssetRoots: factoryAssetRoots2, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
2239
- const projectDir = path18__default.resolve(opts.projectDir);
2240
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
2438
+ const projectDir = path22__default.resolve(opts.projectDir);
2439
+ const yamlPath = path22__default.join(projectDir, "skaile.yaml");
2241
2440
  if (!existsSync(yamlPath)) {
2242
2441
  logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
2243
2442
  process.exit(1);
@@ -2297,8 +2496,8 @@ ${installResult.output}`);
2297
2496
  );
2298
2497
  cmd.command("remove <id>").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Remove a connector from skaile.yaml by its instance ID").action(async (id, opts) => {
2299
2498
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
2300
- const projectDir = path18__default.resolve(opts.projectDir);
2301
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
2499
+ const projectDir = path22__default.resolve(opts.projectDir);
2500
+ const yamlPath = path22__default.join(projectDir, "skaile.yaml");
2302
2501
  if (!existsSync(yamlPath)) {
2303
2502
  logErr("No skaile.yaml found in current directory.");
2304
2503
  process.exit(1);
@@ -2315,7 +2514,7 @@ ${installResult.output}`);
2315
2514
  cmd.command("status [id]").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Connect and report health status for one or all connectors").action(async (id, opts) => {
2316
2515
  const res = await import('../connectors/index.js');
2317
2516
  res.registerBuiltinConnectors();
2318
- const projectDir = path18__default.resolve(opts.projectDir);
2517
+ const projectDir = path22__default.resolve(opts.projectDir);
2319
2518
  const declarations = res.loadConnectorDeclarations(projectDir);
2320
2519
  if (declarations.length === 0) {
2321
2520
  console.log("No connectors configured in skaile.yaml.");
@@ -2339,7 +2538,7 @@ ${installResult.output}`);
2339
2538
  await manager.disconnectAll();
2340
2539
  });
2341
2540
  cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
2342
- const projectDir = path18__default.resolve(opts.projectDir);
2541
+ const projectDir = path22__default.resolve(opts.projectDir);
2343
2542
  const manager = await connectConnectors(projectDir);
2344
2543
  try {
2345
2544
  console.log(JSON.stringify(manager.listConnectors(), null, 2));
@@ -2348,7 +2547,7 @@ ${installResult.output}`);
2348
2547
  }
2349
2548
  });
2350
2549
  cmd.command("sync [id]").description("Re-sync a filesystem-face connector or all of them (git pull, S3 refresh, etc.)").option("--all", "Sync all connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
2351
- const projectDir = path18__default.resolve(opts.projectDir);
2550
+ const projectDir = path22__default.resolve(opts.projectDir);
2352
2551
  const manager = await connectConnectors(projectDir);
2353
2552
  try {
2354
2553
  if (opts.all) {
@@ -2372,7 +2571,7 @@ ${installResult.output}`);
2372
2571
  }
2373
2572
  });
2374
2573
  cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
2375
- const projectDir = path18__default.resolve(opts.projectDir);
2574
+ const projectDir = path22__default.resolve(opts.projectDir);
2376
2575
  const manager = await connectConnectors(projectDir);
2377
2576
  try {
2378
2577
  if (!manager.has(id)) {
@@ -2387,7 +2586,7 @@ ${installResult.output}`);
2387
2586
  }
2388
2587
  });
2389
2588
  cmd.command("read <id> <resource-path>").description("Read content from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
2390
- const projectDir = path18__default.resolve(opts.projectDir);
2589
+ const projectDir = path22__default.resolve(opts.projectDir);
2391
2590
  const manager = await connectConnectors(projectDir);
2392
2591
  try {
2393
2592
  const content = await manager.read(id, resourcePath);
@@ -2397,7 +2596,7 @@ ${installResult.output}`);
2397
2596
  }
2398
2597
  });
2399
2598
  cmd.command("write <id> <resource-path> <content>").description("Write content to a connector at a path").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, content, opts) => {
2400
- const projectDir = path18__default.resolve(opts.projectDir);
2599
+ const projectDir = path22__default.resolve(opts.projectDir);
2401
2600
  const manager = await connectConnectors(projectDir);
2402
2601
  try {
2403
2602
  await manager.write(id, resourcePath, { data: content });
@@ -2407,7 +2606,7 @@ ${installResult.output}`);
2407
2606
  }
2408
2607
  });
2409
2608
  cmd.command("entries <id> [resource-path]").description("List entries in a connector (files, keys, rows, etc)").option("--project-dir <path>", "Workspace directory", process.cwd()).option("--recursive", "Include nested entries").option("--limit <n>", "Maximum entries to return", parsePositiveIntOption).action(async (id, resourcePath, opts) => {
2410
- const projectDir = path18__default.resolve(opts.projectDir);
2609
+ const projectDir = path22__default.resolve(opts.projectDir);
2411
2610
  const manager = await connectConnectors(projectDir);
2412
2611
  try {
2413
2612
  const entries = await manager.list(id, resourcePath, {
@@ -2420,7 +2619,7 @@ ${installResult.output}`);
2420
2619
  }
2421
2620
  });
2422
2621
  cmd.command("search <id> <query>").description("Search within a connector for matching content").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, query, opts) => {
2423
- const projectDir = path18__default.resolve(opts.projectDir);
2622
+ const projectDir = path22__default.resolve(opts.projectDir);
2424
2623
  const manager = await connectConnectors(projectDir);
2425
2624
  try {
2426
2625
  const results = await manager.search(id, query);
@@ -2430,7 +2629,7 @@ ${installResult.output}`);
2430
2629
  }
2431
2630
  });
2432
2631
  cmd.command("delete <id> <resource-path>").description("Delete an entry from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
2433
- const projectDir = path18__default.resolve(opts.projectDir);
2632
+ const projectDir = path22__default.resolve(opts.projectDir);
2434
2633
  const manager = await connectConnectors(projectDir);
2435
2634
  try {
2436
2635
  const ok = await manager.delete(id, resourcePath);
@@ -2440,7 +2639,7 @@ ${installResult.output}`);
2440
2639
  }
2441
2640
  });
2442
2641
  cmd.command("run <id> <op> [args...]").description("Run a custom adapter operation (e.g. git log, sqlite query)").option("--project-dir <path>", "Workspace directory", process.cwd()).allowUnknownOption().action(async (id, op, args, opts) => {
2443
- const projectDir = path18__default.resolve(opts.projectDir);
2642
+ const projectDir = path22__default.resolve(opts.projectDir);
2444
2643
  const manager = await connectConnectors(projectDir);
2445
2644
  try {
2446
2645
  if (!manager.has(id)) {
@@ -2549,7 +2748,7 @@ function envRecord() {
2549
2748
  async function buildDeployContext(projectDir) {
2550
2749
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2551
2750
  const config = resolveSkWorkspaceConfig2(projectDir);
2552
- const workspaceId = config.name ?? path18__default.basename(projectDir);
2751
+ const workspaceId = config.name ?? path22__default.basename(projectDir);
2553
2752
  let log;
2554
2753
  try {
2555
2754
  const { createLogger } = await import('../core/logging.js');
@@ -2581,13 +2780,13 @@ async function ensureTargetsRegistered(projectDir) {
2581
2780
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2582
2781
  const config = resolveSkWorkspaceConfig2(projectDir);
2583
2782
  if (config.plugins && config.plugins.length > 0) {
2584
- const { ensurePluginsLoaded } = await import('../plugin-store-AGQDMING.js');
2783
+ const { ensurePluginsLoaded } = await import('../plugin-store-CK7YWRIC.js');
2585
2784
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
2586
2785
  for (const f of result.failed) logWarn(f.error);
2587
2786
  }
2588
2787
  }
2589
2788
  async function runUp(opts) {
2590
- const projectDir = path18__default.resolve(opts.projectDir);
2789
+ const projectDir = path22__default.resolve(opts.projectDir);
2591
2790
  await ensureTargetsRegistered(projectDir);
2592
2791
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2593
2792
  const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
@@ -2655,7 +2854,7 @@ async function restoreFromHandle(projectDir) {
2655
2854
  return { target, handle, ctx };
2656
2855
  }
2657
2856
  async function runDown(opts) {
2658
- const projectDir = path18__default.resolve(opts.projectDir);
2857
+ const projectDir = path22__default.resolve(opts.projectDir);
2659
2858
  const restored = await restoreFromHandle(projectDir);
2660
2859
  if (!restored) return;
2661
2860
  await restored.handle.stop();
@@ -2664,7 +2863,7 @@ async function runDown(opts) {
2664
2863
  logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
2665
2864
  }
2666
2865
  async function runStatus(opts) {
2667
- const projectDir = path18__default.resolve(opts.projectDir);
2866
+ const projectDir = path22__default.resolve(opts.projectDir);
2668
2867
  const restored = await restoreFromHandle(projectDir);
2669
2868
  if (!restored) return;
2670
2869
  const health = await restored.handle.health();
@@ -2678,7 +2877,7 @@ async function runStatus(opts) {
2678
2877
  console.log();
2679
2878
  }
2680
2879
  async function runLogs(opts) {
2681
- const projectDir = path18__default.resolve(opts.projectDir);
2880
+ const projectDir = path22__default.resolve(opts.projectDir);
2682
2881
  const restored = await restoreFromHandle(projectDir);
2683
2882
  if (!restored) return;
2684
2883
  if (!restored.handle.logs) {
@@ -2706,12 +2905,28 @@ function makeDiffCommand() {
2706
2905
  requireProjectConfig(opts.projectDir);
2707
2906
  const am2 = new AssetManager({
2708
2907
  registry: getKindRegistry(),
2709
- projectDir: path18__default.resolve(opts.projectDir)
2908
+ projectDir: path22__default.resolve(opts.projectDir)
2710
2909
  });
2910
+ try {
2911
+ parseAssetRef(ref);
2912
+ } catch (err2) {
2913
+ const plain = (err2 instanceof Error ? err2.message : String(err2)).replace(
2914
+ / Run the `migrate-skaile-manifest`.*$/,
2915
+ ""
2916
+ );
2917
+ const bare = /^([^:@/]+):([^@/#]+)$/.exec(ref.trim());
2918
+ const held = plain.startsWith("publisher required") && bare ? am2.lockedRefsNamed(bare[1], bare[2]) : [];
2919
+ if (held.length !== 1) {
2920
+ logErr(held.length > 1 ? `${plain} (locked: ${held.join(", ")})` : plain);
2921
+ process.exitCode = 1;
2922
+ return;
2923
+ }
2924
+ }
2711
2925
  const gaps = await am2.gapsOf(ref);
2926
+ const requirementGaps = await am2.requirementGapsOf(ref);
2712
2927
  const blocking = gaps.filter((g) => !DIFF_SHOWS[g.type]);
2713
2928
  if (blocking.length > 0) {
2714
- for (const g of blocking) logErr(g.message);
2929
+ for (const g of [...blocking, ...requirementGaps]) logErr(g.message);
2715
2930
  process.exitCode = 1;
2716
2931
  return;
2717
2932
  }
@@ -2724,27 +2939,33 @@ function makeDiffCommand() {
2724
2939
  if (problems.length === 0) logErr(`Asset not found: ${ref}`);
2725
2940
  break;
2726
2941
  case "not-deployed":
2727
- if (problems.length === 0) logWarn(`${ref} is not deployed \u2014 run skaile install`);
2942
+ if (problems.length === 0) {
2943
+ logErr(
2944
+ `${ref} is not deployed \u2014 nothing in this project locks it; run skaile add ${ref}`
2945
+ );
2946
+ process.exitCode = 1;
2947
+ }
2728
2948
  break;
2729
2949
  case "no-files":
2730
- if (problems.length === 0)
2950
+ if (problems.length === 0 && requirementGaps.length === 0)
2731
2951
  logInfo(`${ref}: preset has no files of its own; run skaile diff on its items`);
2732
2952
  break;
2733
2953
  case "identical":
2734
- if (problems.length === 0) logInfo("No differences.");
2954
+ if (problems.length === 0 && requirementGaps.length === 0) logInfo("No differences.");
2735
2955
  break;
2736
2956
  case "differs":
2737
2957
  console.log(result.diff);
2738
2958
  break;
2739
2959
  }
2740
- for (const g of problems) logErr(g.message);
2741
- if (result.status === "not-found" || problems.length > 0) process.exitCode = 1;
2960
+ for (const g of [...problems, ...requirementGaps]) logErr(g.message);
2961
+ if (result.status === "not-found" || problems.length > 0 || requirementGaps.length > 0)
2962
+ process.exitCode = 1;
2742
2963
  });
2743
2964
  }
2744
2965
  function makeFlowCommand() {
2745
2966
  const cmd = new Command("flow").description("Manage flows");
2746
2967
  cmd.command("list").description("List available flows").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
2747
- const flows = await discoverFlowsWithLibraries(path18__default.resolve(opts.projectDir));
2968
+ const flows = await discoverFlowsWithLibraries(path22__default.resolve(opts.projectDir));
2748
2969
  if (flows.length === 0) {
2749
2970
  logInfo("No flows found.");
2750
2971
  return;
@@ -2759,7 +2980,7 @@ function makeFlowCommand() {
2759
2980
  console.log();
2760
2981
  });
2761
2982
  cmd.command("show <id>").description("Show flow details and node graph").option("--project-dir <path>", "Project directory", process.cwd()).action(async (id, opts) => {
2762
- const flows = await discoverFlowsWithLibraries(path18__default.resolve(opts.projectDir));
2983
+ const flows = await discoverFlowsWithLibraries(path22__default.resolve(opts.projectDir));
2763
2984
  const flow = flows.find((f) => f.id === id);
2764
2985
  if (!flow) {
2765
2986
  logErr(`Flow not found: ${id}`);
@@ -2793,7 +3014,7 @@ function makeHistoryCommand() {
2793
3014
  cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
2794
3015
  const am2 = new AssetManager({
2795
3016
  registry: getKindRegistry(),
2796
- projectDir: path18__default.resolve(opts.projectDir)
3017
+ projectDir: path22__default.resolve(opts.projectDir)
2797
3018
  });
2798
3019
  const limit = parseInt(limitStr, 10) || 20;
2799
3020
  const entries = am2.history(limit);
@@ -2816,7 +3037,7 @@ function makeHistoryCommand() {
2816
3037
  cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
2817
3038
  const am2 = new AssetManager({
2818
3039
  registry: getKindRegistry(),
2819
- projectDir: path18__default.resolve(opts.projectDir)
3040
+ projectDir: path22__default.resolve(opts.projectDir)
2820
3041
  });
2821
3042
  am2.clearHistory();
2822
3043
  logOk("History cleared.");
@@ -2829,8 +3050,24 @@ var MCP_SERVER_ENTRY = {
2829
3050
  args: ["mcp-server"],
2830
3051
  env: {}
2831
3052
  };
3053
+ function mcpFilePath(projectDir) {
3054
+ return path22__default.join(projectDir, ".mcp.json");
3055
+ }
3056
+ function legacyMcpFilePath(projectDir) {
3057
+ return path22__default.join(projectDir, ".claude", "mcp.json");
3058
+ }
3059
+ async function removeSkaileMcpEntry(mcpPath) {
3060
+ const mcp = await readJsonStrict(mcpPath);
3061
+ if (!mcp?.mcpServers || !(SKAILE_MCP_NAME in mcp.mcpServers)) return false;
3062
+ const { [SKAILE_MCP_NAME]: _removed, ...rest } = mcp.mcpServers;
3063
+ const updated = { ...mcp, mcpServers: rest };
3064
+ if (Object.keys(rest).length === 0) delete updated.mcpServers;
3065
+ if (Object.keys(updated).length === 0) await fs5.unlink(mcpPath);
3066
+ else await writeJson(mcpPath, updated);
3067
+ return true;
3068
+ }
2832
3069
  function pluginDir(projectDir) {
2833
- return path18__default.join(projectDir, ".claude", "plugins", "skaile");
3070
+ return path22__default.join(projectDir, ".claude", "plugins", "skaile");
2834
3071
  }
2835
3072
  async function readJsonStrict(p6) {
2836
3073
  let raw;
@@ -2848,7 +3085,7 @@ async function readJsonStrict(p6) {
2848
3085
  }
2849
3086
  }
2850
3087
  async function writeJson(p6, value) {
2851
- await fs5.mkdir(path18__default.dirname(p6), { recursive: true });
3088
+ await fs5.mkdir(path22__default.dirname(p6), { recursive: true });
2852
3089
  await fs5.writeFile(p6, `${JSON.stringify(value, null, 2)}
2853
3090
  `);
2854
3091
  }
@@ -2856,8 +3093,8 @@ async function copyDir(src, dest) {
2856
3093
  await fs5.mkdir(dest, { recursive: true });
2857
3094
  const entries = await fs5.readdir(src, { withFileTypes: true });
2858
3095
  for (const entry of entries) {
2859
- const srcPath = path18__default.join(src, entry.name);
2860
- const destPath = path18__default.join(dest, entry.name);
3096
+ const srcPath = path22__default.join(src, entry.name);
3097
+ const destPath = path22__default.join(dest, entry.name);
2861
3098
  if (entry.isDirectory()) await copyDir(srcPath, destPath);
2862
3099
  else await fs5.copyFile(srcPath, destPath);
2863
3100
  }
@@ -2866,31 +3103,32 @@ async function install(projectDir, opts) {
2866
3103
  return opts?.full ? installFullPlugin(projectDir) : installMcp(projectDir);
2867
3104
  }
2868
3105
  async function installMcp(projectDir) {
2869
- const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
3106
+ const mcpPath = mcpFilePath(projectDir);
2870
3107
  const existing = await readJsonStrict(mcpPath) ?? {};
2871
3108
  const mcpServers = { ...existing.mcpServers ?? {} };
2872
3109
  const previous = mcpServers[SKAILE_MCP_NAME];
2873
3110
  const matches = previous && JSON.stringify(previous) === JSON.stringify(MCP_SERVER_ENTRY);
2874
3111
  let warning;
2875
3112
  if (previous && !matches) {
2876
- warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path18__default.relative(projectDir, mcpPath)}`;
3113
+ warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path22__default.relative(projectDir, mcpPath)}`;
2877
3114
  }
2878
3115
  mcpServers[SKAILE_MCP_NAME] = MCP_SERVER_ENTRY;
2879
3116
  await writeJson(mcpPath, { ...existing, mcpServers });
2880
- return { changed: !matches, method: "mcp", warning };
3117
+ const migrated = await removeSkaileMcpEntry(legacyMcpFilePath(projectDir));
3118
+ return { changed: !matches || migrated, method: "mcp", warning };
2881
3119
  }
2882
3120
  async function installFullPlugin(projectDir) {
2883
3121
  const dir = pluginDir(projectDir);
2884
3122
  for (const [rel, content] of Object.entries(buildClaudePluginFiles())) {
2885
- const dest = path18__default.join(dir, rel);
2886
- await fs5.mkdir(path18__default.dirname(dest), { recursive: true });
3123
+ const dest = path22__default.join(dir, rel);
3124
+ await fs5.mkdir(path22__default.dirname(dest), { recursive: true });
2887
3125
  await fs5.writeFile(dest, content);
2888
3126
  }
2889
- const projectSkillsDir = path18__default.join(projectDir, ".skaile", "skills");
3127
+ const projectSkillsDir = path22__default.join(projectDir, ".skaile", "skills");
2890
3128
  if (existsSync(projectSkillsDir)) {
2891
- await copyDir(projectSkillsDir, path18__default.join(dir, "skills"));
3129
+ await copyDir(projectSkillsDir, path22__default.join(dir, "skills"));
2892
3130
  }
2893
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
3131
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
2894
3132
  const settings = await readJsonStrict(settingsPath) ?? {};
2895
3133
  const plugins = settings.plugins ?? [];
2896
3134
  if (!plugins.includes(dir)) plugins.push(dir);
@@ -2898,47 +3136,43 @@ async function installFullPlugin(projectDir) {
2898
3136
  return { changed: true, method: "plugin" };
2899
3137
  }
2900
3138
  async function uninstall(projectDir) {
2901
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
2902
- const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
3139
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
3140
+ const mcpPath = mcpFilePath(projectDir);
2903
3141
  const dir = pluginDir(projectDir);
2904
- let changed = false;
3142
+ const rel = (p6) => path22__default.relative(projectDir, p6);
3143
+ const files = [];
2905
3144
  const settings = await readJsonStrict(settingsPath);
2906
3145
  if (settings && Array.isArray(settings.plugins)) {
2907
3146
  const next = settings.plugins.filter((p6) => p6 !== dir);
2908
3147
  if (next.length !== settings.plugins.length) {
2909
- changed = true;
3148
+ files.push(rel(settingsPath));
2910
3149
  const updated = { ...settings, plugins: next };
2911
3150
  if (next.length === 0) delete updated.plugins;
2912
- await writeJson(settingsPath, updated);
3151
+ if (Object.keys(updated).length === 0) await fs5.unlink(settingsPath);
3152
+ else await writeJson(settingsPath, updated);
2913
3153
  }
2914
3154
  }
2915
3155
  if (existsSync(dir)) {
2916
3156
  await fs5.rm(dir, { recursive: true, force: true });
2917
- changed = true;
3157
+ files.push(rel(dir));
2918
3158
  }
2919
- const mcp = await readJsonStrict(mcpPath);
2920
- if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
2921
- changed = true;
2922
- const { [SKAILE_MCP_NAME]: _removed, ...rest } = mcp.mcpServers;
2923
- const updated = { ...mcp, mcpServers: rest };
2924
- if (Object.keys(rest).length === 0) delete updated.mcpServers;
2925
- if (Object.keys(updated).length === 0) {
2926
- await fs5.unlink(mcpPath);
2927
- } else {
2928
- await writeJson(mcpPath, updated);
2929
- }
3159
+ if (await removeSkaileMcpEntry(mcpPath)) files.push(rel(mcpPath));
3160
+ const legacyPath = legacyMcpFilePath(projectDir);
3161
+ if (await removeSkaileMcpEntry(legacyPath)) files.push(rel(legacyPath));
3162
+ for (const emptyDir of [path22__default.dirname(dir), path22__default.join(projectDir, ".claude")]) {
3163
+ await fs5.rmdir(emptyDir).catch(() => void 0);
2930
3164
  }
2931
- return { changed };
3165
+ return { changed: files.length > 0, files };
2932
3166
  }
2933
3167
  async function detectInstall(projectDir) {
2934
3168
  const dir = pluginDir(projectDir);
2935
3169
  const settings = await readJsonStrict(
2936
- path18__default.join(projectDir, ".claude", "settings.json")
3170
+ path22__default.join(projectDir, ".claude", "settings.json")
2937
3171
  );
2938
- if (existsSync(path18__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
3172
+ if (existsSync(path22__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
2939
3173
  return { method: "plugin", pluginPath: dir };
2940
3174
  }
2941
- const mcp = await readJsonStrict(path18__default.join(projectDir, ".claude", "mcp.json"));
3175
+ const mcp = await readJsonStrict(mcpFilePath(projectDir));
2942
3176
  if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
2943
3177
  return { method: "mcp" };
2944
3178
  }
@@ -2947,7 +3181,7 @@ async function detectInstall(projectDir) {
2947
3181
  async function enable(projectDir) {
2948
3182
  const detected = await detectInstall(projectDir);
2949
3183
  if (!detected) throw new Error("plugin not installed for claude-code");
2950
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
3184
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
2951
3185
  const settings = await readJsonStrict(settingsPath) ?? {};
2952
3186
  if (detected.method === "plugin") {
2953
3187
  const disabled2 = settings.disabledPlugins ?? [];
@@ -2969,7 +3203,7 @@ async function enable(projectDir) {
2969
3203
  async function disable(projectDir) {
2970
3204
  const detected = await detectInstall(projectDir);
2971
3205
  if (!detected) throw new Error("plugin not installed for claude-code");
2972
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
3206
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
2973
3207
  const settings = await readJsonStrict(settingsPath) ?? {};
2974
3208
  if (detected.method === "plugin") {
2975
3209
  const list2 = settings.disabledPlugins ?? [];
@@ -2989,12 +3223,12 @@ async function disable(projectDir) {
2989
3223
  return { changed: true };
2990
3224
  }
2991
3225
  async function status(projectDir) {
2992
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
2993
- const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
3226
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
3227
+ const mcpPath = mcpFilePath(projectDir);
2994
3228
  const dir = pluginDir(projectDir);
2995
3229
  const settings = await readJsonStrict(settingsPath);
2996
3230
  const mcp = await readJsonStrict(mcpPath);
2997
- const pluginInstalled = !!(existsSync(path18__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
3231
+ const pluginInstalled = !!(existsSync(path22__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
2998
3232
  const mcpInstalled = !!(mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers);
2999
3233
  if (!pluginInstalled && !mcpInstalled) {
3000
3234
  return {
@@ -3012,7 +3246,7 @@ async function status(projectDir) {
3012
3246
  installed: "yes",
3013
3247
  enabled: disabled2 ? "no" : "yes",
3014
3248
  method: "plugin",
3015
- location: path18__default.relative(projectDir, dir)
3249
+ location: path22__default.relative(projectDir, dir)
3016
3250
  };
3017
3251
  }
3018
3252
  const disabled = settings?.disabledMcpjsonServers?.includes(SKAILE_MCP_NAME) ?? false;
@@ -3021,7 +3255,7 @@ async function status(projectDir) {
3021
3255
  installed: "yes",
3022
3256
  enabled: disabled ? "no" : "yes",
3023
3257
  method: "mcp",
3024
- location: path18__default.relative(projectDir, mcpPath)
3258
+ location: path22__default.relative(projectDir, mcpPath)
3025
3259
  };
3026
3260
  }
3027
3261
  var SKAILE_MCP_NAME2 = "skaile-workspace";
@@ -3048,7 +3282,7 @@ async function readConfig(p6) {
3048
3282
  }
3049
3283
  }
3050
3284
  async function writeConfig(p6, value) {
3051
- await fs5.mkdir(path18__default.dirname(p6), { recursive: true });
3285
+ await fs5.mkdir(path22__default.dirname(p6), { recursive: true });
3052
3286
  const cleaned = {};
3053
3287
  for (const [k, v] of Object.entries(value)) {
3054
3288
  if (v === void 0) continue;
@@ -3057,7 +3291,7 @@ async function writeConfig(p6, value) {
3057
3291
  await fs5.writeFile(p6, stringify$1(cleaned));
3058
3292
  }
3059
3293
  function configPath(projectDir) {
3060
- return path18__default.join(projectDir, ".codex", "config.toml");
3294
+ return path22__default.join(projectDir, ".codex", "config.toml");
3061
3295
  }
3062
3296
  async function install2(projectDir) {
3063
3297
  const p6 = configPath(projectDir);
@@ -3068,7 +3302,7 @@ async function install2(projectDir) {
3068
3302
  const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
3069
3303
  let warning;
3070
3304
  if (previous && !matches) {
3071
- warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path18__default.relative(projectDir, p6)}`;
3305
+ warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path22__default.relative(projectDir, p6)}`;
3072
3306
  }
3073
3307
  if (matches) return { changed: false, method: "toml" };
3074
3308
  servers[SKAILE_MCP_NAME2] = next;
@@ -3109,12 +3343,12 @@ async function status2(projectDir) {
3109
3343
  installed: "yes",
3110
3344
  enabled: "n/a",
3111
3345
  method: "mcp",
3112
- location: path18__default.relative(projectDir, p6)
3346
+ location: path22__default.relative(projectDir, p6)
3113
3347
  };
3114
3348
  }
3115
3349
  async function install3(projectDir) {
3116
- const extDir = path18__default.join(projectDir, ".omp", "extensions");
3117
- const extPath = path18__default.join(extDir, "skaile.ts");
3350
+ const extDir = path22__default.join(projectDir, ".omp", "extensions");
3351
+ const extPath = path22__default.join(extDir, "skaile.ts");
3118
3352
  await fs5.mkdir(extDir, { recursive: true });
3119
3353
  const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
3120
3354
  const plugin = new WorkspacePlugin({ projectDir });
@@ -3129,7 +3363,7 @@ async function install3(projectDir) {
3129
3363
  return { changed: true, method: "generated" };
3130
3364
  }
3131
3365
  async function uninstall3(projectDir) {
3132
- const extPath = path18__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3366
+ const extPath = path22__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3133
3367
  try {
3134
3368
  await fs5.unlink(extPath);
3135
3369
  return { changed: true };
@@ -3138,14 +3372,14 @@ async function uninstall3(projectDir) {
3138
3372
  }
3139
3373
  }
3140
3374
  async function status3(projectDir) {
3141
- const extPath = path18__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3375
+ const extPath = path22__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3142
3376
  if (existsSync(extPath)) {
3143
3377
  return {
3144
3378
  harness: "omp",
3145
3379
  installed: "yes",
3146
3380
  enabled: "n/a",
3147
3381
  method: "extension",
3148
- location: path18__default.relative(projectDir, extPath)
3382
+ location: path22__default.relative(projectDir, extPath)
3149
3383
  };
3150
3384
  }
3151
3385
  return {
@@ -3182,7 +3416,7 @@ async function installClaudeCode(projectDir, opts) {
3182
3416
  `Generated ${S.cmd(".claude/plugins/skaile/")} and registered it in ${S.cmd(".claude/settings.json")}`
3183
3417
  );
3184
3418
  } else if (r.changed) {
3185
- logOk(`Wrote ${S.cmd(".claude/mcp.json")} (${SKAILE_MCP_LABEL})`);
3419
+ logOk(`Wrote ${S.cmd(".mcp.json")} (${SKAILE_MCP_LABEL})`);
3186
3420
  } else {
3187
3421
  logInfo(`claude-code: already installed (mcp)`);
3188
3422
  }
@@ -3208,7 +3442,7 @@ async function installCodex(projectDir) {
3208
3442
  console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
3209
3443
  }
3210
3444
  async function runInstall(opts) {
3211
- const projectDir = path18__default.resolve(opts.projectDir);
3445
+ const projectDir = path22__default.resolve(opts.projectDir);
3212
3446
  const targets = resolveDriver(opts.driver);
3213
3447
  let exitCode = 0;
3214
3448
  if (targets.includes("claude-code")) {
@@ -3223,13 +3457,18 @@ async function runInstall(opts) {
3223
3457
  if (targets.includes("codex")) {
3224
3458
  exitCode |= await runHarnessStep("codex install", () => installCodex(projectDir));
3225
3459
  }
3226
- if (exitCode === 0) logOk("Plugin installed.");
3460
+ if (exitCode === 0) {
3461
+ await ignorePerMachineFiles(projectDir, targets);
3462
+ logOk("Plugin installed.");
3463
+ }
3227
3464
  return exitCode;
3228
3465
  }
3229
3466
  async function uninstallClaudeCode(projectDir) {
3230
3467
  const r = await uninstall(projectDir);
3231
- if (r.changed) logOk(`Removed skaile entries from ${S.cmd(".claude/")}`);
3232
- else logInfo(`claude-code: not installed`);
3468
+ if (r.changed) {
3469
+ const from = (r.files ?? []).map((f) => S.cmd(f)).join(", ");
3470
+ logOk(`Removed skaile entries from ${from || S.cmd(".claude/")}`);
3471
+ } else logInfo(`claude-code: not installed`);
3233
3472
  }
3234
3473
  async function uninstallOmp(projectDir) {
3235
3474
  const r = await uninstall3(projectDir);
@@ -3242,7 +3481,7 @@ async function uninstallCodex(projectDir) {
3242
3481
  else logInfo(`codex: not installed`);
3243
3482
  }
3244
3483
  async function runUninstall(opts) {
3245
- const projectDir = path18__default.resolve(opts.projectDir);
3484
+ const projectDir = path22__default.resolve(opts.projectDir);
3246
3485
  const targets = resolveDriver(opts.driver);
3247
3486
  let exitCode = 0;
3248
3487
  if (targets.includes("claude-code")) {
@@ -3257,9 +3496,46 @@ async function runUninstall(opts) {
3257
3496
  if (targets.includes("codex")) {
3258
3497
  exitCode |= await runHarnessStep("codex uninstall", () => uninstallCodex(projectDir));
3259
3498
  }
3260
- if (exitCode === 0) logOk("Plugin uninstalled.");
3499
+ if (exitCode === 0) {
3500
+ await removeEmptyPluginState(projectDir);
3501
+ logOk("Plugin uninstalled.");
3502
+ }
3261
3503
  return exitCode;
3262
3504
  }
3505
+ async function removeEmptyPluginState(projectDir) {
3506
+ const stateFile = path22__default.join(projectDir, ".skaile", "plugin-state.json");
3507
+ try {
3508
+ const parsed = JSON.parse(await fs5.readFile(stateFile, "utf-8"));
3509
+ if (typeof parsed !== "object" || parsed === null || Object.keys(parsed).length > 0) return;
3510
+ await fs5.unlink(stateFile);
3511
+ await fs5.rmdir(path22__default.dirname(stateFile)).catch(() => void 0);
3512
+ } catch {
3513
+ }
3514
+ }
3515
+ var PER_MACHINE_FILES = {
3516
+ "claude-code": [".skaile/plugin-state.json"],
3517
+ omp: [".omp/extensions/skaile.ts", ".skaile/plugin-state.json"],
3518
+ codex: [".codex/config.toml", ".skaile/plugin-state.json"]
3519
+ };
3520
+ async function ignorePerMachineFiles(projectDir, targets) {
3521
+ const gitignore = path22__default.join(projectDir, ".gitignore");
3522
+ let existing = null;
3523
+ try {
3524
+ existing = await fs5.readFile(gitignore, "utf-8");
3525
+ } catch {
3526
+ if (!existsSync(path22__default.join(projectDir, ".git"))) return;
3527
+ }
3528
+ const have = new Set((existing ?? "").split("\n").map((l) => l.trim()));
3529
+ const wanted = [...new Set(targets.flatMap((t) => PER_MACHINE_FILES[t]))];
3530
+ const missing = wanted.filter((f) => !have.has(f));
3531
+ if (missing.length === 0) return;
3532
+ const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
3533
+ await fs5.writeFile(gitignore, `${existing ?? ""}${prefix}${missing.join("\n")}
3534
+ `);
3535
+ logInfo(
3536
+ `Added ${missing.map((f) => S.cmd(f)).join(", ")} to ${S.cmd(".gitignore")} (per machine)`
3537
+ );
3538
+ }
3263
3539
  function checkToggleSupported(targets, requestedAll, action3) {
3264
3540
  if (requestedAll) return null;
3265
3541
  const unsupported = targets.filter((t) => !TOGGLE_SUPPORTED.includes(t));
@@ -3285,7 +3561,7 @@ async function toggleTarget(t, projectDir, action3) {
3285
3561
  });
3286
3562
  }
3287
3563
  async function runToggle(opts, action3) {
3288
- const projectDir = path18__default.resolve(opts.projectDir);
3564
+ const projectDir = path22__default.resolve(opts.projectDir);
3289
3565
  const requestedAll = opts.driver === "all";
3290
3566
  const targets = resolveDriver(opts.driver);
3291
3567
  const usageError = checkToggleSupported(targets, requestedAll, action3);
@@ -3297,7 +3573,7 @@ async function runToggle(opts, action3) {
3297
3573
  return exitCode;
3298
3574
  }
3299
3575
  async function runStatus2(opts) {
3300
- const projectDir = path18__default.resolve(opts.projectDir);
3576
+ const projectDir = path22__default.resolve(opts.projectDir);
3301
3577
  const targets = resolveDriver(opts.driver);
3302
3578
  const rows = [];
3303
3579
  let exitCode = 0;
@@ -3338,12 +3614,12 @@ function printStatusTable(rows) {
3338
3614
  var SKAILE_MCP_LABEL = "skaile-workspace entry";
3339
3615
  var HOOK_EVENTS = ["session-start", "session-end", "user-prompt-submit"];
3340
3616
  async function runHook(event) {
3341
- const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
3342
- registerLogStore(
3343
- new LogStore({
3617
+ const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
3618
+ registerLogStore2(
3619
+ new LogStore2({
3344
3620
  sessionId: `hook-${event}`,
3345
3621
  level: "info",
3346
- sinks: [new StdoutSink({ stream: "stderr" })]
3622
+ sinks: [new StdoutSink2({ stream: "stderr" })]
3347
3623
  })
3348
3624
  );
3349
3625
  const { WorkspacePlugin, PluginStore, resolveProjectDir } = await import('../workspace-plugin/index.js');
@@ -3368,7 +3644,7 @@ async function runHook(event) {
3368
3644
  await plugin.shutdown();
3369
3645
  return;
3370
3646
  }
3371
- const store = new PluginStore(path18__default.join(projectDir, ".skaile", "plugin-state.json"));
3647
+ const store = new PluginStore(path22__default.join(projectDir, ".skaile", "plugin-state.json"));
3372
3648
  await store.load();
3373
3649
  const status4 = store.get("connector:status");
3374
3650
  if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
@@ -3383,6 +3659,45 @@ async function runHook(event) {
3383
3659
  );
3384
3660
  }
3385
3661
  }
3662
+ async function readStdin() {
3663
+ if (process.stdin.isTTY) return "";
3664
+ const chunks = [];
3665
+ for await (const chunk of process.stdin) chunks.push(chunk);
3666
+ return Buffer.concat(chunks).toString("utf-8");
3667
+ }
3668
+ async function runOmpExec(kind, name, projectDir) {
3669
+ if (kind !== "tool" && kind !== "slash") {
3670
+ logErr(`omp-exec: unknown kind '${kind}' (expected: tool | slash)`);
3671
+ return 2;
3672
+ }
3673
+ const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
3674
+ const plugin = new WorkspacePlugin({ projectDir, bootOwned: true });
3675
+ try {
3676
+ const raw = (await readStdin()).trim();
3677
+ const payload = raw ? JSON.parse(raw) : kind === "tool" ? {} : [];
3678
+ await plugin.boot();
3679
+ if (kind === "slash") {
3680
+ const parts = Array.isArray(payload) ? payload.map(String) : [];
3681
+ process.stdout.write(`${await plugin.handleSlashCommand(name, parts)}
3682
+ `);
3683
+ return 0;
3684
+ }
3685
+ const tools = await plugin.buildOmpToolSet();
3686
+ const tool = tools.find((t) => t.name === name);
3687
+ if (!tool) {
3688
+ logErr(`omp-exec: unknown tool '${name}'`);
3689
+ return 2;
3690
+ }
3691
+ process.stdout.write(`${await tool.handler(payload)}
3692
+ `);
3693
+ return 0;
3694
+ } catch (e) {
3695
+ logErr(`omp-exec ${kind} ${name}: ${e instanceof Error ? e.message : String(e)}`);
3696
+ return 1;
3697
+ } finally {
3698
+ await plugin.shutdown();
3699
+ }
3700
+ }
3386
3701
  function makeIntegrationCommand() {
3387
3702
  const cmd = new Command("integration").description(
3388
3703
  "Manage skaile agent integration / workspace-plugin adapter (Claude Code / OMP / Codex)"
@@ -3405,13 +3720,18 @@ function makeIntegrationCommand() {
3405
3720
  cmd.command("status").description("Show install / enable status across harnesses").option("--driver <name>", "Target: claude-code | omp | codex | all", "all").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
3406
3721
  process.exitCode = await runStatus2(opts);
3407
3722
  });
3723
+ cmd.command("omp-exec <kind> <name>").description(
3724
+ "Run one tool or slash command of the omp extension (used by .omp/extensions/skaile.ts)"
3725
+ ).option("--project-dir <path>", "Project directory", process.cwd()).action(async (kind, name, opts) => {
3726
+ process.exitCode = await runOmpExec(kind, name, path22__default.resolve(opts.projectDir));
3727
+ });
3408
3728
  cmd.command("hook <event>").description(
3409
3729
  "Run a Claude Code lifecycle hook (session-start | session-end | user-prompt-submit)"
3410
3730
  ).action(async (event) => {
3411
3731
  try {
3412
3732
  if (!HOOK_EVENTS.includes(event)) {
3413
3733
  process.stderr.write(
3414
- `plugin hook: unknown event '${event}' (expected: ${HOOK_EVENTS.join(" | ")})
3734
+ `integration hook: unknown event '${event}' (expected: ${HOOK_EVENTS.join(" | ")})
3415
3735
  `
3416
3736
  );
3417
3737
  } else {
@@ -3419,7 +3739,7 @@ function makeIntegrationCommand() {
3419
3739
  }
3420
3740
  } catch (err2) {
3421
3741
  process.stderr.write(
3422
- `plugin hook ${event} warning: ${err2 instanceof Error ? err2.message : String(err2)}
3742
+ `integration hook ${event} warning: ${err2 instanceof Error ? err2.message : String(err2)}
3423
3743
  `
3424
3744
  );
3425
3745
  }
@@ -3446,13 +3766,14 @@ function unfinishedGitState(dir) {
3446
3766
  for (const [entry, state2] of Object.entries(UNFINISHED_GIT_ENTRIES)) {
3447
3767
  const p6 = spawnSync("git", ["rev-parse", "--git-path", entry], { cwd: dir, encoding: "utf-8" });
3448
3768
  if (p6.status !== 0) return "the git directory could not be read";
3449
- if (fs8.existsSync(path18.resolve(dir, p6.stdout.trim()))) return state2;
3769
+ if (fs9.existsSync(path22.resolve(dir, p6.stdout.trim()))) return state2;
3450
3770
  }
3451
3771
  return null;
3452
3772
  }
3453
3773
  async function reindexLibrary(lib, library, name) {
3454
3774
  assertManifestEditableOrExit(lib.path);
3455
3775
  exitOnManifestPublisherProblems(lib.path, name);
3776
+ exitOnLibrarySymlinks(lib.path, `skaile library index ${name}`);
3456
3777
  const badRequires = manifestRequiresProblems(lib.path);
3457
3778
  const resolved = resolveLibraryPublisherDetailed(lib, {}, getStoreIdentity());
3458
3779
  warnLibraryNameFallback(name, resolved);
@@ -3461,7 +3782,17 @@ async function reindexLibrary(lib, library, name) {
3461
3782
  lib.path,
3462
3783
  resolved.publisher,
3463
3784
  registry,
3464
- { check: (e) => checkAssetFile(e.source, e.kind, registry) }
3785
+ {
3786
+ check: (e) => checkAssetFile(
3787
+ e.source,
3788
+ e.kind,
3789
+ registry,
3790
+ lib.path,
3791
+ (f) => logWarn(
3792
+ `${path22.relative(lib.path, e.source)} [${f.tag}] \u2014 body is still the scaffold placeholder; publish refuses it until you write the ${f.tag} prompt`
3793
+ )
3794
+ )
3795
+ }
3465
3796
  );
3466
3797
  const manifest = loadSkPublishManifest(lib.path);
3467
3798
  for (const a of unknownKind) {
@@ -3473,19 +3804,25 @@ async function reindexLibrary(lib, library, name) {
3473
3804
  const ref = manifest ? assetEntryRef(a, manifest) : `${a.kind}:${a.name}`;
3474
3805
  logInfo(`Removed manifest entry ${ref} (root ${a.root} is gone)`);
3475
3806
  }
3476
- for (const s of skipped.filter((x) => x.reason === "invalid-version")) {
3477
- logWarn(
3478
- `${s.kind}:${s.name} skipped: ${s.detail}. Set a valid \`metadata.version\` (e.g. 0.1.0) and re-run \`skaile library index ${name}\`.`
3807
+ const invalidVersion = skipped.filter((x) => x.reason === "invalid-version");
3808
+ for (const s of invalidVersion) {
3809
+ const found = checkAssetFile(path22.join(lib.path, s.file), s.kind, registry).find(
3810
+ (f) => f.text.startsWith("version ")
3811
+ );
3812
+ const detail = found?.text ?? s.detail;
3813
+ const hint = detail.includes("Write it quoted") ? "" : " Set a valid `metadata.version` (e.g. 0.1.0).";
3814
+ logErr(
3815
+ `${s.kind}:${s.name} skipped: ${detail}.${hint} Re-run \`skaile library index ${name}\` after the fix.`
3479
3816
  );
3480
3817
  }
3481
3818
  const duplicates = skipped.filter((x) => x.reason === "duplicate");
3482
3819
  for (const s of duplicates) {
3483
- logErr(duplicateAssetMessage(s.kind, s.name, path18.dirname(s.file), s.detail, name));
3820
+ logErr(duplicateAssetMessage(s.kind, s.name, path22.dirname(s.file), s.detail, name));
3484
3821
  }
3485
3822
  for (const s of failed) {
3486
3823
  for (const f of s.findings) logErr(`${s.file} [${f.tag}] \u2014 ${f.text}`);
3487
3824
  }
3488
- const duplicateFiles = new Set(duplicates.map((s) => path18.resolve(lib.path, s.file)));
3825
+ const duplicateFiles = new Set(duplicates.map((s) => path22.resolve(lib.path, s.file)));
3489
3826
  const skippedKeys = new Set(
3490
3827
  [
3491
3828
  ...skipped.filter((s) => s.reason !== "duplicate"),
@@ -3493,7 +3830,7 @@ async function reindexLibrary(lib, library, name) {
3493
3830
  ].map((s) => `${s.kind}:${s.name}`)
3494
3831
  );
3495
3832
  const res = await indexLibrary(lib, library, {
3496
- exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path18.resolve(a.manifestPath))
3833
+ exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path22.resolve(a.manifestPath))
3497
3834
  });
3498
3835
  const unparsable = res.errors.filter((e) => e.includes("ManifestSchemaError:"));
3499
3836
  for (const e of res.errors) (unparsable.includes(e) ? logErr : logWarn)(e);
@@ -3505,14 +3842,21 @@ async function reindexLibrary(lib, library, name) {
3505
3842
  }
3506
3843
  for (const p6 of badRequires) logErr(`${p6.asset}: ${p6.message}`);
3507
3844
  for (const w of await unresolvedManifestDependencies(lib.path)) logWarn(w);
3508
- logOk(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
3845
+ const skippedUnparsable = unparsable.length + syncUnparsable.length;
3846
+ const failing = skippedUnparsable + invalidVersion.length + badRequires.length + failed.length + duplicates.length;
3847
+ (failing > 0 ? logWarn : logOk)(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
3509
3848
  warnIgnoredDomainFiles(lib.path);
3510
3849
  warnLegacyBundleFiles(lib.path);
3511
- const skippedUnparsable = unparsable.length + syncUnparsable.length;
3512
3850
  if (skippedUnparsable > 0) {
3513
3851
  logErr(`${skippedUnparsable} asset(s) skipped: manifest could not be parsed.`);
3514
3852
  process.exitCode = 1;
3515
3853
  }
3854
+ if (invalidVersion.length > 0) {
3855
+ logErr(
3856
+ `${invalidVersion.length} asset(s) skipped: the version is not valid semver (listed above).`
3857
+ );
3858
+ process.exitCode = 1;
3859
+ }
3516
3860
  if (badRequires.length > 0) {
3517
3861
  logErr(
3518
3862
  `${badRequires.length} invalid requires entr${badRequires.length === 1 ? "y" : "ies"} ignored: use the \`kind:@<publisher>/name[#version]\` form.`
@@ -3536,8 +3880,16 @@ async function indexPulledLibrary(lib, library, name) {
3536
3880
  const res = await indexLibrary(lib, library);
3537
3881
  for (const e of res.errors) logWarn(e);
3538
3882
  logOk(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
3883
+ warnUnlistedAssets(await countUnlistedAssets(lib.path), name);
3539
3884
  warnIgnoredDomainFiles(lib.path);
3540
3885
  }
3886
+ function warnUnlistedAssets(unlisted, name) {
3887
+ if (unlisted > 0) {
3888
+ logWarn(
3889
+ `${unlisted} asset(s) on disk are not in the manifest; run \`skaile library index ${name}\`.`
3890
+ );
3891
+ }
3892
+ }
3541
3893
  function assertManifestEditableOrExit(libraryPath) {
3542
3894
  try {
3543
3895
  assertManifestEditable(libraryPath);
@@ -3547,26 +3899,26 @@ function assertManifestEditableOrExit(libraryPath) {
3547
3899
  }
3548
3900
  async function assertLibraryPathFree(manager, dir, exceptId) {
3549
3901
  const clash = (await manager.listLibraries()).find(
3550
- (l) => l.id !== exceptId && path18.resolve(l.path) === dir
3902
+ (l) => l.id !== exceptId && path22.resolve(l.path) === dir
3551
3903
  );
3552
3904
  if (clash) throw new Error(`${dir} is already registered as library "${clash.name}".`);
3553
3905
  }
3554
3906
  function canonicalDir(dir) {
3555
- const abs = path18.resolve(dir);
3907
+ const abs = path22.resolve(dir);
3556
3908
  const missing = [];
3557
3909
  let existing = abs;
3558
- while (!fs8.existsSync(existing)) {
3559
- const parent = path18.dirname(existing);
3910
+ while (!fs9.existsSync(existing)) {
3911
+ const parent = path22.dirname(existing);
3560
3912
  if (parent === existing) return abs;
3561
- missing.unshift(path18.basename(existing));
3913
+ missing.unshift(path22.basename(existing));
3562
3914
  existing = parent;
3563
3915
  }
3564
- return path18.join(fs8.realpathSync(existing), ...missing);
3916
+ return path22.join(fs9.realpathSync(existing), ...missing);
3565
3917
  }
3566
3918
  function refuseGlobalInstallFolder(name, dir) {
3567
3919
  const reserved = globalInstallDir();
3568
- const rel = path18.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
3569
- const inside = rel === "" || !rel.startsWith("..") && !path18.isAbsolute(rel);
3920
+ const rel = path22.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
3921
+ const inside = rel === "" || !rel.startsWith("..") && !path22.isAbsolute(rel);
3570
3922
  if (name?.toLowerCase() === GLOBAL_INSTALL_DIR_NAME || inside) {
3571
3923
  logErr(
3572
3924
  `"${GLOBAL_INSTALL_DIR_NAME}" is reserved: ${reserved} holds assets from \`skaile install\`, not a library you author.`
@@ -3576,8 +3928,8 @@ function refuseGlobalInstallFolder(name, dir) {
3576
3928
  }
3577
3929
  async function refuseNestedLibraryPath(manager, dir, exceptId) {
3578
3930
  const within = (parent, child) => {
3579
- const rel = path18.relative(parent, child);
3580
- return rel === "" || !rel.startsWith("..") && !path18.isAbsolute(rel);
3931
+ const rel = path22.relative(parent, child);
3932
+ return rel === "" || !rel.startsWith("..") && !path22.isAbsolute(rel);
3581
3933
  };
3582
3934
  const target = canonicalDir(dir).toLowerCase();
3583
3935
  const librariesDir = resolveLibraryDir();
@@ -3607,29 +3959,29 @@ async function refuseNestedLibraryPath(manager, dir, exceptId) {
3607
3959
  function assertCreateDirInsideLibrary(libRoot, destDir, given) {
3608
3960
  const exists = (p6) => {
3609
3961
  try {
3610
- fs8.lstatSync(p6);
3962
+ fs9.lstatSync(p6);
3611
3963
  return true;
3612
3964
  } catch {
3613
3965
  return false;
3614
3966
  }
3615
3967
  };
3616
3968
  let probe = destDir;
3617
- while (!exists(probe)) probe = path18.dirname(probe);
3969
+ while (!exists(probe)) probe = path22.dirname(probe);
3618
3970
  let realProbe;
3619
3971
  try {
3620
- realProbe = fs8.realpathSync(probe);
3972
+ realProbe = fs9.realpathSync(probe);
3621
3973
  } catch {
3622
3974
  logErr(`--dir "${given}" passes through a broken symlink (${probe}).`);
3623
3975
  process.exit(1);
3624
3976
  }
3625
- if (!fs8.statSync(realProbe).isDirectory()) {
3977
+ if (!fs9.statSync(realProbe).isDirectory()) {
3626
3978
  logErr(`--dir "${given}": ${probe} is not a directory.`);
3627
3979
  process.exit(1);
3628
3980
  }
3629
3981
  const realRoot = canonicalDir(libRoot);
3630
- const realDest = path18.join(realProbe, path18.relative(probe, destDir));
3631
- const rel = path18.relative(realRoot, realDest);
3632
- if (rel === ".." || rel.startsWith(`..${path18.sep}`) || path18.isAbsolute(rel)) {
3982
+ const realDest = path22.join(realProbe, path22.relative(probe, destDir));
3983
+ const rel = path22.relative(realRoot, realDest);
3984
+ if (rel === ".." || rel.startsWith(`..${path22.sep}`) || path22.isAbsolute(rel)) {
3633
3985
  logErr(
3634
3986
  `--dir "${given}" must stay inside the library (${realRoot}): it resolves to ${realDest}.`
3635
3987
  );
@@ -3637,7 +3989,7 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
3637
3989
  }
3638
3990
  }
3639
3991
  function adoptWritesManifest(libPath) {
3640
- if (!fs8.existsSync(path18.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
3992
+ if (!fs9.existsSync(path22.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
3641
3993
  const manifest = loadSkPublishManifest(libPath);
3642
3994
  if (!manifest || manifest.source || (manifest.assets ?? []).length > 0) return false;
3643
3995
  return manifestPublisherProblems(libPath).length === 0;
@@ -3691,17 +4043,26 @@ function requireValidLibraryName(name) {
3691
4043
  var LOCAL_OWNERSHIP_REASON = "ownership only governs sync with a git remote, and a local library is always owned by you.";
3692
4044
  function pruneEmptyLibraryParents(libPath) {
3693
4045
  const root = canonicalDir(resolveLibraryDir());
3694
- let dir = path18.dirname(path18.resolve(libPath));
4046
+ let dir = path22.dirname(path22.resolve(libPath));
3695
4047
  for (; ; ) {
3696
- const rel = path18.relative(root, canonicalDir(dir));
3697
- if (rel === "" || rel.startsWith("..") || path18.isAbsolute(rel)) return;
3698
- if (!fs8.existsSync(dir) || fs8.readdirSync(dir).length > 0) return;
3699
- fs8.rmdirSync(dir);
3700
- dir = path18.dirname(dir);
4048
+ const rel = path22.relative(root, canonicalDir(dir));
4049
+ if (rel === "" || rel.startsWith("..") || path22.isAbsolute(rel)) return;
4050
+ if (!fs9.existsSync(dir) || fs9.readdirSync(dir).length > 0) return;
4051
+ fs9.rmdirSync(dir);
4052
+ dir = path22.dirname(dir);
3701
4053
  }
3702
4054
  }
4055
+ function remoteBranches(url) {
4056
+ const r = spawnSync("git", ["ls-remote", "--heads", url], {
4057
+ encoding: "utf-8",
4058
+ timeout: 2e4,
4059
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
4060
+ });
4061
+ if (r.status !== 0) return [];
4062
+ return r.stdout.split("\n").map((line) => line.split(" ")[1]?.replace(/^refs\/heads\//, "")).filter((b) => !!b);
4063
+ }
3703
4064
  async function warnIfNotGithubRemote(name, url) {
3704
- const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-53UTB3MB.js');
4065
+ const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-FFIPWIRM.js');
3705
4066
  if (!isGithubRemote(url)) logWarn(notGithubRemoteMessage(name, url));
3706
4067
  }
3707
4068
  function scaffoldLibraryFiles(dir, name) {
@@ -3733,9 +4094,9 @@ by the same ref.
3733
4094
  ];
3734
4095
  const written = [];
3735
4096
  for (const [file, content] of files) {
3736
- const target = path18.join(dir, file);
3737
- if (fs8.existsSync(target)) continue;
3738
- fs8.writeFileSync(target, content, "utf8");
4097
+ const target = path22.join(dir, file);
4098
+ if (fs9.existsSync(target)) continue;
4099
+ fs9.writeFileSync(target, content, "utf8");
3739
4100
  written.push(file);
3740
4101
  }
3741
4102
  return written;
@@ -3823,9 +4184,9 @@ function makeLibraryCommand() {
3823
4184
  opts.path ??= gone.path;
3824
4185
  }
3825
4186
  const ownership = flagged[0] ?? gone?.ownership ?? "owner";
3826
- const libPath = opts.path ? path18.resolve(opts.path) : path18.join(resolveLibraryDir(), name);
4187
+ const libPath = opts.path ? path22.resolve(opts.path) : path22.join(resolveLibraryDir(), name);
3827
4188
  refuseGlobalInstallFolder(name, libPath);
3828
- if (fs8.existsSync(libPath) && !fs8.statSync(libPath).isDirectory()) {
4189
+ if (fs9.existsSync(libPath) && !fs9.statSync(libPath).isDirectory()) {
3829
4190
  logErr(`${libPath} exists and is not a directory.`);
3830
4191
  process.exit(1);
3831
4192
  }
@@ -3864,9 +4225,9 @@ function makeLibraryCommand() {
3864
4225
  backend = "git";
3865
4226
  backendConfig = { url: adopted.url, branch: adopted.branch, authHint: "ssh" };
3866
4227
  } else {
3867
- fs8.mkdirSync(libPath, { recursive: true });
4228
+ fs9.mkdirSync(libPath, { recursive: true });
3868
4229
  }
3869
- const blank = fs8.readdirSync(libPath).every((entry) => entry === ".git");
4230
+ const blank = fs9.readdirSync(libPath).every((entry) => entry === ".git");
3870
4231
  const isDefault = !hasDefault && ownership !== "reader";
3871
4232
  await manager.addLibrary({
3872
4233
  name,
@@ -3911,11 +4272,7 @@ function makeLibraryCommand() {
3911
4272
  const res = await indexLibrary(lib, library);
3912
4273
  for (const e of res.errors) logWarn(e);
3913
4274
  logOk(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
3914
- if (unlisted > 0) {
3915
- logWarn(
3916
- `${unlisted} asset(s) on disk are not in the manifest; run \`skaile library index ${name}\`.`
3917
- );
3918
- }
4275
+ warnUnlistedAssets(unlisted, name);
3919
4276
  warnIgnoredDomainFiles(libPath);
3920
4277
  }
3921
4278
  } catch (err2) {
@@ -3925,7 +4282,10 @@ function makeLibraryCommand() {
3925
4282
  }
3926
4283
  }
3927
4284
  );
3928
- cmd.command("link <name> <git-url>").description("Attach a github remote to a local library (makes it store-publishable)").option("--branch <name>", "Default branch", "main").action(async (name, url, opts) => {
4285
+ cmd.command("link <name> <git-url>").description("Attach a github remote to a local library (makes it store-publishable)").option(
4286
+ "--branch <name>",
4287
+ "Branch to track (default: the checked-out branch of an existing repo, else main)"
4288
+ ).action(async (name, url, opts) => {
3929
4289
  const { manager, close } = await openLibraryManager();
3930
4290
  try {
3931
4291
  const lib = await manager.requireLibraryDir(name);
@@ -3935,11 +4295,25 @@ function makeLibraryCommand() {
3935
4295
  );
3936
4296
  process.exit(1);
3937
4297
  }
3938
- ensureGitRepo(lib.path, url, opts.branch);
3939
- trackOriginBranch(lib.path, opts.branch, { fetch: true });
4298
+ const head = isGitRepo(lib.path) ? spawnSync("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
4299
+ cwd: lib.path,
4300
+ encoding: "utf-8"
4301
+ }) : void 0;
4302
+ const branch = opts.branch ?? (head?.status === 0 && head.stdout.trim() || "main");
4303
+ if (opts.branch === void 0) {
4304
+ const theirs = remoteBranches(url);
4305
+ if (theirs.length > 0 && !theirs.includes(branch)) {
4306
+ logErr(
4307
+ `The remote already has ${theirs.length === 1 ? "branch" : "branches"} ${theirs.join(", ")}; pass --branch ${theirs[0]} to track ${theirs.length === 1 ? "it" : "one"}.`
4308
+ );
4309
+ process.exit(1);
4310
+ }
4311
+ }
4312
+ ensureGitRepo(lib.path, url, branch);
4313
+ trackOriginBranch(lib.path, branch, { fetch: true });
3940
4314
  await manager.updateLibrary(name, {
3941
4315
  backend: "git",
3942
- backendConfig: { url, branch: opts.branch, authHint: "ssh" }
4316
+ backendConfig: { url, branch, authHint: "ssh" }
3943
4317
  });
3944
4318
  logOk(`Library "${name}" linked to ${url}.`);
3945
4319
  await warnIfNotGithubRemote(name, url);
@@ -3980,10 +4354,10 @@ function makeLibraryCommand() {
3980
4354
  exitOnManifestPublisherProblems(target.path, target.name);
3981
4355
  const effectiveKind = opts.kind ?? kind;
3982
4356
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
3983
- const libRoot = path18.resolve(target.path);
3984
- const destDir = opts.dir ? path18.resolve(libRoot, opts.dir) : libRoot;
3985
- const relDest = path18.relative(libRoot, destDir);
3986
- if (relDest === ".." || relDest.startsWith(`..${path18.sep}`) || path18.isAbsolute(relDest)) {
4357
+ const libRoot = path22.resolve(target.path);
4358
+ const destDir = opts.dir ? path22.resolve(libRoot, opts.dir) : libRoot;
4359
+ const relDest = path22.relative(libRoot, destDir);
4360
+ if (relDest === ".." || relDest.startsWith(`..${path22.sep}`) || path22.isAbsolute(relDest)) {
3987
4361
  logErr(`--dir "${opts.dir}" must stay inside the library (${libRoot}).`);
3988
4362
  process.exit(1);
3989
4363
  }
@@ -3992,11 +4366,11 @@ function makeLibraryCommand() {
3992
4366
  libRoot,
3993
4367
  effectiveKind,
3994
4368
  name,
3995
- path18.relative(libRoot, path18.join(destDir, name))
4369
+ path22.relative(libRoot, path22.join(destDir, name))
3996
4370
  );
3997
4371
  if (taken) {
3998
4372
  logErr(
3999
- `${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path18.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
4373
+ `${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path22.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
4000
4374
  );
4001
4375
  process.exit(1);
4002
4376
  }
@@ -4054,13 +4428,13 @@ function makeLibraryCommand() {
4054
4428
  logErr(`A library named "${newName}" is already registered.`);
4055
4429
  process.exit(1);
4056
4430
  }
4057
- const newPath = path18.join(path18.dirname(lib.path), newName);
4431
+ const newPath = path22.join(path22.dirname(lib.path), newName);
4058
4432
  refuseGlobalInstallFolder(newName, newPath);
4059
- if (fs8.existsSync(newPath)) {
4433
+ if (fs9.existsSync(newPath)) {
4060
4434
  logErr(`Target directory already exists: ${newPath}`);
4061
4435
  process.exit(1);
4062
4436
  }
4063
- fs8.renameSync(lib.path, newPath);
4437
+ fs9.renameSync(lib.path, newPath);
4064
4438
  await manager.updateLibrary(lib.id, { name: newName, path: newPath });
4065
4439
  logOk(`Renamed ${lib.name} \u2192 ${newName}`);
4066
4440
  }
@@ -4140,8 +4514,8 @@ function makeLibraryCommand() {
4140
4514
  }
4141
4515
  patch.isDefault = false;
4142
4516
  } else if (field === "path") {
4143
- const dir = path18.resolve(value);
4144
- if (!fs8.existsSync(dir) || !fs8.statSync(dir).isDirectory()) {
4517
+ const dir = path22.resolve(value);
4518
+ if (!fs9.existsSync(dir) || !fs9.statSync(dir).isDirectory()) {
4145
4519
  logErr(`Directory does not exist: ${dir}. \`library set path=\` does not move files.`);
4146
4520
  process.exit(1);
4147
4521
  }
@@ -4352,16 +4726,16 @@ function makeLibraryCommand() {
4352
4726
  "With --create-repo: create the repo private (the store only accepts public repos)"
4353
4727
  ).option("--ref <gitref>", "Git ref to ingest (default: the library branch or main)").option("--dry-run", "Print the plan; push nothing and call no store endpoint").action(
4354
4728
  async (lib, opts) => {
4355
- const { runLibraryPublish } = await import('../library-publish-53UTB3MB.js');
4729
+ const { runLibraryPublish } = await import('../library-publish-FFIPWIRM.js');
4356
4730
  await withStoreErrorHandling(() => runLibraryPublish(lib, opts));
4357
4731
  }
4358
4732
  );
4359
4733
  cmd.command("register <lib>").description("Register the library's manifest without pushing (bytes already on github)").option("--asset <ref>", "Publish only the single asset matching this ref/name").option("--ref <gitref>", "Git ref to ingest (default: the library branch or main)").option("--dry-run", "Print the plan; call no store endpoint").action(async (lib, opts) => {
4360
- const { runLibraryRegister } = await import('../library-publish-53UTB3MB.js');
4734
+ const { runLibraryRegister } = await import('../library-publish-FFIPWIRM.js');
4361
4735
  await withStoreErrorHandling(() => runLibraryRegister(lib, opts));
4362
4736
  });
4363
4737
  cmd.command("yank <lib>").description("Retract the library's published assets from the store").option("--asset <ref>", "Yank only the single asset matching this ref/name").action(async (lib, opts) => {
4364
- const { runLibraryYank } = await import('../library-publish-53UTB3MB.js');
4738
+ const { runLibraryYank } = await import('../library-publish-FFIPWIRM.js');
4365
4739
  await withStoreErrorHandling(() => runLibraryYank(lib, opts));
4366
4740
  });
4367
4741
  return cmd;
@@ -4412,9 +4786,9 @@ async function printOverallStatus(projectDir, asJson) {
4412
4786
  } catch {
4413
4787
  secretsStrategy = "unavailable";
4414
4788
  }
4415
- const resolvedProjectDir = path18.resolve(projectDir);
4416
- const hasWorkspaceConfig = existsSync(path18.join(resolvedProjectDir, "skaile.yaml"));
4417
- const hasLockFile = existsSync(path18.join(resolvedProjectDir, "skaile.lock.yaml"));
4789
+ const resolvedProjectDir = path22.resolve(projectDir);
4790
+ const hasWorkspaceConfig = existsSync(path22.join(resolvedProjectDir, "skaile.yaml"));
4791
+ const hasLockFile = existsSync(path22.join(resolvedProjectDir, "skaile.lock.yaml"));
4418
4792
  let assignments = [];
4419
4793
  if (hasWorkspaceConfig) {
4420
4794
  try {
@@ -5021,7 +5395,7 @@ function scheduleSoftDepPreview() {
5021
5395
  }
5022
5396
  async function loadAssets() {
5023
5397
  softDepPreviewCache.clear();
5024
- const { gatherAssetFeeds } = await import('../asset-feeds-CXGQIDFR.js');
5398
+ const { gatherAssetFeeds } = await import('../asset-feeds-ALMTHLPV.js');
5025
5399
  const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
5026
5400
  if (notes.length > 0) {
5027
5401
  state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
@@ -5029,7 +5403,7 @@ async function loadAssets() {
5029
5403
  const installed = new Set(am.listDeployed().map((e) => `${e.kind}:${e.name}`));
5030
5404
  let lock = null;
5031
5405
  try {
5032
- lock = readLock(path18__default.join(am.projectDir, "skaile.lock.yaml"));
5406
+ lock = readLock(path22__default.join(am.projectDir, "skaile.lock.yaml"));
5033
5407
  } catch {
5034
5408
  }
5035
5409
  const rows = buildAssetRows(
@@ -5051,7 +5425,7 @@ function rebuildSourceTree() {
5051
5425
  rebuildVisibleSources();
5052
5426
  }
5053
5427
  function sourceOrgRepo(s) {
5054
- const parts = s.path.split(path18__default.sep).filter(Boolean);
5428
+ const parts = s.path.split(path22__default.sep).filter(Boolean);
5055
5429
  if (parts.length < 2) return null;
5056
5430
  return { org: parts[parts.length - 2], repo: parts[parts.length - 1] };
5057
5431
  }
@@ -5225,13 +5599,13 @@ function reconcileCollapsedSets(rows) {
5225
5599
  async function loadSourcesAndLibraries() {
5226
5600
  try {
5227
5601
  const [{ openLibraryManager: openLibraryManager2 }, { getGlobalCacheDir: getGlobalCacheDir2, globalSkaileDir: globalSkaileDir2 }] = await Promise.all([
5228
- import('../open-library-BOSPJVID.js'),
5602
+ import('../open-library-PZAT3TJA.js'),
5229
5603
  import('../core/index.js')
5230
5604
  ]);
5231
5605
  const { manager, library, close } = await openLibraryManager2();
5232
5606
  try {
5233
5607
  const newRoot = getGlobalCacheDir2();
5234
- const legacyRoot = path18__default.join(globalSkaileDir2(), "sources");
5608
+ const legacyRoot = path22__default.join(globalSkaileDir2(), "sources");
5235
5609
  const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
5236
5610
  const libs = await manager.listLibraries();
5237
5611
  const defs = await library.listAssetDefs();
@@ -6191,19 +6565,19 @@ async function run(projectDir) {
6191
6565
  }
6192
6566
  function makeManageCommand() {
6193
6567
  return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
6194
- await run(path18__default.resolve(opts.projectDir));
6568
+ await run(path22__default.resolve(opts.projectDir));
6195
6569
  });
6196
6570
  }
6197
6571
  function makeMcpServerCommand() {
6198
6572
  return new Command("mcp-server").description("Start skaile workspace MCP server (stdio transport)").option("--project-dir <path>", "Project directory (default: cwd)", process.cwd()).action(async (opts) => {
6199
- const path43 = await import('path');
6200
- const projectDir = path43.default.resolve(opts.projectDir);
6201
- const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
6202
- registerLogStore(
6203
- new LogStore({
6573
+ const path44 = await import('path');
6574
+ const projectDir = path44.default.resolve(opts.projectDir);
6575
+ const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
6576
+ registerLogStore2(
6577
+ new LogStore2({
6204
6578
  sessionId: "mcp-server",
6205
6579
  level: "info",
6206
- sinks: [new StdoutSink({ stream: "stderr" })]
6580
+ sinks: [new StdoutSink2({ stream: "stderr" })]
6207
6581
  })
6208
6582
  );
6209
6583
  const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
@@ -6244,10 +6618,10 @@ function walkFiles(root, match) {
6244
6618
  return;
6245
6619
  }
6246
6620
  for (const entry of entries) {
6247
- const full = path18__default.join(dir, entry.name);
6621
+ const full = path22__default.join(dir, entry.name);
6248
6622
  if (entry.isDirectory()) {
6249
6623
  if (SKIPPED_DIRS.has(entry.name)) continue;
6250
- if (entry.name === "cache" && path18__default.basename(dir) === ".skaile") continue;
6624
+ if (entry.name === "cache" && path22__default.basename(dir) === ".skaile") continue;
6251
6625
  visit(full);
6252
6626
  } else if (entry.isFile() && match(entry.name)) {
6253
6627
  out.push(full);
@@ -6265,14 +6639,14 @@ function applyChanges2(changes) {
6265
6639
  switch (change.type) {
6266
6640
  case "write":
6267
6641
  case "create":
6268
- mkdirSync(path18__default.dirname(change.path), { recursive: true });
6642
+ mkdirSync(path22__default.dirname(change.path), { recursive: true });
6269
6643
  writeFileSync(change.path, change.after, "utf-8");
6270
6644
  break;
6271
6645
  case "delete":
6272
6646
  rmSync(change.path, { force: true });
6273
6647
  break;
6274
6648
  case "move":
6275
- mkdirSync(path18__default.dirname(change.to), { recursive: true });
6649
+ mkdirSync(path22__default.dirname(change.to), { recursive: true });
6276
6650
  writeFileSync(change.to, change.after, "utf-8");
6277
6651
  rmSync(change.from, { force: true });
6278
6652
  break;
@@ -6365,7 +6739,7 @@ function unifiedDiff(before, after, oldLabel, newLabel, context = 3) {
6365
6739
  return `${out.join("\n")}
6366
6740
  `;
6367
6741
  }
6368
- var posix = (p6) => p6.split(path18__default.sep).join("/");
6742
+ var posix = (p6) => p6.split(path22__default.sep).join("/");
6369
6743
  function colorizeDiff(diff) {
6370
6744
  return diff.split("\n").map((line) => {
6371
6745
  if (line.startsWith("+++") || line.startsWith("---")) return S.bold(line);
@@ -6376,7 +6750,7 @@ function colorizeDiff(diff) {
6376
6750
  }).join("\n");
6377
6751
  }
6378
6752
  function renderChange(change, base) {
6379
- const rel = (p6) => posix(path18__default.relative(base, p6) || path18__default.basename(p6));
6753
+ const rel = (p6) => posix(path22__default.relative(base, p6) || path22__default.basename(p6));
6380
6754
  switch (change.type) {
6381
6755
  case "write":
6382
6756
  return unifiedDiff(
@@ -6403,7 +6777,7 @@ ${diff}`;
6403
6777
  }
6404
6778
  }
6405
6779
  function changeLabel(change, base) {
6406
- const rel = (p6) => posix(path18__default.relative(base, p6) || path18__default.basename(p6));
6780
+ const rel = (p6) => posix(path22__default.relative(base, p6) || path22__default.basename(p6));
6407
6781
  switch (change.type) {
6408
6782
  case "write":
6409
6783
  return `modify ${rel(change.path)}`;
@@ -6463,10 +6837,10 @@ function loadAsset(projectDir, id, ref) {
6463
6837
  )
6464
6838
  };
6465
6839
  }
6466
- const manifestPath = path18__default.join(dir, AGENT_MANIFEST_FILE);
6840
+ const manifestPath = path22__default.join(dir, AGENT_MANIFEST_FILE);
6467
6841
  let text;
6468
6842
  try {
6469
- text = fs8__default.readFileSync(manifestPath, "utf-8");
6843
+ text = fs9__default.readFileSync(manifestPath, "utf-8");
6470
6844
  } catch {
6471
6845
  return {
6472
6846
  diagnostic: err(
@@ -6571,6 +6945,7 @@ function checkAgentInstances(projectDir, parsed) {
6571
6945
  const diagnostics = [];
6572
6946
  const instances = normalizeAgentInstances(parsed.agents, diagnostics);
6573
6947
  const agent = isRecord(parsed.agent) ? parsed.agent : void 0;
6948
+ diagnostics.push(...agentBlockKeyDiagnostics(parsed.agent));
6574
6949
  if (agent?.subagents !== void 0) {
6575
6950
  diagnostics.push(
6576
6951
  err(
@@ -6645,12 +7020,12 @@ function findManifestCandidates(rootPath) {
6645
7020
  function walk(dir) {
6646
7021
  let entries;
6647
7022
  try {
6648
- entries = fs8__default.readdirSync(dir, { withFileTypes: true });
7023
+ entries = fs9__default.readdirSync(dir, { withFileTypes: true });
6649
7024
  } catch {
6650
7025
  return;
6651
7026
  }
6652
7027
  for (const entry of entries) {
6653
- const fullPath = path18__default.join(dir, entry.name);
7028
+ const fullPath = path22__default.join(dir, entry.name);
6654
7029
  if (entry.isDirectory()) {
6655
7030
  if (!SKIP_DIRS.has(entry.name)) walk(fullPath);
6656
7031
  } else if (entry.isFile()) {
@@ -6667,10 +7042,10 @@ function findManifestCandidates(rootPath) {
6667
7042
  return candidates;
6668
7043
  }
6669
7044
  function parseManifestCandidate(c, absRoot) {
6670
- const content = fs8__default.readFileSync(c.filePath, "utf-8");
7045
+ const content = fs9__default.readFileSync(c.filePath, "utf-8");
6671
7046
  const res = parseManifestFile(c.filePath, content);
6672
7047
  if (!res.ok) {
6673
- logErr(`${path18__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 parse error: ${res.reason}`);
7048
+ logErr(`${path22__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 parse error: ${res.reason}`);
6674
7049
  return { kind: "error" };
6675
7050
  }
6676
7051
  return {
@@ -6687,29 +7062,52 @@ function checkComposeKinds(parsed, registry) {
6687
7062
  const diagnostics = [];
6688
7063
  composes.forEach((item, i) => {
6689
7064
  if (item === null || typeof item !== "object") return;
6690
- const kind = item.kind;
7065
+ const fields = item;
7066
+ const kind = fields.kind;
6691
7067
  if (typeof kind !== "string") return;
6692
- if (PSEUDO_COMPOSE_KINDS.has(kind) || registry.getProvider(kind)) return;
6693
- diagnostics.push({
6694
- code: "unknown_asset_kind",
6695
- severity: "error",
6696
- message: `composes item kind "${kind}" is not a registered asset kind (registered: ${registry.getAllKinds().join(", ")})`,
6697
- path: `composes[${i}].kind`
6698
- });
7068
+ if (!PSEUDO_COMPOSE_KINDS.has(kind) && !registry.getProvider(kind)) {
7069
+ diagnostics.push({
7070
+ code: "unknown_asset_kind",
7071
+ severity: "error",
7072
+ message: `composes item kind "${kind}" is not a registered asset kind (registered: ${registry.getAllKinds().join(", ")})`,
7073
+ path: `composes[${i}].kind`
7074
+ });
7075
+ return;
7076
+ }
7077
+ if (fields.binding !== void 0 || typeof fields.ref !== "string") return;
7078
+ try {
7079
+ resolveBinding({ kind, ref: fields.ref });
7080
+ } catch (err2) {
7081
+ if (!(err2 instanceof UnknownCompositionKindError)) throw err2;
7082
+ diagnostics.push({
7083
+ code: "unknown_asset_kind",
7084
+ severity: "error",
7085
+ message: `composes item "${fields.ref}" of kind "${kind}" has no default binding; set \`binding:\` (the session build fails without it)`,
7086
+ path: `composes[${i}].binding`
7087
+ });
7088
+ }
6699
7089
  });
6700
7090
  return diagnostics;
6701
7091
  }
7092
+ function libraryRootOf(absRoot) {
7093
+ for (let dir = absRoot; ; dir = path22__default.dirname(dir)) {
7094
+ if (fs9__default.existsSync(path22__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
7095
+ if (path22__default.dirname(dir) === dir) return absRoot;
7096
+ }
7097
+ }
6702
7098
  function validateManifestCandidate(c, parsed, body, absRoot, registry, strictConformance) {
6703
- const relPath = path18__default.relative(absRoot, c.filePath);
7099
+ const relPath = path22__default.relative(absRoot, c.filePath);
6704
7100
  let errors = 0;
6705
7101
  let warnings = 0;
6706
- const dirName = path18__default.basename(path18__default.dirname(c.filePath));
7102
+ const dirName = path22__default.basename(path22__default.dirname(c.filePath));
6707
7103
  const checked = checkAsset(
6708
7104
  c.kind,
6709
7105
  parsed ?? {},
6710
7106
  body,
6711
7107
  dirName,
6712
- registry
7108
+ registry,
7109
+ fs9__default.readFileSync(c.filePath, "utf-8"),
7110
+ path22__default.basename(c.filePath)
6713
7111
  );
6714
7112
  for (const f of checked.errors) {
6715
7113
  logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
@@ -6717,7 +7115,7 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
6717
7115
  }
6718
7116
  for (const f of checked.advisories) {
6719
7117
  const line = `${relPath} [${f.tag}] \u2014 ${f.text}`;
6720
- if (f.conformance && strictConformance) {
7118
+ if (f.conformance && strictConformance || f.scaffoldBody) {
6721
7119
  logErr(line);
6722
7120
  errors++;
6723
7121
  } else {
@@ -6725,7 +7123,17 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
6725
7123
  warnings++;
6726
7124
  }
6727
7125
  }
6728
- if (c.kind === "agent" && path18__default.basename(c.filePath) === "agent.yaml") {
7126
+ if (c.kind === "agent" && parsed !== null && typeof parsed === "object") {
7127
+ for (const f of checkAgentFiles(
7128
+ parsed,
7129
+ path22__default.dirname(c.filePath),
7130
+ libraryRootOf(absRoot)
7131
+ )) {
7132
+ logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
7133
+ errors++;
7134
+ }
7135
+ }
7136
+ if (c.kind === "agent" && path22__default.basename(c.filePath) === "agent.yaml") {
6729
7137
  for (const d of [
6730
7138
  ...checkComposeKinds(parsed, registry),
6731
7139
  ...composeSlotDiagnostics(parsed),
@@ -6743,17 +7151,36 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
6743
7151
  }
6744
7152
  return { errors, warnings };
6745
7153
  }
7154
+ function scanIdentities(root) {
7155
+ const identities = /* @__PURE__ */ new Set();
7156
+ for (const c of findManifestCandidates(root)) {
7157
+ let parsed;
7158
+ try {
7159
+ const res = parseManifestFile(c.filePath, fs9__default.readFileSync(c.filePath, "utf-8"));
7160
+ if (!res.ok) continue;
7161
+ parsed = res.data;
7162
+ } catch {
7163
+ continue;
7164
+ }
7165
+ if (parsed === null || typeof parsed !== "object") continue;
7166
+ const identity = parsed[c.kind === "flow" ? "id" : "name"];
7167
+ if (typeof identity === "string" && identity.length > 0)
7168
+ identities.add(`${c.kind}:${identity}`);
7169
+ }
7170
+ return identities;
7171
+ }
6746
7172
  function validateManifests(rootPath, strictConformance) {
6747
- const absRoot = path18__default.resolve(rootPath);
6748
- if (!fs8__default.existsSync(absRoot)) {
7173
+ const absRoot = path22__default.resolve(rootPath);
7174
+ if (!fs9__default.existsSync(absRoot)) {
6749
7175
  logErr(`Path does not exist: ${absRoot}`);
6750
7176
  return { total: 0, errors: 1, warnings: 0 };
6751
7177
  }
6752
7178
  const registry = getKindRegistry();
6753
7179
  const candidates = findManifestCandidates(absRoot);
6754
- let errors = 0;
7180
+ let errors = reportLibrarySymlinks(absRoot);
6755
7181
  let warnings = 0;
6756
7182
  const seenIdentity = /* @__PURE__ */ new Map();
7183
+ const agentsToResolve = [];
6757
7184
  for (const c of candidates) {
6758
7185
  const parseResult = parseManifestCandidate(c, absRoot);
6759
7186
  if (parseResult.kind === "error") {
@@ -6770,22 +7197,38 @@ function validateManifests(rootPath, strictConformance) {
6770
7197
  );
6771
7198
  errors += delta.errors;
6772
7199
  warnings += delta.warnings;
7200
+ if (c.kind === "agent" && parseResult.parsed !== null && typeof parseResult.parsed === "object") {
7201
+ agentsToResolve.push({
7202
+ relPath: path22__default.relative(absRoot, c.filePath),
7203
+ parsed: parseResult.parsed
7204
+ });
7205
+ }
6773
7206
  const obj = parseResult.parsed;
6774
7207
  const identity = obj && typeof obj === "object" ? obj[c.kind === "flow" ? "id" : "name"] : null;
6775
7208
  if (typeof identity === "string" && identity.length > 0) {
6776
- const dir = path18__default.dirname(c.filePath);
7209
+ const dir = path22__default.dirname(c.filePath);
6777
7210
  const key = `${c.kind}:${identity}`;
6778
7211
  const first = seenIdentity.get(key);
6779
7212
  if (first === void 0) {
6780
7213
  seenIdentity.set(key, dir);
6781
7214
  } else if (first !== dir) {
6782
7215
  logErr(
6783
- `${path18__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 ${key} is also defined in ${path18__default.relative(absRoot, first) || "."}; two directories cannot share a kind and name (\`skaile library index\` keeps only the first).`
7216
+ `${path22__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 ${key} is also defined in ${path22__default.relative(absRoot, first) || "."}; two directories cannot share a kind and name (\`skaile library index\` keeps only the first).`
6784
7217
  );
6785
7218
  errors++;
6786
7219
  }
6787
7220
  }
6788
7221
  }
7222
+ const libraryRoot = libraryRootOf(absRoot);
7223
+ const libraryPublisher = loadSkPublishManifest(libraryRoot)?.publisher;
7224
+ const siblingIdentities = libraryRoot === absRoot ? /* @__PURE__ */ new Set() : scanIdentities(libraryRoot);
7225
+ const hasAsset = (kind, name) => seenIdentity.has(`${kind}:${name}`) || siblingIdentities.has(`${kind}:${name}`);
7226
+ for (const agent of agentsToResolve) {
7227
+ for (const f of agentComposeRefAdvisories(agent.parsed, hasAsset, libraryPublisher)) {
7228
+ logWarn(`${agent.relPath} [${f.tag}] \u2014 ${f.text}`);
7229
+ warnings++;
7230
+ }
7231
+ }
6789
7232
  return { total: candidates.length, errors, warnings };
6790
7233
  }
6791
7234
  function findWorkspaceManifests(rootPath) {
@@ -6793,12 +7236,12 @@ function findWorkspaceManifests(rootPath) {
6793
7236
  function walk(dir) {
6794
7237
  let entries;
6795
7238
  try {
6796
- entries = fs8__default.readdirSync(dir, { withFileTypes: true });
7239
+ entries = fs9__default.readdirSync(dir, { withFileTypes: true });
6797
7240
  } catch {
6798
7241
  return;
6799
7242
  }
6800
7243
  for (const entry of entries) {
6801
- const full = path18__default.join(dir, entry.name);
7244
+ const full = path22__default.join(dir, entry.name);
6802
7245
  if (entry.isDirectory()) {
6803
7246
  if (!SKIP_DIRS.has(entry.name)) walk(full);
6804
7247
  } else if (entry.isFile() && /(^|\.)skaile\.yaml$/.test(entry.name)) {
@@ -6860,15 +7303,15 @@ function validateWorkspaceAssets(parsed, relPath) {
6860
7303
  }
6861
7304
  return errors;
6862
7305
  }
6863
- function validateWorkspaceManifests(rootPath) {
6864
- const absRoot = path18__default.resolve(rootPath);
7306
+ async function validateWorkspaceManifests(rootPath) {
7307
+ const absRoot = path22__default.resolve(rootPath);
6865
7308
  const files = findWorkspaceManifests(absRoot);
6866
7309
  let errors = 0;
6867
7310
  for (const file of files) {
6868
- const relPath = path18__default.relative(absRoot, file);
7311
+ const relPath = path22__default.relative(absRoot, file);
6869
7312
  let parsed;
6870
7313
  try {
6871
- parsed = parse(fs8__default.readFileSync(file, "utf-8")) ?? {};
7314
+ parsed = parse(fs9__default.readFileSync(file, "utf-8")) ?? {};
6872
7315
  } catch (e) {
6873
7316
  logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
6874
7317
  errors++;
@@ -6876,7 +7319,7 @@ function validateWorkspaceManifests(rootPath) {
6876
7319
  }
6877
7320
  errors += validateWorkspaceRefs(collectWorkspaceRefFields(parsed), relPath);
6878
7321
  errors += validateWorkspaceAssets(parsed, relPath);
6879
- for (const d of checkAgentInstances(path18__default.dirname(file), parsed)) {
7322
+ for (const d of checkAgentInstances(path22__default.dirname(file), parsed)) {
6880
7323
  const line = `${relPath} [agents] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`;
6881
7324
  if (d.severity === "error") {
6882
7325
  logErr(line);
@@ -6885,11 +7328,27 @@ function validateWorkspaceManifests(rootPath) {
6885
7328
  logWarn(line);
6886
7329
  }
6887
7330
  }
7331
+ const decoded = decodeSkaileYaml(fs9__default.readFileSync(file, "utf-8"));
7332
+ for (const d of decoded.diagnostics) {
7333
+ if (d.code !== "connector_missing_driver") continue;
7334
+ logErr(`${relPath} [connectors] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`);
7335
+ errors++;
7336
+ }
7337
+ if ((decoded.config?.connectors ?? []).length > 0) {
7338
+ const assets = await resolveRuntimeAssets(path22__default.dirname(file));
7339
+ if (!assets.warnings.some((w) => w.code === "repo_unavailable")) {
7340
+ for (const w of assets.warnings) {
7341
+ if (w.code !== "missing_driver" || !w.name) continue;
7342
+ logErr(`${relPath} [connectors] \u2014 ${w.code}: ${w.message}`);
7343
+ errors++;
7344
+ }
7345
+ }
7346
+ }
6888
7347
  }
6889
7348
  return { total: files.length, errors };
6890
7349
  }
6891
7350
  function validatePublishManifestRoots(rootPath) {
6892
- const absRoot = path18__default.resolve(rootPath);
7351
+ const absRoot = path22__default.resolve(rootPath);
6893
7352
  const manifest = loadSkPublishManifest(absRoot);
6894
7353
  if (!manifest) return 0;
6895
7354
  const missing = missingRootAssets(absRoot, manifest);
@@ -6901,7 +7360,7 @@ function validatePublishManifestRoots(rootPath) {
6901
7360
  return missing.length;
6902
7361
  }
6903
7362
  function validatePublishManifestRequires(rootPath) {
6904
- const problems = manifestRequiresProblems(path18__default.resolve(rootPath));
7363
+ const problems = manifestRequiresProblems(path22__default.resolve(rootPath));
6905
7364
  for (const p6 of problems) {
6906
7365
  logErr(
6907
7366
  `${SKAILE_MANIFEST_FILENAME} [assets] \u2014 ${p6.asset}: ${p6.message}. Use the \`kind:@<publisher>/name[#version]\` form.`
@@ -6910,20 +7369,29 @@ function validatePublishManifestRequires(rootPath) {
6910
7369
  return problems.length;
6911
7370
  }
6912
7371
  function validatePublishManifestPublisherSlugs(rootPath) {
6913
- const problems = manifestPublisherProblems(path18__default.resolve(rootPath));
7372
+ const problems = manifestPublisherProblems(path22__default.resolve(rootPath));
6914
7373
  for (const message of problems) logErr(message);
6915
7374
  return problems.length;
6916
7375
  }
7376
+ function validatePublishManifestParses(rootPath) {
7377
+ try {
7378
+ assertManifestEditable(path22__default.resolve(rootPath));
7379
+ return 0;
7380
+ } catch (err2) {
7381
+ logErr(err2 instanceof Error ? err2.message : String(err2));
7382
+ return 1;
7383
+ }
7384
+ }
6917
7385
  function validatePublishManifestVersions(rootPath) {
6918
- const absRoot = path18__default.resolve(rootPath);
7386
+ const absRoot = path22__default.resolve(rootPath);
6919
7387
  const manifest = loadSkPublishManifest(absRoot);
6920
7388
  if (!manifest || manifest.source) return 0;
6921
7389
  let warnings = 0;
6922
7390
  for (const a of manifest.assets ?? []) {
6923
7391
  if (!a.root || a.source || !a.version) continue;
6924
- const file = findAssetManifestFile(path18__default.join(absRoot, a.root), a.kind, a.name);
7392
+ const file = findAssetManifestFile(path22__default.join(absRoot, a.root), a.kind, a.name);
6925
7393
  if (!file) continue;
6926
- const res = parseManifestFile(file, fs8__default.readFileSync(file, "utf-8"));
7394
+ const res = parseManifestFile(file, fs9__default.readFileSync(file, "utf-8"));
6927
7395
  if (!res.ok) continue;
6928
7396
  const fileVersion = declaredVersion(res.data);
6929
7397
  if (fileVersion === void 0 || fileVersion === a.version) continue;
@@ -6931,7 +7399,7 @@ function validatePublishManifestVersions(rootPath) {
6931
7399
  manifestVersionMismatchMessage(
6932
7400
  assetEntryRef(a, manifest),
6933
7401
  a.version,
6934
- toPosix(path18__default.relative(absRoot, file)),
7402
+ toPosix(path22__default.relative(absRoot, file)),
6935
7403
  fileVersion
6936
7404
  )
6937
7405
  );
@@ -6940,7 +7408,7 @@ function validatePublishManifestVersions(rootPath) {
6940
7408
  return warnings;
6941
7409
  }
6942
7410
  function validatePublishManifestPublishers(rootPath) {
6943
- const absRoot = path18__default.resolve(rootPath);
7411
+ const absRoot = path22__default.resolve(rootPath);
6944
7412
  const manifest = loadSkPublishManifest(absRoot);
6945
7413
  if (!manifest || manifest.source) return 0;
6946
7414
  const bare = (p6) => p6.trim().replace(/^@/, "");
@@ -6948,15 +7416,15 @@ function validatePublishManifestPublishers(rootPath) {
6948
7416
  for (const a of manifest.assets ?? []) {
6949
7417
  const resolved = a.publisher ?? manifest.publisher;
6950
7418
  if (!a.root || a.source || !resolved) continue;
6951
- const file = findAssetManifestFile(path18__default.join(absRoot, a.root), a.kind, a.name);
7419
+ const file = findAssetManifestFile(path22__default.join(absRoot, a.root), a.kind, a.name);
6952
7420
  if (!file) continue;
6953
- const res = parseManifestFile(file, fs8__default.readFileSync(file, "utf-8"));
7421
+ const res = parseManifestFile(file, fs9__default.readFileSync(file, "utf-8"));
6954
7422
  if (!res.ok) continue;
6955
7423
  const meta = res.data.metadata;
6956
7424
  const declared = meta !== null && typeof meta === "object" ? meta.publisher : null;
6957
7425
  if (typeof declared !== "string" || bare(declared) === bare(resolved)) continue;
6958
7426
  logWarn(
6959
- `${toPosix(path18__default.relative(absRoot, file))} [publisher] \u2014 metadata.publisher "${bare(declared)}" differs from the manifest publisher "${bare(resolved)}" for ${assetEntryRef(a, manifest)}. The manifest wins and the file value is ignored: delete \`metadata.publisher\` from the file, or set the publisher in ${SKAILE_MANIFEST_FILENAME}.`
7427
+ `${toPosix(path22__default.relative(absRoot, file))} [publisher] \u2014 metadata.publisher "${bare(declared)}" differs from the manifest publisher "${bare(resolved)}" for ${assetEntryRef(a, manifest)}. The manifest wins and the file value is ignored: delete \`metadata.publisher\` from the file, or set the publisher in ${SKAILE_MANIFEST_FILENAME}.`
6960
7428
  );
6961
7429
  warnings++;
6962
7430
  }
@@ -6964,7 +7432,7 @@ function validatePublishManifestPublishers(rootPath) {
6964
7432
  }
6965
7433
  var EXCLUDED_PATHS = ["skaileup-shared/", "external/", "docs/"];
6966
7434
  function toPosix(p6) {
6967
- return p6.split(path18__default.sep).join("/");
7435
+ return p6.split(path22__default.sep).join("/");
6968
7436
  }
6969
7437
  function isExcludedPath(relPath) {
6970
7438
  const rel = toPosix(relPath);
@@ -6980,9 +7448,9 @@ var VERSIONED_KINDS = {
6980
7448
  };
6981
7449
  function readAssetVersion(c) {
6982
7450
  const kind = c.kind;
6983
- const fileName = path18__default.basename(c.filePath);
6984
- const dirName = path18__default.basename(path18__default.dirname(c.filePath));
6985
- const content = fs8__default.readFileSync(c.filePath, "utf-8");
7451
+ const fileName = path22__default.basename(c.filePath);
7452
+ const dirName = path22__default.basename(path22__default.dirname(c.filePath));
7453
+ const content = fs9__default.readFileSync(c.filePath, "utf-8");
6986
7454
  if (c.filePath.endsWith(".md")) {
6987
7455
  const res = parseManifestFile(c.filePath, content);
6988
7456
  const data = res.ok ? res.data : {};
@@ -7015,26 +7483,26 @@ function readAssetVersion(c) {
7015
7483
  };
7016
7484
  }
7017
7485
  function collectAssetVersions(root) {
7018
- if (!fs8__default.existsSync(root)) return [];
7486
+ if (!fs9__default.existsSync(root)) return [];
7019
7487
  const assets = [];
7020
7488
  for (const c of findManifestCandidates(root)) {
7021
7489
  if (!VERSIONED_KINDS[c.kind]) continue;
7022
7490
  if (c.filePath.endsWith(".flow.json")) continue;
7023
- if (isExcludedPath(path18__default.relative(root, c.filePath))) continue;
7491
+ if (isExcludedPath(path22__default.relative(root, c.filePath))) continue;
7024
7492
  assets.push(readAssetVersion(c));
7025
7493
  }
7026
7494
  return assets;
7027
7495
  }
7028
7496
  function assetLocation(a, root) {
7029
- return toPosix(path18__default.relative(root, a.filePath));
7497
+ return toPosix(path22__default.relative(root, a.filePath));
7030
7498
  }
7031
7499
  function findChangelogUnit(assetRelPath, root) {
7032
- let dir = path18__default.posix.dirname(toPosix(assetRelPath));
7500
+ let dir = path22__default.posix.dirname(toPosix(assetRelPath));
7033
7501
  for (; ; ) {
7034
7502
  const candidate = dir === "." ? "CHANGELOG.md" : `${dir}/CHANGELOG.md`;
7035
- if (fs8__default.existsSync(path18__default.join(root, candidate))) return candidate;
7503
+ if (fs9__default.existsSync(path22__default.join(root, candidate))) return candidate;
7036
7504
  if (dir === ".") return null;
7037
- dir = path18__default.posix.dirname(dir);
7505
+ dir = path22__default.posix.dirname(dir);
7038
7506
  }
7039
7507
  }
7040
7508
  function checkChangelogUnits(modifiedFiles, root) {
@@ -7084,7 +7552,7 @@ function checkVersionBumps(assets, root) {
7084
7552
  let warnings = 0;
7085
7553
  for (const a of assets) {
7086
7554
  if (!a.version) continue;
7087
- const relPath = toPosix(path18__default.relative(root, a.filePath));
7555
+ const relPath = toPosix(path22__default.relative(root, a.filePath));
7088
7556
  try {
7089
7557
  const headContent = execFileSync("git", ["show", `HEAD:./${relPath}`], {
7090
7558
  cwd: root,
@@ -7117,7 +7585,7 @@ function checkFlowVersionPins(assets, root) {
7117
7585
  pins = flowSkillVersionPins(loadFlow(f.filePath));
7118
7586
  } catch (err2) {
7119
7587
  logWarn(
7120
- `flow:${f.name} (${path18__default.relative(root, f.filePath)}) \u2014 could not be read: ${err2 instanceof Error ? err2.message : err2}`
7588
+ `flow:${f.name} (${path22__default.relative(root, f.filePath)}) \u2014 could not be read: ${err2 instanceof Error ? err2.message : err2}`
7121
7589
  );
7122
7590
  warnings++;
7123
7591
  continue;
@@ -7135,19 +7603,34 @@ function checkFlowVersionPins(assets, root) {
7135
7603
  }
7136
7604
  function resolveCheckRoot(pathArg) {
7137
7605
  if (pathArg) {
7138
- const abs = path18__default.resolve(pathArg);
7139
- if (!fs8__default.existsSync(abs)) {
7606
+ const abs = path22__default.resolve(pathArg);
7607
+ if (!fs9__default.existsSync(abs)) {
7140
7608
  logErr(`Path does not exist: ${abs}`);
7141
7609
  return null;
7142
7610
  }
7143
7611
  return abs;
7144
7612
  }
7145
- for (let dir = process.cwd(); ; dir = path18__default.dirname(dir)) {
7146
- if (fs8__default.existsSync(path18__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
7147
- if (path18__default.dirname(dir) === dir) return AI_RESOURCES;
7613
+ for (let dir = process.cwd(); ; dir = path22__default.dirname(dir)) {
7614
+ if (fs9__default.existsSync(path22__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
7615
+ if (path22__default.dirname(dir) === dir) return AI_RESOURCES;
7148
7616
  }
7149
7617
  }
7150
- function changedFiles(root, ref) {
7618
+ function isInGitWorkTree(root) {
7619
+ try {
7620
+ return execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
7621
+ cwd: root,
7622
+ encoding: "utf-8",
7623
+ stdio: ["ignore", "pipe", "ignore"]
7624
+ }).trim() === "true";
7625
+ } catch {
7626
+ return false;
7627
+ }
7628
+ }
7629
+ function changedFiles(root, ref, what, opts = {}) {
7630
+ if (!isInGitWorkTree(root)) {
7631
+ logErr(`${what} needs a git repository: ${root} is not inside a git work tree.`);
7632
+ return null;
7633
+ }
7151
7634
  try {
7152
7635
  const out = execFileSync(
7153
7636
  "git",
@@ -7158,7 +7641,16 @@ function changedFiles(root, ref) {
7158
7641
  stdio: ["ignore", "pipe", "pipe"]
7159
7642
  }
7160
7643
  );
7161
- return out.trim().split("\n").filter(Boolean);
7644
+ const changed = out.trim().split("\n").filter(Boolean);
7645
+ if (opts.untracked) {
7646
+ const fresh = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
7647
+ cwd: root,
7648
+ encoding: "utf-8",
7649
+ stdio: ["ignore", "pipe", "pipe"]
7650
+ });
7651
+ changed.push(...fresh.trim().split("\n").filter(Boolean));
7652
+ }
7653
+ return changed;
7162
7654
  } catch (err2) {
7163
7655
  const stderr = err2 instanceof Error && "stderr" in err2 ? String(err2.stderr).trim() : "";
7164
7656
  const reason = (stderr || (err2 instanceof Error ? err2.message : String(err2))).split("\n")[0];
@@ -7166,6 +7658,22 @@ function changedFiles(root, ref) {
7166
7658
  return null;
7167
7659
  }
7168
7660
  }
7661
+ function assetOwnDir(a) {
7662
+ const dir = path22__default.dirname(a.filePath);
7663
+ if (["skill", "agent", "contract"].includes(a.kind) || path22__default.basename(dir) === a.name) return dir;
7664
+ return null;
7665
+ }
7666
+ function assetChanged(a, changedAbs) {
7667
+ if (changedAbs.has(a.filePath)) return true;
7668
+ const dir = assetOwnDir(a);
7669
+ if (dir === null) return false;
7670
+ for (const f of changedAbs) {
7671
+ const rel = path22__default.relative(dir, f);
7672
+ if (rel.startsWith("..") || path22__default.isAbsolute(rel)) continue;
7673
+ if (!isNonAssetPath(toPosix(rel))) return true;
7674
+ }
7675
+ return false;
7676
+ }
7169
7677
  function runVersionsCheck(pathArg, opts) {
7170
7678
  const root = resolveCheckRoot(pathArg);
7171
7679
  if (root === null) {
@@ -7174,13 +7682,13 @@ function runVersionsCheck(pathArg, opts) {
7174
7682
  }
7175
7683
  let assets = collectAssetVersions(root);
7176
7684
  if (opts.changedOnly) {
7177
- const changed = changedFiles(root, "HEAD");
7685
+ const changed = changedFiles(root, "HEAD", "--changed-only", { untracked: true });
7178
7686
  if (changed === null) {
7179
7687
  process.exit(1);
7180
7688
  return;
7181
7689
  }
7182
- const changedAbs = new Set(changed.map((f) => path18__default.resolve(root, f)));
7183
- assets = assets.filter((a) => changedAbs.has(a.filePath));
7690
+ const changedAbs = new Set(changed.map((f) => path22__default.resolve(root, f)));
7691
+ assets = assets.filter((a) => assetChanged(a, changedAbs));
7184
7692
  }
7185
7693
  logInfo(`Checking versions in ${root}`);
7186
7694
  const versionCheck = checkAssetVersions(assets, root);
@@ -7212,22 +7720,23 @@ function makeValidateCommand() {
7212
7720
  "--strict-conformance",
7213
7721
  "Treat Agent Skills (agentskills.io) standard findings as errors"
7214
7722
  ).action(async (targetPath, opts) => {
7215
- const absPath = path18__default.resolve(targetPath);
7723
+ const absPath = path22__default.resolve(targetPath);
7216
7724
  logInfo(`Validating manifests in ${absPath}`);
7217
7725
  const { total, errors, warnings } = validateManifests(
7218
7726
  absPath,
7219
7727
  opts.strictConformance ?? false
7220
7728
  );
7221
- const ws = validateWorkspaceManifests(absPath);
7729
+ const ws = await validateWorkspaceManifests(absPath);
7222
7730
  const rootErrors = validatePublishManifestRoots(absPath);
7223
7731
  const slugErrors = validatePublishManifestPublisherSlugs(absPath);
7732
+ const parseErrors = validatePublishManifestParses(absPath);
7224
7733
  const requiresErrors = validatePublishManifestRequires(absPath);
7225
7734
  const versionWarnings = validatePublishManifestVersions(absPath);
7226
7735
  const publisherWarnings = validatePublishManifestPublishers(absPath);
7227
7736
  const dependencyProblems = await unresolvedManifestDependencies(absPath);
7228
7737
  for (const w of dependencyProblems) logWarn(w);
7229
7738
  const dependencyWarnings = dependencyProblems.length;
7230
- const totalErrors = errors + ws.errors + rootErrors + slugErrors + requiresErrors;
7739
+ const totalErrors = errors + ws.errors + rootErrors + slugErrors + parseErrors + requiresErrors;
7231
7740
  console.log();
7232
7741
  warnIgnoredDomainFiles(absPath);
7233
7742
  warnLegacyBundleFiles(absPath);
@@ -7253,7 +7762,7 @@ function makeValidateCommand() {
7253
7762
  process.exit(1);
7254
7763
  return;
7255
7764
  }
7256
- const modifiedFiles = changedFiles(root, opts.base);
7765
+ const modifiedFiles = changedFiles(root, opts.base, "changelog");
7257
7766
  if (modifiedFiles === null) {
7258
7767
  process.exit(1);
7259
7768
  return;
@@ -7302,7 +7811,7 @@ function itemFromRef(raw, defaultKind, ctx) {
7302
7811
  return { kind: prefixed[1], ref: value };
7303
7812
  }
7304
7813
  if (PATH_LIKE.test(value)) return { kind: defaultKind, ref: value };
7305
- if (defaultKind === "skill" && !value.includes("/") && existsSync(path18__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
7814
+ if (defaultKind === "skill" && !value.includes("/") && existsSync(path22__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
7306
7815
  return { kind: "skill", ref: `./skills/${value}` };
7307
7816
  }
7308
7817
  return { kind: defaultKind, ref: `${defaultKind}:${value}` };
@@ -7438,7 +7947,7 @@ function migrateAgentYaml(source, options) {
7438
7947
  manual.push("metadata.soul: not a string; left unchanged");
7439
7948
  continue;
7440
7949
  }
7441
- if (path18__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
7950
+ if (path22__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
7442
7951
  notes.push("metadata.soul \u2192 dropped (SOUL.md is a convention file)");
7443
7952
  } else {
7444
7953
  derived.push({ kind: "persona", ref: soul });
@@ -7672,7 +8181,7 @@ function migrateSubagents(skaileYamlPath, source) {
7672
8181
  if (!isMap(agentNode)) return void 0;
7673
8182
  const subNode = agentNode.get("subagents", true);
7674
8183
  if (!isMap(subNode)) return void 0;
7675
- const dir = path18__default.dirname(skaileYamlPath);
8184
+ const dir = path22__default.dirname(skaileYamlPath);
7676
8185
  const notes = [];
7677
8186
  const manual = [];
7678
8187
  const changes = [];
@@ -7690,10 +8199,10 @@ function migrateSubagents(skaileYamlPath, source) {
7690
8199
  continue;
7691
8200
  }
7692
8201
  const id = instanceId(name);
7693
- const assetDir = path18__default.join(dir, ".skaile", "agents", id);
8202
+ const assetDir = path22__default.join(dir, ".skaile", "agents", id);
7694
8203
  if (takenIds.has(id) || existsSync(assetDir)) {
7695
8204
  manual.push(
7696
- `agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path18__default.relative(dir, assetDir)} already exists`}; left in place`
8205
+ `agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path22__default.relative(dir, assetDir)} already exists`}; left in place`
7697
8206
  );
7698
8207
  continue;
7699
8208
  }
@@ -7717,13 +8226,13 @@ function migrateSubagents(skaileYamlPath, source) {
7717
8226
  manifest.tools = { ...allowed ? { allowed } : {}, ...denied ? { denied } : {} };
7718
8227
  }
7719
8228
  const text = stringify(manifest, { lineWidth: 0 });
7720
- const manifestPath = path18__default.join(assetDir, "agent.yaml");
8229
+ const manifestPath = path22__default.join(assetDir, "agent.yaml");
7721
8230
  changes.push({ type: "create", path: manifestPath, after: text });
7722
8231
  assetManifests.push({ file: manifestPath, text });
7723
8232
  if (typeof spec.prompt === "string" && spec.prompt.trim() !== "") {
7724
8233
  changes.push({
7725
8234
  type: "create",
7726
- path: path18__default.join(assetDir, "SOUL.md"),
8235
+ path: path22__default.join(assetDir, "SOUL.md"),
7727
8236
  after: `${spec.prompt.replace(/\s+$/, "")}
7728
8237
  `
7729
8238
  });
@@ -7782,7 +8291,7 @@ function validateMigratedAgent(text, registry) {
7782
8291
  function collectAgentFiles(paths) {
7783
8292
  const files = /* @__PURE__ */ new Set();
7784
8293
  for (const input of paths) {
7785
- const abs = path18__default.resolve(input);
8294
+ const abs = path22__default.resolve(input);
7786
8295
  if (!existsSync(abs)) continue;
7787
8296
  if (statSync(abs).isDirectory()) {
7788
8297
  for (const f of walkFiles(abs, (b) => b === "agent.yaml" || b === "skaile.yaml"))
@@ -7799,7 +8308,7 @@ function planAgentMigration(options) {
7799
8308
  const reports = [];
7800
8309
  for (const file of collectAgentFiles(options.paths)) {
7801
8310
  const source = readText(file);
7802
- const base = path18__default.basename(file);
8311
+ const base = path22__default.basename(file);
7803
8312
  if (base === "skaile.yaml") {
7804
8313
  const result = migrateSubagents(file, source);
7805
8314
  if (!result) continue;
@@ -7807,7 +8316,7 @@ function planAgentMigration(options) {
7807
8316
  for (const asset of result.assetManifests) {
7808
8317
  const v = validateMigratedAgent(asset.text, options.registry);
7809
8318
  validation2.errors.push(
7810
- ...v.errors.map((e) => `${path18__default.basename(path18__default.dirname(asset.file))}: ${e}`)
8319
+ ...v.errors.map((e) => `${path22__default.basename(path22__default.dirname(asset.file))}: ${e}`)
7811
8320
  );
7812
8321
  validation2.warnings.push(...v.warnings);
7813
8322
  }
@@ -7835,7 +8344,7 @@ function planAgentMigration(options) {
7835
8344
  });
7836
8345
  continue;
7837
8346
  }
7838
- migration = migrateAgentYaml(source, { agentDir: path18__default.dirname(file), knownKinds });
8347
+ migration = migrateAgentYaml(source, { agentDir: path22__default.dirname(file), knownKinds });
7839
8348
  } catch (error) {
7840
8349
  reports.push({
7841
8350
  file,
@@ -7865,7 +8374,7 @@ function planAgentMigration(options) {
7865
8374
  var DEFAULT_PUBLISHER = "skaile-ai";
7866
8375
  var PRESET_DEFAULT_VERSION = "1.0.0";
7867
8376
  var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
7868
- var posix2 = (p6) => p6.split(path18__default.sep).join("/");
8377
+ var posix2 = (p6) => p6.split(path22__default.sep).join("/");
7869
8378
  var MOVED_KINDS = { persona: "PERSONA.md", ruleset: "RULESET.md" };
7870
8379
  var KIND_MANIFEST_FILES = /* @__PURE__ */ new Set(["PERSONA.md", "RULESET.md", "SKILL.md"]);
7871
8380
  function readFrontmatterType(text) {
@@ -7896,14 +8405,14 @@ function planMarkdownMoves(root, knownKinds, manual, unknownTypes) {
7896
8405
  if (!text.startsWith("---")) continue;
7897
8406
  const found = readFrontmatterType(text);
7898
8407
  if (!found) continue;
7899
- const base = path18__default.basename(file);
7900
- const inAgentParts = file.split(path18__default.sep).includes("_agent-parts");
8408
+ const base = path22__default.basename(file);
8409
+ const inAgentParts = file.split(path22__default.sep).includes("_agent-parts");
7901
8410
  const targetName = MOVED_KINDS[found.type];
7902
8411
  if (targetName !== void 0 && !KIND_MANIFEST_FILES.has(base)) {
7903
- const to = path18__default.join(path18__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
8412
+ const to = path22__default.join(path22__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
7904
8413
  if (existsSync(to) || targets.has(to)) {
7905
8414
  manual.push(
7906
- `${posix2(path18__default.relative(root, file))}: ${posix2(path18__default.relative(root, to))} already exists; not moved`
8415
+ `${posix2(path22__default.relative(root, file))}: ${posix2(path22__default.relative(root, to))} already exists; not moved`
7907
8416
  );
7908
8417
  continue;
7909
8418
  }
@@ -7924,13 +8433,13 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
7924
8433
  const changes = [];
7925
8434
  for (const file of walkFiles(root, (b) => b === "agent.yaml")) {
7926
8435
  const source = readText(file);
7927
- const agentDir = path18__default.dirname(file);
8436
+ const agentDir = path22__default.dirname(file);
7928
8437
  let hits = 0;
7929
8438
  const refRewrite = (_kind, ref) => {
7930
- const moved = byOldPath.get(path18__default.resolve(agentDir, ref));
8439
+ const moved = byOldPath.get(path22__default.resolve(agentDir, ref));
7931
8440
  if (moved === void 0) return ref;
7932
8441
  hits++;
7933
- const rel = posix2(path18__default.relative(agentDir, moved));
8442
+ const rel = posix2(path22__default.relative(agentDir, moved));
7934
8443
  return rel.startsWith(".") ? rel : `./${rel}`;
7935
8444
  };
7936
8445
  let output;
@@ -7947,7 +8456,7 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
7947
8456
  if (hits === 0 || output === source) continue;
7948
8457
  changes.push({ type: "write", path: file, before: source, after: output });
7949
8458
  notes.push(
7950
- `${posix2(path18__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
8459
+ `${posix2(path22__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
7951
8460
  );
7952
8461
  }
7953
8462
  return changes;
@@ -7958,10 +8467,9 @@ function presetItemRef(dep, publisher) {
7958
8467
  const [, kind, rest] = match;
7959
8468
  return rest.startsWith("@") ? dep.trim() : `${kind}:@${publisher}/${rest}`;
7960
8469
  }
7961
- function presetText(name, description, refs, publisher, version) {
8470
+ function presetText(name, description, refs, version) {
7962
8471
  return stringify(
7963
8472
  {
7964
- publisher,
7965
8473
  name,
7966
8474
  version,
7967
8475
  description: description && description.trim() !== "" ? description : `Preset ${name}`,
@@ -7972,14 +8480,14 @@ function presetText(name, description, refs, publisher, version) {
7972
8480
  }
7973
8481
  function skillDirs(dir) {
7974
8482
  try {
7975
- return readdirSync(path18__default.join(dir, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync(path18__default.join(dir, "skills", e.name, "SKILL.md"))).map((e) => e.name).sort();
8483
+ return readdirSync(path22__default.join(dir, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync(path22__default.join(dir, "skills", e.name, "SKILL.md"))).map((e) => e.name).sort();
7976
8484
  } catch {
7977
8485
  return [];
7978
8486
  }
7979
8487
  }
7980
8488
  function repoPublisher(root) {
7981
8489
  for (const name of ["skaile.manifest.yaml", "skaile.yaml"]) {
7982
- const file = path18__default.join(root, name);
8490
+ const file = path22__default.join(root, name);
7983
8491
  if (!existsSync(file)) continue;
7984
8492
  try {
7985
8493
  const parsed = parse(readText(file));
@@ -7995,9 +8503,9 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
7995
8503
  const changes = [];
7996
8504
  const presets = [];
7997
8505
  const handled = /* @__PURE__ */ new Set();
7998
- const rel = (p6) => posix2(path18__default.relative(root, p6));
8506
+ const rel = (p6) => posix2(path22__default.relative(root, p6));
7999
8507
  const convert = (name, bundleFile, dir) => {
8000
- const target = path18__default.join(dir, `${name}.preset.yaml`);
8508
+ const target = path22__default.join(dir === root ? path22__default.join(dir, name) : dir, `${name}.preset.yaml`);
8001
8509
  if (existsSync(target)) {
8002
8510
  manual.push(`${rel(target)} already exists; bundle ${name} not converted`);
8003
8511
  return;
@@ -8015,6 +8523,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
8015
8523
  const declared = typeof parsed.version === "string" || typeof parsed.version === "number" ? String(parsed.version) : void 0;
8016
8524
  if (declared !== void 0 && SEMVER_RE.test(declared)) version = declared;
8017
8525
  else if (declared !== void 0) versionNote = `version ${declared} \u2192 ${version}`;
8526
+ else versionNote = `version (none) \u2192 ${version}`;
8018
8527
  const deps = Array.isArray(parsed.dependencies) ? parsed.dependencies : [];
8019
8528
  refs = deps.filter((d) => typeof d === "string").map((d) => presetItemRef(d, publisher));
8020
8529
  if (refs.length !== deps.length) {
@@ -8028,11 +8537,11 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
8028
8537
  }
8029
8538
  if (refs.length === 0) {
8030
8539
  manual.push(
8031
- `bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path18__default.join(dir, "skills"))}`}; no preset generated`
8540
+ `bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path22__default.join(dir, "skills"))}`}; no preset generated`
8032
8541
  );
8033
8542
  return;
8034
8543
  }
8035
- const after = presetText(name, description, refs, publisher, version);
8544
+ const after = presetText(name, description, refs, version);
8036
8545
  if (before !== void 0 && bundleFile) {
8037
8546
  changes.push({ type: "move", from: bundleFile, to: target, before, after });
8038
8547
  handled.add(bundleFile);
@@ -8052,18 +8561,18 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
8052
8561
  const assets = Array.isArray(raw.assets) ? raw.assets : [];
8053
8562
  for (const entry of assets) {
8054
8563
  if (!isRecord(entry) || entry.kind !== "bundle" || typeof entry.name !== "string") continue;
8055
- const baseDir = path18__default.dirname(file);
8056
- const entryRoot = typeof entry.root === "string" ? path18__default.join(baseDir, entry.root) : baseDir;
8564
+ const baseDir = path22__default.dirname(file);
8565
+ const entryRoot = typeof entry.root === "string" ? path22__default.join(baseDir, entry.root) : baseDir;
8057
8566
  const files = Array.isArray(entry.files) ? entry.files : [];
8058
8567
  const bundleName = files.find(
8059
8568
  (f) => typeof f === "string" && f.endsWith(".bundle.yaml")
8060
8569
  );
8061
- convert(entry.name, bundleName ? path18__default.join(entryRoot, bundleName) : void 0, entryRoot);
8570
+ convert(entry.name, bundleName ? path22__default.join(entryRoot, bundleName) : void 0, entryRoot);
8062
8571
  }
8063
8572
  }
8064
8573
  for (const bundleFile of walkFiles(root, (b) => b.endsWith(".bundle.yaml"))) {
8065
8574
  if (handled.has(bundleFile)) continue;
8066
- const base = path18__default.basename(bundleFile);
8575
+ const base = path22__default.basename(bundleFile);
8067
8576
  let name = base.replace(/\.bundle\.yaml$/, "");
8068
8577
  try {
8069
8578
  const parsed = parse(readText(bundleFile));
@@ -8072,7 +8581,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
8072
8581
  } catch {
8073
8582
  }
8074
8583
  if (presets.some((p6) => p6.bundleFile === bundleFile)) continue;
8075
- convert(name, bundleFile, path18__default.dirname(bundleFile));
8584
+ convert(name, bundleFile, path22__default.dirname(bundleFile));
8076
8585
  }
8077
8586
  return changes;
8078
8587
  }
@@ -8082,8 +8591,8 @@ function planSkaileYaml(root, file, source, notes, manual) {
8082
8591
  if (doc.errors.length > 0 || !isMap(doc.contents)) return [];
8083
8592
  const map = doc.contents;
8084
8593
  const raw = doc.toJS();
8085
- const dir = path18__default.dirname(file);
8086
- const rel = (p6) => posix2(path18__default.relative(root, p6));
8594
+ const dir = path22__default.dirname(file);
8595
+ const rel = (p6) => posix2(path22__default.relative(root, p6));
8087
8596
  const changes = [];
8088
8597
  let changed = false;
8089
8598
  const deps = map.get("dependencies", true);
@@ -8100,7 +8609,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
8100
8609
  const hasPublication = PUBLICATION_KEYS.some((k) => raw[k] !== void 0);
8101
8610
  let remove = false;
8102
8611
  if (hasPublication) {
8103
- const manifestPath = path18__default.join(dir, "skaile.manifest.yaml");
8612
+ const manifestPath = path22__default.join(dir, "skaile.manifest.yaml");
8104
8613
  if (existsSync(manifestPath)) {
8105
8614
  manual.push(
8106
8615
  `${rel(file)}: publisher/version/assets left in place \u2014 ${rel(manifestPath)} already exists; merge by hand`
@@ -8157,7 +8666,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
8157
8666
  return changes;
8158
8667
  }
8159
8668
  function planAssetMigration(options) {
8160
- const root = path18__default.resolve(options.root);
8669
+ const root = path22__default.resolve(options.root);
8161
8670
  const knownKinds = new Set(options.registry.getAllKinds());
8162
8671
  const notes = [];
8163
8672
  const manual = [];
@@ -8165,7 +8674,7 @@ function planAssetMigration(options) {
8165
8674
  const { moves, changes: moveChanges } = planMarkdownMoves(root, knownKinds, manual, unknownTypes);
8166
8675
  for (const move of moves) {
8167
8676
  notes.push(
8168
- `${posix2(path18__default.relative(root, move.from))} \u2192 ${posix2(path18__default.relative(root, move.to))} (${move.kind})`
8677
+ `${posix2(path22__default.relative(root, move.from))} \u2192 ${posix2(path22__default.relative(root, move.to))} (${move.kind})`
8169
8678
  );
8170
8679
  }
8171
8680
  const agentChanges = planAgentRefRewrites(root, moves, knownKinds, notes);
@@ -8177,7 +8686,7 @@ function planAssetMigration(options) {
8177
8686
  const raw = parse(source);
8178
8687
  if (isRecord(raw)) skaileYamls.push({ file, source, raw });
8179
8688
  } catch {
8180
- manual.push(`${posix2(path18__default.relative(root, file))}: invalid YAML; skipped`);
8689
+ manual.push(`${posix2(path22__default.relative(root, file))}: invalid YAML; skipped`);
8181
8690
  }
8182
8691
  }
8183
8692
  const publisher = repoPublisher(root);
@@ -8331,7 +8840,7 @@ function workspaceConfigFiles(dir) {
8331
8840
  } catch {
8332
8841
  return [];
8333
8842
  }
8334
- return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path18__default.join(dir, name));
8843
+ return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path22__default.join(dir, name));
8335
8844
  }
8336
8845
  function readAgentConfigBlock(raw) {
8337
8846
  const key = AGENT_CONFIG_KEYS.find((candidate) => raw[candidate] !== void 0);
@@ -8343,7 +8852,7 @@ function readAgentConfigBlock(raw) {
8343
8852
  return flat ? { key, profiles: { default: profiles }, flat } : { key, profiles, flat };
8344
8853
  }
8345
8854
  function planProviderMigration(options) {
8346
- const projectDir = path18__default.resolve(options.projectDir);
8855
+ const projectDir = path22__default.resolve(options.projectDir);
8347
8856
  const registryPath = options.workspace ? workspaceProviderRegistryPath(projectDir) : userProviderRegistryPath();
8348
8857
  const plan = {
8349
8858
  registryPath,
@@ -8359,7 +8868,7 @@ function planProviderMigration(options) {
8359
8868
  raw = parseDocument(readFileSync(file, "utf-8")).toJS() ?? {};
8360
8869
  } catch (error) {
8361
8870
  plan.warnings.push(
8362
- `${path18__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
8871
+ `${path22__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
8363
8872
  );
8364
8873
  continue;
8365
8874
  }
@@ -8408,7 +8917,7 @@ function planProviderMigration(options) {
8408
8917
  });
8409
8918
  if (!model) {
8410
8919
  plan.warnings.push(
8411
- `${path18__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
8920
+ `${path22__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
8412
8921
  );
8413
8922
  }
8414
8923
  touched = true;
@@ -8475,7 +8984,7 @@ function printPlan(plan) {
8475
8984
  for (const entry of plan.entries) {
8476
8985
  const base = entry.entry.base_url ?? S.dim("(transport-derived)");
8477
8986
  console.log(
8478
- ` ${S.label(`${path18__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
8987
+ ` ${S.label(`${path22__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
8479
8988
  );
8480
8989
  console.log(` \u2192 providers.yml ${S.bold(entry.providerId)} ${base}`);
8481
8990
  console.log(
@@ -8491,7 +9000,7 @@ function printPlan(plan) {
8491
9000
  console.log();
8492
9001
  }
8493
9002
  async function runMigrateProviders(opts) {
8494
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
9003
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
8495
9004
  const plan = planProviderMigration({ projectDir, workspace: opts.workspace });
8496
9005
  for (const warning of plan.warnings) logWarn(warning);
8497
9006
  if (plan.entries.length === 0 && Object.keys(plan.providers).length === 0) {
@@ -8573,7 +9082,8 @@ var ASSETS_HELP = `
8573
9082
  Rewrites (run on a repo root):
8574
9083
  type: persona|ruleset markdown <n>.md -> <n>/PERSONA.md | <n>/RULESET.md (type: dropped);
8575
9084
  agent persona:/rules: refs to the old path become composes items
8576
- *.bundle.yaml <name>.preset.yaml beside it (items: kind:@publisher/name);
9085
+ *.bundle.yaml <name>.preset.yaml beside it, or <name>/<name>.preset.yaml
9086
+ for a bundle at the repo root (items: kind:@publisher/name);
8577
9087
  kind: bundle entries of skaile.yaml#assets become kind: preset
8578
9088
  skaile.yaml dependencies bundle:@... -> preset:@...
8579
9089
  skaile.yaml publisher/version/assets
@@ -8622,7 +9132,7 @@ async function runMigrateAgents(paths, opts) {
8622
9132
  let failures = 0;
8623
9133
  let manualCount = 0;
8624
9134
  for (const report of plan.reports) {
8625
- const rel = path18__default.relative(base, report.file) || report.file;
9135
+ const rel = path22__default.relative(base, report.file) || report.file;
8626
9136
  for (const note of report.notes) console.log(` ${S.label(rel)} ${note}`);
8627
9137
  for (const note of report.manual) {
8628
9138
  manualCount++;
@@ -8649,14 +9159,14 @@ async function runMigrateAssets(root, opts) {
8649
9159
  const write = resolveMode(opts);
8650
9160
  const base = process.cwd();
8651
9161
  const plan = planAssetMigration({
8652
- root: path18__default.resolve(root ?? base),
9162
+ root: path22__default.resolve(root ?? base),
8653
9163
  registry: getKindRegistry()
8654
9164
  });
8655
9165
  for (const note of plan.notes) console.log(` ${note}`);
8656
9166
  for (const note of plan.manual) logWarn(note);
8657
9167
  for (const { file, type } of plan.unknownTypes) {
8658
9168
  logWarn(
8659
- `${path18__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
9169
+ `${path22__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
8660
9170
  );
8661
9171
  }
8662
9172
  printChanges(plan.changes, base);
@@ -8679,8 +9189,8 @@ function makeNpxCommand() {
8679
9189
  skills.command("add <url>").description(
8680
9190
  "Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
8681
9191
  ).requiredOption("--skill <name>", "Skill name to install from the repo").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", `Agent framework (${TARGET_DEFAULT_HINT})`).option("--global", "Deploy globally").action(async (url, opts) => {
8682
- const projectDir = path18__default.resolve(opts.projectDir);
8683
- const projYaml = path18__default.join(projectDir, "skaile.yaml");
9192
+ const projectDir = path22__default.resolve(opts.projectDir);
9193
+ const projYaml = path22__default.join(projectDir, "skaile.yaml");
8684
9194
  if (!existsSync(projYaml)) {
8685
9195
  logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
8686
9196
  process.exit(1);
@@ -8693,11 +9203,11 @@ function makeNpxCommand() {
8693
9203
  }
8694
9204
  const spinner = createSpinner();
8695
9205
  const key = sourceCacheKey(url);
8696
- const clonePath = path18__default.join(getGlobalCacheDir(), key);
9206
+ const clonePath = path22__default.join(getGlobalCacheDir(), key);
8697
9207
  spinner.start(`Cloning ${url}`);
8698
9208
  try {
8699
9209
  if (!existsSync(clonePath)) {
8700
- mkdirSync(path18__default.dirname(clonePath), { recursive: true });
9210
+ mkdirSync(path22__default.dirname(clonePath), { recursive: true });
8701
9211
  execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
8702
9212
  }
8703
9213
  spinner.stop(`Cloned to ${key}`);
@@ -8752,7 +9262,7 @@ function makeNpxCommand() {
8752
9262
  return npx;
8753
9263
  }
8754
9264
  function resolvePublisher(clonePath, url) {
8755
- const manifestPath = path18__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
9265
+ const manifestPath = path22__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
8756
9266
  if (existsSync(manifestPath)) {
8757
9267
  try {
8758
9268
  const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
@@ -8765,12 +9275,12 @@ function resolvePublisher(clonePath, url) {
8765
9275
  return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
8766
9276
  }
8767
9277
  function resolveSkillName(clonePath, requested) {
8768
- const skillsDir = path18__default.join(clonePath, "skills");
8769
- if (existsSync(path18__default.join(skillsDir, requested, "SKILL.md"))) return requested;
9278
+ const skillsDir = path22__default.join(clonePath, "skills");
9279
+ if (existsSync(path22__default.join(skillsDir, requested, "SKILL.md"))) return requested;
8770
9280
  if (!existsSync(skillsDir)) return requested;
8771
9281
  for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
8772
9282
  if (!entry.isDirectory()) continue;
8773
- const md = path18__default.join(skillsDir, entry.name, "SKILL.md");
9283
+ const md = path22__default.join(skillsDir, entry.name, "SKILL.md");
8774
9284
  if (!existsSync(md)) continue;
8775
9285
  try {
8776
9286
  const { data } = parseFrontmatter(readFileSync(md, "utf8"));
@@ -8803,7 +9313,7 @@ function makeOutdatedCommand() {
8803
9313
  requireProjectConfig(opts.projectDir);
8804
9314
  const am2 = new AssetManager({
8805
9315
  registry: getKindRegistry(),
8806
- projectDir: path18__default.resolve(opts.projectDir),
9316
+ projectDir: path22__default.resolve(opts.projectDir),
8807
9317
  driverTarget: opts.target
8808
9318
  });
8809
9319
  const entries = await am2.outdated();
@@ -8846,7 +9356,7 @@ function makePatchCommand() {
8846
9356
  cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8847
9357
  const am2 = new AssetManager({
8848
9358
  registry: getKindRegistry(),
8849
- projectDir: path18__default.resolve(opts.projectDir)
9359
+ projectDir: path22__default.resolve(opts.projectDir)
8850
9360
  });
8851
9361
  try {
8852
9362
  const dest = await am2.patch(ref);
@@ -8860,7 +9370,7 @@ function makePatchCommand() {
8860
9370
  cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8861
9371
  const am2 = new AssetManager({
8862
9372
  registry: getKindRegistry(),
8863
- projectDir: path18__default.resolve(opts.projectDir)
9373
+ projectDir: path22__default.resolve(opts.projectDir)
8864
9374
  });
8865
9375
  try {
8866
9376
  const patchFile = await am2.patchCommit(ref);
@@ -8874,7 +9384,7 @@ function makePatchCommand() {
8874
9384
  cmd.command("submit <ref>").description("Apply patch to repo clone and prepare for PR").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8875
9385
  const am2 = new AssetManager({
8876
9386
  registry: getKindRegistry(),
8877
- projectDir: path18__default.resolve(opts.projectDir)
9387
+ projectDir: path22__default.resolve(opts.projectDir)
8878
9388
  });
8879
9389
  try {
8880
9390
  await am2.patchSubmit(ref);
@@ -8890,7 +9400,7 @@ function makePatchCommand() {
8890
9400
  cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
8891
9401
  const am2 = new AssetManager({
8892
9402
  registry: getKindRegistry(),
8893
- projectDir: path18__default.resolve(opts.projectDir)
9403
+ projectDir: path22__default.resolve(opts.projectDir)
8894
9404
  });
8895
9405
  am2.patchRemove(ref);
8896
9406
  logOk(`Patch removed for ${ref}`);
@@ -8908,8 +9418,8 @@ function action2(fn) {
8908
9418
  }
8909
9419
  };
8910
9420
  }
8911
- async function reconcileAndReport(projectDir, plugins) {
8912
- const { reconcilePlugins } = await import('../plugin-store-AGQDMING.js');
9421
+ async function reconcileAndReport(projectDir, plugins, opts = {}) {
9422
+ const { reconcilePlugins } = await import('../plugin-store-CK7YWRIC.js');
8913
9423
  if (plugins.length === 0) {
8914
9424
  logInfo("No plugins declared \u2014 nothing to reconcile.");
8915
9425
  return;
@@ -8919,26 +9429,54 @@ async function reconcileAndReport(projectDir, plugins) {
8919
9429
  if (result.changed) logOk(`Reconciled plugin store (${result.reason}).`);
8920
9430
  else logInfo(`Plugin store ${result.reason}.`);
8921
9431
  } catch (err2) {
9432
+ if (opts.strict) throw err2;
8922
9433
  logWarn(`reconcile skipped: ${err2 instanceof Error ? err2.message : String(err2)}`);
8923
9434
  }
8924
9435
  }
9436
+ async function verifyPluginLoads(projectDir, spec) {
9437
+ const { loadPlugins } = await import('../plugin-store-CK7YWRIC.js');
9438
+ const { createPluginRegistry } = await import('../plugin-registry/index.js');
9439
+ const registry = createPluginRegistry();
9440
+ const result = await loadPlugins(projectDir, [spec], registry);
9441
+ const failure = result.failed[0];
9442
+ if (failure) throw new Error(failure.error);
9443
+ const contributed = ["driver", "connector", "deployTarget"].flatMap(
9444
+ (kind) => registry.list(kind).map((m) => `${kind} ${m.id}`)
9445
+ );
9446
+ logOk(`Loaded ${S.cmd(spec)}${contributed.length > 0 ? ` (${contributed.join(", ")})` : ""}`);
9447
+ }
8925
9448
  async function runInstall2(spec, opts) {
8926
- const projectDir = path18__default.resolve(opts.projectDir);
9449
+ const projectDir = path22__default.resolve(opts.projectDir);
8927
9450
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
8928
- const { specName } = await import('../plugin-store-AGQDMING.js');
8929
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
9451
+ const { specName, rollbackPluginStore } = await import('../plugin-store-CK7YWRIC.js');
9452
+ const yamlPath = path22__default.join(projectDir, "skaile.yaml");
9453
+ const original = existsSync(yamlPath) ? readFileSync(yamlPath, "utf8") : void 0;
8930
9454
  const editor = WorkspaceYamlEditor2.load(yamlPath);
9455
+ const previousPlugins = [...editor.getPlugins()];
8931
9456
  const replaced = editor.addPlugin(spec, specName);
8932
9457
  editor.save();
8933
9458
  if (replaced) logOk(`Updated ${S.cmd(specName(spec))} \u2192 ${S.cmd(spec)} in skaile.yaml`);
8934
9459
  else logOk(`Added ${S.cmd(spec)} to skaile.yaml plugins`);
8935
- await reconcileAndReport(projectDir, editor.getPlugins());
9460
+ try {
9461
+ await reconcileAndReport(projectDir, editor.getPlugins(), { strict: true });
9462
+ await verifyPluginLoads(projectDir, spec);
9463
+ } catch (err2) {
9464
+ if (original !== void 0) {
9465
+ writeFileSync(yamlPath, original);
9466
+ logInfo("skaile.yaml restored; the plugin was not recorded.");
9467
+ } else {
9468
+ rmSync(yamlPath, { force: true });
9469
+ logInfo("skaile.yaml removed; the plugin was not recorded.");
9470
+ }
9471
+ await rollbackPluginStore(projectDir, previousPlugins);
9472
+ throw err2;
9473
+ }
8936
9474
  }
8937
9475
  async function runRemove(name, opts) {
8938
- const projectDir = path18__default.resolve(opts.projectDir);
9476
+ const projectDir = path22__default.resolve(opts.projectDir);
8939
9477
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
8940
- const { specName } = await import('../plugin-store-AGQDMING.js');
8941
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
9478
+ const { specName } = await import('../plugin-store-CK7YWRIC.js');
9479
+ const yamlPath = path22__default.join(projectDir, "skaile.yaml");
8942
9480
  const editor = WorkspaceYamlEditor2.load(yamlPath);
8943
9481
  const removed = editor.removePlugin(name, specName);
8944
9482
  if (!removed) {
@@ -8950,7 +9488,7 @@ async function runRemove(name, opts) {
8950
9488
  await reconcileAndReport(projectDir, editor.getPlugins());
8951
9489
  }
8952
9490
  async function runList(opts) {
8953
- const projectDir = path18__default.resolve(opts.projectDir);
9491
+ const projectDir = path22__default.resolve(opts.projectDir);
8954
9492
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
8955
9493
  const config = resolveSkWorkspaceConfig2(projectDir);
8956
9494
  const declared = config.plugins ?? [];
@@ -8965,7 +9503,7 @@ async function runList(opts) {
8965
9503
  const registry = createPluginRegistry();
8966
9504
  if (declared.length > 0) {
8967
9505
  try {
8968
- const { loadPlugins } = await import('../plugin-store-AGQDMING.js');
9506
+ const { loadPlugins } = await import('../plugin-store-CK7YWRIC.js');
8969
9507
  const result = await loadPlugins(projectDir, declared, registry);
8970
9508
  for (const f of result.failed) logWarn(f.error);
8971
9509
  } catch (err2) {
@@ -9039,9 +9577,11 @@ function presetItemsToWorkspace(preset, values) {
9039
9577
  dependencies.push(ref);
9040
9578
  }
9041
9579
  }
9042
- const sources = (preset.sources ?? []).map(
9043
- (s) => s.pin ? { url: s.url, pin: s.pin } : { url: s.url }
9044
- );
9580
+ const sources = (preset.sources ?? []).map((s) => ({
9581
+ url: s.url,
9582
+ ...s.pin ? { pin: s.pin } : {},
9583
+ ...s.publisher ? { publisher: s.publisher } : {}
9584
+ }));
9045
9585
  return { dependencies, connectors, mcpServers, sources, envVarsToSet: [...envVarsToSet] };
9046
9586
  }
9047
9587
  function resolveItemConfig(item, preset, values, envVarsToSet) {
@@ -9140,7 +9680,7 @@ function neededSources(config, lock) {
9140
9680
  }
9141
9681
  function sourcesWithSidecar(sources) {
9142
9682
  const dir = getStoreManifestsDir();
9143
- return sources.filter((s) => existsSync(path18.join(dir, `${storeManifestSlug(s.url)}.yaml`))).map((s) => s.url);
9683
+ return sources.filter((s) => existsSync(path22.join(dir, `${storeManifestSlug(s.url)}.yaml`))).map((s) => s.url);
9144
9684
  }
9145
9685
  function compact(obj) {
9146
9686
  const out = {};
@@ -9232,8 +9772,8 @@ function redactSecrets(preset, findings) {
9232
9772
  }
9233
9773
  return { preset: next, keys };
9234
9774
  }
9235
- function placeholderKey(itemId, path43) {
9236
- return `${itemId}_${path43}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
9775
+ function placeholderKey(itemId, path44) {
9776
+ return `${itemId}_${path44}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
9237
9777
  }
9238
9778
  function setAtPath(root, segments, value) {
9239
9779
  let node = root;
@@ -9256,7 +9796,7 @@ function makePresetCommand() {
9256
9796
  cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
9257
9797
  const presetName = name ?? "my-preset";
9258
9798
  const filename = `${presetName}.preset.yaml`;
9259
- const outPath = path18__default.join(path18__default.resolve(opts.dir), filename);
9799
+ const outPath = path22__default.join(path22__default.resolve(opts.dir), filename);
9260
9800
  if (existsSync(outPath)) {
9261
9801
  logErr(`File already exists: ${outPath}`);
9262
9802
  logInfo("Choose a different name or remove the existing file.");
@@ -9289,7 +9829,7 @@ function makePresetCommand() {
9289
9829
  return cmd;
9290
9830
  }
9291
9831
  async function runPresetExport(name, opts) {
9292
- const projectDir = path18__default.resolve(opts.projectDir);
9832
+ const projectDir = path22__default.resolve(opts.projectDir);
9293
9833
  const file = loadSkWorkspaceConfig(projectDir);
9294
9834
  if (!file) {
9295
9835
  logErr(`No skaile.yaml found in ${projectDir}`);
@@ -9299,7 +9839,7 @@ async function runPresetExport(name, opts) {
9299
9839
  const presetName = name ?? file.config.name ?? "my-preset";
9300
9840
  let lock = null;
9301
9841
  try {
9302
- lock = readLock(path18__default.join(projectDir, "skaile.lock.yaml"));
9842
+ lock = readLock(path22__default.join(projectDir, "skaile.lock.yaml"));
9303
9843
  } catch {
9304
9844
  lock = null;
9305
9845
  }
@@ -9340,7 +9880,7 @@ async function runPresetExport(name, opts) {
9340
9880
  const contents = header ? `${header}
9341
9881
  ${body}` : body;
9342
9882
  if (opts.out && opts.dir !== process.cwd()) logWarn("--dir is ignored when --out is set.");
9343
- const outPath = opts.out ? path18__default.resolve(opts.out) : path18__default.join(path18__default.resolve(opts.dir), `${presetName}.preset.yaml`);
9883
+ const outPath = opts.out ? path22__default.resolve(opts.out) : path22__default.join(path22__default.resolve(opts.dir), `${presetName}.preset.yaml`);
9344
9884
  if (existsSync(outPath) && !opts.force) {
9345
9885
  logErr(`File already exists: ${outPath}`);
9346
9886
  logInfo("Pass --force to overwrite, or choose a different --out/--dir.");
@@ -9352,7 +9892,7 @@ ${body}` : body;
9352
9892
  logErr(`Failed to write ${outPath}: ${e.message}`);
9353
9893
  process.exit(1);
9354
9894
  }
9355
- logOk(`Exported ${S.brand(path18__default.basename(outPath))}`);
9895
+ logOk(`Exported ${S.brand(path22__default.basename(outPath))}`);
9356
9896
  logInfo(`Path: ${outPath}`);
9357
9897
  if (unresolved.length > 0) {
9358
9898
  console.error(S.err("This file is NOT safe to share."));
@@ -9393,13 +9933,13 @@ function collectInput(value, acc) {
9393
9933
  return acc;
9394
9934
  }
9395
9935
  async function runPresetApply(filePath, opts) {
9396
- const projectDir = path18__default.resolve(opts.projectDir);
9936
+ const projectDir = path22__default.resolve(opts.projectDir);
9397
9937
  const file = loadSkWorkspaceConfig(projectDir);
9398
9938
  if (!file) {
9399
9939
  logErr("No skaile.yaml \u2014 run `skaile init` first");
9400
9940
  process.exit(1);
9401
9941
  }
9402
- const resolved = path18__default.resolve(filePath);
9942
+ const resolved = path22__default.resolve(filePath);
9403
9943
  if (!existsSync(resolved)) {
9404
9944
  logErr(`File not found: ${resolved}`);
9405
9945
  process.exit(1);
@@ -9615,7 +10155,7 @@ async function reportNestedPresetRefs(preset) {
9615
10155
  }
9616
10156
  async function checkPresetCycles(preset, resolved) {
9617
10157
  const { detectCycles } = await import('../discovery/index.js');
9618
- const presetRef = path18__default.basename(resolved, ".preset.yaml");
10158
+ const presetRef = path22__default.basename(resolved, ".preset.yaml");
9619
10159
  const edges = [];
9620
10160
  for (const item of preset.items) {
9621
10161
  if (item.ref) {
@@ -9667,7 +10207,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
9667
10207
  }
9668
10208
  }
9669
10209
  async function runPresetValidate(filePath) {
9670
- const resolved = path18__default.resolve(filePath);
10210
+ const resolved = path22__default.resolve(filePath);
9671
10211
  const preset = await loadPresetForValidation(resolved);
9672
10212
  await reportNestedPresetRefs(preset);
9673
10213
  await checkPresetCycles(preset, resolved);
@@ -9717,11 +10257,11 @@ items:
9717
10257
  }
9718
10258
  function makeRebuildCommand() {
9719
10259
  return new Command("rebuild").description("Re-snapshot inline-snapshot composition items and bump prompt version").argument("[agent]", "Agent name or path (defaults to current project agent)").option("--project-dir <dir>", "Project directory", process.cwd()).action(async (agentArg, opts) => {
9720
- const projectDir = path18__default.resolve(opts.projectDir);
10260
+ const projectDir = path22__default.resolve(opts.projectDir);
9721
10261
  let agentDir;
9722
10262
  if (agentArg) {
9723
10263
  if (agentArg.includes("/") || agentArg.includes("\\")) {
9724
- agentDir = path18__default.resolve(projectDir, agentArg);
10264
+ agentDir = path22__default.resolve(projectDir, agentArg);
9725
10265
  } else {
9726
10266
  let resolved;
9727
10267
  try {
@@ -9730,7 +10270,7 @@ function makeRebuildCommand() {
9730
10270
  if (!(err2 instanceof AgentRefResolutionError)) throw err2;
9731
10271
  logWarn(`${err2.message} \u2014 using "${agentArg}"`);
9732
10272
  }
9733
- agentDir = resolved ?? path18__default.resolve(projectDir, agentArg);
10273
+ agentDir = resolved ?? path22__default.resolve(projectDir, agentArg);
9734
10274
  }
9735
10275
  } else {
9736
10276
  let resolved;
@@ -9796,13 +10336,23 @@ function friendlyDriverError(err2) {
9796
10336
  return `${base}
9797
10337
  Try a different harness with \`--driver claude-sdk\`.`;
9798
10338
  }
10339
+ function driverErrorNotes(err2) {
10340
+ const e = err2;
10341
+ const notes = [];
10342
+ const category = e?.category ?? e?.detail?.category;
10343
+ const hint = e?.hint ?? e?.detail?.hint;
10344
+ if (hint && category !== "config") notes.push(hint);
10345
+ else if (category === "auth") notes.push("Check your API key or login.");
10346
+ notes.push("Full records: .skaile/logs.db (skaile session logs <session-id>).");
10347
+ return notes;
10348
+ }
9799
10349
 
9800
10350
  // cli/src/commands/run.ts
9801
10351
  function resolveSingleShotAgentDir(projectDir, agentDefinition) {
9802
10352
  if (!agentDefinition) return resolveAgentDir(projectDir);
9803
- const asPath = agentDefinition.endsWith("agent.yaml") ? path18__default.dirname(path18__default.resolve(projectDir, agentDefinition)) : agentDefinition;
10353
+ const asPath = agentDefinition.endsWith("agent.yaml") ? path22__default.dirname(path22__default.resolve(projectDir, agentDefinition)) : agentDefinition;
9804
10354
  const dir = resolveAgentDefinitionDir(projectDir, asPath);
9805
- if (!dir || !fs8__default.existsSync(path18__default.join(dir, "agent.yaml"))) {
10355
+ if (!dir || !fs9__default.existsSync(path22__default.join(dir, "agent.yaml"))) {
9806
10356
  throw new Error(
9807
10357
  `--agent-definition "${agentDefinition}" does not resolve to an agent directory with agent.yaml${dir ? ` (looked in ${dir})` : ""}`
9808
10358
  );
@@ -9853,10 +10403,58 @@ async function printCompositionDryRun(projectDir, agentDir, driver, model) {
9853
10403
  }
9854
10404
  for (const warning of resolved.warnings) logWarn(warning);
9855
10405
  }
10406
+ async function findSkillFile(projectDir, skill) {
10407
+ const name = skill.trim().replace(/^skill:/, "").replace(/^@[^/]+\//, "").replace(/#.*$/, "");
10408
+ for (const target of SUPPORTED_DRIVER_TARGETS) {
10409
+ const file = path22__default.join(deployedDir("skill", name, target, false, projectDir), "SKILL.md");
10410
+ if (fs9__default.existsSync(file)) return file;
10411
+ }
10412
+ const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
10413
+ const entry = await am2.info(`skill:${name}`);
10414
+ return entry?.source && fs9__default.existsSync(entry.source) ? entry.source : void 0;
10415
+ }
10416
+ async function printSkillDryRun(projectDir, skill) {
10417
+ const file = await findSkillFile(projectDir, skill);
10418
+ if (!file) {
10419
+ logErr(
10420
+ `Skill not found: ${skill} - not deployed in the project and not held by a registered library or source`
10421
+ );
10422
+ return false;
10423
+ }
10424
+ const content = fs9__default.readFileSync(file, "utf-8");
10425
+ const { data } = parseFrontmatter(content);
10426
+ const meta = data.metadata ?? {};
10427
+ console.log(` ${S.label("Skill:")} ${S.heading(String(data.name ?? skill))}`);
10428
+ console.log(` ${S.label("Source:")} ${file}`);
10429
+ if (meta.version) console.log(` ${S.label("Version:")} ${String(meta.version)}`);
10430
+ if (data.description) console.log(` ${S.label("About:")} ${String(data.description)}`);
10431
+ const requires = parseRequires(data);
10432
+ if (requires.length > 0) {
10433
+ console.log(` ${S.label("Requires:")} ${requires.map((d) => depToStr(d)).join(", ")}`);
10434
+ }
10435
+ const requirements = parseSkillRequirements(content);
10436
+ const report = await validateRequirements(String(data.name ?? skill), requirements, projectDir);
10437
+ const unmet = report.files.filter((f) => !f.exists);
10438
+ for (const f of report.files) {
10439
+ const mark = f.exists ? S.ok("present") : f.gate === "hard" ? S.err("missing") : S.warn("missing");
10440
+ const gate = f.gate === "soft" ? " (soft)" : "";
10441
+ console.log(` ${S.label("File:")} ${f.path}${gate} ${mark}`);
10442
+ }
10443
+ for (const input of report.inputs.filter((i) => i.required && !i.present)) {
10444
+ console.log(` ${S.label("Input:")} ${input.id} ${S.err("required, not collected")}`);
10445
+ }
10446
+ if (unmet.some((f) => f.gate === "hard")) {
10447
+ logWarn("Unmet hard prerequisites: the skill cannot run until those files exist.");
10448
+ }
10449
+ console.log();
10450
+ return true;
10451
+ }
9856
10452
  function makeFlowEventHandler() {
9857
10453
  const md = new MarkdownStreamer();
9858
10454
  const displayed = /* @__PURE__ */ new Set();
10455
+ const printUnstreamed = createFinalTextFallback((text) => md.write(text));
9859
10456
  return (event) => {
10457
+ printUnstreamed(event);
9860
10458
  const e = event;
9861
10459
  if (e.type === "state_changed" && typeof e.store === "string" && e.store.startsWith("flow:")) {
9862
10460
  const nodes = e.state?.nodes ?? {};
@@ -9894,14 +10492,41 @@ function logAgentRunEvent(event) {
9894
10492
  return;
9895
10493
  }
9896
10494
  const verdict = e.error ? `${e.runStatus ?? "failed"}: ${e.error.code} ${e.error.message}` : e.runStatus ?? "finished";
9897
- console.error(` ${S.dim("subagent")} ${who} ${verdict} output=${JSON.stringify(e.output)}`);
10495
+ console.error(` ${S.dim("subagent")} ${who} ${verdict}${subagentOutputSuffix(e)}`);
10496
+ }
10497
+ function subagentOutputSuffix(e) {
10498
+ const value = e.result !== void 0 ? e.result : e.output;
10499
+ return value === void 0 ? "" : ` output=${JSON.stringify(value)}`;
10500
+ }
10501
+ function editDistance2(a, b) {
10502
+ let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
10503
+ for (let i = 1; i <= a.length; i++) {
10504
+ const row = [i];
10505
+ for (let j = 1; j <= b.length; j++) {
10506
+ row[j] = Math.min(
10507
+ prev[j] + 1,
10508
+ row[j - 1] + 1,
10509
+ prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
10510
+ );
10511
+ }
10512
+ prev = row;
10513
+ }
10514
+ return prev[b.length];
10515
+ }
10516
+ function isNearFlowId(typed, id) {
10517
+ const a = typed.toLowerCase();
10518
+ const b = id.toLowerCase();
10519
+ return a.length >= 3 && (b.includes(a) || a.includes(b) || editDistance2(a, b) <= 2);
10520
+ }
10521
+ function driverOptionDescription() {
10522
+ return `Harness to run (${listDrivers().map((d) => d.id).join(", ")})`;
9898
10523
  }
9899
10524
  function makeRunCommand() {
9900
- const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--driver <name>", "Harness to run (claude-sdk, codex, omp)").option("--model <name>", "Model override").option("--label <label>", "Human-readable session label").option("--dry-run", "Print plan without executing (single-shot: resolved composition items)").option(
10525
+ const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--driver <name>", driverOptionDescription()).option("--model <name>", "Model override").option("--label <label>", "Human-readable session label").option("--dry-run", "Print plan without executing (single-shot: resolved composition items)").option(
9901
10526
  "--agent-definition <ref|path>",
9902
10527
  "Agent asset for this one invocation (agent:@pub/name, ai-assets://\u2026, or a directory with agent.yaml); single-shot prompts only"
9903
10528
  ).option("--skill <name>", "Skill name (for single-shot mode)").action(async (positional, opts) => {
9904
- const projectDir = path18__default.resolve(opts.projectDir);
10529
+ const projectDir = path22__default.resolve(opts.projectDir);
9905
10530
  const cliDriver = opts.driver;
9906
10531
  const dryRun = opts.dryRun ?? false;
9907
10532
  const agentDefinition = opts.agentDefinition?.trim() || void 0;
@@ -9945,18 +10570,29 @@ function makeRunCommand() {
9945
10570
  }
9946
10571
  if (!flowPath) {
9947
10572
  const textPrompt = positional.join(" ");
9948
- if (!textPrompt.trim()) {
10573
+ const promptOnlyOption = agentDefinition !== void 0 || opts.skill !== void 0;
10574
+ if (!textPrompt.trim() || positional.length === 1 && !/\s/.test(flowId) && !promptOnlyOption) {
9949
10575
  logErr(`Flow not found: ${flowId}`);
9950
10576
  const available = (await discoverFlowsWithLibraries(projectDir)).map((f) => f.id);
9951
- if (available.length > 0) {
9952
- console.log(` ${S.dim("Available:")} ${available.map((id) => S.cmd(id)).join(", ")}`);
10577
+ const near = available.filter((id) => isNearFlowId(flowId, id));
10578
+ const listed = near.length > 0 ? near : available;
10579
+ if (listed.length > 0) {
10580
+ console.log(
10581
+ ` ${S.dim(near.length > 0 ? "Did you mean:" : "Available:")} ${listed.map((id) => S.cmd(id)).join(", ")}`
10582
+ );
9953
10583
  }
10584
+ console.log(
10585
+ ` ${S.dim('To send it as a prompt, quote more than one word: skaile run "\u2026".')}`
10586
+ );
9954
10587
  process.exit(1);
9955
10588
  }
9956
10589
  try {
9957
10590
  const agentDir = resolveSingleShotAgentDir(projectDir, agentDefinition);
9958
10591
  if (dryRun) {
9959
10592
  await printCompositionDryRun(projectDir, agentDir, driver, model);
10593
+ if (opts.skill && !await printSkillDryRun(projectDir, opts.skill)) {
10594
+ process.exit(1);
10595
+ }
9960
10596
  return;
9961
10597
  }
9962
10598
  await runAgentChat({
@@ -9978,6 +10614,7 @@ function makeRunCommand() {
9978
10614
  logErr(friendly);
9979
10615
  } else {
9980
10616
  logErr(err2 instanceof Error ? err2.message : String(err2));
10617
+ for (const note of driverErrorNotes(err2)) console.error(` ${S.dim(note)}`);
9981
10618
  }
9982
10619
  process.exit(1);
9983
10620
  }
@@ -10020,7 +10657,7 @@ function makeRunCommand() {
10020
10657
  }
10021
10658
  function makeResumeCommand() {
10022
10659
  const cmd = new Command("resume").description("Resume current session").option("--project-dir <path>", "Project directory", process.cwd()).option("--session <run-id>", "Target session by runId").option("--dry-run", "Print plan without executing").action(async (opts) => {
10023
- const projectDir = path18__default.resolve(opts.projectDir);
10660
+ const projectDir = path22__default.resolve(opts.projectDir);
10024
10661
  const sessionId = opts.session;
10025
10662
  const dryRun = opts.dryRun ?? false;
10026
10663
  const session = sessionId ? await loadSessionById(projectDir, sessionId) : await loadSession(projectDir);
@@ -10047,7 +10684,7 @@ function makeResumeCommand() {
10047
10684
  }
10048
10685
  function makeStatusCommand() {
10049
10686
  return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10050
- const projectDir = path18__default.resolve(opts.projectDir);
10687
+ const projectDir = path22__default.resolve(opts.projectDir);
10051
10688
  const session = await loadSession(projectDir);
10052
10689
  if (!session) {
10053
10690
  logInfo("No active session.");
@@ -10060,6 +10697,7 @@ function makeStatusCommand() {
10060
10697
  console.log(` ${S.label("Run ID:")} ${session.runId.slice(0, 8)}`);
10061
10698
  if (session.label) console.log(` ${S.label("Label:")} ${session.label}`);
10062
10699
  console.log(` ${S.label("Status:")} ${statusColor(session.status ?? "unknown")}`);
10700
+ if (session.error) console.log(` ${S.label("Error:")} ${session.error}`);
10063
10701
  console.log(
10064
10702
  ` ${S.label("Driver:")} ${session.driver}${session.model ? S.dim(` / ${session.model}`) : ""}`
10065
10703
  );
@@ -10072,17 +10710,17 @@ function makeStatusCommand() {
10072
10710
  }
10073
10711
  function makeClearCommand() {
10074
10712
  return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10075
- const projectDir = path18__default.resolve(opts.projectDir);
10713
+ const projectDir = path22__default.resolve(opts.projectDir);
10076
10714
  await clearSession(projectDir);
10077
10715
  logOk("Session cleared.");
10078
10716
  });
10079
10717
  }
10080
10718
  function makeReplCommand() {
10081
- return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>", "Harness to run (claude-sdk, omp)").option("--model <name>", "Model override").option("--resume", "Resume last session").option("--resume-session <id>", "Resume specific session").action(async (opts) => {
10719
+ return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>", driverOptionDescription()).option("--model <name>", "Model override").option("--resume", "Resume last session").option("--resume-session <id>", "Resume specific session").action(async (opts) => {
10082
10720
  const { findWorkspaceRoot } = await import('../core/index.js');
10083
10721
  const { startRepl } = await import('../tui/index.js');
10084
10722
  const os2 = await import('os');
10085
- const userCwd = path18__default.resolve(opts.projectDir ?? process.cwd());
10723
+ const userCwd = path22__default.resolve(opts.projectDir ?? process.cwd());
10086
10724
  const workspaceRoot = findWorkspaceRoot(userCwd);
10087
10725
  let projectDir;
10088
10726
  let agentCwd;
@@ -10097,6 +10735,12 @@ function makeReplCommand() {
10097
10735
  console.log();
10098
10736
  logWarn(`No skaile.yaml found in ${S.cmd(userCwd)} or any parent directory.`);
10099
10737
  console.log();
10738
+ if (!process.stdin.isTTY) {
10739
+ logErr(
10740
+ `repl needs a skaile.yaml here when stdin is not a terminal: run ${S.cmd("skaile init")} first.`
10741
+ );
10742
+ process.exit(1);
10743
+ }
10100
10744
  const shouldCreate = await p4.confirm({
10101
10745
  message: "Create a temporary workspace? (session state in /tmp/)"
10102
10746
  });
@@ -10104,13 +10748,13 @@ function makeReplCommand() {
10104
10748
  p4.cancel("Cancelled.");
10105
10749
  process.exit(0);
10106
10750
  }
10107
- const tmpDir = fs8__default.mkdtempSync(path18__default.join(os2.tmpdir(), "skaile-repl-"));
10751
+ const tmpDir = fs9__default.mkdtempSync(path22__default.join(os2.tmpdir(), "skaile-repl-"));
10108
10752
  projectDir = tmpDir;
10109
10753
  agentCwd = userCwd;
10110
10754
  logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
10111
10755
  if (!driverOverride) {
10112
- const claudeDir = path18__default.join(os2.homedir(), ".claude");
10113
- if (fs8__default.existsSync(claudeDir)) {
10756
+ const claudeDir = path22__default.join(os2.homedir(), ".claude");
10757
+ if (fs9__default.existsSync(claudeDir)) {
10114
10758
  driverOverride = "claude-sdk";
10115
10759
  logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} harness`);
10116
10760
  } else {
@@ -10139,7 +10783,10 @@ function parseProviderIds(raw) {
10139
10783
  return (raw ?? "").split(",").map((id) => id.trim()).filter((id) => id.length > 0);
10140
10784
  }
10141
10785
  function makeServeCommand() {
10142
- return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option("--project-dir <path>", "Project directory", process.cwd()).option(
10786
+ return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option(
10787
+ "--host <address>",
10788
+ "Address to bind (default: all interfaces; use 127.0.0.1 for local clients only)"
10789
+ ).option("--project-dir <path>", "Project directory", process.cwd()).option(
10143
10790
  "--managed-codex-config <path>",
10144
10791
  "Explicit private host configuration for managed Codex"
10145
10792
  ).option("--driver <name>", "Override driver").option("--model <name>", "Override model").option("--provider <name>", "Override provider").option("--session-id <id>", "Session ID for conversation continuity").option("--resume-session-id <id>", "OMP session ID to resume (restores native OMP context)").option(
@@ -10167,32 +10814,48 @@ function makeServeCommand() {
10167
10814
  await ensurePluginsLoadedForServe(opts.projectDir);
10168
10815
  }
10169
10816
  const providers = parseProviderIds(opts.providers);
10170
- await startAgentServer({
10171
- port: parseInt(opts.port, 10),
10172
- authTokenIntake: wsAuth,
10173
- ...managedCodex ? { managedCodex } : {},
10174
- // The CLI owns its process, so a dead stdout pipe is fatal here.
10175
- // `SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT=0` opts out — the `local` /
10176
- // `nix` deploy targets set it for children meant to outlive them.
10177
- exitOnBrokenPipe: process.env.SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT !== "0",
10178
- projectDir: opts.projectDir,
10179
- driver: opts.driver,
10180
- model: opts.model,
10181
- provider: opts.provider,
10182
- sessionId: opts.sessionId,
10183
- resumeSessionId: opts.resumeSessionId,
10184
- ...providers.length > 0 ? { providers } : {}
10185
- });
10817
+ const { checkDriverSdk } = await import('../serve-preflight-F7MYF747.js');
10818
+ const driverProblem = managedCodex ? null : await checkDriverSdk(opts.projectDir, opts.driver);
10819
+ if (driverProblem) {
10820
+ const { logErr: logErr2 } = await import('../helpers-53XZW7KF.js');
10821
+ logErr2(driverProblem);
10822
+ process.exitCode = 1;
10823
+ return;
10824
+ }
10825
+ try {
10826
+ await startAgentServer({
10827
+ port: parseInt(opts.port, 10),
10828
+ ...opts.host ? { host: opts.host } : {},
10829
+ authTokenIntake: wsAuth,
10830
+ ...managedCodex ? { managedCodex } : {},
10831
+ // The CLI owns its process, so a dead stdout pipe is fatal here.
10832
+ // `SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT=0` opts out — the `local` /
10833
+ // `nix` deploy targets set it for children meant to outlive them.
10834
+ exitOnBrokenPipe: process.env.SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT !== "0",
10835
+ projectDir: opts.projectDir,
10836
+ driver: opts.driver,
10837
+ model: opts.model,
10838
+ provider: opts.provider,
10839
+ sessionId: opts.sessionId,
10840
+ resumeSessionId: opts.resumeSessionId,
10841
+ ...providers.length > 0 ? { providers } : {}
10842
+ });
10843
+ } catch (err2) {
10844
+ if (err2?.code !== "EADDRINUSE") throw err2;
10845
+ const { logErr: logErr2 } = await import('../helpers-53XZW7KF.js');
10846
+ logErr2(err2.message);
10847
+ process.exit(1);
10848
+ }
10186
10849
  }
10187
10850
  );
10188
10851
  }
10189
10852
  async function ensurePluginsLoadedForServe(projectDir) {
10190
- const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-CFK6YP6R.js');
10853
+ const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-53XZW7KF.js');
10191
10854
  try {
10192
10855
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
10193
10856
  const config = resolveSkWorkspaceConfig2(projectDir);
10194
10857
  if (!config.plugins || config.plugins.length === 0) return;
10195
- const { ensurePluginsLoaded } = await import('../plugin-store-AGQDMING.js');
10858
+ const { ensurePluginsLoaded } = await import('../plugin-store-CK7YWRIC.js');
10196
10859
  const { pluginRegistry } = await import('../plugin-registry/index.js');
10197
10860
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
10198
10861
  if (result.loaded.length > 0) {
@@ -10206,21 +10869,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
10206
10869
  }
10207
10870
  }
10208
10871
  async function runCompileTest(opts) {
10209
- const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-CFK6YP6R.js');
10872
+ const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-53XZW7KF.js');
10210
10873
  const { tmpdir } = await import('os');
10211
- const { dirname: dirname3, join: join6, resolve: resolve5 } = await import('path');
10874
+ const { dirname: dirname3, join: join7, resolve: resolve5 } = await import('path');
10212
10875
  const { fileURLToPath: fileURLToPath2 } = await import('url');
10213
- const { unlinkSync, existsSync: existsSync17 } = await import('fs');
10876
+ const { unlinkSync, existsSync: existsSync21 } = await import('fs');
10214
10877
  const { spawn } = await import('child_process');
10215
10878
  const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
10216
- const { MONOREPO_ROOT } = await import('../paths-SUS4S4YT.js');
10879
+ const { MONOREPO_ROOT } = await import('../paths-KKY3NSBZ.js');
10217
10880
  if (MONOREPO_ROOT === null) {
10218
10881
  logErr2("--compile-test is only available inside the skaile-dev workspace.");
10219
10882
  logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
10220
10883
  process.exitCode = 2;
10221
10884
  return;
10222
10885
  }
10223
- const outfile = join6(tmpdir(), `skaile-compile-test-${Date.now()}`);
10886
+ const outfile = join7(tmpdir(), `skaile-compile-test-${Date.now()}`);
10224
10887
  const __thisFile = fileURLToPath2(import.meta.url);
10225
10888
  const entryPoint = resolve5(dirname3(__thisFile), "..", "index.ts");
10226
10889
  logInfo2(`Building compiled binary...`);
@@ -10275,7 +10938,7 @@ async function runCompileTest(opts) {
10275
10938
  } catch {
10276
10939
  }
10277
10940
  try {
10278
- if (existsSync17(outfile)) unlinkSync(outfile);
10941
+ if (existsSync21(outfile)) unlinkSync(outfile);
10279
10942
  } catch {
10280
10943
  }
10281
10944
  }
@@ -10696,7 +11359,7 @@ function resolveMode2(opts) {
10696
11359
  if (opts.forceLocal && opts.forceRemote) {
10697
11360
  throw new Error("Cannot use both --local and --remote");
10698
11361
  }
10699
- const startDir = path18__default.resolve(opts.projectDir ?? process.cwd());
11362
+ const startDir = path22__default.resolve(opts.projectDir ?? process.cwd());
10700
11363
  const localDb = findLogsDb(startDir);
10701
11364
  if (opts.forceLocal) {
10702
11365
  if (!localDb) {
@@ -10729,14 +11392,14 @@ function resolveMode2(opts) {
10729
11392
  function findLogsDb(startDir) {
10730
11393
  let dir = startDir;
10731
11394
  for (let i = 0; i < MAX_WALK_LEVELS; i++) {
10732
- const candidate = path18__default.join(dir, ".skaile", "logs.db");
11395
+ const candidate = path22__default.join(dir, ".skaile", "logs.db");
10733
11396
  if (existsSync(candidate)) {
10734
11397
  try {
10735
11398
  if (statSync(candidate).isFile()) return candidate;
10736
11399
  } catch {
10737
11400
  }
10738
11401
  }
10739
- const parent = path18__default.dirname(dir);
11402
+ const parent = path22__default.dirname(dir);
10740
11403
  if (parent === dir) return void 0;
10741
11404
  dir = parent;
10742
11405
  }
@@ -10911,7 +11574,7 @@ function parsePositiveInt(value, flag) {
10911
11574
  function makeSessionCommand() {
10912
11575
  const cmd = new Command("session").description("Manage sessions");
10913
11576
  cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10914
- const projectDir = path18__default.resolve(opts.projectDir);
11577
+ const projectDir = path22__default.resolve(opts.projectDir);
10915
11578
  const sessions = await listSessions(projectDir);
10916
11579
  const current = await loadSession(projectDir);
10917
11580
  if (sessions.length === 0) {
@@ -10939,7 +11602,7 @@ function makeSessionCommand() {
10939
11602
  console.log();
10940
11603
  });
10941
11604
  cmd.command("show <run-id>").description("Show a specific session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10942
- const projectDir = path18__default.resolve(opts.projectDir);
11605
+ const projectDir = path22__default.resolve(opts.projectDir);
10943
11606
  const session = await loadSessionById(projectDir, runId);
10944
11607
  if (!session) {
10945
11608
  logErr(`Session not found: ${runId}`);
@@ -10948,7 +11611,7 @@ function makeSessionCommand() {
10948
11611
  console.log(JSON.stringify(session, null, 2));
10949
11612
  });
10950
11613
  cmd.command("switch <run-id>").description("Switch the current session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10951
- const projectDir = path18__default.resolve(opts.projectDir);
11614
+ const projectDir = path22__default.resolve(opts.projectDir);
10952
11615
  if (!await loadSessionById(projectDir, runId)) {
10953
11616
  logErr(`Session not found: ${runId}`);
10954
11617
  process.exit(1);
@@ -10957,7 +11620,7 @@ function makeSessionCommand() {
10957
11620
  logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
10958
11621
  });
10959
11622
  cmd.command("delete <run-id>").description("Delete a session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10960
- const projectDir = path18__default.resolve(opts.projectDir);
11623
+ const projectDir = path22__default.resolve(opts.projectDir);
10961
11624
  if (!await loadSessionById(projectDir, runId)) {
10962
11625
  logErr(`Session not found: ${runId}`);
10963
11626
  process.exit(1);
@@ -11015,12 +11678,12 @@ function showOverview(am2) {
11015
11678
  }
11016
11679
  async function showAsset(am2, kind, name) {
11017
11680
  const entry = await am2.info(`${kind}:${name}`);
11018
- if (entry?.source && fs8__default.existsSync(entry.source)) {
11681
+ if (entry?.source && fs9__default.existsSync(entry.source)) {
11019
11682
  console.log();
11020
11683
  console.log(` ${kindColor(entry.kind)} ${S.heading(entry.name)}`);
11021
11684
  console.log(` ${S.rule(40)}`);
11022
11685
  console.log();
11023
- console.log(fs8__default.readFileSync(entry.source, "utf-8"));
11686
+ console.log(fs9__default.readFileSync(entry.source, "utf-8"));
11024
11687
  return;
11025
11688
  }
11026
11689
  logErr(`Asset not found: ${kind}:${name}`);
@@ -11030,7 +11693,7 @@ function makeShowCommand() {
11030
11693
  return new Command("show").description("Show deployed assets overview, or print asset content").argument("[kind]", "Asset kind (skill, agent, prompt, flow, preset, contract)").argument("[name]", "Asset name").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", `Agent framework (${TARGET_DEFAULT_HINT})`).action(async (kind, name, opts) => {
11031
11694
  const am2 = new AssetManager({
11032
11695
  registry: getKindRegistry(),
11033
- projectDir: path18__default.resolve(opts.projectDir),
11696
+ projectDir: path22__default.resolve(opts.projectDir),
11034
11697
  driverTarget: opts.target
11035
11698
  });
11036
11699
  if (!kind) {
@@ -11048,6 +11711,32 @@ function makeShowCommand() {
11048
11711
  }
11049
11712
  });
11050
11713
  }
11714
+ function searchCuratedManifests(query) {
11715
+ const dir = getStoreManifestsDir();
11716
+ if (!existsSync(dir)) return [];
11717
+ const q = query.toLowerCase();
11718
+ const hits = [];
11719
+ for (const file of readdirSync(dir).sort()) {
11720
+ if (!file.endsWith(".yaml")) continue;
11721
+ const slug = file.slice(0, -".yaml".length);
11722
+ let manifest;
11723
+ try {
11724
+ manifest = decodeSkaileManifest(readFileSync(path22.join(dir, file), "utf-8")).manifest;
11725
+ } catch {
11726
+ continue;
11727
+ }
11728
+ const repoPublisher2 = manifest.publisher?.replace(/^@/, "");
11729
+ for (const a of manifest.assets ?? []) {
11730
+ const publisher = (a.publisher ?? repoPublisher2 ?? "").replace(/^@/, "");
11731
+ const haystack = [a.name, a.description ?? "", publisher, a.kind].join(" ").toLowerCase();
11732
+ if (!haystack.includes(q)) continue;
11733
+ hits.push({ slug, kind: a.kind, publisher, name: a.name, description: a.description });
11734
+ }
11735
+ }
11736
+ return hits;
11737
+ }
11738
+
11739
+ // cli/src/commands/store.ts
11051
11740
  async function fetchIdentity() {
11052
11741
  const jwt = await getStoreToken();
11053
11742
  return storeFetch({ ...getStoreConfig(), jwt }, "/api/v1/me");
@@ -11093,43 +11782,83 @@ function makeStoreCommand() {
11093
11782
  });
11094
11783
  store.command("mode <auto|local|remote>").description("Set the catalog resolution mode (not yet wired)").action((_mode) => {
11095
11784
  logErr(
11096
- `\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path18__default.join(globalSkaileDir(), "store", "config.yaml")}.`
11785
+ `\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path22__default.join(globalSkaileDir(), "store", "config.yaml")}.`
11097
11786
  );
11098
11787
  process.exit(2);
11099
11788
  });
11100
- store.command("search <query>").description("Search the AI Asset Store catalog by name, description, or publisher").option("--kind <kind>", "Filter by asset kind (skill, agent, prompt, flow, \u2026)").option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (query, opts) => {
11101
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-BOSPJVID.js');
11102
- try {
11103
- const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
11104
- const assets = await remote.listAssets(opts.kind ? { kind: opts.kind } : {});
11105
- const results = filterCatalogAssets(assets, query);
11106
- if (results.length === 0) {
11107
- logInfo(`No store results for "${query}".`);
11108
- return;
11789
+ store.command("search <query>").description("Search the AI Asset Store catalog by name, description, or publisher").option("--kind <kind>", "Filter by asset kind (skill, prompt, flow, \u2026)").option(
11790
+ "--all",
11791
+ `List every match (default: ${STORE_ROW_LIMIT} rows, only what \`skaile add\` can install)`
11792
+ ).option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (query, opts) => {
11793
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-PZAT3TJA.js');
11794
+ const { getKnownKinds: getKnownKinds2 } = await import('../open-registry-W46UXZ3I.js');
11795
+ const projectDir = path22__default.resolve(opts.projectDir);
11796
+ if (opts.kind && !getKnownKinds2().has(opts.kind)) {
11797
+ logErr(
11798
+ `Unknown kind "${opts.kind}". Valid kinds: ${[...getKnownKinds2()].sort().join(", ")}`
11799
+ );
11800
+ process.exit(1);
11801
+ }
11802
+ const curated = searchCuratedManifests(query).filter(
11803
+ (h) => !opts.kind || h.kind === opts.kind
11804
+ );
11805
+ const printCurated = () => {
11806
+ if (curated.length === 0) return;
11807
+ console.log(`
11808
+ ${S.heading("Local curated manifests")}`);
11809
+ for (const h of curated) {
11810
+ console.log(
11811
+ ` ${kindColorPad(h.kind)} ${h.kind}:@${h.publisher}/${h.name} ${S.dim(`(manifest ${h.slug})`)}`
11812
+ );
11109
11813
  }
11110
- console.log();
11111
- for (const row of formatStoreRows(results, " ")) console.log(row);
11112
11814
  console.log(
11113
11815
  `
11114
- ${S.dim(`${results.length} result(s) \xB7 \`skaile store show <ref>\` for details`)}
11816
+ ${S.dim("Not published: `skaile source add <repo URL>` indexes them for `skaile add`.")}
11115
11817
  `
11116
11818
  );
11819
+ };
11820
+ try {
11821
+ const remote = await openCatalogSource2({ projectDir });
11822
+ const assets = await remote.listAssets(opts.kind ? { kind: opts.kind } : {});
11823
+ const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
11824
+ if (sel.shown.length === 0) {
11825
+ logInfo(`No store results for "${query}".`);
11826
+ for (const note of storeSelectionNotes(sel, "")) console.log(note);
11827
+ } else {
11828
+ console.log();
11829
+ for (const row of formatStoreRows(sel.shown, " ")) console.log(row);
11830
+ console.log(
11831
+ `
11832
+ ${S.dim(`${sel.shown.length} result(s) \xB7 \`skaile store show <ref>\` for details`)}`
11833
+ );
11834
+ for (const note of storeSelectionNotes(sel, " ")) console.log(note);
11835
+ if (curated.length === 0) console.log();
11836
+ }
11837
+ printCurated();
11117
11838
  } catch (e) {
11839
+ printCurated();
11840
+ if (e instanceof LocalCatalogDisabledError2 && curated.length > 0) return;
11118
11841
  if (e instanceof LocalCatalogDisabledError2) {
11119
11842
  logErr(
11120
11843
  `Remote catalog disabled (catalog.url: local). Set \`catalog.url: https://skaile.store\` in ${userConfigPath()}.`
11121
11844
  );
11122
11845
  } else {
11123
- logErr(`Store search failed: ${e.message}`);
11846
+ logErr(`Store search failed: ${await describeStoreFailure(e, projectDir)}`);
11124
11847
  }
11125
11848
  process.exit(1);
11126
11849
  }
11127
11850
  });
11128
11851
  store.command("show <ref>").description("Show a store asset's details + provenance (source, files, integrity)").option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (ref, opts) => {
11129
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-BOSPJVID.js');
11130
- const { supportsInstallManifest } = await import('../project-I55A4O2T.js');
11852
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-PZAT3TJA.js');
11853
+ const { supportsInstallManifest } = await import('../project-EZUH7PUJ.js');
11131
11854
  try {
11132
- const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
11855
+ parseAssetRef(ref);
11856
+ } catch (e) {
11857
+ logErr(`Invalid asset ref "${ref}": ${e instanceof Error ? e.message : String(e)}`);
11858
+ process.exit(1);
11859
+ }
11860
+ try {
11861
+ const remote = await openCatalogSource2({ projectDir: path22__default.resolve(opts.projectDir) });
11133
11862
  const asset = await remote.resolve(ref);
11134
11863
  if (!asset) {
11135
11864
  logErr(`Not found in store: ${ref} (try a full ref, e.g. skill:@publisher/name#version)`);
@@ -11137,8 +11866,12 @@ function makeStoreCommand() {
11137
11866
  }
11138
11867
  const canonical = catalogAssetRef(asset);
11139
11868
  let manifest = null;
11869
+ const manifestFailure = {};
11140
11870
  if (supportsInstallManifest(remote)) {
11141
- manifest = await remote.getInstallManifest(canonical).catch(() => null);
11871
+ manifest = await remote.getInstallManifest(canonical).catch(async (err2) => {
11872
+ manifestFailure.text = await describeStoreFailure(err2, path22__default.resolve(opts.projectDir));
11873
+ return null;
11874
+ });
11142
11875
  }
11143
11876
  const field = (label, value) => ` ${S.label(label.padEnd(11))}${value}`;
11144
11877
  console.log();
@@ -11168,13 +11901,25 @@ function makeStoreCommand() {
11168
11901
  console.log(field("Repo", asset.repo));
11169
11902
  if (asset.sha256) console.log(field("Integrity", asset.sha256));
11170
11903
  }
11904
+ if (!manifest && manifestFailure.text) {
11905
+ console.log();
11906
+ console.log(field("Files", S.dim(`unavailable (${manifestFailure.text})`)));
11907
+ }
11908
+ if (asset.requires?.length) {
11909
+ console.log();
11910
+ console.log(` ${S.heading("Requires")}`);
11911
+ for (const dep of asset.requires) console.log(` ${S.dim("\u2192")} ${dep}`);
11912
+ }
11171
11913
  if (asset.softDeps?.length) {
11172
11914
  console.log();
11173
11915
  console.log(` ${S.heading("Soft dependencies")}`);
11174
11916
  for (const dep of asset.softDeps) console.log(` ${S.dim("\u2192")} ${dep}`);
11175
11917
  }
11176
11918
  console.log();
11177
- console.log(` ${S.dim(`Install: skaile add ${canonical}`)}`);
11919
+ const notInstallable = storeNotInstallableReason(asset);
11920
+ console.log(
11921
+ notInstallable ? ` ${S.dim(`Not installable: ${notInstallable}`)}` : ` ${S.dim(`Install: skaile add ${canonical}`)}`
11922
+ );
11178
11923
  console.log();
11179
11924
  } catch (e) {
11180
11925
  if (e instanceof LocalCatalogDisabledError2) {
@@ -11182,7 +11927,9 @@ function makeStoreCommand() {
11182
11927
  `Remote catalog disabled (catalog.url: local). Set \`catalog.url: https://skaile.store\` in ${userConfigPath()}.`
11183
11928
  );
11184
11929
  } else {
11185
- logErr(`Store show failed: ${e.message}`);
11930
+ logErr(
11931
+ `Store show failed: ${await describeStoreFailure(e, path22__default.resolve(opts.projectDir))}`
11932
+ );
11186
11933
  }
11187
11934
  process.exit(1);
11188
11935
  }
@@ -11252,9 +11999,10 @@ function treeRefs(nodes) {
11252
11999
  }
11253
12000
  function makeTreeCommand() {
11254
12001
  return new Command("tree").description("Show full dependency tree").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
12002
+ requireProjectConfig(opts.projectDir);
11255
12003
  const am2 = new AssetManager({
11256
12004
  registry: getKindRegistry(),
11257
- projectDir: path18__default.resolve(opts.projectDir)
12005
+ projectDir: path22__default.resolve(opts.projectDir)
11258
12006
  });
11259
12007
  const root = await am2.tree();
11260
12008
  if (root.children.length === 0) {
@@ -11281,15 +12029,17 @@ function makeUpdateCommand() {
11281
12029
  "Update only this declared asset (kind:@publisher/name, kind:name or name); exits 1 when none matches"
11282
12030
  ).option("--project-dir <path>", "Project directory", process.cwd()).option("--no-catalog", "Skip refreshing the catalog cache").option("--catalog-only", "Refresh the catalog cache only; do not re-deploy assets").option("--no-sync", "Skip syncing sources from upstream before re-deploying").option("-y, --yes", "Sync sources without the confirmation prompt").action(
11283
12031
  async (name, opts) => {
11284
- const projectDir = path18__default.resolve(opts.projectDir);
12032
+ const projectDir = path22__default.resolve(opts.projectDir);
11285
12033
  if (!opts.catalogOnly) requireProjectConfig(projectDir);
11286
12034
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
11287
12035
  const target = name !== void 0 && !opts.catalogOnly ? await resolveUpdateTarget(am2, name) : void 0;
11288
- if (opts.catalog !== false) {
12036
+ if (opts.catalog !== false && !opts.catalogOnly && onlyLibraryAssets(projectDir)) {
12037
+ logInfo("Catalog refresh skipped (every locked asset comes from a library)");
12038
+ } else if (opts.catalog !== false) {
11289
12039
  const catalogSpinner = createSpinner();
11290
12040
  catalogSpinner.start("Refreshing catalog cache");
11291
12041
  try {
11292
- const remote = await openCatalogSource({ projectDir: path18__default.resolve(opts.projectDir) });
12042
+ const remote = await openCatalogSource({ projectDir: path22__default.resolve(opts.projectDir) });
11293
12043
  const result2 = await remote.refresh();
11294
12044
  catalogSpinner.stop(
11295
12045
  `Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
@@ -11300,7 +12050,13 @@ function makeUpdateCommand() {
11300
12050
  catalogSpinner.stop("Catalog refresh skipped (catalog.url: local)");
11301
12051
  } else {
11302
12052
  catalogSpinner.stop("Catalog refresh failed");
11303
- logErr(`Catalog refresh failed: ${err2 instanceof Error ? err2.message : String(err2)}`);
12053
+ const why = err2 instanceof Error ? err2.message : String(err2);
12054
+ if (opts.catalogOnly) {
12055
+ logErr(`Catalog refresh failed: ${why}`);
12056
+ logInfo("Run `skaile catalog test` to debug.");
12057
+ process.exit(1);
12058
+ }
12059
+ logWarn(`Catalog refresh failed: ${why}`);
11304
12060
  logInfo("Continuing with asset re-deploy. Run `skaile catalog test` to debug.");
11305
12061
  }
11306
12062
  }
@@ -11402,10 +12158,29 @@ async function resolveUpdateTarget(am2, name) {
11402
12158
  for (const h of hits) console.error(` ${h.ref}`);
11403
12159
  process.exit(1);
11404
12160
  }
12161
+ const chain = await am2.why(name);
12162
+ if (chain.length > 2 && chain[chain.length - 1] === "direct (skaile.yaml)") {
12163
+ const plain = (ref) => ref.replace(/#.*$/, "");
12164
+ const root = chain[chain.length - 2];
12165
+ logErr(
12166
+ `${plain(chain[0])} is required by ${plain(chain[1])}; run \`skaile update ${plain(root)}\`.`
12167
+ );
12168
+ process.exit(1);
12169
+ }
11405
12170
  logErr(`No declared asset matches "${name}".`);
11406
12171
  if (declared.length > 0) logInfo(`Declared: ${declared.map((d) => d.ref).join(", ")}`);
11407
12172
  process.exit(1);
11408
12173
  }
12174
+ function onlyLibraryAssets(projectDir) {
12175
+ let lock;
12176
+ try {
12177
+ lock = readLock(path22__default.join(projectDir, "skaile.lock.yaml"));
12178
+ } catch {
12179
+ return false;
12180
+ }
12181
+ const entries = Object.values(lock?.assets ?? {});
12182
+ return entries.length > 0 && entries.every((e) => e.library !== void 0);
12183
+ }
11409
12184
  function readText2(file) {
11410
12185
  try {
11411
12186
  return readFileSync(file, "utf8");
@@ -11414,13 +12189,16 @@ function readText2(file) {
11414
12189
  }
11415
12190
  }
11416
12191
  async function updateOne(am2, projectDir, target) {
11417
- const lockPath = path18__default.join(projectDir, "skaile.lock.yaml");
12192
+ const lockPath = path22__default.join(projectDir, "skaile.lock.yaml");
11418
12193
  const before = readText2(lockPath);
11419
12194
  const spinner = createSpinner();
11420
12195
  spinner.start(`Updating ${target.ref}`);
11421
12196
  let deployed;
11422
12197
  try {
11423
- deployed = await am2.add(target.ref, { onLibraryMoved: (m) => reportMoved([m]) });
12198
+ deployed = await am2.add(target.ref, {
12199
+ preferLockedLibrary: true,
12200
+ onLibraryMoved: (m) => reportMoved([m])
12201
+ });
11424
12202
  } catch (err2) {
11425
12203
  spinner.stop("Failed");
11426
12204
  logErr(err2 instanceof Error ? err2.message : String(err2));
@@ -11545,9 +12323,10 @@ function whyEmptyMessage(ref, declared) {
11545
12323
  }
11546
12324
  function makeWhyCommand() {
11547
12325
  return new Command("why").description("Show why an asset is installed (dependency chain)").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
12326
+ requireProjectConfig(opts.projectDir);
11548
12327
  const am2 = new AssetManager({
11549
12328
  registry: getKindRegistry(),
11550
- projectDir: path18__default.resolve(opts.projectDir)
12329
+ projectDir: path22__default.resolve(opts.projectDir)
11551
12330
  });
11552
12331
  const chain = await am2.why(ref);
11553
12332
  if (chain.length === 0) {
@@ -11588,11 +12367,38 @@ function makeWhyCommand() {
11588
12367
  });
11589
12368
  }
11590
12369
 
12370
+ // cli/src/index-busy.ts
12371
+ var INDEX_BUSY_MESSAGE = "The skaile index is busy (another skaile process holds it); retry in a moment.";
12372
+ function isIndexBusyError(err2) {
12373
+ const seen = /* @__PURE__ */ new Set();
12374
+ let cur = err2;
12375
+ while (cur && typeof cur === "object" && !seen.has(cur)) {
12376
+ seen.add(cur);
12377
+ const { code, message, cause } = cur;
12378
+ if (typeof code === "string" && code.startsWith("SQLITE_BUSY")) return true;
12379
+ if (typeof message === "string" && /SQLITE_BUSY|database is locked/i.test(message)) return true;
12380
+ cur = cause;
12381
+ }
12382
+ return false;
12383
+ }
12384
+
11591
12385
  // cli/src/index.ts
12386
+ {
12387
+ const envLevel = process.env.SKAILE_LOG_LEVEL;
12388
+ const level = envLevel === "debug" || envLevel === "info" || envLevel === "warn" || envLevel === "error" ? envLevel : "warn";
12389
+ registerLogStore(
12390
+ new LogStore({
12391
+ sessionId: "cli",
12392
+ level,
12393
+ flushIntervalMs: 0,
12394
+ sinks: [new StdoutSink({ stream: "stderr", format: "pretty" })]
12395
+ })
12396
+ );
12397
+ }
11592
12398
  var _defaultFormatHelp = Help.prototype.formatHelp;
11593
12399
  var pkg = JSON.parse(
11594
12400
  readFileSync(
11595
- path18__default.resolve(path18__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
12401
+ path22__default.resolve(path22__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
11596
12402
  "utf-8"
11597
12403
  )
11598
12404
  );
@@ -11603,7 +12409,7 @@ for (const key of [
11603
12409
  "SKAILE_CACHE_DIR"
11604
12410
  ]) {
11605
12411
  const value = process.env[key];
11606
- if (value) process.env[key] = path18__default.resolve(value);
12412
+ if (value) process.env[key] = path22__default.resolve(value);
11607
12413
  }
11608
12414
  var program = new Command("skaile").description("AI asset manager").version(pkg.version, "-v, --version", "Show the skaile CLI version").enablePositionalOptions().configureHelp({
11609
12415
  formatHelp(cmd, helper) {
@@ -11648,7 +12454,7 @@ Execution:
11648
12454
  repl Interactive agent REPL
11649
12455
  resume Resume last session
11650
12456
  serve [--compile-test] Start WebSocket agent server
11651
- mcp-server Start workspace MCP server (for .claude/mcp.json)
12457
+ mcp-server Start workspace MCP server (for .mcp.json)
11652
12458
  integration install [--driver all] Install agent integration (claude-code | omp | codex)
11653
12459
  integration uninstall [--driver all] Uninstall agent integration
11654
12460
  integration enable Enable integration (claude-code only)
@@ -11723,7 +12529,7 @@ program.command("init [project-dir]").description("Initialize a project director
11723
12529
  (projectDir, opts) => runInit(projectDir, opts)
11724
12530
  );
11725
12531
  async function runInit(projectDir, opts) {
11726
- const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync6 } = await import('fs');
12532
+ const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync7 } = await import('fs');
11727
12533
  const { stringify: stringify2 } = await import('yaml');
11728
12534
  const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
11729
12535
  const harness = opts.harness;
@@ -11732,32 +12538,32 @@ async function runInit(projectDir, opts) {
11732
12538
  process.exitCode = 1;
11733
12539
  return;
11734
12540
  }
11735
- const resolved = path18__default.resolve(projectDir ?? ".");
11736
- const projectName = path18__default.basename(resolved);
12541
+ const resolved = path22__default.resolve(projectDir ?? ".");
12542
+ const projectName = path22__default.basename(resolved);
11737
12543
  const created = [];
11738
- const { existsSync: existsSync17 } = await import('fs');
11739
- if (!existsSync17(resolved)) {
12544
+ const { existsSync: existsSync21 } = await import('fs');
12545
+ if (!existsSync21(resolved)) {
11740
12546
  mkdirSync5(resolved, { recursive: true });
11741
12547
  created.push(".");
11742
12548
  }
11743
- const skaileDir = path18__default.join(resolved, ".skaile");
11744
- if (!existsSync17(skaileDir)) {
11745
- mkdirSync5(path18__default.join(skaileDir, "sessions"), { recursive: true });
12549
+ const skaileDir = path22__default.join(resolved, ".skaile");
12550
+ if (!existsSync21(skaileDir)) {
12551
+ mkdirSync5(path22__default.join(skaileDir, "sessions"), { recursive: true });
11746
12552
  created.push(".skaile/");
11747
12553
  }
11748
- const settingsPath = path18__default.join(skaileDir, "settings.json");
11749
- if (!existsSync17(settingsPath)) {
11750
- writeFileSync6(settingsPath, "{}\n");
12554
+ const settingsPath = path22__default.join(skaileDir, "settings.json");
12555
+ if (!existsSync21(settingsPath)) {
12556
+ writeFileSync7(settingsPath, "{}\n");
11751
12557
  created.push(".skaile/settings.json");
11752
12558
  }
11753
- const wsConfigPath = path18__default.join(resolved, "skaile.yaml");
11754
- if (!existsSync17(wsConfigPath)) {
11755
- writeFileSync6(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
12559
+ const wsConfigPath = path22__default.join(resolved, "skaile.yaml");
12560
+ if (!existsSync21(wsConfigPath)) {
12561
+ writeFileSync7(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
11756
12562
  created.push("skaile.yaml");
11757
12563
  }
11758
12564
  for (const dir of new Set(Object.values(DRIVER_TARGETS[harness].local))) {
11759
- const full = path18__default.join(resolved, dir);
11760
- if (!existsSync17(full)) {
12565
+ const full = path22__default.join(resolved, dir);
12566
+ if (!existsSync21(full)) {
11761
12567
  mkdirSync5(full, { recursive: true });
11762
12568
  created.push(`${dir}/`);
11763
12569
  }
@@ -11787,10 +12593,13 @@ function buildInitWorkspaceConfig(projectName, harness) {
11787
12593
  }
11788
12594
  async function initGitScaffold(resolved, created) {
11789
12595
  const { execSync: execSync2 } = await import('child_process');
11790
- const { existsSync: existsSync17, readFileSync: readFileSync10, writeFileSync: writeFileSync6 } = await import('fs');
11791
- const gitignorePath = path18__default.join(resolved, ".gitignore");
12596
+ const { existsSync: existsSync21, readFileSync: readFileSync12, writeFileSync: writeFileSync7 } = await import('fs');
12597
+ const gitignorePath = path22__default.join(resolved, ".gitignore");
11792
12598
  const entries = [
11793
12599
  "node_modules/",
12600
+ // Python bytecode a deployed skill script leaves inside `.claude/skills` and friends.
12601
+ "__pycache__/",
12602
+ "*.pyc",
11794
12603
  ".skaile/sessions/",
11795
12604
  ".skaile/cache/",
11796
12605
  // skaile-created artifacts that must never be committed: the per-session log
@@ -11801,20 +12610,29 @@ async function initGitScaffold(resolved, created) {
11801
12610
  ".skaile/settings.json",
11802
12611
  ".skaile/providers.yml",
11803
12612
  ".skaile/history.yaml",
12613
+ // Per-machine files a run writes into the project: the system prompt handed to the harness
12614
+ // (it carries the host path) and omp's session logs.
12615
+ ".codex/skaile-session-instructions.md",
12616
+ ".omp/system.md",
12617
+ ".omp/sessions/",
12618
+ // `skaile integration install` writes the absolute project path into these.
12619
+ ".codex/config.toml",
12620
+ ".omp/extensions/skaile.ts",
12621
+ ".skaile/plugin-state.json",
11804
12622
  "*.log",
11805
12623
  ".env",
11806
12624
  ".env.local"
11807
12625
  ];
11808
- const existing = existsSync17(gitignorePath) ? readFileSync10(gitignorePath, "utf-8") : "";
12626
+ const existing = existsSync21(gitignorePath) ? readFileSync12(gitignorePath, "utf-8") : "";
11809
12627
  const have = new Set(existing.split("\n").map((l) => l.trim()));
11810
12628
  const append = entries.filter((e) => !have.has(e));
11811
12629
  if (append.length > 0) {
11812
12630
  const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
11813
- writeFileSync6(gitignorePath, `${existing + prefix}${append.join("\n")}
12631
+ writeFileSync7(gitignorePath, `${existing + prefix}${append.join("\n")}
11814
12632
  `);
11815
12633
  if (!existing) created.push(".gitignore");
11816
12634
  }
11817
- if (!existsSync17(path18__default.join(resolved, ".git"))) {
12635
+ if (!existsSync21(path22__default.join(resolved, ".git"))) {
11818
12636
  try {
11819
12637
  execSync2("git init", { cwd: resolved, stdio: "pipe" });
11820
12638
  created.push(".git/");
@@ -11826,10 +12644,10 @@ async function initGitScaffold(resolved, created) {
11826
12644
  }
11827
12645
  async function bootstrapUserConfig() {
11828
12646
  try {
11829
- const fs13 = await import('fs');
12647
+ const fs14 = await import('fs');
11830
12648
  const { userConfigPath: userConfigPath2, saveConfig, getConfigDefaults } = await import('../library/index.js');
11831
12649
  const userCfgPath = userConfigPath2();
11832
- if (!fs13.existsSync(userCfgPath)) {
12650
+ if (!fs14.existsSync(userCfgPath)) {
11833
12651
  const defaults = getConfigDefaults();
11834
12652
  saveConfig(userCfgPath, {
11835
12653
  catalog: { url: defaults.catalog.url, cache_ttl: defaults.catalog.cache_ttl }
@@ -11844,7 +12662,7 @@ async function bootstrapUserConfig() {
11844
12662
  }
11845
12663
  async function hydrateInitSources(resolved, created) {
11846
12664
  try {
11847
- const { ensureSourcesCloned } = await import('../ensure-sources-2RONZKCU.js');
12665
+ const { ensureSourcesCloned } = await import('../ensure-sources-VUKHL65L.js');
11848
12666
  const hydrate = ensureSourcesCloned(resolved, { quiet: true });
11849
12667
  for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
11850
12668
  if (hydrate.failed.length > 0) {
@@ -11860,7 +12678,7 @@ function printInitSummary(resolved, projectDir, created) {
11860
12678
  logOk(`Initialized project at ${S.heading(resolved)}`);
11861
12679
  console.log();
11862
12680
  console.log(S.heading(" Next steps:"));
11863
- const isCurrentDir = resolved === path18__default.resolve(".");
12681
+ const isCurrentDir = resolved === path22__default.resolve(".");
11864
12682
  let step = 1;
11865
12683
  if (!isCurrentDir) {
11866
12684
  console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
@@ -11884,7 +12702,7 @@ function printInitSummary(resolved, projectDir, created) {
11884
12702
  console.log();
11885
12703
  }
11886
12704
  program.command("setup").description("Interactive provider setup wizard").action(async () => {
11887
- const { cmdSetup } = await import('../setup-7DQJKHUI.js');
12705
+ const { cmdSetup } = await import('../setup-L632QIHV.js');
11888
12706
  await cmdSetup([], { projectDir: process.cwd() });
11889
12707
  });
11890
12708
  program.addCommand(makeInstallCommand());
@@ -11972,6 +12790,10 @@ try {
11972
12790
  await program.parseAsync();
11973
12791
  commandSettled = true;
11974
12792
  } catch (err2) {
12793
+ if (isIndexBusyError(err2)) {
12794
+ logErr(INDEX_BUSY_MESSAGE);
12795
+ process.exit(1);
12796
+ }
11975
12797
  const { LibrarySyncError } = await import('../library/index.js');
11976
12798
  if (!(err2 instanceof LibrarySyncError || err2 instanceof SourceEntryError)) throw err2;
11977
12799
  logErr(err2.message);