@skaile/workspaces 6.0.0 → 6.2.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 (431) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/dist/{asset-feeds-PXUWCXVI.js → asset-feeds-KPKCE64E.js} +31 -23
  3. package/dist/asset-feeds-KPKCE64E.js.map +1 -0
  4. package/dist/asset-manager/catalog-deployer.js +10 -10
  5. package/dist/asset-manager/fragments.js +1 -1
  6. package/dist/asset-manager/index.js +19 -19
  7. package/dist/asset-manager/installer.js +13 -13
  8. package/dist/asset-manager/renderers.js +11 -11
  9. package/dist/asset-manager/src/index.d.ts +339 -19
  10. package/dist/asset-manager/src/index.d.ts.map +1 -1
  11. package/dist/asset-manager/src/installer.d.ts +40 -0
  12. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  13. package/dist/asset-manager/src/mcp-config.d.ts +21 -0
  14. package/dist/asset-manager/src/mcp-config.d.ts.map +1 -1
  15. package/dist/asset-manager/src/renderers.d.ts +7 -0
  16. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  17. package/dist/bridge/harnesses/claude-sdk.js +18 -22
  18. package/dist/bridge/harnesses/claude-sdk.js.map +1 -1
  19. package/dist/bridge/harnesses/codex.js +24 -17
  20. package/dist/bridge/harnesses/codex.js.map +1 -1
  21. package/dist/bridge/harnesses/continue.js +14 -14
  22. package/dist/bridge/harnesses/echo.js +4 -4
  23. package/dist/bridge/harnesses/gemini.js +10 -10
  24. package/dist/bridge/harnesses/goose.js +14 -14
  25. package/dist/bridge/harnesses/omp.js +15 -8
  26. package/dist/bridge/harnesses/omp.js.map +1 -1
  27. package/dist/bridge/harnesses/opencode.js +14 -14
  28. package/dist/bridge/harnesses/qwen.js +10 -10
  29. package/dist/bridge/index.js +19 -19
  30. package/dist/bridge/src/claude-sdk-surface.d.ts +17 -0
  31. package/dist/bridge/src/claude-sdk-surface.d.ts.map +1 -0
  32. package/dist/bridge/src/harness-model-check.d.ts +30 -0
  33. package/dist/bridge/src/harness-model-check.d.ts.map +1 -1
  34. package/dist/bridge/src/harnesses/_subprocess-cli.d.ts.map +1 -1
  35. package/dist/bridge/src/harnesses/claude-sdk.d.ts.map +1 -1
  36. package/dist/bridge/src/harnesses/codex.d.ts.map +1 -1
  37. package/dist/bridge/src/harnesses/omp.d.ts.map +1 -1
  38. package/dist/bridge/src/index.d.ts +2 -1
  39. package/dist/bridge/src/index.d.ts.map +1 -1
  40. package/dist/bridge/src/normalizer.d.ts +3 -1
  41. package/dist/bridge/src/normalizer.d.ts.map +1 -1
  42. package/dist/bridge/src/runner-private-env.d.ts +7 -0
  43. package/dist/bridge/src/runner-private-env.d.ts.map +1 -1
  44. package/dist/{chunk-HK7HMEPT.js → chunk-27SXN33H.js} +13 -5
  45. package/dist/chunk-27SXN33H.js.map +1 -0
  46. package/dist/{chunk-TKHJXPSB.js → chunk-2XM3ZH36.js} +183 -33
  47. package/dist/chunk-2XM3ZH36.js.map +1 -0
  48. package/dist/{chunk-E3GPGTW3.js → chunk-3HACK2Z7.js} +142 -28
  49. package/dist/chunk-3HACK2Z7.js.map +1 -0
  50. package/dist/{chunk-T2BDID2J.js → chunk-5JPW27BI.js} +10 -9
  51. package/dist/chunk-5JPW27BI.js.map +1 -0
  52. package/dist/{chunk-2UUKCROR.js → chunk-5LQ62LNT.js} +4 -4
  53. package/dist/{chunk-2UUKCROR.js.map → chunk-5LQ62LNT.js.map} +1 -1
  54. package/dist/{chunk-UL22SDGR.js → chunk-6CYKTHNT.js} +194 -127
  55. package/dist/chunk-6CYKTHNT.js.map +1 -0
  56. package/dist/{chunk-XFIEVEU7.js → chunk-6OHZUUR7.js} +5 -4
  57. package/dist/chunk-6OHZUUR7.js.map +1 -0
  58. package/dist/{chunk-E572OHGY.js → chunk-76FLBODK.js} +4 -3
  59. package/dist/chunk-76FLBODK.js.map +1 -0
  60. package/dist/{chunk-GN4VVSAA.js → chunk-7DRFKAJZ.js} +7 -7
  61. package/dist/{chunk-GN4VVSAA.js.map → chunk-7DRFKAJZ.js.map} +1 -1
  62. package/dist/chunk-7H6XRCPG.js +31 -0
  63. package/dist/chunk-7H6XRCPG.js.map +1 -0
  64. package/dist/{chunk-MCUJTNY5.js → chunk-7Y6S4XLL.js} +3 -3
  65. package/dist/{chunk-MCUJTNY5.js.map → chunk-7Y6S4XLL.js.map} +1 -1
  66. package/dist/{chunk-DHYSUJ3H.js → chunk-BEYNH2LS.js} +4 -4
  67. package/dist/{chunk-DHYSUJ3H.js.map → chunk-BEYNH2LS.js.map} +1 -1
  68. package/dist/{chunk-GEQSUC6U.js → chunk-BOT64P3U.js} +4 -4
  69. package/dist/{chunk-GEQSUC6U.js.map → chunk-BOT64P3U.js.map} +1 -1
  70. package/dist/{chunk-L4YKW5AY.js → chunk-BRK5QZKI.js} +121 -20
  71. package/dist/chunk-BRK5QZKI.js.map +1 -0
  72. package/dist/{chunk-YGRZNFRO.js → chunk-BY5WIRCU.js} +58 -5
  73. package/dist/chunk-BY5WIRCU.js.map +1 -0
  74. package/dist/{chunk-Z7ZEZZB6.js → chunk-C5HFK34M.js} +3 -3
  75. package/dist/chunk-C5HFK34M.js.map +1 -0
  76. package/dist/{chunk-DUMTLYSO.js → chunk-COAFAYBS.js} +31 -7
  77. package/dist/chunk-COAFAYBS.js.map +1 -0
  78. package/dist/{chunk-7XSAW5OC.js → chunk-E5NQRHEB.js} +30 -7
  79. package/dist/chunk-E5NQRHEB.js.map +1 -0
  80. package/dist/{chunk-BFMYYNDT.js → chunk-F3D25RGM.js} +11 -3
  81. package/dist/chunk-F3D25RGM.js.map +1 -0
  82. package/dist/{chunk-VBI7HGHB.js → chunk-GF5JXQIZ.js} +3 -3
  83. package/dist/{chunk-VBI7HGHB.js.map → chunk-GF5JXQIZ.js.map} +1 -1
  84. package/dist/{chunk-ZFUZ5AKM.js → chunk-I7LC5TDY.js} +3 -3
  85. package/dist/{chunk-ZFUZ5AKM.js.map → chunk-I7LC5TDY.js.map} +1 -1
  86. package/dist/{chunk-3IXIEHUB.js → chunk-ICSGNT5P.js} +7 -7
  87. package/dist/{chunk-3IXIEHUB.js.map → chunk-ICSGNT5P.js.map} +1 -1
  88. package/dist/{chunk-WEH33JSG.js → chunk-ITFCWMOY.js} +93 -29
  89. package/dist/chunk-ITFCWMOY.js.map +1 -0
  90. package/dist/{chunk-WDXZA7QW.js → chunk-IZQOO6MN.js} +2 -2
  91. package/dist/{chunk-WDXZA7QW.js.map → chunk-IZQOO6MN.js.map} +1 -1
  92. package/dist/{chunk-WDAIWDLK.js → chunk-JFLQICIU.js} +5 -5
  93. package/dist/{chunk-WDAIWDLK.js.map → chunk-JFLQICIU.js.map} +1 -1
  94. package/dist/{chunk-ARWKK325.js → chunk-JJJ2G4K2.js} +5 -5
  95. package/dist/{chunk-ARWKK325.js.map → chunk-JJJ2G4K2.js.map} +1 -1
  96. package/dist/{chunk-GOCWM7FN.js → chunk-JMIKGAUA.js} +43 -4
  97. package/dist/chunk-JMIKGAUA.js.map +1 -0
  98. package/dist/{chunk-X3RMRJNR.js → chunk-JRN5QF4C.js} +8 -3
  99. package/dist/chunk-JRN5QF4C.js.map +1 -0
  100. package/dist/{chunk-SNEE6UGY.js → chunk-K3R2UKG7.js} +18 -12
  101. package/dist/chunk-K3R2UKG7.js.map +1 -0
  102. package/dist/{chunk-VXEYX73S.js → chunk-KB56WBQ3.js} +4 -4
  103. package/dist/{chunk-VXEYX73S.js.map → chunk-KB56WBQ3.js.map} +1 -1
  104. package/dist/{chunk-OHNKYHRR.js → chunk-KJSC2ZD6.js} +264 -18
  105. package/dist/chunk-KJSC2ZD6.js.map +1 -0
  106. package/dist/{chunk-UQ33Y4DM.js → chunk-KPKGWXUJ.js} +4 -4
  107. package/dist/{chunk-UQ33Y4DM.js.map → chunk-KPKGWXUJ.js.map} +1 -1
  108. package/dist/{chunk-AF432MS3.js → chunk-KXJMQTOU.js} +3 -3
  109. package/dist/{chunk-AF432MS3.js.map → chunk-KXJMQTOU.js.map} +1 -1
  110. package/dist/chunk-LRBP3234.js +302 -0
  111. package/dist/chunk-LRBP3234.js.map +1 -0
  112. package/dist/{chunk-UVVVR4XO.js → chunk-M4OG2YN4.js} +4 -4
  113. package/dist/{chunk-UVVVR4XO.js.map → chunk-M4OG2YN4.js.map} +1 -1
  114. package/dist/{chunk-QOM5Z62G.js → chunk-MAZ3UXJK.js} +17 -24
  115. package/dist/chunk-MAZ3UXJK.js.map +1 -0
  116. package/dist/{chunk-Y2TO2U7W.js → chunk-MM4YO3EL.js} +3 -3
  117. package/dist/{chunk-Y2TO2U7W.js.map → chunk-MM4YO3EL.js.map} +1 -1
  118. package/dist/{chunk-OULSJRXV.js → chunk-OCQNUV4T.js} +7 -7
  119. package/dist/{chunk-OULSJRXV.js.map → chunk-OCQNUV4T.js.map} +1 -1
  120. package/dist/{chunk-SZXGRHQQ.js → chunk-PJJSBZZP.js} +4 -4
  121. package/dist/{chunk-SZXGRHQQ.js.map → chunk-PJJSBZZP.js.map} +1 -1
  122. package/dist/{chunk-OAHVKSQJ.js → chunk-PKBLJI23.js} +1471 -126
  123. package/dist/chunk-PKBLJI23.js.map +1 -0
  124. package/dist/{chunk-NOA6EJXE.js → chunk-PKE3PXOK.js} +3 -3
  125. package/dist/{chunk-NOA6EJXE.js.map → chunk-PKE3PXOK.js.map} +1 -1
  126. package/dist/{chunk-WYHQUCHR.js → chunk-PMWRM4EJ.js} +109 -48
  127. package/dist/chunk-PMWRM4EJ.js.map +1 -0
  128. package/dist/{chunk-H6UVIKQ2.js → chunk-PNUM7GUY.js} +3 -3
  129. package/dist/{chunk-H6UVIKQ2.js.map → chunk-PNUM7GUY.js.map} +1 -1
  130. package/dist/{chunk-SRODW6M2.js → chunk-Q5RN4PWV.js} +3 -3
  131. package/dist/{chunk-SRODW6M2.js.map → chunk-Q5RN4PWV.js.map} +1 -1
  132. package/dist/{chunk-LN6QB7XI.js → chunk-QIHL3YPL.js} +4 -4
  133. package/dist/{chunk-LN6QB7XI.js.map → chunk-QIHL3YPL.js.map} +1 -1
  134. package/dist/{chunk-U56GGCC2.js → chunk-QK7AG5AV.js} +4 -4
  135. package/dist/{chunk-U56GGCC2.js.map → chunk-QK7AG5AV.js.map} +1 -1
  136. package/dist/{chunk-OTIB4D2K.js → chunk-QPWR3YMY.js} +15 -5
  137. package/dist/chunk-QPWR3YMY.js.map +1 -0
  138. package/dist/{chunk-4DWBSTYA.js → chunk-QXKUFROW.js} +22 -5
  139. package/dist/chunk-QXKUFROW.js.map +1 -0
  140. package/dist/{chunk-4XWLB7JB.js → chunk-RQMIZONH.js} +95 -35
  141. package/dist/chunk-RQMIZONH.js.map +1 -0
  142. package/dist/{chunk-LSI2IVFT.js → chunk-RXGPFAMN.js} +4 -3
  143. package/dist/chunk-RXGPFAMN.js.map +1 -0
  144. package/dist/{chunk-3JKGY2YC.js → chunk-S2H3RBK7.js} +182 -33
  145. package/dist/chunk-S2H3RBK7.js.map +1 -0
  146. package/dist/{chunk-VJRTDKXS.js → chunk-SJNZ4WPA.js} +165 -106
  147. package/dist/chunk-SJNZ4WPA.js.map +1 -0
  148. package/dist/{chunk-KX2PT5Q4.js → chunk-T2VBPVWZ.js} +77 -18
  149. package/dist/chunk-T2VBPVWZ.js.map +1 -0
  150. package/dist/{chunk-6Z5KTFJT.js → chunk-TSTRH4SM.js} +3 -3
  151. package/dist/{chunk-6Z5KTFJT.js.map → chunk-TSTRH4SM.js.map} +1 -1
  152. package/dist/{chunk-7CV3HFWJ.js → chunk-TZERN27L.js} +5 -5
  153. package/dist/{chunk-7CV3HFWJ.js.map → chunk-TZERN27L.js.map} +1 -1
  154. package/dist/{chunk-JDR6ILCW.js → chunk-U673DB5U.js} +4 -4
  155. package/dist/{chunk-JDR6ILCW.js.map → chunk-U673DB5U.js.map} +1 -1
  156. package/dist/{chunk-FKU57Q5Q.js → chunk-URCJIV7T.js} +3 -3
  157. package/dist/{chunk-FKU57Q5Q.js.map → chunk-URCJIV7T.js.map} +1 -1
  158. package/dist/{chunk-ADPM6AYF.js → chunk-VSX2G7LA.js} +3 -3
  159. package/dist/{chunk-ADPM6AYF.js.map → chunk-VSX2G7LA.js.map} +1 -1
  160. package/dist/{chunk-F2GOZMRA.js → chunk-X37JUNEW.js} +49 -49
  161. package/dist/chunk-X37JUNEW.js.map +1 -0
  162. package/dist/{chunk-NMI2TWMH.js → chunk-Z3IRZBXB.js} +158 -344
  163. package/dist/chunk-Z3IRZBXB.js.map +1 -0
  164. package/dist/{chunk-7TPYPVAH.js → chunk-ZWJCRHP3.js} +3 -3
  165. package/dist/{chunk-7TPYPVAH.js.map → chunk-ZWJCRHP3.js.map} +1 -1
  166. package/dist/{claude-code-VJGYBXQR.js → claude-code-BBMNVH2J.js} +5 -5
  167. package/dist/{claude-code-VJGYBXQR.js.map → claude-code-BBMNVH2J.js.map} +1 -1
  168. package/dist/cli/index.js +964 -501
  169. package/dist/cli/index.js.map +1 -1
  170. package/dist/cli/src/agent-pins.d.ts +11 -0
  171. package/dist/cli/src/agent-pins.d.ts.map +1 -1
  172. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  173. package/dist/cli/src/commands/catalog.d.ts +1 -1
  174. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  175. package/dist/cli/src/commands/config.d.ts.map +1 -1
  176. package/dist/cli/src/commands/diff.d.ts.map +1 -1
  177. package/dist/cli/src/commands/harness.d.ts +24 -0
  178. package/dist/cli/src/commands/harness.d.ts.map +1 -0
  179. package/dist/cli/src/commands/integration.d.ts.map +1 -1
  180. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  181. package/dist/cli/src/commands/library-index.d.ts +28 -3
  182. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  183. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  184. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  185. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  186. package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
  187. package/dist/cli/src/commands/project.d.ts +19 -1
  188. package/dist/cli/src/commands/project.d.ts.map +1 -1
  189. package/dist/cli/src/commands/rebuild.d.ts.map +1 -1
  190. package/dist/cli/src/commands/run.d.ts.map +1 -1
  191. package/dist/cli/src/commands/serve-preflight.d.ts +31 -1
  192. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
  193. package/dist/cli/src/commands/serve.d.ts +10 -0
  194. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  195. package/dist/cli/src/commands/session-logs/local-query.d.ts +2 -0
  196. package/dist/cli/src/commands/session-logs/local-query.d.ts.map +1 -1
  197. package/dist/cli/src/commands/source-manifest-publish.d.ts.map +1 -1
  198. package/dist/cli/src/commands/source-manifest.d.ts +19 -7
  199. package/dist/cli/src/commands/source-manifest.d.ts.map +1 -1
  200. package/dist/cli/src/commands/source.d.ts +9 -2
  201. package/dist/cli/src/commands/source.d.ts.map +1 -1
  202. package/dist/cli/src/commands/store.d.ts.map +1 -1
  203. package/dist/cli/src/commands/update.d.ts.map +1 -1
  204. package/dist/cli/src/commands/validate-instances.d.ts.map +1 -1
  205. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  206. package/dist/cli/src/commands/why.d.ts.map +1 -1
  207. package/dist/cli/src/config-checks.d.ts +55 -0
  208. package/dist/cli/src/config-checks.d.ts.map +1 -0
  209. package/dist/cli/src/harness-error.d.ts +12 -1
  210. package/dist/cli/src/harness-error.d.ts.map +1 -1
  211. package/dist/cli/src/helpers.d.ts +18 -8
  212. package/dist/cli/src/helpers.d.ts.map +1 -1
  213. package/dist/cli/src/plugin-store/index.d.ts +10 -1
  214. package/dist/cli/src/plugin-store/index.d.ts.map +1 -1
  215. package/dist/cli/src/plugin-store/spec.d.ts +8 -0
  216. package/dist/cli/src/plugin-store/spec.d.ts.map +1 -1
  217. package/dist/cli/src/skill-checks.d.ts +27 -0
  218. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  219. package/dist/cli/src/store-addable.d.ts +11 -0
  220. package/dist/cli/src/store-addable.d.ts.map +1 -1
  221. package/dist/connectors/config.js +5 -5
  222. package/dist/connectors/index.js +23 -23
  223. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  224. package/dist/connectors-47EM6C2P.js +48 -0
  225. package/dist/{connectors-CXZLXAFZ.js.map → connectors-47EM6C2P.js.map} +1 -1
  226. package/dist/core/framework.js +1 -1
  227. package/dist/core/index.js +9 -9
  228. package/dist/core/manifest.js +2 -2
  229. package/dist/core/models.js +1 -1
  230. package/dist/core/provider-registry-credentials.js +2 -2
  231. package/dist/core/provider-registry.js +1 -1
  232. package/dist/core/publish-manifest.js +3 -3
  233. package/dist/core/ref.js +1 -1
  234. package/dist/core/runtime-assets.js +5 -5
  235. package/dist/core/src/agent-instances.d.ts.map +1 -1
  236. package/dist/core/src/config-key-diagnostics.d.ts +9 -0
  237. package/dist/core/src/config-key-diagnostics.d.ts.map +1 -0
  238. package/dist/core/src/framework.d.ts +5 -3
  239. package/dist/core/src/framework.d.ts.map +1 -1
  240. package/dist/core/src/index.d.ts +3 -2
  241. package/dist/core/src/index.d.ts.map +1 -1
  242. package/dist/core/src/lock.d.ts +12 -0
  243. package/dist/core/src/lock.d.ts.map +1 -1
  244. package/dist/core/src/manifest.d.ts +25 -0
  245. package/dist/core/src/manifest.d.ts.map +1 -1
  246. package/dist/core/src/models.d.ts +15 -0
  247. package/dist/core/src/models.d.ts.map +1 -1
  248. package/dist/core/src/provider-registry.d.ts +6 -0
  249. package/dist/core/src/provider-registry.d.ts.map +1 -1
  250. package/dist/core/src/workspace-config.d.ts +18 -1
  251. package/dist/core/src/workspace-config.d.ts.map +1 -1
  252. package/dist/core/src/workspace-yaml-editor.d.ts +9 -2
  253. package/dist/core/src/workspace-yaml-editor.d.ts.map +1 -1
  254. package/dist/core/workspace-config.js +4 -4
  255. package/dist/deploy/index.js +9 -9
  256. package/dist/discovery/index.js +5 -5
  257. package/dist/discovery/src/builtin-providers.d.ts.map +1 -1
  258. package/dist/discovery/src/parse-manifest.d.ts.map +1 -1
  259. package/dist/{ensure-sources-UPTHZKGF.js → ensure-sources-K5EFNC3L.js} +36 -22
  260. package/dist/ensure-sources-K5EFNC3L.js.map +1 -0
  261. package/dist/factory-assets/connectors/box.js +23 -23
  262. package/dist/factory-assets/connectors/deploy.js +23 -23
  263. package/dist/factory-assets/connectors/devserver.js +23 -23
  264. package/dist/factory-assets/connectors/flow/adapter.js +23 -23
  265. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
  266. package/dist/factory-assets/connectors/flow/contract.js +1 -1
  267. package/dist/factory-assets/connectors/flow/engine.js +11 -11
  268. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  269. package/dist/factory-assets/connectors/flow/run-flow.js +25 -25
  270. package/dist/factory-assets/connectors/flow.js +23 -23
  271. package/dist/factory-assets/connectors/git.js +23 -23
  272. package/dist/factory-assets/connectors/gmail.js +23 -23
  273. package/dist/factory-assets/connectors/googledrive.js +23 -23
  274. package/dist/factory-assets/connectors/local.js +23 -23
  275. package/dist/factory-assets/connectors/mattermost.js +23 -23
  276. package/dist/factory-assets/connectors/memory.js +23 -23
  277. package/dist/factory-assets/connectors/minio.js +23 -23
  278. package/dist/factory-assets/connectors/postgres.js +23 -23
  279. package/dist/factory-assets/connectors/s3.js +23 -23
  280. package/dist/factory-assets/connectors/sharepoint.js +23 -23
  281. package/dist/factory-assets/connectors/sqlite.js +23 -23
  282. package/dist/factory-assets/connectors/static-server.js +23 -23
  283. package/dist/factory-assets/connectors/tunnel.js +23 -23
  284. package/dist/factory-assets/connectors/webdav.js +23 -23
  285. package/dist/factory-assets/connectors/xstate-store.js +23 -23
  286. package/dist/factory-assets/connectors/xstate.js +23 -23
  287. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +1 -1
  288. package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +2 -2
  289. package/dist/factory-assets/skills/authoring-skaile-manifests/references/dependency-standard.md +3 -3
  290. package/dist/flows-KLBNSKLO.js +26 -0
  291. package/dist/{flows-TJQIMGUX.js.map → flows-KLBNSKLO.js.map} +1 -1
  292. package/dist/helpers-LUSV2ICC.js +52 -0
  293. package/dist/{helpers-DE53KG3E.js.map → helpers-LUSV2ICC.js.map} +1 -1
  294. package/dist/library/index.js +14 -14
  295. package/dist/library/install.js +5 -5
  296. package/dist/library/src/index.d.ts +2 -2
  297. package/dist/library/src/index.d.ts.map +1 -1
  298. package/dist/library/src/install/index.d.ts +1 -1
  299. package/dist/library/src/install/index.d.ts.map +1 -1
  300. package/dist/library/src/install/install-from-manifest.d.ts +13 -0
  301. package/dist/library/src/install/install-from-manifest.d.ts.map +1 -1
  302. package/dist/library/src/install/source-fetch-github.d.ts.map +1 -1
  303. package/dist/library/src/local/library-dir.d.ts +22 -5
  304. package/dist/library/src/local/library-dir.d.ts.map +1 -1
  305. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  306. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  307. package/dist/library/src/remote/remote-catalog-source.d.ts +8 -0
  308. package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
  309. package/dist/library/src/remote/rest-catalog-source.d.ts +3 -2
  310. package/dist/library/src/remote/rest-catalog-source.d.ts.map +1 -1
  311. package/dist/{library-publish-KKQ2ULLX.js → library-publish-XMRCKRNR.js} +59 -58
  312. package/dist/library-publish-XMRCKRNR.js.map +1 -0
  313. package/dist/model-endpoint/index.js +12 -12
  314. package/dist/model-endpoint/src/openai-chat.d.ts +7 -2
  315. package/dist/model-endpoint/src/openai-chat.d.ts.map +1 -1
  316. package/dist/model-endpoint/src/openai-shared.d.ts +8 -0
  317. package/dist/model-endpoint/src/openai-shared.d.ts.map +1 -1
  318. package/dist/model-endpoint/src/server.d.ts.map +1 -1
  319. package/dist/model-endpoint/src/types.d.ts +1 -1
  320. package/dist/model-endpoint/src/types.d.ts.map +1 -1
  321. package/dist/model-endpoint/src/usage-cost.d.ts +23 -0
  322. package/dist/model-endpoint/src/usage-cost.d.ts.map +1 -0
  323. package/dist/open-library-XBR46DJL.js +56 -0
  324. package/dist/{open-library-RJGJIW5H.js.map → open-library-XBR46DJL.js.map} +1 -1
  325. package/dist/open-registry-W562DCDL.js +32 -0
  326. package/dist/{open-registry-3QS3J7KO.js.map → open-registry-W562DCDL.js.map} +1 -1
  327. package/dist/paths-2AZXB3QL.js +22 -0
  328. package/dist/{paths-QAV4C3KX.js.map → paths-2AZXB3QL.js.map} +1 -1
  329. package/dist/plugin-store-36SIL4TV.js +23 -0
  330. package/dist/{plugin-store-MSH6GK6T.js.map → plugin-store-36SIL4TV.js.map} +1 -1
  331. package/dist/project-D7GN7WLS.js +86 -0
  332. package/dist/{project-HZW2MZPA.js.map → project-D7GN7WLS.js.map} +1 -1
  333. package/dist/resolver/index.js +10 -10
  334. package/dist/runner/index.js +40 -40
  335. package/dist/runner/src/capability-roundtrip.d.ts +7 -6
  336. package/dist/runner/src/capability-roundtrip.d.ts.map +1 -1
  337. package/dist/runner/src/composition/content-source.d.ts.map +1 -1
  338. package/dist/runner/src/composition/errors.d.ts +16 -1
  339. package/dist/runner/src/composition/errors.d.ts.map +1 -1
  340. package/dist/runner/src/credential-notice.d.ts +3 -3
  341. package/dist/runner/src/credential-notice.d.ts.map +1 -1
  342. package/dist/runner/src/serve.d.ts +20 -7
  343. package/dist/runner/src/serve.d.ts.map +1 -1
  344. package/dist/sdk/asset-manager.js +19 -19
  345. package/dist/sdk/bridge.js +19 -19
  346. package/dist/sdk/core.js +9 -9
  347. package/dist/sdk/flow.js +11 -11
  348. package/dist/sdk/index.js +40 -40
  349. package/dist/sdk/resolver.js +10 -10
  350. package/dist/sdk/runner.js +40 -40
  351. package/dist/sdk/transport/ws/server.js +10 -10
  352. package/dist/sdk/transport/ws.js +10 -10
  353. package/dist/sdk/transport.js +10 -10
  354. package/dist/serve-preflight-CGA5G3AE.js +135 -0
  355. package/dist/serve-preflight-CGA5G3AE.js.map +1 -0
  356. package/dist/{setup-AGYB4PKR.js → setup-IBDNJAOU.js} +32 -32
  357. package/dist/{setup-AGYB4PKR.js.map → setup-IBDNJAOU.js.map} +1 -1
  358. package/dist/skills-CTTO7SZK.js +26 -0
  359. package/dist/{skills-2LMQ2IAD.js.map → skills-CTTO7SZK.js.map} +1 -1
  360. package/dist/source-2DJ5KNOI.js +85 -0
  361. package/dist/{source-GBMYD3RO.js.map → source-2DJ5KNOI.js.map} +1 -1
  362. package/dist/source-fetch-github-RWHV4I5Z.js +4 -0
  363. package/dist/{source-fetch-github-ST4MFL3D.js.map → source-fetch-github-RWHV4I5Z.js.map} +1 -1
  364. package/dist/{source-manifest-publish-FK22TVQT.js → source-manifest-publish-IYWUMUCY.js} +55 -57
  365. package/dist/source-manifest-publish-IYWUMUCY.js.map +1 -0
  366. package/dist/transport/index.js +10 -10
  367. package/dist/transport/ws/server.js +10 -10
  368. package/dist/transport/ws.js +10 -10
  369. package/dist/tui/index.js +48 -41
  370. package/dist/tui/index.js.map +1 -1
  371. package/dist/tui/src/repl.d.ts.map +1 -1
  372. package/dist/types/manifests.js +1 -1
  373. package/dist/types/src/install-manifest.d.ts +1 -1
  374. package/dist/types/src/install-manifest.d.ts.map +1 -1
  375. package/dist/types/src/manifests/index.d.ts +1 -1
  376. package/dist/types/src/manifests/index.d.ts.map +1 -1
  377. package/dist/types/src/manifests/scaffold-body.d.ts +2 -0
  378. package/dist/types/src/manifests/scaffold-body.d.ts.map +1 -1
  379. package/dist/workspace-plugin/adapters/mcp.js +30 -30
  380. package/dist/workspace-plugin/adapters/omp.js +15 -15
  381. package/dist/workspace-plugin/index.js +2 -2
  382. package/package.json +1 -1
  383. package/dist/asset-feeds-PXUWCXVI.js.map +0 -1
  384. package/dist/chunk-3JKGY2YC.js.map +0 -1
  385. package/dist/chunk-4DWBSTYA.js.map +0 -1
  386. package/dist/chunk-4XWLB7JB.js.map +0 -1
  387. package/dist/chunk-7XSAW5OC.js.map +0 -1
  388. package/dist/chunk-BFMYYNDT.js.map +0 -1
  389. package/dist/chunk-DUMTLYSO.js.map +0 -1
  390. package/dist/chunk-E3GPGTW3.js.map +0 -1
  391. package/dist/chunk-E572OHGY.js.map +0 -1
  392. package/dist/chunk-F2GOZMRA.js.map +0 -1
  393. package/dist/chunk-GOCWM7FN.js.map +0 -1
  394. package/dist/chunk-HK7HMEPT.js.map +0 -1
  395. package/dist/chunk-KX2PT5Q4.js.map +0 -1
  396. package/dist/chunk-L4YKW5AY.js.map +0 -1
  397. package/dist/chunk-LSI2IVFT.js.map +0 -1
  398. package/dist/chunk-NMI2TWMH.js.map +0 -1
  399. package/dist/chunk-OAHVKSQJ.js.map +0 -1
  400. package/dist/chunk-OHNKYHRR.js.map +0 -1
  401. package/dist/chunk-OTIB4D2K.js.map +0 -1
  402. package/dist/chunk-PUK7TQT4.js +0 -13
  403. package/dist/chunk-PUK7TQT4.js.map +0 -1
  404. package/dist/chunk-QOM5Z62G.js.map +0 -1
  405. package/dist/chunk-SNEE6UGY.js.map +0 -1
  406. package/dist/chunk-T2BDID2J.js.map +0 -1
  407. package/dist/chunk-TKHJXPSB.js.map +0 -1
  408. package/dist/chunk-UL22SDGR.js.map +0 -1
  409. package/dist/chunk-VJRTDKXS.js.map +0 -1
  410. package/dist/chunk-WEH33JSG.js.map +0 -1
  411. package/dist/chunk-WYHQUCHR.js.map +0 -1
  412. package/dist/chunk-X3RMRJNR.js.map +0 -1
  413. package/dist/chunk-XFIEVEU7.js.map +0 -1
  414. package/dist/chunk-YGRZNFRO.js.map +0 -1
  415. package/dist/chunk-Z7ZEZZB6.js.map +0 -1
  416. package/dist/connectors-CXZLXAFZ.js +0 -48
  417. package/dist/ensure-sources-UPTHZKGF.js.map +0 -1
  418. package/dist/flows-TJQIMGUX.js +0 -26
  419. package/dist/helpers-DE53KG3E.js +0 -38
  420. package/dist/library-publish-KKQ2ULLX.js.map +0 -1
  421. package/dist/open-library-RJGJIW5H.js +0 -42
  422. package/dist/open-registry-3QS3J7KO.js +0 -32
  423. package/dist/paths-QAV4C3KX.js +0 -22
  424. package/dist/plugin-store-MSH6GK6T.js +0 -23
  425. package/dist/project-HZW2MZPA.js +0 -84
  426. package/dist/serve-preflight-L4POEHNQ.js +0 -108
  427. package/dist/serve-preflight-L4POEHNQ.js.map +0 -1
  428. package/dist/skills-2LMQ2IAD.js +0 -26
  429. package/dist/source-GBMYD3RO.js +0 -85
  430. package/dist/source-fetch-github-ST4MFL3D.js +0 -4
  431. package/dist/source-manifest-publish-FK22TVQT.js.map +0 -1
package/dist/cli/index.js CHANGED
@@ -1,101 +1,102 @@
1
1
  #!/usr/bin/env node
2
- import { makeValidateCommand, scanIdentities, isRecord } from '../chunk-NMI2TWMH.js';
3
- import { storeNotInstallableReason } from '../chunk-PUK7TQT4.js';
4
- import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError, removeProviderEntry } from '../chunk-3IXIEHUB.js';
5
- import { makeInstallCommand, makeCheckCommand, makeCleanCommand, pinComposedAgents, reportRewritten, reportReplaced, reportRelocked, reportMoved, reportStoreNotChecked, globalProblems, editedConventionFiles, supportsInstallManifest, REF_HINT, reportInstalledSoftDeps } from '../chunk-WEH33JSG.js';
2
+ import { makeValidateCommand, scanIdentities } from '../chunk-Z3IRZBXB.js';
3
+ import { storeNotInstallableReason, mcpNotRunnableHere } from '../chunk-7H6XRCPG.js';
4
+ import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError, removeProviderEntry } from '../chunk-ICSGNT5P.js';
5
+ import { makeInstallCommand, makeCheckCommand, makeCleanCommand, pinComposedAgents, reportRewritten, reportReplaced, reportRelocked, reportMoved, reportStoreNotChecked, globalProblems, editedConventionFiles, supportsInstallManifest, runYamlInstall, REF_HINT, reportInstalledSoftDeps } from '../chunk-ITFCWMOY.js';
6
+ import { reportUnknownHarnesses, reportProjectConfig, agentInstanceErrorLines, isRecord } from '../chunk-LRBP3234.js';
6
7
  import { createSpinner } from '../chunk-NESV47MF.js';
7
- import { getStoreConfig, storeFetch, isStoreAuthenticated, getStoreToken } from '../chunk-VXEYX73S.js';
8
- import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-WYHQUCHR.js';
9
- import { deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, exitOnLibrarySymlinks, resolveLibraryPublisherDetailed, getStoreIdentity, warnLibraryNameFallback, indexLibrary, warnIgnoredDomainFiles, removedDomainOption, rejectRemovedDomainOption, requireValidPublisherOrExit, exitOnManifestPublisherProblems, findAssetManifestFile, checkAssetFile, registerLibraryAsset, DOMAIN_REMOVED_HINT, reportLibrarySymlinks, checkAsset, manifestPublisherProblems, exitOnManifestRootProblems, manifestRequiresProblems, composeRefContext, registeredAssetKeys, assetEntryRef, duplicateAssetMessage, unresolvedManifestDependencies, findEntryManifestFile, unheldRequiresOfFile, warnLegacyBundleFiles, checkComposeKinds } from '../chunk-TKHJXPSB.js';
10
- import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-DHYSUJ3H.js';
11
- import { AI_RESOURCES } from '../chunk-2UUKCROR.js';
12
- import { loadDeclaredPlugins } from '../chunk-YGRZNFRO.js';
13
- import { status, enable, disable, install, uninstall } from '../chunk-Y2TO2U7W.js';
14
- import { logErr, S, logOk, logInfo, logWarn, TARGET_DEFAULT_HINT, parseHarnessFilter, requireProjectConfig, deferredWarnings, warnPlaceholderBodies, warnFilesOnlyDelegates, reportLegacyOmpCopies, logNoProject, warnLegacyClaudeCopies, kindColorPad, kindColor, colorRef, formatSoftDepSection, bareSoftDepName, formatSoftDepHint, formatRelativeTime, formatSoftDepRemovePreview, formatSoftDepAddPreview, fitWidth, KIND_COL_WIDTH } from '../chunk-KX2PT5Q4.js';
15
- import { getKindRegistry, getKnownKinds } from '../chunk-ARWKK325.js';
8
+ import { loadDeclaredPlugins } from '../chunk-BY5WIRCU.js';
9
+ import { getStoreConfig, storeFetch, isStoreAuthenticated, getStoreToken } from '../chunk-KB56WBQ3.js';
10
+ import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-PMWRM4EJ.js';
11
+ import { libraryAssetRefusals, manifestEntryRenames, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, exitOnLibrarySymlinks, resolveLibraryPublisherDetailed, getStoreIdentity, warnLibraryNameFallback, indexLibrary, warnIgnoredDomainFiles, removedDomainOption, rejectRemovedDomainOption, requireValidPublisherOrExit, exitOnManifestPublisherProblems, findAssetManifestFile, checkAssetFile, registerLibraryAsset, DOMAIN_REMOVED_HINT, reportLibrarySymlinks, checkAsset, manifestPublisherProblems, exitOnManifestPathProblems, manifestRequiresProblems, composeRefContext, registeredAssetKeys, assetEntryRef, duplicateAssetMessage, manifestParseFailureLine, manifestParseErrorText, unresolvedManifestDependencies, findEntryManifestFile, unheldRequiresOfFile, warnLegacyBundleFiles, checkComposeKinds } from '../chunk-2XM3ZH36.js';
12
+ import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-BEYNH2LS.js';
13
+ import { AI_RESOURCES } from '../chunk-5LQ62LNT.js';
14
+ import { status, enable, disable, install, uninstall } from '../chunk-MM4YO3EL.js';
15
+ import { logErr, unknownHarnessTargetMessage, S, logOk, logInfo, logWarnErr, unknownHarnessMessage, logWarn, TARGET_DEFAULT_HINT, parseHarnessFilter, requireProjectConfig, deferredWarnings, warnPlaceholderBodies, warnFilesOnlyDelegates, reportLegacyOmpCopies, logNoProject, warnStaleHarnessCopies, kindColorPad, kindColor, colorRef, formatSoftDepSection, bareSoftDepName, driverAliasOption, foldDriverFlag, friendlyHarnessError, harnessErrorNotes, formatSoftDepHint, formatRelativeTime, formatSoftDepRemovePreview, formatSoftDepAddPreview, fitWidth, KIND_COL_WIDTH } from '../chunk-T2VBPVWZ.js';
16
+ import { getKindRegistry, getKnownKinds } from '../chunk-JJJ2G4K2.js';
16
17
  import { LocalSecretsProvider } from '../chunk-ILFGVSTJ.js';
17
- import { resolveInstanceAgentDir, instanceSessionOverrides, runAgentChat, isCompositionError, resolveSessionId, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, hashAgentFiles, createCompositionContentSource, compileComposition, manifestModelForHarness, instanceForSession, resolveAgentInstance, describeComposition, MarkdownStreamer, createFinalTextFallback } from '../chunk-VJRTDKXS.js';
18
- import '../chunk-VBI7HGHB.js';
19
- import '../chunk-OULSJRXV.js';
20
- import '../chunk-7TPYPVAH.js';
21
- import '../chunk-SRODW6M2.js';
18
+ import { resolveInstanceAgentDir, instanceSessionOverrides, runAgentChat, isCompositionError, resolveSessionId, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, hashAgentFiles, createCompositionContentSource, compileComposition, manifestModelForHarness, instanceForSession, resolveAgentInstance, describeComposition, MarkdownStreamer, createFinalTextFallback } from '../chunk-SJNZ4WPA.js';
19
+ import '../chunk-GF5JXQIZ.js';
20
+ import '../chunk-OCQNUV4T.js';
21
+ import '../chunk-ZWJCRHP3.js';
22
+ import '../chunk-Q5RN4PWV.js';
22
23
  import '../chunk-WYZXSJBK.js';
23
- import '../chunk-U56GGCC2.js';
24
- import '../chunk-6Z5KTFJT.js';
24
+ import '../chunk-QK7AG5AV.js';
25
+ import '../chunk-TSTRH4SM.js';
25
26
  import '../chunk-KW37WNXY.js';
26
27
  import '../chunk-3MWQKQUB.js';
27
- import '../chunk-E3GPGTW3.js';
28
+ import '../chunk-3HACK2Z7.js';
28
29
  import '../chunk-O7SG5PC2.js';
29
30
  import '../chunk-7QBNJTTQ.js';
30
31
  import '../chunk-O2SYFJWP.js';
31
- import '../chunk-AF432MS3.js';
32
+ import '../chunk-KXJMQTOU.js';
32
33
  import '../chunk-32NA4TVC.js';
33
34
  import '../chunk-W3UDISS2.js';
34
- import '../chunk-ZFUZ5AKM.js';
35
- import { runFlow, resumeFlow } from '../chunk-T2BDID2J.js';
35
+ import '../chunk-I7LC5TDY.js';
36
+ import { runFlow, resumeFlow } from '../chunk-5JPW27BI.js';
36
37
  import '../chunk-4R6DROGN.js';
37
- import { parseSkillRequirements, validateRequirements } from '../chunk-FKU57Q5Q.js';
38
- import '../chunk-H6UVIKQ2.js';
39
- import '../chunk-SNEE6UGY.js';
38
+ import { parseSkillRequirements, validateRequirements } from '../chunk-URCJIV7T.js';
39
+ import '../chunk-PNUM7GUY.js';
40
+ import '../chunk-K3R2UKG7.js';
40
41
  import '../chunk-6GWSDPBP.js';
41
- import '../chunk-LN6QB7XI.js';
42
- import { checkModelProvider, checkHarnessModel } from '../chunk-4XWLB7JB.js';
43
- import '../chunk-WDAIWDLK.js';
44
- import '../chunk-4DWBSTYA.js';
45
- import '../chunk-JDR6ILCW.js';
42
+ import '../chunk-QIHL3YPL.js';
43
+ import { checkHarnessModel, checkModelProvider } from '../chunk-RQMIZONH.js';
44
+ import '../chunk-JFLQICIU.js';
45
+ import '../chunk-QXKUFROW.js';
46
+ import '../chunk-U673DB5U.js';
46
47
  import '../chunk-LOO5CB5M.js';
47
48
  import '../chunk-BIRW3HOG.js';
48
- import '../chunk-7CV3HFWJ.js';
49
- import '../chunk-GEQSUC6U.js';
50
- import '../chunk-XFIEVEU7.js';
49
+ import '../chunk-TZERN27L.js';
50
+ import '../chunk-BOT64P3U.js';
51
+ import '../chunk-6OHZUUR7.js';
51
52
  import '../chunk-7DN6JKP2.js';
52
- import '../chunk-UVVVR4XO.js';
53
- import { listHarnesses, getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-F2GOZMRA.js';
53
+ import '../chunk-M4OG2YN4.js';
54
+ import { listHarnesses, getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-X37JUNEW.js';
54
55
  import '../chunk-G5SUWZEU.js';
55
56
  import '../chunk-IFGTRL2I.js';
56
- import { loadFlow, flowLookupRoots, findFlowFileInRoots, loadAllFlowEntries } from '../chunk-SZXGRHQQ.js';
57
+ import { loadFlow, flowLookupRoots, findFlowFileInRoots, loadAllFlowEntries } from '../chunk-PJJSBZZP.js';
57
58
  import '../chunk-WD3L5QSU.js';
58
- import { nodeLabel, nodeSkillAsset, nodeIsInert, nodeIsOptional, nodeRunKind } from '../chunk-7RGTAEG6.js';
59
+ import { nodeLabel, nodeSkillAsset, nodeIsInert, nodeIsOptional, nodeRunKind, nodeAssets } from '../chunk-7RGTAEG6.js';
59
60
  import '../chunk-JCPD4QRM.js';
60
- import { LibraryEntryError, AssetManager, parseRefTolerant, MissingManifestError, parseCanonicalLockKey, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-OAHVKSQJ.js';
61
- import { CatalogHttpError, libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, isGitRepo, ensureGitRepo, conflictingAssetRoot, scanUnlistedAssets, setManifestPublisher, LIBRARY_OWNERSHIPS, assertManifestEditable, installLibraryAsset, getStoreManifestsDir, assertValidLibraryName, unparsableAssetFiles, syncManifestWithDisk, renamedLibraryName, storeManifestFile, getDefaultValue, isSecretPlaceholder } from '../chunk-UL22SDGR.js';
62
- import { flowFileNameError, SEMVER_RE } from '../chunk-QOM5Z62G.js';
63
- import '../chunk-7XSAW5OC.js';
64
- import '../chunk-BFMYYNDT.js';
61
+ import { setLibraryAssetCheck, setRenamedEntryLookup, LibraryEntryError, AssetManager, parseRefTolerant, MissingManifestError, parseCanonicalLockKey, normalizeRepoUrl } from '../chunk-PKBLJI23.js';
62
+ import { CatalogHttpError, libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, isGitRepo, ensureGitRepo, conflictingAssetRoot, scanUnlistedAssets, setManifestPublisher, LIBRARY_OWNERSHIPS, assertManifestEditable, installLibraryAsset, getStoreManifestsDir, assertValidLibraryName, unparsableAssetFiles, syncManifestWithDisk, renamedLibraryName, storeManifestFile, getDefaultValue, isSecretPlaceholder } from '../chunk-6CYKTHNT.js';
63
+ import { flowFileNameError, SEMVER_RE } from '../chunk-MAZ3UXJK.js';
64
+ import '../chunk-E5NQRHEB.js';
65
+ import '../chunk-F3D25RGM.js';
65
66
  import '../chunk-3TXEJN4W.js';
66
67
  import '../chunk-ISHJITXJ.js';
67
68
  import '../chunk-LNFKL23K.js';
68
- import '../chunk-X3RMRJNR.js';
69
+ import '../chunk-JRN5QF4C.js';
69
70
  import '../chunk-NUELZWCF.js';
70
- import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-3JKGY2YC.js';
71
- import '../chunk-NOA6EJXE.js';
71
+ import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-S2H3RBK7.js';
72
+ import '../chunk-PKE3PXOK.js';
72
73
  import '../chunk-KTBKW2FI.js';
73
74
  import '../chunk-UQ6LFBPZ.js';
74
- import '../chunk-DUMTLYSO.js';
75
- import { effectiveComposes, validatePreset, validateAgent, composeSlotDiagnostics, agentDeprecationDiagnostics, SLOT_ID_PATTERN } from '../chunk-E572OHGY.js';
76
- import { loadSettings, globalSettingsPath, resolveSettings, projectSettingsPath, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, resolveSettingsWithSources, readLock, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile, aiResourceRoots } from '../chunk-L4YKW5AY.js';
75
+ import '../chunk-COAFAYBS.js';
76
+ import { effectiveComposes, validatePreset, validateAgent, composeSlotDiagnostics, agentDeprecationDiagnostics, SLOT_ID_PATTERN } from '../chunk-76FLBODK.js';
77
+ import { loadSettings, globalSettingsPath, resolveSettings, projectSettingsPath, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, resolveSettingsWithSources, resolveConfiguredHarnessName, readLock, FACTORY_SOURCE_URL, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile, aiResourceRoots } from '../chunk-BRK5QZKI.js';
77
78
  import '../chunk-4GY63JU6.js';
78
- import { factoryAssetRoots } from '../chunk-OTIB4D2K.js';
79
+ import { factoryAssetRoots } from '../chunk-QPWR3YMY.js';
79
80
  import { deployedDir } from '../chunk-5KRMNUL4.js';
80
- import { DEFAULT_HARNESS_ID, HARNESS_DEFAULTS } from '../chunk-Z7ZEZZB6.js';
81
+ import { DEFAULT_HARNESS_ID, HARNESS_DEFAULTS } from '../chunk-C5HFK34M.js';
81
82
  import { findKindDirs } from '../chunk-MWXYN6NY.js';
82
- import { SourceEntryError, LegacyKeyError, resolveSkWorkspaceConfig, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, effectiveAgentInstances, matchPin, coerceVersion, loadSkWorkspaceConfig, findWorkspaceRoot, isWorkspaceConfigFilename, SKAILE_YAML_DEFAULT, AGENT_PROFILE_FIELDS } from '../chunk-OHNKYHRR.js';
83
+ import { SourceEntryError, LegacyKeyError, resolveSkWorkspaceConfig, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, effectiveAgentInstances, matchPin, coerceVersion, loadSkWorkspaceConfig, findWorkspaceRoot, isWorkspaceConfigFilename, SKAILE_YAML_DEFAULT, AGENT_PROFILE_FIELDS } from '../chunk-KJSC2ZD6.js';
83
84
  import { globalCacheRoot, globalSkaileDir, userConfigPath } from '../chunk-L5VSIPQD.js';
84
85
  import { HARNESS_TARGETS, SUPPORTED_HARNESSES, harnessNameForHarnessId } from '../chunk-VTETQCR6.js';
85
- import { SKAILE_MANIFEST_FILENAME, loadSkPublishManifest, decodeSkaileManifest, LIBRARY_GITIGNORE, librarySymlinkMessage, isNonAssetPath, isNonAssetDir, encodeSkaileManifest } from '../chunk-UQ33Y4DM.js';
86
+ import { SKAILE_MANIFEST_FILENAME, loadSkPublishManifest, decodeSkaileManifest, LIBRARY_GITIGNORE, librarySymlinkMessage, isNonAssetPath, isNonAssetDir, encodeSkaileManifest } from '../chunk-KPKGWXUJ.js';
86
87
  import { pluginTitle } from '../chunk-RVRB27AN.js';
87
- import { dedupeRequirements, parseFrontmatter, scanDirectory, parseRequires } from '../chunk-GOCWM7FN.js';
88
- import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, depToStr, assetRefToStr, slugifyAssetName, parseAssetRefLoose } from '../chunk-WDXZA7QW.js';
89
- import { portableSpawn, portableSpawnSync } from '../chunk-ADPM6AYF.js';
88
+ import { setWalkTruncationSink, dedupeRequirements, parseFrontmatter, scanDirectory, parseRequires } from '../chunk-JMIKGAUA.js';
89
+ import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, depToStr, assetRefToStr, slugifyAssetName, parseAssetRefLoose } from '../chunk-IZQOO6MN.js';
90
+ import { portableSpawn, portableSpawnSync } from '../chunk-VSX2G7LA.js';
90
91
  import { openSqlite } from '../chunk-DKXNKFKP.js';
91
- import { parseModelRef, resolveEntryBaseUrl } from '../chunk-LSI2IVFT.js';
92
+ import { parseModelRef, resolveEntryBaseUrl } from '../chunk-RXGPFAMN.js';
92
93
  import '../chunk-C3CAXQMA.js';
93
94
  import { registerLogStore, LogStore, StdoutSink } from '../chunk-BOFL7GIF.js';
94
95
  import '../chunk-NSBPE2FW.js';
95
96
  import * as fs8 from 'fs';
96
97
  import fs8__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
97
- import * as path18 from 'path';
98
- import path18__default, { resolve, join } from 'path';
98
+ import * as path19 from 'path';
99
+ import path19__default, { resolve, join } from 'path';
99
100
  import { fileURLToPath } from 'url';
100
101
  import { Help, Command, Option } from 'commander';
101
102
  import { rcompare } from 'semver';
@@ -224,21 +225,29 @@ async function runSearch(kind, query, opts) {
224
225
  const showLocal = !opts.store;
225
226
  const showStore = !opts.local;
226
227
  const { resolveConfig } = await import('../library/index.js');
227
- const airGapped = resolveConfig({ projectDir: path18__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
228
- if (showLocal) {
229
- await searchLocal(query, kind, opts, showStore, airGapped);
230
- }
231
- if (showStore) {
232
- await searchStore(query, kind, opts, airGapped);
228
+ const airGapped = resolveConfig({ projectDir: path19__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
229
+ const localHits = showLocal ? await searchLocal(query, kind, opts, showStore, airGapped) : false;
230
+ const store = showStore ? await searchStore(query, kind, opts, airGapped) : "skipped";
231
+ if (showLocal && showStore && !localHits && store !== "hits") {
232
+ const what = query ? ` for "${query}"` : kind ? ` for kind "${kind}"` : "";
233
+ logInfo(
234
+ store === "empty" ? `No results${what} (local and store).` : `No local results${what}; the store was not searched.`
235
+ );
233
236
  }
234
237
  }
235
- async function searchIndex(query, kind) {
236
- const { openLibrary: openLibrary2 } = await import('../open-library-RJGJIW5H.js');
238
+ async function searchIndex(query, kind, projectDir) {
239
+ const { openLibrary: openLibrary2 } = await import('../open-library-XBR46DJL.js');
237
240
  const library = await openLibrary2();
238
241
  try {
239
242
  const { libraryDirMissing: libraryDirMissing2 } = await import('../library/index.js');
240
243
  const sources = await library.listSources();
241
244
  const gone = new Set(sources.filter(libraryDirMissing2).map((l) => l.id));
245
+ for (const id of new AssetManager({
246
+ registry: getKindRegistry(),
247
+ projectDir
248
+ }).undeclaredSourceClones(sources)) {
249
+ gone.add(id);
250
+ }
242
251
  const defs = (await library.listAssetDefs(kind ? { kind } : {})).filter((d) => !d.libraryId || !gone.has(d.libraryId));
243
252
  const libraryNames = new Map(sources.map((l) => [l.id, l.name]));
244
253
  let entries = defs.map(
@@ -270,7 +279,7 @@ async function searchIndex(query, kind) {
270
279
  }
271
280
  }
272
281
  async function searchFactory(projectDir, query, kind) {
273
- const prefixes = factoryAssetRoots().map((r) => r.endsWith(path18__default.sep) ? r : r + path18__default.sep);
282
+ const prefixes = factoryAssetRoots().map((r) => r.endsWith(path19__default.sep) ? r : r + path19__default.sep);
274
283
  const isFactoryPath = (p6) => prefixes.some((fp) => p6 === fp.slice(0, -1) || p6.startsWith(fp));
275
284
  try {
276
285
  const entries = await new AssetManager({ registry: getKindRegistry(), projectDir }).search(
@@ -383,18 +392,35 @@ async function expandCompetingOrigins(entries, projectDir) {
383
392
  }
384
393
  return out;
385
394
  }
395
+ async function withAddVersions(entries, projectDir) {
396
+ if (!entries.some((e) => e.library && e.publisher)) return entries;
397
+ let versions;
398
+ try {
399
+ versions = await new AssetManager({
400
+ registry: getKindRegistry(),
401
+ projectDir
402
+ }).sourceAssetVersions();
403
+ } catch {
404
+ return entries;
405
+ }
406
+ if (versions.size === 0) return entries;
407
+ return entries.map((e) => {
408
+ const v = e.library ? versions.get(`${e.library}\0${entryDedupKey(e)}`) : void 0;
409
+ return v && v !== e.version ? { ...e, version: v } : e;
410
+ });
411
+ }
386
412
  async function searchLocal(query, kind, opts, showStore, airGapped) {
387
- const projectDir = path18__default.resolve(opts.projectDir);
388
- const { restoreSourceReaders } = await import('../source-GBMYD3RO.js');
413
+ const projectDir = path19__default.resolve(opts.projectDir);
414
+ const { restoreSourceReaders } = await import('../source-2DJ5KNOI.js');
389
415
  for (const name of await restoreSourceReaders(projectDir)) {
390
416
  logInfo(`Re-registered source "${name}" (its library entry was removed elsewhere).`);
391
417
  }
392
418
  const factory = await searchFactory(projectDir, query, kind);
393
- let entries = unionEntries(await searchIndex(query, kind), factory);
419
+ let entries = unionEntries(await searchIndex(query, kind, projectDir), factory);
394
420
  if (entries.length === 0 && !query && !kind && !airGapped) {
395
- const { autoSyncForSearch } = await import('../source-GBMYD3RO.js');
421
+ const { autoSyncForSearch } = await import('../source-2DJ5KNOI.js');
396
422
  if (await autoSyncForSearch(projectDir)) {
397
- entries = unionEntries(await searchIndex(query, kind), factory);
423
+ entries = unionEntries(await searchIndex(query, kind, projectDir), factory);
398
424
  }
399
425
  }
400
426
  if (entries.length === 0) {
@@ -403,15 +429,19 @@ async function searchLocal(query, kind, opts, showStore, airGapped) {
403
429
  query ? `No entries matching "${query}".` : kind ? `No "${kind}" assets found in this project's sources.` : "No assets found. Run `skaile source sync` first."
404
430
  );
405
431
  }
406
- return;
432
+ return false;
407
433
  }
408
434
  if (showStore) {
409
435
  console.log(`
410
436
  ${S.heading("Local:")}`);
411
437
  }
412
438
  printLocalEntries(
413
- await expandCompetingOrigins(await expandLibraryCopies(entries, projectDir), projectDir)
439
+ await withAddVersions(
440
+ await expandCompetingOrigins(await expandLibraryCopies(entries, projectDir), projectDir),
441
+ projectDir
442
+ )
414
443
  );
444
+ return true;
415
445
  }
416
446
  var MIN_LOCAL_DESCRIPTION_WIDTH = 10;
417
447
  function layoutLocalTable(rows, width, style = {}) {
@@ -504,11 +534,11 @@ function formatStoreRows(assets, indent, width = terminalWidth()) {
504
534
  async function searchStore(query, kind, opts, airGapped) {
505
535
  if (airGapped && !opts.store) {
506
536
  logInfo("air-gapped (cache_ttl: 0) \u2014 local sources only");
507
- return;
537
+ return "skipped";
508
538
  }
509
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-RJGJIW5H.js');
539
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-XBR46DJL.js');
510
540
  try {
511
- const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
541
+ const remote = await openCatalogSource2({ projectDir: path19__default.resolve(opts.projectDir) });
512
542
  const assets = await remote.listAssets(kind ? { kind } : {});
513
543
  const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
514
544
  if (sel.shown.length > 0) {
@@ -519,11 +549,12 @@ async function searchStore(query, kind, opts, airGapped) {
519
549
  logInfo("No results in store");
520
550
  }
521
551
  for (const note of storeSelectionNotes(sel, " ")) console.log(note);
552
+ return sel.shown.length > 0 ? "hits" : "empty";
522
553
  } catch (e) {
523
554
  const local = e instanceof LocalCatalogDisabledError2;
524
555
  if (opts.store) {
525
556
  logErr(
526
- local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${await describeStoreFailure(e, path18__default.resolve(opts.projectDir))}`
557
+ local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${await describeStoreFailure(e, path19__default.resolve(opts.projectDir))}`
527
558
  );
528
559
  process.exit(1);
529
560
  } else {
@@ -531,6 +562,7 @@ async function searchStore(query, kind, opts, airGapped) {
531
562
  local ? "remote catalog disabled (catalog.url: local) \u2014 showing local results only" : "store unavailable \u2014 showing local results only (run with --store to see the error)"
532
563
  );
533
564
  }
565
+ return "skipped";
534
566
  }
535
567
  }
536
568
  async function describeStoreFailure(err, projectDir) {
@@ -615,6 +647,9 @@ function makeAddCommand() {
615
647
  return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:@<publisher>/name#<version>)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Record in ~/.skaile/skaile.yaml + deploy to every global harness").option(
616
648
  "--harness <ids>",
617
649
  "Comma-separated global harnesses to deploy into (default: all resolved); implies --global"
650
+ ).option(
651
+ "--only",
652
+ "with --harness on an asset that is already global: replace its harness set (default: add to it)"
618
653
  ).option("--target <agent>", `Harness target (${TARGET_DEFAULT_HINT})`).option(
619
654
  "--link",
620
655
  "symlink local-path assets instead of copying (dev loop; machine-local, not for committing)"
@@ -624,18 +659,25 @@ function makeAddCommand() {
624
659
  ).option("--no-soft-deps", "skip the soft-dep prompt entirely (don't add, don't report)").option(
625
660
  "--force",
626
661
  "overwrite a deployed folder that no lock entry owns (a hand-made skill of the same name)"
627
- ).option("--verbose", "print the full `exists in N libraries` warning for every asset").action(async (ref, opts) => {
662
+ ).option("--verbose", "print the full `exists in N libraries` warning for every asset").option(
663
+ "--dry-run",
664
+ "show the library, version, dependencies and folders the add would use; change nothing"
665
+ ).action(async (ref, opts) => {
628
666
  if (opts.withSoftDeps && opts.softDeps === false) {
629
667
  logErr("--with-soft-deps and --no-soft-deps are mutually exclusive.");
630
668
  process.exit(1);
631
669
  }
632
670
  const harnesses = parseHarnessFilter(opts.harness);
671
+ if (opts.only && harnesses === void 0) {
672
+ logErr("--only needs --harness: it replaces the set of harnesses the asset goes to.");
673
+ process.exit(1);
674
+ }
633
675
  if (!opts.global && harnesses === void 0) requireProjectConfig(opts.projectDir);
634
676
  const warnings = deferredWarnings();
635
677
  const collisionKeys = [];
636
678
  const am2 = new AssetManager({
637
679
  registry: getKindRegistry(),
638
- projectDir: path18__default.resolve(opts.projectDir),
680
+ projectDir: path19__default.resolve(opts.projectDir),
639
681
  global: opts.global || harnesses !== void 0,
640
682
  harnesses,
641
683
  harness: opts.target,
@@ -653,9 +695,16 @@ function makeAddCommand() {
653
695
  const placeholderDescriptions = [];
654
696
  let presets = [];
655
697
  const skippedSecrets = /* @__PURE__ */ new Set();
698
+ let plan = [];
656
699
  const added = await am2.add(ref, {
657
700
  link: opts.link,
658
701
  force: opts.force,
702
+ only: opts.only === true,
703
+ onDroppedCopy: (droppedRef, harness, copy) => logInfo(
704
+ S.dim(
705
+ `${harness} is no longer in the set of ${droppedRef} but still holds ${copy.replace(homedir(), "~")} (delete it with skaile remove ${droppedRef} --global --harness ${harness})`
706
+ )
707
+ ),
659
708
  onLibraryOrigin: (deployedRef, library) => libraryOf.set(deployedRef, library),
660
709
  onPlaceholderBody: (deployedRef) => placeholderBodies.push(deployedRef),
661
710
  onPlaceholderDescription: (deployedRef) => placeholderDescriptions.push(deployedRef),
@@ -671,9 +720,18 @@ function makeAddCommand() {
671
720
  warnings.push(
672
721
  `${secretPath} looks like a secret: it is not deployed or hashed with the asset. Keep secrets out of an asset root`
673
722
  );
723
+ },
724
+ dryRun: opts.dryRun === true,
725
+ onPlan: (items) => {
726
+ plan = items;
674
727
  }
675
728
  });
676
- spinner.stop("Done");
729
+ spinner.stop(opts.dryRun ? "Planned" : "Done");
730
+ if (opts.dryRun) {
731
+ warnings.flush();
732
+ printAddPlan(plan);
733
+ return;
734
+ }
677
735
  warnings.flush();
678
736
  if (!am2.global) await pinComposedAgents(am2.projectDir);
679
737
  await promptSoftDepAdds(am2, ref, {
@@ -708,24 +766,24 @@ function makeAddCommand() {
708
766
  logInfo(
709
767
  `Recorded in skaile.yaml (store bytes are fetched + verified into .skaile/cache/store). ${kind} assets are not deployed into the harness target \u2014 they are composed when skaile runs the agent.`
710
768
  );
711
- else logInfo("Nothing to deploy (already up to date).");
769
+ else {
770
+ logInfo("Nothing to deploy (already up to date).");
771
+ if (am2.global) reportGlobalPaths(am2, [parsedRef]);
772
+ }
712
773
  } else {
713
774
  for (const a of added) {
714
775
  const library = libraryOf.get(a);
715
776
  logOk(library ? `${a} (library ${library})` : a);
716
777
  }
717
778
  warnPlaceholderBodies(placeholderBodies, placeholderDescriptions);
718
- if (!am2.global) warnFilesOnlyDelegates(am2.projectDir, am2.harness);
779
+ if (!am2.global && added.some((a) => a.startsWith("agent:"))) {
780
+ warnFilesOnlyDelegates(am2.projectDir, am2.harness);
781
+ }
719
782
  if (am2.global) {
720
- for (const a of added) {
721
- const { kind, name } = parseAssetRef(a);
722
- const component = installTargetOf(getKindRegistry(), kind);
723
- if (!component) continue;
724
- for (const harness of am2.deployTargets()) {
725
- const dir = deployedDir(component, name, harness, true);
726
- if (existsSync(dir)) logInfo(S.dim(`${harness}: ${dir.replace(homedir(), "~")}`));
727
- }
728
- }
783
+ reportGlobalPaths(
784
+ am2,
785
+ added.map((a) => parseAssetRef(a))
786
+ );
729
787
  reportLegacyOmpCopies(am2.takeLegacyCopiesRemoved(), am2.takeLegacyCopiesKept());
730
788
  }
731
789
  if (added.length > 1) {
@@ -754,6 +812,29 @@ function makeAddCommand() {
754
812
  }
755
813
  });
756
814
  }
815
+ function reportGlobalPaths(am2, assets) {
816
+ for (const { kind, name } of assets) {
817
+ const component = installTargetOf(getKindRegistry(), kind);
818
+ if (!component) continue;
819
+ for (const harness of am2.deployTargets()) {
820
+ const dir = deployedDir(component, name, harness, true);
821
+ if (existsSync(dir)) logInfo(S.dim(`${harness}: ${dir.replace(homedir(), "~")}`));
822
+ }
823
+ }
824
+ }
825
+ function printAddPlan(plan) {
826
+ const line = (item, label) => {
827
+ logInfo(
828
+ `${label} ${colorRef(item.ref)}${item.version ? `#${item.version}` : ""} (${item.origin})`
829
+ );
830
+ for (const folder of item.folders) console.log(` folder: ${S.dim(folder)}`);
831
+ for (const file of item.renders) console.log(` writes: ${S.dim(file)}`);
832
+ if (item.files.length > 0) console.log(` files: ${S.dim(item.files.join(", "))}`);
833
+ };
834
+ for (const item of plan.filter((i) => i.requested)) line(item, "Would add");
835
+ for (const item of plan.filter((i) => !i.requested)) line(item, "Would also add");
836
+ logInfo("Dry run: nothing was changed.");
837
+ }
757
838
  function readableError(err) {
758
839
  if (err instanceof Error && err.code === "unknown_asset_kind") {
759
840
  return `Error: ${err.message.replace(/^unknown_asset_kind: /, "")}`;
@@ -773,7 +854,7 @@ function makeRemoveCommand() {
773
854
  requireProjectConfig(opts.projectDir, { allowMissing: true });
774
855
  const am2 = new AssetManager({
775
856
  registry: getKindRegistry(),
776
- projectDir: path18__default.resolve(opts.projectDir),
857
+ projectDir: path19__default.resolve(opts.projectDir),
777
858
  global: opts.global || harnesses !== void 0,
778
859
  harnesses,
779
860
  harness: opts.target
@@ -801,7 +882,8 @@ function makeRemoveCommand() {
801
882
  ", "
802
883
  )} (lock entry) \u2014 it was kept; remove that asset to delete it, or \`skaile remove ${ref} --force\`` : void 0;
803
884
  if (!result.changed) {
804
- logErr(`Not deployed or declared: ${ref}`);
885
+ const otherKind = await am2.otherKindHint(ref);
886
+ logErr(`Not deployed or declared: ${ref}${otherKind ? `. ${otherKind}` : ""}`);
805
887
  if (keptNote) logInfo(keptNote);
806
888
  if (ownerNote) logInfo(ownerNote);
807
889
  process.exitCode = 1;
@@ -813,6 +895,9 @@ function makeRemoveCommand() {
813
895
  for (const dep of result.pruned) {
814
896
  logOk(`Removed ${dep} (no longer required by anything declared in skaile.yaml)`);
815
897
  }
898
+ for (const setting of result.droppedSettings ?? []) {
899
+ logOk(`Removed ${setting} from skaile.yaml (it only set values for ${ref})`);
900
+ }
816
901
  await promptSoftDepRemovals(am2, ref, {
817
902
  isTTY: !!process.stdin.isTTY,
818
903
  noSoftDeps: opts.softDeps === false,
@@ -843,9 +928,10 @@ function makeListCommand() {
843
928
  runGlobalList(kind, opts, harnesses);
844
929
  return;
845
930
  }
931
+ if (await reportUnknownHarnesses(path19__default.resolve(opts.projectDir)) > 0) process.exit(1);
846
932
  const am2 = new AssetManager({
847
933
  registry: getKindRegistry(),
848
- projectDir: path18__default.resolve(opts.projectDir),
934
+ projectDir: path19__default.resolve(opts.projectDir),
849
935
  harness: opts.target
850
936
  });
851
937
  let declared;
@@ -862,7 +948,7 @@ function makeListCommand() {
862
948
  }
863
949
  if (declared.length === 0) {
864
950
  logInfo("No dependencies declared in skaile.yaml.");
865
- warnLegacyClaudeCopies(am2);
951
+ warnStaleHarnessCopies(am2);
866
952
  return;
867
953
  }
868
954
  const kindW = Math.max(4, ...declared.map((e) => e.kind.length));
@@ -888,14 +974,14 @@ function makeListCommand() {
888
974
  const invalid = declared.filter((e) => e.state === "invalid").length;
889
975
  if (invalid > 0)
890
976
  logInfo(`${invalid} invalid \u2014 fix the ${S.cmd("skaile.yaml")} dependencies entry.`);
891
- warnLegacyClaudeCopies(am2);
977
+ warnStaleHarnessCopies(am2);
892
978
  console.log();
893
979
  });
894
980
  }
895
981
  function runGlobalList(kind, opts, harnesses) {
896
982
  const am2 = new AssetManager({
897
983
  registry: getKindRegistry(),
898
- projectDir: path18__default.resolve(opts.projectDir),
984
+ projectDir: path19__default.resolve(opts.projectDir),
899
985
  global: true,
900
986
  harnesses
901
987
  });
@@ -974,7 +1060,7 @@ function infoVersionLine(locked, latest) {
974
1060
  }
975
1061
  function lockedVersionOf(projectDir, kind, name, publisher) {
976
1062
  try {
977
- const lock = readLock(path18__default.join(projectDir, "skaile.lock.yaml"));
1063
+ const lock = readLock(path19__default.join(projectDir, "skaile.lock.yaml"));
978
1064
  for (const key of Object.keys(lock?.assets ?? {})) {
979
1065
  const id = parseCanonicalLockKey(key);
980
1066
  if (id.kind !== kind || id.name !== name || !id.version) continue;
@@ -1014,7 +1100,7 @@ async function resolveInfoEntry(am2, ref, opts) {
1014
1100
  return { entry: match ?? deployed };
1015
1101
  }
1016
1102
  const lookup = opts.storeLookup ?? (async (filter) => {
1017
- const { resolveCatalogSource } = await import('../open-library-RJGJIW5H.js');
1103
+ const { resolveCatalogSource } = await import('../open-library-XBR46DJL.js');
1018
1104
  const { source, close } = await resolveCatalogSource({ projectDir: opts.projectDir });
1019
1105
  try {
1020
1106
  return await source.listAssets(filter);
@@ -1030,7 +1116,7 @@ async function resolveInfoEntry(am2, ref, opts) {
1030
1116
  );
1031
1117
  return { entry: hit ? catalogAssetToEntry(hit) : null };
1032
1118
  } catch (err) {
1033
- const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-RJGJIW5H.js');
1119
+ const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-XBR46DJL.js');
1034
1120
  const storeNote = err instanceof Error ? err.message : String(err);
1035
1121
  const disabled = err instanceof LocalCatalogDisabledError2 || /catalog\.url/i.test(storeNote);
1036
1122
  return { entry: null, storeNote, ...disabled ? { storeDisabled: true } : {} };
@@ -1046,7 +1132,7 @@ function infoNotFoundHint(ref, lookup) {
1046
1132
  }
1047
1133
  function makeInfoCommand() {
1048
1134
  return new Command("info").description("Show asset metadata, deps, deploy status").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
1049
- const projectDir = path18__default.resolve(opts.projectDir);
1135
+ const projectDir = path19__default.resolve(opts.projectDir);
1050
1136
  requireProjectConfig(projectDir, { allowMissing: true });
1051
1137
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
1052
1138
  let lookup;
@@ -1058,7 +1144,8 @@ function makeInfoCommand() {
1058
1144
  }
1059
1145
  const entry = lookup.entry;
1060
1146
  if (!entry) {
1061
- logErr(infoNotFoundHint(ref, lookup));
1147
+ const otherKind = await am2.otherKindHint(ref);
1148
+ logErr(`${infoNotFoundHint(ref, lookup)}${otherKind ? ` ${otherKind}` : ""}`);
1062
1149
  process.exit(1);
1063
1150
  }
1064
1151
  const softDeps = await am2.softDepsOf([ref]);
@@ -1079,6 +1166,12 @@ function makeInfoCommand() {
1079
1166
  if (entry.publisher) console.log(` repository: ${S.dim(entry.publisher)}`);
1080
1167
  const infoSource = showLocked && entry.source.endsWith(`#${entry.version}`) ? `${entry.source.slice(0, -`#${entry.version}`.length)}#${infoLocked}` : entry.source;
1081
1168
  console.log(` source: ${S.dim(infoSource)}`);
1169
+ const infoLibrary = await am2.lockedLibraryOf(
1170
+ entry.kind,
1171
+ entry.name,
1172
+ parseRefTolerant(ref)?.publisher ?? entry.publisher
1173
+ );
1174
+ if (infoLibrary) console.log(` library: ${S.dim(infoLibrary)}`);
1082
1175
  if (entry.kind === "mcp-server") {
1083
1176
  const skipped = (await am2.mcpNotices()).find(
1084
1177
  (n) => n.kind === "skipped" && (n.id === entry.name || n.id.endsWith(`/${entry.name}`))
@@ -1117,7 +1210,7 @@ function makeCreateCommand() {
1117
1210
  new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...SCAFFOLD_KINDS])
1118
1211
  ).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
1119
1212
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
1120
- const destDir = opts.dir ? path18__default.resolve(opts.dir) : process.cwd();
1213
+ const destDir = opts.dir ? path19__default.resolve(opts.dir) : process.cwd();
1121
1214
  const result = am2.create(name, opts.kind, destDir);
1122
1215
  if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
1123
1216
  else {
@@ -1132,7 +1225,7 @@ function makeDoctorCommand() {
1132
1225
  const problems = globalProblems(
1133
1226
  new AssetManager({
1134
1227
  registry: getKindRegistry(),
1135
- projectDir: path18__default.resolve(opts.projectDir),
1228
+ projectDir: path19__default.resolve(opts.projectDir),
1136
1229
  global: true,
1137
1230
  harnesses: parseHarnessFilter(opts.harness)
1138
1231
  })
@@ -1146,19 +1239,24 @@ function makeDoctorCommand() {
1146
1239
  return;
1147
1240
  }
1148
1241
  requireProjectConfig(opts.projectDir);
1242
+ const configErrors = await reportProjectConfig(path19__default.resolve(opts.projectDir), {
1243
+ harness: true,
1244
+ instances: true
1245
+ });
1246
+ if (configErrors > 0) process.exitCode = 1;
1149
1247
  const am2 = new AssetManager({
1150
1248
  registry: getKindRegistry(),
1151
- projectDir: path18__default.resolve(opts.projectDir)
1249
+ projectDir: path19__default.resolve(opts.projectDir)
1152
1250
  });
1153
1251
  const { gaps } = await am2.projectState();
1154
- const edited = await editedConventionFiles(path18__default.resolve(opts.projectDir));
1252
+ const edited = await editedConventionFiles(path19__default.resolve(opts.projectDir));
1155
1253
  const notices = [
1156
1254
  ...(await am2.mcpNotices()).map((n) => n.text),
1157
1255
  // A library that went back past the lock is no drift either (p1257).
1158
1256
  ...await am2.libraryOlderNotices()
1159
1257
  ];
1160
1258
  if (gaps.length === 0 && edited.length === 0) {
1161
- logOk("No missing dependencies.");
1259
+ if (configErrors === 0) logOk("No missing dependencies.");
1162
1260
  for (const n of notices) logWarn(n);
1163
1261
  return;
1164
1262
  }
@@ -1189,20 +1287,20 @@ function claudeSkillRoots() {
1189
1287
  const roots = [];
1190
1288
  const override = process.env.SKAILE_CLAUDE_SKILLS_DIR;
1191
1289
  if (override) roots.push(override);
1192
- roots.push(path18.join(os.homedir(), ".claude", "skills"));
1290
+ roots.push(path19.join(os.homedir(), ".claude", "skills"));
1193
1291
  return roots;
1194
1292
  }
1195
1293
  function resolveImportSource(nameOrPath) {
1196
- const asPath = path18.resolve(nameOrPath);
1294
+ const asPath = path19.resolve(nameOrPath);
1197
1295
  if (fs8.existsSync(asPath)) {
1198
- const dir = fs8.statSync(asPath).isDirectory() ? asPath : path18.dirname(asPath);
1199
- const skillFile = path18.join(dir, "SKILL.md");
1296
+ const dir = fs8.statSync(asPath).isDirectory() ? asPath : path19.dirname(asPath);
1297
+ const skillFile = path19.join(dir, "SKILL.md");
1200
1298
  if (fs8.existsSync(skillFile)) return { dir, skillFile, via: "path" };
1201
1299
  }
1202
- if (!nameOrPath.includes(path18.sep) && !nameOrPath.startsWith(".")) {
1300
+ if (!nameOrPath.includes(path19.sep) && !nameOrPath.startsWith(".")) {
1203
1301
  for (const root of claudeSkillRoots()) {
1204
- const dir = path18.join(root, nameOrPath);
1205
- const skillFile = path18.join(dir, "SKILL.md");
1302
+ const dir = path19.join(root, nameOrPath);
1303
+ const skillFile = path19.join(dir, "SKILL.md");
1206
1304
  if (fs8.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
1207
1305
  }
1208
1306
  }
@@ -1260,8 +1358,8 @@ ${body}
1260
1358
  // cli/src/commands/asset-cmd.ts
1261
1359
  function copyFilter(root) {
1262
1360
  return (src) => {
1263
- const rel = path18.relative(root, src).split(path18.sep).join("/");
1264
- return rel === "" || !(isNonAssetPath(rel) || isNonAssetDir(path18.basename(src)));
1361
+ const rel = path19.relative(root, src).split(path19.sep).join("/");
1362
+ return rel === "" || !(isNonAssetPath(rel) || isNonAssetDir(path19.basename(src)));
1265
1363
  };
1266
1364
  }
1267
1365
  async function resolveDefByRef(library, ref, opts) {
@@ -1344,16 +1442,16 @@ function makeAssetCommand() {
1344
1442
  }
1345
1443
  const rawSkill = fs8.readFileSync(src.skillFile, "utf8");
1346
1444
  const norm = opts.normalize ? normalizeSkillContent(rawSkill, {
1347
- fallbackName: path18.basename(src.dir),
1445
+ fallbackName: path19.basename(src.dir),
1348
1446
  version: opts.version,
1349
1447
  stage: opts.stage
1350
- }) : { content: rawSkill, name: path18.basename(src.dir), changed: false, notes: [] };
1448
+ }) : { content: rawSkill, name: path19.basename(src.dir), changed: false, notes: [] };
1351
1449
  if (!opts.normalize && !isValidAssetName(norm.name)) {
1352
1450
  logWarn(
1353
1451
  `Name "${norm.name}" is not canonical (kebab-case); \`skaile validate\` will reject this manifest entry. Drop --no-normalize to slugify it.`
1354
1452
  );
1355
1453
  }
1356
- const destDir = path18.join(target.path, norm.name);
1454
+ const destDir = path19.join(target.path, norm.name);
1357
1455
  if (fs8.existsSync(destDir)) {
1358
1456
  logErr(`Destination already exists: ${destDir}`);
1359
1457
  process.exit(1);
@@ -1374,10 +1472,11 @@ function makeAssetCommand() {
1374
1472
  getKindRegistry(),
1375
1473
  norm.content
1376
1474
  );
1377
- if (checked.errors.length > 0) {
1378
- for (const f of checked.errors) logErr(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
1475
+ const refusals = [...checked.errors, ...checked.advisories.filter((f) => f.scaffoldBody)];
1476
+ if (refusals.length > 0) {
1477
+ for (const f of refusals) logErr(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
1379
1478
  logErr(
1380
- `Not imported: ${checked.errors.length} problem(s) in SKILL.md. Fix them in ${src.skillFile} (or drop --no-normalize) and run the import again.`
1479
+ `Not imported: ${refusals.length} problem(s) in SKILL.md. Fix them in ${src.skillFile} (or drop --no-normalize) and run the import again.`
1381
1480
  );
1382
1481
  process.exit(1);
1383
1482
  }
@@ -1385,7 +1484,7 @@ function makeAssetCommand() {
1385
1484
  logWarn(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
1386
1485
  }
1387
1486
  fs8.cpSync(src.dir, destDir, { recursive: true, filter: copyFilter(src.dir) });
1388
- fs8.writeFileSync(path18.join(destDir, "SKILL.md"), norm.content, "utf8");
1487
+ fs8.writeFileSync(path19.join(destDir, "SKILL.md"), norm.content, "utf8");
1389
1488
  for (const note of norm.notes) logInfo(` \u2022 ${note}`);
1390
1489
  const fm = parseFrontmatter(norm.content).data;
1391
1490
  for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
@@ -1451,10 +1550,10 @@ function makeAssetCommand() {
1451
1550
  );
1452
1551
  process.exit(1);
1453
1552
  }
1454
- const basename3 = path18.basename(srcPath);
1553
+ const basename3 = path19.basename(srcPath);
1455
1554
  const destDir = target.path;
1456
1555
  fs8.mkdirSync(destDir, { recursive: true });
1457
- const destPath = path18.join(destDir, basename3);
1556
+ const destPath = path19.join(destDir, basename3);
1458
1557
  if (fs8.existsSync(destPath)) {
1459
1558
  logErr(`Destination already exists: ${destPath}`);
1460
1559
  process.exit(1);
@@ -1486,7 +1585,7 @@ function makeAssetCommand() {
1486
1585
  }
1487
1586
  logOk(`Migrated ${basename3} \u2192 ${target.name} (${opts.mode})`);
1488
1587
  const publisher = loadSkPublishManifest(target.path)?.publisher ?? "<publisher>";
1489
- const migratedKind = fs8.existsSync(path18.join(destPath, "SKILL.md")) ? "skill" : "<kind>";
1588
+ const migratedKind = fs8.existsSync(path19.join(destPath, "SKILL.md")) ? "skill" : "<kind>";
1490
1589
  logInfo(
1491
1590
  `Not addable yet: run ${S.cmd(`skaile library index ${target.name}`)}, then ${S.cmd(`skaile add ${migratedKind}:@${publisher.replace(/^@/, "")}/${basename3}`)}`
1492
1591
  );
@@ -1612,14 +1711,14 @@ function makeAuthCommand() {
1612
1711
  }
1613
1712
  function collectCacheTargets(scope) {
1614
1713
  const out = [];
1615
- out.push(path18__default.join(scope.projectDir, ".skaile", "cache"));
1616
- out.push(path18__default.join(scope.projectDir, ".skaile", "store-cache"));
1617
- out.push(path18__default.join(scope.projectDir, ".skaile", "repos"));
1714
+ out.push(path19__default.join(scope.projectDir, ".skaile", "cache"));
1715
+ out.push(path19__default.join(scope.projectDir, ".skaile", "store-cache"));
1716
+ out.push(path19__default.join(scope.projectDir, ".skaile", "repos"));
1618
1717
  if (scope.global) {
1619
1718
  out.push(globalCacheRoot());
1620
1719
  const home = globalSkaileDir();
1621
- out.push(path18__default.join(home, "repos"));
1622
- out.push(path18__default.join(home, "catalog-cache"));
1720
+ out.push(path19__default.join(home, "repos"));
1721
+ out.push(path19__default.join(home, "catalog-cache"));
1623
1722
  }
1624
1723
  return out;
1625
1724
  }
@@ -1633,7 +1732,7 @@ function dirSize(target) {
1633
1732
  function dirSizeOfDir(dir) {
1634
1733
  let total = 0;
1635
1734
  for (const ent of readdirSync(dir, { withFileTypes: true })) {
1636
- const child = path18__default.join(dir, ent.name);
1735
+ const child = path19__default.join(dir, ent.name);
1637
1736
  if (ent.isSymbolicLink()) continue;
1638
1737
  if (ent.isDirectory()) total += dirSizeOfDir(child);
1639
1738
  else if (ent.isFile()) total += statSync(child).size;
@@ -1659,7 +1758,7 @@ function makeCacheCommand() {
1659
1758
  const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
1660
1759
  cmd.command("clean").description("Remove the project cache (.skaile/cache); --global also clears ~/.skaile/cache").option("--global", "Also clear the global cache (sources + catalog) and legacy dirs").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
1661
1760
  const targets = collectCacheTargets({
1662
- projectDir: path18__default.resolve(opts.projectDir),
1761
+ projectDir: path19__default.resolve(opts.projectDir),
1663
1762
  global: opts.global
1664
1763
  }).filter((t) => existsSync(t));
1665
1764
  if (targets.length === 0) {
@@ -1689,12 +1788,12 @@ function makeCacheCommand() {
1689
1788
  for (const r of removed) logOk(`Removed ${r}`);
1690
1789
  });
1691
1790
  cmd.command("dir").description("Print the resolved cache roots").option("--global", "Include the global cache root").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
1692
- console.log(path18__default.join(path18__default.resolve(opts.projectDir), ".skaile", "cache"));
1791
+ console.log(path19__default.join(path19__default.resolve(opts.projectDir), ".skaile", "cache"));
1693
1792
  if (opts.global) console.log(globalCacheRoot());
1694
1793
  });
1695
1794
  cmd.command("size").description("Show cache disk usage per directory").option("--global", "Include the global cache").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
1696
1795
  const targets = collectCacheTargets({
1697
- projectDir: path18__default.resolve(opts.projectDir),
1796
+ projectDir: path19__default.resolve(opts.projectDir),
1698
1797
  global: opts.global
1699
1798
  });
1700
1799
  console.log();
@@ -1710,7 +1809,7 @@ function makeCatalogCommand() {
1710
1809
  const catalog = new Command("catalog").description("Catalog source health and configuration");
1711
1810
  catalog.command("test").description("Probe the configured catalog source and report status").option("--project-dir <path>", "Project directory (for project-level config overlay)").option("--url <url>", "Override the catalog URL for this probe").option("--force", "Probe the network even in air-gapped mode (cache_ttl: 0)").action(async (opts) => {
1712
1811
  const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
1713
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : void 0;
1812
+ const projectDir = opts.projectDir ? path19__default.resolve(opts.projectDir) : void 0;
1714
1813
  const cfg = resolveConfig({ projectDir });
1715
1814
  const baseUrl = opts.url ?? cfg.catalog.url;
1716
1815
  if (isLocalCatalogUrl(baseUrl)) {
@@ -1732,7 +1831,7 @@ function makeCatalogCommand() {
1732
1831
  });
1733
1832
  catalog.command("info").description("Print the resolved catalog configuration (url, framing, cacheTtlMs)").option("--project-dir <path>", "Project directory (for project-level config overlay)").action(async (opts) => {
1734
1833
  const { resolveConfig } = await import('../library/index.js');
1735
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : void 0;
1834
+ const projectDir = opts.projectDir ? path19__default.resolve(opts.projectDir) : void 0;
1736
1835
  const cfg = resolveConfig({ projectDir });
1737
1836
  console.log(`url: ${cfg.catalog.url}`);
1738
1837
  console.log(`framing: ${cfg.catalog.framing}`);
@@ -1741,7 +1840,7 @@ function makeCatalogCommand() {
1741
1840
  return catalog;
1742
1841
  }
1743
1842
  async function runLocalCatalogTest(projectDir) {
1744
- const { resolveCatalogSource } = await import('../open-library-RJGJIW5H.js');
1843
+ const { resolveCatalogSource } = await import('../open-library-XBR46DJL.js');
1745
1844
  let resolved;
1746
1845
  try {
1747
1846
  resolved = await resolveCatalogSource({ projectDir });
@@ -1917,13 +2016,13 @@ async function scanLibraryFlowEntries() {
1917
2016
  const { LocalIndex, resolveIndexPath, scanAuthoringLibraries } = await import('../library/index.js');
1918
2017
  const indexPath = resolveIndexPath();
1919
2018
  if (!existsSync(indexPath)) return entries;
1920
- const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-3QS3J7KO.js');
2019
+ const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-W562DCDL.js');
1921
2020
  const index = new LocalIndex({ indexPath });
1922
2021
  try {
1923
2022
  for (const { library, assets } of await scanAuthoringLibraries(index, getKindRegistry2())) {
1924
2023
  for (const asset of assets) {
1925
2024
  if (asset.kind !== "flow") continue;
1926
- if (flowFileNameError(asset.manifest, path18__default.basename(asset.manifestPath))) continue;
2025
+ if (flowFileNameError(asset.manifest, path19__default.basename(asset.manifestPath))) continue;
1927
2026
  try {
1928
2027
  const flow = loadFlow(asset.manifestPath);
1929
2028
  if (flow.id) {
@@ -1991,9 +2090,9 @@ function findSkills() {
1991
2090
  }
1992
2091
  function walkSkills(dir, out) {
1993
2092
  for (const entry of fs8__default.readdirSync(dir, { withFileTypes: true })) {
1994
- const full = path18__default.join(dir, entry.name);
2093
+ const full = path19__default.join(dir, entry.name);
1995
2094
  if (entry.isDirectory()) {
1996
- const skillMd = path18__default.join(full, "SKILL.md");
2095
+ const skillMd = path19__default.join(full, "SKILL.md");
1997
2096
  if (fs8__default.existsSync(skillMd)) {
1998
2097
  out.push({ name: entry.name, path: full, skillPath: skillMd });
1999
2098
  } else {
@@ -2015,7 +2114,7 @@ function resolveFlowIds() {
2015
2114
  }
2016
2115
  }
2017
2116
  function resolveSessionIds(projectDir) {
2018
- const sessionsDir = path18__default.join(projectDir, ".skaile", "sessions");
2117
+ const sessionsDir = path19__default.join(projectDir, ".skaile", "sessions");
2019
2118
  if (!fs8__default.existsSync(sessionsDir)) return [];
2020
2119
  try {
2021
2120
  return fs8__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
@@ -2070,50 +2169,6 @@ function resolveDynamic(words, cword) {
2070
2169
  if (cmd === "config" && ["get", "set"].includes(sub) && isLast(3)) return CONFIG_KEYS;
2071
2170
  return null;
2072
2171
  }
2073
- function unknownHarnessMessage(harness) {
2074
- const known = listHarnesses().map((d) => d.id);
2075
- if (known.includes(harness)) return void 0;
2076
- return `Unknown agent harness: "${harness}". Available: ${known.join(", ")}`;
2077
- }
2078
- var warnedDriverFlag = false;
2079
- function warnDriverFlagDeprecated() {
2080
- if (warnedDriverFlag) return;
2081
- warnedDriverFlag = true;
2082
- console.error("--driver is deprecated; use --harness");
2083
- }
2084
- function driverAliasOption() {
2085
- return new Option("--driver <name>", "Deprecated alias of --harness").hideHelp();
2086
- }
2087
- function foldDriverFlag(opts, fallback) {
2088
- const { driver, ...rest } = opts;
2089
- if (driver !== void 0) warnDriverFlagDeprecated();
2090
- return { ...rest, harness: rest.harness ?? driver ?? fallback };
2091
- }
2092
- function friendlyHarnessError(err) {
2093
- const e = err;
2094
- if (!e) return null;
2095
- const isSpawnEnoent = e.code === "ENOENT" && (e.syscall?.startsWith("spawn") === true || /^spawn .*ENOENT/.test(e.message ?? ""));
2096
- const isConfig = e.category === "config" || e.detail?.category === "config";
2097
- if (!isSpawnEnoent && !isConfig) return null;
2098
- const hint = e.hint ?? e.detail?.hint;
2099
- const base = hint ?? "The configured agent binary is not installed or not on your PATH.";
2100
- return `${base}
2101
- Try a different harness with \`--harness claude-sdk\`.`;
2102
- }
2103
- function harnessErrorNotes(err) {
2104
- const e = err;
2105
- const notes = [];
2106
- const category = e?.category ?? e?.detail?.category;
2107
- const hint = e?.hint ?? e?.detail?.hint;
2108
- if (hint && category !== "config") notes.push(hint);
2109
- else if (category === "auth") notes.push("Check your API key or login.");
2110
- if (e?.logSessionId) {
2111
- notes.push(`Full records: .skaile/logs.db (skaile session logs ${e.logSessionId}).`);
2112
- }
2113
- return notes;
2114
- }
2115
-
2116
- // cli/src/commands/config.ts
2117
2172
  var PERSONAL_KEYS = /* @__PURE__ */ new Set(["harness", "model"]);
2118
2173
  function resolveDriverKeyAlias(key) {
2119
2174
  if (key !== "driver") return key;
@@ -2226,6 +2281,12 @@ function printModelSelectionSection(config, projectDir) {
2226
2281
  console.log(
2227
2282
  ` ${S.dim("no AI provider is configured \u2014 add one with")} ${S.cmd("skaile providers add <id> --preset <preset>")}`
2228
2283
  );
2284
+ } else if (resolved.fallback) {
2285
+ console.log(` ${S.label("selector:".padEnd(16))} ${selector}`);
2286
+ console.log(
2287
+ ` ${S.label("passed on as:".padEnd(16))} the model id ${resolved.modelId ?? selector} ${S.dim("(no provider selected)")}`
2288
+ );
2289
+ for (const warning of resolved.warnings) logWarn(warning);
2229
2290
  } else {
2230
2291
  const entry = registry.providers[resolved.providerId];
2231
2292
  console.log(` ${S.label("selector:".padEnd(16))} ${selector}`);
@@ -2261,7 +2322,7 @@ function printResolvedPathsSection(config) {
2261
2322
  console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
2262
2323
  }
2263
2324
  async function showConfig(opts) {
2264
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2325
+ const projectDir = opts.projectDir ? path19__default.resolve(opts.projectDir) : process.cwd();
2265
2326
  let config;
2266
2327
  let sources;
2267
2328
  let wsDefaults;
@@ -2272,6 +2333,7 @@ async function showConfig(opts) {
2272
2333
  logErr(error instanceof Error ? error.message : String(error));
2273
2334
  process.exit(1);
2274
2335
  }
2336
+ if (await reportUnknownHarnesses(projectDir) > 0) process.exit(1);
2275
2337
  printEffectiveSection(config, sources);
2276
2338
  printWorkspaceDefaultsSection(wsDefaults);
2277
2339
  printModelSelectionSection(config, projectDir);
@@ -2328,7 +2390,7 @@ function makeConfigCommand() {
2328
2390
  cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
2329
2391
  cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").option("--global", "Read ~/.skaile/settings.json only, not the project's value").action(async (rawKey, opts) => {
2330
2392
  const key = resolveDriverKeyAlias(rawKey);
2331
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2393
+ const projectDir = opts.projectDir ? path19__default.resolve(opts.projectDir) : process.cwd();
2332
2394
  if (CATALOG_KEYS.has(key)) {
2333
2395
  const { resolveConfig } = await import('../library/index.js');
2334
2396
  const field = key.slice("catalog.".length);
@@ -2344,7 +2406,7 @@ function makeConfigCommand() {
2344
2406
  ).option("--project-dir <path>", "Project directory").option("--global", "Write to ~/.skaile/settings.json instead of project-local").action(
2345
2407
  async (rawKey, value, opts) => {
2346
2408
  const key = resolveDriverKeyAlias(rawKey);
2347
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2409
+ const projectDir = opts.projectDir ? path19__default.resolve(opts.projectDir) : process.cwd();
2348
2410
  if (CATALOG_KEYS.has(key)) {
2349
2411
  await setCatalogKey(key, value);
2350
2412
  return;
@@ -2378,6 +2440,19 @@ function makeConfigCommand() {
2378
2440
  process.exit(1);
2379
2441
  }
2380
2442
  }
2443
+ if (key === "model") {
2444
+ await loadDeclaredPlugins(projectDir);
2445
+ const harness = (await resolveSettings(projectDir)).harness ?? DEFAULT_HARNESS_ID;
2446
+ const refusal = checkHarnessModel(harness, {
2447
+ registry: loadRegistryView({ projectDir }).merged,
2448
+ model: value,
2449
+ roles: resolveSkWorkspaceConfig(projectDir).roles
2450
+ });
2451
+ if (refusal) {
2452
+ logErr(`${refusal} (the project's harness is ${harness})`);
2453
+ process.exit(1);
2454
+ }
2455
+ }
2381
2456
  const projectHarness = key === "harness" ? resolveSkWorkspaceConfig(projectDir).agent_config?.default?.harness : void 0;
2382
2457
  const filePath = opts.global ? globalSettingsPath() : projectSettingsPath(projectDir);
2383
2458
  const existing = await loadSettings(filePath);
@@ -2397,6 +2472,13 @@ function makeConfigCommand() {
2397
2472
  logWarn(
2398
2473
  "no AI provider is configured yet \u2014 add one with `skaile providers add <id> --preset <preset>`"
2399
2474
  );
2475
+ } else if (resolved.fallback) {
2476
+ console.log(
2477
+ S.dim(
2478
+ ` \u2192 passed on as the model id ${resolved.modelId ?? value} (no provider selected)`
2479
+ )
2480
+ );
2481
+ for (const warning of resolved.warnings) logWarn(warning);
2400
2482
  } else {
2401
2483
  console.log(
2402
2484
  S.dim(
@@ -2412,7 +2494,7 @@ function makeConfigCommand() {
2412
2494
  "Remove a value that `config set` wrote: harness, model, apiKey.<provider> (removes the provider entry) or catalog.url, catalog.cache_ttl, catalog.framing (the default applies again)"
2413
2495
  ).option("--project-dir <path>", "Project directory").option("--global", "Remove from ~/.skaile/settings.json instead of project-local").action(async (rawKey, opts) => {
2414
2496
  const key = resolveDriverKeyAlias(rawKey);
2415
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
2497
+ const projectDir = opts.projectDir ? path19__default.resolve(opts.projectDir) : process.cwd();
2416
2498
  if (CATALOG_KEYS.has(key)) {
2417
2499
  await unsetCatalogKey(key);
2418
2500
  return;
@@ -2735,8 +2817,8 @@ function makeConnectorCommand() {
2735
2817
  async (driver, opts) => {
2736
2818
  const { installNpmPackages } = await import('../connectors/index.js');
2737
2819
  const { scanDirectory: scanDirectory2, factoryAssetRoots: factoryAssetRoots2, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
2738
- const projectDir = path18__default.resolve(opts.projectDir);
2739
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
2820
+ const projectDir = path19__default.resolve(opts.projectDir);
2821
+ const yamlPath = path19__default.join(projectDir, "skaile.yaml");
2740
2822
  if (!existsSync(yamlPath)) {
2741
2823
  logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
2742
2824
  process.exit(1);
@@ -2796,8 +2878,8 @@ ${installResult.output}`);
2796
2878
  );
2797
2879
  cmd.command("remove <id>").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Remove a connector from skaile.yaml by its instance ID").action(async (id, opts) => {
2798
2880
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
2799
- const projectDir = path18__default.resolve(opts.projectDir);
2800
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
2881
+ const projectDir = path19__default.resolve(opts.projectDir);
2882
+ const yamlPath = path19__default.join(projectDir, "skaile.yaml");
2801
2883
  if (!existsSync(yamlPath)) {
2802
2884
  logErr("No skaile.yaml found in current directory.");
2803
2885
  process.exit(1);
@@ -2814,7 +2896,7 @@ ${installResult.output}`);
2814
2896
  cmd.command("status [id]").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Connect and report health status for one or all connectors").action(async (id, opts) => {
2815
2897
  const res = await import('../connectors/index.js');
2816
2898
  res.registerBuiltinConnectors();
2817
- const projectDir = path18__default.resolve(opts.projectDir);
2899
+ const projectDir = path19__default.resolve(opts.projectDir);
2818
2900
  const declarations = res.loadConnectorDeclarations(projectDir);
2819
2901
  if (declarations.length === 0) {
2820
2902
  console.log("No connectors configured in skaile.yaml.");
@@ -2838,7 +2920,7 @@ ${installResult.output}`);
2838
2920
  await manager.disconnectAll();
2839
2921
  });
2840
2922
  cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
2841
- const projectDir = path18__default.resolve(opts.projectDir);
2923
+ const projectDir = path19__default.resolve(opts.projectDir);
2842
2924
  const manager = await connectConnectors(projectDir);
2843
2925
  try {
2844
2926
  console.log(JSON.stringify(manager.listConnectors(), null, 2));
@@ -2847,7 +2929,7 @@ ${installResult.output}`);
2847
2929
  }
2848
2930
  });
2849
2931
  cmd.command("sync [id]").description("Re-sync a filesystem-face connector or all of them (git pull, S3 refresh, etc.)").option("--all", "Sync all connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
2850
- const projectDir = path18__default.resolve(opts.projectDir);
2932
+ const projectDir = path19__default.resolve(opts.projectDir);
2851
2933
  const manager = await connectConnectors(projectDir);
2852
2934
  try {
2853
2935
  if (opts.all) {
@@ -2871,7 +2953,7 @@ ${installResult.output}`);
2871
2953
  }
2872
2954
  });
2873
2955
  cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
2874
- const projectDir = path18__default.resolve(opts.projectDir);
2956
+ const projectDir = path19__default.resolve(opts.projectDir);
2875
2957
  const manager = await connectConnectors(projectDir);
2876
2958
  try {
2877
2959
  if (!manager.has(id)) {
@@ -2886,7 +2968,7 @@ ${installResult.output}`);
2886
2968
  }
2887
2969
  });
2888
2970
  cmd.command("read <id> <resource-path>").description("Read content from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
2889
- const projectDir = path18__default.resolve(opts.projectDir);
2971
+ const projectDir = path19__default.resolve(opts.projectDir);
2890
2972
  const manager = await connectConnectors(projectDir);
2891
2973
  try {
2892
2974
  const content = await manager.read(id, resourcePath);
@@ -2896,7 +2978,7 @@ ${installResult.output}`);
2896
2978
  }
2897
2979
  });
2898
2980
  cmd.command("write <id> <resource-path> <content>").description("Write content to a connector at a path").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, content, opts) => {
2899
- const projectDir = path18__default.resolve(opts.projectDir);
2981
+ const projectDir = path19__default.resolve(opts.projectDir);
2900
2982
  const manager = await connectConnectors(projectDir);
2901
2983
  try {
2902
2984
  await manager.write(id, resourcePath, { data: content });
@@ -2906,7 +2988,7 @@ ${installResult.output}`);
2906
2988
  }
2907
2989
  });
2908
2990
  cmd.command("entries <id> [resource-path]").description("List entries in a connector (files, keys, rows, etc)").option("--project-dir <path>", "Workspace directory", process.cwd()).option("--recursive", "Include nested entries").option("--limit <n>", "Maximum entries to return", parsePositiveIntOption).action(async (id, resourcePath, opts) => {
2909
- const projectDir = path18__default.resolve(opts.projectDir);
2991
+ const projectDir = path19__default.resolve(opts.projectDir);
2910
2992
  const manager = await connectConnectors(projectDir);
2911
2993
  try {
2912
2994
  const entries = await manager.list(id, resourcePath, {
@@ -2919,7 +3001,7 @@ ${installResult.output}`);
2919
3001
  }
2920
3002
  });
2921
3003
  cmd.command("search <id> <query>").description("Search within a connector for matching content").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, query, opts) => {
2922
- const projectDir = path18__default.resolve(opts.projectDir);
3004
+ const projectDir = path19__default.resolve(opts.projectDir);
2923
3005
  const manager = await connectConnectors(projectDir);
2924
3006
  try {
2925
3007
  const results = await manager.search(id, query);
@@ -2929,7 +3011,7 @@ ${installResult.output}`);
2929
3011
  }
2930
3012
  });
2931
3013
  cmd.command("delete <id> <resource-path>").description("Delete an entry from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
2932
- const projectDir = path18__default.resolve(opts.projectDir);
3014
+ const projectDir = path19__default.resolve(opts.projectDir);
2933
3015
  const manager = await connectConnectors(projectDir);
2934
3016
  try {
2935
3017
  const ok = await manager.delete(id, resourcePath);
@@ -2939,7 +3021,7 @@ ${installResult.output}`);
2939
3021
  }
2940
3022
  });
2941
3023
  cmd.command("run <id> <op> [args...]").description("Run a custom adapter operation (e.g. git log, sqlite query)").option("--project-dir <path>", "Workspace directory", process.cwd()).allowUnknownOption().action(async (id, op, args, opts) => {
2942
- const projectDir = path18__default.resolve(opts.projectDir);
3024
+ const projectDir = path19__default.resolve(opts.projectDir);
2943
3025
  const manager = await connectConnectors(projectDir);
2944
3026
  try {
2945
3027
  if (!manager.has(id)) {
@@ -3048,7 +3130,7 @@ function envRecord() {
3048
3130
  async function buildDeployContext(projectDir) {
3049
3131
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
3050
3132
  const config = resolveSkWorkspaceConfig2(projectDir);
3051
- const workspaceId = config.name ?? path18__default.basename(projectDir);
3133
+ const workspaceId = config.name ?? path19__default.basename(projectDir);
3052
3134
  let log;
3053
3135
  try {
3054
3136
  const { createLogger } = await import('../core/logging.js');
@@ -3080,13 +3162,13 @@ async function ensureTargetsRegistered(projectDir) {
3080
3162
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
3081
3163
  const config = resolveSkWorkspaceConfig2(projectDir);
3082
3164
  if (config.plugins && config.plugins.length > 0) {
3083
- const { ensurePluginsLoaded } = await import('../plugin-store-MSH6GK6T.js');
3165
+ const { ensurePluginsLoaded } = await import('../plugin-store-36SIL4TV.js');
3084
3166
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
3085
3167
  for (const f of result.failed) logWarn(f.error);
3086
3168
  }
3087
3169
  }
3088
3170
  async function runUp(opts) {
3089
- const projectDir = path18__default.resolve(opts.projectDir);
3171
+ const projectDir = path19__default.resolve(opts.projectDir);
3090
3172
  await ensureTargetsRegistered(projectDir);
3091
3173
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
3092
3174
  const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
@@ -3154,7 +3236,7 @@ async function restoreFromHandle(projectDir) {
3154
3236
  return { target, handle, ctx };
3155
3237
  }
3156
3238
  async function runDown(opts) {
3157
- const projectDir = path18__default.resolve(opts.projectDir);
3239
+ const projectDir = path19__default.resolve(opts.projectDir);
3158
3240
  const restored = await restoreFromHandle(projectDir);
3159
3241
  if (!restored) return;
3160
3242
  await restored.handle.stop();
@@ -3163,7 +3245,7 @@ async function runDown(opts) {
3163
3245
  logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
3164
3246
  }
3165
3247
  async function runStatus(opts) {
3166
- const projectDir = path18__default.resolve(opts.projectDir);
3248
+ const projectDir = path19__default.resolve(opts.projectDir);
3167
3249
  const restored = await restoreFromHandle(projectDir);
3168
3250
  if (!restored) return;
3169
3251
  const health = await restored.handle.health();
@@ -3177,7 +3259,7 @@ async function runStatus(opts) {
3177
3259
  console.log();
3178
3260
  }
3179
3261
  async function runLogs(opts) {
3180
- const projectDir = path18__default.resolve(opts.projectDir);
3262
+ const projectDir = path19__default.resolve(opts.projectDir);
3181
3263
  const restored = await restoreFromHandle(projectDir);
3182
3264
  if (!restored) return;
3183
3265
  if (!restored.handle.logs) {
@@ -3200,12 +3282,15 @@ function makeDeployCommand() {
3200
3282
  return cmd;
3201
3283
  }
3202
3284
  var DIFF_SHOWS = { content: true, modified: true, incomplete: true };
3285
+ function uniqueMessages(gaps) {
3286
+ return [...new Set(gaps.map((g) => g.message))];
3287
+ }
3203
3288
  function makeDiffCommand() {
3204
3289
  return new Command("diff").description("Show changes between deployed and source versions").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
3205
3290
  requireProjectConfig(opts.projectDir);
3206
3291
  const am2 = new AssetManager({
3207
3292
  registry: getKindRegistry(),
3208
- projectDir: path18__default.resolve(opts.projectDir)
3293
+ projectDir: path19__default.resolve(opts.projectDir)
3209
3294
  });
3210
3295
  try {
3211
3296
  parseAssetRef(ref);
@@ -3226,7 +3311,7 @@ function makeDiffCommand() {
3226
3311
  const requirementGaps = await am2.requirementGapsOf(ref);
3227
3312
  const blocking = gaps.filter((g) => !DIFF_SHOWS[g.type]);
3228
3313
  if (blocking.length > 0) {
3229
- for (const g of [...blocking, ...requirementGaps]) logErr(g.message);
3314
+ for (const line of uniqueMessages([...blocking, ...requirementGaps])) logErr(line);
3230
3315
  process.exitCode = 1;
3231
3316
  return;
3232
3317
  }
@@ -3236,7 +3321,10 @@ function makeDiffCommand() {
3236
3321
  );
3237
3322
  switch (result.status) {
3238
3323
  case "not-found":
3239
- if (problems.length === 0) logErr(`Asset not found: ${ref}`);
3324
+ if (problems.length === 0) {
3325
+ const hint = await am2.otherKindHint(ref);
3326
+ logErr(`Asset not found: ${ref}${hint ? `. ${hint}` : ""}`);
3327
+ }
3240
3328
  break;
3241
3329
  case "not-deployed":
3242
3330
  if (problems.length === 0) {
@@ -3257,7 +3345,7 @@ function makeDiffCommand() {
3257
3345
  console.log(result.diff);
3258
3346
  break;
3259
3347
  }
3260
- for (const g of [...problems, ...requirementGaps]) logErr(g.message);
3348
+ for (const line of uniqueMessages([...problems, ...requirementGaps])) logErr(line);
3261
3349
  if (result.status === "not-found" || problems.length > 0 || requirementGaps.length > 0)
3262
3350
  process.exitCode = 1;
3263
3351
  });
@@ -3265,7 +3353,7 @@ function makeDiffCommand() {
3265
3353
  function makeFlowCommand() {
3266
3354
  const cmd = new Command("flow").description("Manage flows");
3267
3355
  cmd.command("list").description("List the flows of this project").option("--project-dir <path>", "Project directory", process.cwd()).option("--all", "Also list the flows of registered libraries and cached sources").action(async (opts) => {
3268
- const projectDir = path18__default.resolve(opts.projectDir);
3356
+ const projectDir = path19__default.resolve(opts.projectDir);
3269
3357
  const flows = discoverProjectFlows(projectDir);
3270
3358
  const others = opts.all ? await discoverOtherFlows(projectDir) : [];
3271
3359
  if (flows.length === 0 && others.length === 0) {
@@ -3301,7 +3389,7 @@ function makeFlowCommand() {
3301
3389
  }
3302
3390
  });
3303
3391
  cmd.command("show <id>").description("Show flow details and node graph").option("--project-dir <path>", "Project directory", process.cwd()).option("--all", "Also look in registered libraries and cached sources").action(async (id, opts) => {
3304
- const projectDir = path18__default.resolve(opts.projectDir);
3392
+ const projectDir = path19__default.resolve(opts.projectDir);
3305
3393
  const flow = discoverProjectFlows(projectDir).find((f) => f.id === id) ?? (opts.all ? (await discoverOtherFlows(projectDir)).find((o) => o.flow.id === id)?.flow : void 0);
3306
3394
  if (!flow) {
3307
3395
  logErr(`Flow not found: ${id}`);
@@ -3335,12 +3423,68 @@ function makeFlowCommand() {
3335
3423
  cmd.action(() => cmd.help());
3336
3424
  return cmd;
3337
3425
  }
3426
+ var HARNESS_ID_OF_TARGET = {
3427
+ "claude-code": "claude-sdk",
3428
+ omp: "omp",
3429
+ codex: "codex"
3430
+ };
3431
+ function parseHarnessTarget(name) {
3432
+ if (name === "claude-sdk") return "claude-code";
3433
+ return SUPPORTED_HARNESSES.includes(name) ? name : void 0;
3434
+ }
3435
+ function makeHarnessCommand() {
3436
+ const cmd = new Command("harness").description("Choose the coding-agent harness of a project");
3437
+ cmd.command("set <name>").description(
3438
+ `Switch the project to a harness (${SUPPORTED_HARNESSES.join(" | ")}): rewrite skaile.yaml and install for it`
3439
+ ).option("--project-dir <path>", "Project directory", process.cwd()).action(async (name, opts) => {
3440
+ await runHarnessSet(name, path19__default.resolve(opts.projectDir));
3441
+ });
3442
+ cmd.action(() => cmd.help());
3443
+ return cmd;
3444
+ }
3445
+ async function runHarnessSet(name, projectDir) {
3446
+ const target = parseHarnessTarget(name);
3447
+ if (!target) {
3448
+ logErr(unknownHarnessTargetMessage(name));
3449
+ process.exit(1);
3450
+ }
3451
+ requireProjectConfig(projectDir);
3452
+ const file = path19__default.join(projectDir, "skaile.yaml");
3453
+ const before = resolveConfiguredHarnessName(projectDir);
3454
+ let editor;
3455
+ try {
3456
+ editor = WorkspaceYamlEditor.load(file);
3457
+ } catch (err) {
3458
+ logErr(err instanceof Error ? err.message : String(err));
3459
+ process.exit(1);
3460
+ }
3461
+ const profile = editor.getAgentConfig("default");
3462
+ editor.setAgentConfig("default", {
3463
+ agent: target,
3464
+ harness: HARNESS_ID_OF_TARGET[target]
3465
+ });
3466
+ editor.save();
3467
+ if (before === target) {
3468
+ logInfo(`Project is already on ${S.cmd(target)}; installing for it.`);
3469
+ } else {
3470
+ logOk(
3471
+ `Set ${S.cmd("agent-config.default")} to ${S.cmd(`agent: ${target}`)}, ${S.cmd(`harness: ${HARNESS_ID_OF_TARGET[target]}`)} in skaile.yaml`
3472
+ );
3473
+ }
3474
+ if (profile?.model) {
3475
+ logInfo(
3476
+ `model ${profile.model} is kept. Check it fits ${target}: skaile run "hi there" --dry-run`
3477
+ );
3478
+ }
3479
+ logInfo(`Installing for ${target} (${HARNESS_TARGETS[target].local.skill})`);
3480
+ await runYamlInstall({ projectDir });
3481
+ }
3338
3482
  function makeHistoryCommand() {
3339
3483
  const cmd = new Command("history").description("Show recent add/remove/update actions");
3340
3484
  cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
3341
3485
  const am2 = new AssetManager({
3342
3486
  registry: getKindRegistry(),
3343
- projectDir: path18__default.resolve(opts.projectDir)
3487
+ projectDir: path19__default.resolve(opts.projectDir)
3344
3488
  });
3345
3489
  const limit = parseInt(limitStr, 10) || 20;
3346
3490
  const entries = am2.history(limit);
@@ -3363,7 +3507,7 @@ function makeHistoryCommand() {
3363
3507
  cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
3364
3508
  const am2 = new AssetManager({
3365
3509
  registry: getKindRegistry(),
3366
- projectDir: path18__default.resolve(opts.projectDir)
3510
+ projectDir: path19__default.resolve(opts.projectDir)
3367
3511
  });
3368
3512
  am2.clearHistory();
3369
3513
  logOk("History cleared.");
@@ -3394,7 +3538,7 @@ async function readConfig(p6) {
3394
3538
  }
3395
3539
  }
3396
3540
  async function writeConfig(p6, value) {
3397
- await fs5.mkdir(path18__default.dirname(p6), { recursive: true });
3541
+ await fs5.mkdir(path19__default.dirname(p6), { recursive: true });
3398
3542
  const cleaned = {};
3399
3543
  for (const [k, v] of Object.entries(value)) {
3400
3544
  if (v === void 0) continue;
@@ -3403,7 +3547,7 @@ async function writeConfig(p6, value) {
3403
3547
  await fs5.writeFile(p6, stringify$1(cleaned));
3404
3548
  }
3405
3549
  function configPath(projectDir) {
3406
- return path18__default.join(projectDir, ".codex", "config.toml");
3550
+ return path19__default.join(projectDir, ".codex", "config.toml");
3407
3551
  }
3408
3552
  async function install2(projectDir) {
3409
3553
  const p6 = configPath(projectDir);
@@ -3414,7 +3558,7 @@ async function install2(projectDir) {
3414
3558
  const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
3415
3559
  let warning;
3416
3560
  if (previous && !matches) {
3417
- warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path18__default.relative(projectDir, p6)}`;
3561
+ warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path19__default.relative(projectDir, p6)}`;
3418
3562
  }
3419
3563
  if (matches) return { changed: false, method: "toml" };
3420
3564
  servers[SKAILE_MCP_NAME] = next;
@@ -3422,7 +3566,7 @@ async function install2(projectDir) {
3422
3566
  return { changed: true, method: "toml", warning };
3423
3567
  }
3424
3568
  function userConfigPath2() {
3425
- return path18__default.join(process.env.CODEX_HOME || path18__default.join(homedir(), ".codex"), "config.toml");
3569
+ return path19__default.join(process.env.CODEX_HOME || path19__default.join(homedir(), ".codex"), "config.toml");
3426
3570
  }
3427
3571
  async function readUserConfig() {
3428
3572
  const p6 = userConfigPath2();
@@ -3464,7 +3608,7 @@ async function trustProject(projectDir) {
3464
3608
  } catch {
3465
3609
  return "refused";
3466
3610
  }
3467
- await fs5.mkdir(path18__default.dirname(p6), { recursive: true });
3611
+ await fs5.mkdir(path19__default.dirname(p6), { recursive: true });
3468
3612
  await fs5.writeFile(p6, next);
3469
3613
  await writeTrustMark(projectDir, [
3470
3614
  .../* @__PURE__ */ new Set([
@@ -3476,7 +3620,7 @@ async function trustProject(projectDir) {
3476
3620
  }
3477
3621
  var TRUST_MARK = "codexTrustAdded";
3478
3622
  function stateFilePath(projectDir) {
3479
- return path18__default.join(projectDir, ".skaile", "plugin-state.json");
3623
+ return path19__default.join(projectDir, ".skaile", "plugin-state.json");
3480
3624
  }
3481
3625
  async function readState(projectDir) {
3482
3626
  try {
@@ -3500,7 +3644,7 @@ async function writeTrustMark(projectDir, roots) {
3500
3644
  const state2 = await readState(projectDir);
3501
3645
  if (roots.length > 0) state2[TRUST_MARK] = roots;
3502
3646
  else delete state2[TRUST_MARK];
3503
- await fs5.mkdir(path18__default.dirname(stateFilePath(projectDir)), { recursive: true });
3647
+ await fs5.mkdir(path19__default.dirname(stateFilePath(projectDir)), { recursive: true });
3504
3648
  await fs5.writeFile(stateFilePath(projectDir), JSON.stringify(state2, null, 2));
3505
3649
  }
3506
3650
  async function untrustProject(projectDir) {
@@ -3598,12 +3742,12 @@ async function status2(projectDir) {
3598
3742
  installed: "yes",
3599
3743
  enabled: trusted ? "n/a" : "untrusted",
3600
3744
  method: "mcp",
3601
- location: path18__default.relative(projectDir, p6)
3745
+ location: path19__default.relative(projectDir, p6)
3602
3746
  };
3603
3747
  }
3604
3748
  async function install3(projectDir) {
3605
- const extDir = path18__default.join(projectDir, ".omp", "extensions");
3606
- const extPath = path18__default.join(extDir, "skaile.ts");
3749
+ const extDir = path19__default.join(projectDir, ".omp", "extensions");
3750
+ const extPath = path19__default.join(extDir, "skaile.ts");
3607
3751
  await fs5.mkdir(extDir, { recursive: true });
3608
3752
  const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
3609
3753
  const plugin = new WorkspacePlugin({ projectDir });
@@ -3618,7 +3762,7 @@ async function install3(projectDir) {
3618
3762
  return { changed: true, method: "generated" };
3619
3763
  }
3620
3764
  async function uninstall3(projectDir) {
3621
- const extPath = path18__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3765
+ const extPath = path19__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3622
3766
  try {
3623
3767
  await fs5.unlink(extPath);
3624
3768
  return { changed: true };
@@ -3627,14 +3771,14 @@ async function uninstall3(projectDir) {
3627
3771
  }
3628
3772
  }
3629
3773
  async function status3(projectDir) {
3630
- const extPath = path18__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3774
+ const extPath = path19__default.join(projectDir, ".omp", "extensions", "skaile.ts");
3631
3775
  if (existsSync(extPath)) {
3632
3776
  return {
3633
3777
  harness: "omp",
3634
3778
  installed: "yes",
3635
3779
  enabled: "n/a",
3636
3780
  method: "extension",
3637
- location: path18__default.relative(projectDir, extPath)
3781
+ location: path19__default.relative(projectDir, extPath)
3638
3782
  };
3639
3783
  }
3640
3784
  return {
@@ -3652,7 +3796,7 @@ var TOGGLE_SUPPORTED = ["claude-code"];
3652
3796
  function resolveHarness(harness) {
3653
3797
  if (harness === "all") return [...ALL_HARNESSES];
3654
3798
  if (harness === "claude-code" || harness === "omp" || harness === "codex") return [harness];
3655
- logErr(`Unknown harness "${harness}". Supported: ${ALL_HARNESSES.join(", ")}, all`);
3799
+ logErr(unknownHarnessTargetMessage(harness, ["all"]));
3656
3800
  return null;
3657
3801
  }
3658
3802
  function withHarness(raw, fallback) {
@@ -3689,15 +3833,27 @@ async function installOmp(projectDir) {
3689
3833
  logInfo(`omp: already installed (${r.method})`);
3690
3834
  }
3691
3835
  await unignoreOmpExtension(projectDir);
3692
- if (isGitIgnored(projectDir, OMP_EXTENSION)) {
3836
+ const rule = ompExtensionIgnoreRule(projectDir, OMP_EXTENSION);
3837
+ if (rule) {
3693
3838
  logWarn(
3694
- `git ignores ${OMP_EXTENSION} (a global ignore file or .git/info/exclude); omp does not load an ignored extension. Remove that rule.`
3839
+ `git ignores ${OMP_EXTENSION} (${rule}); omp does not load an ignored extension. Remove that rule.`
3695
3840
  );
3696
3841
  }
3697
3842
  console.log(` ${S.dim("\u2192")} OMP auto-discovers extensions on next startup.`);
3698
3843
  }
3699
- function isGitIgnored(projectDir, file) {
3700
- return spawnSync("git", ["check-ignore", "-q", file], { cwd: projectDir, stdio: "ignore" }).status === 0;
3844
+ function ompExtensionIgnoreRule(projectDir, file) {
3845
+ const verbose = (p6) => {
3846
+ const r = spawnSync("git", ["check-ignore", "-v", p6], { cwd: projectDir, encoding: "utf-8" });
3847
+ return r.status === 0 ? r.stdout.trim() || void 0 : void 0;
3848
+ };
3849
+ const hit = verbose(file);
3850
+ if (!hit) return void 0;
3851
+ const dirs = [];
3852
+ for (let d = path19__default.posix.dirname(file); d !== "."; d = path19__default.posix.dirname(d)) dirs.push(d);
3853
+ if (dirs.some((d) => verbose(d) !== void 0)) return void 0;
3854
+ const [rule] = hit.split(" ");
3855
+ const m = /^(.*?):(\d+):(.*)$/.exec(rule ?? "");
3856
+ return m ? `${m[1]}:${m[2]}: ${m[3]}` : rule;
3701
3857
  }
3702
3858
  async function installCodex(projectDir) {
3703
3859
  const r = await install2(projectDir);
@@ -3722,7 +3878,7 @@ ${await trustEntry(projectDir)}`
3722
3878
  console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
3723
3879
  }
3724
3880
  async function runInstall(opts) {
3725
- const projectDir = path18__default.resolve(opts.projectDir);
3881
+ const projectDir = path19__default.resolve(opts.projectDir);
3726
3882
  const targets = resolveHarness(opts.harness);
3727
3883
  if (!targets) return 1;
3728
3884
  let exitCode = 0;
@@ -3785,7 +3941,7 @@ async function uninstallCodex(projectDir) {
3785
3941
  }
3786
3942
  }
3787
3943
  async function runUninstall(opts) {
3788
- const projectDir = path18__default.resolve(opts.projectDir);
3944
+ const projectDir = path19__default.resolve(opts.projectDir);
3789
3945
  const targets = resolveHarness(opts.harness);
3790
3946
  if (!targets) return 1;
3791
3947
  let exitCode = 0;
@@ -3808,12 +3964,12 @@ async function runUninstall(opts) {
3808
3964
  return exitCode;
3809
3965
  }
3810
3966
  async function removeEmptyPluginState(projectDir) {
3811
- const stateFile = path18__default.join(projectDir, ".skaile", "plugin-state.json");
3967
+ const stateFile = path19__default.join(projectDir, ".skaile", "plugin-state.json");
3812
3968
  try {
3813
3969
  const parsed = JSON.parse(await fs5.readFile(stateFile, "utf-8"));
3814
3970
  if (typeof parsed !== "object" || parsed === null || Object.keys(parsed).length > 0) return;
3815
3971
  await fs5.unlink(stateFile);
3816
- await fs5.rmdir(path18__default.dirname(stateFile)).catch(() => void 0);
3972
+ await fs5.rmdir(path19__default.dirname(stateFile)).catch(() => void 0);
3817
3973
  } catch {
3818
3974
  }
3819
3975
  }
@@ -3824,7 +3980,7 @@ var PER_MACHINE_FILES = {
3824
3980
  };
3825
3981
  var OMP_EXTENSION = ".omp/extensions/skaile.ts";
3826
3982
  async function unignoreOmpExtension(projectDir) {
3827
- const gitignore = path18__default.join(projectDir, ".gitignore");
3983
+ const gitignore = path19__default.join(projectDir, ".gitignore");
3828
3984
  let text;
3829
3985
  try {
3830
3986
  text = await fs5.readFile(gitignore, "utf-8");
@@ -3841,12 +3997,12 @@ async function unignoreOmpExtension(projectDir) {
3841
3997
  }
3842
3998
  var CLAUDE_FULL_FILES = [".claude/settings.json", ".claude/plugins/skaile/"];
3843
3999
  async function ignorePerMachineFiles(projectDir, targets, full) {
3844
- const gitignore = path18__default.join(projectDir, ".gitignore");
4000
+ const gitignore = path19__default.join(projectDir, ".gitignore");
3845
4001
  let existing = null;
3846
4002
  try {
3847
4003
  existing = await fs5.readFile(gitignore, "utf-8");
3848
4004
  } catch {
3849
- if (!existsSync(path18__default.join(projectDir, ".git"))) return;
4005
+ if (!existsSync(path19__default.join(projectDir, ".git"))) return;
3850
4006
  }
3851
4007
  const have = new Set((existing ?? "").split("\n").map((l) => l.trim()));
3852
4008
  const wanted = [
@@ -3890,7 +4046,7 @@ async function toggleTarget(t, projectDir, action3) {
3890
4046
  });
3891
4047
  }
3892
4048
  async function runToggle(opts, action3) {
3893
- const projectDir = path18__default.resolve(opts.projectDir);
4049
+ const projectDir = path19__default.resolve(opts.projectDir);
3894
4050
  const requestedAll = opts.harness === "all";
3895
4051
  const targets = resolveHarness(opts.harness);
3896
4052
  if (!targets) return 1;
@@ -3903,7 +4059,7 @@ async function runToggle(opts, action3) {
3903
4059
  return exitCode;
3904
4060
  }
3905
4061
  async function runStatus2(opts) {
3906
- const projectDir = path18__default.resolve(opts.projectDir);
4062
+ const projectDir = path19__default.resolve(opts.projectDir);
3907
4063
  const targets = resolveHarness(opts.harness);
3908
4064
  if (!targets) return 1;
3909
4065
  const rows = [];
@@ -3975,7 +4131,7 @@ async function runHook(event) {
3975
4131
  await plugin.shutdown();
3976
4132
  return;
3977
4133
  }
3978
- const store = new PluginStore(path18__default.join(projectDir, ".skaile", "plugin-state.json"));
4134
+ const store = new PluginStore(path19__default.join(projectDir, ".skaile", "plugin-state.json"));
3979
4135
  await store.load();
3980
4136
  const status4 = store.get("connector:status");
3981
4137
  if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
@@ -4054,7 +4210,7 @@ function makeIntegrationCommand() {
4054
4210
  cmd.command("omp-exec <kind> <name>").description(
4055
4211
  "Run one tool or slash command of the omp extension (used by .omp/extensions/skaile.ts)"
4056
4212
  ).option("--project-dir <path>", "Project directory", process.cwd()).action(async (kind, name, opts) => {
4057
- process.exitCode = await runOmpExec(kind, name, path18__default.resolve(opts.projectDir));
4213
+ process.exitCode = await runOmpExec(kind, name, path19__default.resolve(opts.projectDir));
4058
4214
  });
4059
4215
  cmd.command("hook <event>").description(
4060
4216
  "Run a Claude Code lifecycle hook (session-start | session-end | user-prompt-submit)"
@@ -4097,7 +4253,7 @@ function unfinishedGitState(dir) {
4097
4253
  for (const [entry, state2] of Object.entries(UNFINISHED_GIT_ENTRIES)) {
4098
4254
  const p6 = spawnSync("git", ["rev-parse", "--git-path", entry], { cwd: dir, encoding: "utf-8" });
4099
4255
  if (p6.status !== 0) return "the git directory could not be read";
4100
- if (fs8.existsSync(path18.resolve(dir, p6.stdout.trim()))) return state2;
4256
+ if (fs8.existsSync(path19.resolve(dir, p6.stdout.trim()))) return state2;
4101
4257
  }
4102
4258
  return null;
4103
4259
  }
@@ -4105,7 +4261,7 @@ async function reindexLibrary(lib, library, name) {
4105
4261
  assertManifestEditableOrExit(lib.path);
4106
4262
  exitOnManifestPublisherProblems(lib.path, name);
4107
4263
  exitOnLibrarySymlinks(lib.path, `skaile library index ${name}`);
4108
- exitOnManifestRootProblems(lib.path, `skaile library index ${name}`);
4264
+ exitOnManifestPathProblems(lib.path, `skaile library index ${name}`);
4109
4265
  const badRequires = manifestRequiresProblems(lib.path);
4110
4266
  const resolved = resolveLibraryPublisherDetailed(lib, {}, getStoreIdentity());
4111
4267
  warnLibraryNameFallback(name, resolved);
@@ -4122,7 +4278,7 @@ async function reindexLibrary(lib, library, name) {
4122
4278
  {
4123
4279
  check: (e) => checkAssetFile(e.source, e.kind, registry, lib.path, composeRefs),
4124
4280
  // A flow the engine would never load under its id (p871): keep it out of the manifest and the index.
4125
- refuse: (e) => e.kind === "flow" && flowFileNameError({ id: e.name }, path18.basename(e.source)) !== void 0
4281
+ refuse: (e) => e.kind === "flow" && flowFileNameError({ id: e.name }, path19.basename(e.source)) !== void 0
4126
4282
  }
4127
4283
  );
4128
4284
  const manifest = loadSkPublishManifest(lib.path);
@@ -4143,7 +4299,7 @@ async function reindexLibrary(lib, library, name) {
4143
4299
  }
4144
4300
  const invalidVersion = skipped.filter((x) => x.reason === "invalid-version");
4145
4301
  for (const s of invalidVersion) {
4146
- const found = checkAssetFile(path18.join(lib.path, s.file), s.kind, registry).find(
4302
+ const found = checkAssetFile(path19.join(lib.path, s.file), s.kind, registry).find(
4147
4303
  (f) => f.text.startsWith("version ")
4148
4304
  );
4149
4305
  const detail = found?.text ?? s.detail;
@@ -4154,28 +4310,36 @@ async function reindexLibrary(lib, library, name) {
4154
4310
  }
4155
4311
  const duplicates = skipped.filter((x) => x.reason === "duplicate");
4156
4312
  for (const s of duplicates) {
4157
- logErr(duplicateAssetMessage(s.kind, s.name, path18.dirname(s.file), s.detail, name));
4313
+ logErr(duplicateAssetMessage(s.kind, s.name, path19.dirname(s.file), s.detail, name));
4158
4314
  }
4159
4315
  for (const s of failed) {
4160
4316
  for (const f of s.findings) logErr(`${s.file} [${f.tag}] \u2014 ${f.text}`);
4161
4317
  }
4162
- const duplicateFiles = new Set(duplicates.map((s) => path18.resolve(lib.path, s.file)));
4318
+ const duplicateFiles = new Set(duplicates.map((s) => path19.resolve(lib.path, s.file)));
4163
4319
  const skippedKeys = new Set(
4164
4320
  [
4165
4321
  ...skipped.filter((s) => s.reason !== "duplicate"),
4166
4322
  ...failed.filter((s) => !s.inManifest)
4167
4323
  ].map((s) => `${s.kind}:${s.name}`)
4168
4324
  );
4325
+ const refusedFiles = new Set(
4326
+ [
4327
+ ...skipped.filter((s) => s.reason !== "duplicate"),
4328
+ ...failed.filter((s) => !s.inManifest)
4329
+ ].map((s) => path19.resolve(lib.path, s.file))
4330
+ );
4169
4331
  const res = await indexLibrary(lib, library, {
4170
- exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path18.resolve(a.manifestPath))
4332
+ exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path19.resolve(a.manifestPath)) || refusedFiles.has(path19.resolve(a.manifestPath))
4171
4333
  });
4172
4334
  const unparsable = res.unparsable;
4173
4335
  for (const e of res.errors) (unparsable.includes(e) ? logErr : logWarn)(e);
4174
4336
  const syncUnparsable = skipped.filter(
4175
- (s) => s.reason === "unparsable" && !unparsable.some((e) => e.includes(s.file))
4337
+ (s) => s.reason === "unparsable" && !unparsable.some((e) => e.startsWith(`${s.file} `))
4176
4338
  );
4177
4339
  for (const s of syncUnparsable) {
4178
- logErr(`${s.kind}:${s.name} skipped: manifest file ${s.file} could not be parsed.`);
4340
+ logErr(
4341
+ manifestParseFailureLine(lib.path, s.file) ?? `${s.file} [${s.kind}] \u2014 ${manifestParseErrorText("the manifest file could not be read")}`
4342
+ );
4179
4343
  }
4180
4344
  for (const p6 of badRequires) logErr(`${p6.asset}: ${p6.message}`);
4181
4345
  for (const w of await unresolvedManifestDependencies(lib.path)) logWarn(w);
@@ -4185,7 +4349,7 @@ async function reindexLibrary(lib, library, name) {
4185
4349
  const file = findEntryManifestFile(lib.path, a);
4186
4350
  if (!file) continue;
4187
4351
  for (const f of unheldRequiresOfFile(file, a.kind, composeRefs)) {
4188
- logWarn(`${path18.relative(lib.path, file)} [${f.tag}] \u2014 ${f.text}`);
4352
+ logWarn(`${path19.relative(lib.path, file)} [${f.tag}] \u2014 ${f.text}`);
4189
4353
  }
4190
4354
  }
4191
4355
  const skippedUnparsable = unparsable.length + syncUnparsable.length;
@@ -4236,6 +4400,16 @@ function warnUnlistedAssets(unlisted, name) {
4236
4400
  );
4237
4401
  }
4238
4402
  }
4403
+ function warnManifestNeedsCommit(libPath, name) {
4404
+ const status4 = spawnSync("git", ["status", "--porcelain", "--", SKAILE_MANIFEST_FILENAME], {
4405
+ cwd: libPath,
4406
+ encoding: "utf-8"
4407
+ });
4408
+ if (status4.status !== 0 || status4.stdout.trim() === "") return;
4409
+ logInfo(
4410
+ `${SKAILE_MANIFEST_FILENAME} was changed in the clone. Commit it with \`skaile library commit ${name}\`; \`pull\` and \`sync\` stop until you do.`
4411
+ );
4412
+ }
4239
4413
  function assertManifestEditableOrExit(libraryPath) {
4240
4414
  try {
4241
4415
  assertManifestEditable(libraryPath);
@@ -4250,18 +4424,55 @@ var DEPLOYED_COPY_DIRS = [
4250
4424
  )
4251
4425
  )
4252
4426
  ];
4427
+ var DEPLOY_ROOT_FOLDERS = new Set(
4428
+ DEPLOYED_COPY_DIRS.map((d) => d.split("/")[0])
4429
+ );
4430
+ function deployFolderBelowProject(dir) {
4431
+ const real = canonicalDir(dir);
4432
+ const home = (() => {
4433
+ try {
4434
+ return fs8.realpathSync(os.homedir());
4435
+ } catch {
4436
+ return void 0;
4437
+ }
4438
+ })();
4439
+ for (let cur = real; path19.dirname(cur) !== cur; cur = path19.dirname(cur)) {
4440
+ const project = path19.dirname(cur);
4441
+ const folder = path19.basename(cur);
4442
+ if (!DEPLOY_ROOT_FOLDERS.has(folder) || project === home) continue;
4443
+ const isProject = fs8.existsSync(path19.join(project, "skaile.yaml")) || DEPLOYED_COPY_DIRS.some((d) => {
4444
+ const full = path19.join(project, d);
4445
+ try {
4446
+ return fs8.statSync(full).isDirectory() && fs8.readdirSync(full).length > 0;
4447
+ } catch {
4448
+ return false;
4449
+ }
4450
+ });
4451
+ if (isProject) return { folder, project };
4452
+ }
4453
+ return void 0;
4454
+ }
4455
+ function refuseDeployFolder(dir, force = false) {
4456
+ const deployFolder = force ? void 0 : deployFolderBelowProject(dir);
4457
+ if (!deployFolder) return;
4458
+ logErr(
4459
+ `${dir} is inside the deploy folder ${deployFolder.folder}/ of the project ${deployFolder.project}: a library holds asset sources, not the copies \`skaile add\` deployed. Pick another --path for the library, or pass --force when the sources live in that folder.`
4460
+ );
4461
+ process.exit(1);
4462
+ }
4253
4463
  async function refuseUnusableLibraryDir(dir, force = false) {
4254
4464
  const deployed = DEPLOYED_COPY_DIRS.filter((d) => {
4255
- const full = path18.join(dir, d);
4465
+ const full = path19.join(dir, d);
4256
4466
  return fs8.existsSync(full) && fs8.statSync(full).isDirectory() && fs8.readdirSync(full).length > 0;
4257
4467
  });
4258
4468
  if (deployed.length > 0 && !force) {
4259
- const where = fs8.existsSync(path18.join(dir, "skaile.yaml")) ? "skaile.yaml with deployed copies" : "deployed copies";
4469
+ const where = fs8.existsSync(path19.join(dir, "skaile.yaml")) ? "skaile.yaml with deployed copies" : "deployed copies";
4260
4470
  logErr(
4261
4471
  `${dir} is a project folder (${where} in ${deployed.map((d) => `${d}/`).join(", ")}): a library holds asset sources, not the copies \`skaile add\` deployed. Pick another --path for the library, or pass --force when the sources live in those folders.`
4262
4472
  );
4263
4473
  process.exit(1);
4264
4474
  }
4475
+ refuseDeployFolder(dir, force);
4265
4476
  assertManifestEditableOrExit(dir);
4266
4477
  const unparsable = await unparsableAssetFiles(dir, getKindRegistry());
4267
4478
  if (unparsable.length > 0) {
@@ -4273,26 +4484,26 @@ async function refuseUnusableLibraryDir(dir, force = false) {
4273
4484
  }
4274
4485
  async function assertLibraryPathFree(manager, dir, exceptId) {
4275
4486
  const clash = (await manager.listLibraries()).find(
4276
- (l) => l.id !== exceptId && path18.resolve(l.path) === dir
4487
+ (l) => l.id !== exceptId && path19.resolve(l.path) === dir
4277
4488
  );
4278
4489
  if (clash) throw new Error(`${dir} is already registered as library "${clash.name}".`);
4279
4490
  }
4280
4491
  function canonicalDir(dir) {
4281
- const abs = path18.resolve(dir);
4492
+ const abs = path19.resolve(dir);
4282
4493
  const missing = [];
4283
4494
  let existing = abs;
4284
4495
  while (!fs8.existsSync(existing)) {
4285
- const parent = path18.dirname(existing);
4496
+ const parent = path19.dirname(existing);
4286
4497
  if (parent === existing) return abs;
4287
- missing.unshift(path18.basename(existing));
4498
+ missing.unshift(path19.basename(existing));
4288
4499
  existing = parent;
4289
4500
  }
4290
- return path18.join(fs8.realpathSync(existing), ...missing);
4501
+ return path19.join(fs8.realpathSync(existing), ...missing);
4291
4502
  }
4292
4503
  function refuseGlobalInstallFolder(name, dir) {
4293
4504
  const reserved = globalInstallDir();
4294
- const rel = path18.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
4295
- const inside = rel === "" || !rel.startsWith("..") && !path18.isAbsolute(rel);
4505
+ const rel = path19.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
4506
+ const inside = rel === "" || !rel.startsWith("..") && !path19.isAbsolute(rel);
4296
4507
  if (name?.toLowerCase() === GLOBAL_INSTALL_DIR_NAME || inside) {
4297
4508
  logErr(
4298
4509
  `"${GLOBAL_INSTALL_DIR_NAME}" is reserved: ${reserved} holds assets from \`skaile install\`, not a library you author.`
@@ -4302,8 +4513,8 @@ function refuseGlobalInstallFolder(name, dir) {
4302
4513
  }
4303
4514
  async function refuseNestedLibraryPath(manager, dir, exceptId) {
4304
4515
  const within = (parent, child) => {
4305
- const rel = path18.relative(parent, child);
4306
- return rel === "" || !rel.startsWith("..") && !path18.isAbsolute(rel);
4516
+ const rel = path19.relative(parent, child);
4517
+ return rel === "" || !rel.startsWith("..") && !path19.isAbsolute(rel);
4307
4518
  };
4308
4519
  const target = canonicalDir(dir).toLowerCase();
4309
4520
  const librariesDir = resolveLibraryDir();
@@ -4340,7 +4551,7 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
4340
4551
  }
4341
4552
  };
4342
4553
  let probe = destDir;
4343
- while (!exists(probe)) probe = path18.dirname(probe);
4554
+ while (!exists(probe)) probe = path19.dirname(probe);
4344
4555
  let realProbe;
4345
4556
  try {
4346
4557
  realProbe = fs8.realpathSync(probe);
@@ -4353,19 +4564,19 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
4353
4564
  process.exit(1);
4354
4565
  }
4355
4566
  const realRoot = canonicalDir(libRoot);
4356
- const realDest = path18.join(realProbe, path18.relative(probe, destDir));
4357
- const rel = path18.relative(realRoot, realDest);
4358
- if (rel === ".." || rel.startsWith(`..${path18.sep}`) || path18.isAbsolute(rel)) {
4567
+ const realDest = path19.join(realProbe, path19.relative(probe, destDir));
4568
+ const rel = path19.relative(realRoot, realDest);
4569
+ if (rel === ".." || rel.startsWith(`..${path19.sep}`) || path19.isAbsolute(rel)) {
4359
4570
  logErr(
4360
4571
  `--dir "${given}" must stay inside the library (${realRoot}): it resolves to ${realDest}.`
4361
4572
  );
4362
4573
  process.exit(1);
4363
4574
  }
4364
- const relParts = path18.relative(path18.resolve(libRoot), path18.resolve(destDir)).split(path18.sep);
4365
- let walked = path18.resolve(libRoot);
4575
+ const relParts = path19.relative(path19.resolve(libRoot), path19.resolve(destDir)).split(path19.sep);
4576
+ let walked = path19.resolve(libRoot);
4366
4577
  for (const [i, part] of relParts.entries()) {
4367
4578
  if (part === "" || part === ".") continue;
4368
- walked = path18.join(walked, part);
4579
+ walked = path19.join(walked, part);
4369
4580
  if (!exists(walked)) break;
4370
4581
  if (fs8.lstatSync(walked).isSymbolicLink()) {
4371
4582
  logErr(
@@ -4379,7 +4590,7 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
4379
4590
  }
4380
4591
  }
4381
4592
  function adoptWritesManifest(libPath) {
4382
- if (!fs8.existsSync(path18.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
4593
+ if (!fs8.existsSync(path19.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
4383
4594
  const manifest = loadSkPublishManifest(libPath);
4384
4595
  if (!manifest || manifest.source || (manifest.assets ?? []).length > 0) return false;
4385
4596
  return manifestPublisherProblems(libPath).length === 0;
@@ -4433,13 +4644,13 @@ function requireValidLibraryName(name) {
4433
4644
  var LOCAL_OWNERSHIP_REASON = "ownership only governs sync with a git remote, and a local library is always owned by you.";
4434
4645
  function pruneEmptyLibraryParents(libPath) {
4435
4646
  const root = canonicalDir(resolveLibraryDir());
4436
- let dir = path18.dirname(path18.resolve(libPath));
4647
+ let dir = path19.dirname(path19.resolve(libPath));
4437
4648
  for (; ; ) {
4438
- const rel = path18.relative(root, canonicalDir(dir));
4439
- if (rel === "" || rel.startsWith("..") || path18.isAbsolute(rel)) return;
4649
+ const rel = path19.relative(root, canonicalDir(dir));
4650
+ if (rel === "" || rel.startsWith("..") || path19.isAbsolute(rel)) return;
4440
4651
  if (!fs8.existsSync(dir) || fs8.readdirSync(dir).length > 0) return;
4441
4652
  fs8.rmdirSync(dir);
4442
- dir = path18.dirname(dir);
4653
+ dir = path19.dirname(dir);
4443
4654
  }
4444
4655
  }
4445
4656
  function remoteBranches(url) {
@@ -4452,7 +4663,7 @@ function remoteBranches(url) {
4452
4663
  return r.stdout.split("\n").map((line) => line.split(" ")[1]?.replace(/^refs\/heads\//, "")).filter((b) => !!b);
4453
4664
  }
4454
4665
  async function warnIfNotGithubRemote(name, url) {
4455
- const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-KKQ2ULLX.js');
4666
+ const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-XMRCKRNR.js');
4456
4667
  if (!isGithubRemote(url)) logWarn(notGithubRemoteMessage(name, url));
4457
4668
  }
4458
4669
  function scaffoldLibraryFiles(dir, name) {
@@ -4484,7 +4695,7 @@ by the same ref.
4484
4695
  ];
4485
4696
  const written = [];
4486
4697
  for (const [file, content] of files) {
4487
- const target = path18.join(dir, file);
4698
+ const target = path19.join(dir, file);
4488
4699
  if (fs8.existsSync(target)) continue;
4489
4700
  fs8.writeFileSync(target, content, "utf8");
4490
4701
  written.push(file);
@@ -4519,7 +4730,7 @@ function makeLibraryCommand() {
4519
4730
  for (const l of ls) {
4520
4731
  const def = l.isDefault ? pc5.green("\u25B8 ") : " ";
4521
4732
  console.log(
4522
- `${def}${S.cmd(l.name.padEnd(nameW))} ${pc5.dim(l.backend.padEnd(backendW))} ${pc5.dim(l.ownership.padEnd(ownerW))} ${pc5.dim(l.path)}`
4733
+ `${def}${S.cmd(l.name.padEnd(nameW))} ${pc5.dim(l.backend.padEnd(backendW))} ${pc5.dim(l.ownership.padEnd(ownerW))} ${pc5.dim(l.path)}${libraryDirMissing(l) ? ` ${pc5.red("(directory missing)")}` : ""}`
4523
4734
  );
4524
4735
  }
4525
4736
  console.log(`
@@ -4541,6 +4752,11 @@ function makeLibraryCommand() {
4541
4752
  const { manager, close } = await openLibraryManager();
4542
4753
  try {
4543
4754
  const l = await manager.requireLibrary(name);
4755
+ if (libraryDirMissing(l)) {
4756
+ logErr(missingLibraryDirMessage(l));
4757
+ process.exitCode = 1;
4758
+ return;
4759
+ }
4544
4760
  console.log();
4545
4761
  console.log(S.heading(` ${l.name}`));
4546
4762
  console.log(` ${S.rule(50)}`);
@@ -4552,10 +4768,6 @@ function makeLibraryCommand() {
4552
4768
  console.log(` ${S.label("manifestGen")} ${l.manifestGenerated}`);
4553
4769
  console.log(` ${S.label("backendConfig")} ${JSON.stringify(l.backendConfig)}`);
4554
4770
  console.log();
4555
- if (libraryDirMissing(l)) {
4556
- logErr(missingLibraryDirMessage(l));
4557
- process.exitCode = 1;
4558
- }
4559
4771
  } finally {
4560
4772
  close();
4561
4773
  }
@@ -4577,7 +4789,7 @@ function makeLibraryCommand() {
4577
4789
  opts.path ??= gone.path;
4578
4790
  }
4579
4791
  const ownership = flagged[0] ?? gone?.ownership ?? "owner";
4580
- const libPath = opts.path ? path18.resolve(opts.path) : path18.join(resolveLibraryDir(), name);
4792
+ const libPath = opts.path ? path19.resolve(opts.path) : path19.join(resolveLibraryDir(), name);
4581
4793
  refuseGlobalInstallFolder(name, libPath);
4582
4794
  if (fs8.existsSync(libPath) && !fs8.statSync(libPath).isDirectory()) {
4583
4795
  logErr(`${libPath} exists and is not a directory.`);
@@ -4603,6 +4815,8 @@ function makeLibraryCommand() {
4603
4815
  if (fs8.existsSync(libPath)) {
4604
4816
  exitOnLibrarySymlinks(libPath, `skaile library init ${name} --path ${libPath}`);
4605
4817
  await refuseUnusableLibraryDir(libPath, opts.force);
4818
+ } else {
4819
+ refuseDeployFolder(libPath, opts.force);
4606
4820
  }
4607
4821
  const hasDefault = (await manager.listLibraries()).some((l) => l.isDefault);
4608
4822
  let backend = "local";
@@ -4635,7 +4849,7 @@ function makeLibraryCommand() {
4635
4849
  ownership,
4636
4850
  isDefault
4637
4851
  });
4638
- const scaffolded = blank ? scaffoldLibraryFiles(libPath, name) : [];
4852
+ const scaffolded = blank && ownership !== "reader" ? scaffoldLibraryFiles(libPath, name) : [];
4639
4853
  logOk(
4640
4854
  `Library "${name}" ${blank ? "created" : "registered"} at ${libPath}${isDefault ? " (default)" : ""}`
4641
4855
  );
@@ -4652,8 +4866,9 @@ function makeLibraryCommand() {
4652
4866
  }
4653
4867
  if (!blank) {
4654
4868
  const lib = await manager.requireLibrary(name);
4655
- if (adoptWritesManifest(libPath)) {
4869
+ if (ownership === "owner" && adoptWritesManifest(libPath)) {
4656
4870
  await reindexLibrary(lib, library, name);
4871
+ warnManifestNeedsCommit(lib.path, name);
4657
4872
  return;
4658
4873
  }
4659
4874
  const unlisted = await countUnlistedAssets(libPath);
@@ -4664,8 +4879,9 @@ function makeLibraryCommand() {
4664
4879
  );
4665
4880
  }
4666
4881
  warnLibraryNameFallback(name, resolved);
4667
- if (resolved.source !== "manifest") {
4882
+ if (ownership === "owner" && resolved.source !== "manifest") {
4668
4883
  stampManifestPublisher(lib.path, resolved.publisher);
4884
+ warnManifestNeedsCommit(lib.path, name);
4669
4885
  }
4670
4886
  const res = await indexLibrary(lib, library);
4671
4887
  for (const e of res.errors) logWarn(e);
@@ -4769,10 +4985,10 @@ function makeLibraryCommand() {
4769
4985
  exitOnManifestPublisherProblems(target.path, target.name);
4770
4986
  const effectiveKind = opts.kind ?? kind;
4771
4987
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
4772
- const libRoot = path18.resolve(target.path);
4773
- const destDir = opts.dir ? path18.resolve(libRoot, opts.dir) : libRoot;
4774
- const relDest = path18.relative(libRoot, destDir);
4775
- if (relDest === ".." || relDest.startsWith(`..${path18.sep}`) || path18.isAbsolute(relDest)) {
4988
+ const libRoot = path19.resolve(target.path);
4989
+ const destDir = opts.dir ? path19.resolve(libRoot, opts.dir) : libRoot;
4990
+ const relDest = path19.relative(libRoot, destDir);
4991
+ if (relDest === ".." || relDest.startsWith(`..${path19.sep}`) || path19.isAbsolute(relDest)) {
4776
4992
  logErr(`--dir "${opts.dir}" must stay inside the library (${libRoot}).`);
4777
4993
  process.exit(1);
4778
4994
  }
@@ -4781,21 +4997,21 @@ function makeLibraryCommand() {
4781
4997
  libRoot,
4782
4998
  effectiveKind,
4783
4999
  name,
4784
- path18.relative(libRoot, path18.join(destDir, name))
5000
+ path19.relative(libRoot, path19.join(destDir, name))
4785
5001
  );
4786
5002
  if (taken) {
4787
5003
  logErr(
4788
- `${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path18.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
5004
+ `${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path19.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
4789
5005
  );
4790
5006
  process.exit(1);
4791
5007
  }
4792
- const wanted = path18.relative(libRoot, path18.join(destDir, name));
5008
+ const wanted = path19.relative(libRoot, path19.join(destDir, name));
4793
5009
  const onDisk = (await scanUnlistedAssets(libRoot, target.name, getKindRegistry())).find(
4794
5010
  (u) => u.entry.kind === effectiveKind && u.entry.name === name && u.root !== wanted
4795
5011
  );
4796
5012
  if (onDisk) {
4797
5013
  logErr(
4798
- `${effectiveKind}:${name} already exists at "${onDisk.root}" (not in the manifest yet) \u2014 creating it again under "${path18.relative(libRoot, destDir) || "."}" would be a duplicate. Run \`skaile library index ${target.name}\` first or pick another name.`
5014
+ `${effectiveKind}:${name} already exists at "${onDisk.root}" (not in the manifest yet) \u2014 creating it again under "${path19.relative(libRoot, destDir) || "."}" would be a duplicate. Run \`skaile library index ${target.name}\` first or pick another name.`
4799
5015
  );
4800
5016
  process.exit(1);
4801
5017
  }
@@ -4845,6 +5061,12 @@ function makeLibraryCommand() {
4845
5061
  cmd.command("default <name>").description("Set <name> as the default library").action(async (name) => {
4846
5062
  const { manager, close } = await openLibraryManager();
4847
5063
  try {
5064
+ const lib = await manager.requireLibrary(name);
5065
+ if (libraryDirMissing(lib)) {
5066
+ logErr(missingLibraryDirMessage(lib));
5067
+ process.exitCode = 1;
5068
+ return;
5069
+ }
4848
5070
  const updated = await manager.setDefault(name);
4849
5071
  logOk(`Default \u2192 ${updated.name}`);
4850
5072
  } finally {
@@ -4861,7 +5083,7 @@ function makeLibraryCommand() {
4861
5083
  logErr(`A library named "${newName}" is already registered.`);
4862
5084
  process.exit(1);
4863
5085
  }
4864
- const newPath = path18.join(path18.dirname(lib.path), newName);
5086
+ const newPath = path19.join(path19.dirname(lib.path), newName);
4865
5087
  refuseGlobalInstallFolder(newName, newPath);
4866
5088
  if (fs8.existsSync(newPath)) {
4867
5089
  logErr(`Target directory already exists: ${newPath}`);
@@ -4954,7 +5176,7 @@ function makeLibraryCommand() {
4954
5176
  }
4955
5177
  patch.isDefault = false;
4956
5178
  } else if (field === "path") {
4957
- const dir = path18.resolve(value);
5179
+ const dir = path19.resolve(value);
4958
5180
  if (!fs8.existsSync(dir) || !fs8.statSync(dir).isDirectory()) {
4959
5181
  logErr(`Directory does not exist: ${dir}. \`library set path=\` does not move files.`);
4960
5182
  process.exit(1);
@@ -5174,16 +5396,16 @@ function makeLibraryCommand() {
5174
5396
  "With --create-repo: create the repo private (the store only accepts public repos)"
5175
5397
  ).option("--ref <gitref>", "Git ref to ingest (default: the library branch or main)").option("--dry-run", "Print the plan; push nothing and call no store endpoint").action(
5176
5398
  async (lib, opts) => {
5177
- const { runLibraryPublish } = await import('../library-publish-KKQ2ULLX.js');
5399
+ const { runLibraryPublish } = await import('../library-publish-XMRCKRNR.js');
5178
5400
  await withStoreErrorHandling(() => runLibraryPublish(lib, opts));
5179
5401
  }
5180
5402
  );
5181
5403
  cmd.command("register <lib>").description("Register the library's manifest without pushing (bytes already on github)").option("--asset <ref>", "Publish only the single asset matching this ref/name").option("--ref <gitref>", "Git ref to ingest (default: the library branch or main)").option("--dry-run", "Print the plan; call no store endpoint").action(async (lib, opts) => {
5182
- const { runLibraryRegister } = await import('../library-publish-KKQ2ULLX.js');
5404
+ const { runLibraryRegister } = await import('../library-publish-XMRCKRNR.js');
5183
5405
  await withStoreErrorHandling(() => runLibraryRegister(lib, opts));
5184
5406
  });
5185
5407
  cmd.command("yank <lib>").description("Retract the library's published assets from the store").option("--asset <ref>", "Yank only the single asset matching this ref/name").action(async (lib, opts) => {
5186
- const { runLibraryYank } = await import('../library-publish-KKQ2ULLX.js');
5408
+ const { runLibraryYank } = await import('../library-publish-XMRCKRNR.js');
5187
5409
  await withStoreErrorHandling(() => runLibraryYank(lib, opts));
5188
5410
  });
5189
5411
  return cmd;
@@ -5234,9 +5456,9 @@ async function printOverallStatus(projectDir, asJson) {
5234
5456
  } catch {
5235
5457
  secretsStrategy = "unavailable";
5236
5458
  }
5237
- const resolvedProjectDir = path18.resolve(projectDir);
5238
- const hasWorkspaceConfig = existsSync(path18.join(resolvedProjectDir, "skaile.yaml"));
5239
- const hasLockFile = existsSync(path18.join(resolvedProjectDir, "skaile.lock.yaml"));
5459
+ const resolvedProjectDir = path19.resolve(projectDir);
5460
+ const hasWorkspaceConfig = existsSync(path19.join(resolvedProjectDir, "skaile.yaml"));
5461
+ const hasLockFile = existsSync(path19.join(resolvedProjectDir, "skaile.lock.yaml"));
5240
5462
  let assignments = [];
5241
5463
  if (hasWorkspaceConfig) {
5242
5464
  try {
@@ -5843,7 +6065,7 @@ function scheduleSoftDepPreview() {
5843
6065
  }
5844
6066
  async function loadAssets() {
5845
6067
  softDepPreviewCache.clear();
5846
- const { gatherAssetFeeds } = await import('../asset-feeds-PXUWCXVI.js');
6068
+ const { gatherAssetFeeds } = await import('../asset-feeds-KPKCE64E.js');
5847
6069
  const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
5848
6070
  if (notes.length > 0) {
5849
6071
  state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
@@ -5851,7 +6073,7 @@ async function loadAssets() {
5851
6073
  const installed = new Set(am.listDeployed().map((e) => `${e.kind}:${e.name}`));
5852
6074
  let lock = null;
5853
6075
  try {
5854
- lock = readLock(path18__default.join(am.projectDir, "skaile.lock.yaml"));
6076
+ lock = readLock(path19__default.join(am.projectDir, "skaile.lock.yaml"));
5855
6077
  } catch {
5856
6078
  }
5857
6079
  const rows = buildAssetRows(
@@ -5873,7 +6095,7 @@ function rebuildSourceTree() {
5873
6095
  rebuildVisibleSources();
5874
6096
  }
5875
6097
  function sourceOrgRepo(s) {
5876
- const parts = s.path.split(path18__default.sep).filter(Boolean);
6098
+ const parts = s.path.split(path19__default.sep).filter(Boolean);
5877
6099
  if (parts.length < 2) return null;
5878
6100
  return { org: parts[parts.length - 2], repo: parts[parts.length - 1] };
5879
6101
  }
@@ -6047,13 +6269,13 @@ function reconcileCollapsedSets(rows) {
6047
6269
  async function loadSourcesAndLibraries() {
6048
6270
  try {
6049
6271
  const [{ openLibraryManager: openLibraryManager2 }, { getGlobalCacheDir: getGlobalCacheDir2, globalSkaileDir: globalSkaileDir2 }] = await Promise.all([
6050
- import('../open-library-RJGJIW5H.js'),
6272
+ import('../open-library-XBR46DJL.js'),
6051
6273
  import('../core/index.js')
6052
6274
  ]);
6053
6275
  const { manager, library, close } = await openLibraryManager2();
6054
6276
  try {
6055
6277
  const newRoot = getGlobalCacheDir2();
6056
- const legacyRoot = path18__default.join(globalSkaileDir2(), "sources");
6278
+ const legacyRoot = path19__default.join(globalSkaileDir2(), "sources");
6057
6279
  const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
6058
6280
  const libs = await manager.listLibraries();
6059
6281
  const defs = await library.listAssetDefs();
@@ -7013,13 +7235,13 @@ async function run(projectDir) {
7013
7235
  }
7014
7236
  function makeManageCommand() {
7015
7237
  return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
7016
- await run(path18__default.resolve(opts.projectDir));
7238
+ await run(path19__default.resolve(opts.projectDir));
7017
7239
  });
7018
7240
  }
7019
7241
  function makeMcpServerCommand() {
7020
7242
  return new Command("mcp-server").description("Start skaile workspace MCP server (stdio transport)").option("--project-dir <path>", "Project directory (default: cwd)", process.cwd()).action(async (opts) => {
7021
- const path42 = await import('path');
7022
- const projectDir = path42.default.resolve(opts.projectDir);
7243
+ const path43 = await import('path');
7244
+ const projectDir = path43.default.resolve(opts.projectDir);
7023
7245
  const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
7024
7246
  registerLogStore2(
7025
7247
  new LogStore2({
@@ -7061,10 +7283,10 @@ function walkFiles(root, match) {
7061
7283
  return;
7062
7284
  }
7063
7285
  for (const entry of entries) {
7064
- const full = path18__default.join(dir, entry.name);
7286
+ const full = path19__default.join(dir, entry.name);
7065
7287
  if (entry.isDirectory()) {
7066
7288
  if (SKIPPED_DIRS.has(entry.name)) continue;
7067
- if (entry.name === "cache" && path18__default.basename(dir) === ".skaile") continue;
7289
+ if (entry.name === "cache" && path19__default.basename(dir) === ".skaile") continue;
7068
7290
  visit(full);
7069
7291
  } else if (entry.isFile() && match(entry.name)) {
7070
7292
  out.push(full);
@@ -7082,14 +7304,14 @@ function applyChanges2(changes) {
7082
7304
  switch (change.type) {
7083
7305
  case "write":
7084
7306
  case "create":
7085
- mkdirSync(path18__default.dirname(change.path), { recursive: true });
7307
+ mkdirSync(path19__default.dirname(change.path), { recursive: true });
7086
7308
  writeFileSync(change.path, change.after, "utf-8");
7087
7309
  break;
7088
7310
  case "delete":
7089
7311
  rmSync(change.path, { force: true });
7090
7312
  break;
7091
7313
  case "move":
7092
- mkdirSync(path18__default.dirname(change.to), { recursive: true });
7314
+ mkdirSync(path19__default.dirname(change.to), { recursive: true });
7093
7315
  writeFileSync(change.to, change.after, "utf-8");
7094
7316
  rmSync(change.from, { force: true });
7095
7317
  break;
@@ -7182,7 +7404,7 @@ function unifiedDiff(before, after, oldLabel, newLabel, context = 3) {
7182
7404
  return `${out.join("\n")}
7183
7405
  `;
7184
7406
  }
7185
- var posix = (p6) => p6.split(path18__default.sep).join("/");
7407
+ var posix = (p6) => p6.split(path19__default.sep).join("/");
7186
7408
  function colorizeDiff(diff) {
7187
7409
  return diff.split("\n").map((line) => {
7188
7410
  if (line.startsWith("+++") || line.startsWith("---")) return S.bold(line);
@@ -7193,7 +7415,7 @@ function colorizeDiff(diff) {
7193
7415
  }).join("\n");
7194
7416
  }
7195
7417
  function renderChange(change, base) {
7196
- const rel = (p6) => posix(path18__default.relative(base, p6) || path18__default.basename(p6));
7418
+ const rel = (p6) => posix(path19__default.relative(base, p6) || path19__default.basename(p6));
7197
7419
  switch (change.type) {
7198
7420
  case "write":
7199
7421
  return unifiedDiff(
@@ -7220,7 +7442,7 @@ ${diff}`;
7220
7442
  }
7221
7443
  }
7222
7444
  function changeLabel(change, base) {
7223
- const rel = (p6) => posix(path18__default.relative(base, p6) || path18__default.basename(p6));
7445
+ const rel = (p6) => posix(path19__default.relative(base, p6) || path19__default.basename(p6));
7224
7446
  switch (change.type) {
7225
7447
  case "write":
7226
7448
  return `modify ${rel(change.path)}`;
@@ -7291,7 +7513,7 @@ function itemFromRef(raw, defaultKind, ctx) {
7291
7513
  return { kind: prefixed[1], ref: value };
7292
7514
  }
7293
7515
  if (PATH_LIKE.test(value)) return { kind: defaultKind, ref: value };
7294
- if (defaultKind === "skill" && !value.includes("/") && existsSync(path18__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
7516
+ if (defaultKind === "skill" && !value.includes("/") && existsSync(path19__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
7295
7517
  return { kind: "skill", ref: `./skills/${value}` };
7296
7518
  }
7297
7519
  return { kind: defaultKind, ref: `${defaultKind}:${value}` };
@@ -7427,7 +7649,7 @@ function migrateAgentYaml(source, options) {
7427
7649
  manual.push("metadata.soul: not a string; left unchanged");
7428
7650
  continue;
7429
7651
  }
7430
- if (path18__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
7652
+ if (path19__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
7431
7653
  notes.push("metadata.soul \u2192 dropped (SOUL.md is a convention file)");
7432
7654
  } else {
7433
7655
  derived.push({ kind: "persona", ref: soul });
@@ -7661,7 +7883,7 @@ function migrateSubagents(skaileYamlPath, source) {
7661
7883
  if (!isMap(agentNode)) return void 0;
7662
7884
  const subNode = agentNode.get("subagents", true);
7663
7885
  if (!isMap(subNode)) return void 0;
7664
- const dir = path18__default.dirname(skaileYamlPath);
7886
+ const dir = path19__default.dirname(skaileYamlPath);
7665
7887
  const notes = [];
7666
7888
  const manual = [];
7667
7889
  const changes = [];
@@ -7679,10 +7901,10 @@ function migrateSubagents(skaileYamlPath, source) {
7679
7901
  continue;
7680
7902
  }
7681
7903
  const id = instanceId(name);
7682
- const assetDir = path18__default.join(dir, ".skaile", "agents", id);
7904
+ const assetDir = path19__default.join(dir, ".skaile", "agents", id);
7683
7905
  if (takenIds.has(id) || existsSync(assetDir)) {
7684
7906
  manual.push(
7685
- `agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path18__default.relative(dir, assetDir)} already exists`}; left in place`
7907
+ `agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path19__default.relative(dir, assetDir)} already exists`}; left in place`
7686
7908
  );
7687
7909
  continue;
7688
7910
  }
@@ -7706,13 +7928,13 @@ function migrateSubagents(skaileYamlPath, source) {
7706
7928
  manifest.tools = { ...allowed ? { allowed } : {}, ...denied ? { denied } : {} };
7707
7929
  }
7708
7930
  const text = stringify(manifest, { lineWidth: 0 });
7709
- const manifestPath = path18__default.join(assetDir, "agent.yaml");
7931
+ const manifestPath = path19__default.join(assetDir, "agent.yaml");
7710
7932
  changes.push({ type: "create", path: manifestPath, after: text });
7711
7933
  assetManifests.push({ file: manifestPath, text });
7712
7934
  if (typeof spec.prompt === "string" && spec.prompt.trim() !== "") {
7713
7935
  changes.push({
7714
7936
  type: "create",
7715
- path: path18__default.join(assetDir, "SOUL.md"),
7937
+ path: path19__default.join(assetDir, "SOUL.md"),
7716
7938
  after: `${spec.prompt.replace(/\s+$/, "")}
7717
7939
  `
7718
7940
  });
@@ -7771,7 +7993,7 @@ function validateMigratedAgent(text, registry) {
7771
7993
  function collectAgentFiles(paths) {
7772
7994
  const files = /* @__PURE__ */ new Set();
7773
7995
  for (const input of paths) {
7774
- const abs = path18__default.resolve(input);
7996
+ const abs = path19__default.resolve(input);
7775
7997
  if (!existsSync(abs)) continue;
7776
7998
  if (statSync(abs).isDirectory()) {
7777
7999
  for (const f of walkFiles(abs, (b) => b === "agent.yaml" || b === "skaile.yaml"))
@@ -7788,7 +8010,7 @@ function planAgentMigration(options) {
7788
8010
  const reports = [];
7789
8011
  for (const file of collectAgentFiles(options.paths)) {
7790
8012
  const source = readText(file);
7791
- const base = path18__default.basename(file);
8013
+ const base = path19__default.basename(file);
7792
8014
  if (base === "skaile.yaml") {
7793
8015
  const result = migrateSubagents(file, source);
7794
8016
  if (!result) continue;
@@ -7796,7 +8018,7 @@ function planAgentMigration(options) {
7796
8018
  for (const asset of result.assetManifests) {
7797
8019
  const v = validateMigratedAgent(asset.text, options.registry);
7798
8020
  validation2.errors.push(
7799
- ...v.errors.map((e) => `${path18__default.basename(path18__default.dirname(asset.file))}: ${e}`)
8021
+ ...v.errors.map((e) => `${path19__default.basename(path19__default.dirname(asset.file))}: ${e}`)
7800
8022
  );
7801
8023
  validation2.warnings.push(...v.warnings);
7802
8024
  }
@@ -7824,7 +8046,7 @@ function planAgentMigration(options) {
7824
8046
  });
7825
8047
  continue;
7826
8048
  }
7827
- migration = migrateAgentYaml(source, { agentDir: path18__default.dirname(file), knownKinds });
8049
+ migration = migrateAgentYaml(source, { agentDir: path19__default.dirname(file), knownKinds });
7828
8050
  } catch (error) {
7829
8051
  reports.push({
7830
8052
  file,
@@ -7854,7 +8076,7 @@ function planAgentMigration(options) {
7854
8076
  var DEFAULT_PUBLISHER = "skaile-ai";
7855
8077
  var PRESET_DEFAULT_VERSION = "1.0.0";
7856
8078
  var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
7857
- var posix2 = (p6) => p6.split(path18__default.sep).join("/");
8079
+ var posix2 = (p6) => p6.split(path19__default.sep).join("/");
7858
8080
  var MOVED_KINDS = { persona: "PERSONA.md", ruleset: "RULESET.md" };
7859
8081
  var KIND_MANIFEST_FILES = /* @__PURE__ */ new Set(["PERSONA.md", "RULESET.md", "SKILL.md"]);
7860
8082
  function readFrontmatterType(text) {
@@ -7876,7 +8098,42 @@ ${kept.join("\n")}
7876
8098
  ${rest}`;
7877
8099
  return { type: parsed.type, withoutType };
7878
8100
  }
7879
- function planMarkdownMoves(root, knownKinds, manual, unknownTypes) {
8101
+ function finalIdentity(kind, name) {
8102
+ try {
8103
+ return `${kind}:${slugifyAssetName(name)}`;
8104
+ } catch {
8105
+ return `${kind}:${name}`;
8106
+ }
8107
+ }
8108
+ function existingIdentities(root) {
8109
+ const found = /* @__PURE__ */ new Map();
8110
+ const note = (file, kind, fallback) => {
8111
+ let name = fallback;
8112
+ try {
8113
+ const text = readText(file);
8114
+ const body = file.endsWith(".yaml") ? text : FRONTMATTER.exec(text)?.[1] ?? "";
8115
+ const parsed = parse(body);
8116
+ if (isRecord(parsed) && typeof parsed.name === "string" && parsed.name !== "")
8117
+ name = parsed.name;
8118
+ } catch {
8119
+ }
8120
+ const identity = finalIdentity(kind, name);
8121
+ if (!found.has(identity)) found.set(identity, posix2(path19__default.relative(root, file)));
8122
+ };
8123
+ for (const file of walkFiles(root, (b) => b.endsWith(".preset.yaml"))) {
8124
+ note(file, "preset", path19__default.basename(file).replace(/\.preset\.yaml$/, ""));
8125
+ }
8126
+ for (const [base, kind] of [
8127
+ ["RULESET.md", "ruleset"],
8128
+ ["PERSONA.md", "persona"]
8129
+ ]) {
8130
+ for (const file of walkFiles(root, (b) => b === base)) {
8131
+ note(file, kind, path19__default.basename(path19__default.dirname(file)));
8132
+ }
8133
+ }
8134
+ return found;
8135
+ }
8136
+ function planMarkdownMoves(root, knownKinds, manual, unknownTypes, identities, conflicts, existing) {
7880
8137
  const moves = [];
7881
8138
  const changes = [];
7882
8139
  const targets = /* @__PURE__ */ new Set();
@@ -7885,17 +8142,33 @@ function planMarkdownMoves(root, knownKinds, manual, unknownTypes) {
7885
8142
  if (!text.startsWith("---")) continue;
7886
8143
  const found = readFrontmatterType(text);
7887
8144
  if (!found) continue;
7888
- const base = path18__default.basename(file);
7889
- const inAgentParts = file.split(path18__default.sep).includes("_agent-parts");
8145
+ const base = path19__default.basename(file);
8146
+ const inAgentParts = file.split(path19__default.sep).includes("_agent-parts");
7890
8147
  const targetName = MOVED_KINDS[found.type];
7891
8148
  if (targetName !== void 0 && !KIND_MANIFEST_FILES.has(base)) {
7892
- const to = path18__default.join(path18__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
8149
+ const to = path19__default.join(path19__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
7893
8150
  if (existsSync(to) || targets.has(to)) {
7894
8151
  manual.push(
7895
- `${posix2(path18__default.relative(root, file))}: ${posix2(path18__default.relative(root, to))} already exists; not moved`
8152
+ `${posix2(path19__default.relative(root, file))}: ${posix2(path19__default.relative(root, to))} already exists; not moved`
8153
+ );
8154
+ continue;
8155
+ }
8156
+ const identity = finalIdentity(found.type, base.replace(/\.md$/i, ""));
8157
+ const earlier = identities.get(identity);
8158
+ if (earlier !== void 0) {
8159
+ conflicts.push(
8160
+ `${earlier} and ${posix2(path19__default.relative(root, file))} both become ${identity}: rename one bundle first. Nothing was changed.`
8161
+ );
8162
+ continue;
8163
+ }
8164
+ const present = existing.get(identity);
8165
+ if (present !== void 0) {
8166
+ conflicts.push(
8167
+ `${present} already is ${identity}, and ${posix2(path19__default.relative(root, file))} would become it too: rename one first. Nothing was changed.`
7896
8168
  );
7897
8169
  continue;
7898
8170
  }
8171
+ identities.set(identity, posix2(path19__default.relative(root, file)));
7899
8172
  targets.add(to);
7900
8173
  moves.push({ from: file, to, kind: found.type });
7901
8174
  changes.push({ type: "move", from: file, to, before: text, after: found.withoutType });
@@ -7913,13 +8186,13 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
7913
8186
  const changes = [];
7914
8187
  for (const file of walkFiles(root, (b) => b === "agent.yaml")) {
7915
8188
  const source = readText(file);
7916
- const agentDir = path18__default.dirname(file);
8189
+ const agentDir = path19__default.dirname(file);
7917
8190
  let hits = 0;
7918
8191
  const refRewrite = (_kind, ref) => {
7919
- const moved = byOldPath.get(path18__default.resolve(agentDir, ref));
8192
+ const moved = byOldPath.get(path19__default.resolve(agentDir, ref));
7920
8193
  if (moved === void 0) return ref;
7921
8194
  hits++;
7922
- const rel = posix2(path18__default.relative(agentDir, moved));
8195
+ const rel = posix2(path19__default.relative(agentDir, moved));
7923
8196
  return rel.startsWith(".") ? rel : `./${rel}`;
7924
8197
  };
7925
8198
  let output;
@@ -7936,7 +8209,7 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
7936
8209
  if (hits === 0 || output === source) continue;
7937
8210
  changes.push({ type: "write", path: file, before: source, after: output });
7938
8211
  notes.push(
7939
- `${posix2(path18__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
8212
+ `${posix2(path19__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
7940
8213
  );
7941
8214
  }
7942
8215
  return changes;
@@ -7960,14 +8233,14 @@ function presetText(name, description, refs, version) {
7960
8233
  }
7961
8234
  function skillDirs(dir) {
7962
8235
  try {
7963
- return readdirSync(path18__default.join(dir, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync(path18__default.join(dir, "skills", e.name, "SKILL.md"))).map((e) => e.name).sort();
8236
+ return readdirSync(path19__default.join(dir, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync(path19__default.join(dir, "skills", e.name, "SKILL.md"))).map((e) => e.name).sort();
7964
8237
  } catch {
7965
8238
  return [];
7966
8239
  }
7967
8240
  }
7968
8241
  function repoPublisher(root) {
7969
8242
  for (const name of ["skaile.manifest.yaml", "skaile.yaml"]) {
7970
- const file = path18__default.join(root, name);
8243
+ const file = path19__default.join(root, name);
7971
8244
  if (!existsSync(file)) continue;
7972
8245
  try {
7973
8246
  const parsed = parse(readText(file));
@@ -7979,15 +8252,15 @@ function repoPublisher(root) {
7979
8252
  }
7980
8253
  return DEFAULT_PUBLISHER;
7981
8254
  }
7982
- function planBundles(root, skaileYamls, publisher, notes, manual, conflicts) {
8255
+ function planBundles(root, skaileYamls, publisher, notes, manual, conflicts, identities, existing) {
7983
8256
  const changes = [];
7984
8257
  const presets = [];
7985
8258
  const handled = /* @__PURE__ */ new Set();
7986
8259
  const claimed = /* @__PURE__ */ new Map();
7987
- const rel = (p6) => posix2(path18__default.relative(root, p6));
8260
+ const rel = (p6) => posix2(path19__default.relative(root, p6));
7988
8261
  const convert = (name, bundleFile, dir) => {
7989
- const target = path18__default.join(dir === root ? path18__default.join(dir, name) : dir, `${name}.preset.yaml`);
7990
- const origin = bundleFile ? rel(bundleFile) : `${rel(path18__default.join(dir, "skills")) || "skills"}/`;
8262
+ const target = path19__default.join(dir === root ? path19__default.join(dir, name) : dir, `${name}.preset.yaml`);
8263
+ const origin = bundleFile ? rel(bundleFile) : `${rel(path19__default.join(dir, "skills")) || "skills"}/`;
7991
8264
  const earlier = claimed.get(target);
7992
8265
  if (earlier !== void 0) {
7993
8266
  conflicts.push(
@@ -7995,10 +8268,25 @@ function planBundles(root, skaileYamls, publisher, notes, manual, conflicts) {
7995
8268
  );
7996
8269
  return;
7997
8270
  }
8271
+ const identity = finalIdentity("preset", name);
8272
+ const sameName = identities.get(identity);
8273
+ if (sameName !== void 0) {
8274
+ conflicts.push(
8275
+ `${sameName} and ${origin} both become ${identity}: rename one bundle first. Nothing was changed.`
8276
+ );
8277
+ return;
8278
+ }
7998
8279
  if (existsSync(target)) {
7999
8280
  manual.push(`${rel(target)} already exists; bundle ${name} not converted`);
8000
8281
  return;
8001
8282
  }
8283
+ const present = existing.get(identity);
8284
+ if (present !== void 0) {
8285
+ conflicts.push(
8286
+ `${present} already is ${identity}, and ${origin} would become it too: rename the bundle first. Nothing was changed.`
8287
+ );
8288
+ return;
8289
+ }
8002
8290
  let description;
8003
8291
  let refs = [];
8004
8292
  let before;
@@ -8026,11 +8314,12 @@ function planBundles(root, skaileYamls, publisher, notes, manual, conflicts) {
8026
8314
  }
8027
8315
  if (refs.length === 0) {
8028
8316
  manual.push(
8029
- `bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path18__default.join(dir, "skills"))}`}; no preset generated`
8317
+ `bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path19__default.join(dir, "skills"))}`}; no preset generated`
8030
8318
  );
8031
8319
  return;
8032
8320
  }
8033
8321
  claimed.set(target, origin);
8322
+ identities.set(identity, origin);
8034
8323
  const after = presetText(name, description, refs, version);
8035
8324
  if (before !== void 0 && bundleFile) {
8036
8325
  changes.push({ type: "move", from: bundleFile, to: target, before, after });
@@ -8051,18 +8340,18 @@ function planBundles(root, skaileYamls, publisher, notes, manual, conflicts) {
8051
8340
  const assets = Array.isArray(raw.assets) ? raw.assets : [];
8052
8341
  for (const entry of assets) {
8053
8342
  if (!isRecord(entry) || entry.kind !== "bundle" || typeof entry.name !== "string") continue;
8054
- const baseDir = path18__default.dirname(file);
8055
- const entryRoot = typeof entry.root === "string" ? path18__default.join(baseDir, entry.root) : baseDir;
8343
+ const baseDir = path19__default.dirname(file);
8344
+ const entryRoot = typeof entry.root === "string" ? path19__default.join(baseDir, entry.root) : baseDir;
8056
8345
  const files = Array.isArray(entry.files) ? entry.files : [];
8057
8346
  const bundleName = files.find(
8058
8347
  (f) => typeof f === "string" && f.endsWith(".bundle.yaml")
8059
8348
  );
8060
- convert(entry.name, bundleName ? path18__default.join(entryRoot, bundleName) : void 0, entryRoot);
8349
+ convert(entry.name, bundleName ? path19__default.join(entryRoot, bundleName) : void 0, entryRoot);
8061
8350
  }
8062
8351
  }
8063
8352
  for (const bundleFile of walkFiles(root, (b) => b.endsWith(".bundle.yaml"))) {
8064
8353
  if (handled.has(bundleFile)) continue;
8065
- const base = path18__default.basename(bundleFile);
8354
+ const base = path19__default.basename(bundleFile);
8066
8355
  let name = base.replace(/\.bundle\.yaml$/, "");
8067
8356
  try {
8068
8357
  const parsed = parse(readText(bundleFile));
@@ -8071,7 +8360,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual, conflicts) {
8071
8360
  } catch {
8072
8361
  }
8073
8362
  if (presets.some((p6) => p6.bundleFile === bundleFile)) continue;
8074
- convert(name, bundleFile, path18__default.dirname(bundleFile));
8363
+ convert(name, bundleFile, path19__default.dirname(bundleFile));
8075
8364
  }
8076
8365
  return changes;
8077
8366
  }
@@ -8081,8 +8370,8 @@ function planSkaileYaml(root, file, source, notes, manual) {
8081
8370
  if (doc.errors.length > 0 || !isMap(doc.contents)) return [];
8082
8371
  const map = doc.contents;
8083
8372
  const raw = doc.toJS();
8084
- const dir = path18__default.dirname(file);
8085
- const rel = (p6) => posix2(path18__default.relative(root, p6));
8373
+ const dir = path19__default.dirname(file);
8374
+ const rel = (p6) => posix2(path19__default.relative(root, p6));
8086
8375
  const changes = [];
8087
8376
  let changed = false;
8088
8377
  const deps = map.get("dependencies", true);
@@ -8099,7 +8388,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
8099
8388
  const hasPublication = PUBLICATION_KEYS.some((k) => raw[k] !== void 0);
8100
8389
  let remove = false;
8101
8390
  if (hasPublication) {
8102
- const manifestPath = path18__default.join(dir, "skaile.manifest.yaml");
8391
+ const manifestPath = path19__default.join(dir, "skaile.manifest.yaml");
8103
8392
  if (existsSync(manifestPath)) {
8104
8393
  manual.push(
8105
8394
  `${rel(file)}: publisher/version/assets left in place \u2014 ${rel(manifestPath)} already exists; merge by hand`
@@ -8156,16 +8445,26 @@ function planSkaileYaml(root, file, source, notes, manual) {
8156
8445
  return changes;
8157
8446
  }
8158
8447
  function planAssetMigration(options) {
8159
- const root = path18__default.resolve(options.root);
8448
+ const root = path19__default.resolve(options.root);
8160
8449
  const knownKinds = new Set(options.registry.getAllKinds());
8161
8450
  const notes = [];
8162
8451
  const manual = [];
8163
8452
  const conflicts = [];
8164
8453
  const unknownTypes = [];
8165
- const { moves, changes: moveChanges } = planMarkdownMoves(root, knownKinds, manual, unknownTypes);
8454
+ const identities = /* @__PURE__ */ new Map();
8455
+ const existing = existingIdentities(root);
8456
+ const { moves, changes: moveChanges } = planMarkdownMoves(
8457
+ root,
8458
+ knownKinds,
8459
+ manual,
8460
+ unknownTypes,
8461
+ identities,
8462
+ conflicts,
8463
+ existing
8464
+ );
8166
8465
  for (const move of moves) {
8167
8466
  notes.push(
8168
- `${posix2(path18__default.relative(root, move.from))} \u2192 ${posix2(path18__default.relative(root, move.to))} (${move.kind})`
8467
+ `${posix2(path19__default.relative(root, move.from))} \u2192 ${posix2(path19__default.relative(root, move.to))} (${move.kind})`
8169
8468
  );
8170
8469
  }
8171
8470
  const agentChanges = planAgentRefRewrites(root, moves, knownKinds, notes);
@@ -8177,11 +8476,20 @@ function planAssetMigration(options) {
8177
8476
  const raw = parse(source);
8178
8477
  if (isRecord(raw)) skaileYamls.push({ file, source, raw });
8179
8478
  } catch {
8180
- manual.push(`${posix2(path18__default.relative(root, file))}: invalid YAML; skipped`);
8479
+ manual.push(`${posix2(path19__default.relative(root, file))}: invalid YAML; skipped`);
8181
8480
  }
8182
8481
  }
8183
8482
  const publisher = repoPublisher(root);
8184
- const bundleChanges = planBundles(root, skaileYamls, publisher, notes, manual, conflicts);
8483
+ const bundleChanges = planBundles(
8484
+ root,
8485
+ skaileYamls,
8486
+ publisher,
8487
+ notes,
8488
+ manual,
8489
+ conflicts,
8490
+ identities,
8491
+ existing
8492
+ );
8185
8493
  const skaileChanges = skaileYamls.flatMap(
8186
8494
  ({ file, source }) => planSkaileYaml(root, file, source, notes, manual)
8187
8495
  );
@@ -8266,12 +8574,12 @@ function migrateHarnessSettings(text, label = "settings.json") {
8266
8574
  }
8267
8575
  function workspaceYamlFiles(projectDir) {
8268
8576
  const files = [];
8269
- if (existsSync(path18__default.join(projectDir, SKAILE_YAML_DEFAULT))) {
8270
- files.push(path18__default.join(projectDir, SKAILE_YAML_DEFAULT));
8577
+ if (existsSync(path19__default.join(projectDir, SKAILE_YAML_DEFAULT))) {
8578
+ files.push(path19__default.join(projectDir, SKAILE_YAML_DEFAULT));
8271
8579
  }
8272
8580
  try {
8273
8581
  for (const entry of readdirSync(projectDir).sort()) {
8274
- if (entry.endsWith(SKAILE_YAML_SUFFIX)) files.push(path18__default.join(projectDir, entry));
8582
+ if (entry.endsWith(SKAILE_YAML_SUFFIX)) files.push(path19__default.join(projectDir, entry));
8275
8583
  }
8276
8584
  } catch {
8277
8585
  }
@@ -8285,7 +8593,7 @@ function planHarnessMigration(opts) {
8285
8593
  if (seen.has(file) || !existsSync(file)) return;
8286
8594
  seen.add(file);
8287
8595
  const before = readText(file);
8288
- const label = path18__default.basename(file);
8596
+ const label = path19__default.basename(file);
8289
8597
  let result;
8290
8598
  try {
8291
8599
  result = rewrite(before, label);
@@ -8308,7 +8616,7 @@ function runMigrateHarness(opts) {
8308
8616
  "--apply"
8309
8617
  );
8310
8618
  const cwd = process.cwd();
8311
- const projectDir = path18__default.resolve(opts.projectDir ?? findWorkspaceRoot(cwd) ?? cwd);
8619
+ const projectDir = path19__default.resolve(opts.projectDir ?? findWorkspaceRoot(cwd) ?? cwd);
8312
8620
  const plan = planHarnessMigration({ projectDir });
8313
8621
  for (const note of plan.notes) console.log(` ${note}`);
8314
8622
  printChanges(plan.changes, projectDir);
@@ -8468,7 +8776,7 @@ function workspaceConfigFiles(dir) {
8468
8776
  } catch {
8469
8777
  return [];
8470
8778
  }
8471
- return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path18__default.join(dir, name));
8779
+ return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path19__default.join(dir, name));
8472
8780
  }
8473
8781
  function readAgentConfigBlock(raw) {
8474
8782
  const key = AGENT_CONFIG_KEYS2.find((candidate) => raw[candidate] !== void 0);
@@ -8480,7 +8788,7 @@ function readAgentConfigBlock(raw) {
8480
8788
  return flat ? { key, profiles: { default: profiles }, flat } : { key, profiles, flat };
8481
8789
  }
8482
8790
  function planProviderMigration(options) {
8483
- const projectDir = path18__default.resolve(options.projectDir);
8791
+ const projectDir = path19__default.resolve(options.projectDir);
8484
8792
  const registryPath = options.workspace ? workspaceProviderRegistryPath(projectDir) : userProviderRegistryPath();
8485
8793
  const plan = {
8486
8794
  registryPath,
@@ -8496,7 +8804,7 @@ function planProviderMigration(options) {
8496
8804
  raw = parseDocument(readFileSync(file, "utf-8")).toJS() ?? {};
8497
8805
  } catch (error) {
8498
8806
  plan.warnings.push(
8499
- `${path18__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
8807
+ `${path19__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
8500
8808
  );
8501
8809
  continue;
8502
8810
  }
@@ -8545,7 +8853,7 @@ function planProviderMigration(options) {
8545
8853
  });
8546
8854
  if (!model) {
8547
8855
  plan.warnings.push(
8548
- `${path18__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
8856
+ `${path19__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
8549
8857
  );
8550
8858
  }
8551
8859
  touched = true;
@@ -8612,7 +8920,7 @@ function printPlan(plan) {
8612
8920
  for (const entry of plan.entries) {
8613
8921
  const base = entry.entry.base_url ?? S.dim("(transport-derived)");
8614
8922
  console.log(
8615
- ` ${S.label(`${path18__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
8923
+ ` ${S.label(`${path19__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
8616
8924
  );
8617
8925
  console.log(` \u2192 providers.yml ${S.bold(entry.providerId)} ${base}`);
8618
8926
  console.log(
@@ -8628,7 +8936,7 @@ function printPlan(plan) {
8628
8936
  console.log();
8629
8937
  }
8630
8938
  async function runMigrateProviders(opts) {
8631
- const projectDir = opts.projectDir ? path18__default.resolve(opts.projectDir) : process.cwd();
8939
+ const projectDir = opts.projectDir ? path19__default.resolve(opts.projectDir) : process.cwd();
8632
8940
  const plan = planProviderMigration({ projectDir, workspace: opts.workspace });
8633
8941
  for (const warning of plan.warnings) logWarn(warning);
8634
8942
  if (plan.entries.length === 0 && Object.keys(plan.providers).length === 0) {
@@ -8732,7 +9040,7 @@ async function runMigrateAgents(paths, opts) {
8732
9040
  let failures = 0;
8733
9041
  let manualCount = 0;
8734
9042
  for (const report of plan.reports) {
8735
- const rel = path18__default.relative(base, report.file) || report.file;
9043
+ const rel = path19__default.relative(base, report.file) || report.file;
8736
9044
  for (const note of report.notes) console.log(` ${S.label(rel)} ${note}`);
8737
9045
  for (const note of report.manual) {
8738
9046
  manualCount++;
@@ -8759,7 +9067,7 @@ async function runMigrateAssets(root, opts) {
8759
9067
  const write = resolveMode(opts);
8760
9068
  const base = process.cwd();
8761
9069
  const plan = planAssetMigration({
8762
- root: path18__default.resolve(root ?? base),
9070
+ root: path19__default.resolve(root ?? base),
8763
9071
  registry: getKindRegistry()
8764
9072
  });
8765
9073
  if (plan.conflicts.length > 0) {
@@ -8771,7 +9079,7 @@ async function runMigrateAssets(root, opts) {
8771
9079
  for (const note of plan.manual) logWarn(note);
8772
9080
  for (const { file, type } of plan.unknownTypes) {
8773
9081
  logWarn(
8774
- `${path18__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
9082
+ `${path19__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
8775
9083
  );
8776
9084
  }
8777
9085
  printChanges(plan.changes, base);
@@ -8795,8 +9103,8 @@ function makeNpxCommand() {
8795
9103
  skills.command("add <url>").description(
8796
9104
  "Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
8797
9105
  ).requiredOption("--skill <name>", "Skill name to install from the repo").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", `Agent framework (${TARGET_DEFAULT_HINT})`).option("--global", "Deploy globally").action(async (url, opts) => {
8798
- const projectDir = path18__default.resolve(opts.projectDir);
8799
- const projYaml = path18__default.join(projectDir, "skaile.yaml");
9106
+ const projectDir = path19__default.resolve(opts.projectDir);
9107
+ const projYaml = path19__default.join(projectDir, "skaile.yaml");
8800
9108
  if (!existsSync(projYaml)) {
8801
9109
  logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
8802
9110
  process.exit(1);
@@ -8809,11 +9117,11 @@ function makeNpxCommand() {
8809
9117
  }
8810
9118
  const spinner = createSpinner();
8811
9119
  const key = sourceCacheKey(url);
8812
- const clonePath = path18__default.join(getGlobalCacheDir(), key);
9120
+ const clonePath = path19__default.join(getGlobalCacheDir(), key);
8813
9121
  spinner.start(`Cloning ${url}`);
8814
9122
  try {
8815
9123
  if (!existsSync(clonePath)) {
8816
- mkdirSync(path18__default.dirname(clonePath), { recursive: true });
9124
+ mkdirSync(path19__default.dirname(clonePath), { recursive: true });
8817
9125
  execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
8818
9126
  }
8819
9127
  spinner.stop(`Cloned to ${key}`);
@@ -8868,7 +9176,7 @@ function makeNpxCommand() {
8868
9176
  return npx;
8869
9177
  }
8870
9178
  function resolvePublisher(clonePath, url) {
8871
- const manifestPath = path18__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
9179
+ const manifestPath = path19__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
8872
9180
  if (existsSync(manifestPath)) {
8873
9181
  try {
8874
9182
  const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
@@ -8881,12 +9189,12 @@ function resolvePublisher(clonePath, url) {
8881
9189
  return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
8882
9190
  }
8883
9191
  function resolveSkillName(clonePath, requested) {
8884
- const skillsDir = path18__default.join(clonePath, "skills");
8885
- if (existsSync(path18__default.join(skillsDir, requested, "SKILL.md"))) return requested;
9192
+ const skillsDir = path19__default.join(clonePath, "skills");
9193
+ if (existsSync(path19__default.join(skillsDir, requested, "SKILL.md"))) return requested;
8886
9194
  if (!existsSync(skillsDir)) return requested;
8887
9195
  for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
8888
9196
  if (!entry.isDirectory()) continue;
8889
- const md = path18__default.join(skillsDir, entry.name, "SKILL.md");
9197
+ const md = path19__default.join(skillsDir, entry.name, "SKILL.md");
8890
9198
  if (!existsSync(md)) continue;
8891
9199
  try {
8892
9200
  const { data } = parseFrontmatter(readFileSync(md, "utf8"));
@@ -8940,7 +9248,7 @@ function makeOutdatedCommand() {
8940
9248
  requireProjectConfig(opts.projectDir);
8941
9249
  const am2 = new AssetManager({
8942
9250
  registry: getKindRegistry(),
8943
- projectDir: path18__default.resolve(opts.projectDir),
9251
+ projectDir: path19__default.resolve(opts.projectDir),
8944
9252
  harness: opts.target
8945
9253
  });
8946
9254
  const entries = await am2.outdated();
@@ -8964,8 +9272,15 @@ function makeOutdatedCommand() {
8964
9272
  );
8965
9273
  }
8966
9274
  console.log();
8967
- if (filtered.some((e) => e.problem === void 0 && !e.pinned)) {
8968
- logWarn(`Run ${S.cmd("skaile update")} to re-lock and re-deploy.`);
9275
+ const needsUpdate = filtered.some(
9276
+ (e) => e.problem === void 0 && !e.pinned && !e.contentChanged
9277
+ );
9278
+ const needsRelock = filtered.some(
9279
+ (e) => e.problem === void 0 && !e.pinned && e.contentChanged
9280
+ );
9281
+ if (needsUpdate) logWarn(`Run ${S.cmd("skaile update")} to re-lock and re-deploy.`);
9282
+ if (needsRelock) {
9283
+ logWarn(`Run ${S.cmd("skaile install")} to re-lock the changed library assets.`);
8969
9284
  }
8970
9285
  if (filtered.some((e) => e.problem !== void 0 && !e.manualFix)) {
8971
9286
  logWarn(`Run ${S.cmd("skaile install")} to restore or re-lock the broken assets.`);
@@ -8983,7 +9298,7 @@ function makePatchCommand() {
8983
9298
  cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8984
9299
  const am2 = new AssetManager({
8985
9300
  registry: getKindRegistry(),
8986
- projectDir: path18__default.resolve(opts.projectDir)
9301
+ projectDir: path19__default.resolve(opts.projectDir)
8987
9302
  });
8988
9303
  try {
8989
9304
  const dest = await am2.patch(ref);
@@ -8997,7 +9312,7 @@ function makePatchCommand() {
8997
9312
  cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
8998
9313
  const am2 = new AssetManager({
8999
9314
  registry: getKindRegistry(),
9000
- projectDir: path18__default.resolve(opts.projectDir)
9315
+ projectDir: path19__default.resolve(opts.projectDir)
9001
9316
  });
9002
9317
  try {
9003
9318
  const patchFile = await am2.patchCommit(ref);
@@ -9011,7 +9326,7 @@ function makePatchCommand() {
9011
9326
  cmd.command("submit <ref>").description("Apply patch to repo clone and prepare for PR").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
9012
9327
  const am2 = new AssetManager({
9013
9328
  registry: getKindRegistry(),
9014
- projectDir: path18__default.resolve(opts.projectDir)
9329
+ projectDir: path19__default.resolve(opts.projectDir)
9015
9330
  });
9016
9331
  try {
9017
9332
  await am2.patchSubmit(ref);
@@ -9027,7 +9342,7 @@ function makePatchCommand() {
9027
9342
  cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
9028
9343
  const am2 = new AssetManager({
9029
9344
  registry: getKindRegistry(),
9030
- projectDir: path18__default.resolve(opts.projectDir)
9345
+ projectDir: path19__default.resolve(opts.projectDir)
9031
9346
  });
9032
9347
  am2.patchRemove(ref);
9033
9348
  logOk(`Patch removed for ${ref}`);
@@ -9046,7 +9361,7 @@ function action2(fn) {
9046
9361
  };
9047
9362
  }
9048
9363
  async function reconcileAndReport(projectDir, plugins, opts = {}) {
9049
- const { reconcilePlugins } = await import('../plugin-store-MSH6GK6T.js');
9364
+ const { reconcilePlugins } = await import('../plugin-store-36SIL4TV.js');
9050
9365
  if (plugins.length === 0) {
9051
9366
  logInfo("No plugins declared \u2014 nothing to reconcile.");
9052
9367
  return;
@@ -9061,7 +9376,7 @@ async function reconcileAndReport(projectDir, plugins, opts = {}) {
9061
9376
  }
9062
9377
  }
9063
9378
  async function verifyPluginLoads(projectDir, spec) {
9064
- const { loadPlugins } = await import('../plugin-store-MSH6GK6T.js');
9379
+ const { loadPlugins } = await import('../plugin-store-36SIL4TV.js');
9065
9380
  const { createPluginRegistry } = await import('../plugin-registry/index.js');
9066
9381
  const registry = createPluginRegistry();
9067
9382
  const result = await loadPlugins(projectDir, [spec], registry);
@@ -9073,10 +9388,12 @@ async function verifyPluginLoads(projectDir, spec) {
9073
9388
  logOk(`Loaded ${S.cmd(spec)}${contributed.length > 0 ? ` (${contributed.join(", ")})` : ""}`);
9074
9389
  }
9075
9390
  async function runInstall2(spec, opts) {
9076
- const projectDir = path18__default.resolve(opts.projectDir);
9391
+ const projectDir = path19__default.resolve(opts.projectDir);
9077
9392
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
9078
- const { specName, rollbackPluginStore } = await import('../plugin-store-MSH6GK6T.js');
9079
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
9393
+ const { specName, rollbackPluginStore, npmSpecError } = await import('../plugin-store-36SIL4TV.js');
9394
+ const specError = npmSpecError(spec);
9395
+ if (specError) throw new Error(specError);
9396
+ const yamlPath = path19__default.join(projectDir, "skaile.yaml");
9080
9397
  if (!existsSync(yamlPath)) {
9081
9398
  throw new Error(`no skaile.yaml in ${projectDir}; run \`skaile init\` first`);
9082
9399
  }
@@ -9102,10 +9419,10 @@ async function runInstall2(spec, opts) {
9102
9419
  }
9103
9420
  }
9104
9421
  async function runRemove(name, opts) {
9105
- const projectDir = path18__default.resolve(opts.projectDir);
9422
+ const projectDir = path19__default.resolve(opts.projectDir);
9106
9423
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
9107
- const { specName } = await import('../plugin-store-MSH6GK6T.js');
9108
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
9424
+ const { specName } = await import('../plugin-store-36SIL4TV.js');
9425
+ const yamlPath = path19__default.join(projectDir, "skaile.yaml");
9109
9426
  if (!existsSync(yamlPath)) {
9110
9427
  logInfo(`No plugin matching ${S.cmd(name)}: there is no skaile.yaml in ${projectDir}.`);
9111
9428
  return;
@@ -9121,7 +9438,7 @@ async function runRemove(name, opts) {
9121
9438
  await reconcileAndReport(projectDir, editor.getPlugins());
9122
9439
  }
9123
9440
  async function runList(opts) {
9124
- const projectDir = path18__default.resolve(opts.projectDir);
9441
+ const projectDir = path19__default.resolve(opts.projectDir);
9125
9442
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
9126
9443
  const config = resolveSkWorkspaceConfig2(projectDir);
9127
9444
  const declared = config.plugins ?? [];
@@ -9136,7 +9453,7 @@ async function runList(opts) {
9136
9453
  const registry = createPluginRegistry();
9137
9454
  if (declared.length > 0) {
9138
9455
  try {
9139
- const { loadPlugins } = await import('../plugin-store-MSH6GK6T.js');
9456
+ const { loadPlugins } = await import('../plugin-store-36SIL4TV.js');
9140
9457
  const result = await loadPlugins(projectDir, declared, registry);
9141
9458
  for (const f of result.failed) logWarn(f.error);
9142
9459
  } catch (err) {
@@ -9404,8 +9721,8 @@ function redactSecrets(preset, findings) {
9404
9721
  }
9405
9722
  return { preset: next, keys };
9406
9723
  }
9407
- function placeholderKey(itemId, path42) {
9408
- return `${itemId}_${path42}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
9724
+ function placeholderKey(itemId, path43) {
9725
+ return `${itemId}_${path43}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
9409
9726
  }
9410
9727
  function setAtPath(root, segments, value) {
9411
9728
  let node = root;
@@ -9428,7 +9745,7 @@ function makePresetCommand() {
9428
9745
  cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
9429
9746
  const presetName = name ?? "my-preset";
9430
9747
  const filename = `${presetName}.preset.yaml`;
9431
- const outPath = path18__default.join(path18__default.resolve(opts.dir), filename);
9748
+ const outPath = path19__default.join(path19__default.resolve(opts.dir), filename);
9432
9749
  if (existsSync(outPath)) {
9433
9750
  logErr(`File already exists: ${outPath}`);
9434
9751
  logInfo("Choose a different name or remove the existing file.");
@@ -9461,7 +9778,7 @@ function makePresetCommand() {
9461
9778
  return cmd;
9462
9779
  }
9463
9780
  async function runPresetExport(name, opts) {
9464
- const projectDir = path18__default.resolve(opts.projectDir);
9781
+ const projectDir = path19__default.resolve(opts.projectDir);
9465
9782
  const file = loadSkWorkspaceConfig(projectDir);
9466
9783
  if (!file) {
9467
9784
  logErr(`No skaile.yaml found in ${projectDir}`);
@@ -9471,7 +9788,7 @@ async function runPresetExport(name, opts) {
9471
9788
  const presetName = name ?? file.config.name ?? "my-preset";
9472
9789
  let lock = null;
9473
9790
  try {
9474
- lock = readLock(path18__default.join(projectDir, "skaile.lock.yaml"));
9791
+ lock = readLock(path19__default.join(projectDir, "skaile.lock.yaml"));
9475
9792
  } catch {
9476
9793
  lock = null;
9477
9794
  }
@@ -9512,7 +9829,7 @@ async function runPresetExport(name, opts) {
9512
9829
  const contents = header ? `${header}
9513
9830
  ${body}` : body;
9514
9831
  if (opts.out && opts.dir !== process.cwd()) logWarn("--dir is ignored when --out is set.");
9515
- const outPath = opts.out ? path18__default.resolve(opts.out) : path18__default.join(path18__default.resolve(opts.dir), `${presetName}.preset.yaml`);
9832
+ const outPath = opts.out ? path19__default.resolve(opts.out) : path19__default.join(path19__default.resolve(opts.dir), `${presetName}.preset.yaml`);
9516
9833
  if (existsSync(outPath) && !opts.force) {
9517
9834
  logErr(`File already exists: ${outPath}`);
9518
9835
  logInfo("Pass --force to overwrite, or choose a different --out/--dir.");
@@ -9524,7 +9841,7 @@ ${body}` : body;
9524
9841
  logErr(`Failed to write ${outPath}: ${e.message}`);
9525
9842
  process.exit(1);
9526
9843
  }
9527
- logOk(`Exported ${S.brand(path18__default.basename(outPath))}`);
9844
+ logOk(`Exported ${S.brand(path19__default.basename(outPath))}`);
9528
9845
  logInfo(`Path: ${outPath}`);
9529
9846
  if (unresolved.length > 0) {
9530
9847
  console.error(S.err("This file is NOT safe to share."));
@@ -9565,13 +9882,13 @@ function collectInput(value, acc) {
9565
9882
  return acc;
9566
9883
  }
9567
9884
  async function runPresetApply(filePath, opts) {
9568
- const projectDir = path18__default.resolve(opts.projectDir);
9885
+ const projectDir = path19__default.resolve(opts.projectDir);
9569
9886
  const file = loadSkWorkspaceConfig(projectDir);
9570
9887
  if (!file) {
9571
9888
  logErr("No skaile.yaml \u2014 run `skaile init` first");
9572
9889
  process.exit(1);
9573
9890
  }
9574
- const resolved = path18__default.resolve(filePath);
9891
+ const resolved = path19__default.resolve(filePath);
9575
9892
  if (!existsSync(resolved)) {
9576
9893
  logErr(`File not found: ${resolved}`);
9577
9894
  process.exit(1);
@@ -9789,7 +10106,7 @@ async function reportNestedPresetRefs(preset) {
9789
10106
  }
9790
10107
  async function checkPresetCycles(preset, resolved) {
9791
10108
  const { detectCycles } = await import('../discovery/index.js');
9792
- const presetRef = path18__default.basename(resolved, ".preset.yaml");
10109
+ const presetRef = path19__default.basename(resolved, ".preset.yaml");
9793
10110
  const edges = [];
9794
10111
  for (const item of preset.items) {
9795
10112
  if (item.ref) {
@@ -9841,7 +10158,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
9841
10158
  }
9842
10159
  }
9843
10160
  async function runPresetValidate(filePath) {
9844
- const resolved = path18__default.resolve(filePath);
10161
+ const resolved = path19__default.resolve(filePath);
9845
10162
  const preset = await loadPresetForValidation(resolved);
9846
10163
  await reportNestedPresetRefs(preset);
9847
10164
  await checkPresetCycles(preset, resolved);
@@ -9894,7 +10211,7 @@ function resolveNamedAgent(projectDir, arg) {
9894
10211
  logErr(message);
9895
10212
  process.exit(1);
9896
10213
  };
9897
- const asPath = path18__default.resolve(projectDir, arg);
10214
+ const asPath = path19__default.resolve(projectDir, arg);
9898
10215
  const isPath = arg.includes("/") || arg.includes("\\");
9899
10216
  const viaRef = (ref) => {
9900
10217
  try {
@@ -9919,7 +10236,7 @@ function resolveNamedAgent(projectDir, arg) {
9919
10236
  if (!(err instanceof AgentRefResolutionError)) throw err;
9920
10237
  if (err.code === "ambiguous") return fail(err.message);
9921
10238
  }
9922
- if (existsSync(path18__default.join(asPath, "agent.yaml"))) return asPath;
10239
+ if (existsSync(path19__default.join(asPath, "agent.yaml"))) return asPath;
9923
10240
  const known = Object.keys(instances);
9924
10241
  return fail(
9925
10242
  `No agent "${arg}" found. Give an agent name, an agent: ref or a path` + (known.length > 0 ? ` (agent instances of this project: ${known.join(", ")})` : "") + "."
@@ -9930,8 +10247,13 @@ function makeRebuildCommand() {
9930
10247
  "[agent]",
9931
10248
  "Agent name, agent: ref, instance id or path (defaults to the project agent)"
9932
10249
  ).option("--project-dir <dir>", "Project directory", process.cwd()).action(async (agentArg, opts) => {
9933
- const projectDir = path18__default.resolve(opts.projectDir);
10250
+ const projectDir = path19__default.resolve(opts.projectDir);
9934
10251
  requireProjectConfig(projectDir, { allowMissing: true });
10252
+ const instanceErrors = agentInstanceErrorLines(projectDir);
10253
+ if (instanceErrors.length > 0) {
10254
+ for (const line of instanceErrors) logErr(line);
10255
+ process.exit(1);
10256
+ }
9935
10257
  let agentDir;
9936
10258
  if (agentArg) {
9937
10259
  agentDir = resolveNamedAgent(projectDir, agentArg);
@@ -9988,9 +10310,9 @@ function makeRebuildCommand() {
9988
10310
  }
9989
10311
  function resolveSingleShotAgentDir(projectDir, agentDefinition) {
9990
10312
  if (!agentDefinition) return resolveAgentDir(projectDir);
9991
- const asPath = agentDefinition.endsWith("agent.yaml") ? path18__default.dirname(path18__default.resolve(projectDir, agentDefinition)) : agentDefinition;
10313
+ const asPath = agentDefinition.endsWith("agent.yaml") ? path19__default.dirname(path19__default.resolve(projectDir, agentDefinition)) : agentDefinition;
9992
10314
  const dir = resolveAgentDefinitionDir(projectDir, asPath);
9993
- if (!dir || !fs8__default.existsSync(path18__default.join(dir, "agent.yaml"))) {
10315
+ if (!dir || !fs8__default.existsSync(path19__default.join(dir, "agent.yaml"))) {
9994
10316
  throw new Error(
9995
10317
  `--agent-definition "${agentDefinition}" does not resolve to an agent directory with agent.yaml${dir ? ` (looked in ${dir})` : ""}`
9996
10318
  );
@@ -10049,7 +10371,7 @@ async function printCompositionDryRun(projectDir, agentDir, harness, model, inst
10049
10371
  async function findSkillFile(projectDir, skill) {
10050
10372
  const name = skill.trim().replace(/^skill:/, "").replace(/^@[^/]+\//, "").replace(/#.*$/, "");
10051
10373
  for (const target of SUPPORTED_HARNESSES) {
10052
- const file = path18__default.join(deployedDir("skill", name, target, false, projectDir), "SKILL.md");
10374
+ const file = path19__default.join(deployedDir("skill", name, target, false, projectDir), "SKILL.md");
10053
10375
  if (fs8__default.existsSync(file)) return file;
10054
10376
  }
10055
10377
  const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
@@ -10065,6 +10387,14 @@ async function printSkillDryRun(projectDir, skill) {
10065
10387
  return false;
10066
10388
  }
10067
10389
  const content = fs8__default.readFileSync(file, "utf-8");
10390
+ const prerequisiteErrors = checkAssetFile(file, "skill", getKindRegistry()).filter(
10391
+ (f) => f.text.startsWith("metadata.prerequisites")
10392
+ );
10393
+ if (prerequisiteErrors.length > 0) {
10394
+ for (const f of prerequisiteErrors) logErr(`${file} [${f.tag}] - ${f.text}`);
10395
+ logErr(`Fix the skill's metadata.prerequisites (see \`skaile validate\`), then run it again.`);
10396
+ return false;
10397
+ }
10068
10398
  const { data } = parseFrontmatter(content);
10069
10399
  const meta = data.metadata ?? {};
10070
10400
  console.log(` ${S.label("Skill:")} ${S.heading(String(data.name ?? skill))}`);
@@ -10164,6 +10494,34 @@ function isNearFlowId(typed, id) {
10164
10494
  function harnessOptionDescription() {
10165
10495
  return `Harness to run (${listHarnesses().map((d) => d.id).join(", ")})`;
10166
10496
  }
10497
+ function nodeSkillRefs(flow) {
10498
+ const refs = /* @__PURE__ */ new Map();
10499
+ for (const node of flow.nodes) {
10500
+ for (const asset of nodeAssets(node)) {
10501
+ if (asset.startsWith("skill:") && !refs.has(asset)) refs.set(asset, node.id);
10502
+ }
10503
+ }
10504
+ return refs;
10505
+ }
10506
+ async function reportMissingNodeSkills(projectDir, flow) {
10507
+ const refs = nodeSkillRefs(flow);
10508
+ if (refs.size === 0) return;
10509
+ let missing;
10510
+ try {
10511
+ missing = new AssetManager({
10512
+ registry: getKindRegistry(),
10513
+ projectDir
10514
+ }).undeployedSkills([...refs.keys()]);
10515
+ } catch {
10516
+ return;
10517
+ }
10518
+ for (const ref of missing) {
10519
+ const bare = ref.replace(/#.*$/, "");
10520
+ logWarn(
10521
+ `Node ${refs.get(ref)} needs ${S.cmd(bare)}, which is not deployed. Run ${S.cmd(`skaile add ${bare}`)}.`
10522
+ );
10523
+ }
10524
+ }
10167
10525
  function makeRunCommand() {
10168
10526
  const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--harness <name>", harnessOptionDescription()).addOption(driverAliasOption()).option("--model <name>", "Model override").option("--label <label>", "Human-readable session label").option("--dry-run", "Print plan without executing (single-shot: resolved composition items)").option(
10169
10527
  "--agent-definition <ref|path>",
@@ -10172,8 +10530,11 @@ function makeRunCommand() {
10172
10530
  "--instance <id>",
10173
10531
  "Run the skaile.yaml `agents:` instance <id> (`default` is the primary `agent:`) with its overrides; single-shot prompts only"
10174
10532
  ).option("--skill <name>", "Skill name (for single-shot mode)").action(async (positional, opts) => {
10175
- const projectDir = path18__default.resolve(opts.projectDir);
10533
+ const projectDir = path19__default.resolve(opts.projectDir);
10176
10534
  await loadDeclaredPlugins(projectDir);
10535
+ if (await reportProjectConfig(projectDir, { harness: false, instances: true }) > 0) {
10536
+ process.exit(1);
10537
+ }
10177
10538
  const cliHarness = foldDriverFlag(opts).harness;
10178
10539
  const dryRun = opts.dryRun ?? false;
10179
10540
  const agentDefinition = opts.agentDefinition?.trim() || void 0;
@@ -10329,6 +10690,7 @@ function makeRunCommand() {
10329
10690
  onEvent: makeFlowEventHandler(),
10330
10691
  onLog: (line) => console.log(line)
10331
10692
  });
10693
+ if (dryRun) await reportMissingNodeSkills(projectDir, flow);
10332
10694
  } catch (err) {
10333
10695
  const friendly = friendlyHarnessError(err);
10334
10696
  logErr(friendly ?? (err instanceof Error ? err.message : String(err)));
@@ -10342,7 +10704,7 @@ function makeResumeCommand() {
10342
10704
  "--session <run-id>",
10343
10705
  "Target session by runId (full ID or the prefix `session list` prints)"
10344
10706
  ).option("--dry-run", "Print plan without executing").action(async (opts) => {
10345
- const projectDir = path18__default.resolve(opts.projectDir);
10707
+ const projectDir = path19__default.resolve(opts.projectDir);
10346
10708
  let sessionId = opts.session;
10347
10709
  const dryRun = opts.dryRun ?? false;
10348
10710
  if (sessionId) {
@@ -10383,7 +10745,7 @@ function makeResumeCommand() {
10383
10745
  }
10384
10746
  function makeStatusCommand() {
10385
10747
  return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10386
- const projectDir = path18__default.resolve(opts.projectDir);
10748
+ const projectDir = path19__default.resolve(opts.projectDir);
10387
10749
  const session = await loadSession(projectDir);
10388
10750
  if (!session) {
10389
10751
  logInfo("No active session.");
@@ -10409,7 +10771,7 @@ function makeStatusCommand() {
10409
10771
  }
10410
10772
  function makeClearCommand() {
10411
10773
  return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
10412
- const projectDir = path18__default.resolve(opts.projectDir);
10774
+ const projectDir = path19__default.resolve(opts.projectDir);
10413
10775
  await clearSession(projectDir);
10414
10776
  logOk("Session cleared.");
10415
10777
  });
@@ -10421,8 +10783,8 @@ function makeReplCommand() {
10421
10783
  ).action(async (opts) => {
10422
10784
  const { findWorkspaceRoot: findWorkspaceRoot2 } = await import('../core/index.js');
10423
10785
  const { startRepl } = await import('../tui/index.js');
10424
- const os2 = await import('os');
10425
- const userCwd = path18__default.resolve(opts.projectDir ?? process.cwd());
10786
+ const os3 = await import('os');
10787
+ const userCwd = path19__default.resolve(opts.projectDir ?? process.cwd());
10426
10788
  const workspaceRoot = findWorkspaceRoot2(userCwd);
10427
10789
  const instanceId2 = opts.instance?.trim() || void 0;
10428
10790
  let projectDir;
@@ -10451,12 +10813,12 @@ function makeReplCommand() {
10451
10813
  p4.cancel("Cancelled.");
10452
10814
  process.exit(0);
10453
10815
  }
10454
- const tmpDir = fs8__default.mkdtempSync(path18__default.join(os2.tmpdir(), "skaile-repl-"));
10816
+ const tmpDir = fs8__default.mkdtempSync(path19__default.join(os3.tmpdir(), "skaile-repl-"));
10455
10817
  projectDir = tmpDir;
10456
10818
  agentCwd = userCwd;
10457
10819
  logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
10458
10820
  if (!harnessOverride) {
10459
- const claudeDir = path18__default.join(os2.homedir(), ".claude");
10821
+ const claudeDir = path19__default.join(os3.homedir(), ".claude");
10460
10822
  if (fs8__default.existsSync(claudeDir)) {
10461
10823
  harnessOverride = "claude-sdk";
10462
10824
  logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} harness`);
@@ -10468,6 +10830,9 @@ function makeReplCommand() {
10468
10830
  console.log();
10469
10831
  }
10470
10832
  await loadDeclaredPlugins(projectDir);
10833
+ if (await reportProjectConfig(projectDir, { harness: false, instances: true }) > 0) {
10834
+ process.exit(1);
10835
+ }
10471
10836
  const effective = await resolveSettings(projectDir, {
10472
10837
  harness: harnessOverride,
10473
10838
  model: opts.model
@@ -10503,6 +10868,15 @@ function makeReplCommand() {
10503
10868
  }
10504
10869
  });
10505
10870
  }
10871
+ function valueNotFlag(flag) {
10872
+ return (value) => {
10873
+ if (value.startsWith("--")) {
10874
+ logErr(`${flag} needs a value, got '${value}'`);
10875
+ process.exit(1);
10876
+ }
10877
+ return value;
10878
+ };
10879
+ }
10506
10880
  function parseProviderIds(raw) {
10507
10881
  return (raw ?? "").split(",").map((id) => id.trim()).filter((id) => id.length > 0);
10508
10882
  }
@@ -10549,21 +10923,31 @@ function describeBindError(err, host, port) {
10549
10923
  }
10550
10924
  }
10551
10925
  function makeServeCommand() {
10552
- return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option(
10926
+ return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", valueNotFlag("--port"), "8080").option(
10553
10927
  "--host <address>",
10554
- "Address to bind (default: all interfaces; use 127.0.0.1 for local clients only)"
10555
- ).option("--project-dir <path>", "Project directory", process.cwd()).option(
10928
+ "Address to bind (default: all interfaces; use 127.0.0.1 for local clients only)",
10929
+ valueNotFlag("--host")
10930
+ ).option(
10931
+ "--project-dir <path>",
10932
+ "Project directory",
10933
+ valueNotFlag("--project-dir"),
10934
+ process.cwd()
10935
+ ).option(
10556
10936
  "--managed-codex-config <path>",
10557
- "Explicit private host configuration for managed Codex"
10558
- ).option("--harness <name>", "Override harness").addOption(driverAliasOption()).option("--model <name>", "Override model").option("--provider <name>", "Override provider").option(
10937
+ "Explicit private host configuration for managed Codex",
10938
+ valueNotFlag("--managed-codex-config")
10939
+ ).option("--harness <name>", "Override harness", valueNotFlag("--harness")).addOption(driverAliasOption().argParser(valueNotFlag("--driver"))).option("--model <name>", "Override model", valueNotFlag("--model")).option("--provider <name>", "Override provider", valueNotFlag("--provider")).option(
10559
10940
  "--session-id <id>",
10560
- "Label for the session; does not restore the conversation (use --resume-session-id)"
10941
+ "Label for the session; does not restore the conversation (use --resume-session-id)",
10942
+ valueNotFlag("--session-id")
10561
10943
  ).option(
10562
10944
  "--resume-session-id <id>",
10563
- "harnessSessionId of an earlier session (from its session_info event); restores that conversation"
10945
+ "harnessSessionId of an earlier session (from its session_info event); restores that conversation",
10946
+ valueNotFlag("--resume-session-id")
10564
10947
  ).option(
10565
10948
  "--providers <ids>",
10566
- "Restrict the AI provider registry to these entry ids (comma-separated)"
10949
+ "Restrict the AI provider registry to these entry ids (comma-separated)",
10950
+ valueNotFlag("--providers")
10567
10951
  ).option(
10568
10952
  "--model-endpoint [port]",
10569
10953
  "Serve an OpenAI-compatible model endpoint on loopback for apps next to the session (optional port; default from skaile.yaml model_endpoint.port, else ephemeral)"
@@ -10597,6 +10981,14 @@ function makeServeCommand() {
10597
10981
  process.exitCode = 1;
10598
10982
  return;
10599
10983
  }
10984
+ const dirProblem = (await import('../serve-preflight-CGA5G3AE.js')).checkServeProjectDir(
10985
+ opts.projectDir
10986
+ );
10987
+ if (dirProblem) {
10988
+ logErr(dirProblem);
10989
+ process.exitCode = 1;
10990
+ return;
10991
+ }
10600
10992
  let managedCodex;
10601
10993
  if (opts.managedCodexConfig) {
10602
10994
  try {
@@ -10618,7 +11010,14 @@ function makeServeCommand() {
10618
11010
  }
10619
11011
  const providers = parseProviderIds(opts.providers);
10620
11012
  const modelEndpoint = parseModelEndpointFlag(opts.modelEndpoint);
10621
- const { checkHarnessSdk, checkModelEndpointPeer, checkServeModel } = await import('../serve-preflight-L4POEHNQ.js');
11013
+ const { checkHarnessSdk, checkModelEndpointPeer, checkServeModel } = await import('../serve-preflight-CGA5G3AE.js');
11014
+ const { checkServeHarness, checkServeAgentDefinition } = await import('../serve-preflight-CGA5G3AE.js');
11015
+ const startProblem = managedCodex ? null : await checkServeHarness(opts.projectDir, opts.harness) ?? checkServeAgentDefinition(opts.projectDir);
11016
+ if (startProblem) {
11017
+ logErr(startProblem);
11018
+ process.exitCode = 1;
11019
+ return;
11020
+ }
10622
11021
  const harnessProblem = managedCodex ? null : await checkHarnessSdk(opts.projectDir, opts.harness);
10623
11022
  if (harnessProblem) {
10624
11023
  logErr(harnessProblem);
@@ -10679,12 +11078,12 @@ function makeServeCommand() {
10679
11078
  );
10680
11079
  }
10681
11080
  async function ensurePluginsLoadedForServe(projectDir) {
10682
- const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-DE53KG3E.js');
11081
+ const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-LUSV2ICC.js');
10683
11082
  try {
10684
11083
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
10685
11084
  const config = resolveSkWorkspaceConfig2(projectDir);
10686
11085
  if (!config.plugins || config.plugins.length === 0) return;
10687
- const { ensurePluginsLoaded } = await import('../plugin-store-MSH6GK6T.js');
11086
+ const { ensurePluginsLoaded } = await import('../plugin-store-36SIL4TV.js');
10688
11087
  const { pluginRegistry } = await import('../plugin-registry/index.js');
10689
11088
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
10690
11089
  if (result.loaded.length > 0) {
@@ -10698,14 +11097,14 @@ async function ensurePluginsLoadedForServe(projectDir) {
10698
11097
  }
10699
11098
  }
10700
11099
  async function runCompileTest(opts) {
10701
- const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-DE53KG3E.js');
11100
+ const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-LUSV2ICC.js');
10702
11101
  const { tmpdir } = await import('os');
10703
11102
  const { dirname: dirname3, join: join6, resolve: resolve4 } = await import('path');
10704
11103
  const { fileURLToPath: fileURLToPath2 } = await import('url');
10705
11104
  const { unlinkSync, existsSync: existsSync22 } = await import('fs');
10706
11105
  const { spawn } = await import('child_process');
10707
11106
  const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
10708
- const { MONOREPO_ROOT } = await import('../paths-QAV4C3KX.js');
11107
+ const { MONOREPO_ROOT } = await import('../paths-2AZXB3QL.js');
10709
11108
  if (MONOREPO_ROOT === null) {
10710
11109
  logErr2("--compile-test is only available inside the skaile-dev workspace.");
10711
11110
  logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
@@ -10898,6 +11297,15 @@ function localQuery(dbPath, q) {
10898
11297
  db.close();
10899
11298
  }
10900
11299
  }
11300
+ function localSessionExists(dbPath, sessionId) {
11301
+ const db = openSqlite(dbPath, { readonly: true });
11302
+ try {
11303
+ db.exec("PRAGMA query_only=1;");
11304
+ return db.prepare("SELECT 1 AS found FROM log_entries WHERE session_id = $sid LIMIT 1").get({ $sid: sessionId }) != null;
11305
+ } finally {
11306
+ db.close();
11307
+ }
11308
+ }
10901
11309
  function buildSelect(q) {
10902
11310
  const where = ["session_id = $sid"];
10903
11311
  const params = { $sid: q.sessionId };
@@ -11188,7 +11596,7 @@ function resolveMode2(opts) {
11188
11596
  if (opts.forceLocal && opts.forceRemote) {
11189
11597
  throw new Error("Cannot use both --local and --remote");
11190
11598
  }
11191
- const startDir = path18__default.resolve(opts.projectDir ?? process.cwd());
11599
+ const startDir = path19__default.resolve(opts.projectDir ?? process.cwd());
11192
11600
  const localDb = findLogsDb(startDir);
11193
11601
  if (opts.forceLocal) {
11194
11602
  if (!localDb) {
@@ -11221,14 +11629,14 @@ function resolveMode2(opts) {
11221
11629
  function findLogsDb(startDir) {
11222
11630
  let dir = startDir;
11223
11631
  for (let i = 0; i < MAX_WALK_LEVELS; i++) {
11224
- const candidate = path18__default.join(dir, ".skaile", "logs.db");
11632
+ const candidate = path19__default.join(dir, ".skaile", "logs.db");
11225
11633
  if (existsSync(candidate)) {
11226
11634
  try {
11227
11635
  if (statSync(candidate).isFile()) return candidate;
11228
11636
  } catch {
11229
11637
  }
11230
11638
  }
11231
- const parent = path18__default.dirname(dir);
11639
+ const parent = path19__default.dirname(dir);
11232
11640
  if (parent === dir) return void 0;
11233
11641
  dir = parent;
11234
11642
  }
@@ -11327,6 +11735,9 @@ function buildLogQuery(opts) {
11327
11735
  async function fetchEntries(sessionId, opts, resolved, query) {
11328
11736
  if (resolved.mode === "local") {
11329
11737
  const result2 = localQuery(resolved.dbPath, { ...query, sessionId });
11738
+ if (result2.entries.length === 0 && !localSessionExists(resolved.dbPath, sessionId)) {
11739
+ throw new Error(`No session ${sessionId} in this project's log database.`);
11740
+ }
11330
11741
  return { entries: result2.entries, nextCursor: result2.nextCursor };
11331
11742
  }
11332
11743
  if (!opts.projectId) {
@@ -11418,7 +11829,7 @@ async function requireSession(projectDir, idOrPrefix) {
11418
11829
  function makeSessionCommand() {
11419
11830
  const cmd = new Command("session").description("Manage sessions");
11420
11831
  cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
11421
- const projectDir = path18__default.resolve(opts.projectDir);
11832
+ const projectDir = path19__default.resolve(opts.projectDir);
11422
11833
  const sessions = await listSessions(projectDir);
11423
11834
  const current = await loadSession(projectDir);
11424
11835
  if (sessions.length === 0) {
@@ -11446,18 +11857,18 @@ function makeSessionCommand() {
11446
11857
  console.log();
11447
11858
  });
11448
11859
  cmd.command("show <run-id>").description("Show a specific session (full run ID or the prefix `session list` prints)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (idOrPrefix, opts) => {
11449
- const projectDir = path18__default.resolve(opts.projectDir);
11860
+ const projectDir = path19__default.resolve(opts.projectDir);
11450
11861
  const { session } = await requireSession(projectDir, idOrPrefix);
11451
11862
  console.log(JSON.stringify(session, null, 2));
11452
11863
  });
11453
11864
  cmd.command("switch <run-id>").description("Switch the current session (full run ID or the prefix `session list` prints)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (idOrPrefix, opts) => {
11454
- const projectDir = path18__default.resolve(opts.projectDir);
11865
+ const projectDir = path19__default.resolve(opts.projectDir);
11455
11866
  const { runId } = await requireSession(projectDir, idOrPrefix);
11456
11867
  await setCurrentSession(projectDir, runId);
11457
11868
  logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
11458
11869
  });
11459
11870
  cmd.command("delete <run-id>").description("Delete a session (full run ID or the prefix `session list` prints)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (idOrPrefix, opts) => {
11460
- const projectDir = path18__default.resolve(opts.projectDir);
11871
+ const projectDir = path19__default.resolve(opts.projectDir);
11461
11872
  const { runId } = await requireSession(projectDir, idOrPrefix);
11462
11873
  await deleteSession(projectDir, runId);
11463
11874
  logOk(`Deleted session: ${S.dim(runId.slice(0, 8))}`);
@@ -11534,7 +11945,7 @@ function makeShowCommand() {
11534
11945
  requireProjectConfig(opts.projectDir, { allowMissing: true });
11535
11946
  const am2 = new AssetManager({
11536
11947
  registry: getKindRegistry(),
11537
- projectDir: path18__default.resolve(opts.projectDir),
11948
+ projectDir: path19__default.resolve(opts.projectDir),
11538
11949
  harness: opts.target
11539
11950
  });
11540
11951
  if (!kind) {
@@ -11562,7 +11973,7 @@ function searchCuratedManifests(query) {
11562
11973
  const slug = file.slice(0, -".yaml".length);
11563
11974
  let manifest;
11564
11975
  try {
11565
- manifest = decodeSkaileManifest(readFileSync(path18.join(dir, file), "utf-8")).manifest;
11976
+ manifest = decodeSkaileManifest(readFileSync(path19.join(dir, file), "utf-8")).manifest;
11566
11977
  } catch {
11567
11978
  continue;
11568
11979
  }
@@ -11582,6 +11993,13 @@ async function fetchIdentity() {
11582
11993
  const jwt = await getStoreToken();
11583
11994
  return storeFetch({ ...getStoreConfig(), jwt }, "/api/v1/me");
11584
11995
  }
11996
+ function storeRefProblem(ref, err) {
11997
+ const message = err instanceof Error ? err.message : String(err);
11998
+ const plain = message.replace(/ Run the `migrate-skaile-manifest`.*$/, "");
11999
+ if (!plain.startsWith("publisher required")) return message;
12000
+ const name = /^(?:[^:@/#\s]+:)?([^@/#\s]+)/.exec(ref.trim())?.[1];
12001
+ return name ? `${plain} Find the publisher with \`skaile store search ${name}\`.` : plain;
12002
+ }
11585
12003
  async function storeNotFoundMessage(remote, ref) {
11586
12004
  const parsed = parseAssetRef(ref);
11587
12005
  let versions = [];
@@ -11636,7 +12054,7 @@ function makeStoreCommand() {
11636
12054
  });
11637
12055
  store.command("mode <auto|local|remote>").description("Set the catalog resolution mode (not yet wired)").action((_mode) => {
11638
12056
  logErr(
11639
- `\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path18__default.join(globalSkaileDir(), "store", "config.yaml")}.`
12057
+ `\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path19__default.join(globalSkaileDir(), "store", "config.yaml")}.`
11640
12058
  );
11641
12059
  process.exit(2);
11642
12060
  });
@@ -11644,9 +12062,9 @@ function makeStoreCommand() {
11644
12062
  "--all",
11645
12063
  `List every match (default: ${STORE_ROW_LIMIT} rows, only what \`skaile add\` can install)`
11646
12064
  ).option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (query, opts) => {
11647
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-RJGJIW5H.js');
11648
- const { getKnownKinds: getKnownKinds2 } = await import('../open-registry-3QS3J7KO.js');
11649
- const projectDir = path18__default.resolve(opts.projectDir);
12065
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-XBR46DJL.js');
12066
+ const { getKnownKinds: getKnownKinds2 } = await import('../open-registry-W562DCDL.js');
12067
+ const projectDir = path19__default.resolve(opts.projectDir);
11650
12068
  if (opts.kind && !getKnownKinds2().has(opts.kind)) {
11651
12069
  logErr(
11652
12070
  `Unknown kind "${opts.kind}". Valid kinds: ${[...getKnownKinds2()].sort().join(", ")}`
@@ -11703,16 +12121,16 @@ function makeStoreCommand() {
11703
12121
  }
11704
12122
  });
11705
12123
  store.command("show <ref>").description("Show a store asset's details + provenance (source, files, integrity)").option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (ref, opts) => {
11706
- const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-RJGJIW5H.js');
11707
- const { supportsInstallManifest: supportsInstallManifest2 } = await import('../project-HZW2MZPA.js');
12124
+ const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-XBR46DJL.js');
12125
+ const { supportsInstallManifest: supportsInstallManifest2 } = await import('../project-D7GN7WLS.js');
11708
12126
  try {
11709
12127
  parseAssetRef(ref);
11710
12128
  } catch (e) {
11711
- logErr(`Invalid asset ref "${ref}": ${e instanceof Error ? e.message : String(e)}`);
12129
+ logErr(`Invalid asset ref "${ref}": ${storeRefProblem(ref, e)}`);
11712
12130
  process.exit(1);
11713
12131
  }
11714
12132
  try {
11715
- const remote = await openCatalogSource2({ projectDir: path18__default.resolve(opts.projectDir) });
12133
+ const remote = await openCatalogSource2({ projectDir: path19__default.resolve(opts.projectDir) });
11716
12134
  const asset = await remote.resolve(ref);
11717
12135
  if (!asset) {
11718
12136
  logErr(await storeNotFoundMessage(remote, ref));
@@ -11723,7 +12141,7 @@ function makeStoreCommand() {
11723
12141
  const manifestFailure = {};
11724
12142
  if (supportsInstallManifest2(remote)) {
11725
12143
  manifest = await remote.getInstallManifest(canonical).catch(async (err) => {
11726
- manifestFailure.text = await describeStoreFailure(err, path18__default.resolve(opts.projectDir));
12144
+ manifestFailure.text = await describeStoreFailure(err, path19__default.resolve(opts.projectDir));
11727
12145
  return null;
11728
12146
  });
11729
12147
  }
@@ -11771,9 +12189,14 @@ function makeStoreCommand() {
11771
12189
  }
11772
12190
  console.log();
11773
12191
  const notInstallable = storeNotInstallableReason(asset);
11774
- console.log(
11775
- notInstallable ? ` ${S.dim(`Not installable: ${notInstallable}`)}` : ` ${S.dim(`Install: skaile add ${canonical}`)}`
11776
- );
12192
+ const notRunnable = !notInstallable && asset.kind === "mcp-server" && manifest ? await mcpNotRunnableHere(manifest, asset.name) : void 0;
12193
+ if (notInstallable) console.log(` ${S.dim(`Not installable: ${notInstallable}`)}`);
12194
+ else if (notRunnable) {
12195
+ console.log(` ${S.dim(`Not runnable here: ${notRunnable}`)}`);
12196
+ console.log(
12197
+ ` ${S.dim(`skaile add ${canonical} still records it in the lock, but writes no .mcp.json entry.`)}`
12198
+ );
12199
+ } else console.log(` ${S.dim(`Install: skaile add ${canonical}`)}`);
11777
12200
  console.log();
11778
12201
  } catch (e) {
11779
12202
  if (e instanceof LocalCatalogDisabledError2) {
@@ -11782,7 +12205,7 @@ function makeStoreCommand() {
11782
12205
  );
11783
12206
  } else {
11784
12207
  logErr(
11785
- `Store show failed: ${await describeStoreFailure(e, path18__default.resolve(opts.projectDir))}`
12208
+ `Store show failed: ${await describeStoreFailure(e, path19__default.resolve(opts.projectDir))}`
11786
12209
  );
11787
12210
  }
11788
12211
  process.exit(1);
@@ -11856,7 +12279,7 @@ function makeTreeCommand() {
11856
12279
  requireProjectConfig(opts.projectDir);
11857
12280
  const am2 = new AssetManager({
11858
12281
  registry: getKindRegistry(),
11859
- projectDir: path18__default.resolve(opts.projectDir)
12282
+ projectDir: path19__default.resolve(opts.projectDir)
11860
12283
  });
11861
12284
  const root = await am2.tree();
11862
12285
  if (root.children.length === 0) {
@@ -11882,9 +12305,12 @@ function makeUpdateCommand() {
11882
12305
  return new Command("update").description("Refresh the Catalog cache and re-deploy outdated assets in the current project").argument(
11883
12306
  "[name]",
11884
12307
  "Update only this declared asset (kind:@publisher/name, kind:name or name); exits 1 when none matches"
11885
- ).option("--project-dir <path>", "Project directory", process.cwd()).option("--no-catalog", "Skip refreshing the catalog cache").option("--catalog-only", "Refresh the catalog cache only; do not re-deploy assets").option("--no-sync", "Skip syncing sources from upstream before re-deploying").option("-y, --yes", "Sync sources without the confirmation prompt").action(
12308
+ ).option("--project-dir <path>", "Project directory", process.cwd()).option("--no-catalog", "Skip refreshing the catalog cache").option("--catalog-only", "Refresh the catalog cache only; do not re-deploy assets").option("--no-sync", "Skip syncing sources from upstream before re-deploying").option("-y, --yes", "Sync sources without the confirmation prompt").option(
12309
+ "--force",
12310
+ "Delete files the new content does not ship, and overwrite hand-edited agent files"
12311
+ ).action(
11886
12312
  async (name, opts) => {
11887
- const projectDir = path18__default.resolve(opts.projectDir);
12313
+ const projectDir = path19__default.resolve(opts.projectDir);
11888
12314
  if (!opts.catalogOnly) requireProjectConfig(projectDir);
11889
12315
  const am2 = new AssetManager({
11890
12316
  registry: getKindRegistry(),
@@ -11904,7 +12330,7 @@ function makeUpdateCommand() {
11904
12330
  const catalogSpinner = createSpinner();
11905
12331
  catalogSpinner.start("Refreshing catalog cache");
11906
12332
  try {
11907
- const remote = await openCatalogSource({ projectDir: path18__default.resolve(opts.projectDir) });
12333
+ const remote = await openCatalogSource({ projectDir: path19__default.resolve(opts.projectDir) });
11908
12334
  const result2 = await remote.refresh({ timeoutMs: CATALOG_REFRESH_TIMEOUT_MS });
11909
12335
  catalogSpinner.stop(
11910
12336
  `Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
@@ -11938,14 +12364,14 @@ function makeUpdateCommand() {
11938
12364
  }
11939
12365
  }
11940
12366
  if (target) {
11941
- await updateOne(am2, projectDir, target);
12367
+ await updateOne(am2, projectDir, target, opts.force);
11942
12368
  return;
11943
12369
  }
11944
12370
  const spinner = createSpinner();
11945
12371
  spinner.start("Re-deploying assets");
11946
12372
  let result;
11947
12373
  try {
11948
- result = await am2.install({ moveLibraries: true });
12374
+ result = await am2.install({ moveLibraries: true, force: opts.force });
11949
12375
  } catch (err) {
11950
12376
  spinner.stop("Failed");
11951
12377
  logErr(String(err));
@@ -12032,20 +12458,21 @@ async function resolveUpdateTarget(am2, name) {
12032
12458
  );
12033
12459
  process.exit(1);
12034
12460
  }
12035
- logErr(`No declared asset matches "${name}".`);
12461
+ const otherKind = await am2.otherKindHint(name);
12462
+ logErr(`No declared asset matches "${name}".${otherKind ? ` ${otherKind}` : ""}`);
12036
12463
  if (declared.length > 0) logInfo(`Declared: ${declared.map((d) => d.ref).join(", ")}`);
12037
12464
  process.exit(1);
12038
12465
  }
12039
12466
  async function needsCatalog(am2, projectDir) {
12040
12467
  let lock = null;
12041
12468
  try {
12042
- lock = readLock(path18__default.join(projectDir, "skaile.lock.yaml"));
12469
+ lock = readLock(path19__default.join(projectDir, "skaile.lock.yaml"));
12043
12470
  } catch {
12044
12471
  lock = null;
12045
12472
  }
12046
12473
  let declaredUrls = /* @__PURE__ */ new Set();
12047
12474
  try {
12048
- const yamlPath = path18__default.join(projectDir, "skaile.yaml");
12475
+ const yamlPath = path19__default.join(projectDir, "skaile.yaml");
12049
12476
  declaredUrls = new Set(
12050
12477
  WorkspaceYamlEditor.load(yamlPath).getSources().map((s) => normalizeRepoUrl(s.url))
12051
12478
  );
@@ -12080,8 +12507,8 @@ function readText2(file) {
12080
12507
  return "";
12081
12508
  }
12082
12509
  }
12083
- async function updateOne(am2, projectDir, target) {
12084
- const lockPath = path18__default.join(projectDir, "skaile.lock.yaml");
12510
+ async function updateOne(am2, projectDir, target, force) {
12511
+ const lockPath = path19__default.join(projectDir, "skaile.lock.yaml");
12085
12512
  const before = readText2(lockPath);
12086
12513
  const spinner = createSpinner();
12087
12514
  spinner.start(`Updating ${target.ref}`);
@@ -12089,6 +12516,7 @@ async function updateOne(am2, projectDir, target) {
12089
12516
  try {
12090
12517
  deployed = await am2.add(target.ref, {
12091
12518
  preferLockedLibrary: true,
12519
+ force,
12092
12520
  onLibraryMoved: (m) => reportMoved([m])
12093
12521
  });
12094
12522
  } catch (err) {
@@ -12277,7 +12705,7 @@ function makeWhyCommand() {
12277
12705
  requireProjectConfig(opts.projectDir);
12278
12706
  const am2 = new AssetManager({
12279
12707
  registry: getKindRegistry(),
12280
- projectDir: path18__default.resolve(opts.projectDir)
12708
+ projectDir: path19__default.resolve(opts.projectDir)
12281
12709
  });
12282
12710
  const chain = await am2.why(ref);
12283
12711
  if (chain.length === 0) {
@@ -12287,6 +12715,12 @@ function makeWhyCommand() {
12287
12715
  process.exitCode = 1;
12288
12716
  return;
12289
12717
  }
12718
+ const otherKind = await am2.otherKindHint(ref);
12719
+ if (otherKind) {
12720
+ logErr(`${ref} is not a locked skill. ${otherKind}`);
12721
+ process.exitCode = 1;
12722
+ return;
12723
+ }
12290
12724
  let declared;
12291
12725
  try {
12292
12726
  declared = await am2.listDeclared();
@@ -12349,7 +12783,7 @@ function isIndexBusyError(err) {
12349
12783
  var _defaultFormatHelp = Help.prototype.formatHelp;
12350
12784
  var pkg = JSON.parse(
12351
12785
  readFileSync(
12352
- path18__default.resolve(path18__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
12786
+ path19__default.resolve(path19__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
12353
12787
  "utf-8"
12354
12788
  )
12355
12789
  );
@@ -12360,7 +12794,7 @@ for (const key of [
12360
12794
  "SKAILE_CACHE_DIR"
12361
12795
  ]) {
12362
12796
  const value = process.env[key];
12363
- if (value) process.env[key] = path18__default.resolve(value);
12797
+ if (value) process.env[key] = path19__default.resolve(value);
12364
12798
  }
12365
12799
  var program = new Command("skaile").description("AI asset manager").version(pkg.version, "-v, --version", "Show the skaile CLI version").enablePositionalOptions().configureHelp({
12366
12800
  formatHelp(cmd, helper) {
@@ -12375,6 +12809,7 @@ Project:
12375
12809
  clean [--all] [--dry-run] Remove skaile-managed assets
12376
12810
  setup Interactive provider setup wizard
12377
12811
  config show|get|set Personal settings
12812
+ harness set <name> Switch the project to claude-code | omp | codex and install
12378
12813
 
12379
12814
  Assets (skill, agent, prompt, flow, preset, contract):
12380
12815
  add <ref> [--global] Add to skaile.yaml + deploy
@@ -12472,48 +12907,61 @@ Advanced:
12472
12907
  }
12473
12908
  });
12474
12909
  var INIT_HARNESS_DEFAULTS = {
12475
- "claude-code": { harness: "claude-sdk" },
12476
- omp: { harness: "omp" },
12477
- codex: { harness: "codex" }
12910
+ "claude-code": { harness: HARNESS_ID_OF_TARGET["claude-code"] },
12911
+ omp: { harness: HARNESS_ID_OF_TARGET.omp },
12912
+ codex: { harness: HARNESS_ID_OF_TARGET.codex }
12478
12913
  };
12479
- program.command("init [project-dir]").description("Initialize a project directory (defaults to current directory)").option("--harness <name>", "Coding-agent harness (claude-code | omp | codex)", "claude-code").option("--no-git", "Skip git init and .gitignore").action(
12914
+ program.command("init [project-dir]").description("Initialize a project directory (defaults to current directory)").option(
12915
+ "--harness <name>",
12916
+ "Coding-agent harness of a new project (claude-code | omp | codex; default claude-code)"
12917
+ ).option("--no-git", "Skip git init and .gitignore").action(
12480
12918
  (projectDir, opts) => runInit(projectDir, opts)
12481
12919
  );
12482
12920
  async function runInit(projectDir, opts) {
12483
12921
  const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync7 } = await import('fs');
12484
12922
  const { stringify: stringify2 } = await import('yaml');
12485
- const { HARNESS_TARGETS: HARNESS_TARGETS2, SUPPORTED_HARNESSES: SUPPORTED_HARNESSES2 } = await import('../core/index.js');
12486
- const harness = opts.harness;
12923
+ const { HARNESS_TARGETS: HARNESS_TARGETS2, SUPPORTED_HARNESSES: SUPPORTED_HARNESSES2, resolveConfiguredHarnessName: resolveConfiguredHarnessName2 } = await import('../core/index.js');
12924
+ const harness = opts.harness ?? "claude-code";
12487
12925
  if (!SUPPORTED_HARNESSES2.includes(harness)) {
12488
- logErr(`Unknown harness "${opts.harness}". Supported: ${SUPPORTED_HARNESSES2.join(", ")}`);
12926
+ logErr(unknownHarnessTargetMessage(opts.harness ?? ""));
12489
12927
  process.exitCode = 1;
12490
12928
  return;
12491
12929
  }
12492
- const resolved = path18__default.resolve(projectDir ?? ".");
12493
- const projectName = path18__default.basename(resolved);
12930
+ const resolved = path19__default.resolve(projectDir ?? ".");
12931
+ if (opts.harness && (await import('fs')).existsSync(path19__default.join(resolved, "skaile.yaml"))) {
12932
+ const current = resolveConfiguredHarnessName2(resolved);
12933
+ if (current !== harness) {
12934
+ logErr(
12935
+ `${resolved} is already a skaile project${current ? ` on ${current}` : ""}. To switch it to ${harness}, run: skaile harness set ${harness}`
12936
+ );
12937
+ process.exitCode = 1;
12938
+ return;
12939
+ }
12940
+ }
12941
+ const projectName = path19__default.basename(resolved);
12494
12942
  const created = [];
12495
12943
  const { existsSync: existsSync22 } = await import('fs');
12496
12944
  if (!existsSync22(resolved)) {
12497
12945
  mkdirSync5(resolved, { recursive: true });
12498
12946
  created.push(".");
12499
12947
  }
12500
- const skaileDir = path18__default.join(resolved, ".skaile");
12948
+ const skaileDir = path19__default.join(resolved, ".skaile");
12501
12949
  if (!existsSync22(skaileDir)) {
12502
- mkdirSync5(path18__default.join(skaileDir, "sessions"), { recursive: true });
12950
+ mkdirSync5(path19__default.join(skaileDir, "sessions"), { recursive: true });
12503
12951
  created.push(".skaile/");
12504
12952
  }
12505
- const settingsPath = path18__default.join(skaileDir, "settings.json");
12953
+ const settingsPath = path19__default.join(skaileDir, "settings.json");
12506
12954
  if (!existsSync22(settingsPath)) {
12507
12955
  writeFileSync7(settingsPath, "{}\n");
12508
12956
  created.push(".skaile/settings.json");
12509
12957
  }
12510
- const wsConfigPath = path18__default.join(resolved, "skaile.yaml");
12958
+ const wsConfigPath = path19__default.join(resolved, "skaile.yaml");
12511
12959
  if (!existsSync22(wsConfigPath)) {
12512
12960
  writeFileSync7(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
12513
12961
  created.push("skaile.yaml");
12514
12962
  }
12515
12963
  for (const dir of new Set(Object.values(HARNESS_TARGETS2[harness].local))) {
12516
- const full = path18__default.join(resolved, dir);
12964
+ const full = path19__default.join(resolved, dir);
12517
12965
  if (!existsSync22(full)) {
12518
12966
  mkdirSync5(full, { recursive: true });
12519
12967
  created.push(`${dir}/`);
@@ -12545,7 +12993,7 @@ function buildInitWorkspaceConfig(projectName, harness) {
12545
12993
  async function initGitScaffold(resolved, created) {
12546
12994
  const { execSync: execSync2 } = await import('child_process');
12547
12995
  const { existsSync: existsSync22, readFileSync: readFileSync13, writeFileSync: writeFileSync7 } = await import('fs');
12548
- const gitignorePath = path18__default.join(resolved, ".gitignore");
12996
+ const gitignorePath = path19__default.join(resolved, ".gitignore");
12549
12997
  const entries = [
12550
12998
  "node_modules/",
12551
12999
  // Python bytecode a deployed skill script leaves inside `.claude/skills` and friends.
@@ -12589,7 +13037,7 @@ async function initGitScaffold(resolved, created) {
12589
13037
  `);
12590
13038
  if (!existing) created.push(".gitignore");
12591
13039
  }
12592
- if (!existsSync22(path18__default.join(resolved, ".git"))) {
13040
+ if (!existsSync22(path19__default.join(resolved, ".git"))) {
12593
13041
  try {
12594
13042
  execSync2("git init", { cwd: resolved, stdio: "pipe" });
12595
13043
  created.push(".git/");
@@ -12619,7 +13067,7 @@ async function bootstrapUserConfig() {
12619
13067
  }
12620
13068
  async function hydrateInitSources(resolved, created) {
12621
13069
  try {
12622
- const { ensureSourcesCloned } = await import('../ensure-sources-UPTHZKGF.js');
13070
+ const { ensureSourcesCloned } = await import('../ensure-sources-K5EFNC3L.js');
12623
13071
  const hydrate = ensureSourcesCloned(resolved, { quiet: true });
12624
13072
  for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
12625
13073
  if (hydrate.failed.length > 0) {
@@ -12635,7 +13083,7 @@ function printInitSummary(resolved, projectDir, created) {
12635
13083
  logOk(`Initialized project at ${S.heading(resolved)}`);
12636
13084
  console.log();
12637
13085
  console.log(S.heading(" Next steps:"));
12638
- const isCurrentDir = resolved === path18__default.resolve(".");
13086
+ const isCurrentDir = resolved === path19__default.resolve(".");
12639
13087
  let step = 1;
12640
13088
  if (!isCurrentDir) {
12641
13089
  console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
@@ -12659,7 +13107,7 @@ function printInitSummary(resolved, projectDir, created) {
12659
13107
  console.log();
12660
13108
  }
12661
13109
  program.command("setup").description("Interactive provider setup wizard").action(async () => {
12662
- const { cmdSetup } = await import('../setup-AGYB4PKR.js');
13110
+ const { cmdSetup } = await import('../setup-IBDNJAOU.js');
12663
13111
  await cmdSetup([], { projectDir: process.cwd() });
12664
13112
  });
12665
13113
  program.addCommand(makeInstallCommand());
@@ -12667,6 +13115,7 @@ program.addCommand(makeCheckCommand());
12667
13115
  program.addCommand(makeCleanCommand());
12668
13116
  program.addCommand(makeCacheCommand());
12669
13117
  program.addCommand(makeConfigCommand());
13118
+ program.addCommand(makeHarnessCommand());
12670
13119
  program.addCommand(makeProvidersCommand());
12671
13120
  program.addCommand(makeMigrateCommand());
12672
13121
  program.addCommand(makeAddCommand());
@@ -12738,8 +13187,8 @@ program.hook("postAction", async (_thisCommand, actionCommand) => {
12738
13187
  if (!["add", "remove", "install", "update"].includes(actionCommand.name())) return;
12739
13188
  const opts = actionCommand.opts();
12740
13189
  if (opts.global || opts.dryRun) return;
12741
- const projectDir = path18__default.resolve(opts.projectDir ?? process.cwd());
12742
- const { refreshPluginSkills } = await import('../claude-code-VJGYBXQR.js');
13190
+ const projectDir = path19__default.resolve(opts.projectDir ?? process.cwd());
13191
+ const { refreshPluginSkills } = await import('../claude-code-BBMNVH2J.js');
12743
13192
  try {
12744
13193
  if (await refreshPluginSkills(projectDir)) {
12745
13194
  logInfo(`Updated ${S.cmd(".claude/plugins/skaile/skills")} (the --full plugin copy)`);
@@ -12757,6 +13206,20 @@ process.once("beforeExit", () => {
12757
13206
  logErr("The command ended before it finished (nothing left to wait for).");
12758
13207
  process.exit(1);
12759
13208
  });
13209
+ setLibraryAssetCheck(
13210
+ (asset, libraryPath) => libraryAssetRefusals(asset, libraryPath, getKindRegistry())
13211
+ );
13212
+ setRenamedEntryLookup(manifestEntryRenames);
13213
+ setWalkTruncationSink((info, root) => {
13214
+ const where = path19__default.basename(root);
13215
+ if (info.reason === "cycle") {
13216
+ logWarnErr(
13217
+ `${where}: asset scan truncated (cycle) - the symlink ${info.path} points back into the tree, so the result is incomplete. Remove the symlink; \`skaile library index ${where}\` lists every one.`
13218
+ );
13219
+ return;
13220
+ }
13221
+ logWarnErr(`${where}: asset scan truncated (${info.reason}) - the result is incomplete.`);
13222
+ });
12760
13223
  try {
12761
13224
  await program.parseAsync();
12762
13225
  commandSettled = true;