@skaile/workspaces 6.14.0 → 6.16.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 (447) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/agent-file-refresh-76NNFB4W.js +89 -0
  3. package/dist/agent-file-refresh-76NNFB4W.js.map +1 -0
  4. package/dist/ai-sdk.js +8 -7
  5. package/dist/ai-sdk.js.map +1 -1
  6. package/dist/app-sdk/index.js +1 -1
  7. package/dist/{asset-feeds-DOG5FK7T.js → asset-feeds-ON7FYHHF.js} +25 -23
  8. package/dist/asset-feeds-ON7FYHHF.js.map +1 -0
  9. package/dist/asset-manager/catalog-deployer.js +8 -7
  10. package/dist/asset-manager/history.js +7 -6
  11. package/dist/asset-manager/index.js +17 -15
  12. package/dist/asset-manager/installer.js +16 -9
  13. package/dist/asset-manager/renderers.js +8 -8
  14. package/dist/asset-manager/src/add-remove/add.d.ts +134 -0
  15. package/dist/asset-manager/src/add-remove/add.d.ts.map +1 -0
  16. package/dist/asset-manager/src/add-remove/remove.d.ts +329 -0
  17. package/dist/asset-manager/src/add-remove/remove.d.ts.map +1 -0
  18. package/dist/asset-manager/src/agent-render.d.ts +116 -0
  19. package/dist/asset-manager/src/agent-render.d.ts.map +1 -0
  20. package/dist/asset-manager/src/composed-blocks.d.ts +40 -0
  21. package/dist/asset-manager/src/composed-blocks.d.ts.map +1 -0
  22. package/dist/asset-manager/src/config/core.d.ts +297 -0
  23. package/dist/asset-manager/src/config/core.d.ts.map +1 -0
  24. package/dist/asset-manager/src/config/edit.d.ts +161 -0
  25. package/dist/asset-manager/src/config/edit.d.ts.map +1 -0
  26. package/dist/asset-manager/src/index.d.ts +31 -2961
  27. package/dist/asset-manager/src/index.d.ts.map +1 -1
  28. package/dist/asset-manager/src/install/clone-commit-fetcher.d.ts +11 -0
  29. package/dist/asset-manager/src/install/clone-commit-fetcher.d.ts.map +1 -0
  30. package/dist/asset-manager/src/install/install.d.ts +151 -0
  31. package/dist/asset-manager/src/install/install.d.ts.map +1 -0
  32. package/dist/asset-manager/src/install/restore.d.ts +76 -0
  33. package/dist/asset-manager/src/install/restore.d.ts.map +1 -0
  34. package/dist/asset-manager/src/install-agent.d.ts +52 -4
  35. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  36. package/dist/asset-manager/src/install-instances.d.ts +70 -2
  37. package/dist/asset-manager/src/install-instances.d.ts.map +1 -1
  38. package/dist/asset-manager/src/installer.d.ts +54 -4
  39. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  40. package/dist/asset-manager/src/lock/copies.d.ts +156 -0
  41. package/dist/asset-manager/src/lock/copies.d.ts.map +1 -0
  42. package/dist/asset-manager/src/lock/library.d.ts +261 -0
  43. package/dist/asset-manager/src/lock/library.d.ts.map +1 -0
  44. package/dist/asset-manager/src/mcp-render.d.ts +86 -0
  45. package/dist/asset-manager/src/mcp-render.d.ts.map +1 -0
  46. package/dist/asset-manager/src/omp-sweep.d.ts +25 -0
  47. package/dist/asset-manager/src/omp-sweep.d.ts.map +1 -0
  48. package/dist/asset-manager/src/read/diff.d.ts +109 -0
  49. package/dist/asset-manager/src/read/diff.d.ts.map +1 -0
  50. package/dist/asset-manager/src/read/doctor.d.ts +116 -0
  51. package/dist/asset-manager/src/read/doctor.d.ts.map +1 -0
  52. package/dist/asset-manager/src/read/gaps.d.ts +120 -0
  53. package/dist/asset-manager/src/read/gaps.d.ts.map +1 -0
  54. package/dist/asset-manager/src/read/graph.d.ts +69 -0
  55. package/dist/asset-manager/src/read/graph.d.ts.map +1 -0
  56. package/dist/asset-manager/src/read/outdated.d.ts +152 -0
  57. package/dist/asset-manager/src/read/outdated.d.ts.map +1 -0
  58. package/dist/asset-manager/src/read/state.d.ts +265 -0
  59. package/dist/asset-manager/src/read/state.d.ts.map +1 -0
  60. package/dist/asset-manager/src/renderers.d.ts +11 -1
  61. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  62. package/dist/asset-manager/src/resolve/guards.d.ts +167 -0
  63. package/dist/asset-manager/src/resolve/guards.d.ts.map +1 -0
  64. package/dist/asset-manager/src/resolve/scan.d.ts +222 -0
  65. package/dist/asset-manager/src/resolve/scan.d.ts.map +1 -0
  66. package/dist/asset-manager/src/resolve/stores.d.ts +176 -0
  67. package/dist/asset-manager/src/resolve/stores.d.ts.map +1 -0
  68. package/dist/asset-manager/src/shared/files.d.ts +42 -0
  69. package/dist/asset-manager/src/shared/files.d.ts.map +1 -0
  70. package/dist/asset-manager/src/shared/library-hooks.d.ts +16 -0
  71. package/dist/asset-manager/src/shared/library-hooks.d.ts.map +1 -0
  72. package/dist/asset-manager/src/shared/library.d.ts +96 -0
  73. package/dist/asset-manager/src/shared/library.d.ts.map +1 -0
  74. package/dist/asset-manager/src/shared/refs.d.ts +101 -0
  75. package/dist/asset-manager/src/shared/refs.d.ts.map +1 -0
  76. package/dist/asset-manager/src/shared/types.d.ts +399 -0
  77. package/dist/asset-manager/src/shared/types.d.ts.map +1 -0
  78. package/dist/bridge/harnesses/claude-sdk.js +13 -19
  79. package/dist/bridge/harnesses/claude-sdk.js.map +1 -1
  80. package/dist/bridge/harnesses/codex.js +10 -10
  81. package/dist/bridge/harnesses/continue.js +12 -16
  82. package/dist/bridge/harnesses/continue.js.map +1 -1
  83. package/dist/bridge/harnesses/echo.js +5 -10
  84. package/dist/bridge/harnesses/echo.js.map +1 -1
  85. package/dist/bridge/harnesses/gemini.js +5 -5
  86. package/dist/bridge/harnesses/goose.js +13 -17
  87. package/dist/bridge/harnesses/goose.js.map +1 -1
  88. package/dist/bridge/harnesses/omp.js +7 -13
  89. package/dist/bridge/harnesses/omp.js.map +1 -1
  90. package/dist/bridge/harnesses/opencode.js +13 -17
  91. package/dist/bridge/harnesses/opencode.js.map +1 -1
  92. package/dist/bridge/harnesses/qwen.js +6 -11
  93. package/dist/bridge/harnesses/qwen.js.map +1 -1
  94. package/dist/bridge/index.js +18 -18
  95. package/dist/bridge/src/codex/managed-harness.d.ts.map +1 -1
  96. package/dist/bridge/src/driver-contract.d.ts +72 -0
  97. package/dist/bridge/src/driver-contract.d.ts.map +1 -0
  98. package/dist/bridge/src/harness-model-check.d.ts +1 -1
  99. package/dist/bridge/src/harness-model-check.d.ts.map +1 -1
  100. package/dist/bridge/src/harnesses/_subprocess-cli.d.ts +8 -0
  101. package/dist/bridge/src/harnesses/_subprocess-cli.d.ts.map +1 -1
  102. package/dist/bridge/src/harnesses/claude-sdk.d.ts.map +1 -1
  103. package/dist/bridge/src/harnesses/codex.d.ts +2 -0
  104. package/dist/bridge/src/harnesses/codex.d.ts.map +1 -1
  105. package/dist/bridge/src/harnesses/continue.d.ts.map +1 -1
  106. package/dist/bridge/src/harnesses/echo.d.ts.map +1 -1
  107. package/dist/bridge/src/harnesses/gemini.d.ts.map +1 -1
  108. package/dist/bridge/src/harnesses/goose.d.ts.map +1 -1
  109. package/dist/bridge/src/harnesses/omp.d.ts.map +1 -1
  110. package/dist/bridge/src/harnesses/opencode.d.ts.map +1 -1
  111. package/dist/bridge/src/harnesses/qwen.d.ts.map +1 -1
  112. package/dist/bridge/src/index.d.ts +2 -0
  113. package/dist/bridge/src/index.d.ts.map +1 -1
  114. package/dist/bridge/src/preflight.d.ts +114 -0
  115. package/dist/bridge/src/preflight.d.ts.map +1 -0
  116. package/dist/bridge/src/registry.d.ts +12 -0
  117. package/dist/bridge/src/registry.d.ts.map +1 -1
  118. package/dist/{chunk-7UBCUKJO.js → chunk-2JUCWMIS.js} +8808 -8337
  119. package/dist/chunk-2JUCWMIS.js.map +1 -0
  120. package/dist/{chunk-VS6XC5JE.js → chunk-2MTRRK37.js} +3 -3
  121. package/dist/{chunk-VS6XC5JE.js.map → chunk-2MTRRK37.js.map} +1 -1
  122. package/dist/chunk-2PJYJPDE.js +3 -0
  123. package/dist/chunk-2PJYJPDE.js.map +1 -0
  124. package/dist/{chunk-ZQL6HGTW.js → chunk-2SSG5B24.js} +4 -4
  125. package/dist/{chunk-ZQL6HGTW.js.map → chunk-2SSG5B24.js.map} +1 -1
  126. package/dist/{chunk-WDG5IVEA.js → chunk-2ZDZJ7XQ.js} +3 -3
  127. package/dist/{chunk-WDG5IVEA.js.map → chunk-2ZDZJ7XQ.js.map} +1 -1
  128. package/dist/{chunk-V2VDTQ7A.js → chunk-3A7JUOY2.js} +3 -3
  129. package/dist/{chunk-V2VDTQ7A.js.map → chunk-3A7JUOY2.js.map} +1 -1
  130. package/dist/chunk-3LAJJURV.js +26 -0
  131. package/dist/chunk-3LAJJURV.js.map +1 -0
  132. package/dist/{chunk-X66KSHZF.js → chunk-3UYKT62L.js} +5 -5
  133. package/dist/{chunk-X66KSHZF.js.map → chunk-3UYKT62L.js.map} +1 -1
  134. package/dist/{chunk-J3FJTH3V.js → chunk-4X5WXQV7.js} +4 -4
  135. package/dist/{chunk-J3FJTH3V.js.map → chunk-4X5WXQV7.js.map} +1 -1
  136. package/dist/chunk-4ZNKEDYH.js +887 -0
  137. package/dist/chunk-4ZNKEDYH.js.map +1 -0
  138. package/dist/{chunk-DYH3VSPU.js → chunk-65SOXO7I.js} +20 -14
  139. package/dist/chunk-65SOXO7I.js.map +1 -0
  140. package/dist/{chunk-MVUXBWNW.js → chunk-6HTN2UIJ.js} +3 -3
  141. package/dist/{chunk-MVUXBWNW.js.map → chunk-6HTN2UIJ.js.map} +1 -1
  142. package/dist/{chunk-4SSTREBO.js → chunk-6KV34G6A.js} +8 -8
  143. package/dist/{chunk-4SSTREBO.js.map → chunk-6KV34G6A.js.map} +1 -1
  144. package/dist/{chunk-YNQRVTXH.js → chunk-6M44OQKH.js} +40 -44
  145. package/dist/chunk-6M44OQKH.js.map +1 -0
  146. package/dist/{chunk-B6W5DCH5.js → chunk-72DYHOO2.js} +24 -25
  147. package/dist/chunk-72DYHOO2.js.map +1 -0
  148. package/dist/{chunk-RRAXV5LE.js → chunk-7IW5E6LB.js} +43 -48
  149. package/dist/chunk-7IW5E6LB.js.map +1 -0
  150. package/dist/{chunk-BNLXZXZN.js → chunk-BRAOB37W.js} +97 -47
  151. package/dist/chunk-BRAOB37W.js.map +1 -0
  152. package/dist/{chunk-ZLDAPZIX.js → chunk-BTMSHGN3.js} +4 -4
  153. package/dist/{chunk-ZLDAPZIX.js.map → chunk-BTMSHGN3.js.map} +1 -1
  154. package/dist/{chunk-7K73MCI6.js → chunk-CU5WY6HN.js} +3 -3
  155. package/dist/{chunk-7K73MCI6.js.map → chunk-CU5WY6HN.js.map} +1 -1
  156. package/dist/{chunk-G2ZWIYZR.js → chunk-DFFJKGCW.js} +3 -3
  157. package/dist/{chunk-G2ZWIYZR.js.map → chunk-DFFJKGCW.js.map} +1 -1
  158. package/dist/{chunk-CG63XGVV.js → chunk-EGKCKWWE.js} +3 -3
  159. package/dist/{chunk-CG63XGVV.js.map → chunk-EGKCKWWE.js.map} +1 -1
  160. package/dist/{chunk-CJO3XKO7.js → chunk-ETGC2MEM.js} +4 -4
  161. package/dist/{chunk-CJO3XKO7.js.map → chunk-ETGC2MEM.js.map} +1 -1
  162. package/dist/{chunk-CFRHYD4C.js → chunk-FPG36VC4.js} +8 -13
  163. package/dist/chunk-FPG36VC4.js.map +1 -0
  164. package/dist/{chunk-SBAUZ7XH.js → chunk-H3PY5DFL.js} +4 -4
  165. package/dist/{chunk-SBAUZ7XH.js.map → chunk-H3PY5DFL.js.map} +1 -1
  166. package/dist/{chunk-7HRZACI4.js → chunk-HW4BDJPC.js} +17 -6
  167. package/dist/chunk-HW4BDJPC.js.map +1 -0
  168. package/dist/{chunk-GJT2Q5XD.js → chunk-HXST2IYJ.js} +3 -3
  169. package/dist/{chunk-GJT2Q5XD.js.map → chunk-HXST2IYJ.js.map} +1 -1
  170. package/dist/{chunk-7VBD5XUM.js → chunk-IG4YQ7ER.js} +32 -90
  171. package/dist/chunk-IG4YQ7ER.js.map +1 -0
  172. package/dist/{chunk-DWPQBMCY.js → chunk-JPV4WE5L.js} +2 -2
  173. package/dist/{chunk-DWPQBMCY.js.map → chunk-JPV4WE5L.js.map} +1 -1
  174. package/dist/{chunk-OC3AIMZH.js → chunk-KDRA6FYE.js} +120 -211
  175. package/dist/chunk-KDRA6FYE.js.map +1 -0
  176. package/dist/{chunk-KOI7QFDH.js → chunk-M7XIYHWB.js} +3 -3
  177. package/dist/{chunk-KOI7QFDH.js.map → chunk-M7XIYHWB.js.map} +1 -1
  178. package/dist/{chunk-7LJUK5JK.js → chunk-MG6QD7GE.js} +201 -43
  179. package/dist/chunk-MG6QD7GE.js.map +1 -0
  180. package/dist/{chunk-XHLRMUMO.js → chunk-NAQXDTF3.js} +3 -3
  181. package/dist/{chunk-XHLRMUMO.js.map → chunk-NAQXDTF3.js.map} +1 -1
  182. package/dist/{chunk-YJAKSCCN.js → chunk-NJ6UCY2B.js} +3 -3
  183. package/dist/{chunk-YJAKSCCN.js.map → chunk-NJ6UCY2B.js.map} +1 -1
  184. package/dist/{chunk-OKPITFE3.js → chunk-NNJQQYHY.js} +2 -2
  185. package/dist/{chunk-OKPITFE3.js.map → chunk-NNJQQYHY.js.map} +1 -1
  186. package/dist/{chunk-QNHW26AT.js → chunk-OD4N5O7V.js} +4 -4
  187. package/dist/{chunk-QNHW26AT.js.map → chunk-OD4N5O7V.js.map} +1 -1
  188. package/dist/{chunk-F7WMHDTV.js → chunk-P6FJDT35.js} +27 -7
  189. package/dist/chunk-P6FJDT35.js.map +1 -0
  190. package/dist/{chunk-IOXFT5D7.js → chunk-PD42JZWI.js} +3 -3
  191. package/dist/{chunk-IOXFT5D7.js.map → chunk-PD42JZWI.js.map} +1 -1
  192. package/dist/{chunk-MS2IXLTC.js → chunk-PMXTBWFD.js} +27 -7
  193. package/dist/chunk-PMXTBWFD.js.map +1 -0
  194. package/dist/{chunk-NAAFRZTA.js → chunk-PPSSDUN6.js} +3 -3
  195. package/dist/{chunk-NAAFRZTA.js.map → chunk-PPSSDUN6.js.map} +1 -1
  196. package/dist/{chunk-LMUNQYJQ.js → chunk-PRB67LCK.js} +127 -18
  197. package/dist/chunk-PRB67LCK.js.map +1 -0
  198. package/dist/{chunk-RLV3FF4I.js → chunk-QUIK7L3Z.js} +11 -11
  199. package/dist/{chunk-RLV3FF4I.js.map → chunk-QUIK7L3Z.js.map} +1 -1
  200. package/dist/{chunk-DRUAQ7IY.js → chunk-QUPZKTF3.js} +9 -8
  201. package/dist/chunk-QUPZKTF3.js.map +1 -0
  202. package/dist/{chunk-7FXOOUOC.js → chunk-RPRMD7XV.js} +27 -11
  203. package/dist/chunk-RPRMD7XV.js.map +1 -0
  204. package/dist/{chunk-3BRBTQ6M.js → chunk-S3UOZBGE.js} +20 -3
  205. package/dist/chunk-S3UOZBGE.js.map +1 -0
  206. package/dist/{chunk-LQWOU7S2.js → chunk-SFBLZOV5.js} +3 -3
  207. package/dist/{chunk-LQWOU7S2.js.map → chunk-SFBLZOV5.js.map} +1 -1
  208. package/dist/{chunk-EB2LKPI6.js → chunk-SMFZ5YGN.js} +4 -4
  209. package/dist/{chunk-EB2LKPI6.js.map → chunk-SMFZ5YGN.js.map} +1 -1
  210. package/dist/{chunk-243Z3BNB.js → chunk-SX54OQQT.js} +4 -4
  211. package/dist/{chunk-243Z3BNB.js.map → chunk-SX54OQQT.js.map} +1 -1
  212. package/dist/{chunk-2PVYDAFN.js → chunk-T65N4CIZ.js} +3 -3
  213. package/dist/{chunk-2PVYDAFN.js.map → chunk-T65N4CIZ.js.map} +1 -1
  214. package/dist/{chunk-QBLS7X3Z.js → chunk-TVRL3IPZ.js} +3 -3
  215. package/dist/{chunk-QBLS7X3Z.js.map → chunk-TVRL3IPZ.js.map} +1 -1
  216. package/dist/{chunk-2URJ7W5X.js → chunk-TW5AP6IF.js} +5 -5
  217. package/dist/{chunk-2URJ7W5X.js.map → chunk-TW5AP6IF.js.map} +1 -1
  218. package/dist/{chunk-F6LDWA2N.js → chunk-TYK752MU.js} +3 -3
  219. package/dist/{chunk-F6LDWA2N.js.map → chunk-TYK752MU.js.map} +1 -1
  220. package/dist/{chunk-HPQ2WDYC.js → chunk-U2WPJHRA.js} +5 -5
  221. package/dist/{chunk-HPQ2WDYC.js.map → chunk-U2WPJHRA.js.map} +1 -1
  222. package/dist/{chunk-MEU2HHGV.js → chunk-U7P22GEB.js} +386 -46
  223. package/dist/chunk-U7P22GEB.js.map +1 -0
  224. package/dist/{chunk-6ISJMEDX.js → chunk-VFEZUSB6.js} +4 -4
  225. package/dist/{chunk-6ISJMEDX.js.map → chunk-VFEZUSB6.js.map} +1 -1
  226. package/dist/{chunk-5FO4U3OL.js → chunk-WW22FS74.js} +75 -67
  227. package/dist/chunk-WW22FS74.js.map +1 -0
  228. package/dist/{chunk-WCUT3EQR.js → chunk-Z23I2JA6.js} +7 -7
  229. package/dist/{chunk-WCUT3EQR.js.map → chunk-Z23I2JA6.js.map} +1 -1
  230. package/dist/{chunk-VKGNMXGZ.js → chunk-Z7HLX4V2.js} +4 -4
  231. package/dist/{chunk-VKGNMXGZ.js.map → chunk-Z7HLX4V2.js.map} +1 -1
  232. package/dist/{chunk-LZCX2TCZ.js → chunk-ZII54C3E.js} +355 -1075
  233. package/dist/chunk-ZII54C3E.js.map +1 -0
  234. package/dist/{chunk-CVUMZTNO.js → chunk-ZQPBYLCS.js} +4 -4
  235. package/dist/{chunk-CVUMZTNO.js.map → chunk-ZQPBYLCS.js.map} +1 -1
  236. package/dist/{claude-code-LFAOJ3UQ.js → claude-code-VL6UM7BZ.js} +4 -4
  237. package/dist/{claude-code-LFAOJ3UQ.js.map → claude-code-VL6UM7BZ.js.map} +1 -1
  238. package/dist/cli/index.js +494 -301
  239. package/dist/cli/index.js.map +1 -1
  240. package/dist/cli/src/agent-file-refresh.d.ts +25 -0
  241. package/dist/cli/src/agent-file-refresh.d.ts.map +1 -0
  242. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  243. package/dist/cli/src/commands/catalog.d.ts +9 -2
  244. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  245. package/dist/cli/src/commands/config.d.ts.map +1 -1
  246. package/dist/cli/src/commands/harness.d.ts +1 -1
  247. package/dist/cli/src/commands/harness.d.ts.map +1 -1
  248. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  249. package/dist/cli/src/commands/library-index.d.ts +5 -7
  250. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  251. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  252. package/dist/cli/src/commands/preset-export.d.ts.map +1 -1
  253. package/dist/cli/src/commands/project.d.ts.map +1 -1
  254. package/dist/cli/src/commands/run.d.ts.map +1 -1
  255. package/dist/cli/src/commands/serve-preflight.d.ts +27 -48
  256. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
  257. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  258. package/dist/cli/src/commands/source.d.ts +6 -9
  259. package/dist/cli/src/commands/source.d.ts.map +1 -1
  260. package/dist/cli/src/commands/validate.d.ts +6 -0
  261. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  262. package/dist/cli/src/config-checks.d.ts.map +1 -1
  263. package/dist/cli/src/harness-error.d.ts +11 -9
  264. package/dist/cli/src/harness-error.d.ts.map +1 -1
  265. package/dist/cli/src/skill-checks.d.ts +48 -74
  266. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  267. package/dist/connectors/config.js +5 -5
  268. package/dist/connectors/index.js +22 -22
  269. package/dist/{connectors-KPF4UUDS.js → connectors-7EPJRVLJ.js} +25 -25
  270. package/dist/{connectors-KPF4UUDS.js.map → connectors-7EPJRVLJ.js.map} +1 -1
  271. package/dist/connectors-shared/index.js +2 -2
  272. package/dist/core/index.js +7 -6
  273. package/dist/core/manifest.js +2 -2
  274. package/dist/core/models.js +1 -1
  275. package/dist/core/publish-manifest.js +3 -3
  276. package/dist/core/ref.js +1 -1
  277. package/dist/core/runtime-assets.js +5 -5
  278. package/dist/core/src/agent-prompt-sections.d.ts +96 -4
  279. package/dist/core/src/agent-prompt-sections.d.ts.map +1 -1
  280. package/dist/core/src/check-asset.d.ts +115 -0
  281. package/dist/core/src/check-asset.d.ts.map +1 -0
  282. package/dist/core/src/harness-model.d.ts +20 -0
  283. package/dist/core/src/harness-model.d.ts.map +1 -0
  284. package/dist/core/src/index.d.ts +10 -6
  285. package/dist/core/src/index.d.ts.map +1 -1
  286. package/dist/core/src/lock.d.ts +12 -10
  287. package/dist/core/src/lock.d.ts.map +1 -1
  288. package/dist/core/src/models.d.ts +42 -11
  289. package/dist/core/src/models.d.ts.map +1 -1
  290. package/dist/core/src/publish-manifest.d.ts +17 -0
  291. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  292. package/dist/core/src/repo-identity.d.ts +41 -0
  293. package/dist/core/src/repo-identity.d.ts.map +1 -0
  294. package/dist/core/src/repo-manager.d.ts +3 -9
  295. package/dist/core/src/repo-manager.d.ts.map +1 -1
  296. package/dist/core/src/walker.d.ts.map +1 -1
  297. package/dist/core/src/workspace-config.d.ts.map +1 -1
  298. package/dist/core/workspace-config.js +4 -4
  299. package/dist/deploy/index.js +7 -6
  300. package/dist/deploy/index.js.map +1 -1
  301. package/dist/discovery/index.js +5 -5
  302. package/dist/discovery/src/source-config.d.ts.map +1 -1
  303. package/dist/{ensure-sources-FOMEGCQ5.js → ensure-sources-CI3JQJST.js} +32 -30
  304. package/dist/ensure-sources-CI3JQJST.js.map +1 -0
  305. package/dist/factory-assets/connectors/box.js +22 -22
  306. package/dist/factory-assets/connectors/deploy.js +22 -22
  307. package/dist/factory-assets/connectors/devserver.js +22 -22
  308. package/dist/factory-assets/connectors/flow/adapter.js +22 -22
  309. package/dist/factory-assets/connectors/flow/engine.js +8 -7
  310. package/dist/factory-assets/connectors/flow/run-flow.js +24 -24
  311. package/dist/factory-assets/connectors/flow.js +22 -22
  312. package/dist/factory-assets/connectors/git.js +22 -22
  313. package/dist/factory-assets/connectors/gmail.js +22 -22
  314. package/dist/factory-assets/connectors/googledrive.js +22 -22
  315. package/dist/factory-assets/connectors/local.js +22 -22
  316. package/dist/factory-assets/connectors/mattermost.js +22 -22
  317. package/dist/factory-assets/connectors/memory.js +22 -22
  318. package/dist/factory-assets/connectors/minio.js +22 -22
  319. package/dist/factory-assets/connectors/postgres.js +22 -22
  320. package/dist/factory-assets/connectors/s3.js +22 -22
  321. package/dist/factory-assets/connectors/sharepoint.js +22 -22
  322. package/dist/factory-assets/connectors/sqlite.js +22 -22
  323. package/dist/factory-assets/connectors/static-server.js +22 -22
  324. package/dist/factory-assets/connectors/tunnel.js +22 -22
  325. package/dist/factory-assets/connectors/webdav.js +22 -22
  326. package/dist/factory-assets/connectors/xstate-store.js +22 -22
  327. package/dist/factory-assets/connectors/xstate.js +22 -22
  328. package/dist/{flows-J64L5MGJ.js → flows-6XQAYQS4.js} +12 -11
  329. package/dist/{flows-J64L5MGJ.js.map → flows-6XQAYQS4.js.map} +1 -1
  330. package/dist/{helpers-ZJ67FO3Z.js → helpers-26MR5QPO.js} +32 -30
  331. package/dist/{helpers-ZJ67FO3Z.js.map → helpers-26MR5QPO.js.map} +1 -1
  332. package/dist/library/index.js +10 -10
  333. package/dist/library/install.js +4 -4
  334. package/dist/library/src/index.d.ts +1 -1
  335. package/dist/library/src/index.d.ts.map +1 -1
  336. package/dist/library/src/local/db.d.ts.map +1 -1
  337. package/dist/library/src/local/library-manager.d.ts.map +1 -1
  338. package/dist/library/src/local/library.d.ts.map +1 -1
  339. package/dist/library/src/local/schema.d.ts +19 -0
  340. package/dist/library/src/local/schema.d.ts.map +1 -1
  341. package/dist/library/src/user-library.d.ts +18 -0
  342. package/dist/library/src/user-library.d.ts.map +1 -1
  343. package/dist/{library-publish-RGVXGTY4.js → library-publish-F3AKF66O.js} +74 -68
  344. package/dist/library-publish-F3AKF66O.js.map +1 -0
  345. package/dist/model-endpoint/index.js +10 -9
  346. package/dist/{open-library-I5JHL37T.js → open-library-FVV6GG4I.js} +35 -33
  347. package/dist/{open-library-I5JHL37T.js.map → open-library-FVV6GG4I.js.map} +1 -1
  348. package/dist/{open-registry-4HNCWOCN.js → open-registry-VX2BVMS5.js} +16 -16
  349. package/dist/{open-registry-4HNCWOCN.js.map → open-registry-VX2BVMS5.js.map} +1 -1
  350. package/dist/{paths-PXBWY532.js → paths-PIWSSUUG.js} +10 -9
  351. package/dist/{paths-PXBWY532.js.map → paths-PIWSSUUG.js.map} +1 -1
  352. package/dist/{plugin-store-ZC3EGZ3D.js → plugin-store-MVTW6G7J.js} +10 -9
  353. package/dist/{plugin-store-ZC3EGZ3D.js.map → plugin-store-MVTW6G7J.js.map} +1 -1
  354. package/dist/{project-K5JWPIJ6.js → project-GFQP4TW6.js} +50 -48
  355. package/dist/{project-K5JWPIJ6.js.map → project-GFQP4TW6.js.map} +1 -1
  356. package/dist/resolver/index.js +8 -7
  357. package/dist/runner/composition-content.d.ts +2 -0
  358. package/dist/runner/composition-content.js +29 -0
  359. package/dist/runner/composition-content.js.map +1 -0
  360. package/dist/runner/index.js +40 -39
  361. package/dist/runner/src/compaction/prompt.d.ts.map +1 -1
  362. package/dist/runner/src/composition/content-entry.d.ts +15 -0
  363. package/dist/runner/src/composition/content-entry.d.ts.map +1 -0
  364. package/dist/runner/src/composition/content-source.d.ts +7 -0
  365. package/dist/runner/src/composition/content-source.d.ts.map +1 -1
  366. package/dist/runner/src/composition/dry-run.d.ts +5 -1
  367. package/dist/runner/src/composition/dry-run.d.ts.map +1 -1
  368. package/dist/runner/src/composition/index.d.ts +1 -1
  369. package/dist/runner/src/composition/index.d.ts.map +1 -1
  370. package/dist/runner/src/composition/prompt-sections.d.ts +47 -20
  371. package/dist/runner/src/composition/prompt-sections.d.ts.map +1 -1
  372. package/dist/runner/src/context-usage/compose.d.ts.map +1 -1
  373. package/dist/runner/src/session-builder.d.ts +3 -8
  374. package/dist/runner/src/session-builder.d.ts.map +1 -1
  375. package/dist/runner/src/work-practices.d.ts +9 -0
  376. package/dist/runner/src/work-practices.d.ts.map +1 -0
  377. package/dist/sdk/asset-manager.js +17 -15
  378. package/dist/sdk/bridge.js +18 -18
  379. package/dist/sdk/core.js +7 -6
  380. package/dist/sdk/flow.js +8 -7
  381. package/dist/sdk/index.js +40 -39
  382. package/dist/sdk/index.js.map +1 -1
  383. package/dist/sdk/resolver.js +8 -7
  384. package/dist/sdk/runner.js +40 -39
  385. package/dist/sdk/session.js +2 -2
  386. package/dist/sdk/transport/ws/server.js +8 -7
  387. package/dist/sdk/transport/ws.js +8 -7
  388. package/dist/sdk/transport.js +8 -7
  389. package/dist/sdk/types.js +1 -1
  390. package/dist/serve-preflight-XJS5OZML.js +138 -0
  391. package/dist/serve-preflight-XJS5OZML.js.map +1 -0
  392. package/dist/session/index.js +2 -2
  393. package/dist/{setup-RXTNGML5.js → setup-BFEBJLYF.js} +33 -31
  394. package/dist/setup-BFEBJLYF.js.map +1 -0
  395. package/dist/{skills-5D4KDVPJ.js → skills-OCG7B5CL.js} +13 -12
  396. package/dist/{skills-5D4KDVPJ.js.map → skills-OCG7B5CL.js.map} +1 -1
  397. package/dist/source-P6JPZYWP.js +93 -0
  398. package/dist/{source-2LP5W3ST.js.map → source-P6JPZYWP.js.map} +1 -1
  399. package/dist/{source-manifest-publish-EZNCTSQF.js → source-manifest-publish-XBFHEURV.js} +54 -52
  400. package/dist/source-manifest-publish-XBFHEURV.js.map +1 -0
  401. package/dist/transport/index.js +8 -7
  402. package/dist/transport/ws/server.js +8 -7
  403. package/dist/transport/ws.js +8 -7
  404. package/dist/tui/index.js +40 -39
  405. package/dist/tui/index.js.map +1 -1
  406. package/dist/types/index.js +1 -1
  407. package/dist/types/src/context-usage.d.ts +1 -1
  408. package/dist/types/src/events.d.ts +3 -2
  409. package/dist/types/src/events.d.ts.map +1 -1
  410. package/dist/types/src/runtime.d.ts +6 -0
  411. package/dist/types/src/runtime.d.ts.map +1 -1
  412. package/dist/workspace-plugin/adapters/mcp.js +29 -29
  413. package/dist/workspace-plugin/adapters/omp.js +14 -14
  414. package/dist/workspace-plugin/index.js +1 -1
  415. package/package.json +7 -1
  416. package/dist/asset-feeds-DOG5FK7T.js.map +0 -1
  417. package/dist/chunk-3BRBTQ6M.js.map +0 -1
  418. package/dist/chunk-5FO4U3OL.js.map +0 -1
  419. package/dist/chunk-7FXOOUOC.js.map +0 -1
  420. package/dist/chunk-7HRZACI4.js.map +0 -1
  421. package/dist/chunk-7LJUK5JK.js.map +0 -1
  422. package/dist/chunk-7UBCUKJO.js.map +0 -1
  423. package/dist/chunk-7VBD5XUM.js.map +0 -1
  424. package/dist/chunk-A7TM4PZZ.js +0 -110
  425. package/dist/chunk-A7TM4PZZ.js.map +0 -1
  426. package/dist/chunk-B6W5DCH5.js.map +0 -1
  427. package/dist/chunk-BNLXZXZN.js.map +0 -1
  428. package/dist/chunk-CFRHYD4C.js.map +0 -1
  429. package/dist/chunk-DRUAQ7IY.js.map +0 -1
  430. package/dist/chunk-DYH3VSPU.js.map +0 -1
  431. package/dist/chunk-F7WMHDTV.js.map +0 -1
  432. package/dist/chunk-LMUNQYJQ.js.map +0 -1
  433. package/dist/chunk-LZCX2TCZ.js.map +0 -1
  434. package/dist/chunk-MEU2HHGV.js.map +0 -1
  435. package/dist/chunk-MS2IXLTC.js.map +0 -1
  436. package/dist/chunk-OC3AIMZH.js.map +0 -1
  437. package/dist/chunk-RRAXV5LE.js.map +0 -1
  438. package/dist/chunk-YNQRVTXH.js.map +0 -1
  439. package/dist/cli/src/commands/harness-preflight.d.ts +0 -40
  440. package/dist/cli/src/commands/harness-preflight.d.ts.map +0 -1
  441. package/dist/ensure-sources-FOMEGCQ5.js.map +0 -1
  442. package/dist/library-publish-RGVXGTY4.js.map +0 -1
  443. package/dist/serve-preflight-L6VVCDM5.js +0 -61
  444. package/dist/serve-preflight-L6VVCDM5.js.map +0 -1
  445. package/dist/setup-RXTNGML5.js.map +0 -1
  446. package/dist/source-2LP5W3ST.js +0 -91
  447. package/dist/source-manifest-publish-EZNCTSQF.js.map +0 -1
@@ -9,807 +9,27 @@
9
9
  * const am = new AssetManager({ projectDir: "/path/to/project" })
10
10
  * await am.install()
11
11
  */
12
- import type { AssetRef, CatalogEntry, HarnessName, LockFile, StoreFetcher } from "@skaile/workspaces/core";
13
- import type { IAssetKindRegistry } from "@skaile/workspaces/plugins";
14
12
  import { FACTORY_SOURCE_URL } from "@skaile/workspaces/core";
15
- import type { PresetExpansion } from "@skaile/workspaces/core";
16
- import type { AssetDefinition, AssetFetcher, Library } from "@skaile/workspaces/library";
17
- import type { HistoryEntry } from "./history.js";
18
- import { type InstalledAgentInstance } from "./install-instances.js";
19
- import type { ScaffoldOptions } from "./installer.js";
20
- import { type DeployableEntry } from "./installer.js";
21
- /**
22
- * Normalize a git remote URL to a comparable identity so the same repo declared
23
- * in different syntaxes (`https://…`, `git@host:…`, trailing `/`, `.git` suffix,
24
- * case) compares equal. Used to dedupe the implicit factory source against an
25
- * explicit user declaration.
26
- */
27
- export declare function normalizeRepoUrl(url: string): string;
28
- /**
29
- * The checks one library asset must pass before `add` deploys it, as the lines `skaile validate`
30
- * prints for it (`<file> [<tag>] - <text>`). The asset manager does not know the per-kind checks
31
- * (they live with `validate`), so the host registers them once at startup; none registered means
32
- * `add` runs no such check (library use without the CLI). An asset the check refuses is never
33
- * deployed, as one the manifest does not list is not (p1550).
34
- */
35
- export type LibraryAssetCheck = (asset: {
36
- kind: string;
37
- name: string;
38
- source: string;
39
- }, libraryPath: string) => string[];
40
- /** Register (or with `undefined`, remove) the {@link LibraryAssetCheck} `add` runs per library asset. */
41
- export declare function setLibraryAssetCheck(check: LibraryAssetCheck | undefined): void;
42
- /**
43
- * A first-party manifest entry of a library whose asset file now names another asset (`name:`, a
44
- * flow's `id:`), before `library index` renamed the entry: `publisher` is the entry's own or the
45
- * manifest's, `file` the asset file relative to the library and `now` the name it carries.
46
- */
47
- export interface RenamedLibraryEntry {
48
- kind: string;
49
- name: string;
50
- publisher?: string;
51
- file: string;
52
- now: string;
53
- /**
54
- * The sentence that fixes the entry when `library index` cannot rename it (a flow whose `id:`
55
- * no longer matches its file name: index drops the entry instead), `undefined` when index renames it.
56
- */
57
- fileFix?: string;
58
- }
59
- /** The {@link RenamedLibraryEntry}s of the library at `libraryPath`. Registered by the host, as {@link LibraryAssetCheck}. */
60
- export type RenamedEntryLookup = (libraryPath: string) => RenamedLibraryEntry[];
61
- /** Register (or with `undefined`, remove) the {@link RenamedEntryLookup} `add` asks when a ref resolves to nothing (p1603). */
62
- export declare function setRenamedEntryLookup(lookup: RenamedEntryLookup | undefined): void;
63
- /** One row of {@link AssetManager.libraryHolders}: a library holding a ref at one version. */
64
- export interface LibraryHolder {
65
- library: string;
66
- version: string;
67
- description: string;
68
- /** `true` for the holder `add <ref>` deploys. */
69
- picked: boolean;
70
- }
71
- /**
72
- * One origin that holds a ref, see {@link AssetManager.refOrigins}: the bundled factory
73
- * source, a project source clone, or a registered library.
74
- */
75
- export interface RefOrigin {
76
- kind: "factory" | "source" | "library";
77
- /** `factory`, the source's short name, or the library name. */
78
- label: string;
79
- version: string;
80
- description: string;
81
- }
82
- /**
83
- * Parse a canonical lock key (`<kind>:@<publisher>/<name>#<version>`) into its
84
- * parts. The lock key is a canonical asset ref, so this delegates to the one ref
85
- * parser; `AssetRef.pin` is exposed as `version` so the callers' destructuring is
86
- * unchanged. Stays total — callers rely on `{}`-then-`continue`, but `parseAssetRef`
87
- * throws, so a genuinely malformed key is caught and returned as `{}`.
88
- *
89
- * A **content-sha pseudo-version** key (`#0.0.0-sha.<hash>`, the version every
90
- * manifest-less source gets) fails `parseAssetRef`'s canonical-pin check. Dropping
91
- * it to `{}` would strip the identity, so the install reconcile / state machine
92
- * could never act on such an asset (it silently survives a remove-from-yaml). Fall
93
- * back to parsing the bare identity, keeping the raw pin as `version`.
94
- *
95
- * @internal Exported for unit tests; not part of the stable public surface.
96
- */
97
- export declare function parseCanonicalLockKey(key: string): {
98
- publisher?: string;
99
- kind?: string;
100
- name?: string;
101
- version?: string;
102
- };
103
- /**
104
- * Replace the `diff -u` timestamps of the `---` / `+++` header lines with a label of the side
105
- * (`--- <file> (deployed)`, `+++ <file> (library)`). A file that is missing on one side shows
106
- * the epoch there (`1970-01-01`), which says nothing a reader wants (p1693).
107
- */
108
- export declare function labelDiffHeaders(diff: string, from: string, to: string): string;
109
- /**
110
- * Bare asset name of a soft-dep target ref (`@pub/name@ver` → `name`); splits the
111
- * version off the *last* `@` since the leading one is the scope sigil. The
112
- * present-check matches on this bare name only (under-reports — the safe direction).
113
- */
114
- export declare function softDepName(ref: string): string;
115
- /**
116
- * Parse a ref for lookup, tolerating a **missing publisher** (`kind:name`, the
117
- * shape `listDeployed` emits and the strict `parseAssetRef` rejects). Returns
118
- * `null` when neither kind nor name is recoverable. Unlike {@link parseAssetRefLoose}
119
- * (publisher-required, only strips a `#pin`), this keeps the publisher optional.
120
- *
121
- * @internal Exported for unit tests; not part of the stable public surface.
122
- */
123
- export declare function parseRefTolerant(ref: string): AssetRef | null;
124
- /**
125
- * A library asset that `add`, `install` and the status commands cannot use as it is (a version
126
- * that is not semver, a flow file the engine does not load). The CLI prints its message as one
127
- * `✗` line, never a stack trace (p874, p1082).
128
- */
129
- export declare class LibraryEntryError extends Error {
130
- }
131
- /** A locked asset that now resolves from another library than its lock entry named. */
132
- export interface LibraryMove {
133
- /** `kind:@publisher/name` (no version). */
134
- ref: string;
135
- /** Library name the lock entry recorded. */
136
- from: string;
137
- /** Library name the asset resolved from now. */
138
- to: string;
139
- }
140
- /** One asset a `skaile add --dry-run` would deploy. */
141
- export interface AddPlanItem {
142
- /** `kind:@publisher/name`. */
143
- ref: string;
144
- version: string;
145
- /** `library <name>`, `source <name>`, `factory` or `store`. */
146
- origin: string;
147
- /** True for the asset that was asked for; false for a dependency it pulls. */
148
- requested: boolean;
149
- /** Deploy folders per harness target (project-relative, or `~`-relative for a global add). Empty for an agent. */
150
- folders: string[];
151
- /** Files of the asset, relative to its folder, when the resolver knows them. Empty for an agent. */
152
- files: string[];
153
- /** The native agent files each harness target gets, for an agent: it is rendered, not copied (p1621). */
154
- renders: string[];
155
- }
156
- /** A source whose origin `outdated` could not fetch, so its behind count was not checked (p1820). */
157
- export interface UnreachableSource {
158
- /** Short name of the source (`<owner>/<repo>` of its URL). */
159
- name: string;
160
- url: string;
161
- /** One line why: the fetch error, or why the clone was not compared with its origin at all. */
162
- reason: string;
163
- /** Set when no fetch was tried: the clone's origin is another repository, or it holds no git checkout. */
164
- notCompared?: true;
165
- }
166
- /** A locked library asset whose library holds the locked version with other bytes (an edit with no bump). */
167
- export interface ContentHeld {
168
- /** The lock key, `kind:@publisher/name#version`. */
169
- ref: string;
170
- /** The library that holds the changed files. */
171
- library: string;
172
- version: string;
173
- }
174
- /**
175
- * Reconciliation state of a declared dependency relative to the lock + disk.
176
- * `invalid` flags a `dependencies:` entry that isn't a parseable canonical ref —
177
- * surfaced (not silently dropped) so a `skaile.yaml` typo is visible.
178
- */
179
- export type DeclaredState = "declared" | "installed" | "drift" | "invalid" | "skipped";
180
- /**
181
- * A top-level dependency declared in `skaile.yaml`, annotated with its
182
- * reconciliation {@link DeclaredState}. Transitive (lock-only) deps are never
183
- * included — {@link AssetManager.listDeclared} walks the declared set only.
184
- */
185
- export interface DeclaredAsset {
186
- /** The canonical declared ref exactly as written in `skaile.yaml`. */
187
- ref: string;
188
- kind: string;
189
- name: string;
190
- state: DeclaredState;
191
- /** Set with `skipped`: why skaile does not write the `mcp-server` to the coding agent's MCP config. */
192
- reason?: string;
193
- }
194
- /** A note about an `mcp-server` that fails nothing. See {@link AssetManager.mcpNotices}. */
195
- export interface McpNotice {
196
- /** The declaration id (`sql`, `@admin/sql`). */
197
- id: string;
198
- kind: "skipped" | "unset-field";
199
- /** With `skipped`: why the server is not written to the MCP config. */
200
- reason?: string;
201
- /** The `!` line `check` and `doctor` print. */
202
- text: string;
203
- }
204
- /** A deployed library asset that lacks files of its library entry. See {@link AssetManager.incompleteDeploys}. */
205
- export interface IncompleteDeploy {
206
- /** Canonical ref of the asset. */
207
- ref: string;
208
- /** Files the deploy writes that are absent from the deployed directory, relative to it. */
209
- missing: string[];
210
- }
211
- /**
212
- * A tracked asset whose copy still sits in the project dirs of a harness the
213
- * project no longer deploys to. See {@link AssetManager.listStaleHarnessCopies}.
214
- */
215
- export interface StaleHarnessCopy {
216
- /** The harness whose dir holds the stale copy. */
217
- harness: HarnessName;
218
- kind: string;
219
- name: string;
220
- /** Absolute path of the stale copy. */
221
- path: string;
222
- /**
223
- * `true` when skaile wrote this copy, so `harness set --clean` may delete it: its bytes equal
224
- * the copy the active harness holds now, or (an agent, whose shape differs per harness) the
225
- * lock records the asset. `false` for a folder the user made: it is named and kept (p1671).
226
- */
227
- skaileWrote: boolean;
228
- }
229
- /**
230
- * @deprecated Use {@link StaleHarnessCopy}, which also names the harness of the stale copy.
231
- */
232
- export interface LegacyDeployedAsset {
233
- kind: string;
234
- name: string;
235
- /** Absolute path of the stale copy. */
236
- path: string;
237
- }
238
- /**
239
- * A global declared dependency from `~/.skaile/skaile.yaml`, reconciled against
240
- * **one** harness's global deploy dir. The same ref yields one entry per global
241
- * harness (see {@link AssetManager.globalState}) so an asset can read `installed`
242
- * for `claude-code` and `drift`/`declared` for `codex` simultaneously.
243
- */
244
- export interface HarnessDeclaredAsset extends DeclaredAsset {
245
- /** The global harness this state was reconciled against. */
246
- harness: HarnessName;
247
- }
248
- /** @deprecated Use {@link HarnessDeclaredAsset}; the `backend` field is now `harness`. Removed in the next major. */
249
- export type BackendDeclaredAsset = HarnessDeclaredAsset;
250
- /**
251
- * A body-link soft-dependency edge: asset `from` references target `to` in its
252
- * body (not its typed `requires`). `toRef` is the parseable `skaile add` ref when
253
- * the target is in the index, omitted otherwise. Surfaced read-only — never
254
- * auto-installed (see {@link AssetManager.softDepsOf} / {@link AssetManager.reportSoftDeps}).
255
- */
256
- export interface SoftDepEdge {
257
- from: string;
258
- to: string;
259
- toRef?: string;
260
- }
261
- /**
262
- * A soft-dependency target that would be left orphaned by removing some assets:
263
- * it is still present in the project, came in as `from`'s soft dependency, and
264
- * nothing else still needs it (neither a soft-dep nor a typed `requires`).
265
- * Report-only — {@link AssetManager.orphanedSoftDepsAfterRemoving} never removes
266
- * it; the caller prompts (default No). `targetRef` is the parseable `skaile
267
- * remove` ref when the target is in the index.
268
- */
269
- export interface OrphanedSoftDep {
270
- from: string;
271
- target: string;
272
- targetRef?: string;
273
- }
274
- /**
275
- * Thrown by {@link AssetManager.listDeclared} when the project has no
276
- * `skaile.yaml`. The CLI maps this to a `skaile init` hint.
277
- */
278
- export declare class MissingManifestError extends Error {
279
- readonly projectDir: string;
280
- constructor(projectDir: string);
281
- }
282
- export type { HistoryEntry } from "./history.js";
283
- export { appendHistory, clearHistory, getRecentHistory, loadHistory, } from "./history.js";
284
- export type { DeployOptions, ScaffoldOptions } from "./installer.js";
285
- export type { DeployableEntry } from "./installer.js";
286
- export { createScaffold, deployAll, installTargetOf, removeAsset, SCAFFOLD_KINDS, } from "./installer.js";
287
- export type { RenderMcpConfigOptions, RenderMcpConfigResult, SkippedMcpServer, } from "./mcp-config.js";
288
- export { mcpNotRunnableReason, renderMcpServerConfig } from "./mcp-config.js";
289
- export type { Log } from "./renderers.js";
290
- export { renderAgentToFramework } from "./renderers.js";
291
- /**
292
- * Metadata about a repository declared in `skaile.yaml`.
293
- *
294
- * @docLink packages/asset-manager/concepts#asset-manager
295
- */
296
- export interface RepoInfo {
297
- /** Repository name as declared in `skaile.yaml`. */
298
- name: string;
299
- /** How the repo is sourced: cloned from a URL, mounted from a local path, or symlinked via `skaile repo link`. */
300
- kind: "local" | "remote" | "linked";
301
- /** Remote URL (present when `kind === "remote"`). */
302
- url?: string;
303
- /** Filesystem path (present when `kind === "local"` or `kind === "linked"`). */
304
- path?: string;
305
- /** Git branch configured for this repository. */
306
- branch: string;
307
- /** Whether the repository has been cloned/resolved locally. */
308
- cloned: boolean;
309
- }
310
- /**
311
- * Live sync status for a repository.
312
- *
313
- * @docLink packages/asset-manager/concepts#asset-manager
314
- */
315
- export interface RepoStatusInfo {
316
- /** Repository name as declared in `skaile.yaml`. */
317
- name: string;
318
- /** How the repo is sourced. */
319
- kind: "local" | "remote" | "linked";
320
- /** Number of commits the local clone is behind the remote. */
321
- behind: number;
322
- /** `true` when the local clone matches the remote HEAD. */
323
- upToDate: boolean;
324
- /** Error message when status check failed. */
325
- error?: string;
326
- }
327
- /** The rendered native files of one locked agent that a deploy wrote with other content. */
328
- export interface RewrittenAgent {
329
- /** Lock key of the agent asset. */
330
- ref: string;
331
- /** Project-relative POSIX paths of the files whose bytes changed. */
332
- files: string[];
333
- }
334
- /** One deployed copy `install` made equal to its locked bytes again. */
335
- export interface RestoredAsset {
336
- /** Canonical ref of the asset. */
337
- ref: string;
338
- /** Deployed files whose hand edit was overwritten (project-relative POSIX paths). */
339
- restored: string[];
340
- /** Files the asset does not ship that were deleted from its deployed directory. */
341
- removed: string[];
342
- }
343
- /** One asset `install` moved from one locked version to another. */
344
- export interface ReplacedAsset {
345
- /** `kind:@publisher/name`, no version. */
346
- ref: string;
347
- from: string;
348
- to: string;
349
- }
350
- /**
351
- * Result of a full `skaile install` or `skaile add` run.
352
- *
353
- * @docLink packages/asset-manager/concepts#asset-manager
354
- */
355
- /** A locked store asset `install` did not re-check against the store; see {@link InstallResult.storeNotChecked}. */
356
- export interface StoreNotChecked {
357
- /** The declared ref as `install` reports it (`kind:@publisher/name#version`). */
358
- ref: string;
359
- reason: "air-gapped" | "unreachable" | "skipped";
360
- /** Why the store was not asked, or what it answered (the store URL and the cause). */
361
- detail: string;
362
- }
363
- export interface InstallResult {
364
- /** Canonical refs (`kind:@publisher/name#version`) successfully deployed in this run. */
365
- deployed: string[];
366
- /**
367
- * Deployed library assets whose body is still the untouched `library create` scaffold: they
368
- * fail `validate` and the publish plan, so `install` names them (p926). Absent when none is.
369
- */
370
- placeholderBodies?: string[];
371
- /**
372
- * Deployed library assets whose `description:` is still the `library create` placeholder
373
- * (`TODO: …`): `validate` and the publish plan fail it as well. Absent when none is.
374
- */
375
- placeholderDescriptions?: string[];
376
- /** Asset refs (`kind:name`) removed because they are no longer in the resolved set. */
377
- removed: string[];
378
- /**
379
- * Asset refs that could not be resolved in any configured repository. On the
380
- * non-locked path every entry is a bare ref; the reason a miss happened lives in
381
- * {@link InstallResult.missingHints}. The `--locked` path still appends its prose
382
- * (`ref (not found in library "x")`) to the entry, and also lists every
383
- * {@link AssetManager.projectState} gap (a declared dependency or a locked asset's
384
- * `requires` with no lock entry, a lock that contradicts a `skaile.yaml` pin, a library
385
- * that cannot supply a locked asset) as its one-line message.
386
- */
387
- missing: string[];
388
- /**
389
- * Why a ref in {@link InstallResult.missing} may have missed, keyed by that ref:
390
- * the asset's publisher changed (`library set publisher=`), so the lock still holds
391
- * it under the old one and/or a library now holds it under another. Parenthesised
392
- * parts such as `did you mean skill:@acme/x?` and
393
- * `locked as skill:@plain/x; run skaile install to re-resolve`. Only refs with a
394
- * hint appear; absent when none has.
395
- */
396
- missingHints?: Record<string, string>;
397
- /**
398
- * Locked store assets `install` could not check against the store (p792, p799): the deployed
399
- * copy and the lock entry stay as they are and the asset is not in {@link InstallResult.missing}.
400
- * `air-gapped` (`catalog.cache_ttl: 0`, nothing cached) and `skipped` (`update --no-catalog`)
401
- * are a chosen mode, `unreachable` a store that did not answer. Absent when every locked store
402
- * asset was checked.
403
- */
404
- storeNotChecked?: StoreNotChecked[];
405
- /**
406
- * Lock keys whose entry `install` rewrote for an asset that was already locked: the
407
- * library or source holds another version of it, or the same version with other
408
- * content. A re-lock can happen with nothing to deploy. Absent when none changed.
409
- */
410
- relocked?: string[];
411
- /**
412
- * Locked library assets whose library holds the locked version with other bytes (an edit with
413
- * no version bump). `install` keeps their lock and deployed copy: only `skaile update` takes
414
- * the edit (OQ13, p1911). Absent when none.
415
- */
416
- contentHeld?: ContentHeld[];
417
- /**
418
- * Global entries a 5.12.0 record left without a harness subset, now limited to the one harness
419
- * that holds their copy (`ref` is `kind:@publisher/name`). Absent when nothing was inferred.
420
- */
421
- inferredHarnesses?: Array<{
422
- ref: string;
423
- harnesses: HarnessName[];
424
- }>;
425
- /**
426
- * Library-origin assets whose lock entry now names another library than before. `install`
427
- * keeps a locked asset on its library; only `update`, a pin, or a locked library that no
428
- * longer holds the asset moves it. Absent when none moved.
429
- */
430
- moved?: LibraryMove[];
431
- /**
432
- * Assets whose locked version `install` replaced with another version of the same asset
433
- * (`ref` is `kind:@publisher/name`). Not part of {@link InstallResult.removed}: nothing
434
- * left the project. Absent when none changed.
435
- */
436
- replaced?: ReplacedAsset[];
437
- /**
438
- * Deployed copies `install` made equal to their locked bytes again: a file edited by hand
439
- * (`restored`) or an extra file in the asset directory (`removed`), both as project-relative
440
- * POSIX paths. Absent when every deployed copy already matched.
441
- */
442
- restored?: RestoredAsset[];
443
- /**
444
- * One line per locked library that is not registered here but whose assets `install --locked`
445
- * restored from a store that serves the locked hash (every file SHA-verified): the notice that
446
- * the library is not registered, where the bytes came from, and how to register it. Not a failure: `missing` stays empty (OQ8, p1655).
447
- */
448
- libraryNotices?: string[];
449
- /**
450
- * Rendered agent files that a lock without `rendered:` entries (written by a CLI before
451
- * 5.12.0) did not cover and that this run wrote with other content, because the render of
452
- * the agent changed. Absent when none.
453
- */
454
- rewritten?: RewrittenAgent[];
455
- /** Whether `skaile.lock.yaml` was written or updated. */
456
- lockWritten: boolean;
457
- /**
458
- * npm packages installed as a side effect of resolving runtime asset peer
459
- * deps (connectors / mounts declared in skaile.yaml). Empty when nothing
460
- * needed installing or when the runtime-deps step was skipped.
461
- */
462
- npmInstalled?: string[];
463
- /**
464
- * npm packages that the runtime-deps step tried but failed to install.
465
- * Non-fatal — listed for telemetry and CLI reporting.
466
- */
467
- npmFailed?: string[];
468
- /**
469
- * One entry per `preset:` dependency expanded into this install (nested presets
470
- * included): how many asset items joined the install set and how many instance
471
- * items (`library://`, placeholders) were skipped.
472
- */
473
- presets?: PresetExpansion[];
474
- /**
475
- * One entry per `skaile.yaml` agent instance (`agent:` as `default`, plus
476
- * `agents:`) rendered into the target harness's native agent files, with the
477
- * workspace-relative paths written. Absent for `--global` installs and
478
- * harnesses without a native agent format.
479
- */
480
- agentInstances?: InstalledAgentInstance[];
481
- /**
482
- * Ids of the `agentInstances` whose native agent files changed in this run (a new file,
483
- * other bytes). An instance that rendered the same bytes again is not listed: `install`
484
- * re-renders every instance each run (p1673).
485
- */
486
- agentInstancesChanged?: string[];
487
- /**
488
- * Workspace-relative native agent files removed because their instance left
489
- * `skaile.yaml` (only files an earlier `skaile install` rendered are ever removed).
490
- */
491
- agentFilesRemoved?: string[];
492
- /**
493
- * Agent instances of `skaile.yaml` whose `ref` resolves to no agent (never added, or gone):
494
- * one message each. Their earlier rendering is kept. `skaile install` fails on a non-empty list.
495
- */
496
- agentInstanceErrors?: string[];
497
- /**
498
- * The resolver's own text (with the directories it searched) for each entry of
499
- * {@link agentInstanceErrors} whose message was shortened to one line of advice; for `--verbose`.
500
- */
501
- agentInstanceDetails?: string[];
502
- }
503
- /**
504
- * An installed asset whose source repository is behind the remote.
505
- *
506
- * @docLink packages/asset-manager/concepts#asset-manager
507
- */
508
- export interface OutdatedEntry {
509
- /** Asset kind (`skill`, `agent`, `prompt`, `flow`, `contract`). */
510
- kind: string;
511
- /** Asset name as registered in the catalog. */
512
- name: string;
513
- /** Repository that provides this asset. */
514
- publisher: string;
515
- /** Version string recorded in the lock file at install time. */
516
- currentVersion: string;
517
- /** Number of commits the local repository is behind the remote (always 0 for a library asset). */
518
- behind: number;
519
- /** Library-origin asset only: the version the library index now offers (newer than `currentVersion`). */
520
- latestVersion?: string;
521
- /** Library-origin asset only: name of the library the asset was locked from. */
522
- library?: string;
523
- /**
524
- * Set when the locked asset cannot be checked or is not in place: its library is
525
- * not registered (renamed or removed), its deployed copy is gone, or the lock does not
526
- * cover it ({@link AssetManager.projectState}). Such a row has no `latestVersion`.
527
- */
528
- problem?: string;
529
- /**
530
- * Library-origin asset only: the library's files on disk differ from the content
531
- * hash recorded in the lock at the same version (edited in place, no version bump).
532
- * `skaile update` re-locks and re-deploys them; `install` keeps the lock (OQ13).
533
- */
534
- contentChanged?: boolean;
535
- /**
536
- * Library-origin asset only: the library now holds this OLDER version than the lock. `install`
537
- * keeps the lock and the deployed copy; only `update` moves it back (`replaced X → Y`).
538
- */
539
- libraryOlder?: string;
540
- /**
541
- * Library-origin asset only: the library `update` would re-lock the asset from, when it is
542
- * not the one the lock names (`library`), e.g. after `skaile library default <other>`.
543
- */
544
- movesTo?: string;
545
- /**
546
- * Source asset only: the version the next `install` or `update` locks it under, when that
547
- * is not the locked key. A `0.0.0-sha.<commit>` key whose file now declares a version is
548
- * re-keyed (`0.0.0-sha.7de3555 → 0.2.0`, p914).
549
- */
550
- rekeyTo?: string;
551
- /**
552
- * Set when the row only reports a newer version than the `#version` pin of the asset's ref
553
- * in `skaile.yaml` (`latestVersion`). The pin is deliberate: `update` leaves it and `outdated`
554
- * does not fail on it.
555
- */
556
- pinned?: boolean;
557
- /**
558
- * Set on a `problem` row whose cause `skaile install` cannot fix: the asset's library is
559
- * gone or its publisher changed, so the ref resolves nowhere. `problem` names what to
560
- * change instead (`skaile library init …`, the ref under its new publisher).
561
- */
562
- manualFix?: true;
563
- }
564
- /**
565
- * Outcome of `AssetManager.diff()` — distinguishes an unknown ref from a real
566
- * "no differences" so callers never conflate the two.
567
- *
568
- * - `not-found` — the ref resolves to no asset (source, store or library).
569
- * - `not-deployed` — the asset resolves, but there is no deployed copy to compare.
570
- * - `identical` — the deployed copy matches the source.
571
- * - `differs` — the deployed copy differs; `diff` carries the unified diff. `fileSetDiffers` is
572
- * set when a file is missing from the deployed copy or one is not part of the asset (an
573
- * `mcp-server` payload): that is a state problem as for a skill, so `diff` lists it and exits 1.
574
- * - `no-files` — the asset kind has no files of its own (a preset: its items are the assets to
575
- * compare) and the lock records it.
576
- *
577
- * @docLink packages/asset-manager/concepts#asset-manager
578
- */
579
- export type DiffResult = {
580
- status: "not-found";
581
- } | {
582
- status: "not-deployed";
583
- } | {
584
- status: "identical";
585
- } | {
586
- status: "no-files";
587
- } | {
588
- status: "differs";
589
- diff: string;
590
- fileSetDiffers?: true;
591
- };
592
- /**
593
- * A node in the resolved dependency tree (returned by `AssetManager.tree()`).
594
- *
595
- * @docLink packages/asset-manager/concepts#asset-manager
596
- */
597
- export interface DependencyNode {
598
- /** Lock key (`kind:@publisher/name#version`), or `"project"` for the root node. */
599
- ref: string;
600
- /** Assets this node requires, nested under it. */
601
- children: DependencyNode[];
602
- }
603
- /** Outcome of {@link AssetManager.removeWithDependencies}. */
604
- export interface RemoveResult {
605
- /** Whether anything changed (as {@link AssetManager.remove}). */
606
- changed: boolean;
607
- /** Canonical refs (`kind:@publisher/name`) of the orphaned dependencies dropped as well. */
608
- pruned: string[];
609
- /**
610
- * Set when the removal was refused because other assets still require it; nothing was
611
- * removed. `ref` is the asset (`kind:@publisher/name`), `requiredBy` the refs requiring it.
612
- */
613
- blocked?: {
614
- ref: string;
615
- requiredBy: string[];
616
- };
617
- /**
618
- * Deployed folders or files of the asset that no lock entry holds (the user's own work):
619
- * kept, not deleted. Empty when `force` was given.
620
- */
621
- kept?: string[];
622
- /**
623
- * Deployed folders or files of the asset that another publisher's lock entry holds: kept, not
624
- * deleted (only that entry's own `remove` may delete them, or `force`). `refs` are the owning
625
- * lock entries, `paths` the kept folders.
626
- */
627
- ownedBy?: {
628
- refs: string[];
629
- paths: string[];
630
- }[];
631
- /**
632
- * `mcp_servers` entries of `skaile.yaml` that were dropped with a removed `mcp-server` because
633
- * they only set values for it (an `env` override with no `command` or `url` of its own), as
634
- * `mcp_servers entry "<id>"`. An entry that can run alone stays.
635
- */
636
- droppedSettings?: string[];
637
- }
638
- /**
639
- * A missing dependency detected by `AssetManager.doctor()`.
640
- *
641
- * @docLink packages/asset-manager/concepts#asset-manager
642
- */
643
- export interface DepIssue {
644
- /** Kind of the asset that has the unsatisfied requirement. */
645
- assetKind: string;
646
- /** Name of the asset that has the unsatisfied requirement. */
647
- assetName: string;
648
- /** Kind of the missing dependency. */
649
- depKind: string;
650
- /** Name of the missing dependency (`@<publisher>/<name>` when it names a publisher). */
651
- depName: string;
652
- /** `true` when the missing dependency exists in a configured repository but has not been installed. */
653
- inRepos: boolean;
654
- /**
655
- * `true` when the asset itself is lock-managed but no source or library holds it
656
- * any more, so its `requires` cannot be checked. `depKind`/`depName` repeat the asset.
657
- */
658
- unresolved?: boolean;
659
- /**
660
- * Set with `unresolved` when the lock ties the asset to a library: what to change
661
- * (`register library "x" again with …`, `did you mean <ref>?`). `skaile install`
662
- * cannot restore it. Absent when the lock names no library for it.
663
- */
664
- fix?: string;
665
- }
666
- /**
667
- * One way the project differs from what it declares and locks; see {@link AssetManager.projectState}.
668
- *
669
- * @docLink packages/asset-manager/concepts#asset-manager
670
- */
671
- export interface LockGap {
672
- type: "declared" | "invalid" | "drift" | "pin" | "requires" | "unresolved" | "library" | "incomplete" | "content" | "modified" | "agent" | "flow" | "render" | "source";
673
- /** The ref to act on: the declared ref, the unmet dependency `kind:name`, or the asset itself. */
674
- ref: string;
675
- /** Set on a `requires` gap: the requiring asset, `kind:@publisher/name` (`kind:name` when the lock knows no publisher). */
676
- asset?: string;
677
- /** What is wrong, as a phrase that follows `ref` (e.g. `is declared but not locked — run …`). */
678
- reason: string;
679
- /** One line naming the gap, without a leading status mark: `${ref} ${reason}`, except a `requires` gap, which leads with the requiring asset. */
680
- message: string;
681
- /** Set when `skaile install` cannot fix the gap; `reason` then names what to change instead. */
682
- manualFix?: true;
683
- /** Set on the gap of a `sources:` entry whose clone the walk could not read. `install --locked` restores from the lock alone, so it does not count that as missing. */
684
- unreadableSource?: true;
685
- }
686
- /**
687
- * The project's state as {@link AssetManager.projectState} computes it: the one verdict
688
- * `check`, `doctor`, `outdated`, `diff` and `install --locked` share.
689
- *
690
- * @docLink packages/asset-manager/concepts#asset-manager
691
- */
692
- export interface ProjectState {
693
- /** Every problem, one {@link LockGap} each; empty when the project is as declared and locked. */
694
- gaps: LockGap[];
695
- /** What {@link AssetManager.doctor} found: the unmet requirements (a `doctor` table row each) and the locked assets nothing provides. */
696
- requirements: DepIssue[];
697
- }
698
- /**
699
- * A single deployed asset shown in the workspace overview.
700
- *
701
- * @docLink packages/asset-manager/concepts#asset-manager
702
- */
703
- export interface OverviewEntry {
704
- /** Asset kind (`skill`, `agent`, `prompt`, `flow`, `contract`). */
705
- kind: string;
706
- /** Asset name. */
707
- name: string;
708
- /** Publisher that provides this asset (from the lock file; `"unknown"` when unresolvable). */
709
- publisher: string;
710
- /** Version string from the lock file. */
711
- version: string;
712
- /**
713
- * Sync status relative to the source repository.
714
- * - `"synced"` — local clone matches remote HEAD
715
- * - `"outdated"` — local clone is behind the remote
716
- * - `"local"` — sourced from a local path, no remote to compare
717
- * - `"error"` — status check failed
718
- * - `"unknown"` — repository not found or lock entry missing
719
- */
720
- syncStatus: string;
721
- }
722
- /**
723
- * Aggregated workspace overview returned by `AssetManager.overview()`.
724
- *
725
- * @docLink packages/asset-manager/concepts#asset-manager
726
- */
727
- export interface OverviewResult {
728
- /** Entries grouped by publisher, sorted alphabetically. Each group is sorted by kind then name. */
729
- byPublisher: Map<string, OverviewEntry[]>;
730
- /** Total number of deployed assets. */
731
- total: number;
732
- /** Sync status for each configured repository. */
733
- repos: RepoStatusInfo[];
734
- }
735
- /**
736
- * Options for constructing an {@link AssetManager}.
737
- *
738
- * @docLink packages/asset-manager/concepts#asset-manager
739
- */
740
- export interface AssetManagerOptions {
741
- /** Absolute or relative path to the workspace root (must contain `skaile.yaml`). */
742
- projectDir: string;
743
- /**
744
- * The process's asset-kind registry — the only authority on which kinds exist.
745
- * Typed frontmatter whose `type:` is not registered is reported, not catalogued.
746
- */
747
- registry: IAssetKindRegistry;
748
- /**
749
- * Agent framework to target for asset deployment.
750
- * Determines which framework directories (``.claude/``, ``.omp/``, etc.) are used.
751
- * Defaults to the harness the project is configured for (`skaile.yaml`
752
- * `agent-config.default.harness`, `.skaile/settings.json`), else `"claude-code"`.
753
- */
754
- harness?: HarnessName;
755
- /**
756
- * When `true`, the manager operates in **global cross-harness** mode: config
757
- * SSOT, lock, cache, and history root at `~/.skaile` (not the project), the
758
- * `dependencies:` manifest edits target `~/.skaile/skaile.yaml`, and deploy
759
- * fans out to every harness in {@link harnesses}. When `false` (default),
760
- * everything is project-scoped against the single {@link harness}.
761
- */
762
- global?: boolean;
763
- /**
764
- * Global-mode harness set the deploy fans out to. When omitted in global mode,
765
- * resolved from `~/.skaile/skaile.yaml` `global_harnesses:` else auto-detection
766
- * (`resolveGlobalHarnesses`). Ignored in project mode. A `--harness` filter
767
- * narrows this to a subset.
768
- */
769
- harnesses?: HarnessName[];
770
- /** @deprecated Use `harnesses`. Honoured only when `harnesses` is absent; removed in the next major. */
771
- backends?: HarnessName[];
772
- /**
773
- * Catalog read-protocol fetcher used to resolve store-published assets. When
774
- * omitted, one is built per call from the configured stores
775
- * (`RemoteCatalogSource`). Injected mainly by tests to stay network-free.
776
- */
777
- storeFetcher?: StoreFetcher;
778
- /**
779
- * Byte fetcher used to fetch a store asset's files at its pinned commit before
780
- * deploy. When omitted, the production GitHub fetcher is used. Injected by
781
- * tests to stay network-free.
782
- */
783
- assetFetcher?: AssetFetcher;
784
- /**
785
- * Overrides the global `catalog.url` used as a store fallback when the project
786
- * declares no `stores:`. `"local"` disables the fallback; project `stores:` are
787
- * still asked. `""` (`update --no-catalog`) asks no store at all, project `stores:`
788
- * included. When omitted, the URL is read from `~/.skaile/config.yaml` (`resolveConfig`).
789
- */
790
- catalogUrl?: string;
791
- /**
792
- * Overrides the index SQLite path read by {@link AssetManager.reportSoftDeps}
793
- * (default `~/.skaile/index.db` via `resolveIndexPath`). Injected by tests to
794
- * read a seeded index without touching the user's real one.
795
- */
796
- indexPath?: string;
797
- /**
798
- * Receives the warning printed when {@link AssetManager.add} picks one ref out of several
799
- * local libraries (which library was chosen and why); no other method warns. Defaults to
800
- * `console.warn`
801
- * with a `skaile:` prefix. A CLI with a live spinner passes a collector and
802
- * prints the lines after the spinner stops, so frames can't overwrite them.
803
- */
804
- onLibraryCollision?: (message: string, keys?: readonly string[]) => void;
805
- /**
806
- * An `add` that meets several colliding assets prints one summary line by default; `true`
807
- * prints each asset's full message (`skaile add --verbose`). A single collision always
808
- * prints in full.
809
- */
810
- verboseCollisions?: boolean;
811
- }
812
- export { FACTORY_SOURCE_URL };
13
+ import { AmAdd } from "./add-remove/add.js";
14
+ export { setRenamedEntryLookup } from "./add-remove/add.js";
15
+ export type { RenamedLibraryEntry, RenamedEntryLookup, AddPlanItem } from "./add-remove/add.js";
16
+ export { softDepName } from "./add-remove/remove.js";
17
+ export type { SoftDepEdge, OrphanedSoftDep, RemoveResult } from "./add-remove/remove.js";
18
+ export type { UnreachableSource, AssetManagerOptions } from "./config/core.js";
19
+ export type { McpNotice } from "./mcp-render.js";
20
+ export { labelDiffHeaders } from "./read/diff.js";
21
+ export type { DiffResult } from "./read/diff.js";
22
+ export type { ProjectState } from "./read/doctor.js";
23
+ export type { DependencyNode } from "./read/graph.js";
24
+ export type { OutdatedEntry } from "./read/outdated.js";
25
+ export { MissingManifestError } from "./read/state.js";
26
+ export type { StaleHarnessCopy, LegacyDeployedAsset, HarnessDeclaredAsset, RepoStatusInfo, OverviewEntry, OverviewResult, } from "./read/state.js";
27
+ export { LibraryEntryError } from "./resolve/scan.js";
28
+ export type { LibraryHolder, RefOrigin } from "./resolve/scan.js";
29
+ export { setLibraryAssetCheck } from "./shared/library-hooks.js";
30
+ export type { LibraryAssetCheck } from "./shared/library-hooks.js";
31
+ export { parseCanonicalLockKey, parseRefTolerant } from "./shared/refs.js";
32
+ export type { LibraryMove, ContentHeld, DeclaredState, DeclaredAsset, IncompleteDeploy, BackendDeclaredAsset, RepoInfo, RewrittenAgent, RestoredAsset, ReplacedAsset, StoreNotChecked, InstallResult, DepIssue, LockGap, } from "./shared/types.js";
813
33
  /**
814
34
  * Programmatic API for managing AI assets in a Skaile workspace.
815
35
  *
@@ -837,2168 +57,18 @@ export { FACTORY_SOURCE_URL };
837
57
  *
838
58
  * @docLink packages/asset-manager/concepts#asset-manager
839
59
  */
840
- export declare class AssetManager {
841
- /** Resolved absolute path to the workspace root. */
842
- readonly projectDir: string;
843
- /** Harness all deploy operations target (a `HarnessName`). */
844
- readonly harness: HarnessName;
845
- /** Whether this instance operates in global-install mode. */
846
- readonly global: boolean;
847
- /** Asset-kind registry shared with the host (one instance per process). */
848
- readonly registry: IAssetKindRegistry;
849
- private _knownKinds?;
850
- /** Explicit global-harness override (global mode only); else auto-resolved. */
851
- private readonly harnessesOverride?;
852
- private readonly legacyCopiesRemoved;
853
- private readonly legacyCopiesKept;
854
- /** Injected catalog fetcher (tests / custom); falls back to a built one. */
855
- private readonly injectedStoreFetcher?;
856
- /** Injected byte fetcher for store staging; falls back to GitHub. */
857
- private readonly injectedAssetFetcher?;
858
- /** Injected global catalog URL override for the no-project-store fallback. */
859
- private readonly catalogUrlOverride?;
860
- /** Injected index SQLite path override (tests); else the default index.db. */
861
- private readonly indexPathOverride?;
862
- /** Sink for cross-library collision warnings; else `console.warn`. */
863
- private readonly onLibraryCollision?;
864
- /** Print every colliding asset's full message instead of one summary ({@link AssetManagerOptions.verboseCollisions}). */
865
- private readonly verboseCollisions;
866
- /** Store URLs whose failed version lookup was already reported (one warning per URL). */
867
- private readonly warnedStoreVersionLookups;
868
- /** Whether each store answers: one process asks a dead store once (`processStoreProbe`). */
869
- private readonly storeProbe;
870
- /** Stores a lookup could not reach (store URL -> one line why); `add` reports them instead of "not found". */
871
- private readonly storeFailures;
872
- /** The agent `add` is about to bind to an instance: its deploy writes no file named after the asset. */
873
- private pendingAgentBinding;
874
- /** Source origins `outdated` could not fetch; read once through {@link takeUnreachableSources}. */
875
- private readonly unreachableSources;
876
- /** Store-origin refs `outdated` could not check; read once through {@link takeStoreNotChecked}. */
877
- private readonly storeUnchecked;
878
- /** How many store lookups failed so far; a lookup that moved it failed. */
879
- private storeFailureCount;
880
- /** Set while a lookup reports its own failure: the generic one-line warning stays off. */
881
- private quietStoreLookups;
882
- /** Store URLs a lookup failed on because the client is air-gapped (`cache_ttl: 0`), not because the store is down. */
883
- private readonly airGappedStores;
884
- /** Sources a provenance walk had to skip (source URL → why); one warning per source. */
885
- private readonly skippedSources;
886
- /** `onSourceError` of every provenance walk: name the source once, leave it out, go on. */
887
- private readonly reportSourceError;
888
- constructor(opts: AssetManagerOptions);
889
- /** Registered kind names — the `knownKinds` argument of the manifest scanners. */
890
- private get knownKinds();
891
- /**
892
- * The harness component dir a kind installs into (its provider's
893
- * `installTarget`), or `undefined` for composition-only kinds, which are only
894
- * cached in the store cache and composed at session start.
895
- */
896
- private installTarget;
897
- /**
898
- * Root for this manager's **state** — config SSOT, lock, cache, history.
899
- * `~/.skaile` in global mode (the cross-harness SSOT), else the project dir.
900
- * Deploy dirs are unaffected; they come from `HARNESS_TARGETS[target]`.
901
- */
902
- private get stateRoot();
903
- /**
904
- * The harnesses a global deploy fans out to: the explicit `harnesses` override (a `--harness`
905
- * filter), else the explicit `global_harnesses:` of `~/.skaile/skaile.yaml`, else every harness
906
- * whose root dir exists under `~` plus the harness the project is configured for (a project on
907
- * a harness whose dir does not exist yet still gets its user-scope assets). In project mode
908
- * this is exactly `[harness]`, so the shared fan-out loop degenerates to the
909
- * single-target path.
910
- */
911
- private targetHarnesses;
912
- /** The global harness set without a `--harness` filter (see {@link AssetManager.targetHarnesses}). */
913
- private defaultGlobalHarnesses;
914
- /**
915
- * `global_asset_harnesses:` of `~/.skaile/skaile.yaml`: the harnesses `add --global --harness`
916
- * limited an entry to, keyed by the declared ref without its pin. An entry with no row goes to
917
- * every global harness. Global mode only.
918
- */
919
- private readEntryHarnesses;
920
- /** The harnesses recorded for `kind:name` (`publisher` must agree when both sides have one). */
921
- private entryHarnessRecord;
922
- /** Keep the entries a recorded `--harness` limit sends to `target` (all of them in project mode). */
923
- private entriesForHarness;
924
- /**
925
- * The harness a 5.12.0 `add --global --harness omp` left as the asset's only copy: the copy sits
926
- * under the 5.12.0 omp folder (`~/.omp/skills`) and no other default harness holds one. That
927
- * folder is the only real 5.12.0 evidence: a current `add --global` writes no row either, so a
928
- * lone copy elsewhere may be a copy the user deleted or a harness added later (p1442).
929
- */
930
- private legacySingleCopyHarness;
931
- /**
932
- * Whether `~/.skaile/skaile.yaml` is a 5.12.0 record: it exists and has no
933
- * `global_asset_harnesses:` key yet, so {@link inferLegacyHarnessSubsets} has not run.
934
- */
935
- private isLegacyHarnessRecord;
936
- /**
937
- * A 5.12.0 global record has no `global_asset_harnesses:` key, yet `add --global --harness omp`
938
- * wrote one copy only, under `~/.omp/skills`. On the first global `install`, an entry whose only
939
- * copy sits there (see {@link legacySingleCopyHarness}) is omp's subset (OQ6): record it, so the
940
- * install does not fan the asset out to harnesses the user never asked for (p1442). Nothing is
941
- * inferred without that evidence, once the key exists (an entry without a row then means "every
942
- * harness"), or with one default harness. Global mode only; returns the rows written.
943
- */
944
- private inferLegacyHarnessSubsets;
945
- /**
946
- * Set (or, with `harnesses` undefined, clear) the harness row of `ref` in the parsed
947
- * `~/.skaile/skaile.yaml` `raw`. Returns whether `raw` changed.
948
- */
949
- private setEntryHarnessRow;
950
- /** The harness row of `kind:name` (publisher must agree when both sides have one) in the parsed `raw`. */
951
- private harnessRowIn;
952
- /**
953
- * The harness row `add --global --harness <requested>` leaves for `ref`: the recorded set plus
954
- * `requested`. An asset declared with no row goes to every global harness, so its set is that
955
- * default; `undefined` (no row) when `requested` is already part of it. A new asset gets
956
- * `requested` alone.
957
- */
958
- private widenedHarnessRow;
959
- /**
960
- * After `add --global --harness X`: widen the row of every other entry of the add that has one
961
- * (a requirement declared on its own with `--harness`), so the copy now deployed into X stays
962
- * managed. Entries with no row already go to every harness.
963
- */
964
- private widenDependencyRows;
965
- /**
966
- * `add --global --harness X --only`: name each harness that leaves the asset's set but still
967
- * holds a copy. The copy stays on disk; `remove --global --harness <h>` deletes it.
968
- */
969
- private reportDroppedCopies;
970
- /**
971
- * Delete the copies a 5.12.0 global install left in `~/.omp/skills`, `~/.omp/agents`,
972
- * `~/.omp/prompts` and `~/.omp/contracts` (omp reads `~/.omp/agent/<dir>`) for the assets just
973
- * deployed into omp's new folder, and remember them for {@link takeLegacyCopiesRemoved} (p744).
974
- */
975
- private sweepLegacyOmpCopies;
976
- /** The old omp copies the deploys since the last call kept, as skaile did not write them. */
977
- takeLegacyCopiesKept(): string[];
978
- /**
979
- * The old `~/.omp/<dir>/<name>` copies of the globally locked assets that are still on disk
980
- * (a 5.12.0 install wrote them; omp reads `~/.omp/agent/<dir>`). Global mode only. `check`,
981
- * `doctor` and `clean` with `--global` report or remove them (p911).
982
- */
983
- staleLegacyOmpCopies(): {
984
- ref: string;
985
- path: string;
986
- }[];
987
- /** The old omp copies the deploys since the last call removed (see {@link sweepLegacyOmpCopies}). */
988
- takeLegacyCopiesRemoved(): string[];
989
- /**
990
- * The source origins the last {@link outdated} call could not fetch (name, URL, why). Their
991
- * behind count was not checked, so the CLI must not call the project up to date (p1820).
992
- */
993
- takeUnreachableSources(): UnreachableSource[];
994
- /**
995
- * The refs the last {@link outdated} call could not check because their store did not answer
996
- * (`unreachable`) or the client is air-gapped (`air-gapped`): `outdated`, `check` and `doctor`
997
- * name them and fail on `unreachable` instead of calling the project up to date.
998
- */
999
- takeStoreNotChecked(): StoreNotChecked[];
1000
- /**
1001
- * The harnesses `add` / `install` deploy into: `[harness]` for a project, the global
1002
- * harness set (see {@link AssetManager.targetHarnesses}) for a global manager.
1003
- */
1004
- deployTargets(): HarnessName[];
1005
- private get storeCacheDir();
1006
- private get reposDir();
1007
- /**
1008
- * Project-scoped cache dirs rooted at `.skaile/cache/` (`store`, `sources`)
1009
- * relative to `projectDir`. Reading is a side effect: it triggers lazy
1010
- * migration of the legacy `.skaile/{store-cache,repos}` dirs.
1011
- */
1012
- get projectCacheDirs(): {
1013
- store: string;
1014
- sources: string;
1015
- };
1016
- private get lockPath();
1017
- private get patchDir();
1018
- /** Deploy options for one harness. In global mode, `harness` is the
1019
- * fan-out target (not the constructor's `harness`, which is project-only). */
1020
- private deployOptsFor;
1021
- /** Agent name → the `../` compose folder files its lock entry records (`LockEntry.composed`). */
1022
- private composedRecords;
1023
- /** `install`'s `Missing:` line for a `../` compose folder the library moved past the lock. */
1024
- private composedDriftLine;
1025
- /**
1026
- * Names of the `mcp-server` assets the lock holds (the declaration ids, unscoped); a missing
1027
- * `.mcp.json` entry of one counts as drift even before skaile owned it.
1028
- */
1029
- private lockedMcpNames;
1030
- /**
1031
- * The payloads and managed `.mcp.json` entries of the project's **locked** `mcp-server`
1032
- * assets that differ from what the declarations render (see {@link mcpServerDrift}), one row
1033
- * per server, named by the lock identity `mcp-server:@publisher/name`; `key` is the lock key.
1034
- * An `mcp_servers:` entry of `skaile.yaml` is configuration, not a locked asset: it has no
1035
- * row. Empty for a global manager and for a project that locks no `mcp-server`.
1036
- */
1037
- private mcpDriftRows;
1038
- /**
1039
- * What the render wrote for the `mcp-server` asset `name` into the coding agent's MCP
1040
- * config: the config file and, for a server with a payload, the payload directory
1041
- * (project-relative). `written` is false when the render left the server out (see
1042
- * {@link AssetManager.mcpNotices}). `undefined` when the harness has no MCP config skaile
1043
- * writes (`codex`, `omp`) or for a global manager: the asset is composed at run time only.
1044
- */
1045
- mcpRenderFootprint(name: string): Promise<{
1046
- file: string;
1047
- payloadDir?: string;
1048
- written: boolean;
1049
- } | undefined>;
1050
- /**
1051
- * The declared MCP servers whose `.mcp.json` entry skaile wrote and nothing edited, but that
1052
- * `skaile.yaml` (or a newer asset) now renders differently: the config waits for
1053
- * `skaile install`. Covers a locked `mcp-server` and an `mcp_servers:` entry alike; the
1054
- * server is named by its lock identity when it has one, else `mcp-server:<id>`. Empty for a
1055
- * global manager.
1056
- */
1057
- private mcpPendingRender;
1058
- /**
1059
- * Render the project's declared MCP servers into the harness target's own
1060
- * native MCP config (`<project>/.mcp.json` for `claude-code`), so the coding
1061
- * agent sees the same servers skaile's agent loop wires up.
1062
- *
1063
- * Project scope only: a `--global` install has no project-scope config to
1064
- * write, and the coding agent's user scope is a large user-state file this
1065
- * must not touch. Never fails an install — a render error is warned and
1066
- * swallowed.
1067
- *
1068
- * @returns The payload files and config entries the render wrote back (and the files it
1069
- * removed) because they had drifted from the declaration: `install` names them, as it does
1070
- * a restored skill file.
1071
- */
1072
- private renderHarnessMcpConfig;
1073
- /**
1074
- * Whether a project-relative path is a file an agent instance renders (the ledger's files). An
1075
- * instance claims files and folders (omp renders a folder): a file under a claimed folder is
1076
- * claimed too.
1077
- */
1078
- private instanceClaims;
1079
- /**
1080
- * Whether the path `rel` that the lock lists under `rendered:` for the agent `name` is a file
1081
- * named after the asset that an instance's file (or the `binding: run` role) stands for now.
1082
- * Such a path is no part of the rendering the lock expects any more: a lock of 5.13.0 and older
1083
- * still lists it, `install` drops it at the next lock write, and until then it is neither a
1084
- * missing nor an edited copy. Always `false` in global mode.
1085
- */
1086
- private supersededRendering;
1087
- /**
1088
- * The files named after an agent asset that an earlier CLI rendered and this one does not: the
1089
- * agent is bound by an instance (its rendering is the instance's file), or it only runs as a
1090
- * `binding: run` role. A file counts when no instance of the ledger claims it and either the
1091
- * lock lists it for the agent (`edited` when its bytes differ from the recorded ones), or the
1092
- * lock records no rendering for the agent at all (5.11.0 and older) and the file is the
1093
- * instance's render under the asset's name. A file of the second kind that differs from that
1094
- * render may be the user's own and is not listed. Project mode only.
1095
- */
1096
- private leftoverAgentFiles;
1097
- /**
1098
- * Remove the leftover files {@link leftoverAgentFiles} lists. A file edited since the lock
1099
- * stays (it is the user's now) and is named. The old lock entry is rewritten by the same
1100
- * install, so the lock never keeps a path that is gone; `install --locked` leaves the lock,
1101
- * which `check` does not read for a file that is gone.
1102
- *
1103
- * @returns The project-relative paths removed.
1104
- */
1105
- private pruneAssetNamedAgentFiles;
1106
- /**
1107
- * The `check`, `doctor` and `outdated` lines for the files {@link leftoverAgentFiles} lists: an
1108
- * untouched one is removed by the next `install` (and by `install --locked`), an edited one
1109
- * stays. Empty in global mode and when nothing is left over.
1110
- */
1111
- leftoverAgentFileNotices(): string[];
1112
- /**
1113
- * Render every agent instance of `skaile.yaml` into the harness target's native
1114
- * agent files (`.claude/agents/<id>.md`, …) and prune the renderings of
1115
- * instances that left the config. Runs after the skills deploy, so composed
1116
- * skills resolve. Project scope only. An instance whose `ref` resolves to no agent is
1117
- * reported in `agentInstanceErrors`; any other render error is warned and swallowed.
1118
- *
1119
- * @param opts.prune - Also remove the files named after the agent assets that an earlier CLI
1120
- * rendered and an instance renders now ({@link pruneAssetNamedAgentFiles}). Set by the
1121
- * commands that deploy or re-lock; the lock is left as it is by `install --locked`.
1122
- */
1123
- private renderAgentInstances;
1124
- private loadConfig;
1125
- /** Build provenance-index clones from the resolved source declarations; a clone folder with no git checkout goes to `onSourceError`. */
1126
- private buildClones;
1127
- /**
1128
- * Bridge a resolved {@link ProvenanceCandidate} to a {@link CatalogEntry} for
1129
- * the deploy pipeline. `source` is the absolute path to the asset's primary
1130
- * manifest (or its directory) inside the clone; `publisher` is set to the
1131
- * clone slug so `deployAll`'s repositories lookup resolves local-vs-remote.
1132
- */
1133
- private candidateToCatalogEntry;
1134
- /**
1135
- * The {@link ProvenanceCandidate} a source- or store-origin lock entry stands for: what a
1136
- * deploy needs to restore the asset from the commit the lock names (`files[]` is the asset's
1137
- * whole file set). `null` for a library-origin entry or a key that is not a canonical ref.
1138
- * The source URL is the declared source's own spelling (the bundled factory tree and a
1139
- * `sources:` entry match their declaration by it).
1140
- */
1141
- private lockedCandidate;
1142
- /**
1143
- * Resolve refs the source/store pass could not against the user's registered
1144
- * **libraries** (local authoring places). Each library dir is scanned on disk
1145
- * under its declared publisher (its root `skaile.manifest.yaml`, falling back
1146
- * to the kebab-cased library name); a matching asset becomes a deployable
1147
- * {@link CatalogEntry} whose `source` points at the on-disk manifest. This is
1148
- * the consume side of `library create` — a freshly authored asset is
1149
- * deployable with `skaile add <kind>:@<publisher>/<name>` without publishing.
1150
- *
1151
- * Local read (no network) and mirrors how `findSkills` discovers library
1152
- * content. The returned `libraryOf` map names the library each entry came from
1153
- * so callers can lock it as library-origin (see {@link libraryLockEntries}).
1154
- *
1155
- * @param opts.quiet - Skip the cross-library collision warning (a lookup that only
1156
- * builds an error hint must not warn).
1157
- * @param opts.library - Resolve only from this library (the one a lock entry names), not
1158
- * from every registered one. Never warns: no choice is made between libraries.
1159
- * @param opts.lockedLibraries - `kind:publisher/name` → the library its lock entry names
1160
- * ({@link AssetManager.lockedLibraryNames}). A ref listed here resolves from that library
1161
- * when it holds a match, whatever the default library is.
1162
- * @returns the matched deploy entries, the set of `missing` refs covered, and
1163
- * each entry's originating library name.
1164
- */
1165
- private resolveLibraryEntries;
1166
- /**
1167
- * Scan every candidate library (the set {@link resolveLibraryEntries} resolves from)
1168
- * into `kind:@publisher/name` → every holder, across all libraries and versions.
1169
- *
1170
- * @param minRoots - Return `null` without scanning when fewer candidate libraries
1171
- * exist (a cross-library question needs at least two).
1172
- * @returns `null` when there is no candidate library or none holds an asset.
1173
- */
1174
- private scanLibraries;
1175
- /**
1176
- * Every ref that more than one registered library holds, with one row per holder
1177
- * (all libraries, all versions) in the order `add` prefers them: the first row is
1178
- * the one `add <ref>` deploys. `search` reads this to group the index rows of a ref
1179
- * (one per library) and mark the copy `add` deploys; the versions come from the files
1180
- * themselves, which the index follows only after the next `skaile library index`.
1181
- *
1182
- * @returns `kind:@publisher/name` → holders; refs held by one library are absent.
1183
- */
1184
- libraryHolders(): Promise<Map<string, LibraryHolder[]>>;
1185
- /**
1186
- * Every asset a registered library holds, read from the library directories themselves
1187
- * (not the local index, which lags behind them until the next `skaile library index`).
1188
- * One row per holder, all versions.
1189
- *
1190
- * @returns `[]` when no library holds an asset. Never warns.
1191
- */
1192
- libraryAssets(): Promise<Array<{
1193
- entry: CatalogEntry;
1194
- library: string;
1195
- }>>;
1196
- /**
1197
- * The version `add` deploys for each asset of a source clone registered as a `reader`
1198
- * library, when its file declares none: the repo commit pseudo-version (p855). `search`
1199
- * reads this where no project is in scope, so it lists what `add` locks, not the index
1200
- * default.
1201
- *
1202
- * @returns `<library>\0<kind>:@<publisher>/<name>` -> version; only assets that declare none.
1203
- */
1204
- sourceAssetVersions(): Promise<Map<string, string>>;
1205
- /**
1206
- * Every origin that holds `ref` (`kind:@publisher/name`) with the version it holds, in
1207
- * the order `add <ref>` prefers them, so the first row is the one `add` deploys: the
1208
- * project's source clones and the bundled factory source (highest version first), then
1209
- * the registered libraries. `add`, `info` and `search` all read this, so the three name
1210
- * one origin for one ref. Stores are not asked (no network).
1211
- *
1212
- * @returns one row per origin and version; `[]` for a ref without a publisher or one
1213
- * nothing holds. Never warns.
1214
- */
1215
- refOrigins(ref: string): Promise<RefOrigin[]>;
1216
- /**
1217
- * Every ref (`kind:@publisher/name`) that several origins hold at different versions,
1218
- * with its origins in {@link refOrigins} order. A ref the origins hold at one version
1219
- * has nothing to choose between and is left out.
1220
- */
1221
- competingOrigins(): Promise<Map<string, RefOrigin[]>>;
1222
- /**
1223
- * The origins of {@link refOrigins} for every ref, keyed by `kind:@publisher/name`: the
1224
- * version in each row is the one `add` locks (a source asset whose file declares none is
1225
- * `0.0.0-sha.<commit>`), which `search` lists too (p855).
1226
- */
1227
- allOrigins(): Promise<Map<string, RefOrigin[]>>;
1228
- /**
1229
- * The origins of {@link refOrigins} for every ref, or for the one `only` names
1230
- * (`kind:@publisher/name`), keyed by `kind:@publisher/name`.
1231
- */
1232
- private collectOrigins;
1233
- /**
1234
- * Where each missed publisher-qualified ref went when its publisher changed, for every
1235
- * ref at once (one library scan, one lock read):
1236
- * - `moved` when a registered library holds the same kind + name under another publisher.
1237
- * When the lock ties the missed ref to a library, only that library is looked at (an
1238
- * asset of the same name in another library is a different asset). Without a lock
1239
- * entry, a library asset the project already declares or locks under its own ref is
1240
- * not offered, and two candidate publishers are ambiguous: no hint;
1241
- * - `lockedAs` when the lock holds the same kind + name under another publisher, records
1242
- * the library it came from, and that library now holds the asset under yet another
1243
- * publisher than the locked one. An unrelated asset that merely shares kind + name does
1244
- * not qualify.
1245
- *
1246
- * @param refs - Missed refs; a trailing `(reason)` after the first space is ignored.
1247
- * @returns one finding per ref that has one. Never warns.
1248
- */
1249
- private publisherChangeFindings;
1250
- /**
1251
- * Explain misses caused by a publisher change, as parenthesized hint text per ref:
1252
- * `did you mean <ref>?` when a registered library holds the same kind + name under
1253
- * another publisher, and `locked as <lockRef>; run skaile install to re-resolve` when
1254
- * the lock holds it under the library's previous publisher (see
1255
- * {@link AssetManager.publisherChangeFindings}).
1256
- *
1257
- * @param refs - Missed refs; a trailing `(reason)` after the first space is ignored.
1258
- * @returns hint text per ref, only for refs that have one. Never warns.
1259
- */
1260
- private publisherChangeHints;
1261
- /**
1262
- * What the user has to change for each ref that is locked from a library but resolves
1263
- * nowhere any more, where `skaile install` cannot help: the library is not registered
1264
- * (renamed away or removed), the library now publishes the asset under another
1265
- * publisher, or the library no longer holds it. A ref the lock does not tie to a
1266
- * library has no entry.
1267
- *
1268
- * @param refs - Declared or locked refs, `kind:@publisher/name` (a trailing `(reason)`
1269
- * after the first space is ignored).
1270
- * @returns a phrase per ref that follows the ref name, without parentheses.
1271
- */
1272
- private unresolvedFixes;
1273
- /**
1274
- * A ref pinned to a version its library never held (`#9.9.9`): the thing to change is the pin
1275
- * in `skaile.yaml`, not the library (p1096). Sets the fix and returns `true` when it applies.
1276
- */
1277
- private pinNeverHeld;
1278
- /**
1279
- * The ref a library now holds a flow under when a project still locks it by the slug of the
1280
- * flow's `name:` (5.12.0 named a flow by `name:`; later releases name it by `id:`), or
1281
- * `undefined` when `kind` is no flow, the library is not at hand or no flow of it matches.
1282
- */
1283
- private renamedFlowRef;
1284
- /** Collision messages already printed by this instance (one warning per ref + library set). */
1285
- private readonly warnedLibraryCollisions;
1286
- /**
1287
- * Collisions of one `add`, held back until {@link flushLibraryCollisions} so a dependency
1288
- * tree that touches several colliding assets prints one summary, not one line per asset
1289
- * (p1097). `null` outside an `add`: a collision then warns at once.
1290
- */
1291
- private collisionBatch;
1292
- /**
1293
- * Warn once when `key` is held by more than one library: names every library
1294
- * with its version and the one chosen, so a silent pick can't surprise.
1295
- */
1296
- private warnLibraryCollision;
1297
- /** Print each distinct collision message once; the sink also gets the keys it names. */
1298
- private emitLibraryCollision;
1299
- /**
1300
- * End the batch of {@link collisionBatch}: one collision prints its full message; several
1301
- * print one summary (how many libraries and assets, the library each asset came from, the
1302
- * assets whose bytes differ). `verboseCollisions` prints every asset's full message instead.
1303
- */
1304
- private flushLibraryCollisions;
1305
- /** Kind, name and bare publisher of a deploy entry; the publisher comes from its canonical ref. */
1306
- private entryIdentity;
1307
- /**
1308
- * Refuse to lock a source commit another machine cannot check out. A commit made in the clone
1309
- * itself (or one `source sync` could not fast-forward past) is in no remote branch: the lock
1310
- * would name bytes nobody else has, and `install --locked` there could not restore them.
1311
- * Linked (dev-override) and user-owned local sources are never checked: their lock is
1312
- * machine-local by choice.
1313
- *
1314
- * @param resolved - Candidates about to be locked.
1315
- * @param repositories - Source declarations of the project.
1316
- * @throws With `<url> clone has unpublished commit <sha>` and the way out.
1317
- */
1318
- private assertSourceCommitsPublished;
1319
- /**
1320
- * Refuse assets of one kind and name from different publishers: they deploy into the
1321
- * same folder, so the later one would silently overwrite the earlier. Throws one line
1322
- * naming the folder and the asset that holds it.
1323
- *
1324
- * @param incoming - Assets about to be deployed. Two of them clashing is refused.
1325
- * @param held - Assets the project already declares or has locked; one of them
1326
- * clashing with an incoming asset is refused when its folder is on disk.
1327
- */
1328
- private assertNoFolderCollision;
1329
- /**
1330
- * Refuse to deploy over a folder (or agent file) the project did not put there: it is on disk,
1331
- * but no lock entry of the same kind and name owns it, so it is the user's own work and the
1332
- * deploy would replace it and `remove` would delete it. Throws one line naming the folder.
1333
- *
1334
- * A folder the deploy would rewrite with the same content is adopted silently (the way back
1335
- * from `asset import`: the project's own copy is what the library now holds): every file in
1336
- * it is shipped by the asset with the same bytes, or the same body and an asset frontmatter
1337
- * that only adds to the folder's (import normalizes it). Nothing is lost then.
1338
- *
1339
- * @param incoming - Assets about to be deployed, with the entry whose bytes would be written
1340
- * when there is one.
1341
- * @param owned - Assets the lock holds; one of the same kind and name, from any publisher,
1342
- * owns the folder (a publisher clash is {@link assertNoFolderCollision}'s refusal).
1343
- */
1344
- private assertNoUnownedFolder;
1345
- /**
1346
- * Whether deploying `entry` over the folder already in `target` loses nothing: the folder
1347
- * holds no file the asset does not ship, and each of its files equals the asset's, or is a
1348
- * markdown file with the same body whose frontmatter the asset's only extends.
1349
- */
1350
- private deployWouldOnlyRewriteSame;
1351
- /**
1352
- * Open the local index and snapshot its libraries + asset definitions, scoped to this
1353
- * project's `sources:` ({@link scopeLibraryIndex}).
1354
- * Best-effort: no index file (never indexed), or any open/guard failure,
1355
- * yields `null` — a lock/outdated read must never create `index.db` or throw.
1356
- */
1357
- private loadLibraryIndex;
1358
- /**
1359
- * The `sources:` this project declares by clone key, or `undefined` outside a project (no
1360
- * `skaile.yaml` in `projectDir` or a parent) or when the file does not parse. Outside a
1361
- * project nothing declares sources, so the machine-wide search reads every clone.
1362
- */
1363
- private declaredSourceEntries;
1364
- /** The clone-cache key a source-clone reader row stands for, or `undefined` for any other library. */
1365
- private sourceCloneKey;
1366
- /**
1367
- * Ids of the registered libraries that are the clone of a source this project does not
1368
- * declare. `source add` registers the clone as a machine-wide reader library so `search`
1369
- * and the indexer can read it, but a `sources:` clone belongs to the projects that declare
1370
- * it (OQ4, p321): another project neither resolves it, nor ties with it by name, nor has
1371
- * `update` re-pin its locked assets to it. A reader library the user registered by hand
1372
- * (`library init --reader --git`) lives outside the sources cache and is never hidden.
1373
- */
1374
- undeclaredSourceClones(libraries: readonly Library[]): Set<string>;
1375
- /**
1376
- * The registered libraries as `library list` shows them in this project. A source clone is
1377
- * cache: its row is read from the clone, so it is dropped when the clone is gone and
1378
- * when this project does not declare the source. `sources` holds the ids of the clone rows
1379
- * that stay, so the list can mark them `(source)`.
1380
- */
1381
- scopeLibraryList(libraries: readonly Library[]): {
1382
- libraries: Library[];
1383
- sources: Set<string>;
1384
- };
1385
- /**
1386
- * The index as this project sees it: the source clones of other projects are dropped
1387
- * ({@link undeclaredSourceClones}) and the assets of a declared source carry the publisher
1388
- * this project's `sources:` entry names. The clone and its index rows are shared by every
1389
- * project that declares the source, so a project that declares another `--publisher` is
1390
- * re-labelled here, at read time, and never changes what the others see (p1822).
1391
- */
1392
- scopeLibraryIndex(libraries: Library[], defs: AssetDefinition[]): {
1393
- libraries: Library[];
1394
- defs: AssetDefinition[];
1395
- };
1396
- /**
1397
- * Library-origin lock entries for the assets {@link resolveLibraryEntries}
1398
- * matched. The locked version is the one actually deployed: the on-disk
1399
- * entry's version, falling back to the library index only when the disk entry
1400
- * carries none — the index lags until the next `skaile library index`, so
1401
- * preferring it would lock a stale version after an in-place bump. The hash is
1402
- * computed from the files on disk, so it matches what `install --locked`
1403
- * re-hashes.
1404
- *
1405
- * A git-backed library also records its remote URL. When the previous lock names the
1406
- * library under another name that {@link lockedLibrary} matched to this one by URL (a
1407
- * teammate registered the same remote under a different name), the entry keeps the locked
1408
- * name and URL: the lock does not change because it was installed on another machine. A
1409
- * library renamed on this machine with `library rename` is locked under its new name.
1410
- */
1411
- private libraryLockEntries;
1412
- /**
1413
- * The entries a deploy would write into some target harness: those without a current deployed
1414
- * copy. An intact copy stays as it is, so a library change that does not reach it (a symlink
1415
- * added next to the files) stops no `install` or `update` (p1857).
1416
- */
1417
- private needingDeploy;
1418
- /**
1419
- * The files of a library asset that git has not committed (edited, new or staged only), as
1420
- * paths relative to the library root. The asset's own folder, or its one manifest file when it
1421
- * shares the folder with other assets. Empty when the asset is not in a git work tree.
1422
- */
1423
- private uncommittedAssetFiles;
1424
- /**
1425
- * Warn when a library with a git remote has uncommitted changes in the folders of the assets
1426
- * `add` or `install` lock: the lock records the bytes on this disk, which no clone of the
1427
- * remote holds, so a teammate (or CI) cannot restore them. One line per library naming the
1428
- * files; the command goes on (OQ5, p1859).
1429
- */
1430
- private warnUncommittedLibraryAssets;
1431
- /**
1432
- * Whether every declared ref is locked and no declared pin differs from the locked version:
1433
- * `skaile.yaml` asks for nothing the lock does not hold. A declared preset counts when the
1434
- * lock records it.
1435
- */
1436
- private declaredMatchesLock;
1437
- /**
1438
- * Lock keys that `skaile.yaml` still wants: the entries a declared ref names, plus every
1439
- * entry such an asset requires, transitively. All keys when a `preset:` is declared.
1440
- */
1441
- private declaredLockKeys;
1442
- /**
1443
- * The `Missing:` lines of every library-origin lock entry whose library cannot supply
1444
- * assets on this machine (not registered, or registered with its directory gone). Plain
1445
- * `install` stops on a non-empty list, the same lines `install --locked` prints: it must
1446
- * not re-resolve a locked asset from another origin. The ONE function that decides "the
1447
- * locked library is not here", so a store-restore fallback extends it in one place.
1448
- *
1449
- * An entry `install --locked` already restored from a store (its library is not registered
1450
- * here and the store cache holds the locked version, see {@link restoredFromStoreCache}) is no
1451
- * line: it is returned in `restored`, and plain `install` then restores the lock as
1452
- * `install --locked` does instead of re-resolving it from another origin (OQ8, p1655).
1453
- *
1454
- * Only entries `skaile.yaml` still declares, or that a declared asset requires
1455
- * (transitively, read from the deployed copy), count. A stale entry nothing declares is
1456
- * pruned by `install` as usual, so a removed dependency whose library is gone can be
1457
- * cleaned up. With a declared `preset:` every entry counts: the lock records no edge
1458
- * from a preset to its items, and the preset's own library may be the one that is gone.
1459
- *
1460
- * @param declared - The `dependencies:` refs as written in `skaile.yaml`.
1461
- */
1462
- private unavailableLockedLibraries;
1463
- /**
1464
- * Re-resolve every library-origin lock entry from its named library, for
1465
- * `install --locked`. An entry is restored only when its library is still
1466
- * registered/on disk, still holds the asset, and still offers the locked
1467
- * version; anything else is reported in `missing` with the reason.
1468
- *
1469
- * @param opts.storeFallback - `install --locked` only: an entry whose library is not registered
1470
- * here is restored from a store that serves the locked sha256 (OQ8, OQ15, p1490, p1655). The
1471
- * lock records the library's remote and hash but no commit and no file list, so the library
1472
- * remote itself cannot be fetched at a locked commit; the store pointer names the upstream
1473
- * repository and commit that hold exactly the hashed bytes. Reads such as the drift check
1474
- * never ask a store.
1475
- */
1476
- private restoreLibraryLockEntries;
1477
- /**
1478
- * Whether a library-origin lock entry was restored from a store: its library is not
1479
- * registered here, and the project's store cache holds the locked version (`install --locked`
1480
- * fetched it there and SHA-verified every file against the sha256 the lock recorded). Such an
1481
- * entry is as restorable as a source- or store-origin one: `check`, `doctor` and plain
1482
- * `install` read its requirements from the deployed copy and do not ask for the library (OQ8,
1483
- * p1655). An unregistered library that never restored anything here stays a gap.
1484
- *
1485
- * This only checks that the cache directory of the locked version is not empty: the bytes were
1486
- * verified when they were fetched, and a later edit of the deployed copy is the `modified`
1487
- * drift check's job, not this one's.
1488
- */
1489
- private restoredFromStoreCache;
1490
- /**
1491
- * The store's copy of a library-origin lock entry whose library is not registered here: a
1492
- * store (project `stores:` or the global catalog) that serves `kind:@publisher/name#version`
1493
- * under the very sha256 the lock recorded holds the same bytes. The entry is fetched and
1494
- * verified like any store asset; the lock stays as it is. `null` when the lock has no hash,
1495
- * no store answers, or the hash differs (OQ15, p1490). `from` names the store and the
1496
- * upstream repository and commit its pointer gives, for the notice.
1497
- */
1498
- private storeEntryForLockedLibraryAsset;
1499
- /**
1500
- * Whether a deployed copy exists for the lock entries `install` kept for the unresolved
1501
- * `ref`. A kind with no install target has none, except an `mcp-server`: its copy is the
1502
- * `.mcp.json` entry skaile wrote and the payload that entry points into (p792).
1503
- */
1504
- private keptCopyDeployed;
1505
- /** Whether the deployed copy of a library asset is on disk; a kind with no install target has none to check. */
1506
- private lockedCopyDeployed;
1507
- /**
1508
- * The library-origin lock entries `install` keeps when the library holds a newer version:
1509
- * only `update` moves a locked asset, so `install` restores the locked one (p1095).
1510
- * Keyed by `<publisher>/<kind>:<name>`. `requires` is what the locked version needs: the
1511
- * lock's own list, or for a lock that predates the field the deployed copy's requirements,
1512
- * never the newer library entry's.
1513
- */
1514
- private keepLockedLibraryEntries;
1515
- /**
1516
- * How the library `origin` names stands on this machine. THE one lookup of a locked library
1517
- * ("is it registered here?"): `check`, `outdated`, `install` and `install --locked` all ask it.
1518
- *
1519
- * - registered in the index under its name: `ok` at its registered path, or `dir-missing` when
1520
- * that directory is gone;
1521
- * - not registered: a directory `<libraries dir>/<name>` nobody unregistered still counts as a
1522
- * hand-made library (`ok`). One `library remove` unregistered without `--purge` does not
1523
- * (it stays on disk but no longer resolves), and neither does the reserved `installed` folder.
1524
- * - otherwise, when the lock recorded the library's remote URL: another registered library
1525
- * whose git remote is the same repository (`.git` suffix, trailing `/` and the
1526
- * `git@host:o/r` / `https://host/o/r` forms do not matter) and whose directory exists is
1527
- * `ok`, with `name` set to the name it is registered under here. The library name is
1528
- * machine-local; the remote is what a clone shares.
1529
- */
1530
- private lockedLibrary;
1531
- /**
1532
- * Why `install --locked` cannot restore a locked library asset from its library: the library
1533
- * holds another version than the lock (`library "x" is at 0.1.1, locked 0.1.0`) or the locked
1534
- * version with other bytes (`library "x" content changed since lock`). Only `update` moves
1535
- * the lock to it. `undefined` when the library is not here, no longer holds the asset, or
1536
- * still holds the locked files (the other gaps say what is wrong then).
1537
- */
1538
- private libraryAheadOfLock;
1539
- /** The registered library whose files for `asset` hash to `sha256` (the locked bytes), if any. */
1540
- private libraryHoldingLockedBytes;
1541
- /** On-disk root of the library `origin` names; `null` unless {@link lockedLibrary} says `ok`. */
1542
- private libraryPath;
1543
- /**
1544
- * Rename the library every library-origin lock entry names: `library rename <interim> <old>`
1545
- * puts a library back under its old name, and an entry locked in between would keep the
1546
- * interim name, so a later "register library again" advice would name a library nobody knows
1547
- * any more (p893). Nothing is written when no entry names `from`.
1548
- *
1549
- * @returns the number of lock entries renamed.
1550
- */
1551
- renameLockedLibrary(from: string, to: string): number;
1552
- /**
1553
- * The `kind:@publisher/name` identities the lock holds for one `kind` and `name`, whatever
1554
- * their publisher. `diff` uses it to accept a ref without a publisher only when it names
1555
- * exactly one locked asset.
1556
- */
1557
- lockedRefsNamed(kind: string, name: string): string[];
1558
- /**
1559
- * The library a library-origin lock entry of `kind` and `name` (and `publisher`, when given)
1560
- * resolves to on this machine, or `undefined` when the lock holds no such entry, it is not
1561
- * from a library, or its library is not here. `info` prints it next to `source:`.
1562
- */
1563
- lockedLibraryOf(kind: string, name: string, publisher?: string): Promise<string | undefined>;
1564
- /**
1565
- * Where each library-origin lock entry of this project resolves on this machine: identity
1566
- * `kind:publisher/name` (no scope sigil, no version) → the name the locked library is
1567
- * registered under here. The name differs from the locked one when the lock's remote URL
1568
- * matched another registered library ({@link lockedLibrary}). A deployed entry whose library
1569
- * resolves nowhere (not registered, directory gone) maps to `null`.
1570
- *
1571
- * Direct `asset install` entries (`library.installed`) are included and resolved the same
1572
- * way, but they map to the locked library name when that lookup fails: such a copy sits in
1573
- * the project and does not depend on the library still being registered. A missing or
1574
- * unreadable lock yields an empty map. `skaile manage` uses it to tick the right library row.
1575
- */
1576
- lockedLibraryNames(): Promise<Map<string, string | null>>;
1577
- /**
1578
- * What `update` prefers when libraries tie: the library each lock entry resolves to here
1579
- * ({@link lockedLibraryNames}, a `library rename` followed) and the sha256 it locked.
1580
- */
1581
- private lockedPreference;
1582
- /**
1583
- * Canonical refs of the locked source assets that share a source URL with `resolved` but
1584
- * are locked at another commit than the one `resolved` carries for it. Assets in `resolved`
1585
- * and library-origin entries are skipped.
1586
- */
1587
- private staleSourceSiblingRefs;
1588
- /**
1589
- * The lock entries that came from a source or the store (a `source:`, no `library:`), by
1590
- * identity `<publisher>/<kind>:<name>` -> locked version. The lock's origin
1591
- * wins: a library registered later that holds the same ref does not take such an asset
1592
- * (`update`, `install`, `add`; OQ15, p1490).
1593
- */
1594
- private lockedOriginVersions;
1595
- /**
1596
- * The locked assets whose entry says `origin: store`, by identity -> the store URL. A store
1597
- * origin is a pin: no source that holds the same ref takes the asset until `skaile remove`
1598
- * and `skaile add` move it (`update`, `install`, `add`). A declared ref whose `#pin` the
1599
- * locked version does not satisfy is the user asking for another version: it is not pinned.
1600
- *
1601
- * @param declared - The `dependencies:` refs of `skaile.yaml`.
1602
- * @param asked - Refs being resolved now.
1603
- */
1604
- private storePinnedIdentities;
1605
- /**
1606
- * Say which registered library holds a ref the lock keeps on its source or the store: the
1607
- * candidate that lost, with the way to switch (p1490). Printed once per `add`.
1608
- */
1609
- private noteLosingLibraries;
1610
- /** A candidate's stable identity key (`<publisher>/<kind>:<name>@<version>`). */
1611
- private candidateKey;
1612
- /**
1613
- * Resolve `deps`, falling back to the global `catalog.url` store when the
1614
- * project declares no store and the first pass leaves something missing.
1615
- *
1616
- * The first pass uses the project stores only, so locally-resolvable refs
1617
- * never trigger a network probe. The fallback retry is best-effort: any error
1618
- * (offline, store down) keeps the first pass's result rather than regressing.
1619
- */
1620
- private resolveWithStores;
1621
- /**
1622
- * Resolve `deps` library-first, then walk the dependencies of every library
1623
- * asset it picks.
1624
- *
1625
- * A publisher-qualified ref that no project source declares is looked up in the
1626
- * registered **libraries** before any store is asked, so a locally authored
1627
- * asset resolves (and deploys) with the store unreachable and without a
1628
- * version-discovery round trip. Only refs the libraries did not satisfy go to
1629
- * {@link resolveWithStores}; its misses get one more library try (a ref a source
1630
- * knows only under another version). A `#version` pin still selects through
1631
- * `matchPin` inside {@link resolveLibraryEntries}.
1632
- *
1633
- * Library assets declare `dependencies` / `requires`. Those are fed back through
1634
- * the same resolution with a `seen` identity set (mirrors `resolveAll`), so deps
1635
- * deploy, get lock entries, and a dependency cycle terminates.
1636
- *
1637
- * @returns source/store candidates, still-unresolved refs, applied overrides,
1638
- * expanded presets, and the library leg (entries + originating library per entry).
1639
- */
1640
- private resolveLibraryFirst;
1641
- /**
1642
- * A source asset without a declared version is keyed `0.0.0-sha.<repo commit>`, so every
1643
- * commit of its repo would re-key (and re-lock, and report as updated) every asset of
1644
- * that repo, changed or not. Keep the locked key and version of an asset whose files hash
1645
- * to what the lock holds: `update` then re-locks only what changed, as `outdated` lists.
1646
- * The commit stays the clone's, so the lock's `sources:` row still names the bytes' commit.
1647
- * A ref the user pinned (`#<version>`) keeps the version it names.
1648
- */
1649
- private keepUnchangedSourceVersions;
1650
- /**
1651
- * The catalog fetcher to use: an injected one, else built from `stores`. `catalogUrl: ""`
1652
- * (`update --no-catalog`) asks no store at all, project `stores:` included.
1653
- */
1654
- private storeFetcherFor;
1655
- /**
1656
- * The global `catalog.url` as a single-store fallback, or `[]` when no
1657
- * project store should be synthesized — `local` sentinel, already-declared,
1658
- * or no URL. Honours an explicit `catalogUrl` injection (`""` and `"local"` disable it).
1659
- */
1660
- private globalStoreFallback;
1661
- /**
1662
- * Build deployable catalog entries from resolved candidates. Store-resolved
1663
- * candidates (no local clone bytes) are fetched + SHA-verified into the
1664
- * project store-cache first, then their entry points at the staged bytes so
1665
- * the existing copy-deploy path works. Source-backed candidates keep the
1666
- * clone-relative entry.
1667
- */
1668
- private buildCatalogEntries;
1669
- /**
1670
- * The tail of a `hash mismatch for <file>: expected <lock>, got <fetched>` failure of a locked
1671
- * restore when the deployed copy already holds the fetched bytes: the lock records another
1672
- * hash for the file, and `install` (not `install --locked`) writes the right one. Empty for
1673
- * any other failure, and when the copy is missing or differs from the fetched bytes.
1674
- */
1675
- private wrongLockHashHint;
1676
- /**
1677
- * Fetch + SHA-verify the bytes of every store-resolved candidate that needs
1678
- * bytes on disk into `.skaile/cache/store/`, reusing the same verified-fetch
1679
- * path the pointer-only `library.install` uses (`installFromManifest` flat
1680
- * mode). Every kind with bytes, composition-only kinds included.
1681
- *
1682
- * @returns Map of candidate key → staged primary-manifest path.
1683
- */
1684
- private stageStoreAssets;
1685
- /**
1686
- * The requirements a store candidate's own manifest declares (`metadata.requires`, a manifest
1687
- * `dependencies:`) that its catalog row did not list, read from the staged bytes. The catalog
1688
- * row is the store's own summary and may hold only same-kind ones; the deployed copy is what
1689
- * `check` reads, so a requirement only the manifest names would be missing right after `add`
1690
- * (p1221). Each one is added to the candidate's `deps` and `storeRequires` (the lock records
1691
- * them) and returned so the caller resolves, deploys and locks it like any other dependency.
1692
- * A candidate whose bytes come from a source clone, or that has none, adds nothing.
1693
- */
1694
- private readStoreCandidateRequires;
1695
- /** Repo-relative path of a candidate's primary manifest (un-stripped). */
1696
- private primaryManifestRel;
1697
- /**
1698
- * The primary-manifest path relative to a staged asset dir. Takes the kind's
1699
- * manifest (e.g. `SKILL.md`), then strips the same common-dir prefix
1700
- * `installFromManifest` flat mode removed on write.
1701
- */
1702
- private stagedManifestRel;
1703
- /**
1704
- * `true` when a candidate's primary manifest is present on a local source
1705
- * clone — its `sourceUrl` matches a registered source AND the manifest file
1706
- * exists on disk at the expected path. A URL match alone is not enough: a
1707
- * store can pin a different commit (or a subtree not bundled) of a repo that
1708
- * is also a registered source, in which case the bytes must be fetched from
1709
- * the store rather than read from the clone. (Only the primary manifest is
1710
- * probed — a partially-cloned source is deployed as-is, matching the existing
1711
- * clone-deploy path.)
1712
- */
1713
- private candidateHasLocalBytes;
1714
- /** Build a copy-deploy catalog entry pointing at staged store bytes. */
1715
- private stagedCandidateToEntry;
1716
- /**
1717
- * Install all dependencies declared in `skaile.yaml`.
1718
- *
1719
- * Steps: clone/pull repositories → resolve transitive dependencies → reconcile
1720
- * (remove stale assets) → deploy new assets → write `skaile.lock.yaml` → record history.
1721
- *
1722
- * @param opts - Optional installation options.
1723
- * @param opts.locked - When `true`, restore the exact versions recorded in the existing
1724
- * lock file instead of resolving from source. Throws if no lock file is found, unless the
1725
- * project declares no dependencies (nothing to restore).
1726
- * @param opts.link - When `true`, symlink local-path assets instead of copying them
1727
- * (the author dev-loop). Machine-local / not for committing; a no-op for
1728
- * store/factory sources. Defaults to copy.
1729
- * @param opts.moveLibraries - When `true` (`skaile update`), a locked library asset is
1730
- * re-resolved from every library and may move to another one; {@link InstallResult.moved}
1731
- * lists the moves. Without it a locked asset stays on the library its lock entry names.
1732
- * @returns {@link InstallResult} summarising what was deployed, what was missing, and any collisions.
1733
- */
1734
- install(opts?: {
1735
- locked?: boolean;
1736
- link?: boolean;
1737
- moveLibraries?: boolean;
1738
- /** Deploy over a folder no lock entry owns (a hand-made skill of the same name) instead of refusing. */
1739
- force?: boolean;
1740
- }): Promise<InstallResult>;
1741
- /**
1742
- * Why `install` asks no store, or `undefined` when it does: `--no-catalog`, or `catalog.url:
1743
- * local` with no `stores:` entry in `skaile.yaml`. A locked store asset is then kept as it is,
1744
- * as for an air-gapped client.
1745
- */
1746
- private whyNoStoreAsked;
1747
- /**
1748
- * The kept refs whose locked copy came from a store that `install` did not (or could not)
1749
- * ask, and whose deployed copy is still there: nothing says the copy is wrong, so it stays
1750
- * and the run does not fail on it. A ref whose store answered "no such asset", one with no
1751
- * deployed copy, and one a source or library used to supply stay missing.
1752
- *
1753
- * @param declaredSourceUrls - The `sources:` URLs of `skaile.yaml`; a lock entry from one of
1754
- * them is that source's, not the store's.
1755
- */
1756
- private storeNotCheckedRefs;
1757
- /**
1758
- * Extend `kept` (see {@link keptLockEntries}) with every previous lock entry a kept asset
1759
- * requires, transitively, that the new lock (`freshKeys`) does not already carry. The lock
1760
- * records no edges, so they are read from the kept asset's deployed copy, where the
1761
- * requirement is publisher-qualified the same way a library scan does it. A copy that
1762
- * cannot be read has no known requirements.
1763
- */
1764
- private keepRequiredByKept;
1765
- /**
1766
- * Publisher-qualified refs the deployed copy of `id` requires, read from its own
1767
- * manifest file (`metadata.requires`, a manifest `dependencies:` entry): the one place
1768
- * the requirements stay knowable when no source or library holds the asset any more.
1769
- * A copy that is not deployed or cannot be read has no known requirements.
1770
- */
1771
- private deployedRequirementsOf;
1772
- /**
1773
- * The `requires:` the lock recorded for the store-resolved asset `id` (see
1774
- * {@link LockEntry.requires}): what its deployed copy cannot say, a store agent's skills.
1775
- * Empty for an asset the lock does not hold or records none for.
1776
- */
1777
- private lockedRequirementsOf;
1778
- /**
1779
- * Ensure all source clones are present/up to date. Returns an early
1780
- * {@link InstallResult} describing the failed source on the first error, or
1781
- * `null` when every clone succeeds.
1782
- */
1783
- private ensureSourceClones;
1784
- /**
1785
- * Best-effort twin of {@link ensureSourceClones} for the read-mostly entry
1786
- * points (`add` / `lock`): same declarations and the same pins — a pinned
1787
- * source must never be pulled off its pin — but a clone failure is swallowed
1788
- * so resolution still runs against whatever is on disk.
1789
- */
1790
- private ensureSourceClonesQuiet;
1791
- /** Lock entries `skaile asset install` wrote (copied/linked straight into the project). */
1792
- private directInstallLockEntries;
1793
- /**
1794
- * Refuse to prune a stale lock entry (in the old lock, not in the new resolved set, with no
1795
- * other version taking its place) whose deployed folder holds hand edits: the files that differ
1796
- * from the lock are named, nothing is removed, and `--force` prunes anyway (OQ6).
1797
- */
1798
- private assertNoHandEditsPruned;
1799
- /**
1800
- * Report (and, without `force`, guard) the files a re-lock deletes from a deployed copy
1801
- * (OQ5, p1441): the asset is locked already and its library or source now holds other content
1802
- * (`next` re-locks it), and the deployed folder holds files the new content does not ship. The
1803
- * deploy clears them. Two cases:
1804
- * - the deployed copy still equals what `prevLock` recorded (per-file sha256 for a source
1805
- * or store asset, the library hash for a library asset): the new version dropped those
1806
- * files, nobody edited them, so they are deleted and come back as `removed` rows (an
1807
- * `install`/`update` prints `Removed <file> (not part of <ref>)`), without a refusal;
1808
- * - the copy diverged (a file the previous content did not ship, an edited file, or no hash
1809
- * to compare): without `force` this throws one error naming the files and changes nothing.
1810
- * A source or store asset names only the files the previous content did not ship (or that
1811
- * were edited); a library asset records no file list, so it names every file to delete.
1812
- *
1813
- * @param entries - The catalog entries about to be deployed.
1814
- * @param next - The lock the run is about to write (or merge).
1815
- * @param libraryOf - The library each library-origin entry came from.
1816
- */
1817
- private relockDeletions;
1818
- /**
1819
- * Stop `install` from overwriting a hand-edited rendered agent file that no lock entry
1820
- * records (OQ5, p1440): the lock is gone (or never held the agent), so nothing tells an edit
1821
- * from a stale render, and the deploy would replace the file without a word. Checks the file
1822
- * named after each agent about to be deployed and the file of each agent instance whose bound
1823
- * agent has no lock entry. Throws one error naming each file that exists and differs from its
1824
- * render and changes nothing; `--force` (the caller skips this check) overwrites. A file that
1825
- * equals its render is not an edit. Project mode only.
1826
- */
1827
- private assertNoUnrecordedAgentOverwrite;
1828
- /**
1829
- * Stop a re-lock from replacing a hand edit of a deployed copy (OQ6, p1641): the asset is locked
1830
- * already, its library or source now holds other content (`next` re-locks it), and a deployed
1831
- * file differs from what the lock covers and from the new content. The deploy would replace
1832
- * the file without a word. Throws one error naming each file and changes nothing; `--force`
1833
- * (the caller skips this check) replaces them. An agent's rendered files are compared with the
1834
- * hashes the lock records. A file the new content brings back byte for byte loses nothing.
1835
- * Project mode only.
1836
- */
1837
- private assertNoHandEditsOverwritten;
1838
- /**
1839
- * Remove stale assets — those recorded in the old lock but absent from the
1840
- * newly resolved set (`resolved` source candidates plus `keep`, the canonical
1841
- * refs of library-origin assets locked in this run). Returns the list of
1842
- * removed refs.
1843
- */
1844
- private reconcileRemovedAssets;
1845
- /** Append `add`/`remove` history entries for a completed install reconcile. */
1846
- private recordInstallHistory;
1847
- /**
1848
- * Read the lock, returning null on a legacy v1 lock instead of throwing. A lock that is not
1849
- * valid YAML throws {@link LockParseError}: it is not an empty lock (p1892).
1850
- */
1851
- private tryReadLock;
1852
- /**
1853
- * A catalog client for `storeUrl` that honours `catalog.cache_ttl` (`0` = air-gapped: no
1854
- * network, so every lookup that is not cached throws `OfflineError`).
1855
- */
1856
- private remoteStore;
1857
- /**
1858
- * Remember why a store could not be asked (store URL → one line without a JS error class
1859
- * name), so `add` can say `store unreachable` instead of a bare `Asset not found`.
1860
- */
1861
- private noteStoreFailure;
1862
- /** Build a store fetcher from the configured stores, or undefined when none. */
1863
- private buildStoreFetcher;
1864
- /**
1865
- * Resolve runtime assets and install any missing npm peer deps.
1866
- *
1867
- * - Required deps: installed via `bun add --optional`. Failure is recorded
1868
- * in `npmFailed` but does not throw — install() proceeds so users get a
1869
- * useful error message rather than a hung command.
1870
- * - Optional deps: not installed automatically (would force every consumer
1871
- * to pull every connector's deps). Future: add a flag to opt in.
1872
- */
1873
- private installRuntimeAssetDeps;
1874
- /**
1875
- * Give every ref `install` could not resolve, and that has no hint yet, the fix the shared
1876
- * {@link AssetManager.projectState} names for it (a declared ref no library or source holds,
1877
- * a requirement nothing holds). Runs after the deploy, so a requirer is known by then.
1878
- * Mutates `hints`: ` <reason>` follows the ref in the `Missing:` line.
1879
- */
1880
- private adviseMissing;
1881
- private installLocked;
1882
- /**
1883
- * One notice line per locked library that is not registered here and whose assets
1884
- * `install --locked` restored from a store: names the library, how many assets came from
1885
- * which store (and the upstream repository and commit its pointer names), and how to register
1886
- * the library to move the lock later (OQ8, p1655). Every file was SHA-verified against the
1887
- * hash the lock recorded.
1888
- */
1889
- private storeRestoreNotices;
1890
- /**
1891
- * The versions of `parsed`'s name that a source, a library or a store holds, newest first,
1892
- * for the `Asset not found` of a pinned ref. Empty for an unpinned ref (nothing was ruled
1893
- * out by a version) and when the name is unknown everywhere. A store that cannot be asked
1894
- * adds nothing here: its failure is reported by the caller.
1895
- */
1896
- private availableVersions;
1897
- /**
1898
- * The refs of the other kinds that a source or a library holds under the same publisher and
1899
- * name as `parsed` (`agent:@pub/captain` for a `@pub/captain` that is no skill), for the
1900
- * `Did you mean` of an `add` that missed.
1901
- */
1902
- private otherKindRefs;
1903
- /**
1904
- * The sentence that ends the not-found line of a ref that names no asset but whose name exists
1905
- * under another kind: refs of other kinds under the same name that a source, a library, the
1906
- * lock or `skaile.yaml` holds. For a ref written without a kind (`@pub/name`, which means
1907
- * `skill`) it is `Did you mean agent:@pub/name?`; for a kind-qualified ref of the wrong
1908
- * kind (`skill:@pub/captain`) it is `It is an agent: agent:@pub/captain.`. `undefined`
1909
- * when nothing of another kind answers to it. `add`, `diff`, `update`, `info`, `remove` and
1910
- * `why` end their not-found line with it.
1911
- */
1912
- otherKindHint(ref: string): Promise<string | undefined>;
1913
- /**
1914
- * What `add` would deploy for the resolved candidates and library entries, without touching
1915
- * the project: one item per asset with its origin, version, deploy folders and files.
1916
- */
1917
- private planAddItems;
1918
- /**
1919
- * Parse the ref `add` was given. A ref the grammar rejects fails with the parser's message
1920
- * minus its manifest-migration advice (it points at a skill that is not for `add`), and:
1921
- * - a publisher-less ref (`report-html`, `skill:report-html`) names the assets of that
1922
- * kind and name that `add` can resolve (a source, the bundled factory source or a
1923
- * library holds them), so `Did you mean` never names an asset that does not resolve;
1924
- * - a `@version` suffix (`skill:@acme/x@1.0.0`) says the pin is written `#<version>`.
1925
- */
1926
- private parseAddRef;
1927
- /**
1928
- * The publisher-qualified refs of the assets named like the publisher-less `ref` that
1929
- * `add` resolves: held by a source clone, the bundled factory source or a registered
1930
- * library. A ref without a kind means a skill, as the grammar says.
1931
- */
1932
- private resolvableMatches;
1933
- /**
1934
- * Add a single asset (and its transitive dependencies) to the workspace.
1935
- *
1936
- * Resolves `ref`, deploys the asset and all requirements, then records the ref
1937
- * in `skaile.yaml` `dependencies` so subsequent `skaile install` runs re-deploy it.
1938
- *
1939
- * @param ref - Asset ref in `kind:name` or `repo/kind:name` form (e.g. `skill:my-skill`).
1940
- * @param opts - Optional deploy options.
1941
- * @param opts.link - When `true`, symlink local-path assets instead of copying them
1942
- * (the author dev-loop). Machine-local / not for committing; a no-op for
1943
- * store/factory sources. Defaults to copy.
1944
- * @param opts.onLibraryOrigin - Called once per deployed library-origin asset with its
1945
- * canonical ref and the name of the library it was resolved from.
1946
- * @param opts.onLibraryMoved - Called once per asset whose lock entry named another library
1947
- * than the one this add resolved it from.
1948
- * @param opts.onPresets - Called once with the presets expanded into this add (the
1949
- * added preset and any it nests); a library-held preset names its library.
1950
- * @returns Array of asset refs that were deployed in this call.
1951
- * @throws When the asset cannot be found in any configured repository, or when a
1952
- * preset's items do not all resolve (nothing is deployed or recorded then).
1953
- */
1954
- add(ref: string, opts?: {
1955
- link?: boolean;
1956
- onLibraryOrigin?: (deployedRef: string, library: string) => void;
1957
- /** Called per deployed library asset whose body is still the untouched `library create` scaffold. */
1958
- onPlaceholderBody?: (deployedRef: string) => void;
1959
- /** Called per deployed library asset whose `description:` is still the `library create` placeholder. */
1960
- onPlaceholderDescription?: (deployedRef: string) => void;
1961
- /** Called per already-locked asset this add moved to another library than its lock entry named. */
1962
- onLibraryMoved?: (move: LibraryMove) => void;
1963
- /** Called with the instance id and ref when this add bound an agent as `agents.<id>` of `skaile.yaml`. */
1964
- onAgentBound?: (id: string, ref: string) => void;
1965
- /** Called when the id this add would bind is taken by another agent: `agents.<id>` keeps `keptRef`. */
1966
- onAgentBindingKept?: (id: string, keptRef: string) => void;
1967
- /** `update <name>`: an equal-version tie between libraries goes to the default library, then the locked one (see {@link install}'s `moveLibraries`). */
1968
- preferLockedLibrary?: boolean;
1969
- onPresets?: (presets: PresetExpansion[]) => void;
1970
- /** Deploy over a folder no lock entry owns (a hand-made skill of the same name) instead of refusing. */
1971
- force?: boolean;
1972
- /** Called per `.env` file in an asset's directory that a copy deploy leaves out. */
1973
- onSecretFile?: (ref: string, path: string) => void;
1974
- /** Resolve and check everything, write nothing, and hand the plan to `onPlan`. */
1975
- dryRun?: boolean;
1976
- /** Global `--harness`: replace the recorded harness set instead of adding to it (`--only`). */
1977
- only?: boolean;
1978
- /** With `only`: called per harness that drops out of the set but still holds a copy. */
1979
- onDroppedCopy?: (ref: string, harness: HarnessName, path: string) => void;
1980
- /** Called once with the plan of a `dryRun` add. */
1981
- onPlan?: (plan: AddPlanItem[]) => void;
1982
- }): Promise<string[]>;
1983
- /**
1984
- * Report the body-link **soft dependencies** of the given assets that are not
1985
- * already present in the project.
1986
- *
1987
- * Looks up each ref's persisted `softDeps` in the local index
1988
- * (`~/.skaile/index.db`, populated by `skaile source sync`) and returns the
1989
- * edges whose target is neither a declared dependency nor deployed on disk. It
1990
- * does **not** install anything and never touches the resolver / lock /
1991
- * reconcile path: callers surface the result as a hint, the user opts in with
1992
- * a follow-up `skaile add`. Inspects exactly the passed `refs` — soft deps of
1993
- * their transitively-deployed dependencies are not surfaced here.
1994
- *
1995
- * Opening the index runs its idempotent migrations, so this is not a pure
1996
- * read — but it is **best-effort**: any failure (legacy/corrupt index, a
1997
- * removed-backend guard) yields `[]`, so it can never fail a primary `add`
1998
- * that already succeeded.
1999
- *
2000
- * @param refs - Asset refs to inspect (canonical, `kind:@pub/name`, or `kind:name`).
2001
- * @returns One edge per absent soft-dep target (deduped by target). `toRef` is
2002
- * the parseable `skaile add` ref, omitted when the target isn't in the index.
2003
- */
2004
- reportSoftDeps(refs: string[]): Promise<Array<{
2005
- from: string;
2006
- to: string;
2007
- toRef?: string;
2008
- }>>;
2009
- /**
2010
- * Presets in the configured sources (and the bundled factory source) that list
2011
- * `ref` as an asset item, for the `skaile add` discoverability hint. Membership is
2012
- * not a dependency: nothing here installs the preset or its siblings.
2013
- *
2014
- * Matches on kind + name, and on publisher only when both sides carry one, so
2015
- * a bare `skill:x` item still matches `skill:@pub/x`. Presets already
2016
- * declared in `skaile.yaml` are left out. Best-effort: any failure yields `[]`,
2017
- * so it can never fail an `add` that succeeded.
2018
- *
2019
- * @param ref - The added asset ref (`kind:name`, `kind:@pub/name`, optionally pinned).
2020
- * @returns One `{ name, ref }` per containing preset, deduped by `ref`; `ref` is
2021
- * the `skaile add` form (`preset:@pub/name`, or `preset:name` without a publisher).
2022
- */
2023
- presetsContaining(ref: string): Promise<Array<{
2024
- name: string;
2025
- ref: string;
2026
- }>>;
2027
- /**
2028
- * All body-link soft dependencies of the given assets — present or not.
2029
- *
2030
- * Unlike {@link reportSoftDeps} (which filters to *absent* targets so it can
2031
- * nudge a follow-up `skaile add`), this returns the asset's full inferred
2032
- * soft-dep set for display surfaces (`skaile info` / `tree` / `why`). Read-only
2033
- * and best-effort: any index failure yields `[]`. Targets are deduped.
2034
- *
2035
- * @param refs - Asset refs to inspect (canonical, `kind:@pub/name`, or `kind:name`).
2036
- * @returns One {@link SoftDepEdge} per soft-dep target. `toRef` is the parseable
2037
- * ref, omitted when the target isn't in the index.
2038
- */
2039
- softDepsOf(refs: string[]): Promise<SoftDepEdge[]>;
2040
- /**
2041
- * Reverse lookup: refs (canonical ids) of cached assets whose persisted
2042
- * `softDeps` include `targetRef`. Scans the whole index, not just present
2043
- * assets. Read-only and best-effort (`[]` on any index failure).
2044
- *
2045
- * @param targetRef - Canonical soft-dep target ref (`<publisher>/<name>@<version>`).
2046
- * @returns Def ids that declare `targetRef` as a soft dependency.
2047
- */
2048
- softDepDependents(targetRef: string): Promise<string[]>;
2049
- /**
2050
- * Compute which soft-dependency targets would be left **orphaned** by removing
2051
- * `refs`: targets still present in the project that came in as one of `refs`'
2052
- * soft dependencies and that **nothing else still needs** — neither another
2053
- * present asset's soft-dep ({@link softDepDependents}) nor a typed `requires`.
2054
- *
2055
- * Pure read — never removes anything. The CLI / manage surfaces each result as
2056
- * a prompt (default No) so the user opts in to an extra `skaile remove`. Safe to
2057
- * call before or after the primary remove: assets being removed are excluded
2058
- * from the "needed by others" scan, so a soft target referenced only by the
2059
- * removed asset is still reported as an orphan.
2060
- *
2061
- * @param refs - Asset refs being removed (canonical, `kind:@pub/name`, or `kind:name`).
2062
- * @returns One {@link OrphanedSoftDep} per orphaned target (deduped).
2063
- */
2064
- orphanedSoftDepsAfterRemoving(refs: string[]): Promise<OrphanedSoftDep[]>;
2065
- /**
2066
- * Open the local index, run `fn` against its cached asset defs, and close it.
2067
- * Best-effort: no index (user never ran `source sync`), a missing file, or any
2068
- * open/guard failure yields `fallback` — so a read surface can never throw or
2069
- * create an empty `index.db` as a side effect.
2070
- */
2071
- private withIndexDefs;
2072
- /**
2073
- * Build soft-dep edges for `refs` from cached defs. With `onlyAbsent`, targets
2074
- * already present in the project are skipped (the `reportSoftDeps` nudge); else
2075
- * the full inferred set is returned (the `softDepsOf` display). Deduped by target.
2076
- */
2077
- private collectSoftDeps;
2078
- /**
2079
- * Names of assets already in the project — declared deps + deployed on disk.
2080
- * Bare name only (see {@link softDepName}): a same-named asset of a different
2081
- * publisher/kind counts as present, so the report under-reports rather than
2082
- * nags about something already installed.
2083
- */
2084
- private presentRefNames;
2085
- /**
2086
- * Present asset refs — declared `skaile.yaml` deps (canonical refs as written)
2087
- * plus deployed assets as `kind:name`. Used by the soft-dep present-check and
2088
- * the orphan "needed by others" scan.
2089
- */
2090
- private presentRefs;
2091
- /**
2092
- * Remove a deployed asset and unregister it from `skaile.yaml` and the lock.
2093
- *
2094
- * A declared asset is always unregistered, even when nothing is deployed any
2095
- * more (e.g. its library file was deleted): the declaration and lock entry
2096
- * would otherwise be stuck behind a "not deployed" refusal.
2097
- *
2098
- * Removes only `ref` itself; use {@link removeWithDependencies} to also drop the
2099
- * dependencies it leaves orphaned.
2100
- *
2101
- * Deliberately does NOT re-render the harness target's MCP config: the render
2102
- * step is async (the declaration resolver is), and making this synchronous
2103
- * method async would break every external caller. {@link removeWithDependencies}
2104
- * (what `skaile remove` runs) does re-render it; a caller of this method gets the
2105
- * dropped entry at the next {@link AssetManager.install} — see
2106
- * {@link renderMcpServerConfig}.
2107
- *
2108
- * @param ref - Asset ref: `kind:@publisher/name`, or the short `kind:name` /
2109
- * `name` form when exactly one declared, locked or deployed asset matches it.
2110
- * @returns `true` if anything changed (files undeployed, declaration or lock
2111
- * entry removed), `false` if the asset was neither deployed nor declared.
2112
- * A `preset:` ref has no deployed files: only its declaration goes — its
2113
- * expanded items leave with the next `skaile install`.
2114
- * @throws When `ref` is malformed, or a short ref matches several assets (the
2115
- * message lists them).
2116
- */
2117
- remove(ref: string, opts?: {
2118
- force?: boolean;
2119
- }): boolean;
2120
- /**
2121
- * {@link remove} `ref`, then drop the dependencies that removal left orphaned:
2122
- * locked assets `ref` required (directly or through one another) that
2123
- * `skaile.yaml` no longer declares and no remaining locked asset requires. A
2124
- * preset's items count as its requirements. They are undeployed and unlocked;
2125
- * a dependency still declared or required elsewhere stays.
2126
- *
2127
- * An asset another locked asset (or a declared preset) requires is kept and reported in
2128
- * `blocked`, nothing changes, unless `opts.force` (see {@link requiredByOthers}).
2129
- *
2130
- * @returns `changed` as {@link remove}; `pruned` the canonical refs
2131
- * (`kind:@publisher/name`) of the dependencies dropped as well; `blocked` when the
2132
- * removal was refused.
2133
- */
2134
- removeWithDependencies(ref: string, opts?: {
2135
- force?: boolean;
2136
- }): Promise<RemoveResult>;
2137
- /**
2138
- * Resolve the identity {@link remove} acts on. A publisher-qualified ref is taken
2139
- * as written; a short ref (`kind:name`, or just `name`) is matched on kind + name
2140
- * against the declared dependencies, the lock and the deployed assets, like
2141
- * `why` / `diff` do.
2142
- *
2143
- * @returns the identity, or `null` when a name-only ref matches nothing.
2144
- * @throws On a malformed ref, or when a short ref matches more than one asset.
2145
- */
2146
- private resolveRemoveTarget;
2147
- /**
2148
- * The refs among `refs` (`skill:@publisher/name`, `skill:name`, with or without `#version`)
2149
- * that are not deployed for this manager's harnesses and scope, judged as `check` judges a
2150
- * requirement. A ref that does not parse or names a kind this build does not install is
2151
- * never reported. `run <flow> --dry-run` names the node skills a flow still lacks (p1757).
2152
- */
2153
- undeployedSkills(refs: readonly string[]): string[];
2154
- /**
2155
- * The reverse guard of {@link removeWithDependencies}: which other locked assets (and
2156
- * declared presets) require `target`. Their requirements are read the way {@link lockedGraph}
2157
- * reads them for pruning. Never touches the project.
2158
- *
2159
- * @returns `ref` and `requiredBy` (both `kind:@publisher/name`, version-agnostic), or `null`
2160
- * when `target` is not locked or nothing else requires it.
2161
- */
2162
- private requiredByOthers;
2163
- /**
2164
- * Publishers under which the lock or `skaile.yaml` track `kind:name`. A deployed dir carries
2165
- * no publisher, so this is what says whose copy it is. `undefined` stands for a
2166
- * publisher-less declaration.
2167
- */
2168
- private trackedPublishers;
2169
- /**
2170
- * The lock entries that hold `kind:name`, each with its publisher (no leading `@`) and its
2171
- * canonical ref. A deployed folder carries no publisher; these are who it belongs to.
2172
- */
2173
- private lockHolders;
2174
- /** The folders or files of `kind:name` on disk in `target`, shown relative to the project. */
2175
- private heldDeployPaths;
2176
- /**
2177
- * Undeploy `parsed` from every target harness and drop its declaration and lock entry.
2178
- *
2179
- * A folder no lock entry holds is the user's own work (a hand-made skill of the same name):
2180
- * it is kept and named in `opts.kept` unless `opts.force`.
2181
- */
2182
- private removeResolved;
2183
- /**
2184
- * After an `mcp-server` asset left the project: drop what would keep it rendered. Its staged
2185
- * store bytes under `.skaile/cache/store/<publisher>/mcp-server/<name>/` go (an `mcp_servers:`
2186
- * entry of the same id would otherwise keep loading them), and so does an `mcp_servers:` entry
2187
- * that only sets values for it: `env` and the like, with no `command`, `url` or recipe of its
2188
- * own. An entry that can run alone is the user's own server and stays.
2189
- *
2190
- * @returns The dropped `mcp_servers` entries, as `mcp_servers entry "<id>"`.
2191
- */
2192
- private dropRemovedMcpServerSettings;
2193
- /**
2194
- * After `remove --global --harness X`: the harnesses outside `X` that still hold a copy of the
2195
- * asset, or `undefined` when none does (or this is not a harness-limited global remove).
2196
- */
2197
- private harnessesStillHolding;
2198
- /** Limit the declared global entry of `target` to `harnesses` (`~/.skaile/skaile.yaml`). */
2199
- private limitDeclaredEntry;
2200
- /**
2201
- * Drop the locked assets among `requiredRefs` (and what they require in turn) that
2202
- * nothing needs any more: not declared in `skaile.yaml`, not required by a locked
2203
- * asset outside that set. Call after the requiring asset is gone.
2204
- *
2205
- * @returns the canonical refs of the assets dropped.
2206
- */
2207
- private pruneOrphans;
2208
- /**
2209
- * Drop every lock entry matching a removed asset's identity, version-agnostic so
2210
- * a content-sha pseudo-version key is pruned too. Symmetric with {@link add}'s
2211
- * lock-merge — stops a stale entry reporting a phantom "removed" on next install.
2212
- *
2213
- * @returns `true` when at least one lock entry was dropped.
2214
- */
2215
- private pruneLockEntry;
2216
- /**
2217
- * Search the catalog across all configured repositories.
2218
- *
2219
- * @param query - Substring to match against entry names and descriptions (case-insensitive).
2220
- * Omit to return all entries.
2221
- * @param kind - Filter by asset kind (`"skill"`, `"agent"`, `"prompt"`, `"flow"`, `"contract"`).
2222
- * Omit to return all kinds.
2223
- * @returns Array of matching {@link CatalogEntry} objects from all accessible repositories.
2224
- */
2225
- search(query?: string, kind?: string): Promise<CatalogEntry[]>;
2226
- /**
2227
- * On-disk root + config slug for every declared (and the implicit factory)
2228
- * source that has a local clone. Companion to {@link search}: callers that
2229
- * need to relate a scanned entry back to its source root (e.g. to stamp
2230
- * plugin grouping) can't recover the root from the flat
2231
- * {@link CatalogEntry} list `search` returns.
2232
- */
2233
- searchRepoRoots(): {
2234
- repoName: string;
2235
- root: string;
2236
- }[];
2237
- /**
2238
- * Look up a single asset's full catalog entry.
2239
- *
2240
- * Accepts a bare `kind:name` ref (no publisher) in addition to the fully-qualified
2241
- * `kind:@publisher/name` form — {@link listDeployed} emits publisher-less refs and
2242
- * {@link doctor} passes them straight to this method.
2243
- *
2244
- * @param ref - Asset ref in `kind:name`, `kind:@publisher/name`, or `repo/kind:name` form.
2245
- * @returns The matching {@link CatalogEntry}, or `null` when not found.
2246
- */
2247
- info(ref: string): Promise<DeployableEntry | null>;
2248
- /**
2249
- * List all assets currently deployed in the workspace (or global cache).
2250
- *
2251
- * Scans the framework deploy directories rather than the lock file, so it
2252
- * also returns assets that were installed manually or outside of `skaile install`.
2253
- *
2254
- * @param kind - Filter by asset kind. Omit to return all kinds.
2255
- * @returns Shallow {@link CatalogEntry} objects (description and version will be empty).
2256
- */
2257
- listDeployed(kind?: string): CatalogEntry[];
2258
- /**
2259
- * Absolute path → sha256 of every native agent file the lock records under `rendered:`. A
2260
- * `harness set` rewrites the lock for the new harness, so a caller that cleans up afterwards
2261
- * reads this first and hands it to {@link AssetManager.listStaleHarnessCopies}.
2262
- */
2263
- lockedRenderedHashes(): Map<string, string>;
2264
- /**
2265
- * Tracked assets (`skaile.lock.yaml` or declared in `skaile.yaml`) whose copy
2266
- * still sits in the project dirs of another harness (`.claude/…`, `.omp/…`,
2267
- * `.codex/…`) although this manager deploys to {@link AssetManager.harness}.
2268
- * A project that moved with `skaile harness set` holds orphans there that
2269
- * `remove` / `clean` / `list` no longer look at.
2270
- *
2271
- * Read-only: nothing is deleted. Empty for global mode and for kinds whose
2272
- * dir is shared with the active target (flows).
2273
- *
2274
- * @param opts.renderedBefore - {@link AssetManager.lockedRenderedHashes} of the lock as it was
2275
- * before the move to this harness. An agent copy counts as skaile's only when it matches a
2276
- * hash the lock (now or then) recorded for its path.
2277
- * @returns One {@link StaleHarnessCopy} per stale copy, sorted by harness, kind, then name.
2278
- */
2279
- listStaleHarnessCopies(opts?: {
2280
- renderedBefore?: ReadonlyMap<string, string>;
2281
- }): StaleHarnessCopy[];
2282
- /**
2283
- * @deprecated Use {@link AssetManager.listStaleHarnessCopies}, which covers every
2284
- * other harness folder. This returns only its `.claude/` rows (the old default
2285
- * deploy dir), in the old shape.
2286
- */
2287
- listLegacyClaudeDeployed(): LegacyDeployedAsset[];
2288
- /**
2289
- * List the **declared** top-level dependencies from `skaile.yaml`, each tagged
2290
- * with a reconciliation {@link DeclaredState}:
2291
- *
2292
- * - `declared` — in `skaile.yaml`, not yet resolved into the lock.
2293
- * - `installed` — declared + locked, and (for kinds with an `installTarget`)
2294
- * materialized on disk. An `mcp-server` is instead checked against the
2295
- * declarations the runner would actually wire (store-staged or materialized
2296
- * `MCP.md`); the remaining composition-only kinds (no `installTarget`) count as
2297
- * installed once locked — they are resolved at session start with no harness
2298
- * footprint here.
2299
- * - `drift` — declared + locked but the deployed files are missing on disk.
2300
- * - `invalid` — the `dependencies:` entry isn't a parseable canonical ref. Only
2301
- * surfaced in the unfiltered listing (a `kind` filter can't classify it).
2302
- *
2303
- * Transitive (lock-only) deps are excluded by construction — only the declared
2304
- * set is walked, so a lock entry with no matching `dependencies:` ref never shows.
2305
- *
2306
- * @param kind - Filter by asset kind. Omit to return all kinds.
2307
- * @returns One {@link DeclaredAsset} per declared dep (after the optional kind filter), plus
2308
- * one per locked agent that only an agent instance of `skaile.yaml` binds.
2309
- * @throws {MissingManifestError} when the project has no `skaile.yaml`.
2310
- * @throws {Error} with a `migrate-skaile-manifest` hint on legacy `repositories:` / `ai_resources:` keys.
2311
- */
2312
- listDeclared(kind?: string): Promise<DeclaredAsset[]>;
2313
- /**
2314
- * One note per locked library asset whose library went back to an older version than the lock
2315
- * (`library is at 0.1.0, locked 0.3.0`). Not drift: `install` keeps the lock and only `update`
2316
- * moves it, so `check` and `doctor` print the note as a `!` line and still exit 0 (p1257).
2317
- * Empty for a global manager or when the libraries cannot be read.
2318
- */
2319
- libraryOlderNotices(): Promise<string[]>;
2320
- /**
2321
- * Notes about the project's `mcp-server`s that are not drift and fail nothing: a declared
2322
- * server skaile does not write to the coding agent's MCP config (`reason` from the last
2323
- * render), and a required `MCP.md` field nothing sets. `check` and `doctor` print them as
2324
- * `!` lines; `list` shows the first kind as `skipped`.
2325
- *
2326
- * @returns One {@link McpNotice} per note; empty for a global manager.
2327
- */
2328
- mcpNotices(): Promise<McpNotice[]>;
2329
- /**
2330
- * Locked assets whose deployed directory lacks files the deploy writes — a deleted
2331
- * `build.py` / `scripts/` helper next to an intact `SKILL.md`. The expected set is the file
2332
- * set the lock covers: a library entry's files (every file under its manifest `root:`), a
2333
- * source or store entry's `files[]` (the asset's whole file set at the locked commit). Only
2334
- * presence is checked, so a local edit never counts. An asset with no deployed directory is
2335
- * not listed (`listDeclared` reports it as drift); an agent is rendered, not copied, so it
2336
- * has no file mirror to compare. `skaile install` restores what is listed.
2337
- *
2338
- * @returns One {@link IncompleteDeploy} per affected asset; empty when healthy
2339
- * or when the project has no lock.
2340
- */
2341
- incompleteDeploys(): Promise<IncompleteDeploy[]>;
2342
- /**
2343
- * Per-harness reconciliation of the **global** declared deps
2344
- * (`~/.skaile/skaile.yaml`) against each global harness's deploy dir. The
2345
- * global twin of {@link listDeclared}: the same `declared` / `installed` /
2346
- * `drift` / `invalid` vocabulary, but one row **per (ref, harness)** so an
2347
- * asset can be `installed` for `claude-code` and `drift`/`declared` for
2348
- * `codex` at once.
2349
- *
2350
- * Reads the SSOT + the global lock (`~/.skaile/skaile.lock.yaml`) — construct
2351
- * the manager with `global: true`. Unlike `listDeclared`, a missing SSOT is
2352
- * **not** an error: it yields an empty list (a fresh machine has no globals).
2353
- *
2354
- * @param opts.harness - Reconcile against this one harness only (the
2355
- * `--harness` filter); omit for every harness in {@link targetHarnesses}.
2356
- * @param opts.kind - Filter by asset kind.
2357
- * @returns One {@link HarnessDeclaredAsset} per declared dep × harness.
2358
- * @throws {Error} on legacy keys in `~/.skaile/skaile.yaml` (migration hint).
2359
- */
2360
- globalState(opts?: {
2361
- harness?: HarnessName;
2362
- /** @deprecated Use `harness`. Honoured only when `harness` is absent; removed in the next major. */
2363
- backend?: HarnessName;
2364
- kind?: string;
2365
- }): HarnessDeclaredAsset[];
2366
- /**
2367
- * Build an aggregated workspace overview with publisher grouping and sync status.
2368
- *
2369
- * Combines deployed assets, lock file metadata, and live repository status
2370
- * into a single structured result. Used by `skaile status`.
2371
- *
2372
- * @returns {@link OverviewResult} with entries grouped by publisher and per-repo sync status.
2373
- */
2374
- overview(): OverviewResult;
2375
- /** Collect live sync status for every configured repository, keyed by name. */
2376
- private buildRepoStatuses;
2377
- /**
2378
- * Requirement graph of the locked assets, for {@link tree} / {@link why} / removal pruning.
2379
- *
2380
- * The lock records no edges, so they are rebuilt from each locked asset's own
2381
- * declaration (`requires`, manifest `dependencies`, a preset's items) — the same
2382
- * source the install walk reads, via {@link info}. An asset that no source or
2383
- * library can be found for has no known requirements. Nodes are lock keys, plus
2384
- * each declared `preset:` that the lock does not carry (a preset is expanded at
2385
- * install, never locked), keyed by its declared ref.
2386
- *
2387
- * @returns `requires` (node → the lock keys it requires), `roots` (nodes
2388
- * `skaile.yaml` declares) and `findKey` (a ref → its lock key, version-agnostic).
2389
- */
2390
- private lockedGraph;
2391
- /**
2392
- * Build the resolved dependency tree from the lock file.
2393
- *
2394
- * Required assets nest under the asset that requires them (see {@link lockedGraph});
2395
- * an asset required by several parents appears under each, and a dependency cycle
2396
- * is cut where it would repeat.
2397
- *
2398
- * @returns Root {@link DependencyNode} with `ref === "project"` whose children
2399
- * are the directly-declared assets, followed by locked assets nothing requires,
2400
- * each with the assets it requires as children.
2401
- * Returns a single node with `ref === "(no lock file)"` when no lock exists.
2402
- */
2403
- tree(): Promise<DependencyNode>;
2404
- /**
2405
- * Explain why an asset is installed by tracing its dependency chain.
2406
- *
2407
- * The chain is read from the requirement graph ({@link lockedGraph}): the asset,
2408
- * then the asset that requires it, and so on up to a dependency `skaile.yaml`
2409
- * declares (the shortest such path; cycles are not followed twice).
2410
- *
2411
- * @param ref - Asset ref in `kind:name` form.
2412
- * @returns Chain of refs from the asset back to `"direct (skaile.yaml)"`; an asset
2413
- * no declared dependency reaches ends in `"not required by a declared dependency"`
2414
- * instead. `[]` when the asset is not in the lock file.
2415
- */
2416
- why(ref: string): Promise<string[]>;
2417
- /**
2418
- * The {@link AssetManager.why} chain of a preset. A preset is never a lock asset: its record
2419
- * is the lock's `presets` slice. Declared in `skaile.yaml` it is `direct`; one only a declared
2420
- * preset nests is traced through the presets that list it.
2421
- *
2422
- * @returns `[]` when the lock does not record the preset.
2423
- */
2424
- private whyPreset;
2425
- /**
2426
- * List installed assets that have a newer upstream available.
2427
- *
2428
- * Two kinds of staleness are reported:
2429
- * - **Source assets** — only remote repositories (not local paths) are checked;
2430
- * `behind` counts the commits the clone is missing from the remote plus the
2431
- * commits the clone moved past the locked commit (`source sync` after `add`).
2432
- * - **Library assets** — a library-origin lock entry whose library files on disk
2433
- * (not the index, which lags until `skaile library index`) hold a newer version
2434
- * than the locked one (`latestVersion`, `library` set), or the same version with
2435
- * different bytes (`contentChanged`). `behind` is 0.
2436
- * - **Project state** — every {@link AssetManager.projectState} gap (an unregistered or
2437
- * renamed library, a missing deployed copy, a declared dependency or a deployed asset's
2438
- * `requires` with no lock entry, a lock that contradicts a `skaile.yaml` pin) as a
2439
- * `problem` row, so `outdated` lists what `check`, `doctor` and `install --locked` fail
2440
- * on. An asset that also has a version row is listed once, with that row.
2441
- *
2442
- * @returns Array of {@link OutdatedEntry} objects.
2443
- */
2444
- outdated(): Promise<OutdatedEntry[]>;
2445
- /**
2446
- * The `#pin` of every publisher-qualified `skaile.yaml` dependency, keyed `kind:publisher/name`
2447
- * (no scope sigil). `update` honours it, so `outdated` must not list a move it keeps.
2448
- */
2449
- private declaredPinsByIdentity;
2450
- /**
2451
- * List a locked asset whose `skaile.yaml` ref carries a `#version` pin while a source, a
2452
- * library or a store holds a newer one: `locked 0.7.0 -> 0.9.0 (pinned)`. The pin is the
2453
- * user's choice, so the row only informs (`pinned`): `update` leaves it, `outdated` does not
2454
- * fail on it (OQ13, p1291). An asset already listed keeps its own row.
2455
- */
2456
- private addPinnedRows;
2457
- /**
2458
- * Ask the stores about every locked asset whose lock entry says `origin: store`, and record
2459
- * those no store could be asked about (the URL did not answer, or the client is air-gapped)
2460
- * for {@link takeStoreNotChecked}. `outdated` runs it, and so do `check` and `doctor`, which
2461
- * otherwise never ask a store: without it a dead store reads as "everything is fine".
2462
- * A store that answers, and a client that skips the store on purpose
2463
- * (`catalogUrl: ''`, `--no-catalog`), record nothing. A ref already recorded is not asked again.
2464
- */
2465
- probeStoreOrigins(): Promise<void>;
2466
- /**
2467
- * List a source asset locked under a `0.0.0-sha.<commit>` key whose file now declares a
2468
- * version: the next `install` or `update` re-keys it (`replaced 0.0.0-sha.7de3555 → 0.2.0`),
2469
- * so `outdated` lists it as `re-key (…)` instead of saying everything is up to date (p914).
2470
- * An asset already listed (behind its remote) gets the target on that row.
2471
- */
2472
- private addRekeyRows;
2473
- /**
2474
- * List a locked library asset that `update` would move to another library (a default-library
2475
- * switch, a library that now holds a newer version) as `library → movesTo`, so `outdated`
2476
- * does not say "up to date" and `update` then re-locks it announced only after the fact.
2477
- * The resolution is the one `update` runs ({@link lockedPreference}); an asset already listed
2478
- * with a version row gets the target library on that row.
2479
- */
2480
- private addLibraryMoves;
2481
- /**
2482
- * Add one `problem` row per {@link AssetManager.projectState} gap whose asset is not
2483
- * listed yet, so `outdated` lists the same assets `check`, `doctor` and `install --locked`
2484
- * fail on. An asset that is behind its source and also broken is listed once, with its
2485
- * version row.
2486
- */
2487
- private addLockGapRows;
2488
- /**
2489
- * The deploy entry of a library-origin asset from the library its lock entry records,
2490
- * at the locked version when that library still holds it (else its newest). Other
2491
- * libraries holding the same ref are not consulted: the lock already chose.
2492
- *
2493
- * @param want - Kind, name and optional publisher of the asset.
2494
- * @returns `null` when the lock has no library-origin entry for it, or the recorded
2495
- * library is gone or no longer holds it (callers fall back to a general lookup).
2496
- */
2497
- private lockedLibraryEntry;
2498
- /**
2499
- * The deploy entry of a source- or store-origin asset, carrying the file set its lock entry
2500
- * lists (so a missing or edited helper shows in `diff`, not only the manifest). A source asset
2501
- * reads from its clone; a store asset from the bytes `add`/`install` staged in the project
2502
- * store cache. `null` when the lock has no such entry or its bytes are not on disk.
2503
- *
2504
- * @param want - Kind, name and optional publisher of the asset.
2505
- */
2506
- private lockedSourceEntry;
2507
- /** Whether the lock holds `want` as a store asset (`origin: store`, no library). */
2508
- private isStorePinnedRef;
2509
- /**
2510
- * {@link AssetManager.diff} for a locked source or store asset whose bytes are not on disk:
2511
- * the deployed copy against the per-file hashes the lock records. No text to show without the
2512
- * locked bytes, so an edited file is named and the way to fetch them is. `null` when the lock
2513
- * has no such entry or the kind is rendered (an agent), not copied.
2514
- */
2515
- private diffAgainstLock;
2516
- /**
2517
- * Produce a unified diff from the deployed asset to its catalog source: `-` lines
2518
- * are in the deployed copy only (local edits `update` would overwrite), `+` lines
2519
- * are in the source only (what `update` would add).
2520
- *
2521
- * Useful for detecting manual edits to deployed files or seeing what an upstream
2522
- * change would bring in; also for verifying that a patch
2523
- * was applied correctly.
2524
- *
2525
- * @param ref - Asset ref in `kind:name` form.
2526
- * @returns A {@link DiffResult}: `not-found` (unknown ref), `not-deployed`,
2527
- * `identical`, or `differs` with the unified diff.
2528
- * @throws When `diff(1)` itself fails (exit status other than 0/1).
2529
- */
2530
- diff(ref: string): Promise<DiffResult>;
2531
- /**
2532
- * The agent instances of `skaile.yaml` whose `ref` names `want` (an `agent:` ref, matched on
2533
- * name and, when both name one, publisher) and bind to an agent definition directory.
2534
- */
2535
- private instancesBoundTo;
2536
- /**
2537
- * Resolve all declared dependencies and write (or overwrite) `skaile.lock.yaml`.
2538
- *
2539
- * Performs repository sync and full dependency resolution without deploying assets.
2540
- * Use this to regenerate the lock file after manually editing `skaile.yaml`.
2541
- *
2542
- * @returns The written {@link LockFile} data.
2543
- */
2544
- lock(): Promise<LockFile>;
2545
- /**
2546
- * Extract a deployed asset into a patch working directory for editing.
2547
- *
2548
- * Copies the deployed asset to `.skaile/patches/<kind>-<name>/` so changes
2549
- * can be made there and then committed as a patch file via `patchCommit`.
2550
- *
2551
- * @param ref - Asset ref in `kind:name` form.
2552
- * @returns Absolute path to the patch working directory.
2553
- * @throws When the asset cannot be found in the catalog.
2554
- */
2555
- patch(ref: string): Promise<string>;
2556
- /**
2557
- * Generate a `.patch` file from changes made in the patch working directory.
2558
- *
2559
- * Diffs the patch working directory against the original catalog source and
2560
- * writes the result to `.skaile/patches/<kind>-<name>.patch`.
2561
- *
2562
- * @param ref - Asset ref in `kind:name` form.
2563
- * @returns Absolute path to the generated `.patch` file.
2564
- * @throws When the patch working directory does not exist or no differences are found.
2565
- */
2566
- patchCommit(ref: string): Promise<string>;
2567
- /**
2568
- * Apply the committed patch file to the repository clone and open a contribution branch.
2569
- *
2570
- * Applies `.skaile/patches/<kind>-<name>.patch` to the repository clone, creates a
2571
- * `patch/<kind>-<name>` branch, and stages a commit — ready to push via `contribPush`.
2572
- *
2573
- * @param ref - Asset ref in `kind:name` form.
2574
- * @throws When the asset is not found, has no repository, or the patch file is missing.
2575
- */
2576
- patchSubmit(ref: string): Promise<void>;
2577
- /**
2578
- * Delete the patch working directory and patch file for an asset.
2579
- *
2580
- * @param ref - Asset ref in `kind:name` form.
2581
- */
2582
- patchRemove(ref: string): void;
2583
- /**
2584
- * Scan deployed assets for unsatisfied transitive dependencies.
2585
- *
2586
- * For each deployed asset, checks that all entries in its `requires` list are
2587
- * also deployed. Returns a list of issues with a flag indicating whether the
2588
- * missing dependency can be resolved from a configured repository or library.
2589
- *
2590
- * A deployed asset is looked up by its publisher-qualified identity taken from
2591
- * the lock key (`kind:@pub/name`), so library and source assets resolve alike.
2592
- * A lock-managed asset that no source or library can be found for is reported
2593
- * as an issue with `unresolved: true` (its `requires` cannot be verified);
2594
- * unmanaged deployed files carry no declared origin and are skipped.
2595
- *
2596
- * @returns Array of {@link DepIssue} objects. An empty array means the workspace is healthy.
2597
- */
2598
- doctor(): Promise<DepIssue[]>;
2599
- /**
2600
- * The project's state as one verdict: every way the project differs from what it
2601
- * declares and locks. `skaile check`, `skaile doctor`, `skaile outdated`, `skaile diff`
2602
- * and `skaile install --locked` all take their verdict and exit code from this one list,
2603
- * so one situation reads the same in all five.
2604
- *
2605
- * - `declared` — a `skaile.yaml` dependency with no lock entry (library or source gone,
2606
- * unresolvable ref, never installed);
2607
- * - `invalid` — a `dependencies:` entry that is not a parseable ref;
2608
- * - `drift` — a locked asset whose deployed files are missing;
2609
- * - `pin` — a declared `#pin` that no lock entry for that asset satisfies;
2610
- * - `requires` — a deployed asset's `requires` (or a declared preset's item) that is not
2611
- * deployed (so not locked either);
2612
- * - `unresolved` — a lock-managed deployed asset that no source or library holds any more;
2613
- * - `library` — a locked library asset whose library is not registered (renamed or
2614
- * removed) or no longer holds it, while another library holds it now;
2615
- * - `incomplete` — a deployed library asset that lacks files of its library entry;
2616
- * - `content` — a locked library asset whose files in the library changed since the lock
2617
- * (or whose lock hash predates the one shared asset hash); `skaile install` re-locks it;
2618
- * - `agent` — an `agents.<id>.ref` (or `agent.definition`) that binds to no agent.
2619
- *
2620
- * An asset appears once for what the lock says about it (`unresolved`, else `library`,
2621
- * else `drift`). A declared ref no registered library or source holds names
2622
- * `skaile library init` / `skaile remove`, never `skaile install`: `install` has nothing
2623
- * to resolve it from.
2624
- *
2625
- * Project mode only: a global manager (`global: true`) has no gaps. A project without
2626
- * `skaile.yaml` has no declared set, so only the lock and deployed-asset gaps can appear.
2627
- *
2628
- * @returns The {@link ProjectState}; `gaps` is empty when the project is as declared and locked.
2629
- */
2630
- projectState(): Promise<ProjectState>;
2631
- /**
2632
- * The first `../` compose folder of the locked library agent `kind:name` whose library copy
2633
- * changed since the lock, or `undefined` (project scope only). `install --locked` cannot
2634
- * restore such an agent; `update` moves the lock to the library's copy.
2635
- */
2636
- private lockedComposeDrift;
2637
- /**
2638
- * The agent instances whose `ref` binds to no agent and that the install about to run does not
2639
- * deploy (`entries`), worded as `renderAgentInstances` words them (`errors`, and the resolver's
2640
- * own text in `details` for `--verbose`). The install cannot fix them, and its instance render
2641
- * after the deploy would end the run `Failed` having rewritten files. A ref the `entries` hold
2642
- * binds once they are deployed, so it is no cause.
2643
- */
2644
- private unboundInstanceErrors;
2645
- /**
2646
- * Why the `agent:` ref of agent instance `id` binds to nothing, as the phrase that follows
2647
- * the ref in a {@link LockGap}; see {@link AssetManager.unboundAgentAdvice}.
2648
- */
2649
- private unboundAgentReason;
2650
- /**
2651
- * What is wrong with an `agent:` ref bound by an agent instance and what to do (`lead`, then
2652
- * `advice`). `skaile add` is named only when a registered library or source holds the agent
2653
- * and `add` takes the ref (it needs a publisher); otherwise the user registers the library
2654
- * that holds it, writes the publisher, or drops the binding.
2655
- */
2656
- private unboundAgentAdvice;
2657
- /**
2658
- * Whether the library a locked agent names is here and holds the agent, or the agent comes
2659
- * from a source or store: `install --locked` restores it, so its missing cache is no fault of
2660
- * the library.
2661
- */
2662
- private lockedAgentLibraryHolds;
2663
- /** @deprecated Use `(await projectState()).gaps`; removed in the next major. */
2664
- lockGaps(): Promise<LockGap[]>;
2665
- /**
2666
- * The {@link ProjectState} gaps that name `ref`: as the gap's own ref, or as the asset
2667
- * whose requirement is unmet. A ref without a publisher matches any publisher.
2668
- *
2669
- * @param ref - Asset ref in `kind:name` or `kind:@publisher/name` form.
2670
- */
2671
- gapsOf(ref: string): Promise<LockGap[]>;
2672
- /**
2673
- * The {@link ProjectState} gaps of everything `ref` requires, transitively: what `check`
2674
- * says about the requirements of `ref`, so a command that answers for one asset (`diff`)
2675
- * does not call it fine while a requirement of it is broken. The requirements are read from
2676
- * the deployed copies (the lock records no edges), the way `remove` and `install` read them
2677
- * when no library holds the asset any more. The gaps of `ref` itself are not included
2678
- * ({@link gapsOf}).
2679
- *
2680
- * @param ref - Asset ref in `kind:name` or `kind:@publisher/name` form.
2681
- */
2682
- requirementGapsOf(ref: string): Promise<LockGap[]>;
2683
- /**
2684
- * Locked library assets whose library cannot supply them: the library is not registered
2685
- * (renamed or removed) or no longer holds the asset. Another library holding it makes the
2686
- * gap fixable by `skaile install` (it re-locks); otherwise the user registers the library
2687
- * again or drops the dependency.
2688
- *
2689
- * @param named - `kind:name` identities already reported; they are skipped.
2690
- */
2691
- private libraryOriginGaps;
2692
- /**
2693
- * The locked source assets whose source is no longer in `skaile.yaml` `sources:` (`source
2694
- * remove`, a hand edit), keyed by lock key. ONE sentence for it: `check`, `doctor`, `outdated`,
2695
- * `install`, `install --locked` and `update` all say it (p1062), and none re-clones the source.
2696
- * A GitHub lock entry that no source declares counts as store-supplied only when a store
2697
- * lists the ref (OQ3): a configured store alone proves nothing, as it may never have held
2698
- * the asset. `check`, `doctor` and `outdated` read the store's cached catalog and never touch
2699
- * the network; `install` and `update` (`online`) ask the store itself.
2700
- *
2701
- * @param inScope - Only these lock keys count (`install` prunes an undeclared entry as usual).
2702
- * @param online - Ask the stores when the cached catalog does not list the ref.
2703
- */
2704
- private orphanedSourceGaps;
2705
- /**
2706
- * `true` when one of `stores` lists `ref` (a canonical lock key): its cached catalog holds it
2707
- * or, with `online`, the store answers for it. An injected store fetcher is the store client
2708
- * itself, so it is asked either way. A store an online install cannot ask (unreachable,
2709
- * air-gapped, `--no-catalog`) may hold the ref; `check` never asks, so a store lists only what
2710
- * its cached catalog holds.
2711
- */
2712
- private storeListsRef;
2713
- /**
2714
- * Locked source assets whose source cannot supply them any more: the source is no longer in
2715
- * `skaile.yaml` `sources:` (`source remove`, a hand edit), or it is there but now publishes
2716
- * the asset under another publisher (`source add <url> --publisher`). `skaile install` has
2717
- * nothing to restore them from, so the fix is manual. A source of a store-resolved lock entry
2718
- * is not told apart from one, so no source is called missing while a `stores:` entry exists.
2719
- *
2720
- * @param named - `kind:name` identities already reported; they are skipped.
2721
- * @param index - What the registered sources publish today.
2722
- */
2723
- private sourceOriginGaps;
2724
- /**
2725
- * The locked assets that come from the source `url` (a `sources:` entry): canonical refs,
2726
- * `kind:@publisher/name`. `skaile source remove` refuses while this list is not empty.
2727
- */
2728
- lockedFromSource(url: string): string[];
2729
- /**
2730
- * Record, on every library-origin entry of `lock` that is copied into a harness folder, the
2731
- * files of the deployed copy and their sha256 (`LockEntry.copied`), so a hand edit is named
2732
- * even after the library moved past the lock (p1641). Call it after the deploy. An entry that
2733
- * is unchanged since `prev` keeps its record, or stays without one: the deployed bytes may
2734
- * carry an edit the deploy did not touch. Project mode only; a `--link` deploy and a patched
2735
- * asset are not recorded.
2736
- */
2737
- private withCopiedFiles;
2738
- /**
2739
- * Record, on every agent entry of `lock` that has none, the files the agent's harness
2740
- * rendering occupies and their sha256. Call it after the deploy, so the bytes hashed are the
2741
- * ones `install` just wrote; {@link lockedCopyDrift} compares later edits with them.
2742
- * Entries that carry a record (kept from an earlier lock) are left as they are.
2743
- *
2744
- * @param keepComposedOf - The lock an `install` read: an agent whose `../` compose folder is
2745
- * not in the cache keeps that lock's `composed:` record. Omitted by `update` and `add`,
2746
- * which copy the library's current bytes.
2747
- */
2748
- private withRenderedAgents;
2749
- /**
2750
- * Make the `rendered:` list of every agent entry say exactly which files belong to it: the
2751
- * asset-named files of its own rendering (hashes kept as recorded) plus the files of the agent
2752
- * instances whose `ref` names it (`.claude/agents/default.md`, …) with their current sha256,
2753
- * so a hand edit of an instance file is drift like one of the asset-named file. A path that is
2754
- * neither is dropped: an instance that left `skaile.yaml`, or was bound to another agent, no
2755
- * longer lists its file under the old entry. A file that is another entry's own rendering
2756
- * stays with that entry; an instance whose `ref` names no locked agent (a path ref) has no
2757
- * entry to hold its files. Call it after `renderAgentInstances`, which rewrites every
2758
- * instance file, so the bytes hashed are the ones just written.
2759
- */
2760
- private withInstanceRenderings;
2761
- /** Append the regular files under `path` (a file or a directory) to `out`, project-relative with sha256. Symlinks are skipped. */
2762
- private hashTree;
2763
- /** The files of one agent's rendering for the active harness, project-relative, with sha256. */
2764
- private renderedAgentFiles;
2765
- /**
2766
- * The lock key of the agent entry an agent instance's `ref` names, or `undefined` when no locked
2767
- * agent matches (a path ref has no entry).
2768
- */
2769
- private agentKeyOfRef;
2770
- /**
2771
- * The rendered native files of every locked agent that the lock does not list under
2772
- * `rendered:` (a lock an older CLI wrote), as path → sha256 per lock key, taken before a
2773
- * deploy. `check` cannot tell such a file from a stale one, so {@link changedRenderings}
2774
- * compares it afterwards. `agent` holds the asset-named files of an entry with no `rendered:`
2775
- * at all (5.11.0 and older); `instance` the files of agent instances the entry's `rendered:`
2776
- * does not list yet (5.13.0 and older), which the instance render rewrites. Project mode only.
2777
- */
2778
- private unrecordedRenderings;
2779
- /**
2780
- * The notice `check` and `outdated` print for a lock written before it listed the rendered
2781
- * agent files and the files of agent instances: the next `install`, `add` or `update`
2782
- * adds the list and rewrites those files from the render, so a hand edit of one is lost.
2783
- * Empty for a current lock, and in global mode.
2784
- */
2785
- legacyLockNotices(): string[];
2786
- /**
2787
- * What a deploy changed among the files {@link unrecordedRenderings} saw before it. `rewritten`
2788
- * is one row per locked agent whose asset-named files differ now: a render the CLI changed (the
2789
- * 5.12.0 abilities block) otherwise reaches the user as a silent rewrite. `restored` is one row
2790
- * per agent whose instance files differ now: the render replaced them, a hand edit included.
2791
- */
2792
- private changedRenderings;
2793
- /**
2794
- * The {@link RestoredAsset} rows for the drifted copies (see {@link lockedCopyDrift}) a
2795
- * deploy just wrote again: those whose ref is among the `deployed` canonical refs.
2796
- */
2797
- private restoredCopies;
2798
- /**
2799
- * Hand edits in the deployed copy of a library asset whose library moved past the lock (a
2800
- * version bump, or an in-place edit of the same version): {@link restoreLibraryLockEntries}
2801
- * drops such an entry, so {@link lockedCopyDrift} would not see the edit and `update` would
2802
- * replace the file without a word (p1641). `covered` holds the `kind:@publisher/name` of the
2803
- * entries that were compared already. The lock's per-file record (`copied:`) names the edited
2804
- * files; a lock without one (written before it existed) compares the deployed folder with the
2805
- * one library hash and names the files that also differ from the library's new content.
2806
- */
2807
- private changedLibraryCopyEdits;
2808
- /**
2809
- * Locked assets whose deployed copy differs from the bytes the lock covers: a file edited by
2810
- * hand, or a file the asset does not ship. One row per asset, `ref` being `kind:@publisher/name`
2811
- * and `key` its lock key. The one comparison behind the `modified` gap and the `Restored` lines
2812
- * of `install`.
2813
- *
2814
- * - A library-origin asset is compared with its library's files, but only while those equal the
2815
- * locked hash (changed library content is the `content` gap's business), both modified and
2816
- * extra files.
2817
- * - A source asset is compared with the per-file hashes the lock records (modified files only:
2818
- * the lock lists what the source covers, not what the deploy copies).
2819
- *
2820
- * A `--link` deploy, an asset with a configured patch, and a copy that is missing are not
2821
- * compared: other gaps cover them. An agent (rendered, not copied) is compared with the
2822
- * hashes of its rendered files the lock records (`LockEntry.rendered`); its `modified` paths
2823
- * are project-relative. Project mode only.
2824
- */
2825
- private lockedCopyDrift;
2826
- /**
2827
- * Locked assets (declared or required by one) whose deployed copy is gone: `skaile install`
2828
- * restores them. Same deployability rule as {@link AssetManager.listDeclared}'s `drift`.
2829
- *
2830
- * @param named - `kind:name` identities already reported; they are skipped.
2831
- */
2832
- private undeployedLockGaps;
2833
- /**
2834
- * {@link declaredNoHolderReason} plus, when the name exists under another kind, the same
2835
- * `It is a skill: skill:@pub/name.` tail `add` and `update` end their not-found line with.
2836
- */
2837
- private declaredNoHolderLine;
2838
- /**
2839
- * The `skaile.yaml` side of {@link AssetManager.projectState}: declared refs that do not
2840
- * parse, never resolved into the lock, are not materialized, or contradict a `#pin`.
2841
- * A project with no (or an unreadable) `skaile.yaml` has no declared set to reconcile.
2842
- *
2843
- * @param requirements - What {@link AssetManager.doctor} found; a declared preset whose
2844
- * items it already named needs no second line.
2845
- * @param named - `kind:name` identities already reported; a declared asset among them
2846
- * needs no `drift` line.
2847
- */
2848
- private declaredGaps;
2849
- /** Whether the lock's `presets` slice records `want` (kind, name and, when both carry one, publisher). */
2850
- private presetRecorded;
2851
- /**
2852
- * The first requirement, direct or transitive, of the declared `ref` that no local source or
2853
- * library holds and that nothing in the project already provides — the case `install` ends
2854
- * with `Missing: … nothing was installed`. `undefined` when every requirement is held, when a
2855
- * store is declared (it may hold the requirement and a check never goes to the network), or
2856
- * when `ref` itself resolves to nothing.
2857
- */
2858
- private unmetRequirementOf;
2859
- /**
2860
- * Whether `skaile install` can resolve a declared ref: a source or library holds it, or the
2861
- * project declares a store that may. The global catalog is not asked: a check never goes
2862
- * to the network.
2863
- */
2864
- private declaredRefResolvable;
2865
- /**
2866
- * Items of each declared `preset:` dependency that the lock does not cover.
2867
- *
2868
- * A preset is never locked itself; the lock lists only its expanded items, so an
2869
- * item missing from the lock never resolved (or was declared after the last
2870
- * install). Presets are read from the local sources and libraries (nested presets
2871
- * followed); one only a store holds cannot be read without the network and
2872
- * reports no gaps. Without a lock nothing is reported: `list` and `check` already
2873
- * show a never-installed declaration as `declared`.
2874
- *
2875
- * @param declared - The `dependencies:` refs as written in `skaile.yaml`.
2876
- * @param lock - The current lock, or `null` when none exists.
2877
- * @returns Declared preset ref → its uncovered items; `resolvable` is `true` when a
2878
- * local source or library offers the item (so `skaile install` can fix it).
2879
- * Presets without gaps are absent.
2880
- */
2881
- private declaredPresetGaps;
2882
- /**
2883
- * Create a minimal asset scaffold directory (delegates to {@link createScaffold}).
2884
- *
2885
- * @param name - Asset name (also used as the directory name).
2886
- * @param kind - Asset kind: `skill` | `agent` | `preset` | `flow` | `prompt` | `contract`.
2887
- * @param destDir - Parent directory to create the asset in.
2888
- * @param opts - Optional scaffold content (`description`).
2889
- * @returns `{ ok: true, path }` on success, `{ ok: false, path: errorMessage }` if the
2890
- * directory already exists or `kind` has no scaffold template.
2891
- */
2892
- create(name: string, kind: string, destDir: string, opts?: ScaffoldOptions): {
2893
- ok: boolean;
2894
- path: string;
2895
- };
2896
- /**
2897
- * Return recent asset action history entries, newest first.
2898
- *
2899
- * @param limit - Maximum number of entries to return. Defaults to `20`.
2900
- * @returns Array of {@link HistoryEntry} objects in reverse-chronological order.
2901
- */
2902
- history(limit?: number): HistoryEntry[];
2903
- /**
2904
- * Erase all asset action history for this workspace.
2905
- */
2906
- clearHistory(): void;
2907
- /**
2908
- * Remove deployed assets tracked by the lock file and report unmanaged ones.
2909
- *
2910
- * With `opts.all`, also deletes `.skaile/history.yaml`, `.skaile/patches/`,
2911
- * `.skaile/cache/sources/`, and `skaile.lock.yaml` — effectively resetting the
2912
- * workspace to a pre-install state.
2913
- *
2914
- * @param opts - Optional cleanup options.
2915
- * @param opts.all - When `true`, remove all Skaile-managed state in addition to deployed assets.
2916
- * @returns Object with `removed` (successfully cleaned refs), `skipped` (with reasons),
2917
- * and `unmanaged` (deployed assets not in the lock file).
2918
- */
2919
- clean(opts?: {
2920
- all?: boolean;
2921
- }): {
2922
- removed: string[];
2923
- skipped: Array<{
2924
- ref: string;
2925
- reason: string;
2926
- }>;
2927
- unmanaged: string[];
2928
- };
2929
- /**
2930
- * `clean --global`: remove the copy of every asset the global lock tracks from each global
2931
- * harness (and the old `~/.omp/<dir>` copy), keeping `~/.skaile/skaile.yaml`. With `all`, the
2932
- * global lock goes too.
2933
- */
2934
- private cleanGlobal;
2935
- /**
2936
- * Remove the deployed dir of every asset tracked by the lock; missing dirs
2937
- * still count as removed. Returns the list of cleaned refs.
2938
- */
2939
- private cleanLockedDeployedAssets;
2940
- /**
2941
- * Report deployed assets not tracked by the lock file. Deployed assets are
2942
- * keyed by <kind>:<name>; lock canonical refs are mapped to that shape.
2943
- */
2944
- private collectUnmanagedAssets;
2945
- /** Delete all Skaile-managed state: history file, patches/, cache/sources/, lock. */
2946
- private removeAllManagedState;
2947
- /**
2948
- * Add a dependency ref to the manifest `dependencies:` if not already present.
2949
- * Project mode edits `<projectDir>/skaile.yaml`; global mode edits the
2950
- * user-scope SSOT `~/.skaile/skaile.yaml`, **bootstrapping** the file (and its
2951
- * parent dir) when absent so `skaile add --global` works on a fresh machine.
2952
- */
2953
- private addDependencyToConfig;
2954
- /**
2955
- * Whether the declared `dep` names the same asset (kind, publisher, name) as
2956
- * `ref`, ignoring the version pin. A publisher must agree on both sides —
2957
- * unlike {@link removeDependencyFromConfig}, a bare `kind:name` never replaces a
2958
- * publisher-qualified line. Unparseable entries only match on string equality.
2959
- */
2960
- private sameDeclaredAsset;
2961
- /**
2962
- * Remove a dependency ref from the manifest `dependencies:`. Targets the same
2963
- * file as {@link addDependencyToConfig} (`~/.skaile/skaile.yaml` in global mode).
2964
- *
2965
- * @returns `true` when a declaration was removed.
2966
- */
2967
- private removeDependencyFromConfig;
2968
- /**
2969
- * Whether `target` is an agent that an agent instance of `skaile.yaml` binds and no
2970
- * `dependencies:` line names. Project mode only.
2971
- */
2972
- private boundOnlyByInstance;
2973
- /**
2974
- * The locked agents an agent instance binds (`agents.<id>.ref`, `agent.definition`) that
2975
- * `declared` does not name, as version-less `agent:@publisher/name`. An agent no lock entry
2976
- * holds is left out: `install` does not add what the user never added (`skaile add` does).
2977
- */
2978
- private lockedAgentBindings;
2979
- /**
2980
- * Bind the agent `skaile add agent:<ref>` just added as an instance `agents.<name>:
2981
- * {ref: agent:@publisher/name}` of `skaile.yaml`, so `run --instance <name>` and the repl
2982
- * banner hint work at once. An agent that an instance or `agent:` already binds, or an id
2983
- * `agents:` already holds, is left as it is. Project mode only.
2984
- *
2985
- * @returns the instance id and ref bound; the id with `keptRef` (what that id binds instead)
2986
- * when the id is taken by another agent; `undefined` when nothing was bound and nothing needs saying.
2987
- */
2988
- private bindAgentInstance;
2989
- /** The refs `skaile.yaml` binds agent instances to: every `agents.<id>.ref` and `agent.definition`. Project mode only. */
2990
- private declaredAgentInstanceRefs;
2991
- /**
2992
- * Drop the agent instances of `skaile.yaml` (`agents.<id>`, or the `agent.definition`
2993
- * default) whose `ref` binds to `target`, and the native agent files an install rendered for
2994
- * them. Only an `agent` target has bindings; project mode only. A `ref` without a publisher
2995
- * matches any publisher, and a pin is ignored.
2996
- *
2997
- * @returns `true` when a binding was removed.
2998
- */
2999
- private removeAgentBindings;
3000
- private resolveRepoDir;
60
+ export declare class AssetManager extends AmAdd {
3001
61
  }
62
+ export type { HistoryEntry } from "./history.js";
63
+ export { appendHistory, clearHistory, getRecentHistory, loadHistory, } from "./history.js";
64
+ export type { DeployOptions, ScaffoldOptions } from "./installer.js";
65
+ export type { DeployableEntry } from "./installer.js";
66
+ export { createScaffold, deployAll, installTargetOf, removeAsset, SCAFFOLD_KINDS, } from "./installer.js";
67
+ export type { RenderMcpConfigOptions, RenderMcpConfigResult, SkippedMcpServer, } from "./mcp-config.js";
68
+ export { mcpNotRunnableReason, renderMcpServerConfig } from "./mcp-config.js";
69
+ export type { Log } from "./renderers.js";
70
+ export { renderAgentToFramework } from "./renderers.js";
71
+ export { FACTORY_SOURCE_URL };
3002
72
  export { installAgent } from "./install-agent.js";
3003
73
  export { type HarnessSwitchState, harnessSwitchKeptKey, harnessSwitchStateFile, readHarnessSwitchState, writeHarnessSwitchState, } from "./harness-switch-state.js";
3004
74
  export type { InstalledAgentInstance, InstallAgentInstancesOptions, InstallAgentInstancesResult, } from "./install-instances.js";