@skaile/workspaces 5.19.0 → 6.1.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 (757) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +8 -8
  3. package/dist/app-sdk/index.js +1 -1
  4. package/dist/{asset-feeds-QGLI3AXI.js → asset-feeds-HJFV7UPW.js} +32 -24
  5. package/dist/asset-feeds-HJFV7UPW.js.map +1 -0
  6. package/dist/asset-manager/catalog-deployer.js +12 -12
  7. package/dist/asset-manager/index.js +19 -19
  8. package/dist/asset-manager/installer.js +14 -14
  9. package/dist/asset-manager/renderers.js +13 -13
  10. package/dist/asset-manager/src/index.d.ts +214 -27
  11. package/dist/asset-manager/src/index.d.ts.map +1 -1
  12. package/dist/asset-manager/src/install-agent.d.ts +2 -2
  13. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  14. package/dist/asset-manager/src/install-instances.d.ts +8 -8
  15. package/dist/asset-manager/src/install-instances.d.ts.map +1 -1
  16. package/dist/asset-manager/src/installer.d.ts +34 -3
  17. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  18. package/dist/asset-manager/src/mcp-config.d.ts +35 -14
  19. package/dist/asset-manager/src/mcp-config.d.ts.map +1 -1
  20. package/dist/asset-manager/src/renderers.d.ts +12 -12
  21. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  22. package/dist/bridge/codex-app-server.js +2 -2
  23. package/dist/bridge/harnesses/claude-sdk.d.ts +2 -0
  24. package/dist/bridge/{drivers → harnesses}/claude-sdk.js +69 -73
  25. package/dist/bridge/harnesses/claude-sdk.js.map +1 -0
  26. package/dist/bridge/{drivers/gemini.d.ts → harnesses/codex.d.ts} +1 -1
  27. package/dist/bridge/{drivers → harnesses}/codex.js +53 -53
  28. package/dist/bridge/harnesses/codex.js.map +1 -0
  29. package/dist/bridge/{drivers/claude-sdk.d.ts → harnesses/continue.d.ts} +1 -1
  30. package/dist/bridge/{drivers → harnesses}/continue.js +30 -30
  31. package/dist/bridge/harnesses/continue.js.map +1 -0
  32. package/dist/bridge/{drivers → harnesses}/echo.d.ts +1 -1
  33. package/dist/bridge/{drivers → harnesses}/echo.js +27 -27
  34. package/dist/bridge/harnesses/echo.js.map +1 -0
  35. package/dist/bridge/{drivers/continue.d.ts → harnesses/gemini.d.ts} +1 -1
  36. package/dist/bridge/harnesses/gemini.js +18 -0
  37. package/dist/bridge/{drivers → harnesses}/goose.d.ts +1 -1
  38. package/dist/bridge/{drivers → harnesses}/goose.js +30 -30
  39. package/dist/bridge/harnesses/goose.js.map +1 -0
  40. package/dist/bridge/{drivers → harnesses}/omp.d.ts +1 -1
  41. package/dist/bridge/{drivers → harnesses}/omp.js +31 -31
  42. package/dist/bridge/harnesses/omp.js.map +1 -0
  43. package/dist/bridge/{drivers → harnesses}/opencode.d.ts +1 -1
  44. package/dist/bridge/{drivers → harnesses}/opencode.js +31 -31
  45. package/dist/bridge/harnesses/opencode.js.map +1 -0
  46. package/dist/bridge/{drivers → harnesses}/qwen.d.ts +1 -1
  47. package/dist/bridge/{drivers → harnesses}/qwen.js +20 -20
  48. package/dist/bridge/harnesses/qwen.js.map +1 -0
  49. package/dist/bridge/index.js +25 -25
  50. package/dist/bridge/src/agent-exec.d.ts +2 -2
  51. package/dist/bridge/src/agent-transcript.d.ts +1 -1
  52. package/dist/bridge/src/agent-transcript.d.ts.map +1 -1
  53. package/dist/bridge/src/approval-card.d.ts +3 -3
  54. package/dist/bridge/src/capability-dispatch.d.ts +5 -5
  55. package/dist/bridge/src/claude-sdk-surface.d.ts +17 -0
  56. package/dist/bridge/src/claude-sdk-surface.d.ts.map +1 -0
  57. package/dist/bridge/src/cloud.d.ts +4 -4
  58. package/dist/bridge/src/codex/config-toml.d.ts +3 -3
  59. package/dist/bridge/src/codex/friendly-error.d.ts +1 -1
  60. package/dist/bridge/src/codex/friendly-error.d.ts.map +1 -1
  61. package/dist/bridge/src/codex/{managed-driver.d.ts → managed-harness.d.ts} +5 -5
  62. package/dist/bridge/src/codex/managed-harness.d.ts.map +1 -0
  63. package/dist/bridge/src/codex/native-approvals.d.ts +1 -1
  64. package/dist/bridge/src/codex/native-approvals.d.ts.map +1 -1
  65. package/dist/bridge/src/error-classifier.d.ts +7 -7
  66. package/dist/bridge/src/{driver-capabilities.d.ts → harness-capabilities.d.ts} +18 -18
  67. package/dist/bridge/src/harness-capabilities.d.ts.map +1 -0
  68. package/dist/bridge/src/harness-model-check.d.ts +40 -0
  69. package/dist/bridge/src/harness-model-check.d.ts.map +1 -0
  70. package/dist/bridge/src/{drivers → harnesses}/_subprocess-cli.d.ts +8 -8
  71. package/dist/bridge/src/harnesses/_subprocess-cli.d.ts.map +1 -0
  72. package/dist/bridge/src/{drivers → harnesses}/claude-context-usage.d.ts +5 -5
  73. package/dist/bridge/src/harnesses/claude-context-usage.d.ts.map +1 -0
  74. package/dist/bridge/src/{drivers → harnesses}/claude-sdk.d.ts +27 -27
  75. package/dist/bridge/src/harnesses/claude-sdk.d.ts.map +1 -0
  76. package/dist/bridge/src/{drivers → harnesses}/claude-self-turns.d.ts +5 -5
  77. package/dist/bridge/src/harnesses/claude-self-turns.d.ts.map +1 -0
  78. package/dist/bridge/src/{drivers → harnesses}/claude-tool-allowlist.d.ts +4 -4
  79. package/dist/bridge/src/harnesses/claude-tool-allowlist.d.ts.map +1 -0
  80. package/dist/bridge/src/{drivers → harnesses}/codex.d.ts +14 -14
  81. package/dist/bridge/src/harnesses/codex.d.ts.map +1 -0
  82. package/dist/bridge/src/{drivers → harnesses}/continue.d.ts +12 -12
  83. package/dist/bridge/src/harnesses/continue.d.ts.map +1 -0
  84. package/dist/bridge/src/{drivers → harnesses}/echo.d.ts +16 -16
  85. package/dist/bridge/src/harnesses/echo.d.ts.map +1 -0
  86. package/dist/bridge/src/{drivers → harnesses}/flow-script.d.ts +9 -9
  87. package/dist/bridge/src/harnesses/flow-script.d.ts.map +1 -0
  88. package/dist/bridge/src/{drivers → harnesses}/gemini.d.ts +15 -15
  89. package/dist/bridge/src/harnesses/gemini.d.ts.map +1 -0
  90. package/dist/bridge/src/{drivers → harnesses}/goose.d.ts +10 -10
  91. package/dist/bridge/src/harnesses/goose.d.ts.map +1 -0
  92. package/dist/bridge/src/{drivers → harnesses}/omp-models-yml.d.ts +12 -12
  93. package/dist/bridge/src/harnesses/omp-models-yml.d.ts.map +1 -0
  94. package/dist/bridge/src/{drivers → harnesses}/omp.d.ts +23 -23
  95. package/dist/bridge/src/harnesses/omp.d.ts.map +1 -0
  96. package/dist/bridge/src/{drivers → harnesses}/opencode.d.ts +11 -11
  97. package/dist/bridge/src/harnesses/opencode.d.ts.map +1 -0
  98. package/dist/bridge/src/{drivers → harnesses}/qwen.d.ts +12 -12
  99. package/dist/bridge/src/harnesses/qwen.d.ts.map +1 -0
  100. package/dist/bridge/src/{drivers → harnesses}/recovery-policy.d.ts +4 -4
  101. package/dist/bridge/src/harnesses/recovery-policy.d.ts.map +1 -0
  102. package/dist/bridge/src/{drivers → harnesses}/resume-probe.d.ts +3 -3
  103. package/dist/bridge/src/harnesses/resume-probe.d.ts.map +1 -0
  104. package/dist/bridge/src/{drivers → harnesses}/sanitize-assistant-text.d.ts +1 -1
  105. package/dist/bridge/src/harnesses/sanitize-assistant-text.d.ts.map +1 -0
  106. package/dist/bridge/src/{drivers → harnesses}/scrub-transcript.d.ts +1 -1
  107. package/dist/bridge/src/harnesses/scrub-transcript.d.ts.map +1 -0
  108. package/dist/bridge/src/index.d.ts +5 -4
  109. package/dist/bridge/src/index.d.ts.map +1 -1
  110. package/dist/bridge/src/logger.d.ts +4 -4
  111. package/dist/bridge/src/models.d.ts +1 -1
  112. package/dist/bridge/src/normalizer.d.ts +5 -3
  113. package/dist/bridge/src/normalizer.d.ts.map +1 -1
  114. package/dist/bridge/src/provider-materialize/continue-config-yaml.d.ts +5 -5
  115. package/dist/bridge/src/provider-materialize/continue-config-yaml.d.ts.map +1 -1
  116. package/dist/bridge/src/provider-materialize/credential-env.d.ts +3 -3
  117. package/dist/bridge/src/provider-materialize/{env-drivers.d.ts → env-harnesses.d.ts} +19 -19
  118. package/dist/bridge/src/provider-materialize/env-harnesses.d.ts.map +1 -0
  119. package/dist/bridge/src/provider-materialize/goose-custom-providers.d.ts +5 -5
  120. package/dist/bridge/src/provider-materialize/goose-custom-providers.d.ts.map +1 -1
  121. package/dist/bridge/src/provider-materialize/opencode-config.d.ts +7 -7
  122. package/dist/bridge/src/provider-materialize/opencode-config.d.ts.map +1 -1
  123. package/dist/bridge/src/provider-materialize/session-config-home.d.ts +5 -5
  124. package/dist/bridge/src/provider-materialize/session-config-home.d.ts.map +1 -1
  125. package/dist/bridge/src/provider-registry-derive.d.ts +4 -4
  126. package/dist/bridge/src/provider-registry-derive.d.ts.map +1 -1
  127. package/dist/bridge/src/reconfigure-ledger.d.ts +8 -8
  128. package/dist/bridge/src/reconfigure-ledger.d.ts.map +1 -1
  129. package/dist/bridge/src/registry.d.ts +34 -41
  130. package/dist/bridge/src/registry.d.ts.map +1 -1
  131. package/dist/bridge/src/runner-private-env.d.ts +2 -2
  132. package/dist/bridge/src/runtime.d.ts +11 -11
  133. package/dist/bridge/src/runtime.d.ts.map +1 -1
  134. package/dist/bridge/src/types.d.ts +158 -158
  135. package/dist/bridge/src/types.d.ts.map +1 -1
  136. package/dist/{chunk-7NT4F6SR.js → chunk-2LAPHLDH.js} +587 -521
  137. package/dist/chunk-2LAPHLDH.js.map +1 -0
  138. package/dist/{chunk-25ZVWL2R.js → chunk-3GMOPFWH.js} +4 -4
  139. package/dist/{chunk-25ZVWL2R.js.map → chunk-3GMOPFWH.js.map} +1 -1
  140. package/dist/{chunk-X5YPJV4N.js → chunk-3MWQKQUB.js} +2 -2
  141. package/dist/{chunk-X5YPJV4N.js.map → chunk-3MWQKQUB.js.map} +1 -1
  142. package/dist/{chunk-EPBKISS5.js → chunk-3TG2NV2F.js} +2 -2
  143. package/dist/chunk-3TG2NV2F.js.map +1 -0
  144. package/dist/{chunk-L2AMXONH.js → chunk-3X7VTCPG.js} +2 -2
  145. package/dist/chunk-3X7VTCPG.js.map +1 -0
  146. package/dist/{chunk-VIM3PWZM.js → chunk-4FVIT5DI.js} +3 -3
  147. package/dist/{chunk-VIM3PWZM.js.map → chunk-4FVIT5DI.js.map} +1 -1
  148. package/dist/{chunk-IF6IA3PZ.js → chunk-4MUDQCBP.js} +4 -4
  149. package/dist/{chunk-IF6IA3PZ.js.map → chunk-4MUDQCBP.js.map} +1 -1
  150. package/dist/{chunk-MKRWN7XP.js → chunk-5J4NPGFM.js} +5 -5
  151. package/dist/chunk-5J4NPGFM.js.map +1 -0
  152. package/dist/{chunk-5TBFN46Z.js → chunk-5KRMNUL4.js} +4 -4
  153. package/dist/chunk-5KRMNUL4.js.map +1 -0
  154. package/dist/{chunk-7SCS64BG.js → chunk-5Y2KGB4H.js} +109 -74
  155. package/dist/chunk-5Y2KGB4H.js.map +1 -0
  156. package/dist/{chunk-YIF2IJUA.js → chunk-6GWSDPBP.js} +3 -3
  157. package/dist/{chunk-YIF2IJUA.js.map → chunk-6GWSDPBP.js.map} +1 -1
  158. package/dist/{chunk-WST6UITC.js → chunk-6YR4ALVX.js} +17 -17
  159. package/dist/chunk-6YR4ALVX.js.map +1 -0
  160. package/dist/{chunk-YROR332M.js → chunk-7DN6JKP2.js} +2 -2
  161. package/dist/chunk-7DN6JKP2.js.map +1 -0
  162. package/dist/{chunk-IZCR27MU.js → chunk-7EKQDY2T.js} +3 -3
  163. package/dist/chunk-7EKQDY2T.js.map +1 -0
  164. package/dist/chunk-7HX6FNKL.js +317 -0
  165. package/dist/chunk-7HX6FNKL.js.map +1 -0
  166. package/dist/{chunk-COJIL7G4.js → chunk-7LP7RCZI.js} +7 -7
  167. package/dist/chunk-7LP7RCZI.js.map +1 -0
  168. package/dist/{chunk-2PBSAH3Z.js → chunk-AATHJRKL.js} +4 -4
  169. package/dist/{chunk-2PBSAH3Z.js.map → chunk-AATHJRKL.js.map} +1 -1
  170. package/dist/{chunk-C7WBGSBV.js → chunk-ABFPSVIS.js} +10 -10
  171. package/dist/chunk-ABFPSVIS.js.map +1 -0
  172. package/dist/{chunk-ICSCSM5D.js → chunk-ADPM6AYF.js} +3 -3
  173. package/dist/{chunk-ICSCSM5D.js.map → chunk-ADPM6AYF.js.map} +1 -1
  174. package/dist/{chunk-WOIRYY5L.js → chunk-AITJ7ELM.js} +141 -27
  175. package/dist/chunk-AITJ7ELM.js.map +1 -0
  176. package/dist/{chunk-HU5HVKY7.js → chunk-ASWTQQ7E.js} +4 -4
  177. package/dist/{chunk-HU5HVKY7.js.map → chunk-ASWTQQ7E.js.map} +1 -1
  178. package/dist/{chunk-RO6VOM6Z.js → chunk-AZ2H6R5I.js} +51 -25
  179. package/dist/chunk-AZ2H6R5I.js.map +1 -0
  180. package/dist/{chunk-I7TWVK6N.js → chunk-BBBCJSSU.js} +4 -4
  181. package/dist/{chunk-I7TWVK6N.js.map → chunk-BBBCJSSU.js.map} +1 -1
  182. package/dist/{chunk-AJ7EGIFR.js → chunk-BIRW3HOG.js} +3 -3
  183. package/dist/chunk-BIRW3HOG.js.map +1 -0
  184. package/dist/{chunk-FPHNJE4M.js → chunk-CEKW3KXP.js} +91 -30
  185. package/dist/chunk-CEKW3KXP.js.map +1 -0
  186. package/dist/{chunk-F6AA42GW.js → chunk-COYF6IG2.js} +5 -5
  187. package/dist/{chunk-F6AA42GW.js.map → chunk-COYF6IG2.js.map} +1 -1
  188. package/dist/{chunk-HT35SQZD.js → chunk-DGTI65OC.js} +30 -30
  189. package/dist/chunk-DGTI65OC.js.map +1 -0
  190. package/dist/{chunk-W4Q6CKJ5.js → chunk-DIGFA7Z5.js} +11 -11
  191. package/dist/chunk-DIGFA7Z5.js.map +1 -0
  192. package/dist/{chunk-335ENCCS.js → chunk-E572OHGY.js} +2 -2
  193. package/dist/{chunk-335ENCCS.js.map → chunk-E572OHGY.js.map} +1 -1
  194. package/dist/{chunk-Y5MBW5EU.js → chunk-EJPMNDTP.js} +3 -3
  195. package/dist/{chunk-Y5MBW5EU.js.map → chunk-EJPMNDTP.js.map} +1 -1
  196. package/dist/chunk-EX3GLAL6.js +31 -0
  197. package/dist/chunk-EX3GLAL6.js.map +1 -0
  198. package/dist/{chunk-XWOPZW26.js → chunk-FKQNBCDW.js} +38 -38
  199. package/dist/chunk-FKQNBCDW.js.map +1 -0
  200. package/dist/{chunk-6E6PKKAD.js → chunk-G5SUWZEU.js} +18 -8
  201. package/dist/chunk-G5SUWZEU.js.map +1 -0
  202. package/dist/{chunk-2GXSSZAM.js → chunk-GNZBFSRB.js} +12 -12
  203. package/dist/chunk-GNZBFSRB.js.map +1 -0
  204. package/dist/{chunk-PYJS5K7V.js → chunk-HMISULVD.js} +5 -5
  205. package/dist/{chunk-PYJS5K7V.js.map → chunk-HMISULVD.js.map} +1 -1
  206. package/dist/{chunk-IP2IPMEH.js → chunk-HPMQRAIF.js} +18 -18
  207. package/dist/chunk-HPMQRAIF.js.map +1 -0
  208. package/dist/{chunk-MRHVPQNO.js → chunk-HWNK3F3X.js} +1015 -189
  209. package/dist/chunk-HWNK3F3X.js.map +1 -0
  210. package/dist/{chunk-ZQSOJH6I.js → chunk-IHFGPHCT.js} +141 -341
  211. package/dist/chunk-IHFGPHCT.js.map +1 -0
  212. package/dist/{chunk-CQJH4G2K.js → chunk-ILLTBKDJ.js} +101 -102
  213. package/dist/chunk-ILLTBKDJ.js.map +1 -0
  214. package/dist/{chunk-FKU57Q5Q.js → chunk-IRYKRKVQ.js} +3 -3
  215. package/dist/{chunk-FKU57Q5Q.js.map → chunk-IRYKRKVQ.js.map} +1 -1
  216. package/dist/{chunk-J24CY3PF.js → chunk-J72MO2WA.js} +39 -39
  217. package/dist/chunk-J72MO2WA.js.map +1 -0
  218. package/dist/{chunk-Y56YIT6J.js → chunk-JCPD4QRM.js} +4 -4
  219. package/dist/chunk-JCPD4QRM.js.map +1 -0
  220. package/dist/{chunk-X3RMRJNR.js → chunk-JRN5QF4C.js} +8 -3
  221. package/dist/chunk-JRN5QF4C.js.map +1 -0
  222. package/dist/{chunk-K4O6L3WH.js → chunk-KNY356I3.js} +3 -3
  223. package/dist/{chunk-K4O6L3WH.js.map → chunk-KNY356I3.js.map} +1 -1
  224. package/dist/{chunk-XJVBUDDJ.js → chunk-KUQAJVYT.js} +8 -8
  225. package/dist/chunk-KUQAJVYT.js.map +1 -0
  226. package/dist/{chunk-4ZTPYIBE.js → chunk-KW37WNXY.js} +12 -12
  227. package/dist/chunk-KW37WNXY.js.map +1 -0
  228. package/dist/{chunk-MJHSLODD.js → chunk-LSI2IVFT.js} +2 -2
  229. package/dist/chunk-LSI2IVFT.js.map +1 -0
  230. package/dist/{chunk-WDXZA7QW.js → chunk-LSSYC5IC.js} +2 -2
  231. package/dist/{chunk-WDXZA7QW.js.map → chunk-LSSYC5IC.js.map} +1 -1
  232. package/dist/{chunk-WG6V4ISA.js → chunk-NB7SYQYP.js} +7 -7
  233. package/dist/{chunk-WG6V4ISA.js.map → chunk-NB7SYQYP.js.map} +1 -1
  234. package/dist/{chunk-EAZECHPM.js → chunk-NBAGV6L2.js} +5 -5
  235. package/dist/chunk-NBAGV6L2.js.map +1 -0
  236. package/dist/{chunk-JTOWA6RS.js → chunk-NUA33BYO.js} +181 -64
  237. package/dist/chunk-NUA33BYO.js.map +1 -0
  238. package/dist/{chunk-A6SMCEEE.js → chunk-QAKUD6QN.js} +11 -11
  239. package/dist/{chunk-A6SMCEEE.js.map → chunk-QAKUD6QN.js.map} +1 -1
  240. package/dist/{chunk-QG6GHTRM.js → chunk-QEULL4Q3.js} +8 -8
  241. package/dist/chunk-QEULL4Q3.js.map +1 -0
  242. package/dist/{chunk-ZX4KRWRB.js → chunk-QSYQOTWN.js} +4 -4
  243. package/dist/{chunk-ZX4KRWRB.js.map → chunk-QSYQOTWN.js.map} +1 -1
  244. package/dist/{chunk-X4ZZTHU3.js → chunk-RDTLPOPD.js} +4 -4
  245. package/dist/{chunk-X4ZZTHU3.js.map → chunk-RDTLPOPD.js.map} +1 -1
  246. package/dist/{chunk-GOCWM7FN.js → chunk-RHN5MRQO.js} +21 -4
  247. package/dist/chunk-RHN5MRQO.js.map +1 -0
  248. package/dist/{chunk-XM6T2AZ2.js → chunk-S2XHGWQC.js} +162 -124
  249. package/dist/chunk-S2XHGWQC.js.map +1 -0
  250. package/dist/{chunk-VJ7NU7GD.js → chunk-SVTMNSPI.js} +23 -6
  251. package/dist/chunk-SVTMNSPI.js.map +1 -0
  252. package/dist/{chunk-I37INEWE.js → chunk-UI745XC3.js} +10 -23
  253. package/dist/chunk-UI745XC3.js.map +1 -0
  254. package/dist/{chunk-N46LQR46.js → chunk-VMVDAZLA.js} +53 -30
  255. package/dist/chunk-VMVDAZLA.js.map +1 -0
  256. package/dist/{chunk-IG5LZ3WU.js → chunk-VTETQCR6.js} +10 -10
  257. package/dist/chunk-VTETQCR6.js.map +1 -0
  258. package/dist/{chunk-EFLKSMCO.js → chunk-VUJXZDCY.js} +5 -5
  259. package/dist/{chunk-EFLKSMCO.js.map → chunk-VUJXZDCY.js.map} +1 -1
  260. package/dist/{chunk-H6UVIKQ2.js → chunk-VYVTEMAW.js} +3 -3
  261. package/dist/{chunk-H6UVIKQ2.js.map → chunk-VYVTEMAW.js.map} +1 -1
  262. package/dist/{chunk-M3WPBTGJ.js → chunk-WD3L5QSU.js} +2 -2
  263. package/dist/{chunk-M3WPBTGJ.js.map → chunk-WD3L5QSU.js.map} +1 -1
  264. package/dist/{chunk-R6O6YWU7.js → chunk-WYZXSJBK.js} +3 -3
  265. package/dist/{chunk-R6O6YWU7.js.map → chunk-WYZXSJBK.js.map} +1 -1
  266. package/dist/{chunk-R4I3VBSS.js → chunk-X3YGUKCG.js} +5 -5
  267. package/dist/{chunk-R4I3VBSS.js.map → chunk-X3YGUKCG.js.map} +1 -1
  268. package/dist/{chunk-RPZVHXQ3.js → chunk-XFIEVEU7.js} +4 -4
  269. package/dist/chunk-XFIEVEU7.js.map +1 -0
  270. package/dist/{chunk-VSZWNUZC.js → chunk-XGULGQA3.js} +4 -4
  271. package/dist/chunk-XGULGQA3.js.map +1 -0
  272. package/dist/{chunk-Q6E6FM7P.js → chunk-XKNXPLKR.js} +6 -6
  273. package/dist/{chunk-Q6E6FM7P.js.map → chunk-XKNXPLKR.js.map} +1 -1
  274. package/dist/{chunk-7XSAW5OC.js → chunk-YLLVSR2U.js} +4 -4
  275. package/dist/{chunk-7XSAW5OC.js.map → chunk-YLLVSR2U.js.map} +1 -1
  276. package/dist/{chunk-6Z5KTFJT.js → chunk-Z3VKUWAX.js} +3 -3
  277. package/dist/{chunk-6Z5KTFJT.js.map → chunk-Z3VKUWAX.js.map} +1 -1
  278. package/dist/{chunk-5BEFNLOR.js → chunk-Z7ZEZZB6.js} +8 -8
  279. package/dist/chunk-Z7ZEZZB6.js.map +1 -0
  280. package/dist/{chunk-2LSDMJI2.js → chunk-ZAELRYKS.js} +4 -4
  281. package/dist/{chunk-2LSDMJI2.js.map → chunk-ZAELRYKS.js.map} +1 -1
  282. package/dist/{chunk-UQ33Y4DM.js → chunk-ZBHZLWV3.js} +4 -4
  283. package/dist/{chunk-UQ33Y4DM.js.map → chunk-ZBHZLWV3.js.map} +1 -1
  284. package/dist/{chunk-TIIXG3PN.js → chunk-ZDLUQLI6.js} +4 -4
  285. package/dist/{chunk-TIIXG3PN.js.map → chunk-ZDLUQLI6.js.map} +1 -1
  286. package/dist/{chunk-PHRNUTSG.js → chunk-ZFUZ5AKM.js} +4 -4
  287. package/dist/{chunk-PHRNUTSG.js.map → chunk-ZFUZ5AKM.js.map} +1 -1
  288. package/dist/{chunk-V257LUBM.js → chunk-ZHGKAZJ7.js} +251 -26
  289. package/dist/chunk-ZHGKAZJ7.js.map +1 -0
  290. package/dist/claude-code-RE46FJXI.js +10 -0
  291. package/dist/{claude-code-2PU7TITZ.js.map → claude-code-RE46FJXI.js.map} +1 -1
  292. package/dist/cli/index.js +1066 -647
  293. package/dist/cli/index.js.map +1 -1
  294. package/dist/cli/src/agent-pins.d.ts +11 -0
  295. package/dist/cli/src/agent-pins.d.ts.map +1 -1
  296. package/dist/cli/src/commands/catalog.d.ts +4 -4
  297. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  298. package/dist/cli/src/commands/complete-resolvers.d.ts.map +1 -1
  299. package/dist/cli/src/commands/config.d.ts +2 -2
  300. package/dist/cli/src/commands/config.d.ts.map +1 -1
  301. package/dist/cli/src/commands/diff.d.ts.map +1 -1
  302. package/dist/cli/src/commands/harness.d.ts +24 -0
  303. package/dist/cli/src/commands/harness.d.ts.map +1 -0
  304. package/dist/cli/src/commands/integration.d.ts +1 -1
  305. package/dist/cli/src/commands/integration.d.ts.map +1 -1
  306. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  307. package/dist/cli/src/commands/library-index.d.ts +20 -2
  308. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  309. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  310. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  311. package/dist/cli/src/commands/migrate-files.d.ts +14 -0
  312. package/dist/cli/src/commands/migrate-files.d.ts.map +1 -1
  313. package/dist/cli/src/commands/migrate-harness.d.ts +49 -0
  314. package/dist/cli/src/commands/migrate-harness.d.ts.map +1 -0
  315. package/dist/cli/src/commands/migrate.d.ts +4 -2
  316. package/dist/cli/src/commands/migrate.d.ts.map +1 -1
  317. package/dist/cli/src/commands/plugin/types.d.ts +1 -6
  318. package/dist/cli/src/commands/plugin/types.d.ts.map +1 -1
  319. package/dist/cli/src/commands/plugin-registry-cmd.d.ts +1 -1
  320. package/dist/cli/src/commands/preset-export.d.ts +1 -1
  321. package/dist/cli/src/commands/project.d.ts +20 -2
  322. package/dist/cli/src/commands/project.d.ts.map +1 -1
  323. package/dist/cli/src/commands/run.d.ts +2 -2
  324. package/dist/cli/src/commands/run.d.ts.map +1 -1
  325. package/dist/cli/src/commands/serve-preflight.d.ts +11 -11
  326. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
  327. package/dist/cli/src/commands/serve.d.ts +1 -1
  328. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  329. package/dist/cli/src/commands/session-logs/local-query.d.ts +2 -0
  330. package/dist/cli/src/commands/session-logs/local-query.d.ts.map +1 -1
  331. package/dist/cli/src/commands/source.d.ts +9 -2
  332. package/dist/cli/src/commands/source.d.ts.map +1 -1
  333. package/dist/cli/src/commands/store.d.ts.map +1 -1
  334. package/dist/cli/src/commands/update.d.ts.map +1 -1
  335. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  336. package/dist/cli/src/config-checks.d.ts +37 -0
  337. package/dist/cli/src/config-checks.d.ts.map +1 -0
  338. package/dist/cli/src/harness-error.d.ts +47 -0
  339. package/dist/cli/src/harness-error.d.ts.map +1 -0
  340. package/dist/cli/src/helpers.d.ts +5 -5
  341. package/dist/cli/src/helpers.d.ts.map +1 -1
  342. package/dist/cli/src/plugin-store/index.d.ts +2 -2
  343. package/dist/cli/src/setup.d.ts +3 -3
  344. package/dist/cli/src/setup.d.ts.map +1 -1
  345. package/dist/cli/src/skill-checks.d.ts +27 -0
  346. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  347. package/dist/cli/src/store-addable.d.ts +11 -0
  348. package/dist/cli/src/store-addable.d.ts.map +1 -1
  349. package/dist/connectors/config.js +6 -6
  350. package/dist/connectors/index.js +31 -31
  351. package/dist/connectors/src/connector-prompt.d.ts +5 -5
  352. package/dist/connectors/src/connector-registry.d.ts +1 -1
  353. package/dist/connectors-7THEF7YA.js +48 -0
  354. package/dist/{connectors-RBGZ3M7G.js.map → connectors-7THEF7YA.js.map} +1 -1
  355. package/dist/connectors-shared/index.js +2 -2
  356. package/dist/core/framework.js +1 -1
  357. package/dist/{bridge/drivers/codex.d.ts → core/harness-targets.d.ts} +1 -1
  358. package/dist/core/harness-targets.js +4 -0
  359. package/dist/core/harness-targets.js.map +1 -0
  360. package/dist/core/index.js +11 -11
  361. package/dist/core/manifest.js +2 -2
  362. package/dist/core/models.js +1 -1
  363. package/dist/core/provider-registry-credentials.js +2 -2
  364. package/dist/core/provider-registry.js +1 -1
  365. package/dist/core/publish-manifest.js +3 -3
  366. package/dist/core/ref.js +1 -1
  367. package/dist/core/runtime-assets.js +6 -6
  368. package/dist/core/src/agent-instances.d.ts.map +1 -1
  369. package/dist/core/src/asset-roots.d.ts +2 -2
  370. package/dist/core/src/config-key-diagnostics.d.ts +9 -0
  371. package/dist/core/src/config-key-diagnostics.d.ts.map +1 -0
  372. package/dist/core/src/framework.d.ts +21 -21
  373. package/dist/core/src/framework.d.ts.map +1 -1
  374. package/dist/core/src/{driver-sdk.d.ts → harness-sdk.d.ts} +9 -9
  375. package/dist/core/src/harness-sdk.d.ts.map +1 -0
  376. package/dist/core/src/harness-targets.d.ts +71 -0
  377. package/dist/core/src/harness-targets.d.ts.map +1 -0
  378. package/dist/core/src/index.d.ts +8 -8
  379. package/dist/core/src/index.d.ts.map +1 -1
  380. package/dist/core/src/manifest.d.ts +10 -0
  381. package/dist/core/src/manifest.d.ts.map +1 -1
  382. package/dist/core/src/models.d.ts +8 -0
  383. package/dist/core/src/models.d.ts.map +1 -1
  384. package/dist/core/src/provider-registry.d.ts +2 -2
  385. package/dist/core/src/settings.d.ts +17 -16
  386. package/dist/core/src/settings.d.ts.map +1 -1
  387. package/dist/core/src/store.d.ts +12 -12
  388. package/dist/core/src/store.d.ts.map +1 -1
  389. package/dist/core/src/workspace-config.d.ts +39 -21
  390. package/dist/core/src/workspace-config.d.ts.map +1 -1
  391. package/dist/core/src/workspace-yaml-editor.d.ts +10 -3
  392. package/dist/core/src/workspace-yaml-editor.d.ts.map +1 -1
  393. package/dist/core/store.js +2 -2
  394. package/dist/core/workspace-config.js +5 -5
  395. package/dist/deploy/index.js +12 -12
  396. package/dist/discovery/index.js +5 -5
  397. package/dist/discovery/src/builtin-providers.d.ts.map +1 -1
  398. package/dist/discovery/src/parse-manifest.d.ts.map +1 -1
  399. package/dist/{ensure-sources-GKVLE6L5.js → ensure-sources-IH7CHSJF.js} +22 -22
  400. package/dist/{ensure-sources-GKVLE6L5.js.map → ensure-sources-IH7CHSJF.js.map} +1 -1
  401. package/dist/factory-assets/connectors/box.js +31 -31
  402. package/dist/factory-assets/connectors/deploy.js +31 -31
  403. package/dist/factory-assets/connectors/devserver.js +31 -31
  404. package/dist/factory-assets/connectors/flow/CONNECTOR.md +5 -5
  405. package/dist/factory-assets/connectors/flow/adapter.d.ts +3 -3
  406. package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
  407. package/dist/factory-assets/connectors/flow/adapter.js +31 -31
  408. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
  409. package/dist/factory-assets/connectors/flow/contract.js +1 -1
  410. package/dist/factory-assets/connectors/flow/engine/types.d.ts +1 -1
  411. package/dist/factory-assets/connectors/flow/engine.js +13 -13
  412. package/dist/factory-assets/connectors/flow/inline-sub-flow-host.d.ts +2 -2
  413. package/dist/factory-assets/connectors/flow/inline-sub-flow-host.d.ts.map +1 -1
  414. package/dist/factory-assets/connectors/flow/orchestrator-turn.d.ts +4 -4
  415. package/dist/factory-assets/connectors/flow/orchestrator-turn.d.ts.map +1 -1
  416. package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts +1 -1
  417. package/dist/factory-assets/connectors/flow/prompt-fragments.js +1 -1
  418. package/dist/factory-assets/connectors/flow/run-flow.d.ts +12 -12
  419. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  420. package/dist/factory-assets/connectors/flow/run-flow.js +33 -33
  421. package/dist/factory-assets/connectors/flow/sub-flow-runner.d.ts +1 -1
  422. package/dist/factory-assets/connectors/flow/sub-flow-runner.d.ts.map +1 -1
  423. package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts +22 -22
  424. package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts.map +1 -1
  425. package/dist/factory-assets/connectors/flow.js +31 -31
  426. package/dist/factory-assets/connectors/git.js +31 -31
  427. package/dist/factory-assets/connectors/gmail.js +31 -31
  428. package/dist/factory-assets/connectors/googledrive.js +31 -31
  429. package/dist/factory-assets/connectors/local.js +31 -31
  430. package/dist/factory-assets/connectors/mattermost.js +31 -31
  431. package/dist/factory-assets/connectors/memory.js +31 -31
  432. package/dist/factory-assets/connectors/minio.js +31 -31
  433. package/dist/factory-assets/connectors/postgres.js +31 -31
  434. package/dist/factory-assets/connectors/s3.js +31 -31
  435. package/dist/factory-assets/connectors/sharepoint.js +31 -31
  436. package/dist/factory-assets/connectors/sqlite.js +31 -31
  437. package/dist/factory-assets/connectors/static-server.js +31 -31
  438. package/dist/factory-assets/connectors/tunnel.js +31 -31
  439. package/dist/factory-assets/connectors/webdav.js +31 -31
  440. package/dist/factory-assets/connectors/xstate-store.js +31 -31
  441. package/dist/factory-assets/connectors/xstate.js +31 -31
  442. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +1 -1
  443. package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +2 -2
  444. package/dist/factory-assets/skills/authoring-skaile-manifests/references/dependency-standard.md +3 -3
  445. package/dist/factory-assets/skills/skaile-manage-workspace/SKILL.md +1 -1
  446. package/dist/flows-4JZQ3XFK.js +26 -0
  447. package/dist/{flows-W2FB7WIM.js.map → flows-4JZQ3XFK.js.map} +1 -1
  448. package/dist/{helpers-34QNVIGB.js → helpers-JNMK3FC2.js} +22 -22
  449. package/dist/{helpers-34QNVIGB.js.map → helpers-JNMK3FC2.js.map} +1 -1
  450. package/dist/library/index.js +15 -15
  451. package/dist/library/install.js +4 -4
  452. package/dist/library/src/index.d.ts +1 -1
  453. package/dist/library/src/index.d.ts.map +1 -1
  454. package/dist/library/src/local/library-dir.d.ts +22 -5
  455. package/dist/library/src/local/library-dir.d.ts.map +1 -1
  456. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  457. package/dist/library/src/remote/remote-catalog-source.d.ts +6 -0
  458. package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
  459. package/dist/{library-publish-RUQTKTJU.js → library-publish-I3UWXAHI.js} +69 -67
  460. package/dist/library-publish-I3UWXAHI.js.map +1 -0
  461. package/dist/model-endpoint/index.js +15 -15
  462. package/dist/model-endpoint/src/resolve.d.ts +1 -1
  463. package/dist/open-library-NKKUJLWA.js +42 -0
  464. package/dist/{open-library-PVTIUQUF.js.map → open-library-NKKUJLWA.js.map} +1 -1
  465. package/dist/open-registry-BYAXSHUI.js +32 -0
  466. package/dist/{open-registry-SOIS3TA2.js.map → open-registry-BYAXSHUI.js.map} +1 -1
  467. package/dist/paths-UKWE35XS.js +22 -0
  468. package/dist/{paths-JLNX7Y4X.js.map → paths-UKWE35XS.js.map} +1 -1
  469. package/dist/plugin-registry/index.js +1 -1
  470. package/dist/plugin-registry/src/context.d.ts +3 -3
  471. package/dist/plugin-registry/src/context.d.ts.map +1 -1
  472. package/dist/plugin-registry/src/deploy-handle.d.ts +1 -1
  473. package/dist/plugin-registry/src/index.d.ts +2 -2
  474. package/dist/plugin-registry/src/index.d.ts.map +1 -1
  475. package/dist/plugin-registry/src/internal.d.ts.map +1 -1
  476. package/dist/plugin-registry/src/registry.d.ts +3 -3
  477. package/dist/plugin-registry/src/registry.d.ts.map +1 -1
  478. package/dist/plugin-registry/src/targets.d.ts +9 -9
  479. package/dist/plugin-registry/src/targets.d.ts.map +1 -1
  480. package/dist/plugin-store-ABE35NRX.js +23 -0
  481. package/dist/{plugin-store-G2GWAHSD.js.map → plugin-store-ABE35NRX.js.map} +1 -1
  482. package/dist/plugins/src/asset-kind-provider.d.ts +1 -1
  483. package/dist/project-BIPK47JK.js +86 -0
  484. package/dist/{project-EX47PUBN.js.map → project-BIPK47JK.js.map} +1 -1
  485. package/dist/resolver/index.js +12 -12
  486. package/dist/runner/index.js +50 -50
  487. package/dist/runner/src/agent.d.ts +3 -3
  488. package/dist/runner/src/agent.d.ts.map +1 -1
  489. package/dist/runner/src/agents/in-process-host.d.ts +1 -1
  490. package/dist/runner/src/agents/instances.d.ts +1 -1
  491. package/dist/runner/src/agents/instances.d.ts.map +1 -1
  492. package/dist/runner/src/agents/run-controller.d.ts +7 -7
  493. package/dist/runner/src/agents/run-controller.d.ts.map +1 -1
  494. package/dist/runner/src/agents/standalone-surface.d.ts +2 -2
  495. package/dist/runner/src/agents/standalone-surface.d.ts.map +1 -1
  496. package/dist/runner/src/ai-provider-switch.d.ts +7 -7
  497. package/dist/runner/src/assistant-home.d.ts +1 -1
  498. package/dist/runner/src/capability-registry.d.ts +2 -2
  499. package/dist/runner/src/coalesced-restart.d.ts +2 -2
  500. package/dist/runner/src/compaction/context-window.d.ts +8 -8
  501. package/dist/runner/src/compaction/context-window.d.ts.map +1 -1
  502. package/dist/runner/src/compaction/orchestrator.d.ts +24 -24
  503. package/dist/runner/src/compaction/orchestrator.d.ts.map +1 -1
  504. package/dist/runner/src/compaction-gate.d.ts +30 -30
  505. package/dist/runner/src/compaction-gate.d.ts.map +1 -1
  506. package/dist/runner/src/composition/content-source.d.ts.map +1 -1
  507. package/dist/runner/src/composition/dry-run.d.ts +2 -2
  508. package/dist/runner/src/composition/dry-run.d.ts.map +1 -1
  509. package/dist/runner/src/composition/errors.d.ts +16 -1
  510. package/dist/runner/src/composition/errors.d.ts.map +1 -1
  511. package/dist/runner/src/composition/resolve-instance.d.ts +2 -2
  512. package/dist/runner/src/composition/resolve.d.ts +1 -1
  513. package/dist/runner/src/config.d.ts +3 -3
  514. package/dist/runner/src/config.d.ts.map +1 -1
  515. package/dist/runner/src/context-usage/collector.d.ts +15 -15
  516. package/dist/runner/src/context-usage/collector.d.ts.map +1 -1
  517. package/dist/runner/src/context-usage/compose.d.ts +6 -6
  518. package/dist/runner/src/context-usage/compose.d.ts.map +1 -1
  519. package/dist/runner/src/context-usage/estimator.d.ts +1 -1
  520. package/dist/runner/src/context-usage/index.d.ts +1 -1
  521. package/dist/runner/src/context-usage/index.d.ts.map +1 -1
  522. package/dist/runner/src/context-usage/transcript-tracker.d.ts +2 -2
  523. package/dist/runner/src/context-usage/transcript-tracker.d.ts.map +1 -1
  524. package/dist/runner/src/credential-notice.d.ts +4 -4
  525. package/dist/runner/src/credential-notice.d.ts.map +1 -1
  526. package/dist/runner/src/credential-rotated.d.ts +1 -1
  527. package/dist/runner/src/final-text.d.ts +1 -1
  528. package/dist/runner/src/{driver-swap-gate.d.ts → harness-swap-gate.d.ts} +21 -21
  529. package/dist/runner/src/harness-swap-gate.d.ts.map +1 -0
  530. package/dist/runner/src/late-mcp-rebuild.d.ts +6 -6
  531. package/dist/runner/src/late-mcp-rebuild.d.ts.map +1 -1
  532. package/dist/runner/src/lifecycle-handler.d.ts +1 -1
  533. package/dist/runner/src/lifecycle-handler.d.ts.map +1 -1
  534. package/dist/runner/src/manifest.d.ts +1 -1
  535. package/dist/runner/src/mcp-runtime-handlers.d.ts +6 -6
  536. package/dist/runner/src/mcp-runtime-handlers.d.ts.map +1 -1
  537. package/dist/runner/src/model-endpoint-discovery.d.ts +1 -1
  538. package/dist/runner/src/pending-turns.d.ts +3 -3
  539. package/dist/runner/src/platform-blocks.d.ts +5 -5
  540. package/dist/runner/src/platform-blocks.d.ts.map +1 -1
  541. package/dist/runner/src/prompt-turn-queue.d.ts +1 -1
  542. package/dist/runner/src/provider-quota-forwarder.d.ts +1 -1
  543. package/dist/runner/src/provider-quota-forwarder.d.ts.map +1 -1
  544. package/dist/runner/src/reconfigure-handler.d.ts +14 -14
  545. package/dist/runner/src/reconfigure-handler.d.ts.map +1 -1
  546. package/dist/runner/src/resource-handler.d.ts +1 -1
  547. package/dist/runner/src/resources.d.ts +5 -5
  548. package/dist/runner/src/resources.d.ts.map +1 -1
  549. package/dist/runner/src/runner-capabilities.d.ts +7 -7
  550. package/dist/runner/src/runtime-session-emit.d.ts +5 -5
  551. package/dist/runner/src/runtime-session-emit.d.ts.map +1 -1
  552. package/dist/runner/src/s3-presign-client.d.ts +1 -1
  553. package/dist/runner/src/serve-credentials.d.ts +7 -7
  554. package/dist/runner/src/serve-credentials.d.ts.map +1 -1
  555. package/dist/runner/src/serve.d.ts +46 -34
  556. package/dist/runner/src/serve.d.ts.map +1 -1
  557. package/dist/runner/src/session-builder.d.ts +41 -41
  558. package/dist/runner/src/session-builder.d.ts.map +1 -1
  559. package/dist/runner/src/session-capability-wiring.d.ts +9 -9
  560. package/dist/runner/src/session-capability-wiring.d.ts.map +1 -1
  561. package/dist/runner/src/session-stimulus.d.ts +1 -1
  562. package/dist/runner/src/session.d.ts +5 -5
  563. package/dist/runner/src/session.d.ts.map +1 -1
  564. package/dist/runner/src/skill-staging.d.ts +16 -16
  565. package/dist/runner/src/skill-staging.d.ts.map +1 -1
  566. package/dist/runner/src/turn-end-contract.d.ts +5 -5
  567. package/dist/runner/src/turn-end-contract.d.ts.map +1 -1
  568. package/dist/runner/src/turn-scheduler.d.ts +22 -22
  569. package/dist/runner/src/turn-scheduler.d.ts.map +1 -1
  570. package/dist/runner/src/turn-status-replay.d.ts +1 -1
  571. package/dist/runner/src/usage-limit-turn-hold.d.ts +1 -1
  572. package/dist/sdk/asset-manager.js +19 -19
  573. package/dist/sdk/bridge.js +25 -25
  574. package/dist/sdk/core.js +11 -11
  575. package/dist/sdk/flow.js +13 -13
  576. package/dist/sdk/index.js +54 -54
  577. package/dist/sdk/index.js.map +1 -1
  578. package/dist/sdk/resolver.js +12 -12
  579. package/dist/sdk/runner.js +50 -50
  580. package/dist/sdk/session.js +2 -2
  581. package/dist/sdk/src/agent-session.d.ts +1 -1
  582. package/dist/sdk/src/local-runtime.d.ts +1 -1
  583. package/dist/sdk/src/local-runtime.d.ts.map +1 -1
  584. package/dist/sdk/src/types.d.ts +1 -1
  585. package/dist/sdk/src/types.d.ts.map +1 -1
  586. package/dist/sdk/store.js +2 -2
  587. package/dist/sdk/transport/ws/server.js +12 -12
  588. package/dist/sdk/transport/ws.js +12 -12
  589. package/dist/sdk/transport.js +12 -12
  590. package/dist/sdk/types.js +1 -1
  591. package/dist/serve-preflight-FLTIBTEX.js +107 -0
  592. package/dist/serve-preflight-FLTIBTEX.js.map +1 -0
  593. package/dist/session/index.js +2 -2
  594. package/dist/session/src/dispatcher.d.ts +2 -2
  595. package/dist/sessions-2Q7SSYPT.js +5 -0
  596. package/dist/{sessions-DICDEONJ.js.map → sessions-2Q7SSYPT.js.map} +1 -1
  597. package/dist/{setup-AFZQNGKA.js → setup-AG6NFHSN.js} +52 -52
  598. package/dist/setup-AG6NFHSN.js.map +1 -0
  599. package/dist/skills-UQYUHVKO.js +26 -0
  600. package/dist/{skills-YYYC6D5X.js.map → skills-UQYUHVKO.js.map} +1 -1
  601. package/dist/source-ASEHI2XS.js +85 -0
  602. package/dist/{source-DGPCT5IC.js.map → source-ASEHI2XS.js.map} +1 -1
  603. package/dist/{source-manifest-publish-AGJ63JF2.js → source-manifest-publish-IEVV3W6J.js} +62 -62
  604. package/dist/{source-manifest-publish-AGJ63JF2.js.map → source-manifest-publish-IEVV3W6J.js.map} +1 -1
  605. package/dist/store/index.js +2 -2
  606. package/dist/store/src/store.d.ts +3 -3
  607. package/dist/store/src/store.d.ts.map +1 -1
  608. package/dist/transport/index.js +12 -12
  609. package/dist/transport/ws/server.js +12 -12
  610. package/dist/transport/ws.js +12 -12
  611. package/dist/tui/index.js +70 -70
  612. package/dist/tui/index.js.map +1 -1
  613. package/dist/tui/src/repl-session.d.ts +5 -5
  614. package/dist/tui/src/repl.d.ts +5 -5
  615. package/dist/tui/src/repl.d.ts.map +1 -1
  616. package/dist/types/index.js +1 -1
  617. package/dist/types/manifests.js +1 -1
  618. package/dist/types/src/agent-lifecycle.d.ts +1 -1
  619. package/dist/types/src/agent-lifecycle.d.ts.map +1 -1
  620. package/dist/types/src/ask-slots.d.ts +1 -1
  621. package/dist/types/src/capabilities.d.ts +1 -1
  622. package/dist/types/src/context-usage.d.ts +22 -22
  623. package/dist/types/src/context-usage.d.ts.map +1 -1
  624. package/dist/types/src/events.d.ts +49 -49
  625. package/dist/types/src/events.d.ts.map +1 -1
  626. package/dist/types/src/index.d.ts +2 -2
  627. package/dist/types/src/index.d.ts.map +1 -1
  628. package/dist/types/src/install-manifest.d.ts +1 -1
  629. package/dist/types/src/install-manifest.d.ts.map +1 -1
  630. package/dist/types/src/lifecycle.d.ts +6 -6
  631. package/dist/types/src/lifecycle.d.ts.map +1 -1
  632. package/dist/types/src/logging.d.ts +1 -1
  633. package/dist/types/src/manifests/agent.d.ts +3 -3
  634. package/dist/types/src/protocol.d.ts +4 -4
  635. package/dist/types/src/runtime.d.ts +38 -38
  636. package/dist/types/src/runtime.d.ts.map +1 -1
  637. package/dist/types/src/version.d.ts +22 -11
  638. package/dist/types/src/version.d.ts.map +1 -1
  639. package/dist/validator-DRHMJ457.js +5 -0
  640. package/dist/{validator-FA2PFW6N.js.map → validator-DRHMJ457.js.map} +1 -1
  641. package/dist/workspace-plugin/adapters/mcp.js +41 -41
  642. package/dist/workspace-plugin/adapters/omp.js +26 -26
  643. package/dist/workspace-plugin/adapters/omp.js.map +1 -1
  644. package/dist/workspace-plugin/index.js +3 -3
  645. package/dist/workspace-plugin/src/plugin.d.ts +5 -5
  646. package/dist/workspace-plugin/src/plugin.d.ts.map +1 -1
  647. package/dist/workspace-plugin/src/tools/flows.d.ts +1 -1
  648. package/dist/workspace-plugin/src/tools/validator.d.ts +6 -6
  649. package/dist/workspace-plugin/src/tools/validator.d.ts.map +1 -1
  650. package/dist/workspace-plugin/src/types.d.ts +2 -2
  651. package/dist/workspace-plugin/src/types.d.ts.map +1 -1
  652. package/package.json +59 -59
  653. package/dist/asset-feeds-QGLI3AXI.js.map +0 -1
  654. package/dist/bridge/drivers/claude-sdk.js.map +0 -1
  655. package/dist/bridge/drivers/codex.js.map +0 -1
  656. package/dist/bridge/drivers/continue.js.map +0 -1
  657. package/dist/bridge/drivers/echo.js.map +0 -1
  658. package/dist/bridge/drivers/gemini.js +0 -18
  659. package/dist/bridge/drivers/goose.js.map +0 -1
  660. package/dist/bridge/drivers/omp.js.map +0 -1
  661. package/dist/bridge/drivers/opencode.js.map +0 -1
  662. package/dist/bridge/drivers/qwen.js.map +0 -1
  663. package/dist/bridge/src/codex/managed-driver.d.ts.map +0 -1
  664. package/dist/bridge/src/driver-capabilities.d.ts.map +0 -1
  665. package/dist/bridge/src/driver-model-check.d.ts +0 -25
  666. package/dist/bridge/src/driver-model-check.d.ts.map +0 -1
  667. package/dist/bridge/src/drivers/_subprocess-cli.d.ts.map +0 -1
  668. package/dist/bridge/src/drivers/claude-context-usage.d.ts.map +0 -1
  669. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +0 -1
  670. package/dist/bridge/src/drivers/claude-self-turns.d.ts.map +0 -1
  671. package/dist/bridge/src/drivers/claude-tool-allowlist.d.ts.map +0 -1
  672. package/dist/bridge/src/drivers/codex.d.ts.map +0 -1
  673. package/dist/bridge/src/drivers/continue.d.ts.map +0 -1
  674. package/dist/bridge/src/drivers/echo.d.ts.map +0 -1
  675. package/dist/bridge/src/drivers/flow-script.d.ts.map +0 -1
  676. package/dist/bridge/src/drivers/gemini.d.ts.map +0 -1
  677. package/dist/bridge/src/drivers/goose.d.ts.map +0 -1
  678. package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +0 -1
  679. package/dist/bridge/src/drivers/omp.d.ts.map +0 -1
  680. package/dist/bridge/src/drivers/opencode.d.ts.map +0 -1
  681. package/dist/bridge/src/drivers/qwen.d.ts.map +0 -1
  682. package/dist/bridge/src/drivers/recovery-policy.d.ts.map +0 -1
  683. package/dist/bridge/src/drivers/resume-probe.d.ts.map +0 -1
  684. package/dist/bridge/src/drivers/sanitize-assistant-text.d.ts.map +0 -1
  685. package/dist/bridge/src/drivers/scrub-transcript.d.ts.map +0 -1
  686. package/dist/bridge/src/provider-materialize/env-drivers.d.ts.map +0 -1
  687. package/dist/chunk-2GXSSZAM.js.map +0 -1
  688. package/dist/chunk-4ZTPYIBE.js.map +0 -1
  689. package/dist/chunk-5BEFNLOR.js.map +0 -1
  690. package/dist/chunk-5TBFN46Z.js.map +0 -1
  691. package/dist/chunk-6E6PKKAD.js.map +0 -1
  692. package/dist/chunk-7NT4F6SR.js.map +0 -1
  693. package/dist/chunk-7SCS64BG.js.map +0 -1
  694. package/dist/chunk-AJ7EGIFR.js.map +0 -1
  695. package/dist/chunk-C7WBGSBV.js.map +0 -1
  696. package/dist/chunk-COJIL7G4.js.map +0 -1
  697. package/dist/chunk-CQJH4G2K.js.map +0 -1
  698. package/dist/chunk-EAZECHPM.js.map +0 -1
  699. package/dist/chunk-EPBKISS5.js.map +0 -1
  700. package/dist/chunk-FPHNJE4M.js.map +0 -1
  701. package/dist/chunk-GOCWM7FN.js.map +0 -1
  702. package/dist/chunk-HT35SQZD.js.map +0 -1
  703. package/dist/chunk-I37INEWE.js.map +0 -1
  704. package/dist/chunk-IG5LZ3WU.js.map +0 -1
  705. package/dist/chunk-IP2IPMEH.js.map +0 -1
  706. package/dist/chunk-IZCR27MU.js.map +0 -1
  707. package/dist/chunk-J24CY3PF.js.map +0 -1
  708. package/dist/chunk-JTOWA6RS.js.map +0 -1
  709. package/dist/chunk-L2AMXONH.js.map +0 -1
  710. package/dist/chunk-MJHSLODD.js.map +0 -1
  711. package/dist/chunk-MKRWN7XP.js.map +0 -1
  712. package/dist/chunk-MRHVPQNO.js.map +0 -1
  713. package/dist/chunk-N46LQR46.js.map +0 -1
  714. package/dist/chunk-PUK7TQT4.js +0 -13
  715. package/dist/chunk-PUK7TQT4.js.map +0 -1
  716. package/dist/chunk-QG6GHTRM.js.map +0 -1
  717. package/dist/chunk-RO6VOM6Z.js.map +0 -1
  718. package/dist/chunk-RPZVHXQ3.js.map +0 -1
  719. package/dist/chunk-V257LUBM.js.map +0 -1
  720. package/dist/chunk-VJ7NU7GD.js.map +0 -1
  721. package/dist/chunk-VSZWNUZC.js.map +0 -1
  722. package/dist/chunk-W4Q6CKJ5.js.map +0 -1
  723. package/dist/chunk-WOIRYY5L.js.map +0 -1
  724. package/dist/chunk-WST6UITC.js.map +0 -1
  725. package/dist/chunk-X3RMRJNR.js.map +0 -1
  726. package/dist/chunk-XJVBUDDJ.js.map +0 -1
  727. package/dist/chunk-XM6T2AZ2.js.map +0 -1
  728. package/dist/chunk-XWOPZW26.js.map +0 -1
  729. package/dist/chunk-Y56YIT6J.js.map +0 -1
  730. package/dist/chunk-YROR332M.js.map +0 -1
  731. package/dist/chunk-ZQSOJH6I.js.map +0 -1
  732. package/dist/claude-code-2PU7TITZ.js +0 -10
  733. package/dist/cli/src/driver-error.d.ts +0 -28
  734. package/dist/cli/src/driver-error.d.ts.map +0 -1
  735. package/dist/connectors-RBGZ3M7G.js +0 -48
  736. package/dist/core/driver-targets.d.ts +0 -2
  737. package/dist/core/driver-targets.js +0 -4
  738. package/dist/core/driver-targets.js.map +0 -1
  739. package/dist/core/src/driver-sdk.d.ts.map +0 -1
  740. package/dist/core/src/driver-targets.d.ts +0 -71
  741. package/dist/core/src/driver-targets.d.ts.map +0 -1
  742. package/dist/flows-W2FB7WIM.js +0 -26
  743. package/dist/library-publish-RUQTKTJU.js.map +0 -1
  744. package/dist/open-library-PVTIUQUF.js +0 -42
  745. package/dist/open-registry-SOIS3TA2.js +0 -32
  746. package/dist/paths-JLNX7Y4X.js +0 -22
  747. package/dist/plugin-store-G2GWAHSD.js +0 -23
  748. package/dist/project-EX47PUBN.js +0 -84
  749. package/dist/runner/src/driver-swap-gate.d.ts.map +0 -1
  750. package/dist/serve-preflight-QXRKGOI5.js +0 -108
  751. package/dist/serve-preflight-QXRKGOI5.js.map +0 -1
  752. package/dist/sessions-DICDEONJ.js +0 -5
  753. package/dist/setup-AFZQNGKA.js.map +0 -1
  754. package/dist/skills-YYYC6D5X.js +0 -26
  755. package/dist/source-DGPCT5IC.js +0 -85
  756. package/dist/validator-FA2PFW6N.js +0 -5
  757. /package/dist/bridge/{drivers → harnesses}/gemini.js.map +0 -0
@@ -1,22 +1,23 @@
1
- import { unregisteredLibraryNames, renamedLibraryName, resolveConfig, RemoteCatalogSource, OfflineError, describeCatalogError, CatalogHttpError, scanUnlistedAssets, missingRootAssets, storeManifestFile, missingLibraryDirMessage, filesEntryPaths } from './chunk-XM6T2AZ2.js';
2
- import { SEMVER_RE, invalidSemverMessage, flowFileNameError, readManifestSourceConfig, discoverAssetsInTree, isManifestMode } from './chunk-I37INEWE.js';
3
- import { parseFlowDefinition } from './chunk-X3RMRJNR.js';
4
- import { installTargetOf, readKeptLegacyCopies, writeKeptLegacyCopies, canonicalEntryRef, diffDeployedAgent, deployedAssetDrift, assertNoLibrarySymlinks, deployAll, removeAsset, createScaffold, installAgent } from './chunk-JTOWA6RS.js';
1
+ import { unregisteredLibraryNames, renamedLibraryName, resolveConfig, RemoteCatalogSource, OfflineError, describeCatalogError, CatalogHttpError, scanUnlistedAssets, missingRootAssets, storeManifestFile, missingLibraryDirMessage, filesEntryPaths, lastLibraryName } from './chunk-S2XHGWQC.js';
2
+ import { SEMVER_RE, invalidSemverMessage, flowFileNameError, computeDeterministicHash, readManifestSourceConfig, discoverAssetsInTree, isManifestMode } from './chunk-UI745XC3.js';
3
+ import { parseFlowDefinition } from './chunk-JRN5QF4C.js';
4
+ import { installTargetOf, readKeptLegacyCopies, writeKeptLegacyCopies, canonicalEntryRef, diffDeployedAgent, deployedAssetDrift, assertNoLibrarySymlinks, deployAll, removeAsset, sourceComposedFiles, cachedComposedFiles, createScaffold, installAgent } from './chunk-NUA33BYO.js';
5
5
  import { appendHistory, getRecentHistory, clearHistory } from './chunk-KTBKW2FI.js';
6
6
  import { commitChanges } from './chunk-UQ6LFBPZ.js';
7
- import { driverTargetSupportsAgents, CODEX_IDENTITY_DIR } from './chunk-C7WBGSBV.js';
8
- import { isScaffoldBody, isScaffoldDescription } from './chunk-335ENCCS.js';
9
- import { resolveConfiguredDriverTarget, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, writeLock, computeHash, buildLockFile, readLock, assertLockHashes, verifyLock, mergeLockFile, resyncLockSources, extractForPatch, generatePatch, savePatch, applyPatch, LOCK_SCHEMA_VERSION } from './chunk-N46LQR46.js';
10
- import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-TIIXG3PN.js';
11
- import { deployedBase, isDeployed, deployedPaths, deployedDir } from './chunk-5TBFN46Z.js';
12
- import { resolveSkWorkspaceConfig, effectiveAgentInstances, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, readLinks, isCommitOnRemote, resolveAll, agentSourceCacheDir, ensureRepo, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAgentDefinitionDir, resolveAsset, MAX_PRESET_DEPTH, PresetDepthError, DEFAULT_AGENT_INSTANCE_ID } from './chunk-V257LUBM.js';
7
+ import { harnessTargetSupportsAgents, CODEX_IDENTITY_DIR } from './chunk-ABFPSVIS.js';
8
+ import { isScaffoldBody, isScaffoldDescription } from './chunk-E572OHGY.js';
9
+ import { resolveConfiguredHarnessName, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, writeLock, computeHash, buildLockFile, readLock, assertLockHashes, verifyLock, mergeLockFile, resyncLockSources, extractForPatch, generatePatch, savePatch, applyPatch, LOCK_SCHEMA_VERSION } from './chunk-VMVDAZLA.js';
10
+ import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-ZDLUQLI6.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, resolveAll, agentSourceCacheDir, ensureRepo, resolveAgentDefinitionDir, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, MAX_PRESET_DEPTH, PresetDepthError, DEFAULT_AGENT_INSTANCE_ID } from './chunk-ZHGKAZJ7.js';
13
13
  import { globalSkaileDir, globalCacheRoot, migrateLegacyDir } from './chunk-L5VSIPQD.js';
14
- import { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS } from './chunk-IG5LZ3WU.js';
15
- import { loadSkPublishManifest, listAssetFiles, isNonAssetDir, isNonAssetFile } from './chunk-UQ33Y4DM.js';
16
- import { scanDirectory, parseFrontmatter, parseRequires, dedupeRequirements, readAssetBody } from './chunk-GOCWM7FN.js';
17
- import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr, parseDep } from './chunk-WDXZA7QW.js';
14
+ import { HARNESS_TARGETS, SUPPORTED_HARNESSES } from './chunk-VTETQCR6.js';
15
+ import { listAssetFiles, loadSkPublishManifest, decodeSkaileManifest, isNonAssetDir, isNonAssetFile } from './chunk-ZBHZLWV3.js';
16
+ import { scanDirectory, parseFrontmatter, parseRequires, dedupeRequirements, readAssetBody } from './chunk-RHN5MRQO.js';
17
+ import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr, parseDep } from './chunk-LSSYC5IC.js';
18
18
  import { spawnSync } from 'child_process';
19
- import { existsSync, rmSync, readFileSync, readdirSync, lstatSync, writeFileSync, unlinkSync, mkdirSync } from 'fs';
19
+ import { existsSync, rmSync, readFileSync, writeFileSync, readdirSync, lstatSync, statSync, unlinkSync, mkdirSync } from 'fs';
20
+ import { homedir } from 'os';
20
21
  import path, { resolve, dirname, sep, join, relative, posix } from 'path';
21
22
  import { gt } from 'semver';
22
23
  import { parse, stringify } from 'yaml';
@@ -40,8 +41,8 @@ function writeLedger(projectDir, ledger) {
40
41
  writeFileSync(p, `${JSON.stringify(ledger, null, 2)}
41
42
  `, "utf-8");
42
43
  }
43
- function renderedInstanceFiles(projectDir, driverTarget) {
44
- const recorded = readLedger(projectDir).targets[driverTarget];
44
+ function renderedInstanceFiles(projectDir, harness) {
45
+ const recorded = readLedger(projectDir).targets[harness];
45
46
  if (!recorded) return [];
46
47
  let instances;
47
48
  try {
@@ -51,11 +52,11 @@ function renderedInstanceFiles(projectDir, driverTarget) {
51
52
  }
52
53
  return Object.entries(instances).filter(([id]) => recorded[id]?.length).map(([id, instance]) => ({ id, ref: instance.ref, files: recorded[id] }));
53
54
  }
54
- function instanceRenderedAgentNames(projectDir, driverTarget) {
55
+ function instanceRenderedAgentNames(projectDir, harness) {
55
56
  const names = /* @__PURE__ */ new Set();
56
- if (!driverTargetSupportsAgents(driverTarget)) return names;
57
- const agentDir = resolve(deployedBase("agent", driverTarget, false, projectDir));
58
- for (const files of Object.values(readLedger(projectDir).targets[driverTarget] ?? {})) {
57
+ if (!harnessTargetSupportsAgents(harness)) return names;
58
+ const agentDir = resolve(deployedBase("agent", harness, false, projectDir));
59
+ for (const files of Object.values(readLedger(projectDir).targets[harness] ?? {})) {
59
60
  for (const rel of files) {
60
61
  const abs = resolve(projectDir, rel);
61
62
  if (!abs.startsWith(agentDir + sep)) continue;
@@ -80,8 +81,8 @@ function bindInstance(projectDir, id, instance) {
80
81
  }
81
82
  return { srcDir, errors };
82
83
  }
83
- function unboundAgentInstances(projectDir, driverTarget) {
84
- if (!driverTargetSupportsAgents(driverTarget)) return [];
84
+ function unboundAgentInstances(projectDir, harness) {
85
+ if (!harnessTargetSupportsAgents(harness)) return [];
85
86
  let instances;
86
87
  try {
87
88
  instances = effectiveAgentInstances(resolveSkWorkspaceConfig(projectDir));
@@ -96,16 +97,16 @@ function unboundAgentInstances(projectDir, driverTarget) {
96
97
  return out;
97
98
  }
98
99
  function removeAgentInstanceRenderings(opts) {
99
- const { projectDir, driverTarget, ids } = opts;
100
- if (!driverTargetSupportsAgents(driverTarget) || ids.length === 0) return [];
100
+ const { projectDir, harness, ids } = opts;
101
+ if (!harnessTargetSupportsAgents(harness) || ids.length === 0) return [];
101
102
  const ledger = readLedger(projectDir);
102
- const previous = ledger.targets[driverTarget];
103
+ const previous = ledger.targets[harness];
103
104
  if (!previous) return [];
104
105
  const gone = new Set(ids);
105
106
  const claimed = new Set(
106
107
  Object.entries(previous).filter(([id]) => !gone.has(id)).flatMap(([, files]) => files)
107
108
  );
108
- const agentDeployDir = deployedBase("agent", driverTarget, false, projectDir);
109
+ const agentDeployDir = deployedBase("agent", harness, false, projectDir);
109
110
  const removable = [resolve(agentDeployDir), resolve(dirname(agentDeployDir), CODEX_IDENTITY_DIR)];
110
111
  const root = resolve(projectDir);
111
112
  const removed = [];
@@ -120,28 +121,28 @@ function removeAgentInstanceRenderings(opts) {
120
121
  }
121
122
  const owned = Object.fromEntries(Object.entries(previous).filter(([id]) => !gone.has(id)));
122
123
  const nextTargets = { ...ledger.targets };
123
- if (Object.keys(owned).length > 0) nextTargets[driverTarget] = owned;
124
- else delete nextTargets[driverTarget];
124
+ if (Object.keys(owned).length > 0) nextTargets[harness] = owned;
125
+ else delete nextTargets[harness];
125
126
  if (JSON.stringify(nextTargets) !== JSON.stringify(ledger.targets)) {
126
127
  writeLedger(projectDir, { version: 1, targets: nextTargets });
127
128
  }
128
129
  return removed;
129
130
  }
130
131
  function installAgentInstances(opts) {
131
- const { projectDir, driverTarget, log } = opts;
132
+ const { projectDir, harness, log } = opts;
132
133
  const result = {
133
134
  instances: [],
134
135
  removed: [],
135
136
  warnings: [],
136
137
  errors: []
137
138
  };
138
- if (!driverTargetSupportsAgents(driverTarget)) return result;
139
+ if (!harnessTargetSupportsAgents(harness)) return result;
139
140
  const wsConfig = opts.wsConfig ?? resolveSkWorkspaceConfig(projectDir);
140
141
  const instances = effectiveAgentInstances(wsConfig);
141
- const agentDeployDir = deployedBase("agent", driverTarget, false, projectDir);
142
- const skillsRelDir = DRIVER_TARGETS[driverTarget]?.local.skill ?? "";
142
+ const agentDeployDir = deployedBase("agent", harness, false, projectDir);
143
+ const skillsRelDir = HARNESS_TARGETS[harness]?.local.skill ?? "";
143
144
  const ledger = readLedger(projectDir);
144
- const previous = ledger.targets[driverTarget] ?? {};
145
+ const previous = ledger.targets[harness] ?? {};
145
146
  const owned = {};
146
147
  for (const [id, instance] of Object.entries(instances)) {
147
148
  const { srcDir, errors } = bindInstance(projectDir, id, instance);
@@ -154,7 +155,7 @@ function installAgentInstances(opts) {
154
155
  srcDir,
155
156
  agentDeployDir,
156
157
  projectDir,
157
- driverTarget,
158
+ harness,
158
159
  skillsRelDir,
159
160
  id,
160
161
  /* includeSubAgents */
@@ -180,8 +181,8 @@ function installAgentInstances(opts) {
180
181
  result.removed.push(rel);
181
182
  }
182
183
  const nextTargets = { ...ledger.targets };
183
- if (Object.keys(owned).length > 0) nextTargets[driverTarget] = owned;
184
- else delete nextTargets[driverTarget];
184
+ if (Object.keys(owned).length > 0) nextTargets[harness] = owned;
185
+ else delete nextTargets[harness];
185
186
  if (JSON.stringify(nextTargets) !== JSON.stringify(ledger.targets)) {
186
187
  writeLedger(projectDir, { version: 1, targets: nextTargets });
187
188
  }
@@ -497,12 +498,12 @@ function canonicalJson(value) {
497
498
  function entryHash(entry) {
498
499
  return createHash("sha256").update(canonicalJson(entry)).digest("hex");
499
500
  }
500
- async function mcpServerDrift(projectDir, driverTarget, opts = {}) {
501
- const relConfig = TARGET_MCP_CONFIG[driverTarget];
501
+ async function mcpServerDrift(projectDir, harnessTarget, opts = {}) {
502
+ const relConfig = TARGET_MCP_CONFIG[harnessTarget];
502
503
  if (!relConfig) return [];
503
504
  const declarations = opts.declarations ?? await loadMcpServerDeclarations(projectDir);
504
- const skippedNow = await readNotedSkips(projectDir, driverTarget);
505
- const ledger = await readManaged(projectDir, driverTarget);
505
+ const skippedNow = await readNotedSkips(projectDir, harnessTarget);
506
+ const ledger = await readManaged(projectDir, harnessTarget);
506
507
  const managed = new Set(ledger.ids);
507
508
  let servers = {};
508
509
  try {
@@ -595,13 +596,21 @@ function requiredFieldsAdvice(id, keys) {
595
596
  const setting = keys.map((k) => `${k}: env:${k}`).join(", ");
596
597
  return `needs ${keys.join(", ")} (required): set it with an mcp_servers entry (id: ${id}, env: ${setting}) in skaile.yaml and export the variable, then run skaile install`;
597
598
  }
598
- function mcpConfigFileOf(driverTarget) {
599
- return TARGET_MCP_CONFIG[driverTarget];
599
+ function mcpNotRunnableReason(mdContent, name) {
600
+ try {
601
+ const decl = mcpDeclarationFromMdContent(mdContent, name);
602
+ return decl ? skipReason(decl) : void 0;
603
+ } catch {
604
+ return void 0;
605
+ }
606
+ }
607
+ function mcpConfigFileOf(harnessTarget) {
608
+ return TARGET_MCP_CONFIG[harnessTarget];
600
609
  }
601
- async function mcpRenderedFootprint(projectDir, driverTarget, name) {
602
- const relConfig = TARGET_MCP_CONFIG[driverTarget];
610
+ async function mcpRenderedFootprint(projectDir, harnessTarget, name) {
611
+ const relConfig = TARGET_MCP_CONFIG[harnessTarget];
603
612
  if (!relConfig) return void 0;
604
- const ledger = await readManaged(projectDir, driverTarget);
613
+ const ledger = await readManaged(projectDir, harnessTarget);
605
614
  if (!ledger.ids.includes(name)) return void 0;
606
615
  const dir = payloadDir(projectDir, name);
607
616
  let hasPayload = false;
@@ -616,15 +625,47 @@ async function mcpRenderedFootprint(projectDir, driverTarget, name) {
616
625
  ...dir && hasPayload ? { payloadDir: `${path.relative(projectDir, dir).split(path.sep).join("/")}/` } : {}
617
626
  };
618
627
  }
619
- async function renderMcpServerConfig(projectDir, driverTarget, opts) {
628
+ async function mcpCommittedRenderIntact(projectDir, harnessTarget, name) {
629
+ const relConfig = TARGET_MCP_CONFIG[harnessTarget];
630
+ if (!relConfig) return false;
631
+ if ((await readNotedSkips(projectDir, harnessTarget))[name] !== void 0) return true;
632
+ let ledger;
633
+ let servers;
634
+ try {
635
+ ledger = await readManaged(projectDir, harnessTarget);
636
+ const file = await readJsonStrict(path.join(projectDir, relConfig));
637
+ servers = file?.mcpServers ?? {};
638
+ } catch {
639
+ return false;
640
+ }
641
+ if (!Object.hasOwn(servers, name)) return false;
642
+ const entry = servers[name];
643
+ const recorded = ledger.ids.includes(name) ? ledger.rendered[name] : void 0;
644
+ if (recorded !== void 0 && entryHash(entry) !== recorded) return false;
645
+ const e = entry ?? {};
646
+ const strings = [e.command, ...Array.isArray(e.args) ? e.args : []].filter(
647
+ (v) => typeof v === "string"
648
+ );
649
+ for (const v of strings) {
650
+ const at = v.indexOf(".skaile/assets/");
651
+ if (at < 0) continue;
652
+ try {
653
+ await fs.stat(path.join(projectDir, v.slice(at)));
654
+ } catch {
655
+ return false;
656
+ }
657
+ }
658
+ return true;
659
+ }
660
+ async function renderMcpServerConfig(projectDir, harnessTarget, opts) {
620
661
  const warn = opts?.warn ?? ((m) => console.warn(`skaile: ${m}`));
621
- const relConfig = TARGET_MCP_CONFIG[driverTarget];
662
+ const relConfig = TARGET_MCP_CONFIG[harnessTarget];
622
663
  if (!relConfig) return { written: false, servers: [], removed: [], skipped: [] };
623
664
  const configPath = path.join(projectDir, relConfig);
624
665
  const declarations = await loadMcpServerDeclarations(projectDir);
625
666
  const skipped = [];
626
667
  const renderable = /* @__PURE__ */ new Map();
627
- const noted = await readNotedSkips(projectDir, driverTarget);
668
+ const noted = await readNotedSkips(projectDir, harnessTarget);
628
669
  for (const decl of declarations) {
629
670
  const reason = skipReason(decl) ?? await ensurePayload(projectDir, decl, opts?.fetchPayload ?? defaultFetchPayload);
630
671
  if (reason) {
@@ -636,8 +677,8 @@ async function renderMcpServerConfig(projectDir, driverTarget, opts) {
636
677
  }
637
678
  renderable.set(decl.id, buildEntry(decl));
638
679
  }
639
- await writeNotedSkips(projectDir, driverTarget, noted, skipped);
640
- const ledger = await readManaged(projectDir, driverTarget);
680
+ await writeNotedSkips(projectDir, harnessTarget, noted, skipped);
681
+ const ledger = await readManaged(projectDir, harnessTarget);
641
682
  const managedIds = ledger.ids;
642
683
  const existingFile = await readJsonStrict(configPath);
643
684
  if (renderable.size === 0 && managedIds.length === 0 && !existingFile) {
@@ -660,7 +701,7 @@ async function renderMcpServerConfig(projectDir, driverTarget, opts) {
660
701
  }
661
702
  const rendered = Object.fromEntries(owned.map((id) => [id, entryHash(next[id])]));
662
703
  const ledgerStale = JSON.stringify(owned) !== JSON.stringify(managedIds) || canonicalJson(rendered) !== canonicalJson(ledger.rendered);
663
- if (ledgerStale) await writeManaged(projectDir, driverTarget, { ids: owned, rendered });
704
+ if (ledgerStale) await writeManaged(projectDir, harnessTarget, { ids: owned, rendered });
664
705
  if (Object.keys(next).length === 0 && !existingFile) {
665
706
  return { path: configPath, written: false, servers: owned, removed, skipped };
666
707
  }
@@ -839,6 +880,16 @@ function libraryDiskHashes(libPath, cache, registry) {
839
880
  }
840
881
  return hashes;
841
882
  }
883
+ function repoManifestVersion(repoDir) {
884
+ try {
885
+ const { manifest } = decodeSkaileManifest(
886
+ readFileSync(join(repoDir, "skaile.manifest.yaml"), "utf8")
887
+ );
888
+ return manifest.version || void 0;
889
+ } catch {
890
+ return void 0;
891
+ }
892
+ }
842
893
  function manifestFileHasAssetsArray(libPath) {
843
894
  try {
844
895
  const doc = parse(readFileSync(join(libPath, "skaile.manifest.yaml"), "utf8"));
@@ -847,6 +898,10 @@ function manifestFileHasAssetsArray(libPath) {
847
898
  return false;
848
899
  }
849
900
  }
901
+ var libraryAssetCheck;
902
+ function setLibraryAssetCheck(check) {
903
+ libraryAssetCheck = check;
904
+ }
850
905
  function isUnlistedLibraryAsset(entry, libPath) {
851
906
  const manifest = loadSkPublishManifest(libPath);
852
907
  const listed = manifest?.assets ?? [];
@@ -1117,7 +1172,9 @@ function relockedRefs(prev, next) {
1117
1172
  e.library?.version ?? "",
1118
1173
  e.library && !e.library.installed ? e.library.name : "",
1119
1174
  e.library?.sha256 ?? e.sha256,
1120
- key.includes("#0.0.0-sha.") ? "" : e.source?.commit ?? ""
1175
+ key.includes("#0.0.0-sha.") ? "" : e.source?.commit ?? "",
1176
+ // The `../` compose folders are part of the lock: `update` moving them is a re-lock.
1177
+ (e.composed ?? []).map((f) => `${f.path}:${f.sha256}`).join("\n")
1121
1178
  ].join("\0");
1122
1179
  const out = [];
1123
1180
  for (const [key, entry] of Object.entries(next.assets)) {
@@ -1152,9 +1209,13 @@ function libraryMoves(prev, next) {
1152
1209
  }
1153
1210
  return out;
1154
1211
  }
1212
+ function unregisteredLibraryName(origin) {
1213
+ return lastLibraryName(origin.name) ?? origin.name;
1214
+ }
1155
1215
  function unregisteredLibraryFix(origin, ref) {
1156
- const register = origin.url ? `\`skaile library init ${origin.name} --git ${origin.url}\` (no registered library has the remote ${origin.url} either)` : `\`skaile library init ${origin.name} --path <dir>\``;
1157
- return `register library "${origin.name}" again with ${register}, or drop the dependency with \`skaile remove ${ref}\``;
1216
+ const name = unregisteredLibraryName(origin);
1217
+ const register = origin.url ? `\`skaile library init ${name} --git ${origin.url}\` (no registered library has the remote ${origin.url} either)` : `\`skaile library init ${name} --path <dir>\``;
1218
+ return `register library "${name}" again with ${register}, or drop the dependency with \`skaile remove ${ref}\``;
1158
1219
  }
1159
1220
  function declaredNoHolderReason(ref) {
1160
1221
  return `is declared but no library or source holds it \u2014 register the library that holds it with \`skaile library init <name> --path <dir>\`, or drop it with \`skaile remove ${ref.split("#")[0]}\``;
@@ -1180,7 +1241,7 @@ function libraryCollisionSummary(all) {
1180
1241
  return `${all.length} assets exist in several libraries (${libraries.join(", ")}); using ${usedText.join(", ")}. Highest version wins; an equal version goes to the default library, then by name. ` + (differing.length > 0 ? `Same version, different bytes for: ${differing.join(", ")}. ` : "") + "Pin a version (<ref>#<version>) to choose another; `--verbose` lists each asset.";
1181
1242
  }
1182
1243
  function lockedLibraryProblem(lookup, origin, ref) {
1183
- return lookup.state === "dir-missing" ? missingLibraryDirMessage({ name: origin.name, path: lookup.path }) : `library "${origin.name}" is not registered \u2014 renamed or removed? ${unregisteredLibraryFix(origin, ref)}`;
1244
+ return lookup.state === "dir-missing" ? missingLibraryDirMessage({ name: origin.name, path: lookup.path }) : `library "${unregisteredLibraryName(origin)}" is not registered \u2014 renamed or removed? ${unregisteredLibraryFix(origin, ref)}`;
1184
1245
  }
1185
1246
  function gapIdentity(ref) {
1186
1247
  const p = parseRefTolerant(ref);
@@ -1293,7 +1354,7 @@ function decodeEntryHarnesses(value) {
1293
1354
  for (const [key, list] of Object.entries(value)) {
1294
1355
  if (!Array.isArray(list)) continue;
1295
1356
  const valid = list.filter(
1296
- (h) => SUPPORTED_DRIVER_TARGETS.includes(h)
1357
+ (h) => SUPPORTED_HARNESSES.includes(h)
1297
1358
  );
1298
1359
  if (valid.length > 0) out[key] = [...new Set(valid)];
1299
1360
  }
@@ -1302,8 +1363,8 @@ function decodeEntryHarnesses(value) {
1302
1363
  var AssetManager = class {
1303
1364
  /** Resolved absolute path to the workspace root. */
1304
1365
  projectDir;
1305
- /** Agent framework driver target used for all deploy operations. */
1306
- driverTarget;
1366
+ /** Harness all deploy operations target (a `HarnessName`). */
1367
+ harness;
1307
1368
  /** Whether this instance operates in global-install mode. */
1308
1369
  global;
1309
1370
  /** Asset-kind registry shared with the host (one instance per process). */
@@ -1344,7 +1405,7 @@ var AssetManager = class {
1344
1405
  this.projectDir = resolve(opts.projectDir);
1345
1406
  this.global = opts.global ?? false;
1346
1407
  this.registry = opts.registry;
1347
- this.driverTarget = opts.driverTarget ?? (this.global ? void 0 : resolveConfiguredDriverTarget(this.projectDir)) ?? "claude-code";
1408
+ this.harness = opts.harness ?? (this.global ? void 0 : resolveConfiguredHarnessName(this.projectDir)) ?? "claude-code";
1348
1409
  this.harnessesOverride = opts.harnesses ?? opts.backends;
1349
1410
  this.injectedStoreFetcher = opts.storeFetcher;
1350
1411
  this.injectedAssetFetcher = opts.assetFetcher;
@@ -1369,7 +1430,7 @@ var AssetManager = class {
1369
1430
  /**
1370
1431
  * Root for this manager's **state** — config SSOT, lock, cache, history.
1371
1432
  * `~/.skaile` in global mode (the cross-harness SSOT), else the project dir.
1372
- * Deploy dirs are unaffected; they come from `DRIVER_TARGETS[target]`.
1433
+ * Deploy dirs are unaffected; they come from `HARNESS_TARGETS[target]`.
1373
1434
  */
1374
1435
  get stateRoot() {
1375
1436
  return this.global ? globalSkaileDir() : this.projectDir;
@@ -1379,11 +1440,11 @@ var AssetManager = class {
1379
1440
  * filter), else the explicit `global_harnesses:` of `~/.skaile/skaile.yaml`, else every harness
1380
1441
  * whose root dir exists under `~` plus the harness the project is configured for (a project on
1381
1442
  * a harness whose dir does not exist yet still gets its user-scope assets). In project mode
1382
- * this is exactly `[driverTarget]`, so the shared fan-out loop degenerates to the
1443
+ * this is exactly `[harness]`, so the shared fan-out loop degenerates to the
1383
1444
  * single-target path.
1384
1445
  */
1385
1446
  targetHarnesses() {
1386
- if (!this.global) return [this.driverTarget];
1447
+ if (!this.global) return [this.harness];
1387
1448
  if (this.harnessesOverride && this.harnessesOverride.length > 0) return this.harnessesOverride;
1388
1449
  return this.defaultGlobalHarnesses();
1389
1450
  }
@@ -1391,7 +1452,7 @@ var AssetManager = class {
1391
1452
  defaultGlobalHarnesses() {
1392
1453
  const resolved = resolveGlobalHarnesses();
1393
1454
  if (resolveGlobalSkWorkspaceConfig().global_harnesses?.length) return resolved;
1394
- const configured = resolveConfiguredDriverTarget(this.projectDir);
1455
+ const configured = resolveConfiguredHarnessName(this.projectDir);
1395
1456
  return configured && !resolved.includes(configured) ? [...resolved, configured] : resolved;
1396
1457
  }
1397
1458
  /**
@@ -1429,6 +1490,43 @@ var AssetManager = class {
1429
1490
  return !recorded || recorded.includes(target);
1430
1491
  });
1431
1492
  }
1493
+ /**
1494
+ * A 5.12.0 global record has no `global_asset_harnesses:` key, yet `add --global --harness`
1495
+ * wrote one copy only. On the first global `install`, an entry with exactly one existing copy
1496
+ * among several default harnesses is that harness's subset (OQ6): record it, so the install
1497
+ * does not fan the asset out to harnesses the user never asked for (p1442). A copy under the
1498
+ * 5.12.0 omp folder (`~/.omp/skills`) counts as an omp copy. Nothing is inferred once the key
1499
+ * exists (an entry without a row then means "every harness"), with one default harness, or
1500
+ * with no copy yet. Global mode only; returns the rows written.
1501
+ */
1502
+ inferLegacyHarnessSubsets(entries) {
1503
+ if (!this.global) return [];
1504
+ const configPath = join(this.stateRoot, "skaile.yaml");
1505
+ if (!existsSync(configPath)) return [];
1506
+ let raw;
1507
+ try {
1508
+ raw = parse(readFileSync(configPath, "utf8"));
1509
+ } catch {
1510
+ return [];
1511
+ }
1512
+ if (!raw || typeof raw !== "object" || ENTRY_HARNESSES_KEY in raw) return [];
1513
+ const all = this.defaultGlobalHarnesses();
1514
+ if (all.length < 2) return [];
1515
+ const rows = [];
1516
+ for (const e of entries) {
1517
+ const component = this.installTarget(e.kind);
1518
+ if (!component || !e.name) continue;
1519
+ const holding = all.filter(
1520
+ (h) => isDeployed(component, e.name, h, true) || h === "omp" && legacyOmpPaths(component, e.name).length > 0
1521
+ );
1522
+ if (holding.length !== 1) continue;
1523
+ const publisher = e.publisher?.replace(/^@/, "");
1524
+ const ref = `${e.kind}:${publisher ? `@${publisher}/` : ""}${e.name}`;
1525
+ if (this.setEntryHarnessRow(raw, ref, holding)) rows.push({ ref, harnesses: holding });
1526
+ }
1527
+ if (rows.length > 0) writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
1528
+ return rows;
1529
+ }
1432
1530
  /**
1433
1531
  * Set (or, with `harnesses` undefined, clear) the harness row of `ref` in the parsed
1434
1532
  * `~/.skaile/skaile.yaml` `raw`. Returns whether `raw` changed.
@@ -1520,7 +1618,7 @@ var AssetManager = class {
1520
1618
  return this.legacyCopiesRemoved.splice(0);
1521
1619
  }
1522
1620
  /**
1523
- * The harnesses `add` / `install` deploy into: `[driverTarget]` for a project, the global
1621
+ * The harnesses `add` / `install` deploy into: `[harness]` for a project, the global
1524
1622
  * harness set (see {@link AssetManager.targetHarnesses}) for a global manager.
1525
1623
  */
1526
1624
  deployTargets() {
@@ -1554,18 +1652,38 @@ var AssetManager = class {
1554
1652
  get patchDir() {
1555
1653
  return join(this.projectDir, ".skaile", "patches");
1556
1654
  }
1557
- /** Deploy options for one harness. In global mode, `driverTarget` is the
1558
- * fan-out target (not the constructor's `driverTarget`, which is project-only). */
1559
- deployOptsFor(target, link, onSecretFile) {
1655
+ /** Deploy options for one harness. In global mode, `harness` is the
1656
+ * fan-out target (not the constructor's `harness`, which is project-only). */
1657
+ deployOptsFor(target, link, onSecretFile, composed) {
1658
+ const records = this.global ? void 0 : this.composedRecords();
1560
1659
  return {
1561
1660
  registry: this.registry,
1562
- driverTarget: target,
1661
+ harness: target,
1563
1662
  global: this.global,
1564
1663
  cwd: this.projectDir,
1565
1664
  link: link === true,
1566
- ...onSecretFile ? { onSecretFile: (entry, p) => onSecretFile(canonicalEntryRef(entry), p) } : {}
1665
+ ...onSecretFile ? { onSecretFile: (entry, p) => onSecretFile(canonicalEntryRef(entry), p) } : {},
1666
+ ...records ? { lockedComposed: (agent) => records.get(agent) } : {},
1667
+ ...composed ? {
1668
+ refreshComposed: composed.refresh,
1669
+ onComposedDrift: (entry, ref) => composed.onDrift(canonicalEntryRef(entry), ref)
1670
+ } : {}
1567
1671
  };
1568
1672
  }
1673
+ /** Agent name → the `../` compose folder files its lock entry records (`LockEntry.composed`). */
1674
+ composedRecords() {
1675
+ const out = /* @__PURE__ */ new Map();
1676
+ for (const [key, entry] of Object.entries(this.tryReadLock()?.assets ?? {})) {
1677
+ if (!entry.composed?.length) continue;
1678
+ const { name } = parseCanonicalLockKey(key);
1679
+ if (name) out.set(name, entry.composed);
1680
+ }
1681
+ return out;
1682
+ }
1683
+ /** `install`'s `Missing:` line for a `../` compose folder the library moved past the lock. */
1684
+ composedDriftLine(agentRef, composeRef) {
1685
+ return `${agentRef} (composes ${composeRef}: the library's copy changed since the lock; \`skaile update\` moves the lock to it)`;
1686
+ }
1569
1687
  /**
1570
1688
  * Names of the `mcp-server` assets the lock holds (the declaration ids, unscoped); a missing
1571
1689
  * `.mcp.json` entry of one counts as drift even before skaile owned it.
@@ -1588,7 +1706,7 @@ var AssetManager = class {
1588
1706
  if (locked.size === 0) return [];
1589
1707
  let rows;
1590
1708
  try {
1591
- rows = await mcpServerDrift(this.projectDir, this.driverTarget, { locked });
1709
+ rows = await mcpServerDrift(this.projectDir, this.harness, { locked });
1592
1710
  } catch {
1593
1711
  return [];
1594
1712
  }
@@ -1616,13 +1734,9 @@ var AssetManager = class {
1616
1734
  */
1617
1735
  async mcpRenderFootprint(name) {
1618
1736
  if (this.global) return void 0;
1619
- const file = mcpConfigFileOf(this.driverTarget);
1737
+ const file = mcpConfigFileOf(this.harness);
1620
1738
  if (!file) return void 0;
1621
- const footprint = await mcpRenderedFootprint(
1622
- this.projectDir,
1623
- this.driverTarget,
1624
- unscopedName(name)
1625
- );
1739
+ const footprint = await mcpRenderedFootprint(this.projectDir, this.harness, unscopedName(name));
1626
1740
  return footprint ? { ...footprint, written: true } : { file, written: false };
1627
1741
  }
1628
1742
  /**
@@ -1634,11 +1748,11 @@ var AssetManager = class {
1634
1748
  */
1635
1749
  async mcpPendingRender() {
1636
1750
  if (this.global) return [];
1637
- const file = mcpConfigFileOf(this.driverTarget);
1751
+ const file = mcpConfigFileOf(this.harness);
1638
1752
  if (!file) return [];
1639
1753
  let rows;
1640
1754
  try {
1641
- rows = await mcpServerDrift(this.projectDir, this.driverTarget, {
1755
+ rows = await mcpServerDrift(this.projectDir, this.harness, {
1642
1756
  locked: this.lockedMcpNames()
1643
1757
  });
1644
1758
  } catch {
@@ -1652,7 +1766,7 @@ var AssetManager = class {
1652
1766
  });
1653
1767
  }
1654
1768
  /**
1655
- * Render the project's declared MCP servers into the driver target's own
1769
+ * Render the project's declared MCP servers into the harness target's own
1656
1770
  * native MCP config (`<project>/.mcp.json` for `claude-code`), so the coding
1657
1771
  * agent sees the same servers skaile's agent loop wires up.
1658
1772
  *
@@ -1665,14 +1779,14 @@ var AssetManager = class {
1665
1779
  * removed) because they had drifted from the declaration: `install` names them, as it does
1666
1780
  * a restored skill file.
1667
1781
  */
1668
- async renderDriverMcpConfig() {
1782
+ async renderHarnessMcpConfig() {
1669
1783
  if (this.global) return [];
1670
1784
  const before = await this.mcpDriftRows();
1671
1785
  try {
1672
- await renderMcpServerConfig(this.projectDir, this.driverTarget);
1786
+ await renderMcpServerConfig(this.projectDir, this.harness);
1673
1787
  } catch (err) {
1674
1788
  console.warn(
1675
- `skaile: could not render MCP config for ${this.driverTarget}: ${err instanceof Error ? err.message : String(err)}`
1789
+ `skaile: could not render MCP config for ${this.harness}: ${err instanceof Error ? err.message : String(err)}`
1676
1790
  );
1677
1791
  return [];
1678
1792
  }
@@ -1696,7 +1810,7 @@ var AssetManager = class {
1696
1810
  return restored;
1697
1811
  }
1698
1812
  /**
1699
- * Render every agent instance of `skaile.yaml` into the driver target's native
1813
+ * Render every agent instance of `skaile.yaml` into the harness target's native
1700
1814
  * agent files (`.claude/agents/<id>.md`, …) and prune the renderings of
1701
1815
  * instances that left the config. Runs after the skills deploy, so composed
1702
1816
  * skills resolve. Project scope only. An instance whose `ref` resolves to no agent is
@@ -1707,10 +1821,10 @@ var AssetManager = class {
1707
1821
  try {
1708
1822
  const result = installAgentInstances({
1709
1823
  projectDir: this.projectDir,
1710
- driverTarget: this.driverTarget
1824
+ harness: this.harness
1711
1825
  });
1712
1826
  const details = [];
1713
- for (const u of unboundAgentInstances(this.projectDir, this.driverTarget)) {
1827
+ for (const u of unboundAgentInstances(this.projectDir, this.harness)) {
1714
1828
  if (!u.ref.startsWith("agent:")) continue;
1715
1829
  const at = result.errors.findIndex((e) => e.startsWith(`agent instance "${u.id}":`));
1716
1830
  if (at < 0) continue;
@@ -1727,7 +1841,7 @@ var AssetManager = class {
1727
1841
  };
1728
1842
  } catch (err) {
1729
1843
  console.warn(
1730
- `skaile: could not render agent instances for ${this.driverTarget}: ${err instanceof Error ? err.message : String(err)}`
1844
+ `skaile: could not render agent instances for ${this.harness}: ${err instanceof Error ? err.message : String(err)}`
1731
1845
  );
1732
1846
  return {};
1733
1847
  }
@@ -1770,6 +1884,15 @@ var AssetManager = class {
1770
1884
  for (const [slug, decl] of Object.entries(repositories)) {
1771
1885
  const localPath = this.resolveRepoDir(decl, slug);
1772
1886
  if (!localPath || !existsSync(localPath)) continue;
1887
+ if (decl.url && normalizeRepoUrl(decl.url) !== normalizeRepoUrl(FACTORY_SOURCE_URL) && !existsSync(join(localPath, ".git"))) {
1888
+ this.reportSourceError(
1889
+ { localPath, sourceUrl: decl.url, commit: "" },
1890
+ new Error(
1891
+ `${decl.url}: its clone ${localPath} is not a git repository, so git pull fails - run \`skaile source sync\` to clone it again`
1892
+ )
1893
+ );
1894
+ continue;
1895
+ }
1773
1896
  const commit = getRepoCommit(localPath) ?? "0".repeat(40);
1774
1897
  clones.push({
1775
1898
  localPath,
@@ -2093,6 +2216,33 @@ var AssetManager = class {
2093
2216
  if (!scan) return [];
2094
2217
  return [...scan.byKey.values()].flat();
2095
2218
  }
2219
+ /**
2220
+ * The version `add` deploys for each asset of a source clone registered as a `reader`
2221
+ * library, when its file declares none: the repo commit pseudo-version (p855). `search`
2222
+ * reads this where no project is in scope, so it lists what `add` locks, not the index
2223
+ * default.
2224
+ *
2225
+ * @returns `<library>\0<kind>:@<publisher>/<name>` -> version; only assets that declare none.
2226
+ */
2227
+ async sourceAssetVersions() {
2228
+ const out = /* @__PURE__ */ new Map();
2229
+ const scan = await this.scanLibraries();
2230
+ if (!scan) return out;
2231
+ const snap = await this.loadLibraryIndex();
2232
+ for (const [key, candidates] of scan.byKey) {
2233
+ for (const c of candidates) {
2234
+ if (c.entry.version) continue;
2235
+ const lib = snap?.libraries.find((l) => l.name === c.library);
2236
+ if (lib?.ownership !== "reader" || !("url" in lib.backendConfig)) continue;
2237
+ const manifestVersion = repoManifestVersion(lib.path);
2238
+ const commit = getRepoCommit(lib.path);
2239
+ if (manifestVersion) out.set(`${c.library}\0${key}`, manifestVersion);
2240
+ else if (commit)
2241
+ out.set(`${c.library}\0${key}`, `${PSEUDO_VERSION_PREFIX}${commit.slice(0, 7)}`);
2242
+ }
2243
+ }
2244
+ return out;
2245
+ }
2096
2246
  /**
2097
2247
  * Every origin that holds `ref` (`kind:@publisher/name`) with the version it holds, in
2098
2248
  * the order `add <ref>` prefers them, so the first row is the one `add` deploys: the
@@ -2486,7 +2636,7 @@ var AssetManager = class {
2486
2636
  const slot = `${component}/${a.name}`;
2487
2637
  const prior = seen.get(slot);
2488
2638
  if (prior && differs(prior, a)) {
2489
- const dir2 = deployedDir(component, a.name, this.driverTarget, this.global, this.projectDir);
2639
+ const dir2 = deployedDir(component, a.name, this.harness, this.global, this.projectDir);
2490
2640
  throw new Error(
2491
2641
  `${refOf(prior)} and ${refOf(a)} both deploy to ${shown(dir2)} \u2014 keep only one of them`
2492
2642
  );
@@ -2558,7 +2708,7 @@ var AssetManager = class {
2558
2708
  }
2559
2709
  const drift = deployedAssetDrift(entry, {
2560
2710
  registry: this.registry,
2561
- driverTarget: target,
2711
+ harness: target,
2562
2712
  global: this.global,
2563
2713
  cwd: this.projectDir
2564
2714
  });
@@ -2602,7 +2752,14 @@ var AssetManager = class {
2602
2752
  if (!existsSync(indexPath)) return null;
2603
2753
  const index = new LocalIndex({ indexPath });
2604
2754
  try {
2605
- return { libraries: await index.listSources(), defs: await index.listAssetDefs() };
2755
+ const libraries = await index.listSources();
2756
+ const defs = await index.listAssetDefs();
2757
+ const hidden = this.undeclaredSourceClones(libraries);
2758
+ if (hidden.size === 0) return { libraries, defs };
2759
+ return {
2760
+ libraries: libraries.filter((l) => !hidden.has(l.id)),
2761
+ defs: defs.filter((d) => !d.libraryId || !hidden.has(d.libraryId))
2762
+ };
2606
2763
  } finally {
2607
2764
  index.close();
2608
2765
  }
@@ -2610,6 +2767,32 @@ var AssetManager = class {
2610
2767
  return null;
2611
2768
  }
2612
2769
  }
2770
+ /**
2771
+ * Ids of the registered libraries that are the clone of a source this project does not
2772
+ * declare. `source add` registers the clone as a machine-wide reader library so `search`
2773
+ * and the indexer can read it, but a `sources:` clone belongs to the projects that declare
2774
+ * it (OQ12, p321): another project neither resolves it, nor ties with it by name, nor has
2775
+ * `update` re-pin its locked assets to it. A reader library the user registered by hand
2776
+ * (`library init --reader --git`) lives outside the sources cache and is never hidden.
2777
+ */
2778
+ undeclaredSourceClones(libraries) {
2779
+ const hidden = /* @__PURE__ */ new Set();
2780
+ if (!this.global && !findWorkspaceRoot(this.projectDir)) return hidden;
2781
+ let declared;
2782
+ try {
2783
+ declared = new Set(this.loadConfig().sources.map((s) => sourceCacheKey(s.url)));
2784
+ } catch {
2785
+ return hidden;
2786
+ }
2787
+ const cloneRoots = [join(globalCacheRoot(), "sources"), this.reposDir].map((d) => resolve(d));
2788
+ for (const l of libraries) {
2789
+ if (l.ownership !== "reader" || !("url" in l.backendConfig)) continue;
2790
+ const at = resolve(l.path);
2791
+ if (!cloneRoots.some((root) => at.startsWith(root + sep))) continue;
2792
+ if (!declared.has(sourceCacheKey(l.backendConfig.url))) hidden.add(l.id);
2793
+ }
2794
+ return hidden;
2795
+ }
2613
2796
  /**
2614
2797
  * Library-origin lock entries for the assets {@link resolveLibraryEntries}
2615
2798
  * matched. The locked version is the one actually deployed: the on-disk
@@ -2741,7 +2924,7 @@ var AssetManager = class {
2741
2924
  const lookup = this.lockedLibrary(e.library, snap, { kind, publisher, name });
2742
2925
  if (lookup.state === "ok") continue;
2743
2926
  const component = this.installTarget(kind);
2744
- const deployed = component !== void 0 && isDeployed(component, name, this.driverTarget, this.global, this.projectDir);
2927
+ const deployed = component !== void 0 && isDeployed(component, name, this.harness, this.global, this.projectDir);
2745
2928
  const problem = lockedLibraryProblem(lookup, e.library, `${kind}:@${publisher}/${name}`);
2746
2929
  const kept = deployed ? "the deployed copy and its lock entry are kept" : "its lock entry is kept; no deployed copy exists";
2747
2930
  lines.push(`${ref} (${problem}; ${kept})`);
@@ -2753,14 +2936,19 @@ var AssetManager = class {
2753
2936
  * `install --locked`. An entry is restored only when its library is still
2754
2937
  * registered/on disk, still holds the asset, and still offers the locked
2755
2938
  * version; anything else is reported in `missing` with the reason.
2939
+ *
2940
+ * @param opts.storeFallback - `install --locked` only: an entry whose library is not registered
2941
+ * here is restored from a store that serves the locked sha256 (OQ15, p1490). Reads such as
2942
+ * the drift check never ask a store.
2756
2943
  */
2757
- async restoreLibraryLockEntries(lock) {
2944
+ async restoreLibraryLockEntries(lock, opts) {
2758
2945
  const entries = [];
2759
2946
  const missing = [];
2947
+ const viaStore = [];
2760
2948
  const locked = Object.entries(lock.assets).filter(
2761
2949
  ([, e]) => e.library !== void 0 && !e.library.installed
2762
2950
  );
2763
- if (locked.length === 0) return { entries, missing };
2951
+ if (locked.length === 0) return { entries, missing, viaStore };
2764
2952
  const snap = await this.loadLibraryIndex();
2765
2953
  const diskHashes = /* @__PURE__ */ new Map();
2766
2954
  const fileSets = /* @__PURE__ */ new Map();
@@ -2773,6 +2961,12 @@ var AssetManager = class {
2773
2961
  }
2774
2962
  const lookup = this.lockedLibrary(origin, snap, { kind, publisher, name });
2775
2963
  if (lookup.state !== "ok") {
2964
+ const fallback = lookup.state === "unregistered" && opts?.storeFallback ? await this.storeEntryForLockedLibraryAsset(publisher, kind, name, origin) : null;
2965
+ if (fallback) {
2966
+ entries.push(fallback);
2967
+ viaStore.push(ref);
2968
+ continue;
2969
+ }
2776
2970
  missing.push(
2777
2971
  `${ref} (${lockedLibraryProblem(lookup, origin, `${kind}:@${publisher}/${name}`)})`
2778
2972
  );
@@ -2795,7 +2989,7 @@ var AssetManager = class {
2795
2989
  const component = this.installTarget(kind);
2796
2990
  const newer = gt(coerceVersion(current), coerceVersion(origin.version));
2797
2991
  const comparable = !isPseudoVersion(current) && !isPseudoVersion(origin.version);
2798
- const intact = (newer || comparable) && (component === void 0 || isDeployed(component, name, this.driverTarget, this.global, this.projectDir));
2992
+ const intact = (newer || comparable) && (component === void 0 || isDeployed(component, name, this.harness, this.global, this.projectDir));
2799
2993
  if (!intact) {
2800
2994
  missing.push(
2801
2995
  `${ref} (library "${lookup.name}" is at ${current}, locked ${origin.version}${newer || comparable ? "; `skaile update` moves the lock to it" : ""})`
@@ -2815,27 +3009,76 @@ var AssetManager = class {
2815
3009
  found.version = sameVersion ? origin.version : current;
2816
3010
  entries.push(withLibraryFiles(found, libPath, fileSets, this.registry));
2817
3011
  }
2818
- return { entries, missing };
3012
+ return { entries, missing, viaStore };
3013
+ }
3014
+ /**
3015
+ * The store's copy of a library-origin lock entry whose library is not registered here: a
3016
+ * store (project `stores:` or the global catalog) that serves `kind:@publisher/name#version`
3017
+ * under the very sha256 the lock recorded holds the same bytes. The entry is fetched and
3018
+ * verified like any store asset; the lock stays as it is. `null` when the lock has no hash,
3019
+ * no store answers, or the hash differs (OQ15, p1490).
3020
+ */
3021
+ async storeEntryForLockedLibraryAsset(publisher, kind, name, origin) {
3022
+ if (!origin.sha256 || !origin.version || isPseudoVersion(origin.version)) return null;
3023
+ const { repositories, stores: projectStores } = this.loadConfig();
3024
+ const stores = [...projectStores, ...await this.globalStoreFallback(projectStores)];
3025
+ const fetcher = this.storeFetcherFor(stores);
3026
+ if (!fetcher) return null;
3027
+ for (const store of stores) {
3028
+ try {
3029
+ const m = await fetcher.getInstallManifest(
3030
+ store.url,
3031
+ `${kind}:@${publisher}/${name}#${origin.version}`
3032
+ );
3033
+ if (!m || m.sha256 !== origin.sha256) continue;
3034
+ const [entry] = await this.buildCatalogEntries(
3035
+ [
3036
+ {
3037
+ publisher,
3038
+ kind,
3039
+ name,
3040
+ version: origin.version,
3041
+ sourceUrl: m.sourceUrl,
3042
+ commit: m.commit,
3043
+ files: m.files,
3044
+ sha256: m.sha256,
3045
+ ...m.deps?.length ? { deps: m.deps, storeRequires: m.deps } : {}
3046
+ }
3047
+ ],
3048
+ repositories
3049
+ );
3050
+ if (entry) return entry;
3051
+ } catch (err) {
3052
+ this.noteStoreFailure(store.url, err);
3053
+ }
3054
+ }
3055
+ return null;
2819
3056
  }
2820
3057
  /**
2821
3058
  * Whether a deployed copy exists for the lock entries `install` kept for the unresolved
2822
- * `ref`. A kind with no install target has no deployed copy.
3059
+ * `ref`. A kind with no install target has none, except an `mcp-server`: its copy is the
3060
+ * `.mcp.json` entry skaile wrote and the payload that entry points into (p792).
2823
3061
  */
2824
- keptCopyDeployed(kept, ref) {
3062
+ async keptCopyDeployed(kept, ref) {
2825
3063
  const want = parseRefTolerant(ref.split(" ")[0] ?? ref);
2826
3064
  if (!want) return false;
2827
- return Object.keys(kept.assets).some((key) => {
3065
+ for (const key of Object.keys(kept.assets)) {
2828
3066
  const id = parseCanonicalLockKey(key);
2829
- if (id.kind !== want.kind || id.name !== want.name) return false;
2830
- if (want.publisher && id.publisher !== want.publisher) return false;
3067
+ if (id.kind !== want.kind || id.name !== want.name) continue;
3068
+ if (want.publisher && id.publisher !== want.publisher) continue;
2831
3069
  const component = this.installTarget(id.kind);
2832
- return component !== void 0 && isDeployed(component, id.name, this.driverTarget, this.global, this.projectDir);
2833
- });
3070
+ if (component !== void 0) {
3071
+ if (isDeployed(component, id.name, this.harness, this.global, this.projectDir)) return true;
3072
+ } else if (id.kind === "mcp-server" && !this.global && await mcpCommittedRenderIntact(this.projectDir, this.harness, id.name)) {
3073
+ return true;
3074
+ }
3075
+ }
3076
+ return false;
2834
3077
  }
2835
3078
  /** Whether the deployed copy of a library asset is on disk; a kind with no install target has none to check. */
2836
3079
  lockedCopyDeployed(kind, name) {
2837
3080
  const component = this.installTarget(kind);
2838
- return component === void 0 || isDeployed(component, name, this.driverTarget, this.global, this.projectDir);
3081
+ return component === void 0 || isDeployed(component, name, this.harness, this.global, this.projectDir);
2839
3082
  }
2840
3083
  /**
2841
3084
  * The library-origin lock entries `install` keeps when the library holds a newer version:
@@ -2953,6 +3196,24 @@ var AssetManager = class {
2953
3196
  lockedRefsNamed(kind, name) {
2954
3197
  return Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey).filter((id) => id.kind === kind && id.name === name).map((id) => id.publisher ? `${kind}:@${id.publisher}/${name}` : `${kind}:${name}`);
2955
3198
  }
3199
+ /**
3200
+ * The library a library-origin lock entry of `kind` and `name` (and `publisher`, when given)
3201
+ * resolves to on this machine, or `undefined` when the lock holds no such entry, it is not
3202
+ * from a library, or its library is not here. `info` prints it next to `source:`.
3203
+ */
3204
+ async lockedLibraryOf(kind, name, publisher) {
3205
+ const bare = publisher?.replace(/^@/, "");
3206
+ const names = await this.lockedLibraryNames();
3207
+ for (const [key, entry] of Object.entries(this.tryReadLock()?.assets ?? {})) {
3208
+ if (!entry.library || entry.library.installed) continue;
3209
+ const id = parseCanonicalLockKey(key);
3210
+ if (id.kind !== kind || id.name !== name || !id.publisher) continue;
3211
+ if (bare && id.publisher !== bare) continue;
3212
+ const lib = names.get(`${kind}:${id.publisher}/${name}`);
3213
+ if (lib) return lib;
3214
+ }
3215
+ return void 0;
3216
+ }
2956
3217
  /**
2957
3218
  * Where each library-origin lock entry of this project resolves on this machine: identity
2958
3219
  * `kind:publisher/name` (no scope sigil, no version) → the name the locked library is
@@ -2995,6 +3256,88 @@ var AssetManager = class {
2995
3256
  }
2996
3257
  return { libraries: await this.lockedLibraryNames(), shas };
2997
3258
  }
3259
+ /**
3260
+ * Canonical refs of the locked source assets that share a source URL with `resolved` but
3261
+ * are locked at another commit than the one `resolved` carries for it. Assets in `resolved`
3262
+ * and library-origin entries are skipped.
3263
+ */
3264
+ staleSourceSiblingRefs(resolved, declared = []) {
3265
+ const pinOf = /* @__PURE__ */ new Map();
3266
+ for (const d of declared) {
3267
+ const id = refIdentity(d);
3268
+ const pin = parseAssetRefLoose(d)?.pin;
3269
+ if (id !== null && pin) pinOf.set(id.replace(/^@/, ""), pin);
3270
+ }
3271
+ const commitOf = /* @__PURE__ */ new Map();
3272
+ const held = /* @__PURE__ */ new Set();
3273
+ for (const c of resolved) {
3274
+ if (!c.sourceUrl || !c.commit) continue;
3275
+ commitOf.set(normalizeRepoUrl(c.sourceUrl), c.commit);
3276
+ held.add(`${c.publisher.replace(/^@/, "")}/${c.kind}:${c.name}`);
3277
+ }
3278
+ const out = [];
3279
+ for (const [key, entry] of Object.entries(this.tryReadLock()?.assets ?? {})) {
3280
+ const src = entry.source;
3281
+ if (!src?.url || entry.library) continue;
3282
+ const commit = commitOf.get(normalizeRepoUrl(src.url));
3283
+ if (!commit || src.commit === commit) continue;
3284
+ const { publisher, kind, name } = parseCanonicalLockKey(key);
3285
+ if (!publisher || !kind || !name || held.has(`${publisher}/${kind}:${name}`)) continue;
3286
+ const pin = pinOf.get(`${publisher}/${kind}:${name}`);
3287
+ out.push(`${kind}:@${publisher}/${name}${pin ? `#${pin}` : ""}`);
3288
+ }
3289
+ return out;
3290
+ }
3291
+ /**
3292
+ * The lock entries that came from a source or the store (a `source:`, no `library:`), by
3293
+ * identity `<publisher>/<kind>:<name>` -> locked version. The lock's origin
3294
+ * wins: a library registered later that holds the same ref does not take such an asset
3295
+ * (`update`, `install`, `add`; OQ15, p1490).
3296
+ */
3297
+ lockedOriginVersions() {
3298
+ const out = /* @__PURE__ */ new Map();
3299
+ for (const [key, e] of Object.entries(this.tryReadLock()?.assets ?? {})) {
3300
+ if (!e.source || e.library) continue;
3301
+ const { publisher, kind, name, version } = parseCanonicalLockKey(key);
3302
+ if (publisher && kind && name) out.set(`${publisher}/${kind}:${name}`, version ?? "");
3303
+ }
3304
+ return out;
3305
+ }
3306
+ /**
3307
+ * Say which registered library holds a ref the lock keeps on its source or the store: the
3308
+ * candidate that lost, with the way to switch (p1490). Printed once per `add`.
3309
+ */
3310
+ async noteLosingLibraries(refs) {
3311
+ const lock = this.tryReadLock();
3312
+ for (const ref of refs) {
3313
+ const plain = ref.split("#")[0] ?? ref;
3314
+ let hit;
3315
+ try {
3316
+ hit = await this.resolveLibraryEntries([plain], { quiet: true });
3317
+ } catch {
3318
+ continue;
3319
+ }
3320
+ const entry = hit.entries[0];
3321
+ const library = entry ? hit.libraryOf.get(entry) : void 0;
3322
+ if (!entry || !library) continue;
3323
+ const canonical = canonicalEntryRef(entry);
3324
+ const plainCanonical = canonical.split("#")[0] ?? canonical;
3325
+ const lockedUrl = Object.entries(lock?.assets ?? {}).find(([k, e]) => {
3326
+ const id = parseCanonicalLockKey(k);
3327
+ return e.source && !e.library && `${id.kind}:@${id.publisher}/${id.name}` === plainCanonical;
3328
+ })?.[1].source?.url;
3329
+ if (lockedUrl) {
3330
+ const ownClone = (await this.loadLibraryIndex())?.libraries.some(
3331
+ (l) => l.name === library && l.ownership === "reader" && "url" in l.backendConfig && sourceCacheKey(l.backendConfig.url) === sourceCacheKey(lockedUrl)
3332
+ );
3333
+ if (ownClone) continue;
3334
+ }
3335
+ this.emitLibraryCollision(
3336
+ `${plainCanonical} is locked from ${lockedUrl ?? "its source"}, which wins; library "${library}" also holds it${entry.version ? ` (${entry.version})` : ""} and is not used. To switch, run \`skaile remove ${plainCanonical}\`, then \`skaile add ${plainCanonical}\`.`,
3337
+ [plainCanonical]
3338
+ );
3339
+ }
3340
+ }
2998
3341
  // ── Store fetch-then-deploy ────────────────────────────────────────────
2999
3342
  /** A candidate's stable identity key (`<publisher>/<kind>:<name>@<version>`). */
3000
3343
  candidateKey(c) {
@@ -3154,10 +3497,19 @@ var AssetManager = class {
3154
3497
  fresh.push(ref);
3155
3498
  }
3156
3499
  if (fresh.length === 0) break;
3500
+ const keepsOrigin = (ref) => {
3501
+ const id = refIdentity(ref);
3502
+ const locked = id !== null ? opts.lockedOrigin?.get(id) : void 0;
3503
+ if (locked === void 0) return false;
3504
+ const pin = ref.includes("#") ? ref.slice(ref.indexOf("#") + 1).trim() : void 0;
3505
+ return !pin || locked === "" || matchPin(pin, locked);
3506
+ };
3507
+ const originKept = fresh.filter(keepsOrigin);
3508
+ if (opts.warnCollisions && originKept.length > 0) await this.noteLosingLibraries(originKept);
3157
3509
  const libraryTried = new Set(
3158
3510
  fresh.filter((ref) => {
3159
3511
  const id = refIdentity(ref);
3160
- return id !== null && (opts.provenanceIndex.get(id)?.length ?? 0) === 0;
3512
+ return id !== null && (opts.provenanceIndex.get(id)?.length ?? 0) === 0 && !keepsOrigin(ref);
3161
3513
  })
3162
3514
  );
3163
3515
  const hit = await this.resolveLibraryEntries([...libraryTried], {
@@ -3185,7 +3537,7 @@ var AssetManager = class {
3185
3537
  }
3186
3538
  presets.push(...r.presets);
3187
3539
  const hit2 = await this.resolveLibraryEntries(
3188
- r.missing.filter((m) => !libraryTried.has(m)),
3540
+ r.missing.filter((m) => !libraryTried.has(m) && !keepsOrigin(m)),
3189
3541
  {
3190
3542
  quiet: !opts.warnCollisions,
3191
3543
  lockedLibraries: opts.lockedLibraries,
@@ -3488,7 +3840,8 @@ var AssetManager = class {
3488
3840
  };
3489
3841
  }
3490
3842
  const orphans = await this.orphanedSourceGaps(
3491
- await this.declaredLockKeys(lockForLibraries, dependencies)
3843
+ await this.declaredLockKeys(lockForLibraries, dependencies),
3844
+ true
3492
3845
  );
3493
3846
  if (orphans.size > 0) {
3494
3847
  return {
@@ -3531,6 +3884,7 @@ var AssetManager = class {
3531
3884
  // library holding the same ref does not move a locked asset. `update` re-resolves.
3532
3885
  ...opts?.moveLibraries ? { preferLocked: await this.lockedPreference() } : { lockedLibraries: await this.lockedLibraryNames() },
3533
3886
  ...keepLocked ? { keepLocked } : {},
3887
+ lockedOrigin: this.lockedOriginVersions(),
3534
3888
  readStoreRequires: true
3535
3889
  });
3536
3890
  this.assertNoFolderCollision([...resolved, ...lib.entries.map((e) => this.entryIdentity(e))]);
@@ -3574,7 +3928,7 @@ var AssetManager = class {
3574
3928
  const missingHints = await this.publisherChangeHints(stillMissing);
3575
3929
  const prevLock = this.tryReadLock();
3576
3930
  const kept = keptLockEntries(prevLock, stillMissing);
3577
- const storeNotChecked = this.storeNotCheckedRefs(
3931
+ const storeNotChecked = await this.storeNotCheckedRefs(
3578
3932
  kept,
3579
3933
  sources.map((s) => s.url)
3580
3934
  );
@@ -3582,7 +3936,7 @@ var AssetManager = class {
3582
3936
  for (const ref of /* @__PURE__ */ new Set([...kept.refs, ...fixes.keys()])) {
3583
3937
  const fix = fixes.get(ref);
3584
3938
  const notes = [
3585
- kept.refs.has(ref) ? this.keptCopyDeployed(kept, ref) ? "the deployed copy and its lock entry are kept" : "its lock entry is kept; no deployed copy exists" : void 0,
3939
+ kept.refs.has(ref) ? await this.keptCopyDeployed(kept, ref) ? "the deployed copy and its lock entry are kept" : "its lock entry is kept; no deployed copy exists" : void 0,
3586
3940
  fix
3587
3941
  ].filter((n) => n !== void 0);
3588
3942
  missingHints[ref] = `${fix ? "" : missingHints[ref] ?? ""} (${notes.join("; ")})`;
@@ -3601,12 +3955,24 @@ var AssetManager = class {
3601
3955
  const entries = [...await this.buildCatalogEntries(resolved, repositories), ...lib.entries];
3602
3956
  assertFlowsLoad(entries, "installed");
3603
3957
  assertNoLibrarySymlinks(entries, this.registry, repositories, opts?.link === true);
3958
+ const forceCommand = opts?.moveLibraries === true ? "skaile update --force" : "skaile install --force";
3604
3959
  if (!opts?.force) {
3605
3960
  await this.assertNoHandEditsPruned(
3606
3961
  resolved,
3607
- /* @__PURE__ */ new Set([...Object.keys(libraryLock), ...Object.keys(kept.assets)])
3962
+ /* @__PURE__ */ new Set([...Object.keys(libraryLock), ...Object.keys(kept.assets)]),
3963
+ forceCommand
3608
3964
  );
3609
3965
  }
3966
+ const relockRemoved = await this.relockDeletions(
3967
+ entries,
3968
+ prevLock,
3969
+ withKeptLockEntries(freshLock, kept),
3970
+ opts?.force === true,
3971
+ forceCommand,
3972
+ lib.libraryOf
3973
+ );
3974
+ if (!opts?.force) this.assertNoUnrecordedAgentOverwrite(entries, prevLock, forceCommand);
3975
+ const inferredHarnesses = this.inferLegacyHarnessSubsets(entries);
3610
3976
  const { removed, replaced } = this.reconcileRemovedAssets(
3611
3977
  resolved,
3612
3978
  /* @__PURE__ */ new Set([...Object.keys(libraryLock), ...Object.keys(kept.assets)])
@@ -3614,6 +3980,7 @@ var AssetManager = class {
3614
3980
  const copyDrift = await this.lockedCopyDrift();
3615
3981
  const missingCopies = await this.incompleteDeploys();
3616
3982
  const unrecordedAgents = this.unrecordedAgentFiles(prevLock);
3983
+ const composedDrift = /* @__PURE__ */ new Set();
3617
3984
  const deployed = [
3618
3985
  ...new Set(
3619
3986
  this.targetHarnesses().flatMap(
@@ -3621,22 +3988,32 @@ var AssetManager = class {
3621
3988
  this.entriesForHarness(entries, t),
3622
3989
  repositories,
3623
3990
  patches,
3624
- this.deployOptsFor(t, opts?.link)
3991
+ this.deployOptsFor(t, opts?.link, void 0, {
3992
+ refresh: opts?.moveLibraries === true,
3993
+ onDrift: (ref, composeRef) => composedDrift.add(this.composedDriftLine(ref, composeRef))
3994
+ })
3625
3995
  )
3626
3996
  )
3627
3997
  )
3628
3998
  ];
3629
3999
  this.sweepLegacyOmpCopies(entries);
3630
- const mcpRestored = await this.renderDriverMcpConfig();
4000
+ const mcpRestored = await this.renderHarnessMcpConfig();
3631
4001
  const agentRender = await this.renderAgentInstances();
3632
- const restored = [...this.restoredCopies(copyDrift, deployed, missingCopies), ...mcpRestored];
4002
+ const restored = [
4003
+ ...this.restoredCopies(copyDrift, deployed, missingCopies),
4004
+ ...relockRemoved,
4005
+ ...mcpRestored
4006
+ ];
3633
4007
  const rewritten = this.rewrittenAgentFiles(unrecordedAgents);
3634
4008
  const lockWanted = resolved.length > 0 || lib.entries.length > 0 || existsSync(this.lockPath);
3635
4009
  let lockWritten = false;
3636
4010
  let relocked = [];
3637
4011
  let moved = [];
3638
4012
  if (lockWanted) {
3639
- const lockData = this.withRenderedAgents(withKeptLockEntries(freshLock, kept));
4013
+ const lockData = this.withRenderedAgents(
4014
+ withKeptLockEntries(freshLock, kept),
4015
+ opts?.moveLibraries ? void 0 : prevLock
4016
+ );
3640
4017
  moved = libraryMoves(prevLock, libraryLock);
3641
4018
  const movedRefs = new Set(moved.map((m) => m.ref));
3642
4019
  relocked = relockedRefs(prevLock, lockData).filter((k) => !movedRefs.has(k.split("#")[0]));
@@ -3652,12 +4029,17 @@ var AssetManager = class {
3652
4029
  return {
3653
4030
  deployed,
3654
4031
  removed,
3655
- missing: [...reportedMissing, ...versionBlocked.filter((b) => !reportedMissing.includes(b))],
4032
+ missing: [
4033
+ ...reportedMissing,
4034
+ ...versionBlocked.filter((b) => !reportedMissing.includes(b)),
4035
+ ...composedDrift
4036
+ ],
3656
4037
  ...placeholderBodies.length > 0 ? { placeholderBodies } : {},
3657
4038
  ...placeholderDescriptions.length > 0 ? { placeholderDescriptions } : {},
3658
4039
  ...storeNotChecked.length > 0 ? { storeNotChecked } : {},
3659
4040
  ...Object.keys(missingHints).length > 0 ? { missingHints } : {},
3660
4041
  ...relocked.length > 0 ? { relocked } : {},
4042
+ ...inferredHarnesses.length > 0 ? { inferredHarnesses } : {},
3661
4043
  ...moved.length > 0 ? { moved } : {},
3662
4044
  ...replaced.length > 0 ? { replaced } : {},
3663
4045
  ...restored.length > 0 ? { restored } : {},
@@ -3678,7 +4060,7 @@ var AssetManager = class {
3678
4060
  * @param declaredSourceUrls - The `sources:` URLs of `skaile.yaml`; a lock entry from one of
3679
4061
  * them is that source's, not the store's.
3680
4062
  */
3681
- storeNotCheckedRefs(kept, declaredSourceUrls) {
4063
+ async storeNotCheckedRefs(kept, declaredSourceUrls) {
3682
4064
  const skipped = this.catalogUrlOverride === "";
3683
4065
  if (!skipped && this.storeFailures.size === 0) return [];
3684
4066
  const declared = new Set(declaredSourceUrls.map(normalizeRepoUrl));
@@ -3689,7 +4071,7 @@ var AssetManager = class {
3689
4071
  const entry = kept.assets[key];
3690
4072
  return entry !== void 0 && !entry.library && entry.source !== void 0 && !declared.has(normalizeRepoUrl(entry.source.url));
3691
4073
  });
3692
- if (!fromStore || !this.keptCopyDeployed(kept, ref)) continue;
4074
+ if (!fromStore || !await this.keptCopyDeployed(kept, ref)) continue;
3693
4075
  if (skipped && this.storeFailures.size === 0) {
3694
4076
  out.push({ ref, reason: "skipped", detail: "--no-catalog: the store was not asked" });
3695
4077
  continue;
@@ -3745,7 +4127,7 @@ var AssetManager = class {
3745
4127
  const locked = this.lockedRequirementsOf(id);
3746
4128
  const withLocked = (scanned) => [.../* @__PURE__ */ new Set([...scanned, ...locked])];
3747
4129
  const keptAgent = kind === "agent" && !this.global ? join(agentSourceCacheDir(this.projectDir), name) : null;
3748
- const dir = keptAgent && existsSync(keptAgent) ? keptAgent : deployedDir(component, name, this.driverTarget, this.global, this.projectDir);
4130
+ const dir = keptAgent && existsSync(keptAgent) ? keptAgent : deployedDir(component, name, this.harness, this.global, this.projectDir);
3749
4131
  if (!existsSync(dir)) return withLocked([]);
3750
4132
  try {
3751
4133
  const scanned = await scanDirectory(dir, publisher ?? "", { knownKinds: this.knownKinds });
@@ -3835,7 +4217,7 @@ var AssetManager = class {
3835
4217
  * other version taking its place) whose deployed folder holds hand edits: the files that differ
3836
4218
  * from the lock are named, nothing is removed, and `--force` prunes anyway (OQ6).
3837
4219
  */
3838
- async assertNoHandEditsPruned(resolved, keep) {
4220
+ async assertNoHandEditsPruned(resolved, keep, forceCommand) {
3839
4221
  const oldLock = this.tryReadLock();
3840
4222
  if (!oldLock) return;
3841
4223
  const resolvedRefs = [
@@ -3867,7 +4249,158 @@ var AssetManager = class {
3867
4249
  throw new Error(
3868
4250
  `Not pruned: skaile.yaml no longer declares ${lines.length === 1 ? "an asset" : "assets"} whose deployed copy holds your edits:
3869
4251
  ${lines.join("\n ")}
3870
- Nothing was changed. Declare it again to keep it, or run \`skaile install --force\` to prune it with its edits.`
4252
+ Nothing was changed. Declare it again to keep it, or run \`${forceCommand}\` to prune it with its edits.`
4253
+ );
4254
+ }
4255
+ /**
4256
+ * Report (and, without `force`, guard) the files a re-lock deletes from a deployed copy
4257
+ * (OQ5, p1441): the asset is locked already and its library or source now holds other content
4258
+ * (`next` re-locks it), and the deployed folder holds files the new content does not ship. The
4259
+ * deploy clears them. Two cases:
4260
+ * - the deployed copy still equals what `prevLock` recorded (per-file sha256 for a source
4261
+ * or store asset, the library hash for a library asset): the new version dropped those
4262
+ * files, nobody edited them, so they are deleted and come back as `removed` rows (an
4263
+ * `install`/`update` prints `Removed <file> (not part of <ref>)`), without a refusal;
4264
+ * - the copy diverged (a file the previous content did not ship, an edited file, or no hash
4265
+ * to compare): without `force` this throws one error naming the files and changes nothing.
4266
+ * A source or store asset names only the files the previous content did not ship (or that
4267
+ * were edited); a library asset records no file list, so it names every file to delete.
4268
+ *
4269
+ * @param entries - The catalog entries about to be deployed.
4270
+ * @param next - The lock the run is about to write (or merge).
4271
+ * @param libraryOf - The library each library-origin entry came from.
4272
+ */
4273
+ async relockDeletions(entries, prevLock, next, force, forceCommand, libraryOf) {
4274
+ if (!prevLock) return [];
4275
+ const relocked = relockedRefs(prevLock, next).map((key) => ({
4276
+ key,
4277
+ id: parseCanonicalLockKey(key)
4278
+ }));
4279
+ if (relocked.length === 0) return [];
4280
+ const shown = (p) => (this.global ? p : relative(this.projectDir, p)).split(sep).join("/");
4281
+ let snap;
4282
+ const rows = [];
4283
+ const refused = [];
4284
+ for (const e of entries) {
4285
+ const hit = relocked.find(({ id }) => id.kind === e.kind && id.name === e.name);
4286
+ const component = hit ? this.installTarget(e.kind) : void 0;
4287
+ if (!hit || !component) continue;
4288
+ const prevEntry = Object.entries(prevLock.assets).find(([k]) => {
4289
+ const o = parseCanonicalLockKey(k);
4290
+ return o.kind === hit.id.kind && o.name === hit.id.name && o.publisher === hit.id.publisher;
4291
+ })?.[1];
4292
+ const removed = [];
4293
+ const blocked = [];
4294
+ for (const t of this.targetHarnesses()) {
4295
+ const drift = deployedAssetDrift(e, this.deployOptsFor(t));
4296
+ if (!drift || drift.extra.length === 0) continue;
4297
+ const dir = deployedDir(component, e.name, t, this.global, this.projectDir);
4298
+ const files = drift.extra;
4299
+ let untouched;
4300
+ if (prevEntry && prevEntry.files.length > 0) {
4301
+ const locked = new Map(
4302
+ lockedAssetFiles(e.kind, prevEntry.files).map((f) => [f.rel, f.sha256])
4303
+ );
4304
+ untouched = files.filter((rel) => {
4305
+ const want = locked.get(rel);
4306
+ if (want === void 0) return false;
4307
+ try {
4308
+ return computeHash(join(dir, rel)) === want;
4309
+ } catch {
4310
+ return false;
4311
+ }
4312
+ });
4313
+ } else if (prevEntry?.library?.sha256 && !prevEntry.library.installed) {
4314
+ const libName = libraryOf.get(e);
4315
+ snap ??= await this.loadLibraryIndex();
4316
+ const libPath = libName ? this.libraryPath({ name: libName }, snap) : null;
4317
+ if (libPath) {
4318
+ const assetRoot = statSync(e.source).isDirectory() ? e.source : dirname(e.source);
4319
+ const hash = computeDeterministicHash(
4320
+ dir,
4321
+ listAssetFiles(dir),
4322
+ posix.normalize(relative(libPath, assetRoot).split(sep).join("/"))
4323
+ );
4324
+ if (hash === prevEntry.library.sha256) untouched = [...files];
4325
+ }
4326
+ }
4327
+ const own = new Set(untouched ?? []);
4328
+ for (const f of files) (own.has(f) ? removed : blocked).push(shown(join(dir, f)));
4329
+ }
4330
+ if (removed.length > 0) rows.push({ ref: hit.key, restored: [], removed });
4331
+ if (blocked.length > 0) refused.push({ ref: hit.key, restored: [], removed: blocked });
4332
+ }
4333
+ if (refused.length === 0 || force) return [...rows, ...refused];
4334
+ const lines = refused.map((r) => `${r.ref} (${r.removed.join(", ")})`);
4335
+ throw new Error(
4336
+ `Not re-locked: the deployed copy of ${refused.length === 1 ? "an asset" : "assets"} holds files its locked content did not ship or that were edited, and the deploy would delete them:
4337
+ ${lines.join("\n ")}
4338
+ Nothing was changed. Copy what you need, or run \`${forceCommand}\` to delete them.`
4339
+ );
4340
+ }
4341
+ /**
4342
+ * Stop `install` from overwriting a hand-edited rendered agent file that no lock entry
4343
+ * records (OQ5, p1440): the lock is gone (or never held the agent), so nothing tells an edit
4344
+ * from a stale render, and the deploy would replace the file without a word. Checks the file
4345
+ * named after each agent about to be deployed and the file of each agent instance whose bound
4346
+ * agent has no lock entry. Throws one error naming each file that exists and differs from its
4347
+ * render and changes nothing; `--force` (the caller skips this check) overwrites. A file that
4348
+ * equals its render is not an edit. Project mode only.
4349
+ */
4350
+ assertNoUnrecordedAgentOverwrite(entries, prevLock, forceCommand) {
4351
+ if (this.global) return;
4352
+ const lockedAgents = new Set(
4353
+ Object.keys(prevLock?.assets ?? {}).map(parseCanonicalLockKey).filter((k) => k.kind && this.installTarget(k.kind) === "agent").map((k) => k.name)
4354
+ );
4355
+ const opts = this.deployOptsFor(this.harness);
4356
+ const lines = /* @__PURE__ */ new Set();
4357
+ const collect = (diff, what) => {
4358
+ if (!diff) return;
4359
+ for (const m of diff.matchAll(/^--- (.+?)\t/gm)) {
4360
+ const abs = m[1];
4361
+ if (!existsSync(abs)) continue;
4362
+ lines.add(
4363
+ `${relative(this.projectDir, abs).split(sep).join("/")} (${what} differs from its render)`
4364
+ );
4365
+ }
4366
+ };
4367
+ for (const e of entries) {
4368
+ if (this.installTarget(e.kind) !== "agent" || lockedAgents.has(e.name)) continue;
4369
+ try {
4370
+ collect(diffDeployedAgent(e, opts), `agent ${e.name}`);
4371
+ } catch {
4372
+ }
4373
+ }
4374
+ let instances = {};
4375
+ try {
4376
+ instances = effectiveAgentInstances(resolveSkWorkspaceConfig(this.projectDir));
4377
+ } catch {
4378
+ }
4379
+ for (const [id, config] of Object.entries(instances)) {
4380
+ if (!config.ref.startsWith("agent:")) continue;
4381
+ const bound = parseRefTolerant(config.ref);
4382
+ if (bound?.kind === "agent" && lockedAgents.has(bound.name)) continue;
4383
+ try {
4384
+ const srcDir = resolveAgentDefinitionDir(this.projectDir, config.ref);
4385
+ if (srcDir === void 0) continue;
4386
+ const entry = {
4387
+ kind: "agent",
4388
+ name: id,
4389
+ description: "",
4390
+ source: srcDir,
4391
+ version: "",
4392
+ requires: [],
4393
+ dependencies: []
4394
+ };
4395
+ collect(diffDeployedAgent(entry, opts, { id, srcDir, config }), `agent instance ${id}`);
4396
+ } catch {
4397
+ }
4398
+ }
4399
+ if (lines.size === 0) return;
4400
+ throw new Error(
4401
+ `Not deployed: the deploy would overwrite ${lines.size === 1 ? "a rendered agent file" : "rendered agent files"} that no lock entry records:
4402
+ ${[...lines].join("\n ")}
4403
+ Nothing was changed. Move your edits away, or run \`${forceCommand}\` to overwrite the file.`
3871
4404
  );
3872
4405
  }
3873
4406
  /**
@@ -4095,7 +4628,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4095
4628
  }
4096
4629
  assertLockHashes(lock);
4097
4630
  this.assertNoFolderCollision(Object.keys(lock.assets).map(parseCanonicalLockKey));
4098
- const orphaned = [...(await this.orphanedSourceGaps()).values()];
4631
+ const orphaned = [...(await this.orphanedSourceGaps(void 0, true)).values()];
4099
4632
  if (orphaned.length > 0) {
4100
4633
  throw new Error(
4101
4634
  `Lock file verification failed:
@@ -4170,12 +4703,14 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4170
4703
  throw new Error(`Lock file verification failed:
4171
4704
  ${reason}`);
4172
4705
  }
4173
- const library = await this.restoreLibraryLockEntries(lock);
4706
+ const library = await this.restoreLibraryLockEntries(lock, { storeFallback: true });
4174
4707
  assertFlowsLoad([...resolved, ...library.entries], "installed");
4175
4708
  assertNoLibrarySymlinks([...resolved, ...library.entries], this.registry, repositories);
4709
+ const inferredHarnesses = this.inferLegacyHarnessSubsets([...resolved, ...library.entries]);
4176
4710
  const copyDrift = await this.lockedCopyDrift();
4177
4711
  const missingCopies = await this.incompleteDeploys();
4178
4712
  const unrecordedAgents = this.unrecordedAgentFiles(lock);
4713
+ const composedDrift = /* @__PURE__ */ new Set();
4179
4714
  const deployed = [
4180
4715
  ...new Set(
4181
4716
  this.targetHarnesses().flatMap(
@@ -4183,13 +4718,16 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4183
4718
  this.entriesForHarness([...resolved, ...library.entries], t),
4184
4719
  repositories,
4185
4720
  patches,
4186
- this.deployOptsFor(t)
4721
+ this.deployOptsFor(t, void 0, void 0, {
4722
+ refresh: false,
4723
+ onDrift: (ref, composeRef) => composedDrift.add(this.composedDriftLine(ref, composeRef))
4724
+ })
4187
4725
  )
4188
4726
  )
4189
4727
  )
4190
4728
  ];
4191
4729
  this.sweepLegacyOmpCopies([...resolved, ...library.entries]);
4192
- const mcpRestored = await this.renderDriverMcpConfig();
4730
+ const mcpRestored = await this.renderHarnessMcpConfig();
4193
4731
  const agentRender = await this.renderAgentInstances();
4194
4732
  const restored = [...this.restoredCopies(copyDrift, deployed, missingCopies), ...mcpRestored];
4195
4733
  const rewritten = this.rewrittenAgentFiles(unrecordedAgents);
@@ -4201,6 +4739,8 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4201
4739
  );
4202
4740
  const gaps = (await this.projectState()).gaps.filter((g) => {
4203
4741
  if (g.type === "agent") return false;
4742
+ if (g.unreadableSource) return false;
4743
+ if (g.type === "library" && library.viaStore.includes(g.ref)) return false;
4204
4744
  const p = parseRefTolerant(g.ref);
4205
4745
  return !(p && alreadyMissing.has(`${p.kind}:${p.name}`));
4206
4746
  }).map((g) => g.message);
@@ -4209,10 +4749,11 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4209
4749
  return {
4210
4750
  deployed,
4211
4751
  removed: [],
4212
- missing: [...library.missing, ...gaps],
4752
+ missing: [...library.missing, ...gaps, ...composedDrift],
4213
4753
  ...placeholderBodies.length > 0 ? { placeholderBodies } : {},
4214
4754
  ...placeholderDescriptions.length > 0 ? { placeholderDescriptions } : {},
4215
4755
  lockWritten: false,
4756
+ ...inferredHarnesses.length > 0 ? { inferredHarnesses } : {},
4216
4757
  ...restored.length > 0 ? { restored } : {},
4217
4758
  ...rewritten.length > 0 ? { rewritten } : {},
4218
4759
  ...agentRender
@@ -4240,6 +4781,72 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4240
4781
  }
4241
4782
  return [...found].sort((a, b) => gt(coerceVersion(a), coerceVersion(b)) ? -1 : 1);
4242
4783
  }
4784
+ /**
4785
+ * The refs of the other kinds that a source or a library holds under the same publisher and
4786
+ * name as `parsed` (`agent:@pub/captain` for a `@pub/captain` that is no skill), for the
4787
+ * `Did you mean` of an `add` that missed.
4788
+ */
4789
+ async otherKindRefs(parsed) {
4790
+ if (!parsed.publisher) return [];
4791
+ const publisher = parsed.publisher.replace(/^@/, "");
4792
+ const found = [];
4793
+ for (const kind of [...this.knownKinds].sort()) {
4794
+ if (kind === parsed.kind) continue;
4795
+ const candidate = `${kind}:@${publisher}/${parsed.name}`;
4796
+ try {
4797
+ if (await this.info(candidate) !== null) found.push(candidate);
4798
+ } catch {
4799
+ }
4800
+ }
4801
+ return found;
4802
+ }
4803
+ /**
4804
+ * What `add` would deploy for the resolved candidates and library entries, without touching
4805
+ * the project: one item per asset with its origin, version, deploy folders and files.
4806
+ */
4807
+ planAddItems(resolved, lib, stores, parsed) {
4808
+ const storeUrls = new Set(stores.map((s) => normalizeRepoUrl(s.url)));
4809
+ const factoryUrl = normalizeRepoUrl(FACTORY_SOURCE_URL);
4810
+ const folders = (kind, name) => {
4811
+ const component = this.installTarget(kind);
4812
+ if (!component) return [];
4813
+ return this.targetHarnesses().map((t) => {
4814
+ const dir = deployedDir(component, name, t, this.global, this.projectDir);
4815
+ const rel = relative(this.projectDir, dir);
4816
+ const shown = this.global || rel.startsWith("..") ? dir.replace(homedir(), "~") : `${rel}${dir.endsWith(sep) ? sep : ""}`;
4817
+ return shown;
4818
+ });
4819
+ };
4820
+ const asked = (kind, name, publisher) => kind === parsed.kind && name === parsed.name && (!parsed.publisher || (publisher ?? "").replace(/^@/, "") === parsed.publisher.replace(/^@/, ""));
4821
+ const items = [];
4822
+ for (const c of resolved) {
4823
+ const url = normalizeRepoUrl(c.sourceUrl);
4824
+ items.push({
4825
+ ref: assetRefToStr({
4826
+ kind: c.kind,
4827
+ name: c.name,
4828
+ publisher: c.publisher.replace(/^@/, "")
4829
+ }),
4830
+ version: c.version,
4831
+ origin: storeUrls.has(url) ? `store ${c.sourceUrl}` : url === factoryUrl ? "factory" : `source ${sourceShortName(c.sourceUrl)}`,
4832
+ requested: asked(c.kind, c.name, c.publisher),
4833
+ folders: folders(c.kind, c.name),
4834
+ files: c.files.map((f) => f.path)
4835
+ });
4836
+ }
4837
+ for (const e of lib.entries) {
4838
+ const id = this.entryIdentity(e);
4839
+ items.push({
4840
+ ref: canonicalEntryRef(e),
4841
+ version: e.version ?? "",
4842
+ origin: `library ${lib.libraryOf.get(e) ?? ""}`.trim(),
4843
+ requested: asked(e.kind, e.name, id.publisher),
4844
+ folders: folders(e.kind, e.name),
4845
+ files: [...e.files ?? []]
4846
+ });
4847
+ }
4848
+ return items.sort((a, b) => Number(b.requested) - Number(a.requested));
4849
+ }
4243
4850
  /**
4244
4851
  * Parse the ref `add` was given. A ref the grammar rejects fails with the parser's message
4245
4852
  * minus its manifest-migration advice (it points at a skill that is not for `add`), and:
@@ -4257,7 +4864,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4257
4864
  const plain = err.message.endsWith(advice) ? err.message.slice(0, -advice.length) : err.message;
4258
4865
  if (plain.startsWith("publisher required")) {
4259
4866
  const matches = await this.resolvableMatches(ref, repositories, sources);
4260
- const hint = matches.length === 0 ? "" : matches.length === 1 ? ` Did you mean ${matches[0]}?` : ` Did you mean one of: ${matches.join(", ")}?`;
4867
+ const hint = matches.length === 0 ? ` Find the publisher with \`skaile store search ${ref.trim().replace(/^[^:@/#\s]+:/, "").replace(/#.*$/, "")}\`.` : matches.length === 1 ? ` Did you mean ${matches[0]}?` : ` Did you mean one of: ${matches.join(", ")}?`;
4261
4868
  throw new Error(`${plain}${hint}`);
4262
4869
  }
4263
4870
  const pinned = /^(.*\/[^@#/]+)@([^@#/]+)$/.exec(ref.trim());
@@ -4338,6 +4945,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4338
4945
  stores,
4339
4946
  declaredRefs: dependencies,
4340
4947
  warnCollisions: true,
4948
+ lockedOrigin: this.lockedOriginVersions(),
4341
4949
  readStoreRequires: true,
4342
4950
  ...opts?.preferLockedLibrary ? { preferLocked: await this.lockedPreference() } : {}
4343
4951
  });
@@ -4381,8 +4989,9 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4381
4989
  );
4382
4990
  }
4383
4991
  const available = await this.availableVersions(parsed, stores);
4992
+ const otherKinds = /^[^@/#\s]+:/.test(ref.trim()) ? [] : await this.otherKindRefs(parsed);
4384
4993
  throw new Error(
4385
- `Asset not found: ${ref}${(await this.publisherChangeHints([ref]))[ref] ?? ""}${missing.length ? ` (missing: ${missing.join(", ")})` : ""}${available.length ? `; ${parsed.name} has version(s): ${available.join(", ")}` : ""}`
4994
+ `Asset not found: ${ref}${(await this.publisherChangeHints([ref]))[ref] ?? ""}${missing.length ? ` (missing: ${missing.join(", ")})` : ""}${available.length ? `; ${parsed.name} has version(s): ${available.join(", ")}` : ""}` + (otherKinds.length === 0 ? "" : otherKinds.length === 1 ? `. Did you mean ${otherKinds[0]}?` : `. Did you mean one of: ${otherKinds.join(", ")}?`)
4386
4995
  );
4387
4996
  }
4388
4997
  if (parsed.kind === "preset" && missing.length > 0) {
@@ -4405,6 +5014,62 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4405
5014
  )
4406
5015
  );
4407
5016
  }
5017
+ const problems = origin && libPath && !(e.kind === "flow" && flowLoadError(e) !== void 0) ? libraryAssetCheck?.({ kind: e.kind, name: e.name, source: e.source }, libPath) ?? [] : [];
5018
+ if (problems.length > 0) {
5019
+ throw new Error(
5020
+ `${canonicalEntryRef(e)} in library "${origin}" fails the checks of \`skaile validate\` - nothing was added:
5021
+ ${problems.map((l) => ` ${l}`).join("\n")}
5022
+ Fix the asset, then run \`skaile library index ${origin}\` and add it again.`
5023
+ );
5024
+ }
5025
+ }
5026
+ }
5027
+ if (libraryAssetCheck) {
5028
+ for (const c of resolved) {
5029
+ const decl = Object.entries(repositories).find(([, d]) => d.url === c.sourceUrl);
5030
+ const cloneDir = decl ? this.resolveRepoDir(decl[1], decl[0]) : null;
5031
+ const entry = cloneDir ? this.candidateToCatalogEntry(c, repositories) : null;
5032
+ if (!cloneDir || !entry) continue;
5033
+ if (entry.kind === "flow" && flowLoadError(entry) !== void 0) continue;
5034
+ const problems = libraryAssetCheck(
5035
+ { kind: entry.kind, name: entry.name, source: entry.source },
5036
+ cloneDir
5037
+ );
5038
+ if (problems.length > 0) {
5039
+ throw new Error(
5040
+ `${canonicalEntryRef(entry)} from source ${c.sourceUrl} fails the checks of \`skaile validate\` - nothing was added:
5041
+ ${problems.map((l) => ` ${l}`).join("\n")}
5042
+ Fix the asset in the source repo, then run \`skaile source sync\` and add it again.`
5043
+ );
5044
+ }
5045
+ }
5046
+ }
5047
+ const staleSiblings = this.staleSourceSiblingRefs(resolved, dependencies);
5048
+ if (staleSiblings.length > 0) {
5049
+ const siblings = await this.resolveLibraryFirst(staleSiblings, {
5050
+ provenanceIndex,
5051
+ overrides,
5052
+ stores,
5053
+ declaredRefs: dependencies,
5054
+ lockedOrigin: this.lockedOriginVersions(),
5055
+ readStoreRequires: true
5056
+ });
5057
+ for (const sib of staleSiblings) {
5058
+ const pin = parseAssetRefLoose(sib)?.pin;
5059
+ if (!pin) continue;
5060
+ const id = refIdentity(sib.replace(/#.*$/, ""));
5061
+ const kept = siblings.resolved.some(
5062
+ (c) => `${c.publisher.replace(/^@/, "")}/${c.kind}:${c.name}` === id?.replace(/^@/, "") && matchPin(pin, c.version ?? "")
5063
+ );
5064
+ if (!kept) {
5065
+ throw new Error(
5066
+ `${sib.replace(/#.*$/, "")} is pinned to ${pin} in skaile.yaml, but its source moved on and no longer holds ${pin}, so adding ${ref} would break the lock - nothing was added. Change the pin in skaile.yaml, or drop the pinned asset, then add again.`
5067
+ );
5068
+ }
5069
+ }
5070
+ const held = new Set(resolved.map((c) => this.candidateKey(c)));
5071
+ for (const c of siblings.resolved) {
5072
+ if (!held.has(this.candidateKey(c))) resolved.push(c);
4408
5073
  }
4409
5074
  }
4410
5075
  this.assertSourceCommitsPublished(resolved, repositories);
@@ -4441,6 +5106,11 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4441
5106
  `${ref.split("#")[0]} requires ${missing.join(", ")} (not found \u2014 ${REGISTER_HOLDER}, or remove the requirement from the asset's manifest) \u2014 nothing was added`
4442
5107
  );
4443
5108
  }
5109
+ if (opts?.dryRun) {
5110
+ const plan = this.planAddItems(resolved, lib, stores, parsed);
5111
+ opts.onPlan?.(plan);
5112
+ return [];
5113
+ }
4444
5114
  const entries = [...await this.buildCatalogEntries(resolved, repositories), ...lib.entries];
4445
5115
  assertFlowsLoad(entries, "added");
4446
5116
  assertNoLibrarySymlinks(entries, this.registry, repositories, opts?.link === true);
@@ -4463,7 +5133,11 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4463
5133
  this.entriesForHarness(entries, t),
4464
5134
  repositories,
4465
5135
  patches,
4466
- this.deployOptsFor(t, opts?.link, opts?.onSecretFile)
5136
+ this.deployOptsFor(t, opts?.link, opts?.onSecretFile, {
5137
+ refresh: true,
5138
+ onDrift: () => {
5139
+ }
5140
+ })
4467
5141
  )
4468
5142
  )
4469
5143
  )
@@ -4484,7 +5158,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4484
5158
  opts?.onPlaceholderDescription?.(placeholder);
4485
5159
  }
4486
5160
  this.addDependencyToConfig(ref);
4487
- await this.renderDriverMcpConfig();
5161
+ await this.renderHarnessMcpConfig();
4488
5162
  await this.renderAgentInstances();
4489
5163
  if (resolved.length > 0 || lib.entries.length > 0) {
4490
5164
  const libraryLock = await this.libraryLockEntries(lib);
@@ -4751,7 +5425,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4751
5425
  * Removes only `ref` itself; use {@link removeWithDependencies} to also drop the
4752
5426
  * dependencies it leaves orphaned.
4753
5427
  *
4754
- * Deliberately does NOT re-render the driver target's MCP config: the render
5428
+ * Deliberately does NOT re-render the harness target's MCP config: the render
4755
5429
  * step is async (the declaration resolver is), and making this synchronous
4756
5430
  * method async would break every external caller. {@link removeWithDependencies}
4757
5431
  * (what `skaile remove` runs) does re-render it; a caller of this method gets the
@@ -4820,14 +5494,22 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4820
5494
  }
4821
5495
  const kept = [];
4822
5496
  const ownedBy = [];
5497
+ const mcpPublishers = target.kind === "mcp-server" && !this.global ? [
5498
+ .../* @__PURE__ */ new Set([
5499
+ ...this.lockHolders("mcp-server", target.name).map((h) => h.publisher),
5500
+ target.publisher?.replace(/^@/, "")
5501
+ ])
5502
+ ].filter((p) => !!p) : [];
4823
5503
  const changed = this.removeResolved(target, { force: opts?.force, kept, ownedBy });
5504
+ const droppedSettings = changed && mcpPublishers.length > 0 ? this.dropRemovedMcpServerSettings(target.name, mcpPublishers) : [];
4824
5505
  const keptNote = {
4825
5506
  ...kept.length > 0 ? { kept } : {},
4826
- ...ownedBy.length > 0 ? { ownedBy } : {}
5507
+ ...ownedBy.length > 0 ? { ownedBy } : {},
5508
+ ...droppedSettings.length > 0 ? { droppedSettings } : {}
4827
5509
  };
4828
5510
  const pruned = changed && requiredRefs.length > 0 ? await this.pruneOrphans(requiredRefs) : [];
4829
5511
  if (changed && (target.kind === "mcp-server" || pruned.some((r) => r.startsWith("mcp-server:")))) {
4830
- await this.renderDriverMcpConfig();
5512
+ await this.renderHarnessMcpConfig();
4831
5513
  }
4832
5514
  return { changed, pruned, ...keptNote };
4833
5515
  }
@@ -4991,6 +5673,40 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
4991
5673
  }
4992
5674
  return changed;
4993
5675
  }
5676
+ /**
5677
+ * After an `mcp-server` asset left the project: drop what would keep it rendered. Its staged
5678
+ * store bytes under `.skaile/cache/store/<publisher>/mcp-server/<name>/` go (an `mcp_servers:`
5679
+ * entry of the same id would otherwise keep loading them), and so does an `mcp_servers:` entry
5680
+ * that only sets values for it: `env` and the like, with no `command`, `url` or recipe of its
5681
+ * own. An entry that can run alone is the user's own server and stays.
5682
+ *
5683
+ * @returns The dropped `mcp_servers` entries, as `mcp_servers entry "<id>"`.
5684
+ */
5685
+ dropRemovedMcpServerSettings(name, publishers) {
5686
+ for (const publisher of publishers) {
5687
+ rmSync(join(this.storeCacheDir, publisher, "mcp-server", name), {
5688
+ recursive: true,
5689
+ force: true
5690
+ });
5691
+ }
5692
+ const configPath = join(this.stateRoot, "skaile.yaml");
5693
+ if (!existsSync(configPath)) return [];
5694
+ const raw = parse(readFileSync(configPath, "utf8")) ?? {};
5695
+ if (!Array.isArray(raw.mcp_servers)) return [];
5696
+ const dropped = [];
5697
+ const standalone = ["command", "url", "recipe", "launcher"];
5698
+ raw.mcp_servers = raw.mcp_servers.filter((entry) => {
5699
+ const e = entry;
5700
+ if (!e || typeof e.id !== "string" || unscopedName(e.id) !== name) return true;
5701
+ if (standalone.some((k) => e[k] !== void 0 && e[k] !== null)) return true;
5702
+ dropped.push(`mcp_servers entry "${e.id}"`);
5703
+ return false;
5704
+ });
5705
+ if (dropped.length === 0) return [];
5706
+ if (raw.mcp_servers.length === 0) delete raw.mcp_servers;
5707
+ writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
5708
+ return dropped;
5709
+ }
4994
5710
  /**
4995
5711
  * After `remove --global --harness X`: the harnesses outside `X` that still hold a copy of the
4996
5712
  * asset, or `undefined` when none does (or this is not a harness-limited global remove).
@@ -5162,7 +5878,11 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5162
5878
  }
5163
5879
  }
5164
5880
  if (best) return best;
5165
- const lib = await this.resolveLibraryEntries([ref], { quiet: true });
5881
+ const lockedLibraries = await this.lockedLibraryNames();
5882
+ const lib = await this.resolveLibraryEntries([ref], {
5883
+ quiet: true,
5884
+ ...lockedLibraries.size > 0 ? { lockedLibraries } : {}
5885
+ });
5166
5886
  return lib.entries[0] ?? null;
5167
5887
  }
5168
5888
  /**
@@ -5184,7 +5904,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5184
5904
  const seen = /* @__PURE__ */ new Set();
5185
5905
  for (const k of kinds) {
5186
5906
  try {
5187
- const base = deployedBase(k, this.driverTarget, this.global, this.projectDir);
5907
+ const base = deployedBase(k, this.harness, this.global, this.projectDir);
5188
5908
  if (!existsSync(base)) continue;
5189
5909
  for (const item of readdirSync(base, { withFileTypes: true })) {
5190
5910
  let name;
@@ -5226,7 +5946,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5226
5946
  * @returns One {@link LegacyDeployedAsset} per stale copy, sorted by kind then name.
5227
5947
  */
5228
5948
  listLegacyClaudeDeployed() {
5229
- if (this.global || this.driverTarget === "claude-code") return [];
5949
+ if (this.global || this.harness === "claude-code") return [];
5230
5950
  const tracked = /* @__PURE__ */ new Map();
5231
5951
  const track = (kind, name) => {
5232
5952
  const component = kind ? this.installTarget(kind) : void 0;
@@ -5254,7 +5974,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5254
5974
  const out = [];
5255
5975
  for (const { kind, name, component: k } of tracked.values()) {
5256
5976
  const legacy = deployedDir(k, name, "claude-code", false, this.projectDir);
5257
- if (legacy === deployedDir(k, name, this.driverTarget, false, this.projectDir)) continue;
5977
+ if (legacy === deployedDir(k, name, this.harness, false, this.projectDir)) continue;
5258
5978
  const found = deployedPaths(k, name, "claude-code", false, this.projectDir).find((p) => {
5259
5979
  try {
5260
5980
  lstatSync(p);
@@ -5329,9 +6049,13 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5329
6049
  state = "declared";
5330
6050
  } else if (parsed.kind === "mcp-server") {
5331
6051
  const wired = await wiredMcpNames();
5332
- const isWired = wired.has(parsed.name) || wired.has(unscopedName(parsed.name));
6052
+ const isWired = wired.has(parsed.name) || wired.has(unscopedName(parsed.name)) || !this.global && await mcpCommittedRenderIntact(
6053
+ this.projectDir,
6054
+ this.harness,
6055
+ unscopedName(parsed.name)
6056
+ );
5333
6057
  const skippedReason = Object.entries(
5334
- await readSkippedMcpServers(this.projectDir, this.driverTarget)
6058
+ await readSkippedMcpServers(this.projectDir, this.harness)
5335
6059
  ).find(([id]) => id === parsed.name || unscopedName(id) === parsed.name)?.[1];
5336
6060
  const drifted = (await this.mcpDriftRows()).some(
5337
6061
  (r) => unscopedName(r.drift.id) === unscopedName(parsed.name) && r.drift.missing.length + r.drift.modified.length + r.drift.extra.length > 0
@@ -5350,7 +6074,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5350
6074
  const onDisk = isDeployed(
5351
6075
  component,
5352
6076
  parsed.name,
5353
- this.driverTarget,
6077
+ this.harness,
5354
6078
  this.global,
5355
6079
  this.projectDir
5356
6080
  );
@@ -5388,7 +6112,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5388
6112
  async mcpNotices() {
5389
6113
  if (this.global) return [];
5390
6114
  const out = [];
5391
- const skipped = await readSkippedMcpServers(this.projectDir, this.driverTarget);
6115
+ const skipped = await readSkippedMcpServers(this.projectDir, this.harness);
5392
6116
  for (const [id, reason] of Object.entries(skipped)) {
5393
6117
  out.push({ id, kind: "skipped", reason, text: `MCP server "${id}" is skipped: ${reason}` });
5394
6118
  }
@@ -5433,10 +6157,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5433
6157
  const component = kind ? this.installTarget(kind) : void 0;
5434
6158
  if (!publisher || !kind || !name || !component || component === "agent") continue;
5435
6159
  if (patches[`${kind}:${name}`]) continue;
5436
- const dest = join(
5437
- deployedBase(component, this.driverTarget, this.global, this.projectDir),
5438
- name
5439
- );
6160
+ const dest = join(deployedBase(component, this.harness, this.global, this.projectDir), name);
5440
6161
  if (!existsSync(dest) || lstatSync(dest).isSymbolicLink()) continue;
5441
6162
  const missing = lockedAssetFiles(kind, entry.files).map((f) => f.rel).filter((rel) => !existsSync(join(dest, rel)));
5442
6163
  if (missing.length > 0) out.push({ ref: `${kind}:@${publisher}/${name}`, missing });
@@ -5453,7 +6174,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5453
6174
  const component = this.installTarget(entry.kind);
5454
6175
  if (!entry.files || !component || component === "agent") continue;
5455
6176
  const dest = join(
5456
- deployedBase(component, this.driverTarget, this.global, this.projectDir),
6177
+ deployedBase(component, this.harness, this.global, this.projectDir),
5457
6178
  entry.name
5458
6179
  );
5459
6180
  if (!existsSync(dest)) continue;
@@ -5531,7 +6252,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5531
6252
  const repoStatuses = this.buildRepoStatuses(repositories);
5532
6253
  const lockByKindName = indexLockByKindName(lock);
5533
6254
  const entries = [];
5534
- const instanceFiles = this.global ? /* @__PURE__ */ new Set() : instanceRenderedAgentNames(this.projectDir, this.driverTarget);
6255
+ const instanceFiles = this.global ? /* @__PURE__ */ new Set() : instanceRenderedAgentNames(this.projectDir, this.harness);
5535
6256
  for (const d of deployed) {
5536
6257
  const lockEntry = lockByKindName.get(`${d.kind}:${d.name}`);
5537
6258
  if (!lockEntry && d.kind === "agent" && instanceFiles.has(d.name)) continue;
@@ -5677,11 +6398,12 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5677
6398
  if (!lock) return [];
5678
6399
  const bare = (s) => s.includes("#") ? s.slice(0, s.indexOf("#")) : s;
5679
6400
  const asked = parseRefTolerant(ref);
6401
+ const askedPublisher = asked?.publisher?.replace(/^@/, "");
5680
6402
  const matchesIdentity = (k) => {
5681
6403
  if (bare(k) === bare(ref)) return true;
5682
- if (!asked || asked.publisher) return false;
6404
+ if (!asked) return false;
5683
6405
  const locked = parseCanonicalLockKey(k);
5684
- return locked.kind === asked.kind && locked.name === asked.name;
6406
+ return locked.kind === asked.kind && locked.name === asked.name && (!askedPublisher || locked.publisher === askedPublisher);
5685
6407
  };
5686
6408
  const key = lock.assets[ref] ? ref : Object.keys(lock.assets).find(matchesIdentity);
5687
6409
  if (!key) return asked?.kind === "preset" ? this.whyPreset(lock, asked) : [];
@@ -5817,6 +6539,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5817
6539
  const libraryAssets = Object.entries(lock.assets).filter(
5818
6540
  ([, e]) => e.library && !e.library.installed
5819
6541
  );
6542
+ const declaredPins = this.declaredPinsByIdentity();
5820
6543
  if (libraryAssets.length > 0) {
5821
6544
  const snap = await this.loadLibraryIndex();
5822
6545
  const diskHashes = /* @__PURE__ */ new Map();
@@ -5842,6 +6565,8 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5842
6565
  { kind, publisher, name },
5843
6566
  found.version
5844
6567
  );
6568
+ const declaredPin = declaredPins.get(`${kind}:${publisher}/${name}`);
6569
+ if (declaredPin && diskVersion && !matchPin(declaredPin, diskVersion)) continue;
5845
6570
  if (diskVersion && !isPseudoVersion(diskVersion) && gt(coerceVersion(diskVersion), coerceVersion(origin.version))) {
5846
6571
  result.push({
5847
6572
  kind,
@@ -5880,6 +6605,26 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5880
6605
  library: lookup.name,
5881
6606
  contentChanged: true
5882
6607
  });
6608
+ continue;
6609
+ }
6610
+ }
6611
+ if (entry.composed && kind === "agent") {
6612
+ const srcDir = statSync(found.source).isDirectory() ? found.source : dirname(found.source);
6613
+ const now = new Map(
6614
+ sourceComposedFiles(srcDir, name, this.projectDir).map((f) => [f.path, f.sha256])
6615
+ );
6616
+ const locked = new Map(entry.composed.map((f) => [f.path, f.sha256]));
6617
+ const same = now.size === locked.size && [...now].every(([f, h]) => locked.get(f) === h);
6618
+ if (!same) {
6619
+ result.push({
6620
+ kind,
6621
+ name,
6622
+ publisher,
6623
+ currentVersion: origin.version,
6624
+ behind: 0,
6625
+ library: lookup.name,
6626
+ contentChanged: true
6627
+ });
5883
6628
  }
5884
6629
  }
5885
6630
  }
@@ -5889,6 +6634,23 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5889
6634
  await this.addPinnedRows(lock, result);
5890
6635
  return this.addLockGapRows(result);
5891
6636
  }
6637
+ /**
6638
+ * The `#pin` of every publisher-qualified `skaile.yaml` dependency, keyed `kind:publisher/name`
6639
+ * (no scope sigil). `update` honours it, so `outdated` must not list a move it keeps.
6640
+ */
6641
+ declaredPinsByIdentity() {
6642
+ const pins = /* @__PURE__ */ new Map();
6643
+ for (const dep of this.loadConfig().dependencies) {
6644
+ try {
6645
+ const p = parseAssetRef(dep);
6646
+ if (p.pin && p.publisher) {
6647
+ pins.set(`${p.kind}:${p.publisher.replace(/^@/, "")}/${p.name}`, p.pin);
6648
+ }
6649
+ } catch {
6650
+ }
6651
+ }
6652
+ return pins;
6653
+ }
5892
6654
  /**
5893
6655
  * List a locked asset whose `skaile.yaml` ref carries a `#version` pin while a source, a
5894
6656
  * library or a store holds a newer one: `locked 0.7.0 -> 0.9.0 (pinned)`. The pin is the
@@ -5993,20 +6755,20 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
5993
6755
  async addLibraryMoves(libraryAssets, rows) {
5994
6756
  const refs = [];
5995
6757
  const lockedIn = /* @__PURE__ */ new Map();
6758
+ const declaredPins = this.declaredPinsByIdentity();
5996
6759
  for (const [key, entry] of libraryAssets) {
5997
6760
  const { publisher, kind, name } = parseCanonicalLockKey(key);
5998
6761
  if (!publisher || !kind || !name || !entry.library) continue;
5999
6762
  const ref = `${kind}:@${publisher}/${name}`;
6000
- refs.push(ref);
6763
+ const pin = declaredPins.get(`${kind}:${publisher}/${name}`);
6764
+ refs.push(pin ? `${ref}#${pin}` : ref);
6001
6765
  lockedIn.set(ref, { name: entry.library.name, key });
6002
6766
  }
6003
6767
  if (refs.length === 0) return;
6004
6768
  let res;
6769
+ const preferLocked = await this.lockedPreference();
6005
6770
  try {
6006
- res = await this.resolveLibraryEntries(refs, {
6007
- quiet: true,
6008
- preferLocked: await this.lockedPreference()
6009
- });
6771
+ res = await this.resolveLibraryEntries(refs, { quiet: true, preferLocked });
6010
6772
  } catch {
6011
6773
  return;
6012
6774
  }
@@ -6016,9 +6778,11 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6016
6778
  const ref = `${e.kind}:@${publisher}/${e.name}`;
6017
6779
  const from = lockedIn.get(ref);
6018
6780
  if (!to || !from || from.name === to) continue;
6781
+ const renamedOnly = preferLocked.libraries.get(`${e.kind}:${publisher}/${e.name}`) === to;
6019
6782
  const row = rows.find(
6020
6783
  (r) => r.kind === e.kind && r.name === e.name && r.publisher.replace(/^@/, "") === publisher
6021
6784
  );
6785
+ if (renamedOnly && !row) continue;
6022
6786
  if (row) {
6023
6787
  row.library = from.name;
6024
6788
  row.movesTo = to;
@@ -6150,7 +6914,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6150
6914
  (r) => unscopedName(r.drift.id) === unscopedName(parsed.name)
6151
6915
  );
6152
6916
  if (!row) return { status: "identical" };
6153
- const fileSetDiffers = row.drift.extra.length > 0 || row.drift.missing.some((f) => !f.includes(" entry "));
6917
+ const fileSetDiffers = row.drift.extra.length > 0 || row.drift.missing.length > 0;
6154
6918
  return {
6155
6919
  status: "differs",
6156
6920
  diff: mcpDriftDiff(row.drift),
@@ -6171,7 +6935,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6171
6935
  if (parsed.kind === "preset" && this.presetRecorded(parsed)) return { status: "no-files" };
6172
6936
  if (!component) return { status: "not-deployed" };
6173
6937
  if (component === "agent") {
6174
- const opts = this.deployOptsFor(this.driverTarget);
6938
+ const opts = this.deployOptsFor(this.harness);
6175
6939
  const parts = [diffDeployedAgent(entry, opts)];
6176
6940
  for (const inst of this.instancesBoundTo(parsed)) {
6177
6941
  parts.push(diffDeployedAgent(entry, opts, inst));
@@ -6181,7 +6945,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6181
6945
  return diff === "" ? { status: "identical" } : { status: "differs", diff };
6182
6946
  }
6183
6947
  const deployedPath = join(
6184
- deployedBase(component, this.driverTarget, this.global, this.projectDir),
6948
+ deployedBase(component, this.harness, this.global, this.projectDir),
6185
6949
  parsed.name
6186
6950
  );
6187
6951
  if (!existsSync(deployedPath)) return { status: "not-deployed" };
@@ -6248,7 +7012,8 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6248
7012
  provenanceIndex,
6249
7013
  overrides,
6250
7014
  stores,
6251
- declaredRefs: dependencies
7015
+ declaredRefs: dependencies,
7016
+ lockedOrigin: this.lockedOriginVersions()
6252
7017
  });
6253
7018
  this.assertSourceCommitsPublished(resolved, repositories);
6254
7019
  const libraryLock = await this.libraryLockEntries(lib);
@@ -6257,6 +7022,8 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6257
7022
  for (const [key, entry] of Object.entries(lockData.assets)) {
6258
7023
  const rendered = prior?.assets[key]?.rendered;
6259
7024
  if (rendered) entry.rendered = rendered;
7025
+ const composed = prior?.assets[key]?.composed;
7026
+ if (composed) entry.composed = composed;
6260
7027
  }
6261
7028
  writeLock(this.lockPath, lockData);
6262
7029
  return lockData;
@@ -6404,7 +7171,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6404
7171
  const dep = memberIdentity(depToStr(req));
6405
7172
  if (!dep) continue;
6406
7173
  const depComponent = this.installTarget(dep.kind);
6407
- if (depComponent && !isDeployed(depComponent, dep.name, this.driverTarget, this.global, this.projectDir)) {
7174
+ if (depComponent && !isDeployed(depComponent, dep.name, this.harness, this.global, this.projectDir)) {
6408
7175
  const inRepos = await resolveAsset({ kind: dep.kind, name: dep.name }, repositories, this.reposDir, {
6409
7176
  knownKinds: this.knownKinds
6410
7177
  }) !== null;
@@ -6616,10 +7383,11 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6616
7383
  ref: s.url,
6617
7384
  reason,
6618
7385
  message: `source ${s.url} ${reason}`,
6619
- manualFix: true
7386
+ manualFix: true,
7387
+ unreadableSource: true
6620
7388
  });
6621
7389
  }
6622
- for (const u of unboundAgentInstances(this.projectDir, this.driverTarget)) {
7390
+ for (const u of unboundAgentInstances(this.projectDir, this.harness)) {
6623
7391
  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`;
6624
7392
  gaps.push({
6625
7393
  type: "agent",
@@ -6842,7 +7610,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6842
7610
  continue;
6843
7611
  }
6844
7612
  if (lookup.state === "unregistered") {
6845
- const reason2 = `is locked, but library "${origin.name}" is not registered (renamed or removed?) \u2014 ${unregisteredLibraryFix(origin, ref)}`;
7613
+ const reason2 = `is locked, but library "${unregisteredLibraryName(origin)}" is not registered (renamed or removed?) \u2014 ${unregisteredLibraryFix(origin, ref)}`;
6846
7614
  gaps.push({ type: "library", ref, reason: reason2, message: `${ref} ${reason2}`, manualFix: true });
6847
7615
  continue;
6848
7616
  }
@@ -6862,12 +7630,15 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6862
7630
  * The locked source assets whose source is no longer in `skaile.yaml` `sources:` (`source
6863
7631
  * remove`, a hand edit), keyed by lock key. ONE sentence for it: `check`, `doctor`, `outdated`,
6864
7632
  * `install`, `install --locked` and `update` all say it (p1062), and none re-clones the source.
6865
- * A source of a store-resolved lock entry is not told apart from one, so no GitHub source is
6866
- * called missing while a `stores:` entry exists.
7633
+ * A GitHub lock entry that no source declares counts as store-supplied only when a store
7634
+ * lists the ref (OQ3): a configured store alone proves nothing, as it may never have held
7635
+ * the asset. `check`, `doctor` and `outdated` read the store's cached catalog and never touch
7636
+ * the network; `install` and `update` (`online`) ask the store itself.
6867
7637
  *
6868
7638
  * @param inScope - Only these lock keys count (`install` prunes an undeclared entry as usual).
7639
+ * @param online - Ask the stores when the cached catalog does not list the ref.
6869
7640
  */
6870
- async orphanedSourceGaps(inScope) {
7641
+ async orphanedSourceGaps(inScope, online = false) {
6871
7642
  const out = /* @__PURE__ */ new Map();
6872
7643
  let config;
6873
7644
  try {
@@ -6875,7 +7646,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6875
7646
  } catch {
6876
7647
  return out;
6877
7648
  }
6878
- const storeBacked = config.stores.length > 0 || (await this.globalStoreFallback(config.stores, false)).length > 0;
7649
+ const stores = [...config.stores, ...await this.globalStoreFallback(config.stores, false)];
6879
7650
  const registered = new Set(config.sources.map((s) => sourceCacheKey(s.url)));
6880
7651
  for (const [key, entry] of Object.entries(this.tryReadLock()?.assets ?? {})) {
6881
7652
  const url = entry.source?.url;
@@ -6885,13 +7656,38 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6885
7656
  const { publisher, kind, name } = parseCanonicalLockKey(key);
6886
7657
  if (!publisher || !kind || !name) continue;
6887
7658
  if (registered.has(sourceCacheKey(url))) continue;
6888
- if (storeBacked && GITHUB_REPO_URL.test(url)) continue;
6889
7659
  const ref = `${kind}:@${publisher}/${name}`;
7660
+ if (GITHUB_REPO_URL.test(url) && await this.storeListsRef(stores, ref, online)) continue;
6890
7661
  const reason = `is locked, but its source ${url} is not in skaile.yaml sources: any more \u2014 register it again with \`skaile source add ${url}\`, or drop the dependency with \`skaile remove ${ref}\``;
6891
7662
  out.set(key, { type: "source", ref, reason, message: `${ref} ${reason}`, manualFix: true });
6892
7663
  }
6893
7664
  return out;
6894
7665
  }
7666
+ /**
7667
+ * `true` when one of `stores` lists `ref` (a canonical lock key): its cached catalog holds it
7668
+ * or, with `online`, the store answers for it. An injected store fetcher is the store client
7669
+ * itself, so it is asked either way. A store an online install cannot ask (unreachable,
7670
+ * air-gapped, `--no-catalog`) may hold the ref; `check` never asks, so a store lists only what
7671
+ * its cached catalog holds.
7672
+ */
7673
+ async storeListsRef(stores, ref, online) {
7674
+ for (const store of stores) {
7675
+ try {
7676
+ if (this.injectedStoreFetcher) {
7677
+ if (await this.injectedStoreFetcher.getInstallManifest(store.url, ref)) return true;
7678
+ continue;
7679
+ }
7680
+ const remote = this.remoteStore(store.url);
7681
+ if (remote.holdsCached(ref)) return true;
7682
+ if (!online) continue;
7683
+ if (this.catalogUrlOverride === "") return true;
7684
+ if (await remote.resolve(ref)) return true;
7685
+ } catch {
7686
+ if (online) return true;
7687
+ }
7688
+ }
7689
+ return false;
7690
+ }
6895
7691
  /**
6896
7692
  * Locked source assets whose source cannot supply them any more: the source is no longer in
6897
7693
  * `skaile.yaml` `sources:` (`source remove`, a hand edit), or it is there but now publishes
@@ -6948,8 +7744,12 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6948
7744
  * rendering occupies and their sha256. Call it after the deploy, so the bytes hashed are the
6949
7745
  * ones `install` just wrote; {@link lockedCopyDrift} compares later edits with them.
6950
7746
  * Entries that carry a record (kept from an earlier lock) are left as they are.
7747
+ *
7748
+ * @param keepComposedOf - The lock an `install` read: an agent whose `../` compose folder is
7749
+ * not in the cache keeps that lock's `composed:` record. Omitted by `update` and `add`,
7750
+ * which copy the library's current bytes.
6951
7751
  */
6952
- withRenderedAgents(lock) {
7752
+ withRenderedAgents(lock, keepComposedOf) {
6953
7753
  if (this.global) return lock;
6954
7754
  for (const [key, entry] of Object.entries(lock.assets)) {
6955
7755
  if (entry.rendered || entry.library?.installed) continue;
@@ -6958,6 +7758,18 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6958
7758
  const rendered = this.renderedAgentFiles(name);
6959
7759
  if (rendered.length > 0) entry.rendered = rendered;
6960
7760
  }
7761
+ for (const [key, entry] of Object.entries(lock.assets)) {
7762
+ if (entry.library?.installed) continue;
7763
+ const { kind, name } = parseCanonicalLockKey(key);
7764
+ if (!kind || !name || this.installTarget(kind) !== "agent") continue;
7765
+ const composed = cachedComposedFiles(name, this.projectDir);
7766
+ if (composed.length > 0) entry.composed = composed;
7767
+ else {
7768
+ const earlier = keepComposedOf?.assets[key]?.composed;
7769
+ if (earlier?.length) entry.composed = earlier;
7770
+ else delete entry.composed;
7771
+ }
7772
+ }
6961
7773
  return this.withInstanceRenderings(lock);
6962
7774
  }
6963
7775
  /**
@@ -6983,7 +7795,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
6983
7795
  ownFiles.set(key, new Set(this.renderedAgentFiles(name).map((f) => f.path)));
6984
7796
  }
6985
7797
  const instanceFiles = /* @__PURE__ */ new Map();
6986
- for (const instance of renderedInstanceFiles(this.projectDir, this.driverTarget)) {
7798
+ for (const instance of renderedInstanceFiles(this.projectDir, this.harness)) {
6987
7799
  const want = parseRefTolerant(instance.ref);
6988
7800
  if (!want || want.kind !== "agent") continue;
6989
7801
  const wantPublisher = want.publisher?.replace(/^@/, "");
@@ -7038,12 +7850,12 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7038
7850
  /** The files of one agent's rendering for the active harness, project-relative, with sha256. */
7039
7851
  renderedAgentFiles(name) {
7040
7852
  const out = [];
7041
- for (const path2 of deployedPaths("agent", name, this.driverTarget, false, this.projectDir)) {
7853
+ for (const path2 of deployedPaths("agent", name, this.harness, false, this.projectDir)) {
7042
7854
  this.hashTree(path2, out);
7043
7855
  }
7044
7856
  this.hashTree(
7045
7857
  join(
7046
- dirname(deployedBase("agent", this.driverTarget, false, this.projectDir)),
7858
+ dirname(deployedBase("agent", this.harness, false, this.projectDir)),
7047
7859
  CODEX_IDENTITY_DIR,
7048
7860
  `${name}.md`
7049
7861
  ),
@@ -7110,7 +7922,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7110
7922
  if (!kind || !name || !component) continue;
7111
7923
  const dir = relative(
7112
7924
  this.projectDir,
7113
- deployedDir(component, name, this.driverTarget, this.global, this.projectDir)
7925
+ deployedDir(component, name, this.harness, this.global, this.projectDir)
7114
7926
  ).split(sep).join("/");
7115
7927
  out.push({
7116
7928
  ref: d.key,
@@ -7127,7 +7939,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7127
7939
  if (!kind || !name || !component) continue;
7128
7940
  const dir = relative(
7129
7941
  this.projectDir,
7130
- deployedDir(component, name, this.driverTarget, this.global, this.projectDir)
7942
+ deployedDir(component, name, this.harness, this.global, this.projectDir)
7131
7943
  ).split(sep).join("/");
7132
7944
  const files = inc.missing.map((f) => `${dir}/${f}`);
7133
7945
  const row = out.find((r) => r.ref.split("#")[0] === bare);
@@ -7161,7 +7973,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7161
7973
  const out = [];
7162
7974
  const deployOpts = {
7163
7975
  registry: this.registry,
7164
- driverTarget: this.driverTarget,
7976
+ harness: this.harness,
7165
7977
  global: this.global,
7166
7978
  cwd: this.projectDir
7167
7979
  };
@@ -7185,7 +7997,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7185
7997
  const component = kind ? this.installTarget(kind) : void 0;
7186
7998
  if (!kind || !name || !component || component === "agent") continue;
7187
7999
  if (patches[`${kind}:${name}`]) continue;
7188
- const dest = deployedDir(component, name, this.driverTarget, this.global, this.projectDir);
8000
+ const dest = deployedDir(component, name, this.harness, this.global, this.projectDir);
7189
8001
  try {
7190
8002
  const deployed = lstatSync(dest);
7191
8003
  if (deployed.isSymbolicLink() || !deployed.isDirectory()) continue;
@@ -7213,12 +8025,13 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7213
8025
  out.push({ ref: refOf(key), key, modified, extra, library: false });
7214
8026
  }
7215
8027
  for (const [key, entry] of Object.entries(lock.assets)) {
7216
- if (!entry.rendered || entry.rendered.length === 0 || entry.library?.installed) continue;
8028
+ const recorded = [...entry.rendered ?? [], ...entry.composed ?? []];
8029
+ if (recorded.length === 0 || entry.library?.installed) continue;
7217
8030
  const { kind, name } = parseCanonicalLockKey(key);
7218
8031
  if (!kind || !name || this.installTarget(kind) !== "agent") continue;
7219
8032
  if (patches[`${kind}:${name}`]) continue;
7220
8033
  const modified = [];
7221
- for (const f of entry.rendered) {
8034
+ for (const f of recorded) {
7222
8035
  const file = join(this.projectDir, f.path);
7223
8036
  if (!existsSync(file)) continue;
7224
8037
  try {
@@ -7229,7 +8042,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7229
8042
  }
7230
8043
  if (modified.length > 0) {
7231
8044
  const instanceOf = /* @__PURE__ */ new Map();
7232
- for (const inst of renderedInstanceFiles(this.projectDir, this.driverTarget)) {
8045
+ for (const inst of renderedInstanceFiles(this.projectDir, this.harness)) {
7233
8046
  for (const f of inst.files) if (modified.includes(f)) instanceOf.set(f, inst.id);
7234
8047
  }
7235
8048
  out.push({
@@ -7239,7 +8052,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7239
8052
  extra: [],
7240
8053
  library: false,
7241
8054
  rendered: true,
7242
- lockedSha: new Map(entry.rendered.map((f) => [f.path, f.sha256])),
8055
+ lockedSha: new Map(recorded.map((f) => [f.path, f.sha256])),
7243
8056
  instanceOf
7244
8057
  });
7245
8058
  }
@@ -7259,7 +8072,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7259
8072
  const { publisher, kind, name } = parseCanonicalLockKey(key);
7260
8073
  const component = kind ? this.installTarget(kind) : void 0;
7261
8074
  if (!kind || !name || !component || named.has(`${kind}:${name}`)) continue;
7262
- if (isDeployed(component, name, this.driverTarget, this.global, this.projectDir)) {
8075
+ if (isDeployed(component, name, this.harness, this.global, this.projectDir)) {
7263
8076
  const renderedGone = component === "agent" && !this.global && (entry.rendered ?? []).some((f) => !existsSync(join(this.projectDir, f.path)));
7264
8077
  if (!renderedGone) continue;
7265
8078
  }
@@ -7267,7 +8080,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7267
8080
  const dangling = deployedPaths(
7268
8081
  component,
7269
8082
  name,
7270
- this.driverTarget,
8083
+ this.harness,
7271
8084
  this.global,
7272
8085
  this.projectDir
7273
8086
  ).find((p) => isSymlink(p) && !existsSync(p));
@@ -7352,10 +8165,23 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7352
8165
  ({ id }) => id.kind === want.kind && id.name === want.name && (!want.publisher || id.publisher === want.publisher)
7353
8166
  );
7354
8167
  if (held.length > 0 && !held.some(({ id }) => !id.version || matchPin(want.pin, id.version))) {
7355
- gap = {
7356
- type: "pin",
7357
- reason: `is pinned in skaile.yaml but the lock holds ${held.map((h) => h.key).join(", ")} \u2014 run \`skaile install\``
7358
- };
8168
+ const lockHolds = held.map((h) => h.key).join(", ");
8169
+ const pinned = await this.info(d.ref);
8170
+ const pinHeld = pinned !== null && matchPin(want.pin, pinned.version ?? "");
8171
+ if (!pinHeld && this.loadConfig().stores.length === 0) {
8172
+ const plainRef = d.ref.split("#")[0] ?? d.ref;
8173
+ const other = pinned ?? await this.info(plainRef);
8174
+ gap = {
8175
+ type: "pin",
8176
+ reason: `is pinned in skaile.yaml but the lock holds ${lockHolds}, and no library or source holds ${want.pin}${other?.version ? ` (${want.name} has version(s): ${other.version})` : ""} \u2014 change the pin in skaile.yaml`,
8177
+ manualFix: true
8178
+ };
8179
+ } else {
8180
+ gap = {
8181
+ type: "pin",
8182
+ reason: `is pinned in skaile.yaml but the lock holds ${lockHolds} \u2014 run \`skaile install\``
8183
+ };
8184
+ }
7359
8185
  }
7360
8186
  }
7361
8187
  if (gap) gaps.push({ ...gap, ref: d.ref, message: `${d.ref} ${gap.reason}` });
@@ -7585,7 +8411,7 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7585
8411
  for (const dest of deployedPaths(
7586
8412
  component,
7587
8413
  name,
7588
- this.driverTarget,
8414
+ this.harness,
7589
8415
  this.global,
7590
8416
  this.projectDir
7591
8417
  )) {
@@ -7806,8 +8632,8 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7806
8632
  }
7807
8633
  if (ids.length === 0) return false;
7808
8634
  writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
7809
- for (const driverTarget of this.targetHarnesses()) {
7810
- removeAgentInstanceRenderings({ projectDir: this.projectDir, driverTarget, ids });
8635
+ for (const harness of this.targetHarnesses()) {
8636
+ removeAgentInstanceRenderings({ projectDir: this.projectDir, harness, ids });
7811
8637
  }
7812
8638
  return true;
7813
8639
  }
@@ -7828,6 +8654,6 @@ Nothing was changed. Declare it again to keep it, or run \`skaile install --forc
7828
8654
  }
7829
8655
  };
7830
8656
 
7831
- export { AssetManager, FACTORY_SOURCE_URL, LibraryEntryError, MissingManifestError, installAgentInstances, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, softDepName };
7832
- //# sourceMappingURL=chunk-MRHVPQNO.js.map
7833
- //# sourceMappingURL=chunk-MRHVPQNO.js.map
8657
+ export { AssetManager, FACTORY_SOURCE_URL, LibraryEntryError, MissingManifestError, installAgentInstances, mcpNotRunnableReason, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, setLibraryAssetCheck, softDepName };
8658
+ //# sourceMappingURL=chunk-HWNK3F3X.js.map
8659
+ //# sourceMappingURL=chunk-HWNK3F3X.js.map