@skaile/workspaces 5.10.0 → 5.12.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 (425) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +14 -2
  3. package/dist/{asset-feeds-ELEBTNUS.js → asset-feeds-AM6PSSGM.js} +24 -21
  4. package/dist/asset-feeds-AM6PSSGM.js.map +1 -0
  5. package/dist/asset-manager/catalog-deployer.js +8 -8
  6. package/dist/asset-manager/fragments.js +1 -1
  7. package/dist/asset-manager/index.js +16 -16
  8. package/dist/asset-manager/installer.js +11 -11
  9. package/dist/asset-manager/renderers.js +9 -9
  10. package/dist/asset-manager/src/fragments.d.ts +5 -0
  11. package/dist/asset-manager/src/fragments.d.ts.map +1 -1
  12. package/dist/asset-manager/src/index.d.ts +197 -11
  13. package/dist/asset-manager/src/index.d.ts.map +1 -1
  14. package/dist/asset-manager/src/install-agent.d.ts +9 -1
  15. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  16. package/dist/asset-manager/src/install-instances.d.ts.map +1 -1
  17. package/dist/asset-manager/src/installer.d.ts +33 -3
  18. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  19. package/dist/asset-manager/src/renderers.d.ts +5 -0
  20. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  21. package/dist/bridge/drivers/claude-sdk.js +16 -13
  22. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  23. package/dist/bridge/drivers/codex.js +43 -16
  24. package/dist/bridge/drivers/codex.js.map +1 -1
  25. package/dist/bridge/drivers/continue.js +10 -10
  26. package/dist/bridge/drivers/echo.js +2 -2
  27. package/dist/bridge/drivers/gemini.js +7 -7
  28. package/dist/bridge/drivers/goose.js +10 -10
  29. package/dist/bridge/drivers/omp.js +52 -9
  30. package/dist/bridge/drivers/omp.js.map +1 -1
  31. package/dist/bridge/drivers/opencode.js +10 -10
  32. package/dist/bridge/drivers/qwen.js +7 -7
  33. package/dist/bridge/index.js +12 -12
  34. package/dist/bridge/src/codex/config-toml.d.ts +8 -3
  35. package/dist/bridge/src/codex/config-toml.d.ts.map +1 -1
  36. package/dist/bridge/src/codex/managed-driver.d.ts.map +1 -1
  37. package/dist/bridge/src/drivers/claude-sdk.d.ts +1 -1
  38. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  39. package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
  40. package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +1 -1
  41. package/dist/bridge/src/drivers/omp.d.ts +9 -0
  42. package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
  43. package/dist/bridge/src/provider-materialize/credential-env.d.ts +15 -0
  44. package/dist/bridge/src/provider-materialize/credential-env.d.ts.map +1 -1
  45. package/dist/{chunk-7CR6HT2X.js → chunk-27L6BBAT.js} +9 -9
  46. package/dist/{chunk-7CR6HT2X.js.map → chunk-27L6BBAT.js.map} +1 -1
  47. package/dist/{chunk-QG3HOJEK.js → chunk-2JFIFDDO.js} +3 -3
  48. package/dist/{chunk-QG3HOJEK.js.map → chunk-2JFIFDDO.js.map} +1 -1
  49. package/dist/{chunk-IJHH4DSW.js → chunk-2X3JBVGD.js} +11 -10
  50. package/dist/chunk-2X3JBVGD.js.map +1 -0
  51. package/dist/{chunk-G54USEUP.js → chunk-3HUV2LJF.js} +4 -4
  52. package/dist/{chunk-G54USEUP.js.map → chunk-3HUV2LJF.js.map} +1 -1
  53. package/dist/{chunk-JFXQEVLF.js → chunk-3LVB3HGH.js} +3 -3
  54. package/dist/{chunk-JFXQEVLF.js.map → chunk-3LVB3HGH.js.map} +1 -1
  55. package/dist/{chunk-32XKCNCL.js → chunk-6VLHITAM.js} +146 -4
  56. package/dist/chunk-6VLHITAM.js.map +1 -0
  57. package/dist/{chunk-GEWAIQZ5.js → chunk-7CR2OZPA.js} +10 -12
  58. package/dist/chunk-7CR2OZPA.js.map +1 -0
  59. package/dist/{chunk-6HHE63CO.js → chunk-7QWQTA5S.js} +89 -12
  60. package/dist/chunk-7QWQTA5S.js.map +1 -0
  61. package/dist/{chunk-7I5VRVDP.js → chunk-7XWUJC3A.js} +4 -4
  62. package/dist/{chunk-7I5VRVDP.js.map → chunk-7XWUJC3A.js.map} +1 -1
  63. package/dist/{chunk-3BEY4WK3.js → chunk-C3BMXXTN.js} +203 -31
  64. package/dist/chunk-C3BMXXTN.js.map +1 -0
  65. package/dist/{chunk-IXWODEED.js → chunk-CTP3XBMF.js} +47 -8
  66. package/dist/chunk-CTP3XBMF.js.map +1 -0
  67. package/dist/{chunk-HOHUEKES.js → chunk-DCHQ6BAZ.js} +3 -3
  68. package/dist/{chunk-HOHUEKES.js.map → chunk-DCHQ6BAZ.js.map} +1 -1
  69. package/dist/{chunk-DALV4HHP.js → chunk-DKXNKFKP.js} +3 -2
  70. package/dist/{chunk-DALV4HHP.js.map → chunk-DKXNKFKP.js.map} +1 -1
  71. package/dist/{chunk-3MKPZZRE.js → chunk-G3X4MLDB.js} +3 -3
  72. package/dist/{chunk-3MKPZZRE.js.map → chunk-G3X4MLDB.js.map} +1 -1
  73. package/dist/{chunk-SBFW3CJH.js → chunk-GWD3QNVS.js} +5 -5
  74. package/dist/{chunk-SBFW3CJH.js.map → chunk-GWD3QNVS.js.map} +1 -1
  75. package/dist/chunk-H5U7LNTJ.js +122 -0
  76. package/dist/chunk-H5U7LNTJ.js.map +1 -0
  77. package/dist/{chunk-SX5U422E.js → chunk-HYMERG57.js} +3 -3
  78. package/dist/{chunk-SX5U422E.js.map → chunk-HYMERG57.js.map} +1 -1
  79. package/dist/{chunk-V5TZH4GF.js → chunk-ICIYSJBQ.js} +4 -4
  80. package/dist/{chunk-V5TZH4GF.js.map → chunk-ICIYSJBQ.js.map} +1 -1
  81. package/dist/{chunk-YBQONMH2.js → chunk-ID745F3R.js} +353 -193
  82. package/dist/chunk-ID745F3R.js.map +1 -0
  83. package/dist/{chunk-CLTHEKHR.js → chunk-JQ3DXNQV.js} +4 -4
  84. package/dist/{chunk-CLTHEKHR.js.map → chunk-JQ3DXNQV.js.map} +1 -1
  85. package/dist/chunk-K4VOEYOR.js +21 -0
  86. package/dist/chunk-K4VOEYOR.js.map +1 -0
  87. package/dist/{chunk-XCNK4UE5.js → chunk-KVSDRB35.js} +5 -5
  88. package/dist/{chunk-XCNK4UE5.js.map → chunk-KVSDRB35.js.map} +1 -1
  89. package/dist/{chunk-HJ5MCB3L.js → chunk-MF54ZHWT.js} +20 -3
  90. package/dist/chunk-MF54ZHWT.js.map +1 -0
  91. package/dist/{chunk-NRDSGLCQ.js → chunk-N5M2EISA.js} +240 -52
  92. package/dist/chunk-N5M2EISA.js.map +1 -0
  93. package/dist/{chunk-OBVJ7RPW.js → chunk-NDF24LYP.js} +3 -3
  94. package/dist/{chunk-OBVJ7RPW.js.map → chunk-NDF24LYP.js.map} +1 -1
  95. package/dist/{chunk-ZGQTS3Y4.js → chunk-NGJIVDDD.js} +3 -3
  96. package/dist/{chunk-ZGQTS3Y4.js.map → chunk-NGJIVDDD.js.map} +1 -1
  97. package/dist/{chunk-PE36IF2D.js → chunk-NJV5SLEK.js} +159 -44
  98. package/dist/chunk-NJV5SLEK.js.map +1 -0
  99. package/dist/{chunk-OOWHXOK6.js → chunk-NJXR5OAM.js} +4 -4
  100. package/dist/{chunk-OOWHXOK6.js.map → chunk-NJXR5OAM.js.map} +1 -1
  101. package/dist/{chunk-CGYEHQOX.js → chunk-NOA6EJXE.js} +11 -2
  102. package/dist/chunk-NOA6EJXE.js.map +1 -0
  103. package/dist/{chunk-V7PQZOBR.js → chunk-NR7H7ZJP.js} +14 -6
  104. package/dist/chunk-NR7H7ZJP.js.map +1 -0
  105. package/dist/{chunk-OBYKJB4U.js → chunk-O2SYFJWP.js} +79 -5
  106. package/dist/chunk-O2SYFJWP.js.map +1 -0
  107. package/dist/{chunk-5LKOAX7I.js → chunk-OQ5MKDS3.js} +21 -5
  108. package/dist/chunk-OQ5MKDS3.js.map +1 -0
  109. package/dist/{chunk-4P3KTUZH.js → chunk-P23WJCH2.js} +51 -14
  110. package/dist/chunk-P23WJCH2.js.map +1 -0
  111. package/dist/{chunk-NWDSLXOX.js → chunk-PHRNUTSG.js} +118 -118
  112. package/dist/chunk-PHRNUTSG.js.map +1 -0
  113. package/dist/{chunk-JZCSNEHK.js → chunk-PNOGX36L.js} +141 -39
  114. package/dist/chunk-PNOGX36L.js.map +1 -0
  115. package/dist/{chunk-4OV5DSBB.js → chunk-PNTXHTBC.js} +5 -5
  116. package/dist/chunk-PNTXHTBC.js.map +1 -0
  117. package/dist/{chunk-TRSQP3JD.js → chunk-POQ6PGNE.js} +20 -4
  118. package/dist/chunk-POQ6PGNE.js.map +1 -0
  119. package/dist/{chunk-Y63UQZ7P.js → chunk-QCEKGYHF.js} +3 -3
  120. package/dist/{chunk-Y63UQZ7P.js.map → chunk-QCEKGYHF.js.map} +1 -1
  121. package/dist/{chunk-GFCXNFTW.js → chunk-SHQMPGOL.js} +4 -4
  122. package/dist/{chunk-GFCXNFTW.js.map → chunk-SHQMPGOL.js.map} +1 -1
  123. package/dist/{chunk-WBYDAL6X.js → chunk-SMT3LNAG.js} +4 -4
  124. package/dist/{chunk-WBYDAL6X.js.map → chunk-SMT3LNAG.js.map} +1 -1
  125. package/dist/{chunk-2FMEGSBN.js → chunk-T5TSLSRO.js} +135 -47
  126. package/dist/chunk-T5TSLSRO.js.map +1 -0
  127. package/dist/{chunk-2JMLDZLP.js → chunk-TVAR4JHA.js} +903 -138
  128. package/dist/chunk-TVAR4JHA.js.map +1 -0
  129. package/dist/{chunk-MVQ3Q2HM.js → chunk-UTKENBB6.js} +5 -5
  130. package/dist/{chunk-MVQ3Q2HM.js.map → chunk-UTKENBB6.js.map} +1 -1
  131. package/dist/{chunk-TH4CTXHX.js → chunk-VRLKHL74.js} +6 -6
  132. package/dist/{chunk-TH4CTXHX.js.map → chunk-VRLKHL74.js.map} +1 -1
  133. package/dist/{chunk-Z2K6BGUR.js → chunk-WI4T3KIS.js} +51 -16
  134. package/dist/chunk-WI4T3KIS.js.map +1 -0
  135. package/dist/{chunk-MGGFBZWA.js → chunk-X3RMRJNR.js} +6 -4
  136. package/dist/chunk-X3RMRJNR.js.map +1 -0
  137. package/dist/{chunk-FRPBSUFH.js → chunk-X6LKA3TJ.js} +5 -5
  138. package/dist/{chunk-FRPBSUFH.js.map → chunk-X6LKA3TJ.js.map} +1 -1
  139. package/dist/{chunk-3KHYGOEY.js → chunk-XMAJJPA4.js} +3 -3
  140. package/dist/{chunk-3KHYGOEY.js.map → chunk-XMAJJPA4.js.map} +1 -1
  141. package/dist/{chunk-Y34MSWEZ.js → chunk-XTVSNWLL.js} +19 -7
  142. package/dist/chunk-XTVSNWLL.js.map +1 -0
  143. package/dist/{chunk-VLXDXRRX.js → chunk-XZY6SBGU.js} +3 -3
  144. package/dist/{chunk-VLXDXRRX.js.map → chunk-XZY6SBGU.js.map} +1 -1
  145. package/dist/{chunk-5QI2JYJC.js → chunk-YQU2BPQD.js} +7 -5
  146. package/dist/chunk-YQU2BPQD.js.map +1 -0
  147. package/dist/cli/index.js +1207 -580
  148. package/dist/cli/index.js.map +1 -1
  149. package/dist/cli/src/agent-checks.d.ts +40 -0
  150. package/dist/cli/src/agent-checks.d.ts.map +1 -0
  151. package/dist/cli/src/asset-feeds.d.ts.map +1 -1
  152. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  153. package/dist/cli/src/commands/catalog.d.ts +24 -0
  154. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  155. package/dist/cli/src/commands/config.d.ts.map +1 -1
  156. package/dist/cli/src/commands/diff.d.ts +1 -1
  157. package/dist/cli/src/commands/diff.d.ts.map +1 -1
  158. package/dist/cli/src/commands/integration.d.ts.map +1 -1
  159. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  160. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  161. package/dist/cli/src/commands/manage.d.ts +6 -0
  162. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  163. package/dist/cli/src/commands/mcp-server.d.ts +1 -1
  164. package/dist/cli/src/commands/migrate-assets.d.ts +2 -1
  165. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  166. package/dist/cli/src/commands/migrate.d.ts.map +1 -1
  167. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  168. package/dist/cli/src/commands/plugin/claude-code.d.ts +1 -1
  169. package/dist/cli/src/commands/plugin/claude-code.d.ts.map +1 -1
  170. package/dist/cli/src/commands/plugin/types.d.ts +1 -1
  171. package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
  172. package/dist/cli/src/commands/project.d.ts +3 -1
  173. package/dist/cli/src/commands/project.d.ts.map +1 -1
  174. package/dist/cli/src/commands/publish-core.d.ts +5 -0
  175. package/dist/cli/src/commands/publish-core.d.ts.map +1 -1
  176. package/dist/cli/src/commands/run.d.ts +2 -1
  177. package/dist/cli/src/commands/run.d.ts.map +1 -1
  178. package/dist/cli/src/commands/serve-preflight.d.ts +22 -0
  179. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -0
  180. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  181. package/dist/cli/src/commands/source-manifest-publish.d.ts.map +1 -1
  182. package/dist/cli/src/commands/source-manifest.d.ts.map +1 -1
  183. package/dist/cli/src/commands/source.d.ts.map +1 -1
  184. package/dist/cli/src/commands/store.d.ts.map +1 -1
  185. package/dist/cli/src/commands/tree.d.ts.map +1 -1
  186. package/dist/cli/src/commands/update.d.ts.map +1 -1
  187. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  188. package/dist/cli/src/commands/why.d.ts +1 -0
  189. package/dist/cli/src/commands/why.d.ts.map +1 -1
  190. package/dist/cli/src/curated-manifests.d.ts +21 -0
  191. package/dist/cli/src/curated-manifests.d.ts.map +1 -0
  192. package/dist/cli/src/helpers.d.ts +12 -0
  193. package/dist/cli/src/helpers.d.ts.map +1 -1
  194. package/dist/cli/src/index-busy.d.ts +8 -0
  195. package/dist/cli/src/index-busy.d.ts.map +1 -0
  196. package/dist/cli/src/plugin-store/paths.d.ts +7 -3
  197. package/dist/cli/src/plugin-store/paths.d.ts.map +1 -1
  198. package/dist/cli/src/skill-checks.d.ts +29 -8
  199. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  200. package/dist/cli/src/store-addable.d.ts +18 -0
  201. package/dist/cli/src/store-addable.d.ts.map +1 -0
  202. package/dist/connectors/config.js +5 -5
  203. package/dist/connectors/index.js +16 -16
  204. package/dist/{connectors-OXP2JBGI.js → connectors-UNKUKEPG.js} +19 -19
  205. package/dist/{connectors-OXP2JBGI.js.map → connectors-UNKUKEPG.js.map} +1 -1
  206. package/dist/core/index.js +7 -7
  207. package/dist/core/logging.js +1 -1
  208. package/dist/core/manifest.js +2 -2
  209. package/dist/core/models.js +1 -1
  210. package/dist/core/publish-manifest.js +2 -2
  211. package/dist/core/ref.js +1 -1
  212. package/dist/core/runtime-assets.js +5 -5
  213. package/dist/core/src/index.d.ts +5 -4
  214. package/dist/core/src/index.d.ts.map +1 -1
  215. package/dist/core/src/lock.d.ts +19 -8
  216. package/dist/core/src/lock.d.ts.map +1 -1
  217. package/dist/core/src/logging/sinks/sqlite-sink.d.ts.map +1 -1
  218. package/dist/core/src/manifest.d.ts +5 -0
  219. package/dist/core/src/manifest.d.ts.map +1 -1
  220. package/dist/core/src/models.d.ts +4 -4
  221. package/dist/core/src/models.d.ts.map +1 -1
  222. package/dist/core/src/package-manager.d.ts +19 -0
  223. package/dist/core/src/package-manager.d.ts.map +1 -0
  224. package/dist/core/src/publish-manifest.d.ts +11 -1
  225. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  226. package/dist/core/src/repo-manager.d.ts +11 -0
  227. package/dist/core/src/repo-manager.d.ts.map +1 -1
  228. package/dist/core/src/settings.d.ts +26 -6
  229. package/dist/core/src/settings.d.ts.map +1 -1
  230. package/dist/core/src/walker.d.ts +6 -1
  231. package/dist/core/src/walker.d.ts.map +1 -1
  232. package/dist/core/src/workspace-config.d.ts +4 -1
  233. package/dist/core/src/workspace-config.d.ts.map +1 -1
  234. package/dist/core/workspace-config.js +4 -4
  235. package/dist/deploy/index.js +7 -7
  236. package/dist/discovery/index.js +5 -5
  237. package/dist/discovery/src/source-config.d.ts.map +1 -1
  238. package/dist/{ensure-sources-5ISVIA4T.js → ensure-sources-POMEQSTM.js} +19 -19
  239. package/dist/{ensure-sources-5ISVIA4T.js.map → ensure-sources-POMEQSTM.js.map} +1 -1
  240. package/dist/factory-assets/connectors/box.js +16 -16
  241. package/dist/factory-assets/connectors/deploy.js +16 -16
  242. package/dist/factory-assets/connectors/devserver.js +16 -16
  243. package/dist/factory-assets/connectors/flow/adapter.js +16 -16
  244. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
  245. package/dist/factory-assets/connectors/flow/contract.js +1 -1
  246. package/dist/factory-assets/connectors/flow/engine.js +9 -9
  247. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  248. package/dist/factory-assets/connectors/flow/run-flow.js +18 -18
  249. package/dist/factory-assets/connectors/flow.js +16 -16
  250. package/dist/factory-assets/connectors/git.js +16 -16
  251. package/dist/factory-assets/connectors/gmail.js +16 -16
  252. package/dist/factory-assets/connectors/googledrive.js +16 -16
  253. package/dist/factory-assets/connectors/local.js +16 -16
  254. package/dist/factory-assets/connectors/mattermost.js +16 -16
  255. package/dist/factory-assets/connectors/memory.js +16 -16
  256. package/dist/factory-assets/connectors/minio.js +16 -16
  257. package/dist/factory-assets/connectors/postgres.js +16 -16
  258. package/dist/factory-assets/connectors/s3.js +16 -16
  259. package/dist/factory-assets/connectors/sharepoint.js +16 -16
  260. package/dist/factory-assets/connectors/sqlite.js +16 -16
  261. package/dist/factory-assets/connectors/static-server.js +16 -16
  262. package/dist/factory-assets/connectors/tunnel.js +16 -16
  263. package/dist/factory-assets/connectors/webdav.js +16 -16
  264. package/dist/factory-assets/connectors/xstate-store.js +16 -16
  265. package/dist/factory-assets/connectors/xstate.js +16 -16
  266. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +10 -8
  267. package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +15 -11
  268. package/dist/factory-assets/skills/authoring-skaile-manifests/references/dependency-standard.md +16 -11
  269. package/dist/factory-assets/skills/skaile-author-asset/SKILL.md +2 -2
  270. package/dist/{flows-HMSE76PO.js → flows-DVKMZKM4.js} +12 -12
  271. package/dist/{flows-HMSE76PO.js.map → flows-DVKMZKM4.js.map} +1 -1
  272. package/dist/{helpers-X6URBGSF.js → helpers-Y4OT7VIS.js} +19 -19
  273. package/dist/{helpers-X6URBGSF.js.map → helpers-Y4OT7VIS.js.map} +1 -1
  274. package/dist/library/index.js +12 -12
  275. package/dist/library/install.js +4 -4
  276. package/dist/library/src/index.d.ts +3 -3
  277. package/dist/library/src/index.d.ts.map +1 -1
  278. package/dist/library/src/install/source-fetch-github.d.ts.map +1 -1
  279. package/dist/library/src/local/db.d.ts +2 -0
  280. package/dist/library/src/local/db.d.ts.map +1 -1
  281. package/dist/library/src/local/library-dir.d.ts +26 -0
  282. package/dist/library/src/local/library-dir.d.ts.map +1 -1
  283. package/dist/library/src/local/library-manager.d.ts +5 -0
  284. package/dist/library/src/local/library-manager.d.ts.map +1 -1
  285. package/dist/library/src/local/library.d.ts +5 -3
  286. package/dist/library/src/local/library.d.ts.map +1 -1
  287. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  288. package/dist/library/src/local/store-paths.d.ts +9 -0
  289. package/dist/library/src/local/store-paths.d.ts.map +1 -1
  290. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  291. package/dist/library/src/remote/index.d.ts +1 -1
  292. package/dist/library/src/remote/index.d.ts.map +1 -1
  293. package/dist/library/src/remote/remote-catalog-source.d.ts +17 -0
  294. package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
  295. package/dist/library/src/sync/git-driver.d.ts +2 -0
  296. package/dist/library/src/sync/git-driver.d.ts.map +1 -1
  297. package/dist/{library-publish-OS3JDW4S.js → library-publish-DI4Q5UOG.js} +73 -38
  298. package/dist/library-publish-DI4Q5UOG.js.map +1 -0
  299. package/dist/open-library-N6ESO6IK.js +40 -0
  300. package/dist/{open-library-4QSUORI6.js.map → open-library-N6ESO6IK.js.map} +1 -1
  301. package/dist/open-registry-CBZ5MWTT.js +32 -0
  302. package/dist/{open-registry-VCKS3MP5.js.map → open-registry-CBZ5MWTT.js.map} +1 -1
  303. package/dist/paths-U6W6MQNQ.js +22 -0
  304. package/dist/{paths-BVO56A25.js.map → paths-U6W6MQNQ.js.map} +1 -1
  305. package/dist/{plugin-store-X7GPWGBG.js → plugin-store-XMZSPVBF.js} +48 -12
  306. package/dist/plugin-store-XMZSPVBF.js.map +1 -0
  307. package/dist/project-UP52HEHC.js +79 -0
  308. package/dist/{project-PAXP46RD.js.map → project-UP52HEHC.js.map} +1 -1
  309. package/dist/resolver/index.js +8 -8
  310. package/dist/runner/index.js +33 -33
  311. package/dist/runner/src/agent.d.ts.map +1 -1
  312. package/dist/runner/src/agents/in-process-host.d.ts.map +1 -1
  313. package/dist/runner/src/composition/index.d.ts +1 -0
  314. package/dist/runner/src/composition/index.d.ts.map +1 -1
  315. package/dist/runner/src/composition/prompt-sections.d.ts +7 -4
  316. package/dist/runner/src/composition/prompt-sections.d.ts.map +1 -1
  317. package/dist/runner/src/composition/resolve.d.ts +10 -1
  318. package/dist/runner/src/composition/resolve.d.ts.map +1 -1
  319. package/dist/runner/src/composition/verify.d.ts +29 -0
  320. package/dist/runner/src/composition/verify.d.ts.map +1 -0
  321. package/dist/runner/src/credential-notice.d.ts +14 -0
  322. package/dist/runner/src/credential-notice.d.ts.map +1 -0
  323. package/dist/runner/src/environment.d.ts.map +1 -1
  324. package/dist/runner/src/final-text.d.ts +17 -0
  325. package/dist/runner/src/final-text.d.ts.map +1 -0
  326. package/dist/runner/src/index.d.ts +2 -0
  327. package/dist/runner/src/index.d.ts.map +1 -1
  328. package/dist/runner/src/resource-handler.d.ts.map +1 -1
  329. package/dist/runner/src/serve.d.ts +13 -0
  330. package/dist/runner/src/serve.d.ts.map +1 -1
  331. package/dist/runner/src/usage-limit-turn-hold.d.ts +51 -0
  332. package/dist/runner/src/usage-limit-turn-hold.d.ts.map +1 -0
  333. package/dist/sdk/asset-manager.js +16 -16
  334. package/dist/sdk/bridge.js +12 -12
  335. package/dist/sdk/core.js +7 -7
  336. package/dist/sdk/flow.js +9 -9
  337. package/dist/sdk/index.js +36 -34
  338. package/dist/sdk/index.js.map +1 -1
  339. package/dist/sdk/resolver.js +8 -8
  340. package/dist/sdk/runner.js +33 -33
  341. package/dist/sdk/src/local-runtime.d.ts.map +1 -1
  342. package/dist/sdk/transport/ws/client.js +1 -1
  343. package/dist/sdk/transport/ws/server.js +1 -1
  344. package/dist/sdk/transport/ws.js +2 -2
  345. package/dist/sdk/transport.js +2 -2
  346. package/dist/serve-preflight-6P2JJEJ3.js +47 -0
  347. package/dist/serve-preflight-6P2JJEJ3.js.map +1 -0
  348. package/dist/{setup-BV55VHWC.js → setup-5IRUH5OS.js} +24 -24
  349. package/dist/{setup-BV55VHWC.js.map → setup-5IRUH5OS.js.map} +1 -1
  350. package/dist/{skills-EDFUCJPX.js → skills-HA36RFNM.js} +13 -13
  351. package/dist/{skills-EDFUCJPX.js.map → skills-HA36RFNM.js.map} +1 -1
  352. package/dist/source-DX5SGWEI.js +41 -0
  353. package/dist/{source-E4VAT5RZ.js.map → source-DX5SGWEI.js.map} +1 -1
  354. package/dist/source-fetch-github-PIO6EMMF.js +4 -0
  355. package/dist/{source-fetch-github-QN4LLTL5.js.map → source-fetch-github-PIO6EMMF.js.map} +1 -1
  356. package/dist/{source-manifest-publish-CLEE6TNH.js → source-manifest-publish-NMRLXWVW.js} +27 -26
  357. package/dist/source-manifest-publish-NMRLXWVW.js.map +1 -0
  358. package/dist/transport/index.js +2 -2
  359. package/dist/transport/src/ws/client.d.ts +6 -0
  360. package/dist/transport/src/ws/client.d.ts.map +1 -1
  361. package/dist/transport/src/ws/server.d.ts +4 -0
  362. package/dist/transport/src/ws/server.d.ts.map +1 -1
  363. package/dist/transport/ws/client.js +1 -1
  364. package/dist/transport/ws/server.js +1 -1
  365. package/dist/transport/ws.js +2 -2
  366. package/dist/tui/index.js +89 -52
  367. package/dist/tui/index.js.map +1 -1
  368. package/dist/tui/src/repl-session.d.ts +1 -1
  369. package/dist/tui/src/repl-session.d.ts.map +1 -1
  370. package/dist/tui/src/repl.d.ts +3 -0
  371. package/dist/tui/src/repl.d.ts.map +1 -1
  372. package/dist/types/manifests.js +1 -1
  373. package/dist/types/src/manifests/agent-composition.d.ts +20 -0
  374. package/dist/types/src/manifests/agent-composition.d.ts.map +1 -1
  375. package/dist/types/src/manifests/agent.d.ts.map +1 -1
  376. package/dist/types/src/manifests/cron.d.ts +15 -0
  377. package/dist/types/src/manifests/cron.d.ts.map +1 -0
  378. package/dist/types/src/manifests/index.d.ts +3 -2
  379. package/dist/types/src/manifests/index.d.ts.map +1 -1
  380. package/dist/types/src/manifests/preset.d.ts +1 -1
  381. package/dist/workspace-plugin/adapters/mcp.js +23 -23
  382. package/dist/workspace-plugin/adapters/omp.js +106 -51
  383. package/dist/workspace-plugin/adapters/omp.js.map +1 -1
  384. package/dist/workspace-plugin/index.js +2 -2
  385. package/dist/workspace-plugin/src/adapters/claude-code.d.ts.map +1 -1
  386. package/dist/workspace-plugin/src/adapters/omp.d.ts +11 -2
  387. package/dist/workspace-plugin/src/adapters/omp.d.ts.map +1 -1
  388. package/package.json +1 -1
  389. package/dist/asset-feeds-ELEBTNUS.js.map +0 -1
  390. package/dist/chunk-2FMEGSBN.js.map +0 -1
  391. package/dist/chunk-2JMLDZLP.js.map +0 -1
  392. package/dist/chunk-32XKCNCL.js.map +0 -1
  393. package/dist/chunk-3BEY4WK3.js.map +0 -1
  394. package/dist/chunk-4OV5DSBB.js.map +0 -1
  395. package/dist/chunk-4P3KTUZH.js.map +0 -1
  396. package/dist/chunk-5LKOAX7I.js.map +0 -1
  397. package/dist/chunk-5QI2JYJC.js.map +0 -1
  398. package/dist/chunk-6HHE63CO.js.map +0 -1
  399. package/dist/chunk-CGYEHQOX.js.map +0 -1
  400. package/dist/chunk-GEWAIQZ5.js.map +0 -1
  401. package/dist/chunk-HJ5MCB3L.js.map +0 -1
  402. package/dist/chunk-IJHH4DSW.js.map +0 -1
  403. package/dist/chunk-IXWODEED.js.map +0 -1
  404. package/dist/chunk-JZCSNEHK.js.map +0 -1
  405. package/dist/chunk-MGGFBZWA.js.map +0 -1
  406. package/dist/chunk-NRDSGLCQ.js.map +0 -1
  407. package/dist/chunk-NWDSLXOX.js.map +0 -1
  408. package/dist/chunk-OBYKJB4U.js.map +0 -1
  409. package/dist/chunk-PE36IF2D.js.map +0 -1
  410. package/dist/chunk-R7FOF242.js +0 -59
  411. package/dist/chunk-R7FOF242.js.map +0 -1
  412. package/dist/chunk-TRSQP3JD.js.map +0 -1
  413. package/dist/chunk-V7PQZOBR.js.map +0 -1
  414. package/dist/chunk-Y34MSWEZ.js.map +0 -1
  415. package/dist/chunk-YBQONMH2.js.map +0 -1
  416. package/dist/chunk-Z2K6BGUR.js.map +0 -1
  417. package/dist/library-publish-OS3JDW4S.js.map +0 -1
  418. package/dist/open-library-4QSUORI6.js +0 -40
  419. package/dist/open-registry-VCKS3MP5.js +0 -32
  420. package/dist/paths-BVO56A25.js +0 -22
  421. package/dist/plugin-store-X7GPWGBG.js.map +0 -1
  422. package/dist/project-PAXP46RD.js +0 -41
  423. package/dist/source-E4VAT5RZ.js +0 -41
  424. package/dist/source-fetch-github-QN4LLTL5.js +0 -4
  425. package/dist/source-manifest-publish-CLEE6TNH.js.map +0 -1
package/dist/cli/index.js CHANGED
@@ -1,98 +1,100 @@
1
1
  #!/usr/bin/env node
2
- import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-XCNK4UE5.js';
3
- import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-Z2K6BGUR.js';
4
- import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportReplaced, reportRelocked, REF_HINT, reportInstalledSoftDeps } from '../chunk-4P3KTUZH.js';
2
+ import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-KVSDRB35.js';
3
+ import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-WI4T3KIS.js';
4
+ import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportReplaced, reportRelocked, reportMoved, REF_HINT, reportInstalledSoftDeps } from '../chunk-P23WJCH2.js';
5
5
  import { createSpinner } from '../chunk-NESV47MF.js';
6
- import { AI_RESOURCES } from '../chunk-WBYDAL6X.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-YBQONMH2.js';
8
- import { getStoreConfig, storeFetch, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, isStoreAuthenticated, getStoreToken, getStoreIdentity, assetEntryRef, manifestVersionMismatchMessage } from '../chunk-V7PQZOBR.js';
9
- import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-CLTHEKHR.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-TRSQP3JD.js';
11
- import { getKindRegistry, getKnownKinds } from '../chunk-SBFW3CJH.js';
6
+ import { AI_RESOURCES } from '../chunk-SMT3LNAG.js';
7
+ import { unresolvedManifestDependencies, warnIgnoredDomainFiles, warnLegacyBundleFiles, removedDomainOption, rejectRemovedDomainOption, resolveLibraryPublisherDetailed, warnLibraryNameFallback, indexLibrary, requireValidPublisherOrExit, exitOnManifestPublisherProblems, registerLibraryAsset, DOMAIN_REMOVED_HINT, checkAsset, agentComposeRefAdvisories, manifestPublisherProblems, manifestRequiresProblems, findAssetManifestFile, declaredVersion, checkAssetFile, duplicateAssetMessage, readAssetBody, checkAgentFiles, invalidSemverText } from '../chunk-ID745F3R.js';
8
+ import { getStoreConfig, storeFetch, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, isStoreAuthenticated, getStoreToken, getStoreIdentity, assetEntryRef, manifestVersionMismatchMessage } from '../chunk-NR7H7ZJP.js';
9
+ import { storeNotInstallableReason, STORE_UNADDABLE_KINDS } from '../chunk-K4VOEYOR.js';
10
+ import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-JQ3DXNQV.js';
11
+ 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-POQ6PGNE.js';
12
+ import { getKindRegistry, getKnownKinds } from '../chunk-GWD3QNVS.js';
12
13
  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-NRDSGLCQ.js';
14
- import { buildClaudePluginFiles } from '../chunk-5QI2JYJC.js';
15
- import '../chunk-FRPBSUFH.js';
16
- import '../chunk-SX5U422E.js';
14
+ import { runAgentChat, isCompositionError, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, hashAgentFiles, createCompositionContentSource, compileComposition, instanceForSession, resolveAgentInstance, describeComposition, MarkdownStreamer, createFinalTextFallback } from '../chunk-N5M2EISA.js';
15
+ import { buildClaudePluginFiles } from '../chunk-YQU2BPQD.js';
16
+ import '../chunk-X6LKA3TJ.js';
17
+ import '../chunk-HYMERG57.js';
17
18
  import '../chunk-R6O6YWU7.js';
18
- import '../chunk-G54USEUP.js';
19
- import '../chunk-Y63UQZ7P.js';
19
+ import '../chunk-3HUV2LJF.js';
20
+ import '../chunk-QCEKGYHF.js';
20
21
  import '../chunk-4ZTPYIBE.js';
21
- import '../chunk-VLXDXRRX.js';
22
+ import '../chunk-XZY6SBGU.js';
22
23
  import '../chunk-X5YPJV4N.js';
23
24
  import '../chunk-O7SG5PC2.js';
24
25
  import '../chunk-7QBNJTTQ.js';
25
- import '../chunk-OBYKJB4U.js';
26
- import '../chunk-5LKOAX7I.js';
26
+ import '../chunk-O2SYFJWP.js';
27
+ import '../chunk-OQ5MKDS3.js';
27
28
  import '../chunk-32NA4TVC.js';
28
29
  import '../chunk-W3UDISS2.js';
29
- import '../chunk-NWDSLXOX.js';
30
- import { runFlow, resumeFlow } from '../chunk-IJHH4DSW.js';
30
+ import '../chunk-PHRNUTSG.js';
31
+ import { runFlow, resumeFlow } from '../chunk-2X3JBVGD.js';
31
32
  import '../chunk-4R6DROGN.js';
32
- import { validateFlowVersions } from '../chunk-3MKPZZRE.js';
33
- import '../chunk-HOHUEKES.js';
33
+ import { parseSkillRequirements, validateRequirements, validateFlowVersions } from '../chunk-G3X4MLDB.js';
34
+ import '../chunk-DCHQ6BAZ.js';
34
35
  import '../chunk-ISHJITXJ.js';
35
- import '../chunk-7CR6HT2X.js';
36
+ import '../chunk-27L6BBAT.js';
36
37
  import '../chunk-X4BAYGMT.js';
37
- import '../chunk-V5TZH4GF.js';
38
- import '../chunk-OBVJ7RPW.js';
39
- import '../chunk-QG3HOJEK.js';
38
+ import '../chunk-ICIYSJBQ.js';
39
+ import '../chunk-NDF24LYP.js';
40
+ import '../chunk-2JFIFDDO.js';
40
41
  import '../chunk-LOO5CB5M.js';
41
42
  import '../chunk-2H73V6XR.js';
42
- import '../chunk-OOWHXOK6.js';
43
+ import '../chunk-NJXR5OAM.js';
43
44
  import '../chunk-B4X2N7JQ.js';
44
45
  import '../chunk-YROR332M.js';
45
- import { getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-HJ5MCB3L.js';
46
+ import { listDrivers, getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-MF54ZHWT.js';
46
47
  import '../chunk-6E6PKKAD.js';
47
48
  import '../chunk-IFGTRL2I.js';
48
- import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-7I5VRVDP.js';
49
+ import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-7XWUJC3A.js';
49
50
  import '../chunk-LNFKL23K.js';
50
- import '../chunk-MGGFBZWA.js';
51
+ import '../chunk-X3RMRJNR.js';
51
52
  import '../chunk-M3WPBTGJ.js';
52
53
  import { nodeLabel, nodeSkillAsset, nodeIsInert, nodeIsOptional, nodeRunKind, flowSkillVersionPins } from '../chunk-7RGTAEG6.js';
53
54
  import '../chunk-NUELZWCF.js';
54
55
  import '../chunk-F4NJDSR7.js';
55
- import { AssetManager, MissingManifestError, parseRefTolerant, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-2JMLDZLP.js';
56
- import { libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, ensureGitRepo, conflictingAssetRoot, setManifestPublisher, LIBRARY_OWNERSHIPS, isGitRepo, assertManifestEditable, installLibraryAsset, missingRootAssets, assertValidLibraryName, syncManifestWithDisk, getStoreManifestsDir, getDefaultValue, isSecretPlaceholder } from '../chunk-3BEY4WK3.js';
57
- import { parseManifestFile, SEMVER_RE } from '../chunk-GEWAIQZ5.js';
58
- import '../chunk-MVQ3Q2HM.js';
59
- import '../chunk-R7FOF242.js';
56
+ import { AssetManager, MissingManifestError, parseRefTolerant, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-TVAR4JHA.js';
57
+ import { libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, isGitRepo, ensureGitRepo, conflictingAssetRoot, setManifestPublisher, LIBRARY_OWNERSHIPS, assertManifestEditable, installLibraryAsset, missingRootAssets, getStoreManifestsDir, assertValidLibraryName, syncManifestWithDisk, getDefaultValue, isSecretPlaceholder } from '../chunk-C3BMXXTN.js';
58
+ import { parseManifestFile, SEMVER_RE } from '../chunk-7CR2OZPA.js';
59
+ import '../chunk-UTKENBB6.js';
60
+ import '../chunk-H5U7LNTJ.js';
60
61
  import '../chunk-3TXEJN4W.js';
61
- import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-PE36IF2D.js';
62
- import '../chunk-CGYEHQOX.js';
62
+ import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-NJV5SLEK.js';
63
+ import '../chunk-NOA6EJXE.js';
63
64
  import '../chunk-KTBKW2FI.js';
64
65
  import '../chunk-UQ6LFBPZ.js';
65
- import '../chunk-6HHE63CO.js';
66
- import { effectiveComposes, validatePreset, composeSlotDiagnostics, agentDeprecationDiagnostics, validateAgent, SLOT_ID_PATTERN } from '../chunk-32XKCNCL.js';
67
- import { resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, readLock, aiResourceRoots, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile } from '../chunk-2FMEGSBN.js';
66
+ import '../chunk-7QWQTA5S.js';
67
+ import { effectiveComposes, validatePreset, composeSlotDiagnostics, agentDeprecationDiagnostics, validateAgent, SLOT_ID_PATTERN } from '../chunk-6VLHITAM.js';
68
+ import { resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, resolveSettingsWithSources, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, readLock, aiResourceRoots, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile } from '../chunk-T5TSLSRO.js';
68
69
  import '../chunk-4GY63JU6.js';
69
- import { factoryAssetRoots } from '../chunk-GFCXNFTW.js';
70
- import '../chunk-PMECEZK3.js';
70
+ import { factoryAssetRoots } from '../chunk-SHQMPGOL.js';
71
+ import { deployedDir } from '../chunk-PMECEZK3.js';
71
72
  import { DEFAULT_DRIVER_ID, DRIVER_DEFAULTS } from '../chunk-5BEFNLOR.js';
72
73
  import { findKindDirs } from '../chunk-A2ULN3KX.js';
73
- import { SourceEntryError, SKAILE_YAML_DEFAULT, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, resolveSkWorkspaceConfig, matchPin, coerceVersion, loadSkWorkspaceConfig, normalizeAgentInstances, agentInstanceDiagnostics, storeManifestSlug, isWorkspaceConfigFilename } from '../chunk-JZCSNEHK.js';
74
+ import { SourceEntryError, resolveSkWorkspaceConfig, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, decodeSkaileYaml, matchPin, coerceVersion, loadSkWorkspaceConfig, normalizeAgentInstances, agentInstanceDiagnostics, storeManifestSlug, isWorkspaceConfigFilename } from '../chunk-PNOGX36L.js';
74
75
  import { globalCacheRoot, globalSkaileDir, userConfigPath } from '../chunk-L5VSIPQD.js';
75
76
  import { SUPPORTED_DRIVER_TARGETS, driverTargetForDriver } from '../chunk-CPSIPIX7.js';
76
- import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, encodeSkaileManifest } from '../chunk-IXWODEED.js';
77
+ import { SKAILE_MANIFEST_FILENAME, loadSkPublishManifest, decodeSkaileManifest, isNonAssetPath, isNonAssetDir, encodeSkaileManifest } from '../chunk-CTP3XBMF.js';
77
78
  import { pluginTitle } from '../chunk-RVRB27AN.js';
78
- import { dedupeRequirements, parseFrontmatter, scanDirectory } from '../chunk-Y34MSWEZ.js';
79
- import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, slugifyAssetName, parseAssetRefLoose, assetRefToStr } from '../chunk-4OV5DSBB.js';
79
+ import { dedupeRequirements, parseFrontmatter, scanDirectory, parseRequires } from '../chunk-XTVSNWLL.js';
80
+ import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, depToStr, slugifyAssetName, parseAssetRefLoose, assetRefToStr } from '../chunk-PNTXHTBC.js';
80
81
  import { portableSpawn, portableSpawnSync } from '../chunk-ICSCSM5D.js';
81
- import { openSqlite } from '../chunk-DALV4HHP.js';
82
+ import { openSqlite } from '../chunk-DKXNKFKP.js';
82
83
  import { parseModelRef, resolveEntryBaseUrl } from '../chunk-MJHSLODD.js';
83
84
  import '../chunk-C3CAXQMA.js';
84
- import '../chunk-BOFL7GIF.js';
85
+ import { registerLogStore, LogStore, StdoutSink } from '../chunk-BOFL7GIF.js';
85
86
  import '../chunk-NSBPE2FW.js';
86
87
  import * as fs8 from 'fs';
87
88
  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';
89
+ import * as path22 from 'path';
90
+ import path22__default, { resolve, join } from 'path';
90
91
  import { fileURLToPath } from 'url';
91
92
  import { Help, Command, Option } from 'commander';
92
93
  import { rcompare } from 'semver';
94
+ import * as os from 'os';
95
+ import { homedir } from 'os';
93
96
  import * as p4 from '@clack/prompts';
94
97
  import pc5 from 'picocolors';
95
- import * as os from 'os';
96
98
  import { parse, stringify, parseDocument, isMap, isScalar, isSeq } from 'yaml';
97
99
  import * as readline from 'readline';
98
100
  import { createInterface } from 'readline';
@@ -128,6 +130,45 @@ function filterCatalogAssets(assets, query) {
128
130
  (a) => a.name.toLowerCase().includes(q) || (a.description?.toLowerCase().includes(q) ?? false) || a.publisher.toLowerCase().includes(q)
129
131
  );
130
132
  }
133
+ var STORE_TEST_NAME_RE = /^(test|demo)(-|$)/;
134
+ var STORE_ROW_LIMIT = 20;
135
+ function selectStoreRows(matches, query, all) {
136
+ const q = query?.toLowerCase();
137
+ const rank = (a) => {
138
+ if (!q) return 3;
139
+ const n = a.name.toLowerCase();
140
+ if (n === q) return 0;
141
+ if (n.startsWith(q)) return 1;
142
+ if (n.includes(q)) return 2;
143
+ return 3;
144
+ };
145
+ const ranked = [...matches].sort(
146
+ (a, b) => rank(a) - rank(b) || a.name.localeCompare(b.name) || a.version.localeCompare(b.version)
147
+ );
148
+ if (all) return { shown: ranked, hidden: 0, cut: 0 };
149
+ const keep = ranked.filter(
150
+ (a) => storeNotInstallableReason(a) === void 0 && !STORE_TEST_NAME_RE.test(a.name)
151
+ );
152
+ return {
153
+ shown: keep.slice(0, STORE_ROW_LIMIT),
154
+ hidden: ranked.length - keep.length,
155
+ cut: Math.max(0, keep.length - STORE_ROW_LIMIT)
156
+ };
157
+ }
158
+ function storeSelectionNotes(sel, indent) {
159
+ const notes = [];
160
+ if (sel.cut > 0) {
161
+ notes.push(
162
+ `${indent}${S.dim(`\u2026 ${sel.cut} more store match(es); narrow the query, or pass --all to list every one`)}`
163
+ );
164
+ }
165
+ if (sel.hidden > 0) {
166
+ notes.push(
167
+ `${indent}${S.dim(`${sel.hidden} store entr${sel.hidden === 1 ? "y" : "ies"} hidden: kinds \`add\` cannot install yet (${[...STORE_UNADDABLE_KINDS].join(", ")}), names that are not valid refs, test/demo entries; --all lists them`)}`
168
+ );
169
+ }
170
+ return notes;
171
+ }
131
172
  function nearAssetKind(word) {
132
173
  const w = word.toLowerCase();
133
174
  let best;
@@ -175,7 +216,7 @@ async function runSearch(kind, query, opts) {
175
216
  const showLocal = !opts.store;
176
217
  const showStore = !opts.local;
177
218
  const { resolveConfig } = await import('../library/index.js');
178
- const airGapped = resolveConfig({ projectDir: path18__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
219
+ const airGapped = resolveConfig({ projectDir: path22__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
179
220
  if (showLocal) {
180
221
  await searchLocal(query, kind, opts, showStore, airGapped);
181
222
  }
@@ -184,7 +225,7 @@ async function runSearch(kind, query, opts) {
184
225
  }
185
226
  }
186
227
  async function searchIndex(query, kind) {
187
- const { openLibrary: openLibrary2 } = await import('../open-library-4QSUORI6.js');
228
+ const { openLibrary: openLibrary2 } = await import('../open-library-N6ESO6IK.js');
188
229
  const library = await openLibrary2();
189
230
  try {
190
231
  const { libraryDirMissing: libraryDirMissing2 } = await import('../library/index.js');
@@ -221,7 +262,7 @@ async function searchIndex(query, kind) {
221
262
  }
222
263
  }
223
264
  async function searchFactory(projectDir, query, kind) {
224
- const prefixes = factoryAssetRoots().map((r) => r.endsWith(path18__default.sep) ? r : r + path18__default.sep);
265
+ const prefixes = factoryAssetRoots().map((r) => r.endsWith(path22__default.sep) ? r : r + path22__default.sep);
225
266
  const isFactoryPath = (p6) => prefixes.some((fp) => p6 === fp.slice(0, -1) || p6.startsWith(fp));
226
267
  try {
227
268
  const entries = await new AssetManager({ registry: getKindRegistry(), projectDir }).search(
@@ -331,11 +372,11 @@ async function expandCompetingOrigins(entries, projectDir) {
331
372
  return out;
332
373
  }
333
374
  async function searchLocal(query, kind, opts, showStore, airGapped) {
334
- const projectDir = path18__default.resolve(opts.projectDir);
375
+ const projectDir = path22__default.resolve(opts.projectDir);
335
376
  const factory = await searchFactory(projectDir, query, kind);
336
377
  let entries = unionEntries(await searchIndex(query, kind), factory);
337
378
  if (entries.length === 0 && !query && !kind && !airGapped) {
338
- const { autoSyncForSearch } = await import('../source-E4VAT5RZ.js');
379
+ const { autoSyncForSearch } = await import('../source-DX5SGWEI.js');
339
380
  if (await autoSyncForSearch(projectDir)) {
340
381
  entries = unionEntries(await searchIndex(query, kind), factory);
341
382
  }
@@ -455,24 +496,26 @@ async function searchStore(query, kind, opts, airGapped) {
455
496
  logInfo("air-gapped (cache_ttl: 0) \u2014 local sources only");
456
497
  return;
457
498
  }
458
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-4QSUORI6.js');
499
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-N6ESO6IK.js');
459
500
  try {
460
- const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
501
+ const remote = await openCatalogSource2({ projectDir: path22__default.resolve(opts.projectDir) });
461
502
  const assets = await remote.listAssets(kind ? { kind } : {});
462
- const results = filterCatalogAssets(assets, query);
463
- if (results.length > 0) {
503
+ const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
504
+ if (sel.shown.length > 0) {
464
505
  console.log(`
465
506
  ${S.heading("Store:")}`);
466
- for (const row of formatStoreRows(results, " ")) console.log(row);
507
+ for (const row of formatStoreRows(sel.shown, " ")) console.log(row);
467
508
  } else if (opts.store) {
468
509
  logInfo("No results in store");
469
510
  }
511
+ for (const note of storeSelectionNotes(sel, " ")) console.log(note);
470
512
  } catch (e) {
471
513
  const local = e instanceof LocalCatalogDisabledError2;
472
514
  if (opts.store) {
473
515
  logErr(
474
- local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${e.message}`
516
+ local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${await describeStoreFailure(e, path22__default.resolve(opts.projectDir))}`
475
517
  );
518
+ process.exit(1);
476
519
  } else {
477
520
  logInfo(
478
521
  local ? "remote catalog disabled (catalog.url: local) \u2014 showing local results only" : "store unavailable \u2014 showing local results only (run with --store to see the error)"
@@ -480,8 +523,16 @@ async function searchStore(query, kind, opts, airGapped) {
480
523
  }
481
524
  }
482
525
  }
526
+ async function describeStoreFailure(err2, projectDir) {
527
+ const { resolveConfig, describeCatalogError } = await import('../library/index.js');
528
+ const url = resolveConfig({ projectDir }).catalog.url;
529
+ return `${describeCatalogError(err2, url)}. Check the catalog with \`skaile catalog test\`.`;
530
+ }
483
531
  function makeSearchCommand() {
484
- return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind (a single non-kind argument is the query)").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").action(async (kind, query, opts) => {
532
+ return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind (a single non-kind argument is the query)").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").option(
533
+ "--all",
534
+ `Store leg: list every match (default: ${STORE_ROW_LIMIT} rows, only what add can install)`
535
+ ).action(async (kind, query, opts) => {
485
536
  await runSearch(kind, query, opts);
486
537
  });
487
538
  }
@@ -578,17 +629,11 @@ function makeAddCommand() {
578
629
  process.exit(1);
579
630
  }
580
631
  const harnesses = parseHarnessFilter(opts.harness);
581
- if (!opts.global && harnesses === void 0) {
582
- const projectDir = path18__default.resolve(opts.projectDir);
583
- if (!existsSync(path18__default.join(projectDir, SKAILE_YAML_DEFAULT))) {
584
- logErr(`No ${S.cmd("skaile.yaml")} found. Run ${S.cmd("skaile init")} to create one.`);
585
- process.exit(1);
586
- }
587
- }
632
+ if (!opts.global && harnesses === void 0) requireProjectConfig(opts.projectDir);
588
633
  const warnings = deferredWarnings();
589
634
  const am2 = new AssetManager({
590
635
  registry: getKindRegistry(),
591
- projectDir: path18__default.resolve(opts.projectDir),
636
+ projectDir: path22__default.resolve(opts.projectDir),
592
637
  global: opts.global || harnesses !== void 0,
593
638
  harnesses,
594
639
  driverTarget: opts.target,
@@ -600,9 +645,11 @@ function makeAddCommand() {
600
645
  const libraryOf = /* @__PURE__ */ new Map();
601
646
  let presets = [];
602
647
  const skippedLinks = /* @__PURE__ */ new Set();
648
+ const skippedEnv = /* @__PURE__ */ new Set();
603
649
  const added = await am2.add(ref, {
604
650
  link: opts.link,
605
651
  onLibraryOrigin: (deployedRef, library) => libraryOf.set(deployedRef, library),
652
+ onLibraryMoved: (m) => warnings.push(`${m.ref} moved from ${m.from} to ${m.to}`),
606
653
  onPresets: (expanded) => {
607
654
  presets = expanded;
608
655
  },
@@ -611,6 +658,14 @@ function makeAddCommand() {
611
658
  if (skippedLinks.has(linkPath)) return;
612
659
  skippedLinks.add(linkPath);
613
660
  warnings.push(`skipped symlink ${linkPath}`);
661
+ },
662
+ // A `.env` in an asset root is never deployed or hashed: say so once per file.
663
+ onEnvFile: (_assetRef, envPath) => {
664
+ if (skippedEnv.has(envPath)) return;
665
+ skippedEnv.add(envPath);
666
+ warnings.push(
667
+ `${envPath} is a .env file: it is not deployed or hashed with the asset. Keep secrets out of an asset root`
668
+ );
614
669
  }
615
670
  });
616
671
  spinner.stop("Done");
@@ -640,6 +695,20 @@ function makeAddCommand() {
640
695
  const library = libraryOf.get(a);
641
696
  logOk(library ? `${a} (library ${library})` : a);
642
697
  }
698
+ if (am2.global) {
699
+ for (const a of added) {
700
+ const { kind, name } = parseAssetRef(a);
701
+ const component = installTargetOf(getKindRegistry(), kind);
702
+ if (!component) continue;
703
+ for (const harness of am2.deployTargets()) {
704
+ const dir = deployedDir(component, name, harness, true);
705
+ if (existsSync(dir)) logInfo(S.dim(`${harness}: ${dir.replace(homedir(), "~")}`));
706
+ }
707
+ }
708
+ }
709
+ if (added.length > 1) {
710
+ logInfo(S.dim(`${added.length} assets deployed (${ref} and ${added.length - 1} more)`));
711
+ }
643
712
  }
644
713
  const addOrigins = await competingOriginsOf(am2, ref);
645
714
  if (addOrigins) {
@@ -665,9 +734,11 @@ function makeRemoveCommand() {
665
734
  "Comma-separated global harnesses to undeploy from (default: all resolved); implies --global"
666
735
  ).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) => {
667
736
  const harnesses = parseHarnessFilter(opts.harness);
737
+ if (!opts.global && harnesses === void 0)
738
+ requireProjectConfig(opts.projectDir, { allowMissing: true });
668
739
  const am2 = new AssetManager({
669
740
  registry: getKindRegistry(),
670
- projectDir: path18__default.resolve(opts.projectDir),
741
+ projectDir: path22__default.resolve(opts.projectDir),
671
742
  global: opts.global || harnesses !== void 0,
672
743
  harnesses,
673
744
  driverTarget: opts.target
@@ -729,7 +800,7 @@ function makeListCommand() {
729
800
  }
730
801
  const am2 = new AssetManager({
731
802
  registry: getKindRegistry(),
732
- projectDir: path18__default.resolve(opts.projectDir),
803
+ projectDir: path22__default.resolve(opts.projectDir),
733
804
  driverTarget: opts.target
734
805
  });
735
806
  let declared;
@@ -777,7 +848,7 @@ function makeListCommand() {
777
848
  function runGlobalList(kind, opts, harnesses) {
778
849
  const am2 = new AssetManager({
779
850
  registry: getKindRegistry(),
780
- projectDir: path18__default.resolve(opts.projectDir),
851
+ projectDir: path22__default.resolve(opts.projectDir),
781
852
  global: true,
782
853
  harnesses
783
854
  });
@@ -850,7 +921,7 @@ async function resolveInfoEntry(am2, ref, opts) {
850
921
  return { entry: match ?? deployed };
851
922
  }
852
923
  const lookup = opts.storeLookup ?? (async (filter) => {
853
- const { resolveCatalogSource } = await import('../open-library-4QSUORI6.js');
924
+ const { resolveCatalogSource } = await import('../open-library-N6ESO6IK.js');
854
925
  const { source, close } = await resolveCatalogSource({ projectDir: opts.projectDir });
855
926
  try {
856
927
  return await source.listAssets(filter);
@@ -866,7 +937,7 @@ async function resolveInfoEntry(am2, ref, opts) {
866
937
  );
867
938
  return { entry: hit ? catalogAssetToEntry(hit) : null };
868
939
  } catch (err2) {
869
- const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-4QSUORI6.js');
940
+ const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-N6ESO6IK.js');
870
941
  const storeNote = err2 instanceof Error ? err2.message : String(err2);
871
942
  const disabled = err2 instanceof LocalCatalogDisabledError2 || /catalog\.url/i.test(storeNote);
872
943
  return { entry: null, storeNote, ...disabled ? { storeDisabled: true } : {} };
@@ -882,7 +953,8 @@ function infoNotFoundHint(ref, lookup) {
882
953
  }
883
954
  function makeInfoCommand() {
884
955
  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) => {
885
- const projectDir = path18__default.resolve(opts.projectDir);
956
+ const projectDir = path22__default.resolve(opts.projectDir);
957
+ requireProjectConfig(projectDir, { allowMissing: true });
886
958
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
887
959
  const lookup = await resolveInfoEntry(am2, ref, { projectDir });
888
960
  const entry = lookup.entry;
@@ -931,7 +1003,7 @@ function makeCreateCommand() {
931
1003
  new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...SCAFFOLD_KINDS])
932
1004
  ).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
933
1005
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
934
- const destDir = opts.dir ? path18__default.resolve(opts.dir) : process.cwd();
1006
+ const destDir = opts.dir ? path22__default.resolve(opts.dir) : process.cwd();
935
1007
  const result = am2.create(name, opts.kind, destDir);
936
1008
  if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
937
1009
  else {
@@ -942,31 +1014,31 @@ function makeCreateCommand() {
942
1014
  }
943
1015
  function makeDoctorCommand() {
944
1016
  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) => {
1017
+ requireProjectConfig(opts.projectDir);
945
1018
  const am2 = new AssetManager({
946
1019
  registry: getKindRegistry(),
947
- projectDir: path18__default.resolve(opts.projectDir)
1020
+ projectDir: path22__default.resolve(opts.projectDir)
948
1021
  });
949
- const { gaps, requirements } = await am2.projectState();
1022
+ const { gaps } = await am2.projectState();
950
1023
  if (gaps.length === 0) {
951
1024
  logOk("No missing dependencies.");
952
1025
  return;
953
1026
  }
954
1027
  process.exitCode = 1;
955
1028
  for (const g of gaps) if (g.type !== "requires") logErr(g.message);
956
- const missing = requirements.filter((i) => !i.unresolved);
1029
+ const missing = gaps.filter((g) => g.type === "requires" && g.asset !== void 0);
957
1030
  if (missing.length === 0) return;
958
- const assetW = Math.max(5, ...missing.map((i) => `${i.assetKind}:${i.assetName}`.length));
959
- const depW = Math.max(11, ...missing.map((i) => `${i.depKind}:${i.depName}`.length));
1031
+ const assetW = Math.max(5, ...missing.map((g) => (g.asset ?? "").length));
1032
+ const depW = Math.max(11, ...missing.map((g) => g.ref.length));
960
1033
  console.log();
961
1034
  console.log(
962
1035
  ` ${S.dim("ASSET".padEnd(assetW))} ${S.dim("MISSING DEP".padEnd(depW))} ${S.dim("IN REPOS")}`
963
1036
  );
964
1037
  console.log(` ${S.rule(assetW + depW + 15)}`);
965
- for (const i of missing) {
966
- const asset = `${i.assetKind}:${i.assetName}`;
967
- const dep = `${i.depKind}:${i.depName}`;
968
- const status4 = i.inRepos ? S.warn("fixable") : S.err("not found");
969
- console.log(` ${asset.padEnd(assetW)} ${dep.padEnd(depW)} ${status4}`);
1038
+ for (const g of missing) {
1039
+ const asset = g.asset ?? "";
1040
+ const status4 = g.manualFix ? S.err("not found") : S.warn("fixable");
1041
+ console.log(` ${asset.padEnd(assetW)} ${g.ref.padEnd(depW)} ${status4}`);
970
1042
  }
971
1043
  console.log();
972
1044
  });
@@ -977,20 +1049,20 @@ function claudeSkillRoots() {
977
1049
  const roots = [];
978
1050
  const override = process.env.SKAILE_CLAUDE_SKILLS_DIR;
979
1051
  if (override) roots.push(override);
980
- roots.push(path18.join(os.homedir(), ".claude", "skills"));
1052
+ roots.push(path22.join(os.homedir(), ".claude", "skills"));
981
1053
  return roots;
982
1054
  }
983
1055
  function resolveImportSource(nameOrPath) {
984
- const asPath = path18.resolve(nameOrPath);
1056
+ const asPath = path22.resolve(nameOrPath);
985
1057
  if (fs8.existsSync(asPath)) {
986
- const dir = fs8.statSync(asPath).isDirectory() ? asPath : path18.dirname(asPath);
987
- const skillFile = path18.join(dir, "SKILL.md");
1058
+ const dir = fs8.statSync(asPath).isDirectory() ? asPath : path22.dirname(asPath);
1059
+ const skillFile = path22.join(dir, "SKILL.md");
988
1060
  if (fs8.existsSync(skillFile)) return { dir, skillFile, via: "path" };
989
1061
  }
990
- if (!nameOrPath.includes(path18.sep) && !nameOrPath.startsWith(".")) {
1062
+ if (!nameOrPath.includes(path22.sep) && !nameOrPath.startsWith(".")) {
991
1063
  for (const root of claudeSkillRoots()) {
992
- const dir = path18.join(root, nameOrPath);
993
- const skillFile = path18.join(dir, "SKILL.md");
1064
+ const dir = path22.join(root, nameOrPath);
1065
+ const skillFile = path22.join(dir, "SKILL.md");
994
1066
  if (fs8.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
995
1067
  }
996
1068
  }
@@ -1046,6 +1118,12 @@ ${body}
1046
1118
  }
1047
1119
 
1048
1120
  // cli/src/commands/asset-cmd.ts
1121
+ function copyFilter(root) {
1122
+ return (src) => {
1123
+ const rel = path22.relative(root, src).split(path22.sep).join("/");
1124
+ return rel === "" || !(isNonAssetPath(rel) || isNonAssetDir(path22.basename(src)));
1125
+ };
1126
+ }
1049
1127
  async function resolveDefByRef(library, ref, opts) {
1050
1128
  let parsed;
1051
1129
  try {
@@ -1120,16 +1198,16 @@ function makeAssetCommand() {
1120
1198
  exitOnManifestPublisherProblems(target.path, target.name);
1121
1199
  const rawSkill = fs8.readFileSync(src.skillFile, "utf8");
1122
1200
  const norm = opts.normalize ? normalizeSkillContent(rawSkill, {
1123
- fallbackName: path18.basename(src.dir),
1201
+ fallbackName: path22.basename(src.dir),
1124
1202
  version: opts.version,
1125
1203
  stage: opts.stage
1126
- }) : { content: rawSkill, name: path18.basename(src.dir), changed: false, notes: [] };
1204
+ }) : { content: rawSkill, name: path22.basename(src.dir), changed: false, notes: [] };
1127
1205
  if (!opts.normalize && !isValidAssetName(norm.name)) {
1128
1206
  logWarn(
1129
1207
  `Name "${norm.name}" is not canonical (kebab-case); \`skaile validate\` will reject this manifest entry. Drop --no-normalize to slugify it.`
1130
1208
  );
1131
1209
  }
1132
- const destDir = path18.join(target.path, norm.name);
1210
+ const destDir = path22.join(target.path, norm.name);
1133
1211
  if (fs8.existsSync(destDir)) {
1134
1212
  logErr(`Destination already exists: ${destDir}`);
1135
1213
  process.exit(1);
@@ -1141,8 +1219,27 @@ function makeAssetCommand() {
1141
1219
  );
1142
1220
  process.exit(1);
1143
1221
  }
1144
- fs8.cpSync(src.dir, destDir, { recursive: true });
1145
- fs8.writeFileSync(path18.join(destDir, "SKILL.md"), norm.content, "utf8");
1222
+ const importedFm = parseFrontmatter(norm.content);
1223
+ const checked = checkAsset(
1224
+ "skill",
1225
+ importedFm.data,
1226
+ importedFm.body,
1227
+ norm.name,
1228
+ getKindRegistry(),
1229
+ norm.content
1230
+ );
1231
+ if (checked.errors.length > 0) {
1232
+ for (const f of checked.errors) logErr(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
1233
+ logErr(
1234
+ `Not imported: ${checked.errors.length} problem(s) in SKILL.md. Fix them in ${src.skillFile} (or drop --no-normalize) and run the import again.`
1235
+ );
1236
+ process.exit(1);
1237
+ }
1238
+ for (const f of checked.advisories) {
1239
+ logWarn(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
1240
+ }
1241
+ fs8.cpSync(src.dir, destDir, { recursive: true, filter: copyFilter(src.dir) });
1242
+ fs8.writeFileSync(path22.join(destDir, "SKILL.md"), norm.content, "utf8");
1146
1243
  for (const note of norm.notes) logInfo(` \u2022 ${note}`);
1147
1244
  const fm = parseFrontmatter(norm.content).data;
1148
1245
  for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
@@ -1208,23 +1305,23 @@ function makeAssetCommand() {
1208
1305
  );
1209
1306
  process.exit(1);
1210
1307
  }
1211
- const basename3 = path18.basename(srcPath);
1308
+ const basename3 = path22.basename(srcPath);
1212
1309
  const destDir = target.path;
1213
1310
  fs8.mkdirSync(destDir, { recursive: true });
1214
- const destPath = path18.join(destDir, basename3);
1311
+ const destPath = path22.join(destDir, basename3);
1215
1312
  if (fs8.existsSync(destPath)) {
1216
1313
  logErr(`Destination already exists: ${destPath}`);
1217
1314
  process.exit(1);
1218
1315
  }
1219
1316
  switch (opts.mode) {
1220
1317
  case "copy":
1221
- fs8.cpSync(srcPath, destPath, { recursive: true });
1318
+ fs8.cpSync(srcPath, destPath, { recursive: true, filter: copyFilter(srcPath) });
1222
1319
  break;
1223
1320
  case "move":
1224
1321
  fs8.renameSync(srcPath, destPath);
1225
1322
  break;
1226
1323
  case "link":
1227
- fs8.symlinkSync(path18.resolve(srcPath), destPath);
1324
+ fs8.symlinkSync(path22.resolve(srcPath), destPath);
1228
1325
  break;
1229
1326
  }
1230
1327
  if (target.backend === "git" && opts.commit) {
@@ -1239,6 +1336,11 @@ function makeAssetCommand() {
1239
1336
  }
1240
1337
  }
1241
1338
  logOk(`Migrated ${basename3} \u2192 ${target.name} (${opts.mode})`);
1339
+ const publisher = loadSkPublishManifest(target.path)?.publisher ?? "<publisher>";
1340
+ const migratedKind = fs8.existsSync(path22.join(destPath, "SKILL.md")) ? "skill" : "<kind>";
1341
+ logInfo(
1342
+ `Not addable yet: run ${S.cmd(`skaile library index ${target.name}`)}, then ${S.cmd(`skaile add ${migratedKind}:@${publisher.replace(/^@/, "")}/${basename3}`)}`
1343
+ );
1242
1344
  if (opts.mode === "move") {
1243
1345
  logInfo("Source moved into the library \u2014 future edits modify the library copy.");
1244
1346
  } else if (opts.mode === "copy") {
@@ -1354,14 +1456,14 @@ function makeAuthCommand() {
1354
1456
  }
1355
1457
  function collectCacheTargets(scope) {
1356
1458
  const out = [];
1357
- out.push(path18__default.join(scope.projectDir, ".skaile", "cache"));
1358
- out.push(path18__default.join(scope.projectDir, ".skaile", "store-cache"));
1359
- out.push(path18__default.join(scope.projectDir, ".skaile", "repos"));
1459
+ out.push(path22__default.join(scope.projectDir, ".skaile", "cache"));
1460
+ out.push(path22__default.join(scope.projectDir, ".skaile", "store-cache"));
1461
+ out.push(path22__default.join(scope.projectDir, ".skaile", "repos"));
1360
1462
  if (scope.global) {
1361
1463
  out.push(globalCacheRoot());
1362
1464
  const home = globalSkaileDir();
1363
- out.push(path18__default.join(home, "repos"));
1364
- out.push(path18__default.join(home, "catalog-cache"));
1465
+ out.push(path22__default.join(home, "repos"));
1466
+ out.push(path22__default.join(home, "catalog-cache"));
1365
1467
  }
1366
1468
  return out;
1367
1469
  }
@@ -1375,7 +1477,7 @@ function dirSize(target) {
1375
1477
  function dirSizeOfDir(dir) {
1376
1478
  let total = 0;
1377
1479
  for (const ent of readdirSync(dir, { withFileTypes: true })) {
1378
- const child = path18__default.join(dir, ent.name);
1480
+ const child = path22__default.join(dir, ent.name);
1379
1481
  if (ent.isSymbolicLink()) continue;
1380
1482
  if (ent.isDirectory()) total += dirSizeOfDir(child);
1381
1483
  else if (ent.isFile()) total += statSync(child).size;
@@ -1401,7 +1503,7 @@ function makeCacheCommand() {
1401
1503
  const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
1402
1504
  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) => {
1403
1505
  const targets = collectCacheTargets({
1404
- projectDir: path18__default.resolve(opts.projectDir),
1506
+ projectDir: path22__default.resolve(opts.projectDir),
1405
1507
  global: opts.global
1406
1508
  }).filter((t) => existsSync(t));
1407
1509
  if (targets.length === 0) {
@@ -1431,12 +1533,12 @@ function makeCacheCommand() {
1431
1533
  for (const r of removed) logOk(`Removed ${r}`);
1432
1534
  });
1433
1535
  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) => {
1434
- console.log(path18__default.join(path18__default.resolve(opts.projectDir), ".skaile", "cache"));
1536
+ console.log(path22__default.join(path22__default.resolve(opts.projectDir), ".skaile", "cache"));
1435
1537
  if (opts.global) console.log(globalCacheRoot());
1436
1538
  });
1437
1539
  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) => {
1438
1540
  const targets = collectCacheTargets({
1439
- projectDir: path18__default.resolve(opts.projectDir),
1541
+ projectDir: path22__default.resolve(opts.projectDir),
1440
1542
  global: opts.global
1441
1543
  });
1442
1544
  console.log();
@@ -1452,7 +1554,7 @@ function makeCatalogCommand() {
1452
1554
  const catalog = new Command("catalog").description("Catalog source health and configuration");
1453
1555
  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) => {
1454
1556
  const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
1455
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : void 0;
1557
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : void 0;
1456
1558
  const cfg = resolveConfig({ projectDir });
1457
1559
  const baseUrl = opts.url ?? cfg.catalog.url;
1458
1560
  if (isLocalCatalogUrl(baseUrl)) {
@@ -1470,7 +1572,7 @@ function makeCatalogCommand() {
1470
1572
  });
1471
1573
  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) => {
1472
1574
  const { resolveConfig } = await import('../library/index.js');
1473
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : void 0;
1575
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : void 0;
1474
1576
  const cfg = resolveConfig({ projectDir });
1475
1577
  console.log(`url: ${cfg.catalog.url}`);
1476
1578
  console.log(`framing: ${cfg.catalog.framing}`);
@@ -1479,7 +1581,7 @@ function makeCatalogCommand() {
1479
1581
  return catalog;
1480
1582
  }
1481
1583
  async function runLocalCatalogTest(projectDir) {
1482
- const { resolveCatalogSource } = await import('../open-library-4QSUORI6.js');
1584
+ const { resolveCatalogSource } = await import('../open-library-N6ESO6IK.js');
1483
1585
  let resolved;
1484
1586
  try {
1485
1587
  resolved = await resolveCatalogSource({ projectDir });
@@ -1622,7 +1724,7 @@ async function scanLibraryFlowEntries() {
1622
1724
  const { LocalIndex, resolveIndexPath, scanAuthoringLibraries } = await import('../library/index.js');
1623
1725
  const indexPath = resolveIndexPath();
1624
1726
  if (!existsSync(indexPath)) return entries;
1625
- const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-VCKS3MP5.js');
1727
+ const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-CBZ5MWTT.js');
1626
1728
  const index = new LocalIndex({ indexPath });
1627
1729
  try {
1628
1730
  for (const { assets } of await scanAuthoringLibraries(index, getKindRegistry2())) {
@@ -1673,9 +1775,9 @@ function findSkills() {
1673
1775
  }
1674
1776
  function walkSkills(dir, out) {
1675
1777
  for (const entry of fs8__default.readdirSync(dir, { withFileTypes: true })) {
1676
- const full = path18__default.join(dir, entry.name);
1778
+ const full = path22__default.join(dir, entry.name);
1677
1779
  if (entry.isDirectory()) {
1678
- const skillMd = path18__default.join(full, "SKILL.md");
1780
+ const skillMd = path22__default.join(full, "SKILL.md");
1679
1781
  if (fs8__default.existsSync(skillMd)) {
1680
1782
  out.push({ name: entry.name, path: full, skillPath: skillMd });
1681
1783
  } else {
@@ -1697,7 +1799,7 @@ function resolveFlowIds() {
1697
1799
  }
1698
1800
  }
1699
1801
  function resolveSessionIds(projectDir) {
1700
- const sessionsDir = path18__default.join(projectDir, ".skaile", "sessions");
1802
+ const sessionsDir = path22__default.join(projectDir, ".skaile", "sessions");
1701
1803
  if (!fs8__default.existsSync(sessionsDir)) return [];
1702
1804
  try {
1703
1805
  return fs8__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
@@ -1753,6 +1855,33 @@ function resolveDynamic(words, cword) {
1753
1855
  return null;
1754
1856
  }
1755
1857
  var PERSONAL_KEYS = /* @__PURE__ */ new Set(["driver", "model"]);
1858
+ var CATALOG_KEYS = /* @__PURE__ */ new Set(["catalog.url", "catalog.cache_ttl", "catalog.framing"]);
1859
+ async function setCatalogKey(key, raw) {
1860
+ const { CatalogConfigSchema, saveConfig } = await import('../library/index.js');
1861
+ const { parse: parseYaml5 } = await import('yaml');
1862
+ const field = key.slice("catalog.".length);
1863
+ const value = field === "cache_ttl" ? /^\d+$/.test(raw.trim()) ? Number(raw) : raw : raw;
1864
+ const checked = CatalogConfigSchema.safeParse({ [field]: value });
1865
+ if (!checked.success) {
1866
+ const hint = field === "url" ? 'a http(s) URL, or "local" to turn the remote catalog off' : field === "cache_ttl" ? "a whole number of seconds (0 = air-gapped)" : '"trpc" or "rest"';
1867
+ logErr(`'${key}' must be ${hint}; got "${raw}".`);
1868
+ process.exit(1);
1869
+ }
1870
+ const filePath = userConfigPath();
1871
+ const fs13 = await import('fs');
1872
+ let existing = {};
1873
+ if (fs13.existsSync(filePath)) {
1874
+ const parsed = parseYaml5(fs13.readFileSync(filePath, "utf-8"));
1875
+ if (parsed && typeof parsed === "object") existing = parsed;
1876
+ }
1877
+ const catalog = {
1878
+ ...existing.catalog ?? {},
1879
+ [field]: checked.data[field]
1880
+ };
1881
+ saveConfig(filePath, { ...existing, catalog });
1882
+ logOk(`Set ${pc5.bold(key)} = ${String(checked.data[field])}`);
1883
+ console.log(S.dim(` \u2192 ${filePath}`));
1884
+ }
1756
1885
  var API_KEY_PREFIX = "apiKey.";
1757
1886
  function collectWorkspaceDefaults(projectDir) {
1758
1887
  const wsDefaults = {};
@@ -1768,14 +1897,17 @@ function collectWorkspaceDefaults(projectDir) {
1768
1897
  }
1769
1898
  return wsDefaults;
1770
1899
  }
1771
- function printEffectiveSection(config) {
1900
+ function printEffectiveSection(config, sources) {
1772
1901
  console.log();
1773
1902
  console.log(S.heading(" Effective Config"));
1774
1903
  console.log(` ${S.rule(40)}`);
1775
1904
  for (const key of ["driver", "model"]) {
1776
1905
  const value = config[key];
1777
1906
  if (value !== void 0) {
1778
- console.log(` ${S.label(`${key}:`.padEnd(16))} ${value}`);
1907
+ const origin = sources[key];
1908
+ console.log(
1909
+ ` ${S.label(`${key}:`.padEnd(16))} ${value}${origin ? ` ${S.dim(`(${origin})`)}` : ""}`
1910
+ );
1779
1911
  }
1780
1912
  }
1781
1913
  }
@@ -1839,17 +1971,18 @@ function printResolvedPathsSection(config) {
1839
1971
  console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
1840
1972
  }
1841
1973
  async function showConfig(opts) {
1842
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
1974
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
1843
1975
  let config;
1976
+ let sources;
1844
1977
  let wsDefaults;
1845
1978
  try {
1846
- config = await resolveSettings(projectDir);
1979
+ ({ settings: config, sources } = await resolveSettingsWithSources(projectDir));
1847
1980
  wsDefaults = collectWorkspaceDefaults(projectDir);
1848
1981
  } catch (error) {
1849
1982
  logErr(error instanceof Error ? error.message : String(error));
1850
1983
  process.exit(1);
1851
1984
  }
1852
- printEffectiveSection(config);
1985
+ printEffectiveSection(config, sources);
1853
1986
  printWorkspaceDefaultsSection(wsDefaults);
1854
1987
  printModelSelectionSection(config, projectDir);
1855
1988
  printResolvedPathsSection(config);
@@ -1884,13 +2017,25 @@ function makeConfigCommand() {
1884
2017
  const cmd = new Command("config").description("Manage personal config (.skaile/settings.json)");
1885
2018
  cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
1886
2019
  cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").action(async (key, opts) => {
1887
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2020
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
2021
+ if (CATALOG_KEYS.has(key)) {
2022
+ const { resolveConfig } = await import('../library/index.js');
2023
+ const field = key.slice("catalog.".length);
2024
+ console.log(resolveConfig({ projectDir }).catalog[field]);
2025
+ return;
2026
+ }
1888
2027
  const config = await resolveSettings(projectDir);
1889
2028
  const value = config[key];
1890
2029
  console.log(value ?? S.dim("(not set)"));
1891
2030
  });
1892
- 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) => {
1893
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2031
+ cmd.command("set <key> <value>").description(
2032
+ "Set a personal config value (driver, model, apiKey.<provider>) or a catalog setting (catalog.url, catalog.cache_ttl, catalog.framing)"
2033
+ ).option("--project-dir <path>", "Project directory").option("--global", "Write to ~/.skaile/settings.json instead of project-local").action(async (key, value, opts) => {
2034
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
2035
+ if (CATALOG_KEYS.has(key)) {
2036
+ await setCatalogKey(key, value);
2037
+ return;
2038
+ }
1894
2039
  if (key === "provider" || key === "cloud" || key === "cloudConfig") {
1895
2040
  logErr(
1896
2041
  `'${key}' is no longer a setting \u2014 an endpoint is an AI provider registry entry and a session selects one with a model reference.
@@ -1917,6 +2062,14 @@ function makeConfigCommand() {
1917
2062
  await saveSettings({ ...existing, [key]: value }, filePath);
1918
2063
  logOk(`Set ${pc5.bold(key)} = ${value}`);
1919
2064
  console.log(S.dim(` \u2192 ${filePath}`));
2065
+ if (key === "driver") {
2066
+ const projectDriver = resolveSkWorkspaceConfig(projectDir).agent_config?.default?.driver;
2067
+ if (projectDriver && projectDriver !== value) {
2068
+ logWarn(
2069
+ `skaile.yaml sets driver ${projectDriver}; a personal driver does not override the project harness. Change agent-config.default.driver in skaile.yaml to move the project.`
2070
+ );
2071
+ }
2072
+ }
1920
2073
  if (key === "model") {
1921
2074
  const view = loadRegistryView({ projectDir });
1922
2075
  const resolved = parseModelRef(value, view.merged);
@@ -2230,8 +2383,8 @@ function makeConnectorCommand() {
2230
2383
  async (driver, opts) => {
2231
2384
  const { installNpmPackages } = await import('../connectors/index.js');
2232
2385
  const { scanDirectory: scanDirectory2, factoryAssetRoots: factoryAssetRoots2, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
2233
- const projectDir = path18__default.resolve(opts.projectDir);
2234
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
2386
+ const projectDir = path22__default.resolve(opts.projectDir);
2387
+ const yamlPath = path22__default.join(projectDir, "skaile.yaml");
2235
2388
  if (!existsSync(yamlPath)) {
2236
2389
  logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
2237
2390
  process.exit(1);
@@ -2291,8 +2444,8 @@ ${installResult.output}`);
2291
2444
  );
2292
2445
  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) => {
2293
2446
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
2294
- const projectDir = path18__default.resolve(opts.projectDir);
2295
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
2447
+ const projectDir = path22__default.resolve(opts.projectDir);
2448
+ const yamlPath = path22__default.join(projectDir, "skaile.yaml");
2296
2449
  if (!existsSync(yamlPath)) {
2297
2450
  logErr("No skaile.yaml found in current directory.");
2298
2451
  process.exit(1);
@@ -2309,7 +2462,7 @@ ${installResult.output}`);
2309
2462
  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) => {
2310
2463
  const res = await import('../connectors/index.js');
2311
2464
  res.registerBuiltinConnectors();
2312
- const projectDir = path18__default.resolve(opts.projectDir);
2465
+ const projectDir = path22__default.resolve(opts.projectDir);
2313
2466
  const declarations = res.loadConnectorDeclarations(projectDir);
2314
2467
  if (declarations.length === 0) {
2315
2468
  console.log("No connectors configured in skaile.yaml.");
@@ -2333,7 +2486,7 @@ ${installResult.output}`);
2333
2486
  await manager.disconnectAll();
2334
2487
  });
2335
2488
  cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
2336
- const projectDir = path18__default.resolve(opts.projectDir);
2489
+ const projectDir = path22__default.resolve(opts.projectDir);
2337
2490
  const manager = await connectConnectors(projectDir);
2338
2491
  try {
2339
2492
  console.log(JSON.stringify(manager.listConnectors(), null, 2));
@@ -2342,7 +2495,7 @@ ${installResult.output}`);
2342
2495
  }
2343
2496
  });
2344
2497
  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) => {
2345
- const projectDir = path18__default.resolve(opts.projectDir);
2498
+ const projectDir = path22__default.resolve(opts.projectDir);
2346
2499
  const manager = await connectConnectors(projectDir);
2347
2500
  try {
2348
2501
  if (opts.all) {
@@ -2366,7 +2519,7 @@ ${installResult.output}`);
2366
2519
  }
2367
2520
  });
2368
2521
  cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
2369
- const projectDir = path18__default.resolve(opts.projectDir);
2522
+ const projectDir = path22__default.resolve(opts.projectDir);
2370
2523
  const manager = await connectConnectors(projectDir);
2371
2524
  try {
2372
2525
  if (!manager.has(id)) {
@@ -2381,7 +2534,7 @@ ${installResult.output}`);
2381
2534
  }
2382
2535
  });
2383
2536
  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) => {
2384
- const projectDir = path18__default.resolve(opts.projectDir);
2537
+ const projectDir = path22__default.resolve(opts.projectDir);
2385
2538
  const manager = await connectConnectors(projectDir);
2386
2539
  try {
2387
2540
  const content = await manager.read(id, resourcePath);
@@ -2391,7 +2544,7 @@ ${installResult.output}`);
2391
2544
  }
2392
2545
  });
2393
2546
  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) => {
2394
- const projectDir = path18__default.resolve(opts.projectDir);
2547
+ const projectDir = path22__default.resolve(opts.projectDir);
2395
2548
  const manager = await connectConnectors(projectDir);
2396
2549
  try {
2397
2550
  await manager.write(id, resourcePath, { data: content });
@@ -2401,7 +2554,7 @@ ${installResult.output}`);
2401
2554
  }
2402
2555
  });
2403
2556
  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) => {
2404
- const projectDir = path18__default.resolve(opts.projectDir);
2557
+ const projectDir = path22__default.resolve(opts.projectDir);
2405
2558
  const manager = await connectConnectors(projectDir);
2406
2559
  try {
2407
2560
  const entries = await manager.list(id, resourcePath, {
@@ -2414,7 +2567,7 @@ ${installResult.output}`);
2414
2567
  }
2415
2568
  });
2416
2569
  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) => {
2417
- const projectDir = path18__default.resolve(opts.projectDir);
2570
+ const projectDir = path22__default.resolve(opts.projectDir);
2418
2571
  const manager = await connectConnectors(projectDir);
2419
2572
  try {
2420
2573
  const results = await manager.search(id, query);
@@ -2424,7 +2577,7 @@ ${installResult.output}`);
2424
2577
  }
2425
2578
  });
2426
2579
  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) => {
2427
- const projectDir = path18__default.resolve(opts.projectDir);
2580
+ const projectDir = path22__default.resolve(opts.projectDir);
2428
2581
  const manager = await connectConnectors(projectDir);
2429
2582
  try {
2430
2583
  const ok = await manager.delete(id, resourcePath);
@@ -2434,7 +2587,7 @@ ${installResult.output}`);
2434
2587
  }
2435
2588
  });
2436
2589
  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) => {
2437
- const projectDir = path18__default.resolve(opts.projectDir);
2590
+ const projectDir = path22__default.resolve(opts.projectDir);
2438
2591
  const manager = await connectConnectors(projectDir);
2439
2592
  try {
2440
2593
  if (!manager.has(id)) {
@@ -2543,7 +2696,7 @@ function envRecord() {
2543
2696
  async function buildDeployContext(projectDir) {
2544
2697
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2545
2698
  const config = resolveSkWorkspaceConfig2(projectDir);
2546
- const workspaceId = config.name ?? path18__default.basename(projectDir);
2699
+ const workspaceId = config.name ?? path22__default.basename(projectDir);
2547
2700
  let log;
2548
2701
  try {
2549
2702
  const { createLogger } = await import('../core/logging.js');
@@ -2575,13 +2728,13 @@ async function ensureTargetsRegistered(projectDir) {
2575
2728
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2576
2729
  const config = resolveSkWorkspaceConfig2(projectDir);
2577
2730
  if (config.plugins && config.plugins.length > 0) {
2578
- const { ensurePluginsLoaded } = await import('../plugin-store-X7GPWGBG.js');
2731
+ const { ensurePluginsLoaded } = await import('../plugin-store-XMZSPVBF.js');
2579
2732
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
2580
2733
  for (const f of result.failed) logWarn(f.error);
2581
2734
  }
2582
2735
  }
2583
2736
  async function runUp(opts) {
2584
- const projectDir = path18__default.resolve(opts.projectDir);
2737
+ const projectDir = path22__default.resolve(opts.projectDir);
2585
2738
  await ensureTargetsRegistered(projectDir);
2586
2739
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
2587
2740
  const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
@@ -2649,7 +2802,7 @@ async function restoreFromHandle(projectDir) {
2649
2802
  return { target, handle, ctx };
2650
2803
  }
2651
2804
  async function runDown(opts) {
2652
- const projectDir = path18__default.resolve(opts.projectDir);
2805
+ const projectDir = path22__default.resolve(opts.projectDir);
2653
2806
  const restored = await restoreFromHandle(projectDir);
2654
2807
  if (!restored) return;
2655
2808
  await restored.handle.stop();
@@ -2658,7 +2811,7 @@ async function runDown(opts) {
2658
2811
  logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
2659
2812
  }
2660
2813
  async function runStatus(opts) {
2661
- const projectDir = path18__default.resolve(opts.projectDir);
2814
+ const projectDir = path22__default.resolve(opts.projectDir);
2662
2815
  const restored = await restoreFromHandle(projectDir);
2663
2816
  if (!restored) return;
2664
2817
  const health = await restored.handle.health();
@@ -2672,7 +2825,7 @@ async function runStatus(opts) {
2672
2825
  console.log();
2673
2826
  }
2674
2827
  async function runLogs(opts) {
2675
- const projectDir = path18__default.resolve(opts.projectDir);
2828
+ const projectDir = path22__default.resolve(opts.projectDir);
2676
2829
  const restored = await restoreFromHandle(projectDir);
2677
2830
  if (!restored) return;
2678
2831
  if (!restored.handle.logs) {
@@ -2694,25 +2847,59 @@ function makeDeployCommand() {
2694
2847
  cmd.action(() => cmd.help());
2695
2848
  return cmd;
2696
2849
  }
2850
+ var DIFF_SHOWS = { content: true, modified: true, incomplete: true };
2697
2851
  function makeDiffCommand() {
2698
2852
  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) => {
2853
+ requireProjectConfig(opts.projectDir);
2699
2854
  const am2 = new AssetManager({
2700
2855
  registry: getKindRegistry(),
2701
- projectDir: path18__default.resolve(opts.projectDir)
2856
+ projectDir: path22__default.resolve(opts.projectDir)
2702
2857
  });
2858
+ try {
2859
+ parseAssetRef(ref);
2860
+ } catch (err2) {
2861
+ const plain = (err2 instanceof Error ? err2.message : String(err2)).replace(
2862
+ / Run the `migrate-skaile-manifest`.*$/,
2863
+ ""
2864
+ );
2865
+ const bare = /^([^:@/]+):([^@/#]+)$/.exec(ref.trim());
2866
+ const held = plain.startsWith("publisher required") && bare ? am2.lockedRefsNamed(bare[1], bare[2]) : [];
2867
+ if (held.length !== 1) {
2868
+ logErr(held.length > 1 ? `${plain} (locked: ${held.join(", ")})` : plain);
2869
+ process.exitCode = 1;
2870
+ return;
2871
+ }
2872
+ }
2873
+ const gaps = await am2.gapsOf(ref);
2874
+ const requirementGaps = await am2.requirementGapsOf(ref);
2875
+ const blocking = [...gaps.filter((g) => !DIFF_SHOWS[g.type]), ...requirementGaps];
2876
+ if (blocking.length > 0) {
2877
+ for (const g of blocking) logErr(g.message);
2878
+ process.exitCode = 1;
2879
+ return;
2880
+ }
2703
2881
  const result = await am2.diff(ref);
2704
- const problems = (await am2.gapsOf(ref)).filter(
2705
- (g) => !(g.type === "content" && result.status === "differs")
2882
+ const problems = gaps.filter(
2883
+ (g) => !(result.status === "differs" && (g.type === "content" || g.type === "modified"))
2706
2884
  );
2707
2885
  switch (result.status) {
2708
2886
  case "not-found":
2709
2887
  if (problems.length === 0) logErr(`Asset not found: ${ref}`);
2710
2888
  break;
2711
2889
  case "not-deployed":
2712
- if (problems.length === 0) logWarn(`${ref} is not deployed \u2014 run skaile install`);
2890
+ if (problems.length === 0) {
2891
+ logErr(
2892
+ `${ref} is not deployed \u2014 nothing in this project locks it; run skaile add ${ref}`
2893
+ );
2894
+ process.exitCode = 1;
2895
+ }
2896
+ break;
2897
+ case "no-files":
2898
+ if (problems.length === 0)
2899
+ logInfo(`${ref}: preset has no files of its own; run skaile diff on its items`);
2713
2900
  break;
2714
2901
  case "identical":
2715
- logInfo("No differences.");
2902
+ if (problems.length === 0) logInfo("No differences.");
2716
2903
  break;
2717
2904
  case "differs":
2718
2905
  console.log(result.diff);
@@ -2725,7 +2912,7 @@ function makeDiffCommand() {
2725
2912
  function makeFlowCommand() {
2726
2913
  const cmd = new Command("flow").description("Manage flows");
2727
2914
  cmd.command("list").description("List available flows").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
2728
- const flows = await discoverFlowsWithLibraries(path18__default.resolve(opts.projectDir));
2915
+ const flows = await discoverFlowsWithLibraries(path22__default.resolve(opts.projectDir));
2729
2916
  if (flows.length === 0) {
2730
2917
  logInfo("No flows found.");
2731
2918
  return;
@@ -2740,7 +2927,7 @@ function makeFlowCommand() {
2740
2927
  console.log();
2741
2928
  });
2742
2929
  cmd.command("show <id>").description("Show flow details and node graph").option("--project-dir <path>", "Project directory", process.cwd()).action(async (id, opts) => {
2743
- const flows = await discoverFlowsWithLibraries(path18__default.resolve(opts.projectDir));
2930
+ const flows = await discoverFlowsWithLibraries(path22__default.resolve(opts.projectDir));
2744
2931
  const flow = flows.find((f) => f.id === id);
2745
2932
  if (!flow) {
2746
2933
  logErr(`Flow not found: ${id}`);
@@ -2774,7 +2961,7 @@ function makeHistoryCommand() {
2774
2961
  cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
2775
2962
  const am2 = new AssetManager({
2776
2963
  registry: getKindRegistry(),
2777
- projectDir: path18__default.resolve(opts.projectDir)
2964
+ projectDir: path22__default.resolve(opts.projectDir)
2778
2965
  });
2779
2966
  const limit = parseInt(limitStr, 10) || 20;
2780
2967
  const entries = am2.history(limit);
@@ -2797,7 +2984,7 @@ function makeHistoryCommand() {
2797
2984
  cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
2798
2985
  const am2 = new AssetManager({
2799
2986
  registry: getKindRegistry(),
2800
- projectDir: path18__default.resolve(opts.projectDir)
2987
+ projectDir: path22__default.resolve(opts.projectDir)
2801
2988
  });
2802
2989
  am2.clearHistory();
2803
2990
  logOk("History cleared.");
@@ -2810,8 +2997,24 @@ var MCP_SERVER_ENTRY = {
2810
2997
  args: ["mcp-server"],
2811
2998
  env: {}
2812
2999
  };
3000
+ function mcpFilePath(projectDir) {
3001
+ return path22__default.join(projectDir, ".mcp.json");
3002
+ }
3003
+ function legacyMcpFilePath(projectDir) {
3004
+ return path22__default.join(projectDir, ".claude", "mcp.json");
3005
+ }
3006
+ async function removeSkaileMcpEntry(mcpPath) {
3007
+ const mcp = await readJsonStrict(mcpPath);
3008
+ if (!mcp?.mcpServers || !(SKAILE_MCP_NAME in mcp.mcpServers)) return false;
3009
+ const { [SKAILE_MCP_NAME]: _removed, ...rest } = mcp.mcpServers;
3010
+ const updated = { ...mcp, mcpServers: rest };
3011
+ if (Object.keys(rest).length === 0) delete updated.mcpServers;
3012
+ if (Object.keys(updated).length === 0) await fs5.unlink(mcpPath);
3013
+ else await writeJson(mcpPath, updated);
3014
+ return true;
3015
+ }
2813
3016
  function pluginDir(projectDir) {
2814
- return path18__default.join(projectDir, ".claude", "plugins", "skaile");
3017
+ return path22__default.join(projectDir, ".claude", "plugins", "skaile");
2815
3018
  }
2816
3019
  async function readJsonStrict(p6) {
2817
3020
  let raw;
@@ -2829,7 +3032,7 @@ async function readJsonStrict(p6) {
2829
3032
  }
2830
3033
  }
2831
3034
  async function writeJson(p6, value) {
2832
- await fs5.mkdir(path18__default.dirname(p6), { recursive: true });
3035
+ await fs5.mkdir(path22__default.dirname(p6), { recursive: true });
2833
3036
  await fs5.writeFile(p6, `${JSON.stringify(value, null, 2)}
2834
3037
  `);
2835
3038
  }
@@ -2837,8 +3040,8 @@ async function copyDir(src, dest) {
2837
3040
  await fs5.mkdir(dest, { recursive: true });
2838
3041
  const entries = await fs5.readdir(src, { withFileTypes: true });
2839
3042
  for (const entry of entries) {
2840
- const srcPath = path18__default.join(src, entry.name);
2841
- const destPath = path18__default.join(dest, entry.name);
3043
+ const srcPath = path22__default.join(src, entry.name);
3044
+ const destPath = path22__default.join(dest, entry.name);
2842
3045
  if (entry.isDirectory()) await copyDir(srcPath, destPath);
2843
3046
  else await fs5.copyFile(srcPath, destPath);
2844
3047
  }
@@ -2847,31 +3050,32 @@ async function install(projectDir, opts) {
2847
3050
  return opts?.full ? installFullPlugin(projectDir) : installMcp(projectDir);
2848
3051
  }
2849
3052
  async function installMcp(projectDir) {
2850
- const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
3053
+ const mcpPath = mcpFilePath(projectDir);
2851
3054
  const existing = await readJsonStrict(mcpPath) ?? {};
2852
3055
  const mcpServers = { ...existing.mcpServers ?? {} };
2853
3056
  const previous = mcpServers[SKAILE_MCP_NAME];
2854
3057
  const matches = previous && JSON.stringify(previous) === JSON.stringify(MCP_SERVER_ENTRY);
2855
3058
  let warning;
2856
3059
  if (previous && !matches) {
2857
- warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path18__default.relative(projectDir, mcpPath)}`;
3060
+ warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path22__default.relative(projectDir, mcpPath)}`;
2858
3061
  }
2859
3062
  mcpServers[SKAILE_MCP_NAME] = MCP_SERVER_ENTRY;
2860
3063
  await writeJson(mcpPath, { ...existing, mcpServers });
2861
- return { changed: !matches, method: "mcp", warning };
3064
+ const migrated = await removeSkaileMcpEntry(legacyMcpFilePath(projectDir));
3065
+ return { changed: !matches || migrated, method: "mcp", warning };
2862
3066
  }
2863
3067
  async function installFullPlugin(projectDir) {
2864
3068
  const dir = pluginDir(projectDir);
2865
3069
  for (const [rel, content] of Object.entries(buildClaudePluginFiles())) {
2866
- const dest = path18__default.join(dir, rel);
2867
- await fs5.mkdir(path18__default.dirname(dest), { recursive: true });
3070
+ const dest = path22__default.join(dir, rel);
3071
+ await fs5.mkdir(path22__default.dirname(dest), { recursive: true });
2868
3072
  await fs5.writeFile(dest, content);
2869
3073
  }
2870
- const projectSkillsDir = path18__default.join(projectDir, ".skaile", "skills");
3074
+ const projectSkillsDir = path22__default.join(projectDir, ".skaile", "skills");
2871
3075
  if (existsSync(projectSkillsDir)) {
2872
- await copyDir(projectSkillsDir, path18__default.join(dir, "skills"));
3076
+ await copyDir(projectSkillsDir, path22__default.join(dir, "skills"));
2873
3077
  }
2874
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
3078
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
2875
3079
  const settings = await readJsonStrict(settingsPath) ?? {};
2876
3080
  const plugins = settings.plugins ?? [];
2877
3081
  if (!plugins.includes(dir)) plugins.push(dir);
@@ -2879,8 +3083,8 @@ async function installFullPlugin(projectDir) {
2879
3083
  return { changed: true, method: "plugin" };
2880
3084
  }
2881
3085
  async function uninstall(projectDir) {
2882
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
2883
- const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
3086
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
3087
+ const mcpPath = mcpFilePath(projectDir);
2884
3088
  const dir = pluginDir(projectDir);
2885
3089
  let changed = false;
2886
3090
  const settings = await readJsonStrict(settingsPath);
@@ -2897,29 +3101,19 @@ async function uninstall(projectDir) {
2897
3101
  await fs5.rm(dir, { recursive: true, force: true });
2898
3102
  changed = true;
2899
3103
  }
2900
- const mcp = await readJsonStrict(mcpPath);
2901
- if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
2902
- changed = true;
2903
- const { [SKAILE_MCP_NAME]: _removed, ...rest } = mcp.mcpServers;
2904
- const updated = { ...mcp, mcpServers: rest };
2905
- if (Object.keys(rest).length === 0) delete updated.mcpServers;
2906
- if (Object.keys(updated).length === 0) {
2907
- await fs5.unlink(mcpPath);
2908
- } else {
2909
- await writeJson(mcpPath, updated);
2910
- }
2911
- }
3104
+ if (await removeSkaileMcpEntry(mcpPath)) changed = true;
3105
+ if (await removeSkaileMcpEntry(legacyMcpFilePath(projectDir))) changed = true;
2912
3106
  return { changed };
2913
3107
  }
2914
3108
  async function detectInstall(projectDir) {
2915
3109
  const dir = pluginDir(projectDir);
2916
3110
  const settings = await readJsonStrict(
2917
- path18__default.join(projectDir, ".claude", "settings.json")
3111
+ path22__default.join(projectDir, ".claude", "settings.json")
2918
3112
  );
2919
- if (existsSync(path18__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
3113
+ if (existsSync(path22__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
2920
3114
  return { method: "plugin", pluginPath: dir };
2921
3115
  }
2922
- const mcp = await readJsonStrict(path18__default.join(projectDir, ".claude", "mcp.json"));
3116
+ const mcp = await readJsonStrict(mcpFilePath(projectDir));
2923
3117
  if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
2924
3118
  return { method: "mcp" };
2925
3119
  }
@@ -2928,7 +3122,7 @@ async function detectInstall(projectDir) {
2928
3122
  async function enable(projectDir) {
2929
3123
  const detected = await detectInstall(projectDir);
2930
3124
  if (!detected) throw new Error("plugin not installed for claude-code");
2931
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
3125
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
2932
3126
  const settings = await readJsonStrict(settingsPath) ?? {};
2933
3127
  if (detected.method === "plugin") {
2934
3128
  const disabled2 = settings.disabledPlugins ?? [];
@@ -2950,7 +3144,7 @@ async function enable(projectDir) {
2950
3144
  async function disable(projectDir) {
2951
3145
  const detected = await detectInstall(projectDir);
2952
3146
  if (!detected) throw new Error("plugin not installed for claude-code");
2953
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
3147
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
2954
3148
  const settings = await readJsonStrict(settingsPath) ?? {};
2955
3149
  if (detected.method === "plugin") {
2956
3150
  const list2 = settings.disabledPlugins ?? [];
@@ -2970,12 +3164,12 @@ async function disable(projectDir) {
2970
3164
  return { changed: true };
2971
3165
  }
2972
3166
  async function status(projectDir) {
2973
- const settingsPath = path18__default.join(projectDir, ".claude", "settings.json");
2974
- const mcpPath = path18__default.join(projectDir, ".claude", "mcp.json");
3167
+ const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
3168
+ const mcpPath = mcpFilePath(projectDir);
2975
3169
  const dir = pluginDir(projectDir);
2976
3170
  const settings = await readJsonStrict(settingsPath);
2977
3171
  const mcp = await readJsonStrict(mcpPath);
2978
- const pluginInstalled = !!(existsSync(path18__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
3172
+ const pluginInstalled = !!(existsSync(path22__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
2979
3173
  const mcpInstalled = !!(mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers);
2980
3174
  if (!pluginInstalled && !mcpInstalled) {
2981
3175
  return {
@@ -2993,7 +3187,7 @@ async function status(projectDir) {
2993
3187
  installed: "yes",
2994
3188
  enabled: disabled2 ? "no" : "yes",
2995
3189
  method: "plugin",
2996
- location: path18__default.relative(projectDir, dir)
3190
+ location: path22__default.relative(projectDir, dir)
2997
3191
  };
2998
3192
  }
2999
3193
  const disabled = settings?.disabledMcpjsonServers?.includes(SKAILE_MCP_NAME) ?? false;
@@ -3002,7 +3196,7 @@ async function status(projectDir) {
3002
3196
  installed: "yes",
3003
3197
  enabled: disabled ? "no" : "yes",
3004
3198
  method: "mcp",
3005
- location: path18__default.relative(projectDir, mcpPath)
3199
+ location: path22__default.relative(projectDir, mcpPath)
3006
3200
  };
3007
3201
  }
3008
3202
  var SKAILE_MCP_NAME2 = "skaile-workspace";
@@ -3029,7 +3223,7 @@ async function readConfig(p6) {
3029
3223
  }
3030
3224
  }
3031
3225
  async function writeConfig(p6, value) {
3032
- await fs5.mkdir(path18__default.dirname(p6), { recursive: true });
3226
+ await fs5.mkdir(path22__default.dirname(p6), { recursive: true });
3033
3227
  const cleaned = {};
3034
3228
  for (const [k, v] of Object.entries(value)) {
3035
3229
  if (v === void 0) continue;
@@ -3038,7 +3232,7 @@ async function writeConfig(p6, value) {
3038
3232
  await fs5.writeFile(p6, stringify$1(cleaned));
3039
3233
  }
3040
3234
  function configPath(projectDir) {
3041
- return path18__default.join(projectDir, ".codex", "config.toml");
3235
+ return path22__default.join(projectDir, ".codex", "config.toml");
3042
3236
  }
3043
3237
  async function install2(projectDir) {
3044
3238
  const p6 = configPath(projectDir);
@@ -3049,7 +3243,7 @@ async function install2(projectDir) {
3049
3243
  const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
3050
3244
  let warning;
3051
3245
  if (previous && !matches) {
3052
- warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path18__default.relative(projectDir, p6)}`;
3246
+ warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path22__default.relative(projectDir, p6)}`;
3053
3247
  }
3054
3248
  if (matches) return { changed: false, method: "toml" };
3055
3249
  servers[SKAILE_MCP_NAME2] = next;
@@ -3090,12 +3284,12 @@ async function status2(projectDir) {
3090
3284
  installed: "yes",
3091
3285
  enabled: "n/a",
3092
3286
  method: "mcp",
3093
- location: path18__default.relative(projectDir, p6)
3287
+ location: path22__default.relative(projectDir, p6)
3094
3288
  };
3095
3289
  }
3096
3290
  async function install3(projectDir) {
3097
- const extDir = path18__default.join(projectDir, ".omp", "extensions");
3098
- const extPath = path18__default.join(extDir, "skaile.ts");
3291
+ const extDir = path22__default.join(projectDir, ".omp", "extensions");
3292
+ const extPath = path22__default.join(extDir, "skaile.ts");
3099
3293
  await fs5.mkdir(extDir, { recursive: true });
3100
3294
  const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
3101
3295
  const plugin = new WorkspacePlugin({ projectDir });
@@ -3110,7 +3304,7 @@ async function install3(projectDir) {
3110
3304
  return { changed: true, method: "generated" };
3111
3305
  }
3112
3306
  async function uninstall3(projectDir) {
3113
- const extPath = path18__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3307
+ const extPath = path22__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3114
3308
  try {
3115
3309
  await fs5.unlink(extPath);
3116
3310
  return { changed: true };
@@ -3119,14 +3313,14 @@ async function uninstall3(projectDir) {
3119
3313
  }
3120
3314
  }
3121
3315
  async function status3(projectDir) {
3122
- const extPath = path18__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3316
+ const extPath = path22__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3123
3317
  if (existsSync(extPath)) {
3124
3318
  return {
3125
3319
  harness: "omp",
3126
3320
  installed: "yes",
3127
3321
  enabled: "n/a",
3128
3322
  method: "extension",
3129
- location: path18__default.relative(projectDir, extPath)
3323
+ location: path22__default.relative(projectDir, extPath)
3130
3324
  };
3131
3325
  }
3132
3326
  return {
@@ -3163,7 +3357,7 @@ async function installClaudeCode(projectDir, opts) {
3163
3357
  `Generated ${S.cmd(".claude/plugins/skaile/")} and registered it in ${S.cmd(".claude/settings.json")}`
3164
3358
  );
3165
3359
  } else if (r.changed) {
3166
- logOk(`Wrote ${S.cmd(".claude/mcp.json")} (${SKAILE_MCP_LABEL})`);
3360
+ logOk(`Wrote ${S.cmd(".mcp.json")} (${SKAILE_MCP_LABEL})`);
3167
3361
  } else {
3168
3362
  logInfo(`claude-code: already installed (mcp)`);
3169
3363
  }
@@ -3189,7 +3383,7 @@ async function installCodex(projectDir) {
3189
3383
  console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
3190
3384
  }
3191
3385
  async function runInstall(opts) {
3192
- const projectDir = path18__default.resolve(opts.projectDir);
3386
+ const projectDir = path22__default.resolve(opts.projectDir);
3193
3387
  const targets = resolveDriver(opts.driver);
3194
3388
  let exitCode = 0;
3195
3389
  if (targets.includes("claude-code")) {
@@ -3223,7 +3417,7 @@ async function uninstallCodex(projectDir) {
3223
3417
  else logInfo(`codex: not installed`);
3224
3418
  }
3225
3419
  async function runUninstall(opts) {
3226
- const projectDir = path18__default.resolve(opts.projectDir);
3420
+ const projectDir = path22__default.resolve(opts.projectDir);
3227
3421
  const targets = resolveDriver(opts.driver);
3228
3422
  let exitCode = 0;
3229
3423
  if (targets.includes("claude-code")) {
@@ -3266,7 +3460,7 @@ async function toggleTarget(t, projectDir, action3) {
3266
3460
  });
3267
3461
  }
3268
3462
  async function runToggle(opts, action3) {
3269
- const projectDir = path18__default.resolve(opts.projectDir);
3463
+ const projectDir = path22__default.resolve(opts.projectDir);
3270
3464
  const requestedAll = opts.driver === "all";
3271
3465
  const targets = resolveDriver(opts.driver);
3272
3466
  const usageError = checkToggleSupported(targets, requestedAll, action3);
@@ -3278,7 +3472,7 @@ async function runToggle(opts, action3) {
3278
3472
  return exitCode;
3279
3473
  }
3280
3474
  async function runStatus2(opts) {
3281
- const projectDir = path18__default.resolve(opts.projectDir);
3475
+ const projectDir = path22__default.resolve(opts.projectDir);
3282
3476
  const targets = resolveDriver(opts.driver);
3283
3477
  const rows = [];
3284
3478
  let exitCode = 0;
@@ -3319,12 +3513,12 @@ function printStatusTable(rows) {
3319
3513
  var SKAILE_MCP_LABEL = "skaile-workspace entry";
3320
3514
  var HOOK_EVENTS = ["session-start", "session-end", "user-prompt-submit"];
3321
3515
  async function runHook(event) {
3322
- const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
3323
- registerLogStore(
3324
- new LogStore({
3516
+ const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
3517
+ registerLogStore2(
3518
+ new LogStore2({
3325
3519
  sessionId: `hook-${event}`,
3326
3520
  level: "info",
3327
- sinks: [new StdoutSink({ stream: "stderr" })]
3521
+ sinks: [new StdoutSink2({ stream: "stderr" })]
3328
3522
  })
3329
3523
  );
3330
3524
  const { WorkspacePlugin, PluginStore, resolveProjectDir } = await import('../workspace-plugin/index.js');
@@ -3349,7 +3543,7 @@ async function runHook(event) {
3349
3543
  await plugin.shutdown();
3350
3544
  return;
3351
3545
  }
3352
- const store = new PluginStore(path18__default.join(projectDir, ".skaile", "plugin-state.json"));
3546
+ const store = new PluginStore(path22__default.join(projectDir, ".skaile", "plugin-state.json"));
3353
3547
  await store.load();
3354
3548
  const status4 = store.get("connector:status");
3355
3549
  if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
@@ -3364,6 +3558,45 @@ async function runHook(event) {
3364
3558
  );
3365
3559
  }
3366
3560
  }
3561
+ async function readStdin() {
3562
+ if (process.stdin.isTTY) return "";
3563
+ const chunks = [];
3564
+ for await (const chunk of process.stdin) chunks.push(chunk);
3565
+ return Buffer.concat(chunks).toString("utf-8");
3566
+ }
3567
+ async function runOmpExec(kind, name, projectDir) {
3568
+ if (kind !== "tool" && kind !== "slash") {
3569
+ logErr(`omp-exec: unknown kind '${kind}' (expected: tool | slash)`);
3570
+ return 2;
3571
+ }
3572
+ const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
3573
+ const plugin = new WorkspacePlugin({ projectDir, bootOwned: true });
3574
+ try {
3575
+ const raw = (await readStdin()).trim();
3576
+ const payload = raw ? JSON.parse(raw) : kind === "tool" ? {} : [];
3577
+ await plugin.boot();
3578
+ if (kind === "slash") {
3579
+ const parts = Array.isArray(payload) ? payload.map(String) : [];
3580
+ process.stdout.write(`${await plugin.handleSlashCommand(name, parts)}
3581
+ `);
3582
+ return 0;
3583
+ }
3584
+ const tools = await plugin.buildOmpToolSet();
3585
+ const tool = tools.find((t) => t.name === name);
3586
+ if (!tool) {
3587
+ logErr(`omp-exec: unknown tool '${name}'`);
3588
+ return 2;
3589
+ }
3590
+ process.stdout.write(`${await tool.handler(payload)}
3591
+ `);
3592
+ return 0;
3593
+ } catch (e) {
3594
+ logErr(`omp-exec ${kind} ${name}: ${e instanceof Error ? e.message : String(e)}`);
3595
+ return 1;
3596
+ } finally {
3597
+ await plugin.shutdown();
3598
+ }
3599
+ }
3367
3600
  function makeIntegrationCommand() {
3368
3601
  const cmd = new Command("integration").description(
3369
3602
  "Manage skaile agent integration / workspace-plugin adapter (Claude Code / OMP / Codex)"
@@ -3386,13 +3619,18 @@ function makeIntegrationCommand() {
3386
3619
  cmd.command("status").description("Show install / enable status across harnesses").option("--driver <name>", "Target: claude-code | omp | codex | all", "all").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
3387
3620
  process.exitCode = await runStatus2(opts);
3388
3621
  });
3622
+ cmd.command("omp-exec <kind> <name>").description(
3623
+ "Run one tool or slash command of the omp extension (used by .omp/extensions/skaile.ts)"
3624
+ ).option("--project-dir <path>", "Project directory", process.cwd()).action(async (kind, name, opts) => {
3625
+ process.exitCode = await runOmpExec(kind, name, path22__default.resolve(opts.projectDir));
3626
+ });
3389
3627
  cmd.command("hook <event>").description(
3390
3628
  "Run a Claude Code lifecycle hook (session-start | session-end | user-prompt-submit)"
3391
3629
  ).action(async (event) => {
3392
3630
  try {
3393
3631
  if (!HOOK_EVENTS.includes(event)) {
3394
3632
  process.stderr.write(
3395
- `plugin hook: unknown event '${event}' (expected: ${HOOK_EVENTS.join(" | ")})
3633
+ `integration hook: unknown event '${event}' (expected: ${HOOK_EVENTS.join(" | ")})
3396
3634
  `
3397
3635
  );
3398
3636
  } else {
@@ -3400,7 +3638,7 @@ function makeIntegrationCommand() {
3400
3638
  }
3401
3639
  } catch (err2) {
3402
3640
  process.stderr.write(
3403
- `plugin hook ${event} warning: ${err2 instanceof Error ? err2.message : String(err2)}
3641
+ `integration hook ${event} warning: ${err2 instanceof Error ? err2.message : String(err2)}
3404
3642
  `
3405
3643
  );
3406
3644
  }
@@ -3427,7 +3665,7 @@ function unfinishedGitState(dir) {
3427
3665
  for (const [entry, state2] of Object.entries(UNFINISHED_GIT_ENTRIES)) {
3428
3666
  const p6 = spawnSync("git", ["rev-parse", "--git-path", entry], { cwd: dir, encoding: "utf-8" });
3429
3667
  if (p6.status !== 0) return "the git directory could not be read";
3430
- if (fs8.existsSync(path18.resolve(dir, p6.stdout.trim()))) return state2;
3668
+ if (fs8.existsSync(path22.resolve(dir, p6.stdout.trim()))) return state2;
3431
3669
  }
3432
3670
  return null;
3433
3671
  }
@@ -3442,7 +3680,7 @@ async function reindexLibrary(lib, library, name) {
3442
3680
  lib.path,
3443
3681
  resolved.publisher,
3444
3682
  registry,
3445
- { check: (e) => checkAssetFile(e.source, e.kind, registry) }
3683
+ { check: (e) => checkAssetFile(e.source, e.kind, registry, lib.path) }
3446
3684
  );
3447
3685
  const manifest = loadSkPublishManifest(lib.path);
3448
3686
  for (const a of unknownKind) {
@@ -3454,19 +3692,25 @@ async function reindexLibrary(lib, library, name) {
3454
3692
  const ref = manifest ? assetEntryRef(a, manifest) : `${a.kind}:${a.name}`;
3455
3693
  logInfo(`Removed manifest entry ${ref} (root ${a.root} is gone)`);
3456
3694
  }
3457
- for (const s of skipped.filter((x) => x.reason === "invalid-version")) {
3458
- logWarn(
3459
- `${s.kind}:${s.name} skipped: ${s.detail}. Set a valid \`metadata.version\` (e.g. 0.1.0) and re-run \`skaile library index ${name}\`.`
3695
+ const invalidVersion = skipped.filter((x) => x.reason === "invalid-version");
3696
+ for (const s of invalidVersion) {
3697
+ const found = checkAssetFile(path22.join(lib.path, s.file), s.kind, registry).find(
3698
+ (f) => f.text.startsWith("version ")
3699
+ );
3700
+ const detail = found?.text ?? s.detail;
3701
+ const hint = detail.includes("Write it quoted") ? "" : " Set a valid `metadata.version` (e.g. 0.1.0).";
3702
+ logErr(
3703
+ `${s.kind}:${s.name} skipped: ${detail}.${hint} Re-run \`skaile library index ${name}\` after the fix.`
3460
3704
  );
3461
3705
  }
3462
3706
  const duplicates = skipped.filter((x) => x.reason === "duplicate");
3463
3707
  for (const s of duplicates) {
3464
- logErr(duplicateAssetMessage(s.kind, s.name, path18.dirname(s.file), s.detail, name));
3708
+ logErr(duplicateAssetMessage(s.kind, s.name, path22.dirname(s.file), s.detail, name));
3465
3709
  }
3466
3710
  for (const s of failed) {
3467
3711
  for (const f of s.findings) logErr(`${s.file} [${f.tag}] \u2014 ${f.text}`);
3468
3712
  }
3469
- const duplicateFiles = new Set(duplicates.map((s) => path18.resolve(lib.path, s.file)));
3713
+ const duplicateFiles = new Set(duplicates.map((s) => path22.resolve(lib.path, s.file)));
3470
3714
  const skippedKeys = new Set(
3471
3715
  [
3472
3716
  ...skipped.filter((s) => s.reason !== "duplicate"),
@@ -3474,7 +3718,7 @@ async function reindexLibrary(lib, library, name) {
3474
3718
  ].map((s) => `${s.kind}:${s.name}`)
3475
3719
  );
3476
3720
  const res = await indexLibrary(lib, library, {
3477
- exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path18.resolve(a.manifestPath))
3721
+ exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path22.resolve(a.manifestPath))
3478
3722
  });
3479
3723
  const unparsable = res.errors.filter((e) => e.includes("ManifestSchemaError:"));
3480
3724
  for (const e of res.errors) (unparsable.includes(e) ? logErr : logWarn)(e);
@@ -3486,14 +3730,21 @@ async function reindexLibrary(lib, library, name) {
3486
3730
  }
3487
3731
  for (const p6 of badRequires) logErr(`${p6.asset}: ${p6.message}`);
3488
3732
  for (const w of await unresolvedManifestDependencies(lib.path)) logWarn(w);
3489
- logOk(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
3733
+ const skippedUnparsable = unparsable.length + syncUnparsable.length;
3734
+ const failing = skippedUnparsable + invalidVersion.length + badRequires.length + failed.length + duplicates.length;
3735
+ (failing > 0 ? logWarn : logOk)(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
3490
3736
  warnIgnoredDomainFiles(lib.path);
3491
3737
  warnLegacyBundleFiles(lib.path);
3492
- const skippedUnparsable = unparsable.length + syncUnparsable.length;
3493
3738
  if (skippedUnparsable > 0) {
3494
3739
  logErr(`${skippedUnparsable} asset(s) skipped: manifest could not be parsed.`);
3495
3740
  process.exitCode = 1;
3496
3741
  }
3742
+ if (invalidVersion.length > 0) {
3743
+ logErr(
3744
+ `${invalidVersion.length} asset(s) skipped: the version is not valid semver (listed above).`
3745
+ );
3746
+ process.exitCode = 1;
3747
+ }
3497
3748
  if (badRequires.length > 0) {
3498
3749
  logErr(
3499
3750
  `${badRequires.length} invalid requires entr${badRequires.length === 1 ? "y" : "ies"} ignored: use the \`kind:@<publisher>/name[#version]\` form.`
@@ -3528,26 +3779,26 @@ function assertManifestEditableOrExit(libraryPath) {
3528
3779
  }
3529
3780
  async function assertLibraryPathFree(manager, dir, exceptId) {
3530
3781
  const clash = (await manager.listLibraries()).find(
3531
- (l) => l.id !== exceptId && path18.resolve(l.path) === dir
3782
+ (l) => l.id !== exceptId && path22.resolve(l.path) === dir
3532
3783
  );
3533
3784
  if (clash) throw new Error(`${dir} is already registered as library "${clash.name}".`);
3534
3785
  }
3535
3786
  function canonicalDir(dir) {
3536
- const abs = path18.resolve(dir);
3787
+ const abs = path22.resolve(dir);
3537
3788
  const missing = [];
3538
3789
  let existing = abs;
3539
3790
  while (!fs8.existsSync(existing)) {
3540
- const parent = path18.dirname(existing);
3791
+ const parent = path22.dirname(existing);
3541
3792
  if (parent === existing) return abs;
3542
- missing.unshift(path18.basename(existing));
3793
+ missing.unshift(path22.basename(existing));
3543
3794
  existing = parent;
3544
3795
  }
3545
- return path18.join(fs8.realpathSync(existing), ...missing);
3796
+ return path22.join(fs8.realpathSync(existing), ...missing);
3546
3797
  }
3547
3798
  function refuseGlobalInstallFolder(name, dir) {
3548
3799
  const reserved = globalInstallDir();
3549
- const rel = path18.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
3550
- const inside = rel === "" || !rel.startsWith("..") && !path18.isAbsolute(rel);
3800
+ const rel = path22.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
3801
+ const inside = rel === "" || !rel.startsWith("..") && !path22.isAbsolute(rel);
3551
3802
  if (name?.toLowerCase() === GLOBAL_INSTALL_DIR_NAME || inside) {
3552
3803
  logErr(
3553
3804
  `"${GLOBAL_INSTALL_DIR_NAME}" is reserved: ${reserved} holds assets from \`skaile install\`, not a library you author.`
@@ -3557,8 +3808,8 @@ function refuseGlobalInstallFolder(name, dir) {
3557
3808
  }
3558
3809
  async function refuseNestedLibraryPath(manager, dir, exceptId) {
3559
3810
  const within = (parent, child) => {
3560
- const rel = path18.relative(parent, child);
3561
- return rel === "" || !rel.startsWith("..") && !path18.isAbsolute(rel);
3811
+ const rel = path22.relative(parent, child);
3812
+ return rel === "" || !rel.startsWith("..") && !path22.isAbsolute(rel);
3562
3813
  };
3563
3814
  const target = canonicalDir(dir).toLowerCase();
3564
3815
  const librariesDir = resolveLibraryDir();
@@ -3595,7 +3846,7 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
3595
3846
  }
3596
3847
  };
3597
3848
  let probe = destDir;
3598
- while (!exists(probe)) probe = path18.dirname(probe);
3849
+ while (!exists(probe)) probe = path22.dirname(probe);
3599
3850
  let realProbe;
3600
3851
  try {
3601
3852
  realProbe = fs8.realpathSync(probe);
@@ -3608,9 +3859,9 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
3608
3859
  process.exit(1);
3609
3860
  }
3610
3861
  const realRoot = canonicalDir(libRoot);
3611
- const realDest = path18.join(realProbe, path18.relative(probe, destDir));
3612
- const rel = path18.relative(realRoot, realDest);
3613
- if (rel === ".." || rel.startsWith(`..${path18.sep}`) || path18.isAbsolute(rel)) {
3862
+ const realDest = path22.join(realProbe, path22.relative(probe, destDir));
3863
+ const rel = path22.relative(realRoot, realDest);
3864
+ if (rel === ".." || rel.startsWith(`..${path22.sep}`) || path22.isAbsolute(rel)) {
3614
3865
  logErr(
3615
3866
  `--dir "${given}" must stay inside the library (${realRoot}): it resolves to ${realDest}.`
3616
3867
  );
@@ -3618,7 +3869,7 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
3618
3869
  }
3619
3870
  }
3620
3871
  function adoptWritesManifest(libPath) {
3621
- if (!fs8.existsSync(path18.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
3872
+ if (!fs8.existsSync(path22.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
3622
3873
  const manifest = loadSkPublishManifest(libPath);
3623
3874
  if (!manifest || manifest.source || (manifest.assets ?? []).length > 0) return false;
3624
3875
  return manifestPublisherProblems(libPath).length === 0;
@@ -3672,17 +3923,17 @@ function requireValidLibraryName(name) {
3672
3923
  var LOCAL_OWNERSHIP_REASON = "ownership only governs sync with a git remote, and a local library is always owned by you.";
3673
3924
  function pruneEmptyLibraryParents(libPath) {
3674
3925
  const root = canonicalDir(resolveLibraryDir());
3675
- let dir = path18.dirname(path18.resolve(libPath));
3926
+ let dir = path22.dirname(path22.resolve(libPath));
3676
3927
  for (; ; ) {
3677
- const rel = path18.relative(root, canonicalDir(dir));
3678
- if (rel === "" || rel.startsWith("..") || path18.isAbsolute(rel)) return;
3928
+ const rel = path22.relative(root, canonicalDir(dir));
3929
+ if (rel === "" || rel.startsWith("..") || path22.isAbsolute(rel)) return;
3679
3930
  if (!fs8.existsSync(dir) || fs8.readdirSync(dir).length > 0) return;
3680
3931
  fs8.rmdirSync(dir);
3681
- dir = path18.dirname(dir);
3932
+ dir = path22.dirname(dir);
3682
3933
  }
3683
3934
  }
3684
3935
  async function warnIfNotGithubRemote(name, url) {
3685
- const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-OS3JDW4S.js');
3936
+ const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-DI4Q5UOG.js');
3686
3937
  if (!isGithubRemote(url)) logWarn(notGithubRemoteMessage(name, url));
3687
3938
  }
3688
3939
  function scaffoldLibraryFiles(dir, name) {
@@ -3714,7 +3965,7 @@ by the same ref.
3714
3965
  ];
3715
3966
  const written = [];
3716
3967
  for (const [file, content] of files) {
3717
- const target = path18.join(dir, file);
3968
+ const target = path22.join(dir, file);
3718
3969
  if (fs8.existsSync(target)) continue;
3719
3970
  fs8.writeFileSync(target, content, "utf8");
3720
3971
  written.push(file);
@@ -3782,7 +4033,10 @@ function makeLibraryCommand() {
3782
4033
  console.log(` ${S.label("manifestGen")} ${l.manifestGenerated}`);
3783
4034
  console.log(` ${S.label("backendConfig")} ${JSON.stringify(l.backendConfig)}`);
3784
4035
  console.log();
3785
- if (libraryDirMissing(l)) logWarn(missingLibraryDirMessage(l));
4036
+ if (libraryDirMissing(l)) {
4037
+ logErr(missingLibraryDirMessage(l));
4038
+ process.exitCode = 1;
4039
+ }
3786
4040
  } finally {
3787
4041
  close();
3788
4042
  }
@@ -3801,7 +4055,7 @@ function makeLibraryCommand() {
3801
4055
  opts.path ??= gone.path;
3802
4056
  }
3803
4057
  const ownership = flagged[0] ?? gone?.ownership ?? "owner";
3804
- const libPath = opts.path ? path18.resolve(opts.path) : path18.join(resolveLibraryDir(), name);
4058
+ const libPath = opts.path ? path22.resolve(opts.path) : path22.join(resolveLibraryDir(), name);
3805
4059
  refuseGlobalInstallFolder(name, libPath);
3806
4060
  if (fs8.existsSync(libPath) && !fs8.statSync(libPath).isDirectory()) {
3807
4061
  logErr(`${libPath} exists and is not a directory.`);
@@ -3903,7 +4157,10 @@ function makeLibraryCommand() {
3903
4157
  }
3904
4158
  }
3905
4159
  );
3906
- 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) => {
4160
+ cmd.command("link <name> <git-url>").description("Attach a github remote to a local library (makes it store-publishable)").option(
4161
+ "--branch <name>",
4162
+ "Branch to track (default: the checked-out branch of an existing repo, else main)"
4163
+ ).action(async (name, url, opts) => {
3907
4164
  const { manager, close } = await openLibraryManager();
3908
4165
  try {
3909
4166
  const lib = await manager.requireLibraryDir(name);
@@ -3913,11 +4170,16 @@ function makeLibraryCommand() {
3913
4170
  );
3914
4171
  process.exit(1);
3915
4172
  }
3916
- ensureGitRepo(lib.path, url, opts.branch);
3917
- trackOriginBranch(lib.path, opts.branch, { fetch: true });
4173
+ const head = isGitRepo(lib.path) ? spawnSync("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
4174
+ cwd: lib.path,
4175
+ encoding: "utf-8"
4176
+ }) : void 0;
4177
+ const branch = opts.branch ?? (head?.status === 0 && head.stdout.trim() || "main");
4178
+ ensureGitRepo(lib.path, url, branch);
4179
+ trackOriginBranch(lib.path, branch, { fetch: true });
3918
4180
  await manager.updateLibrary(name, {
3919
4181
  backend: "git",
3920
- backendConfig: { url, branch: opts.branch, authHint: "ssh" }
4182
+ backendConfig: { url, branch, authHint: "ssh" }
3921
4183
  });
3922
4184
  logOk(`Library "${name}" linked to ${url}.`);
3923
4185
  await warnIfNotGithubRemote(name, url);
@@ -3958,10 +4220,10 @@ function makeLibraryCommand() {
3958
4220
  exitOnManifestPublisherProblems(target.path, target.name);
3959
4221
  const effectiveKind = opts.kind ?? kind;
3960
4222
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
3961
- const libRoot = path18.resolve(target.path);
3962
- const destDir = opts.dir ? path18.resolve(libRoot, opts.dir) : libRoot;
3963
- const relDest = path18.relative(libRoot, destDir);
3964
- if (relDest === ".." || relDest.startsWith(`..${path18.sep}`) || path18.isAbsolute(relDest)) {
4223
+ const libRoot = path22.resolve(target.path);
4224
+ const destDir = opts.dir ? path22.resolve(libRoot, opts.dir) : libRoot;
4225
+ const relDest = path22.relative(libRoot, destDir);
4226
+ if (relDest === ".." || relDest.startsWith(`..${path22.sep}`) || path22.isAbsolute(relDest)) {
3965
4227
  logErr(`--dir "${opts.dir}" must stay inside the library (${libRoot}).`);
3966
4228
  process.exit(1);
3967
4229
  }
@@ -3970,11 +4232,11 @@ function makeLibraryCommand() {
3970
4232
  libRoot,
3971
4233
  effectiveKind,
3972
4234
  name,
3973
- path18.relative(libRoot, path18.join(destDir, name))
4235
+ path22.relative(libRoot, path22.join(destDir, name))
3974
4236
  );
3975
4237
  if (taken) {
3976
4238
  logErr(
3977
- `${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path18.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
4239
+ `${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path22.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
3978
4240
  );
3979
4241
  process.exit(1);
3980
4242
  }
@@ -3984,7 +4246,7 @@ function makeLibraryCommand() {
3984
4246
  process.exit(1);
3985
4247
  }
3986
4248
  logOk(`Created ${effectiveKind}: ${pc5.dim(res.path)}`);
3987
- if (opts.description === void 0 && ["skill", "agent", "prompt", "contract"].includes(effectiveKind)) {
4249
+ if (opts.description === void 0) {
3988
4250
  logWarn(
3989
4251
  `Description is a TODO placeholder \u2014 edit it (what the ${effectiveKind} does and when to use it) or \`skaile validate\` will fail.`
3990
4252
  );
@@ -4023,12 +4285,16 @@ function makeLibraryCommand() {
4023
4285
  }
4024
4286
  });
4025
4287
  async function renameLibrary(manager, lib, newName) {
4288
+ if (libraryDirMissing(lib)) {
4289
+ logErr(missingLibraryDirMessage(lib));
4290
+ process.exit(1);
4291
+ }
4026
4292
  requireValidLibraryName(newName);
4027
4293
  if (await manager.getLibrary(newName)) {
4028
4294
  logErr(`A library named "${newName}" is already registered.`);
4029
4295
  process.exit(1);
4030
4296
  }
4031
- const newPath = path18.join(path18.dirname(lib.path), newName);
4297
+ const newPath = path22.join(path22.dirname(lib.path), newName);
4032
4298
  refuseGlobalInstallFolder(newName, newPath);
4033
4299
  if (fs8.existsSync(newPath)) {
4034
4300
  logErr(`Target directory already exists: ${newPath}`);
@@ -4114,7 +4380,7 @@ function makeLibraryCommand() {
4114
4380
  }
4115
4381
  patch.isDefault = false;
4116
4382
  } else if (field === "path") {
4117
- const dir = path18.resolve(value);
4383
+ const dir = path22.resolve(value);
4118
4384
  if (!fs8.existsSync(dir) || !fs8.statSync(dir).isDirectory()) {
4119
4385
  logErr(`Directory does not exist: ${dir}. \`library set path=\` does not move files.`);
4120
4386
  process.exit(1);
@@ -4326,16 +4592,16 @@ function makeLibraryCommand() {
4326
4592
  "With --create-repo: create the repo private (the store only accepts public repos)"
4327
4593
  ).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(
4328
4594
  async (lib, opts) => {
4329
- const { runLibraryPublish } = await import('../library-publish-OS3JDW4S.js');
4595
+ const { runLibraryPublish } = await import('../library-publish-DI4Q5UOG.js');
4330
4596
  await withStoreErrorHandling(() => runLibraryPublish(lib, opts));
4331
4597
  }
4332
4598
  );
4333
4599
  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) => {
4334
- const { runLibraryRegister } = await import('../library-publish-OS3JDW4S.js');
4600
+ const { runLibraryRegister } = await import('../library-publish-DI4Q5UOG.js');
4335
4601
  await withStoreErrorHandling(() => runLibraryRegister(lib, opts));
4336
4602
  });
4337
4603
  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) => {
4338
- const { runLibraryYank } = await import('../library-publish-OS3JDW4S.js');
4604
+ const { runLibraryYank } = await import('../library-publish-DI4Q5UOG.js');
4339
4605
  await withStoreErrorHandling(() => runLibraryYank(lib, opts));
4340
4606
  });
4341
4607
  return cmd;
@@ -4386,9 +4652,9 @@ async function printOverallStatus(projectDir, asJson) {
4386
4652
  } catch {
4387
4653
  secretsStrategy = "unavailable";
4388
4654
  }
4389
- const resolvedProjectDir = path18.resolve(projectDir);
4390
- const hasWorkspaceConfig = existsSync(path18.join(resolvedProjectDir, "skaile.yaml"));
4391
- const hasLockFile = existsSync(path18.join(resolvedProjectDir, "skaile.lock.yaml"));
4655
+ const resolvedProjectDir = path22.resolve(projectDir);
4656
+ const hasWorkspaceConfig = existsSync(path22.join(resolvedProjectDir, "skaile.yaml"));
4657
+ const hasLockFile = existsSync(path22.join(resolvedProjectDir, "skaile.lock.yaml"));
4392
4658
  let assignments = [];
4393
4659
  if (hasWorkspaceConfig) {
4394
4660
  try {
@@ -4995,7 +5261,7 @@ function scheduleSoftDepPreview() {
4995
5261
  }
4996
5262
  async function loadAssets() {
4997
5263
  softDepPreviewCache.clear();
4998
- const { gatherAssetFeeds } = await import('../asset-feeds-ELEBTNUS.js');
5264
+ const { gatherAssetFeeds } = await import('../asset-feeds-AM6PSSGM.js');
4999
5265
  const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
5000
5266
  if (notes.length > 0) {
5001
5267
  state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
@@ -5003,7 +5269,7 @@ async function loadAssets() {
5003
5269
  const installed = new Set(am.listDeployed().map((e) => `${e.kind}:${e.name}`));
5004
5270
  let lock = null;
5005
5271
  try {
5006
- lock = readLock(path18__default.join(am.projectDir, "skaile.lock.yaml"));
5272
+ lock = readLock(path22__default.join(am.projectDir, "skaile.lock.yaml"));
5007
5273
  } catch {
5008
5274
  }
5009
5275
  const rows = buildAssetRows(
@@ -5025,7 +5291,7 @@ function rebuildSourceTree() {
5025
5291
  rebuildVisibleSources();
5026
5292
  }
5027
5293
  function sourceOrgRepo(s) {
5028
- const parts = s.path.split(path18__default.sep).filter(Boolean);
5294
+ const parts = s.path.split(path22__default.sep).filter(Boolean);
5029
5295
  if (parts.length < 2) return null;
5030
5296
  return { org: parts[parts.length - 2], repo: parts[parts.length - 1] };
5031
5297
  }
@@ -5199,13 +5465,13 @@ function reconcileCollapsedSets(rows) {
5199
5465
  async function loadSourcesAndLibraries() {
5200
5466
  try {
5201
5467
  const [{ openLibraryManager: openLibraryManager2 }, { getGlobalCacheDir: getGlobalCacheDir2, globalSkaileDir: globalSkaileDir2 }] = await Promise.all([
5202
- import('../open-library-4QSUORI6.js'),
5468
+ import('../open-library-N6ESO6IK.js'),
5203
5469
  import('../core/index.js')
5204
5470
  ]);
5205
5471
  const { manager, library, close } = await openLibraryManager2();
5206
5472
  try {
5207
5473
  const newRoot = getGlobalCacheDir2();
5208
- const legacyRoot = path18__default.join(globalSkaileDir2(), "sources");
5474
+ const legacyRoot = path22__default.join(globalSkaileDir2(), "sources");
5209
5475
  const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
5210
5476
  const libs = await manager.listLibraries();
5211
5477
  const defs = await library.listAssetDefs();
@@ -5331,12 +5597,25 @@ function pendingCountsFor(match) {
5331
5597
  }
5332
5598
  return [add, remove];
5333
5599
  }
5334
- function groupStatus(refs) {
5335
- if (refs.length === 0) return pc5.dim("\xB7 ");
5336
- if (refs.some((r) => state.pendingAdds.has(r))) return pc5.blue("+ ");
5337
- if (refs.some((r) => state.pendingRemoves.has(r))) return pc5.red("- ");
5338
- const allInstalled = refs.every((r) => findAssetRow(r)?.installed);
5339
- return allInstalled ? pc5.green("\u2713 ") : pc5.dim("\xB7 ");
5600
+ function groupSelectionState(rows, pendingAdds, pendingRemoves) {
5601
+ const own = rows.filter((r) => assetRefOf(r) !== null);
5602
+ if (own.length === 0) return "empty";
5603
+ const refs = refsOf(own);
5604
+ if (refs.some((r) => pendingAdds.has(r))) return "add";
5605
+ if (refs.some((r) => pendingRemoves.has(r))) return "remove";
5606
+ return own.every((r) => r.installed) ? "installed" : "none";
5607
+ }
5608
+ function groupStatus(rows) {
5609
+ switch (groupSelectionState(rows, state.pendingAdds, state.pendingRemoves)) {
5610
+ case "add":
5611
+ return pc5.blue("+ ");
5612
+ case "remove":
5613
+ return pc5.red("- ");
5614
+ case "installed":
5615
+ return pc5.green("\u2713 ");
5616
+ default:
5617
+ return pc5.dim("\xB7 ");
5618
+ }
5340
5619
  }
5341
5620
  function renderHeaderLine(opts) {
5342
5621
  const indicator = opts.collapsed ? "\u25B6" : "\u25BC";
@@ -5348,7 +5627,7 @@ function renderHeaderLine(opts) {
5348
5627
  if (add > 0) count += pc5.green(`+${add}`);
5349
5628
  if (remove > 0) count += pc5.red(`-${remove}`);
5350
5629
  count += `/${total}`;
5351
- const status4 = groupStatus(opts.refs);
5630
+ const status4 = groupStatus(countRows.filter(opts.match));
5352
5631
  const line = `${opts.indent}${status4}${indicator} ${opts.label} (${count} assets)`;
5353
5632
  return opts.selected ? pc5.bgWhite(pc5.black(`${line} `.padEnd(state.cols))) : line;
5354
5633
  }
@@ -5360,7 +5639,6 @@ function renderAssetRow(row, selected) {
5360
5639
  indent: " ",
5361
5640
  collapsed: state.collapsedOrigins.has(origin),
5362
5641
  match: (r) => isAsset(r) && rowOrigin(r) === origin,
5363
- refs: originAssetRefs(state.assetRows, origin),
5364
5642
  label: `${meta.icon} ${pc5.bold(pc5.cyan(meta.label))}`,
5365
5643
  selected
5366
5644
  });
@@ -5371,7 +5649,6 @@ function renderAssetRow(row, selected) {
5371
5649
  indent: " ".repeat(3),
5372
5650
  collapsed: state.collapsedSources.has(srcKey(origin, row.source)),
5373
5651
  match: (r) => isAsset(r) && inSource(r, origin, row.source),
5374
- refs: sourceAssetRefs(state.assetRows, origin, row.source),
5375
5652
  label: pc5.bold(pc5.cyan(row.source)),
5376
5653
  selected
5377
5654
  });
@@ -5383,7 +5660,6 @@ function renderAssetRow(row, selected) {
5383
5660
  indent: " ".repeat(5),
5384
5661
  collapsed: state.collapsedPlugins.has(pluginKey(origin, row.source, plugin)),
5385
5662
  match: (r) => isAsset(r) && inPlugin(r, origin, row.source, plugin),
5386
- refs: pluginAssetRefs(state.assetRows, origin, row.source, plugin),
5387
5663
  label: pluginHeaderLabel(plugin),
5388
5664
  selected
5389
5665
  });
@@ -5426,7 +5702,6 @@ function renderSourceTreeRow(row, selected) {
5426
5702
  indent: " ".repeat(3),
5427
5703
  collapsed: state.collapsedSourceOrgs.has(org),
5428
5704
  match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org,
5429
- refs: sourceOrgRefs(state.sourceTreeRows, org),
5430
5705
  label: pc5.bold(pc5.cyan(org)),
5431
5706
  selected,
5432
5707
  rows: state.sourceTreeRows
@@ -5439,7 +5714,6 @@ function renderSourceTreeRow(row, selected) {
5439
5714
  indent: " ".repeat(5),
5440
5715
  collapsed: state.collapsedSourceRepos.has(repoKey(org, repo)),
5441
5716
  match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo,
5442
- refs: sourceRepoRefs(state.sourceTreeRows, org, repo),
5443
5717
  label: pc5.bold(repo),
5444
5718
  selected,
5445
5719
  rows: state.sourceTreeRows
@@ -5453,7 +5727,6 @@ function renderSourceTreeRow(row, selected) {
5453
5727
  indent: " ".repeat(7),
5454
5728
  collapsed: state.collapsedSourcePlugins.has(srcPluginKey(org, repo, plugin)),
5455
5729
  match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo && r.plugin === plugin,
5456
- refs: sourcePluginRefs(state.sourceTreeRows, org, repo, plugin),
5457
5730
  label: pluginHeaderLabel(plugin),
5458
5731
  selected,
5459
5732
  rows: state.sourceTreeRows
@@ -5474,7 +5747,6 @@ function renderLibraryTreeRow(row, selected) {
5474
5747
  indent: " ".repeat(3),
5475
5748
  collapsed: state.collapsedLibraryGroups.has(group),
5476
5749
  match: (r) => isAsset(r) && rowOrigin(r) === "library" && rowGroup(r) === group,
5477
- refs: libraryGroupRefs(state.libraryTreeRows, group),
5478
5750
  label: pc5.bold(pc5.cyan(group)),
5479
5751
  selected,
5480
5752
  rows: state.libraryTreeRows
@@ -5487,7 +5759,6 @@ function renderLibraryTreeRow(row, selected) {
5487
5759
  indent: " ".repeat(5),
5488
5760
  collapsed: state.collapsedLibraryPlugins.has(libPluginKey(group, plugin)),
5489
5761
  match: (r) => isAsset(r) && inPlugin(r, "library", group, plugin),
5490
- refs: pluginAssetRefs(state.libraryTreeRows, "library", group, plugin),
5491
5762
  label: pluginHeaderLabel(plugin),
5492
5763
  selected,
5493
5764
  rows: state.libraryTreeRows
@@ -6160,19 +6431,19 @@ async function run(projectDir) {
6160
6431
  }
6161
6432
  function makeManageCommand() {
6162
6433
  return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
6163
- await run(path18__default.resolve(opts.projectDir));
6434
+ await run(path22__default.resolve(opts.projectDir));
6164
6435
  });
6165
6436
  }
6166
6437
  function makeMcpServerCommand() {
6167
6438
  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) => {
6168
- const path43 = await import('path');
6169
- const projectDir = path43.default.resolve(opts.projectDir);
6170
- const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
6171
- registerLogStore(
6172
- new LogStore({
6439
+ const path44 = await import('path');
6440
+ const projectDir = path44.default.resolve(opts.projectDir);
6441
+ const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
6442
+ registerLogStore2(
6443
+ new LogStore2({
6173
6444
  sessionId: "mcp-server",
6174
6445
  level: "info",
6175
- sinks: [new StdoutSink({ stream: "stderr" })]
6446
+ sinks: [new StdoutSink2({ stream: "stderr" })]
6176
6447
  })
6177
6448
  );
6178
6449
  const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
@@ -6213,10 +6484,10 @@ function walkFiles(root, match) {
6213
6484
  return;
6214
6485
  }
6215
6486
  for (const entry of entries) {
6216
- const full = path18__default.join(dir, entry.name);
6487
+ const full = path22__default.join(dir, entry.name);
6217
6488
  if (entry.isDirectory()) {
6218
6489
  if (SKIPPED_DIRS.has(entry.name)) continue;
6219
- if (entry.name === "cache" && path18__default.basename(dir) === ".skaile") continue;
6490
+ if (entry.name === "cache" && path22__default.basename(dir) === ".skaile") continue;
6220
6491
  visit(full);
6221
6492
  } else if (entry.isFile() && match(entry.name)) {
6222
6493
  out.push(full);
@@ -6234,14 +6505,14 @@ function applyChanges2(changes) {
6234
6505
  switch (change.type) {
6235
6506
  case "write":
6236
6507
  case "create":
6237
- mkdirSync(path18__default.dirname(change.path), { recursive: true });
6508
+ mkdirSync(path22__default.dirname(change.path), { recursive: true });
6238
6509
  writeFileSync(change.path, change.after, "utf-8");
6239
6510
  break;
6240
6511
  case "delete":
6241
6512
  rmSync(change.path, { force: true });
6242
6513
  break;
6243
6514
  case "move":
6244
- mkdirSync(path18__default.dirname(change.to), { recursive: true });
6515
+ mkdirSync(path22__default.dirname(change.to), { recursive: true });
6245
6516
  writeFileSync(change.to, change.after, "utf-8");
6246
6517
  rmSync(change.from, { force: true });
6247
6518
  break;
@@ -6334,7 +6605,7 @@ function unifiedDiff(before, after, oldLabel, newLabel, context = 3) {
6334
6605
  return `${out.join("\n")}
6335
6606
  `;
6336
6607
  }
6337
- var posix = (p6) => p6.split(path18__default.sep).join("/");
6608
+ var posix = (p6) => p6.split(path22__default.sep).join("/");
6338
6609
  function colorizeDiff(diff) {
6339
6610
  return diff.split("\n").map((line) => {
6340
6611
  if (line.startsWith("+++") || line.startsWith("---")) return S.bold(line);
@@ -6345,7 +6616,7 @@ function colorizeDiff(diff) {
6345
6616
  }).join("\n");
6346
6617
  }
6347
6618
  function renderChange(change, base) {
6348
- const rel = (p6) => posix(path18__default.relative(base, p6) || path18__default.basename(p6));
6619
+ const rel = (p6) => posix(path22__default.relative(base, p6) || path22__default.basename(p6));
6349
6620
  switch (change.type) {
6350
6621
  case "write":
6351
6622
  return unifiedDiff(
@@ -6372,7 +6643,7 @@ ${diff}`;
6372
6643
  }
6373
6644
  }
6374
6645
  function changeLabel(change, base) {
6375
- const rel = (p6) => posix(path18__default.relative(base, p6) || path18__default.basename(p6));
6646
+ const rel = (p6) => posix(path22__default.relative(base, p6) || path22__default.basename(p6));
6376
6647
  switch (change.type) {
6377
6648
  case "write":
6378
6649
  return `modify ${rel(change.path)}`;
@@ -6432,7 +6703,7 @@ function loadAsset(projectDir, id, ref) {
6432
6703
  )
6433
6704
  };
6434
6705
  }
6435
- const manifestPath = path18__default.join(dir, AGENT_MANIFEST_FILE);
6706
+ const manifestPath = path22__default.join(dir, AGENT_MANIFEST_FILE);
6436
6707
  let text;
6437
6708
  try {
6438
6709
  text = fs8__default.readFileSync(manifestPath, "utf-8");
@@ -6619,7 +6890,7 @@ function findManifestCandidates(rootPath) {
6619
6890
  return;
6620
6891
  }
6621
6892
  for (const entry of entries) {
6622
- const fullPath = path18__default.join(dir, entry.name);
6893
+ const fullPath = path22__default.join(dir, entry.name);
6623
6894
  if (entry.isDirectory()) {
6624
6895
  if (!SKIP_DIRS.has(entry.name)) walk(fullPath);
6625
6896
  } else if (entry.isFile()) {
@@ -6635,30 +6906,11 @@ function findManifestCandidates(rootPath) {
6635
6906
  walk(rootPath);
6636
6907
  return candidates;
6637
6908
  }
6638
- function checkManifestIdentity(kind, parsed) {
6639
- if (parsed === null || typeof parsed !== "object") return null;
6640
- const obj = parsed;
6641
- const identity = kind === "flow" ? obj.id : obj.name;
6642
- if (typeof identity !== "string" || identity.length === 0) return null;
6643
- const publisher = typeof obj.publisher === "string" ? obj.publisher : void 0;
6644
- if (publisher !== void 0) {
6645
- try {
6646
- parseAssetRef(`${kind}:@${publisher}/${identity}`);
6647
- return null;
6648
- } catch (e) {
6649
- return e instanceof Error ? e.message : String(e);
6650
- }
6651
- }
6652
- if (!isValidAssetName(identity)) {
6653
- return `invalid asset ${kind === "flow" ? "id" : "name"} "${identity}" \u2014 ${ASSET_NAME_HINT}`;
6654
- }
6655
- return null;
6656
- }
6657
6909
  function parseManifestCandidate(c, absRoot) {
6658
6910
  const content = fs8__default.readFileSync(c.filePath, "utf-8");
6659
6911
  const res = parseManifestFile(c.filePath, content);
6660
6912
  if (!res.ok) {
6661
- logErr(`${path18__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 parse error: ${res.reason}`);
6913
+ logErr(`${path22__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 parse error: ${res.reason}`);
6662
6914
  return { kind: "error" };
6663
6915
  }
6664
6916
  return {
@@ -6687,22 +6939,24 @@ function checkComposeKinds(parsed, registry) {
6687
6939
  });
6688
6940
  return diagnostics;
6689
6941
  }
6942
+ function libraryRootOf(absRoot) {
6943
+ for (let dir = absRoot; ; dir = path22__default.dirname(dir)) {
6944
+ if (fs8__default.existsSync(path22__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
6945
+ if (path22__default.dirname(dir) === dir) return absRoot;
6946
+ }
6947
+ }
6690
6948
  function validateManifestCandidate(c, parsed, body, absRoot, registry, strictConformance) {
6691
- const relPath = path18__default.relative(absRoot, c.filePath);
6949
+ const relPath = path22__default.relative(absRoot, c.filePath);
6692
6950
  let errors = 0;
6693
6951
  let warnings = 0;
6694
- const identityError = checkManifestIdentity(c.kind, parsed);
6695
- if (identityError) {
6696
- logErr(`${relPath} [${c.kind}] \u2014 ${identityError}`);
6697
- errors++;
6698
- }
6699
- const dirName = path18__default.basename(path18__default.dirname(c.filePath));
6952
+ const dirName = path22__default.basename(path22__default.dirname(c.filePath));
6700
6953
  const checked = checkAsset(
6701
6954
  c.kind,
6702
6955
  parsed ?? {},
6703
6956
  body,
6704
6957
  dirName,
6705
- registry
6958
+ registry,
6959
+ fs8__default.readFileSync(c.filePath, "utf-8")
6706
6960
  );
6707
6961
  for (const f of checked.errors) {
6708
6962
  logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
@@ -6718,7 +6972,17 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
6718
6972
  warnings++;
6719
6973
  }
6720
6974
  }
6721
- if (c.kind === "agent" && path18__default.basename(c.filePath) === "agent.yaml") {
6975
+ if (c.kind === "agent" && parsed !== null && typeof parsed === "object") {
6976
+ for (const f of checkAgentFiles(
6977
+ parsed,
6978
+ path22__default.dirname(c.filePath),
6979
+ libraryRootOf(absRoot)
6980
+ )) {
6981
+ logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
6982
+ errors++;
6983
+ }
6984
+ }
6985
+ if (c.kind === "agent" && path22__default.basename(c.filePath) === "agent.yaml") {
6722
6986
  for (const d of [
6723
6987
  ...checkComposeKinds(parsed, registry),
6724
6988
  ...composeSlotDiagnostics(parsed),
@@ -6737,7 +7001,7 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
6737
7001
  return { errors, warnings };
6738
7002
  }
6739
7003
  function validateManifests(rootPath, strictConformance) {
6740
- const absRoot = path18__default.resolve(rootPath);
7004
+ const absRoot = path22__default.resolve(rootPath);
6741
7005
  if (!fs8__default.existsSync(absRoot)) {
6742
7006
  logErr(`Path does not exist: ${absRoot}`);
6743
7007
  return { total: 0, errors: 1, warnings: 0 };
@@ -6747,6 +7011,7 @@ function validateManifests(rootPath, strictConformance) {
6747
7011
  let errors = 0;
6748
7012
  let warnings = 0;
6749
7013
  const seenIdentity = /* @__PURE__ */ new Map();
7014
+ const agentsToResolve = [];
6750
7015
  for (const c of candidates) {
6751
7016
  const parseResult = parseManifestCandidate(c, absRoot);
6752
7017
  if (parseResult.kind === "error") {
@@ -6763,22 +7028,36 @@ function validateManifests(rootPath, strictConformance) {
6763
7028
  );
6764
7029
  errors += delta.errors;
6765
7030
  warnings += delta.warnings;
7031
+ if (c.kind === "agent" && parseResult.parsed !== null && typeof parseResult.parsed === "object") {
7032
+ agentsToResolve.push({
7033
+ relPath: path22__default.relative(absRoot, c.filePath),
7034
+ parsed: parseResult.parsed
7035
+ });
7036
+ }
6766
7037
  const obj = parseResult.parsed;
6767
7038
  const identity = obj && typeof obj === "object" ? obj[c.kind === "flow" ? "id" : "name"] : null;
6768
7039
  if (typeof identity === "string" && identity.length > 0) {
6769
- const dir = path18__default.dirname(c.filePath);
7040
+ const dir = path22__default.dirname(c.filePath);
6770
7041
  const key = `${c.kind}:${identity}`;
6771
7042
  const first = seenIdentity.get(key);
6772
7043
  if (first === void 0) {
6773
7044
  seenIdentity.set(key, dir);
6774
7045
  } else if (first !== dir) {
6775
7046
  logErr(
6776
- `${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).`
7047
+ `${path22__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 ${key} is also defined in ${path22__default.relative(absRoot, first) || "."}; two directories cannot share a kind and name (\`skaile library index\` keeps only the first).`
6777
7048
  );
6778
7049
  errors++;
6779
7050
  }
6780
7051
  }
6781
7052
  }
7053
+ const libraryPublisher = loadSkPublishManifest(libraryRootOf(absRoot))?.publisher;
7054
+ const hasAsset = (kind, name) => seenIdentity.has(`${kind}:${name}`);
7055
+ for (const agent of agentsToResolve) {
7056
+ for (const f of agentComposeRefAdvisories(agent.parsed, hasAsset, libraryPublisher)) {
7057
+ logWarn(`${agent.relPath} [${f.tag}] \u2014 ${f.text}`);
7058
+ warnings++;
7059
+ }
7060
+ }
6782
7061
  return { total: candidates.length, errors, warnings };
6783
7062
  }
6784
7063
  function findWorkspaceManifests(rootPath) {
@@ -6791,7 +7070,7 @@ function findWorkspaceManifests(rootPath) {
6791
7070
  return;
6792
7071
  }
6793
7072
  for (const entry of entries) {
6794
- const full = path18__default.join(dir, entry.name);
7073
+ const full = path22__default.join(dir, entry.name);
6795
7074
  if (entry.isDirectory()) {
6796
7075
  if (!SKIP_DIRS.has(entry.name)) walk(full);
6797
7076
  } else if (entry.isFile() && /(^|\.)skaile\.yaml$/.test(entry.name)) {
@@ -6854,11 +7133,11 @@ function validateWorkspaceAssets(parsed, relPath) {
6854
7133
  return errors;
6855
7134
  }
6856
7135
  function validateWorkspaceManifests(rootPath) {
6857
- const absRoot = path18__default.resolve(rootPath);
7136
+ const absRoot = path22__default.resolve(rootPath);
6858
7137
  const files = findWorkspaceManifests(absRoot);
6859
7138
  let errors = 0;
6860
7139
  for (const file of files) {
6861
- const relPath = path18__default.relative(absRoot, file);
7140
+ const relPath = path22__default.relative(absRoot, file);
6862
7141
  let parsed;
6863
7142
  try {
6864
7143
  parsed = parse(fs8__default.readFileSync(file, "utf-8")) ?? {};
@@ -6869,7 +7148,7 @@ function validateWorkspaceManifests(rootPath) {
6869
7148
  }
6870
7149
  errors += validateWorkspaceRefs(collectWorkspaceRefFields(parsed), relPath);
6871
7150
  errors += validateWorkspaceAssets(parsed, relPath);
6872
- for (const d of checkAgentInstances(path18__default.dirname(file), parsed)) {
7151
+ for (const d of checkAgentInstances(path22__default.dirname(file), parsed)) {
6873
7152
  const line = `${relPath} [agents] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`;
6874
7153
  if (d.severity === "error") {
6875
7154
  logErr(line);
@@ -6878,11 +7157,16 @@ function validateWorkspaceManifests(rootPath) {
6878
7157
  logWarn(line);
6879
7158
  }
6880
7159
  }
7160
+ for (const d of decodeSkaileYaml(fs8__default.readFileSync(file, "utf-8")).diagnostics) {
7161
+ if (d.code !== "connector_missing_driver") continue;
7162
+ logErr(`${relPath} [connectors] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`);
7163
+ errors++;
7164
+ }
6881
7165
  }
6882
7166
  return { total: files.length, errors };
6883
7167
  }
6884
7168
  function validatePublishManifestRoots(rootPath) {
6885
- const absRoot = path18__default.resolve(rootPath);
7169
+ const absRoot = path22__default.resolve(rootPath);
6886
7170
  const manifest = loadSkPublishManifest(absRoot);
6887
7171
  if (!manifest) return 0;
6888
7172
  const missing = missingRootAssets(absRoot, manifest);
@@ -6894,7 +7178,7 @@ function validatePublishManifestRoots(rootPath) {
6894
7178
  return missing.length;
6895
7179
  }
6896
7180
  function validatePublishManifestRequires(rootPath) {
6897
- const problems = manifestRequiresProblems(path18__default.resolve(rootPath));
7181
+ const problems = manifestRequiresProblems(path22__default.resolve(rootPath));
6898
7182
  for (const p6 of problems) {
6899
7183
  logErr(
6900
7184
  `${SKAILE_MANIFEST_FILENAME} [assets] \u2014 ${p6.asset}: ${p6.message}. Use the \`kind:@<publisher>/name[#version]\` form.`
@@ -6903,18 +7187,27 @@ function validatePublishManifestRequires(rootPath) {
6903
7187
  return problems.length;
6904
7188
  }
6905
7189
  function validatePublishManifestPublisherSlugs(rootPath) {
6906
- const problems = manifestPublisherProblems(path18__default.resolve(rootPath));
7190
+ const problems = manifestPublisherProblems(path22__default.resolve(rootPath));
6907
7191
  for (const message of problems) logErr(message);
6908
7192
  return problems.length;
6909
7193
  }
7194
+ function validatePublishManifestParses(rootPath) {
7195
+ try {
7196
+ assertManifestEditable(path22__default.resolve(rootPath));
7197
+ return 0;
7198
+ } catch (err2) {
7199
+ logErr(err2 instanceof Error ? err2.message : String(err2));
7200
+ return 1;
7201
+ }
7202
+ }
6910
7203
  function validatePublishManifestVersions(rootPath) {
6911
- const absRoot = path18__default.resolve(rootPath);
7204
+ const absRoot = path22__default.resolve(rootPath);
6912
7205
  const manifest = loadSkPublishManifest(absRoot);
6913
7206
  if (!manifest || manifest.source) return 0;
6914
7207
  let warnings = 0;
6915
7208
  for (const a of manifest.assets ?? []) {
6916
7209
  if (!a.root || a.source || !a.version) continue;
6917
- const file = findAssetManifestFile(path18__default.join(absRoot, a.root), a.kind, a.name);
7210
+ const file = findAssetManifestFile(path22__default.join(absRoot, a.root), a.kind, a.name);
6918
7211
  if (!file) continue;
6919
7212
  const res = parseManifestFile(file, fs8__default.readFileSync(file, "utf-8"));
6920
7213
  if (!res.ok) continue;
@@ -6924,7 +7217,7 @@ function validatePublishManifestVersions(rootPath) {
6924
7217
  manifestVersionMismatchMessage(
6925
7218
  assetEntryRef(a, manifest),
6926
7219
  a.version,
6927
- toPosix(path18__default.relative(absRoot, file)),
7220
+ toPosix(path22__default.relative(absRoot, file)),
6928
7221
  fileVersion
6929
7222
  )
6930
7223
  );
@@ -6933,7 +7226,7 @@ function validatePublishManifestVersions(rootPath) {
6933
7226
  return warnings;
6934
7227
  }
6935
7228
  function validatePublishManifestPublishers(rootPath) {
6936
- const absRoot = path18__default.resolve(rootPath);
7229
+ const absRoot = path22__default.resolve(rootPath);
6937
7230
  const manifest = loadSkPublishManifest(absRoot);
6938
7231
  if (!manifest || manifest.source) return 0;
6939
7232
  const bare = (p6) => p6.trim().replace(/^@/, "");
@@ -6941,7 +7234,7 @@ function validatePublishManifestPublishers(rootPath) {
6941
7234
  for (const a of manifest.assets ?? []) {
6942
7235
  const resolved = a.publisher ?? manifest.publisher;
6943
7236
  if (!a.root || a.source || !resolved) continue;
6944
- const file = findAssetManifestFile(path18__default.join(absRoot, a.root), a.kind, a.name);
7237
+ const file = findAssetManifestFile(path22__default.join(absRoot, a.root), a.kind, a.name);
6945
7238
  if (!file) continue;
6946
7239
  const res = parseManifestFile(file, fs8__default.readFileSync(file, "utf-8"));
6947
7240
  if (!res.ok) continue;
@@ -6949,7 +7242,7 @@ function validatePublishManifestPublishers(rootPath) {
6949
7242
  const declared = meta !== null && typeof meta === "object" ? meta.publisher : null;
6950
7243
  if (typeof declared !== "string" || bare(declared) === bare(resolved)) continue;
6951
7244
  logWarn(
6952
- `${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}.`
7245
+ `${toPosix(path22__default.relative(absRoot, file))} [publisher] \u2014 metadata.publisher "${bare(declared)}" differs from the manifest publisher "${bare(resolved)}" for ${assetEntryRef(a, manifest)}. The manifest wins and the file value is ignored: delete \`metadata.publisher\` from the file, or set the publisher in ${SKAILE_MANIFEST_FILENAME}.`
6953
7246
  );
6954
7247
  warnings++;
6955
7248
  }
@@ -6957,7 +7250,7 @@ function validatePublishManifestPublishers(rootPath) {
6957
7250
  }
6958
7251
  var EXCLUDED_PATHS = ["skaileup-shared/", "external/", "docs/"];
6959
7252
  function toPosix(p6) {
6960
- return p6.split(path18__default.sep).join("/");
7253
+ return p6.split(path22__default.sep).join("/");
6961
7254
  }
6962
7255
  function isExcludedPath(relPath) {
6963
7256
  const rel = toPosix(relPath);
@@ -6973,8 +7266,8 @@ var VERSIONED_KINDS = {
6973
7266
  };
6974
7267
  function readAssetVersion(c) {
6975
7268
  const kind = c.kind;
6976
- const fileName = path18__default.basename(c.filePath);
6977
- const dirName = path18__default.basename(path18__default.dirname(c.filePath));
7269
+ const fileName = path22__default.basename(c.filePath);
7270
+ const dirName = path22__default.basename(path22__default.dirname(c.filePath));
6978
7271
  const content = fs8__default.readFileSync(c.filePath, "utf-8");
6979
7272
  if (c.filePath.endsWith(".md")) {
6980
7273
  const res = parseManifestFile(c.filePath, content);
@@ -7013,21 +7306,21 @@ function collectAssetVersions(root) {
7013
7306
  for (const c of findManifestCandidates(root)) {
7014
7307
  if (!VERSIONED_KINDS[c.kind]) continue;
7015
7308
  if (c.filePath.endsWith(".flow.json")) continue;
7016
- if (isExcludedPath(path18__default.relative(root, c.filePath))) continue;
7309
+ if (isExcludedPath(path22__default.relative(root, c.filePath))) continue;
7017
7310
  assets.push(readAssetVersion(c));
7018
7311
  }
7019
7312
  return assets;
7020
7313
  }
7021
7314
  function assetLocation(a, root) {
7022
- return toPosix(path18__default.relative(root, a.filePath));
7315
+ return toPosix(path22__default.relative(root, a.filePath));
7023
7316
  }
7024
7317
  function findChangelogUnit(assetRelPath, root) {
7025
- let dir = path18__default.posix.dirname(toPosix(assetRelPath));
7318
+ let dir = path22__default.posix.dirname(toPosix(assetRelPath));
7026
7319
  for (; ; ) {
7027
7320
  const candidate = dir === "." ? "CHANGELOG.md" : `${dir}/CHANGELOG.md`;
7028
- if (fs8__default.existsSync(path18__default.join(root, candidate))) return candidate;
7321
+ if (fs8__default.existsSync(path22__default.join(root, candidate))) return candidate;
7029
7322
  if (dir === ".") return null;
7030
- dir = path18__default.posix.dirname(dir);
7323
+ dir = path22__default.posix.dirname(dir);
7031
7324
  }
7032
7325
  }
7033
7326
  function checkChangelogUnits(modifiedFiles, root) {
@@ -7077,7 +7370,7 @@ function checkVersionBumps(assets, root) {
7077
7370
  let warnings = 0;
7078
7371
  for (const a of assets) {
7079
7372
  if (!a.version) continue;
7080
- const relPath = toPosix(path18__default.relative(root, a.filePath));
7373
+ const relPath = toPosix(path22__default.relative(root, a.filePath));
7081
7374
  try {
7082
7375
  const headContent = execFileSync("git", ["show", `HEAD:./${relPath}`], {
7083
7376
  cwd: root,
@@ -7110,7 +7403,7 @@ function checkFlowVersionPins(assets, root) {
7110
7403
  pins = flowSkillVersionPins(loadFlow(f.filePath));
7111
7404
  } catch (err2) {
7112
7405
  logWarn(
7113
- `flow:${f.name} (${path18__default.relative(root, f.filePath)}) \u2014 could not be read: ${err2 instanceof Error ? err2.message : err2}`
7406
+ `flow:${f.name} (${path22__default.relative(root, f.filePath)}) \u2014 could not be read: ${err2 instanceof Error ? err2.message : err2}`
7114
7407
  );
7115
7408
  warnings++;
7116
7409
  continue;
@@ -7128,19 +7421,34 @@ function checkFlowVersionPins(assets, root) {
7128
7421
  }
7129
7422
  function resolveCheckRoot(pathArg) {
7130
7423
  if (pathArg) {
7131
- const abs = path18__default.resolve(pathArg);
7424
+ const abs = path22__default.resolve(pathArg);
7132
7425
  if (!fs8__default.existsSync(abs)) {
7133
7426
  logErr(`Path does not exist: ${abs}`);
7134
7427
  return null;
7135
7428
  }
7136
7429
  return abs;
7137
7430
  }
7138
- for (let dir = process.cwd(); ; dir = path18__default.dirname(dir)) {
7139
- if (fs8__default.existsSync(path18__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
7140
- if (path18__default.dirname(dir) === dir) return AI_RESOURCES;
7431
+ for (let dir = process.cwd(); ; dir = path22__default.dirname(dir)) {
7432
+ if (fs8__default.existsSync(path22__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
7433
+ if (path22__default.dirname(dir) === dir) return AI_RESOURCES;
7434
+ }
7435
+ }
7436
+ function isInGitWorkTree(root) {
7437
+ try {
7438
+ return execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
7439
+ cwd: root,
7440
+ encoding: "utf-8",
7441
+ stdio: ["ignore", "pipe", "ignore"]
7442
+ }).trim() === "true";
7443
+ } catch {
7444
+ return false;
7141
7445
  }
7142
7446
  }
7143
- function changedFiles(root, ref) {
7447
+ function changedFiles(root, ref, what, opts = {}) {
7448
+ if (!isInGitWorkTree(root)) {
7449
+ logErr(`${what} needs a git repository: ${root} is not inside a git work tree.`);
7450
+ return null;
7451
+ }
7144
7452
  try {
7145
7453
  const out = execFileSync(
7146
7454
  "git",
@@ -7151,7 +7459,16 @@ function changedFiles(root, ref) {
7151
7459
  stdio: ["ignore", "pipe", "pipe"]
7152
7460
  }
7153
7461
  );
7154
- return out.trim().split("\n").filter(Boolean);
7462
+ const changed = out.trim().split("\n").filter(Boolean);
7463
+ if (opts.untracked) {
7464
+ const fresh = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
7465
+ cwd: root,
7466
+ encoding: "utf-8",
7467
+ stdio: ["ignore", "pipe", "pipe"]
7468
+ });
7469
+ changed.push(...fresh.trim().split("\n").filter(Boolean));
7470
+ }
7471
+ return changed;
7155
7472
  } catch (err2) {
7156
7473
  const stderr = err2 instanceof Error && "stderr" in err2 ? String(err2.stderr).trim() : "";
7157
7474
  const reason = (stderr || (err2 instanceof Error ? err2.message : String(err2))).split("\n")[0];
@@ -7159,6 +7476,22 @@ function changedFiles(root, ref) {
7159
7476
  return null;
7160
7477
  }
7161
7478
  }
7479
+ function assetOwnDir(a) {
7480
+ const dir = path22__default.dirname(a.filePath);
7481
+ if (["skill", "agent", "contract"].includes(a.kind) || path22__default.basename(dir) === a.name) return dir;
7482
+ return null;
7483
+ }
7484
+ function assetChanged(a, changedAbs) {
7485
+ if (changedAbs.has(a.filePath)) return true;
7486
+ const dir = assetOwnDir(a);
7487
+ if (dir === null) return false;
7488
+ for (const f of changedAbs) {
7489
+ const rel = path22__default.relative(dir, f);
7490
+ if (rel.startsWith("..") || path22__default.isAbsolute(rel)) continue;
7491
+ if (!isNonAssetPath(toPosix(rel))) return true;
7492
+ }
7493
+ return false;
7494
+ }
7162
7495
  function runVersionsCheck(pathArg, opts) {
7163
7496
  const root = resolveCheckRoot(pathArg);
7164
7497
  if (root === null) {
@@ -7167,13 +7500,13 @@ function runVersionsCheck(pathArg, opts) {
7167
7500
  }
7168
7501
  let assets = collectAssetVersions(root);
7169
7502
  if (opts.changedOnly) {
7170
- const changed = changedFiles(root, "HEAD");
7503
+ const changed = changedFiles(root, "HEAD", "--changed-only", { untracked: true });
7171
7504
  if (changed === null) {
7172
7505
  process.exit(1);
7173
7506
  return;
7174
7507
  }
7175
- const changedAbs = new Set(changed.map((f) => path18__default.resolve(root, f)));
7176
- assets = assets.filter((a) => changedAbs.has(a.filePath));
7508
+ const changedAbs = new Set(changed.map((f) => path22__default.resolve(root, f)));
7509
+ assets = assets.filter((a) => assetChanged(a, changedAbs));
7177
7510
  }
7178
7511
  logInfo(`Checking versions in ${root}`);
7179
7512
  const versionCheck = checkAssetVersions(assets, root);
@@ -7205,7 +7538,7 @@ function makeValidateCommand() {
7205
7538
  "--strict-conformance",
7206
7539
  "Treat Agent Skills (agentskills.io) standard findings as errors"
7207
7540
  ).action(async (targetPath, opts) => {
7208
- const absPath = path18__default.resolve(targetPath);
7541
+ const absPath = path22__default.resolve(targetPath);
7209
7542
  logInfo(`Validating manifests in ${absPath}`);
7210
7543
  const { total, errors, warnings } = validateManifests(
7211
7544
  absPath,
@@ -7214,13 +7547,14 @@ function makeValidateCommand() {
7214
7547
  const ws = validateWorkspaceManifests(absPath);
7215
7548
  const rootErrors = validatePublishManifestRoots(absPath);
7216
7549
  const slugErrors = validatePublishManifestPublisherSlugs(absPath);
7550
+ const parseErrors = validatePublishManifestParses(absPath);
7217
7551
  const requiresErrors = validatePublishManifestRequires(absPath);
7218
7552
  const versionWarnings = validatePublishManifestVersions(absPath);
7219
7553
  const publisherWarnings = validatePublishManifestPublishers(absPath);
7220
7554
  const dependencyProblems = await unresolvedManifestDependencies(absPath);
7221
7555
  for (const w of dependencyProblems) logWarn(w);
7222
7556
  const dependencyWarnings = dependencyProblems.length;
7223
- const totalErrors = errors + ws.errors + rootErrors + slugErrors + requiresErrors;
7557
+ const totalErrors = errors + ws.errors + rootErrors + slugErrors + parseErrors + requiresErrors;
7224
7558
  console.log();
7225
7559
  warnIgnoredDomainFiles(absPath);
7226
7560
  warnLegacyBundleFiles(absPath);
@@ -7246,7 +7580,7 @@ function makeValidateCommand() {
7246
7580
  process.exit(1);
7247
7581
  return;
7248
7582
  }
7249
- const modifiedFiles = changedFiles(root, opts.base);
7583
+ const modifiedFiles = changedFiles(root, opts.base, "changelog");
7250
7584
  if (modifiedFiles === null) {
7251
7585
  process.exit(1);
7252
7586
  return;
@@ -7295,7 +7629,7 @@ function itemFromRef(raw, defaultKind, ctx) {
7295
7629
  return { kind: prefixed[1], ref: value };
7296
7630
  }
7297
7631
  if (PATH_LIKE.test(value)) return { kind: defaultKind, ref: value };
7298
- if (defaultKind === "skill" && !value.includes("/") && existsSync(path18__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
7632
+ if (defaultKind === "skill" && !value.includes("/") && existsSync(path22__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
7299
7633
  return { kind: "skill", ref: `./skills/${value}` };
7300
7634
  }
7301
7635
  return { kind: defaultKind, ref: `${defaultKind}:${value}` };
@@ -7431,7 +7765,7 @@ function migrateAgentYaml(source, options) {
7431
7765
  manual.push("metadata.soul: not a string; left unchanged");
7432
7766
  continue;
7433
7767
  }
7434
- if (path18__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
7768
+ if (path22__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
7435
7769
  notes.push("metadata.soul \u2192 dropped (SOUL.md is a convention file)");
7436
7770
  } else {
7437
7771
  derived.push({ kind: "persona", ref: soul });
@@ -7665,7 +7999,7 @@ function migrateSubagents(skaileYamlPath, source) {
7665
7999
  if (!isMap(agentNode)) return void 0;
7666
8000
  const subNode = agentNode.get("subagents", true);
7667
8001
  if (!isMap(subNode)) return void 0;
7668
- const dir = path18__default.dirname(skaileYamlPath);
8002
+ const dir = path22__default.dirname(skaileYamlPath);
7669
8003
  const notes = [];
7670
8004
  const manual = [];
7671
8005
  const changes = [];
@@ -7683,10 +8017,10 @@ function migrateSubagents(skaileYamlPath, source) {
7683
8017
  continue;
7684
8018
  }
7685
8019
  const id = instanceId(name);
7686
- const assetDir = path18__default.join(dir, ".skaile", "agents", id);
8020
+ const assetDir = path22__default.join(dir, ".skaile", "agents", id);
7687
8021
  if (takenIds.has(id) || existsSync(assetDir)) {
7688
8022
  manual.push(
7689
- `agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path18__default.relative(dir, assetDir)} already exists`}; left in place`
8023
+ `agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path22__default.relative(dir, assetDir)} already exists`}; left in place`
7690
8024
  );
7691
8025
  continue;
7692
8026
  }
@@ -7710,13 +8044,13 @@ function migrateSubagents(skaileYamlPath, source) {
7710
8044
  manifest.tools = { ...allowed ? { allowed } : {}, ...denied ? { denied } : {} };
7711
8045
  }
7712
8046
  const text = stringify(manifest, { lineWidth: 0 });
7713
- const manifestPath = path18__default.join(assetDir, "agent.yaml");
8047
+ const manifestPath = path22__default.join(assetDir, "agent.yaml");
7714
8048
  changes.push({ type: "create", path: manifestPath, after: text });
7715
8049
  assetManifests.push({ file: manifestPath, text });
7716
8050
  if (typeof spec.prompt === "string" && spec.prompt.trim() !== "") {
7717
8051
  changes.push({
7718
8052
  type: "create",
7719
- path: path18__default.join(assetDir, "SOUL.md"),
8053
+ path: path22__default.join(assetDir, "SOUL.md"),
7720
8054
  after: `${spec.prompt.replace(/\s+$/, "")}
7721
8055
  `
7722
8056
  });
@@ -7775,7 +8109,7 @@ function validateMigratedAgent(text, registry) {
7775
8109
  function collectAgentFiles(paths) {
7776
8110
  const files = /* @__PURE__ */ new Set();
7777
8111
  for (const input of paths) {
7778
- const abs = path18__default.resolve(input);
8112
+ const abs = path22__default.resolve(input);
7779
8113
  if (!existsSync(abs)) continue;
7780
8114
  if (statSync(abs).isDirectory()) {
7781
8115
  for (const f of walkFiles(abs, (b) => b === "agent.yaml" || b === "skaile.yaml"))
@@ -7792,7 +8126,7 @@ function planAgentMigration(options) {
7792
8126
  const reports = [];
7793
8127
  for (const file of collectAgentFiles(options.paths)) {
7794
8128
  const source = readText(file);
7795
- const base = path18__default.basename(file);
8129
+ const base = path22__default.basename(file);
7796
8130
  if (base === "skaile.yaml") {
7797
8131
  const result = migrateSubagents(file, source);
7798
8132
  if (!result) continue;
@@ -7800,7 +8134,7 @@ function planAgentMigration(options) {
7800
8134
  for (const asset of result.assetManifests) {
7801
8135
  const v = validateMigratedAgent(asset.text, options.registry);
7802
8136
  validation2.errors.push(
7803
- ...v.errors.map((e) => `${path18__default.basename(path18__default.dirname(asset.file))}: ${e}`)
8137
+ ...v.errors.map((e) => `${path22__default.basename(path22__default.dirname(asset.file))}: ${e}`)
7804
8138
  );
7805
8139
  validation2.warnings.push(...v.warnings);
7806
8140
  }
@@ -7828,7 +8162,7 @@ function planAgentMigration(options) {
7828
8162
  });
7829
8163
  continue;
7830
8164
  }
7831
- migration = migrateAgentYaml(source, { agentDir: path18__default.dirname(file), knownKinds });
8165
+ migration = migrateAgentYaml(source, { agentDir: path22__default.dirname(file), knownKinds });
7832
8166
  } catch (error) {
7833
8167
  reports.push({
7834
8168
  file,
@@ -7858,7 +8192,7 @@ function planAgentMigration(options) {
7858
8192
  var DEFAULT_PUBLISHER = "skaile-ai";
7859
8193
  var PRESET_DEFAULT_VERSION = "1.0.0";
7860
8194
  var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
7861
- var posix2 = (p6) => p6.split(path18__default.sep).join("/");
8195
+ var posix2 = (p6) => p6.split(path22__default.sep).join("/");
7862
8196
  var MOVED_KINDS = { persona: "PERSONA.md", ruleset: "RULESET.md" };
7863
8197
  var KIND_MANIFEST_FILES = /* @__PURE__ */ new Set(["PERSONA.md", "RULESET.md", "SKILL.md"]);
7864
8198
  function readFrontmatterType(text) {
@@ -7889,14 +8223,14 @@ function planMarkdownMoves(root, knownKinds, manual, unknownTypes) {
7889
8223
  if (!text.startsWith("---")) continue;
7890
8224
  const found = readFrontmatterType(text);
7891
8225
  if (!found) continue;
7892
- const base = path18__default.basename(file);
7893
- const inAgentParts = file.split(path18__default.sep).includes("_agent-parts");
8226
+ const base = path22__default.basename(file);
8227
+ const inAgentParts = file.split(path22__default.sep).includes("_agent-parts");
7894
8228
  const targetName = MOVED_KINDS[found.type];
7895
8229
  if (targetName !== void 0 && !KIND_MANIFEST_FILES.has(base)) {
7896
- const to = path18__default.join(path18__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
8230
+ const to = path22__default.join(path22__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
7897
8231
  if (existsSync(to) || targets.has(to)) {
7898
8232
  manual.push(
7899
- `${posix2(path18__default.relative(root, file))}: ${posix2(path18__default.relative(root, to))} already exists; not moved`
8233
+ `${posix2(path22__default.relative(root, file))}: ${posix2(path22__default.relative(root, to))} already exists; not moved`
7900
8234
  );
7901
8235
  continue;
7902
8236
  }
@@ -7917,13 +8251,13 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
7917
8251
  const changes = [];
7918
8252
  for (const file of walkFiles(root, (b) => b === "agent.yaml")) {
7919
8253
  const source = readText(file);
7920
- const agentDir = path18__default.dirname(file);
8254
+ const agentDir = path22__default.dirname(file);
7921
8255
  let hits = 0;
7922
8256
  const refRewrite = (_kind, ref) => {
7923
- const moved = byOldPath.get(path18__default.resolve(agentDir, ref));
8257
+ const moved = byOldPath.get(path22__default.resolve(agentDir, ref));
7924
8258
  if (moved === void 0) return ref;
7925
8259
  hits++;
7926
- const rel = posix2(path18__default.relative(agentDir, moved));
8260
+ const rel = posix2(path22__default.relative(agentDir, moved));
7927
8261
  return rel.startsWith(".") ? rel : `./${rel}`;
7928
8262
  };
7929
8263
  let output;
@@ -7940,7 +8274,7 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
7940
8274
  if (hits === 0 || output === source) continue;
7941
8275
  changes.push({ type: "write", path: file, before: source, after: output });
7942
8276
  notes.push(
7943
- `${posix2(path18__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
8277
+ `${posix2(path22__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
7944
8278
  );
7945
8279
  }
7946
8280
  return changes;
@@ -7951,10 +8285,9 @@ function presetItemRef(dep, publisher) {
7951
8285
  const [, kind, rest] = match;
7952
8286
  return rest.startsWith("@") ? dep.trim() : `${kind}:@${publisher}/${rest}`;
7953
8287
  }
7954
- function presetText(name, description, refs, publisher, version) {
8288
+ function presetText(name, description, refs, version) {
7955
8289
  return stringify(
7956
8290
  {
7957
- publisher,
7958
8291
  name,
7959
8292
  version,
7960
8293
  description: description && description.trim() !== "" ? description : `Preset ${name}`,
@@ -7965,14 +8298,14 @@ function presetText(name, description, refs, publisher, version) {
7965
8298
  }
7966
8299
  function skillDirs(dir) {
7967
8300
  try {
7968
- 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();
8301
+ return readdirSync(path22__default.join(dir, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync(path22__default.join(dir, "skills", e.name, "SKILL.md"))).map((e) => e.name).sort();
7969
8302
  } catch {
7970
8303
  return [];
7971
8304
  }
7972
8305
  }
7973
8306
  function repoPublisher(root) {
7974
8307
  for (const name of ["skaile.manifest.yaml", "skaile.yaml"]) {
7975
- const file = path18__default.join(root, name);
8308
+ const file = path22__default.join(root, name);
7976
8309
  if (!existsSync(file)) continue;
7977
8310
  try {
7978
8311
  const parsed = parse(readText(file));
@@ -7988,9 +8321,9 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
7988
8321
  const changes = [];
7989
8322
  const presets = [];
7990
8323
  const handled = /* @__PURE__ */ new Set();
7991
- const rel = (p6) => posix2(path18__default.relative(root, p6));
8324
+ const rel = (p6) => posix2(path22__default.relative(root, p6));
7992
8325
  const convert = (name, bundleFile, dir) => {
7993
- const target = path18__default.join(dir, `${name}.preset.yaml`);
8326
+ const target = path22__default.join(dir === root ? path22__default.join(dir, name) : dir, `${name}.preset.yaml`);
7994
8327
  if (existsSync(target)) {
7995
8328
  manual.push(`${rel(target)} already exists; bundle ${name} not converted`);
7996
8329
  return;
@@ -8008,6 +8341,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
8008
8341
  const declared = typeof parsed.version === "string" || typeof parsed.version === "number" ? String(parsed.version) : void 0;
8009
8342
  if (declared !== void 0 && SEMVER_RE.test(declared)) version = declared;
8010
8343
  else if (declared !== void 0) versionNote = `version ${declared} \u2192 ${version}`;
8344
+ else versionNote = `version (none) \u2192 ${version}`;
8011
8345
  const deps = Array.isArray(parsed.dependencies) ? parsed.dependencies : [];
8012
8346
  refs = deps.filter((d) => typeof d === "string").map((d) => presetItemRef(d, publisher));
8013
8347
  if (refs.length !== deps.length) {
@@ -8021,11 +8355,11 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
8021
8355
  }
8022
8356
  if (refs.length === 0) {
8023
8357
  manual.push(
8024
- `bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path18__default.join(dir, "skills"))}`}; no preset generated`
8358
+ `bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path22__default.join(dir, "skills"))}`}; no preset generated`
8025
8359
  );
8026
8360
  return;
8027
8361
  }
8028
- const after = presetText(name, description, refs, publisher, version);
8362
+ const after = presetText(name, description, refs, version);
8029
8363
  if (before !== void 0 && bundleFile) {
8030
8364
  changes.push({ type: "move", from: bundleFile, to: target, before, after });
8031
8365
  handled.add(bundleFile);
@@ -8045,18 +8379,18 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
8045
8379
  const assets = Array.isArray(raw.assets) ? raw.assets : [];
8046
8380
  for (const entry of assets) {
8047
8381
  if (!isRecord(entry) || entry.kind !== "bundle" || typeof entry.name !== "string") continue;
8048
- const baseDir = path18__default.dirname(file);
8049
- const entryRoot = typeof entry.root === "string" ? path18__default.join(baseDir, entry.root) : baseDir;
8382
+ const baseDir = path22__default.dirname(file);
8383
+ const entryRoot = typeof entry.root === "string" ? path22__default.join(baseDir, entry.root) : baseDir;
8050
8384
  const files = Array.isArray(entry.files) ? entry.files : [];
8051
8385
  const bundleName = files.find(
8052
8386
  (f) => typeof f === "string" && f.endsWith(".bundle.yaml")
8053
8387
  );
8054
- convert(entry.name, bundleName ? path18__default.join(entryRoot, bundleName) : void 0, entryRoot);
8388
+ convert(entry.name, bundleName ? path22__default.join(entryRoot, bundleName) : void 0, entryRoot);
8055
8389
  }
8056
8390
  }
8057
8391
  for (const bundleFile of walkFiles(root, (b) => b.endsWith(".bundle.yaml"))) {
8058
8392
  if (handled.has(bundleFile)) continue;
8059
- const base = path18__default.basename(bundleFile);
8393
+ const base = path22__default.basename(bundleFile);
8060
8394
  let name = base.replace(/\.bundle\.yaml$/, "");
8061
8395
  try {
8062
8396
  const parsed = parse(readText(bundleFile));
@@ -8065,7 +8399,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
8065
8399
  } catch {
8066
8400
  }
8067
8401
  if (presets.some((p6) => p6.bundleFile === bundleFile)) continue;
8068
- convert(name, bundleFile, path18__default.dirname(bundleFile));
8402
+ convert(name, bundleFile, path22__default.dirname(bundleFile));
8069
8403
  }
8070
8404
  return changes;
8071
8405
  }
@@ -8075,8 +8409,8 @@ function planSkaileYaml(root, file, source, notes, manual) {
8075
8409
  if (doc.errors.length > 0 || !isMap(doc.contents)) return [];
8076
8410
  const map = doc.contents;
8077
8411
  const raw = doc.toJS();
8078
- const dir = path18__default.dirname(file);
8079
- const rel = (p6) => posix2(path18__default.relative(root, p6));
8412
+ const dir = path22__default.dirname(file);
8413
+ const rel = (p6) => posix2(path22__default.relative(root, p6));
8080
8414
  const changes = [];
8081
8415
  let changed = false;
8082
8416
  const deps = map.get("dependencies", true);
@@ -8093,7 +8427,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
8093
8427
  const hasPublication = PUBLICATION_KEYS.some((k) => raw[k] !== void 0);
8094
8428
  let remove = false;
8095
8429
  if (hasPublication) {
8096
- const manifestPath = path18__default.join(dir, "skaile.manifest.yaml");
8430
+ const manifestPath = path22__default.join(dir, "skaile.manifest.yaml");
8097
8431
  if (existsSync(manifestPath)) {
8098
8432
  manual.push(
8099
8433
  `${rel(file)}: publisher/version/assets left in place \u2014 ${rel(manifestPath)} already exists; merge by hand`
@@ -8150,7 +8484,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
8150
8484
  return changes;
8151
8485
  }
8152
8486
  function planAssetMigration(options) {
8153
- const root = path18__default.resolve(options.root);
8487
+ const root = path22__default.resolve(options.root);
8154
8488
  const knownKinds = new Set(options.registry.getAllKinds());
8155
8489
  const notes = [];
8156
8490
  const manual = [];
@@ -8158,7 +8492,7 @@ function planAssetMigration(options) {
8158
8492
  const { moves, changes: moveChanges } = planMarkdownMoves(root, knownKinds, manual, unknownTypes);
8159
8493
  for (const move of moves) {
8160
8494
  notes.push(
8161
- `${posix2(path18__default.relative(root, move.from))} \u2192 ${posix2(path18__default.relative(root, move.to))} (${move.kind})`
8495
+ `${posix2(path22__default.relative(root, move.from))} \u2192 ${posix2(path22__default.relative(root, move.to))} (${move.kind})`
8162
8496
  );
8163
8497
  }
8164
8498
  const agentChanges = planAgentRefRewrites(root, moves, knownKinds, notes);
@@ -8170,7 +8504,7 @@ function planAssetMigration(options) {
8170
8504
  const raw = parse(source);
8171
8505
  if (isRecord(raw)) skaileYamls.push({ file, source, raw });
8172
8506
  } catch {
8173
- manual.push(`${posix2(path18__default.relative(root, file))}: invalid YAML; skipped`);
8507
+ manual.push(`${posix2(path22__default.relative(root, file))}: invalid YAML; skipped`);
8174
8508
  }
8175
8509
  }
8176
8510
  const publisher = repoPublisher(root);
@@ -8324,7 +8658,7 @@ function workspaceConfigFiles(dir) {
8324
8658
  } catch {
8325
8659
  return [];
8326
8660
  }
8327
- return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path18__default.join(dir, name));
8661
+ return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path22__default.join(dir, name));
8328
8662
  }
8329
8663
  function readAgentConfigBlock(raw) {
8330
8664
  const key = AGENT_CONFIG_KEYS.find((candidate) => raw[candidate] !== void 0);
@@ -8336,7 +8670,7 @@ function readAgentConfigBlock(raw) {
8336
8670
  return flat ? { key, profiles: { default: profiles }, flat } : { key, profiles, flat };
8337
8671
  }
8338
8672
  function planProviderMigration(options) {
8339
- const projectDir = path18__default.resolve(options.projectDir);
8673
+ const projectDir = path22__default.resolve(options.projectDir);
8340
8674
  const registryPath = options.workspace ? workspaceProviderRegistryPath(projectDir) : userProviderRegistryPath();
8341
8675
  const plan = {
8342
8676
  registryPath,
@@ -8352,7 +8686,7 @@ function planProviderMigration(options) {
8352
8686
  raw = parseDocument(readFileSync(file, "utf-8")).toJS() ?? {};
8353
8687
  } catch (error) {
8354
8688
  plan.warnings.push(
8355
- `${path18__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
8689
+ `${path22__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
8356
8690
  );
8357
8691
  continue;
8358
8692
  }
@@ -8401,7 +8735,7 @@ function planProviderMigration(options) {
8401
8735
  });
8402
8736
  if (!model) {
8403
8737
  plan.warnings.push(
8404
- `${path18__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
8738
+ `${path22__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
8405
8739
  );
8406
8740
  }
8407
8741
  touched = true;
@@ -8468,7 +8802,7 @@ function printPlan(plan) {
8468
8802
  for (const entry of plan.entries) {
8469
8803
  const base = entry.entry.base_url ?? S.dim("(transport-derived)");
8470
8804
  console.log(
8471
- ` ${S.label(`${path18__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
8805
+ ` ${S.label(`${path22__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
8472
8806
  );
8473
8807
  console.log(` \u2192 providers.yml ${S.bold(entry.providerId)} ${base}`);
8474
8808
  console.log(
@@ -8484,7 +8818,7 @@ function printPlan(plan) {
8484
8818
  console.log();
8485
8819
  }
8486
8820
  async function runMigrateProviders(opts) {
8487
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
8821
+ const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
8488
8822
  const plan = planProviderMigration({ projectDir, workspace: opts.workspace });
8489
8823
  for (const warning of plan.warnings) logWarn(warning);
8490
8824
  if (plan.entries.length === 0 && Object.keys(plan.providers).length === 0) {
@@ -8566,7 +8900,8 @@ var ASSETS_HELP = `
8566
8900
  Rewrites (run on a repo root):
8567
8901
  type: persona|ruleset markdown <n>.md -> <n>/PERSONA.md | <n>/RULESET.md (type: dropped);
8568
8902
  agent persona:/rules: refs to the old path become composes items
8569
- *.bundle.yaml <name>.preset.yaml beside it (items: kind:@publisher/name);
8903
+ *.bundle.yaml <name>.preset.yaml beside it, or <name>/<name>.preset.yaml
8904
+ for a bundle at the repo root (items: kind:@publisher/name);
8570
8905
  kind: bundle entries of skaile.yaml#assets become kind: preset
8571
8906
  skaile.yaml dependencies bundle:@... -> preset:@...
8572
8907
  skaile.yaml publisher/version/assets
@@ -8615,7 +8950,7 @@ async function runMigrateAgents(paths, opts) {
8615
8950
  let failures = 0;
8616
8951
  let manualCount = 0;
8617
8952
  for (const report of plan.reports) {
8618
- const rel = path18__default.relative(base, report.file) || report.file;
8953
+ const rel = path22__default.relative(base, report.file) || report.file;
8619
8954
  for (const note of report.notes) console.log(` ${S.label(rel)} ${note}`);
8620
8955
  for (const note of report.manual) {
8621
8956
  manualCount++;
@@ -8642,14 +8977,14 @@ async function runMigrateAssets(root, opts) {
8642
8977
  const write = resolveMode(opts);
8643
8978
  const base = process.cwd();
8644
8979
  const plan = planAssetMigration({
8645
- root: path18__default.resolve(root ?? base),
8980
+ root: path22__default.resolve(root ?? base),
8646
8981
  registry: getKindRegistry()
8647
8982
  });
8648
8983
  for (const note of plan.notes) console.log(` ${note}`);
8649
8984
  for (const note of plan.manual) logWarn(note);
8650
8985
  for (const { file, type } of plan.unknownTypes) {
8651
8986
  logWarn(
8652
- `${path18__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
8987
+ `${path22__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
8653
8988
  );
8654
8989
  }
8655
8990
  printChanges(plan.changes, base);
@@ -8672,8 +9007,8 @@ function makeNpxCommand() {
8672
9007
  skills.command("add <url>").description(
8673
9008
  "Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
8674
9009
  ).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) => {
8675
- const projectDir = path18__default.resolve(opts.projectDir);
8676
- const projYaml = path18__default.join(projectDir, "skaile.yaml");
9010
+ const projectDir = path22__default.resolve(opts.projectDir);
9011
+ const projYaml = path22__default.join(projectDir, "skaile.yaml");
8677
9012
  if (!existsSync(projYaml)) {
8678
9013
  logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
8679
9014
  process.exit(1);
@@ -8686,11 +9021,11 @@ function makeNpxCommand() {
8686
9021
  }
8687
9022
  const spinner = createSpinner();
8688
9023
  const key = sourceCacheKey(url);
8689
- const clonePath = path18__default.join(getGlobalCacheDir(), key);
9024
+ const clonePath = path22__default.join(getGlobalCacheDir(), key);
8690
9025
  spinner.start(`Cloning ${url}`);
8691
9026
  try {
8692
9027
  if (!existsSync(clonePath)) {
8693
- mkdirSync(path18__default.dirname(clonePath), { recursive: true });
9028
+ mkdirSync(path22__default.dirname(clonePath), { recursive: true });
8694
9029
  execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
8695
9030
  }
8696
9031
  spinner.stop(`Cloned to ${key}`);
@@ -8745,7 +9080,7 @@ function makeNpxCommand() {
8745
9080
  return npx;
8746
9081
  }
8747
9082
  function resolvePublisher(clonePath, url) {
8748
- const manifestPath = path18__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
9083
+ const manifestPath = path22__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
8749
9084
  if (existsSync(manifestPath)) {
8750
9085
  try {
8751
9086
  const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
@@ -8758,12 +9093,12 @@ function resolvePublisher(clonePath, url) {
8758
9093
  return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
8759
9094
  }
8760
9095
  function resolveSkillName(clonePath, requested) {
8761
- const skillsDir = path18__default.join(clonePath, "skills");
8762
- if (existsSync(path18__default.join(skillsDir, requested, "SKILL.md"))) return requested;
9096
+ const skillsDir = path22__default.join(clonePath, "skills");
9097
+ if (existsSync(path22__default.join(skillsDir, requested, "SKILL.md"))) return requested;
8763
9098
  if (!existsSync(skillsDir)) return requested;
8764
9099
  for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
8765
9100
  if (!entry.isDirectory()) continue;
8766
- const md = path18__default.join(skillsDir, entry.name, "SKILL.md");
9101
+ const md = path22__default.join(skillsDir, entry.name, "SKILL.md");
8767
9102
  if (!existsSync(md)) continue;
8768
9103
  try {
8769
9104
  const { data } = parseFrontmatter(readFileSync(md, "utf8"));
@@ -8793,9 +9128,10 @@ function makeOutdatedCommand() {
8793
9128
  SUPPORTED_DRIVER_TARGETS
8794
9129
  )
8795
9130
  ).action(async (filter, opts) => {
9131
+ requireProjectConfig(opts.projectDir);
8796
9132
  const am2 = new AssetManager({
8797
9133
  registry: getKindRegistry(),
8798
- projectDir: path18__default.resolve(opts.projectDir),
9134
+ projectDir: path22__default.resolve(opts.projectDir),
8799
9135
  driverTarget: opts.target
8800
9136
  });
8801
9137
  const entries = await am2.outdated();
@@ -8838,7 +9174,7 @@ function makePatchCommand() {
8838
9174
  cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8839
9175
  const am2 = new AssetManager({
8840
9176
  registry: getKindRegistry(),
8841
- projectDir: path18__default.resolve(opts.projectDir)
9177
+ projectDir: path22__default.resolve(opts.projectDir)
8842
9178
  });
8843
9179
  try {
8844
9180
  const dest = await am2.patch(ref);
@@ -8852,7 +9188,7 @@ function makePatchCommand() {
8852
9188
  cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8853
9189
  const am2 = new AssetManager({
8854
9190
  registry: getKindRegistry(),
8855
- projectDir: path18__default.resolve(opts.projectDir)
9191
+ projectDir: path22__default.resolve(opts.projectDir)
8856
9192
  });
8857
9193
  try {
8858
9194
  const patchFile = await am2.patchCommit(ref);
@@ -8866,7 +9202,7 @@ function makePatchCommand() {
8866
9202
  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) => {
8867
9203
  const am2 = new AssetManager({
8868
9204
  registry: getKindRegistry(),
8869
- projectDir: path18__default.resolve(opts.projectDir)
9205
+ projectDir: path22__default.resolve(opts.projectDir)
8870
9206
  });
8871
9207
  try {
8872
9208
  await am2.patchSubmit(ref);
@@ -8882,7 +9218,7 @@ function makePatchCommand() {
8882
9218
  cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
8883
9219
  const am2 = new AssetManager({
8884
9220
  registry: getKindRegistry(),
8885
- projectDir: path18__default.resolve(opts.projectDir)
9221
+ projectDir: path22__default.resolve(opts.projectDir)
8886
9222
  });
8887
9223
  am2.patchRemove(ref);
8888
9224
  logOk(`Patch removed for ${ref}`);
@@ -8900,8 +9236,8 @@ function action2(fn) {
8900
9236
  }
8901
9237
  };
8902
9238
  }
8903
- async function reconcileAndReport(projectDir, plugins) {
8904
- const { reconcilePlugins } = await import('../plugin-store-X7GPWGBG.js');
9239
+ async function reconcileAndReport(projectDir, plugins, opts = {}) {
9240
+ const { reconcilePlugins } = await import('../plugin-store-XMZSPVBF.js');
8905
9241
  if (plugins.length === 0) {
8906
9242
  logInfo("No plugins declared \u2014 nothing to reconcile.");
8907
9243
  return;
@@ -8911,26 +9247,52 @@ async function reconcileAndReport(projectDir, plugins) {
8911
9247
  if (result.changed) logOk(`Reconciled plugin store (${result.reason}).`);
8912
9248
  else logInfo(`Plugin store ${result.reason}.`);
8913
9249
  } catch (err2) {
9250
+ if (opts.strict) throw err2;
8914
9251
  logWarn(`reconcile skipped: ${err2 instanceof Error ? err2.message : String(err2)}`);
8915
9252
  }
8916
9253
  }
9254
+ async function verifyPluginLoads(projectDir, spec) {
9255
+ const { loadPlugins } = await import('../plugin-store-XMZSPVBF.js');
9256
+ const { createPluginRegistry } = await import('../plugin-registry/index.js');
9257
+ const registry = createPluginRegistry();
9258
+ const result = await loadPlugins(projectDir, [spec], registry);
9259
+ const failure = result.failed[0];
9260
+ if (failure) throw new Error(failure.error);
9261
+ const contributed = ["driver", "connector", "deployTarget"].flatMap(
9262
+ (kind) => registry.list(kind).map((m) => `${kind} ${m.id}`)
9263
+ );
9264
+ logOk(`Loaded ${S.cmd(spec)}${contributed.length > 0 ? ` (${contributed.join(", ")})` : ""}`);
9265
+ }
8917
9266
  async function runInstall2(spec, opts) {
8918
- const projectDir = path18__default.resolve(opts.projectDir);
9267
+ const projectDir = path22__default.resolve(opts.projectDir);
8919
9268
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
8920
- const { specName } = await import('../plugin-store-X7GPWGBG.js');
8921
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
9269
+ const { specName } = await import('../plugin-store-XMZSPVBF.js');
9270
+ const yamlPath = path22__default.join(projectDir, "skaile.yaml");
9271
+ const original = existsSync(yamlPath) ? readFileSync(yamlPath, "utf8") : void 0;
8922
9272
  const editor = WorkspaceYamlEditor2.load(yamlPath);
8923
9273
  const replaced = editor.addPlugin(spec, specName);
8924
9274
  editor.save();
8925
9275
  if (replaced) logOk(`Updated ${S.cmd(specName(spec))} \u2192 ${S.cmd(spec)} in skaile.yaml`);
8926
9276
  else logOk(`Added ${S.cmd(spec)} to skaile.yaml plugins`);
8927
- await reconcileAndReport(projectDir, editor.getPlugins());
9277
+ try {
9278
+ await reconcileAndReport(projectDir, editor.getPlugins(), { strict: true });
9279
+ await verifyPluginLoads(projectDir, spec);
9280
+ } catch (err2) {
9281
+ if (original !== void 0) {
9282
+ writeFileSync(yamlPath, original);
9283
+ logInfo("skaile.yaml restored; the plugin was not recorded.");
9284
+ } else {
9285
+ rmSync(yamlPath, { force: true });
9286
+ logInfo("skaile.yaml removed; the plugin was not recorded.");
9287
+ }
9288
+ throw err2;
9289
+ }
8928
9290
  }
8929
9291
  async function runRemove(name, opts) {
8930
- const projectDir = path18__default.resolve(opts.projectDir);
9292
+ const projectDir = path22__default.resolve(opts.projectDir);
8931
9293
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
8932
- const { specName } = await import('../plugin-store-X7GPWGBG.js');
8933
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
9294
+ const { specName } = await import('../plugin-store-XMZSPVBF.js');
9295
+ const yamlPath = path22__default.join(projectDir, "skaile.yaml");
8934
9296
  const editor = WorkspaceYamlEditor2.load(yamlPath);
8935
9297
  const removed = editor.removePlugin(name, specName);
8936
9298
  if (!removed) {
@@ -8942,7 +9304,7 @@ async function runRemove(name, opts) {
8942
9304
  await reconcileAndReport(projectDir, editor.getPlugins());
8943
9305
  }
8944
9306
  async function runList(opts) {
8945
- const projectDir = path18__default.resolve(opts.projectDir);
9307
+ const projectDir = path22__default.resolve(opts.projectDir);
8946
9308
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
8947
9309
  const config = resolveSkWorkspaceConfig2(projectDir);
8948
9310
  const declared = config.plugins ?? [];
@@ -8957,7 +9319,7 @@ async function runList(opts) {
8957
9319
  const registry = createPluginRegistry();
8958
9320
  if (declared.length > 0) {
8959
9321
  try {
8960
- const { loadPlugins } = await import('../plugin-store-X7GPWGBG.js');
9322
+ const { loadPlugins } = await import('../plugin-store-XMZSPVBF.js');
8961
9323
  const result = await loadPlugins(projectDir, declared, registry);
8962
9324
  for (const f of result.failed) logWarn(f.error);
8963
9325
  } catch (err2) {
@@ -9132,7 +9494,7 @@ function neededSources(config, lock) {
9132
9494
  }
9133
9495
  function sourcesWithSidecar(sources) {
9134
9496
  const dir = getStoreManifestsDir();
9135
- return sources.filter((s) => existsSync(path18.join(dir, `${storeManifestSlug(s.url)}.yaml`))).map((s) => s.url);
9497
+ return sources.filter((s) => existsSync(path22.join(dir, `${storeManifestSlug(s.url)}.yaml`))).map((s) => s.url);
9136
9498
  }
9137
9499
  function compact(obj) {
9138
9500
  const out = {};
@@ -9224,8 +9586,8 @@ function redactSecrets(preset, findings) {
9224
9586
  }
9225
9587
  return { preset: next, keys };
9226
9588
  }
9227
- function placeholderKey(itemId, path43) {
9228
- return `${itemId}_${path43}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
9589
+ function placeholderKey(itemId, path44) {
9590
+ return `${itemId}_${path44}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
9229
9591
  }
9230
9592
  function setAtPath(root, segments, value) {
9231
9593
  let node = root;
@@ -9248,7 +9610,7 @@ function makePresetCommand() {
9248
9610
  cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
9249
9611
  const presetName = name ?? "my-preset";
9250
9612
  const filename = `${presetName}.preset.yaml`;
9251
- const outPath = path18__default.join(path18__default.resolve(opts.dir), filename);
9613
+ const outPath = path22__default.join(path22__default.resolve(opts.dir), filename);
9252
9614
  if (existsSync(outPath)) {
9253
9615
  logErr(`File already exists: ${outPath}`);
9254
9616
  logInfo("Choose a different name or remove the existing file.");
@@ -9281,7 +9643,7 @@ function makePresetCommand() {
9281
9643
  return cmd;
9282
9644
  }
9283
9645
  async function runPresetExport(name, opts) {
9284
- const projectDir = path18__default.resolve(opts.projectDir);
9646
+ const projectDir = path22__default.resolve(opts.projectDir);
9285
9647
  const file = loadSkWorkspaceConfig(projectDir);
9286
9648
  if (!file) {
9287
9649
  logErr(`No skaile.yaml found in ${projectDir}`);
@@ -9291,7 +9653,7 @@ async function runPresetExport(name, opts) {
9291
9653
  const presetName = name ?? file.config.name ?? "my-preset";
9292
9654
  let lock = null;
9293
9655
  try {
9294
- lock = readLock(path18__default.join(projectDir, "skaile.lock.yaml"));
9656
+ lock = readLock(path22__default.join(projectDir, "skaile.lock.yaml"));
9295
9657
  } catch {
9296
9658
  lock = null;
9297
9659
  }
@@ -9332,7 +9694,7 @@ async function runPresetExport(name, opts) {
9332
9694
  const contents = header ? `${header}
9333
9695
  ${body}` : body;
9334
9696
  if (opts.out && opts.dir !== process.cwd()) logWarn("--dir is ignored when --out is set.");
9335
- const outPath = opts.out ? path18__default.resolve(opts.out) : path18__default.join(path18__default.resolve(opts.dir), `${presetName}.preset.yaml`);
9697
+ const outPath = opts.out ? path22__default.resolve(opts.out) : path22__default.join(path22__default.resolve(opts.dir), `${presetName}.preset.yaml`);
9336
9698
  if (existsSync(outPath) && !opts.force) {
9337
9699
  logErr(`File already exists: ${outPath}`);
9338
9700
  logInfo("Pass --force to overwrite, or choose a different --out/--dir.");
@@ -9344,7 +9706,7 @@ ${body}` : body;
9344
9706
  logErr(`Failed to write ${outPath}: ${e.message}`);
9345
9707
  process.exit(1);
9346
9708
  }
9347
- logOk(`Exported ${S.brand(path18__default.basename(outPath))}`);
9709
+ logOk(`Exported ${S.brand(path22__default.basename(outPath))}`);
9348
9710
  logInfo(`Path: ${outPath}`);
9349
9711
  if (unresolved.length > 0) {
9350
9712
  console.error(S.err("This file is NOT safe to share."));
@@ -9385,13 +9747,13 @@ function collectInput(value, acc) {
9385
9747
  return acc;
9386
9748
  }
9387
9749
  async function runPresetApply(filePath, opts) {
9388
- const projectDir = path18__default.resolve(opts.projectDir);
9750
+ const projectDir = path22__default.resolve(opts.projectDir);
9389
9751
  const file = loadSkWorkspaceConfig(projectDir);
9390
9752
  if (!file) {
9391
9753
  logErr("No skaile.yaml \u2014 run `skaile init` first");
9392
9754
  process.exit(1);
9393
9755
  }
9394
- const resolved = path18__default.resolve(filePath);
9756
+ const resolved = path22__default.resolve(filePath);
9395
9757
  if (!existsSync(resolved)) {
9396
9758
  logErr(`File not found: ${resolved}`);
9397
9759
  process.exit(1);
@@ -9607,7 +9969,7 @@ async function reportNestedPresetRefs(preset) {
9607
9969
  }
9608
9970
  async function checkPresetCycles(preset, resolved) {
9609
9971
  const { detectCycles } = await import('../discovery/index.js');
9610
- const presetRef = path18__default.basename(resolved, ".preset.yaml");
9972
+ const presetRef = path22__default.basename(resolved, ".preset.yaml");
9611
9973
  const edges = [];
9612
9974
  for (const item of preset.items) {
9613
9975
  if (item.ref) {
@@ -9659,7 +10021,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
9659
10021
  }
9660
10022
  }
9661
10023
  async function runPresetValidate(filePath) {
9662
- const resolved = path18__default.resolve(filePath);
10024
+ const resolved = path22__default.resolve(filePath);
9663
10025
  const preset = await loadPresetForValidation(resolved);
9664
10026
  await reportNestedPresetRefs(preset);
9665
10027
  await checkPresetCycles(preset, resolved);
@@ -9709,11 +10071,11 @@ items:
9709
10071
  }
9710
10072
  function makeRebuildCommand() {
9711
10073
  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) => {
9712
- const projectDir = path18__default.resolve(opts.projectDir);
10074
+ const projectDir = path22__default.resolve(opts.projectDir);
9713
10075
  let agentDir;
9714
10076
  if (agentArg) {
9715
10077
  if (agentArg.includes("/") || agentArg.includes("\\")) {
9716
- agentDir = path18__default.resolve(projectDir, agentArg);
10078
+ agentDir = path22__default.resolve(projectDir, agentArg);
9717
10079
  } else {
9718
10080
  let resolved;
9719
10081
  try {
@@ -9722,7 +10084,7 @@ function makeRebuildCommand() {
9722
10084
  if (!(err2 instanceof AgentRefResolutionError)) throw err2;
9723
10085
  logWarn(`${err2.message} \u2014 using "${agentArg}"`);
9724
10086
  }
9725
- agentDir = resolved ?? path18__default.resolve(projectDir, agentArg);
10087
+ agentDir = resolved ?? path22__default.resolve(projectDir, agentArg);
9726
10088
  }
9727
10089
  } else {
9728
10090
  let resolved;
@@ -9792,9 +10154,9 @@ Try a different harness with \`--driver claude-sdk\`.`;
9792
10154
  // cli/src/commands/run.ts
9793
10155
  function resolveSingleShotAgentDir(projectDir, agentDefinition) {
9794
10156
  if (!agentDefinition) return resolveAgentDir(projectDir);
9795
- const asPath = agentDefinition.endsWith("agent.yaml") ? path18__default.dirname(path18__default.resolve(projectDir, agentDefinition)) : agentDefinition;
10157
+ const asPath = agentDefinition.endsWith("agent.yaml") ? path22__default.dirname(path22__default.resolve(projectDir, agentDefinition)) : agentDefinition;
9796
10158
  const dir = resolveAgentDefinitionDir(projectDir, asPath);
9797
- if (!dir || !fs8__default.existsSync(path18__default.join(dir, "agent.yaml"))) {
10159
+ if (!dir || !fs8__default.existsSync(path22__default.join(dir, "agent.yaml"))) {
9798
10160
  throw new Error(
9799
10161
  `--agent-definition "${agentDefinition}" does not resolve to an agent directory with agent.yaml${dir ? ` (looked in ${dir})` : ""}`
9800
10162
  );
@@ -9845,10 +10207,58 @@ async function printCompositionDryRun(projectDir, agentDir, driver, model) {
9845
10207
  }
9846
10208
  for (const warning of resolved.warnings) logWarn(warning);
9847
10209
  }
10210
+ async function findSkillFile(projectDir, skill) {
10211
+ const name = skill.trim().replace(/^skill:/, "").replace(/^@[^/]+\//, "").replace(/#.*$/, "");
10212
+ for (const target of SUPPORTED_DRIVER_TARGETS) {
10213
+ const file = path22__default.join(deployedDir("skill", name, target, false, projectDir), "SKILL.md");
10214
+ if (fs8__default.existsSync(file)) return file;
10215
+ }
10216
+ const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
10217
+ const entry = await am2.info(`skill:${name}`);
10218
+ return entry?.source && fs8__default.existsSync(entry.source) ? entry.source : void 0;
10219
+ }
10220
+ async function printSkillDryRun(projectDir, skill) {
10221
+ const file = await findSkillFile(projectDir, skill);
10222
+ if (!file) {
10223
+ logErr(
10224
+ `Skill not found: ${skill} - not deployed in the project and not held by a registered library or source`
10225
+ );
10226
+ return false;
10227
+ }
10228
+ const content = fs8__default.readFileSync(file, "utf-8");
10229
+ const { data } = parseFrontmatter(content);
10230
+ const meta = data.metadata ?? {};
10231
+ console.log(` ${S.label("Skill:")} ${S.heading(String(data.name ?? skill))}`);
10232
+ console.log(` ${S.label("Source:")} ${file}`);
10233
+ if (meta.version) console.log(` ${S.label("Version:")} ${String(meta.version)}`);
10234
+ if (data.description) console.log(` ${S.label("About:")} ${String(data.description)}`);
10235
+ const requires = parseRequires(data);
10236
+ if (requires.length > 0) {
10237
+ console.log(` ${S.label("Requires:")} ${requires.map((d) => depToStr(d)).join(", ")}`);
10238
+ }
10239
+ const requirements = parseSkillRequirements(content);
10240
+ const report = await validateRequirements(String(data.name ?? skill), requirements, projectDir);
10241
+ const unmet = report.files.filter((f) => !f.exists);
10242
+ for (const f of report.files) {
10243
+ const mark = f.exists ? S.ok("present") : f.gate === "hard" ? S.err("missing") : S.warn("missing");
10244
+ const gate = f.gate === "soft" ? " (soft)" : "";
10245
+ console.log(` ${S.label("File:")} ${f.path}${gate} ${mark}`);
10246
+ }
10247
+ for (const input of report.inputs.filter((i) => i.required && !i.present)) {
10248
+ console.log(` ${S.label("Input:")} ${input.id} ${S.err("required, not collected")}`);
10249
+ }
10250
+ if (unmet.some((f) => f.gate === "hard")) {
10251
+ logWarn("Unmet hard prerequisites: the skill cannot run until those files exist.");
10252
+ }
10253
+ console.log();
10254
+ return true;
10255
+ }
9848
10256
  function makeFlowEventHandler() {
9849
10257
  const md = new MarkdownStreamer();
9850
10258
  const displayed = /* @__PURE__ */ new Set();
10259
+ const printUnstreamed = createFinalTextFallback((text) => md.write(text));
9851
10260
  return (event) => {
10261
+ printUnstreamed(event);
9852
10262
  const e = event;
9853
10263
  if (e.type === "state_changed" && typeof e.store === "string" && e.store.startsWith("flow:")) {
9854
10264
  const nodes = e.state?.nodes ?? {};
@@ -9888,12 +10298,35 @@ function logAgentRunEvent(event) {
9888
10298
  const verdict = e.error ? `${e.runStatus ?? "failed"}: ${e.error.code} ${e.error.message}` : e.runStatus ?? "finished";
9889
10299
  console.error(` ${S.dim("subagent")} ${who} ${verdict} output=${JSON.stringify(e.output)}`);
9890
10300
  }
10301
+ function editDistance2(a, b) {
10302
+ let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
10303
+ for (let i = 1; i <= a.length; i++) {
10304
+ const row = [i];
10305
+ for (let j = 1; j <= b.length; j++) {
10306
+ row[j] = Math.min(
10307
+ prev[j] + 1,
10308
+ row[j - 1] + 1,
10309
+ prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
10310
+ );
10311
+ }
10312
+ prev = row;
10313
+ }
10314
+ return prev[b.length];
10315
+ }
10316
+ function isNearFlowId(typed, id) {
10317
+ const a = typed.toLowerCase();
10318
+ const b = id.toLowerCase();
10319
+ return a.length >= 3 && (b.includes(a) || a.includes(b) || editDistance2(a, b) <= 2);
10320
+ }
10321
+ function driverOptionDescription() {
10322
+ return `Harness to run (${listDrivers().map((d) => d.id).join(", ")})`;
10323
+ }
9891
10324
  function makeRunCommand() {
9892
- const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--driver <name>", "Harness to run (claude-sdk, codex, omp)").option("--model <name>", "Model override").option("--label <label>", "Human-readable session label").option("--dry-run", "Print plan without executing (single-shot: resolved composition items)").option(
10325
+ const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--driver <name>", driverOptionDescription()).option("--model <name>", "Model override").option("--label <label>", "Human-readable session label").option("--dry-run", "Print plan without executing (single-shot: resolved composition items)").option(
9893
10326
  "--agent-definition <ref|path>",
9894
10327
  "Agent asset for this one invocation (agent:@pub/name, ai-assets://\u2026, or a directory with agent.yaml); single-shot prompts only"
9895
10328
  ).option("--skill <name>", "Skill name (for single-shot mode)").action(async (positional, opts) => {
9896
- const projectDir = path18__default.resolve(opts.projectDir);
10329
+ const projectDir = path22__default.resolve(opts.projectDir);
9897
10330
  const cliDriver = opts.driver;
9898
10331
  const dryRun = opts.dryRun ?? false;
9899
10332
  const agentDefinition = opts.agentDefinition?.trim() || void 0;
@@ -9937,18 +10370,29 @@ function makeRunCommand() {
9937
10370
  }
9938
10371
  if (!flowPath) {
9939
10372
  const textPrompt = positional.join(" ");
9940
- if (!textPrompt.trim()) {
10373
+ const promptOnlyOption = agentDefinition !== void 0 || opts.skill !== void 0;
10374
+ if (!textPrompt.trim() || positional.length === 1 && !/\s/.test(flowId) && !promptOnlyOption) {
9941
10375
  logErr(`Flow not found: ${flowId}`);
9942
10376
  const available = (await discoverFlowsWithLibraries(projectDir)).map((f) => f.id);
9943
- if (available.length > 0) {
9944
- console.log(` ${S.dim("Available:")} ${available.map((id) => S.cmd(id)).join(", ")}`);
10377
+ const near = available.filter((id) => isNearFlowId(flowId, id));
10378
+ const listed = near.length > 0 ? near : available;
10379
+ if (listed.length > 0) {
10380
+ console.log(
10381
+ ` ${S.dim(near.length > 0 ? "Did you mean:" : "Available:")} ${listed.map((id) => S.cmd(id)).join(", ")}`
10382
+ );
9945
10383
  }
10384
+ console.log(
10385
+ ` ${S.dim('To send it as a prompt, quote more than one word: skaile run "\u2026".')}`
10386
+ );
9946
10387
  process.exit(1);
9947
10388
  }
9948
10389
  try {
9949
10390
  const agentDir = resolveSingleShotAgentDir(projectDir, agentDefinition);
9950
10391
  if (dryRun) {
9951
10392
  await printCompositionDryRun(projectDir, agentDir, driver, model);
10393
+ if (opts.skill && !await printSkillDryRun(projectDir, opts.skill)) {
10394
+ process.exit(1);
10395
+ }
9952
10396
  return;
9953
10397
  }
9954
10398
  await runAgentChat({
@@ -10012,7 +10456,7 @@ function makeRunCommand() {
10012
10456
  }
10013
10457
  function makeResumeCommand() {
10014
10458
  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) => {
10015
- const projectDir = path18__default.resolve(opts.projectDir);
10459
+ const projectDir = path22__default.resolve(opts.projectDir);
10016
10460
  const sessionId = opts.session;
10017
10461
  const dryRun = opts.dryRun ?? false;
10018
10462
  const session = sessionId ? await loadSessionById(projectDir, sessionId) : await loadSession(projectDir);
@@ -10039,7 +10483,7 @@ function makeResumeCommand() {
10039
10483
  }
10040
10484
  function makeStatusCommand() {
10041
10485
  return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10042
- const projectDir = path18__default.resolve(opts.projectDir);
10486
+ const projectDir = path22__default.resolve(opts.projectDir);
10043
10487
  const session = await loadSession(projectDir);
10044
10488
  if (!session) {
10045
10489
  logInfo("No active session.");
@@ -10064,17 +10508,17 @@ function makeStatusCommand() {
10064
10508
  }
10065
10509
  function makeClearCommand() {
10066
10510
  return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10067
- const projectDir = path18__default.resolve(opts.projectDir);
10511
+ const projectDir = path22__default.resolve(opts.projectDir);
10068
10512
  await clearSession(projectDir);
10069
10513
  logOk("Session cleared.");
10070
10514
  });
10071
10515
  }
10072
10516
  function makeReplCommand() {
10073
- return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>", "Harness to run (claude-sdk, omp)").option("--model <name>", "Model override").option("--resume", "Resume last session").option("--resume-session <id>", "Resume specific session").action(async (opts) => {
10517
+ return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>", driverOptionDescription()).option("--model <name>", "Model override").option("--resume", "Resume last session").option("--resume-session <id>", "Resume specific session").action(async (opts) => {
10074
10518
  const { findWorkspaceRoot } = await import('../core/index.js');
10075
10519
  const { startRepl } = await import('../tui/index.js');
10076
10520
  const os2 = await import('os');
10077
- const userCwd = path18__default.resolve(opts.projectDir ?? process.cwd());
10521
+ const userCwd = path22__default.resolve(opts.projectDir ?? process.cwd());
10078
10522
  const workspaceRoot = findWorkspaceRoot(userCwd);
10079
10523
  let projectDir;
10080
10524
  let agentCwd;
@@ -10089,6 +10533,12 @@ function makeReplCommand() {
10089
10533
  console.log();
10090
10534
  logWarn(`No skaile.yaml found in ${S.cmd(userCwd)} or any parent directory.`);
10091
10535
  console.log();
10536
+ if (!process.stdin.isTTY) {
10537
+ logErr(
10538
+ `repl needs a skaile.yaml here when stdin is not a terminal: run ${S.cmd("skaile init")} first.`
10539
+ );
10540
+ process.exit(1);
10541
+ }
10092
10542
  const shouldCreate = await p4.confirm({
10093
10543
  message: "Create a temporary workspace? (session state in /tmp/)"
10094
10544
  });
@@ -10096,12 +10546,12 @@ function makeReplCommand() {
10096
10546
  p4.cancel("Cancelled.");
10097
10547
  process.exit(0);
10098
10548
  }
10099
- const tmpDir = fs8__default.mkdtempSync(path18__default.join(os2.tmpdir(), "skaile-repl-"));
10549
+ const tmpDir = fs8__default.mkdtempSync(path22__default.join(os2.tmpdir(), "skaile-repl-"));
10100
10550
  projectDir = tmpDir;
10101
10551
  agentCwd = userCwd;
10102
10552
  logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
10103
10553
  if (!driverOverride) {
10104
- const claudeDir = path18__default.join(os2.homedir(), ".claude");
10554
+ const claudeDir = path22__default.join(os2.homedir(), ".claude");
10105
10555
  if (fs8__default.existsSync(claudeDir)) {
10106
10556
  driverOverride = "claude-sdk";
10107
10557
  logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} harness`);
@@ -10112,21 +10562,29 @@ function makeReplCommand() {
10112
10562
  }
10113
10563
  console.log();
10114
10564
  }
10115
- await startRepl({
10116
- projectDir,
10117
- cwd: agentCwd !== projectDir ? agentCwd : void 0,
10118
- driver: driverOverride,
10119
- model: opts.model,
10120
- resume: opts.resume,
10121
- resumeSessionId: opts.resumeSession
10122
- });
10565
+ try {
10566
+ await startRepl({
10567
+ projectDir,
10568
+ cwd: agentCwd !== projectDir ? agentCwd : void 0,
10569
+ driver: driverOverride,
10570
+ model: opts.model,
10571
+ resume: opts.resume,
10572
+ resumeSessionId: opts.resumeSession
10573
+ });
10574
+ } catch (err2) {
10575
+ logErr(friendlyDriverError(err2) ?? (err2 instanceof Error ? err2.message : String(err2)));
10576
+ process.exit(1);
10577
+ }
10123
10578
  });
10124
10579
  }
10125
10580
  function parseProviderIds(raw) {
10126
10581
  return (raw ?? "").split(",").map((id) => id.trim()).filter((id) => id.length > 0);
10127
10582
  }
10128
10583
  function makeServeCommand() {
10129
- return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option("--project-dir <path>", "Project directory", process.cwd()).option(
10584
+ return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option(
10585
+ "--host <address>",
10586
+ "Address to bind (default: all interfaces; use 127.0.0.1 for local clients only)"
10587
+ ).option("--project-dir <path>", "Project directory", process.cwd()).option(
10130
10588
  "--managed-codex-config <path>",
10131
10589
  "Explicit private host configuration for managed Codex"
10132
10590
  ).option("--driver <name>", "Override driver").option("--model <name>", "Override model").option("--provider <name>", "Override provider").option("--session-id <id>", "Session ID for conversation continuity").option("--resume-session-id <id>", "OMP session ID to resume (restores native OMP context)").option(
@@ -10154,32 +10612,48 @@ function makeServeCommand() {
10154
10612
  await ensurePluginsLoadedForServe(opts.projectDir);
10155
10613
  }
10156
10614
  const providers = parseProviderIds(opts.providers);
10157
- await startAgentServer({
10158
- port: parseInt(opts.port, 10),
10159
- authTokenIntake: wsAuth,
10160
- ...managedCodex ? { managedCodex } : {},
10161
- // The CLI owns its process, so a dead stdout pipe is fatal here.
10162
- // `SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT=0` opts out — the `local` /
10163
- // `nix` deploy targets set it for children meant to outlive them.
10164
- exitOnBrokenPipe: process.env.SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT !== "0",
10165
- projectDir: opts.projectDir,
10166
- driver: opts.driver,
10167
- model: opts.model,
10168
- provider: opts.provider,
10169
- sessionId: opts.sessionId,
10170
- resumeSessionId: opts.resumeSessionId,
10171
- ...providers.length > 0 ? { providers } : {}
10172
- });
10615
+ const { checkDriverSdk } = await import('../serve-preflight-6P2JJEJ3.js');
10616
+ const driverProblem = managedCodex ? null : await checkDriverSdk(opts.projectDir, opts.driver);
10617
+ if (driverProblem) {
10618
+ const { logErr: logErr2 } = await import('../helpers-Y4OT7VIS.js');
10619
+ logErr2(driverProblem);
10620
+ process.exitCode = 1;
10621
+ return;
10622
+ }
10623
+ try {
10624
+ await startAgentServer({
10625
+ port: parseInt(opts.port, 10),
10626
+ ...opts.host ? { host: opts.host } : {},
10627
+ authTokenIntake: wsAuth,
10628
+ ...managedCodex ? { managedCodex } : {},
10629
+ // The CLI owns its process, so a dead stdout pipe is fatal here.
10630
+ // `SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT=0` opts out — the `local` /
10631
+ // `nix` deploy targets set it for children meant to outlive them.
10632
+ exitOnBrokenPipe: process.env.SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT !== "0",
10633
+ projectDir: opts.projectDir,
10634
+ driver: opts.driver,
10635
+ model: opts.model,
10636
+ provider: opts.provider,
10637
+ sessionId: opts.sessionId,
10638
+ resumeSessionId: opts.resumeSessionId,
10639
+ ...providers.length > 0 ? { providers } : {}
10640
+ });
10641
+ } catch (err2) {
10642
+ if (err2?.code !== "EADDRINUSE") throw err2;
10643
+ const { logErr: logErr2 } = await import('../helpers-Y4OT7VIS.js');
10644
+ logErr2(err2.message);
10645
+ process.exitCode = 1;
10646
+ }
10173
10647
  }
10174
10648
  );
10175
10649
  }
10176
10650
  async function ensurePluginsLoadedForServe(projectDir) {
10177
- const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-X6URBGSF.js');
10651
+ const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-Y4OT7VIS.js');
10178
10652
  try {
10179
10653
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
10180
10654
  const config = resolveSkWorkspaceConfig2(projectDir);
10181
10655
  if (!config.plugins || config.plugins.length === 0) return;
10182
- const { ensurePluginsLoaded } = await import('../plugin-store-X7GPWGBG.js');
10656
+ const { ensurePluginsLoaded } = await import('../plugin-store-XMZSPVBF.js');
10183
10657
  const { pluginRegistry } = await import('../plugin-registry/index.js');
10184
10658
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
10185
10659
  if (result.loaded.length > 0) {
@@ -10193,21 +10667,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
10193
10667
  }
10194
10668
  }
10195
10669
  async function runCompileTest(opts) {
10196
- const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-X6URBGSF.js');
10670
+ const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-Y4OT7VIS.js');
10197
10671
  const { tmpdir } = await import('os');
10198
- const { dirname: dirname3, join: join6, resolve: resolve5 } = await import('path');
10672
+ const { dirname: dirname3, join: join7, resolve: resolve5 } = await import('path');
10199
10673
  const { fileURLToPath: fileURLToPath2 } = await import('url');
10200
- const { unlinkSync, existsSync: existsSync18 } = await import('fs');
10674
+ const { unlinkSync, existsSync: existsSync20 } = await import('fs');
10201
10675
  const { spawn } = await import('child_process');
10202
10676
  const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
10203
- const { MONOREPO_ROOT } = await import('../paths-BVO56A25.js');
10677
+ const { MONOREPO_ROOT } = await import('../paths-U6W6MQNQ.js');
10204
10678
  if (MONOREPO_ROOT === null) {
10205
10679
  logErr2("--compile-test is only available inside the skaile-dev workspace.");
10206
10680
  logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
10207
10681
  process.exitCode = 2;
10208
10682
  return;
10209
10683
  }
10210
- const outfile = join6(tmpdir(), `skaile-compile-test-${Date.now()}`);
10684
+ const outfile = join7(tmpdir(), `skaile-compile-test-${Date.now()}`);
10211
10685
  const __thisFile = fileURLToPath2(import.meta.url);
10212
10686
  const entryPoint = resolve5(dirname3(__thisFile), "..", "index.ts");
10213
10687
  logInfo2(`Building compiled binary...`);
@@ -10262,7 +10736,7 @@ async function runCompileTest(opts) {
10262
10736
  } catch {
10263
10737
  }
10264
10738
  try {
10265
- if (existsSync18(outfile)) unlinkSync(outfile);
10739
+ if (existsSync20(outfile)) unlinkSync(outfile);
10266
10740
  } catch {
10267
10741
  }
10268
10742
  }
@@ -10683,7 +11157,7 @@ function resolveMode2(opts) {
10683
11157
  if (opts.forceLocal && opts.forceRemote) {
10684
11158
  throw new Error("Cannot use both --local and --remote");
10685
11159
  }
10686
- const startDir = path18__default.resolve(opts.projectDir ?? process.cwd());
11160
+ const startDir = path22__default.resolve(opts.projectDir ?? process.cwd());
10687
11161
  const localDb = findLogsDb(startDir);
10688
11162
  if (opts.forceLocal) {
10689
11163
  if (!localDb) {
@@ -10716,14 +11190,14 @@ function resolveMode2(opts) {
10716
11190
  function findLogsDb(startDir) {
10717
11191
  let dir = startDir;
10718
11192
  for (let i = 0; i < MAX_WALK_LEVELS; i++) {
10719
- const candidate = path18__default.join(dir, ".skaile", "logs.db");
11193
+ const candidate = path22__default.join(dir, ".skaile", "logs.db");
10720
11194
  if (existsSync(candidate)) {
10721
11195
  try {
10722
11196
  if (statSync(candidate).isFile()) return candidate;
10723
11197
  } catch {
10724
11198
  }
10725
11199
  }
10726
- const parent = path18__default.dirname(dir);
11200
+ const parent = path22__default.dirname(dir);
10727
11201
  if (parent === dir) return void 0;
10728
11202
  dir = parent;
10729
11203
  }
@@ -10898,7 +11372,7 @@ function parsePositiveInt(value, flag) {
10898
11372
  function makeSessionCommand() {
10899
11373
  const cmd = new Command("session").description("Manage sessions");
10900
11374
  cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10901
- const projectDir = path18__default.resolve(opts.projectDir);
11375
+ const projectDir = path22__default.resolve(opts.projectDir);
10902
11376
  const sessions = await listSessions(projectDir);
10903
11377
  const current = await loadSession(projectDir);
10904
11378
  if (sessions.length === 0) {
@@ -10926,7 +11400,7 @@ function makeSessionCommand() {
10926
11400
  console.log();
10927
11401
  });
10928
11402
  cmd.command("show <run-id>").description("Show a specific session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10929
- const projectDir = path18__default.resolve(opts.projectDir);
11403
+ const projectDir = path22__default.resolve(opts.projectDir);
10930
11404
  const session = await loadSessionById(projectDir, runId);
10931
11405
  if (!session) {
10932
11406
  logErr(`Session not found: ${runId}`);
@@ -10935,7 +11409,7 @@ function makeSessionCommand() {
10935
11409
  console.log(JSON.stringify(session, null, 2));
10936
11410
  });
10937
11411
  cmd.command("switch <run-id>").description("Switch the current session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10938
- const projectDir = path18__default.resolve(opts.projectDir);
11412
+ const projectDir = path22__default.resolve(opts.projectDir);
10939
11413
  if (!await loadSessionById(projectDir, runId)) {
10940
11414
  logErr(`Session not found: ${runId}`);
10941
11415
  process.exit(1);
@@ -10944,7 +11418,7 @@ function makeSessionCommand() {
10944
11418
  logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
10945
11419
  });
10946
11420
  cmd.command("delete <run-id>").description("Delete a session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
10947
- const projectDir = path18__default.resolve(opts.projectDir);
11421
+ const projectDir = path22__default.resolve(opts.projectDir);
10948
11422
  if (!await loadSessionById(projectDir, runId)) {
10949
11423
  logErr(`Session not found: ${runId}`);
10950
11424
  process.exit(1);
@@ -11017,7 +11491,7 @@ function makeShowCommand() {
11017
11491
  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) => {
11018
11492
  const am2 = new AssetManager({
11019
11493
  registry: getKindRegistry(),
11020
- projectDir: path18__default.resolve(opts.projectDir),
11494
+ projectDir: path22__default.resolve(opts.projectDir),
11021
11495
  driverTarget: opts.target
11022
11496
  });
11023
11497
  if (!kind) {
@@ -11035,6 +11509,32 @@ function makeShowCommand() {
11035
11509
  }
11036
11510
  });
11037
11511
  }
11512
+ function searchCuratedManifests(query) {
11513
+ const dir = getStoreManifestsDir();
11514
+ if (!existsSync(dir)) return [];
11515
+ const q = query.toLowerCase();
11516
+ const hits = [];
11517
+ for (const file of readdirSync(dir).sort()) {
11518
+ if (!file.endsWith(".yaml")) continue;
11519
+ const slug = file.slice(0, -".yaml".length);
11520
+ let manifest;
11521
+ try {
11522
+ manifest = decodeSkaileManifest(readFileSync(path22.join(dir, file), "utf-8")).manifest;
11523
+ } catch {
11524
+ continue;
11525
+ }
11526
+ const repoPublisher2 = manifest.publisher?.replace(/^@/, "");
11527
+ for (const a of manifest.assets ?? []) {
11528
+ const publisher = (a.publisher ?? repoPublisher2 ?? "").replace(/^@/, "");
11529
+ const haystack = [a.name, a.description ?? "", publisher, a.kind].join(" ").toLowerCase();
11530
+ if (!haystack.includes(q)) continue;
11531
+ hits.push({ slug, kind: a.kind, publisher, name: a.name, description: a.description });
11532
+ }
11533
+ }
11534
+ return hits;
11535
+ }
11536
+
11537
+ // cli/src/commands/store.ts
11038
11538
  async function fetchIdentity() {
11039
11539
  const jwt = await getStoreToken();
11040
11540
  return storeFetch({ ...getStoreConfig(), jwt }, "/api/v1/me");
@@ -11080,43 +11580,70 @@ function makeStoreCommand() {
11080
11580
  });
11081
11581
  store.command("mode <auto|local|remote>").description("Set the catalog resolution mode (not yet wired)").action((_mode) => {
11082
11582
  logErr(
11083
- `\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path18__default.join(globalSkaileDir(), "store", "config.yaml")}.`
11583
+ `\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path22__default.join(globalSkaileDir(), "store", "config.yaml")}.`
11084
11584
  );
11085
11585
  process.exit(2);
11086
11586
  });
11087
- 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) => {
11088
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-4QSUORI6.js');
11089
- try {
11090
- const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
11091
- const assets = await remote.listAssets(opts.kind ? { kind: opts.kind } : {});
11092
- const results = filterCatalogAssets(assets, query);
11093
- if (results.length === 0) {
11094
- logInfo(`No store results for "${query}".`);
11095
- return;
11587
+ store.command("search <query>").description("Search the AI Asset Store catalog by name, description, or publisher").option("--kind <kind>", "Filter by asset kind (skill, prompt, flow, \u2026)").option(
11588
+ "--all",
11589
+ `List every match (default: ${STORE_ROW_LIMIT} rows, only what \`skaile add\` can install)`
11590
+ ).option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (query, opts) => {
11591
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-N6ESO6IK.js');
11592
+ const projectDir = path22__default.resolve(opts.projectDir);
11593
+ const curated = searchCuratedManifests(query).filter(
11594
+ (h) => !opts.kind || h.kind === opts.kind
11595
+ );
11596
+ const printCurated = () => {
11597
+ if (curated.length === 0) return;
11598
+ console.log(`
11599
+ ${S.heading("Local curated manifests")}`);
11600
+ for (const h of curated) {
11601
+ console.log(
11602
+ ` ${kindColorPad(h.kind)} ${h.kind}:@${h.publisher}/${h.name} ${S.dim(`(manifest ${h.slug})`)}`
11603
+ );
11096
11604
  }
11097
- console.log();
11098
- for (const row of formatStoreRows(results, " ")) console.log(row);
11099
11605
  console.log(
11100
11606
  `
11101
- ${S.dim(`${results.length} result(s) \xB7 \`skaile store show <ref>\` for details`)}
11607
+ ${S.dim("Not published: `skaile source add <repo URL>` indexes them for `skaile add`.")}
11102
11608
  `
11103
11609
  );
11610
+ };
11611
+ try {
11612
+ const remote = await openCatalogSource2({ projectDir });
11613
+ const assets = await remote.listAssets(opts.kind ? { kind: opts.kind } : {});
11614
+ const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
11615
+ if (sel.shown.length === 0) {
11616
+ logInfo(`No store results for "${query}".`);
11617
+ for (const note of storeSelectionNotes(sel, "")) console.log(note);
11618
+ } else {
11619
+ console.log();
11620
+ for (const row of formatStoreRows(sel.shown, " ")) console.log(row);
11621
+ console.log(
11622
+ `
11623
+ ${S.dim(`${sel.shown.length} result(s) \xB7 \`skaile store show <ref>\` for details`)}`
11624
+ );
11625
+ for (const note of storeSelectionNotes(sel, " ")) console.log(note);
11626
+ if (curated.length === 0) console.log();
11627
+ }
11628
+ printCurated();
11104
11629
  } catch (e) {
11630
+ printCurated();
11631
+ if (e instanceof LocalCatalogDisabledError2 && curated.length > 0) return;
11105
11632
  if (e instanceof LocalCatalogDisabledError2) {
11106
11633
  logErr(
11107
11634
  `Remote catalog disabled (catalog.url: local). Set \`catalog.url: https://skaile.store\` in ${userConfigPath()}.`
11108
11635
  );
11109
11636
  } else {
11110
- logErr(`Store search failed: ${e.message}`);
11637
+ logErr(`Store search failed: ${await describeStoreFailure(e, projectDir)}`);
11111
11638
  }
11112
11639
  process.exit(1);
11113
11640
  }
11114
11641
  });
11115
11642
  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) => {
11116
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-4QSUORI6.js');
11117
- const { supportsInstallManifest } = await import('../project-PAXP46RD.js');
11643
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-N6ESO6IK.js');
11644
+ const { supportsInstallManifest } = await import('../project-UP52HEHC.js');
11118
11645
  try {
11119
- const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
11646
+ const remote = await openCatalogSource2({ projectDir: path22__default.resolve(opts.projectDir) });
11120
11647
  const asset = await remote.resolve(ref);
11121
11648
  if (!asset) {
11122
11649
  logErr(`Not found in store: ${ref} (try a full ref, e.g. skill:@publisher/name#version)`);
@@ -11124,8 +11651,12 @@ function makeStoreCommand() {
11124
11651
  }
11125
11652
  const canonical = catalogAssetRef(asset);
11126
11653
  let manifest = null;
11654
+ const manifestFailure = {};
11127
11655
  if (supportsInstallManifest(remote)) {
11128
- manifest = await remote.getInstallManifest(canonical).catch(() => null);
11656
+ manifest = await remote.getInstallManifest(canonical).catch(async (err2) => {
11657
+ manifestFailure.text = await describeStoreFailure(err2, path22__default.resolve(opts.projectDir));
11658
+ return null;
11659
+ });
11129
11660
  }
11130
11661
  const field = (label, value) => ` ${S.label(label.padEnd(11))}${value}`;
11131
11662
  console.log();
@@ -11155,13 +11686,25 @@ function makeStoreCommand() {
11155
11686
  console.log(field("Repo", asset.repo));
11156
11687
  if (asset.sha256) console.log(field("Integrity", asset.sha256));
11157
11688
  }
11689
+ if (!manifest && manifestFailure.text) {
11690
+ console.log();
11691
+ console.log(field("Files", S.dim(`unavailable (${manifestFailure.text})`)));
11692
+ }
11693
+ if (asset.requires?.length) {
11694
+ console.log();
11695
+ console.log(` ${S.heading("Requires")}`);
11696
+ for (const dep of asset.requires) console.log(` ${S.dim("\u2192")} ${dep}`);
11697
+ }
11158
11698
  if (asset.softDeps?.length) {
11159
11699
  console.log();
11160
11700
  console.log(` ${S.heading("Soft dependencies")}`);
11161
11701
  for (const dep of asset.softDeps) console.log(` ${S.dim("\u2192")} ${dep}`);
11162
11702
  }
11163
11703
  console.log();
11164
- console.log(` ${S.dim(`Install: skaile add ${canonical}`)}`);
11704
+ const notInstallable = storeNotInstallableReason(asset);
11705
+ console.log(
11706
+ notInstallable ? ` ${S.dim(`Not installable: ${notInstallable}`)}` : ` ${S.dim(`Install: skaile add ${canonical}`)}`
11707
+ );
11165
11708
  console.log();
11166
11709
  } catch (e) {
11167
11710
  if (e instanceof LocalCatalogDisabledError2) {
@@ -11169,7 +11712,9 @@ function makeStoreCommand() {
11169
11712
  `Remote catalog disabled (catalog.url: local). Set \`catalog.url: https://skaile.store\` in ${userConfigPath()}.`
11170
11713
  );
11171
11714
  } else {
11172
- logErr(`Store show failed: ${e.message}`);
11715
+ logErr(
11716
+ `Store show failed: ${await describeStoreFailure(e, path22__default.resolve(opts.projectDir))}`
11717
+ );
11173
11718
  }
11174
11719
  process.exit(1);
11175
11720
  }
@@ -11239,9 +11784,10 @@ function treeRefs(nodes) {
11239
11784
  }
11240
11785
  function makeTreeCommand() {
11241
11786
  return new Command("tree").description("Show full dependency tree").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
11787
+ requireProjectConfig(opts.projectDir);
11242
11788
  const am2 = new AssetManager({
11243
11789
  registry: getKindRegistry(),
11244
- projectDir: path18__default.resolve(opts.projectDir)
11790
+ projectDir: path22__default.resolve(opts.projectDir)
11245
11791
  });
11246
11792
  const root = await am2.tree();
11247
11793
  if (root.children.length === 0) {
@@ -11268,14 +11814,15 @@ function makeUpdateCommand() {
11268
11814
  "Update only this declared asset (kind:@publisher/name, kind:name or name); exits 1 when none matches"
11269
11815
  ).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(
11270
11816
  async (name, opts) => {
11271
- const projectDir = path18__default.resolve(opts.projectDir);
11817
+ const projectDir = path22__default.resolve(opts.projectDir);
11818
+ if (!opts.catalogOnly) requireProjectConfig(projectDir);
11272
11819
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
11273
11820
  const target = name !== void 0 && !opts.catalogOnly ? await resolveUpdateTarget(am2, name) : void 0;
11274
11821
  if (opts.catalog !== false) {
11275
11822
  const catalogSpinner = createSpinner();
11276
11823
  catalogSpinner.start("Refreshing catalog cache");
11277
11824
  try {
11278
- const remote = await openCatalogSource({ projectDir: path18__default.resolve(opts.projectDir) });
11825
+ const remote = await openCatalogSource({ projectDir: path22__default.resolve(opts.projectDir) });
11279
11826
  const result2 = await remote.refresh();
11280
11827
  catalogSpinner.stop(
11281
11828
  `Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
@@ -11287,6 +11834,10 @@ function makeUpdateCommand() {
11287
11834
  } else {
11288
11835
  catalogSpinner.stop("Catalog refresh failed");
11289
11836
  logErr(`Catalog refresh failed: ${err2 instanceof Error ? err2.message : String(err2)}`);
11837
+ if (opts.catalogOnly) {
11838
+ logInfo("Run `skaile catalog test` to debug.");
11839
+ process.exit(1);
11840
+ }
11290
11841
  logInfo("Continuing with asset re-deploy. Run `skaile catalog test` to debug.");
11291
11842
  }
11292
11843
  }
@@ -11295,11 +11846,11 @@ function makeUpdateCommand() {
11295
11846
  if (await shouldSyncSources(opts)) {
11296
11847
  const syncSpinner = createSpinner();
11297
11848
  syncSpinner.start("Syncing sources");
11298
- const { total, synced, failed } = await syncProjectSources(projectDir);
11849
+ const { total, synced, failed: failed2 } = await syncProjectSources(projectDir);
11299
11850
  syncSpinner.stop(
11300
- total === 0 ? "No sources to sync." : `Synced ${S.heading(`${synced}/${total}`)} source(s)` + (failed ? ` (${failed} failed)` : "")
11851
+ total === 0 ? "No sources to sync." : `Synced ${S.heading(`${synced}/${total}`)} source(s)` + (failed2 ? ` (${failed2} failed)` : "")
11301
11852
  );
11302
- if (failed > 0) process.exitCode = 1;
11853
+ if (failed2 > 0) process.exitCode = 1;
11303
11854
  } else {
11304
11855
  for (const slug of divergedSourceClones(projectDir)) {
11305
11856
  logErr(`${slug}: git pull failed: Not possible to fast-forward, aborting.`);
@@ -11314,27 +11865,39 @@ function makeUpdateCommand() {
11314
11865
  spinner.start("Re-deploying assets");
11315
11866
  let result;
11316
11867
  try {
11317
- result = await am2.install();
11868
+ result = await am2.install({ moveLibraries: true });
11318
11869
  } catch (err2) {
11319
11870
  spinner.stop("Failed");
11320
11871
  logErr(String(err2));
11321
11872
  process.exit(1);
11322
11873
  }
11323
- spinner.stop("Done");
11874
+ const failed = result.missing.length > 0 || !!result.agentInstanceErrors?.length || process.exitCode === 1;
11875
+ spinner.stop(failed ? "Failed" : "Done");
11324
11876
  if (result.deployed.length > 0) {
11325
11877
  for (const d of result.deployed) logOk(`Updated ${d}`);
11326
11878
  }
11879
+ for (const r of result.restored ?? []) {
11880
+ for (const f of r.restored) logInfo(`Restored ${f}`);
11881
+ for (const f of r.removed) logInfo(`Removed ${f} (not part of ${r.ref})`);
11882
+ }
11327
11883
  for (const r of result.removed) logWarn(`Removed: ${r}`);
11328
11884
  reportReplaced(result.replaced);
11329
11885
  reportRelocked(result.relocked);
11330
- const changed = result.deployed.length > 0 || result.removed.length > 0 || !!result.replaced?.length || !!result.relocked?.length;
11886
+ reportMoved(result.moved);
11887
+ const changed = result.deployed.length > 0 || result.removed.length > 0 || !!result.replaced?.length || !!result.moved?.length || !!result.relocked?.length;
11331
11888
  if (result.lockWritten && changed) {
11332
11889
  logInfo(`Lock file written: ${S.dim("skaile.lock.yaml")}`);
11333
11890
  }
11891
+ if (result.agentInstanceErrors?.length) {
11892
+ logErr(
11893
+ `${result.agentInstanceErrors.length} agent instance(s) could not be rendered (see above)`
11894
+ );
11895
+ process.exitCode = 1;
11896
+ }
11334
11897
  if (result.missing.length > 0) {
11335
11898
  for (const m of result.missing) logErr(`Missing: ${m}${result.missingHints?.[m] ?? ""}`);
11336
11899
  process.exitCode = 1;
11337
- } else if (!changed) {
11900
+ } else if (!changed && !failed) {
11338
11901
  logInfo("Nothing to update.");
11339
11902
  }
11340
11903
  }
@@ -11388,20 +11951,23 @@ function readText2(file) {
11388
11951
  }
11389
11952
  }
11390
11953
  async function updateOne(am2, projectDir, target) {
11391
- const lockPath = path18__default.join(projectDir, "skaile.lock.yaml");
11954
+ const lockPath = path22__default.join(projectDir, "skaile.lock.yaml");
11392
11955
  const before = readText2(lockPath);
11393
11956
  const spinner = createSpinner();
11394
11957
  spinner.start(`Updating ${target.ref}`);
11395
11958
  let deployed;
11396
11959
  try {
11397
- deployed = await am2.add(target.ref);
11960
+ deployed = await am2.add(target.ref, {
11961
+ preferLockedLibrary: true,
11962
+ onLibraryMoved: (m) => reportMoved([m])
11963
+ });
11398
11964
  } catch (err2) {
11399
11965
  spinner.stop("Failed");
11400
11966
  logErr(err2 instanceof Error ? err2.message : String(err2));
11401
11967
  process.exitCode = 1;
11402
11968
  return;
11403
11969
  }
11404
- spinner.stop("Done");
11970
+ spinner.stop(process.exitCode === 1 ? "Failed" : "Done");
11405
11971
  for (const d of deployed) logOk(`Updated ${d}`);
11406
11972
  if (deployed.length > 0) return;
11407
11973
  if (readText2(lockPath) !== before) logInfo(`Re-locked ${target.ref}`);
@@ -11495,17 +12061,23 @@ function refKindName(ref) {
11495
12061
  let rest = colon === -1 ? trimmed : trimmed.slice(colon + 1);
11496
12062
  const hash = rest.indexOf("#");
11497
12063
  if (hash !== -1) rest = rest.slice(0, hash);
12064
+ let publisher;
11498
12065
  if (rest.startsWith("@")) {
11499
12066
  const slash = rest.indexOf("/");
11500
- if (slash !== -1) rest = rest.slice(slash + 1);
12067
+ if (slash !== -1) {
12068
+ publisher = rest.slice(1, slash);
12069
+ rest = rest.slice(slash + 1);
12070
+ }
11501
12071
  }
11502
- return { kind, name: rest };
12072
+ return { kind, name: rest, publisher };
11503
12073
  }
11504
12074
  function whyEmptyMessage(ref, declared) {
11505
- const { kind, name } = refKindName(ref);
11506
- const isDeclared = declared.some(
11507
- (d) => d.name === name && (kind === void 0 || d.kind === kind)
11508
- );
12075
+ const { kind, name, publisher } = refKindName(ref);
12076
+ const isDeclared = declared.some((d) => {
12077
+ if (d.name !== name || kind !== void 0 && d.kind !== kind) return false;
12078
+ const declaredPublisher = d.ref ? refKindName(d.ref).publisher : void 0;
12079
+ return !publisher || !declaredPublisher || publisher === declaredPublisher;
12080
+ });
11509
12081
  if (isDeclared) {
11510
12082
  return `${ref} not found in lock file. Run \`skaile install\` first.`;
11511
12083
  }
@@ -11513,17 +12085,26 @@ function whyEmptyMessage(ref, declared) {
11513
12085
  }
11514
12086
  function makeWhyCommand() {
11515
12087
  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) => {
12088
+ requireProjectConfig(opts.projectDir);
11516
12089
  const am2 = new AssetManager({
11517
12090
  registry: getKindRegistry(),
11518
- projectDir: path18__default.resolve(opts.projectDir)
12091
+ projectDir: path22__default.resolve(opts.projectDir)
11519
12092
  });
11520
12093
  const chain = await am2.why(ref);
11521
12094
  if (chain.length === 0) {
12095
+ const declaredGap = (await am2.gapsOf(ref)).find((g) => g.type === "declared");
12096
+ if (declaredGap) {
12097
+ logErr(declaredGap.message);
12098
+ process.exitCode = 1;
12099
+ return;
12100
+ }
11522
12101
  let declared;
11523
12102
  try {
11524
12103
  declared = await am2.listDeclared();
11525
- } catch {
11526
- logErr(`${ref} not found in lock file. Run \`skaile install\` first.`);
12104
+ } catch (err2) {
12105
+ logErr(
12106
+ `${ref} is not in the lock file, and skaile.yaml cannot be read: ${err2 instanceof Error ? err2.message : String(err2)}`
12107
+ );
11527
12108
  process.exitCode = 1;
11528
12109
  return;
11529
12110
  }
@@ -11548,11 +12129,38 @@ function makeWhyCommand() {
11548
12129
  });
11549
12130
  }
11550
12131
 
12132
+ // cli/src/index-busy.ts
12133
+ var INDEX_BUSY_MESSAGE = "The skaile index is busy (another skaile process holds it); retry in a moment.";
12134
+ function isIndexBusyError(err2) {
12135
+ const seen = /* @__PURE__ */ new Set();
12136
+ let cur = err2;
12137
+ while (cur && typeof cur === "object" && !seen.has(cur)) {
12138
+ seen.add(cur);
12139
+ const { code, message, cause } = cur;
12140
+ if (typeof code === "string" && code.startsWith("SQLITE_BUSY")) return true;
12141
+ if (typeof message === "string" && /SQLITE_BUSY|database is locked/i.test(message)) return true;
12142
+ cur = cause;
12143
+ }
12144
+ return false;
12145
+ }
12146
+
11551
12147
  // cli/src/index.ts
12148
+ {
12149
+ const envLevel = process.env.SKAILE_LOG_LEVEL;
12150
+ const level = envLevel === "debug" || envLevel === "info" || envLevel === "warn" || envLevel === "error" ? envLevel : "warn";
12151
+ registerLogStore(
12152
+ new LogStore({
12153
+ sessionId: "cli",
12154
+ level,
12155
+ flushIntervalMs: 0,
12156
+ sinks: [new StdoutSink({ stream: "stderr", format: "pretty" })]
12157
+ })
12158
+ );
12159
+ }
11552
12160
  var _defaultFormatHelp = Help.prototype.formatHelp;
11553
12161
  var pkg = JSON.parse(
11554
12162
  readFileSync(
11555
- path18__default.resolve(path18__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
12163
+ path22__default.resolve(path22__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
11556
12164
  "utf-8"
11557
12165
  )
11558
12166
  );
@@ -11563,7 +12171,7 @@ for (const key of [
11563
12171
  "SKAILE_CACHE_DIR"
11564
12172
  ]) {
11565
12173
  const value = process.env[key];
11566
- if (value) process.env[key] = path18__default.resolve(value);
12174
+ if (value) process.env[key] = path22__default.resolve(value);
11567
12175
  }
11568
12176
  var program = new Command("skaile").description("AI asset manager").version(pkg.version, "-v, --version", "Show the skaile CLI version").enablePositionalOptions().configureHelp({
11569
12177
  formatHelp(cmd, helper) {
@@ -11608,7 +12216,7 @@ Execution:
11608
12216
  repl Interactive agent REPL
11609
12217
  resume Resume last session
11610
12218
  serve [--compile-test] Start WebSocket agent server
11611
- mcp-server Start workspace MCP server (for .claude/mcp.json)
12219
+ mcp-server Start workspace MCP server (for .mcp.json)
11612
12220
  integration install [--driver all] Install agent integration (claude-code | omp | codex)
11613
12221
  integration uninstall [--driver all] Uninstall agent integration
11614
12222
  integration enable Enable integration (claude-code only)
@@ -11683,7 +12291,7 @@ program.command("init [project-dir]").description("Initialize a project director
11683
12291
  (projectDir, opts) => runInit(projectDir, opts)
11684
12292
  );
11685
12293
  async function runInit(projectDir, opts) {
11686
- const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync6 } = await import('fs');
12294
+ const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync7 } = await import('fs');
11687
12295
  const { stringify: stringify2 } = await import('yaml');
11688
12296
  const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
11689
12297
  const harness = opts.harness;
@@ -11692,32 +12300,32 @@ async function runInit(projectDir, opts) {
11692
12300
  process.exitCode = 1;
11693
12301
  return;
11694
12302
  }
11695
- const resolved = path18__default.resolve(projectDir ?? ".");
11696
- const projectName = path18__default.basename(resolved);
12303
+ const resolved = path22__default.resolve(projectDir ?? ".");
12304
+ const projectName = path22__default.basename(resolved);
11697
12305
  const created = [];
11698
- const { existsSync: existsSync18 } = await import('fs');
11699
- if (!existsSync18(resolved)) {
12306
+ const { existsSync: existsSync20 } = await import('fs');
12307
+ if (!existsSync20(resolved)) {
11700
12308
  mkdirSync5(resolved, { recursive: true });
11701
12309
  created.push(".");
11702
12310
  }
11703
- const skaileDir = path18__default.join(resolved, ".skaile");
11704
- if (!existsSync18(skaileDir)) {
11705
- mkdirSync5(path18__default.join(skaileDir, "sessions"), { recursive: true });
12311
+ const skaileDir = path22__default.join(resolved, ".skaile");
12312
+ if (!existsSync20(skaileDir)) {
12313
+ mkdirSync5(path22__default.join(skaileDir, "sessions"), { recursive: true });
11706
12314
  created.push(".skaile/");
11707
12315
  }
11708
- const settingsPath = path18__default.join(skaileDir, "settings.json");
11709
- if (!existsSync18(settingsPath)) {
11710
- writeFileSync6(settingsPath, "{}\n");
12316
+ const settingsPath = path22__default.join(skaileDir, "settings.json");
12317
+ if (!existsSync20(settingsPath)) {
12318
+ writeFileSync7(settingsPath, "{}\n");
11711
12319
  created.push(".skaile/settings.json");
11712
12320
  }
11713
- const wsConfigPath = path18__default.join(resolved, "skaile.yaml");
11714
- if (!existsSync18(wsConfigPath)) {
11715
- writeFileSync6(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
12321
+ const wsConfigPath = path22__default.join(resolved, "skaile.yaml");
12322
+ if (!existsSync20(wsConfigPath)) {
12323
+ writeFileSync7(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
11716
12324
  created.push("skaile.yaml");
11717
12325
  }
11718
12326
  for (const dir of new Set(Object.values(DRIVER_TARGETS[harness].local))) {
11719
- const full = path18__default.join(resolved, dir);
11720
- if (!existsSync18(full)) {
12327
+ const full = path22__default.join(resolved, dir);
12328
+ if (!existsSync20(full)) {
11721
12329
  mkdirSync5(full, { recursive: true });
11722
12330
  created.push(`${dir}/`);
11723
12331
  }
@@ -11747,10 +12355,13 @@ function buildInitWorkspaceConfig(projectName, harness) {
11747
12355
  }
11748
12356
  async function initGitScaffold(resolved, created) {
11749
12357
  const { execSync: execSync2 } = await import('child_process');
11750
- const { existsSync: existsSync18, readFileSync: readFileSync10, writeFileSync: writeFileSync6 } = await import('fs');
11751
- const gitignorePath = path18__default.join(resolved, ".gitignore");
12358
+ const { existsSync: existsSync20, readFileSync: readFileSync12, writeFileSync: writeFileSync7 } = await import('fs');
12359
+ const gitignorePath = path22__default.join(resolved, ".gitignore");
11752
12360
  const entries = [
11753
12361
  "node_modules/",
12362
+ // Python bytecode a deployed skill script leaves inside `.claude/skills` and friends.
12363
+ "__pycache__/",
12364
+ "*.pyc",
11754
12365
  ".skaile/sessions/",
11755
12366
  ".skaile/cache/",
11756
12367
  // skaile-created artifacts that must never be committed: the per-session log
@@ -11761,20 +12372,25 @@ async function initGitScaffold(resolved, created) {
11761
12372
  ".skaile/settings.json",
11762
12373
  ".skaile/providers.yml",
11763
12374
  ".skaile/history.yaml",
12375
+ // Per-machine files a run writes into the project: the system prompt handed to the harness
12376
+ // (it carries the host path) and omp's session logs.
12377
+ ".codex/skaile-session-instructions.md",
12378
+ ".omp/system.md",
12379
+ ".omp/sessions/",
11764
12380
  "*.log",
11765
12381
  ".env",
11766
12382
  ".env.local"
11767
12383
  ];
11768
- const existing = existsSync18(gitignorePath) ? readFileSync10(gitignorePath, "utf-8") : "";
12384
+ const existing = existsSync20(gitignorePath) ? readFileSync12(gitignorePath, "utf-8") : "";
11769
12385
  const have = new Set(existing.split("\n").map((l) => l.trim()));
11770
12386
  const append = entries.filter((e) => !have.has(e));
11771
12387
  if (append.length > 0) {
11772
12388
  const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
11773
- writeFileSync6(gitignorePath, `${existing + prefix}${append.join("\n")}
12389
+ writeFileSync7(gitignorePath, `${existing + prefix}${append.join("\n")}
11774
12390
  `);
11775
12391
  if (!existing) created.push(".gitignore");
11776
12392
  }
11777
- if (!existsSync18(path18__default.join(resolved, ".git"))) {
12393
+ if (!existsSync20(path22__default.join(resolved, ".git"))) {
11778
12394
  try {
11779
12395
  execSync2("git init", { cwd: resolved, stdio: "pipe" });
11780
12396
  created.push(".git/");
@@ -11804,7 +12420,7 @@ async function bootstrapUserConfig() {
11804
12420
  }
11805
12421
  async function hydrateInitSources(resolved, created) {
11806
12422
  try {
11807
- const { ensureSourcesCloned } = await import('../ensure-sources-5ISVIA4T.js');
12423
+ const { ensureSourcesCloned } = await import('../ensure-sources-POMEQSTM.js');
11808
12424
  const hydrate = ensureSourcesCloned(resolved, { quiet: true });
11809
12425
  for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
11810
12426
  if (hydrate.failed.length > 0) {
@@ -11820,7 +12436,7 @@ function printInitSummary(resolved, projectDir, created) {
11820
12436
  logOk(`Initialized project at ${S.heading(resolved)}`);
11821
12437
  console.log();
11822
12438
  console.log(S.heading(" Next steps:"));
11823
- const isCurrentDir = resolved === path18__default.resolve(".");
12439
+ const isCurrentDir = resolved === path22__default.resolve(".");
11824
12440
  let step = 1;
11825
12441
  if (!isCurrentDir) {
11826
12442
  console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
@@ -11844,7 +12460,7 @@ function printInitSummary(resolved, projectDir, created) {
11844
12460
  console.log();
11845
12461
  }
11846
12462
  program.command("setup").description("Interactive provider setup wizard").action(async () => {
11847
- const { cmdSetup } = await import('../setup-BV55VHWC.js');
12463
+ const { cmdSetup } = await import('../setup-5IRUH5OS.js');
11848
12464
  await cmdSetup([], { projectDir: process.cwd() });
11849
12465
  });
11850
12466
  program.addCommand(makeInstallCommand());
@@ -11922,9 +12538,20 @@ process.stdout.on("error", (err2) => {
11922
12538
  if (err2.code === "EPIPE") process.exit(0);
11923
12539
  throw err2;
11924
12540
  });
12541
+ var commandSettled = false;
12542
+ process.once("beforeExit", () => {
12543
+ if (commandSettled) return;
12544
+ logErr("The command ended before it finished (nothing left to wait for).");
12545
+ process.exit(1);
12546
+ });
11925
12547
  try {
11926
12548
  await program.parseAsync();
12549
+ commandSettled = true;
11927
12550
  } catch (err2) {
12551
+ if (isIndexBusyError(err2)) {
12552
+ logErr(INDEX_BUSY_MESSAGE);
12553
+ process.exit(1);
12554
+ }
11928
12555
  const { LibrarySyncError } = await import('../library/index.js');
11929
12556
  if (!(err2 instanceof LibrarySyncError || err2 instanceof SourceEntryError)) throw err2;
11930
12557
  logErr(err2.message);