@skaile/workspaces 5.9.0 → 5.11.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 (316) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/README.md +12 -0
  3. package/dist/{asset-feeds-XMKKUUK6.js → asset-feeds-CXGQIDFR.js} +19 -19
  4. package/dist/{asset-feeds-XMKKUUK6.js.map → asset-feeds-CXGQIDFR.js.map} +1 -1
  5. package/dist/asset-manager/catalog-deployer.js +8 -8
  6. package/dist/asset-manager/index.js +14 -14
  7. package/dist/asset-manager/installer.js +10 -10
  8. package/dist/asset-manager/renderers.js +9 -9
  9. package/dist/asset-manager/src/index.d.ts +400 -35
  10. package/dist/asset-manager/src/index.d.ts.map +1 -1
  11. package/dist/asset-manager/src/install-agent.d.ts +3 -1
  12. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  13. package/dist/asset-manager/src/install-instances.d.ts +31 -1
  14. package/dist/asset-manager/src/install-instances.d.ts.map +1 -1
  15. package/dist/asset-manager/src/installer.d.ts +43 -3
  16. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  17. package/dist/asset-manager/src/renderers.d.ts +4 -5
  18. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  19. package/dist/bridge/drivers/claude-sdk.js +11 -11
  20. package/dist/bridge/drivers/codex.js +11 -11
  21. package/dist/bridge/drivers/continue.js +10 -10
  22. package/dist/bridge/drivers/echo.js +2 -2
  23. package/dist/bridge/drivers/gemini.js +7 -7
  24. package/dist/bridge/drivers/goose.js +10 -10
  25. package/dist/bridge/drivers/omp.js +19 -3
  26. package/dist/bridge/drivers/omp.js.map +1 -1
  27. package/dist/bridge/drivers/opencode.js +10 -10
  28. package/dist/bridge/drivers/qwen.js +7 -7
  29. package/dist/bridge/index.js +12 -12
  30. package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
  31. package/dist/{chunk-4MQS7CAF.js → chunk-2F5AWQX5.js} +437 -175
  32. package/dist/chunk-2F5AWQX5.js.map +1 -0
  33. package/dist/{chunk-UM7RIAHO.js → chunk-3SM2DL2T.js} +8 -8
  34. package/dist/{chunk-UM7RIAHO.js.map → chunk-3SM2DL2T.js.map} +1 -1
  35. package/dist/{chunk-5NNNV76P.js → chunk-47U4GZ4M.js} +2 -2
  36. package/dist/{chunk-5NNNV76P.js.map → chunk-47U4GZ4M.js.map} +1 -1
  37. package/dist/{chunk-TTRYE6AC.js → chunk-4A4OD24G.js} +9 -9
  38. package/dist/{chunk-TTRYE6AC.js.map → chunk-4A4OD24G.js.map} +1 -1
  39. package/dist/{chunk-ZTBAYUDY.js → chunk-6O2X3GPW.js} +2 -2
  40. package/dist/{chunk-ZTBAYUDY.js.map → chunk-6O2X3GPW.js.map} +1 -1
  41. package/dist/{chunk-JAKOMFC6.js → chunk-ALEYHUC5.js} +114 -46
  42. package/dist/chunk-ALEYHUC5.js.map +1 -0
  43. package/dist/{chunk-QVNRCDTV.js → chunk-BNMZVPYA.js} +7 -7
  44. package/dist/chunk-BNMZVPYA.js.map +1 -0
  45. package/dist/{chunk-2FRUUDZY.js → chunk-CAHB6MHA.js} +5 -5
  46. package/dist/{chunk-2FRUUDZY.js.map → chunk-CAHB6MHA.js.map} +1 -1
  47. package/dist/{chunk-GKMZ6THE.js → chunk-CJERAGFY.js} +44 -33
  48. package/dist/chunk-CJERAGFY.js.map +1 -0
  49. package/dist/{chunk-CKQEIY43.js → chunk-COH6FQAG.js} +4 -4
  50. package/dist/{chunk-CKQEIY43.js.map → chunk-COH6FQAG.js.map} +1 -1
  51. package/dist/{chunk-UO7WPLDY.js → chunk-CPWLNZGJ.js} +3 -3
  52. package/dist/{chunk-UO7WPLDY.js.map → chunk-CPWLNZGJ.js.map} +1 -1
  53. package/dist/{chunk-MGGFBZWA.js → chunk-D3B36CYC.js} +4 -3
  54. package/dist/chunk-D3B36CYC.js.map +1 -0
  55. package/dist/{chunk-UMVKJM4Q.js → chunk-DALV4HHP.js} +18 -3
  56. package/dist/chunk-DALV4HHP.js.map +1 -0
  57. package/dist/{chunk-IMKSM5NL.js → chunk-DZMNFCWB.js} +1447 -199
  58. package/dist/chunk-DZMNFCWB.js.map +1 -0
  59. package/dist/{chunk-GB7WDMH2.js → chunk-EDYHEMJA.js} +4 -4
  60. package/dist/{chunk-GB7WDMH2.js.map → chunk-EDYHEMJA.js.map} +1 -1
  61. package/dist/{chunk-YSHVQGUS.js → chunk-FH7W6TJ4.js} +164 -41
  62. package/dist/chunk-FH7W6TJ4.js.map +1 -0
  63. package/dist/{chunk-W5DWWE4Y.js → chunk-G4FFOV3N.js} +4 -4
  64. package/dist/{chunk-W5DWWE4Y.js.map → chunk-G4FFOV3N.js.map} +1 -1
  65. package/dist/{chunk-2LWYNQK7.js → chunk-GCHPUTA3.js} +3 -3
  66. package/dist/{chunk-2LWYNQK7.js.map → chunk-GCHPUTA3.js.map} +1 -1
  67. package/dist/{chunk-JZ5EHBPI.js → chunk-GV4DZ6MT.js} +20 -4
  68. package/dist/chunk-GV4DZ6MT.js.map +1 -0
  69. package/dist/{chunk-S53LOR7B.js → chunk-HCEVNYSH.js} +3 -3
  70. package/dist/{chunk-S53LOR7B.js.map → chunk-HCEVNYSH.js.map} +1 -1
  71. package/dist/{chunk-EF7NPDDU.js → chunk-HZXUXHIV.js} +31 -17
  72. package/dist/chunk-HZXUXHIV.js.map +1 -0
  73. package/dist/{chunk-IR33D6EP.js → chunk-IER3KIPH.js} +5 -5
  74. package/dist/{chunk-IR33D6EP.js.map → chunk-IER3KIPH.js.map} +1 -1
  75. package/dist/{chunk-Y7QA2OLD.js → chunk-J4RBUFGM.js} +22 -20
  76. package/dist/chunk-J4RBUFGM.js.map +1 -0
  77. package/dist/{chunk-J7U3PIOE.js → chunk-M3B6EIJD.js} +4 -4
  78. package/dist/{chunk-J7U3PIOE.js.map → chunk-M3B6EIJD.js.map} +1 -1
  79. package/dist/{chunk-DNZYOKOJ.js → chunk-MZG34MBZ.js} +3 -3
  80. package/dist/{chunk-DNZYOKOJ.js.map → chunk-MZG34MBZ.js.map} +1 -1
  81. package/dist/{chunk-V2DXZYBB.js → chunk-NWDSLXOX.js} +3 -3
  82. package/dist/{chunk-V2DXZYBB.js.map → chunk-NWDSLXOX.js.map} +1 -1
  83. package/dist/{chunk-36AFURKZ.js → chunk-PBBPZYVG.js} +61 -12
  84. package/dist/chunk-PBBPZYVG.js.map +1 -0
  85. package/dist/{chunk-P67WJVP4.js → chunk-PQFHMQHQ.js} +10 -9
  86. package/dist/chunk-PQFHMQHQ.js.map +1 -0
  87. package/dist/{chunk-UAROCOXF.js → chunk-QVFAS5IO.js} +3 -3
  88. package/dist/{chunk-UAROCOXF.js.map → chunk-QVFAS5IO.js.map} +1 -1
  89. package/dist/{chunk-K3CVFRVS.js → chunk-QZNJOHN6.js} +3 -3
  90. package/dist/{chunk-K3CVFRVS.js.map → chunk-QZNJOHN6.js.map} +1 -1
  91. package/dist/{chunk-FVJK4QWM.js → chunk-R7NHYEJF.js} +4 -4
  92. package/dist/{chunk-FVJK4QWM.js.map → chunk-R7NHYEJF.js.map} +1 -1
  93. package/dist/{chunk-GXLQLPE5.js → chunk-RYYLMBA2.js} +5 -5
  94. package/dist/{chunk-GXLQLPE5.js.map → chunk-RYYLMBA2.js.map} +1 -1
  95. package/dist/{chunk-Y4N2NUZD.js → chunk-S3O3GKB7.js} +4 -4
  96. package/dist/{chunk-Y4N2NUZD.js.map → chunk-S3O3GKB7.js.map} +1 -1
  97. package/dist/{chunk-GTILM2CI.js → chunk-SBSA3IQA.js} +43 -12
  98. package/dist/chunk-SBSA3IQA.js.map +1 -0
  99. package/dist/{chunk-4PTSR4UU.js → chunk-T42WRQ4O.js} +3 -3
  100. package/dist/{chunk-4PTSR4UU.js.map → chunk-T42WRQ4O.js.map} +1 -1
  101. package/dist/{chunk-MR5HBOUF.js → chunk-T7CTHHG7.js} +3 -3
  102. package/dist/{chunk-MR5HBOUF.js.map → chunk-T7CTHHG7.js.map} +1 -1
  103. package/dist/{chunk-FZNG4V4J.js → chunk-TCHRMVTO.js} +4 -4
  104. package/dist/{chunk-FZNG4V4J.js.map → chunk-TCHRMVTO.js.map} +1 -1
  105. package/dist/{chunk-LAMCXQGA.js → chunk-VLTQGE2E.js} +75 -25
  106. package/dist/chunk-VLTQGE2E.js.map +1 -0
  107. package/dist/{chunk-7AI3Q5AQ.js → chunk-WSBKB4CJ.js} +71 -24
  108. package/dist/chunk-WSBKB4CJ.js.map +1 -0
  109. package/dist/{chunk-CGT45WN7.js → chunk-X77SUM4P.js} +3 -3
  110. package/dist/{chunk-CGT45WN7.js.map → chunk-X77SUM4P.js.map} +1 -1
  111. package/dist/{chunk-SCOT677Q.js → chunk-XDKH7XSA.js} +5 -5
  112. package/dist/{chunk-SCOT677Q.js.map → chunk-XDKH7XSA.js.map} +1 -1
  113. package/dist/{chunk-QVEKLSEH.js → chunk-XUSALIEI.js} +6 -6
  114. package/dist/{chunk-QVEKLSEH.js.map → chunk-XUSALIEI.js.map} +1 -1
  115. package/dist/{chunk-FYXZRVID.js → chunk-Y3HTGHJC.js} +3 -3
  116. package/dist/{chunk-FYXZRVID.js.map → chunk-Y3HTGHJC.js.map} +1 -1
  117. package/dist/chunk-YOH2L76X.js +505 -0
  118. package/dist/chunk-YOH2L76X.js.map +1 -0
  119. package/dist/{chunk-B6GIW55K.js → chunk-ZCAJZ4B2.js} +7 -4
  120. package/dist/chunk-ZCAJZ4B2.js.map +1 -0
  121. package/dist/{chunk-BTE2V4IW.js → chunk-ZPWTOUTK.js} +76 -7
  122. package/dist/{chunk-BTE2V4IW.js.map → chunk-ZPWTOUTK.js.map} +1 -1
  123. package/dist/cli/index.js +1034 -794
  124. package/dist/cli/index.js.map +1 -1
  125. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  126. package/dist/cli/src/commands/catalog.d.ts +8 -5
  127. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  128. package/dist/cli/src/commands/diff.d.ts +4 -2
  129. package/dist/cli/src/commands/diff.d.ts.map +1 -1
  130. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  131. package/dist/cli/src/commands/library-index.d.ts +34 -2
  132. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  133. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  134. package/dist/cli/src/commands/manage.d.ts +12 -5
  135. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  136. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  137. package/dist/cli/src/commands/outdated.d.ts +7 -5
  138. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  139. package/dist/cli/src/commands/project.d.ts +13 -8
  140. package/dist/cli/src/commands/project.d.ts.map +1 -1
  141. package/dist/cli/src/commands/run.d.ts.map +1 -1
  142. package/dist/cli/src/commands/source.d.ts +30 -1
  143. package/dist/cli/src/commands/source.d.ts.map +1 -1
  144. package/dist/cli/src/commands/update.d.ts.map +1 -1
  145. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  146. package/dist/cli/src/commands/why.d.ts +1 -0
  147. package/dist/cli/src/commands/why.d.ts.map +1 -1
  148. package/dist/cli/src/helpers.d.ts +12 -0
  149. package/dist/cli/src/helpers.d.ts.map +1 -1
  150. package/dist/cli/src/skill-checks.d.ts +57 -4
  151. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  152. package/dist/connectors/config.js +5 -5
  153. package/dist/connectors/index.js +16 -16
  154. package/dist/{connectors-C7UQ73BK.js → connectors-4QWAKPHB.js} +19 -19
  155. package/dist/{connectors-C7UQ73BK.js.map → connectors-4QWAKPHB.js.map} +1 -1
  156. package/dist/core/index.js +7 -7
  157. package/dist/core/logging.js +1 -1
  158. package/dist/core/manifest.js +2 -2
  159. package/dist/core/models.js +1 -1
  160. package/dist/core/publish-manifest.js +2 -2
  161. package/dist/core/ref.js +1 -1
  162. package/dist/core/runtime-assets.js +5 -5
  163. package/dist/core/src/index.d.ts +2 -1
  164. package/dist/core/src/index.d.ts.map +1 -1
  165. package/dist/core/src/lock.d.ts +6 -2
  166. package/dist/core/src/lock.d.ts.map +1 -1
  167. package/dist/core/src/logging/sinks/sqlite-runtime.d.ts.map +1 -1
  168. package/dist/core/src/manifest.d.ts.map +1 -1
  169. package/dist/core/src/models.d.ts +22 -6
  170. package/dist/core/src/models.d.ts.map +1 -1
  171. package/dist/core/src/publish-manifest.d.ts +29 -3
  172. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  173. package/dist/core/src/repo-manager.d.ts.map +1 -1
  174. package/dist/core/src/requirements.d.ts +26 -0
  175. package/dist/core/src/requirements.d.ts.map +1 -0
  176. package/dist/core/src/walker.d.ts.map +1 -1
  177. package/dist/core/src/workspace-config.d.ts +22 -1
  178. package/dist/core/src/workspace-config.d.ts.map +1 -1
  179. package/dist/core/src/workspace-yaml-editor.d.ts +4 -1
  180. package/dist/core/src/workspace-yaml-editor.d.ts.map +1 -1
  181. package/dist/core/workspace-config.js +4 -4
  182. package/dist/deploy/index.js +7 -7
  183. package/dist/discovery/index.js +5 -5
  184. package/dist/discovery/src/builtin-providers.d.ts.map +1 -1
  185. package/dist/discovery/src/discover-manifest.d.ts.map +1 -1
  186. package/dist/discovery/src/discover.d.ts.map +1 -1
  187. package/dist/discovery/src/source-config.d.ts.map +1 -1
  188. package/dist/discovery/src/tree-entries.d.ts.map +1 -1
  189. package/dist/{ensure-sources-SRC2DVR5.js → ensure-sources-2RONZKCU.js} +17 -17
  190. package/dist/{ensure-sources-SRC2DVR5.js.map → ensure-sources-2RONZKCU.js.map} +1 -1
  191. package/dist/factory-assets/connectors/box.js +16 -16
  192. package/dist/factory-assets/connectors/deploy.js +16 -16
  193. package/dist/factory-assets/connectors/devserver.js +16 -16
  194. package/dist/factory-assets/connectors/flow/adapter.js +16 -16
  195. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
  196. package/dist/factory-assets/connectors/flow/contract.js +1 -1
  197. package/dist/factory-assets/connectors/flow/engine.js +9 -9
  198. package/dist/factory-assets/connectors/flow/run-flow.js +18 -18
  199. package/dist/factory-assets/connectors/flow.js +16 -16
  200. package/dist/factory-assets/connectors/git.js +16 -16
  201. package/dist/factory-assets/connectors/gmail.js +16 -16
  202. package/dist/factory-assets/connectors/googledrive.js +16 -16
  203. package/dist/factory-assets/connectors/local.js +16 -16
  204. package/dist/factory-assets/connectors/mattermost.js +16 -16
  205. package/dist/factory-assets/connectors/memory.js +16 -16
  206. package/dist/factory-assets/connectors/minio.js +16 -16
  207. package/dist/factory-assets/connectors/postgres.js +16 -16
  208. package/dist/factory-assets/connectors/s3.js +16 -16
  209. package/dist/factory-assets/connectors/sharepoint.js +16 -16
  210. package/dist/factory-assets/connectors/sqlite.js +16 -16
  211. package/dist/factory-assets/connectors/static-server.js +16 -16
  212. package/dist/factory-assets/connectors/tunnel.js +16 -16
  213. package/dist/factory-assets/connectors/webdav.js +16 -16
  214. package/dist/factory-assets/connectors/xstate-store.js +16 -16
  215. package/dist/factory-assets/connectors/xstate.js +16 -16
  216. package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +9 -3
  217. package/dist/factory-assets/skills/authoring-skaile-manifests/references/dependency-standard.md +4 -2
  218. package/dist/{flows-CBYRSAGS.js → flows-EQF2CH4U.js} +12 -12
  219. package/dist/{flows-CBYRSAGS.js.map → flows-EQF2CH4U.js.map} +1 -1
  220. package/dist/{helpers-XAEKCZKT.js → helpers-CFK6YP6R.js} +17 -17
  221. package/dist/{helpers-XAEKCZKT.js.map → helpers-CFK6YP6R.js.map} +1 -1
  222. package/dist/library/index.js +11 -11
  223. package/dist/library/install.js +3 -3
  224. package/dist/library/src/index.d.ts +2 -1
  225. package/dist/library/src/index.d.ts.map +1 -1
  226. package/dist/library/src/local/library-dir.d.ts +68 -0
  227. package/dist/library/src/local/library-dir.d.ts.map +1 -0
  228. package/dist/library/src/local/library-manager.d.ts +10 -1
  229. package/dist/library/src/local/library-manager.d.ts.map +1 -1
  230. package/dist/library/src/local/library.d.ts +2 -2
  231. package/dist/library/src/local/library.d.ts.map +1 -1
  232. package/dist/library/src/local/local-catalog-source.d.ts +9 -0
  233. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  234. package/dist/library/src/manifest-writer.d.ts +55 -4
  235. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  236. package/dist/library/src/remote/cache.d.ts +18 -1
  237. package/dist/library/src/remote/cache.d.ts.map +1 -1
  238. package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
  239. package/dist/library/src/remote/rest-catalog-source.d.ts.map +1 -1
  240. package/dist/library/src/sync/git-driver.d.ts +7 -6
  241. package/dist/library/src/sync/git-driver.d.ts.map +1 -1
  242. package/dist/{library-publish-VJSWMOLH.js → library-publish-53UTB3MB.js} +151 -42
  243. package/dist/library-publish-53UTB3MB.js.map +1 -0
  244. package/dist/open-library-BOSPJVID.js +40 -0
  245. package/dist/{open-library-DB2PNL2X.js.map → open-library-BOSPJVID.js.map} +1 -1
  246. package/dist/open-registry-4FI7HKET.js +32 -0
  247. package/dist/{open-registry-ZUZJ7MS7.js.map → open-registry-4FI7HKET.js.map} +1 -1
  248. package/dist/paths-SUS4S4YT.js +22 -0
  249. package/dist/{paths-FQ64OLJG.js.map → paths-SUS4S4YT.js.map} +1 -1
  250. package/dist/{plugin-store-MPAMD5OT.js → plugin-store-AGQDMING.js} +9 -9
  251. package/dist/{plugin-store-MPAMD5OT.js.map → plugin-store-AGQDMING.js.map} +1 -1
  252. package/dist/project-I55A4O2T.js +41 -0
  253. package/dist/{project-I6NX3NFB.js.map → project-I55A4O2T.js.map} +1 -1
  254. package/dist/resolver/index.js +8 -8
  255. package/dist/runner/index.js +30 -30
  256. package/dist/runner/src/agent.d.ts.map +1 -1
  257. package/dist/runner/src/serve.d.ts.map +1 -1
  258. package/dist/runner/src/usage-limit-turn-hold.d.ts +51 -0
  259. package/dist/runner/src/usage-limit-turn-hold.d.ts.map +1 -0
  260. package/dist/sdk/asset-manager.js +14 -14
  261. package/dist/sdk/bridge.js +12 -12
  262. package/dist/sdk/core.js +7 -7
  263. package/dist/sdk/flow.js +9 -9
  264. package/dist/sdk/index.js +30 -30
  265. package/dist/sdk/resolver.js +8 -8
  266. package/dist/sdk/runner.js +30 -30
  267. package/dist/{setup-B7JUHYJW.js → setup-7DQJKHUI.js} +22 -22
  268. package/dist/{setup-B7JUHYJW.js.map → setup-7DQJKHUI.js.map} +1 -1
  269. package/dist/{skills-TVO26Y4V.js → skills-NUEN5NDX.js} +13 -13
  270. package/dist/{skills-TVO26Y4V.js.map → skills-NUEN5NDX.js.map} +1 -1
  271. package/dist/source-G2LV5LVD.js +41 -0
  272. package/dist/{source-PJBMDCKX.js.map → source-G2LV5LVD.js.map} +1 -1
  273. package/dist/{source-manifest-publish-LLJWXGID.js → source-manifest-publish-6RM7SWLZ.js} +24 -24
  274. package/dist/{source-manifest-publish-LLJWXGID.js.map → source-manifest-publish-6RM7SWLZ.js.map} +1 -1
  275. package/dist/tui/index.js +61 -41
  276. package/dist/tui/index.js.map +1 -1
  277. package/dist/tui/src/repl.d.ts.map +1 -1
  278. package/dist/types/manifests.js +1 -1
  279. package/dist/types/src/manifests/agent.d.ts +2 -0
  280. package/dist/types/src/manifests/agent.d.ts.map +1 -1
  281. package/dist/types/src/manifests/contract.d.ts +2 -0
  282. package/dist/types/src/manifests/contract.d.ts.map +1 -1
  283. package/dist/types/src/manifests/index.d.ts +3 -3
  284. package/dist/types/src/manifests/index.d.ts.map +1 -1
  285. package/dist/types/src/manifests/preset.d.ts +1 -1
  286. package/dist/types/src/manifests/prompt.d.ts +2 -0
  287. package/dist/types/src/manifests/prompt.d.ts.map +1 -1
  288. package/dist/workspace-plugin/adapters/mcp.js +23 -23
  289. package/dist/workspace-plugin/adapters/omp.js +14 -14
  290. package/dist/workspace-plugin/index.js +2 -2
  291. package/package.json +1 -1
  292. package/dist/chunk-36AFURKZ.js.map +0 -1
  293. package/dist/chunk-4MQS7CAF.js.map +0 -1
  294. package/dist/chunk-7AI3Q5AQ.js.map +0 -1
  295. package/dist/chunk-B6GIW55K.js.map +0 -1
  296. package/dist/chunk-EF7NPDDU.js.map +0 -1
  297. package/dist/chunk-GKMZ6THE.js.map +0 -1
  298. package/dist/chunk-GTILM2CI.js.map +0 -1
  299. package/dist/chunk-IMKSM5NL.js.map +0 -1
  300. package/dist/chunk-JAKOMFC6.js.map +0 -1
  301. package/dist/chunk-JZ5EHBPI.js.map +0 -1
  302. package/dist/chunk-LAMCXQGA.js.map +0 -1
  303. package/dist/chunk-MGGFBZWA.js.map +0 -1
  304. package/dist/chunk-P67WJVP4.js.map +0 -1
  305. package/dist/chunk-QVNRCDTV.js.map +0 -1
  306. package/dist/chunk-UMVKJM4Q.js.map +0 -1
  307. package/dist/chunk-Y7QA2OLD.js.map +0 -1
  308. package/dist/chunk-YSHVQGUS.js.map +0 -1
  309. package/dist/chunk-ZAOGFXDO.js +0 -112
  310. package/dist/chunk-ZAOGFXDO.js.map +0 -1
  311. package/dist/library-publish-VJSWMOLH.js.map +0 -1
  312. package/dist/open-library-DB2PNL2X.js +0 -40
  313. package/dist/open-registry-ZUZJ7MS7.js +0 -32
  314. package/dist/paths-FQ64OLJG.js +0 -22
  315. package/dist/project-I6NX3NFB.js +0 -41
  316. package/dist/source-PJBMDCKX.js +0 -41
package/dist/cli/index.js CHANGED
@@ -1,24 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-SCOT677Q.js';
3
- import { makeSourceCommand, syncProjectSources } from '../chunk-7AI3Q5AQ.js';
4
- import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportRelocked, REF_HINT, reportInstalledSoftDeps } from '../chunk-GKMZ6THE.js';
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';
5
5
  import { createSpinner } from '../chunk-NESV47MF.js';
6
- import { AI_RESOURCES } from '../chunk-Y4N2NUZD.js';
7
- import { findAssetManifestFile, declaredVersion, readAssetBody, checkAssetManifest } from '../chunk-ZAOGFXDO.js';
8
- import { getStoreConfig, storeFetch, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, isStoreAuthenticated, getStoreToken, getStoreIdentity, assetEntryRef, manifestVersionMismatchMessage, refFor } from '../chunk-GXLQLPE5.js';
9
- import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-P67WJVP4.js';
10
- import { logErr, S, logOk, logInfo, logWarn, TARGET_DEFAULT_HINT, deferredWarnings, warnLegacyClaudeCopies, kindColorPad, kindColor, colorRef, formatSoftDepSection, bareSoftDepName, formatSoftDepHint, formatRelativeTime, formatSoftDepRemovePreview, formatSoftDepAddPreview, fitWidth, KIND_COL_WIDTH } from '../chunk-JZ5EHBPI.js';
11
- import { getKindRegistry, getKnownKinds } from '../chunk-2FRUUDZY.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';
12
12
  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-LAMCXQGA.js';
14
- import { buildClaudePluginFiles } from '../chunk-ZTBAYUDY.js';
15
- import '../chunk-IR33D6EP.js';
16
- import '../chunk-UAROCOXF.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';
17
17
  import '../chunk-R6O6YWU7.js';
18
- import '../chunk-W5DWWE4Y.js';
19
- import '../chunk-4PTSR4UU.js';
18
+ import '../chunk-G4FFOV3N.js';
19
+ import '../chunk-T42WRQ4O.js';
20
20
  import '../chunk-4ZTPYIBE.js';
21
- import '../chunk-DNZYOKOJ.js';
21
+ import '../chunk-MZG34MBZ.js';
22
22
  import '../chunk-X5YPJV4N.js';
23
23
  import '../chunk-O7SG5PC2.js';
24
24
  import '../chunk-7QBNJTTQ.js';
@@ -26,77 +26,77 @@ import '../chunk-OBYKJB4U.js';
26
26
  import '../chunk-5LKOAX7I.js';
27
27
  import '../chunk-32NA4TVC.js';
28
28
  import '../chunk-W3UDISS2.js';
29
- import '../chunk-V2DXZYBB.js';
30
- import { runFlow, resumeFlow } from '../chunk-UM7RIAHO.js';
29
+ import '../chunk-NWDSLXOX.js';
30
+ import { runFlow, resumeFlow } from '../chunk-3SM2DL2T.js';
31
31
  import '../chunk-4R6DROGN.js';
32
- import { validateFlowVersions, parseSkillFrontmatter } from '../chunk-CGT45WN7.js';
33
- import '../chunk-2LWYNQK7.js';
32
+ import { validateFlowVersions } from '../chunk-X77SUM4P.js';
33
+ import '../chunk-GCHPUTA3.js';
34
34
  import '../chunk-ISHJITXJ.js';
35
- import '../chunk-TTRYE6AC.js';
35
+ import '../chunk-4A4OD24G.js';
36
36
  import '../chunk-X4BAYGMT.js';
37
- import '../chunk-FVJK4QWM.js';
38
- import '../chunk-MR5HBOUF.js';
39
- import '../chunk-S53LOR7B.js';
37
+ import '../chunk-R7NHYEJF.js';
38
+ import '../chunk-T7CTHHG7.js';
39
+ import '../chunk-HCEVNYSH.js';
40
40
  import '../chunk-LOO5CB5M.js';
41
41
  import '../chunk-2H73V6XR.js';
42
- import '../chunk-J7U3PIOE.js';
42
+ import '../chunk-M3B6EIJD.js';
43
43
  import '../chunk-B4X2N7JQ.js';
44
44
  import '../chunk-YROR332M.js';
45
- import { getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-5NNNV76P.js';
45
+ import { getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-47U4GZ4M.js';
46
46
  import '../chunk-6E6PKKAD.js';
47
47
  import '../chunk-IFGTRL2I.js';
48
- import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-FZNG4V4J.js';
48
+ import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-TCHRMVTO.js';
49
49
  import '../chunk-LNFKL23K.js';
50
- import '../chunk-MGGFBZWA.js';
50
+ import '../chunk-D3B36CYC.js';
51
51
  import '../chunk-M3WPBTGJ.js';
52
52
  import { nodeLabel, nodeSkillAsset, nodeIsInert, nodeIsOptional, nodeRunKind, flowSkillVersionPins } from '../chunk-7RGTAEG6.js';
53
53
  import '../chunk-NUELZWCF.js';
54
54
  import '../chunk-F4NJDSR7.js';
55
- import { AssetManager, MissingManifestError, parseRefTolerant, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-IMKSM5NL.js';
56
- import { cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, ensureGitRepo, conflictingAssetRoot, setManifestPublisher, LIBRARY_OWNERSHIPS, isGitRepo, assertManifestEditable, installLibraryAsset, missingRootAssets, assertValidLibraryName, upsertManifestAsset, syncManifestWithDisk, getStoreManifestsDir, getDefaultValue, isSecretPlaceholder } from '../chunk-4MQS7CAF.js';
57
- import { parseManifestFile, requiresSyntaxErrors, SEMVER_RE } from '../chunk-Y7QA2OLD.js';
58
- import '../chunk-CKQEIY43.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
59
  import '../chunk-R7FOF242.js';
60
60
  import '../chunk-3TXEJN4W.js';
61
- import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-YSHVQGUS.js';
61
+ import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-FH7W6TJ4.js';
62
62
  import '../chunk-CGYEHQOX.js';
63
63
  import '../chunk-KTBKW2FI.js';
64
64
  import '../chunk-UQ6LFBPZ.js';
65
- import '../chunk-EF7NPDDU.js';
66
- import { effectiveComposes, validatePreset, composeSlotDiagnostics, agentDeprecationDiagnostics, validateAgent, SLOT_ID_PATTERN } from '../chunk-B6GIW55K.js';
67
- import { resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, readLock, aiResourceRoots, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile } from '../chunk-36AFURKZ.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';
68
68
  import '../chunk-4GY63JU6.js';
69
- import { factoryAssetRoots } from '../chunk-GB7WDMH2.js';
69
+ import { factoryAssetRoots } from '../chunk-EDYHEMJA.js';
70
70
  import '../chunk-PMECEZK3.js';
71
71
  import { DEFAULT_DRIVER_ID, DRIVER_DEFAULTS } from '../chunk-5BEFNLOR.js';
72
72
  import { findKindDirs } from '../chunk-A2ULN3KX.js';
73
- import { sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, resolveSkWorkspaceConfig, matchPin, coerceVersion, loadSkWorkspaceConfig, normalizeAgentInstances, agentInstanceDiagnostics, storeManifestSlug, isWorkspaceConfigFilename } from '../chunk-JAKOMFC6.js';
73
+ import { SourceEntryError, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, resolveSkWorkspaceConfig, matchPin, coerceVersion, loadSkWorkspaceConfig, normalizeAgentInstances, agentInstanceDiagnostics, storeManifestSlug, isWorkspaceConfigFilename } from '../chunk-ALEYHUC5.js';
74
74
  import { globalCacheRoot, globalSkaileDir, userConfigPath } from '../chunk-L5VSIPQD.js';
75
75
  import { SUPPORTED_DRIVER_TARGETS, driverTargetForDriver } from '../chunk-CPSIPIX7.js';
76
- import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, encodeSkaileManifest } from '../chunk-BTE2V4IW.js';
76
+ import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, encodeSkaileManifest } from '../chunk-ZPWTOUTK.js';
77
77
  import { pluginTitle } from '../chunk-RVRB27AN.js';
78
- import { parseFrontmatter, scanDirectory } from '../chunk-GTILM2CI.js';
79
- import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, slugifyAssetName, parseAssetRefLoose, assetRefToStr } from '../chunk-QVNRCDTV.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
80
  import { portableSpawn, portableSpawnSync } from '../chunk-ICSCSM5D.js';
81
- import { openSqlite } from '../chunk-UMVKJM4Q.js';
81
+ import { openSqlite } from '../chunk-DALV4HHP.js';
82
82
  import { parseModelRef, resolveEntryBaseUrl } from '../chunk-MJHSLODD.js';
83
83
  import '../chunk-C3CAXQMA.js';
84
84
  import '../chunk-BOFL7GIF.js';
85
85
  import '../chunk-NSBPE2FW.js';
86
- import * as fs9 from 'fs';
87
- import fs9__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
88
- import * as path23 from 'path';
89
- import path23__default, { resolve, join } from 'path';
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';
90
90
  import { fileURLToPath } from 'url';
91
91
  import { Help, Command, Option } from 'commander';
92
92
  import { rcompare } from 'semver';
93
93
  import * as p4 from '@clack/prompts';
94
94
  import pc5 from 'picocolors';
95
- import { parse, stringify, parseDocument, isMap, isScalar, isSeq } from 'yaml';
96
95
  import * as os from 'os';
96
+ import { parse, stringify, parseDocument, isMap, isScalar, isSeq } from 'yaml';
97
97
  import * as readline from 'readline';
98
98
  import { createInterface } from 'readline';
99
- import fs6 from 'fs/promises';
99
+ import fs5 from 'fs/promises';
100
100
  import { parse as parse$1, stringify as stringify$1 } from 'smol-toml';
101
101
  import { execSync, spawnSync, execFileSync } from 'child_process';
102
102
  import * as readline2 from 'readline/promises';
@@ -175,7 +175,7 @@ async function runSearch(kind, query, opts) {
175
175
  const showLocal = !opts.store;
176
176
  const showStore = !opts.local;
177
177
  const { resolveConfig } = await import('../library/index.js');
178
- const airGapped = resolveConfig({ projectDir: path23__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
178
+ const airGapped = resolveConfig({ projectDir: path18__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
179
179
  if (showLocal) {
180
180
  await searchLocal(query, kind, opts, showStore, airGapped);
181
181
  }
@@ -184,11 +184,14 @@ async function runSearch(kind, query, opts) {
184
184
  }
185
185
  }
186
186
  async function searchIndex(query, kind) {
187
- const { openLibrary: openLibrary2 } = await import('../open-library-DB2PNL2X.js');
187
+ const { openLibrary: openLibrary2 } = await import('../open-library-BOSPJVID.js');
188
188
  const library = await openLibrary2();
189
189
  try {
190
- const defs = await library.listAssetDefs(kind ? { kind } : {});
191
- const libraryNames = new Map((await library.listSources()).map((l) => [l.id, l.name]));
190
+ const { libraryDirMissing: libraryDirMissing2 } = await import('../library/index.js');
191
+ const sources = await library.listSources();
192
+ const gone = new Set(sources.filter(libraryDirMissing2).map((l) => l.id));
193
+ const defs = (await library.listAssetDefs(kind ? { kind } : {})).filter((d) => !d.libraryId || !gone.has(d.libraryId));
194
+ const libraryNames = new Map(sources.map((l) => [l.id, l.name]));
192
195
  let entries = defs.map(
193
196
  (d) => ({
194
197
  name: d.name,
@@ -218,7 +221,7 @@ async function searchIndex(query, kind) {
218
221
  }
219
222
  }
220
223
  async function searchFactory(projectDir, query, kind) {
221
- const prefixes = factoryAssetRoots().map((r) => r.endsWith(path23__default.sep) ? r : r + path23__default.sep);
224
+ const prefixes = factoryAssetRoots().map((r) => r.endsWith(path18__default.sep) ? r : r + path18__default.sep);
222
225
  const isFactoryPath = (p6) => prefixes.some((fp) => p6 === fp.slice(0, -1) || p6.startsWith(fp));
223
226
  try {
224
227
  const entries = await new AssetManager({ registry: getKindRegistry(), projectDir }).search(
@@ -269,12 +272,70 @@ async function expandLibraryCopies(entries, projectDir) {
269
272
  }
270
273
  return out;
271
274
  }
275
+ function originAtVersion(o) {
276
+ return `${describeOrigin(o)}${o.version ? ` v${o.version}` : ""}`;
277
+ }
278
+ async function competingOriginsOf(am2, target) {
279
+ let ref;
280
+ if (typeof target === "string") {
281
+ if (target.includes("#")) return void 0;
282
+ ref = target;
283
+ } else {
284
+ const publisher = (target.canonicalRef ? parseRefTolerant(target.canonicalRef)?.publisher : void 0) ?? target.publisher;
285
+ if (!publisher) return void 0;
286
+ ref = `${target.kind}:@${publisher}/${target.name}`;
287
+ }
288
+ try {
289
+ const origins = await am2.refOrigins(ref);
290
+ return new Set(origins.map((o) => o.version)).size > 1 ? origins : void 0;
291
+ } catch {
292
+ return void 0;
293
+ }
294
+ }
295
+ function describeOrigin(o) {
296
+ return o.kind === "factory" ? "factory" : `${o.kind} ${o.label}`;
297
+ }
298
+ async function expandCompetingOrigins(entries, projectDir) {
299
+ if (entries.length === 0) return entries;
300
+ let competing;
301
+ try {
302
+ competing = await new AssetManager({
303
+ registry: getKindRegistry(),
304
+ projectDir
305
+ }).competingOrigins();
306
+ } catch {
307
+ return entries;
308
+ }
309
+ if (competing.size === 0) return entries;
310
+ const out = [];
311
+ const expanded = /* @__PURE__ */ new Set();
312
+ for (const e of entries) {
313
+ const key = entryDedupKey(e);
314
+ const origins = competing.get(key);
315
+ if (!origins) {
316
+ out.push(e);
317
+ continue;
318
+ }
319
+ if (expanded.has(key)) continue;
320
+ expanded.add(key);
321
+ origins.forEach((o, i) => {
322
+ out.push({
323
+ ...e,
324
+ version: o.version,
325
+ description: o.description || e.description,
326
+ library: describeOrigin(o),
327
+ usedByAdd: i === 0
328
+ });
329
+ });
330
+ }
331
+ return out;
332
+ }
272
333
  async function searchLocal(query, kind, opts, showStore, airGapped) {
273
- const projectDir = path23__default.resolve(opts.projectDir);
334
+ const projectDir = path18__default.resolve(opts.projectDir);
274
335
  const factory = await searchFactory(projectDir, query, kind);
275
336
  let entries = unionEntries(await searchIndex(query, kind), factory);
276
337
  if (entries.length === 0 && !query && !kind && !airGapped) {
277
- const { autoSyncForSearch } = await import('../source-PJBMDCKX.js');
338
+ const { autoSyncForSearch } = await import('../source-G2LV5LVD.js');
278
339
  if (await autoSyncForSearch(projectDir)) {
279
340
  entries = unionEntries(await searchIndex(query, kind), factory);
280
341
  }
@@ -291,7 +352,9 @@ async function searchLocal(query, kind, opts, showStore, airGapped) {
291
352
  console.log(`
292
353
  ${S.heading("Local:")}`);
293
354
  }
294
- printLocalEntries(await expandLibraryCopies(entries, projectDir));
355
+ printLocalEntries(
356
+ await expandCompetingOrigins(await expandLibraryCopies(entries, projectDir), projectDir)
357
+ );
295
358
  }
296
359
  var MIN_LOCAL_DESCRIPTION_WIDTH = 10;
297
360
  function layoutLocalTable(rows, width, style = {}) {
@@ -392,9 +455,9 @@ async function searchStore(query, kind, opts, airGapped) {
392
455
  logInfo("air-gapped (cache_ttl: 0) \u2014 local sources only");
393
456
  return;
394
457
  }
395
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-DB2PNL2X.js');
458
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-BOSPJVID.js');
396
459
  try {
397
- const remote = await openCatalogSource2({ projectDir: path23__default.resolve(opts.projectDir) });
460
+ const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
398
461
  const assets = await remote.listAssets(kind ? { kind } : {});
399
462
  const results = filterCatalogAssets(assets, query);
400
463
  if (results.length > 0) {
@@ -515,10 +578,11 @@ function makeAddCommand() {
515
578
  process.exit(1);
516
579
  }
517
580
  const harnesses = parseHarnessFilter(opts.harness);
581
+ if (!opts.global && harnesses === void 0) requireProjectConfig(opts.projectDir);
518
582
  const warnings = deferredWarnings();
519
583
  const am2 = new AssetManager({
520
584
  registry: getKindRegistry(),
521
- projectDir: path23__default.resolve(opts.projectDir),
585
+ projectDir: path18__default.resolve(opts.projectDir),
522
586
  global: opts.global || harnesses !== void 0,
523
587
  harnesses,
524
588
  driverTarget: opts.target,
@@ -529,11 +593,28 @@ function makeAddCommand() {
529
593
  try {
530
594
  const libraryOf = /* @__PURE__ */ new Map();
531
595
  let presets = [];
596
+ const skippedLinks = /* @__PURE__ */ new Set();
597
+ const skippedEnv = /* @__PURE__ */ new Set();
532
598
  const added = await am2.add(ref, {
533
599
  link: opts.link,
534
600
  onLibraryOrigin: (deployedRef, library) => libraryOf.set(deployedRef, library),
601
+ onLibraryMoved: (m) => warnings.push(`${m.ref} moved from ${m.from} to ${m.to}`),
535
602
  onPresets: (expanded) => {
536
603
  presets = expanded;
604
+ },
605
+ // One line per dropped link, however many harnesses the asset is deployed into.
606
+ onSkippedSymlink: (_assetRef, linkPath) => {
607
+ if (skippedLinks.has(linkPath)) return;
608
+ skippedLinks.add(linkPath);
609
+ warnings.push(`skipped symlink ${linkPath}`);
610
+ },
611
+ // A `.env` in an asset root is never deployed or hashed: say so once per file.
612
+ onEnvFile: (_assetRef, envPath) => {
613
+ if (skippedEnv.has(envPath)) return;
614
+ skippedEnv.add(envPath);
615
+ warnings.push(
616
+ `${envPath} is a .env file: it is not deployed or hashed with the asset. Keep secrets out of an asset root`
617
+ );
537
618
  }
538
619
  });
539
620
  spinner.stop("Done");
@@ -564,6 +645,15 @@ function makeAddCommand() {
564
645
  logOk(library ? `${a} (library ${library})` : a);
565
646
  }
566
647
  }
648
+ const addOrigins = await competingOriginsOf(am2, ref);
649
+ if (addOrigins) {
650
+ const [first, ...rest] = addOrigins;
651
+ logInfo(
652
+ S.dim(
653
+ `${ref} is held at different versions; used ${originAtVersion(first)} (also ${rest.map(originAtVersion).join(", ")})`
654
+ )
655
+ );
656
+ }
567
657
  await reportPresetMembership(am2, ref, (line) => logInfo(S.dim(line)));
568
658
  } catch (err2) {
569
659
  spinner.stop("Failed");
@@ -577,23 +667,33 @@ function makeRemoveCommand() {
577
667
  return new Command("remove").description("Remove from skaile.yaml + undeploy").argument("<ref>", "Asset reference (kind:@publisher/name, or kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Remove from ~/.skaile/skaile.yaml + undeploy from every global harness").option(
578
668
  "--harness <ids>",
579
669
  "Comma-separated global harnesses to undeploy from (default: all resolved); implies --global"
580
- ).option("--target <agent>", `Driver target (${TARGET_DEFAULT_HINT})`).option("--no-soft-deps", "skip the orphaned-soft-dep prompt (don't remove, don't report)").action(async (ref, opts) => {
670
+ ).option("--target <agent>", `Driver target (${TARGET_DEFAULT_HINT})`).option("--force", "Remove even when another installed asset requires it").option("--no-soft-deps", "skip the orphaned-soft-dep prompt (don't remove, don't report)").action(async (ref, opts) => {
581
671
  const harnesses = parseHarnessFilter(opts.harness);
672
+ if (!opts.global && harnesses === void 0)
673
+ requireProjectConfig(opts.projectDir, { allowMissing: true });
582
674
  const am2 = new AssetManager({
583
675
  registry: getKindRegistry(),
584
- projectDir: path23__default.resolve(opts.projectDir),
676
+ projectDir: path18__default.resolve(opts.projectDir),
585
677
  global: opts.global || harnesses !== void 0,
586
678
  harnesses,
587
679
  driverTarget: opts.target
588
680
  });
589
681
  let result;
590
682
  try {
591
- result = await am2.removeWithDependencies(ref);
683
+ result = await am2.removeWithDependencies(ref, { force: opts.force === true });
592
684
  } catch (err2) {
593
685
  logErr(err2 instanceof Error ? err2.message : String(err2));
594
686
  process.exitCode = 1;
595
687
  return;
596
688
  }
689
+ if (result.blocked) {
690
+ logWarn(`${result.blocked.ref} is required by ${result.blocked.requiredBy.join(", ")}`);
691
+ logInfo(
692
+ `Nothing removed. Remove ${result.blocked.requiredBy.length === 1 ? "that asset" : "those assets"} first, or run \`skaile remove ${ref} --force\`.`
693
+ );
694
+ process.exitCode = 1;
695
+ return;
696
+ }
597
697
  if (!result.changed) {
598
698
  logErr(`Not deployed or declared: ${ref}`);
599
699
  process.exitCode = 1;
@@ -635,7 +735,7 @@ function makeListCommand() {
635
735
  }
636
736
  const am2 = new AssetManager({
637
737
  registry: getKindRegistry(),
638
- projectDir: path23__default.resolve(opts.projectDir),
738
+ projectDir: path18__default.resolve(opts.projectDir),
639
739
  driverTarget: opts.target
640
740
  });
641
741
  let declared;
@@ -683,7 +783,7 @@ function makeListCommand() {
683
783
  function runGlobalList(kind, opts, harnesses) {
684
784
  const am2 = new AssetManager({
685
785
  registry: getKindRegistry(),
686
- projectDir: path23__default.resolve(opts.projectDir),
786
+ projectDir: path18__default.resolve(opts.projectDir),
687
787
  global: true,
688
788
  harnesses
689
789
  });
@@ -756,7 +856,7 @@ async function resolveInfoEntry(am2, ref, opts) {
756
856
  return { entry: match ?? deployed };
757
857
  }
758
858
  const lookup = opts.storeLookup ?? (async (filter) => {
759
- const { resolveCatalogSource } = await import('../open-library-DB2PNL2X.js');
859
+ const { resolveCatalogSource } = await import('../open-library-BOSPJVID.js');
760
860
  const { source, close } = await resolveCatalogSource({ projectDir: opts.projectDir });
761
861
  try {
762
862
  return await source.listAssets(filter);
@@ -772,7 +872,7 @@ async function resolveInfoEntry(am2, ref, opts) {
772
872
  );
773
873
  return { entry: hit ? catalogAssetToEntry(hit) : null };
774
874
  } catch (err2) {
775
- const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-DB2PNL2X.js');
875
+ const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-BOSPJVID.js');
776
876
  const storeNote = err2 instanceof Error ? err2.message : String(err2);
777
877
  const disabled = err2 instanceof LocalCatalogDisabledError2 || /catalog\.url/i.test(storeNote);
778
878
  return { entry: null, storeNote, ...disabled ? { storeDisabled: true } : {} };
@@ -788,7 +888,7 @@ function infoNotFoundHint(ref, lookup) {
788
888
  }
789
889
  function makeInfoCommand() {
790
890
  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) => {
791
- const projectDir = path23__default.resolve(opts.projectDir);
891
+ const projectDir = path18__default.resolve(opts.projectDir);
792
892
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
793
893
  const lookup = await resolveInfoEntry(am2, ref, { projectDir });
794
894
  const entry = lookup.entry;
@@ -805,9 +905,20 @@ function makeInfoCommand() {
805
905
  if (entry.description) console.log(` description: ${entry.description}`);
806
906
  if (entry.publisher) console.log(` repository: ${S.dim(entry.publisher)}`);
807
907
  console.log(` source: ${S.dim(entry.source)}`);
808
- if (entry.requires.length) {
908
+ const infoOrigins = await competingOriginsOf(am2, entry);
909
+ if (infoOrigins) {
910
+ const [first, ...rest] = infoOrigins;
911
+ console.log(
912
+ ` origin: ${describeOrigin(first)} (used by add; also ${rest.map(originAtVersion).join(", ")})`
913
+ );
914
+ }
915
+ const ownPublisher = (entry.canonicalRef ? parseRefTolerant(entry.canonicalRef)?.publisher : void 0) ?? entry.publisher;
916
+ const requirements = dedupeRequirements(entry.requires, ownPublisher).map(
917
+ (d) => d.publisher || !ownPublisher ? d : { ...d, publisher: ownPublisher }
918
+ );
919
+ if (requirements.length) {
809
920
  console.log(` requires:`);
810
- for (const d of entry.requires) {
921
+ for (const d of requirements) {
811
922
  const scope = d.publisher ? `@${d.publisher}/` : "";
812
923
  console.log(` ${S.dim("\xB7")} ${kindColor(d.kind)}:${scope}${d.name}`);
813
924
  }
@@ -826,7 +937,7 @@ function makeCreateCommand() {
826
937
  new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...SCAFFOLD_KINDS])
827
938
  ).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
828
939
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
829
- const destDir = opts.dir ? path23__default.resolve(opts.dir) : process.cwd();
940
+ const destDir = opts.dir ? path18__default.resolve(opts.dir) : process.cwd();
830
941
  const result = am2.create(name, opts.kind, destDir);
831
942
  if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
832
943
  else {
@@ -837,213 +948,56 @@ function makeCreateCommand() {
837
948
  }
838
949
  function makeDoctorCommand() {
839
950
  return new Command("doctor").description("Scan for missing dependency chains").argument("[name]", "Check a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (name, opts) => {
951
+ requireProjectConfig(opts.projectDir);
840
952
  const am2 = new AssetManager({
841
953
  registry: getKindRegistry(),
842
- projectDir: path23__default.resolve(opts.projectDir)
954
+ projectDir: path18__default.resolve(opts.projectDir)
843
955
  });
844
- const issues = await am2.doctor();
845
- if (issues.length === 0) {
956
+ const { gaps } = await am2.projectState();
957
+ if (gaps.length === 0) {
846
958
  logOk("No missing dependencies.");
847
959
  return;
848
960
  }
849
- const unresolved = issues.filter((i) => i.unresolved);
850
- const missing = issues.filter((i) => !i.unresolved);
851
- for (const i of unresolved) {
852
- logErr(
853
- `${i.assetKind}:${i.assetName}: locked, but no source or library provides it \u2014 ${i.fix ?? "run skaile install"}`
854
- );
855
- }
961
+ process.exitCode = 1;
962
+ for (const g of gaps) if (g.type !== "requires") logErr(g.message);
963
+ const missing = gaps.filter((g) => g.type === "requires" && g.asset !== void 0);
856
964
  if (missing.length === 0) return;
857
- const assetW = Math.max(5, ...missing.map((i) => `${i.assetKind}:${i.assetName}`.length));
858
- const depW = Math.max(11, ...missing.map((i) => `${i.depKind}:${i.depName}`.length));
965
+ const assetW = Math.max(5, ...missing.map((g) => (g.asset ?? "").length));
966
+ const depW = Math.max(11, ...missing.map((g) => g.ref.length));
859
967
  console.log();
860
968
  console.log(
861
969
  ` ${S.dim("ASSET".padEnd(assetW))} ${S.dim("MISSING DEP".padEnd(depW))} ${S.dim("IN REPOS")}`
862
970
  );
863
971
  console.log(` ${S.rule(assetW + depW + 15)}`);
864
- for (const i of missing) {
865
- const asset = `${i.assetKind}:${i.assetName}`;
866
- const dep = `${i.depKind}:${i.depName}`;
867
- const status4 = i.inRepos ? S.warn("fixable") : S.err("not found");
868
- console.log(` ${asset.padEnd(assetW)} ${dep.padEnd(depW)} ${status4}`);
972
+ for (const g of missing) {
973
+ const asset = g.asset ?? "";
974
+ const status4 = g.manualFix ? S.err("not found") : S.warn("fixable");
975
+ console.log(` ${asset.padEnd(assetW)} ${g.ref.padEnd(depW)} ${status4}`);
869
976
  }
870
977
  console.log();
871
978
  });
872
979
  }
873
- function manifestRequiresProblems(dir) {
874
- const file = path23.join(dir, "skaile.manifest.yaml");
875
- let doc;
876
- try {
877
- doc = parse(fs9.readFileSync(file, "utf-8"));
878
- } catch {
879
- return [];
880
- }
881
- const assets = doc?.assets;
882
- if (!Array.isArray(assets)) return [];
883
- const problems = [];
884
- for (const a of assets) {
885
- if (!a || typeof a !== "object") continue;
886
- const { kind, name, dependencies } = a;
887
- if (!Array.isArray(dependencies)) continue;
888
- const entries = dependencies.map((d) => typeof d === "string" ? d : String(d));
889
- for (const message of requiresSyntaxErrors(entries)) {
890
- problems.push({
891
- asset: `${String(kind)}:${String(name)}`,
892
- message: `ManifestRequiresError: ${message}`
893
- });
894
- }
895
- }
896
- return problems;
897
- }
898
- async function indexLibrary(lib, index, opts = {}) {
899
- const { LocalCatalogSource } = await import('../library/index.js');
900
- const own = index ?? await openLibrary();
901
- try {
902
- const source = new LocalCatalogSource(own, lib.id, lib.path, getKindRegistry());
903
- const res = await source.sync({ exclude: opts.exclude });
904
- return {
905
- assetsFound: res.assetsFound,
906
- assetsUpdated: res.assetsUpdated,
907
- errors: res.errors
908
- };
909
- } finally {
910
- if (!index) own.close();
911
- }
912
- }
913
- function resolveLibraryPublisherDetailed(lib, opts, storeIdentity) {
914
- const bare = (p6) => p6.startsWith("@") ? p6.slice(1) : p6;
915
- if (opts.publisher?.trim()) return { publisher: bare(opts.publisher.trim()), source: "flag" };
916
- const declared = loadSkPublishManifest(lib.path)?.publisher?.trim();
917
- if (declared) return { publisher: bare(declared), source: "manifest" };
918
- const identity = (storeIdentity?.githubLogin ?? storeIdentity?.username)?.trim();
919
- if (identity) return { publisher: identity, source: "identity" };
920
- try {
921
- return { publisher: slugifyAssetName(lib.name), source: "library-name" };
922
- } catch {
923
- return { publisher: "library", source: "library-name" };
924
- }
925
- }
926
- function warnLibraryNameFallback(libName, resolved) {
927
- if (resolved.source !== "library-name") return;
928
- logWarn(
929
- `No publisher given and not signed in \u2014 using the library name "${resolved.publisher}" as the publisher. Pass --publisher <name> or run \`skaile store login\`; change it later with \`skaile library set ${libName} publisher=<name>\`.`
930
- );
931
- }
932
- function normalizeAssetFrontmatter(assetDir) {
933
- let markerFile = ["SKILL.md", "AGENT.md", "CONTRACT.md"].map((m) => path23.join(assetDir, m)).find((f) => fs9.existsSync(f));
934
- if (!markerFile) {
935
- const promptMd = fs9.readdirSync(assetDir).find((f) => f.endsWith(".prompt.md"));
936
- if (promptMd) markerFile = path23.join(assetDir, promptMd);
937
- }
938
- if (!markerFile) return;
939
- try {
940
- const { data, body } = parseFrontmatter(fs9.readFileSync(markerFile, "utf8"));
941
- const fm = stringify(data).trimEnd();
942
- fs9.writeFileSync(markerFile, `---
943
- ${fm}
944
- ---
945
-
946
- ${body}
947
- `, "utf8");
948
- } catch {
949
- }
950
- }
951
- async function registerLibraryAsset(lib, index, input) {
952
- const { publisher, source } = resolveLibraryPublisherDetailed(
953
- lib,
954
- { publisher: input.publisher },
955
- getStoreIdentity()
956
- );
957
- warnLibraryNameFallback(lib.name, { publisher, source });
958
- normalizeAssetFrontmatter(input.assetDir);
959
- stampManifestPublisher(lib.path, publisher);
960
- upsertManifestAsset(lib.path, {
961
- kind: input.kind,
962
- name: input.name,
963
- root: path23.relative(lib.path, input.assetDir) || input.name,
964
- version: input.version,
965
- publisher
966
- });
967
- const idx = await indexLibrary(lib, index);
968
- for (const e of idx.errors) logWarn(e);
969
- return { publisher, ref: refFor(input.kind, publisher, input.name, input.version) };
970
- }
971
- var LIBRARY_UPGRADE_DOCS = "https://github.com/skaile-ai/workspaces/blob/main/docs/sections/cli/commands/library.md#upgrading-a-4x-library";
972
- var DOMAIN_REMOVED_HINT = `Domains were removed in 5.0 \u2014 delete DOMAIN.md files; group assets with .claude-plugin/marketplace.json. See ${LIBRARY_UPGRADE_DOCS}`;
973
- function removedDomainOption() {
974
- return new Option("--domain <domain>", "Removed in 5.0").hideHelp();
975
- }
976
- function rejectRemovedDomainOption(opts) {
977
- if (opts.domain === void 0) return;
978
- logErr(DOMAIN_REMOVED_HINT);
979
- process.exit(1);
980
- }
981
- function findFiles(root, match) {
982
- const found = [];
983
- const walk = (dir) => {
984
- let entries;
985
- try {
986
- entries = fs9.readdirSync(dir, { withFileTypes: true });
987
- } catch {
988
- return;
989
- }
990
- for (const entry of entries) {
991
- if (entry.isDirectory()) {
992
- if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
993
- walk(path23.join(dir, entry.name));
994
- }
995
- } else if (match(entry.name)) {
996
- found.push(path23.join(dir, entry.name));
997
- }
998
- }
999
- };
1000
- walk(root);
1001
- return found;
1002
- }
1003
- function countDomainFiles(root) {
1004
- return findFiles(root, (name) => name === "DOMAIN.md").length;
1005
- }
1006
- function warnIgnoredDomainFiles(root) {
1007
- const count = countDomainFiles(root);
1008
- if (count > 0) {
1009
- logWarn(
1010
- `${count} DOMAIN.md file(s) are ignored since 5.0 (domains were removed) \u2014 delete them; group assets with .claude-plugin/marketplace.json. See ${LIBRARY_UPGRADE_DOCS}`
1011
- );
1012
- }
1013
- return count;
1014
- }
1015
- function warnLegacyBundleFiles(root) {
1016
- const files = findFiles(root, (name) => name.endsWith(".bundle.yaml"));
1017
- if (files.length > 0) {
1018
- const shown = files.slice(0, 5).map((f) => path23.relative(root, f) || f);
1019
- const more = files.length > shown.length ? `, +${files.length - shown.length} more` : "";
1020
- logWarn(
1021
- `${files.length} *.bundle.yaml file(s) are not scanned (the bundle kind became preset): ${shown.join(", ")}${more}. Run \`skaile migrate assets ${root} --write\` to rename them to *.preset.yaml. See ${LIBRARY_UPGRADE_DOCS}`
1022
- );
1023
- }
1024
- return files.length;
1025
- }
1026
980
  var DEFAULT_IMPORT_VERSION = "0.1.0";
1027
981
  var DEFAULT_IMPORT_STAGE = "alpha";
1028
982
  function claudeSkillRoots() {
1029
983
  const roots = [];
1030
984
  const override = process.env.SKAILE_CLAUDE_SKILLS_DIR;
1031
985
  if (override) roots.push(override);
1032
- roots.push(path23.join(os.homedir(), ".claude", "skills"));
986
+ roots.push(path18.join(os.homedir(), ".claude", "skills"));
1033
987
  return roots;
1034
988
  }
1035
989
  function resolveImportSource(nameOrPath) {
1036
- const asPath = path23.resolve(nameOrPath);
1037
- if (fs9.existsSync(asPath)) {
1038
- const dir = fs9.statSync(asPath).isDirectory() ? asPath : path23.dirname(asPath);
1039
- const skillFile = path23.join(dir, "SKILL.md");
1040
- if (fs9.existsSync(skillFile)) return { dir, skillFile, via: "path" };
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" };
1041
995
  }
1042
- if (!nameOrPath.includes(path23.sep) && !nameOrPath.startsWith(".")) {
996
+ if (!nameOrPath.includes(path18.sep) && !nameOrPath.startsWith(".")) {
1043
997
  for (const root of claudeSkillRoots()) {
1044
- const dir = path23.join(root, nameOrPath);
1045
- const skillFile = path23.join(dir, "SKILL.md");
1046
- if (fs9.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
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" };
1047
1001
  }
1048
1002
  }
1049
1003
  return null;
@@ -1139,13 +1093,7 @@ function makeAssetCommand() {
1139
1093
  ).option("--commit", "Auto-commit in git-backed libraries", false).action(
1140
1094
  async (nameOrPath, opts) => {
1141
1095
  rejectRemovedDomainOption(opts);
1142
- if (opts.publisher !== void 0) {
1143
- const bare = opts.publisher.trim().replace(/^@/, "");
1144
- if (!isValidPublisher(bare)) {
1145
- logErr(`Invalid publisher "${opts.publisher}": ${PUBLISHER_HINT}.`);
1146
- process.exit(1);
1147
- }
1148
- }
1096
+ if (opts.publisher !== void 0) requireValidPublisherOrExit(opts.publisher);
1149
1097
  const src = resolveImportSource(nameOrPath);
1150
1098
  if (!src) {
1151
1099
  logErr(
@@ -1175,19 +1123,20 @@ function makeAssetCommand() {
1175
1123
  logErr(err2 instanceof Error ? err2.message : String(err2));
1176
1124
  process.exit(1);
1177
1125
  }
1178
- const rawSkill = fs9.readFileSync(src.skillFile, "utf8");
1126
+ exitOnManifestPublisherProblems(target.path, target.name);
1127
+ const rawSkill = fs8.readFileSync(src.skillFile, "utf8");
1179
1128
  const norm = opts.normalize ? normalizeSkillContent(rawSkill, {
1180
- fallbackName: path23.basename(src.dir),
1129
+ fallbackName: path18.basename(src.dir),
1181
1130
  version: opts.version,
1182
1131
  stage: opts.stage
1183
- }) : { content: rawSkill, name: path23.basename(src.dir), changed: false, notes: [] };
1132
+ }) : { content: rawSkill, name: path18.basename(src.dir), changed: false, notes: [] };
1184
1133
  if (!opts.normalize && !isValidAssetName(norm.name)) {
1185
1134
  logWarn(
1186
1135
  `Name "${norm.name}" is not canonical (kebab-case); \`skaile validate\` will reject this manifest entry. Drop --no-normalize to slugify it.`
1187
1136
  );
1188
1137
  }
1189
- const destDir = path23.join(target.path, norm.name);
1190
- if (fs9.existsSync(destDir)) {
1138
+ const destDir = path18.join(target.path, norm.name);
1139
+ if (fs8.existsSync(destDir)) {
1191
1140
  logErr(`Destination already exists: ${destDir}`);
1192
1141
  process.exit(1);
1193
1142
  }
@@ -1198,8 +1147,8 @@ function makeAssetCommand() {
1198
1147
  );
1199
1148
  process.exit(1);
1200
1149
  }
1201
- fs9.cpSync(src.dir, destDir, { recursive: true });
1202
- fs9.writeFileSync(path23.join(destDir, "SKILL.md"), norm.content, "utf8");
1150
+ fs8.cpSync(src.dir, destDir, { recursive: true });
1151
+ fs8.writeFileSync(path18.join(destDir, "SKILL.md"), norm.content, "utf8");
1203
1152
  for (const note of norm.notes) logInfo(` \u2022 ${note}`);
1204
1153
  const fm = parseFrontmatter(norm.content).data;
1205
1154
  for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
@@ -1239,7 +1188,7 @@ function makeAssetCommand() {
1239
1188
  logErr(`Invalid --mode "${opts.mode}". Expected: copy | move | link.`);
1240
1189
  process.exit(1);
1241
1190
  }
1242
- if (!fs9.existsSync(srcPath)) {
1191
+ if (!fs8.existsSync(srcPath)) {
1243
1192
  logErr(`Source path does not exist: ${srcPath}`);
1244
1193
  process.exit(1);
1245
1194
  }
@@ -1265,23 +1214,23 @@ function makeAssetCommand() {
1265
1214
  );
1266
1215
  process.exit(1);
1267
1216
  }
1268
- const basename3 = path23.basename(srcPath);
1217
+ const basename3 = path18.basename(srcPath);
1269
1218
  const destDir = target.path;
1270
- fs9.mkdirSync(destDir, { recursive: true });
1271
- const destPath = path23.join(destDir, basename3);
1272
- if (fs9.existsSync(destPath)) {
1219
+ fs8.mkdirSync(destDir, { recursive: true });
1220
+ const destPath = path18.join(destDir, basename3);
1221
+ if (fs8.existsSync(destPath)) {
1273
1222
  logErr(`Destination already exists: ${destPath}`);
1274
1223
  process.exit(1);
1275
1224
  }
1276
1225
  switch (opts.mode) {
1277
1226
  case "copy":
1278
- fs9.cpSync(srcPath, destPath, { recursive: true });
1227
+ fs8.cpSync(srcPath, destPath, { recursive: true });
1279
1228
  break;
1280
1229
  case "move":
1281
- fs9.renameSync(srcPath, destPath);
1230
+ fs8.renameSync(srcPath, destPath);
1282
1231
  break;
1283
1232
  case "link":
1284
- fs9.symlinkSync(path23.resolve(srcPath), destPath);
1233
+ fs8.symlinkSync(path18.resolve(srcPath), destPath);
1285
1234
  break;
1286
1235
  }
1287
1236
  if (target.backend === "git" && opts.commit) {
@@ -1411,14 +1360,14 @@ function makeAuthCommand() {
1411
1360
  }
1412
1361
  function collectCacheTargets(scope) {
1413
1362
  const out = [];
1414
- out.push(path23__default.join(scope.projectDir, ".skaile", "cache"));
1415
- out.push(path23__default.join(scope.projectDir, ".skaile", "store-cache"));
1416
- out.push(path23__default.join(scope.projectDir, ".skaile", "repos"));
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"));
1417
1366
  if (scope.global) {
1418
1367
  out.push(globalCacheRoot());
1419
1368
  const home = globalSkaileDir();
1420
- out.push(path23__default.join(home, "repos"));
1421
- out.push(path23__default.join(home, "catalog-cache"));
1369
+ out.push(path18__default.join(home, "repos"));
1370
+ out.push(path18__default.join(home, "catalog-cache"));
1422
1371
  }
1423
1372
  return out;
1424
1373
  }
@@ -1432,7 +1381,7 @@ function dirSize(target) {
1432
1381
  function dirSizeOfDir(dir) {
1433
1382
  let total = 0;
1434
1383
  for (const ent of readdirSync(dir, { withFileTypes: true })) {
1435
- const child = path23__default.join(dir, ent.name);
1384
+ const child = path18__default.join(dir, ent.name);
1436
1385
  if (ent.isSymbolicLink()) continue;
1437
1386
  if (ent.isDirectory()) total += dirSizeOfDir(child);
1438
1387
  else if (ent.isFile()) total += statSync(child).size;
@@ -1458,7 +1407,7 @@ function makeCacheCommand() {
1458
1407
  const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
1459
1408
  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) => {
1460
1409
  const targets = collectCacheTargets({
1461
- projectDir: path23__default.resolve(opts.projectDir),
1410
+ projectDir: path18__default.resolve(opts.projectDir),
1462
1411
  global: opts.global
1463
1412
  }).filter((t) => existsSync(t));
1464
1413
  if (targets.length === 0) {
@@ -1488,12 +1437,12 @@ function makeCacheCommand() {
1488
1437
  for (const r of removed) logOk(`Removed ${r}`);
1489
1438
  });
1490
1439
  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) => {
1491
- console.log(path23__default.join(path23__default.resolve(opts.projectDir), ".skaile", "cache"));
1440
+ console.log(path18__default.join(path18__default.resolve(opts.projectDir), ".skaile", "cache"));
1492
1441
  if (opts.global) console.log(globalCacheRoot());
1493
1442
  });
1494
1443
  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) => {
1495
1444
  const targets = collectCacheTargets({
1496
- projectDir: path23__default.resolve(opts.projectDir),
1445
+ projectDir: path18__default.resolve(opts.projectDir),
1497
1446
  global: opts.global
1498
1447
  });
1499
1448
  console.log();
@@ -1509,7 +1458,7 @@ function makeCatalogCommand() {
1509
1458
  const catalog = new Command("catalog").description("Catalog source health and configuration");
1510
1459
  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) => {
1511
1460
  const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
1512
- const projectDir = opts.projectDir ? path23__default.resolve(opts.projectDir) : void 0;
1461
+ const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : void 0;
1513
1462
  const cfg = resolveConfig({ projectDir });
1514
1463
  const baseUrl = opts.url ?? cfg.catalog.url;
1515
1464
  if (isLocalCatalogUrl(baseUrl)) {
@@ -1527,7 +1476,7 @@ function makeCatalogCommand() {
1527
1476
  });
1528
1477
  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) => {
1529
1478
  const { resolveConfig } = await import('../library/index.js');
1530
- const projectDir = opts.projectDir ? path23__default.resolve(opts.projectDir) : void 0;
1479
+ const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : void 0;
1531
1480
  const cfg = resolveConfig({ projectDir });
1532
1481
  console.log(`url: ${cfg.catalog.url}`);
1533
1482
  console.log(`framing: ${cfg.catalog.framing}`);
@@ -1536,7 +1485,7 @@ function makeCatalogCommand() {
1536
1485
  return catalog;
1537
1486
  }
1538
1487
  async function runLocalCatalogTest(projectDir) {
1539
- const { resolveCatalogSource } = await import('../open-library-DB2PNL2X.js');
1488
+ const { resolveCatalogSource } = await import('../open-library-BOSPJVID.js');
1540
1489
  let resolved;
1541
1490
  try {
1542
1491
  resolved = await resolveCatalogSource({ projectDir });
@@ -1679,7 +1628,7 @@ async function scanLibraryFlowEntries() {
1679
1628
  const { LocalIndex, resolveIndexPath, scanAuthoringLibraries } = await import('../library/index.js');
1680
1629
  const indexPath = resolveIndexPath();
1681
1630
  if (!existsSync(indexPath)) return entries;
1682
- const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-ZUZJ7MS7.js');
1631
+ const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-4FI7HKET.js');
1683
1632
  const index = new LocalIndex({ indexPath });
1684
1633
  try {
1685
1634
  for (const { assets } of await scanAuthoringLibraries(index, getKindRegistry2())) {
@@ -1729,11 +1678,11 @@ function findSkills() {
1729
1678
  return deduped;
1730
1679
  }
1731
1680
  function walkSkills(dir, out) {
1732
- for (const entry of fs9__default.readdirSync(dir, { withFileTypes: true })) {
1733
- const full = path23__default.join(dir, entry.name);
1681
+ for (const entry of fs8__default.readdirSync(dir, { withFileTypes: true })) {
1682
+ const full = path18__default.join(dir, entry.name);
1734
1683
  if (entry.isDirectory()) {
1735
- const skillMd = path23__default.join(full, "SKILL.md");
1736
- if (fs9__default.existsSync(skillMd)) {
1684
+ const skillMd = path18__default.join(full, "SKILL.md");
1685
+ if (fs8__default.existsSync(skillMd)) {
1737
1686
  out.push({ name: entry.name, path: full, skillPath: skillMd });
1738
1687
  } else {
1739
1688
  walkSkills(full, out);
@@ -1754,10 +1703,10 @@ function resolveFlowIds() {
1754
1703
  }
1755
1704
  }
1756
1705
  function resolveSessionIds(projectDir) {
1757
- const sessionsDir = path23__default.join(projectDir, ".skaile", "sessions");
1758
- if (!fs9__default.existsSync(sessionsDir)) return [];
1706
+ const sessionsDir = path18__default.join(projectDir, ".skaile", "sessions");
1707
+ if (!fs8__default.existsSync(sessionsDir)) return [];
1759
1708
  try {
1760
- return fs9__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
1709
+ return fs8__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
1761
1710
  } catch {
1762
1711
  return [];
1763
1712
  }
@@ -1896,7 +1845,7 @@ function printResolvedPathsSection(config) {
1896
1845
  console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
1897
1846
  }
1898
1847
  async function showConfig(opts) {
1899
- const projectDir = opts.projectDir ? path23__default.resolve(opts.projectDir) : process.cwd();
1848
+ const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
1900
1849
  let config;
1901
1850
  let wsDefaults;
1902
1851
  try {
@@ -1941,13 +1890,13 @@ function makeConfigCommand() {
1941
1890
  const cmd = new Command("config").description("Manage personal config (.skaile/settings.json)");
1942
1891
  cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
1943
1892
  cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").action(async (key, opts) => {
1944
- const projectDir = opts.projectDir ? path23__default.resolve(opts.projectDir) : process.cwd();
1893
+ const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
1945
1894
  const config = await resolveSettings(projectDir);
1946
1895
  const value = config[key];
1947
1896
  console.log(value ?? S.dim("(not set)"));
1948
1897
  });
1949
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) => {
1950
- const projectDir = opts.projectDir ? path23__default.resolve(opts.projectDir) : process.cwd();
1899
+ const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
1951
1900
  if (key === "provider" || key === "cloud" || key === "cloudConfig") {
1952
1901
  logErr(
1953
1902
  `'${key}' is no longer a setting \u2014 an endpoint is an AI provider registry entry and a session selects one with a model reference.
@@ -2287,8 +2236,8 @@ function makeConnectorCommand() {
2287
2236
  async (driver, opts) => {
2288
2237
  const { installNpmPackages } = await import('../connectors/index.js');
2289
2238
  const { scanDirectory: scanDirectory2, factoryAssetRoots: factoryAssetRoots2, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
2290
- const projectDir = path23__default.resolve(opts.projectDir);
2291
- const yamlPath = path23__default.join(projectDir, "skaile.yaml");
2239
+ const projectDir = path18__default.resolve(opts.projectDir);
2240
+ const yamlPath = path18__default.join(projectDir, "skaile.yaml");
2292
2241
  if (!existsSync(yamlPath)) {
2293
2242
  logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
2294
2243
  process.exit(1);
@@ -2348,8 +2297,8 @@ ${installResult.output}`);
2348
2297
  );
2349
2298
  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) => {
2350
2299
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
2351
- const projectDir = path23__default.resolve(opts.projectDir);
2352
- const yamlPath = path23__default.join(projectDir, "skaile.yaml");
2300
+ const projectDir = path18__default.resolve(opts.projectDir);
2301
+ const yamlPath = path18__default.join(projectDir, "skaile.yaml");
2353
2302
  if (!existsSync(yamlPath)) {
2354
2303
  logErr("No skaile.yaml found in current directory.");
2355
2304
  process.exit(1);
@@ -2366,7 +2315,7 @@ ${installResult.output}`);
2366
2315
  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) => {
2367
2316
  const res = await import('../connectors/index.js');
2368
2317
  res.registerBuiltinConnectors();
2369
- const projectDir = path23__default.resolve(opts.projectDir);
2318
+ const projectDir = path18__default.resolve(opts.projectDir);
2370
2319
  const declarations = res.loadConnectorDeclarations(projectDir);
2371
2320
  if (declarations.length === 0) {
2372
2321
  console.log("No connectors configured in skaile.yaml.");
@@ -2390,7 +2339,7 @@ ${installResult.output}`);
2390
2339
  await manager.disconnectAll();
2391
2340
  });
2392
2341
  cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
2393
- const projectDir = path23__default.resolve(opts.projectDir);
2342
+ const projectDir = path18__default.resolve(opts.projectDir);
2394
2343
  const manager = await connectConnectors(projectDir);
2395
2344
  try {
2396
2345
  console.log(JSON.stringify(manager.listConnectors(), null, 2));
@@ -2399,7 +2348,7 @@ ${installResult.output}`);
2399
2348
  }
2400
2349
  });
2401
2350
  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) => {
2402
- const projectDir = path23__default.resolve(opts.projectDir);
2351
+ const projectDir = path18__default.resolve(opts.projectDir);
2403
2352
  const manager = await connectConnectors(projectDir);
2404
2353
  try {
2405
2354
  if (opts.all) {
@@ -2423,7 +2372,7 @@ ${installResult.output}`);
2423
2372
  }
2424
2373
  });
2425
2374
  cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
2426
- const projectDir = path23__default.resolve(opts.projectDir);
2375
+ const projectDir = path18__default.resolve(opts.projectDir);
2427
2376
  const manager = await connectConnectors(projectDir);
2428
2377
  try {
2429
2378
  if (!manager.has(id)) {
@@ -2438,7 +2387,7 @@ ${installResult.output}`);
2438
2387
  }
2439
2388
  });
2440
2389
  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) => {
2441
- const projectDir = path23__default.resolve(opts.projectDir);
2390
+ const projectDir = path18__default.resolve(opts.projectDir);
2442
2391
  const manager = await connectConnectors(projectDir);
2443
2392
  try {
2444
2393
  const content = await manager.read(id, resourcePath);
@@ -2448,7 +2397,7 @@ ${installResult.output}`);
2448
2397
  }
2449
2398
  });
2450
2399
  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) => {
2451
- const projectDir = path23__default.resolve(opts.projectDir);
2400
+ const projectDir = path18__default.resolve(opts.projectDir);
2452
2401
  const manager = await connectConnectors(projectDir);
2453
2402
  try {
2454
2403
  await manager.write(id, resourcePath, { data: content });
@@ -2458,7 +2407,7 @@ ${installResult.output}`);
2458
2407
  }
2459
2408
  });
2460
2409
  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) => {
2461
- const projectDir = path23__default.resolve(opts.projectDir);
2410
+ const projectDir = path18__default.resolve(opts.projectDir);
2462
2411
  const manager = await connectConnectors(projectDir);
2463
2412
  try {
2464
2413
  const entries = await manager.list(id, resourcePath, {
@@ -2471,7 +2420,7 @@ ${installResult.output}`);
2471
2420
  }
2472
2421
  });
2473
2422
  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) => {
2474
- const projectDir = path23__default.resolve(opts.projectDir);
2423
+ const projectDir = path18__default.resolve(opts.projectDir);
2475
2424
  const manager = await connectConnectors(projectDir);
2476
2425
  try {
2477
2426
  const results = await manager.search(id, query);
@@ -2481,7 +2430,7 @@ ${installResult.output}`);
2481
2430
  }
2482
2431
  });
2483
2432
  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) => {
2484
- const projectDir = path23__default.resolve(opts.projectDir);
2433
+ const projectDir = path18__default.resolve(opts.projectDir);
2485
2434
  const manager = await connectConnectors(projectDir);
2486
2435
  try {
2487
2436
  const ok = await manager.delete(id, resourcePath);
@@ -2491,7 +2440,7 @@ ${installResult.output}`);
2491
2440
  }
2492
2441
  });
2493
2442
  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) => {
2494
- const projectDir = path23__default.resolve(opts.projectDir);
2443
+ const projectDir = path18__default.resolve(opts.projectDir);
2495
2444
  const manager = await connectConnectors(projectDir);
2496
2445
  try {
2497
2446
  if (!manager.has(id)) {
@@ -2600,7 +2549,7 @@ function envRecord() {
2600
2549
  async function buildDeployContext(projectDir) {
2601
2550
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2602
2551
  const config = resolveSkWorkspaceConfig2(projectDir);
2603
- const workspaceId = config.name ?? path23__default.basename(projectDir);
2552
+ const workspaceId = config.name ?? path18__default.basename(projectDir);
2604
2553
  let log;
2605
2554
  try {
2606
2555
  const { createLogger } = await import('../core/logging.js');
@@ -2632,13 +2581,13 @@ async function ensureTargetsRegistered(projectDir) {
2632
2581
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2633
2582
  const config = resolveSkWorkspaceConfig2(projectDir);
2634
2583
  if (config.plugins && config.plugins.length > 0) {
2635
- const { ensurePluginsLoaded } = await import('../plugin-store-MPAMD5OT.js');
2584
+ const { ensurePluginsLoaded } = await import('../plugin-store-AGQDMING.js');
2636
2585
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
2637
2586
  for (const f of result.failed) logWarn(f.error);
2638
2587
  }
2639
2588
  }
2640
2589
  async function runUp(opts) {
2641
- const projectDir = path23__default.resolve(opts.projectDir);
2590
+ const projectDir = path18__default.resolve(opts.projectDir);
2642
2591
  await ensureTargetsRegistered(projectDir);
2643
2592
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2644
2593
  const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
@@ -2706,7 +2655,7 @@ async function restoreFromHandle(projectDir) {
2706
2655
  return { target, handle, ctx };
2707
2656
  }
2708
2657
  async function runDown(opts) {
2709
- const projectDir = path23__default.resolve(opts.projectDir);
2658
+ const projectDir = path18__default.resolve(opts.projectDir);
2710
2659
  const restored = await restoreFromHandle(projectDir);
2711
2660
  if (!restored) return;
2712
2661
  await restored.handle.stop();
@@ -2715,7 +2664,7 @@ async function runDown(opts) {
2715
2664
  logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
2716
2665
  }
2717
2666
  async function runStatus(opts) {
2718
- const projectDir = path23__default.resolve(opts.projectDir);
2667
+ const projectDir = path18__default.resolve(opts.projectDir);
2719
2668
  const restored = await restoreFromHandle(projectDir);
2720
2669
  if (!restored) return;
2721
2670
  const health = await restored.handle.health();
@@ -2729,7 +2678,7 @@ async function runStatus(opts) {
2729
2678
  console.log();
2730
2679
  }
2731
2680
  async function runLogs(opts) {
2732
- const projectDir = path23__default.resolve(opts.projectDir);
2681
+ const projectDir = path18__default.resolve(opts.projectDir);
2733
2682
  const restored = await restoreFromHandle(projectDir);
2734
2683
  if (!restored) return;
2735
2684
  if (!restored.handle.logs) {
@@ -2751,34 +2700,51 @@ function makeDeployCommand() {
2751
2700
  cmd.action(() => cmd.help());
2752
2701
  return cmd;
2753
2702
  }
2703
+ var DIFF_SHOWS = { content: true, modified: true, incomplete: true };
2754
2704
  function makeDiffCommand() {
2755
2705
  return new Command("diff").description("Show changes between deployed and source versions").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
2706
+ requireProjectConfig(opts.projectDir);
2756
2707
  const am2 = new AssetManager({
2757
2708
  registry: getKindRegistry(),
2758
- projectDir: path23__default.resolve(opts.projectDir)
2709
+ projectDir: path18__default.resolve(opts.projectDir)
2759
2710
  });
2711
+ const gaps = await am2.gapsOf(ref);
2712
+ const blocking = gaps.filter((g) => !DIFF_SHOWS[g.type]);
2713
+ if (blocking.length > 0) {
2714
+ for (const g of blocking) logErr(g.message);
2715
+ process.exitCode = 1;
2716
+ return;
2717
+ }
2760
2718
  const result = await am2.diff(ref);
2719
+ const problems = gaps.filter(
2720
+ (g) => !(result.status === "differs" && (g.type === "content" || g.type === "modified"))
2721
+ );
2761
2722
  switch (result.status) {
2762
2723
  case "not-found":
2763
- logErr(`Asset not found: ${ref}`);
2764
- process.exitCode = 1;
2765
- return;
2724
+ if (problems.length === 0) logErr(`Asset not found: ${ref}`);
2725
+ break;
2766
2726
  case "not-deployed":
2767
- logWarn(`${ref} is not deployed \u2014 run skaile install`);
2768
- return;
2727
+ if (problems.length === 0) logWarn(`${ref} is not deployed \u2014 run skaile install`);
2728
+ break;
2729
+ case "no-files":
2730
+ if (problems.length === 0)
2731
+ logInfo(`${ref}: preset has no files of its own; run skaile diff on its items`);
2732
+ break;
2769
2733
  case "identical":
2770
- logInfo("No differences.");
2771
- return;
2734
+ if (problems.length === 0) logInfo("No differences.");
2735
+ break;
2772
2736
  case "differs":
2773
2737
  console.log(result.diff);
2774
- return;
2738
+ break;
2775
2739
  }
2740
+ for (const g of problems) logErr(g.message);
2741
+ if (result.status === "not-found" || problems.length > 0) process.exitCode = 1;
2776
2742
  });
2777
2743
  }
2778
2744
  function makeFlowCommand() {
2779
2745
  const cmd = new Command("flow").description("Manage flows");
2780
2746
  cmd.command("list").description("List available flows").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
2781
- const flows = await discoverFlowsWithLibraries(path23__default.resolve(opts.projectDir));
2747
+ const flows = await discoverFlowsWithLibraries(path18__default.resolve(opts.projectDir));
2782
2748
  if (flows.length === 0) {
2783
2749
  logInfo("No flows found.");
2784
2750
  return;
@@ -2793,7 +2759,7 @@ function makeFlowCommand() {
2793
2759
  console.log();
2794
2760
  });
2795
2761
  cmd.command("show <id>").description("Show flow details and node graph").option("--project-dir <path>", "Project directory", process.cwd()).action(async (id, opts) => {
2796
- const flows = await discoverFlowsWithLibraries(path23__default.resolve(opts.projectDir));
2762
+ const flows = await discoverFlowsWithLibraries(path18__default.resolve(opts.projectDir));
2797
2763
  const flow = flows.find((f) => f.id === id);
2798
2764
  if (!flow) {
2799
2765
  logErr(`Flow not found: ${id}`);
@@ -2827,7 +2793,7 @@ function makeHistoryCommand() {
2827
2793
  cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
2828
2794
  const am2 = new AssetManager({
2829
2795
  registry: getKindRegistry(),
2830
- projectDir: path23__default.resolve(opts.projectDir)
2796
+ projectDir: path18__default.resolve(opts.projectDir)
2831
2797
  });
2832
2798
  const limit = parseInt(limitStr, 10) || 20;
2833
2799
  const entries = am2.history(limit);
@@ -2850,7 +2816,7 @@ function makeHistoryCommand() {
2850
2816
  cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
2851
2817
  const am2 = new AssetManager({
2852
2818
  registry: getKindRegistry(),
2853
- projectDir: path23__default.resolve(opts.projectDir)
2819
+ projectDir: path18__default.resolve(opts.projectDir)
2854
2820
  });
2855
2821
  am2.clearHistory();
2856
2822
  logOk("History cleared.");
@@ -2864,12 +2830,12 @@ var MCP_SERVER_ENTRY = {
2864
2830
  env: {}
2865
2831
  };
2866
2832
  function pluginDir(projectDir) {
2867
- return path23__default.join(projectDir, ".claude", "plugins", "skaile");
2833
+ return path18__default.join(projectDir, ".claude", "plugins", "skaile");
2868
2834
  }
2869
2835
  async function readJsonStrict(p6) {
2870
2836
  let raw;
2871
2837
  try {
2872
- raw = await fs6.readFile(p6, "utf-8");
2838
+ raw = await fs5.readFile(p6, "utf-8");
2873
2839
  } catch {
2874
2840
  return null;
2875
2841
  }
@@ -2882,32 +2848,32 @@ async function readJsonStrict(p6) {
2882
2848
  }
2883
2849
  }
2884
2850
  async function writeJson(p6, value) {
2885
- await fs6.mkdir(path23__default.dirname(p6), { recursive: true });
2886
- await fs6.writeFile(p6, `${JSON.stringify(value, null, 2)}
2851
+ await fs5.mkdir(path18__default.dirname(p6), { recursive: true });
2852
+ await fs5.writeFile(p6, `${JSON.stringify(value, null, 2)}
2887
2853
  `);
2888
2854
  }
2889
2855
  async function copyDir(src, dest) {
2890
- await fs6.mkdir(dest, { recursive: true });
2891
- const entries = await fs6.readdir(src, { withFileTypes: true });
2856
+ await fs5.mkdir(dest, { recursive: true });
2857
+ const entries = await fs5.readdir(src, { withFileTypes: true });
2892
2858
  for (const entry of entries) {
2893
- const srcPath = path23__default.join(src, entry.name);
2894
- const destPath = path23__default.join(dest, entry.name);
2859
+ const srcPath = path18__default.join(src, entry.name);
2860
+ const destPath = path18__default.join(dest, entry.name);
2895
2861
  if (entry.isDirectory()) await copyDir(srcPath, destPath);
2896
- else await fs6.copyFile(srcPath, destPath);
2862
+ else await fs5.copyFile(srcPath, destPath);
2897
2863
  }
2898
2864
  }
2899
2865
  async function install(projectDir, opts) {
2900
2866
  return opts?.full ? installFullPlugin(projectDir) : installMcp(projectDir);
2901
2867
  }
2902
2868
  async function installMcp(projectDir) {
2903
- const mcpPath = path23__default.join(projectDir, ".claude", "mcp.json");
2869
+ const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
2904
2870
  const existing = await readJsonStrict(mcpPath) ?? {};
2905
2871
  const mcpServers = { ...existing.mcpServers ?? {} };
2906
2872
  const previous = mcpServers[SKAILE_MCP_NAME];
2907
2873
  const matches = previous && JSON.stringify(previous) === JSON.stringify(MCP_SERVER_ENTRY);
2908
2874
  let warning;
2909
2875
  if (previous && !matches) {
2910
- warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path23__default.relative(projectDir, mcpPath)}`;
2876
+ warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path18__default.relative(projectDir, mcpPath)}`;
2911
2877
  }
2912
2878
  mcpServers[SKAILE_MCP_NAME] = MCP_SERVER_ENTRY;
2913
2879
  await writeJson(mcpPath, { ...existing, mcpServers });
@@ -2916,15 +2882,15 @@ async function installMcp(projectDir) {
2916
2882
  async function installFullPlugin(projectDir) {
2917
2883
  const dir = pluginDir(projectDir);
2918
2884
  for (const [rel, content] of Object.entries(buildClaudePluginFiles())) {
2919
- const dest = path23__default.join(dir, rel);
2920
- await fs6.mkdir(path23__default.dirname(dest), { recursive: true });
2921
- await fs6.writeFile(dest, content);
2885
+ const dest = path18__default.join(dir, rel);
2886
+ await fs5.mkdir(path18__default.dirname(dest), { recursive: true });
2887
+ await fs5.writeFile(dest, content);
2922
2888
  }
2923
- const projectSkillsDir = path23__default.join(projectDir, ".skaile", "skills");
2889
+ const projectSkillsDir = path18__default.join(projectDir, ".skaile", "skills");
2924
2890
  if (existsSync(projectSkillsDir)) {
2925
- await copyDir(projectSkillsDir, path23__default.join(dir, "skills"));
2891
+ await copyDir(projectSkillsDir, path18__default.join(dir, "skills"));
2926
2892
  }
2927
- const settingsPath = path23__default.join(projectDir, ".claude", "settings.json");
2893
+ const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
2928
2894
  const settings = await readJsonStrict(settingsPath) ?? {};
2929
2895
  const plugins = settings.plugins ?? [];
2930
2896
  if (!plugins.includes(dir)) plugins.push(dir);
@@ -2932,8 +2898,8 @@ async function installFullPlugin(projectDir) {
2932
2898
  return { changed: true, method: "plugin" };
2933
2899
  }
2934
2900
  async function uninstall(projectDir) {
2935
- const settingsPath = path23__default.join(projectDir, ".claude", "settings.json");
2936
- const mcpPath = path23__default.join(projectDir, ".claude", "mcp.json");
2901
+ const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
2902
+ const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
2937
2903
  const dir = pluginDir(projectDir);
2938
2904
  let changed = false;
2939
2905
  const settings = await readJsonStrict(settingsPath);
@@ -2947,7 +2913,7 @@ async function uninstall(projectDir) {
2947
2913
  }
2948
2914
  }
2949
2915
  if (existsSync(dir)) {
2950
- await fs6.rm(dir, { recursive: true, force: true });
2916
+ await fs5.rm(dir, { recursive: true, force: true });
2951
2917
  changed = true;
2952
2918
  }
2953
2919
  const mcp = await readJsonStrict(mcpPath);
@@ -2957,7 +2923,7 @@ async function uninstall(projectDir) {
2957
2923
  const updated = { ...mcp, mcpServers: rest };
2958
2924
  if (Object.keys(rest).length === 0) delete updated.mcpServers;
2959
2925
  if (Object.keys(updated).length === 0) {
2960
- await fs6.unlink(mcpPath);
2926
+ await fs5.unlink(mcpPath);
2961
2927
  } else {
2962
2928
  await writeJson(mcpPath, updated);
2963
2929
  }
@@ -2967,12 +2933,12 @@ async function uninstall(projectDir) {
2967
2933
  async function detectInstall(projectDir) {
2968
2934
  const dir = pluginDir(projectDir);
2969
2935
  const settings = await readJsonStrict(
2970
- path23__default.join(projectDir, ".claude", "settings.json")
2936
+ path18__default.join(projectDir, ".claude", "settings.json")
2971
2937
  );
2972
- if (existsSync(path23__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
2938
+ if (existsSync(path18__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
2973
2939
  return { method: "plugin", pluginPath: dir };
2974
2940
  }
2975
- const mcp = await readJsonStrict(path23__default.join(projectDir, ".claude", "mcp.json"));
2941
+ const mcp = await readJsonStrict(path18__default.join(projectDir, ".claude", "mcp.json"));
2976
2942
  if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
2977
2943
  return { method: "mcp" };
2978
2944
  }
@@ -2981,7 +2947,7 @@ async function detectInstall(projectDir) {
2981
2947
  async function enable(projectDir) {
2982
2948
  const detected = await detectInstall(projectDir);
2983
2949
  if (!detected) throw new Error("plugin not installed for claude-code");
2984
- const settingsPath = path23__default.join(projectDir, ".claude", "settings.json");
2950
+ const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
2985
2951
  const settings = await readJsonStrict(settingsPath) ?? {};
2986
2952
  if (detected.method === "plugin") {
2987
2953
  const disabled2 = settings.disabledPlugins ?? [];
@@ -3003,7 +2969,7 @@ async function enable(projectDir) {
3003
2969
  async function disable(projectDir) {
3004
2970
  const detected = await detectInstall(projectDir);
3005
2971
  if (!detected) throw new Error("plugin not installed for claude-code");
3006
- const settingsPath = path23__default.join(projectDir, ".claude", "settings.json");
2972
+ const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
3007
2973
  const settings = await readJsonStrict(settingsPath) ?? {};
3008
2974
  if (detected.method === "plugin") {
3009
2975
  const list2 = settings.disabledPlugins ?? [];
@@ -3023,12 +2989,12 @@ async function disable(projectDir) {
3023
2989
  return { changed: true };
3024
2990
  }
3025
2991
  async function status(projectDir) {
3026
- const settingsPath = path23__default.join(projectDir, ".claude", "settings.json");
3027
- const mcpPath = path23__default.join(projectDir, ".claude", "mcp.json");
2992
+ const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
2993
+ const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
3028
2994
  const dir = pluginDir(projectDir);
3029
2995
  const settings = await readJsonStrict(settingsPath);
3030
2996
  const mcp = await readJsonStrict(mcpPath);
3031
- const pluginInstalled = !!(existsSync(path23__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
2997
+ const pluginInstalled = !!(existsSync(path18__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
3032
2998
  const mcpInstalled = !!(mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers);
3033
2999
  if (!pluginInstalled && !mcpInstalled) {
3034
3000
  return {
@@ -3046,7 +3012,7 @@ async function status(projectDir) {
3046
3012
  installed: "yes",
3047
3013
  enabled: disabled2 ? "no" : "yes",
3048
3014
  method: "plugin",
3049
- location: path23__default.relative(projectDir, dir)
3015
+ location: path18__default.relative(projectDir, dir)
3050
3016
  };
3051
3017
  }
3052
3018
  const disabled = settings?.disabledMcpjsonServers?.includes(SKAILE_MCP_NAME) ?? false;
@@ -3055,7 +3021,7 @@ async function status(projectDir) {
3055
3021
  installed: "yes",
3056
3022
  enabled: disabled ? "no" : "yes",
3057
3023
  method: "mcp",
3058
- location: path23__default.relative(projectDir, mcpPath)
3024
+ location: path18__default.relative(projectDir, mcpPath)
3059
3025
  };
3060
3026
  }
3061
3027
  var SKAILE_MCP_NAME2 = "skaile-workspace";
@@ -3069,7 +3035,7 @@ function buildEntry(projectDir) {
3069
3035
  async function readConfig(p6) {
3070
3036
  let raw;
3071
3037
  try {
3072
- raw = await fs6.readFile(p6, "utf-8");
3038
+ raw = await fs5.readFile(p6, "utf-8");
3073
3039
  } catch {
3074
3040
  return null;
3075
3041
  }
@@ -3082,16 +3048,16 @@ async function readConfig(p6) {
3082
3048
  }
3083
3049
  }
3084
3050
  async function writeConfig(p6, value) {
3085
- await fs6.mkdir(path23__default.dirname(p6), { recursive: true });
3051
+ await fs5.mkdir(path18__default.dirname(p6), { recursive: true });
3086
3052
  const cleaned = {};
3087
3053
  for (const [k, v] of Object.entries(value)) {
3088
3054
  if (v === void 0) continue;
3089
3055
  cleaned[k] = v;
3090
3056
  }
3091
- await fs6.writeFile(p6, stringify$1(cleaned));
3057
+ await fs5.writeFile(p6, stringify$1(cleaned));
3092
3058
  }
3093
3059
  function configPath(projectDir) {
3094
- return path23__default.join(projectDir, ".codex", "config.toml");
3060
+ return path18__default.join(projectDir, ".codex", "config.toml");
3095
3061
  }
3096
3062
  async function install2(projectDir) {
3097
3063
  const p6 = configPath(projectDir);
@@ -3102,7 +3068,7 @@ async function install2(projectDir) {
3102
3068
  const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
3103
3069
  let warning;
3104
3070
  if (previous && !matches) {
3105
- warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path23__default.relative(projectDir, p6)}`;
3071
+ warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path18__default.relative(projectDir, p6)}`;
3106
3072
  }
3107
3073
  if (matches) return { changed: false, method: "toml" };
3108
3074
  servers[SKAILE_MCP_NAME2] = next;
@@ -3119,7 +3085,7 @@ async function uninstall2(projectDir) {
3119
3085
  const updated = { ...cfg, mcp_servers: rest };
3120
3086
  if (Object.keys(rest).length === 0) delete updated.mcp_servers;
3121
3087
  if (Object.keys(updated).length === 0) {
3122
- await fs6.unlink(p6);
3088
+ await fs5.unlink(p6);
3123
3089
  } else {
3124
3090
  await writeConfig(p6, updated);
3125
3091
  }
@@ -3143,43 +3109,43 @@ async function status2(projectDir) {
3143
3109
  installed: "yes",
3144
3110
  enabled: "n/a",
3145
3111
  method: "mcp",
3146
- location: path23__default.relative(projectDir, p6)
3112
+ location: path18__default.relative(projectDir, p6)
3147
3113
  };
3148
3114
  }
3149
3115
  async function install3(projectDir) {
3150
- const extDir = path23__default.join(projectDir, ".omp", "extensions");
3151
- const extPath = path23__default.join(extDir, "skaile.ts");
3152
- await fs6.mkdir(extDir, { recursive: true });
3116
+ const extDir = path18__default.join(projectDir, ".omp", "extensions");
3117
+ const extPath = path18__default.join(extDir, "skaile.ts");
3118
+ await fs5.mkdir(extDir, { recursive: true });
3153
3119
  const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
3154
3120
  const plugin = new WorkspacePlugin({ projectDir });
3155
3121
  const nextSrc = await plugin.buildOmpExtensionSource();
3156
3122
  let prevSrc = null;
3157
3123
  try {
3158
- prevSrc = await fs6.readFile(extPath, "utf-8");
3124
+ prevSrc = await fs5.readFile(extPath, "utf-8");
3159
3125
  } catch {
3160
3126
  }
3161
3127
  if (prevSrc === nextSrc) return { changed: false, method: "generated" };
3162
- await fs6.writeFile(extPath, nextSrc);
3128
+ await fs5.writeFile(extPath, nextSrc);
3163
3129
  return { changed: true, method: "generated" };
3164
3130
  }
3165
3131
  async function uninstall3(projectDir) {
3166
- const extPath = path23__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3132
+ const extPath = path18__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3167
3133
  try {
3168
- await fs6.unlink(extPath);
3134
+ await fs5.unlink(extPath);
3169
3135
  return { changed: true };
3170
3136
  } catch {
3171
3137
  return { changed: false };
3172
3138
  }
3173
3139
  }
3174
3140
  async function status3(projectDir) {
3175
- const extPath = path23__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3141
+ const extPath = path18__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3176
3142
  if (existsSync(extPath)) {
3177
3143
  return {
3178
3144
  harness: "omp",
3179
3145
  installed: "yes",
3180
3146
  enabled: "n/a",
3181
3147
  method: "extension",
3182
- location: path23__default.relative(projectDir, extPath)
3148
+ location: path18__default.relative(projectDir, extPath)
3183
3149
  };
3184
3150
  }
3185
3151
  return {
@@ -3242,7 +3208,7 @@ async function installCodex(projectDir) {
3242
3208
  console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
3243
3209
  }
3244
3210
  async function runInstall(opts) {
3245
- const projectDir = path23__default.resolve(opts.projectDir);
3211
+ const projectDir = path18__default.resolve(opts.projectDir);
3246
3212
  const targets = resolveDriver(opts.driver);
3247
3213
  let exitCode = 0;
3248
3214
  if (targets.includes("claude-code")) {
@@ -3276,7 +3242,7 @@ async function uninstallCodex(projectDir) {
3276
3242
  else logInfo(`codex: not installed`);
3277
3243
  }
3278
3244
  async function runUninstall(opts) {
3279
- const projectDir = path23__default.resolve(opts.projectDir);
3245
+ const projectDir = path18__default.resolve(opts.projectDir);
3280
3246
  const targets = resolveDriver(opts.driver);
3281
3247
  let exitCode = 0;
3282
3248
  if (targets.includes("claude-code")) {
@@ -3319,7 +3285,7 @@ async function toggleTarget(t, projectDir, action3) {
3319
3285
  });
3320
3286
  }
3321
3287
  async function runToggle(opts, action3) {
3322
- const projectDir = path23__default.resolve(opts.projectDir);
3288
+ const projectDir = path18__default.resolve(opts.projectDir);
3323
3289
  const requestedAll = opts.driver === "all";
3324
3290
  const targets = resolveDriver(opts.driver);
3325
3291
  const usageError = checkToggleSupported(targets, requestedAll, action3);
@@ -3331,7 +3297,7 @@ async function runToggle(opts, action3) {
3331
3297
  return exitCode;
3332
3298
  }
3333
3299
  async function runStatus2(opts) {
3334
- const projectDir = path23__default.resolve(opts.projectDir);
3300
+ const projectDir = path18__default.resolve(opts.projectDir);
3335
3301
  const targets = resolveDriver(opts.driver);
3336
3302
  const rows = [];
3337
3303
  let exitCode = 0;
@@ -3402,7 +3368,7 @@ async function runHook(event) {
3402
3368
  await plugin.shutdown();
3403
3369
  return;
3404
3370
  }
3405
- const store = new PluginStore(path23__default.join(projectDir, ".skaile", "plugin-state.json"));
3371
+ const store = new PluginStore(path18__default.join(projectDir, ".skaile", "plugin-state.json"));
3406
3372
  await store.load();
3407
3373
  const status4 = store.get("connector:status");
3408
3374
  if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
@@ -3480,19 +3446,22 @@ function unfinishedGitState(dir) {
3480
3446
  for (const [entry, state2] of Object.entries(UNFINISHED_GIT_ENTRIES)) {
3481
3447
  const p6 = spawnSync("git", ["rev-parse", "--git-path", entry], { cwd: dir, encoding: "utf-8" });
3482
3448
  if (p6.status !== 0) return "the git directory could not be read";
3483
- if (fs9.existsSync(path23.resolve(dir, p6.stdout.trim()))) return state2;
3449
+ if (fs8.existsSync(path18.resolve(dir, p6.stdout.trim()))) return state2;
3484
3450
  }
3485
3451
  return null;
3486
3452
  }
3487
3453
  async function reindexLibrary(lib, library, name) {
3488
3454
  assertManifestEditableOrExit(lib.path);
3455
+ exitOnManifestPublisherProblems(lib.path, name);
3489
3456
  const badRequires = manifestRequiresProblems(lib.path);
3490
3457
  const resolved = resolveLibraryPublisherDetailed(lib, {}, getStoreIdentity());
3491
3458
  warnLibraryNameFallback(name, resolved);
3492
- const { removed, unknownKind, skipped } = await syncManifestWithDisk(
3459
+ const registry = getKindRegistry();
3460
+ const { removed, unknownKind, skipped, failed } = await syncManifestWithDisk(
3493
3461
  lib.path,
3494
3462
  resolved.publisher,
3495
- getKindRegistry()
3463
+ registry,
3464
+ { check: (e) => checkAssetFile(e.source, e.kind, registry) }
3496
3465
  );
3497
3466
  const manifest = loadSkPublishManifest(lib.path);
3498
3467
  for (const a of unknownKind) {
@@ -3511,16 +3480,20 @@ async function reindexLibrary(lib, library, name) {
3511
3480
  }
3512
3481
  const duplicates = skipped.filter((x) => x.reason === "duplicate");
3513
3482
  for (const s of duplicates) {
3514
- logErr(
3515
- `${s.kind}:${s.name} found in ${path23.dirname(s.file)} but ${s.detail}. Rename or delete one of the two directories, then re-run \`skaile library index ${name}\`.`
3516
- );
3483
+ logErr(duplicateAssetMessage(s.kind, s.name, path18.dirname(s.file), s.detail, name));
3517
3484
  }
3518
- const duplicateFiles = new Set(duplicates.map((s) => path23.resolve(lib.path, s.file)));
3485
+ for (const s of failed) {
3486
+ for (const f of s.findings) logErr(`${s.file} [${f.tag}] \u2014 ${f.text}`);
3487
+ }
3488
+ const duplicateFiles = new Set(duplicates.map((s) => path18.resolve(lib.path, s.file)));
3519
3489
  const skippedKeys = new Set(
3520
- skipped.filter((s) => s.reason !== "duplicate").map((s) => `${s.kind}:${s.name}`)
3490
+ [
3491
+ ...skipped.filter((s) => s.reason !== "duplicate"),
3492
+ ...failed.filter((s) => !s.inManifest)
3493
+ ].map((s) => `${s.kind}:${s.name}`)
3521
3494
  );
3522
3495
  const res = await indexLibrary(lib, library, {
3523
- exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path23.resolve(a.manifestPath))
3496
+ exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path18.resolve(a.manifestPath))
3524
3497
  });
3525
3498
  const unparsable = res.errors.filter((e) => e.includes("ManifestSchemaError:"));
3526
3499
  for (const e of res.errors) (unparsable.includes(e) ? logErr : logWarn)(e);
@@ -3531,6 +3504,7 @@ async function reindexLibrary(lib, library, name) {
3531
3504
  logErr(`${s.kind}:${s.name} skipped: manifest file ${s.file} could not be parsed.`);
3532
3505
  }
3533
3506
  for (const p6 of badRequires) logErr(`${p6.asset}: ${p6.message}`);
3507
+ for (const w of await unresolvedManifestDependencies(lib.path)) logWarn(w);
3534
3508
  logOk(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
3535
3509
  warnIgnoredDomainFiles(lib.path);
3536
3510
  warnLegacyBundleFiles(lib.path);
@@ -3545,6 +3519,12 @@ async function reindexLibrary(lib, library, name) {
3545
3519
  );
3546
3520
  process.exitCode = 1;
3547
3521
  }
3522
+ if (failed.length > 0) {
3523
+ logErr(
3524
+ `${failed.length} asset(s) fail the checks of \`skaile validate\` (listed above); fix them and re-run \`skaile library index ${name}\`.`
3525
+ );
3526
+ process.exitCode = 1;
3527
+ }
3548
3528
  if (duplicates.length > 0) {
3549
3529
  logErr(
3550
3530
  `${duplicates.length} asset(s) skipped: kind + name already registered in another directory.`
@@ -3567,26 +3547,26 @@ function assertManifestEditableOrExit(libraryPath) {
3567
3547
  }
3568
3548
  async function assertLibraryPathFree(manager, dir, exceptId) {
3569
3549
  const clash = (await manager.listLibraries()).find(
3570
- (l) => l.id !== exceptId && path23.resolve(l.path) === dir
3550
+ (l) => l.id !== exceptId && path18.resolve(l.path) === dir
3571
3551
  );
3572
3552
  if (clash) throw new Error(`${dir} is already registered as library "${clash.name}".`);
3573
3553
  }
3574
3554
  function canonicalDir(dir) {
3575
- const abs = path23.resolve(dir);
3555
+ const abs = path18.resolve(dir);
3576
3556
  const missing = [];
3577
3557
  let existing = abs;
3578
- while (!fs9.existsSync(existing)) {
3579
- const parent = path23.dirname(existing);
3558
+ while (!fs8.existsSync(existing)) {
3559
+ const parent = path18.dirname(existing);
3580
3560
  if (parent === existing) return abs;
3581
- missing.unshift(path23.basename(existing));
3561
+ missing.unshift(path18.basename(existing));
3582
3562
  existing = parent;
3583
3563
  }
3584
- return path23.join(fs9.realpathSync(existing), ...missing);
3564
+ return path18.join(fs8.realpathSync(existing), ...missing);
3585
3565
  }
3586
3566
  function refuseGlobalInstallFolder(name, dir) {
3587
3567
  const reserved = globalInstallDir();
3588
- const rel = path23.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
3589
- const inside = rel === "" || !rel.startsWith("..") && !path23.isAbsolute(rel);
3568
+ const rel = path18.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
3569
+ const inside = rel === "" || !rel.startsWith("..") && !path18.isAbsolute(rel);
3590
3570
  if (name?.toLowerCase() === GLOBAL_INSTALL_DIR_NAME || inside) {
3591
3571
  logErr(
3592
3572
  `"${GLOBAL_INSTALL_DIR_NAME}" is reserved: ${reserved} holds assets from \`skaile install\`, not a library you author.`
@@ -3594,6 +3574,85 @@ function refuseGlobalInstallFolder(name, dir) {
3594
3574
  process.exit(1);
3595
3575
  }
3596
3576
  }
3577
+ async function refuseNestedLibraryPath(manager, dir, exceptId) {
3578
+ const within = (parent, child) => {
3579
+ const rel = path18.relative(parent, child);
3580
+ return rel === "" || !rel.startsWith("..") && !path18.isAbsolute(rel);
3581
+ };
3582
+ const target = canonicalDir(dir).toLowerCase();
3583
+ const librariesDir = resolveLibraryDir();
3584
+ if (within(target, canonicalDir(librariesDir).toLowerCase())) {
3585
+ logErr(
3586
+ `"libraries" is reserved: ${librariesDir} holds every library and the global installs, not a library you author.`
3587
+ );
3588
+ process.exit(1);
3589
+ }
3590
+ for (const other of await manager.listLibraries()) {
3591
+ if (other.id === exceptId) continue;
3592
+ const otherDir = canonicalDir(other.path).toLowerCase();
3593
+ if (within(otherDir, target)) {
3594
+ logErr(
3595
+ `${dir} is inside the library "${other.name}" (${other.path}): a library cannot live inside another library.`
3596
+ );
3597
+ process.exit(1);
3598
+ }
3599
+ if (within(target, otherDir)) {
3600
+ logErr(
3601
+ `${dir} contains the library "${other.name}" (${other.path}): a library cannot contain another library.`
3602
+ );
3603
+ process.exit(1);
3604
+ }
3605
+ }
3606
+ }
3607
+ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
3608
+ const exists = (p6) => {
3609
+ try {
3610
+ fs8.lstatSync(p6);
3611
+ return true;
3612
+ } catch {
3613
+ return false;
3614
+ }
3615
+ };
3616
+ let probe = destDir;
3617
+ while (!exists(probe)) probe = path18.dirname(probe);
3618
+ let realProbe;
3619
+ try {
3620
+ realProbe = fs8.realpathSync(probe);
3621
+ } catch {
3622
+ logErr(`--dir "${given}" passes through a broken symlink (${probe}).`);
3623
+ process.exit(1);
3624
+ }
3625
+ if (!fs8.statSync(realProbe).isDirectory()) {
3626
+ logErr(`--dir "${given}": ${probe} is not a directory.`);
3627
+ process.exit(1);
3628
+ }
3629
+ 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)) {
3633
+ logErr(
3634
+ `--dir "${given}" must stay inside the library (${realRoot}): it resolves to ${realDest}.`
3635
+ );
3636
+ process.exit(1);
3637
+ }
3638
+ }
3639
+ function adoptWritesManifest(libPath) {
3640
+ if (!fs8.existsSync(path18.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
3641
+ const manifest = loadSkPublishManifest(libPath);
3642
+ if (!manifest || manifest.source || (manifest.assets ?? []).length > 0) return false;
3643
+ return manifestPublisherProblems(libPath).length === 0;
3644
+ }
3645
+ async function countUnlistedAssets(libPath) {
3646
+ const manifest = loadSkPublishManifest(libPath);
3647
+ const listed = manifest?.assets ?? [];
3648
+ if (!manifest || manifest.source || listed.length === 0) return 0;
3649
+ const keys = new Set(listed.map((a) => `${a.kind}:${a.name}`));
3650
+ const onDisk = await scanDirectory(libPath, "unlisted", {
3651
+ knownKinds: new Set(getKindRegistry().getAllKinds()),
3652
+ keepDuplicates: true
3653
+ });
3654
+ return new Set(onDisk.map((e) => `${e.kind}:${e.name}`).filter((k) => !keys.has(k))).size;
3655
+ }
3597
3656
  function readOriginTracking(dir) {
3598
3657
  if (!isGitRepo(dir)) return null;
3599
3658
  const origin = spawnSync("git", ["remote", "get-url", "origin"], { cwd: dir, encoding: "utf-8" });
@@ -3613,6 +3672,15 @@ function requireGitBackend(lib, verb) {
3613
3672
  process.exit(1);
3614
3673
  }
3615
3674
  }
3675
+ async function findLibraryWithMissingDir(name) {
3676
+ const { manager, close } = await openLibraryManager();
3677
+ try {
3678
+ const lib = await manager.getLibrary(name);
3679
+ return lib && libraryDirMissing(lib) ? lib : null;
3680
+ } finally {
3681
+ close();
3682
+ }
3683
+ }
3616
3684
  function requireValidLibraryName(name) {
3617
3685
  try {
3618
3686
  assertValidLibraryName(name);
@@ -3623,17 +3691,17 @@ function requireValidLibraryName(name) {
3623
3691
  var LOCAL_OWNERSHIP_REASON = "ownership only governs sync with a git remote, and a local library is always owned by you.";
3624
3692
  function pruneEmptyLibraryParents(libPath) {
3625
3693
  const root = canonicalDir(resolveLibraryDir());
3626
- let dir = path23.dirname(path23.resolve(libPath));
3694
+ let dir = path18.dirname(path18.resolve(libPath));
3627
3695
  for (; ; ) {
3628
- const rel = path23.relative(root, canonicalDir(dir));
3629
- if (rel === "" || rel.startsWith("..") || path23.isAbsolute(rel)) return;
3630
- if (!fs9.existsSync(dir) || fs9.readdirSync(dir).length > 0) return;
3631
- fs9.rmdirSync(dir);
3632
- dir = path23.dirname(dir);
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);
3633
3701
  }
3634
3702
  }
3635
3703
  async function warnIfNotGithubRemote(name, url) {
3636
- const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-VJSWMOLH.js');
3704
+ const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-53UTB3MB.js');
3637
3705
  if (!isGithubRemote(url)) logWarn(notGithubRemoteMessage(name, url));
3638
3706
  }
3639
3707
  function scaffoldLibraryFiles(dir, name) {
@@ -3665,9 +3733,9 @@ by the same ref.
3665
3733
  ];
3666
3734
  const written = [];
3667
3735
  for (const [file, content] of files) {
3668
- const target = path23.join(dir, file);
3669
- if (fs9.existsSync(target)) continue;
3670
- fs9.writeFileSync(target, content, "utf8");
3736
+ const target = path18.join(dir, file);
3737
+ if (fs8.existsSync(target)) continue;
3738
+ fs8.writeFileSync(target, content, "utf8");
3671
3739
  written.push(file);
3672
3740
  }
3673
3741
  return written;
@@ -3678,7 +3746,15 @@ function makeLibraryCommand() {
3678
3746
  const { manager, close } = await openLibraryManager();
3679
3747
  try {
3680
3748
  const ls = await manager.listLibraries();
3681
- if (opts.json) return console.log(JSON.stringify(ls, null, 2));
3749
+ if (opts.json) {
3750
+ return console.log(
3751
+ JSON.stringify(
3752
+ ls.map((l) => libraryDirMissing(l) ? { ...l, directoryMissing: true } : l),
3753
+ null,
3754
+ 2
3755
+ )
3756
+ );
3757
+ }
3682
3758
  if (ls.length === 0) {
3683
3759
  logInfo("No libraries registered. Run `skaile library init personal` to start.");
3684
3760
  return;
@@ -3698,6 +3774,7 @@ function makeLibraryCommand() {
3698
3774
  console.log(`
3699
3775
  ${S.dim(`${ls.length} library(s)`)}
3700
3776
  `);
3777
+ for (const l of ls) if (libraryDirMissing(l)) logWarn(missingLibraryDirMessage(l));
3701
3778
  } finally {
3702
3779
  close();
3703
3780
  }
@@ -3724,6 +3801,10 @@ function makeLibraryCommand() {
3724
3801
  console.log(` ${S.label("manifestGen")} ${l.manifestGenerated}`);
3725
3802
  console.log(` ${S.label("backendConfig")} ${JSON.stringify(l.backendConfig)}`);
3726
3803
  console.log();
3804
+ if (libraryDirMissing(l)) {
3805
+ logErr(missingLibraryDirMessage(l));
3806
+ process.exitCode = 1;
3807
+ }
3727
3808
  } finally {
3728
3809
  close();
3729
3810
  }
@@ -3736,10 +3817,15 @@ function makeLibraryCommand() {
3736
3817
  logErr("Pick one of --owner, --contributor, --reader.");
3737
3818
  process.exit(1);
3738
3819
  }
3739
- const ownership = flagged[0] ?? "owner";
3740
- const libPath = opts.path ? path23.resolve(opts.path) : path23.join(resolveLibraryDir(), name);
3820
+ const gone = await findLibraryWithMissingDir(name);
3821
+ if (gone) {
3822
+ if (gone.backend === "git") opts.git ??= gone.backendConfig.url;
3823
+ opts.path ??= gone.path;
3824
+ }
3825
+ const ownership = flagged[0] ?? gone?.ownership ?? "owner";
3826
+ const libPath = opts.path ? path18.resolve(opts.path) : path18.join(resolveLibraryDir(), name);
3741
3827
  refuseGlobalInstallFolder(name, libPath);
3742
- if (fs9.existsSync(libPath) && !fs9.statSync(libPath).isDirectory()) {
3828
+ if (fs8.existsSync(libPath) && !fs8.statSync(libPath).isDirectory()) {
3743
3829
  logErr(`${libPath} exists and is not a directory.`);
3744
3830
  process.exit(1);
3745
3831
  }
@@ -3752,11 +3838,14 @@ function makeLibraryCommand() {
3752
3838
  }
3753
3839
  const { manager, library, close } = await openLibraryManager();
3754
3840
  try {
3755
- if (await manager.getLibrary(name)) {
3841
+ const existing = await manager.getLibrary(name);
3842
+ if (existing && !gone) {
3756
3843
  logErr(`A library named "${name}" is already registered.`);
3757
3844
  process.exit(1);
3758
3845
  }
3846
+ if (existing) await manager.removeLibrary(name);
3759
3847
  await assertLibraryPathFree(manager, libPath);
3848
+ await refuseNestedLibraryPath(manager, libPath);
3760
3849
  const hasDefault = (await manager.listLibraries()).some((l) => l.isDefault);
3761
3850
  let backend = "local";
3762
3851
  let backendConfig;
@@ -3775,9 +3864,9 @@ function makeLibraryCommand() {
3775
3864
  backend = "git";
3776
3865
  backendConfig = { url: adopted.url, branch: adopted.branch, authHint: "ssh" };
3777
3866
  } else {
3778
- fs9.mkdirSync(libPath, { recursive: true });
3867
+ fs8.mkdirSync(libPath, { recursive: true });
3779
3868
  }
3780
- const blank = fs9.readdirSync(libPath).every((entry) => entry === ".git");
3869
+ const blank = fs8.readdirSync(libPath).every((entry) => entry === ".git");
3781
3870
  const isDefault = !hasDefault && ownership !== "reader";
3782
3871
  await manager.addLibrary({
3783
3872
  name,
@@ -3804,6 +3893,11 @@ function makeLibraryCommand() {
3804
3893
  }
3805
3894
  if (!blank) {
3806
3895
  const lib = await manager.requireLibrary(name);
3896
+ if (adoptWritesManifest(libPath)) {
3897
+ await reindexLibrary(lib, library, name);
3898
+ return;
3899
+ }
3900
+ const unlisted = await countUnlistedAssets(libPath);
3807
3901
  const resolved = resolveLibraryPublisherDetailed(lib, {}, getStoreIdentity());
3808
3902
  if (resolved.source === "manifest" && !isValidPublisher(resolved.publisher)) {
3809
3903
  logWarn(
@@ -3817,6 +3911,11 @@ function makeLibraryCommand() {
3817
3911
  const res = await indexLibrary(lib, library);
3818
3912
  for (const e of res.errors) logWarn(e);
3819
3913
  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
+ }
3820
3919
  warnIgnoredDomainFiles(libPath);
3821
3920
  }
3822
3921
  } catch (err2) {
@@ -3829,7 +3928,7 @@ function makeLibraryCommand() {
3829
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) => {
3830
3929
  const { manager, close } = await openLibraryManager();
3831
3930
  try {
3832
- const lib = await manager.requireLibrary(name);
3931
+ const lib = await manager.requireLibraryDir(name);
3833
3932
  if (lib.backend === "git") {
3834
3933
  logErr(
3835
3934
  `Library "${name}" is already git-backed. Use \`skaile library set ${name} backendConfig.url=${url}\` to change its remote.`
@@ -3866,13 +3965,7 @@ function makeLibraryCommand() {
3866
3965
  logErr(`Invalid asset name "${name}": ${ASSET_NAME_HINT}.`);
3867
3966
  process.exit(1);
3868
3967
  }
3869
- if (opts.publisher !== void 0) {
3870
- const bare = opts.publisher.trim().replace(/^@/, "");
3871
- if (!isValidPublisher(bare)) {
3872
- logErr(`Invalid publisher "${opts.publisher}": ${PUBLISHER_HINT}.`);
3873
- process.exit(1);
3874
- }
3875
- }
3968
+ if (opts.publisher !== void 0) requireValidPublisherOrExit(opts.publisher);
3876
3969
  if (opts.description !== void 0) {
3877
3970
  const len = opts.description.trim().length;
3878
3971
  if (len === 0 || len > 1024) {
@@ -3884,24 +3977,26 @@ function makeLibraryCommand() {
3884
3977
  try {
3885
3978
  const target = await resolveTargetLibrary(manager, opts.library);
3886
3979
  assertManifestEditableOrExit(target.path);
3980
+ exitOnManifestPublisherProblems(target.path, target.name);
3887
3981
  const effectiveKind = opts.kind ?? kind;
3888
3982
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
3889
- const libRoot = path23.resolve(target.path);
3890
- const destDir = opts.dir ? path23.resolve(libRoot, opts.dir) : libRoot;
3891
- const relDest = path23.relative(libRoot, destDir);
3892
- if (relDest === ".." || relDest.startsWith(`..${path23.sep}`) || path23.isAbsolute(relDest)) {
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)) {
3893
3987
  logErr(`--dir "${opts.dir}" must stay inside the library (${libRoot}).`);
3894
3988
  process.exit(1);
3895
3989
  }
3990
+ if (opts.dir) assertCreateDirInsideLibrary(libRoot, destDir, opts.dir);
3896
3991
  const taken = conflictingAssetRoot(
3897
3992
  libRoot,
3898
3993
  effectiveKind,
3899
3994
  name,
3900
- path23.relative(libRoot, path23.join(destDir, name))
3995
+ path18.relative(libRoot, path18.join(destDir, name))
3901
3996
  );
3902
3997
  if (taken) {
3903
3998
  logErr(
3904
- `${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path23.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
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.`
3905
4000
  );
3906
4001
  process.exit(1);
3907
4002
  }
@@ -3911,9 +4006,9 @@ function makeLibraryCommand() {
3911
4006
  process.exit(1);
3912
4007
  }
3913
4008
  logOk(`Created ${effectiveKind}: ${pc5.dim(res.path)}`);
3914
- if (opts.description === void 0 && effectiveKind === "skill") {
4009
+ if (opts.description === void 0) {
3915
4010
  logWarn(
3916
- "Description is a TODO placeholder \u2014 edit it (what the skill does and when to use it) or `skaile validate` will fail."
4011
+ `Description is a TODO placeholder \u2014 edit it (what the ${effectiveKind} does and when to use it) or \`skaile validate\` will fail.`
3917
4012
  );
3918
4013
  }
3919
4014
  const { ref } = await registerLibraryAsset(target, library, {
@@ -3930,9 +4025,9 @@ function makeLibraryCommand() {
3930
4025
  }
3931
4026
  );
3932
4027
  async function resolveTargetLibrary(manager, libraryName) {
3933
- if (libraryName) return manager.requireLibrary(libraryName);
4028
+ if (libraryName) return manager.requireLibraryDir(libraryName);
3934
4029
  const def = await manager.findDefaultLibrary();
3935
- if (def) return def;
4030
+ if (def) return manager.requireLibraryDir(def.name);
3936
4031
  if ((await manager.listLibraries()).length === 0) {
3937
4032
  logErr("No libraries registered. Run `skaile library init <name>` first.");
3938
4033
  process.exit(1);
@@ -3950,18 +4045,22 @@ function makeLibraryCommand() {
3950
4045
  }
3951
4046
  });
3952
4047
  async function renameLibrary(manager, lib, newName) {
4048
+ if (libraryDirMissing(lib)) {
4049
+ logErr(missingLibraryDirMessage(lib));
4050
+ process.exit(1);
4051
+ }
3953
4052
  requireValidLibraryName(newName);
3954
4053
  if (await manager.getLibrary(newName)) {
3955
4054
  logErr(`A library named "${newName}" is already registered.`);
3956
4055
  process.exit(1);
3957
4056
  }
3958
- const newPath = path23.join(path23.dirname(lib.path), newName);
4057
+ const newPath = path18.join(path18.dirname(lib.path), newName);
3959
4058
  refuseGlobalInstallFolder(newName, newPath);
3960
- if (fs9.existsSync(newPath)) {
4059
+ if (fs8.existsSync(newPath)) {
3961
4060
  logErr(`Target directory already exists: ${newPath}`);
3962
4061
  process.exit(1);
3963
4062
  }
3964
- fs9.renameSync(lib.path, newPath);
4063
+ fs8.renameSync(lib.path, newPath);
3965
4064
  await manager.updateLibrary(lib.id, { name: newName, path: newPath });
3966
4065
  logOk(`Renamed ${lib.name} \u2192 ${newName}`);
3967
4066
  }
@@ -3988,17 +4087,17 @@ function makeLibraryCommand() {
3988
4087
  try {
3989
4088
  const lib = await manager.requireLibrary(name);
3990
4089
  if (field === "publisher") {
3991
- const publisher = value.trim().replace(/^@/, "");
3992
- if (!isValidPublisher(publisher)) {
3993
- logErr(`Invalid publisher "${value}": ${PUBLISHER_HINT}.`);
3994
- process.exit(1);
3995
- }
4090
+ const publisher = requireValidPublisherOrExit(value);
3996
4091
  if (lib.ownership === "reader") {
3997
4092
  logErr(
3998
4093
  `Library "${lib.name}" is read-only (ownership=reader); its publisher is not yours to set.`
3999
4094
  );
4000
4095
  process.exit(1);
4001
4096
  }
4097
+ if (libraryDirMissing(lib)) {
4098
+ logErr(missingLibraryDirMessage(lib));
4099
+ process.exit(1);
4100
+ }
4002
4101
  assertManifestEditableOrExit(lib.path);
4003
4102
  setManifestPublisher(lib.path, publisher);
4004
4103
  const res = await indexLibrary(lib, library);
@@ -4041,13 +4140,14 @@ function makeLibraryCommand() {
4041
4140
  }
4042
4141
  patch.isDefault = false;
4043
4142
  } else if (field === "path") {
4044
- const dir = path23.resolve(value);
4045
- if (!fs9.existsSync(dir) || !fs9.statSync(dir).isDirectory()) {
4143
+ const dir = path18.resolve(value);
4144
+ if (!fs8.existsSync(dir) || !fs8.statSync(dir).isDirectory()) {
4046
4145
  logErr(`Directory does not exist: ${dir}. \`library set path=\` does not move files.`);
4047
4146
  process.exit(1);
4048
4147
  }
4049
4148
  refuseGlobalInstallFolder(null, dir);
4050
4149
  await assertLibraryPathFree(manager, dir, lib.id);
4150
+ await refuseNestedLibraryPath(manager, dir, lib.id);
4051
4151
  patch.path = dir;
4052
4152
  } else if (field.startsWith("backendConfig.")) {
4053
4153
  const key = field.split(".")[1];
@@ -4105,7 +4205,7 @@ function makeLibraryCommand() {
4105
4205
  cmd.command("sync <name>").description("Pull then push (as backend permits)").action(async (name) => {
4106
4206
  const { manager, library, close } = await openLibraryManager();
4107
4207
  try {
4108
- const lib = await manager.requireLibrary(name);
4208
+ const lib = await manager.requireLibraryDir(name);
4109
4209
  requireGitBackend(lib, "sync");
4110
4210
  const drv = manager.driverFor(lib.backend);
4111
4211
  const pull = await drv.pull(lib);
@@ -4127,8 +4227,10 @@ function makeLibraryCommand() {
4127
4227
  cmd.command("index <name>").description("(Re)index a library's assets into the local index").action(async (name) => {
4128
4228
  const { manager, library, close } = await openLibraryManager();
4129
4229
  try {
4130
- const lib = await manager.requireLibrary(name);
4230
+ const lib = await manager.requireLibraryDir(name);
4131
4231
  await reindexLibrary(lib, library, name);
4232
+ } catch (err2) {
4233
+ exitOnSyncError(err2);
4132
4234
  } finally {
4133
4235
  close();
4134
4236
  }
@@ -4136,7 +4238,7 @@ function makeLibraryCommand() {
4136
4238
  cmd.command("pull <name>").description("Pull from remote").action(async (name) => {
4137
4239
  const { manager, library, close } = await openLibraryManager();
4138
4240
  try {
4139
- const lib = await manager.requireLibrary(name);
4241
+ const lib = await manager.requireLibraryDir(name);
4140
4242
  requireGitBackend(lib, "pull");
4141
4243
  const res = await manager.driverFor(lib.backend).pull(lib);
4142
4244
  if (res.conflicts.length > 0) {
@@ -4154,7 +4256,7 @@ function makeLibraryCommand() {
4154
4256
  cmd.command("push <name>").description("Push local commits (owner only)").option("--force", "Force-with-lease push", false).action(async (name, opts) => {
4155
4257
  const { manager, close } = await openLibraryManager();
4156
4258
  try {
4157
- const lib = await manager.requireLibrary(name);
4259
+ const lib = await manager.requireLibraryDir(name);
4158
4260
  requireGitBackend(lib, "push");
4159
4261
  const res = await manager.driverFor(lib.backend).push(lib, { force: opts.force });
4160
4262
  logOk(`Pushed (${res.pushed}).`);
@@ -4167,7 +4269,7 @@ function makeLibraryCommand() {
4167
4269
  cmd.command("propose <name>").description("Open a pull request on the upstream repo (contributor only)").option("--title <title>", "PR title").option("--body <body>", "PR body").option("--branch <name>", "Branch name (default: skaile/<timestamp>)").action(async (name, opts) => {
4168
4270
  const { manager, close } = await openLibraryManager();
4169
4271
  try {
4170
- const lib = await manager.requireLibrary(name);
4272
+ const lib = await manager.requireLibraryDir(name);
4171
4273
  const res = await manager.driverFor(lib.backend).propose(lib, opts);
4172
4274
  logOk(`PR opened: ${res.prUrl}`);
4173
4275
  } catch (err2) {
@@ -4179,7 +4281,7 @@ function makeLibraryCommand() {
4179
4281
  cmd.command("commit <name>").description("Git-commit local changes inside the library (git only)").option("-m, --message <msg>", "Commit message", "skaile: update assets").action(async (name, opts) => {
4180
4282
  const { manager, close } = await openLibraryManager();
4181
4283
  try {
4182
- const lib = await manager.requireLibrary(name);
4284
+ const lib = await manager.requireLibraryDir(name);
4183
4285
  requireGitBackend(lib, "commit");
4184
4286
  if (!isGitRepo(lib.path)) {
4185
4287
  logErr(
@@ -4232,13 +4334,15 @@ function makeLibraryCommand() {
4232
4334
  const args = rawArgs[0] === "--" ? rawArgs.slice(1) : rawArgs;
4233
4335
  const { manager, close } = await openLibraryManager();
4234
4336
  try {
4235
- const lib = await manager.requireLibrary(name);
4337
+ const lib = await manager.requireLibraryDir(name);
4236
4338
  const r = spawnSync("git", args, { cwd: lib.path, stdio: "inherit" });
4237
4339
  if (r.error) {
4238
4340
  logErr(`Could not run git: ${r.error.message}`);
4239
4341
  process.exit(1);
4240
4342
  }
4241
4343
  process.exit(r.status ?? 1);
4344
+ } catch (err2) {
4345
+ exitOnSyncError(err2);
4242
4346
  } finally {
4243
4347
  close();
4244
4348
  }
@@ -4248,16 +4352,16 @@ function makeLibraryCommand() {
4248
4352
  "With --create-repo: create the repo private (the store only accepts public repos)"
4249
4353
  ).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(
4250
4354
  async (lib, opts) => {
4251
- const { runLibraryPublish } = await import('../library-publish-VJSWMOLH.js');
4355
+ const { runLibraryPublish } = await import('../library-publish-53UTB3MB.js');
4252
4356
  await withStoreErrorHandling(() => runLibraryPublish(lib, opts));
4253
4357
  }
4254
4358
  );
4255
4359
  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) => {
4256
- const { runLibraryRegister } = await import('../library-publish-VJSWMOLH.js');
4360
+ const { runLibraryRegister } = await import('../library-publish-53UTB3MB.js');
4257
4361
  await withStoreErrorHandling(() => runLibraryRegister(lib, opts));
4258
4362
  });
4259
4363
  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) => {
4260
- const { runLibraryYank } = await import('../library-publish-VJSWMOLH.js');
4364
+ const { runLibraryYank } = await import('../library-publish-53UTB3MB.js');
4261
4365
  await withStoreErrorHandling(() => runLibraryYank(lib, opts));
4262
4366
  });
4263
4367
  return cmd;
@@ -4273,7 +4377,7 @@ async function withStoreErrorHandling(fn) {
4273
4377
  async function printPerLibraryStatus(name, asJson) {
4274
4378
  const { manager, close } = await openLibraryManager();
4275
4379
  try {
4276
- const lib = await manager.requireLibrary(name);
4380
+ const lib = await manager.requireLibraryDir(name);
4277
4381
  const status4 = await manager.driverFor(lib.backend).status(lib);
4278
4382
  if (asJson) return console.log(JSON.stringify({ library: lib.name, status: status4 }, null, 2));
4279
4383
  console.log(`
@@ -4308,9 +4412,9 @@ async function printOverallStatus(projectDir, asJson) {
4308
4412
  } catch {
4309
4413
  secretsStrategy = "unavailable";
4310
4414
  }
4311
- const resolvedProjectDir = path23.resolve(projectDir);
4312
- const hasWorkspaceConfig = existsSync(path23.join(resolvedProjectDir, "skaile.yaml"));
4313
- const hasLockFile = existsSync(path23.join(resolvedProjectDir, "skaile.lock.yaml"));
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"));
4314
4418
  let assignments = [];
4315
4419
  if (hasWorkspaceConfig) {
4316
4420
  try {
@@ -4917,7 +5021,7 @@ function scheduleSoftDepPreview() {
4917
5021
  }
4918
5022
  async function loadAssets() {
4919
5023
  softDepPreviewCache.clear();
4920
- const { gatherAssetFeeds } = await import('../asset-feeds-XMKKUUK6.js');
5024
+ const { gatherAssetFeeds } = await import('../asset-feeds-CXGQIDFR.js');
4921
5025
  const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
4922
5026
  if (notes.length > 0) {
4923
5027
  state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
@@ -4925,10 +5029,15 @@ async function loadAssets() {
4925
5029
  const installed = new Set(am.listDeployed().map((e) => `${e.kind}:${e.name}`));
4926
5030
  let lock = null;
4927
5031
  try {
4928
- lock = readLock(path23__default.join(am.projectDir, "skaile.lock.yaml"));
5032
+ lock = readLock(path18__default.join(am.projectDir, "skaile.lock.yaml"));
4929
5033
  } catch {
4930
5034
  }
4931
- const rows = buildAssetRows(entries, installed, lockedLibraryByIdentity(lock));
5035
+ const rows = buildAssetRows(
5036
+ entries,
5037
+ installed,
5038
+ await am.lockedLibraryNames(),
5039
+ lockedPublishersByName(lock)
5040
+ );
4932
5041
  state.assetRows = rows;
4933
5042
  reconcileCollapsedSets(rows);
4934
5043
  rebuildVisible();
@@ -4942,7 +5051,7 @@ function rebuildSourceTree() {
4942
5051
  rebuildVisibleSources();
4943
5052
  }
4944
5053
  function sourceOrgRepo(s) {
4945
- const parts = s.path.split(path23__default.sep).filter(Boolean);
5054
+ const parts = s.path.split(path18__default.sep).filter(Boolean);
4946
5055
  if (parts.length < 2) return null;
4947
5056
  return { org: parts[parts.length - 2], repo: parts[parts.length - 1] };
4948
5057
  }
@@ -5015,22 +5124,27 @@ function rebuildVisibleLibraries() {
5015
5124
  );
5016
5125
  clampCursor();
5017
5126
  }
5018
- function lockedLibraryByIdentity(lock) {
5127
+ function lockedPublishersByName(lock) {
5019
5128
  const out = /* @__PURE__ */ new Map();
5020
- for (const [key, locked] of Object.entries(lock?.assets ?? {})) {
5021
- if (!locked.library) continue;
5129
+ for (const key of Object.keys(lock?.assets ?? {})) {
5022
5130
  const ref = parseAssetRefLoose(key);
5023
- if (ref?.publisher) out.set(`${ref.kind}:${ref.publisher}/${ref.name}`, locked.library.name);
5131
+ if (!ref?.publisher) continue;
5132
+ const id = `${ref.kind}:${ref.name}`;
5133
+ const publishers = out.get(id) ?? /* @__PURE__ */ new Set();
5134
+ publishers.add(ref.publisher);
5135
+ out.set(id, publishers);
5024
5136
  }
5025
5137
  return out;
5026
5138
  }
5027
- function isRowInstalled(origin, group, entry, installed, lockedLibrary) {
5139
+ function isRowInstalled(origin, group, entry, installed, lockedLibrary, lockedPublishers) {
5028
5140
  if (!installed.has(`${entry.kind}:${entry.name}`)) return false;
5029
5141
  const publisher = entry.publisher?.replace(/^@/, "");
5142
+ const lockedFor = lockedPublishers.get(`${entry.kind}:${entry.name}`);
5143
+ if (publisher && lockedFor && !lockedFor.has(publisher)) return false;
5030
5144
  const locked = publisher ? lockedLibrary.get(`${entry.kind}:${publisher}/${entry.name}`) : void 0;
5031
- return locked === void 0 || origin === "library" && group === locked;
5145
+ return locked === void 0 || origin === "library" && locked !== null && group === locked;
5032
5146
  }
5033
- function buildAssetRows(entries, installed, lockedLibrary = /* @__PURE__ */ new Map()) {
5147
+ function buildAssetRows(entries, installed, lockedLibrary = /* @__PURE__ */ new Map(), lockedPublishers = /* @__PURE__ */ new Map()) {
5034
5148
  const byOrigin = /* @__PURE__ */ new Map();
5035
5149
  for (const { origin, entry, group } of entries) {
5036
5150
  const publisher = group || entry.publisher || "other";
@@ -5058,7 +5172,14 @@ function buildAssetRows(entries, installed, lockedLibrary = /* @__PURE__ */ new
5058
5172
  source: group,
5059
5173
  org: entry.repo?.includes("/") ? entry.repo.slice(0, entry.repo.indexOf("/")) : void 0,
5060
5174
  entry,
5061
- installed: isRowInstalled(origin, group, entry, installed, lockedLibrary),
5175
+ installed: isRowInstalled(
5176
+ origin,
5177
+ group,
5178
+ entry,
5179
+ installed,
5180
+ lockedLibrary,
5181
+ lockedPublishers
5182
+ ),
5062
5183
  plugin
5063
5184
  });
5064
5185
  }
@@ -5104,13 +5225,13 @@ function reconcileCollapsedSets(rows) {
5104
5225
  async function loadSourcesAndLibraries() {
5105
5226
  try {
5106
5227
  const [{ openLibraryManager: openLibraryManager2 }, { getGlobalCacheDir: getGlobalCacheDir2, globalSkaileDir: globalSkaileDir2 }] = await Promise.all([
5107
- import('../open-library-DB2PNL2X.js'),
5228
+ import('../open-library-BOSPJVID.js'),
5108
5229
  import('../core/index.js')
5109
5230
  ]);
5110
5231
  const { manager, library, close } = await openLibraryManager2();
5111
5232
  try {
5112
5233
  const newRoot = getGlobalCacheDir2();
5113
- const legacyRoot = path23__default.join(globalSkaileDir2(), "sources");
5234
+ const legacyRoot = path18__default.join(globalSkaileDir2(), "sources");
5114
5235
  const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
5115
5236
  const libs = await manager.listLibraries();
5116
5237
  const defs = await library.listAssetDefs();
@@ -5236,12 +5357,25 @@ function pendingCountsFor(match) {
5236
5357
  }
5237
5358
  return [add, remove];
5238
5359
  }
5239
- function groupStatus(refs) {
5240
- if (refs.length === 0) return pc5.dim("\xB7 ");
5241
- if (refs.some((r) => state.pendingAdds.has(r))) return pc5.blue("+ ");
5242
- if (refs.some((r) => state.pendingRemoves.has(r))) return pc5.red("- ");
5243
- const allInstalled = refs.every((r) => findAssetRow(r)?.installed);
5244
- return allInstalled ? pc5.green("\u2713 ") : pc5.dim("\xB7 ");
5360
+ function groupSelectionState(rows, pendingAdds, pendingRemoves) {
5361
+ const own = rows.filter((r) => assetRefOf(r) !== null);
5362
+ if (own.length === 0) return "empty";
5363
+ const refs = refsOf(own);
5364
+ if (refs.some((r) => pendingAdds.has(r))) return "add";
5365
+ if (refs.some((r) => pendingRemoves.has(r))) return "remove";
5366
+ return own.every((r) => r.installed) ? "installed" : "none";
5367
+ }
5368
+ function groupStatus(rows) {
5369
+ switch (groupSelectionState(rows, state.pendingAdds, state.pendingRemoves)) {
5370
+ case "add":
5371
+ return pc5.blue("+ ");
5372
+ case "remove":
5373
+ return pc5.red("- ");
5374
+ case "installed":
5375
+ return pc5.green("\u2713 ");
5376
+ default:
5377
+ return pc5.dim("\xB7 ");
5378
+ }
5245
5379
  }
5246
5380
  function renderHeaderLine(opts) {
5247
5381
  const indicator = opts.collapsed ? "\u25B6" : "\u25BC";
@@ -5253,7 +5387,7 @@ function renderHeaderLine(opts) {
5253
5387
  if (add > 0) count += pc5.green(`+${add}`);
5254
5388
  if (remove > 0) count += pc5.red(`-${remove}`);
5255
5389
  count += `/${total}`;
5256
- const status4 = groupStatus(opts.refs);
5390
+ const status4 = groupStatus(countRows.filter(opts.match));
5257
5391
  const line = `${opts.indent}${status4}${indicator} ${opts.label} (${count} assets)`;
5258
5392
  return opts.selected ? pc5.bgWhite(pc5.black(`${line} `.padEnd(state.cols))) : line;
5259
5393
  }
@@ -5265,7 +5399,6 @@ function renderAssetRow(row, selected) {
5265
5399
  indent: " ",
5266
5400
  collapsed: state.collapsedOrigins.has(origin),
5267
5401
  match: (r) => isAsset(r) && rowOrigin(r) === origin,
5268
- refs: originAssetRefs(state.assetRows, origin),
5269
5402
  label: `${meta.icon} ${pc5.bold(pc5.cyan(meta.label))}`,
5270
5403
  selected
5271
5404
  });
@@ -5276,7 +5409,6 @@ function renderAssetRow(row, selected) {
5276
5409
  indent: " ".repeat(3),
5277
5410
  collapsed: state.collapsedSources.has(srcKey(origin, row.source)),
5278
5411
  match: (r) => isAsset(r) && inSource(r, origin, row.source),
5279
- refs: sourceAssetRefs(state.assetRows, origin, row.source),
5280
5412
  label: pc5.bold(pc5.cyan(row.source)),
5281
5413
  selected
5282
5414
  });
@@ -5288,7 +5420,6 @@ function renderAssetRow(row, selected) {
5288
5420
  indent: " ".repeat(5),
5289
5421
  collapsed: state.collapsedPlugins.has(pluginKey(origin, row.source, plugin)),
5290
5422
  match: (r) => isAsset(r) && inPlugin(r, origin, row.source, plugin),
5291
- refs: pluginAssetRefs(state.assetRows, origin, row.source, plugin),
5292
5423
  label: pluginHeaderLabel(plugin),
5293
5424
  selected
5294
5425
  });
@@ -5331,7 +5462,6 @@ function renderSourceTreeRow(row, selected) {
5331
5462
  indent: " ".repeat(3),
5332
5463
  collapsed: state.collapsedSourceOrgs.has(org),
5333
5464
  match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org,
5334
- refs: sourceOrgRefs(state.sourceTreeRows, org),
5335
5465
  label: pc5.bold(pc5.cyan(org)),
5336
5466
  selected,
5337
5467
  rows: state.sourceTreeRows
@@ -5344,7 +5474,6 @@ function renderSourceTreeRow(row, selected) {
5344
5474
  indent: " ".repeat(5),
5345
5475
  collapsed: state.collapsedSourceRepos.has(repoKey(org, repo)),
5346
5476
  match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo,
5347
- refs: sourceRepoRefs(state.sourceTreeRows, org, repo),
5348
5477
  label: pc5.bold(repo),
5349
5478
  selected,
5350
5479
  rows: state.sourceTreeRows
@@ -5358,7 +5487,6 @@ function renderSourceTreeRow(row, selected) {
5358
5487
  indent: " ".repeat(7),
5359
5488
  collapsed: state.collapsedSourcePlugins.has(srcPluginKey(org, repo, plugin)),
5360
5489
  match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo && r.plugin === plugin,
5361
- refs: sourcePluginRefs(state.sourceTreeRows, org, repo, plugin),
5362
5490
  label: pluginHeaderLabel(plugin),
5363
5491
  selected,
5364
5492
  rows: state.sourceTreeRows
@@ -5379,7 +5507,6 @@ function renderLibraryTreeRow(row, selected) {
5379
5507
  indent: " ".repeat(3),
5380
5508
  collapsed: state.collapsedLibraryGroups.has(group),
5381
5509
  match: (r) => isAsset(r) && rowOrigin(r) === "library" && rowGroup(r) === group,
5382
- refs: libraryGroupRefs(state.libraryTreeRows, group),
5383
5510
  label: pc5.bold(pc5.cyan(group)),
5384
5511
  selected,
5385
5512
  rows: state.libraryTreeRows
@@ -5392,7 +5519,6 @@ function renderLibraryTreeRow(row, selected) {
5392
5519
  indent: " ".repeat(5),
5393
5520
  collapsed: state.collapsedLibraryPlugins.has(libPluginKey(group, plugin)),
5394
5521
  match: (r) => isAsset(r) && inPlugin(r, "library", group, plugin),
5395
- refs: pluginAssetRefs(state.libraryTreeRows, "library", group, plugin),
5396
5522
  label: pluginHeaderLabel(plugin),
5397
5523
  selected,
5398
5524
  rows: state.libraryTreeRows
@@ -5480,10 +5606,15 @@ async function applyChanges() {
5480
5606
  let pruned = 0;
5481
5607
  const appliedAdds = [];
5482
5608
  const appliedRemoves = [];
5609
+ const blockedRemovals = [];
5483
5610
  for (const ref of state.pendingRemoves) {
5484
5611
  try {
5485
5612
  const result = await am.removeWithDependencies(ref);
5486
- if (result.changed) {
5613
+ if (result.blocked) {
5614
+ blockedRemovals.push(
5615
+ `kept ${result.blocked.ref}: required by ${result.blocked.requiredBy.join(", ")} (skaile remove --force overrides)`
5616
+ );
5617
+ } else if (result.changed) {
5487
5618
  removed++;
5488
5619
  pruned += result.pruned.length;
5489
5620
  appliedRemoves.push(ref);
@@ -5510,6 +5641,7 @@ async function applyChanges() {
5510
5641
  if (added > 0) parts.push(pc5.green(`+${added} added`));
5511
5642
  if (removed > 0) parts.push(pc5.red(`-${removed} removed`));
5512
5643
  if (pruned > 0) parts.push(pc5.red(`-${pruned} no longer required`));
5644
+ for (const b of blockedRemovals) parts.push(pc5.yellow(b));
5513
5645
  const softDeps = appliedAdds.length > 0 ? await am.reportSoftDeps(appliedAdds) : [];
5514
5646
  if (softDeps.length > 0) {
5515
5647
  parts.push(pc5.dim(`${softDeps.length} soft dep${softDeps.length === 1 ? "" : "s"} referenced`));
@@ -6059,13 +6191,13 @@ async function run(projectDir) {
6059
6191
  }
6060
6192
  function makeManageCommand() {
6061
6193
  return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
6062
- await run(path23__default.resolve(opts.projectDir));
6194
+ await run(path18__default.resolve(opts.projectDir));
6063
6195
  });
6064
6196
  }
6065
6197
  function makeMcpServerCommand() {
6066
6198
  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) => {
6067
- const path44 = await import('path');
6068
- const projectDir = path44.default.resolve(opts.projectDir);
6199
+ const path43 = await import('path');
6200
+ const projectDir = path43.default.resolve(opts.projectDir);
6069
6201
  const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
6070
6202
  registerLogStore(
6071
6203
  new LogStore({
@@ -6112,10 +6244,10 @@ function walkFiles(root, match) {
6112
6244
  return;
6113
6245
  }
6114
6246
  for (const entry of entries) {
6115
- const full = path23__default.join(dir, entry.name);
6247
+ const full = path18__default.join(dir, entry.name);
6116
6248
  if (entry.isDirectory()) {
6117
6249
  if (SKIPPED_DIRS.has(entry.name)) continue;
6118
- if (entry.name === "cache" && path23__default.basename(dir) === ".skaile") continue;
6250
+ if (entry.name === "cache" && path18__default.basename(dir) === ".skaile") continue;
6119
6251
  visit(full);
6120
6252
  } else if (entry.isFile() && match(entry.name)) {
6121
6253
  out.push(full);
@@ -6133,14 +6265,14 @@ function applyChanges2(changes) {
6133
6265
  switch (change.type) {
6134
6266
  case "write":
6135
6267
  case "create":
6136
- mkdirSync(path23__default.dirname(change.path), { recursive: true });
6268
+ mkdirSync(path18__default.dirname(change.path), { recursive: true });
6137
6269
  writeFileSync(change.path, change.after, "utf-8");
6138
6270
  break;
6139
6271
  case "delete":
6140
6272
  rmSync(change.path, { force: true });
6141
6273
  break;
6142
6274
  case "move":
6143
- mkdirSync(path23__default.dirname(change.to), { recursive: true });
6275
+ mkdirSync(path18__default.dirname(change.to), { recursive: true });
6144
6276
  writeFileSync(change.to, change.after, "utf-8");
6145
6277
  rmSync(change.from, { force: true });
6146
6278
  break;
@@ -6233,7 +6365,7 @@ function unifiedDiff(before, after, oldLabel, newLabel, context = 3) {
6233
6365
  return `${out.join("\n")}
6234
6366
  `;
6235
6367
  }
6236
- var posix = (p6) => p6.split(path23__default.sep).join("/");
6368
+ var posix = (p6) => p6.split(path18__default.sep).join("/");
6237
6369
  function colorizeDiff(diff) {
6238
6370
  return diff.split("\n").map((line) => {
6239
6371
  if (line.startsWith("+++") || line.startsWith("---")) return S.bold(line);
@@ -6244,7 +6376,7 @@ function colorizeDiff(diff) {
6244
6376
  }).join("\n");
6245
6377
  }
6246
6378
  function renderChange(change, base) {
6247
- const rel = (p6) => posix(path23__default.relative(base, p6) || path23__default.basename(p6));
6379
+ const rel = (p6) => posix(path18__default.relative(base, p6) || path18__default.basename(p6));
6248
6380
  switch (change.type) {
6249
6381
  case "write":
6250
6382
  return unifiedDiff(
@@ -6271,7 +6403,7 @@ ${diff}`;
6271
6403
  }
6272
6404
  }
6273
6405
  function changeLabel(change, base) {
6274
- const rel = (p6) => posix(path23__default.relative(base, p6) || path23__default.basename(p6));
6406
+ const rel = (p6) => posix(path18__default.relative(base, p6) || path18__default.basename(p6));
6275
6407
  switch (change.type) {
6276
6408
  case "write":
6277
6409
  return `modify ${rel(change.path)}`;
@@ -6331,10 +6463,10 @@ function loadAsset(projectDir, id, ref) {
6331
6463
  )
6332
6464
  };
6333
6465
  }
6334
- const manifestPath = path23__default.join(dir, AGENT_MANIFEST_FILE);
6466
+ const manifestPath = path18__default.join(dir, AGENT_MANIFEST_FILE);
6335
6467
  let text;
6336
6468
  try {
6337
- text = fs9__default.readFileSync(manifestPath, "utf-8");
6469
+ text = fs8__default.readFileSync(manifestPath, "utf-8");
6338
6470
  } catch {
6339
6471
  return {
6340
6472
  diagnostic: err(
@@ -6513,12 +6645,12 @@ function findManifestCandidates(rootPath) {
6513
6645
  function walk(dir) {
6514
6646
  let entries;
6515
6647
  try {
6516
- entries = fs9__default.readdirSync(dir, { withFileTypes: true });
6648
+ entries = fs8__default.readdirSync(dir, { withFileTypes: true });
6517
6649
  } catch {
6518
6650
  return;
6519
6651
  }
6520
6652
  for (const entry of entries) {
6521
- const fullPath = path23__default.join(dir, entry.name);
6653
+ const fullPath = path18__default.join(dir, entry.name);
6522
6654
  if (entry.isDirectory()) {
6523
6655
  if (!SKIP_DIRS.has(entry.name)) walk(fullPath);
6524
6656
  } else if (entry.isFile()) {
@@ -6534,30 +6666,11 @@ function findManifestCandidates(rootPath) {
6534
6666
  walk(rootPath);
6535
6667
  return candidates;
6536
6668
  }
6537
- function checkManifestIdentity(kind, parsed) {
6538
- if (parsed === null || typeof parsed !== "object") return null;
6539
- const obj = parsed;
6540
- const identity = kind === "flow" ? obj.id : obj.name;
6541
- if (typeof identity !== "string" || identity.length === 0) return null;
6542
- const publisher = typeof obj.publisher === "string" ? obj.publisher : void 0;
6543
- if (publisher !== void 0) {
6544
- try {
6545
- parseAssetRef(`${kind}:@${publisher}/${identity}`);
6546
- return null;
6547
- } catch (e) {
6548
- return e instanceof Error ? e.message : String(e);
6549
- }
6550
- }
6551
- if (!isValidAssetName(identity)) {
6552
- return `invalid asset ${kind === "flow" ? "id" : "name"} "${identity}" \u2014 ${ASSET_NAME_HINT}`;
6553
- }
6554
- return null;
6555
- }
6556
6669
  function parseManifestCandidate(c, absRoot) {
6557
- const content = fs9__default.readFileSync(c.filePath, "utf-8");
6670
+ const content = fs8__default.readFileSync(c.filePath, "utf-8");
6558
6671
  const res = parseManifestFile(c.filePath, content);
6559
6672
  if (!res.ok) {
6560
- logErr(`${path23__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 parse error: ${res.reason}`);
6673
+ logErr(`${path18__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 parse error: ${res.reason}`);
6561
6674
  return { kind: "error" };
6562
6675
  }
6563
6676
  return {
@@ -6587,34 +6700,32 @@ function checkComposeKinds(parsed, registry) {
6587
6700
  return diagnostics;
6588
6701
  }
6589
6702
  function validateManifestCandidate(c, parsed, body, absRoot, registry, strictConformance) {
6590
- const relPath = path23__default.relative(absRoot, c.filePath);
6703
+ const relPath = path18__default.relative(absRoot, c.filePath);
6591
6704
  let errors = 0;
6592
6705
  let warnings = 0;
6593
- const identityError = checkManifestIdentity(c.kind, parsed);
6594
- if (identityError) {
6595
- logErr(`${relPath} [${c.kind}] \u2014 ${identityError}`);
6706
+ const dirName = path18__default.basename(path18__default.dirname(c.filePath));
6707
+ const checked = checkAsset(
6708
+ c.kind,
6709
+ parsed ?? {},
6710
+ body,
6711
+ dirName,
6712
+ registry
6713
+ );
6714
+ for (const f of checked.errors) {
6715
+ logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
6596
6716
  errors++;
6597
6717
  }
6598
- if (parsed && typeof parsed === "object") {
6599
- const manifest = parsed;
6600
- const version = declaredVersion(manifest);
6601
- if (version !== void 0 && !isValidSemver(version)) {
6602
- logErr(`${relPath} [${c.kind}] \u2014 version "${version}" is not valid semver`);
6718
+ for (const f of checked.advisories) {
6719
+ const line = `${relPath} [${f.tag}] \u2014 ${f.text}`;
6720
+ if (f.conformance && strictConformance) {
6721
+ logErr(line);
6603
6722
  errors++;
6604
- }
6605
- const dirName = path23__default.basename(path23__default.dirname(c.filePath));
6606
- for (const f of checkAssetManifest(c.kind, manifest, body, dirName)) {
6607
- const line = `${relPath} [${f.tag}] \u2014 ${f.text}`;
6608
- if (f.conformance && strictConformance) {
6609
- logErr(line);
6610
- errors++;
6611
- } else {
6612
- logWarn(line);
6613
- warnings++;
6614
- }
6723
+ } else {
6724
+ logWarn(line);
6725
+ warnings++;
6615
6726
  }
6616
6727
  }
6617
- if (c.kind === "agent" && path23__default.basename(c.filePath) === "agent.yaml") {
6728
+ if (c.kind === "agent" && path18__default.basename(c.filePath) === "agent.yaml") {
6618
6729
  for (const d of [
6619
6730
  ...checkComposeKinds(parsed, registry),
6620
6731
  ...composeSlotDiagnostics(parsed),
@@ -6630,23 +6741,11 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
6630
6741
  }
6631
6742
  }
6632
6743
  }
6633
- const provider = registry.getProvider(c.kind);
6634
- if (!provider) {
6635
- logErr(`${relPath} [${c.kind}] \u2014 unknown_asset_kind: kind "${c.kind}" is not registered`);
6636
- return { errors: errors + 1, warnings };
6637
- }
6638
- const result = provider.validateManifest(parsed);
6639
- if (!result.ok) {
6640
- for (const err2 of result.errors) {
6641
- logErr(`${relPath} [${c.kind}] \u2014 ${err2.path ? `${err2.path}: ` : ""}${err2.message}`);
6642
- }
6643
- errors += result.errors.length;
6644
- }
6645
6744
  return { errors, warnings };
6646
6745
  }
6647
6746
  function validateManifests(rootPath, strictConformance) {
6648
- const absRoot = path23__default.resolve(rootPath);
6649
- if (!fs9__default.existsSync(absRoot)) {
6747
+ const absRoot = path18__default.resolve(rootPath);
6748
+ if (!fs8__default.existsSync(absRoot)) {
6650
6749
  logErr(`Path does not exist: ${absRoot}`);
6651
6750
  return { total: 0, errors: 1, warnings: 0 };
6652
6751
  }
@@ -6674,14 +6773,14 @@ function validateManifests(rootPath, strictConformance) {
6674
6773
  const obj = parseResult.parsed;
6675
6774
  const identity = obj && typeof obj === "object" ? obj[c.kind === "flow" ? "id" : "name"] : null;
6676
6775
  if (typeof identity === "string" && identity.length > 0) {
6677
- const dir = path23__default.dirname(c.filePath);
6776
+ const dir = path18__default.dirname(c.filePath);
6678
6777
  const key = `${c.kind}:${identity}`;
6679
6778
  const first = seenIdentity.get(key);
6680
6779
  if (first === void 0) {
6681
6780
  seenIdentity.set(key, dir);
6682
6781
  } else if (first !== dir) {
6683
6782
  logErr(
6684
- `${path23__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 ${key} is also defined in ${path23__default.relative(absRoot, first) || "."}; two directories cannot share a kind and name (\`skaile library index\` keeps only the first).`
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).`
6685
6784
  );
6686
6785
  errors++;
6687
6786
  }
@@ -6694,12 +6793,12 @@ function findWorkspaceManifests(rootPath) {
6694
6793
  function walk(dir) {
6695
6794
  let entries;
6696
6795
  try {
6697
- entries = fs9__default.readdirSync(dir, { withFileTypes: true });
6796
+ entries = fs8__default.readdirSync(dir, { withFileTypes: true });
6698
6797
  } catch {
6699
6798
  return;
6700
6799
  }
6701
6800
  for (const entry of entries) {
6702
- const full = path23__default.join(dir, entry.name);
6801
+ const full = path18__default.join(dir, entry.name);
6703
6802
  if (entry.isDirectory()) {
6704
6803
  if (!SKIP_DIRS.has(entry.name)) walk(full);
6705
6804
  } else if (entry.isFile() && /(^|\.)skaile\.yaml$/.test(entry.name)) {
@@ -6762,14 +6861,14 @@ function validateWorkspaceAssets(parsed, relPath) {
6762
6861
  return errors;
6763
6862
  }
6764
6863
  function validateWorkspaceManifests(rootPath) {
6765
- const absRoot = path23__default.resolve(rootPath);
6864
+ const absRoot = path18__default.resolve(rootPath);
6766
6865
  const files = findWorkspaceManifests(absRoot);
6767
6866
  let errors = 0;
6768
6867
  for (const file of files) {
6769
- const relPath = path23__default.relative(absRoot, file);
6868
+ const relPath = path18__default.relative(absRoot, file);
6770
6869
  let parsed;
6771
6870
  try {
6772
- parsed = parse(fs9__default.readFileSync(file, "utf-8")) ?? {};
6871
+ parsed = parse(fs8__default.readFileSync(file, "utf-8")) ?? {};
6773
6872
  } catch (e) {
6774
6873
  logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
6775
6874
  errors++;
@@ -6777,7 +6876,7 @@ function validateWorkspaceManifests(rootPath) {
6777
6876
  }
6778
6877
  errors += validateWorkspaceRefs(collectWorkspaceRefFields(parsed), relPath);
6779
6878
  errors += validateWorkspaceAssets(parsed, relPath);
6780
- for (const d of checkAgentInstances(path23__default.dirname(file), parsed)) {
6879
+ for (const d of checkAgentInstances(path18__default.dirname(file), parsed)) {
6781
6880
  const line = `${relPath} [agents] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`;
6782
6881
  if (d.severity === "error") {
6783
6882
  logErr(line);
@@ -6790,7 +6889,7 @@ function validateWorkspaceManifests(rootPath) {
6790
6889
  return { total: files.length, errors };
6791
6890
  }
6792
6891
  function validatePublishManifestRoots(rootPath) {
6793
- const absRoot = path23__default.resolve(rootPath);
6892
+ const absRoot = path18__default.resolve(rootPath);
6794
6893
  const manifest = loadSkPublishManifest(absRoot);
6795
6894
  if (!manifest) return 0;
6796
6895
  const missing = missingRootAssets(absRoot, manifest);
@@ -6802,7 +6901,7 @@ function validatePublishManifestRoots(rootPath) {
6802
6901
  return missing.length;
6803
6902
  }
6804
6903
  function validatePublishManifestRequires(rootPath) {
6805
- const problems = manifestRequiresProblems(path23__default.resolve(rootPath));
6904
+ const problems = manifestRequiresProblems(path18__default.resolve(rootPath));
6806
6905
  for (const p6 of problems) {
6807
6906
  logErr(
6808
6907
  `${SKAILE_MANIFEST_FILENAME} [assets] \u2014 ${p6.asset}: ${p6.message}. Use the \`kind:@<publisher>/name[#version]\` form.`
@@ -6810,16 +6909,21 @@ function validatePublishManifestRequires(rootPath) {
6810
6909
  }
6811
6910
  return problems.length;
6812
6911
  }
6912
+ function validatePublishManifestPublisherSlugs(rootPath) {
6913
+ const problems = manifestPublisherProblems(path18__default.resolve(rootPath));
6914
+ for (const message of problems) logErr(message);
6915
+ return problems.length;
6916
+ }
6813
6917
  function validatePublishManifestVersions(rootPath) {
6814
- const absRoot = path23__default.resolve(rootPath);
6918
+ const absRoot = path18__default.resolve(rootPath);
6815
6919
  const manifest = loadSkPublishManifest(absRoot);
6816
6920
  if (!manifest || manifest.source) return 0;
6817
6921
  let warnings = 0;
6818
6922
  for (const a of manifest.assets ?? []) {
6819
6923
  if (!a.root || a.source || !a.version) continue;
6820
- const file = findAssetManifestFile(path23__default.join(absRoot, a.root), a.kind, a.name);
6924
+ const file = findAssetManifestFile(path18__default.join(absRoot, a.root), a.kind, a.name);
6821
6925
  if (!file) continue;
6822
- const res = parseManifestFile(file, fs9__default.readFileSync(file, "utf-8"));
6926
+ const res = parseManifestFile(file, fs8__default.readFileSync(file, "utf-8"));
6823
6927
  if (!res.ok) continue;
6824
6928
  const fileVersion = declaredVersion(res.data);
6825
6929
  if (fileVersion === void 0 || fileVersion === a.version) continue;
@@ -6827,7 +6931,7 @@ function validatePublishManifestVersions(rootPath) {
6827
6931
  manifestVersionMismatchMessage(
6828
6932
  assetEntryRef(a, manifest),
6829
6933
  a.version,
6830
- toPosix(path23__default.relative(absRoot, file)),
6934
+ toPosix(path18__default.relative(absRoot, file)),
6831
6935
  fileVersion
6832
6936
  )
6833
6937
  );
@@ -6836,7 +6940,7 @@ function validatePublishManifestVersions(rootPath) {
6836
6940
  return warnings;
6837
6941
  }
6838
6942
  function validatePublishManifestPublishers(rootPath) {
6839
- const absRoot = path23__default.resolve(rootPath);
6943
+ const absRoot = path18__default.resolve(rootPath);
6840
6944
  const manifest = loadSkPublishManifest(absRoot);
6841
6945
  if (!manifest || manifest.source) return 0;
6842
6946
  const bare = (p6) => p6.trim().replace(/^@/, "");
@@ -6844,15 +6948,15 @@ function validatePublishManifestPublishers(rootPath) {
6844
6948
  for (const a of manifest.assets ?? []) {
6845
6949
  const resolved = a.publisher ?? manifest.publisher;
6846
6950
  if (!a.root || a.source || !resolved) continue;
6847
- const file = findAssetManifestFile(path23__default.join(absRoot, a.root), a.kind, a.name);
6951
+ const file = findAssetManifestFile(path18__default.join(absRoot, a.root), a.kind, a.name);
6848
6952
  if (!file) continue;
6849
- const res = parseManifestFile(file, fs9__default.readFileSync(file, "utf-8"));
6953
+ const res = parseManifestFile(file, fs8__default.readFileSync(file, "utf-8"));
6850
6954
  if (!res.ok) continue;
6851
6955
  const meta = res.data.metadata;
6852
6956
  const declared = meta !== null && typeof meta === "object" ? meta.publisher : null;
6853
6957
  if (typeof declared !== "string" || bare(declared) === bare(resolved)) continue;
6854
6958
  logWarn(
6855
- `${toPosix(path23__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}.`
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}.`
6856
6960
  );
6857
6961
  warnings++;
6858
6962
  }
@@ -6860,7 +6964,7 @@ function validatePublishManifestPublishers(rootPath) {
6860
6964
  }
6861
6965
  var EXCLUDED_PATHS = ["skaileup-shared/", "external/", "docs/"];
6862
6966
  function toPosix(p6) {
6863
- return p6.split(path23__default.sep).join("/");
6967
+ return p6.split(path18__default.sep).join("/");
6864
6968
  }
6865
6969
  function isExcludedPath(relPath) {
6866
6970
  const rel = toPosix(relPath);
@@ -6870,20 +6974,23 @@ var VERSIONED_KINDS = {
6870
6974
  skill: true,
6871
6975
  agent: true,
6872
6976
  flow: true,
6873
- prompt: true
6977
+ prompt: true,
6978
+ preset: true,
6979
+ contract: true
6874
6980
  };
6875
6981
  function readAssetVersion(c) {
6876
6982
  const kind = c.kind;
6877
- const fileName = path23__default.basename(c.filePath);
6878
- const dirName = path23__default.basename(path23__default.dirname(c.filePath));
6879
- const content = fs9__default.readFileSync(c.filePath, "utf-8");
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");
6880
6986
  if (c.filePath.endsWith(".md")) {
6881
- const fm = parseSkillFrontmatter(content);
6987
+ const res = parseManifestFile(c.filePath, content);
6988
+ const data = res.ok ? res.data : {};
6882
6989
  const stem = fileName.replace(/\.prompt\.md$/, "");
6883
6990
  return {
6884
6991
  kind,
6885
- name: fm?.name ?? (kind === "prompt" ? stem : dirName),
6886
- version: fm?.metadata?.version ?? "",
6992
+ name: typeof data.name === "string" ? data.name : kind === "prompt" ? stem : dirName,
6993
+ version: declaredVersion(data) ?? "",
6887
6994
  filePath: c.filePath
6888
6995
  };
6889
6996
  }
@@ -6908,26 +7015,26 @@ function readAssetVersion(c) {
6908
7015
  };
6909
7016
  }
6910
7017
  function collectAssetVersions(root) {
6911
- if (!fs9__default.existsSync(root)) return [];
7018
+ if (!fs8__default.existsSync(root)) return [];
6912
7019
  const assets = [];
6913
7020
  for (const c of findManifestCandidates(root)) {
6914
7021
  if (!VERSIONED_KINDS[c.kind]) continue;
6915
7022
  if (c.filePath.endsWith(".flow.json")) continue;
6916
- if (isExcludedPath(path23__default.relative(root, c.filePath))) continue;
7023
+ if (isExcludedPath(path18__default.relative(root, c.filePath))) continue;
6917
7024
  assets.push(readAssetVersion(c));
6918
7025
  }
6919
7026
  return assets;
6920
7027
  }
6921
7028
  function assetLocation(a, root) {
6922
- return toPosix(path23__default.relative(root, a.filePath));
7029
+ return toPosix(path18__default.relative(root, a.filePath));
6923
7030
  }
6924
7031
  function findChangelogUnit(assetRelPath, root) {
6925
- let dir = path23__default.posix.dirname(toPosix(assetRelPath));
7032
+ let dir = path18__default.posix.dirname(toPosix(assetRelPath));
6926
7033
  for (; ; ) {
6927
7034
  const candidate = dir === "." ? "CHANGELOG.md" : `${dir}/CHANGELOG.md`;
6928
- if (fs9__default.existsSync(path23__default.join(root, candidate))) return candidate;
7035
+ if (fs8__default.existsSync(path18__default.join(root, candidate))) return candidate;
6929
7036
  if (dir === ".") return null;
6930
- dir = path23__default.posix.dirname(dir);
7037
+ dir = path18__default.posix.dirname(dir);
6931
7038
  }
6932
7039
  }
6933
7040
  function checkChangelogUnits(modifiedFiles, root) {
@@ -6945,9 +7052,6 @@ function checkChangelogUnits(modifiedFiles, root) {
6945
7052
  const stale = [...units].filter((u) => !modified.has(u));
6946
7053
  return { updated, stale, orphans };
6947
7054
  }
6948
- function isValidSemver(v) {
6949
- return SEMVER_RE.test(v);
6950
- }
6951
7055
  function extractVersionFromContent(filePath, content) {
6952
7056
  if (filePath.endsWith(".yaml")) {
6953
7057
  const parsed2 = parse(content);
@@ -6962,13 +7066,15 @@ function checkAssetVersions(assets, root) {
6962
7066
  let errors = 0;
6963
7067
  const warnings = 0;
6964
7068
  for (const a of assets) {
7069
+ const location = assetLocation(a, root);
6965
7070
  if (!a.version) {
6966
- logErr(`${a.kind}:${a.name} (${assetLocation(a, root)}) \u2014 missing version`);
7071
+ logErr(`${a.kind}:${a.name} (${location}) \u2014 missing version`);
6967
7072
  errors++;
6968
- } else if (!isValidSemver(a.version)) {
6969
- logErr(
6970
- `${a.kind}:${a.name} (${assetLocation(a, root)}) \u2014 version "${a.version}" is not valid semver`
6971
- );
7073
+ continue;
7074
+ }
7075
+ const invalid = invalidSemverText(a.version);
7076
+ if (invalid) {
7077
+ logErr(`${a.kind}:${a.name} (${location}) \u2014 ${invalid}`);
6972
7078
  errors++;
6973
7079
  }
6974
7080
  }
@@ -6978,7 +7084,7 @@ function checkVersionBumps(assets, root) {
6978
7084
  let warnings = 0;
6979
7085
  for (const a of assets) {
6980
7086
  if (!a.version) continue;
6981
- const relPath = toPosix(path23__default.relative(root, a.filePath));
7087
+ const relPath = toPosix(path18__default.relative(root, a.filePath));
6982
7088
  try {
6983
7089
  const headContent = execFileSync("git", ["show", `HEAD:./${relPath}`], {
6984
7090
  cwd: root,
@@ -7011,7 +7117,7 @@ function checkFlowVersionPins(assets, root) {
7011
7117
  pins = flowSkillVersionPins(loadFlow(f.filePath));
7012
7118
  } catch (err2) {
7013
7119
  logWarn(
7014
- `flow:${f.name} (${path23__default.relative(root, f.filePath)}) \u2014 could not be read: ${err2 instanceof Error ? err2.message : err2}`
7120
+ `flow:${f.name} (${path18__default.relative(root, f.filePath)}) \u2014 could not be read: ${err2 instanceof Error ? err2.message : err2}`
7015
7121
  );
7016
7122
  warnings++;
7017
7123
  continue;
@@ -7029,16 +7135,16 @@ function checkFlowVersionPins(assets, root) {
7029
7135
  }
7030
7136
  function resolveCheckRoot(pathArg) {
7031
7137
  if (pathArg) {
7032
- const abs = path23__default.resolve(pathArg);
7033
- if (!fs9__default.existsSync(abs)) {
7138
+ const abs = path18__default.resolve(pathArg);
7139
+ if (!fs8__default.existsSync(abs)) {
7034
7140
  logErr(`Path does not exist: ${abs}`);
7035
7141
  return null;
7036
7142
  }
7037
7143
  return abs;
7038
7144
  }
7039
- for (let dir = process.cwd(); ; dir = path23__default.dirname(dir)) {
7040
- if (fs9__default.existsSync(path23__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
7041
- if (path23__default.dirname(dir) === dir) return AI_RESOURCES;
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;
7042
7148
  }
7043
7149
  }
7044
7150
  function changedFiles(root, ref) {
@@ -7073,7 +7179,7 @@ function runVersionsCheck(pathArg, opts) {
7073
7179
  process.exit(1);
7074
7180
  return;
7075
7181
  }
7076
- const changedAbs = new Set(changed.map((f) => path23__default.resolve(root, f)));
7182
+ const changedAbs = new Set(changed.map((f) => path18__default.resolve(root, f)));
7077
7183
  assets = assets.filter((a) => changedAbs.has(a.filePath));
7078
7184
  }
7079
7185
  logInfo(`Checking versions in ${root}`);
@@ -7105,8 +7211,8 @@ function makeValidateCommand() {
7105
7211
  cmd.argument("[path]", "Path to asset repo or directory to validate", ".").option(
7106
7212
  "--strict-conformance",
7107
7213
  "Treat Agent Skills (agentskills.io) standard findings as errors"
7108
- ).action((targetPath, opts) => {
7109
- const absPath = path23__default.resolve(targetPath);
7214
+ ).action(async (targetPath, opts) => {
7215
+ const absPath = path18__default.resolve(targetPath);
7110
7216
  logInfo(`Validating manifests in ${absPath}`);
7111
7217
  const { total, errors, warnings } = validateManifests(
7112
7218
  absPath,
@@ -7114,15 +7220,19 @@ function makeValidateCommand() {
7114
7220
  );
7115
7221
  const ws = validateWorkspaceManifests(absPath);
7116
7222
  const rootErrors = validatePublishManifestRoots(absPath);
7223
+ const slugErrors = validatePublishManifestPublisherSlugs(absPath);
7117
7224
  const requiresErrors = validatePublishManifestRequires(absPath);
7118
7225
  const versionWarnings = validatePublishManifestVersions(absPath);
7119
7226
  const publisherWarnings = validatePublishManifestPublishers(absPath);
7120
- const totalErrors = errors + ws.errors + rootErrors + requiresErrors;
7227
+ const dependencyProblems = await unresolvedManifestDependencies(absPath);
7228
+ for (const w of dependencyProblems) logWarn(w);
7229
+ const dependencyWarnings = dependencyProblems.length;
7230
+ const totalErrors = errors + ws.errors + rootErrors + slugErrors + requiresErrors;
7121
7231
  console.log();
7122
7232
  warnIgnoredDomainFiles(absPath);
7123
7233
  warnLegacyBundleFiles(absPath);
7124
7234
  logInfo(`Scanned ${total} asset manifest(s) and ${ws.total} skaile.yaml file(s)`);
7125
- const totalWarnings = warnings + versionWarnings + publisherWarnings;
7235
+ const totalWarnings = warnings + versionWarnings + publisherWarnings + dependencyWarnings;
7126
7236
  if (totalWarnings > 0) logWarn(`${totalWarnings} warning(s)`);
7127
7237
  if (totalErrors === 0) {
7128
7238
  logOk("All manifests valid");
@@ -7192,7 +7302,7 @@ function itemFromRef(raw, defaultKind, ctx) {
7192
7302
  return { kind: prefixed[1], ref: value };
7193
7303
  }
7194
7304
  if (PATH_LIKE.test(value)) return { kind: defaultKind, ref: value };
7195
- if (defaultKind === "skill" && !value.includes("/") && existsSync(path23__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
7305
+ if (defaultKind === "skill" && !value.includes("/") && existsSync(path18__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
7196
7306
  return { kind: "skill", ref: `./skills/${value}` };
7197
7307
  }
7198
7308
  return { kind: defaultKind, ref: `${defaultKind}:${value}` };
@@ -7328,7 +7438,7 @@ function migrateAgentYaml(source, options) {
7328
7438
  manual.push("metadata.soul: not a string; left unchanged");
7329
7439
  continue;
7330
7440
  }
7331
- if (path23__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
7441
+ if (path18__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
7332
7442
  notes.push("metadata.soul \u2192 dropped (SOUL.md is a convention file)");
7333
7443
  } else {
7334
7444
  derived.push({ kind: "persona", ref: soul });
@@ -7562,7 +7672,7 @@ function migrateSubagents(skaileYamlPath, source) {
7562
7672
  if (!isMap(agentNode)) return void 0;
7563
7673
  const subNode = agentNode.get("subagents", true);
7564
7674
  if (!isMap(subNode)) return void 0;
7565
- const dir = path23__default.dirname(skaileYamlPath);
7675
+ const dir = path18__default.dirname(skaileYamlPath);
7566
7676
  const notes = [];
7567
7677
  const manual = [];
7568
7678
  const changes = [];
@@ -7580,10 +7690,10 @@ function migrateSubagents(skaileYamlPath, source) {
7580
7690
  continue;
7581
7691
  }
7582
7692
  const id = instanceId(name);
7583
- const assetDir = path23__default.join(dir, ".skaile", "agents", id);
7693
+ const assetDir = path18__default.join(dir, ".skaile", "agents", id);
7584
7694
  if (takenIds.has(id) || existsSync(assetDir)) {
7585
7695
  manual.push(
7586
- `agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path23__default.relative(dir, assetDir)} already exists`}; left in place`
7696
+ `agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path18__default.relative(dir, assetDir)} already exists`}; left in place`
7587
7697
  );
7588
7698
  continue;
7589
7699
  }
@@ -7607,13 +7717,13 @@ function migrateSubagents(skaileYamlPath, source) {
7607
7717
  manifest.tools = { ...allowed ? { allowed } : {}, ...denied ? { denied } : {} };
7608
7718
  }
7609
7719
  const text = stringify(manifest, { lineWidth: 0 });
7610
- const manifestPath = path23__default.join(assetDir, "agent.yaml");
7720
+ const manifestPath = path18__default.join(assetDir, "agent.yaml");
7611
7721
  changes.push({ type: "create", path: manifestPath, after: text });
7612
7722
  assetManifests.push({ file: manifestPath, text });
7613
7723
  if (typeof spec.prompt === "string" && spec.prompt.trim() !== "") {
7614
7724
  changes.push({
7615
7725
  type: "create",
7616
- path: path23__default.join(assetDir, "SOUL.md"),
7726
+ path: path18__default.join(assetDir, "SOUL.md"),
7617
7727
  after: `${spec.prompt.replace(/\s+$/, "")}
7618
7728
  `
7619
7729
  });
@@ -7672,7 +7782,7 @@ function validateMigratedAgent(text, registry) {
7672
7782
  function collectAgentFiles(paths) {
7673
7783
  const files = /* @__PURE__ */ new Set();
7674
7784
  for (const input of paths) {
7675
- const abs = path23__default.resolve(input);
7785
+ const abs = path18__default.resolve(input);
7676
7786
  if (!existsSync(abs)) continue;
7677
7787
  if (statSync(abs).isDirectory()) {
7678
7788
  for (const f of walkFiles(abs, (b) => b === "agent.yaml" || b === "skaile.yaml"))
@@ -7689,7 +7799,7 @@ function planAgentMigration(options) {
7689
7799
  const reports = [];
7690
7800
  for (const file of collectAgentFiles(options.paths)) {
7691
7801
  const source = readText(file);
7692
- const base = path23__default.basename(file);
7802
+ const base = path18__default.basename(file);
7693
7803
  if (base === "skaile.yaml") {
7694
7804
  const result = migrateSubagents(file, source);
7695
7805
  if (!result) continue;
@@ -7697,7 +7807,7 @@ function planAgentMigration(options) {
7697
7807
  for (const asset of result.assetManifests) {
7698
7808
  const v = validateMigratedAgent(asset.text, options.registry);
7699
7809
  validation2.errors.push(
7700
- ...v.errors.map((e) => `${path23__default.basename(path23__default.dirname(asset.file))}: ${e}`)
7810
+ ...v.errors.map((e) => `${path18__default.basename(path18__default.dirname(asset.file))}: ${e}`)
7701
7811
  );
7702
7812
  validation2.warnings.push(...v.warnings);
7703
7813
  }
@@ -7725,7 +7835,7 @@ function planAgentMigration(options) {
7725
7835
  });
7726
7836
  continue;
7727
7837
  }
7728
- migration = migrateAgentYaml(source, { agentDir: path23__default.dirname(file), knownKinds });
7838
+ migration = migrateAgentYaml(source, { agentDir: path18__default.dirname(file), knownKinds });
7729
7839
  } catch (error) {
7730
7840
  reports.push({
7731
7841
  file,
@@ -7753,8 +7863,9 @@ function planAgentMigration(options) {
7753
7863
  return { changes, reports };
7754
7864
  }
7755
7865
  var DEFAULT_PUBLISHER = "skaile-ai";
7866
+ var PRESET_DEFAULT_VERSION = "1.0.0";
7756
7867
  var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
7757
- var posix2 = (p6) => p6.split(path23__default.sep).join("/");
7868
+ var posix2 = (p6) => p6.split(path18__default.sep).join("/");
7758
7869
  var MOVED_KINDS = { persona: "PERSONA.md", ruleset: "RULESET.md" };
7759
7870
  var KIND_MANIFEST_FILES = /* @__PURE__ */ new Set(["PERSONA.md", "RULESET.md", "SKILL.md"]);
7760
7871
  function readFrontmatterType(text) {
@@ -7785,14 +7896,14 @@ function planMarkdownMoves(root, knownKinds, manual, unknownTypes) {
7785
7896
  if (!text.startsWith("---")) continue;
7786
7897
  const found = readFrontmatterType(text);
7787
7898
  if (!found) continue;
7788
- const base = path23__default.basename(file);
7789
- const inAgentParts = file.split(path23__default.sep).includes("_agent-parts");
7899
+ const base = path18__default.basename(file);
7900
+ const inAgentParts = file.split(path18__default.sep).includes("_agent-parts");
7790
7901
  const targetName = MOVED_KINDS[found.type];
7791
7902
  if (targetName !== void 0 && !KIND_MANIFEST_FILES.has(base)) {
7792
- const to = path23__default.join(path23__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
7903
+ const to = path18__default.join(path18__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
7793
7904
  if (existsSync(to) || targets.has(to)) {
7794
7905
  manual.push(
7795
- `${posix2(path23__default.relative(root, file))}: ${posix2(path23__default.relative(root, to))} already exists; not moved`
7906
+ `${posix2(path18__default.relative(root, file))}: ${posix2(path18__default.relative(root, to))} already exists; not moved`
7796
7907
  );
7797
7908
  continue;
7798
7909
  }
@@ -7813,13 +7924,13 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
7813
7924
  const changes = [];
7814
7925
  for (const file of walkFiles(root, (b) => b === "agent.yaml")) {
7815
7926
  const source = readText(file);
7816
- const agentDir = path23__default.dirname(file);
7927
+ const agentDir = path18__default.dirname(file);
7817
7928
  let hits = 0;
7818
7929
  const refRewrite = (_kind, ref) => {
7819
- const moved = byOldPath.get(path23__default.resolve(agentDir, ref));
7930
+ const moved = byOldPath.get(path18__default.resolve(agentDir, ref));
7820
7931
  if (moved === void 0) return ref;
7821
7932
  hits++;
7822
- const rel = posix2(path23__default.relative(agentDir, moved));
7933
+ const rel = posix2(path18__default.relative(agentDir, moved));
7823
7934
  return rel.startsWith(".") ? rel : `./${rel}`;
7824
7935
  };
7825
7936
  let output;
@@ -7836,7 +7947,7 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
7836
7947
  if (hits === 0 || output === source) continue;
7837
7948
  changes.push({ type: "write", path: file, before: source, after: output });
7838
7949
  notes.push(
7839
- `${posix2(path23__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
7950
+ `${posix2(path18__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
7840
7951
  );
7841
7952
  }
7842
7953
  return changes;
@@ -7847,12 +7958,12 @@ function presetItemRef(dep, publisher) {
7847
7958
  const [, kind, rest] = match;
7848
7959
  return rest.startsWith("@") ? dep.trim() : `${kind}:@${publisher}/${rest}`;
7849
7960
  }
7850
- function presetText(name, description, refs, publisher) {
7961
+ function presetText(name, description, refs, publisher, version) {
7851
7962
  return stringify(
7852
7963
  {
7853
7964
  publisher,
7854
7965
  name,
7855
- version: "1.0.0",
7966
+ version,
7856
7967
  description: description && description.trim() !== "" ? description : `Preset ${name}`,
7857
7968
  items: refs.map((ref) => ({ ref }))
7858
7969
  },
@@ -7861,14 +7972,14 @@ function presetText(name, description, refs, publisher) {
7861
7972
  }
7862
7973
  function skillDirs(dir) {
7863
7974
  try {
7864
- return readdirSync(path23__default.join(dir, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync(path23__default.join(dir, "skills", e.name, "SKILL.md"))).map((e) => e.name).sort();
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();
7865
7976
  } catch {
7866
7977
  return [];
7867
7978
  }
7868
7979
  }
7869
7980
  function repoPublisher(root) {
7870
7981
  for (const name of ["skaile.manifest.yaml", "skaile.yaml"]) {
7871
- const file = path23__default.join(root, name);
7982
+ const file = path18__default.join(root, name);
7872
7983
  if (!existsSync(file)) continue;
7873
7984
  try {
7874
7985
  const parsed = parse(readText(file));
@@ -7884,9 +7995,9 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
7884
7995
  const changes = [];
7885
7996
  const presets = [];
7886
7997
  const handled = /* @__PURE__ */ new Set();
7887
- const rel = (p6) => posix2(path23__default.relative(root, p6));
7998
+ const rel = (p6) => posix2(path18__default.relative(root, p6));
7888
7999
  const convert = (name, bundleFile, dir) => {
7889
- const target = path23__default.join(dir, `${name}.preset.yaml`);
8000
+ const target = path18__default.join(dir, `${name}.preset.yaml`);
7890
8001
  if (existsSync(target)) {
7891
8002
  manual.push(`${rel(target)} already exists; bundle ${name} not converted`);
7892
8003
  return;
@@ -7894,11 +8005,16 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
7894
8005
  let description;
7895
8006
  let refs = [];
7896
8007
  let before;
8008
+ let version = PRESET_DEFAULT_VERSION;
8009
+ let versionNote;
7897
8010
  if (bundleFile && existsSync(bundleFile)) {
7898
8011
  before = readText(bundleFile);
7899
8012
  const parsed = parse(before);
7900
8013
  if (isRecord(parsed)) {
7901
8014
  if (typeof parsed.description === "string") description = parsed.description;
8015
+ const declared = typeof parsed.version === "string" || typeof parsed.version === "number" ? String(parsed.version) : void 0;
8016
+ if (declared !== void 0 && SEMVER_RE.test(declared)) version = declared;
8017
+ else if (declared !== void 0) versionNote = `version ${declared} \u2192 ${version}`;
7902
8018
  const deps = Array.isArray(parsed.dependencies) ? parsed.dependencies : [];
7903
8019
  refs = deps.filter((d) => typeof d === "string").map((d) => presetItemRef(d, publisher));
7904
8020
  if (refs.length !== deps.length) {
@@ -7912,11 +8028,11 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
7912
8028
  }
7913
8029
  if (refs.length === 0) {
7914
8030
  manual.push(
7915
- `bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path23__default.join(dir, "skills"))}`}; no preset generated`
8031
+ `bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path18__default.join(dir, "skills"))}`}; no preset generated`
7916
8032
  );
7917
8033
  return;
7918
8034
  }
7919
- const after = presetText(name, description, refs, publisher);
8035
+ const after = presetText(name, description, refs, publisher, version);
7920
8036
  if (before !== void 0 && bundleFile) {
7921
8037
  changes.push({ type: "move", from: bundleFile, to: target, before, after });
7922
8038
  handled.add(bundleFile);
@@ -7928,24 +8044,26 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
7928
8044
  file: target,
7929
8045
  ...bundleFile && before !== void 0 ? { bundleFile } : {}
7930
8046
  });
7931
- notes.push(`bundle ${name} \u2192 ${rel(target)} (${refs.length} items)`);
8047
+ notes.push(
8048
+ `bundle ${name} \u2192 ${rel(target)} (${refs.length} items${versionNote ? `, ${versionNote}` : ""})`
8049
+ );
7932
8050
  };
7933
8051
  for (const { file, raw } of skaileYamls) {
7934
8052
  const assets = Array.isArray(raw.assets) ? raw.assets : [];
7935
8053
  for (const entry of assets) {
7936
8054
  if (!isRecord(entry) || entry.kind !== "bundle" || typeof entry.name !== "string") continue;
7937
- const baseDir = path23__default.dirname(file);
7938
- const entryRoot = typeof entry.root === "string" ? path23__default.join(baseDir, entry.root) : baseDir;
8055
+ const baseDir = path18__default.dirname(file);
8056
+ const entryRoot = typeof entry.root === "string" ? path18__default.join(baseDir, entry.root) : baseDir;
7939
8057
  const files = Array.isArray(entry.files) ? entry.files : [];
7940
8058
  const bundleName = files.find(
7941
8059
  (f) => typeof f === "string" && f.endsWith(".bundle.yaml")
7942
8060
  );
7943
- convert(entry.name, bundleName ? path23__default.join(entryRoot, bundleName) : void 0, entryRoot);
8061
+ convert(entry.name, bundleName ? path18__default.join(entryRoot, bundleName) : void 0, entryRoot);
7944
8062
  }
7945
8063
  }
7946
8064
  for (const bundleFile of walkFiles(root, (b) => b.endsWith(".bundle.yaml"))) {
7947
8065
  if (handled.has(bundleFile)) continue;
7948
- const base = path23__default.basename(bundleFile);
8066
+ const base = path18__default.basename(bundleFile);
7949
8067
  let name = base.replace(/\.bundle\.yaml$/, "");
7950
8068
  try {
7951
8069
  const parsed = parse(readText(bundleFile));
@@ -7954,7 +8072,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
7954
8072
  } catch {
7955
8073
  }
7956
8074
  if (presets.some((p6) => p6.bundleFile === bundleFile)) continue;
7957
- convert(name, bundleFile, path23__default.dirname(bundleFile));
8075
+ convert(name, bundleFile, path18__default.dirname(bundleFile));
7958
8076
  }
7959
8077
  return changes;
7960
8078
  }
@@ -7964,8 +8082,8 @@ function planSkaileYaml(root, file, source, notes, manual) {
7964
8082
  if (doc.errors.length > 0 || !isMap(doc.contents)) return [];
7965
8083
  const map = doc.contents;
7966
8084
  const raw = doc.toJS();
7967
- const dir = path23__default.dirname(file);
7968
- const rel = (p6) => posix2(path23__default.relative(root, p6));
8085
+ const dir = path18__default.dirname(file);
8086
+ const rel = (p6) => posix2(path18__default.relative(root, p6));
7969
8087
  const changes = [];
7970
8088
  let changed = false;
7971
8089
  const deps = map.get("dependencies", true);
@@ -7982,7 +8100,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
7982
8100
  const hasPublication = PUBLICATION_KEYS.some((k) => raw[k] !== void 0);
7983
8101
  let remove = false;
7984
8102
  if (hasPublication) {
7985
- const manifestPath = path23__default.join(dir, "skaile.manifest.yaml");
8103
+ const manifestPath = path18__default.join(dir, "skaile.manifest.yaml");
7986
8104
  if (existsSync(manifestPath)) {
7987
8105
  manual.push(
7988
8106
  `${rel(file)}: publisher/version/assets left in place \u2014 ${rel(manifestPath)} already exists; merge by hand`
@@ -8039,7 +8157,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
8039
8157
  return changes;
8040
8158
  }
8041
8159
  function planAssetMigration(options) {
8042
- const root = path23__default.resolve(options.root);
8160
+ const root = path18__default.resolve(options.root);
8043
8161
  const knownKinds = new Set(options.registry.getAllKinds());
8044
8162
  const notes = [];
8045
8163
  const manual = [];
@@ -8047,7 +8165,7 @@ function planAssetMigration(options) {
8047
8165
  const { moves, changes: moveChanges } = planMarkdownMoves(root, knownKinds, manual, unknownTypes);
8048
8166
  for (const move of moves) {
8049
8167
  notes.push(
8050
- `${posix2(path23__default.relative(root, move.from))} \u2192 ${posix2(path23__default.relative(root, move.to))} (${move.kind})`
8168
+ `${posix2(path18__default.relative(root, move.from))} \u2192 ${posix2(path18__default.relative(root, move.to))} (${move.kind})`
8051
8169
  );
8052
8170
  }
8053
8171
  const agentChanges = planAgentRefRewrites(root, moves, knownKinds, notes);
@@ -8059,7 +8177,7 @@ function planAssetMigration(options) {
8059
8177
  const raw = parse(source);
8060
8178
  if (isRecord(raw)) skaileYamls.push({ file, source, raw });
8061
8179
  } catch {
8062
- manual.push(`${posix2(path23__default.relative(root, file))}: invalid YAML; skipped`);
8180
+ manual.push(`${posix2(path18__default.relative(root, file))}: invalid YAML; skipped`);
8063
8181
  }
8064
8182
  }
8065
8183
  const publisher = repoPublisher(root);
@@ -8213,7 +8331,7 @@ function workspaceConfigFiles(dir) {
8213
8331
  } catch {
8214
8332
  return [];
8215
8333
  }
8216
- return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path23__default.join(dir, name));
8334
+ return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path18__default.join(dir, name));
8217
8335
  }
8218
8336
  function readAgentConfigBlock(raw) {
8219
8337
  const key = AGENT_CONFIG_KEYS.find((candidate) => raw[candidate] !== void 0);
@@ -8225,7 +8343,7 @@ function readAgentConfigBlock(raw) {
8225
8343
  return flat ? { key, profiles: { default: profiles }, flat } : { key, profiles, flat };
8226
8344
  }
8227
8345
  function planProviderMigration(options) {
8228
- const projectDir = path23__default.resolve(options.projectDir);
8346
+ const projectDir = path18__default.resolve(options.projectDir);
8229
8347
  const registryPath = options.workspace ? workspaceProviderRegistryPath(projectDir) : userProviderRegistryPath();
8230
8348
  const plan = {
8231
8349
  registryPath,
@@ -8241,7 +8359,7 @@ function planProviderMigration(options) {
8241
8359
  raw = parseDocument(readFileSync(file, "utf-8")).toJS() ?? {};
8242
8360
  } catch (error) {
8243
8361
  plan.warnings.push(
8244
- `${path23__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
8362
+ `${path18__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
8245
8363
  );
8246
8364
  continue;
8247
8365
  }
@@ -8290,7 +8408,7 @@ function planProviderMigration(options) {
8290
8408
  });
8291
8409
  if (!model) {
8292
8410
  plan.warnings.push(
8293
- `${path23__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
8411
+ `${path18__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
8294
8412
  );
8295
8413
  }
8296
8414
  touched = true;
@@ -8357,7 +8475,7 @@ function printPlan(plan) {
8357
8475
  for (const entry of plan.entries) {
8358
8476
  const base = entry.entry.base_url ?? S.dim("(transport-derived)");
8359
8477
  console.log(
8360
- ` ${S.label(`${path23__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
8478
+ ` ${S.label(`${path18__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
8361
8479
  );
8362
8480
  console.log(` \u2192 providers.yml ${S.bold(entry.providerId)} ${base}`);
8363
8481
  console.log(
@@ -8373,7 +8491,7 @@ function printPlan(plan) {
8373
8491
  console.log();
8374
8492
  }
8375
8493
  async function runMigrateProviders(opts) {
8376
- const projectDir = opts.projectDir ? path23__default.resolve(opts.projectDir) : process.cwd();
8494
+ const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
8377
8495
  const plan = planProviderMigration({ projectDir, workspace: opts.workspace });
8378
8496
  for (const warning of plan.warnings) logWarn(warning);
8379
8497
  if (plan.entries.length === 0 && Object.keys(plan.providers).length === 0) {
@@ -8504,7 +8622,7 @@ async function runMigrateAgents(paths, opts) {
8504
8622
  let failures = 0;
8505
8623
  let manualCount = 0;
8506
8624
  for (const report of plan.reports) {
8507
- const rel = path23__default.relative(base, report.file) || report.file;
8625
+ const rel = path18__default.relative(base, report.file) || report.file;
8508
8626
  for (const note of report.notes) console.log(` ${S.label(rel)} ${note}`);
8509
8627
  for (const note of report.manual) {
8510
8628
  manualCount++;
@@ -8531,14 +8649,14 @@ async function runMigrateAssets(root, opts) {
8531
8649
  const write = resolveMode(opts);
8532
8650
  const base = process.cwd();
8533
8651
  const plan = planAssetMigration({
8534
- root: path23__default.resolve(root ?? base),
8652
+ root: path18__default.resolve(root ?? base),
8535
8653
  registry: getKindRegistry()
8536
8654
  });
8537
8655
  for (const note of plan.notes) console.log(` ${note}`);
8538
8656
  for (const note of plan.manual) logWarn(note);
8539
8657
  for (const { file, type } of plan.unknownTypes) {
8540
8658
  logWarn(
8541
- `${path23__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
8659
+ `${path18__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
8542
8660
  );
8543
8661
  }
8544
8662
  printChanges(plan.changes, base);
@@ -8561,8 +8679,8 @@ function makeNpxCommand() {
8561
8679
  skills.command("add <url>").description(
8562
8680
  "Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
8563
8681
  ).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) => {
8564
- const projectDir = path23__default.resolve(opts.projectDir);
8565
- const projYaml = path23__default.join(projectDir, "skaile.yaml");
8682
+ const projectDir = path18__default.resolve(opts.projectDir);
8683
+ const projYaml = path18__default.join(projectDir, "skaile.yaml");
8566
8684
  if (!existsSync(projYaml)) {
8567
8685
  logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
8568
8686
  process.exit(1);
@@ -8575,11 +8693,11 @@ function makeNpxCommand() {
8575
8693
  }
8576
8694
  const spinner = createSpinner();
8577
8695
  const key = sourceCacheKey(url);
8578
- const clonePath = path23__default.join(getGlobalCacheDir(), key);
8696
+ const clonePath = path18__default.join(getGlobalCacheDir(), key);
8579
8697
  spinner.start(`Cloning ${url}`);
8580
8698
  try {
8581
8699
  if (!existsSync(clonePath)) {
8582
- mkdirSync(path23__default.dirname(clonePath), { recursive: true });
8700
+ mkdirSync(path18__default.dirname(clonePath), { recursive: true });
8583
8701
  execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
8584
8702
  }
8585
8703
  spinner.stop(`Cloned to ${key}`);
@@ -8634,7 +8752,7 @@ function makeNpxCommand() {
8634
8752
  return npx;
8635
8753
  }
8636
8754
  function resolvePublisher(clonePath, url) {
8637
- const manifestPath = path23__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
8755
+ const manifestPath = path18__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
8638
8756
  if (existsSync(manifestPath)) {
8639
8757
  try {
8640
8758
  const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
@@ -8647,12 +8765,12 @@ function resolvePublisher(clonePath, url) {
8647
8765
  return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
8648
8766
  }
8649
8767
  function resolveSkillName(clonePath, requested) {
8650
- const skillsDir = path23__default.join(clonePath, "skills");
8651
- if (existsSync(path23__default.join(skillsDir, requested, "SKILL.md"))) return requested;
8768
+ const skillsDir = path18__default.join(clonePath, "skills");
8769
+ if (existsSync(path18__default.join(skillsDir, requested, "SKILL.md"))) return requested;
8652
8770
  if (!existsSync(skillsDir)) return requested;
8653
8771
  for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
8654
8772
  if (!entry.isDirectory()) continue;
8655
- const md = path23__default.join(skillsDir, entry.name, "SKILL.md");
8773
+ const md = path18__default.join(skillsDir, entry.name, "SKILL.md");
8656
8774
  if (!existsSync(md)) continue;
8657
8775
  try {
8658
8776
  const { data } = parseFrontmatter(readFileSync(md, "utf8"));
@@ -8682,9 +8800,10 @@ function makeOutdatedCommand() {
8682
8800
  SUPPORTED_DRIVER_TARGETS
8683
8801
  )
8684
8802
  ).action(async (filter, opts) => {
8803
+ requireProjectConfig(opts.projectDir);
8685
8804
  const am2 = new AssetManager({
8686
8805
  registry: getKindRegistry(),
8687
- projectDir: path23__default.resolve(opts.projectDir),
8806
+ projectDir: path18__default.resolve(opts.projectDir),
8688
8807
  driverTarget: opts.target
8689
8808
  });
8690
8809
  const entries = await am2.outdated();
@@ -8714,6 +8833,12 @@ function makeOutdatedCommand() {
8714
8833
  if (filtered.some((e) => e.problem !== void 0 && !e.manualFix)) {
8715
8834
  logWarn(`Run ${S.cmd("skaile install")} to restore or re-lock the broken assets.`);
8716
8835
  }
8836
+ for (const e of filtered) {
8837
+ if (e.problem !== void 0 || (await am2.gapsOf(outdatedRef(e))).length > 0) {
8838
+ process.exitCode = 1;
8839
+ break;
8840
+ }
8841
+ }
8717
8842
  });
8718
8843
  }
8719
8844
  function makePatchCommand() {
@@ -8721,7 +8846,7 @@ function makePatchCommand() {
8721
8846
  cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8722
8847
  const am2 = new AssetManager({
8723
8848
  registry: getKindRegistry(),
8724
- projectDir: path23__default.resolve(opts.projectDir)
8849
+ projectDir: path18__default.resolve(opts.projectDir)
8725
8850
  });
8726
8851
  try {
8727
8852
  const dest = await am2.patch(ref);
@@ -8735,7 +8860,7 @@ function makePatchCommand() {
8735
8860
  cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8736
8861
  const am2 = new AssetManager({
8737
8862
  registry: getKindRegistry(),
8738
- projectDir: path23__default.resolve(opts.projectDir)
8863
+ projectDir: path18__default.resolve(opts.projectDir)
8739
8864
  });
8740
8865
  try {
8741
8866
  const patchFile = await am2.patchCommit(ref);
@@ -8749,7 +8874,7 @@ function makePatchCommand() {
8749
8874
  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) => {
8750
8875
  const am2 = new AssetManager({
8751
8876
  registry: getKindRegistry(),
8752
- projectDir: path23__default.resolve(opts.projectDir)
8877
+ projectDir: path18__default.resolve(opts.projectDir)
8753
8878
  });
8754
8879
  try {
8755
8880
  await am2.patchSubmit(ref);
@@ -8765,7 +8890,7 @@ function makePatchCommand() {
8765
8890
  cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
8766
8891
  const am2 = new AssetManager({
8767
8892
  registry: getKindRegistry(),
8768
- projectDir: path23__default.resolve(opts.projectDir)
8893
+ projectDir: path18__default.resolve(opts.projectDir)
8769
8894
  });
8770
8895
  am2.patchRemove(ref);
8771
8896
  logOk(`Patch removed for ${ref}`);
@@ -8784,7 +8909,7 @@ function action2(fn) {
8784
8909
  };
8785
8910
  }
8786
8911
  async function reconcileAndReport(projectDir, plugins) {
8787
- const { reconcilePlugins } = await import('../plugin-store-MPAMD5OT.js');
8912
+ const { reconcilePlugins } = await import('../plugin-store-AGQDMING.js');
8788
8913
  if (plugins.length === 0) {
8789
8914
  logInfo("No plugins declared \u2014 nothing to reconcile.");
8790
8915
  return;
@@ -8798,10 +8923,10 @@ async function reconcileAndReport(projectDir, plugins) {
8798
8923
  }
8799
8924
  }
8800
8925
  async function runInstall2(spec, opts) {
8801
- const projectDir = path23__default.resolve(opts.projectDir);
8926
+ const projectDir = path18__default.resolve(opts.projectDir);
8802
8927
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
8803
- const { specName } = await import('../plugin-store-MPAMD5OT.js');
8804
- const yamlPath = path23__default.join(projectDir, "skaile.yaml");
8928
+ const { specName } = await import('../plugin-store-AGQDMING.js');
8929
+ const yamlPath = path18__default.join(projectDir, "skaile.yaml");
8805
8930
  const editor = WorkspaceYamlEditor2.load(yamlPath);
8806
8931
  const replaced = editor.addPlugin(spec, specName);
8807
8932
  editor.save();
@@ -8810,10 +8935,10 @@ async function runInstall2(spec, opts) {
8810
8935
  await reconcileAndReport(projectDir, editor.getPlugins());
8811
8936
  }
8812
8937
  async function runRemove(name, opts) {
8813
- const projectDir = path23__default.resolve(opts.projectDir);
8938
+ const projectDir = path18__default.resolve(opts.projectDir);
8814
8939
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
8815
- const { specName } = await import('../plugin-store-MPAMD5OT.js');
8816
- const yamlPath = path23__default.join(projectDir, "skaile.yaml");
8940
+ const { specName } = await import('../plugin-store-AGQDMING.js');
8941
+ const yamlPath = path18__default.join(projectDir, "skaile.yaml");
8817
8942
  const editor = WorkspaceYamlEditor2.load(yamlPath);
8818
8943
  const removed = editor.removePlugin(name, specName);
8819
8944
  if (!removed) {
@@ -8825,7 +8950,7 @@ async function runRemove(name, opts) {
8825
8950
  await reconcileAndReport(projectDir, editor.getPlugins());
8826
8951
  }
8827
8952
  async function runList(opts) {
8828
- const projectDir = path23__default.resolve(opts.projectDir);
8953
+ const projectDir = path18__default.resolve(opts.projectDir);
8829
8954
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
8830
8955
  const config = resolveSkWorkspaceConfig2(projectDir);
8831
8956
  const declared = config.plugins ?? [];
@@ -8840,7 +8965,7 @@ async function runList(opts) {
8840
8965
  const registry = createPluginRegistry();
8841
8966
  if (declared.length > 0) {
8842
8967
  try {
8843
- const { loadPlugins } = await import('../plugin-store-MPAMD5OT.js');
8968
+ const { loadPlugins } = await import('../plugin-store-AGQDMING.js');
8844
8969
  const result = await loadPlugins(projectDir, declared, registry);
8845
8970
  for (const f of result.failed) logWarn(f.error);
8846
8971
  } catch (err2) {
@@ -9015,7 +9140,7 @@ function neededSources(config, lock) {
9015
9140
  }
9016
9141
  function sourcesWithSidecar(sources) {
9017
9142
  const dir = getStoreManifestsDir();
9018
- return sources.filter((s) => existsSync(path23.join(dir, `${storeManifestSlug(s.url)}.yaml`))).map((s) => s.url);
9143
+ return sources.filter((s) => existsSync(path18.join(dir, `${storeManifestSlug(s.url)}.yaml`))).map((s) => s.url);
9019
9144
  }
9020
9145
  function compact(obj) {
9021
9146
  const out = {};
@@ -9107,8 +9232,8 @@ function redactSecrets(preset, findings) {
9107
9232
  }
9108
9233
  return { preset: next, keys };
9109
9234
  }
9110
- function placeholderKey(itemId, path44) {
9111
- return `${itemId}_${path44}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
9235
+ function placeholderKey(itemId, path43) {
9236
+ return `${itemId}_${path43}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
9112
9237
  }
9113
9238
  function setAtPath(root, segments, value) {
9114
9239
  let node = root;
@@ -9131,7 +9256,7 @@ function makePresetCommand() {
9131
9256
  cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
9132
9257
  const presetName = name ?? "my-preset";
9133
9258
  const filename = `${presetName}.preset.yaml`;
9134
- const outPath = path23__default.join(path23__default.resolve(opts.dir), filename);
9259
+ const outPath = path18__default.join(path18__default.resolve(opts.dir), filename);
9135
9260
  if (existsSync(outPath)) {
9136
9261
  logErr(`File already exists: ${outPath}`);
9137
9262
  logInfo("Choose a different name or remove the existing file.");
@@ -9164,7 +9289,7 @@ function makePresetCommand() {
9164
9289
  return cmd;
9165
9290
  }
9166
9291
  async function runPresetExport(name, opts) {
9167
- const projectDir = path23__default.resolve(opts.projectDir);
9292
+ const projectDir = path18__default.resolve(opts.projectDir);
9168
9293
  const file = loadSkWorkspaceConfig(projectDir);
9169
9294
  if (!file) {
9170
9295
  logErr(`No skaile.yaml found in ${projectDir}`);
@@ -9174,7 +9299,7 @@ async function runPresetExport(name, opts) {
9174
9299
  const presetName = name ?? file.config.name ?? "my-preset";
9175
9300
  let lock = null;
9176
9301
  try {
9177
- lock = readLock(path23__default.join(projectDir, "skaile.lock.yaml"));
9302
+ lock = readLock(path18__default.join(projectDir, "skaile.lock.yaml"));
9178
9303
  } catch {
9179
9304
  lock = null;
9180
9305
  }
@@ -9215,7 +9340,7 @@ async function runPresetExport(name, opts) {
9215
9340
  const contents = header ? `${header}
9216
9341
  ${body}` : body;
9217
9342
  if (opts.out && opts.dir !== process.cwd()) logWarn("--dir is ignored when --out is set.");
9218
- const outPath = opts.out ? path23__default.resolve(opts.out) : path23__default.join(path23__default.resolve(opts.dir), `${presetName}.preset.yaml`);
9343
+ const outPath = opts.out ? path18__default.resolve(opts.out) : path18__default.join(path18__default.resolve(opts.dir), `${presetName}.preset.yaml`);
9219
9344
  if (existsSync(outPath) && !opts.force) {
9220
9345
  logErr(`File already exists: ${outPath}`);
9221
9346
  logInfo("Pass --force to overwrite, or choose a different --out/--dir.");
@@ -9227,7 +9352,7 @@ ${body}` : body;
9227
9352
  logErr(`Failed to write ${outPath}: ${e.message}`);
9228
9353
  process.exit(1);
9229
9354
  }
9230
- logOk(`Exported ${S.brand(path23__default.basename(outPath))}`);
9355
+ logOk(`Exported ${S.brand(path18__default.basename(outPath))}`);
9231
9356
  logInfo(`Path: ${outPath}`);
9232
9357
  if (unresolved.length > 0) {
9233
9358
  console.error(S.err("This file is NOT safe to share."));
@@ -9268,13 +9393,13 @@ function collectInput(value, acc) {
9268
9393
  return acc;
9269
9394
  }
9270
9395
  async function runPresetApply(filePath, opts) {
9271
- const projectDir = path23__default.resolve(opts.projectDir);
9396
+ const projectDir = path18__default.resolve(opts.projectDir);
9272
9397
  const file = loadSkWorkspaceConfig(projectDir);
9273
9398
  if (!file) {
9274
9399
  logErr("No skaile.yaml \u2014 run `skaile init` first");
9275
9400
  process.exit(1);
9276
9401
  }
9277
- const resolved = path23__default.resolve(filePath);
9402
+ const resolved = path18__default.resolve(filePath);
9278
9403
  if (!existsSync(resolved)) {
9279
9404
  logErr(`File not found: ${resolved}`);
9280
9405
  process.exit(1);
@@ -9490,7 +9615,7 @@ async function reportNestedPresetRefs(preset) {
9490
9615
  }
9491
9616
  async function checkPresetCycles(preset, resolved) {
9492
9617
  const { detectCycles } = await import('../discovery/index.js');
9493
- const presetRef = path23__default.basename(resolved, ".preset.yaml");
9618
+ const presetRef = path18__default.basename(resolved, ".preset.yaml");
9494
9619
  const edges = [];
9495
9620
  for (const item of preset.items) {
9496
9621
  if (item.ref) {
@@ -9542,7 +9667,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
9542
9667
  }
9543
9668
  }
9544
9669
  async function runPresetValidate(filePath) {
9545
- const resolved = path23__default.resolve(filePath);
9670
+ const resolved = path18__default.resolve(filePath);
9546
9671
  const preset = await loadPresetForValidation(resolved);
9547
9672
  await reportNestedPresetRefs(preset);
9548
9673
  await checkPresetCycles(preset, resolved);
@@ -9592,11 +9717,11 @@ items:
9592
9717
  }
9593
9718
  function makeRebuildCommand() {
9594
9719
  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) => {
9595
- const projectDir = path23__default.resolve(opts.projectDir);
9720
+ const projectDir = path18__default.resolve(opts.projectDir);
9596
9721
  let agentDir;
9597
9722
  if (agentArg) {
9598
9723
  if (agentArg.includes("/") || agentArg.includes("\\")) {
9599
- agentDir = path23__default.resolve(projectDir, agentArg);
9724
+ agentDir = path18__default.resolve(projectDir, agentArg);
9600
9725
  } else {
9601
9726
  let resolved;
9602
9727
  try {
@@ -9605,7 +9730,7 @@ function makeRebuildCommand() {
9605
9730
  if (!(err2 instanceof AgentRefResolutionError)) throw err2;
9606
9731
  logWarn(`${err2.message} \u2014 using "${agentArg}"`);
9607
9732
  }
9608
- agentDir = resolved ?? path23__default.resolve(projectDir, agentArg);
9733
+ agentDir = resolved ?? path18__default.resolve(projectDir, agentArg);
9609
9734
  }
9610
9735
  } else {
9611
9736
  let resolved;
@@ -9675,9 +9800,9 @@ Try a different harness with \`--driver claude-sdk\`.`;
9675
9800
  // cli/src/commands/run.ts
9676
9801
  function resolveSingleShotAgentDir(projectDir, agentDefinition) {
9677
9802
  if (!agentDefinition) return resolveAgentDir(projectDir);
9678
- const asPath = agentDefinition.endsWith("agent.yaml") ? path23__default.dirname(path23__default.resolve(projectDir, agentDefinition)) : agentDefinition;
9803
+ const asPath = agentDefinition.endsWith("agent.yaml") ? path18__default.dirname(path18__default.resolve(projectDir, agentDefinition)) : agentDefinition;
9679
9804
  const dir = resolveAgentDefinitionDir(projectDir, asPath);
9680
- if (!dir || !fs9__default.existsSync(path23__default.join(dir, "agent.yaml"))) {
9805
+ if (!dir || !fs8__default.existsSync(path18__default.join(dir, "agent.yaml"))) {
9681
9806
  throw new Error(
9682
9807
  `--agent-definition "${agentDefinition}" does not resolve to an agent directory with agent.yaml${dir ? ` (looked in ${dir})` : ""}`
9683
9808
  );
@@ -9776,7 +9901,7 @@ function makeRunCommand() {
9776
9901
  "--agent-definition <ref|path>",
9777
9902
  "Agent asset for this one invocation (agent:@pub/name, ai-assets://\u2026, or a directory with agent.yaml); single-shot prompts only"
9778
9903
  ).option("--skill <name>", "Skill name (for single-shot mode)").action(async (positional, opts) => {
9779
- const projectDir = path23__default.resolve(opts.projectDir);
9904
+ const projectDir = path18__default.resolve(opts.projectDir);
9780
9905
  const cliDriver = opts.driver;
9781
9906
  const dryRun = opts.dryRun ?? false;
9782
9907
  const agentDefinition = opts.agentDefinition?.trim() || void 0;
@@ -9895,7 +10020,7 @@ function makeRunCommand() {
9895
10020
  }
9896
10021
  function makeResumeCommand() {
9897
10022
  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) => {
9898
- const projectDir = path23__default.resolve(opts.projectDir);
10023
+ const projectDir = path18__default.resolve(opts.projectDir);
9899
10024
  const sessionId = opts.session;
9900
10025
  const dryRun = opts.dryRun ?? false;
9901
10026
  const session = sessionId ? await loadSessionById(projectDir, sessionId) : await loadSession(projectDir);
@@ -9922,7 +10047,7 @@ function makeResumeCommand() {
9922
10047
  }
9923
10048
  function makeStatusCommand() {
9924
10049
  return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
9925
- const projectDir = path23__default.resolve(opts.projectDir);
10050
+ const projectDir = path18__default.resolve(opts.projectDir);
9926
10051
  const session = await loadSession(projectDir);
9927
10052
  if (!session) {
9928
10053
  logInfo("No active session.");
@@ -9947,7 +10072,7 @@ function makeStatusCommand() {
9947
10072
  }
9948
10073
  function makeClearCommand() {
9949
10074
  return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
9950
- const projectDir = path23__default.resolve(opts.projectDir);
10075
+ const projectDir = path18__default.resolve(opts.projectDir);
9951
10076
  await clearSession(projectDir);
9952
10077
  logOk("Session cleared.");
9953
10078
  });
@@ -9957,7 +10082,7 @@ function makeReplCommand() {
9957
10082
  const { findWorkspaceRoot } = await import('../core/index.js');
9958
10083
  const { startRepl } = await import('../tui/index.js');
9959
10084
  const os2 = await import('os');
9960
- const userCwd = path23__default.resolve(opts.projectDir ?? process.cwd());
10085
+ const userCwd = path18__default.resolve(opts.projectDir ?? process.cwd());
9961
10086
  const workspaceRoot = findWorkspaceRoot(userCwd);
9962
10087
  let projectDir;
9963
10088
  let agentCwd;
@@ -9979,13 +10104,13 @@ function makeReplCommand() {
9979
10104
  p4.cancel("Cancelled.");
9980
10105
  process.exit(0);
9981
10106
  }
9982
- const tmpDir = fs9__default.mkdtempSync(path23__default.join(os2.tmpdir(), "skaile-repl-"));
10107
+ const tmpDir = fs8__default.mkdtempSync(path18__default.join(os2.tmpdir(), "skaile-repl-"));
9983
10108
  projectDir = tmpDir;
9984
10109
  agentCwd = userCwd;
9985
10110
  logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
9986
10111
  if (!driverOverride) {
9987
- const claudeDir = path23__default.join(os2.homedir(), ".claude");
9988
- if (fs9__default.existsSync(claudeDir)) {
10112
+ const claudeDir = path18__default.join(os2.homedir(), ".claude");
10113
+ if (fs8__default.existsSync(claudeDir)) {
9989
10114
  driverOverride = "claude-sdk";
9990
10115
  logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} harness`);
9991
10116
  } else {
@@ -9995,14 +10120,19 @@ function makeReplCommand() {
9995
10120
  }
9996
10121
  console.log();
9997
10122
  }
9998
- await startRepl({
9999
- projectDir,
10000
- cwd: agentCwd !== projectDir ? agentCwd : void 0,
10001
- driver: driverOverride,
10002
- model: opts.model,
10003
- resume: opts.resume,
10004
- resumeSessionId: opts.resumeSession
10005
- });
10123
+ try {
10124
+ await startRepl({
10125
+ projectDir,
10126
+ cwd: agentCwd !== projectDir ? agentCwd : void 0,
10127
+ driver: driverOverride,
10128
+ model: opts.model,
10129
+ resume: opts.resume,
10130
+ resumeSessionId: opts.resumeSession
10131
+ });
10132
+ } catch (err2) {
10133
+ logErr(friendlyDriverError(err2) ?? (err2 instanceof Error ? err2.message : String(err2)));
10134
+ process.exit(1);
10135
+ }
10006
10136
  });
10007
10137
  }
10008
10138
  function parseProviderIds(raw) {
@@ -10057,12 +10187,12 @@ function makeServeCommand() {
10057
10187
  );
10058
10188
  }
10059
10189
  async function ensurePluginsLoadedForServe(projectDir) {
10060
- const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-XAEKCZKT.js');
10190
+ const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-CFK6YP6R.js');
10061
10191
  try {
10062
10192
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
10063
10193
  const config = resolveSkWorkspaceConfig2(projectDir);
10064
10194
  if (!config.plugins || config.plugins.length === 0) return;
10065
- const { ensurePluginsLoaded } = await import('../plugin-store-MPAMD5OT.js');
10195
+ const { ensurePluginsLoaded } = await import('../plugin-store-AGQDMING.js');
10066
10196
  const { pluginRegistry } = await import('../plugin-registry/index.js');
10067
10197
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
10068
10198
  if (result.loaded.length > 0) {
@@ -10076,21 +10206,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
10076
10206
  }
10077
10207
  }
10078
10208
  async function runCompileTest(opts) {
10079
- const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-XAEKCZKT.js');
10209
+ const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-CFK6YP6R.js');
10080
10210
  const { tmpdir } = await import('os');
10081
- const { dirname: dirname3, join: join7, resolve: resolve5 } = await import('path');
10211
+ const { dirname: dirname3, join: join6, resolve: resolve5 } = await import('path');
10082
10212
  const { fileURLToPath: fileURLToPath2 } = await import('url');
10083
- const { unlinkSync, existsSync: existsSync18 } = await import('fs');
10213
+ const { unlinkSync, existsSync: existsSync17 } = await import('fs');
10084
10214
  const { spawn } = await import('child_process');
10085
10215
  const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
10086
- const { MONOREPO_ROOT } = await import('../paths-FQ64OLJG.js');
10216
+ const { MONOREPO_ROOT } = await import('../paths-SUS4S4YT.js');
10087
10217
  if (MONOREPO_ROOT === null) {
10088
10218
  logErr2("--compile-test is only available inside the skaile-dev workspace.");
10089
10219
  logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
10090
10220
  process.exitCode = 2;
10091
10221
  return;
10092
10222
  }
10093
- const outfile = join7(tmpdir(), `skaile-compile-test-${Date.now()}`);
10223
+ const outfile = join6(tmpdir(), `skaile-compile-test-${Date.now()}`);
10094
10224
  const __thisFile = fileURLToPath2(import.meta.url);
10095
10225
  const entryPoint = resolve5(dirname3(__thisFile), "..", "index.ts");
10096
10226
  logInfo2(`Building compiled binary...`);
@@ -10145,7 +10275,7 @@ async function runCompileTest(opts) {
10145
10275
  } catch {
10146
10276
  }
10147
10277
  try {
10148
- if (existsSync18(outfile)) unlinkSync(outfile);
10278
+ if (existsSync17(outfile)) unlinkSync(outfile);
10149
10279
  } catch {
10150
10280
  }
10151
10281
  }
@@ -10566,7 +10696,7 @@ function resolveMode2(opts) {
10566
10696
  if (opts.forceLocal && opts.forceRemote) {
10567
10697
  throw new Error("Cannot use both --local and --remote");
10568
10698
  }
10569
- const startDir = path23__default.resolve(opts.projectDir ?? process.cwd());
10699
+ const startDir = path18__default.resolve(opts.projectDir ?? process.cwd());
10570
10700
  const localDb = findLogsDb(startDir);
10571
10701
  if (opts.forceLocal) {
10572
10702
  if (!localDb) {
@@ -10599,14 +10729,14 @@ function resolveMode2(opts) {
10599
10729
  function findLogsDb(startDir) {
10600
10730
  let dir = startDir;
10601
10731
  for (let i = 0; i < MAX_WALK_LEVELS; i++) {
10602
- const candidate = path23__default.join(dir, ".skaile", "logs.db");
10732
+ const candidate = path18__default.join(dir, ".skaile", "logs.db");
10603
10733
  if (existsSync(candidate)) {
10604
10734
  try {
10605
10735
  if (statSync(candidate).isFile()) return candidate;
10606
10736
  } catch {
10607
10737
  }
10608
10738
  }
10609
- const parent = path23__default.dirname(dir);
10739
+ const parent = path18__default.dirname(dir);
10610
10740
  if (parent === dir) return void 0;
10611
10741
  dir = parent;
10612
10742
  }
@@ -10781,7 +10911,7 @@ function parsePositiveInt(value, flag) {
10781
10911
  function makeSessionCommand() {
10782
10912
  const cmd = new Command("session").description("Manage sessions");
10783
10913
  cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10784
- const projectDir = path23__default.resolve(opts.projectDir);
10914
+ const projectDir = path18__default.resolve(opts.projectDir);
10785
10915
  const sessions = await listSessions(projectDir);
10786
10916
  const current = await loadSession(projectDir);
10787
10917
  if (sessions.length === 0) {
@@ -10809,7 +10939,7 @@ function makeSessionCommand() {
10809
10939
  console.log();
10810
10940
  });
10811
10941
  cmd.command("show <run-id>").description("Show a specific session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10812
- const projectDir = path23__default.resolve(opts.projectDir);
10942
+ const projectDir = path18__default.resolve(opts.projectDir);
10813
10943
  const session = await loadSessionById(projectDir, runId);
10814
10944
  if (!session) {
10815
10945
  logErr(`Session not found: ${runId}`);
@@ -10818,7 +10948,7 @@ function makeSessionCommand() {
10818
10948
  console.log(JSON.stringify(session, null, 2));
10819
10949
  });
10820
10950
  cmd.command("switch <run-id>").description("Switch the current session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10821
- const projectDir = path23__default.resolve(opts.projectDir);
10951
+ const projectDir = path18__default.resolve(opts.projectDir);
10822
10952
  if (!await loadSessionById(projectDir, runId)) {
10823
10953
  logErr(`Session not found: ${runId}`);
10824
10954
  process.exit(1);
@@ -10827,7 +10957,7 @@ function makeSessionCommand() {
10827
10957
  logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
10828
10958
  });
10829
10959
  cmd.command("delete <run-id>").description("Delete a session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10830
- const projectDir = path23__default.resolve(opts.projectDir);
10960
+ const projectDir = path18__default.resolve(opts.projectDir);
10831
10961
  if (!await loadSessionById(projectDir, runId)) {
10832
10962
  logErr(`Session not found: ${runId}`);
10833
10963
  process.exit(1);
@@ -10885,12 +11015,12 @@ function showOverview(am2) {
10885
11015
  }
10886
11016
  async function showAsset(am2, kind, name) {
10887
11017
  const entry = await am2.info(`${kind}:${name}`);
10888
- if (entry?.source && fs9__default.existsSync(entry.source)) {
11018
+ if (entry?.source && fs8__default.existsSync(entry.source)) {
10889
11019
  console.log();
10890
11020
  console.log(` ${kindColor(entry.kind)} ${S.heading(entry.name)}`);
10891
11021
  console.log(` ${S.rule(40)}`);
10892
11022
  console.log();
10893
- console.log(fs9__default.readFileSync(entry.source, "utf-8"));
11023
+ console.log(fs8__default.readFileSync(entry.source, "utf-8"));
10894
11024
  return;
10895
11025
  }
10896
11026
  logErr(`Asset not found: ${kind}:${name}`);
@@ -10900,7 +11030,7 @@ function makeShowCommand() {
10900
11030
  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) => {
10901
11031
  const am2 = new AssetManager({
10902
11032
  registry: getKindRegistry(),
10903
- projectDir: path23__default.resolve(opts.projectDir),
11033
+ projectDir: path18__default.resolve(opts.projectDir),
10904
11034
  driverTarget: opts.target
10905
11035
  });
10906
11036
  if (!kind) {
@@ -10963,14 +11093,14 @@ function makeStoreCommand() {
10963
11093
  });
10964
11094
  store.command("mode <auto|local|remote>").description("Set the catalog resolution mode (not yet wired)").action((_mode) => {
10965
11095
  logErr(
10966
- `\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path23__default.join(globalSkaileDir(), "store", "config.yaml")}.`
11096
+ `\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path18__default.join(globalSkaileDir(), "store", "config.yaml")}.`
10967
11097
  );
10968
11098
  process.exit(2);
10969
11099
  });
10970
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) => {
10971
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-DB2PNL2X.js');
11101
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-BOSPJVID.js');
10972
11102
  try {
10973
- const remote = await openCatalogSource2({ projectDir: path23__default.resolve(opts.projectDir) });
11103
+ const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
10974
11104
  const assets = await remote.listAssets(opts.kind ? { kind: opts.kind } : {});
10975
11105
  const results = filterCatalogAssets(assets, query);
10976
11106
  if (results.length === 0) {
@@ -10996,10 +11126,10 @@ function makeStoreCommand() {
10996
11126
  }
10997
11127
  });
10998
11128
  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) => {
10999
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-DB2PNL2X.js');
11000
- const { supportsInstallManifest } = await import('../project-I6NX3NFB.js');
11129
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-BOSPJVID.js');
11130
+ const { supportsInstallManifest } = await import('../project-I55A4O2T.js');
11001
11131
  try {
11002
- const remote = await openCatalogSource2({ projectDir: path23__default.resolve(opts.projectDir) });
11132
+ const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
11003
11133
  const asset = await remote.resolve(ref);
11004
11134
  if (!asset) {
11005
11135
  logErr(`Not found in store: ${ref} (try a full ref, e.g. skill:@publisher/name#version)`);
@@ -11124,7 +11254,7 @@ function makeTreeCommand() {
11124
11254
  return new Command("tree").description("Show full dependency tree").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
11125
11255
  const am2 = new AssetManager({
11126
11256
  registry: getKindRegistry(),
11127
- projectDir: path23__default.resolve(opts.projectDir)
11257
+ projectDir: path18__default.resolve(opts.projectDir)
11128
11258
  });
11129
11259
  const root = await am2.tree();
11130
11260
  if (root.children.length === 0) {
@@ -11146,13 +11276,20 @@ function makeTreeCommand() {
11146
11276
  });
11147
11277
  }
11148
11278
  function makeUpdateCommand() {
11149
- return new Command("update").description("Refresh the Catalog cache and re-deploy outdated assets in the current project").argument("[name]", "Update a specific asset (kind:name)").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(
11150
- async (_name, opts) => {
11279
+ return new Command("update").description("Refresh the Catalog cache and re-deploy outdated assets in the current project").argument(
11280
+ "[name]",
11281
+ "Update only this declared asset (kind:@publisher/name, kind:name or name); exits 1 when none matches"
11282
+ ).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
+ async (name, opts) => {
11284
+ const projectDir = path18__default.resolve(opts.projectDir);
11285
+ if (!opts.catalogOnly) requireProjectConfig(projectDir);
11286
+ const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
11287
+ const target = name !== void 0 && !opts.catalogOnly ? await resolveUpdateTarget(am2, name) : void 0;
11151
11288
  if (opts.catalog !== false) {
11152
11289
  const catalogSpinner = createSpinner();
11153
11290
  catalogSpinner.start("Refreshing catalog cache");
11154
11291
  try {
11155
- const remote = await openCatalogSource({ projectDir: path23__default.resolve(opts.projectDir) });
11292
+ const remote = await openCatalogSource({ projectDir: path18__default.resolve(opts.projectDir) });
11156
11293
  const result2 = await remote.refresh();
11157
11294
  catalogSpinner.stop(
11158
11295
  `Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
@@ -11169,53 +11306,133 @@ function makeUpdateCommand() {
11169
11306
  }
11170
11307
  }
11171
11308
  if (opts.catalogOnly) return;
11172
- const projectDir = path23__default.resolve(opts.projectDir);
11173
11309
  if (await shouldSyncSources(opts)) {
11174
11310
  const syncSpinner = createSpinner();
11175
11311
  syncSpinner.start("Syncing sources");
11176
- const { total, synced, failed } = await syncProjectSources(projectDir);
11312
+ const { total, synced, failed: failed2 } = await syncProjectSources(projectDir);
11177
11313
  syncSpinner.stop(
11178
- total === 0 ? "No sources to sync." : `Synced ${S.heading(`${synced}/${total}`)} source(s)` + (failed ? ` (${failed} failed)` : "")
11314
+ total === 0 ? "No sources to sync." : `Synced ${S.heading(`${synced}/${total}`)} source(s)` + (failed2 ? ` (${failed2} failed)` : "")
11179
11315
  );
11180
- if (failed > 0) process.exitCode = 1;
11316
+ if (failed2 > 0) process.exitCode = 1;
11317
+ } else {
11318
+ for (const slug of divergedSourceClones(projectDir)) {
11319
+ logErr(`${slug}: git pull failed: Not possible to fast-forward, aborting.`);
11320
+ process.exitCode = 1;
11321
+ }
11322
+ }
11323
+ if (target) {
11324
+ await updateOne(am2, projectDir, target);
11325
+ return;
11181
11326
  }
11182
- const warnings = deferredWarnings();
11183
- const am2 = new AssetManager({
11184
- registry: getKindRegistry(),
11185
- projectDir,
11186
- onLibraryCollision: warnings.push
11187
- });
11188
11327
  const spinner = createSpinner();
11189
11328
  spinner.start("Re-deploying assets");
11190
11329
  let result;
11191
11330
  try {
11192
- result = await am2.install();
11331
+ result = await am2.install({ moveLibraries: true });
11193
11332
  } catch (err2) {
11194
11333
  spinner.stop("Failed");
11195
- warnings.flush();
11196
11334
  logErr(String(err2));
11197
11335
  process.exit(1);
11198
11336
  }
11199
- spinner.stop("Done");
11200
- warnings.flush();
11337
+ const failed = result.missing.length > 0 || !!result.agentInstanceErrors?.length || process.exitCode === 1;
11338
+ spinner.stop(failed ? "Failed" : "Done");
11201
11339
  if (result.deployed.length > 0) {
11202
11340
  for (const d of result.deployed) logOk(`Updated ${d}`);
11203
11341
  }
11342
+ for (const r of result.restored ?? []) {
11343
+ for (const f of r.restored) logInfo(`Restored ${f}`);
11344
+ for (const f of r.removed) logInfo(`Removed ${f} (not part of ${r.ref})`);
11345
+ }
11204
11346
  for (const r of result.removed) logWarn(`Removed: ${r}`);
11347
+ reportReplaced(result.replaced);
11205
11348
  reportRelocked(result.relocked);
11206
- const changed = result.deployed.length > 0 || result.removed.length > 0 || !!result.relocked?.length;
11349
+ reportMoved(result.moved);
11350
+ const changed = result.deployed.length > 0 || result.removed.length > 0 || !!result.replaced?.length || !!result.moved?.length || !!result.relocked?.length;
11207
11351
  if (result.lockWritten && changed) {
11208
11352
  logInfo(`Lock file written: ${S.dim("skaile.lock.yaml")}`);
11209
11353
  }
11354
+ if (result.agentInstanceErrors?.length) {
11355
+ logErr(
11356
+ `${result.agentInstanceErrors.length} agent instance(s) could not be rendered (see above)`
11357
+ );
11358
+ process.exitCode = 1;
11359
+ }
11210
11360
  if (result.missing.length > 0) {
11211
11361
  for (const m of result.missing) logErr(`Missing: ${m}${result.missingHints?.[m] ?? ""}`);
11212
11362
  process.exitCode = 1;
11213
- } else if (!changed) {
11363
+ } else if (!changed && !failed) {
11214
11364
  logInfo("Nothing to update.");
11215
11365
  }
11216
11366
  }
11217
11367
  );
11218
11368
  }
11369
+ function declaredMatches(d, arg) {
11370
+ const declared = parseAssetRefLoose(d.ref);
11371
+ if (!declared) return false;
11372
+ const spec = arg.trim().replace(/#.*$/, "");
11373
+ const colon = spec.indexOf(":");
11374
+ const kindRaw = colon >= 0 ? spec.slice(0, colon) : void 0;
11375
+ const rest = colon >= 0 ? spec.slice(colon + 1) : spec;
11376
+ const kind = kindRaw === "mcp" ? "mcp-server" : kindRaw;
11377
+ let publisher;
11378
+ let name = rest;
11379
+ if (rest.startsWith("@")) {
11380
+ const slash = rest.indexOf("/");
11381
+ publisher = rest.slice(1, slash < 0 ? void 0 : slash);
11382
+ name = slash < 0 ? "" : rest.slice(slash + 1);
11383
+ }
11384
+ return (kind === void 0 || kind === declared.kind) && (publisher === void 0 || publisher === declared.publisher?.replace(/^@/, "")) && name === declared.name;
11385
+ }
11386
+ async function resolveUpdateTarget(am2, name) {
11387
+ let declared;
11388
+ try {
11389
+ declared = (await am2.listDeclared()).filter((d) => d.state !== "invalid");
11390
+ } catch (err2) {
11391
+ if (err2 instanceof MissingManifestError) {
11392
+ logErr("No skaile.yaml found in this directory. Run `skaile init` first.");
11393
+ } else {
11394
+ logErr(err2 instanceof Error ? err2.message : String(err2));
11395
+ }
11396
+ process.exit(1);
11397
+ }
11398
+ const hits = declared.filter((d) => declaredMatches(d, name));
11399
+ if (hits.length === 1) return hits[0];
11400
+ if (hits.length > 1) {
11401
+ logErr(`"${name}" matches ${hits.length} declared assets; name the one you mean:`);
11402
+ for (const h of hits) console.error(` ${h.ref}`);
11403
+ process.exit(1);
11404
+ }
11405
+ logErr(`No declared asset matches "${name}".`);
11406
+ if (declared.length > 0) logInfo(`Declared: ${declared.map((d) => d.ref).join(", ")}`);
11407
+ process.exit(1);
11408
+ }
11409
+ function readText2(file) {
11410
+ try {
11411
+ return readFileSync(file, "utf8");
11412
+ } catch {
11413
+ return "";
11414
+ }
11415
+ }
11416
+ async function updateOne(am2, projectDir, target) {
11417
+ const lockPath = path18__default.join(projectDir, "skaile.lock.yaml");
11418
+ const before = readText2(lockPath);
11419
+ const spinner = createSpinner();
11420
+ spinner.start(`Updating ${target.ref}`);
11421
+ let deployed;
11422
+ try {
11423
+ deployed = await am2.add(target.ref, { onLibraryMoved: (m) => reportMoved([m]) });
11424
+ } catch (err2) {
11425
+ spinner.stop("Failed");
11426
+ logErr(err2 instanceof Error ? err2.message : String(err2));
11427
+ process.exitCode = 1;
11428
+ return;
11429
+ }
11430
+ spinner.stop(process.exitCode === 1 ? "Failed" : "Done");
11431
+ for (const d of deployed) logOk(`Updated ${d}`);
11432
+ if (deployed.length > 0) return;
11433
+ if (readText2(lockPath) !== before) logInfo(`Re-locked ${target.ref}`);
11434
+ else logInfo(`${target.ref} is up to date.`);
11435
+ }
11219
11436
  async function shouldSyncSources(opts) {
11220
11437
  if (opts.sync === false) return false;
11221
11438
  if (opts.yes || !process.stdin.isTTY) return true;
@@ -11304,17 +11521,23 @@ function refKindName(ref) {
11304
11521
  let rest = colon === -1 ? trimmed : trimmed.slice(colon + 1);
11305
11522
  const hash = rest.indexOf("#");
11306
11523
  if (hash !== -1) rest = rest.slice(0, hash);
11524
+ let publisher;
11307
11525
  if (rest.startsWith("@")) {
11308
11526
  const slash = rest.indexOf("/");
11309
- if (slash !== -1) rest = rest.slice(slash + 1);
11527
+ if (slash !== -1) {
11528
+ publisher = rest.slice(1, slash);
11529
+ rest = rest.slice(slash + 1);
11530
+ }
11310
11531
  }
11311
- return { kind, name: rest };
11532
+ return { kind, name: rest, publisher };
11312
11533
  }
11313
11534
  function whyEmptyMessage(ref, declared) {
11314
- const { kind, name } = refKindName(ref);
11315
- const isDeclared = declared.some(
11316
- (d) => d.name === name && (kind === void 0 || d.kind === kind)
11317
- );
11535
+ const { kind, name, publisher } = refKindName(ref);
11536
+ const isDeclared = declared.some((d) => {
11537
+ if (d.name !== name || kind !== void 0 && d.kind !== kind) return false;
11538
+ const declaredPublisher = d.ref ? refKindName(d.ref).publisher : void 0;
11539
+ return !publisher || !declaredPublisher || publisher === declaredPublisher;
11540
+ });
11318
11541
  if (isDeclared) {
11319
11542
  return `${ref} not found in lock file. Run \`skaile install\` first.`;
11320
11543
  }
@@ -11324,18 +11547,28 @@ function makeWhyCommand() {
11324
11547
  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) => {
11325
11548
  const am2 = new AssetManager({
11326
11549
  registry: getKindRegistry(),
11327
- projectDir: path23__default.resolve(opts.projectDir)
11550
+ projectDir: path18__default.resolve(opts.projectDir)
11328
11551
  });
11329
11552
  const chain = await am2.why(ref);
11330
11553
  if (chain.length === 0) {
11554
+ const declaredGap = (await am2.gapsOf(ref)).find((g) => g.type === "declared");
11555
+ if (declaredGap) {
11556
+ logErr(declaredGap.message);
11557
+ process.exitCode = 1;
11558
+ return;
11559
+ }
11331
11560
  let declared;
11332
11561
  try {
11333
11562
  declared = await am2.listDeclared();
11334
- } catch {
11335
- logErr(`${ref} not found in lock file. Run \`skaile install\` first.`);
11563
+ } catch (err2) {
11564
+ logErr(
11565
+ `${ref} is not in the lock file, and skaile.yaml cannot be read: ${err2 instanceof Error ? err2.message : String(err2)}`
11566
+ );
11567
+ process.exitCode = 1;
11336
11568
  return;
11337
11569
  }
11338
11570
  logErr(whyEmptyMessage(ref, declared));
11571
+ process.exitCode = 1;
11339
11572
  return;
11340
11573
  }
11341
11574
  console.log();
@@ -11359,7 +11592,7 @@ function makeWhyCommand() {
11359
11592
  var _defaultFormatHelp = Help.prototype.formatHelp;
11360
11593
  var pkg = JSON.parse(
11361
11594
  readFileSync(
11362
- path23__default.resolve(path23__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
11595
+ path18__default.resolve(path18__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
11363
11596
  "utf-8"
11364
11597
  )
11365
11598
  );
@@ -11370,7 +11603,7 @@ for (const key of [
11370
11603
  "SKAILE_CACHE_DIR"
11371
11604
  ]) {
11372
11605
  const value = process.env[key];
11373
- if (value) process.env[key] = path23__default.resolve(value);
11606
+ if (value) process.env[key] = path18__default.resolve(value);
11374
11607
  }
11375
11608
  var program = new Command("skaile").description("AI asset manager").version(pkg.version, "-v, --version", "Show the skaile CLI version").enablePositionalOptions().configureHelp({
11376
11609
  formatHelp(cmd, helper) {
@@ -11490,7 +11723,7 @@ program.command("init [project-dir]").description("Initialize a project director
11490
11723
  (projectDir, opts) => runInit(projectDir, opts)
11491
11724
  );
11492
11725
  async function runInit(projectDir, opts) {
11493
- const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync7 } = await import('fs');
11726
+ const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync6 } = await import('fs');
11494
11727
  const { stringify: stringify2 } = await import('yaml');
11495
11728
  const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
11496
11729
  const harness = opts.harness;
@@ -11499,32 +11732,32 @@ async function runInit(projectDir, opts) {
11499
11732
  process.exitCode = 1;
11500
11733
  return;
11501
11734
  }
11502
- const resolved = path23__default.resolve(projectDir ?? ".");
11503
- const projectName = path23__default.basename(resolved);
11735
+ const resolved = path18__default.resolve(projectDir ?? ".");
11736
+ const projectName = path18__default.basename(resolved);
11504
11737
  const created = [];
11505
- const { existsSync: existsSync18 } = await import('fs');
11506
- if (!existsSync18(resolved)) {
11738
+ const { existsSync: existsSync17 } = await import('fs');
11739
+ if (!existsSync17(resolved)) {
11507
11740
  mkdirSync5(resolved, { recursive: true });
11508
11741
  created.push(".");
11509
11742
  }
11510
- const skaileDir = path23__default.join(resolved, ".skaile");
11511
- if (!existsSync18(skaileDir)) {
11512
- mkdirSync5(path23__default.join(skaileDir, "sessions"), { recursive: true });
11743
+ const skaileDir = path18__default.join(resolved, ".skaile");
11744
+ if (!existsSync17(skaileDir)) {
11745
+ mkdirSync5(path18__default.join(skaileDir, "sessions"), { recursive: true });
11513
11746
  created.push(".skaile/");
11514
11747
  }
11515
- const settingsPath = path23__default.join(skaileDir, "settings.json");
11516
- if (!existsSync18(settingsPath)) {
11517
- writeFileSync7(settingsPath, "{}\n");
11748
+ const settingsPath = path18__default.join(skaileDir, "settings.json");
11749
+ if (!existsSync17(settingsPath)) {
11750
+ writeFileSync6(settingsPath, "{}\n");
11518
11751
  created.push(".skaile/settings.json");
11519
11752
  }
11520
- const wsConfigPath = path23__default.join(resolved, "skaile.yaml");
11521
- if (!existsSync18(wsConfigPath)) {
11522
- writeFileSync7(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
11753
+ const wsConfigPath = path18__default.join(resolved, "skaile.yaml");
11754
+ if (!existsSync17(wsConfigPath)) {
11755
+ writeFileSync6(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
11523
11756
  created.push("skaile.yaml");
11524
11757
  }
11525
11758
  for (const dir of new Set(Object.values(DRIVER_TARGETS[harness].local))) {
11526
- const full = path23__default.join(resolved, dir);
11527
- if (!existsSync18(full)) {
11759
+ const full = path18__default.join(resolved, dir);
11760
+ if (!existsSync17(full)) {
11528
11761
  mkdirSync5(full, { recursive: true });
11529
11762
  created.push(`${dir}/`);
11530
11763
  }
@@ -11554,8 +11787,8 @@ function buildInitWorkspaceConfig(projectName, harness) {
11554
11787
  }
11555
11788
  async function initGitScaffold(resolved, created) {
11556
11789
  const { execSync: execSync2 } = await import('child_process');
11557
- const { existsSync: existsSync18, readFileSync: readFileSync10, writeFileSync: writeFileSync7 } = await import('fs');
11558
- const gitignorePath = path23__default.join(resolved, ".gitignore");
11790
+ const { existsSync: existsSync17, readFileSync: readFileSync10, writeFileSync: writeFileSync6 } = await import('fs');
11791
+ const gitignorePath = path18__default.join(resolved, ".gitignore");
11559
11792
  const entries = [
11560
11793
  "node_modules/",
11561
11794
  ".skaile/sessions/",
@@ -11572,16 +11805,16 @@ async function initGitScaffold(resolved, created) {
11572
11805
  ".env",
11573
11806
  ".env.local"
11574
11807
  ];
11575
- const existing = existsSync18(gitignorePath) ? readFileSync10(gitignorePath, "utf-8") : "";
11808
+ const existing = existsSync17(gitignorePath) ? readFileSync10(gitignorePath, "utf-8") : "";
11576
11809
  const have = new Set(existing.split("\n").map((l) => l.trim()));
11577
11810
  const append = entries.filter((e) => !have.has(e));
11578
11811
  if (append.length > 0) {
11579
11812
  const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
11580
- writeFileSync7(gitignorePath, `${existing + prefix}${append.join("\n")}
11813
+ writeFileSync6(gitignorePath, `${existing + prefix}${append.join("\n")}
11581
11814
  `);
11582
11815
  if (!existing) created.push(".gitignore");
11583
11816
  }
11584
- if (!existsSync18(path23__default.join(resolved, ".git"))) {
11817
+ if (!existsSync17(path18__default.join(resolved, ".git"))) {
11585
11818
  try {
11586
11819
  execSync2("git init", { cwd: resolved, stdio: "pipe" });
11587
11820
  created.push(".git/");
@@ -11593,10 +11826,10 @@ async function initGitScaffold(resolved, created) {
11593
11826
  }
11594
11827
  async function bootstrapUserConfig() {
11595
11828
  try {
11596
- const fs14 = await import('fs');
11829
+ const fs13 = await import('fs');
11597
11830
  const { userConfigPath: userConfigPath2, saveConfig, getConfigDefaults } = await import('../library/index.js');
11598
11831
  const userCfgPath = userConfigPath2();
11599
- if (!fs14.existsSync(userCfgPath)) {
11832
+ if (!fs13.existsSync(userCfgPath)) {
11600
11833
  const defaults = getConfigDefaults();
11601
11834
  saveConfig(userCfgPath, {
11602
11835
  catalog: { url: defaults.catalog.url, cache_ttl: defaults.catalog.cache_ttl }
@@ -11611,7 +11844,7 @@ async function bootstrapUserConfig() {
11611
11844
  }
11612
11845
  async function hydrateInitSources(resolved, created) {
11613
11846
  try {
11614
- const { ensureSourcesCloned } = await import('../ensure-sources-SRC2DVR5.js');
11847
+ const { ensureSourcesCloned } = await import('../ensure-sources-2RONZKCU.js');
11615
11848
  const hydrate = ensureSourcesCloned(resolved, { quiet: true });
11616
11849
  for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
11617
11850
  if (hydrate.failed.length > 0) {
@@ -11627,7 +11860,7 @@ function printInitSummary(resolved, projectDir, created) {
11627
11860
  logOk(`Initialized project at ${S.heading(resolved)}`);
11628
11861
  console.log();
11629
11862
  console.log(S.heading(" Next steps:"));
11630
- const isCurrentDir = resolved === path23__default.resolve(".");
11863
+ const isCurrentDir = resolved === path18__default.resolve(".");
11631
11864
  let step = 1;
11632
11865
  if (!isCurrentDir) {
11633
11866
  console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
@@ -11651,7 +11884,7 @@ function printInitSummary(resolved, projectDir, created) {
11651
11884
  console.log();
11652
11885
  }
11653
11886
  program.command("setup").description("Interactive provider setup wizard").action(async () => {
11654
- const { cmdSetup } = await import('../setup-B7JUHYJW.js');
11887
+ const { cmdSetup } = await import('../setup-7DQJKHUI.js');
11655
11888
  await cmdSetup([], { projectDir: process.cwd() });
11656
11889
  });
11657
11890
  program.addCommand(makeInstallCommand());
@@ -11729,11 +11962,18 @@ process.stdout.on("error", (err2) => {
11729
11962
  if (err2.code === "EPIPE") process.exit(0);
11730
11963
  throw err2;
11731
11964
  });
11965
+ var commandSettled = false;
11966
+ process.once("beforeExit", () => {
11967
+ if (commandSettled) return;
11968
+ logErr("The command ended before it finished (nothing left to wait for).");
11969
+ process.exit(1);
11970
+ });
11732
11971
  try {
11733
11972
  await program.parseAsync();
11973
+ commandSettled = true;
11734
11974
  } catch (err2) {
11735
11975
  const { LibrarySyncError } = await import('../library/index.js');
11736
- if (!(err2 instanceof LibrarySyncError)) throw err2;
11976
+ if (!(err2 instanceof LibrarySyncError || err2 instanceof SourceEntryError)) throw err2;
11737
11977
  logErr(err2.message);
11738
11978
  process.exit(1);
11739
11979
  }