@skaile/workspaces 5.11.0 → 5.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/README.md +4 -4
  3. package/dist/{asset-feeds-CXGQIDFR.js → asset-feeds-ALMTHLPV.js} +26 -23
  4. package/dist/asset-feeds-ALMTHLPV.js.map +1 -0
  5. package/dist/asset-manager/catalog-deployer.js +10 -10
  6. package/dist/asset-manager/fragments.js +1 -1
  7. package/dist/asset-manager/index.js +18 -18
  8. package/dist/asset-manager/installer.js +13 -13
  9. package/dist/asset-manager/renderers.js +11 -11
  10. package/dist/asset-manager/src/fragments.d.ts +5 -0
  11. package/dist/asset-manager/src/fragments.d.ts.map +1 -1
  12. package/dist/asset-manager/src/index.d.ts +140 -12
  13. package/dist/asset-manager/src/index.d.ts.map +1 -1
  14. package/dist/asset-manager/src/install-agent.d.ts +9 -1
  15. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  16. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  17. package/dist/asset-manager/src/renderers.d.ts +5 -0
  18. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  19. package/dist/bridge/drivers/claude-sdk.js +21 -16
  20. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  21. package/dist/bridge/drivers/codex.js +101 -29
  22. package/dist/bridge/drivers/codex.js.map +1 -1
  23. package/dist/bridge/drivers/continue.js +12 -12
  24. package/dist/bridge/drivers/echo.js +2 -2
  25. package/dist/bridge/drivers/gemini.js +7 -7
  26. package/dist/bridge/drivers/goose.js +12 -12
  27. package/dist/bridge/drivers/omp.js +135 -33
  28. package/dist/bridge/drivers/omp.js.map +1 -1
  29. package/dist/bridge/drivers/opencode.js +12 -12
  30. package/dist/bridge/drivers/qwen.js +7 -7
  31. package/dist/bridge/index.js +14 -14
  32. package/dist/bridge/src/codex/config-toml.d.ts +16 -3
  33. package/dist/bridge/src/codex/config-toml.d.ts.map +1 -1
  34. package/dist/bridge/src/codex/managed-driver.d.ts.map +1 -1
  35. package/dist/bridge/src/drivers/claude-sdk.d.ts +1 -1
  36. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  37. package/dist/bridge/src/drivers/codex.d.ts +6 -0
  38. package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
  39. package/dist/bridge/src/drivers/omp-models-yml.d.ts +32 -0
  40. package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +1 -1
  41. package/dist/bridge/src/drivers/omp.d.ts +29 -6
  42. package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
  43. package/dist/bridge/src/provider-materialize/credential-env.d.ts +15 -0
  44. package/dist/bridge/src/provider-materialize/credential-env.d.ts.map +1 -1
  45. package/dist/{chunk-T42WRQ4O.js → chunk-2BIESC6S.js} +3 -3
  46. package/dist/{chunk-T42WRQ4O.js.map → chunk-2BIESC6S.js.map} +1 -1
  47. package/dist/{chunk-CPWLNZGJ.js → chunk-4DLQESIY.js} +3 -3
  48. package/dist/{chunk-CPWLNZGJ.js.map → chunk-4DLQESIY.js.map} +1 -1
  49. package/dist/{chunk-HZXUXHIV.js → chunk-4L4R5LV3.js} +89 -12
  50. package/dist/chunk-4L4R5LV3.js.map +1 -0
  51. package/dist/{chunk-CAHB6MHA.js → chunk-4NJ3QQHZ.js} +5 -5
  52. package/dist/{chunk-CAHB6MHA.js.map → chunk-4NJ3QQHZ.js.map} +1 -1
  53. package/dist/{chunk-ZCAJZ4B2.js → chunk-57SF6W6E.js} +147 -4
  54. package/dist/chunk-57SF6W6E.js.map +1 -0
  55. package/dist/{chunk-FH7W6TJ4.js → chunk-5FYOM4RF.js} +106 -25
  56. package/dist/chunk-5FYOM4RF.js.map +1 -0
  57. package/dist/{chunk-R7NHYEJF.js → chunk-5SKVCMRC.js} +15 -7
  58. package/dist/chunk-5SKVCMRC.js.map +1 -0
  59. package/dist/{chunk-CJERAGFY.js → chunk-6GICC4RJ.js} +44 -13
  60. package/dist/chunk-6GICC4RJ.js.map +1 -0
  61. package/dist/{chunk-G4FFOV3N.js → chunk-6JKIOPT3.js} +4 -4
  62. package/dist/{chunk-G4FFOV3N.js.map → chunk-6JKIOPT3.js.map} +1 -1
  63. package/dist/{chunk-T7CTHHG7.js → chunk-6NQDDCIL.js} +3 -3
  64. package/dist/{chunk-T7CTHHG7.js.map → chunk-6NQDDCIL.js.map} +1 -1
  65. package/dist/{chunk-XUSALIEI.js → chunk-7SMP4GNW.js} +6 -6
  66. package/dist/{chunk-XUSALIEI.js.map → chunk-7SMP4GNW.js.map} +1 -1
  67. package/dist/{chunk-Y3HTGHJC.js → chunk-AHCI4V5L.js} +3 -3
  68. package/dist/{chunk-Y3HTGHJC.js.map → chunk-AHCI4V5L.js.map} +1 -1
  69. package/dist/{chunk-M3B6EIJD.js → chunk-B7CZYFB2.js} +4 -4
  70. package/dist/{chunk-M3B6EIJD.js.map → chunk-B7CZYFB2.js.map} +1 -1
  71. package/dist/{chunk-PBBPZYVG.js → chunk-BF422IDP.js} +112 -46
  72. package/dist/chunk-BF422IDP.js.map +1 -0
  73. package/dist/{chunk-47U4GZ4M.js → chunk-BVJU2GKE.js} +20 -3
  74. package/dist/chunk-BVJU2GKE.js.map +1 -0
  75. package/dist/{chunk-PMECEZK3.js → chunk-D54T2F54.js} +5 -4
  76. package/dist/chunk-D54T2F54.js.map +1 -0
  77. package/dist/{chunk-2F5AWQX5.js → chunk-DKGEV6SQ.js} +192 -42
  78. package/dist/chunk-DKGEV6SQ.js.map +1 -0
  79. package/dist/{chunk-DALV4HHP.js → chunk-DKXNKFKP.js} +3 -2
  80. package/dist/{chunk-DALV4HHP.js.map → chunk-DKXNKFKP.js.map} +1 -1
  81. package/dist/chunk-FB3NREF7.js +649 -0
  82. package/dist/chunk-FB3NREF7.js.map +1 -0
  83. package/dist/{chunk-QZNJOHN6.js → chunk-FHDK3BFD.js} +3 -3
  84. package/dist/{chunk-QZNJOHN6.js.map → chunk-FHDK3BFD.js.map} +1 -1
  85. package/dist/{chunk-3SM2DL2T.js → chunk-GMDSRSGI.js} +21 -11
  86. package/dist/chunk-GMDSRSGI.js.map +1 -0
  87. package/dist/chunk-H5U7LNTJ.js +122 -0
  88. package/dist/chunk-H5U7LNTJ.js.map +1 -0
  89. package/dist/{chunk-VLTQGE2E.js → chunk-HBZD3MIW.js} +269 -81
  90. package/dist/chunk-HBZD3MIW.js.map +1 -0
  91. package/dist/{chunk-S3O3GKB7.js → chunk-HWGYJMME.js} +4 -4
  92. package/dist/{chunk-S3O3GKB7.js.map → chunk-HWGYJMME.js.map} +1 -1
  93. package/dist/{chunk-CPSIPIX7.js → chunk-IG5LZ3WU.js} +8 -6
  94. package/dist/chunk-IG5LZ3WU.js.map +1 -0
  95. package/dist/{chunk-ZPWTOUTK.js → chunk-IY5E7Y5W.js} +61 -8
  96. package/dist/chunk-IY5E7Y5W.js.map +1 -0
  97. package/dist/{chunk-6O2X3GPW.js → chunk-J4DB5G36.js} +7 -5
  98. package/dist/chunk-J4DB5G36.js.map +1 -0
  99. package/dist/{chunk-BNMZVPYA.js → chunk-J4OYIYFQ.js} +2 -2
  100. package/dist/{chunk-BNMZVPYA.js.map → chunk-J4OYIYFQ.js.map} +1 -1
  101. package/dist/{chunk-ALEYHUC5.js → chunk-L3ZGYSWY.js} +182 -41
  102. package/dist/chunk-L3ZGYSWY.js.map +1 -0
  103. package/dist/{chunk-SBSA3IQA.js → chunk-M3P4BYRK.js} +49 -14
  104. package/dist/chunk-M3P4BYRK.js.map +1 -0
  105. package/dist/{chunk-IER3KIPH.js → chunk-NDUYFYJB.js} +5 -5
  106. package/dist/{chunk-IER3KIPH.js.map → chunk-NDUYFYJB.js.map} +1 -1
  107. package/dist/{chunk-CGYEHQOX.js → chunk-NOA6EJXE.js} +11 -2
  108. package/dist/chunk-NOA6EJXE.js.map +1 -0
  109. package/dist/{chunk-J4RBUFGM.js → chunk-NVO6WECE.js} +9 -8
  110. package/dist/chunk-NVO6WECE.js.map +1 -0
  111. package/dist/{chunk-OBYKJB4U.js → chunk-O2SYFJWP.js} +79 -5
  112. package/dist/chunk-O2SYFJWP.js.map +1 -0
  113. package/dist/{chunk-5LKOAX7I.js → chunk-OQ5MKDS3.js} +21 -5
  114. package/dist/chunk-OQ5MKDS3.js.map +1 -0
  115. package/dist/{chunk-NWDSLXOX.js → chunk-PHRNUTSG.js} +118 -118
  116. package/dist/chunk-PHRNUTSG.js.map +1 -0
  117. package/dist/chunk-PN44DOGP.js +345 -0
  118. package/dist/chunk-PN44DOGP.js.map +1 -0
  119. package/dist/{chunk-COH6FQAG.js → chunk-PXDWTJ3P.js} +5 -5
  120. package/dist/{chunk-COH6FQAG.js.map → chunk-PXDWTJ3P.js.map} +1 -1
  121. package/dist/{chunk-GV4DZ6MT.js → chunk-PYTTF754.js} +22 -6
  122. package/dist/chunk-PYTTF754.js.map +1 -0
  123. package/dist/chunk-PZOO7L26.js +64 -0
  124. package/dist/chunk-PZOO7L26.js.map +1 -0
  125. package/dist/{chunk-EDYHEMJA.js → chunk-QO7CR3KB.js} +10 -5
  126. package/dist/chunk-QO7CR3KB.js.map +1 -0
  127. package/dist/{chunk-XDKH7XSA.js → chunk-R6QHJEHE.js} +5 -5
  128. package/dist/{chunk-XDKH7XSA.js.map → chunk-R6QHJEHE.js.map} +1 -1
  129. package/dist/chunk-U27JRO5L.js +13 -0
  130. package/dist/chunk-U27JRO5L.js.map +1 -0
  131. package/dist/{chunk-X77SUM4P.js → chunk-USHB5KEY.js} +3 -3
  132. package/dist/{chunk-X77SUM4P.js.map → chunk-USHB5KEY.js.map} +1 -1
  133. package/dist/{chunk-QVFAS5IO.js → chunk-V5JHD4I2.js} +3 -3
  134. package/dist/{chunk-QVFAS5IO.js.map → chunk-V5JHD4I2.js.map} +1 -1
  135. package/dist/{chunk-PQFHMQHQ.js → chunk-VLBIME5L.js} +6 -6
  136. package/dist/{chunk-PQFHMQHQ.js.map → chunk-VLBIME5L.js.map} +1 -1
  137. package/dist/{chunk-D3B36CYC.js → chunk-X3RMRJNR.js} +4 -3
  138. package/dist/chunk-X3RMRJNR.js.map +1 -0
  139. package/dist/{chunk-TCHRMVTO.js → chunk-XBYSURMK.js} +4 -4
  140. package/dist/{chunk-TCHRMVTO.js.map → chunk-XBYSURMK.js.map} +1 -1
  141. package/dist/{chunk-MZG34MBZ.js → chunk-XJYBCDY2.js} +3 -3
  142. package/dist/{chunk-MZG34MBZ.js.map → chunk-XJYBCDY2.js.map} +1 -1
  143. package/dist/{chunk-4A4OD24G.js → chunk-Y4Z7LGSH.js} +9 -9
  144. package/dist/{chunk-4A4OD24G.js.map → chunk-Y4Z7LGSH.js.map} +1 -1
  145. package/dist/{chunk-DZMNFCWB.js → chunk-Y7WKXPWS.js} +816 -143
  146. package/dist/chunk-Y7WKXPWS.js.map +1 -0
  147. package/dist/{chunk-HCEVNYSH.js → chunk-YTZFSKWL.js} +3 -3
  148. package/dist/{chunk-HCEVNYSH.js.map → chunk-YTZFSKWL.js.map} +1 -1
  149. package/dist/{chunk-WSBKB4CJ.js → chunk-ZSMMX3JD.js} +167 -25
  150. package/dist/chunk-ZSMMX3JD.js.map +1 -0
  151. package/dist/{chunk-GCHPUTA3.js → chunk-ZU24LWBI.js} +3 -3
  152. package/dist/{chunk-GCHPUTA3.js.map → chunk-ZU24LWBI.js.map} +1 -1
  153. package/dist/cli/index.js +1427 -605
  154. package/dist/cli/index.js.map +1 -1
  155. package/dist/cli/src/agent-checks.d.ts +40 -0
  156. package/dist/cli/src/agent-checks.d.ts.map +1 -0
  157. package/dist/cli/src/asset-feeds.d.ts.map +1 -1
  158. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  159. package/dist/cli/src/commands/catalog-cmd.d.ts.map +1 -1
  160. package/dist/cli/src/commands/catalog.d.ts +26 -0
  161. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  162. package/dist/cli/src/commands/config.d.ts.map +1 -1
  163. package/dist/cli/src/commands/diff.d.ts +1 -1
  164. package/dist/cli/src/commands/diff.d.ts.map +1 -1
  165. package/dist/cli/src/commands/integration.d.ts.map +1 -1
  166. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  167. package/dist/cli/src/commands/library-index.d.ts +10 -0
  168. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  169. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  170. package/dist/cli/src/commands/mcp-server.d.ts +1 -1
  171. package/dist/cli/src/commands/migrate-assets.d.ts +2 -1
  172. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  173. package/dist/cli/src/commands/migrate.d.ts.map +1 -1
  174. package/dist/cli/src/commands/plugin/claude-code.d.ts +1 -1
  175. package/dist/cli/src/commands/plugin/claude-code.d.ts.map +1 -1
  176. package/dist/cli/src/commands/plugin/types.d.ts +3 -1
  177. package/dist/cli/src/commands/plugin/types.d.ts.map +1 -1
  178. package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
  179. package/dist/cli/src/commands/preset-apply.d.ts.map +1 -1
  180. package/dist/cli/src/commands/project.d.ts +8 -0
  181. package/dist/cli/src/commands/project.d.ts.map +1 -1
  182. package/dist/cli/src/commands/publish-core.d.ts +5 -0
  183. package/dist/cli/src/commands/publish-core.d.ts.map +1 -1
  184. package/dist/cli/src/commands/run.d.ts +11 -1
  185. package/dist/cli/src/commands/run.d.ts.map +1 -1
  186. package/dist/cli/src/commands/serve-preflight.d.ts +23 -0
  187. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -0
  188. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  189. package/dist/cli/src/commands/source-manifest-publish.d.ts.map +1 -1
  190. package/dist/cli/src/commands/source-manifest.d.ts +1 -0
  191. package/dist/cli/src/commands/source-manifest.d.ts.map +1 -1
  192. package/dist/cli/src/commands/source.d.ts +9 -1
  193. package/dist/cli/src/commands/source.d.ts.map +1 -1
  194. package/dist/cli/src/commands/store.d.ts.map +1 -1
  195. package/dist/cli/src/commands/tree.d.ts.map +1 -1
  196. package/dist/cli/src/commands/update.d.ts.map +1 -1
  197. package/dist/cli/src/commands/validate-instances.d.ts.map +1 -1
  198. package/dist/cli/src/commands/validate.d.ts +3 -2
  199. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  200. package/dist/cli/src/commands/why.d.ts.map +1 -1
  201. package/dist/cli/src/curated-manifests.d.ts +21 -0
  202. package/dist/cli/src/curated-manifests.d.ts.map +1 -0
  203. package/dist/cli/src/driver-error.d.ts +7 -0
  204. package/dist/cli/src/driver-error.d.ts.map +1 -1
  205. package/dist/cli/src/helpers.d.ts +6 -0
  206. package/dist/cli/src/helpers.d.ts.map +1 -1
  207. package/dist/cli/src/index-busy.d.ts +8 -0
  208. package/dist/cli/src/index-busy.d.ts.map +1 -0
  209. package/dist/cli/src/plugin-store/index.d.ts +1 -1
  210. package/dist/cli/src/plugin-store/index.d.ts.map +1 -1
  211. package/dist/cli/src/plugin-store/paths.d.ts +7 -3
  212. package/dist/cli/src/plugin-store/paths.d.ts.map +1 -1
  213. package/dist/cli/src/plugin-store/reconcile.d.ts +24 -4
  214. package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -1
  215. package/dist/cli/src/skill-checks.d.ts +27 -3
  216. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  217. package/dist/cli/src/store-addable.d.ts +17 -0
  218. package/dist/cli/src/store-addable.d.ts.map +1 -0
  219. package/dist/connectors/config.js +6 -6
  220. package/dist/connectors/index.js +18 -18
  221. package/dist/connectors/src/config.d.ts.map +1 -1
  222. package/dist/{connectors-4QWAKPHB.js → connectors-GFKMKAXV.js} +21 -21
  223. package/dist/{connectors-4QWAKPHB.js.map → connectors-GFKMKAXV.js.map} +1 -1
  224. package/dist/core/driver-targets.js +1 -1
  225. package/dist/core/index.js +9 -9
  226. package/dist/core/logging.js +1 -1
  227. package/dist/core/manifest.js +2 -2
  228. package/dist/core/models.js +1 -1
  229. package/dist/core/publish-manifest.js +4 -2
  230. package/dist/core/ref.js +1 -1
  231. package/dist/core/runtime-assets.js +6 -6
  232. package/dist/core/src/agent-instances.d.ts +5 -0
  233. package/dist/core/src/agent-instances.d.ts.map +1 -1
  234. package/dist/core/src/driver-targets.d.ts.map +1 -1
  235. package/dist/core/src/index.d.ts +6 -5
  236. package/dist/core/src/index.d.ts.map +1 -1
  237. package/dist/core/src/lock.d.ts +15 -5
  238. package/dist/core/src/lock.d.ts.map +1 -1
  239. package/dist/core/src/logging/sinks/sqlite-sink.d.ts.map +1 -1
  240. package/dist/core/src/manifest.d.ts +14 -3
  241. package/dist/core/src/manifest.d.ts.map +1 -1
  242. package/dist/core/src/models.d.ts +11 -3
  243. package/dist/core/src/models.d.ts.map +1 -1
  244. package/dist/core/src/package-manager.d.ts +19 -0
  245. package/dist/core/src/package-manager.d.ts.map +1 -0
  246. package/dist/core/src/publish-manifest.d.ts +38 -1
  247. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  248. package/dist/core/src/repo-manager.d.ts +19 -3
  249. package/dist/core/src/repo-manager.d.ts.map +1 -1
  250. package/dist/core/src/runtime-assets.d.ts.map +1 -1
  251. package/dist/core/src/settings.d.ts +26 -6
  252. package/dist/core/src/settings.d.ts.map +1 -1
  253. package/dist/core/src/store.d.ts +4 -0
  254. package/dist/core/src/store.d.ts.map +1 -1
  255. package/dist/core/src/walker.d.ts +8 -1
  256. package/dist/core/src/walker.d.ts.map +1 -1
  257. package/dist/core/src/workspace-config.d.ts +24 -2
  258. package/dist/core/src/workspace-config.d.ts.map +1 -1
  259. package/dist/core/store.js +2 -2
  260. package/dist/core/workspace-config.js +5 -5
  261. package/dist/deploy/index.js +9 -9
  262. package/dist/discovery/index.js +5 -5
  263. package/dist/discovery/src/parse-manifest.d.ts.map +1 -1
  264. package/dist/discovery/src/source-config.d.ts +5 -3
  265. package/dist/discovery/src/source-config.d.ts.map +1 -1
  266. package/dist/{ensure-sources-2RONZKCU.js → ensure-sources-VUKHL65L.js} +21 -21
  267. package/dist/{ensure-sources-2RONZKCU.js.map → ensure-sources-VUKHL65L.js.map} +1 -1
  268. package/dist/factory-assets/README.md +1 -1
  269. package/dist/factory-assets/connectors/box.js +18 -18
  270. package/dist/factory-assets/connectors/deploy.js +18 -18
  271. package/dist/factory-assets/connectors/devserver.js +18 -18
  272. package/dist/factory-assets/connectors/flow/adapter.js +18 -18
  273. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
  274. package/dist/factory-assets/connectors/flow/contract.js +1 -1
  275. package/dist/factory-assets/connectors/flow/engine.js +11 -11
  276. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  277. package/dist/factory-assets/connectors/flow/run-flow.js +20 -20
  278. package/dist/factory-assets/connectors/flow.js +18 -18
  279. package/dist/factory-assets/connectors/git.js +18 -18
  280. package/dist/factory-assets/connectors/gmail.js +18 -18
  281. package/dist/factory-assets/connectors/googledrive.js +18 -18
  282. package/dist/factory-assets/connectors/local.js +18 -18
  283. package/dist/factory-assets/connectors/mattermost.js +18 -18
  284. package/dist/factory-assets/connectors/memory.js +18 -18
  285. package/dist/factory-assets/connectors/minio.js +18 -18
  286. package/dist/factory-assets/connectors/postgres.js +18 -18
  287. package/dist/factory-assets/connectors/s3.js +18 -18
  288. package/dist/factory-assets/connectors/sharepoint.js +18 -18
  289. package/dist/factory-assets/connectors/sqlite.js +18 -18
  290. package/dist/factory-assets/connectors/static-server.js +18 -18
  291. package/dist/factory-assets/connectors/tunnel.js +18 -18
  292. package/dist/factory-assets/connectors/webdav.js +18 -18
  293. package/dist/factory-assets/connectors/xstate-store.js +18 -18
  294. package/dist/factory-assets/connectors/xstate.js +18 -18
  295. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +10 -8
  296. package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +15 -11
  297. package/dist/factory-assets/skills/authoring-skaile-manifests/references/dependency-standard.md +12 -9
  298. package/dist/factory-assets/skills/skaile-author-asset/SKILL.md +2 -2
  299. package/dist/flows-A4YALSZY.js +26 -0
  300. package/dist/{flows-EQF2CH4U.js.map → flows-A4YALSZY.js.map} +1 -1
  301. package/dist/helpers-53XZW7KF.js +34 -0
  302. package/dist/{helpers-CFK6YP6R.js.map → helpers-53XZW7KF.js.map} +1 -1
  303. package/dist/library/index.js +14 -14
  304. package/dist/library/install.js +6 -4
  305. package/dist/library/src/index.d.ts +2 -2
  306. package/dist/library/src/index.d.ts.map +1 -1
  307. package/dist/library/src/install/source-fetch-github.d.ts.map +1 -1
  308. package/dist/library/src/local/db.d.ts +2 -0
  309. package/dist/library/src/local/db.d.ts.map +1 -1
  310. package/dist/library/src/local/library-manager.d.ts +5 -0
  311. package/dist/library/src/local/library-manager.d.ts.map +1 -1
  312. package/dist/library/src/local/library.d.ts +5 -3
  313. package/dist/library/src/local/library.d.ts.map +1 -1
  314. package/dist/library/src/local/local-catalog-source.d.ts +6 -0
  315. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  316. package/dist/library/src/local/store-paths.d.ts +9 -0
  317. package/dist/library/src/local/store-paths.d.ts.map +1 -1
  318. package/dist/library/src/manifest-writer.d.ts +1 -1
  319. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  320. package/dist/library/src/remote/index.d.ts +1 -1
  321. package/dist/library/src/remote/index.d.ts.map +1 -1
  322. package/dist/library/src/remote/remote-catalog-source.d.ts +17 -0
  323. package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
  324. package/dist/library/src/sync/git-driver.d.ts.map +1 -1
  325. package/dist/library/src/user-library.d.ts +2 -0
  326. package/dist/library/src/user-library.d.ts.map +1 -1
  327. package/dist/{library-publish-53UTB3MB.js → library-publish-FFIPWIRM.js} +50 -39
  328. package/dist/library-publish-FFIPWIRM.js.map +1 -0
  329. package/dist/open-library-PZAT3TJA.js +40 -0
  330. package/dist/{open-library-BOSPJVID.js.map → open-library-PZAT3TJA.js.map} +1 -1
  331. package/dist/open-registry-W46UXZ3I.js +32 -0
  332. package/dist/{open-registry-4FI7HKET.js.map → open-registry-W46UXZ3I.js.map} +1 -1
  333. package/dist/paths-KKY3NSBZ.js +22 -0
  334. package/dist/{paths-SUS4S4YT.js.map → paths-KKY3NSBZ.js.map} +1 -1
  335. package/dist/plugin-store-CK7YWRIC.js +227 -0
  336. package/dist/plugin-store-CK7YWRIC.js.map +1 -0
  337. package/dist/plugins/src/catalog-source.d.ts +6 -0
  338. package/dist/plugins/src/catalog-source.d.ts.map +1 -1
  339. package/dist/project-EZUH7PUJ.js +79 -0
  340. package/dist/{project-I55A4O2T.js.map → project-EZUH7PUJ.js.map} +1 -1
  341. package/dist/resolver/index.js +10 -10
  342. package/dist/runner/index.js +35 -35
  343. package/dist/runner/src/agent.d.ts.map +1 -1
  344. package/dist/runner/src/agents/in-process-host.d.ts.map +1 -1
  345. package/dist/runner/src/composition/index.d.ts +2 -1
  346. package/dist/runner/src/composition/index.d.ts.map +1 -1
  347. package/dist/runner/src/composition/prompt-sections.d.ts +20 -5
  348. package/dist/runner/src/composition/prompt-sections.d.ts.map +1 -1
  349. package/dist/runner/src/composition/resolve.d.ts +10 -1
  350. package/dist/runner/src/composition/resolve.d.ts.map +1 -1
  351. package/dist/runner/src/composition/verify.d.ts +29 -0
  352. package/dist/runner/src/composition/verify.d.ts.map +1 -0
  353. package/dist/runner/src/credential-notice.d.ts +14 -0
  354. package/dist/runner/src/credential-notice.d.ts.map +1 -0
  355. package/dist/runner/src/environment.d.ts.map +1 -1
  356. package/dist/runner/src/final-text.d.ts +17 -0
  357. package/dist/runner/src/final-text.d.ts.map +1 -0
  358. package/dist/runner/src/index.d.ts +2 -0
  359. package/dist/runner/src/index.d.ts.map +1 -1
  360. package/dist/runner/src/resource-handler.d.ts.map +1 -1
  361. package/dist/runner/src/serve.d.ts +13 -0
  362. package/dist/runner/src/serve.d.ts.map +1 -1
  363. package/dist/runner/src/session-builder.d.ts.map +1 -1
  364. package/dist/runner/src/session.d.ts +2 -0
  365. package/dist/runner/src/session.d.ts.map +1 -1
  366. package/dist/runner/src/ws-auth-warning.d.ts +17 -0
  367. package/dist/runner/src/ws-auth-warning.d.ts.map +1 -0
  368. package/dist/sdk/asset-manager.js +18 -18
  369. package/dist/sdk/bridge.js +14 -14
  370. package/dist/sdk/core.js +9 -9
  371. package/dist/sdk/flow.js +11 -11
  372. package/dist/sdk/index.js +38 -36
  373. package/dist/sdk/index.js.map +1 -1
  374. package/dist/sdk/resolver.js +10 -10
  375. package/dist/sdk/runner.js +35 -35
  376. package/dist/sdk/src/local-runtime.d.ts.map +1 -1
  377. package/dist/sdk/transport/ws/client.js +1 -1
  378. package/dist/sdk/transport/ws/server.js +1 -1
  379. package/dist/sdk/transport/ws.js +2 -2
  380. package/dist/sdk/transport.js +2 -2
  381. package/dist/serve-preflight-F7MYF747.js +64 -0
  382. package/dist/serve-preflight-F7MYF747.js.map +1 -0
  383. package/dist/{setup-7DQJKHUI.js → setup-L632QIHV.js} +26 -26
  384. package/dist/{setup-7DQJKHUI.js.map → setup-L632QIHV.js.map} +1 -1
  385. package/dist/skills-OY3Y5GKA.js +26 -0
  386. package/dist/{skills-NUEN5NDX.js.map → skills-OY3Y5GKA.js.map} +1 -1
  387. package/dist/source-36FHMN5V.js +42 -0
  388. package/dist/{source-G2LV5LVD.js.map → source-36FHMN5V.js.map} +1 -1
  389. package/dist/source-fetch-github-PIO6EMMF.js +4 -0
  390. package/dist/{source-fetch-github-QN4LLTL5.js.map → source-fetch-github-PIO6EMMF.js.map} +1 -1
  391. package/dist/{source-manifest-publish-6RM7SWLZ.js → source-manifest-publish-NIXJSJ22.js} +30 -28
  392. package/dist/source-manifest-publish-NIXJSJ22.js.map +1 -0
  393. package/dist/transport/index.js +2 -2
  394. package/dist/transport/src/ws/client.d.ts +6 -0
  395. package/dist/transport/src/ws/client.d.ts.map +1 -1
  396. package/dist/transport/src/ws/server.d.ts +4 -0
  397. package/dist/transport/src/ws/server.d.ts.map +1 -1
  398. package/dist/transport/ws/client.js +1 -1
  399. package/dist/transport/ws/server.js +1 -1
  400. package/dist/transport/ws.js +2 -2
  401. package/dist/tui/index.js +77 -50
  402. package/dist/tui/index.js.map +1 -1
  403. package/dist/tui/src/repl-session.d.ts +1 -1
  404. package/dist/tui/src/repl-session.d.ts.map +1 -1
  405. package/dist/tui/src/repl.d.ts +3 -0
  406. package/dist/tui/src/repl.d.ts.map +1 -1
  407. package/dist/types/manifests.js +1 -1
  408. package/dist/types/src/lifecycle.d.ts +2 -1
  409. package/dist/types/src/lifecycle.d.ts.map +1 -1
  410. package/dist/types/src/manifests/agent-composition.d.ts +20 -0
  411. package/dist/types/src/manifests/agent-composition.d.ts.map +1 -1
  412. package/dist/types/src/manifests/agent.d.ts.map +1 -1
  413. package/dist/types/src/manifests/cron.d.ts +15 -0
  414. package/dist/types/src/manifests/cron.d.ts.map +1 -0
  415. package/dist/types/src/manifests/index.d.ts +3 -2
  416. package/dist/types/src/manifests/index.d.ts.map +1 -1
  417. package/dist/types/src/manifests/preset.d.ts +6 -1
  418. package/dist/types/src/manifests/preset.d.ts.map +1 -1
  419. package/dist/workspace-plugin/adapters/mcp.js +25 -25
  420. package/dist/workspace-plugin/adapters/omp.js +106 -51
  421. package/dist/workspace-plugin/adapters/omp.js.map +1 -1
  422. package/dist/workspace-plugin/index.js +2 -2
  423. package/dist/workspace-plugin/src/adapters/claude-code.d.ts.map +1 -1
  424. package/dist/workspace-plugin/src/adapters/omp.d.ts +11 -2
  425. package/dist/workspace-plugin/src/adapters/omp.d.ts.map +1 -1
  426. package/package.json +1 -1
  427. package/dist/asset-feeds-CXGQIDFR.js.map +0 -1
  428. package/dist/chunk-2F5AWQX5.js.map +0 -1
  429. package/dist/chunk-3SM2DL2T.js.map +0 -1
  430. package/dist/chunk-47U4GZ4M.js.map +0 -1
  431. package/dist/chunk-5LKOAX7I.js.map +0 -1
  432. package/dist/chunk-6O2X3GPW.js.map +0 -1
  433. package/dist/chunk-ALEYHUC5.js.map +0 -1
  434. package/dist/chunk-CGYEHQOX.js.map +0 -1
  435. package/dist/chunk-CJERAGFY.js.map +0 -1
  436. package/dist/chunk-CPSIPIX7.js.map +0 -1
  437. package/dist/chunk-D3B36CYC.js.map +0 -1
  438. package/dist/chunk-DZMNFCWB.js.map +0 -1
  439. package/dist/chunk-EDYHEMJA.js.map +0 -1
  440. package/dist/chunk-FH7W6TJ4.js.map +0 -1
  441. package/dist/chunk-GV4DZ6MT.js.map +0 -1
  442. package/dist/chunk-HZXUXHIV.js.map +0 -1
  443. package/dist/chunk-J4RBUFGM.js.map +0 -1
  444. package/dist/chunk-NWDSLXOX.js.map +0 -1
  445. package/dist/chunk-OBYKJB4U.js.map +0 -1
  446. package/dist/chunk-PBBPZYVG.js.map +0 -1
  447. package/dist/chunk-PMECEZK3.js.map +0 -1
  448. package/dist/chunk-R7FOF242.js +0 -59
  449. package/dist/chunk-R7FOF242.js.map +0 -1
  450. package/dist/chunk-R7NHYEJF.js.map +0 -1
  451. package/dist/chunk-RYYLMBA2.js +0 -392
  452. package/dist/chunk-RYYLMBA2.js.map +0 -1
  453. package/dist/chunk-SBSA3IQA.js.map +0 -1
  454. package/dist/chunk-VLTQGE2E.js.map +0 -1
  455. package/dist/chunk-WSBKB4CJ.js.map +0 -1
  456. package/dist/chunk-YOH2L76X.js +0 -505
  457. package/dist/chunk-YOH2L76X.js.map +0 -1
  458. package/dist/chunk-ZCAJZ4B2.js.map +0 -1
  459. package/dist/chunk-ZPWTOUTK.js.map +0 -1
  460. package/dist/flows-EQF2CH4U.js +0 -26
  461. package/dist/helpers-CFK6YP6R.js +0 -34
  462. package/dist/library-publish-53UTB3MB.js.map +0 -1
  463. package/dist/open-library-BOSPJVID.js +0 -40
  464. package/dist/open-registry-4FI7HKET.js +0 -32
  465. package/dist/paths-SUS4S4YT.js +0 -22
  466. package/dist/plugin-store-AGQDMING.js +0 -149
  467. package/dist/plugin-store-AGQDMING.js.map +0 -1
  468. package/dist/project-I55A4O2T.js +0 -41
  469. package/dist/skills-NUEN5NDX.js +0 -26
  470. package/dist/source-G2LV5LVD.js +0 -41
  471. package/dist/source-fetch-github-QN4LLTL5.js +0 -4
  472. package/dist/source-manifest-publish-6RM7SWLZ.js.map +0 -1
@@ -1,20 +1,20 @@
1
- import { unregisteredLibraryNames, renamedLibraryName, scanUnlistedAssets, getStoreManifestsDir, missingLibraryDirMessage } from './chunk-2F5AWQX5.js';
2
- import { readManifestSourceConfig, isManifestMode, discoverAssetsInTree } from './chunk-J4RBUFGM.js';
3
- import { installTargetOf, canonicalEntryRef, deployAll, removeAsset, diffDeployedAgent, deployedAssetDrift, createScaffold, installAgent } from './chunk-FH7W6TJ4.js';
1
+ import { unregisteredLibraryNames, renamedLibraryName, resolveConfig, RemoteCatalogSource, OfflineError, describeCatalogError, CatalogHttpError, scanUnlistedAssets, getStoreManifestsDir, missingLibraryDirMessage } from './chunk-DKGEV6SQ.js';
2
+ import { readManifestSourceConfig, discoverAssetsInTree, isManifestMode } from './chunk-NVO6WECE.js';
3
+ import { installTargetOf, canonicalEntryRef, deployedAssetDrift, deployAll, removeAsset, diffDeployedAgent, createScaffold, installAgent } from './chunk-5FYOM4RF.js';
4
4
  import { appendHistory, getRecentHistory, clearHistory } from './chunk-KTBKW2FI.js';
5
5
  import { commitChanges } from './chunk-UQ6LFBPZ.js';
6
- import { driverTargetSupportsAgents, CODEX_IDENTITY_DIR } from './chunk-HZXUXHIV.js';
7
- import { resolveConfiguredDriverTarget, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, buildLockFile, writeLock, readLock, verifyLock, mergeLockFile, extractForPatch, generatePatch, savePatch, applyPatch, computeHash } from './chunk-PBBPZYVG.js';
8
- import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-EDYHEMJA.js';
9
- import { deployedBase, deployedDir, isDeployed, deployedPaths } from './chunk-PMECEZK3.js';
10
- import { resolveSkWorkspaceConfig, effectiveAgentInstances, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, resolveAll, ensureRepo, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, readLinks, MAX_PRESET_DEPTH, PresetDepthError, DEFAULT_AGENT_INSTANCE_ID, resolveAgentDefinitionDir, storeManifestSlug } from './chunk-ALEYHUC5.js';
6
+ import { driverTargetSupportsAgents, CODEX_IDENTITY_DIR } from './chunk-4L4R5LV3.js';
7
+ import { resolveConfiguredDriverTarget, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, computeHash, buildLockFile, writeLock, readLock, verifyLock, mergeLockFile, extractForPatch, generatePatch, savePatch, applyPatch, LOCK_SCHEMA_VERSION } from './chunk-BF422IDP.js';
8
+ import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-QO7CR3KB.js';
9
+ import { deployedBase, deployedDir, isDeployed, deployedPaths } from './chunk-D54T2F54.js';
10
+ import { resolveSkWorkspaceConfig, effectiveAgentInstances, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, readLinks, isCommitOnRemote, resolveAll, agentSourceCacheDir, ensureRepo, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, MAX_PRESET_DEPTH, PresetDepthError, DEFAULT_AGENT_INSTANCE_ID, resolveAgentDefinitionDir, storeManifestSlug } from './chunk-L3ZGYSWY.js';
11
11
  import { globalSkaileDir, globalCacheRoot, migrateLegacyDir } from './chunk-L5VSIPQD.js';
12
- import { DRIVER_TARGETS } from './chunk-CPSIPIX7.js';
13
- import { loadSkPublishManifest } from './chunk-ZPWTOUTK.js';
14
- import { scanDirectory, parseRequires, dedupeRequirements } from './chunk-SBSA3IQA.js';
15
- import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr } from './chunk-BNMZVPYA.js';
12
+ import { DRIVER_TARGETS } from './chunk-IG5LZ3WU.js';
13
+ import { loadSkPublishManifest } from './chunk-IY5E7Y5W.js';
14
+ import { scanDirectory, parseFrontmatter, parseRequires, dedupeRequirements } from './chunk-M3P4BYRK.js';
15
+ import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr, parseDep } from './chunk-J4OYIYFQ.js';
16
16
  import { spawnSync } from 'child_process';
17
- import { existsSync, rmSync, readdirSync, lstatSync, unlinkSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
17
+ import { existsSync, rmSync, readdirSync, lstatSync, readFileSync, unlinkSync, mkdirSync, writeFileSync } from 'fs';
18
18
  import path, { resolve, dirname, sep, join, relative, posix } from 'path';
19
19
  import { gt } from 'semver';
20
20
  import { stringify, parse } from 'yaml';
@@ -401,6 +401,19 @@ function filesUnderManifestDir(paths, manifestRel) {
401
401
  const manifestDir = posix.dirname(manifestRel);
402
402
  return paths.map((p) => posix.relative(manifestDir, p)).filter((rel) => rel !== "" && !rel.startsWith(".."));
403
403
  }
404
+ function lockedAssetFiles(kind, files) {
405
+ const manifestRel = matchManifestPath(
406
+ kind,
407
+ files.map((f) => f.path)
408
+ ) ?? files[0]?.path;
409
+ if (!manifestRel) return [];
410
+ const manifestDir = posix.dirname(manifestRel);
411
+ return files.flatMap((f) => {
412
+ const rel = posix.relative(manifestDir, f.path);
413
+ return rel === "" || rel.startsWith("..") ? [] : [{ rel, sha256: f.sha256 }];
414
+ });
415
+ }
416
+ var GITHUB_REPO_URL = /github\.com[/:]/i;
404
417
  function indexLockByKindName(lock) {
405
418
  const lockByKindName = /* @__PURE__ */ new Map();
406
419
  for (const [key, entry] of Object.entries(lock?.assets ?? {})) {
@@ -435,6 +448,28 @@ function commitsBetween(repoDir, from, to, cache) {
435
448
  return count;
436
449
  }
437
450
  var COMMIT_ID = /^[0-9a-f]{7,64}$/;
451
+ function commitsTouching(repoDir, from, to, dir, cache) {
452
+ if (!COMMIT_ID.test(from) || !COMMIT_ID.test(to)) return null;
453
+ if (from === to) return 0;
454
+ const key = `${from}..${to} -- ${dir}`;
455
+ const hit = cache.get(key);
456
+ if (hit !== void 0) return hit;
457
+ const r = spawnSync("git", ["-C", repoDir, "rev-list", "--count", `${from}..${to}`, "--", dir], {
458
+ encoding: "utf8",
459
+ stdio: "pipe"
460
+ });
461
+ const n = r.status === 0 ? Number.parseInt(r.stdout.trim(), 10) : Number.NaN;
462
+ if (!Number.isFinite(n) || n < 0) return null;
463
+ cache.set(key, n);
464
+ return n;
465
+ }
466
+ function lockedAssetDir(kind, files) {
467
+ const manifestRel = matchManifestPath(
468
+ kind,
469
+ files.map((f) => f.path)
470
+ ) ?? files[0]?.path;
471
+ return manifestRel ? posix.dirname(manifestRel) : ".";
472
+ }
438
473
  function libraryDiskHashes(libPath, cache, registry) {
439
474
  let hashes = cache.get(libPath);
440
475
  if (!hashes) {
@@ -506,7 +541,7 @@ function newestLibraryDef(snap, libraryName, id) {
506
541
  }
507
542
  return best;
508
543
  }
509
- function libraryPreference(isDefaultLib) {
544
+ function libraryPreference(isDefaultLib, rank) {
510
545
  return (a, b) => {
511
546
  const va = coerceVersion(a.entry.version ?? "");
512
547
  const vb = coerceVersion(b.entry.version ?? "");
@@ -514,7 +549,9 @@ function libraryPreference(isDefaultLib) {
514
549
  if (gt(vb, va)) return 1;
515
550
  const da = isDefaultLib.get(a.library) ? 0 : 1;
516
551
  const db = isDefaultLib.get(b.library) ? 0 : 1;
517
- return da - db || a.library.localeCompare(b.library);
552
+ if (da !== db) return da - db;
553
+ const byRank = rank ? rank(a) - rank(b) : 0;
554
+ return byRank || a.library.localeCompare(b.library);
518
555
  };
519
556
  }
520
557
  function qualifyDepRef(ref, fallback) {
@@ -649,15 +686,18 @@ function withKeptLockEntries(lock, kept) {
649
686
  for (const s of kept.sources) if (!sources.has(s.url)) sources.set(s.url, s);
650
687
  return {
651
688
  ...lock,
652
- // v4 once a library-origin entry is present (see buildLockFile).
653
- schema_version: lock.schema_version === 4 || Object.values(kept.assets).some((e) => e.library) ? 4 : 3,
689
+ schema_version: LOCK_SCHEMA_VERSION,
654
690
  assets: { ...lock.assets, ...kept.assets },
655
691
  sources: [...sources.values()].sort((a, b) => a.url.localeCompare(b.url))
656
692
  };
657
693
  }
658
694
  function relockedRefs(prev, next) {
659
695
  if (!prev) return [];
660
- const fingerprint = (e) => [e.library?.version ?? "", e.library?.sha256 ?? e.sha256, e.source?.commit ?? ""].join("\0");
696
+ const fingerprint = (e, key) => [
697
+ e.library?.version ?? "",
698
+ e.library?.sha256 ?? e.sha256,
699
+ key.includes("#0.0.0-sha.") ? "" : e.source?.commit ?? ""
700
+ ].join("\0");
661
701
  const out = [];
662
702
  for (const [key, entry] of Object.entries(next.assets)) {
663
703
  if (entry.library?.installed) continue;
@@ -667,7 +707,8 @@ function relockedRefs(prev, next) {
667
707
  return o.kind === id.kind && o.name === id.name && o.publisher === id.publisher;
668
708
  });
669
709
  if (!before) continue;
670
- if (before[0] !== key || fingerprint(before[1]) !== fingerprint(entry)) out.push(key);
710
+ if (before[0] !== key || fingerprint(before[1], before[0]) !== fingerprint(entry, key))
711
+ out.push(key);
671
712
  }
672
713
  return out;
673
714
  }
@@ -793,6 +834,17 @@ var AssetManager = class {
793
834
  onLibraryCollision;
794
835
  /** Store URLs whose failed version lookup was already reported (one warning per URL). */
795
836
  warnedStoreVersionLookups = /* @__PURE__ */ new Set();
837
+ /** Stores a lookup could not reach (store URL -> one line why); `add` reports them instead of "not found". */
838
+ storeFailures = /* @__PURE__ */ new Map();
839
+ /** Sources a provenance walk had to skip (source URL → why); one warning per source. */
840
+ skippedSources = /* @__PURE__ */ new Map();
841
+ /** `onSourceError` of every provenance walk: name the source once, leave it out, go on. */
842
+ reportSourceError = (clone, err) => {
843
+ const why = err instanceof Error ? err.message : String(err);
844
+ if (this.skippedSources.has(clone.sourceUrl)) return;
845
+ this.skippedSources.set(clone.sourceUrl, why);
846
+ console.warn(`skaile: source ${clone.sourceUrl} skipped: ${why}`);
847
+ };
796
848
  constructor(opts) {
797
849
  this.projectDir = resolve(opts.projectDir);
798
850
  this.global = opts.global ?? false;
@@ -827,15 +879,27 @@ var AssetManager = class {
827
879
  return this.global ? globalSkaileDir() : this.projectDir;
828
880
  }
829
881
  /**
830
- * The harnesses a global deploy fans out to: the explicit `harnesses` override
831
- * (a `--harness` filter), else `resolveGlobalHarnesses()`. In project mode this
832
- * is exactly `[driverTarget]`, so the shared fan-out loop degenerates to the
882
+ * The harnesses a global deploy fans out to: the explicit `harnesses` override (a `--harness`
883
+ * filter), else the explicit `global_harnesses:` of `~/.skaile/skaile.yaml`, else every harness
884
+ * whose root dir exists under `~` plus the harness the project is configured for (a project on
885
+ * a harness whose dir does not exist yet still gets its user-scope assets). In project mode
886
+ * this is exactly `[driverTarget]`, so the shared fan-out loop degenerates to the
833
887
  * single-target path.
834
888
  */
835
889
  targetHarnesses() {
836
890
  if (!this.global) return [this.driverTarget];
837
891
  if (this.harnessesOverride && this.harnessesOverride.length > 0) return this.harnessesOverride;
838
- return resolveGlobalHarnesses();
892
+ const resolved = resolveGlobalHarnesses();
893
+ if (resolveGlobalSkWorkspaceConfig().global_harnesses?.length) return resolved;
894
+ const configured = resolveConfiguredDriverTarget(this.projectDir);
895
+ return configured && !resolved.includes(configured) ? [...resolved, configured] : resolved;
896
+ }
897
+ /**
898
+ * The harnesses `add` / `install` deploy into: `[driverTarget]` for a project, the global
899
+ * harness set (see {@link AssetManager.targetHarnesses}) for a global manager.
900
+ */
901
+ deployTargets() {
902
+ return this.targetHarnesses();
839
903
  }
840
904
  get storeCacheDir() {
841
905
  if (this.global) return join(globalCacheRoot(), "store");
@@ -942,7 +1006,11 @@ var AssetManager = class {
942
1006
  for (const s of sources) {
943
1007
  const slug = sourceCacheKey(s.url);
944
1008
  if (repositories[slug]) continue;
945
- repositories[slug] = { path: join(sourcesDir, slug), url: s.url };
1009
+ repositories[slug] = {
1010
+ path: join(sourcesDir, slug),
1011
+ url: s.url,
1012
+ ...s.publisher ? { publisher: s.publisher } : {}
1013
+ };
946
1014
  }
947
1015
  const factory = resolveFactorySource();
948
1016
  const factoryUrl = normalizeRepoUrl(FACTORY_SOURCE_URL);
@@ -970,6 +1038,7 @@ var AssetManager = class {
970
1038
  sourceUrl: decl.url ?? localPath,
971
1039
  commit,
972
1040
  tag: decl.branch,
1041
+ ...decl.publisher ? { publisher: decl.publisher } : {},
973
1042
  // A curated store manifest (`source manifest init` → the flat
974
1043
  // `~/.skaile/store/manifests/<slug>.yaml`) is the authoritative inventory
975
1044
  // for a foreign source. Point the walker at it so `add`/resolve honor the
@@ -1039,6 +1108,31 @@ var AssetManager = class {
1039
1108
  if (c.homepage != null) entry.homepage = c.homepage;
1040
1109
  return entry;
1041
1110
  }
1111
+ /**
1112
+ * The {@link ProvenanceCandidate} a source- or store-origin lock entry stands for: what a
1113
+ * deploy needs to restore the asset from the commit the lock names (`files[]` is the asset's
1114
+ * whole file set). `null` for a library-origin entry or a key that is not a canonical ref.
1115
+ * The source URL is the declared source's own spelling (the bundled factory tree and a
1116
+ * `sources:` entry match their declaration by it).
1117
+ */
1118
+ lockedCandidate(key, entry, repositories) {
1119
+ if (!entry.source) return null;
1120
+ const { publisher, kind, name, version } = parseCanonicalLockKey(key);
1121
+ if (!publisher || !kind || !name) return null;
1122
+ const url = entry.source.url;
1123
+ const factory = Object.values(repositories).find((d) => d.factory);
1124
+ const declared = factory?.url !== void 0 && normalizeRepoUrl(url) === normalizeRepoUrl(factory.url) ? factory : repositories[sourceCacheKey(url)];
1125
+ return {
1126
+ publisher,
1127
+ kind,
1128
+ name,
1129
+ version: version ?? "",
1130
+ sourceUrl: declared?.url ?? url,
1131
+ commit: entry.source.commit,
1132
+ files: entry.files,
1133
+ sha256: entry.sha256
1134
+ };
1135
+ }
1042
1136
  /**
1043
1137
  * Resolve refs the source/store pass could not against the user's registered
1044
1138
  * **libraries** (local authoring places). Each library dir is scanned on disk
@@ -1071,6 +1165,7 @@ var AssetManager = class {
1071
1165
  const { byKey, isDefaultLib, libraryDir } = scan;
1072
1166
  const entries = [];
1073
1167
  const fileSets = /* @__PURE__ */ new Map();
1168
+ const diskHashes = /* @__PURE__ */ new Map();
1074
1169
  let snap;
1075
1170
  const allCandidates = [...byKey.values()].flat();
1076
1171
  for (const ref of missing) {
@@ -1098,23 +1193,34 @@ var AssetManager = class {
1098
1193
  }
1099
1194
  let candidates = pool.filter((c) => !pin || matchPin(pin, c.entry.version ?? ""));
1100
1195
  let lockedLibrary;
1196
+ const lockedMap = opts.preferLocked?.libraries ?? opts.lockedLibraries;
1101
1197
  if (parsed.publisher) {
1102
- lockedLibrary = opts.lockedLibraries?.get(
1198
+ lockedLibrary = lockedMap?.get(
1103
1199
  `${parsed.kind}:${parsed.publisher.replace(/^@/, "")}/${parsed.name}`
1104
1200
  );
1105
1201
  } else {
1106
- const same = [...opts.lockedLibraries ?? []].filter(([k]) => {
1202
+ const same = [...lockedMap ?? []].filter(([k]) => {
1107
1203
  const slash = k.indexOf("/");
1108
1204
  return k.startsWith(`${parsed.kind}:`) && k.slice(slash + 1) === parsed.name;
1109
1205
  });
1110
1206
  if (same.length === 1) lockedLibrary = same[0][1];
1111
1207
  }
1112
- if (lockedLibrary) {
1208
+ if (lockedLibrary && !opts.preferLocked) {
1113
1209
  const inLocked = candidates.filter((c) => c.library === lockedLibrary);
1114
1210
  if (inLocked.length > 0) candidates = inLocked;
1115
1211
  }
1116
1212
  if (candidates.length === 0) continue;
1117
- candidates.sort(libraryPreference(isDefaultLib));
1213
+ const prefer = opts.preferLocked ? (c) => {
1214
+ if (lockedLibrary && c.library === lockedLibrary) return 0;
1215
+ const id = `${c.entry.kind}:${(c.entry.publisher ?? "").replace(/^@/, "")}/${c.entry.name}`;
1216
+ const lockedSha = opts.preferLocked?.shas.get(id);
1217
+ const libPath = libraryDir.get(c.library);
1218
+ const onDisk = lockedSha && libPath ? libraryDiskHashes(libPath, diskHashes, this.registry).get(
1219
+ `${c.entry.kind}:${c.entry.name}`
1220
+ ) : void 0;
1221
+ return onDisk !== void 0 && onDisk === lockedSha ? 1 : 2;
1222
+ } : void 0;
1223
+ candidates.sort(libraryPreference(isDefaultLib, prefer));
1118
1224
  const hit = candidates[0];
1119
1225
  if (!opts.quiet && !opts.library) {
1120
1226
  this.warnLibraryCollision(
@@ -1255,7 +1361,8 @@ var AssetManager = class {
1255
1361
  const cloneDirs = new Set(clones.map((c) => resolve(c.localPath)));
1256
1362
  const index = await buildProvenanceIndex(clones, {
1257
1363
  projectDir: this.projectDir,
1258
- knownKinds: this.knownKinds
1364
+ knownKinds: this.knownKinds,
1365
+ onSourceError: this.reportSourceError
1259
1366
  });
1260
1367
  const factoryUrl = normalizeRepoUrl(FACTORY_SOURCE_URL);
1261
1368
  const hasFactory = Object.values(repositories).some((d) => d.factory);
@@ -1464,6 +1571,34 @@ var AssetManager = class {
1464
1571
  publisher: ref?.publisher ?? entry.publisher?.replace(/^@/, "")
1465
1572
  };
1466
1573
  }
1574
+ /**
1575
+ * Refuse to lock a source commit another machine cannot check out. A commit made in the clone
1576
+ * itself (or one `source sync` could not fast-forward past) is in no remote branch: the lock
1577
+ * would name bytes nobody else has, and `install --locked` there could not restore them.
1578
+ * Linked (dev-override) and user-owned local sources are never checked: their lock is
1579
+ * machine-local by choice.
1580
+ *
1581
+ * @param resolved - Candidates about to be locked.
1582
+ * @param repositories - Source declarations of the project.
1583
+ * @throws With `<url> clone has unpublished commit <sha>` and the way out.
1584
+ */
1585
+ assertSourceCommitsPublished(resolved, repositories) {
1586
+ const links = readLinks(this.projectDir);
1587
+ const checked = /* @__PURE__ */ new Set();
1588
+ for (const c of resolved) {
1589
+ if (!c.commit || /^0+$/.test(c.commit) || checked.has(`${c.sourceUrl}@${c.commit}`)) continue;
1590
+ checked.add(`${c.sourceUrl}@${c.commit}`);
1591
+ const hit = Object.entries(repositories).find(
1592
+ ([, d]) => d.url !== void 0 && !d.factory && d.url === c.sourceUrl
1593
+ );
1594
+ if (!hit || links[hit[0]]) continue;
1595
+ const dir = this.resolveRepoDir(hit[1], hit[0]);
1596
+ if (!dir || isCommitOnRemote(dir, c.commit)) continue;
1597
+ throw new Error(
1598
+ `${c.sourceUrl} clone has unpublished commit ${c.commit.slice(0, 7)} - push it, or reset the clone (git -C ${dir} reset --hard origin/${hit[1].branch ?? "main"}) - nothing was locked`
1599
+ );
1600
+ }
1601
+ }
1467
1602
  /**
1468
1603
  * Refuse assets of one kind and name from different publishers: they deploy into the
1469
1604
  * same folder, so the later one would silently overwrite the earlier. Throws one line
@@ -1505,6 +1640,83 @@ var AssetManager = class {
1505
1640
  );
1506
1641
  }
1507
1642
  }
1643
+ /**
1644
+ * Refuse to deploy over a folder (or agent file) the project did not put there: it is on disk,
1645
+ * but no lock entry of the same kind and name owns it, so it is the user's own work and the
1646
+ * deploy would replace it and `remove` would delete it. Throws one line naming the folder.
1647
+ *
1648
+ * A folder the deploy would rewrite with the same content is adopted silently (the way back
1649
+ * from `asset import`: the project's own copy is what the library now holds): every file in
1650
+ * it is shipped by the asset with the same bytes, or the same body and an asset frontmatter
1651
+ * that only adds to the folder's (import normalizes it). Nothing is lost then.
1652
+ *
1653
+ * @param incoming - Assets about to be deployed, with the entry whose bytes would be written
1654
+ * when there is one.
1655
+ * @param owned - Assets the lock holds; one of the same kind and name, from any publisher,
1656
+ * owns the folder (a publisher clash is {@link assertNoFolderCollision}'s refusal).
1657
+ */
1658
+ assertNoUnownedFolder(incoming, owned) {
1659
+ for (const { id: a, entry } of incoming) {
1660
+ if (!a.kind || !a.name) continue;
1661
+ const component = installTargetOf(this.registry, a.kind);
1662
+ if (!component) continue;
1663
+ const isOwned = owned.some(
1664
+ (o) => !!o.kind && o.name === a.name && installTargetOf(this.registry, o.kind) === component
1665
+ );
1666
+ if (isOwned) continue;
1667
+ for (const target of this.targetHarnesses()) {
1668
+ const held = deployedPaths(component, a.name, target, this.global, this.projectDir).find(
1669
+ (p) => existsSync(p)
1670
+ );
1671
+ if (!held) continue;
1672
+ if (entry && this.deployWouldOnlyRewriteSame(entry, target)) continue;
1673
+ const shown = this.global ? held : relative(this.projectDir, held);
1674
+ throw new Error(
1675
+ `${assetRefToStr({ kind: a.kind, name: a.name, publisher: a.publisher })} would overwrite ${shown}, which no lock entry owns (your own files?) \u2014 move it away, or pass --force to replace it`
1676
+ );
1677
+ }
1678
+ }
1679
+ }
1680
+ /**
1681
+ * Whether deploying `entry` over the folder already in `target` loses nothing: the folder
1682
+ * holds no file the asset does not ship, and each of its files equals the asset's, or is a
1683
+ * markdown file with the same body whose frontmatter the asset's only extends.
1684
+ */
1685
+ deployWouldOnlyRewriteSame(entry, target) {
1686
+ const drift = deployedAssetDrift(entry, {
1687
+ registry: this.registry,
1688
+ driverTarget: target,
1689
+ global: this.global,
1690
+ cwd: this.projectDir
1691
+ });
1692
+ if (!drift || drift.extra.length > 0) return false;
1693
+ if (drift.modified.length === 0) return true;
1694
+ const component = installTargetOf(this.registry, entry.kind);
1695
+ if (!component) return false;
1696
+ const dest = deployedDir(component, entry.name, target, this.global, this.projectDir);
1697
+ let assetRoot;
1698
+ try {
1699
+ assetRoot = lstatSync(entry.source).isDirectory() ? entry.source : dirname(entry.source);
1700
+ } catch {
1701
+ return false;
1702
+ }
1703
+ return drift.modified.every((rel) => {
1704
+ if (!/\.md$/i.test(rel)) return false;
1705
+ try {
1706
+ const mine = parseFrontmatter(readFileSync(join(dest, rel), "utf8"));
1707
+ const theirs = parseFrontmatter(readFileSync(join(assetRoot, rel), "utf8"));
1708
+ if (mine.body !== theirs.body) return false;
1709
+ const covered = (have, want) => Object.entries(have).every(([k, v]) => {
1710
+ const w = want[k];
1711
+ if (JSON.stringify(v) === JSON.stringify(w)) return true;
1712
+ return k === "metadata" && !!v && typeof v === "object" && !!w && typeof w === "object" && covered(v, w);
1713
+ });
1714
+ return covered(mine.data, theirs.data);
1715
+ } catch {
1716
+ return false;
1717
+ }
1718
+ });
1719
+ }
1508
1720
  /**
1509
1721
  * Open the local index and snapshot its libraries + asset definitions.
1510
1722
  * Best-effort: no index file (never indexed), or any open/guard failure,
@@ -1771,6 +1983,14 @@ var AssetManager = class {
1771
1983
  const found = this.lockedLibrary(origin, snap);
1772
1984
  return found.state === "ok" ? found.path : null;
1773
1985
  }
1986
+ /**
1987
+ * The `kind:@publisher/name` identities the lock holds for one `kind` and `name`, whatever
1988
+ * their publisher. `diff` uses it to accept a ref without a publisher only when it names
1989
+ * exactly one locked asset.
1990
+ */
1991
+ lockedRefsNamed(kind, name) {
1992
+ return Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey).filter((id) => id.kind === kind && id.name === name).map((id) => id.publisher ? `${kind}:@${id.publisher}/${name}` : `${kind}:${name}`);
1993
+ }
1774
1994
  /**
1775
1995
  * Where each library-origin lock entry of this project resolves on this machine: identity
1776
1996
  * `kind:publisher/name` (no scope sigil, no version) → the name the locked library is
@@ -1800,6 +2020,19 @@ var AssetManager = class {
1800
2020
  }
1801
2021
  return out;
1802
2022
  }
2023
+ /**
2024
+ * What `update` prefers when libraries tie: the library each lock entry resolves to here
2025
+ * ({@link lockedLibraryNames}, a `library rename` followed) and the sha256 it locked.
2026
+ */
2027
+ async lockedPreference() {
2028
+ const shas = /* @__PURE__ */ new Map();
2029
+ for (const [key, e] of Object.entries(this.tryReadLock()?.assets ?? {})) {
2030
+ if (!e.library?.sha256 || e.library.installed) continue;
2031
+ const { publisher, kind, name } = parseCanonicalLockKey(key);
2032
+ if (publisher && kind && name) shas.set(`${kind}:${publisher}/${name}`, e.library.sha256);
2033
+ }
2034
+ return { libraries: await this.lockedLibraryNames(), shas };
2035
+ }
1803
2036
  // ── Store fetch-then-deploy ────────────────────────────────────────────
1804
2037
  /** A candidate's stable identity key (`<publisher>/<kind>:<name>@<version>`). */
1805
2038
  candidateKey(c) {
@@ -1865,6 +2098,7 @@ var AssetManager = class {
1865
2098
  const resolved = [];
1866
2099
  const overridesApplied = /* @__PURE__ */ new Set();
1867
2100
  const presets = [];
2101
+ const requiredBy = /* @__PURE__ */ new Map();
1868
2102
  const lib = { entries: [], resolved: /* @__PURE__ */ new Set(), libraryOf: /* @__PURE__ */ new Map() };
1869
2103
  const missing = /* @__PURE__ */ new Set();
1870
2104
  const seen = /* @__PURE__ */ new Set();
@@ -1913,6 +2147,13 @@ var AssetManager = class {
1913
2147
  return depId !== null && declaredById.get(depId) || dep;
1914
2148
  })
1915
2149
  );
2150
+ if (e.kind !== "preset") {
2151
+ for (const dep of deps2) {
2152
+ const depId = refIdentity(dep);
2153
+ if (depId !== null && declaredById.has(depId)) continue;
2154
+ requiredBy.set(dep, [...requiredBy.get(dep) ?? [], canonicalEntryRef(e)]);
2155
+ }
2156
+ }
1916
2157
  }
1917
2158
  for (const r of hit.resolved) lib.resolved.add(r);
1918
2159
  return next;
@@ -1937,7 +2178,8 @@ var AssetManager = class {
1937
2178
  );
1938
2179
  const hit = await this.resolveLibraryEntries([...libraryTried], {
1939
2180
  quiet: !opts.warnCollisions,
1940
- lockedLibraries: opts.lockedLibraries
2181
+ lockedLibraries: opts.lockedLibraries,
2182
+ preferLocked: opts.preferLocked
1941
2183
  });
1942
2184
  const next = absorb(hit);
1943
2185
  const rest = fresh.filter((ref) => !hit.resolved.has(ref));
@@ -1954,7 +2196,11 @@ var AssetManager = class {
1954
2196
  presets.push(...r.presets);
1955
2197
  const hit2 = await this.resolveLibraryEntries(
1956
2198
  r.missing.filter((m) => !libraryTried.has(m)),
1957
- { quiet: !opts.warnCollisions, lockedLibraries: opts.lockedLibraries }
2199
+ {
2200
+ quiet: !opts.warnCollisions,
2201
+ lockedLibraries: opts.lockedLibraries,
2202
+ preferLocked: opts.preferLocked
2203
+ }
1958
2204
  );
1959
2205
  next.push(...absorb(hit2));
1960
2206
  for (const m of r.missing) if (!hit2.resolved.has(m)) missing.add(m);
@@ -1965,7 +2211,37 @@ var AssetManager = class {
1965
2211
  const id = refIdentity(m);
1966
2212
  return !lib.resolved.has(m) && !(id !== null && covered.has(id));
1967
2213
  });
1968
- return { resolved, missing: stillMissing, overridesApplied, lib, presets };
2214
+ this.keepUnchangedSourceVersions(resolved, [...deps, ...opts.declaredRefs ?? []]);
2215
+ return { resolved, missing: stillMissing, overridesApplied, lib, presets, requiredBy };
2216
+ }
2217
+ /**
2218
+ * A source asset without a declared version is keyed `0.0.0-sha.<repo commit>`, so every
2219
+ * commit of its repo would re-key (and re-lock, and report as updated) every asset of
2220
+ * that repo, changed or not. Keep the locked key and version of an asset whose files hash
2221
+ * to what the lock holds: `update` then re-locks only what changed, as `outdated` lists.
2222
+ * The commit stays the clone's, so the lock's `sources:` row still names the bytes' commit.
2223
+ * A ref the user pinned (`#<version>`) keeps the version it names.
2224
+ */
2225
+ keepUnchangedSourceVersions(resolved, requested) {
2226
+ const prev = this.tryReadLock();
2227
+ if (!prev) return;
2228
+ const pinned = /* @__PURE__ */ new Set();
2229
+ for (const ref of requested) {
2230
+ const id = refIdentity(ref);
2231
+ if (id !== null && ref.includes("#")) pinned.add(id);
2232
+ }
2233
+ for (const c of resolved) {
2234
+ if (!c.version.startsWith("0.0.0-sha.")) continue;
2235
+ const id = `${c.publisher}/${c.kind}:${c.name}`;
2236
+ if (pinned.has(id)) continue;
2237
+ for (const [key, entry] of Object.entries(prev.assets)) {
2238
+ const o = parseCanonicalLockKey(key);
2239
+ if (o.kind !== c.kind || o.name !== c.name || o.publisher !== c.publisher) continue;
2240
+ if (!o.version?.startsWith("0.0.0-sha.")) continue;
2241
+ if (entry.source?.url === c.sourceUrl && entry.sha256 === c.sha256) c.version = o.version;
2242
+ break;
2243
+ }
2244
+ }
1969
2245
  }
1970
2246
  /** The catalog fetcher to use: an injected one, else built from `stores`. */
1971
2247
  storeFetcherFor(stores) {
@@ -1980,8 +2256,8 @@ var AssetManager = class {
1980
2256
  let url = this.catalogUrlOverride;
1981
2257
  if (url === void 0) {
1982
2258
  try {
1983
- const { resolveConfig } = await import('./library/index.js');
1984
- url = resolveConfig({ projectDir: this.projectDir }).catalog.url;
2259
+ const { resolveConfig: resolveConfig2 } = await import('./library/index.js');
2260
+ url = resolveConfig2({ projectDir: this.projectDir }).catalog.url;
1985
2261
  } catch {
1986
2262
  return [];
1987
2263
  }
@@ -2039,13 +2315,31 @@ var AssetManager = class {
2039
2315
  // from source.url@commit and ignores it, so "" is inert.
2040
2316
  tier: ""
2041
2317
  };
2042
- const { installPath } = await installFromManifest({
2043
- manifest,
2044
- libraryRoot: this.storeCacheDir,
2045
- targetDir,
2046
- fetcher: this.injectedAssetFetcher
2318
+ const root = commonDirPrefix(c.files.map((f) => f.path));
2319
+ const intact = c.files.every((f) => {
2320
+ const rel = root && f.path.startsWith(`${root}/`) ? f.path.slice(root.length + 1) : f.path;
2321
+ try {
2322
+ return computeHash(join(targetDir, rel)) === f.sha256;
2323
+ } catch {
2324
+ return false;
2325
+ }
2047
2326
  });
2048
- staged.set(this.candidateKey(c), join(installPath, this.stagedManifestRel(c)));
2327
+ if (intact) {
2328
+ staged.set(this.candidateKey(c), join(targetDir, this.stagedManifestRel(c)));
2329
+ continue;
2330
+ }
2331
+ try {
2332
+ const { installPath } = await installFromManifest({
2333
+ manifest,
2334
+ libraryRoot: this.storeCacheDir,
2335
+ targetDir,
2336
+ fetcher: this.injectedAssetFetcher
2337
+ });
2338
+ staged.set(this.candidateKey(c), join(installPath, this.stagedManifestRel(c)));
2339
+ } catch (err) {
2340
+ const reason = err instanceof Error ? err.message : String(err);
2341
+ throw new Error(`${manifest.ref} (${c.sourceUrl} at ${c.commit.slice(0, 7)}): ${reason}`);
2342
+ }
2049
2343
  }
2050
2344
  return staged;
2051
2345
  }
@@ -2151,26 +2445,52 @@ var AssetManager = class {
2151
2445
  };
2152
2446
  }
2153
2447
  }
2154
- const cloneError = this.ensureSourceClones(repositories, sources);
2448
+ const cloneError = this.ensureSourceClones(
2449
+ repositories,
2450
+ sources,
2451
+ opts?.moveLibraries ? void 0 : lockForLibraries
2452
+ );
2155
2453
  if (cloneError) return cloneError;
2156
2454
  const provenanceIndex = await buildProvenanceIndex(this.buildClones(repositories), {
2157
2455
  projectDir: this.projectDir,
2158
- knownKinds: this.knownKinds
2456
+ knownKinds: this.knownKinds,
2457
+ onSourceError: this.reportSourceError
2458
+ });
2459
+ const { resolved, missing, overridesApplied, lib, presets, requiredBy } = await this.resolveLibraryFirst(dependencies, {
2460
+ provenanceIndex,
2461
+ overrides,
2462
+ stores,
2463
+ declaredRefs: dependencies,
2464
+ // `install` restores what the lock recorded: a changed default library or a second
2465
+ // library holding the same ref does not move a locked asset. `update` re-resolves.
2466
+ ...opts?.moveLibraries ? { preferLocked: await this.lockedPreference() } : { lockedLibraries: await this.lockedLibraryNames() }
2159
2467
  });
2160
- const { resolved, missing, overridesApplied, lib, presets } = await this.resolveLibraryFirst(
2161
- dependencies,
2162
- {
2163
- provenanceIndex,
2164
- overrides,
2165
- stores,
2166
- declaredRefs: dependencies,
2167
- // `install` restores what the lock recorded: a changed default library or a second
2168
- // library holding the same ref does not move a locked asset. `update` re-resolves.
2169
- ...opts?.moveLibraries ? {} : { lockedLibraries: await this.lockedLibraryNames() }
2170
- }
2171
- );
2172
2468
  this.assertNoFolderCollision([...resolved, ...lib.entries.map((e) => this.entryIdentity(e))]);
2469
+ this.assertSourceCommitsPublished(resolved, repositories);
2173
2470
  const stillMissing = missing.filter((m) => !lib.resolved.has(m));
2471
+ const lockedKeys = new Set(Object.keys(this.tryReadLock()?.assets ?? {}));
2472
+ const unmetByNew = /* @__PURE__ */ new Map();
2473
+ for (const m of stillMissing) {
2474
+ const newcomers = (requiredBy.get(m) ?? []).filter((parent) => !lockedKeys.has(parent));
2475
+ if (newcomers.length > 0) unmetByNew.set(m, newcomers);
2476
+ }
2477
+ if (unmetByNew.size > 0) {
2478
+ const hints = {};
2479
+ for (const [m, parents] of unmetByNew) {
2480
+ const requirer = parents.map((p) => p.split("#")[0]).join(", ");
2481
+ const unreachable = [...this.storeFailures.values()];
2482
+ hints[m] = unreachable.length > 0 ? ` is required by ${requirer} (store unreachable, so it was not looked up: ${unreachable.join("; ")} \u2014 check the URL with \`skaile catalog test\`) \u2014 nothing was installed` : ` is required by ${requirer} (not found \u2014 ${REGISTER_HOLDER}, or drop ${requirer} with \`skaile remove ${parents[0].split("#")[0]}\`) \u2014 nothing was installed`;
2483
+ }
2484
+ return {
2485
+ deployed: [],
2486
+ removed: [],
2487
+ missing: [...unmetByNew.keys()],
2488
+ missingHints: hints,
2489
+ lockWritten: false,
2490
+ npmInstalled: [],
2491
+ npmFailed: []
2492
+ };
2493
+ }
2174
2494
  const missingHints = await this.publisherChangeHints(stillMissing);
2175
2495
  const prevLock = this.tryReadLock();
2176
2496
  const kept = keptLockEntries(prevLock, stillMissing);
@@ -2211,7 +2531,7 @@ var AssetManager = class {
2211
2531
  let relocked = [];
2212
2532
  let moved = [];
2213
2533
  if (lockWanted) {
2214
- const lockData = withKeptLockEntries(freshLock, kept);
2534
+ const lockData = this.withRenderedAgents(withKeptLockEntries(freshLock, kept));
2215
2535
  relocked = relockedRefs(prevLock, lockData);
2216
2536
  moved = libraryMoves(prevLock, libraryLock);
2217
2537
  lockWritten = writeLock(this.lockPath, lockData);
@@ -2273,7 +2593,8 @@ var AssetManager = class {
2273
2593
  const { kind, name, publisher } = id;
2274
2594
  const component = kind ? this.installTarget(kind) : void 0;
2275
2595
  if (!kind || !name || !component) return [];
2276
- const dir = deployedDir(component, name, this.driverTarget, this.global, this.projectDir);
2596
+ const keptAgent = kind === "agent" && !this.global ? join(agentSourceCacheDir(this.projectDir), name) : null;
2597
+ const dir = keptAgent && existsSync(keptAgent) ? keptAgent : deployedDir(component, name, this.driverTarget, this.global, this.projectDir);
2277
2598
  if (!existsSync(dir)) return [];
2278
2599
  try {
2279
2600
  const scanned = await scanDirectory(dir, publisher ?? "", { knownKinds: this.knownKinds });
@@ -2288,13 +2609,25 @@ var AssetManager = class {
2288
2609
  * {@link InstallResult} describing the failed source on the first error, or
2289
2610
  * `null` when every clone succeeds.
2290
2611
  */
2291
- ensureSourceClones(repositories, sources) {
2612
+ ensureSourceClones(repositories, sources, lock) {
2292
2613
  const pinBySlug = pinsBySlug(sources);
2614
+ const lockedCommit = /* @__PURE__ */ new Map();
2615
+ for (const s of lock?.sources ?? []) {
2616
+ if (!/^0*$/.test(s.commit)) lockedCommit.set(sourceCacheKey(s.url), s.commit);
2617
+ }
2293
2618
  for (const [name, decl] of Object.entries(repositories)) {
2294
2619
  try {
2620
+ const declaredPin = pinBySlug.get(name);
2621
+ let locked = decl.url && !decl.factory ? lockedCommit.get(name) : void 0;
2622
+ if (locked && declaredPin === void 0) {
2623
+ const dir = this.resolveRepoDir(decl, name);
2624
+ const head = dir ? getRepoCommit(dir) : void 0;
2625
+ if (dir && head && head !== locked && !isCommitOnRemote(dir, head)) locked = void 0;
2626
+ }
2295
2627
  ensureRepo(decl, name, this.reposDir, {
2296
2628
  projectDir: this.projectDir,
2297
- pin: pinBySlug.get(name)
2629
+ pin: declaredPin ?? locked,
2630
+ ...declaredPin === void 0 && locked ? { strictPin: true } : {}
2298
2631
  });
2299
2632
  } catch (err) {
2300
2633
  return {
@@ -2397,13 +2730,33 @@ var AssetManager = class {
2397
2730
  return null;
2398
2731
  }
2399
2732
  }
2733
+ /**
2734
+ * A catalog client for `storeUrl` that honours `catalog.cache_ttl` (`0` = air-gapped: no
2735
+ * network, so every lookup that is not cached throws `OfflineError`).
2736
+ */
2737
+ remoteStore(storeUrl) {
2738
+ let cacheTtlMs;
2739
+ try {
2740
+ cacheTtlMs = resolveConfig({ projectDir: this.projectDir }).catalog.cache_ttl * 1e3;
2741
+ } catch {
2742
+ }
2743
+ return new RemoteCatalogSource({ baseUrl: storeUrl, cacheTtlMs });
2744
+ }
2745
+ /**
2746
+ * Remember why a store could not be asked (store URL → one line without a JS error class
2747
+ * name), so `add` can say `store unreachable` instead of a bare `Asset not found`.
2748
+ */
2749
+ noteStoreFailure(storeUrl, err) {
2750
+ const text = err instanceof OfflineError ? `${storeUrl}: air-gapped (catalog.cache_ttl: 0), the store was not asked` : describeCatalogError(err, storeUrl);
2751
+ this.storeFailures.set(storeUrl, text);
2752
+ return text;
2753
+ }
2400
2754
  /** Build a store fetcher from the configured stores, or undefined when none. */
2401
2755
  buildStoreFetcher(stores) {
2402
2756
  if (stores.length === 0) return void 0;
2403
2757
  return {
2404
2758
  getInstallManifest: async (storeUrl, ref) => {
2405
- const { RemoteCatalogSource, CatalogHttpError } = await import('./library/index.js');
2406
- const src = new RemoteCatalogSource({ baseUrl: storeUrl });
2759
+ const src = this.remoteStore(storeUrl);
2407
2760
  try {
2408
2761
  const m = await src.getInstallManifest(ref);
2409
2762
  let deps;
@@ -2416,7 +2769,7 @@ var AssetManager = class {
2416
2769
  else if (deps === void 0)
2417
2770
  gap = `has a cached catalog row for ${ref} without dependencies`;
2418
2771
  } catch (err) {
2419
- gap = `dependency lookup for ${ref} failed \u2014 ${err}`;
2772
+ gap = `dependency lookup for ${ref} failed \u2014 ${describeCatalogError(err, storeUrl)}`;
2420
2773
  }
2421
2774
  if (gap) {
2422
2775
  console.warn(`skaile: store ${storeUrl} ${gap}; installing without its dependencies`);
@@ -2430,23 +2783,23 @@ var AssetManager = class {
2430
2783
  };
2431
2784
  } catch (err) {
2432
2785
  if (err instanceof CatalogHttpError && err.status === 404) return null;
2786
+ this.noteStoreFailure(storeUrl, err);
2433
2787
  throw err;
2434
2788
  }
2435
2789
  },
2436
2790
  getCanonicalDigest: async (storeUrl, ref) => {
2437
- const { RemoteCatalogSource } = await import('./library/index.js');
2438
- const src = new RemoteCatalogSource({ baseUrl: storeUrl });
2791
+ const src = this.remoteStore(storeUrl);
2439
2792
  return src.getCanonicalDigest(ref);
2440
2793
  },
2441
2794
  listVersions: async (storeUrl, ref) => {
2442
- const { RemoteCatalogSource } = await import('./library/index.js');
2443
- const src = new RemoteCatalogSource({ baseUrl: storeUrl });
2795
+ const src = this.remoteStore(storeUrl);
2444
2796
  try {
2445
2797
  return await src.listVersions(ref);
2446
2798
  } catch (err) {
2799
+ const text = this.noteStoreFailure(storeUrl, err);
2447
2800
  if (!this.warnedStoreVersionLookups.has(storeUrl)) {
2448
2801
  this.warnedStoreVersionLookups.add(storeUrl);
2449
- console.warn(`skaile: store ${storeUrl} version lookup for ${ref} failed \u2014 ${err}`);
2802
+ console.warn(`skaile: store lookup of ${ref} failed: ${text}`);
2450
2803
  }
2451
2804
  return [];
2452
2805
  }
@@ -2522,20 +2875,46 @@ var AssetManager = class {
2522
2875
  this.assertNoFolderCollision(Object.keys(lock.assets).map(parseCanonicalLockKey));
2523
2876
  const declBySlug = new Map(Object.entries(repositories));
2524
2877
  const factoryUrl = normalizeRepoUrl(FACTORY_SOURCE_URL);
2525
- const factoryDir = Object.values(repositories).find((d) => d.factory)?.path ?? null;
2878
+ const factoryDecl = Object.values(repositories).find((d) => d.factory);
2879
+ const factoryDir = factoryDecl?.path ?? null;
2880
+ const isFactoryUrl = (url) => factoryDir !== null && normalizeRepoUrl(url) === factoryUrl;
2881
+ const unavailable = [];
2526
2882
  for (const src of lock.sources) {
2527
- if (factoryDir && normalizeRepoUrl(src.url) === factoryUrl) continue;
2883
+ if (isFactoryUrl(src.url)) continue;
2528
2884
  const slug = sourceCacheKey(src.url);
2529
- const decl = declBySlug.get(slug) ?? { url: src.url };
2530
- ensureRepo(decl, slug, this.reposDir, { projectDir: this.projectDir, pin: src.commit });
2885
+ const declared = declBySlug.get(slug);
2886
+ if (!declared && GITHUB_REPO_URL.test(src.url)) continue;
2887
+ try {
2888
+ const dir = ensureRepo(declared ?? { url: src.url }, slug, this.reposDir, {
2889
+ projectDir: this.projectDir,
2890
+ // A lock restore deploys the pinned commit's bytes or fails: never another commit's.
2891
+ .../^0*$/.test(src.commit) ? {} : { pin: src.commit, strictPin: true }
2892
+ });
2893
+ if (!declared) repositories[slug] = { url: src.url, path: dir };
2894
+ } catch (err) {
2895
+ const reason = err instanceof Error ? err.message : String(err);
2896
+ unavailable.push(`unavailable: ${src.url} at ${src.commit.slice(0, 7)} (${reason})`);
2897
+ }
2531
2898
  }
2532
- const resolveCloneDir = (sourceUrl) => {
2533
- if (factoryDir && normalizeRepoUrl(sourceUrl) === factoryUrl) return factoryDir;
2899
+ if (unavailable.length > 0) {
2900
+ throw new Error(`Lock file verification failed:
2901
+ ${unavailable.join("\n ")}`);
2902
+ }
2903
+ const candidates = [];
2904
+ const cloneOrigin = {};
2905
+ for (const [key, entry] of Object.entries(lock.assets)) {
2906
+ const candidate = this.lockedCandidate(key, entry, repositories);
2907
+ if (!candidate) continue;
2908
+ candidates.push(candidate);
2909
+ if (this.candidateHasLocalBytes(candidate, repositories)) {
2910
+ cloneOrigin[key] = entry;
2911
+ }
2912
+ }
2913
+ const verification = verifyLock({ ...lock, assets: cloneOrigin }, (sourceUrl) => {
2914
+ if (isFactoryUrl(sourceUrl)) return factoryDir;
2534
2915
  const slug = sourceCacheKey(sourceUrl);
2535
- const decl = declBySlug.get(slug) ?? { url: sourceUrl };
2536
- return this.resolveRepoDir(decl, slug);
2537
- };
2538
- const verification = verifyLock(lock, resolveCloneDir);
2916
+ return this.resolveRepoDir(repositories[slug] ?? { url: sourceUrl }, slug);
2917
+ });
2539
2918
  if (!verification.ok) {
2540
2919
  const issues = [
2541
2920
  ...verification.drifted.map((r) => `drifted: ${r}`),
@@ -2554,28 +2933,13 @@ var AssetManager = class {
2554
2933
  ${lines.join("\n ")}`
2555
2934
  );
2556
2935
  }
2557
- const resolved = [];
2558
- for (const [ref, entry] of Object.entries(lock.assets)) {
2559
- if (!entry.source) continue;
2560
- const { publisher, kind, name } = parseCanonicalLockKey(ref);
2561
- if (!publisher || !kind || !name) continue;
2562
- const slug = sourceCacheKey(entry.source.url);
2563
- const cloneDir = resolveCloneDir(entry.source.url) ?? join(this.reposDir, slug);
2564
- const mdRel = entry.files.find((f) => /\.(md|yaml)$/i.test(f.path))?.path ?? entry.files[0]?.path ?? "";
2565
- resolved.push({
2566
- name,
2567
- kind,
2568
- description: "",
2569
- source: mdRel ? join(cloneDir, mdRel) : cloneDir,
2570
- // Keep the publisher label slash-free (repo name), not the full cache key.
2571
- publisher: sourceShortName(entry.source.url),
2572
- version: entry.source.commit,
2573
- // The lock key is the canonical ref; `publisher` above is only a clone label.
2574
- canonicalRef: ref,
2575
- requires: [],
2576
- dependencies: []
2577
- });
2578
- if (!repositories[slug]) repositories[slug] = { url: entry.source.url, path: cloneDir };
2936
+ let resolved;
2937
+ try {
2938
+ resolved = await this.buildCatalogEntries(candidates, repositories);
2939
+ } catch (err) {
2940
+ const reason = err instanceof Error ? err.message : String(err);
2941
+ throw new Error(`Lock file verification failed:
2942
+ ${reason}`);
2579
2943
  }
2580
2944
  const library = await this.restoreLibraryLockEntries(lock);
2581
2945
  const copyDrift = await this.lockedCopyDrift();
@@ -2664,7 +3028,8 @@ var AssetManager = class {
2664
3028
  this.ensureSourceClonesQuiet(repositories, sources);
2665
3029
  const index = await buildProvenanceIndex(this.buildClones(repositories), {
2666
3030
  projectDir: this.projectDir,
2667
- knownKinds: this.knownKinds
3031
+ knownKinds: this.knownKinds,
3032
+ onSourceError: this.reportSourceError
2668
3033
  });
2669
3034
  for (const candidates of index.values()) for (const c of candidates) note(c);
2670
3035
  for (const { entry } of await this.libraryAssets()) note(entry);
@@ -2699,11 +3064,19 @@ var AssetManager = class {
2699
3064
  this.ensureSourceClonesQuiet(repositories, sources);
2700
3065
  const provenanceIndex = await buildProvenanceIndex(this.buildClones(repositories), {
2701
3066
  projectDir: this.projectDir,
2702
- knownKinds: this.knownKinds
3067
+ knownKinds: this.knownKinds,
3068
+ onSourceError: this.reportSourceError
2703
3069
  });
2704
3070
  const { resolved, missing, overridesApplied, lib, presets } = await this.resolveLibraryFirst(
2705
3071
  [ref],
2706
- { provenanceIndex, overrides, stores, declaredRefs: dependencies, warnCollisions: true }
3072
+ {
3073
+ provenanceIndex,
3074
+ overrides,
3075
+ stores,
3076
+ declaredRefs: dependencies,
3077
+ warnCollisions: true,
3078
+ ...opts?.preferLockedLibrary ? { preferLocked: await this.lockedPreference() } : {}
3079
+ }
2707
3080
  );
2708
3081
  if (resolved.length === 0 && lib.entries.length === 0 && presets.length === 0) {
2709
3082
  const snap = await this.loadLibraryIndex();
@@ -2721,6 +3094,12 @@ var AssetManager = class {
2721
3094
  );
2722
3095
  }
2723
3096
  }
3097
+ const unreachable = [...this.storeFailures.values()];
3098
+ if (unreachable.length > 0) {
3099
+ throw new Error(
3100
+ `Store unreachable \u2014 ${ref} was not looked up: ${unreachable.join("; ")}. Check the URL with \`skaile catalog test\`; a library or source can still hold the asset.`
3101
+ );
3102
+ }
2724
3103
  throw new Error(
2725
3104
  `Asset not found: ${ref}${(await this.publisherChangeHints([ref]))[ref] ?? ""}${missing.length ? ` (missing: ${missing.join(", ")})` : ""}`
2726
3105
  );
@@ -2742,6 +3121,7 @@ var AssetManager = class {
2742
3121
  }
2743
3122
  }
2744
3123
  }
3124
+ this.assertSourceCommitsPublished(resolved, repositories);
2745
3125
  this.assertNoFolderCollision(
2746
3126
  [...resolved, ...lib.entries.map((e) => this.entryIdentity(e))],
2747
3127
  [
@@ -2749,7 +3129,28 @@ var AssetManager = class {
2749
3129
  ...dependencies.map((d) => parseAssetRefLoose(d) ?? {})
2750
3130
  ]
2751
3131
  );
3132
+ if (!opts?.force) {
3133
+ this.assertNoUnownedFolder(
3134
+ [
3135
+ ...resolved.map((c) => ({
3136
+ id: c,
3137
+ entry: this.candidateToCatalogEntry(c, repositories)
3138
+ })),
3139
+ ...lib.entries.map((e) => ({ id: this.entryIdentity(e), entry: e }))
3140
+ ],
3141
+ [
3142
+ ...Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey),
3143
+ ...dependencies.map((d) => parseAssetRefLoose(d) ?? {})
3144
+ ]
3145
+ );
3146
+ }
2752
3147
  if (missing.length > 0) {
3148
+ const unreachable = [...this.storeFailures.values()];
3149
+ if (unreachable.length > 0) {
3150
+ throw new Error(
3151
+ `Store unreachable \u2014 ${ref.split("#")[0]} requires ${missing.join(", ")}, which was not looked up: ${unreachable.join("; ")}. Check the URL with \`skaile catalog test\`; a library or source can still hold the requirement \u2014 nothing was added`
3152
+ );
3153
+ }
2753
3154
  throw new Error(
2754
3155
  `${ref.split("#")[0]} requires ${missing.join(", ")} (not found \u2014 ${REGISTER_HOLDER}, or remove the requirement from the asset's manifest) \u2014 nothing was added`
2755
3156
  );
@@ -2788,7 +3189,7 @@ var AssetManager = class {
2788
3189
  if (opts?.onLibraryMoved) {
2789
3190
  for (const m of libraryMoves(prevLock, libraryLock)) opts.onLibraryMoved(m);
2790
3191
  }
2791
- writeLock(this.lockPath, mergeLockFile(prevLock, fresh));
3192
+ writeLock(this.lockPath, mergeLockFile(prevLock, this.withRenderedAgents(fresh)));
2792
3193
  }
2793
3194
  for (const d of deployed) {
2794
3195
  appendHistory(this.projectDir, {
@@ -3301,7 +3702,13 @@ var AssetManager = class {
3301
3702
  for (const [name, decl] of Object.entries(repositories)) {
3302
3703
  const repoDir = this.resolveRepoDir(decl, name);
3303
3704
  if (!repoDir) continue;
3304
- all = [...all, ...await scanRepo(repoDir, name, { knownKinds: this.knownKinds })];
3705
+ all = [
3706
+ ...all,
3707
+ ...await scanRepo(repoDir, name, {
3708
+ knownKinds: this.knownKinds,
3709
+ declaredPublisher: decl.publisher
3710
+ })
3711
+ ];
3305
3712
  }
3306
3713
  if (kind) all = all.filter((e) => e.kind === kind);
3307
3714
  if (query) {
@@ -3346,7 +3753,10 @@ var AssetManager = class {
3346
3753
  for (const [name, decl] of Object.entries(repositories)) {
3347
3754
  const repoDir = this.resolveRepoDir(decl, name);
3348
3755
  if (!repoDir) continue;
3349
- const entries = await scanRepo(repoDir, name, { knownKinds: this.knownKinds });
3756
+ const entries = await scanRepo(repoDir, name, {
3757
+ knownKinds: this.knownKinds,
3758
+ declaredPublisher: decl.publisher
3759
+ });
3350
3760
  const match = entries.find(
3351
3761
  (e) => e.kind === parsed.kind && e.name === parsed.name && (!parsed.publisher || e.publisher === parsed.publisher)
3352
3762
  );
@@ -3542,12 +3952,12 @@ var AssetManager = class {
3542
3952
  return out;
3543
3953
  }
3544
3954
  /**
3545
- * Library-locked assets whose deployed directory lacks files the deploy writes —
3546
- * a deleted `build.py` / `scripts/` helper next to an intact `SKILL.md`. The
3547
- * expected set is the library entry's file set (every file under its manifest
3548
- * `root:`), the same bytes the lock hashes; only presence is checked, so a
3549
- * local edit never counts. An asset with no deployed directory is not listed
3550
- * (`listDeclared` reports it as drift); an agent is rendered, not copied, so it
3955
+ * Locked assets whose deployed directory lacks files the deploy writes — a deleted
3956
+ * `build.py` / `scripts/` helper next to an intact `SKILL.md`. The expected set is the file
3957
+ * set the lock covers: a library entry's files (every file under its manifest `root:`), a
3958
+ * source or store entry's `files[]` (the asset's whole file set at the locked commit). Only
3959
+ * presence is checked, so a local edit never counts. An asset with no deployed directory is
3960
+ * not listed (`listDeclared` reports it as drift); an agent is rendered, not copied, so it
3551
3961
  * has no file mirror to compare. `skaile install` restores what is listed.
3552
3962
  *
3553
3963
  * @returns One {@link IncompleteDeploy} per affected asset; empty when healthy
@@ -3556,10 +3966,25 @@ var AssetManager = class {
3556
3966
  async incompleteDeploys() {
3557
3967
  const lock = this.tryReadLock();
3558
3968
  if (!lock) return [];
3969
+ const out = [];
3970
+ const { patches } = this.loadConfig();
3971
+ for (const [key, entry] of Object.entries(lock.assets)) {
3972
+ if (!entry.source || entry.files.length === 0) continue;
3973
+ const { publisher, kind, name } = parseCanonicalLockKey(key);
3974
+ const component = kind ? this.installTarget(kind) : void 0;
3975
+ if (!publisher || !kind || !name || !component || component === "agent") continue;
3976
+ if (patches[`${kind}:${name}`]) continue;
3977
+ const dest = join(
3978
+ deployedBase(component, this.driverTarget, this.global, this.projectDir),
3979
+ name
3980
+ );
3981
+ if (!existsSync(dest) || lstatSync(dest).isSymbolicLink()) continue;
3982
+ const missing = lockedAssetFiles(kind, entry.files).map((f) => f.rel).filter((rel) => !existsSync(join(dest, rel)));
3983
+ if (missing.length > 0) out.push({ ref: `${kind}:@${publisher}/${name}`, missing });
3984
+ }
3559
3985
  const locked = Object.entries(lock.assets).filter(([, e]) => e.library !== void 0 && !e.library.installed).map(([key]) => key);
3560
- if (locked.length === 0) return [];
3986
+ if (locked.length === 0) return out;
3561
3987
  const lib = await this.resolveLibraryEntries(locked, { quiet: true });
3562
- const out = [];
3563
3988
  for (const entry of lib.entries) {
3564
3989
  const component = this.installTarget(entry.kind);
3565
3990
  if (!entry.files || !component || component === "agent") continue;
@@ -3900,7 +4325,17 @@ var AssetManager = class {
3900
4325
  if (!kind || !name) continue;
3901
4326
  const lockedCommit = entry.source.commit || src.commit;
3902
4327
  const moved = lockedCommit && !/^0+$/.test(lockedCommit) && lockedCommit !== status.localHead ? commitsBetween(clone, lockedCommit, status.localHead, commitCounts) : 0;
3903
- const behind = status.behind + moved;
4328
+ let behind = status.behind + moved;
4329
+ if (behind > 0) {
4330
+ const touching = commitsTouching(
4331
+ clone,
4332
+ COMMIT_ID.test(lockedCommit) && !/^0+$/.test(lockedCommit) ? lockedCommit : status.localHead,
4333
+ status.behind > 0 && status.remoteHead ? status.remoteHead : status.localHead,
4334
+ lockedAssetDir(kind, entry.files),
4335
+ commitCounts
4336
+ );
4337
+ if (touching !== null) behind = touching;
4338
+ }
3904
4339
  if (behind <= 0) continue;
3905
4340
  result.push({
3906
4341
  kind,
@@ -4018,6 +4453,37 @@ var AssetManager = class {
4018
4453
  }
4019
4454
  return null;
4020
4455
  }
4456
+ /**
4457
+ * The deploy entry of a source- or store-origin asset, carrying the file set its lock entry
4458
+ * lists (so a missing or edited helper shows in `diff`, not only the manifest). A source asset
4459
+ * reads from its clone; a store asset from the bytes `add`/`install` staged in the project
4460
+ * store cache. `null` when the lock has no such entry or its bytes are not on disk.
4461
+ *
4462
+ * @param want - Kind, name and optional publisher of the asset.
4463
+ */
4464
+ lockedSourceEntry(want) {
4465
+ const { repositories } = this.loadConfig();
4466
+ for (const [key, e] of Object.entries(this.tryReadLock()?.assets ?? {})) {
4467
+ const id = parseCanonicalLockKey(key);
4468
+ if (!e.source || id.kind !== want.kind || id.name !== want.name) continue;
4469
+ if (want.publisher && id.publisher !== want.publisher) continue;
4470
+ const c = this.lockedCandidate(key, e, repositories);
4471
+ if (!c) continue;
4472
+ if (this.candidateHasLocalBytes(c, repositories)) {
4473
+ return this.candidateToCatalogEntry(c, repositories);
4474
+ }
4475
+ const staged = join(
4476
+ this.storeCacheDir,
4477
+ c.publisher,
4478
+ c.kind,
4479
+ c.name,
4480
+ c.version,
4481
+ this.stagedManifestRel(c)
4482
+ );
4483
+ if (existsSync(staged)) return this.stagedCandidateToEntry(c, staged);
4484
+ }
4485
+ return null;
4486
+ }
4021
4487
  /**
4022
4488
  * Produce a unified diff from the deployed asset to its catalog source: `-` lines
4023
4489
  * are in the deployed copy only (local edits `update` would overwrite), `+` lines
@@ -4035,8 +4501,15 @@ var AssetManager = class {
4035
4501
  async diff(ref) {
4036
4502
  const parsed = parseRefTolerant(ref);
4037
4503
  if (!parsed) return { status: "not-found" };
4038
- const entry = await this.lockedLibraryEntry(parsed) ?? await this.info(ref);
4504
+ const entry = await this.lockedLibraryEntry(parsed) ?? this.lockedSourceEntry(parsed) ?? await this.info(ref);
4039
4505
  if (!entry || !existsSync(entry.source)) return { status: "not-found" };
4506
+ const wantPublisher = parsed.publisher?.replace(/^@/, "");
4507
+ if (wantPublisher) {
4508
+ const lockedHere = Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey).filter((id) => id.kind === parsed.kind && id.name === parsed.name);
4509
+ if (lockedHere.length > 0 && !lockedHere.some((id) => id.publisher === wantPublisher)) {
4510
+ return { status: "not-deployed" };
4511
+ }
4512
+ }
4040
4513
  const component = this.installTarget(parsed.kind);
4041
4514
  if (parsed.kind === "preset" && this.presetRecorded(parsed)) return { status: "no-files" };
4042
4515
  if (!component) return { status: "not-deployed" };
@@ -4079,7 +4552,8 @@ var AssetManager = class {
4079
4552
  this.ensureSourceClonesQuiet(repositories, sources);
4080
4553
  const provenanceIndex = await buildProvenanceIndex(this.buildClones(repositories), {
4081
4554
  projectDir: this.projectDir,
4082
- knownKinds: this.knownKinds
4555
+ knownKinds: this.knownKinds,
4556
+ onSourceError: this.reportSourceError
4083
4557
  });
4084
4558
  const { resolved, overridesApplied, lib } = await this.resolveLibraryFirst(dependencies, {
4085
4559
  provenanceIndex,
@@ -4087,8 +4561,14 @@ var AssetManager = class {
4087
4561
  stores,
4088
4562
  declaredRefs: dependencies
4089
4563
  });
4564
+ this.assertSourceCommitsPublished(resolved, repositories);
4090
4565
  const libraryLock = await this.libraryLockEntries(lib);
4091
4566
  const lockData = buildLockFile(resolved, overridesApplied, libraryLock);
4567
+ const prior = this.tryReadLock();
4568
+ for (const [key, entry] of Object.entries(lockData.assets)) {
4569
+ const rendered = prior?.assets[key]?.rendered;
4570
+ if (rendered) entry.rendered = rendered;
4571
+ }
4092
4572
  writeLock(this.lockPath, lockData);
4093
4573
  return lockData;
4094
4574
  }
@@ -4206,7 +4686,11 @@ var AssetManager = class {
4206
4686
  const full = await this.info(
4207
4687
  publisher ? `${entry.kind}:@${publisher}/${entry.name}` : `${entry.kind}:${entry.name}`
4208
4688
  );
4209
- if (!full) {
4689
+ const restorable = !full && publisher !== void 0 && Object.entries(lock?.assets ?? {}).some(([key, e]) => {
4690
+ const id = parseCanonicalLockKey(key);
4691
+ return e.source !== void 0 && id.kind === entry.kind && id.name === entry.name && id.publisher === publisher;
4692
+ });
4693
+ if (!full && !restorable) {
4210
4694
  if (publisher) {
4211
4695
  const canonical = `${entry.kind}:@${publisher}/${entry.name}`;
4212
4696
  const fix = (await this.unresolvedFixes([canonical])).get(canonical);
@@ -4222,8 +4706,9 @@ var AssetManager = class {
4222
4706
  }
4223
4707
  continue;
4224
4708
  }
4709
+ const declaredRequires = full ? full.requires : (await this.deployedRequirementsOf({ ...entry, publisher })).map(parseDep);
4225
4710
  const gaps = [];
4226
- const requirements = dedupeRequirements(full.requires, publisher).map(
4711
+ const requirements = dedupeRequirements(declaredRequires, publisher).map(
4227
4712
  (r) => r.publisher || !publisher ? r : { ...r, publisher }
4228
4713
  );
4229
4714
  for (const req of requirements) {
@@ -4327,13 +4812,25 @@ var AssetManager = class {
4327
4812
  }
4328
4813
  const asset = lockIdentity(i.assetKind, i.assetName);
4329
4814
  const dep = `${i.depKind}:${i.depName}`;
4330
- if (i.inRepos) {
4815
+ const depId = /^@([^/]+)\/(.+)$/.exec(i.depName);
4816
+ const lockedOnly = lockedIds.some(
4817
+ (id) => id.kind === i.depKind && id.name === (depId ? depId[2] : i.depName) && (!depId || id.publisher === depId[1])
4818
+ );
4819
+ if (lockedOnly) {
4331
4820
  gaps.push({
4332
4821
  type: "requires",
4333
4822
  ref: dep,
4334
4823
  asset,
4335
- reason: `is required by ${asset} but neither deployed nor locked (fixable)`,
4336
- message: `${asset} requires ${dep} (fixable)`
4824
+ reason: `is required by ${asset} but locked and not deployed (run skaile install --locked)`,
4825
+ message: `${asset} requires ${dep} (run skaile install --locked)`
4826
+ });
4827
+ } else if (i.inRepos) {
4828
+ gaps.push({
4829
+ type: "requires",
4830
+ ref: dep,
4831
+ asset,
4832
+ reason: `is required by ${asset} but neither deployed nor locked (run skaile install)`,
4833
+ message: `${asset} requires ${dep} (run skaile install)`
4337
4834
  });
4338
4835
  } else {
4339
4836
  const fix = requirementNoHolderFix(asset);
@@ -4378,6 +4875,25 @@ var AssetManager = class {
4378
4875
  const reason = `is deployed without ${d.missing.join(", ")} \u2014 run \`skaile install\` to restore it`;
4379
4876
  gaps.push({ type: "incomplete", ref: d.ref, reason, message: `${d.ref} ${reason}` });
4380
4877
  }
4878
+ const skipped = [];
4879
+ await buildProvenanceIndex(this.buildClones(this.loadConfig().repositories), {
4880
+ projectDir: this.projectDir,
4881
+ knownKinds: this.knownKinds,
4882
+ onSourceError: (clone, err) => skipped.push({
4883
+ url: clone.sourceUrl,
4884
+ why: err instanceof Error ? err.message : String(err)
4885
+ })
4886
+ });
4887
+ for (const s of skipped) {
4888
+ const reason = `is skipped: ${s.why.replace(`${s.url}: `, "")} \u2014 fix it or run \`skaile source remove\``;
4889
+ gaps.push({
4890
+ type: "source",
4891
+ ref: s.url,
4892
+ reason,
4893
+ message: `source ${s.url} ${reason}`,
4894
+ manualFix: true
4895
+ });
4896
+ }
4381
4897
  for (const u of unboundAgentInstances(this.projectDir, this.driverTarget)) {
4382
4898
  const reason = u.ref.startsWith("agent:") ? await this.unboundAgentReason(u.id, u.ref) : `is bound by agent instance "${u.id}" but resolves to no agent.yaml \u2014 fix the path, or drop the binding from skaile.yaml`;
4383
4899
  gaps.push({
@@ -4411,7 +4927,18 @@ var AssetManager = class {
4411
4927
  */
4412
4928
  async unboundAgentAdvice(ref) {
4413
4929
  const drop = "or drop the binding from skaile.yaml";
4414
- const publisher = parseRefTolerant(ref)?.publisher;
4930
+ const parsedRef = parseRefTolerant(ref);
4931
+ const publisher = parsedRef?.publisher;
4932
+ const lockedAgent = Object.keys(this.tryReadLock()?.assets ?? {}).some((key) => {
4933
+ const k = parseCanonicalLockKey(key);
4934
+ return k.kind === "agent" && k.name === parsedRef?.name && (!publisher || !k.publisher || k.publisher === publisher);
4935
+ });
4936
+ if (lockedAgent) {
4937
+ return {
4938
+ lead: "the agent is locked but not restored here",
4939
+ advice: `run \`skaile install --locked\` first, ${drop}`
4940
+ };
4941
+ }
4415
4942
  if (publisher && await this.info(ref) !== null) {
4416
4943
  return {
4417
4944
  lead: "no agent was added for it",
@@ -4458,6 +4985,52 @@ var AssetManager = class {
4458
4985
  (g) => names(g.ref) || g.asset && names(g.asset)
4459
4986
  );
4460
4987
  }
4988
+ /**
4989
+ * The {@link ProjectState} gaps of everything `ref` requires, transitively: what `check`
4990
+ * says about the requirements of `ref`, so a command that answers for one asset (`diff`)
4991
+ * does not call it fine while a requirement of it is broken. The requirements are read from
4992
+ * the deployed copies (the lock records no edges), the way `remove` and `install` read them
4993
+ * when no library holds the asset any more. The gaps of `ref` itself are not included
4994
+ * ({@link gapsOf}).
4995
+ *
4996
+ * @param ref - Asset ref in `kind:name` or `kind:@publisher/name` form.
4997
+ */
4998
+ async requirementGapsOf(ref) {
4999
+ const want = parseRefTolerant(ref);
5000
+ if (!want) return [];
5001
+ const gaps = (await this.projectState()).gaps;
5002
+ const lockedIds = Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey);
5003
+ const idKey = (id) => `${id.publisher ?? ""}/${id.kind}:${id.name}`;
5004
+ const seen = /* @__PURE__ */ new Set();
5005
+ const queue = [
5006
+ {
5007
+ kind: want.kind,
5008
+ name: want.name,
5009
+ publisher: want.publisher?.replace(/^@/, "") ?? lockedIds.find((l) => l.kind === want.kind && l.name === want.name)?.publisher
5010
+ }
5011
+ ];
5012
+ seen.add(idKey(queue[0]));
5013
+ const out = [];
5014
+ for (const asset of queue) {
5015
+ for (const dep of await this.deployedRequirementsOf(asset)) {
5016
+ const id = memberIdentity(dep);
5017
+ if (!id) continue;
5018
+ const publisher = id.publisher ?? lockedIds.find((l) => l.kind === id.kind && l.name === id.name)?.publisher;
5019
+ const next = { kind: id.kind, name: id.name, publisher };
5020
+ if (seen.has(idKey(next))) continue;
5021
+ seen.add(idKey(next));
5022
+ queue.push(next);
5023
+ for (const g of gaps) {
5024
+ if (out.includes(g)) continue;
5025
+ const p = parseRefTolerant(g.ref);
5026
+ if (p !== null && p.kind === next.kind && p.name === next.name && (!publisher || !p.publisher || p.publisher.replace(/^@/, "") === publisher)) {
5027
+ out.push(g);
5028
+ }
5029
+ }
5030
+ }
5031
+ }
5032
+ return out;
5033
+ }
4461
5034
  /**
4462
5035
  * Locked library assets whose library cannot supply them: the library is not registered
4463
5036
  * (renamed or removed) or no longer holds the asset. Another library holding it makes the
@@ -4523,6 +5096,55 @@ var AssetManager = class {
4523
5096
  }
4524
5097
  return gaps;
4525
5098
  }
5099
+ /**
5100
+ * Record, on every agent entry of `lock` that has none, the files the agent's harness
5101
+ * rendering occupies and their sha256. Call it after the deploy, so the bytes hashed are the
5102
+ * ones `install` just wrote; {@link lockedCopyDrift} compares later edits with them.
5103
+ * Entries that carry a record (kept from an earlier lock) are left as they are.
5104
+ */
5105
+ withRenderedAgents(lock) {
5106
+ if (this.global) return lock;
5107
+ for (const [key, entry] of Object.entries(lock.assets)) {
5108
+ if (entry.rendered || entry.library?.installed) continue;
5109
+ const { kind, name } = parseCanonicalLockKey(key);
5110
+ if (!kind || !name || this.installTarget(kind) !== "agent") continue;
5111
+ const rendered = this.renderedAgentFiles(name);
5112
+ if (rendered.length > 0) entry.rendered = rendered;
5113
+ }
5114
+ return lock;
5115
+ }
5116
+ /** The files of one agent's rendering for the active harness, project-relative, with sha256. */
5117
+ renderedAgentFiles(name) {
5118
+ const out = [];
5119
+ const walk = (path2) => {
5120
+ let stat;
5121
+ try {
5122
+ stat = lstatSync(path2);
5123
+ } catch {
5124
+ return;
5125
+ }
5126
+ if (stat.isSymbolicLink()) return;
5127
+ if (stat.isDirectory()) {
5128
+ for (const child of readdirSync(path2).sort()) walk(join(path2, child));
5129
+ } else if (stat.isFile()) {
5130
+ out.push({
5131
+ path: relative(this.projectDir, path2).split(sep).join("/"),
5132
+ sha256: computeHash(path2)
5133
+ });
5134
+ }
5135
+ };
5136
+ for (const path2 of deployedPaths("agent", name, this.driverTarget, false, this.projectDir)) {
5137
+ walk(path2);
5138
+ }
5139
+ walk(
5140
+ join(
5141
+ dirname(deployedBase("agent", this.driverTarget, false, this.projectDir)),
5142
+ CODEX_IDENTITY_DIR,
5143
+ `${name}.md`
5144
+ )
5145
+ );
5146
+ return out.sort((a, b) => a.path.localeCompare(b.path));
5147
+ }
4526
5148
  /**
4527
5149
  * The {@link RestoredAsset} rows for the drifted copies (see {@link lockedCopyDrift}) a
4528
5150
  * deploy just wrote again: those whose ref is among the `deployed` canonical refs.
@@ -4532,6 +5154,10 @@ var AssetManager = class {
4532
5154
  const out = [];
4533
5155
  for (const d of drifts) {
4534
5156
  if (!rewritten.has(d.ref)) continue;
5157
+ if (d.rendered) {
5158
+ out.push({ ref: d.key, restored: [...d.modified], removed: [] });
5159
+ continue;
5160
+ }
4535
5161
  const { kind, name } = parseCanonicalLockKey(d.key);
4536
5162
  const component = kind ? this.installTarget(kind) : void 0;
4537
5163
  if (!kind || !name || !component) continue;
@@ -4559,8 +5185,10 @@ var AssetManager = class {
4559
5185
  * - A source asset is compared with the per-file hashes the lock records (modified files only:
4560
5186
  * the lock lists what the source covers, not what the deploy copies).
4561
5187
  *
4562
- * An agent (rendered, not copied), a `--link` deploy, an asset with a configured patch, and a
4563
- * copy that is missing are not compared: other gaps cover them. Project mode only.
5188
+ * A `--link` deploy, an asset with a configured patch, and a copy that is missing are not
5189
+ * compared: other gaps cover them. An agent (rendered, not copied) is compared with the
5190
+ * hashes of its rendered files the lock records (`LockEntry.rendered`); its `modified` paths
5191
+ * are project-relative. Project mode only.
4564
5192
  */
4565
5193
  async lockedCopyDrift() {
4566
5194
  if (this.global) return [];
@@ -4601,30 +5229,37 @@ var AssetManager = class {
4601
5229
  } catch {
4602
5230
  continue;
4603
5231
  }
4604
- const dirs = entry.files.map(
4605
- (f) => posix.dirname(f.path).split("/").filter((s) => s !== ".")
4606
- );
4607
- let common = dirs[0] ?? [];
4608
- for (const d of dirs.slice(1)) {
4609
- let i = 0;
4610
- while (i < common.length && i < d.length && common[i] === d[i]) i++;
4611
- common = common.slice(0, i);
4612
- }
4613
- const prefix = common.length > 0 ? `${common.join("/")}/` : "";
4614
5232
  const modified = [];
4615
- for (const f of entry.files) {
4616
- const rel = f.path.startsWith(prefix) ? f.path.slice(prefix.length) : f.path;
4617
- const deployedFile = join(dest, rel);
5233
+ for (const f of lockedAssetFiles(kind, entry.files)) {
5234
+ const deployedFile = join(dest, f.rel);
4618
5235
  if (!existsSync(deployedFile)) continue;
4619
5236
  try {
4620
- if (computeHash(deployedFile) !== f.sha256) modified.push(rel);
5237
+ if (computeHash(deployedFile) !== f.sha256) modified.push(f.rel);
4621
5238
  } catch {
4622
- modified.push(rel);
5239
+ modified.push(f.rel);
4623
5240
  }
4624
5241
  }
4625
5242
  if (modified.length > 0)
4626
5243
  out.push({ ref: refOf(key), key, modified, extra: [], library: false });
4627
5244
  }
5245
+ for (const [key, entry] of Object.entries(lock.assets)) {
5246
+ if (!entry.rendered || entry.rendered.length === 0 || entry.library?.installed) continue;
5247
+ const { kind, name } = parseCanonicalLockKey(key);
5248
+ if (!kind || !name || this.installTarget(kind) !== "agent") continue;
5249
+ if (patches[`${kind}:${name}`]) continue;
5250
+ const modified = [];
5251
+ for (const f of entry.rendered) {
5252
+ const file = join(this.projectDir, f.path);
5253
+ if (!existsSync(file)) continue;
5254
+ try {
5255
+ if (computeHash(file) !== f.sha256) modified.push(f.path);
5256
+ } catch {
5257
+ modified.push(f.path);
5258
+ }
5259
+ }
5260
+ if (modified.length > 0)
5261
+ out.push({ ref: refOf(key), key, modified, extra: [], library: false, rendered: true });
5262
+ }
4628
5263
  return out;
4629
5264
  }
4630
5265
  /**
@@ -4642,7 +5277,7 @@ var AssetManager = class {
4642
5277
  if (!kind || !name || !component || named.has(`${kind}:${name}`)) continue;
4643
5278
  if (isDeployed(component, name, this.driverTarget, this.global, this.projectDir)) continue;
4644
5279
  const ref = publisher ? `${kind}:@${publisher}/${name}` : `${kind}:${name}`;
4645
- const reason = "is locked but its deployed copy is missing \u2014 run `skaile install`";
5280
+ const reason = "is locked but its deployed copy is missing \u2014 run `skaile install --locked`";
4646
5281
  gaps.push({ type: "drift", ref, reason, message: `${ref} ${reason}` });
4647
5282
  }
4648
5283
  return gaps;
@@ -4693,7 +5328,12 @@ var AssetManager = class {
4693
5328
  manualFix: true
4694
5329
  };
4695
5330
  } else if (await this.declaredRefResolvable(d.ref)) {
4696
- gap = { type: "declared", reason: "is declared but not locked \u2014 run `skaile install`" };
5331
+ const unmet = await this.unmetRequirementOf(d.ref);
5332
+ gap = unmet ? {
5333
+ type: "declared",
5334
+ reason: `requires ${unmet} but no library or source holds it \u2014 ${REGISTER_HOLDER}, or drop ${d.ref.split("#")[0]} with \`skaile remove ${d.ref.split("#")[0]}\``,
5335
+ manualFix: true
5336
+ } : { type: "declared", reason: "is declared but not locked \u2014 run `skaile install`" };
4697
5337
  } else {
4698
5338
  gap = {
4699
5339
  type: "declared",
@@ -4735,6 +5375,38 @@ var AssetManager = class {
4735
5375
  return p !== null && p.kind === want.kind && p.name === want.name && (!want.publisher || !p.publisher || p.publisher === want.publisher);
4736
5376
  });
4737
5377
  }
5378
+ /**
5379
+ * The first requirement, direct or transitive, of the declared `ref` that no local source or
5380
+ * library holds and that nothing in the project already provides — the case `install` ends
5381
+ * with `Missing: … nothing was installed`. `undefined` when every requirement is held, when a
5382
+ * store is declared (it may hold the requirement and a check never goes to the network), or
5383
+ * when `ref` itself resolves to nothing.
5384
+ */
5385
+ async unmetRequirementOf(ref) {
5386
+ if (this.loadConfig().stores.length > 0) return void 0;
5387
+ const lockedIds = Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey);
5388
+ const seen = /* @__PURE__ */ new Set();
5389
+ const queue = [ref];
5390
+ for (let cur = queue.shift(); cur !== void 0; cur = queue.shift()) {
5391
+ const id = refIdentity(cur);
5392
+ if (id !== null) {
5393
+ if (seen.has(id)) continue;
5394
+ seen.add(id);
5395
+ }
5396
+ const entry = await this.info(cur);
5397
+ if (!entry) {
5398
+ if (cur === ref) return void 0;
5399
+ const want = parseRefTolerant(cur);
5400
+ const locked = want !== null && lockedIds.some(
5401
+ (l) => l.kind === want.kind && l.name === want.name && (!want.publisher || l.publisher === want.publisher)
5402
+ );
5403
+ if (!locked) return cur;
5404
+ continue;
5405
+ }
5406
+ queue.push(...libraryEntryDepRefs(entry));
5407
+ }
5408
+ return void 0;
5409
+ }
4738
5410
  /**
4739
5411
  * Whether `skaile install` can resolve a declared ref: a source or library holds it, or the
4740
5412
  * project declares a store that may. The global catalog is not asked: a check never goes
@@ -4768,7 +5440,8 @@ var AssetManager = class {
4768
5440
  const { repositories } = this.loadConfig();
4769
5441
  const provenanceIndex = await buildProvenanceIndex(this.buildClones(repositories), {
4770
5442
  projectDir: this.projectDir,
4771
- knownKinds: this.knownKinds
5443
+ knownKinds: this.knownKinds,
5444
+ onSourceError: this.reportSourceError
4772
5445
  });
4773
5446
  const lockKeys = Object.keys(lock.assets).map(parseCanonicalLockKey);
4774
5447
  const sourceCandidate = (ref) => {
@@ -5076,5 +5749,5 @@ var AssetManager = class {
5076
5749
  };
5077
5750
 
5078
5751
  export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, installAgentInstances, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, softDepName };
5079
- //# sourceMappingURL=chunk-DZMNFCWB.js.map
5080
- //# sourceMappingURL=chunk-DZMNFCWB.js.map
5752
+ //# sourceMappingURL=chunk-Y7WKXPWS.js.map
5753
+ //# sourceMappingURL=chunk-Y7WKXPWS.js.map