@skaile/workspaces 6.6.0 → 6.7.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 (358) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/ai-sdk.js +10 -17
  3. package/dist/ai-sdk.js.map +1 -1
  4. package/dist/app-sdk/index.js +1 -1
  5. package/dist/{asset-feeds-WQ6YQPHV.js → asset-feeds-4A7PJ4OB.js} +18 -18
  6. package/dist/{asset-feeds-WQ6YQPHV.js.map → asset-feeds-4A7PJ4OB.js.map} +1 -1
  7. package/dist/asset-manager/catalog-deployer.js +4 -4
  8. package/dist/asset-manager/index.js +10 -10
  9. package/dist/asset-manager/installer.js +6 -6
  10. package/dist/asset-manager/renderers.js +5 -5
  11. package/dist/asset-manager/src/index.d.ts +89 -15
  12. package/dist/asset-manager/src/index.d.ts.map +1 -1
  13. package/dist/asset-manager/src/install-agent.d.ts +22 -1
  14. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  15. package/dist/asset-manager/src/install-instances.d.ts +30 -1
  16. package/dist/asset-manager/src/install-instances.d.ts.map +1 -1
  17. package/dist/asset-manager/src/installer.d.ts +12 -0
  18. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  19. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  20. package/dist/bridge/harnesses/claude-sdk.js +21 -15
  21. package/dist/bridge/harnesses/claude-sdk.js.map +1 -1
  22. package/dist/bridge/harnesses/codex.js +9 -8
  23. package/dist/bridge/harnesses/codex.js.map +1 -1
  24. package/dist/bridge/harnesses/continue.js +11 -9
  25. package/dist/bridge/harnesses/continue.js.map +1 -1
  26. package/dist/bridge/harnesses/echo.js +5 -4
  27. package/dist/bridge/harnesses/echo.js.map +1 -1
  28. package/dist/bridge/harnesses/gemini.js +8 -6
  29. package/dist/bridge/harnesses/goose.js +11 -9
  30. package/dist/bridge/harnesses/goose.js.map +1 -1
  31. package/dist/bridge/harnesses/omp.js +9 -7
  32. package/dist/bridge/harnesses/omp.js.map +1 -1
  33. package/dist/bridge/harnesses/opencode.js +11 -9
  34. package/dist/bridge/harnesses/opencode.js.map +1 -1
  35. package/dist/bridge/harnesses/qwen.js +9 -7
  36. package/dist/bridge/harnesses/qwen.js.map +1 -1
  37. package/dist/bridge/index.js +17 -15
  38. package/dist/bridge/src/ai-sdk.d.ts.map +1 -1
  39. package/dist/bridge/src/claude-sdk-surface.d.ts +2 -1
  40. package/dist/bridge/src/claude-sdk-surface.d.ts.map +1 -1
  41. package/dist/bridge/src/harness-binaries.d.ts +21 -0
  42. package/dist/bridge/src/harness-binaries.d.ts.map +1 -0
  43. package/dist/bridge/src/harness-model-check.d.ts +22 -6
  44. package/dist/bridge/src/harness-model-check.d.ts.map +1 -1
  45. package/dist/bridge/src/harnesses/claude-sdk.d.ts.map +1 -1
  46. package/dist/bridge/src/harnesses/continue.d.ts.map +1 -1
  47. package/dist/bridge/src/harnesses/gemini.d.ts.map +1 -1
  48. package/dist/bridge/src/harnesses/goose.d.ts.map +1 -1
  49. package/dist/bridge/src/harnesses/omp-models-yml.d.ts.map +1 -1
  50. package/dist/bridge/src/harnesses/omp.d.ts.map +1 -1
  51. package/dist/bridge/src/harnesses/opencode.d.ts.map +1 -1
  52. package/dist/bridge/src/harnesses/qwen.d.ts.map +1 -1
  53. package/dist/bridge/src/index.d.ts +2 -1
  54. package/dist/bridge/src/index.d.ts.map +1 -1
  55. package/dist/{chunk-LBJ4M5J2.js → chunk-237BMOZW.js} +4 -4
  56. package/dist/{chunk-LBJ4M5J2.js.map → chunk-237BMOZW.js.map} +1 -1
  57. package/dist/{chunk-2TLPC6TQ.js → chunk-37AYPPOO.js} +41 -19
  58. package/dist/chunk-37AYPPOO.js.map +1 -0
  59. package/dist/{chunk-GTGWRKMJ.js → chunk-37X4A6VZ.js} +6 -6
  60. package/dist/{chunk-GTGWRKMJ.js.map → chunk-37X4A6VZ.js.map} +1 -1
  61. package/dist/{chunk-MXI3XWV6.js → chunk-3HSLJAMJ.js} +4 -4
  62. package/dist/{chunk-MXI3XWV6.js.map → chunk-3HSLJAMJ.js.map} +1 -1
  63. package/dist/{chunk-RHCEX2EV.js → chunk-3W6XZQ2Y.js} +3 -3
  64. package/dist/{chunk-RHCEX2EV.js.map → chunk-3W6XZQ2Y.js.map} +1 -1
  65. package/dist/{chunk-F4CZQD3T.js → chunk-4C2E5QUP.js} +4 -3
  66. package/dist/chunk-4C2E5QUP.js.map +1 -0
  67. package/dist/{chunk-DS6UUCFG.js → chunk-4CD2R4MJ.js} +5 -4
  68. package/dist/chunk-4CD2R4MJ.js.map +1 -0
  69. package/dist/{chunk-AQNW2FET.js → chunk-6RPS7JEH.js} +92 -39
  70. package/dist/chunk-6RPS7JEH.js.map +1 -0
  71. package/dist/{chunk-BSMW3PX2.js → chunk-6UP2EDFN.js} +4 -313
  72. package/dist/chunk-6UP2EDFN.js.map +1 -0
  73. package/dist/{chunk-4J7JQX4G.js → chunk-72TLO2AG.js} +4 -4
  74. package/dist/{chunk-4J7JQX4G.js.map → chunk-72TLO2AG.js.map} +1 -1
  75. package/dist/{chunk-I5IF3JCG.js → chunk-AO57IFME.js} +3 -3
  76. package/dist/{chunk-I5IF3JCG.js.map → chunk-AO57IFME.js.map} +1 -1
  77. package/dist/{chunk-G5SYFFMD.js → chunk-ASBZOTEO.js} +2 -2
  78. package/dist/{chunk-G5SYFFMD.js.map → chunk-ASBZOTEO.js.map} +1 -1
  79. package/dist/{chunk-O7QZI6MQ.js → chunk-BB5EJLKZ.js} +2 -2
  80. package/dist/{chunk-O7QZI6MQ.js.map → chunk-BB5EJLKZ.js.map} +1 -1
  81. package/dist/{chunk-N2PBAXAA.js → chunk-BKLDBUQA.js} +3 -3
  82. package/dist/{chunk-N2PBAXAA.js.map → chunk-BKLDBUQA.js.map} +1 -1
  83. package/dist/{chunk-XD3RYAMR.js → chunk-CTRTFMCX.js} +6 -6
  84. package/dist/{chunk-XD3RYAMR.js.map → chunk-CTRTFMCX.js.map} +1 -1
  85. package/dist/{chunk-EPXZQIC6.js → chunk-DFP476EU.js} +8 -4
  86. package/dist/chunk-DFP476EU.js.map +1 -0
  87. package/dist/{chunk-MMOWIRHP.js → chunk-G44FFUMA.js} +12 -10
  88. package/dist/chunk-G44FFUMA.js.map +1 -0
  89. package/dist/{chunk-JIQUF3X2.js → chunk-G7NMF5WQ.js} +3 -3
  90. package/dist/{chunk-JIQUF3X2.js.map → chunk-G7NMF5WQ.js.map} +1 -1
  91. package/dist/{chunk-SHTXMERQ.js → chunk-GAIMSCZ7.js} +10 -8
  92. package/dist/chunk-GAIMSCZ7.js.map +1 -0
  93. package/dist/{chunk-6A6HE5LW.js → chunk-HLAEYFUN.js} +3 -3
  94. package/dist/{chunk-6A6HE5LW.js.map → chunk-HLAEYFUN.js.map} +1 -1
  95. package/dist/{chunk-YN6N3RBM.js → chunk-HMVAGPYR.js} +47 -11
  96. package/dist/chunk-HMVAGPYR.js.map +1 -0
  97. package/dist/{chunk-U3UDOX6I.js → chunk-HPXONAI2.js} +6 -4
  98. package/dist/chunk-HPXONAI2.js.map +1 -0
  99. package/dist/{chunk-5ETYBC2X.js → chunk-IRK3LNG3.js} +6 -6
  100. package/dist/{chunk-5ETYBC2X.js.map → chunk-IRK3LNG3.js.map} +1 -1
  101. package/dist/{chunk-J262X4JU.js → chunk-J7VEQORJ.js} +69 -16
  102. package/dist/chunk-J7VEQORJ.js.map +1 -0
  103. package/dist/{chunk-DI6J2PJB.js → chunk-KO3VSZQP.js} +47 -18
  104. package/dist/chunk-KO3VSZQP.js.map +1 -0
  105. package/dist/{chunk-KSH5CFQS.js → chunk-KORDNXKA.js} +3 -3
  106. package/dist/{chunk-KSH5CFQS.js.map → chunk-KORDNXKA.js.map} +1 -1
  107. package/dist/{chunk-SCRYXAHH.js → chunk-L3JQJ6D5.js} +6 -6
  108. package/dist/{chunk-SCRYXAHH.js.map → chunk-L3JQJ6D5.js.map} +1 -1
  109. package/dist/{chunk-7I5PNB2G.js → chunk-L7QOZG5V.js} +3 -3
  110. package/dist/{chunk-7I5PNB2G.js.map → chunk-L7QOZG5V.js.map} +1 -1
  111. package/dist/{chunk-VXYZ5M7Z.js → chunk-LX4TTTRR.js} +64 -27
  112. package/dist/chunk-LX4TTTRR.js.map +1 -0
  113. package/dist/{chunk-KSUT5KAE.js → chunk-LZPJOF7Y.js} +3 -3
  114. package/dist/{chunk-KSUT5KAE.js.map → chunk-LZPJOF7Y.js.map} +1 -1
  115. package/dist/{chunk-65UAC3ZR.js → chunk-N6ZGB5ES.js} +4 -3
  116. package/dist/chunk-N6ZGB5ES.js.map +1 -0
  117. package/dist/{chunk-2M3VLKT2.js → chunk-NURTGAWM.js} +3 -3
  118. package/dist/{chunk-2M3VLKT2.js.map → chunk-NURTGAWM.js.map} +1 -1
  119. package/dist/{chunk-J4WKNJHO.js → chunk-O5Y7VMVQ.js} +15 -14
  120. package/dist/chunk-O5Y7VMVQ.js.map +1 -0
  121. package/dist/{chunk-6SXSVKQY.js → chunk-O7ADRMCR.js} +63 -14
  122. package/dist/chunk-O7ADRMCR.js.map +1 -0
  123. package/dist/{chunk-7PVGND4J.js → chunk-OGTQUEAO.js} +21 -14
  124. package/dist/chunk-OGTQUEAO.js.map +1 -0
  125. package/dist/{chunk-VJRL6ZK6.js → chunk-OSABUEWA.js} +3 -3
  126. package/dist/{chunk-VJRL6ZK6.js.map → chunk-OSABUEWA.js.map} +1 -1
  127. package/dist/{chunk-WW5NAU6N.js → chunk-PLLZSKOO.js} +3 -3
  128. package/dist/{chunk-WW5NAU6N.js.map → chunk-PLLZSKOO.js.map} +1 -1
  129. package/dist/{chunk-7SJHSGUV.js → chunk-Q2NYTMT6.js} +16 -15
  130. package/dist/chunk-Q2NYTMT6.js.map +1 -0
  131. package/dist/{chunk-E2EC6SAX.js → chunk-QC5BYUED.js} +51 -15
  132. package/dist/chunk-QC5BYUED.js.map +1 -0
  133. package/dist/{chunk-RAU5QPI6.js → chunk-QCR5AE5E.js} +5 -5
  134. package/dist/{chunk-RAU5QPI6.js.map → chunk-QCR5AE5E.js.map} +1 -1
  135. package/dist/{chunk-TUFNY6OD.js → chunk-QW5B3TEO.js} +10 -4
  136. package/dist/chunk-QW5B3TEO.js.map +1 -0
  137. package/dist/{chunk-Z4FERR4U.js → chunk-RAHAZ7LP.js} +2 -2
  138. package/dist/{chunk-Z4FERR4U.js.map → chunk-RAHAZ7LP.js.map} +1 -1
  139. package/dist/{chunk-OY22B7E2.js → chunk-SBNUXJ6E.js} +3 -3
  140. package/dist/{chunk-OY22B7E2.js.map → chunk-SBNUXJ6E.js.map} +1 -1
  141. package/dist/{chunk-6ARPZHOV.js → chunk-TMJBEGS4.js} +35 -6
  142. package/dist/chunk-TMJBEGS4.js.map +1 -0
  143. package/dist/{chunk-6RHWTZPT.js → chunk-TXX3OUYI.js} +3 -3
  144. package/dist/{chunk-6RHWTZPT.js.map → chunk-TXX3OUYI.js.map} +1 -1
  145. package/dist/{chunk-SZKCE7EC.js → chunk-U52FYGK5.js} +5 -5
  146. package/dist/{chunk-SZKCE7EC.js.map → chunk-U52FYGK5.js.map} +1 -1
  147. package/dist/{chunk-TCH5UDKT.js → chunk-UCB7FK25.js} +10 -8
  148. package/dist/chunk-UCB7FK25.js.map +1 -0
  149. package/dist/{chunk-5XHQBCB5.js → chunk-WFK4MUBL.js} +21 -7
  150. package/dist/chunk-WFK4MUBL.js.map +1 -0
  151. package/dist/{chunk-HGZN6JLP.js → chunk-WIYVR24B.js} +4 -4
  152. package/dist/{chunk-HGZN6JLP.js.map → chunk-WIYVR24B.js.map} +1 -1
  153. package/dist/{chunk-B6N653ZG.js → chunk-WKENHNDM.js} +6 -6
  154. package/dist/{chunk-B6N653ZG.js.map → chunk-WKENHNDM.js.map} +1 -1
  155. package/dist/chunk-WWSRIT3J.js +59 -0
  156. package/dist/chunk-WWSRIT3J.js.map +1 -0
  157. package/dist/chunk-XON6ODIC.js +315 -0
  158. package/dist/chunk-XON6ODIC.js.map +1 -0
  159. package/dist/{chunk-4BFEPZ6J.js → chunk-ZBA4P5TD.js} +3 -3
  160. package/dist/{chunk-4BFEPZ6J.js.map → chunk-ZBA4P5TD.js.map} +1 -1
  161. package/dist/{chunk-JRVQV7WC.js → chunk-ZDTDS62B.js} +595 -126
  162. package/dist/chunk-ZDTDS62B.js.map +1 -0
  163. package/dist/{chunk-XYCYGN3Q.js → chunk-ZM4SDVUV.js} +79 -20
  164. package/dist/chunk-ZM4SDVUV.js.map +1 -0
  165. package/dist/{claude-code-LZH7Y4Y5.js → claude-code-BLFRZU2X.js} +4 -4
  166. package/dist/{claude-code-LZH7Y4Y5.js.map → claude-code-BLFRZU2X.js.map} +1 -1
  167. package/dist/cli/index.js +474 -198
  168. package/dist/cli/index.js.map +1 -1
  169. package/dist/cli/src/agent-pins.d.ts +9 -3
  170. package/dist/cli/src/agent-pins.d.ts.map +1 -1
  171. package/dist/cli/src/commands/asset-cmd.d.ts +1 -1
  172. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  173. package/dist/cli/src/commands/cache.d.ts.map +1 -1
  174. package/dist/cli/src/commands/catalog.d.ts +2 -0
  175. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  176. package/dist/cli/src/commands/config.d.ts.map +1 -1
  177. package/dist/cli/src/commands/harness-preflight.d.ts +38 -0
  178. package/dist/cli/src/commands/harness-preflight.d.ts.map +1 -0
  179. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  180. package/dist/cli/src/commands/library-index.d.ts +16 -0
  181. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  182. package/dist/cli/src/commands/migrate-assets.d.ts +5 -0
  183. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  184. package/dist/cli/src/commands/migrate-harness.d.ts +15 -7
  185. package/dist/cli/src/commands/migrate-harness.d.ts.map +1 -1
  186. package/dist/cli/src/commands/migrate.d.ts.map +1 -1
  187. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  188. package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
  189. package/dist/cli/src/commands/project.d.ts +14 -0
  190. package/dist/cli/src/commands/project.d.ts.map +1 -1
  191. package/dist/cli/src/commands/run.d.ts.map +1 -1
  192. package/dist/cli/src/commands/serve-preflight.d.ts +6 -5
  193. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
  194. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  195. package/dist/cli/src/commands/session.d.ts.map +1 -1
  196. package/dist/cli/src/commands/source.d.ts +11 -0
  197. package/dist/cli/src/commands/source.d.ts.map +1 -1
  198. package/dist/cli/src/commands/update.d.ts.map +1 -1
  199. package/dist/cli/src/commands/validate-instances.d.ts +6 -0
  200. package/dist/cli/src/commands/validate-instances.d.ts.map +1 -1
  201. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  202. package/dist/cli/src/commands/why.d.ts.map +1 -1
  203. package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -1
  204. package/dist/cli/src/session-hint.d.ts +7 -0
  205. package/dist/cli/src/session-hint.d.ts.map +1 -0
  206. package/dist/connectors/config.js +3 -3
  207. package/dist/connectors/index.js +21 -19
  208. package/dist/connectors/src/managed-gitconfig.d.ts +6 -4
  209. package/dist/connectors/src/managed-gitconfig.d.ts.map +1 -1
  210. package/dist/{connectors-HU5MHSUJ.js → connectors-OJJU4LSN.js} +24 -22
  211. package/dist/{connectors-HU5MHSUJ.js.map → connectors-OJJU4LSN.js.map} +1 -1
  212. package/dist/connectors-shared/index.js +2 -2
  213. package/dist/core/index.js +4 -4
  214. package/dist/core/publish-manifest.js +1 -1
  215. package/dist/core/runtime-assets.js +3 -3
  216. package/dist/core/src/agent-instances.d.ts +11 -0
  217. package/dist/core/src/agent-instances.d.ts.map +1 -1
  218. package/dist/core/src/index.d.ts +3 -2
  219. package/dist/core/src/index.d.ts.map +1 -1
  220. package/dist/core/src/publish-manifest.d.ts +20 -6
  221. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  222. package/dist/core/src/repo-manager.d.ts +9 -0
  223. package/dist/core/src/repo-manager.d.ts.map +1 -1
  224. package/dist/core/src/run-state-ignore.d.ts +17 -0
  225. package/dist/core/src/run-state-ignore.d.ts.map +1 -0
  226. package/dist/core/src/workspace-config.d.ts.map +1 -1
  227. package/dist/core/workspace-config.js +2 -2
  228. package/dist/deploy/index.js +4 -4
  229. package/dist/discovery/index.js +2 -2
  230. package/dist/discovery/src/builtin-providers.d.ts.map +1 -1
  231. package/dist/discovery/src/discover-manifest.d.ts.map +1 -1
  232. package/dist/discovery/src/tree-entries.d.ts.map +1 -1
  233. package/dist/{ensure-sources-CAMWJTMR.js → ensure-sources-F6VQDCWY.js} +26 -24
  234. package/dist/ensure-sources-F6VQDCWY.js.map +1 -0
  235. package/dist/factory-assets/connectors/box.js +21 -19
  236. package/dist/factory-assets/connectors/deploy.js +21 -19
  237. package/dist/factory-assets/connectors/devserver.js +21 -19
  238. package/dist/factory-assets/connectors/flow/adapter.js +21 -19
  239. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts +2 -0
  240. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts.map +1 -1
  241. package/dist/factory-assets/connectors/flow/engine.js +5 -5
  242. package/dist/factory-assets/connectors/flow/run-flow.js +22 -20
  243. package/dist/factory-assets/connectors/flow.js +21 -19
  244. package/dist/factory-assets/connectors/git/CONNECTOR.md +4 -1
  245. package/dist/factory-assets/connectors/git/exec.d.ts.map +1 -1
  246. package/dist/factory-assets/connectors/git.js +21 -19
  247. package/dist/factory-assets/connectors/gmail.js +21 -19
  248. package/dist/factory-assets/connectors/googledrive.js +21 -19
  249. package/dist/factory-assets/connectors/local.js +21 -19
  250. package/dist/factory-assets/connectors/mattermost.js +21 -19
  251. package/dist/factory-assets/connectors/memory.js +21 -19
  252. package/dist/factory-assets/connectors/minio.js +21 -19
  253. package/dist/factory-assets/connectors/postgres.js +21 -19
  254. package/dist/factory-assets/connectors/s3.js +21 -19
  255. package/dist/factory-assets/connectors/sharepoint.js +21 -19
  256. package/dist/factory-assets/connectors/sqlite.js +21 -19
  257. package/dist/factory-assets/connectors/static-server.js +21 -19
  258. package/dist/factory-assets/connectors/tunnel.js +21 -19
  259. package/dist/factory-assets/connectors/webdav.js +21 -19
  260. package/dist/factory-assets/connectors/xstate-store.js +21 -19
  261. package/dist/factory-assets/connectors/xstate.js +21 -19
  262. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +14 -1
  263. package/dist/{flows-GVOVQGQW.js → flows-I6ODIPZZ.js} +7 -7
  264. package/dist/{flows-GVOVQGQW.js.map → flows-I6ODIPZZ.js.map} +1 -1
  265. package/dist/{helpers-WMCCODAV.js → helpers-PJNUTZXZ.js} +26 -24
  266. package/dist/{helpers-WMCCODAV.js.map → helpers-PJNUTZXZ.js.map} +1 -1
  267. package/dist/library/index.js +7 -7
  268. package/dist/library/install.js +2 -2
  269. package/dist/library/src/manifest-writer.d.ts +5 -0
  270. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  271. package/dist/{library-publish-UQQMHTND.js → library-publish-FNNDWVBO.js} +47 -45
  272. package/dist/library-publish-FNNDWVBO.js.map +1 -0
  273. package/dist/model-endpoint/index.js +8 -7
  274. package/dist/{open-library-OJ4HT2X4.js → open-library-R5EZROFN.js} +29 -27
  275. package/dist/{open-library-OJ4HT2X4.js.map → open-library-R5EZROFN.js.map} +1 -1
  276. package/dist/{open-registry-LWGIOJDK.js → open-registry-RZW2AFD6.js} +11 -11
  277. package/dist/{open-registry-LWGIOJDK.js.map → open-registry-RZW2AFD6.js.map} +1 -1
  278. package/dist/{paths-FR2752HV.js → paths-RPK5PNZQ.js} +7 -7
  279. package/dist/{paths-FR2752HV.js.map → paths-RPK5PNZQ.js.map} +1 -1
  280. package/dist/{plugin-store-IALJUBN2.js → plugin-store-OJTERUEZ.js} +7 -7
  281. package/dist/{plugin-store-IALJUBN2.js.map → plugin-store-OJTERUEZ.js.map} +1 -1
  282. package/dist/{project-UQFCYHYS.js → project-S2FT3LLR.js} +43 -41
  283. package/dist/{project-UQFCYHYS.js.map → project-S2FT3LLR.js.map} +1 -1
  284. package/dist/resolver/index.js +4 -4
  285. package/dist/runner/index.js +32 -30
  286. package/dist/runner/src/capability-roundtrip.d.ts +6 -6
  287. package/dist/runner/src/capability-roundtrip.d.ts.map +1 -1
  288. package/dist/runner/src/composition/run-snapshot.d.ts +7 -1
  289. package/dist/runner/src/composition/run-snapshot.d.ts.map +1 -1
  290. package/dist/runner/src/serve.d.ts.map +1 -1
  291. package/dist/sdk/asset-manager.js +10 -10
  292. package/dist/sdk/bridge.js +17 -15
  293. package/dist/sdk/core.js +4 -4
  294. package/dist/sdk/flow.js +5 -5
  295. package/dist/sdk/index.js +32 -30
  296. package/dist/sdk/index.js.map +1 -1
  297. package/dist/sdk/resolver.js +4 -4
  298. package/dist/sdk/runner.js +32 -30
  299. package/dist/sdk/session.js +2 -2
  300. package/dist/sdk/transport/ws/server.js +5 -5
  301. package/dist/sdk/transport/ws.js +5 -5
  302. package/dist/sdk/transport.js +5 -5
  303. package/dist/sdk/types.js +1 -1
  304. package/dist/serve-preflight-AADSOUO2.js +58 -0
  305. package/dist/{serve-preflight-TYEKHC32.js.map → serve-preflight-AADSOUO2.js.map} +1 -1
  306. package/dist/session/index.js +2 -2
  307. package/dist/{setup-4JV2IMCB.js → setup-HOAJHUFQ.js} +27 -25
  308. package/dist/setup-HOAJHUFQ.js.map +1 -0
  309. package/dist/{skills-6QTKFMLW.js → skills-KHHW3RZ3.js} +6 -6
  310. package/dist/{skills-6QTKFMLW.js.map → skills-KHHW3RZ3.js.map} +1 -1
  311. package/dist/source-FOELFCY6.js +88 -0
  312. package/dist/{source-XYMMJVKR.js.map → source-FOELFCY6.js.map} +1 -1
  313. package/dist/{source-manifest-publish-SZFGGKB4.js → source-manifest-publish-Q7P5AEVU.js} +44 -42
  314. package/dist/source-manifest-publish-Q7P5AEVU.js.map +1 -0
  315. package/dist/transport/index.js +5 -5
  316. package/dist/transport/ws/server.js +5 -5
  317. package/dist/transport/ws.js +5 -5
  318. package/dist/tui/index.js +56 -37
  319. package/dist/tui/index.js.map +1 -1
  320. package/dist/tui/src/repl.d.ts +10 -0
  321. package/dist/tui/src/repl.d.ts.map +1 -1
  322. package/dist/types/index.js +1 -1
  323. package/dist/types/src/version.d.ts +4 -4
  324. package/dist/workspace-plugin/adapters/mcp.js +24 -22
  325. package/dist/workspace-plugin/adapters/omp.js +14 -14
  326. package/dist/workspace-plugin/index.js +1 -1
  327. package/package.json +1 -1
  328. package/dist/chunk-2TLPC6TQ.js.map +0 -1
  329. package/dist/chunk-5XHQBCB5.js.map +0 -1
  330. package/dist/chunk-65UAC3ZR.js.map +0 -1
  331. package/dist/chunk-6ARPZHOV.js.map +0 -1
  332. package/dist/chunk-6SXSVKQY.js.map +0 -1
  333. package/dist/chunk-7PVGND4J.js.map +0 -1
  334. package/dist/chunk-7SJHSGUV.js.map +0 -1
  335. package/dist/chunk-AQNW2FET.js.map +0 -1
  336. package/dist/chunk-BSMW3PX2.js.map +0 -1
  337. package/dist/chunk-DI6J2PJB.js.map +0 -1
  338. package/dist/chunk-DS6UUCFG.js.map +0 -1
  339. package/dist/chunk-E2EC6SAX.js.map +0 -1
  340. package/dist/chunk-EPXZQIC6.js.map +0 -1
  341. package/dist/chunk-F4CZQD3T.js.map +0 -1
  342. package/dist/chunk-J262X4JU.js.map +0 -1
  343. package/dist/chunk-J4WKNJHO.js.map +0 -1
  344. package/dist/chunk-JRVQV7WC.js.map +0 -1
  345. package/dist/chunk-MMOWIRHP.js.map +0 -1
  346. package/dist/chunk-SHTXMERQ.js.map +0 -1
  347. package/dist/chunk-TCH5UDKT.js.map +0 -1
  348. package/dist/chunk-TUFNY6OD.js.map +0 -1
  349. package/dist/chunk-U3UDOX6I.js.map +0 -1
  350. package/dist/chunk-VXYZ5M7Z.js.map +0 -1
  351. package/dist/chunk-XYCYGN3Q.js.map +0 -1
  352. package/dist/chunk-YN6N3RBM.js.map +0 -1
  353. package/dist/ensure-sources-CAMWJTMR.js.map +0 -1
  354. package/dist/library-publish-UQQMHTND.js.map +0 -1
  355. package/dist/serve-preflight-TYEKHC32.js +0 -56
  356. package/dist/setup-4JV2IMCB.js.map +0 -1
  357. package/dist/source-XYMMJVKR.js +0 -86
  358. package/dist/source-manifest-publish-SZFGGKB4.js.map +0 -1
@@ -1,18 +1,18 @@
1
- import { unregisteredLibraryNames, renamedLibraryName, resolveConfig, RemoteCatalogSource, OfflineError, describeCatalogError, CatalogHttpError, scanUnlistedAssets, missingRootAssets, storeManifestFile, missingLibraryDirMessage, lastLibraryName, filesEntryPaths } from './chunk-MMOWIRHP.js';
2
- import { SEMVER_RE, invalidSemverMessage, flowFileNameError, computeDeterministicHash, readManifestSourceConfig, discoverAssetsInTree, isManifestMode } from './chunk-J4WKNJHO.js';
1
+ import { unregisteredLibraryNames, libraryDirMissing, renamedLibraryName, resolveConfig, RemoteCatalogSource, OfflineError, describeCatalogError, CatalogHttpError, scanUnlistedAssets, missingRootAssets, storeManifestFile, missingLibraryDirMessage, lastLibraryName, filesEntryPaths } from './chunk-G44FFUMA.js';
2
+ import { SEMVER_RE, invalidSemverMessage, flowFileNameError, computeDeterministicHash, readManifestSourceConfig, discoverAssetsInTree, isManifestMode } from './chunk-O5Y7VMVQ.js';
3
3
  import { parseFlowDefinition } from './chunk-JRN5QF4C.js';
4
- import { installTargetOf, readKeptLegacyCopies, writeKeptLegacyCopies, canonicalEntryRef, diffDeployedAgent, deployedAssetDrift, entriesNeedingDeploy, assertNoLibrarySymlinks, deployAll, removeAsset, composedDriftRefs, sourceComposedFiles, cachedComposedFiles, createScaffold, installAgent } from './chunk-DI6J2PJB.js';
4
+ import { installTargetOf, readKeptLegacyCopies, writeKeptLegacyCopies, canonicalEntryRef, diffDeployedAgent, deployedAssetDrift, entriesNeedingDeploy, resetMissingParentWarnings, assertNoLibrarySymlinks, composedDriftRefs, deployAll, removeAsset, sourceComposedFiles, cachedComposedFiles, createScaffold, composedAgentNamesOf, installAgent } from './chunk-KO3VSZQP.js';
5
5
  import { appendHistory, getRecentHistory, clearHistory } from './chunk-KTBKW2FI.js';
6
6
  import { commitChanges } from './chunk-UQ6LFBPZ.js';
7
- import { harnessTargetSupportsAgents, CODEX_IDENTITY_DIR, agentRenderFiles } from './chunk-DS6UUCFG.js';
7
+ import { harnessTargetSupportsAgents, CODEX_IDENTITY_DIR, agentRenderFiles } from './chunk-4CD2R4MJ.js';
8
8
  import { isScaffoldBody, isScaffoldDescription } from './chunk-VT6G5AJV.js';
9
- import { resolveConfiguredHarnessName, FACTORY_SOURCE_URL, isFactoryMemorySource, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, writeLock, computeHash, buildLockFile, readLock, LockParseError, assertLockHashes, verifyLock, mergeLockFile, resyncLockSources, extractForPatch, generatePatch, savePatch, applyPatch, LOCK_SCHEMA_VERSION } from './chunk-6ARPZHOV.js';
10
- import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-JIQUF3X2.js';
11
- import { deployedBase, isDeployed, deployedPaths, deployedDir } from './chunk-5KRMNUL4.js';
12
- import { resolveSkWorkspaceConfig, effectiveAgentInstances, mcpDeclarationFromMdContent, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, readLinks, isCommitOnRemote, findWorkspaceRoot, resolveSourcePublisher, resolveAll, agentSourceCacheDir, ensureRepo, resolveAgentDefinitionDir, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, DEFAULT_AGENT_INSTANCE_ID, MAX_PRESET_DEPTH, PresetDepthError } from './chunk-6SXSVKQY.js';
9
+ import { resolveConfiguredHarnessName, computeHash, FACTORY_SOURCE_URL, isFactoryMemorySource, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, writeLock, buildLockFile, readLock, LockParseError, assertLockHashes, verifyLock, mergeLockFile, resyncLockSources, extractForPatch, generatePatch, savePatch, applyPatch, ensureRunStateIgnored, LOCK_SCHEMA_VERSION } from './chunk-TMJBEGS4.js';
10
+ import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-G7NMF5WQ.js';
11
+ import { deployedBase, deployedPaths, deployedDir, isDeployed } from './chunk-5KRMNUL4.js';
12
+ import { resolveSkWorkspaceConfig, effectiveAgentInstances, mcpDeclarationFromMdContent, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, readLinks, isCommitOnRemote, findWorkspaceRoot, resolveSourcePublisher, resolveAll, agentSourceCacheDir, ensureRepo, resolveAgentDefinitionDir, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, cloneOriginMismatch, DEFAULT_AGENT_INSTANCE_ID, MAX_PRESET_DEPTH, PresetDepthError } from './chunk-O7ADRMCR.js';
13
13
  import { globalSkaileDir, globalCacheRoot, migrateLegacyDir } from './chunk-L5VSIPQD.js';
14
14
  import { HARNESS_TARGETS, SUPPORTED_HARNESSES } from './chunk-VTETQCR6.js';
15
- import { listAssetFiles, loadSkPublishManifest, decodeSkaileManifest, isNonAssetDir, isNonAssetFile } from './chunk-E2EC6SAX.js';
15
+ import { listAssetFiles, loadSkPublishManifest, decodeSkaileManifest, isNonAssetDir, isNonAssetFile } from './chunk-QC5BYUED.js';
16
16
  import { scanDirectory, parseFrontmatter, parseRequires, dedupeRequirements, readAssetBody } from './chunk-GNUA7XT2.js';
17
17
  import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr, parseDep } from './chunk-V5KG6CCV.js';
18
18
  import { spawnSync } from 'child_process';
@@ -40,6 +40,7 @@ function writeLedger(projectDir, ledger) {
40
40
  mkdirSync(dirname(p), { recursive: true });
41
41
  writeFileSync(p, `${JSON.stringify(ledger, null, 2)}
42
42
  `, "utf-8");
43
+ ensureRunStateIgnored(projectDir);
43
44
  }
44
45
  function renderedInstanceFiles(projectDir, harness) {
45
46
  const recorded = readLedger(projectDir).targets[harness];
@@ -52,6 +53,71 @@ function renderedInstanceFiles(projectDir, harness) {
52
53
  }
53
54
  return Object.entries(instances).filter(([id]) => recorded[id]?.length).map(([id, instance]) => ({ id, ref: instance.ref, files: recorded[id] }));
54
55
  }
56
+ function agentOfRef(ref) {
57
+ if (!ref.startsWith("agent:")) return void 0;
58
+ const body = (ref.slice("agent:".length).split("#")[0] ?? "").trim();
59
+ const slash = body.lastIndexOf("/");
60
+ const name = slash < 0 ? body : body.slice(slash + 1);
61
+ if (!name) return void 0;
62
+ const publisher = slash < 0 ? void 0 : body.slice(0, slash).replace(/^@/, "");
63
+ return { name, ...publisher ? { publisher } : {} };
64
+ }
65
+ function instancesBoundToAgent(projectDir, name, publisher) {
66
+ let instances;
67
+ try {
68
+ instances = effectiveAgentInstances(resolveSkWorkspaceConfig(projectDir));
69
+ } catch {
70
+ return [];
71
+ }
72
+ return Object.entries(instances).filter(([, instance]) => {
73
+ const bound = agentOfRef(instance.ref);
74
+ return bound !== void 0 && bound.name === name && (true);
75
+ }).map(([id]) => id);
76
+ }
77
+ function boundAgentNames(projectDir) {
78
+ try {
79
+ return new Set(
80
+ Object.values(effectiveAgentInstances(resolveSkWorkspaceConfig(projectDir))).map((instance) => agentOfRef(instance.ref)?.name).filter((name) => name !== void 0)
81
+ );
82
+ } catch {
83
+ return /* @__PURE__ */ new Set();
84
+ }
85
+ }
86
+ function isAgentInstanceRendered(projectDir, harness, name) {
87
+ if (!harnessTargetSupportsAgents(harness)) return false;
88
+ const recorded = readLedger(projectDir).targets[harness];
89
+ if (!recorded) return false;
90
+ return instancesBoundToAgent(projectDir, name).some((id) => {
91
+ const files = recorded[id] ?? [];
92
+ return files.length > 0 && files.every((rel) => {
93
+ try {
94
+ return lstatSync(resolve(projectDir, rel)) !== void 0;
95
+ } catch {
96
+ return false;
97
+ }
98
+ });
99
+ });
100
+ }
101
+ function runRoleAgentNames(projectDir) {
102
+ const run = /* @__PURE__ */ new Set();
103
+ const delegate = /* @__PURE__ */ new Set();
104
+ const cache = agentSourceCacheDir(projectDir);
105
+ if (!existsSync(cache)) return run;
106
+ for (const dir of readdirSync(cache, { withFileTypes: true })) {
107
+ if (!dir.isDirectory()) continue;
108
+ const composed = composedAgentNamesOf(join(cache, dir.name));
109
+ for (const name of composed.run) run.add(name);
110
+ for (const name of composed.delegate) delegate.add(name);
111
+ }
112
+ for (const name of delegate) run.delete(name);
113
+ return run;
114
+ }
115
+ function isAssetDeployed(kind, name, harness, global, projectDir) {
116
+ if (isDeployed(kind, name, harness, global, projectDir)) return true;
117
+ if (kind !== "agent" || global || projectDir === void 0) return false;
118
+ if (isAgentInstanceRendered(projectDir, harness, name)) return true;
119
+ return runRoleAgentNames(projectDir).has(name) && existsSync(join(agentSourceCacheDir(projectDir), name));
120
+ }
55
121
  function instanceRenderedAgentNames(projectDir, harness) {
56
122
  const names = /* @__PURE__ */ new Set();
57
123
  if (!harnessTargetSupportsAgents(harness)) return names;
@@ -325,7 +391,7 @@ async function extraPayloadEntries(dir, dest) {
325
391
  return [];
326
392
  }
327
393
  if (entries.some((e) => e.name === "MCP.md")) return [];
328
- return entries.filter((e) => e.name !== dest && e.name !== "package.json").filter((e) => !(e.isDirectory() ? isNonAssetDir(e.name) : isNonAssetFile(e.name))).map((e) => e.name).sort();
394
+ return entries.filter((e) => e.name !== dest && e.name !== "package.json").filter((e) => !(e.isDirectory() ? isNonAssetDir(e.name, true) : isNonAssetFile(e.name))).map((e) => e.name).sort();
329
395
  }
330
396
  async function pruneExtraPayloadFiles(dir, dest) {
331
397
  for (const name of await extraPayloadEntries(dir, dest)) {
@@ -1127,7 +1193,7 @@ function parseCanonicalLockKey(key) {
1127
1193
  }
1128
1194
  }
1129
1195
  function labelDiffHeaders(diff, from, to) {
1130
- const stamp = "\\t(?:\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)? [+-]\\d{4}|[A-Z][a-z]{2} [A-Z][a-z]{2} [ \\d]\\d \\d{2}:\\d{2}:\\d{2} \\d{4})";
1196
+ const stamp = "\\t(?:\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?: [+-]\\d{4})?|[A-Z][a-z]{2} [A-Z][a-z]{2} [ \\d]\\d \\d{2}:\\d{2}:\\d{2} \\d{4})";
1131
1197
  return diff.replace(
1132
1198
  new RegExp(`^(---|\\+\\+\\+) (.*?)${stamp}$`, "gm"),
1133
1199
  (_m, mark, file) => `${mark} ${file} (${mark === "---" ? from : to})`
@@ -1159,10 +1225,8 @@ function parseRefTolerant(ref) {
1159
1225
  }
1160
1226
  }
1161
1227
  var LibraryEntryError = class extends Error {
1162
- constructor(message) {
1163
- super(message);
1164
- this.name = "LibraryEntryError";
1165
- }
1228
+ // The name stays `Error`: a failure prints as `Error: <message>` like every other `add` failure,
1229
+ // never with the class name.
1166
1230
  };
1167
1231
  function keptLockEntries(prev, missing) {
1168
1232
  const out = { assets: {}, sources: [], refs: /* @__PURE__ */ new Set(), keysByRef: /* @__PURE__ */ new Map() };
@@ -1199,6 +1263,16 @@ function withKeptLockEntries(lock, kept) {
1199
1263
  sources: [...sources.values()].sort((a, b) => a.url.localeCompare(b.url))
1200
1264
  };
1201
1265
  }
1266
+ function withUnchangedSourceCommits(lock, prev) {
1267
+ if (!prev) return lock;
1268
+ for (const [key, entry] of Object.entries(lock.assets)) {
1269
+ const before = prev.assets[key];
1270
+ if (!entry.source || entry.library || !before?.source || before.library) continue;
1271
+ if (before.sha256 !== entry.sha256 || before.source.url !== entry.source.url) continue;
1272
+ if (before.source.commit) entry.source.commit = before.source.commit;
1273
+ }
1274
+ return lock;
1275
+ }
1202
1276
  function relockedRefs(prev, next) {
1203
1277
  if (!prev) return [];
1204
1278
  const fingerprint = (e, key) => [
@@ -1320,9 +1394,19 @@ var MissingManifestError = class extends Error {
1320
1394
  };
1321
1395
  function unlistedAssetMessage(ref, library, libPath, ownership) {
1322
1396
  const head = `${ref} is in library "${library}" but not listed in its skaile.manifest.yaml, so only part of its files would be deployed.`;
1397
+ return isReadOnlyLibrary(libPath, ownership) ? `${head} "${library}" is a read-only source clone: add it to skaile.manifest.yaml in the source repo and push, then run \`skaile source sync\`.` : `${head} Run \`skaile library index ${library}\`, then add it again.`;
1398
+ }
1399
+ function isSourceCacheClone(libPath) {
1323
1400
  const segments = libPath.split(/[\\/]/);
1324
- const isReader = ownership === "reader" || segments.some((s, i) => s === "cache" && segments[i + 1] === "sources");
1325
- return isReader ? `${head} "${library}" is a read-only source clone: add it to skaile.manifest.yaml in the source repo and push, then run \`skaile source sync\`.` : `${head} Run \`skaile library index ${library}\`, then add it again.`;
1401
+ return segments.some((s, i) => s === "cache" && segments[i + 1] === "sources");
1402
+ }
1403
+ function isReadOnlyLibrary(libPath, ownership) {
1404
+ return ownership === "reader" || isSourceCacheClone(libPath);
1405
+ }
1406
+ function libraryFixAdvice(library, libPath, ownership, ownerAdvice, readOnlyAdvice) {
1407
+ if (!isReadOnlyLibrary(libPath, ownership)) return ownerAdvice;
1408
+ const refresh = isSourceCacheClone(libPath) ? "skaile source sync" : `skaile library pull ${library}`;
1409
+ return `${readOnlyAdvice}, then run \`${refresh}\`.`;
1326
1410
  }
1327
1411
  function pathEntryExists(p) {
1328
1412
  try {
@@ -1425,8 +1509,16 @@ var AssetManager = class {
1425
1509
  warnedStoreVersionLookups = /* @__PURE__ */ new Set();
1426
1510
  /** Stores a lookup could not reach (store URL -> one line why); `add` reports them instead of "not found". */
1427
1511
  storeFailures = /* @__PURE__ */ new Map();
1512
+ /** The agent `add` is about to bind to an instance: its deploy writes no file named after the asset. */
1513
+ pendingAgentBinding;
1428
1514
  /** Source origins `outdated` could not fetch; read once through {@link takeUnreachableSources}. */
1429
1515
  unreachableSources = [];
1516
+ /** Store-origin refs `outdated` could not check; read once through {@link takeStoreNotChecked}. */
1517
+ storeUnchecked = [];
1518
+ /** How many store lookups failed so far; a lookup that moved it failed. */
1519
+ storeFailureCount = 0;
1520
+ /** Set while a lookup reports its own failure: the generic one-line warning stays off. */
1521
+ quietStoreLookups = false;
1430
1522
  /** Store URLs a lookup failed on because the client is air-gapped (`cache_ttl: 0`), not because the store is down. */
1431
1523
  airGappedStores = /* @__PURE__ */ new Set();
1432
1524
  /** Sources a provenance walk had to skip (source URL → why); one warning per source. */
@@ -1535,7 +1627,7 @@ var AssetManager = class {
1535
1627
  */
1536
1628
  legacySingleCopyHarness(component, name, all) {
1537
1629
  if (!all.includes("omp") || legacyOmpPaths(component, name).length === 0) return [];
1538
- const others = all.filter((h) => h !== "omp" && isDeployed(component, name, h, true));
1630
+ const others = all.filter((h) => h !== "omp" && isAssetDeployed(component, name, h, true));
1539
1631
  return others.length === 0 ? ["omp"] : [];
1540
1632
  }
1541
1633
  /**
@@ -1681,7 +1773,7 @@ var AssetManager = class {
1681
1773
  if (!declared) return;
1682
1774
  const current = this.harnessRowIn(raw, target) ?? this.defaultGlobalHarnesses();
1683
1775
  for (const h of current) {
1684
- if (named.includes(h) || !isDeployed(component, target.name, h, true)) continue;
1776
+ if (named.includes(h) || !isAssetDeployed(component, target.name, h, true)) continue;
1685
1777
  const where = deployedPaths(component, target.name, h, true)[0];
1686
1778
  onDropped(ref, h, where ?? deployedDir(component, target.name, h, true));
1687
1779
  }
@@ -1698,7 +1790,7 @@ var AssetManager = class {
1698
1790
  for (const entry of entries) {
1699
1791
  const component = this.installTarget(entry.kind);
1700
1792
  if (!component || !entry.name) continue;
1701
- if (!isDeployed(component, entry.name, "omp", true)) continue;
1793
+ if (!isAssetDeployed(component, entry.name, "omp", true)) continue;
1702
1794
  const modern = deployedPaths(component, entry.name, "omp", true).filter(
1703
1795
  (p) => p.includes(`${sep}.omp${sep}agent${sep}`)
1704
1796
  );
@@ -1756,6 +1848,14 @@ var AssetManager = class {
1756
1848
  takeUnreachableSources() {
1757
1849
  return this.unreachableSources.splice(0);
1758
1850
  }
1851
+ /**
1852
+ * The refs the last {@link outdated} call could not check because their store did not answer
1853
+ * (`unreachable`) or the client is air-gapped (`air-gapped`): `outdated`, `check` and `doctor`
1854
+ * name them and fail on `unreachable` instead of calling the project up to date.
1855
+ */
1856
+ takeStoreNotChecked() {
1857
+ return this.storeUnchecked.splice(0);
1858
+ }
1759
1859
  /**
1760
1860
  * The harnesses `add` / `install` deploy into: `[harness]` for a project, the global
1761
1861
  * harness set (see {@link AssetManager.targetHarnesses}) for a global manager.
@@ -1795,12 +1895,19 @@ var AssetManager = class {
1795
1895
  * fan-out target (not the constructor's `harness`, which is project-only). */
1796
1896
  deployOptsFor(target, link, onSecretFile, composed) {
1797
1897
  const records = this.global ? void 0 : this.composedRecords();
1898
+ const bound = this.global ? void 0 : boundAgentNames(this.projectDir);
1899
+ if (bound && this.pendingAgentBinding) bound.add(this.pendingAgentBinding);
1900
+ const lockedAgents = this.global ? void 0 : new Set(
1901
+ Object.keys(this.tryReadLock()?.assets ?? {}).map((k) => parseCanonicalLockKey(k).name)
1902
+ );
1798
1903
  return {
1799
1904
  registry: this.registry,
1800
1905
  harness: target,
1801
1906
  global: this.global,
1802
1907
  cwd: this.projectDir,
1803
1908
  link: link === true,
1909
+ ...bound ? { instanceBoundAgents: bound } : {},
1910
+ ...lockedAgents ? { agentLocked: (name) => lockedAgents.has(name) } : {},
1804
1911
  ...onSecretFile ? { onSecretFile: (entry, p) => onSecretFile(canonicalEntryRef(entry), p) } : {},
1805
1912
  ...records ? { lockedComposed: (agent) => records.get(agent) } : {},
1806
1913
  ...composed ? {
@@ -1948,20 +2055,81 @@ var AssetManager = class {
1948
2055
  }
1949
2056
  return restored;
1950
2057
  }
2058
+ /**
2059
+ * Remove the files named after an agent asset that an earlier CLI rendered and this one does
2060
+ * not: the agent is bound by an instance (its rendering is the instance's file), or
2061
+ * it only runs as a `binding: run` role. Only a file the lock lists for the agent, whose bytes
2062
+ * still equal what the lock recorded, and that no instance of the ledger claims is removed;
2063
+ * an edited one stays (it is the user's now) and is named. The old lock entry is rewritten
2064
+ * by the same install, so the lock never keeps a path that is gone.
2065
+ *
2066
+ * @returns The project-relative paths removed.
2067
+ */
2068
+ pruneAssetNamedAgentFiles() {
2069
+ const lock = this.tryReadLock();
2070
+ if (this.global || !lock || !harnessTargetSupportsAgents(this.harness)) return [];
2071
+ const bound = boundAgentNames(this.projectDir);
2072
+ const runRoles = runRoleAgentNames(this.projectDir);
2073
+ const claimedPaths = renderedInstanceFiles(this.projectDir, this.harness).flatMap(
2074
+ (i) => i.files
2075
+ );
2076
+ const claimed = (rel) => claimedPaths.some((c) => rel === c || rel.startsWith(`${c}/`));
2077
+ const agentDir = resolve(deployedBase("agent", this.harness, false, this.projectDir));
2078
+ const removed = [];
2079
+ for (const [key, entry] of Object.entries(lock.assets)) {
2080
+ const { kind, name } = parseCanonicalLockKey(key);
2081
+ if (!kind || !name || this.installTarget(kind) !== "agent" || !entry.rendered?.length) {
2082
+ continue;
2083
+ }
2084
+ if (!bound.has(name) && !runRoles.has(name)) continue;
2085
+ if (!runRoles.has(name) && !isAgentInstanceRendered(this.projectDir, this.harness, name)) {
2086
+ continue;
2087
+ }
2088
+ const named = new Set(this.renderedAgentFiles(name).map((f) => f.path));
2089
+ for (const f of entry.rendered) {
2090
+ if (!named.has(f.path) || claimed(f.path)) continue;
2091
+ const abs = join(this.projectDir, f.path);
2092
+ if (!existsSync(abs)) continue;
2093
+ let intact = false;
2094
+ try {
2095
+ intact = computeHash(abs) === f.sha256;
2096
+ } catch {
2097
+ }
2098
+ if (!intact) {
2099
+ console.warn(
2100
+ `skaile: ${f.path} is no longer written for ${name} (an instance renders it); it was edited, so it stays`
2101
+ );
2102
+ continue;
2103
+ }
2104
+ rmSync(abs, { force: true });
2105
+ removed.push(f.path);
2106
+ for (let dir = dirname(abs); dir.startsWith(agentDir + sep); dir = dirname(dir)) {
2107
+ if (readdirSync(dir).length > 0) break;
2108
+ rmSync(dir, { recursive: true, force: true });
2109
+ }
2110
+ }
2111
+ }
2112
+ return removed;
2113
+ }
1951
2114
  /**
1952
2115
  * Render every agent instance of `skaile.yaml` into the harness target's native
1953
2116
  * agent files (`.claude/agents/<id>.md`, …) and prune the renderings of
1954
2117
  * instances that left the config. Runs after the skills deploy, so composed
1955
2118
  * skills resolve. Project scope only. An instance whose `ref` resolves to no agent is
1956
2119
  * reported in `agentInstanceErrors`; any other render error is warned and swallowed.
2120
+ *
2121
+ * @param opts.prune - Also remove the files named after the agent assets that an earlier CLI
2122
+ * rendered and an instance renders now ({@link pruneAssetNamedAgentFiles}). Set by the
2123
+ * commands that rewrite the lock; `install --locked` leaves the lock, so it leaves them.
1957
2124
  */
1958
- async renderAgentInstances() {
2125
+ async renderAgentInstances(opts) {
1959
2126
  if (this.global) return {};
1960
2127
  try {
1961
2128
  const result = installAgentInstances({
1962
2129
  projectDir: this.projectDir,
1963
2130
  harness: this.harness
1964
2131
  });
2132
+ if (opts?.prune) result.removed.push(...this.pruneAssetNamedAgentFiles());
1965
2133
  const details = [];
1966
2134
  for (const u of unboundAgentInstances(this.projectDir, this.harness)) {
1967
2135
  if (!u.ref.startsWith("agent:")) continue;
@@ -2782,7 +2950,7 @@ var AssetManager = class {
2782
2950
  );
2783
2951
  if (!holder) continue;
2784
2952
  const target = this.targetHarnesses().find(
2785
- (t) => isDeployed(component, a.name, t, this.global, this.projectDir)
2953
+ (t) => isAssetDeployed(component, a.name, t, this.global, this.projectDir)
2786
2954
  );
2787
2955
  if (!target) continue;
2788
2956
  const dir = deployedDir(component, a.name, target, this.global, this.projectDir);
@@ -2938,6 +3106,26 @@ var AssetManager = class {
2938
3106
  }
2939
3107
  return hidden;
2940
3108
  }
3109
+ /**
3110
+ * The registered libraries as `library list` shows them in this project. A source clone is
3111
+ * cache: its row is read from the clone, so it is dropped when the clone is gone and
3112
+ * when this project does not declare the source. `sources` holds the ids of the clone rows
3113
+ * that stay, so the list can mark them `(source)`.
3114
+ */
3115
+ scopeLibraryList(libraries) {
3116
+ const hidden = this.undeclaredSourceClones(libraries);
3117
+ const sources = /* @__PURE__ */ new Set();
3118
+ const shown = [];
3119
+ for (const l of libraries) {
3120
+ if (hidden.has(l.id)) continue;
3121
+ if (this.sourceCloneKey(l) !== void 0) {
3122
+ if (libraryDirMissing(l)) continue;
3123
+ sources.add(l.id);
3124
+ }
3125
+ shown.push(l);
3126
+ }
3127
+ return { libraries: shown, sources };
3128
+ }
2941
3129
  /**
2942
3130
  * The index as this project sees it: the source clones of other projects are dropped
2943
3131
  * ({@link undeclaredSourceClones}) and the assets of a declared source carry the publisher
@@ -3216,7 +3404,7 @@ var AssetManager = class {
3216
3404
  continue;
3217
3405
  }
3218
3406
  const component = this.installTarget(kind);
3219
- const deployed = component !== void 0 && isDeployed(component, name, this.harness, this.global, this.projectDir);
3407
+ const deployed = component !== void 0 && isAssetDeployed(component, name, this.harness, this.global, this.projectDir);
3220
3408
  const problem = lockedLibraryProblem(lookup, e.library, `${kind}:@${publisher}/${name}`);
3221
3409
  const kept = deployed ? "the deployed copy and its lock entry are kept" : "its lock entry is kept; no deployed copy exists";
3222
3410
  lines.push(`${ref} (${problem}; ${kept})`);
@@ -3286,7 +3474,7 @@ var AssetManager = class {
3286
3474
  const component = this.installTarget(kind);
3287
3475
  const newer = gt(coerceVersion(current), coerceVersion(origin.version));
3288
3476
  const comparable = !isPseudoVersion(current) && !isPseudoVersion(origin.version);
3289
- const intact = (newer || comparable) && (component === void 0 || isDeployed(component, name, this.harness, this.global, this.projectDir));
3477
+ const intact = (newer || comparable) && (component === void 0 || isAssetDeployed(component, name, this.harness, this.global, this.projectDir));
3290
3478
  if (!intact) {
3291
3479
  missing.push(
3292
3480
  `${ref} (library "${lookup.name}" is at ${current}, locked ${origin.version}${newer || comparable ? "; `skaile update` moves the lock to it" : ""})`
@@ -3398,7 +3586,7 @@ var AssetManager = class {
3398
3586
  if (want.publisher && id.publisher !== want.publisher) continue;
3399
3587
  const component = this.installTarget(id.kind);
3400
3588
  if (component !== void 0) {
3401
- if (isDeployed(component, id.name, this.harness, this.global, this.projectDir)) return true;
3589
+ if (isAssetDeployed(component, id.name, this.harness, this.global, this.projectDir)) return true;
3402
3590
  } else if (id.kind === "mcp-server" && !this.global && await mcpCommittedRenderIntact(this.projectDir, this.harness, id.name)) {
3403
3591
  return true;
3404
3592
  }
@@ -3408,7 +3596,7 @@ var AssetManager = class {
3408
3596
  /** Whether the deployed copy of a library asset is on disk; a kind with no install target has none to check. */
3409
3597
  lockedCopyDeployed(kind, name) {
3410
3598
  const component = this.installTarget(kind);
3411
- return component === void 0 || isDeployed(component, name, this.harness, this.global, this.projectDir);
3599
+ return component === void 0 || isAssetDeployed(component, name, this.harness, this.global, this.projectDir);
3412
3600
  }
3413
3601
  /**
3414
3602
  * The library-origin lock entries `install` keeps when the library holds a newer version:
@@ -4179,6 +4367,7 @@ var AssetManager = class {
4179
4367
  * @returns {@link InstallResult} summarising what was deployed, what was missing, and any collisions.
4180
4368
  */
4181
4369
  async install(opts) {
4370
+ resetMissingParentWarnings();
4182
4371
  const config = this.loadConfig();
4183
4372
  const { repositories, sources, stores, overrides, patches } = config;
4184
4373
  const dependencies = [...config.dependencies, ...this.lockedAgentBindings(config.dependencies)];
@@ -4375,13 +4564,64 @@ Fix the asset, then run \`skaile library index ${origin}\` and install again.`
4375
4564
  );
4376
4565
  }
4377
4566
  const inferredHarnesses = this.inferLegacyHarnessSubsets(entries);
4567
+ const restoredRefs = stillMissing.filter((m) => {
4568
+ const keys = kept.keysByRef.get(m) ?? [];
4569
+ return keys.length > 0 && keys.every((k) => restoredFromStore.has(k));
4570
+ });
4571
+ const reportedMissing = stillMissing.filter(
4572
+ (m) => !storeNotChecked.some((n) => n.ref === m) && !restoredRefs.includes(m)
4573
+ );
4574
+ for (const n of storeNotChecked) delete missingHints[n.ref];
4575
+ for (const m of restoredRefs) delete missingHints[m];
4576
+ const editedHeld = new Set(
4577
+ (await this.lockedCopyDrift()).filter((d) => d.libraryChanged).map((d) => d.ref)
4578
+ );
4579
+ const heldEdits = editedHeld.size > 0 && opts?.moveLibraries !== true ? (await this.projectState()).gaps.filter((g) => g.type === "modified" && editedHeld.has(g.ref)).map((g) => g.message) : [];
4580
+ const composedPre = /* @__PURE__ */ new Set();
4581
+ if (!this.global && opts?.moveLibraries !== true) {
4582
+ for (const e of entries) {
4583
+ if (this.installTarget(e.kind) !== "agent") continue;
4584
+ try {
4585
+ for (const composeRef of composedDriftRefs(e, this.deployOptsFor(this.harness))) {
4586
+ composedPre.add(this.composedDriftLine(canonicalEntryRef(e), composeRef));
4587
+ }
4588
+ } catch {
4589
+ }
4590
+ }
4591
+ }
4592
+ const unbound = this.global ? { errors: [], details: [] } : await this.unboundInstanceErrors(entries);
4593
+ const failing = [
4594
+ ...reportedMissing,
4595
+ ...versionBlocked.filter((b) => !reportedMissing.includes(b)),
4596
+ ...composedPre,
4597
+ ...heldEdits.filter((h) => !reportedMissing.includes(h))
4598
+ ];
4599
+ const storeUnreachable = storeNotChecked.some((n) => n.reason === "unreachable");
4600
+ if (failing.length > 0 || contentHeld.length > 0 || storeUnreachable || unbound.errors.length > 0) {
4601
+ await this.adviseMissing(reportedMissing, missingHints);
4602
+ for (const e of unbound.errors) console.warn(`skaile: ${e}`);
4603
+ return {
4604
+ deployed: [],
4605
+ removed: [],
4606
+ missing: failing,
4607
+ ...storeNotChecked.length > 0 ? { storeNotChecked } : {},
4608
+ ...Object.keys(missingHints).length > 0 ? { missingHints } : {},
4609
+ ...contentHeld.length > 0 ? { contentHeld } : {},
4610
+ ...unbound.errors.length > 0 ? { agentInstanceErrors: unbound.errors } : {},
4611
+ ...unbound.details.length > 0 ? { agentInstanceDetails: unbound.details } : {},
4612
+ lockWritten: false,
4613
+ npmInstalled: [],
4614
+ npmFailed: [],
4615
+ presets
4616
+ };
4617
+ }
4378
4618
  const { removed, replaced } = this.reconcileRemovedAssets(
4379
4619
  resolved,
4380
4620
  /* @__PURE__ */ new Set([...Object.keys(libraryLock), ...Object.keys(kept.assets)])
4381
4621
  );
4382
4622
  const copyDrift = await this.lockedCopyDrift();
4383
4623
  const missingCopies = await this.incompleteDeploys();
4384
- const unrecordedAgents = this.unrecordedAgentFiles(prevLock);
4624
+ const unrecordedRenderings = this.unrecordedRenderings(prevLock);
4385
4625
  const composedDrift = /* @__PURE__ */ new Set();
4386
4626
  const deployed = [
4387
4627
  ...new Set(
@@ -4400,24 +4640,37 @@ Fix the asset, then run \`skaile library index ${origin}\` and install again.`
4400
4640
  ];
4401
4641
  this.sweepLegacyOmpCopies(entries);
4402
4642
  const mcpRestored = await this.renderHarnessMcpConfig();
4403
- const agentRender = await this.renderAgentInstances();
4643
+ const agentRender = await this.renderAgentInstances({ prune: true });
4644
+ if (agentRender.agentFilesRemoved?.length) {
4645
+ for (const t of this.targetHarnesses()) {
4646
+ deployAll(
4647
+ this.entriesForHarness(entries, t),
4648
+ repositories,
4649
+ patches,
4650
+ this.deployOptsFor(t, opts?.link, void 0, { refresh: false, onDrift: () => {
4651
+ } })
4652
+ );
4653
+ }
4654
+ }
4655
+ const { rewritten, restored: restoredRenderings } = this.changedRenderings(unrecordedRenderings);
4404
4656
  const restored = [
4405
4657
  ...this.restoredCopies(copyDrift, deployed, missingCopies),
4406
4658
  ...relockRemoved,
4407
- ...mcpRestored
4659
+ ...mcpRestored,
4660
+ ...restoredRenderings
4408
4661
  ];
4409
- const rewritten = this.rewrittenAgentFiles(unrecordedAgents);
4410
- const editedHeld = new Set(copyDrift.filter((d) => d.libraryChanged).map((d) => d.ref));
4411
- const heldEdits = editedHeld.size > 0 && opts?.moveLibraries !== true ? (await this.projectState()).gaps.filter((g) => g.type === "modified" && editedHeld.has(g.ref)).map((g) => g.message) : [];
4412
4662
  const lockWanted = resolved.length > 0 || lib.entries.length > 0 || existsSync(this.lockPath);
4413
4663
  let lockWritten = false;
4414
4664
  let relocked = [];
4415
4665
  let moved = [];
4416
4666
  if (lockWanted) {
4417
- const lockData = this.withCopiedFiles(
4418
- this.withRenderedAgents(
4419
- withKeptLockEntries(freshLock, kept),
4420
- opts?.moveLibraries ? void 0 : prevLock
4667
+ const lockData = withUnchangedSourceCommits(
4668
+ this.withCopiedFiles(
4669
+ this.withRenderedAgents(
4670
+ withKeptLockEntries(freshLock, kept),
4671
+ opts?.moveLibraries ? void 0 : prevLock
4672
+ ),
4673
+ prevLock
4421
4674
  ),
4422
4675
  prevLock
4423
4676
  );
@@ -4428,33 +4681,16 @@ Fix the asset, then run \`skaile library index ${origin}\` and install again.`
4428
4681
  }
4429
4682
  this.recordInstallHistory(deployed, removed);
4430
4683
  const { npmInstalled, npmFailed } = await this.installRuntimeAssetDeps();
4431
- const restoredRefs = stillMissing.filter((m) => {
4432
- const keys = kept.keysByRef.get(m) ?? [];
4433
- return keys.length > 0 && keys.every((k) => restoredFromStore.has(k));
4434
- });
4435
- const reportedMissing = stillMissing.filter(
4436
- (m) => !storeNotChecked.some((n) => n.ref === m) && !restoredRefs.includes(m)
4437
- );
4438
- for (const n of storeNotChecked) delete missingHints[n.ref];
4439
- for (const m of restoredRefs) delete missingHints[m];
4440
- await this.adviseMissing(reportedMissing, missingHints);
4441
4684
  const placeholderBodies = scaffoldBodyRefs(lib.entries, deployed);
4442
4685
  const placeholderDescriptions = scaffoldDescriptionRefs(lib.entries, deployed);
4443
4686
  return {
4444
4687
  deployed,
4445
4688
  removed,
4446
- missing: [
4447
- ...reportedMissing,
4448
- ...versionBlocked.filter((b) => !reportedMissing.includes(b)),
4449
- ...composedDrift,
4450
- ...heldEdits.filter((h) => !reportedMissing.includes(h))
4451
- ],
4689
+ missing: [...composedDrift],
4452
4690
  ...placeholderBodies.length > 0 ? { placeholderBodies } : {},
4453
4691
  ...placeholderDescriptions.length > 0 ? { placeholderDescriptions } : {},
4454
4692
  ...storeNotChecked.length > 0 ? { storeNotChecked } : {},
4455
- ...Object.keys(missingHints).length > 0 ? { missingHints } : {},
4456
4693
  ...relocked.length > 0 ? { relocked } : {},
4457
- ...contentHeld.length > 0 ? { contentHeld } : {},
4458
4694
  ...inferredHarnesses.length > 0 ? { inferredHarnesses } : {},
4459
4695
  ...moved.length > 0 ? { moved } : {},
4460
4696
  ...replaced.length > 0 ? { replaced } : {},
@@ -4955,6 +5191,7 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
4955
5191
  * name), so `add` can say `store unreachable` instead of a bare `Asset not found`.
4956
5192
  */
4957
5193
  noteStoreFailure(storeUrl, err) {
5194
+ this.storeFailureCount++;
4958
5195
  const text = err instanceof OfflineError ? `${storeUrl}: air-gapped (catalog.cache_ttl: 0), the store was not asked` : describeCatalogError(err, storeUrl);
4959
5196
  this.storeFailures.set(storeUrl, text);
4960
5197
  if (err instanceof OfflineError) this.airGappedStores.add(storeUrl);
@@ -5007,7 +5244,7 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5007
5244
  return await src.listVersions(ref);
5008
5245
  } catch (err) {
5009
5246
  const text = this.noteStoreFailure(storeUrl, err);
5010
- if (!this.warnedStoreVersionLookups.has(storeUrl)) {
5247
+ if (!this.quietStoreLookups && !this.warnedStoreVersionLookups.has(storeUrl)) {
5011
5248
  this.warnedStoreVersionLookups.add(storeUrl);
5012
5249
  console.warn(`skaile: store lookup of ${ref} failed: ${text}`);
5013
5250
  }
@@ -5199,9 +5436,39 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5199
5436
  npmFailed: []
5200
5437
  };
5201
5438
  }
5439
+ const alreadyMissing = new Set(
5440
+ library.missing.map((m) => {
5441
+ const p = parseRefTolerant(m.split(" ")[0] ?? m);
5442
+ return p ? `${p.kind}:${p.name}` : m;
5443
+ })
5444
+ );
5445
+ const viaStoreIds = new Set(library.viaStore.map(gapIdentity));
5446
+ const lockGaps = async (only) => (await this.projectState()).gaps.filter((g) => {
5447
+ if (only && !only.has(g.type)) return false;
5448
+ if (g.type === "agent") return false;
5449
+ if (g.unreadableSource) return false;
5450
+ if ((g.type === "library" || g.type === "unresolved") && viaStoreIds.has(gapIdentity(g.ref))) {
5451
+ return false;
5452
+ }
5453
+ const p = parseRefTolerant(g.ref);
5454
+ return !(p && alreadyMissing.has(`${p.kind}:${p.name}`));
5455
+ }).map((g) => g.message);
5456
+ const unfixable = await lockGaps(
5457
+ /* @__PURE__ */ new Set(["declared", "invalid", "pin", "library", "content", "source"])
5458
+ );
5459
+ if (unfixable.length > 0) {
5460
+ return {
5461
+ deployed: [],
5462
+ removed: [],
5463
+ missing: unfixable,
5464
+ lockWritten: false,
5465
+ npmInstalled: [],
5466
+ npmFailed: []
5467
+ };
5468
+ }
5202
5469
  const copyDrift = await this.lockedCopyDrift();
5203
5470
  const missingCopies = await this.incompleteDeploys();
5204
- const unrecordedAgents = this.unrecordedAgentFiles(lock);
5471
+ const unrecordedRenderings = this.unrecordedRenderings(lock);
5205
5472
  const composedDrift = /* @__PURE__ */ new Set();
5206
5473
  const deployed = [
5207
5474
  ...new Set(
@@ -5221,24 +5488,13 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5221
5488
  this.sweepLegacyOmpCopies([...resolved, ...library.entries]);
5222
5489
  const mcpRestored = await this.renderHarnessMcpConfig();
5223
5490
  const agentRender = await this.renderAgentInstances();
5224
- const restored = [...this.restoredCopies(copyDrift, deployed, missingCopies), ...mcpRestored];
5225
- const rewritten = this.rewrittenAgentFiles(unrecordedAgents);
5226
- const alreadyMissing = new Set(
5227
- library.missing.map((m) => {
5228
- const p = parseRefTolerant(m.split(" ")[0] ?? m);
5229
- return p ? `${p.kind}:${p.name}` : m;
5230
- })
5231
- );
5232
- const viaStoreIds = new Set(library.viaStore.map(gapIdentity));
5233
- const gaps = (await this.projectState()).gaps.filter((g) => {
5234
- if (g.type === "agent") return false;
5235
- if (g.unreadableSource) return false;
5236
- if ((g.type === "library" || g.type === "unresolved") && viaStoreIds.has(gapIdentity(g.ref))) {
5237
- return false;
5238
- }
5239
- const p = parseRefTolerant(g.ref);
5240
- return !(p && alreadyMissing.has(`${p.kind}:${p.name}`));
5241
- }).map((g) => g.message);
5491
+ const { rewritten, restored: restoredRenderings } = this.changedRenderings(unrecordedRenderings);
5492
+ const restored = [
5493
+ ...this.restoredCopies(copyDrift, deployed, missingCopies),
5494
+ ...mcpRestored,
5495
+ ...restoredRenderings
5496
+ ];
5497
+ const gaps = await lockGaps();
5242
5498
  const libraryNotices = this.storeRestoreNotices(
5243
5499
  lock,
5244
5500
  library.viaStore,
@@ -5345,14 +5601,16 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5345
5601
  return found;
5346
5602
  }
5347
5603
  /**
5348
- * The `Did you mean agent:@pub/name?` sentence for a ref written without a kind (`@pub/name`,
5349
- * which means `skill`) that names no asset: the refs of other kinds under the same name that
5350
- * a source, a library, the lock or `skaile.yaml` holds (p1425). `undefined` when the ref has a
5351
- * kind or nothing of another kind answers to it. `add`, `diff`, `update`, `info`, `remove` and
5604
+ * The sentence that ends the not-found line of a ref that names no asset but whose name exists
5605
+ * under another kind: refs of other kinds under the same name that a source, a library, the
5606
+ * lock or `skaile.yaml` holds. For a ref written without a kind (`@pub/name`, which means
5607
+ * `skill`) it is `Did you mean agent:@pub/name?`; for a kind-qualified ref of the wrong
5608
+ * kind (`skill:@pub/captain`) it is `It is an agent: agent:@pub/captain.`. `undefined`
5609
+ * when nothing of another kind answers to it. `add`, `diff`, `update`, `info`, `remove` and
5352
5610
  * `why` end their not-found line with it.
5353
5611
  */
5354
5612
  async otherKindHint(ref) {
5355
- if (/^[^@/#\s]+:/.test(ref.trim())) return void 0;
5613
+ const kinded = /^[^@/#\s]+:/.test(ref.trim());
5356
5614
  const parsed = parseRefTolerant(ref);
5357
5615
  if (!parsed) return void 0;
5358
5616
  const wantPublisher = parsed.publisher?.replace(/^@/, "");
@@ -5376,6 +5634,14 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5376
5634
  }
5377
5635
  const refs = [...found].sort();
5378
5636
  if (refs.length === 0) return void 0;
5637
+ if (kinded) {
5638
+ try {
5639
+ if (await this.info(ref) !== null) return void 0;
5640
+ } catch {
5641
+ }
5642
+ const kinds = refs.map((r) => parseRefTolerant(r)?.kind ?? "");
5643
+ return refs.length === 1 ? `It is ${/^[aeiou]/.test(kinds[0]) ? "an" : "a"} ${kinds[0]}: ${refs[0]}.` : `It exists as another kind: ${refs.join(", ")}.`;
5644
+ }
5379
5645
  return refs.length === 1 ? `Did you mean ${refs[0]}?` : `Did you mean one of: ${refs.join(", ")}?`;
5380
5646
  }
5381
5647
  /**
@@ -5519,6 +5785,7 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5519
5785
  * preset's items do not all resolve (nothing is deployed or recorded then).
5520
5786
  */
5521
5787
  async add(ref, opts) {
5788
+ resetMissingParentWarnings();
5522
5789
  const { repositories, sources, stores, dependencies, overrides, patches } = this.loadConfig();
5523
5790
  const parsed = await this.parseAddRef(ref, repositories, sources);
5524
5791
  this.ensureSourceClonesQuiet(repositories, sources);
@@ -5569,7 +5836,13 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5569
5836
  );
5570
5837
  if (gone) {
5571
5838
  throw new Error(
5572
- `library "${l.name}" lists ${parsed.kind}:${parsed.name} but its directory ${gone.root}/ is missing: run \`skaile library index ${l.name}\` to drop the entry, or restore the directory.`
5839
+ `library "${l.name}" lists ${parsed.kind}:${parsed.name} but its directory ${gone.root}/ is missing: ` + libraryFixAdvice(
5840
+ l.name,
5841
+ libPath,
5842
+ l.ownership,
5843
+ `run \`skaile library index ${l.name}\` to drop the entry, or restore the directory.`,
5844
+ `"${l.name}" is a read-only clone: ask the owner to push ${gone.root}/ or drop the entry from skaile.manifest.yaml`
5845
+ )
5573
5846
  );
5574
5847
  }
5575
5848
  }
@@ -5587,7 +5860,13 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5587
5860
  publisher: bare(renamed.publisher)
5588
5861
  }) : `${renamed.kind}:${renamed.name}`;
5589
5862
  throw new Error(
5590
- `${shown}: ${renamed.file} now names "${renamed.now}", so the library entry is a ref \`add\` cannot resolve. Run \`skaile library index ${l.name}\` to rename the entry, or restore the name.`
5863
+ `${shown}: ${renamed.file} now names "${renamed.now}", so the library entry is a ref \`add\` cannot resolve. ` + libraryFixAdvice(
5864
+ l.name,
5865
+ libPath,
5866
+ l.ownership,
5867
+ `Run \`skaile library index ${l.name}\` to rename the entry, or restore the name.`,
5868
+ `"${l.name}" is a read-only clone: ask the owner to rename the entry in skaile.manifest.yaml or restore the name and push`
5869
+ )
5591
5870
  );
5592
5871
  }
5593
5872
  }
@@ -5611,7 +5890,13 @@ Nothing was changed. Copy your edits away, or run \`${forceCommand}\` to replace
5611
5890
  throw new Error(
5612
5891
  `${parsed.kind}:${parsed.name} in library "${l.name}" fails the checks of \`skaile validate\` - nothing was added:
5613
5892
  ${problems.map((line) => ` ${line}`).join("\n")}
5614
- Fix the asset, then run \`skaile library index ${l.name}\` and add it again.`
5893
+ ` + libraryFixAdvice(
5894
+ l.name,
5895
+ libPath,
5896
+ l.ownership,
5897
+ `Fix the asset, then run \`skaile library index ${l.name}\` and add it again.`,
5898
+ `Fix the asset in the source repo, or ask the owner to fix it and push`
5899
+ )
5615
5900
  );
5616
5901
  }
5617
5902
  }
@@ -5775,22 +6060,29 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
5775
6060
  const harnessNamed = this.global && (this.harnessesOverride?.length ?? 0) > 0;
5776
6061
  if (harnessNamed && opts?.only && opts.onDroppedCopy)
5777
6062
  this.reportDroppedCopies(parsed, opts.onDroppedCopy);
5778
- const deployed = [
5779
- ...new Set(
5780
- this.targetHarnesses().flatMap(
5781
- (t) => deployAll(
5782
- harnessNamed ? entries : this.entriesForHarness(entries, t),
5783
- repositories,
5784
- patches,
5785
- this.deployOptsFor(t, opts?.link, opts?.onSecretFile, {
5786
- refresh: true,
5787
- onDrift: () => {
5788
- }
5789
- })
6063
+ const willBind = opts?.preferLockedLibrary ? void 0 : this.bindAgentInstance(entries, parsed, false);
6064
+ this.pendingAgentBinding = willBind && willBind.keptRef === void 0 ? parsed.name : void 0;
6065
+ let deployed;
6066
+ try {
6067
+ deployed = [
6068
+ ...new Set(
6069
+ this.targetHarnesses().flatMap(
6070
+ (t) => deployAll(
6071
+ harnessNamed ? entries : this.entriesForHarness(entries, t),
6072
+ repositories,
6073
+ patches,
6074
+ this.deployOptsFor(t, opts?.link, opts?.onSecretFile, {
6075
+ refresh: true,
6076
+ onDrift: () => {
6077
+ }
6078
+ })
6079
+ )
5790
6080
  )
5791
6081
  )
5792
- )
5793
- ];
6082
+ ];
6083
+ } finally {
6084
+ this.pendingAgentBinding = void 0;
6085
+ }
5794
6086
  this.sweepLegacyOmpCopies(entries);
5795
6087
  if (opts?.onLibraryOrigin) {
5796
6088
  for (const e of lib.entries) {
@@ -5814,7 +6106,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
5814
6106
  else if (bound) opts?.onAgentBound?.(bound.id, bound.ref);
5815
6107
  }
5816
6108
  await this.renderHarnessMcpConfig();
5817
- await this.renderAgentInstances();
6109
+ await this.renderAgentInstances({ prune: true });
5818
6110
  if (resolved.length > 0 || lib.entries.length > 0) {
5819
6111
  await this.warnUncommittedLibraryAssets(lib);
5820
6112
  const libraryLock = await this.libraryLockEntries(lib);
@@ -6233,7 +6525,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
6233
6525
  if (!parsed) continue;
6234
6526
  const component = this.installTarget(parsed.kind);
6235
6527
  if (!component) continue;
6236
- if (!isDeployed(component, parsed.name, this.harness, this.global, this.projectDir)) {
6528
+ if (!isAssetDeployed(component, parsed.name, this.harness, this.global, this.projectDir)) {
6237
6529
  out.push(ref);
6238
6530
  }
6239
6531
  }
@@ -6394,7 +6686,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
6394
6686
  if (!component) return void 0;
6395
6687
  const current = this.entryHarnessRecord(target.kind, target.name, target.publisher) ?? this.defaultGlobalHarnesses();
6396
6688
  const left = current.filter((h) => !this.harnessesOverride?.includes(h));
6397
- const holding = left.filter((h) => isDeployed(component, target.name, h, true));
6689
+ const holding = left.filter((h) => isAssetDeployed(component, target.name, h, true));
6398
6690
  return holding.length > 0 ? holding : void 0;
6399
6691
  }
6400
6692
  /** Limit the declared global entry of `target` to `harnesses` (`~/.skaile/skaile.yaml`). */
@@ -6776,7 +7068,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
6776
7068
  if (!component) {
6777
7069
  state = "installed";
6778
7070
  } else {
6779
- const onDisk = isDeployed(
7071
+ const onDisk = isAssetDeployed(
6780
7072
  component,
6781
7073
  parsed.name,
6782
7074
  this.harness,
@@ -6941,7 +7233,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
6941
7233
  state = "declared";
6942
7234
  } else {
6943
7235
  const component = this.installTarget(parsed.kind);
6944
- state = !component || isDeployed(component, parsed.name, harness, true) ? "installed" : "drift";
7236
+ state = !component || isAssetDeployed(component, parsed.name, harness, true) ? "installed" : "drift";
6945
7237
  }
6946
7238
  out.push({ ref, kind: parsed.kind, name: parsed.name, state, harness });
6947
7239
  }
@@ -7218,7 +7510,25 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
7218
7510
  const decl = repositories[slug];
7219
7511
  if (!decl) continue;
7220
7512
  const status = checkRepoStatus(decl, slug, this.reposDir);
7513
+ if (status.kind === "remote" && !status.localHead && status.error === "Not cloned yet" && decl.path !== void 0 && existsSync(decl.path) && readdirSync(decl.path).length > 0) {
7514
+ this.unreachableSources.push({
7515
+ name: sourceShortName(src.url),
7516
+ url: src.url,
7517
+ reason: "its clone folder holds no git checkout; run `skaile source sync` to clone it again",
7518
+ notCompared: true
7519
+ });
7520
+ continue;
7521
+ }
7221
7522
  if (status.kind !== "remote" || !status.localHead) continue;
7523
+ if (status.cloneOrigin !== void 0) {
7524
+ this.unreachableSources.push({
7525
+ name: sourceShortName(src.url),
7526
+ url: src.url,
7527
+ reason: status.error ?? "clone origin differs from the declared url",
7528
+ notCompared: true
7529
+ });
7530
+ continue;
7531
+ }
7222
7532
  if (status.error !== void 0) {
7223
7533
  this.unreachableSources.push({
7224
7534
  name: sourceShortName(src.url),
@@ -7350,6 +7660,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
7350
7660
  }
7351
7661
  await this.addRekeyRows(lock, result);
7352
7662
  await this.addPinnedRows(lock, result);
7663
+ await this.probeStoreOrigins();
7353
7664
  return this.addLockGapRows(result);
7354
7665
  }
7355
7666
  /**
@@ -7398,10 +7709,23 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
7398
7709
  continue;
7399
7710
  }
7400
7711
  let latest;
7712
+ const storeOrigin = lockedKey ? lock.assets[lockedKey]?.origin === "store" : false;
7713
+ const failuresBefore = this.storeFailureCount;
7714
+ this.quietStoreLookups = storeOrigin;
7401
7715
  try {
7402
7716
  latest = (await this.availableVersions(parsed, stores))[0];
7403
7717
  } catch {
7404
7718
  continue;
7719
+ } finally {
7720
+ this.quietStoreLookups = false;
7721
+ }
7722
+ if (storeOrigin && this.storeFailureCount !== failuresBefore) {
7723
+ this.storeUnchecked.push({
7724
+ ref: `${parsed.kind}:@${publisher}/${parsed.name}#${parsed.pin}`,
7725
+ reason: [...this.storeFailures.keys()].every((url) => this.airGappedStores.has(url)) ? "air-gapped" : "unreachable",
7726
+ detail: [...this.storeFailures.values()].join("; ")
7727
+ });
7728
+ continue;
7405
7729
  }
7406
7730
  if (!latest || isPseudoVersion(latest)) continue;
7407
7731
  if (!gt(coerceVersion(latest), coerceVersion(locked))) continue;
@@ -7416,6 +7740,49 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
7416
7740
  });
7417
7741
  }
7418
7742
  }
7743
+ /**
7744
+ * Ask the stores about every locked asset whose lock entry says `origin: store`, and record
7745
+ * those no store could be asked about (the URL did not answer, or the client is air-gapped)
7746
+ * for {@link takeStoreNotChecked}. `outdated` runs it, and so do `check` and `doctor`, which
7747
+ * otherwise never ask a store: without it a dead store reads as "everything is fine".
7748
+ * A store that answers, and a client that skips the store on purpose
7749
+ * (`catalogUrl: ''`, `--no-catalog`), record nothing. A ref already recorded is not asked again.
7750
+ */
7751
+ async probeStoreOrigins() {
7752
+ const lock = this.tryReadLock();
7753
+ if (!lock) return;
7754
+ const { stores } = this.loadConfig();
7755
+ const seen = new Set(this.storeUnchecked.map((n) => n.ref.split("#")[0]));
7756
+ for (const [key, entry] of Object.entries(lock.assets)) {
7757
+ if (entry.origin !== "store") continue;
7758
+ const id = parseCanonicalLockKey(key);
7759
+ if (!id.version || !id.publisher || isPseudoVersion(id.version)) continue;
7760
+ const identity = `${id.kind}:@${id.publisher.replace(/^@/, "")}/${id.name}`;
7761
+ if (seen.has(identity)) continue;
7762
+ let parsed;
7763
+ try {
7764
+ parsed = parseAssetRef(`${identity}#${id.version}`);
7765
+ } catch {
7766
+ continue;
7767
+ }
7768
+ const failuresBefore = this.storeFailureCount;
7769
+ this.quietStoreLookups = true;
7770
+ try {
7771
+ await this.availableVersions(parsed, stores);
7772
+ } catch {
7773
+ continue;
7774
+ } finally {
7775
+ this.quietStoreLookups = false;
7776
+ }
7777
+ if (this.storeFailureCount === failuresBefore) continue;
7778
+ seen.add(identity);
7779
+ this.storeUnchecked.push({
7780
+ ref: `${identity}#${id.version}`,
7781
+ reason: [...this.storeFailures.keys()].every((url) => this.airGappedStores.has(url)) ? "air-gapped" : "unreachable",
7782
+ detail: [...this.storeFailures.values()].join("; ")
7783
+ });
7784
+ }
7785
+ }
7419
7786
  /**
7420
7787
  * List a source asset locked under a `0.0.0-sha.<commit>` key whose file now declares a
7421
7788
  * version: the next `install` or `update` re-keys it (`replaced 0.0.0-sha.7de3555 → 0.2.0`),
@@ -7914,7 +8281,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
7914
8281
  const dep = memberIdentity(depToStr(req));
7915
8282
  if (!dep) continue;
7916
8283
  const depComponent = this.installTarget(dep.kind);
7917
- if (depComponent && !isDeployed(depComponent, dep.name, this.harness, this.global, this.projectDir)) {
8284
+ if (depComponent && !isAssetDeployed(depComponent, dep.name, this.harness, this.global, this.projectDir)) {
7918
8285
  const inRepos = await resolveAsset({ kind: dep.kind, name: dep.name }, repositories, this.reposDir, {
7919
8286
  knownKinds: this.knownKinds
7920
8287
  }) !== null;
@@ -8134,6 +8501,20 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
8134
8501
  unreadableSource: true
8135
8502
  });
8136
8503
  }
8504
+ for (const decl of Object.values(this.loadConfig().repositories)) {
8505
+ if (!decl.url || decl.factory || !decl.path) continue;
8506
+ const actual = cloneOriginMismatch(decl.path, decl.url);
8507
+ if (actual === void 0) continue;
8508
+ const reason = `clone origin ${actual} differs from declared ${decl.url.replace(/[^/\s@]+@/g, "***@")}`;
8509
+ gaps.push({
8510
+ type: "source",
8511
+ ref: decl.url,
8512
+ reason,
8513
+ message: `source ${sourceShortName(decl.url)}: ${reason}`,
8514
+ manualFix: true,
8515
+ unreadableSource: true
8516
+ });
8517
+ }
8137
8518
  for (const u of unboundAgentInstances(this.projectDir, this.harness)) {
8138
8519
  const reason = u.ref.startsWith("agent:") ? await this.unboundAgentReason(u.id, u.ref) : `is bound by agent instance "${u.id}" but resolves to no agent.yaml \u2014 fix the path, or drop the binding from skaile.yaml`;
8139
8520
  gaps.push({
@@ -8167,6 +8548,33 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
8167
8548
  return void 0;
8168
8549
  }
8169
8550
  }
8551
+ /**
8552
+ * The agent instances whose `ref` binds to no agent and that the install about to run does not
8553
+ * deploy (`entries`), worded as `renderAgentInstances` words them (`errors`, and the resolver's
8554
+ * own text in `details` for `--verbose`). The install cannot fix them, and its instance render
8555
+ * after the deploy would end the run `Failed` having rewritten files. A ref the `entries` hold
8556
+ * binds once they are deployed, so it is no cause.
8557
+ */
8558
+ async unboundInstanceErrors(entries) {
8559
+ const errors = [];
8560
+ const details = [];
8561
+ for (const u of unboundAgentInstances(this.projectDir, this.harness)) {
8562
+ if (!u.ref.startsWith("agent:")) {
8563
+ errors.push(u.error);
8564
+ continue;
8565
+ }
8566
+ const want = parseRefTolerant(u.ref);
8567
+ const wantPublisher = want?.publisher?.replace(/^@/, "");
8568
+ const deployedNow = entries.some(
8569
+ (e) => e.kind === "agent" && e.name === want?.name && (!wantPublisher || !e.publisher || e.publisher.replace(/^@/, "") === wantPublisher)
8570
+ );
8571
+ if (deployedNow) continue;
8572
+ details.push(u.error);
8573
+ const { lead, advice } = await this.unboundAgentAdvice(u.ref);
8574
+ errors.push(`agent instance "${u.id}" is bound to ${u.ref} but ${lead} \u2014 ${advice}`);
8575
+ }
8576
+ return { errors, details };
8577
+ }
8170
8578
  /**
8171
8579
  * Why the `agent:` ref of agent instance `id` binds to nothing, as the phrase that follows
8172
8580
  * the ref in a {@link LockGap}; see {@link AssetManager.unboundAgentAdvice}.
@@ -8572,10 +8980,14 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
8572
8980
  */
8573
8981
  withRenderedAgents(lock, keepComposedOf) {
8574
8982
  if (this.global) return lock;
8983
+ const noAssetFile = /* @__PURE__ */ new Set([
8984
+ ...boundAgentNames(this.projectDir),
8985
+ ...runRoleAgentNames(this.projectDir)
8986
+ ]);
8575
8987
  for (const [key, entry] of Object.entries(lock.assets)) {
8576
8988
  if (entry.rendered || entry.library?.installed) continue;
8577
8989
  const { kind, name } = parseCanonicalLockKey(key);
8578
- if (!kind || !name || this.installTarget(kind) !== "agent") continue;
8990
+ if (!kind || !name || this.installTarget(kind) !== "agent" || noAssetFile.has(name)) continue;
8579
8991
  const rendered = this.renderedAgentFiles(name);
8580
8992
  if (rendered.length > 0) entry.rendered = rendered;
8581
8993
  }
@@ -8685,37 +9097,94 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
8685
9097
  return out.sort((a, b) => a.path.localeCompare(b.path));
8686
9098
  }
8687
9099
  /**
8688
- * The rendered native files of every locked agent whose lock entry records no `rendered:`
8689
- * (a lock an older CLI wrote), as path → sha256, taken before a deploy. `check` cannot tell
8690
- * such a file from a stale one, so {@link rewrittenAgentFiles} compares it afterwards.
8691
- * Project mode only.
9100
+ * The lock key of the agent entry an agent instance's `ref` names, or `undefined` when no locked
9101
+ * agent matches (a path ref has no entry).
8692
9102
  */
8693
- unrecordedAgentFiles(lock) {
8694
- const out = /* @__PURE__ */ new Map();
8695
- if (this.global || !lock) return out;
9103
+ agentKeyOfRef(agentKeys, ref) {
9104
+ const want = parseRefTolerant(ref);
9105
+ if (!want || want.kind !== "agent") return void 0;
9106
+ const wantPublisher = want.publisher?.replace(/^@/, "");
9107
+ return agentKeys.find((k) => {
9108
+ const p = parseCanonicalLockKey(k);
9109
+ return p.name === want.name && (wantPublisher === void 0 || p.publisher === wantPublisher);
9110
+ });
9111
+ }
9112
+ /**
9113
+ * The rendered native files of every locked agent that the lock does not list under
9114
+ * `rendered:` (a lock an older CLI wrote), as path → sha256 per lock key, taken before a
9115
+ * deploy. `check` cannot tell such a file from a stale one, so {@link changedRenderings}
9116
+ * compares it afterwards. `agent` holds the asset-named files of an entry with no `rendered:`
9117
+ * at all (5.11.0 and older); `instance` the files of agent instances the entry's `rendered:`
9118
+ * does not list yet (5.13.0 and older), which the instance render rewrites. Project mode only.
9119
+ */
9120
+ unrecordedRenderings(lock) {
9121
+ const agent = /* @__PURE__ */ new Map();
9122
+ const instance = /* @__PURE__ */ new Map();
9123
+ if (this.global || !lock) return { agent, instance };
9124
+ const agentKeys = [];
9125
+ const own = /* @__PURE__ */ new Set();
8696
9126
  for (const [key, entry] of Object.entries(lock.assets)) {
8697
- if (entry.rendered || entry.library?.installed) continue;
9127
+ if (entry.library?.installed) continue;
8698
9128
  const { kind, name } = parseCanonicalLockKey(key);
8699
9129
  if (!kind || !name || this.installTarget(kind) !== "agent") continue;
9130
+ agentKeys.push(key);
8700
9131
  const files = this.renderedAgentFiles(name);
8701
- if (files.length > 0) out.set(key, new Map(files.map((f) => [f.path, f.sha256])));
9132
+ for (const f of files) own.add(f.path);
9133
+ if (!entry.rendered && files.length > 0) {
9134
+ agent.set(key, new Map(files.map((f) => [f.path, f.sha256])));
9135
+ }
8702
9136
  }
8703
- return out;
9137
+ for (const bound of renderedInstanceFiles(this.projectDir, this.harness)) {
9138
+ const key = this.agentKeyOfRef(agentKeys, bound.ref);
9139
+ if (!key) continue;
9140
+ const listed = new Set((lock.assets[key]?.rendered ?? []).map((f) => f.path));
9141
+ const files = [];
9142
+ for (const rel of bound.files) this.hashTree(join(this.projectDir, rel), files);
9143
+ const held = instance.get(key) ?? /* @__PURE__ */ new Map();
9144
+ for (const f of files) {
9145
+ if (!listed.has(f.path) && !own.has(f.path)) held.set(f.path, f.sha256);
9146
+ }
9147
+ if (held.size > 0) instance.set(key, held);
9148
+ }
9149
+ return { agent, instance };
8704
9150
  }
8705
9151
  /**
8706
- * The agent files a deploy changed that {@link unrecordedAgentFiles} saw before it: one row
8707
- * per locked agent, listing the project-relative paths whose bytes differ now. A render the
8708
- * CLI changed (the 5.12.0 abilities block) otherwise reaches the user as a silent rewrite.
9152
+ * The notice `check` and `outdated` print for a lock written before it listed the rendered
9153
+ * agent files and the files of agent instances: the next `install`, `add` or `update`
9154
+ * adds the list and rewrites those files from the render, so a hand edit of one is lost.
9155
+ * Empty for a current lock, and in global mode.
8709
9156
  */
8710
- rewrittenAgentFiles(before) {
8711
- const out = [];
8712
- for (const [key, files] of before) {
9157
+ legacyLockNotices() {
9158
+ const before = this.unrecordedRenderings(this.tryReadLock());
9159
+ if (before.agent.size === 0 && before.instance.size === 0) return [];
9160
+ return ["lock predates instance files: run skaile update"];
9161
+ }
9162
+ /**
9163
+ * What a deploy changed among the files {@link unrecordedRenderings} saw before it. `rewritten`
9164
+ * is one row per locked agent whose asset-named files differ now: a render the CLI changed (the
9165
+ * 5.12.0 abilities block) otherwise reaches the user as a silent rewrite. `restored` is one row
9166
+ * per agent whose instance files differ now: the render replaced them, a hand edit included.
9167
+ */
9168
+ changedRenderings(before) {
9169
+ const rewritten = [];
9170
+ const restored = [];
9171
+ for (const [key, files] of before.agent) {
8713
9172
  const { name } = parseCanonicalLockKey(key);
8714
9173
  if (!name) continue;
8715
9174
  const changed = this.renderedAgentFiles(name).filter((f) => files.has(f.path) && files.get(f.path) !== f.sha256).map((f) => f.path);
8716
- if (changed.length > 0) out.push({ ref: key, files: changed });
9175
+ if (changed.length > 0) rewritten.push({ ref: key, files: changed });
8717
9176
  }
8718
- return out;
9177
+ for (const [key, files] of before.instance) {
9178
+ const changed = [];
9179
+ for (const [file, sha] of files) {
9180
+ try {
9181
+ if (computeHash(join(this.projectDir, file)) !== sha) changed.push(file);
9182
+ } catch {
9183
+ }
9184
+ }
9185
+ if (changed.length > 0) restored.push({ ref: key, restored: changed.sort(), removed: [] });
9186
+ }
9187
+ return { rewritten, restored };
8719
9188
  }
8720
9189
  /**
8721
9190
  * The {@link RestoredAsset} rows for the drifted copies (see {@link lockedCopyDrift}) a
@@ -8985,7 +9454,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
8985
9454
  const { publisher, kind, name } = parseCanonicalLockKey(key);
8986
9455
  const component = kind ? this.installTarget(kind) : void 0;
8987
9456
  if (!kind || !name || !component || named.has(`${kind}:${name}`)) continue;
8988
- if (isDeployed(component, name, this.harness, this.global, this.projectDir)) {
9457
+ if (isAssetDeployed(component, name, this.harness, this.global, this.projectDir)) {
8989
9458
  const renderedGone = component === "agent" && !this.global && (entry.rendered ?? []).some((f) => !existsSync(join(this.projectDir, f.path)));
8990
9459
  if (!renderedGone) continue;
8991
9460
  }
@@ -9502,7 +9971,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
9502
9971
  * @returns the instance id and ref bound; the id with `keptRef` (what that id binds instead)
9503
9972
  * when the id is taken by another agent; `undefined` when nothing was bound and nothing needs saying.
9504
9973
  */
9505
- bindAgentInstance(entries, parsed) {
9974
+ bindAgentInstance(entries, parsed, write = true) {
9506
9975
  if (this.global || parsed.kind !== "agent") return void 0;
9507
9976
  const configPath = join(this.stateRoot, "skaile.yaml");
9508
9977
  if (!existsSync(configPath)) return void 0;
@@ -9537,7 +10006,7 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
9537
10006
  return { id, ref, keptRef: primary };
9538
10007
  }
9539
10008
  raw.agents = { ...instances, [id]: { ref } };
9540
- writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
10009
+ if (write) writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
9541
10010
  return { id, ref };
9542
10011
  }
9543
10012
  /** The refs `skaile.yaml` binds agent instances to: every `agents.<id>.ref` and `agent.definition`. Project mode only. */
@@ -9622,5 +10091,5 @@ Fix the asset in the source repo, then run \`skaile source sync\` and add it aga
9622
10091
  };
9623
10092
 
9624
10093
  export { AssetManager, LibraryEntryError, MissingManifestError, installAgentInstances, labelDiffHeaders, mcpNotRunnableReason, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, setLibraryAssetCheck, setRenamedEntryLookup, softDepName };
9625
- //# sourceMappingURL=chunk-JRVQV7WC.js.map
9626
- //# sourceMappingURL=chunk-JRVQV7WC.js.map
10094
+ //# sourceMappingURL=chunk-ZDTDS62B.js.map
10095
+ //# sourceMappingURL=chunk-ZDTDS62B.js.map