@alan-ai-hq/agent-manager 0.1.113 → 0.1.115

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 (655) hide show
  1. package/LICENSE +88 -0
  2. package/dist/__tests__/binding-switch-git.test.d.ts +2 -0
  3. package/dist/__tests__/binding-switch-git.test.d.ts.map +1 -0
  4. package/dist/__tests__/binding-switch-git.test.js +555 -0
  5. package/dist/__tests__/binding-switch-git.test.js.map +1 -0
  6. package/dist/__tests__/cli-ensure-install.test.d.ts +2 -0
  7. package/dist/__tests__/cli-ensure-install.test.d.ts.map +1 -0
  8. package/dist/__tests__/cli-ensure-install.test.js +177 -0
  9. package/dist/__tests__/cli-ensure-install.test.js.map +1 -0
  10. package/dist/__tests__/cli-executable.test.d.ts +2 -0
  11. package/dist/__tests__/cli-executable.test.d.ts.map +1 -0
  12. package/dist/__tests__/cli-executable.test.js +155 -0
  13. package/dist/__tests__/cli-executable.test.js.map +1 -0
  14. package/dist/__tests__/cli-executable.windows.test.d.ts +2 -0
  15. package/dist/__tests__/cli-executable.windows.test.d.ts.map +1 -0
  16. package/dist/__tests__/cli-executable.windows.test.js +123 -0
  17. package/dist/__tests__/cli-executable.windows.test.js.map +1 -0
  18. package/dist/__tests__/cli-help.test.d.ts +2 -0
  19. package/dist/__tests__/cli-help.test.d.ts.map +1 -0
  20. package/dist/__tests__/cli-help.test.js +47 -0
  21. package/dist/__tests__/cli-help.test.js.map +1 -0
  22. package/dist/__tests__/computer-readiness.test.d.ts +2 -0
  23. package/dist/__tests__/computer-readiness.test.d.ts.map +1 -0
  24. package/dist/__tests__/computer-readiness.test.js +63 -0
  25. package/dist/__tests__/computer-readiness.test.js.map +1 -0
  26. package/dist/__tests__/core-agent-provider-auth-env.test.d.ts +2 -0
  27. package/dist/__tests__/core-agent-provider-auth-env.test.d.ts.map +1 -0
  28. package/dist/__tests__/core-agent-provider-auth-env.test.js +93 -0
  29. package/dist/__tests__/core-agent-provider-auth-env.test.js.map +1 -0
  30. package/dist/__tests__/core-agent-workflow-context.test.d.ts +2 -0
  31. package/dist/__tests__/core-agent-workflow-context.test.d.ts.map +1 -0
  32. package/dist/__tests__/core-agent-workflow-context.test.js +139 -0
  33. package/dist/__tests__/core-agent-workflow-context.test.js.map +1 -0
  34. package/dist/__tests__/daemon-native-hooks.test.d.ts +2 -0
  35. package/dist/__tests__/daemon-native-hooks.test.d.ts.map +1 -0
  36. package/dist/__tests__/daemon-native-hooks.test.js +94 -0
  37. package/dist/__tests__/daemon-native-hooks.test.js.map +1 -0
  38. package/dist/__tests__/daemon-reconcile-ask.test.d.ts +2 -0
  39. package/dist/__tests__/daemon-reconcile-ask.test.d.ts.map +1 -0
  40. package/dist/__tests__/daemon-reconcile-ask.test.js +100 -0
  41. package/dist/__tests__/daemon-reconcile-ask.test.js.map +1 -0
  42. package/dist/__tests__/daemon-runner-status.test.d.ts +2 -0
  43. package/dist/__tests__/daemon-runner-status.test.d.ts.map +1 -0
  44. package/dist/__tests__/daemon-runner-status.test.js +102 -0
  45. package/dist/__tests__/daemon-runner-status.test.js.map +1 -0
  46. package/dist/__tests__/daemon-socket.integration.test.d.ts +2 -0
  47. package/dist/__tests__/daemon-socket.integration.test.d.ts.map +1 -0
  48. package/dist/__tests__/daemon-socket.integration.test.js +435 -0
  49. package/dist/__tests__/daemon-socket.integration.test.js.map +1 -0
  50. package/dist/__tests__/daemon.test.d.ts +2 -0
  51. package/dist/__tests__/daemon.test.d.ts.map +1 -0
  52. package/dist/__tests__/daemon.test.js +4884 -0
  53. package/dist/__tests__/daemon.test.js.map +1 -0
  54. package/dist/__tests__/ensure-shared-checkout-branch.test.d.ts +2 -0
  55. package/dist/__tests__/ensure-shared-checkout-branch.test.d.ts.map +1 -0
  56. package/dist/__tests__/ensure-shared-checkout-branch.test.js +129 -0
  57. package/dist/__tests__/ensure-shared-checkout-branch.test.js.map +1 -0
  58. package/dist/__tests__/event-journal-stress.test.d.ts +2 -0
  59. package/dist/__tests__/event-journal-stress.test.d.ts.map +1 -0
  60. package/dist/__tests__/event-journal-stress.test.js +124 -0
  61. package/dist/__tests__/event-journal-stress.test.js.map +1 -0
  62. package/dist/__tests__/event-journal.test.d.ts +2 -0
  63. package/dist/__tests__/event-journal.test.d.ts.map +1 -0
  64. package/dist/__tests__/event-journal.test.js +264 -0
  65. package/dist/__tests__/event-journal.test.js.map +1 -0
  66. package/dist/__tests__/event-outbox-persist-failure.test.d.ts +2 -0
  67. package/dist/__tests__/event-outbox-persist-failure.test.d.ts.map +1 -0
  68. package/dist/__tests__/event-outbox-persist-failure.test.js +143 -0
  69. package/dist/__tests__/event-outbox-persist-failure.test.js.map +1 -0
  70. package/dist/__tests__/event-outbox.test.d.ts +2 -0
  71. package/dist/__tests__/event-outbox.test.d.ts.map +1 -0
  72. package/dist/__tests__/event-outbox.test.js +602 -0
  73. package/dist/__tests__/event-outbox.test.js.map +1 -0
  74. package/dist/__tests__/execution-activity-tracker.test.d.ts +2 -0
  75. package/dist/__tests__/execution-activity-tracker.test.d.ts.map +1 -0
  76. package/dist/__tests__/execution-activity-tracker.test.js +64 -0
  77. package/dist/__tests__/execution-activity-tracker.test.js.map +1 -0
  78. package/dist/__tests__/execution-lease-client.test.d.ts +2 -0
  79. package/dist/__tests__/execution-lease-client.test.d.ts.map +1 -0
  80. package/dist/__tests__/execution-lease-client.test.js +274 -0
  81. package/dist/__tests__/execution-lease-client.test.js.map +1 -0
  82. package/dist/__tests__/fake-provider-cli.test.d.ts +2 -0
  83. package/dist/__tests__/fake-provider-cli.test.d.ts.map +1 -0
  84. package/dist/__tests__/fake-provider-cli.test.js +46 -0
  85. package/dist/__tests__/fake-provider-cli.test.js.map +1 -0
  86. package/dist/__tests__/generated-images.test.d.ts +2 -0
  87. package/dist/__tests__/generated-images.test.d.ts.map +1 -0
  88. package/dist/__tests__/generated-images.test.js +132 -0
  89. package/dist/__tests__/generated-images.test.js.map +1 -0
  90. package/dist/__tests__/helpers/sandbox-outbox.d.ts +3 -0
  91. package/dist/__tests__/helpers/sandbox-outbox.d.ts.map +1 -0
  92. package/dist/__tests__/helpers/sandbox-outbox.js +23 -0
  93. package/dist/__tests__/helpers/sandbox-outbox.js.map +1 -0
  94. package/dist/__tests__/install-command.test.d.ts +2 -0
  95. package/dist/__tests__/install-command.test.d.ts.map +1 -0
  96. package/dist/__tests__/install-command.test.js +185 -0
  97. package/dist/__tests__/install-command.test.js.map +1 -0
  98. package/dist/__tests__/integration-cli.test.d.ts +2 -0
  99. package/dist/__tests__/integration-cli.test.d.ts.map +1 -0
  100. package/dist/__tests__/integration-cli.test.js +150 -0
  101. package/dist/__tests__/integration-cli.test.js.map +1 -0
  102. package/dist/__tests__/lifecycle-contracts.test.d.ts +2 -0
  103. package/dist/__tests__/lifecycle-contracts.test.d.ts.map +1 -0
  104. package/dist/__tests__/lifecycle-contracts.test.js +66 -0
  105. package/dist/__tests__/lifecycle-contracts.test.js.map +1 -0
  106. package/dist/__tests__/lifecycle-logger.test.d.ts +2 -0
  107. package/dist/__tests__/lifecycle-logger.test.d.ts.map +1 -0
  108. package/dist/__tests__/lifecycle-logger.test.js +49 -0
  109. package/dist/__tests__/lifecycle-logger.test.js.map +1 -0
  110. package/dist/__tests__/local-daemon-lifecycle.test.d.ts +2 -0
  111. package/dist/__tests__/local-daemon-lifecycle.test.d.ts.map +1 -0
  112. package/dist/__tests__/local-daemon-lifecycle.test.js +594 -0
  113. package/dist/__tests__/local-daemon-lifecycle.test.js.map +1 -0
  114. package/dist/__tests__/local-git-status.test.d.ts +2 -0
  115. package/dist/__tests__/local-git-status.test.d.ts.map +1 -0
  116. package/dist/__tests__/local-git-status.test.js +31 -0
  117. package/dist/__tests__/local-git-status.test.js.map +1 -0
  118. package/dist/__tests__/mcp-config-adapters-files.test.d.ts +2 -0
  119. package/dist/__tests__/mcp-config-adapters-files.test.d.ts.map +1 -0
  120. package/dist/__tests__/mcp-config-adapters-files.test.js +486 -0
  121. package/dist/__tests__/mcp-config-adapters-files.test.js.map +1 -0
  122. package/dist/__tests__/mcp-config-adapters.test.d.ts +2 -0
  123. package/dist/__tests__/mcp-config-adapters.test.d.ts.map +1 -0
  124. package/dist/__tests__/mcp-config-adapters.test.js +492 -0
  125. package/dist/__tests__/mcp-config-adapters.test.js.map +1 -0
  126. package/dist/__tests__/mcp-sync.test.d.ts +2 -0
  127. package/dist/__tests__/mcp-sync.test.d.ts.map +1 -0
  128. package/dist/__tests__/mcp-sync.test.js +21 -0
  129. package/dist/__tests__/mcp-sync.test.js.map +1 -0
  130. package/dist/__tests__/model-scan-runner.test.d.ts +2 -0
  131. package/dist/__tests__/model-scan-runner.test.d.ts.map +1 -0
  132. package/dist/__tests__/model-scan-runner.test.js +80 -0
  133. package/dist/__tests__/model-scan-runner.test.js.map +1 -0
  134. package/dist/__tests__/native-hook-command.test.d.ts +2 -0
  135. package/dist/__tests__/native-hook-command.test.d.ts.map +1 -0
  136. package/dist/__tests__/native-hook-command.test.js +386 -0
  137. package/dist/__tests__/native-hook-command.test.js.map +1 -0
  138. package/dist/__tests__/native-hook-config.test.d.ts +2 -0
  139. package/dist/__tests__/native-hook-config.test.d.ts.map +1 -0
  140. package/dist/__tests__/native-hook-config.test.js +374 -0
  141. package/dist/__tests__/native-hook-config.test.js.map +1 -0
  142. package/dist/__tests__/native-hook-drain.test.d.ts +2 -0
  143. package/dist/__tests__/native-hook-drain.test.d.ts.map +1 -0
  144. package/dist/__tests__/native-hook-drain.test.js +197 -0
  145. package/dist/__tests__/native-hook-drain.test.js.map +1 -0
  146. package/dist/__tests__/native-hook-inbox.test.d.ts +2 -0
  147. package/dist/__tests__/native-hook-inbox.test.d.ts.map +1 -0
  148. package/dist/__tests__/native-hook-inbox.test.js +139 -0
  149. package/dist/__tests__/native-hook-inbox.test.js.map +1 -0
  150. package/dist/__tests__/native-session.test.d.ts +2 -0
  151. package/dist/__tests__/native-session.test.d.ts.map +1 -0
  152. package/dist/__tests__/native-session.test.js +41 -0
  153. package/dist/__tests__/native-session.test.js.map +1 -0
  154. package/dist/__tests__/native-stream-outbox.test.d.ts +2 -0
  155. package/dist/__tests__/native-stream-outbox.test.d.ts.map +1 -0
  156. package/dist/__tests__/native-stream-outbox.test.js +231 -0
  157. package/dist/__tests__/native-stream-outbox.test.js.map +1 -0
  158. package/dist/__tests__/native-stream-platform.test.d.ts +2 -0
  159. package/dist/__tests__/native-stream-platform.test.d.ts.map +1 -0
  160. package/dist/__tests__/native-stream-platform.test.js +20 -0
  161. package/dist/__tests__/native-stream-platform.test.js.map +1 -0
  162. package/dist/__tests__/native-transcript-cursor.test.d.ts +2 -0
  163. package/dist/__tests__/native-transcript-cursor.test.d.ts.map +1 -0
  164. package/dist/__tests__/native-transcript-cursor.test.js +60 -0
  165. package/dist/__tests__/native-transcript-cursor.test.js.map +1 -0
  166. package/dist/__tests__/native-transcript-stream.test.d.ts +2 -0
  167. package/dist/__tests__/native-transcript-stream.test.d.ts.map +1 -0
  168. package/dist/__tests__/native-transcript-stream.test.js +378 -0
  169. package/dist/__tests__/native-transcript-stream.test.js.map +1 -0
  170. package/dist/__tests__/network-diagnostics.test.d.ts +2 -0
  171. package/dist/__tests__/network-diagnostics.test.d.ts.map +1 -0
  172. package/dist/__tests__/network-diagnostics.test.js +26 -0
  173. package/dist/__tests__/network-diagnostics.test.js.map +1 -0
  174. package/dist/__tests__/observable-map.test.d.ts +2 -0
  175. package/dist/__tests__/observable-map.test.d.ts.map +1 -0
  176. package/dist/__tests__/observable-map.test.js +54 -0
  177. package/dist/__tests__/observable-map.test.js.map +1 -0
  178. package/dist/__tests__/outbox-baseline.bench.test.d.ts +2 -0
  179. package/dist/__tests__/outbox-baseline.bench.test.d.ts.map +1 -0
  180. package/dist/__tests__/outbox-baseline.bench.test.js +108 -0
  181. package/dist/__tests__/outbox-baseline.bench.test.js.map +1 -0
  182. package/dist/__tests__/provider-auth-preflight.test.d.ts +2 -0
  183. package/dist/__tests__/provider-auth-preflight.test.d.ts.map +1 -0
  184. package/dist/__tests__/provider-auth-preflight.test.js +123 -0
  185. package/dist/__tests__/provider-auth-preflight.test.js.map +1 -0
  186. package/dist/__tests__/provider-model-discovery.test.d.ts +2 -0
  187. package/dist/__tests__/provider-model-discovery.test.d.ts.map +1 -0
  188. package/dist/__tests__/provider-model-discovery.test.js +1071 -0
  189. package/dist/__tests__/provider-model-discovery.test.js.map +1 -0
  190. package/dist/__tests__/resource-diagnostics.test.d.ts +2 -0
  191. package/dist/__tests__/resource-diagnostics.test.d.ts.map +1 -0
  192. package/dist/__tests__/resource-diagnostics.test.js +138 -0
  193. package/dist/__tests__/resource-diagnostics.test.js.map +1 -0
  194. package/dist/__tests__/resume-fallback-env.test.d.ts +2 -0
  195. package/dist/__tests__/resume-fallback-env.test.d.ts.map +1 -0
  196. package/dist/__tests__/resume-fallback-env.test.js +28 -0
  197. package/dist/__tests__/resume-fallback-env.test.js.map +1 -0
  198. package/dist/__tests__/run-journal.test.d.ts +2 -0
  199. package/dist/__tests__/run-journal.test.d.ts.map +1 -0
  200. package/dist/__tests__/run-journal.test.js +121 -0
  201. package/dist/__tests__/run-journal.test.js.map +1 -0
  202. package/dist/__tests__/run-start-gate.test.d.ts +2 -0
  203. package/dist/__tests__/run-start-gate.test.d.ts.map +1 -0
  204. package/dist/__tests__/run-start-gate.test.js +18 -0
  205. package/dist/__tests__/run-start-gate.test.js.map +1 -0
  206. package/dist/__tests__/runtime-capabilities-sync.test.d.ts +2 -0
  207. package/dist/__tests__/runtime-capabilities-sync.test.d.ts.map +1 -0
  208. package/dist/__tests__/runtime-capabilities-sync.test.js +66 -0
  209. package/dist/__tests__/runtime-capabilities-sync.test.js.map +1 -0
  210. package/dist/__tests__/runtime-config.test.d.ts +2 -0
  211. package/dist/__tests__/runtime-config.test.d.ts.map +1 -0
  212. package/dist/__tests__/runtime-config.test.js +137 -0
  213. package/dist/__tests__/runtime-config.test.js.map +1 -0
  214. package/dist/__tests__/runtime-presenter-heartbeat.test.d.ts +2 -0
  215. package/dist/__tests__/runtime-presenter-heartbeat.test.d.ts.map +1 -0
  216. package/dist/__tests__/runtime-presenter-heartbeat.test.js +253 -0
  217. package/dist/__tests__/runtime-presenter-heartbeat.test.js.map +1 -0
  218. package/dist/__tests__/runtime-registration.test.d.ts +2 -0
  219. package/dist/__tests__/runtime-registration.test.d.ts.map +1 -0
  220. package/dist/__tests__/runtime-registration.test.js +109 -0
  221. package/dist/__tests__/runtime-registration.test.js.map +1 -0
  222. package/dist/__tests__/sandbox-outbox-storage.test.d.ts +2 -0
  223. package/dist/__tests__/sandbox-outbox-storage.test.d.ts.map +1 -0
  224. package/dist/__tests__/sandbox-outbox-storage.test.js +81 -0
  225. package/dist/__tests__/sandbox-outbox-storage.test.js.map +1 -0
  226. package/dist/__tests__/sandbox-outbox.test.d.ts +2 -0
  227. package/dist/__tests__/sandbox-outbox.test.d.ts.map +1 -0
  228. package/dist/__tests__/sandbox-outbox.test.js +300 -0
  229. package/dist/__tests__/sandbox-outbox.test.js.map +1 -0
  230. package/dist/__tests__/sandbox-workflow-context.test.d.ts +2 -0
  231. package/dist/__tests__/sandbox-workflow-context.test.d.ts.map +1 -0
  232. package/dist/__tests__/sandbox-workflow-context.test.js +600 -0
  233. package/dist/__tests__/sandbox-workflow-context.test.js.map +1 -0
  234. package/dist/__tests__/service-manager-deadline.test.d.ts +2 -0
  235. package/dist/__tests__/service-manager-deadline.test.d.ts.map +1 -0
  236. package/dist/__tests__/service-manager-deadline.test.js +36 -0
  237. package/dist/__tests__/service-manager-deadline.test.js.map +1 -0
  238. package/dist/__tests__/service-manager.test.d.ts +2 -0
  239. package/dist/__tests__/service-manager.test.d.ts.map +1 -0
  240. package/dist/__tests__/service-manager.test.js +769 -0
  241. package/dist/__tests__/service-manager.test.js.map +1 -0
  242. package/dist/__tests__/service-stop-ownership.test.d.ts +2 -0
  243. package/dist/__tests__/service-stop-ownership.test.d.ts.map +1 -0
  244. package/dist/__tests__/service-stop-ownership.test.js +89 -0
  245. package/dist/__tests__/service-stop-ownership.test.js.map +1 -0
  246. package/dist/__tests__/skill-invocation.test.d.ts +2 -0
  247. package/dist/__tests__/skill-invocation.test.d.ts.map +1 -0
  248. package/dist/__tests__/skill-invocation.test.js +40 -0
  249. package/dist/__tests__/skill-invocation.test.js.map +1 -0
  250. package/dist/__tests__/sleep-inhibitor-real.test.d.ts +2 -0
  251. package/dist/__tests__/sleep-inhibitor-real.test.d.ts.map +1 -0
  252. package/dist/__tests__/sleep-inhibitor-real.test.js +68 -0
  253. package/dist/__tests__/sleep-inhibitor-real.test.js.map +1 -0
  254. package/dist/__tests__/sleep-inhibitor.test.d.ts +2 -0
  255. package/dist/__tests__/sleep-inhibitor.test.d.ts.map +1 -0
  256. package/dist/__tests__/sleep-inhibitor.test.js +236 -0
  257. package/dist/__tests__/sleep-inhibitor.test.js.map +1 -0
  258. package/dist/__tests__/status-local-workspace.test.d.ts +2 -0
  259. package/dist/__tests__/status-local-workspace.test.d.ts.map +1 -0
  260. package/dist/__tests__/status-local-workspace.test.js +121 -0
  261. package/dist/__tests__/status-local-workspace.test.js.map +1 -0
  262. package/dist/__tests__/suspension-detector.test.d.ts +2 -0
  263. package/dist/__tests__/suspension-detector.test.d.ts.map +1 -0
  264. package/dist/__tests__/suspension-detector.test.js +112 -0
  265. package/dist/__tests__/suspension-detector.test.js.map +1 -0
  266. package/dist/__tests__/web-presenter-parent-events.test.d.ts +2 -0
  267. package/dist/__tests__/web-presenter-parent-events.test.d.ts.map +1 -0
  268. package/dist/__tests__/web-presenter-parent-events.test.js +168 -0
  269. package/dist/__tests__/web-presenter-parent-events.test.js.map +1 -0
  270. package/dist/__tests__/workspace-probe-concurrency.test.d.ts +2 -0
  271. package/dist/__tests__/workspace-probe-concurrency.test.d.ts.map +1 -0
  272. package/dist/__tests__/workspace-probe-concurrency.test.js +54 -0
  273. package/dist/__tests__/workspace-probe-concurrency.test.js.map +1 -0
  274. package/dist/__tests__/workspace-relocation.test.d.ts +2 -0
  275. package/dist/__tests__/workspace-relocation.test.d.ts.map +1 -0
  276. package/dist/__tests__/workspace-relocation.test.js +66 -0
  277. package/dist/__tests__/workspace-relocation.test.js.map +1 -0
  278. package/dist/__tests__/workspace-rpc.test.d.ts +2 -0
  279. package/dist/__tests__/workspace-rpc.test.d.ts.map +1 -0
  280. package/dist/__tests__/workspace-rpc.test.js +90 -0
  281. package/dist/__tests__/workspace-rpc.test.js.map +1 -0
  282. package/dist/__tests__/workspace-run-lease.test.d.ts +2 -0
  283. package/dist/__tests__/workspace-run-lease.test.d.ts.map +1 -0
  284. package/dist/__tests__/workspace-run-lease.test.js +331 -0
  285. package/dist/__tests__/workspace-run-lease.test.js.map +1 -0
  286. package/dist/__tests__/ws-client-connection.test.d.ts +2 -0
  287. package/dist/__tests__/ws-client-connection.test.d.ts.map +1 -0
  288. package/dist/__tests__/ws-client-connection.test.js +295 -0
  289. package/dist/__tests__/ws-client-connection.test.js.map +1 -0
  290. package/dist/__tests__/ws-client-heartbeat-volatile.test.d.ts +2 -0
  291. package/dist/__tests__/ws-client-heartbeat-volatile.test.d.ts.map +1 -0
  292. package/dist/__tests__/ws-client-heartbeat-volatile.test.js +63 -0
  293. package/dist/__tests__/ws-client-heartbeat-volatile.test.js.map +1 -0
  294. package/dist/__tests__/ws-client-heartbeat.integration.test.d.ts +2 -0
  295. package/dist/__tests__/ws-client-heartbeat.integration.test.d.ts.map +1 -0
  296. package/dist/__tests__/ws-client-heartbeat.integration.test.js +236 -0
  297. package/dist/__tests__/ws-client-heartbeat.integration.test.js.map +1 -0
  298. package/dist/__tests__/ws-client-user-message-ack.integration.test.d.ts +2 -0
  299. package/dist/__tests__/ws-client-user-message-ack.integration.test.d.ts.map +1 -0
  300. package/dist/__tests__/ws-client-user-message-ack.integration.test.js +211 -0
  301. package/dist/__tests__/ws-client-user-message-ack.integration.test.js.map +1 -0
  302. package/dist/antigravity-api-key-config.d.ts +2 -0
  303. package/dist/antigravity-api-key-config.d.ts.map +1 -0
  304. package/dist/antigravity-api-key-config.js +79 -0
  305. package/dist/antigravity-api-key-config.js.map +1 -0
  306. package/dist/binding-switch-git.d.ts +26 -0
  307. package/dist/binding-switch-git.d.ts.map +1 -0
  308. package/dist/binding-switch-git.js +871 -0
  309. package/dist/binding-switch-git.js.map +1 -0
  310. package/dist/cli-ensure-install.d.ts +34 -0
  311. package/dist/cli-ensure-install.d.ts.map +1 -0
  312. package/dist/cli-ensure-install.js +154 -0
  313. package/dist/cli-ensure-install.js.map +1 -0
  314. package/dist/cli-executable.d.ts +44 -0
  315. package/dist/cli-executable.d.ts.map +1 -0
  316. package/dist/cli-executable.js +435 -0
  317. package/dist/cli-executable.js.map +1 -0
  318. package/dist/cli-help.d.ts +11 -0
  319. package/dist/cli-help.d.ts.map +1 -0
  320. package/dist/cli-help.js +65 -0
  321. package/dist/cli-help.js.map +1 -0
  322. package/dist/computer-readiness.d.ts +41 -0
  323. package/dist/computer-readiness.d.ts.map +1 -0
  324. package/dist/computer-readiness.js +191 -0
  325. package/dist/computer-readiness.js.map +1 -0
  326. package/dist/core-agent.d.ts +32 -0
  327. package/dist/core-agent.d.ts.map +1 -0
  328. package/dist/core-agent.js +331 -0
  329. package/dist/core-agent.js.map +1 -0
  330. package/dist/daemon-execute.d.ts +42 -0
  331. package/dist/daemon-execute.d.ts.map +1 -0
  332. package/dist/daemon-execute.js +666 -0
  333. package/dist/daemon-execute.js.map +1 -0
  334. package/dist/daemon-helpers.d.ts +150 -0
  335. package/dist/daemon-helpers.d.ts.map +1 -0
  336. package/dist/daemon-helpers.js +157 -0
  337. package/dist/daemon-helpers.js.map +1 -0
  338. package/dist/daemon-local-control.d.ts +208 -0
  339. package/dist/daemon-local-control.d.ts.map +1 -0
  340. package/dist/daemon-local-control.js +826 -0
  341. package/dist/daemon-local-control.js.map +1 -0
  342. package/dist/daemon-local-http.d.ts +57 -0
  343. package/dist/daemon-local-http.d.ts.map +1 -0
  344. package/dist/daemon-local-http.js +375 -0
  345. package/dist/daemon-local-http.js.map +1 -0
  346. package/dist/daemon-native-hooks.d.ts +17 -0
  347. package/dist/daemon-native-hooks.d.ts.map +1 -0
  348. package/dist/daemon-native-hooks.js +54 -0
  349. package/dist/daemon-native-hooks.js.map +1 -0
  350. package/dist/daemon-provider-scan.d.ts +33 -0
  351. package/dist/daemon-provider-scan.d.ts.map +1 -0
  352. package/dist/daemon-provider-scan.js +187 -0
  353. package/dist/daemon-provider-scan.js.map +1 -0
  354. package/dist/daemon-runner-status.d.ts +164 -0
  355. package/dist/daemon-runner-status.d.ts.map +1 -0
  356. package/dist/daemon-runner-status.js +424 -0
  357. package/dist/daemon-runner-status.js.map +1 -0
  358. package/dist/daemon-start.d.ts +5 -0
  359. package/dist/daemon-start.d.ts.map +1 -0
  360. package/dist/daemon-start.js +1313 -0
  361. package/dist/daemon-start.js.map +1 -0
  362. package/dist/daemon-workspace.d.ts +36 -0
  363. package/dist/daemon-workspace.d.ts.map +1 -0
  364. package/dist/daemon-workspace.js +154 -0
  365. package/dist/daemon-workspace.js.map +1 -0
  366. package/dist/daemon.d.ts +59 -0
  367. package/dist/daemon.d.ts.map +1 -0
  368. package/dist/daemon.js +681 -0
  369. package/dist/daemon.js.map +1 -0
  370. package/dist/event-journal-crypto.d.ts +14 -0
  371. package/dist/event-journal-crypto.d.ts.map +1 -0
  372. package/dist/event-journal-crypto.js +89 -0
  373. package/dist/event-journal-crypto.js.map +1 -0
  374. package/dist/event-journal-paths.d.ts +10 -0
  375. package/dist/event-journal-paths.d.ts.map +1 -0
  376. package/dist/event-journal-paths.js +29 -0
  377. package/dist/event-journal-paths.js.map +1 -0
  378. package/dist/event-journal-recovery.d.ts +83 -0
  379. package/dist/event-journal-recovery.d.ts.map +1 -0
  380. package/dist/event-journal-recovery.js +333 -0
  381. package/dist/event-journal-recovery.js.map +1 -0
  382. package/dist/event-journal-types.d.ts +54 -0
  383. package/dist/event-journal-types.d.ts.map +1 -0
  384. package/dist/event-journal-types.js +10 -0
  385. package/dist/event-journal-types.js.map +1 -0
  386. package/dist/event-journal-writer.d.ts +44 -0
  387. package/dist/event-journal-writer.d.ts.map +1 -0
  388. package/dist/event-journal-writer.js +182 -0
  389. package/dist/event-journal-writer.js.map +1 -0
  390. package/dist/event-outbox.d.ts +113 -0
  391. package/dist/event-outbox.d.ts.map +1 -0
  392. package/dist/event-outbox.js +707 -0
  393. package/dist/event-outbox.js.map +1 -0
  394. package/dist/execution-activity-tracker.d.ts +43 -0
  395. package/dist/execution-activity-tracker.d.ts.map +1 -0
  396. package/dist/execution-activity-tracker.js +116 -0
  397. package/dist/execution-activity-tracker.js.map +1 -0
  398. package/dist/execution-lease-client.d.ts +62 -0
  399. package/dist/execution-lease-client.d.ts.map +1 -0
  400. package/dist/execution-lease-client.js +271 -0
  401. package/dist/execution-lease-client.js.map +1 -0
  402. package/dist/fake-provider-cli.d.ts +13 -0
  403. package/dist/fake-provider-cli.d.ts.map +1 -0
  404. package/dist/fake-provider-cli.js +53 -0
  405. package/dist/fake-provider-cli.js.map +1 -0
  406. package/dist/generated-images.d.ts +2 -0
  407. package/dist/generated-images.d.ts.map +1 -0
  408. package/dist/generated-images.js +2 -0
  409. package/dist/generated-images.js.map +1 -0
  410. package/dist/index.cjs +47033 -45514
  411. package/dist/index.d.ts +2 -0
  412. package/dist/index.d.ts.map +1 -0
  413. package/dist/index.js +224 -0
  414. package/dist/index.js.map +1 -0
  415. package/dist/install-command.d.ts +2 -0
  416. package/dist/install-command.d.ts.map +1 -0
  417. package/dist/install-command.js +96 -0
  418. package/dist/install-command.js.map +1 -0
  419. package/dist/integration-cli.d.ts +14 -0
  420. package/dist/integration-cli.d.ts.map +1 -0
  421. package/dist/integration-cli.js +80 -0
  422. package/dist/integration-cli.js.map +1 -0
  423. package/dist/lifecycle-logger.d.ts +25 -0
  424. package/dist/lifecycle-logger.d.ts.map +1 -0
  425. package/dist/lifecycle-logger.js +73 -0
  426. package/dist/lifecycle-logger.js.map +1 -0
  427. package/dist/local-daemon-lifecycle.d.ts +112 -0
  428. package/dist/local-daemon-lifecycle.d.ts.map +1 -0
  429. package/dist/local-daemon-lifecycle.js +433 -0
  430. package/dist/local-daemon-lifecycle.js.map +1 -0
  431. package/dist/local-git-status.d.ts +14 -0
  432. package/dist/local-git-status.d.ts.map +1 -0
  433. package/dist/local-git-status.js +43 -0
  434. package/dist/local-git-status.js.map +1 -0
  435. package/dist/managed-mcp.d.ts +7 -0
  436. package/dist/managed-mcp.d.ts.map +1 -0
  437. package/dist/managed-mcp.js +16 -0
  438. package/dist/managed-mcp.js.map +1 -0
  439. package/dist/mcp-config-adapters.d.ts +57 -0
  440. package/dist/mcp-config-adapters.d.ts.map +1 -0
  441. package/dist/mcp-config-adapters.js +929 -0
  442. package/dist/mcp-config-adapters.js.map +1 -0
  443. package/dist/mcp-sync.d.ts +44 -0
  444. package/dist/mcp-sync.d.ts.map +1 -0
  445. package/dist/mcp-sync.js +68 -0
  446. package/dist/mcp-sync.js.map +1 -0
  447. package/dist/model-scan-runner.d.ts +15 -0
  448. package/dist/model-scan-runner.d.ts.map +1 -0
  449. package/dist/model-scan-runner.js +56 -0
  450. package/dist/model-scan-runner.js.map +1 -0
  451. package/dist/native-hook-command.d.ts +31 -0
  452. package/dist/native-hook-command.d.ts.map +1 -0
  453. package/dist/native-hook-command.js +289 -0
  454. package/dist/native-hook-command.js.map +1 -0
  455. package/dist/native-hook-config.d.ts +43 -0
  456. package/dist/native-hook-config.d.ts.map +1 -0
  457. package/dist/native-hook-config.js +601 -0
  458. package/dist/native-hook-config.js.map +1 -0
  459. package/dist/native-hook-drain.d.ts +34 -0
  460. package/dist/native-hook-drain.d.ts.map +1 -0
  461. package/dist/native-hook-drain.js +83 -0
  462. package/dist/native-hook-drain.js.map +1 -0
  463. package/dist/native-hook-inbox.d.ts +40 -0
  464. package/dist/native-hook-inbox.d.ts.map +1 -0
  465. package/dist/native-hook-inbox.js +217 -0
  466. package/dist/native-hook-inbox.js.map +1 -0
  467. package/dist/native-project-config.d.ts +11 -0
  468. package/dist/native-project-config.d.ts.map +1 -0
  469. package/dist/native-project-config.js +49 -0
  470. package/dist/native-project-config.js.map +1 -0
  471. package/dist/native-session.d.ts +20 -0
  472. package/dist/native-session.d.ts.map +1 -0
  473. package/dist/native-session.js +213 -0
  474. package/dist/native-session.js.map +1 -0
  475. package/dist/native-stream-journal.d.ts +22 -0
  476. package/dist/native-stream-journal.d.ts.map +1 -0
  477. package/dist/native-stream-journal.js +98 -0
  478. package/dist/native-stream-journal.js.map +1 -0
  479. package/dist/native-stream-outbox.d.ts +40 -0
  480. package/dist/native-stream-outbox.d.ts.map +1 -0
  481. package/dist/native-stream-outbox.js +358 -0
  482. package/dist/native-stream-outbox.js.map +1 -0
  483. package/dist/native-stream-platform.d.ts +4 -0
  484. package/dist/native-stream-platform.d.ts.map +1 -0
  485. package/dist/native-stream-platform.js +11 -0
  486. package/dist/native-stream-platform.js.map +1 -0
  487. package/dist/native-transcript-cursor.d.ts +33 -0
  488. package/dist/native-transcript-cursor.d.ts.map +1 -0
  489. package/dist/native-transcript-cursor.js +108 -0
  490. package/dist/native-transcript-cursor.js.map +1 -0
  491. package/dist/native-transcript-stream.d.ts +20 -0
  492. package/dist/native-transcript-stream.d.ts.map +1 -0
  493. package/dist/native-transcript-stream.js +438 -0
  494. package/dist/native-transcript-stream.js.map +1 -0
  495. package/dist/network-diagnostics.d.ts +8 -0
  496. package/dist/network-diagnostics.d.ts.map +1 -0
  497. package/dist/network-diagnostics.js +56 -0
  498. package/dist/network-diagnostics.js.map +1 -0
  499. package/dist/observable-map.d.ts +13 -0
  500. package/dist/observable-map.d.ts.map +1 -0
  501. package/dist/observable-map.js +30 -0
  502. package/dist/observable-map.js.map +1 -0
  503. package/dist/provider-auth-preflight.d.ts +19 -0
  504. package/dist/provider-auth-preflight.d.ts.map +1 -0
  505. package/dist/provider-auth-preflight.js +107 -0
  506. package/dist/provider-auth-preflight.js.map +1 -0
  507. package/dist/provider-model-discovery.d.ts +33 -0
  508. package/dist/provider-model-discovery.d.ts.map +1 -0
  509. package/dist/provider-model-discovery.js +731 -0
  510. package/dist/provider-model-discovery.js.map +1 -0
  511. package/dist/resource-diagnostics.d.ts +21 -0
  512. package/dist/resource-diagnostics.d.ts.map +1 -0
  513. package/dist/resource-diagnostics.js +161 -0
  514. package/dist/resource-diagnostics.js.map +1 -0
  515. package/dist/resume-fallback-env.d.ts +3 -0
  516. package/dist/resume-fallback-env.d.ts.map +1 -0
  517. package/dist/resume-fallback-env.js +14 -0
  518. package/dist/resume-fallback-env.js.map +1 -0
  519. package/dist/run-journal.d.ts +51 -0
  520. package/dist/run-journal.d.ts.map +1 -0
  521. package/dist/run-journal.js +193 -0
  522. package/dist/run-journal.js.map +1 -0
  523. package/dist/runtime-backends.d.ts +2 -0
  524. package/dist/runtime-backends.d.ts.map +1 -0
  525. package/dist/runtime-backends.js +2 -0
  526. package/dist/runtime-backends.js.map +1 -0
  527. package/dist/runtime-capabilities-sync.d.ts +40 -0
  528. package/dist/runtime-capabilities-sync.d.ts.map +1 -0
  529. package/dist/runtime-capabilities-sync.js +56 -0
  530. package/dist/runtime-capabilities-sync.js.map +1 -0
  531. package/dist/runtime-config.d.ts +26 -0
  532. package/dist/runtime-config.d.ts.map +1 -0
  533. package/dist/runtime-config.js +170 -0
  534. package/dist/runtime-config.js.map +1 -0
  535. package/dist/runtime-presenter.d.ts +81 -0
  536. package/dist/runtime-presenter.d.ts.map +1 -0
  537. package/dist/runtime-presenter.js +422 -0
  538. package/dist/runtime-presenter.js.map +1 -0
  539. package/dist/runtime-registration.d.ts +40 -0
  540. package/dist/runtime-registration.d.ts.map +1 -0
  541. package/dist/runtime-registration.js +143 -0
  542. package/dist/runtime-registration.js.map +1 -0
  543. package/dist/sandbox-outbox-storage.d.ts +13 -0
  544. package/dist/sandbox-outbox-storage.d.ts.map +1 -0
  545. package/dist/sandbox-outbox-storage.js +98 -0
  546. package/dist/sandbox-outbox-storage.js.map +1 -0
  547. package/dist/sandbox-outbox.d.ts +115 -0
  548. package/dist/sandbox-outbox.d.ts.map +1 -0
  549. package/dist/sandbox-outbox.js +213 -0
  550. package/dist/sandbox-outbox.js.map +1 -0
  551. package/dist/sandbox.d.ts +34 -0
  552. package/dist/sandbox.d.ts.map +1 -0
  553. package/dist/sandbox.js +469 -0
  554. package/dist/sandbox.js.map +1 -0
  555. package/dist/service-manager.d.ts +113 -0
  556. package/dist/service-manager.d.ts.map +1 -0
  557. package/dist/service-manager.js +1065 -0
  558. package/dist/service-manager.js.map +1 -0
  559. package/dist/skills/__tests__/local-skill-source.test.d.ts +2 -0
  560. package/dist/skills/__tests__/local-skill-source.test.d.ts.map +1 -0
  561. package/dist/skills/__tests__/local-skill-source.test.js +373 -0
  562. package/dist/skills/__tests__/local-skill-source.test.js.map +1 -0
  563. package/dist/skills/__tests__/managed-skill-store.test.d.ts +2 -0
  564. package/dist/skills/__tests__/managed-skill-store.test.d.ts.map +1 -0
  565. package/dist/skills/__tests__/managed-skill-store.test.js +114 -0
  566. package/dist/skills/__tests__/managed-skill-store.test.js.map +1 -0
  567. package/dist/skills/__tests__/runtime-skill-coordinator.test.d.ts +2 -0
  568. package/dist/skills/__tests__/runtime-skill-coordinator.test.d.ts.map +1 -0
  569. package/dist/skills/__tests__/runtime-skill-coordinator.test.js +251 -0
  570. package/dist/skills/__tests__/runtime-skill-coordinator.test.js.map +1 -0
  571. package/dist/skills/__tests__/runtime-skill-manager.test.d.ts +2 -0
  572. package/dist/skills/__tests__/runtime-skill-manager.test.d.ts.map +1 -0
  573. package/dist/skills/__tests__/runtime-skill-manager.test.js +664 -0
  574. package/dist/skills/__tests__/runtime-skill-manager.test.js.map +1 -0
  575. package/dist/skills/__tests__/skill-bundle.test.d.ts +2 -0
  576. package/dist/skills/__tests__/skill-bundle.test.d.ts.map +1 -0
  577. package/dist/skills/__tests__/skill-bundle.test.js +42 -0
  578. package/dist/skills/__tests__/skill-bundle.test.js.map +1 -0
  579. package/dist/skills/__tests__/skill-control-client.test.d.ts +2 -0
  580. package/dist/skills/__tests__/skill-control-client.test.d.ts.map +1 -0
  581. package/dist/skills/__tests__/skill-control-client.test.js +49 -0
  582. package/dist/skills/__tests__/skill-control-client.test.js.map +1 -0
  583. package/dist/skills/__tests__/skill-source-config.test.d.ts +2 -0
  584. package/dist/skills/__tests__/skill-source-config.test.d.ts.map +1 -0
  585. package/dist/skills/__tests__/skill-source-config.test.js +295 -0
  586. package/dist/skills/__tests__/skill-source-config.test.js.map +1 -0
  587. package/dist/skills/local-skill-source.d.ts +77 -0
  588. package/dist/skills/local-skill-source.d.ts.map +1 -0
  589. package/dist/skills/local-skill-source.js +660 -0
  590. package/dist/skills/local-skill-source.js.map +1 -0
  591. package/dist/skills/managed-skill-store.d.ts +44 -0
  592. package/dist/skills/managed-skill-store.d.ts.map +1 -0
  593. package/dist/skills/managed-skill-store.js +160 -0
  594. package/dist/skills/managed-skill-store.js.map +1 -0
  595. package/dist/skills/runtime-skill-coordinator.d.ts +35 -0
  596. package/dist/skills/runtime-skill-coordinator.d.ts.map +1 -0
  597. package/dist/skills/runtime-skill-coordinator.js +166 -0
  598. package/dist/skills/runtime-skill-coordinator.js.map +1 -0
  599. package/dist/skills/runtime-skill-manager.d.ts +89 -0
  600. package/dist/skills/runtime-skill-manager.d.ts.map +1 -0
  601. package/dist/skills/runtime-skill-manager.js +934 -0
  602. package/dist/skills/runtime-skill-manager.js.map +1 -0
  603. package/dist/skills/skill-bundle.d.ts +2 -0
  604. package/dist/skills/skill-bundle.d.ts.map +1 -0
  605. package/dist/skills/skill-bundle.js +2 -0
  606. package/dist/skills/skill-bundle.js.map +1 -0
  607. package/dist/skills/skill-cli.d.ts +2 -0
  608. package/dist/skills/skill-cli.d.ts.map +1 -0
  609. package/dist/skills/skill-cli.js +81 -0
  610. package/dist/skills/skill-cli.js.map +1 -0
  611. package/dist/skills/skill-control-client.d.ts +20 -0
  612. package/dist/skills/skill-control-client.d.ts.map +1 -0
  613. package/dist/skills/skill-control-client.js +56 -0
  614. package/dist/skills/skill-control-client.js.map +1 -0
  615. package/dist/skills/skill-invocation.d.ts +10 -0
  616. package/dist/skills/skill-invocation.d.ts.map +1 -0
  617. package/dist/skills/skill-invocation.js +24 -0
  618. package/dist/skills/skill-invocation.js.map +1 -0
  619. package/dist/sleep-inhibitor.d.ts +32 -0
  620. package/dist/sleep-inhibitor.d.ts.map +1 -0
  621. package/dist/sleep-inhibitor.js +297 -0
  622. package/dist/sleep-inhibitor.js.map +1 -0
  623. package/dist/suspension-detector.d.ts +24 -0
  624. package/dist/suspension-detector.d.ts.map +1 -0
  625. package/dist/suspension-detector.js +59 -0
  626. package/dist/suspension-detector.js.map +1 -0
  627. package/dist/types.d.ts +2 -0
  628. package/dist/types.d.ts.map +1 -0
  629. package/dist/types.js +2 -0
  630. package/dist/types.js.map +1 -0
  631. package/dist/version.d.ts +2 -0
  632. package/dist/version.d.ts.map +1 -0
  633. package/dist/version.js +2 -0
  634. package/dist/version.js.map +1 -0
  635. package/dist/web-presenter.d.ts +52 -0
  636. package/dist/web-presenter.d.ts.map +1 -0
  637. package/dist/web-presenter.js +264 -0
  638. package/dist/web-presenter.js.map +1 -0
  639. package/dist/workspace-relocation.d.ts +22 -0
  640. package/dist/workspace-relocation.d.ts.map +1 -0
  641. package/dist/workspace-relocation.js +90 -0
  642. package/dist/workspace-relocation.js.map +1 -0
  643. package/dist/workspace-rpc.d.ts +2 -0
  644. package/dist/workspace-rpc.d.ts.map +1 -0
  645. package/dist/workspace-rpc.js +15 -0
  646. package/dist/workspace-rpc.js.map +1 -0
  647. package/dist/workspace-run-lease.d.ts +116 -0
  648. package/dist/workspace-run-lease.d.ts.map +1 -0
  649. package/dist/workspace-run-lease.js +320 -0
  650. package/dist/workspace-run-lease.js.map +1 -0
  651. package/dist/ws-client.d.ts +168 -0
  652. package/dist/ws-client.d.ts.map +1 -0
  653. package/dist/ws-client.js +440 -0
  654. package/dist/ws-client.js.map +1 -0
  655. package/package.json +4 -3
@@ -0,0 +1,664 @@
1
+ import { createHash } from "node:crypto";
2
+ import { lstat, mkdir, mkdtemp, readdir, readFile, readlink, realpath, rm, writeFile, } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { inspectSkillPackage } from "@alan-ai/shared/node/skill-package";
6
+ import { afterEach, describe, expect, it, vi } from "vitest";
7
+ import { RuntimeSkillManager } from "../runtime-skill-manager.js";
8
+ import { createSkillBundle } from "../skill-bundle.js";
9
+ const temporaryDirectories = [];
10
+ async function createTemporaryDirectory() {
11
+ const directory = await mkdtemp(join(tmpdir(), "alan-runtime-skills-"));
12
+ temporaryDirectories.push(directory);
13
+ return directory;
14
+ }
15
+ afterEach(async () => {
16
+ await Promise.all(temporaryDirectories
17
+ .splice(0)
18
+ .map((directory) => rm(directory, { recursive: true, force: true })));
19
+ });
20
+ describe("RuntimeSkillManager", () => {
21
+ it("adopts only an exact manifest-owned legacy Skill and retires the old inventory", async () => {
22
+ const homeDirectory = await createTemporaryDirectory();
23
+ const legacyAgents = join(homeDirectory, ".agents", "skills", "review-pr");
24
+ const legacyClaude = join(homeDirectory, ".claude", "skills", "review-pr");
25
+ const content = "---\nname: review-pr\ndescription: Review this pull request.\n---\nReview carefully.\n";
26
+ await mkdir(join(homeDirectory, ".alan"), { recursive: true });
27
+ await mkdir(legacyAgents, { recursive: true });
28
+ await mkdir(legacyClaude, { recursive: true });
29
+ await writeFile(join(legacyAgents, "SKILL.md"), content);
30
+ await writeFile(join(legacyClaude, "SKILL.md"), content);
31
+ const legacyHash = createHash("sha256").update(content).digest("hex").slice(0, 16);
32
+ await writeFile(join(homeDirectory, ".alan", "sync-manifest.json"), JSON.stringify({ skills: { "review-pr": { hash: legacyHash } } }));
33
+ const bundle = await createSkillBundle(legacyAgents);
34
+ const downloadBundle = vi.fn(async () => bundle.bytes);
35
+ const manager = await RuntimeSkillManager.open({ homeDirectory, downloadBundle });
36
+ const manifest = desiredManifest(bundle, "review-pr", "review-pr--skill1", "9");
37
+ const result = await manager.reconcile({ manifest });
38
+ expect(result.skills[0]?.state).toBe("applied");
39
+ expect(downloadBundle).not.toHaveBeenCalled();
40
+ expect(JSON.parse(await readFile(join(homeDirectory, ".agents", "skills", "review-pr--skill1", ".alan-managed.json"), "utf8"))).toMatchObject({ skillId: manifest.skills[0]?.skillId });
41
+ await expect(lstat(legacyAgents)).rejects.toMatchObject({ code: "ENOENT" });
42
+ expect((await lstat(join(homeDirectory, ".claude", "skills", "review-pr--skill1"))).isSymbolicLink()).toBe(true);
43
+ await expect(lstat(join(homeDirectory, ".alan", "sync-manifest.json"))).rejects.toMatchObject({
44
+ code: "ENOENT",
45
+ });
46
+ });
47
+ it("preserves an edited legacy Skill and treats it as user-owned", async () => {
48
+ const homeDirectory = await createTemporaryDirectory();
49
+ const legacy = join(homeDirectory, ".agents", "skills", "review-pr");
50
+ await mkdir(join(homeDirectory, ".alan"), { recursive: true });
51
+ await mkdir(legacy, { recursive: true });
52
+ const original = "---\nname: review-pr\ndescription: Review this pull request.\n---\nOriginal.\n";
53
+ await writeFile(join(legacy, "SKILL.md"), `${original}User edit.\n`);
54
+ await writeFile(join(homeDirectory, ".alan", "sync-manifest.json"), JSON.stringify({
55
+ skills: {
56
+ "review-pr": {
57
+ hash: createHash("sha256").update(original).digest("hex").slice(0, 16),
58
+ },
59
+ },
60
+ }));
61
+ const bundle = await createTestBundle("review-pr", "Review this pull request.");
62
+ const manager = await RuntimeSkillManager.open({
63
+ homeDirectory,
64
+ downloadBundle: async () => bundle.bytes,
65
+ });
66
+ await manager.reconcile({
67
+ manifest: desiredManifest(bundle, "review-pr", "review-pr--skill1", "8"),
68
+ });
69
+ expect(await readFile(join(legacy, "SKILL.md"), "utf8")).toContain("User edit");
70
+ });
71
+ it("publishes the exact complete package from the last complete discovery snapshot", async () => {
72
+ const homeDirectory = await createTemporaryDirectory();
73
+ const sourceRoot = join(homeDirectory, "editable-skills");
74
+ const source = join(sourceRoot, "release-notes");
75
+ await mkdir(join(source, "references"), { recursive: true });
76
+ await writeFile(join(source, "SKILL.md"), "---\nname: release-notes\ndescription: Prepare release notes.\n---\nRead references/format.md.\n");
77
+ await writeFile(join(source, "references", "format.md"), "# Required format\n");
78
+ const expectedBundle = await createSkillBundle(source);
79
+ const uploadedChunks = [];
80
+ const controlClient = {
81
+ sync: vi.fn(),
82
+ uploadPreparedBundle: vi.fn(async (_grant, bytes) => {
83
+ uploadedChunks.push(Buffer.from(bytes));
84
+ }),
85
+ };
86
+ const downloadBundle = vi.fn(async () => expectedBundle.bytes);
87
+ const manager = await RuntimeSkillManager.open({
88
+ homeDirectory,
89
+ controlClient,
90
+ downloadBundle,
91
+ });
92
+ const scan = await manager.scan({
93
+ mode: "audit",
94
+ reason: "before_publish",
95
+ roots: [
96
+ {
97
+ kind: "configured",
98
+ declarationId: "source-1",
99
+ path: sourceRoot,
100
+ label: "Editable Skills",
101
+ precedence: 0,
102
+ },
103
+ ],
104
+ });
105
+ expect(scan.status).toBe("complete");
106
+ if (scan.status !== "complete")
107
+ throw new Error("expected complete scan");
108
+ const candidate = scan.candidates[0];
109
+ const localPreview = await manager.inspectLocalPackage({
110
+ localKey: candidate.localKey,
111
+ expectedContentHash: candidate.contentHash,
112
+ });
113
+ expect(localPreview.package.files.map((file) => file.path)).toEqual([
114
+ "SKILL.md",
115
+ "references/format.md",
116
+ ]);
117
+ await expect(manager.readLocalPackageFile({
118
+ localKey: candidate.localKey,
119
+ expectedContentHash: candidate.contentHash,
120
+ expectedFileHash: localPreview.package.files[1].sha256,
121
+ path: "references/format.md",
122
+ })).resolves.toMatchObject({ encoding: "utf8", content: "# Required format\n" });
123
+ expect(controlClient.uploadPreparedBundle).not.toHaveBeenCalled();
124
+ const published = await manager.publish({
125
+ commandId: "44444444-4444-4444-8444-444444444444",
126
+ previewId: "55555555-5555-4555-8555-555555555555",
127
+ localKey: candidate.localKey,
128
+ expectedContentHash: candidate.contentHash,
129
+ uploadGrant: {
130
+ method: "PUT",
131
+ url: "https://runtime.invalid/signed-upload",
132
+ headers: { "content-type": "application/gzip" },
133
+ expiresAt: "2099-01-01T00:00:00.000Z",
134
+ maxBytes: 10 * 1024 * 1024,
135
+ },
136
+ });
137
+ expect(published).toMatchObject({
138
+ state: "uploaded",
139
+ contentHash: expectedBundle.contentHash,
140
+ archiveHash: expectedBundle.archiveHash,
141
+ compressedBytes: expectedBundle.bytes.byteLength,
142
+ });
143
+ expect(Buffer.concat(uploadedChunks)).toEqual(expectedBundle.bytes);
144
+ const manifest = desiredManifest(expectedBundle, "release-notes", "release-notes--skill1", "7");
145
+ const reconciled = await manager.reconcile({ manifest });
146
+ expect(reconciled.skills[0]?.state).toBe("applied");
147
+ expect(downloadBundle).toHaveBeenCalledOnce();
148
+ expect(await readFile(join(homeDirectory, ".agents", "skills", "release-notes--skill1", "SKILL.md"), "utf8")).toContain("Read references/format.md");
149
+ });
150
+ it("downloads, verifies, caches, and atomically projects an exact complete Skill Version", async () => {
151
+ const homeDirectory = await createTemporaryDirectory();
152
+ const sourceParent = await createTemporaryDirectory();
153
+ const source = join(sourceParent, "release-notes");
154
+ await mkdir(join(source, "scripts"), { recursive: true });
155
+ await writeFile(join(source, "SKILL.md"), "---\nname: release-notes\ndescription: Prepare release notes.\n---\nRun scripts/collect.sh.\n");
156
+ await writeFile(join(source, "scripts", "collect.sh"), "#!/bin/sh\necho collect\n", {
157
+ mode: 0o755,
158
+ });
159
+ const bundle = await createSkillBundle(source);
160
+ const downloadBundle = vi.fn(async () => bundle.bytes);
161
+ const manager = await RuntimeSkillManager.open({ homeDirectory, downloadBundle });
162
+ const manifest = {
163
+ protocolVersion: 1,
164
+ revision: `sha256:${"a".repeat(64)}`,
165
+ skills: [
166
+ {
167
+ skillId: "11111111-1111-4111-8111-111111111111",
168
+ versionId: "22222222-2222-4222-8222-222222222222",
169
+ slug: "release-notes",
170
+ runtimeDirectory: "release-notes--skill1",
171
+ contentHash: bundle.contentHash,
172
+ archiveHash: bundle.archiveHash,
173
+ compressedBytes: bundle.bytes.byteLength,
174
+ downloadUrl: "https://runtime.invalid/signed-bundle",
175
+ downloadUrlExpiresAt: "2099-01-01T00:00:00.000Z",
176
+ },
177
+ ],
178
+ };
179
+ const first = await manager.reconcile({ manifest });
180
+ const projected = join(homeDirectory, ".agents", "skills", "release-notes--skill1");
181
+ expect(first.skills).toEqual([
182
+ expect.objectContaining({
183
+ skillId: "11111111-1111-4111-8111-111111111111",
184
+ versionId: "22222222-2222-4222-8222-222222222222",
185
+ contentHash: bundle.contentHash,
186
+ observedHash: bundle.contentHash,
187
+ state: "applied",
188
+ }),
189
+ ]);
190
+ expect(await readFile(join(projected, "scripts", "collect.sh"), "utf8")).toContain("echo collect");
191
+ expect(JSON.parse(await readFile(join(projected, ".alan-managed.json"), "utf8"))).toEqual({
192
+ protocolVersion: 1,
193
+ skillId: "11111111-1111-4111-8111-111111111111",
194
+ versionId: "22222222-2222-4222-8222-222222222222",
195
+ contentHash: bundle.contentHash,
196
+ });
197
+ expect((await inspectSkillPackage(projected, { expectedName: null })).contentHash).toBe(bundle.contentHash);
198
+ const compatibility = join(homeDirectory, ".claude", "skills", "release-notes--skill1");
199
+ expect((await lstat(compatibility)).isSymbolicLink()).toBe(true);
200
+ expect(await readlink(compatibility)).toBe(projected);
201
+ const second = await manager.reconcile({ manifest });
202
+ expect(second.skills[0]?.state).toBe("applied");
203
+ expect(downloadBundle).toHaveBeenCalledTimes(1);
204
+ expect((await manager.inspect()).appliedRevision).toBe(manifest.revision);
205
+ });
206
+ it("resolves an invocation by immutable identity and rejects a same-name different Version", async () => {
207
+ const homeDirectory = await createTemporaryDirectory();
208
+ const bundle = await createTestBundle("review-pr", "Review this pull request.");
209
+ const manifest = desiredManifest(bundle, "review-pr", "review-pr--skill1", "a");
210
+ const manager = await RuntimeSkillManager.open({
211
+ homeDirectory,
212
+ downloadBundle: async () => bundle.bytes,
213
+ });
214
+ await manager.reconcile({ manifest });
215
+ const installed = manifest.skills[0];
216
+ await expect(manager.resolveInvocation("runtime-1", {
217
+ kind: "skill_version",
218
+ skillId: installed.skillId,
219
+ versionId: installed.versionId,
220
+ displayName: "Review PR",
221
+ })).resolves.toMatchObject({
222
+ packageDirectory: join(homeDirectory, ".agents", "skills", "review-pr--skill1"),
223
+ });
224
+ await expect(manager.resolveInvocation("runtime-1", {
225
+ kind: "skill_version",
226
+ skillId: installed.skillId,
227
+ versionId: "33333333-3333-4333-8333-333333333333",
228
+ displayName: "Review PR",
229
+ })).rejects.toThrow("not installed");
230
+ });
231
+ it("keeps production and staging projections isolated for the same runtime directory", async () => {
232
+ const homeDirectory = await createTemporaryDirectory();
233
+ const productionBundle = await createTestBundle("review-pr", "Production instructions.");
234
+ const stagingBundle = await createTestBundle("review-pr", "Staging instructions.");
235
+ const productionManifest = desiredManifest(productionBundle, "review-pr", "review-pr--skill1", "1");
236
+ const stagingManifest = {
237
+ ...desiredManifest(stagingBundle, "review-pr", "review-pr--skill1", "2"),
238
+ skills: [
239
+ {
240
+ ...desiredManifest(stagingBundle, "review-pr", "review-pr--skill1", "2").skills[0],
241
+ versionId: "33333333-3333-4333-8333-333333333333",
242
+ },
243
+ ],
244
+ };
245
+ const downloadBundle = vi.fn(async (entry) => entry.versionId === productionManifest.skills[0].versionId
246
+ ? productionBundle.bytes
247
+ : stagingBundle.bytes);
248
+ const productionManager = await RuntimeSkillManager.open({
249
+ homeDirectory,
250
+ downloadBundle,
251
+ endpointProfile: "production",
252
+ });
253
+ await productionManager.reconcile({ manifest: productionManifest });
254
+ const stagingManager = await RuntimeSkillManager.open({
255
+ homeDirectory,
256
+ downloadBundle,
257
+ endpointProfile: "staging",
258
+ });
259
+ await stagingManager.reconcile({ manifest: stagingManifest });
260
+ expect(JSON.parse(await readFile(join(homeDirectory, ".alan", "skills", "profiles", "production", "state.json"), "utf8"))).toMatchObject({ appliedRevision: productionManifest.revision });
261
+ expect(JSON.parse(await readFile(join(homeDirectory, ".alan", "skills", "profiles", "staging", "state.json"), "utf8"))).toMatchObject({ appliedRevision: stagingManifest.revision });
262
+ await expect(productionManager.resolveInvocation("runtime-production", {
263
+ kind: "skill_version",
264
+ skillId: productionManifest.skills[0].skillId,
265
+ versionId: productionManifest.skills[0].versionId,
266
+ displayName: "Review PR",
267
+ })).resolves.toMatchObject({
268
+ packageDirectory: join(homeDirectory, ".agents", "skills", "review-pr--skill1--alan-production"),
269
+ });
270
+ await expect(stagingManager.resolveInvocation("runtime-staging", {
271
+ kind: "skill_version",
272
+ skillId: stagingManifest.skills[0].skillId,
273
+ versionId: stagingManifest.skills[0].versionId,
274
+ displayName: "Review PR",
275
+ })).resolves.toMatchObject({
276
+ packageDirectory: join(homeDirectory, ".agents", "skills", "review-pr--skill1--alan-staging"),
277
+ });
278
+ });
279
+ it("isolates custom runtimes by their stable config identity", async () => {
280
+ const homeDirectory = await createTemporaryDirectory();
281
+ const firstBundle = await createTestBundle("review-pr", "First custom runtime.");
282
+ const secondBundle = await createTestBundle("review-pr", "Second custom runtime.");
283
+ const firstManifest = desiredManifest(firstBundle, "review-pr", "review-pr--skill1", "3");
284
+ const secondManifest = {
285
+ ...desiredManifest(secondBundle, "review-pr", "review-pr--skill1", "4"),
286
+ skills: [
287
+ {
288
+ ...desiredManifest(secondBundle, "review-pr", "review-pr--skill1", "4").skills[0],
289
+ versionId: "33333333-3333-4333-8333-333333333333",
290
+ },
291
+ ],
292
+ };
293
+ const firstIdentity = join(homeDirectory, "configs", "first.json");
294
+ const secondIdentity = join(homeDirectory, "configs", "second.json");
295
+ const firstManager = await RuntimeSkillManager.open({
296
+ homeDirectory,
297
+ endpointProfile: "custom",
298
+ profileStorageIdentity: firstIdentity,
299
+ downloadBundle: async () => firstBundle.bytes,
300
+ });
301
+ const secondManager = await RuntimeSkillManager.open({
302
+ homeDirectory,
303
+ endpointProfile: "custom",
304
+ profileStorageIdentity: secondIdentity,
305
+ downloadBundle: async () => secondBundle.bytes,
306
+ });
307
+ await firstManager.reconcile({ manifest: firstManifest });
308
+ await secondManager.reconcile({ manifest: secondManifest });
309
+ const firstNamespace = `custom-${createHash("sha256").update(firstIdentity).digest("hex").slice(0, 12)}`;
310
+ const secondNamespace = `custom-${createHash("sha256").update(secondIdentity).digest("hex").slice(0, 12)}`;
311
+ await expect(firstManager.resolveInvocation("runtime-first", {
312
+ kind: "skill_version",
313
+ skillId: firstManifest.skills[0].skillId,
314
+ versionId: firstManifest.skills[0].versionId,
315
+ displayName: "Review PR",
316
+ })).resolves.toMatchObject({
317
+ packageDirectory: join(homeDirectory, ".agents", "skills", `review-pr--skill1--alan-${firstNamespace}`),
318
+ });
319
+ await expect(secondManager.resolveInvocation("runtime-second", {
320
+ kind: "skill_version",
321
+ skillId: secondManifest.skills[0].skillId,
322
+ versionId: secondManifest.skills[0].versionId,
323
+ displayName: "Review PR",
324
+ })).resolves.toMatchObject({
325
+ packageDirectory: join(homeDirectory, ".agents", "skills", `review-pr--skill1--alan-${secondNamespace}`),
326
+ });
327
+ });
328
+ it("preserves an exact unscoped projection while rebuilding scoped state", async () => {
329
+ const homeDirectory = await createTemporaryDirectory();
330
+ const sourceRoot = join(homeDirectory, "editable-skills");
331
+ const source = join(sourceRoot, "local-review");
332
+ await mkdir(source, { recursive: true });
333
+ await writeFile(join(source, "SKILL.md"), "---\nname: local-review\ndescription: Local review instructions.\n---\nReview locally.\n");
334
+ const bundle = await createTestBundle("review-pr", "Managed instructions.");
335
+ const manifest = desiredManifest(bundle, "review-pr", "review-pr--skill1", "5");
336
+ const scanInput = {
337
+ mode: "audit",
338
+ reason: "startup",
339
+ roots: [
340
+ {
341
+ kind: "configured",
342
+ declarationId: "source-1",
343
+ path: sourceRoot,
344
+ label: "Editable Skills",
345
+ precedence: 0,
346
+ },
347
+ ],
348
+ };
349
+ const unscopedManager = await RuntimeSkillManager.open({
350
+ homeDirectory,
351
+ downloadBundle: async () => bundle.bytes,
352
+ });
353
+ const unscopedScan = await unscopedManager.scan(scanInput);
354
+ if (unscopedScan.status !== "complete")
355
+ throw new Error("expected complete unscoped scan");
356
+ await unscopedManager.reconcile({ manifest });
357
+ const localCandidate = unscopedScan.candidates[0];
358
+ const localRuntimeId = "44444444-4444-4444-8444-444444444444";
359
+ const scopedManager = await RuntimeSkillManager.open({
360
+ homeDirectory,
361
+ endpointProfile: "production",
362
+ downloadBundle: async () => bundle.bytes,
363
+ });
364
+ await expect(scopedManager.resolveInvocation(localRuntimeId, {
365
+ kind: "local_skill",
366
+ runtimeId: localRuntimeId,
367
+ localKey: localCandidate.localKey,
368
+ contentHash: localCandidate.contentHash,
369
+ displayName: localCandidate.name,
370
+ })).rejects.toThrow("last complete scan");
371
+ await scopedManager.reconcile({ manifest });
372
+ const scopedScan = await scopedManager.scan(scanInput);
373
+ if (scopedScan.status !== "complete")
374
+ throw new Error("expected complete scoped scan");
375
+ expect(await readFile(join(homeDirectory, ".agents", "skills", "review-pr--skill1", "SKILL.md"), "utf8")).toContain("Managed instructions.");
376
+ expect((await lstat(join(homeDirectory, ".claude", "skills", "review-pr--skill1"))).isSymbolicLink()).toBe(true);
377
+ await expect(scopedManager.resolveInvocation(localRuntimeId, {
378
+ kind: "local_skill",
379
+ runtimeId: localRuntimeId,
380
+ localKey: localCandidate.localKey,
381
+ contentHash: localCandidate.contentHash,
382
+ displayName: localCandidate.name,
383
+ })).resolves.toMatchObject({ packageDirectory: await realpath(source) });
384
+ await expect(scopedManager.resolveInvocation("runtime-production", {
385
+ kind: "skill_version",
386
+ skillId: manifest.skills[0].skillId,
387
+ versionId: manifest.skills[0].versionId,
388
+ displayName: "Review PR",
389
+ })).resolves.toMatchObject({
390
+ packageDirectory: join(homeDirectory, ".agents", "skills", "review-pr--skill1--alan-production"),
391
+ });
392
+ });
393
+ it("preserves a mismatched unscoped projection during scoped reconciliation", async () => {
394
+ const homeDirectory = await createTemporaryDirectory();
395
+ const unscopedBundle = await createTestBundle("review-pr", "Unscoped instructions.");
396
+ const scopedBundle = await createTestBundle("review-pr", "Scoped staging instructions.");
397
+ const unscopedManifest = desiredManifest(unscopedBundle, "review-pr", "review-pr--skill1", "6");
398
+ const scopedManifest = {
399
+ ...desiredManifest(scopedBundle, "review-pr", "review-pr--skill1", "7"),
400
+ skills: [
401
+ {
402
+ ...desiredManifest(scopedBundle, "review-pr", "review-pr--skill1", "7").skills[0],
403
+ versionId: "33333333-3333-4333-8333-333333333333",
404
+ },
405
+ ],
406
+ };
407
+ const unscopedManager = await RuntimeSkillManager.open({
408
+ homeDirectory,
409
+ downloadBundle: async () => unscopedBundle.bytes,
410
+ });
411
+ await unscopedManager.reconcile({ manifest: unscopedManifest });
412
+ const scopedManager = await RuntimeSkillManager.open({
413
+ homeDirectory,
414
+ endpointProfile: "staging",
415
+ downloadBundle: async () => scopedBundle.bytes,
416
+ });
417
+ await scopedManager.reconcile({ manifest: scopedManifest });
418
+ expect(await readFile(join(homeDirectory, ".agents", "skills", "review-pr--skill1", "SKILL.md"), "utf8")).toContain("Unscoped instructions.");
419
+ await expect(scopedManager.resolveInvocation("runtime-staging", {
420
+ kind: "skill_version",
421
+ skillId: scopedManifest.skills[0].skillId,
422
+ versionId: scopedManifest.skills[0].versionId,
423
+ displayName: "Review PR",
424
+ })).resolves.toMatchObject({
425
+ packageDirectory: join(homeDirectory, ".agents", "skills", "review-pr--skill1--alan-staging"),
426
+ });
427
+ });
428
+ it("restores a directly edited managed projection from the cloud bundle", async () => {
429
+ const homeDirectory = await createTemporaryDirectory();
430
+ const bundle = await createTestBundle("review-pr", "Review this pull request.");
431
+ const downloadBundle = vi.fn(async () => bundle.bytes);
432
+ const manifest = desiredManifest(bundle, "review-pr", "review-pr--skill1", "b");
433
+ const manager = await RuntimeSkillManager.open({ homeDirectory, downloadBundle });
434
+ await manager.reconcile({ manifest });
435
+ const projected = join(homeDirectory, ".agents", "skills", "review-pr--skill1", "SKILL.md");
436
+ await writeFile(projected, "---\nname: review-pr\ndescription: Changed directly.\n---\nLocal edit.\n");
437
+ const result = await manager.reconcile({ manifest });
438
+ expect(result.skills[0]?.state).toBe("applied");
439
+ expect(await readFile(projected, "utf8")).toContain("Review this pull request.");
440
+ expect(await readFile(projected, "utf8")).not.toContain("Local edit.");
441
+ expect(downloadBundle).toHaveBeenCalledTimes(1);
442
+ });
443
+ it("resolves local invocations only for the scanned runtime and exact observed hash", async () => {
444
+ const homeDirectory = await createTemporaryDirectory();
445
+ const sourceRoot = join(homeDirectory, "editable-skills");
446
+ const source = join(sourceRoot, "review-pr");
447
+ await mkdir(source, { recursive: true });
448
+ await writeFile(join(source, "SKILL.md"), "---\nname: review-pr\ndescription: Review a pull request.\n---\nReview carefully.\n");
449
+ const manager = await RuntimeSkillManager.open({ homeDirectory });
450
+ const scan = await manager.scan({
451
+ mode: "audit",
452
+ reason: "startup",
453
+ roots: [
454
+ {
455
+ kind: "configured",
456
+ declarationId: "source-1",
457
+ path: sourceRoot,
458
+ label: "Editable Skills",
459
+ precedence: 0,
460
+ },
461
+ ],
462
+ });
463
+ if (scan.status !== "complete")
464
+ throw new Error("expected complete scan");
465
+ const candidate = scan.candidates[0];
466
+ const runtimeId = "11111111-1111-4111-8111-111111111111";
467
+ await expect(manager.resolveInvocation(runtimeId, {
468
+ kind: "local_skill",
469
+ runtimeId,
470
+ localKey: candidate.localKey,
471
+ contentHash: candidate.contentHash,
472
+ displayName: candidate.name,
473
+ })).resolves.toMatchObject({ packageDirectory: await realpath(source) });
474
+ await writeFile(join(source, "SKILL.md"), "changed after selection\n");
475
+ await expect(manager.resolveInvocation(runtimeId, {
476
+ kind: "local_skill",
477
+ runtimeId,
478
+ localKey: candidate.localKey,
479
+ contentHash: candidate.contentHash,
480
+ displayName: candidate.name,
481
+ })).rejects.toThrow();
482
+ });
483
+ it("never overwrites an unmanaged destination", async () => {
484
+ const homeDirectory = await createTemporaryDirectory();
485
+ const bundle = await createTestBundle("review-pr", "Review this pull request.");
486
+ const destination = join(homeDirectory, ".agents", "skills", "review-pr--skill1");
487
+ await mkdir(destination, { recursive: true });
488
+ await writeFile(join(destination, "keep.txt"), "user owned\n");
489
+ const downloadBundle = vi.fn(async () => bundle.bytes);
490
+ const manager = await RuntimeSkillManager.open({ homeDirectory, downloadBundle });
491
+ const result = await manager.reconcile({
492
+ manifest: desiredManifest(bundle, "review-pr", "review-pr--skill1", "b"),
493
+ });
494
+ expect(result.skills[0]).toMatchObject({
495
+ state: "conflict",
496
+ errorCode: "UNMANAGED_PATH_CONFLICT",
497
+ });
498
+ expect(await readFile(join(destination, "keep.txt"), "utf8")).toBe("user owned\n");
499
+ expect(downloadBundle).not.toHaveBeenCalled();
500
+ });
501
+ it("renames the exact conflicting local Skill and immediately installs the managed Skill", async () => {
502
+ const homeDirectory = await createTemporaryDirectory();
503
+ const bundle = await createTestBundle("review-pr", "Managed instructions.");
504
+ const runtimeDirectory = "review-pr--skill1";
505
+ const destination = join(homeDirectory, ".agents", "skills", runtimeDirectory);
506
+ await mkdir(destination, { recursive: true });
507
+ await writeFile(join(destination, "SKILL.md"), "---\nname: review-pr\ndescription: Local instructions.\n---\nKeep this local package.\n");
508
+ const manager = await RuntimeSkillManager.open({
509
+ homeDirectory,
510
+ downloadBundle: async () => bundle.bytes,
511
+ });
512
+ const manifest = desiredManifest(bundle, "review-pr", runtimeDirectory, "4");
513
+ const reported = await manager.reconcile({ manifest });
514
+ const conflict = reported.skills[0]?.conflict;
515
+ if (!conflict)
516
+ throw new Error("expected a structured conflict");
517
+ const resolved = await manager.resolveConflict({
518
+ commandId: "00000000-0000-4000-8000-000000000001",
519
+ manifest,
520
+ skillId: manifest.skills[0].skillId,
521
+ versionId: manifest.skills[0].versionId,
522
+ expectedConflict: conflict,
523
+ resolution: { kind: "rename_local", name: "review-pr-local" },
524
+ });
525
+ expect(resolved.state).toBe("applied");
526
+ expect(await readFile(join(homeDirectory, ".agents", "skills", "review-pr-local", "SKILL.md"), "utf8")).toContain("name: review-pr-local");
527
+ expect(await readFile(join(destination, "SKILL.md"), "utf8")).toContain("Managed instructions.");
528
+ });
529
+ it("overwrites only the reported conflict and rolls directly into managed installation", async () => {
530
+ const homeDirectory = await createTemporaryDirectory();
531
+ const bundle = await createTestBundle("review-pr", "Managed replacement.");
532
+ const runtimeDirectory = "review-pr--skill1";
533
+ const destination = join(homeDirectory, ".agents", "skills", runtimeDirectory);
534
+ await mkdir(destination, { recursive: true });
535
+ await writeFile(join(destination, "SKILL.md"), "---\nname: review-pr\ndescription: Local instructions.\n---\nLocal version.\n");
536
+ const manager = await RuntimeSkillManager.open({
537
+ homeDirectory,
538
+ downloadBundle: async () => bundle.bytes,
539
+ });
540
+ const manifest = desiredManifest(bundle, "review-pr", runtimeDirectory, "5");
541
+ const reported = await manager.reconcile({ manifest });
542
+ const conflict = reported.skills[0]?.conflict;
543
+ if (!conflict)
544
+ throw new Error("expected a structured conflict");
545
+ const resolved = await manager.resolveConflict({
546
+ commandId: "00000000-0000-4000-8000-000000000002",
547
+ manifest,
548
+ skillId: manifest.skills[0].skillId,
549
+ versionId: manifest.skills[0].versionId,
550
+ expectedConflict: conflict,
551
+ resolution: { kind: "overwrite_local" },
552
+ });
553
+ expect(resolved.state).toBe("applied");
554
+ expect(await readFile(join(destination, "SKILL.md"), "utf8")).toContain("Managed replacement.");
555
+ expect((await readdir(join(homeDirectory, ".agents", "skills"))).filter((name) => name.includes("overwrite-backup"))).toEqual([]);
556
+ });
557
+ it("rejects a stale conflict resolution without mutating the changed local Skill", async () => {
558
+ const homeDirectory = await createTemporaryDirectory();
559
+ const bundle = await createTestBundle("review-pr", "Managed replacement.");
560
+ const runtimeDirectory = "review-pr--skill1";
561
+ const destination = join(homeDirectory, ".agents", "skills", runtimeDirectory);
562
+ await mkdir(destination, { recursive: true });
563
+ const localMarkdown = "---\nname: review-pr\ndescription: Local instructions.\n---\nLocal version.\n";
564
+ await writeFile(join(destination, "SKILL.md"), localMarkdown);
565
+ const manager = await RuntimeSkillManager.open({
566
+ homeDirectory,
567
+ downloadBundle: async () => bundle.bytes,
568
+ });
569
+ const manifest = desiredManifest(bundle, "review-pr", runtimeDirectory, "6");
570
+ const reported = await manager.reconcile({ manifest });
571
+ const conflict = reported.skills[0]?.conflict;
572
+ if (!conflict)
573
+ throw new Error("expected a structured conflict");
574
+ await writeFile(join(destination, "SKILL.md"), `${localMarkdown}Changed after report.\n`);
575
+ const resolved = await manager.resolveConflict({
576
+ commandId: "00000000-0000-4000-8000-000000000003",
577
+ manifest,
578
+ skillId: manifest.skills[0].skillId,
579
+ versionId: manifest.skills[0].versionId,
580
+ expectedConflict: conflict,
581
+ resolution: { kind: "overwrite_local" },
582
+ });
583
+ expect(resolved).toMatchObject({ state: "stale", errorCode: "SKILL_CONFLICT_STALE" });
584
+ expect(await readFile(join(destination, "SKILL.md"), "utf8")).toContain("Changed after report.");
585
+ });
586
+ it("keeps the last good projection and revision when an update bundle fails verification", async () => {
587
+ const homeDirectory = await createTemporaryDirectory();
588
+ const firstBundle = await createTestBundle("review-pr", "Review version one.");
589
+ const secondBundle = await createTestBundle("review-pr", "Review version two.");
590
+ const downloadBundle = vi
591
+ .fn()
592
+ .mockResolvedValueOnce(firstBundle.bytes)
593
+ .mockResolvedValueOnce(Buffer.from("not a bundle"));
594
+ const manager = await RuntimeSkillManager.open({ homeDirectory, downloadBundle });
595
+ const firstManifest = desiredManifest(firstBundle, "review-pr", "review-pr--skill1", "c");
596
+ await manager.reconcile({ manifest: firstManifest });
597
+ const projectedSkill = join(homeDirectory, ".agents", "skills", "review-pr--skill1", "SKILL.md");
598
+ const update = await manager.reconcile({
599
+ manifest: {
600
+ ...desiredManifest(secondBundle, "review-pr", "review-pr--skill1", "d"),
601
+ skills: [
602
+ {
603
+ ...desiredManifest(secondBundle, "review-pr", "review-pr--skill1", "d").skills[0],
604
+ versionId: "33333333-3333-4333-8333-333333333333",
605
+ },
606
+ ],
607
+ },
608
+ });
609
+ expect(update.skills[0]?.state).toBe("failed");
610
+ expect(await readFile(projectedSkill, "utf8")).toContain("Review version one.");
611
+ expect((await manager.inspect()).appliedRevision).toBe(firstManifest.revision);
612
+ });
613
+ it("removes only recorded managed projections when a Skill is no longer desired", async () => {
614
+ const homeDirectory = await createTemporaryDirectory();
615
+ const bundle = await createTestBundle("review-pr", "Review this pull request.");
616
+ const manager = await RuntimeSkillManager.open({
617
+ homeDirectory,
618
+ downloadBundle: async () => bundle.bytes,
619
+ });
620
+ await manager.reconcile({
621
+ manifest: desiredManifest(bundle, "review-pr", "review-pr--skill1", "e"),
622
+ });
623
+ const unmanaged = join(homeDirectory, ".agents", "skills", "my-own-skill");
624
+ await mkdir(unmanaged, { recursive: true });
625
+ await writeFile(join(unmanaged, "keep.txt"), "keep\n");
626
+ await manager.reconcile({
627
+ manifest: {
628
+ protocolVersion: 1,
629
+ revision: `sha256:${"f".repeat(64)}`,
630
+ skills: [],
631
+ },
632
+ });
633
+ await expect(readFile(join(homeDirectory, ".agents", "skills", "review-pr--skill1", "SKILL.md"))).rejects.toMatchObject({ code: "ENOENT" });
634
+ await expect(lstat(join(homeDirectory, ".claude", "skills", "review-pr--skill1"))).rejects.toMatchObject({ code: "ENOENT" });
635
+ expect(await readFile(join(unmanaged, "keep.txt"), "utf8")).toBe("keep\n");
636
+ });
637
+ });
638
+ async function createTestBundle(name, instructions) {
639
+ const sourceParent = await createTemporaryDirectory();
640
+ const source = join(sourceParent, name);
641
+ await mkdir(source, { recursive: true });
642
+ await writeFile(join(source, "SKILL.md"), `---\nname: ${name}\ndescription: Test ${name}.\n---\n${instructions}\n`);
643
+ return createSkillBundle(source);
644
+ }
645
+ function desiredManifest(bundle, slug, runtimeDirectory, revisionCharacter) {
646
+ return {
647
+ protocolVersion: 1,
648
+ revision: `sha256:${revisionCharacter.repeat(64)}`,
649
+ skills: [
650
+ {
651
+ skillId: "11111111-1111-4111-8111-111111111111",
652
+ versionId: "22222222-2222-4222-8222-222222222222",
653
+ slug,
654
+ runtimeDirectory,
655
+ contentHash: bundle.contentHash,
656
+ archiveHash: bundle.archiveHash,
657
+ compressedBytes: bundle.bytes.byteLength,
658
+ downloadUrl: "https://runtime.invalid/signed-bundle",
659
+ downloadUrlExpiresAt: "2099-01-01T00:00:00.000Z",
660
+ },
661
+ ],
662
+ };
663
+ }
664
+ //# sourceMappingURL=runtime-skill-manager.test.js.map