alchemy 2.0.0-beta.84 → 2.0.0-beta.85

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 (758) hide show
  1. package/THIRD_PARTY_LICENSES.md +2 -2
  2. package/bin/cli.js +14 -6
  3. package/bin/register-oxc.js +16 -12
  4. package/lib/AdoptPolicy.d.ts +73 -0
  5. package/lib/AdoptPolicy.d.ts.map +1 -1
  6. package/lib/AdoptPolicy.js +54 -0
  7. package/lib/AdoptPolicy.js.map +1 -1
  8. package/lib/Alchemist/AuthRegistry.d.ts +31 -0
  9. package/lib/Alchemist/AuthRegistry.d.ts.map +1 -0
  10. package/lib/Alchemist/AuthRegistry.js +95 -0
  11. package/lib/Alchemist/AuthRegistry.js.map +1 -0
  12. package/lib/Alchemist/Drift.d.ts +70 -0
  13. package/lib/Alchemist/Drift.d.ts.map +1 -0
  14. package/lib/Alchemist/Drift.js +54 -0
  15. package/lib/Alchemist/Drift.js.map +1 -0
  16. package/lib/Alchemist/Entrypoint.d.ts +27 -3
  17. package/lib/Alchemist/Entrypoint.d.ts.map +1 -1
  18. package/lib/Alchemist/Entrypoint.js +34 -3
  19. package/lib/Alchemist/Entrypoint.js.map +1 -1
  20. package/lib/Alchemist/Errors.d.ts +1 -1
  21. package/lib/Alchemist/Errors.d.ts.map +1 -1
  22. package/lib/Alchemist/Errors.js +1 -1
  23. package/lib/Alchemist/Errors.js.map +1 -1
  24. package/lib/Alchemist/Logs.d.ts +46 -0
  25. package/lib/Alchemist/Logs.d.ts.map +1 -0
  26. package/lib/Alchemist/{routes/logs.js → Logs.js} +21 -26
  27. package/lib/Alchemist/Logs.js.map +1 -0
  28. package/lib/Alchemist/Nuke.d.ts +69 -0
  29. package/lib/Alchemist/Nuke.d.ts.map +1 -0
  30. package/lib/Alchemist/Nuke.js +35 -0
  31. package/lib/Alchemist/Nuke.js.map +1 -0
  32. package/lib/Alchemist/Operations.d.ts +168 -0
  33. package/lib/Alchemist/Operations.d.ts.map +1 -0
  34. package/lib/Alchemist/Operations.js +165 -0
  35. package/lib/Alchemist/Operations.js.map +1 -0
  36. package/lib/Alchemist/Profile.d.ts +132 -0
  37. package/lib/Alchemist/Profile.d.ts.map +1 -0
  38. package/lib/Alchemist/{routes/profile.js → Profile.js} +20 -21
  39. package/lib/Alchemist/Profile.js.map +1 -0
  40. package/lib/Alchemist/{routes/provider.d.ts → Provider.d.ts} +4 -4
  41. package/lib/Alchemist/Provider.d.ts.map +1 -0
  42. package/lib/Alchemist/{routes/provider.js → Provider.js} +7 -6
  43. package/lib/Alchemist/Provider.js.map +1 -0
  44. package/lib/Alchemist/Runtime.d.ts +10 -6
  45. package/lib/Alchemist/Runtime.d.ts.map +1 -1
  46. package/lib/Alchemist/Runtime.js +38 -2
  47. package/lib/Alchemist/Runtime.js.map +1 -1
  48. package/lib/Alchemist/{routes/state.d.ts → State.d.ts} +36 -16
  49. package/lib/Alchemist/State.d.ts.map +1 -0
  50. package/lib/Alchemist/{routes/state.js → State.js} +50 -15
  51. package/lib/Alchemist/State.js.map +1 -0
  52. package/lib/Alchemist/index.d.ts +11 -10
  53. package/lib/Alchemist/index.d.ts.map +1 -1
  54. package/lib/Alchemist/index.js +10 -9
  55. package/lib/Alchemist/index.js.map +1 -1
  56. package/lib/Apply.d.ts +2 -8
  57. package/lib/Apply.d.ts.map +1 -1
  58. package/lib/Apply.js +364 -184
  59. package/lib/Apply.js.map +1 -1
  60. package/lib/Auth/AuthProvider.d.ts +24 -11
  61. package/lib/Auth/AuthProvider.d.ts.map +1 -1
  62. package/lib/Auth/AuthProvider.js +28 -12
  63. package/lib/Auth/AuthProvider.js.map +1 -1
  64. package/lib/Auth/BrowserOAuth.d.ts +6 -8
  65. package/lib/Auth/BrowserOAuth.d.ts.map +1 -1
  66. package/lib/Auth/BrowserOAuth.js +25 -41
  67. package/lib/Auth/BrowserOAuth.js.map +1 -1
  68. package/lib/Auth/Credentials.d.ts.map +1 -1
  69. package/lib/Auth/Credentials.js +2 -2
  70. package/lib/Auth/Credentials.js.map +1 -1
  71. package/lib/Auth/Demand.d.ts +4 -4
  72. package/lib/Auth/Demand.d.ts.map +1 -1
  73. package/lib/Auth/Demand.js +16 -10
  74. package/lib/Auth/Demand.js.map +1 -1
  75. package/lib/Auth/Env.d.ts +2 -1
  76. package/lib/Auth/Env.d.ts.map +1 -1
  77. package/lib/Auth/Env.js +4 -2
  78. package/lib/Auth/Env.js.map +1 -1
  79. package/lib/Auth/Inspect.d.ts +2 -2
  80. package/lib/Auth/Inspect.d.ts.map +1 -1
  81. package/lib/Auth/Inspect.js +3 -1
  82. package/lib/Auth/Inspect.js.map +1 -1
  83. package/lib/Auth/Lock.d.ts.map +1 -1
  84. package/lib/Auth/Lock.js +4 -8
  85. package/lib/Auth/Lock.js.map +1 -1
  86. package/lib/Auth/OAuthFlow.d.ts +3 -12
  87. package/lib/Auth/OAuthFlow.d.ts.map +1 -1
  88. package/lib/Auth/OAuthFlow.js +7 -17
  89. package/lib/Auth/OAuthFlow.js.map +1 -1
  90. package/lib/Auth/Paths.d.ts +2 -1
  91. package/lib/Auth/Paths.d.ts.map +1 -1
  92. package/lib/Auth/Paths.js +3 -2
  93. package/lib/Auth/Paths.js.map +1 -1
  94. package/lib/Auth/Profile.d.ts +10 -0
  95. package/lib/Auth/Profile.d.ts.map +1 -1
  96. package/lib/Auth/Profile.js +19 -2
  97. package/lib/Auth/Profile.js.map +1 -1
  98. package/lib/Auth/Registry.d.ts +20 -0
  99. package/lib/Auth/Registry.d.ts.map +1 -0
  100. package/lib/Auth/Registry.js +17 -0
  101. package/lib/Auth/Registry.js.map +1 -0
  102. package/lib/Auth/Resolve.d.ts +34 -2
  103. package/lib/Auth/Resolve.d.ts.map +1 -1
  104. package/lib/Auth/Resolve.js +51 -3
  105. package/lib/Auth/Resolve.js.map +1 -1
  106. package/lib/Auth/StoredAuthProvider.d.ts +1 -1
  107. package/lib/Auth/StoredAuthProvider.d.ts.map +1 -1
  108. package/lib/Auth/StoredAuthProvider.js +1 -2
  109. package/lib/Auth/StoredAuthProvider.js.map +1 -1
  110. package/lib/Binding.d.ts.map +1 -1
  111. package/lib/Binding.js +3 -1
  112. package/lib/Binding.js.map +1 -1
  113. package/lib/Bundle/Bundle.d.ts +5 -0
  114. package/lib/Bundle/Bundle.d.ts.map +1 -1
  115. package/lib/Bundle/Bundle.js +36 -6
  116. package/lib/Bundle/Bundle.js.map +1 -1
  117. package/lib/Bundle/NamespaceImportPlugin.d.ts +55 -0
  118. package/lib/Bundle/NamespaceImportPlugin.d.ts.map +1 -0
  119. package/lib/Bundle/NamespaceImportPlugin.js +226 -0
  120. package/lib/Bundle/NamespaceImportPlugin.js.map +1 -0
  121. package/lib/Bundle/index.d.ts +1 -0
  122. package/lib/Bundle/index.d.ts.map +1 -1
  123. package/lib/Bundle/index.js +1 -0
  124. package/lib/Bundle/index.js.map +1 -1
  125. package/lib/Cli/Format.d.ts.map +1 -1
  126. package/lib/Cli/Format.js +2 -1
  127. package/lib/Cli/Format.js.map +1 -1
  128. package/lib/Cli/GlobalLog.d.ts +72 -26
  129. package/lib/Cli/GlobalLog.d.ts.map +1 -1
  130. package/lib/Cli/GlobalLog.js +151 -59
  131. package/lib/Cli/GlobalLog.js.map +1 -1
  132. package/lib/Cli/LoggingCli.d.ts.map +1 -1
  133. package/lib/Cli/LoggingCli.js +24 -18
  134. package/lib/Cli/LoggingCli.js.map +1 -1
  135. package/lib/Cli/PlainCliFormatter.d.ts.map +1 -1
  136. package/lib/Cli/PlainCliFormatter.js +4 -1
  137. package/lib/Cli/PlainCliFormatter.js.map +1 -1
  138. package/lib/Cli/Present.d.ts +14 -0
  139. package/lib/Cli/Present.d.ts.map +1 -0
  140. package/lib/Cli/Present.js +22 -0
  141. package/lib/Cli/Present.js.map +1 -0
  142. package/lib/Cli/SigilRenderer.d.ts +58 -0
  143. package/lib/Cli/SigilRenderer.d.ts.map +1 -0
  144. package/lib/Cli/SigilRenderer.js +39 -0
  145. package/lib/Cli/SigilRenderer.js.map +1 -0
  146. package/lib/Cli/checkVersion.d.ts +11 -14
  147. package/lib/Cli/checkVersion.d.ts.map +1 -1
  148. package/lib/Cli/checkVersion.js +19 -77
  149. package/lib/Cli/checkVersion.js.map +1 -1
  150. package/lib/Cli/commands/confirm.d.ts +2 -2
  151. package/lib/Cli/commands/confirm.d.ts.map +1 -1
  152. package/lib/Cli/commands/confirm.js +3 -3
  153. package/lib/Cli/commands/confirm.js.map +1 -1
  154. package/lib/Cli/commands/deploy.d.ts +4 -4
  155. package/lib/Cli/commands/deploy.d.ts.map +1 -1
  156. package/lib/Cli/commands/deploy.js +40 -39
  157. package/lib/Cli/commands/deploy.js.map +1 -1
  158. package/lib/Cli/commands/dev.d.ts.map +1 -1
  159. package/lib/Cli/commands/dev.js +41 -3
  160. package/lib/Cli/commands/dev.js.map +1 -1
  161. package/lib/Cli/commands/drift.d.ts +2 -2
  162. package/lib/Cli/commands/drift.d.ts.map +1 -1
  163. package/lib/Cli/commands/drift.js +14 -13
  164. package/lib/Cli/commands/drift.js.map +1 -1
  165. package/lib/Cli/commands/errors.d.ts.map +1 -1
  166. package/lib/Cli/commands/errors.js +2 -1
  167. package/lib/Cli/commands/errors.js.map +1 -1
  168. package/lib/Cli/commands/instrument.d.ts +15 -5
  169. package/lib/Cli/commands/instrument.d.ts.map +1 -1
  170. package/lib/Cli/commands/instrument.js +33 -8
  171. package/lib/Cli/commands/instrument.js.map +1 -1
  172. package/lib/Cli/commands/logs.d.ts +1 -1
  173. package/lib/Cli/commands/logs.d.ts.map +1 -1
  174. package/lib/Cli/commands/logs.js +22 -22
  175. package/lib/Cli/commands/logs.js.map +1 -1
  176. package/lib/Cli/commands/nuke.d.ts +3 -2
  177. package/lib/Cli/commands/nuke.d.ts.map +1 -1
  178. package/lib/Cli/commands/nuke.js +19 -17
  179. package/lib/Cli/commands/nuke.js.map +1 -1
  180. package/lib/Cli/commands/profile/commands.d.ts +3 -2
  181. package/lib/Cli/commands/profile/commands.d.ts.map +1 -1
  182. package/lib/Cli/commands/profile/commands.js +26 -27
  183. package/lib/Cli/commands/profile/commands.js.map +1 -1
  184. package/lib/Cli/commands/profile/flows.d.ts +6 -5
  185. package/lib/Cli/commands/profile/flows.d.ts.map +1 -1
  186. package/lib/Cli/commands/profile/flows.js +19 -17
  187. package/lib/Cli/commands/profile/flows.js.map +1 -1
  188. package/lib/Cli/commands/profile/hub.d.ts +1 -2
  189. package/lib/Cli/commands/profile/hub.d.ts.map +1 -1
  190. package/lib/Cli/commands/profile/hub.js +15 -17
  191. package/lib/Cli/commands/profile/hub.js.map +1 -1
  192. package/lib/Cli/commands/provider.d.ts +3 -1
  193. package/lib/Cli/commands/provider.d.ts.map +1 -1
  194. package/lib/Cli/commands/provider.js +4 -4
  195. package/lib/Cli/commands/provider.js.map +1 -1
  196. package/lib/Cli/commands/render.d.ts +2 -4
  197. package/lib/Cli/commands/render.d.ts.map +1 -1
  198. package/lib/Cli/commands/render.js +33 -56
  199. package/lib/Cli/commands/render.js.map +1 -1
  200. package/lib/Cli/commands/state.d.ts +1 -2
  201. package/lib/Cli/commands/state.d.ts.map +1 -1
  202. package/lib/Cli/commands/state.js +74 -27
  203. package/lib/Cli/commands/state.js.map +1 -1
  204. package/lib/Cli/components/capabilities.d.ts +4 -0
  205. package/lib/Cli/components/capabilities.d.ts.map +1 -0
  206. package/lib/Cli/components/capabilities.js +18 -0
  207. package/lib/Cli/components/capabilities.js.map +1 -0
  208. package/lib/Cli/components/types.d.ts +2 -81
  209. package/lib/Cli/components/types.d.ts.map +1 -1
  210. package/lib/Cli/components/types.js +1 -3
  211. package/lib/Cli/components/types.js.map +1 -1
  212. package/lib/Cli/components/ui/Environment.d.ts +3 -3
  213. package/lib/Cli/components/ui/Environment.d.ts.map +1 -1
  214. package/lib/Cli/components/ui/Environment.js.map +1 -1
  215. package/lib/Cli/components/ui/Interactive.d.ts +17 -4
  216. package/lib/Cli/components/ui/Interactive.d.ts.map +1 -1
  217. package/lib/Cli/components/ui/Interactive.js +7 -11
  218. package/lib/Cli/components/ui/Interactive.js.map +1 -1
  219. package/lib/Cli/components/ui/Layout.d.ts +1 -1
  220. package/lib/Cli/components/ui/Layout.d.ts.map +1 -1
  221. package/lib/Cli/components/ui/Layout.js +1 -1
  222. package/lib/Cli/components/ui/Layout.js.map +1 -1
  223. package/lib/Cli/components/ui/Typography.d.ts +1 -1
  224. package/lib/Cli/components/ui/Typography.d.ts.map +1 -1
  225. package/lib/Cli/components/ui/Typography.js +1 -1
  226. package/lib/Cli/components/ui/Typography.js.map +1 -1
  227. package/lib/Cli/components/ui/index.d.ts +2 -2
  228. package/lib/Cli/components/ui/index.js +2 -2
  229. package/lib/Cli/components/view/ApprovePlan.d.ts +1 -1
  230. package/lib/Cli/components/view/ApprovePlan.d.ts.map +1 -1
  231. package/lib/Cli/components/view/ApprovePlan.js +2 -1
  232. package/lib/Cli/components/view/ApprovePlan.js.map +1 -1
  233. package/lib/Cli/components/view/Format.d.ts +5 -0
  234. package/lib/Cli/components/view/Format.d.ts.map +1 -0
  235. package/lib/Cli/components/view/Format.js +39 -0
  236. package/lib/Cli/components/view/Format.js.map +1 -0
  237. package/lib/Cli/components/view/Help.d.ts +2 -2
  238. package/lib/Cli/components/view/Help.d.ts.map +1 -1
  239. package/lib/Cli/components/view/Help.js +7 -5
  240. package/lib/Cli/components/view/Help.js.map +1 -1
  241. package/lib/Cli/components/view/Logo.js +1 -1
  242. package/lib/Cli/components/view/Logo.js.map +1 -1
  243. package/lib/Cli/components/view/Nuke.d.ts +8 -9
  244. package/lib/Cli/components/view/Nuke.d.ts.map +1 -1
  245. package/lib/Cli/components/view/Nuke.js +49 -52
  246. package/lib/Cli/components/view/Nuke.js.map +1 -1
  247. package/lib/Cli/components/view/PlanDecision.d.ts +1 -1
  248. package/lib/Cli/components/view/PlanDecision.d.ts.map +1 -1
  249. package/lib/Cli/components/view/PlanDecision.js +1 -1
  250. package/lib/Cli/components/view/PlanDecision.js.map +1 -1
  251. package/lib/Cli/components/view/PlanRow.js +1 -1
  252. package/lib/Cli/components/view/PlanRow.js.map +1 -1
  253. package/lib/Cli/components/view/PlanTree.d.ts +1 -1
  254. package/lib/Cli/components/view/PlanTree.d.ts.map +1 -1
  255. package/lib/Cli/components/view/PlanTree.js +1 -1
  256. package/lib/Cli/components/view/PlanView.js +1 -1
  257. package/lib/Cli/components/view/PlanView.js.map +1 -1
  258. package/lib/Cli/components/view/Profile.d.ts +1 -1
  259. package/lib/Cli/components/view/Profile.js +2 -2
  260. package/lib/Cli/components/view/Profile.js.map +1 -1
  261. package/lib/Cli/components/view/ProfileDashboard.d.ts +4 -4
  262. package/lib/Cli/components/view/ProfileDashboard.d.ts.map +1 -1
  263. package/lib/Cli/components/view/ProfileDashboard.js +9 -8
  264. package/lib/Cli/components/view/ProfileDashboard.js.map +1 -1
  265. package/lib/Cli/components/view/Prompts.d.ts +3 -3
  266. package/lib/Cli/components/view/Prompts.d.ts.map +1 -1
  267. package/lib/Cli/components/view/Prompts.js +11 -18
  268. package/lib/Cli/components/view/Prompts.js.map +1 -1
  269. package/lib/Cli/components/view/Runtime.d.ts +5 -5
  270. package/lib/Cli/components/view/Runtime.d.ts.map +1 -1
  271. package/lib/Cli/components/view/Runtime.js +136 -219
  272. package/lib/Cli/components/view/Runtime.js.map +1 -1
  273. package/lib/Cli/components/view/SigilCli.d.ts +2 -2
  274. package/lib/Cli/components/view/SigilCli.d.ts.map +1 -1
  275. package/lib/Cli/components/view/SigilCli.js +7 -7
  276. package/lib/Cli/components/view/SigilCli.js.map +1 -1
  277. package/lib/Cli/components/view/StateExplorer.d.ts +1 -1
  278. package/lib/Cli/components/view/StateExplorer.d.ts.map +1 -1
  279. package/lib/Cli/components/view/StateExplorer.js +2 -1
  280. package/lib/Cli/components/view/StateExplorer.js.map +1 -1
  281. package/lib/Cli/components/view/statusStyle.d.ts +2 -2
  282. package/lib/Cli/components/view/statusStyle.d.ts.map +1 -1
  283. package/lib/Cli/components/view/statusStyle.js +1 -1
  284. package/lib/Cli/components/view/statusStyle.js.map +1 -1
  285. package/lib/Cli/exec.d.ts +6 -1
  286. package/lib/Cli/exec.d.ts.map +1 -1
  287. package/lib/Cli/exec.js +29 -34
  288. package/lib/Cli/exec.js.map +1 -1
  289. package/lib/Cli/main.d.ts.map +1 -1
  290. package/lib/Cli/main.js +35 -26
  291. package/lib/Cli/main.js.map +1 -1
  292. package/lib/Cli/selectCli.d.ts +2 -2
  293. package/lib/Cli/selectCli.d.ts.map +1 -1
  294. package/lib/Cli/selectCli.js +2 -2
  295. package/lib/Cli/selectCli.js.map +1 -1
  296. package/lib/Command/Command.js +1 -1
  297. package/lib/Command/Command.js.map +1 -1
  298. package/lib/Command/Dev.d.ts +58 -4
  299. package/lib/Command/Dev.d.ts.map +1 -1
  300. package/lib/Command/Dev.js +87 -30
  301. package/lib/Command/Dev.js.map +1 -1
  302. package/lib/Command/Local.d.ts +1 -1
  303. package/lib/Command/Memo.js +1 -1
  304. package/lib/Command/Memo.js.map +1 -1
  305. package/lib/Command/Providers.d.ts +1 -1
  306. package/lib/Command/Providers.d.ts.map +1 -1
  307. package/lib/Contributions.d.ts +2 -3
  308. package/lib/Contributions.d.ts.map +1 -1
  309. package/lib/Contributions.js +38 -6
  310. package/lib/Contributions.js.map +1 -1
  311. package/lib/DNS/Adapter.d.ts +204 -0
  312. package/lib/DNS/Adapter.d.ts.map +1 -0
  313. package/lib/DNS/Adapter.js +112 -0
  314. package/lib/DNS/Adapter.js.map +1 -0
  315. package/lib/DNS/index.d.ts +2 -0
  316. package/lib/DNS/index.d.ts.map +1 -0
  317. package/lib/DNS/index.js +2 -0
  318. package/lib/DNS/index.js.map +1 -0
  319. package/lib/Deploy.d.ts +7 -2
  320. package/lib/Deploy.d.ts.map +1 -1
  321. package/lib/Deploy.js +8 -3
  322. package/lib/Deploy.js.map +1 -1
  323. package/lib/Destroy.d.ts +5 -8
  324. package/lib/Destroy.d.ts.map +1 -1
  325. package/lib/Destroy.js +10 -7
  326. package/lib/Destroy.js.map +1 -1
  327. package/lib/Diff.d.ts.map +1 -1
  328. package/lib/Diff.js +14 -4
  329. package/lib/Diff.js.map +1 -1
  330. package/lib/Drift.d.ts +7 -7
  331. package/lib/Drift.d.ts.map +1 -1
  332. package/lib/Drift.js +184 -101
  333. package/lib/Drift.js.map +1 -1
  334. package/lib/EvalStack.d.ts +23 -0
  335. package/lib/EvalStack.d.ts.map +1 -0
  336. package/lib/EvalStack.js +47 -0
  337. package/lib/EvalStack.js.map +1 -0
  338. package/lib/Events.d.ts +210 -0
  339. package/lib/Events.d.ts.map +1 -0
  340. package/lib/Events.js +244 -0
  341. package/lib/Events.js.map +1 -0
  342. package/lib/Interaction.d.ts +159 -48
  343. package/lib/Interaction.d.ts.map +1 -1
  344. package/lib/Interaction.js +139 -58
  345. package/lib/Interaction.js.map +1 -1
  346. package/lib/Local/LocalProvider.d.ts.map +1 -1
  347. package/lib/Local/LocalProvider.js +31 -9
  348. package/lib/Local/LocalProvider.js.map +1 -1
  349. package/lib/Local/RpcProvider.d.ts.map +1 -1
  350. package/lib/Local/RpcProvider.js +10 -1
  351. package/lib/Local/RpcProvider.js.map +1 -1
  352. package/lib/Local/RpcProviderProxy.d.ts +16 -0
  353. package/lib/Local/RpcProviderProxy.d.ts.map +1 -1
  354. package/lib/Local/RpcProviderProxy.js +19 -10
  355. package/lib/Local/RpcProviderProxy.js.map +1 -1
  356. package/lib/Local/RpcSerialization.d.ts +3 -2
  357. package/lib/Local/RpcSerialization.d.ts.map +1 -1
  358. package/lib/Local/RpcSerialization.js +13 -10
  359. package/lib/Local/RpcSerialization.js.map +1 -1
  360. package/lib/Local/RpcServer.d.ts +2 -1
  361. package/lib/Local/RpcServer.d.ts.map +1 -1
  362. package/lib/Local/RpcServer.js +19 -14
  363. package/lib/Local/RpcServer.js.map +1 -1
  364. package/lib/Local/RpcServerBun.d.ts.map +1 -1
  365. package/lib/Local/RpcServerBun.js +8 -4
  366. package/lib/Local/RpcServerBun.js.map +1 -1
  367. package/lib/Local/RpcServerEnvironment.d.ts +2 -3
  368. package/lib/Local/RpcServerEnvironment.d.ts.map +1 -1
  369. package/lib/Local/RpcServerEnvironment.js +2 -2
  370. package/lib/Local/RpcServerEnvironment.js.map +1 -1
  371. package/lib/Local/RpcServerNode.d.ts.map +1 -1
  372. package/lib/Local/RpcServerNode.js +5 -1
  373. package/lib/Local/RpcServerNode.js.map +1 -1
  374. package/lib/Local/RpcServerSession.d.ts +1 -1
  375. package/lib/Local/RpcServerSession.d.ts.map +1 -1
  376. package/lib/Local/RpcServerSession.js.map +1 -1
  377. package/lib/Local/RpcSpawner.d.ts +6 -8
  378. package/lib/Local/RpcSpawner.d.ts.map +1 -1
  379. package/lib/Local/RpcSpawner.js +45 -36
  380. package/lib/Local/RpcSpawner.js.map +1 -1
  381. package/lib/Local/Sidecar.d.ts +23 -0
  382. package/lib/Local/Sidecar.d.ts.map +1 -1
  383. package/lib/Local/Sidecar.js +14 -9
  384. package/lib/Local/Sidecar.js.map +1 -1
  385. package/lib/Nuke.d.ts +5 -23
  386. package/lib/Nuke.d.ts.map +1 -1
  387. package/lib/Nuke.js +48 -13
  388. package/lib/Nuke.js.map +1 -1
  389. package/lib/Output.d.ts +19 -1
  390. package/lib/Output.d.ts.map +1 -1
  391. package/lib/Output.js +96 -3
  392. package/lib/Output.js.map +1 -1
  393. package/lib/Plan.d.ts +5 -1
  394. package/lib/Plan.d.ts.map +1 -1
  395. package/lib/Plan.js +111 -33
  396. package/lib/Plan.js.map +1 -1
  397. package/lib/Platform.d.ts.map +1 -1
  398. package/lib/Platform.js +31 -7
  399. package/lib/Platform.js.map +1 -1
  400. package/lib/Provider.d.ts +45 -0
  401. package/lib/Provider.d.ts.map +1 -1
  402. package/lib/Provider.js +2 -2
  403. package/lib/Provider.js.map +1 -1
  404. package/lib/Report.d.ts +17 -195
  405. package/lib/Report.d.ts.map +1 -1
  406. package/lib/Report.js +39 -12
  407. package/lib/Report.js.map +1 -1
  408. package/lib/Runtime/ManagedHttpShutdown.d.ts +17 -0
  409. package/lib/Runtime/ManagedHttpShutdown.d.ts.map +1 -1
  410. package/lib/Runtime/ManagedHttpShutdown.js +11 -2
  411. package/lib/Runtime/ManagedHttpShutdown.js.map +1 -1
  412. package/lib/RuntimeContext.js +1 -1
  413. package/lib/RuntimeContext.js.map +1 -1
  414. package/lib/Stack.d.ts +49 -29
  415. package/lib/Stack.d.ts.map +1 -1
  416. package/lib/Stack.js +25 -31
  417. package/lib/Stack.js.map +1 -1
  418. package/lib/State/BucketState.d.ts.map +1 -1
  419. package/lib/State/BucketState.js +43 -14
  420. package/lib/State/BucketState.js.map +1 -1
  421. package/lib/State/LocalState.d.ts.map +1 -1
  422. package/lib/State/LocalState.js +3 -3
  423. package/lib/State/LocalState.js.map +1 -1
  424. package/lib/State/Provisioning.d.ts +5 -0
  425. package/lib/State/Provisioning.d.ts.map +1 -1
  426. package/lib/State/Provisioning.js +3 -1
  427. package/lib/State/Provisioning.js.map +1 -1
  428. package/lib/State/ResourceState.d.ts +2 -0
  429. package/lib/State/ResourceState.d.ts.map +1 -1
  430. package/lib/State/State.d.ts +26 -0
  431. package/lib/State/State.d.ts.map +1 -1
  432. package/lib/State/StateEncoding.d.ts +7 -0
  433. package/lib/State/StateEncoding.d.ts.map +1 -1
  434. package/lib/State/StateEncoding.js +19 -0
  435. package/lib/State/StateEncoding.js.map +1 -1
  436. package/lib/State/index.js +2 -2
  437. package/lib/State/index.js.map +1 -1
  438. package/lib/Telemetry/Layer.d.ts +2 -5
  439. package/lib/Telemetry/Layer.d.ts.map +1 -1
  440. package/lib/Telemetry/Layer.js +3 -23
  441. package/lib/Telemetry/Layer.js.map +1 -1
  442. package/lib/Telemetry/Metrics.d.ts +1 -1
  443. package/lib/Telemetry/Metrics.d.ts.map +1 -1
  444. package/lib/TelemetryRelay.js +1 -1
  445. package/lib/TelemetryRelay.js.map +1 -1
  446. package/lib/TelemetryRuntime.d.ts +1 -1
  447. package/lib/TelemetryRuntime.d.ts.map +1 -1
  448. package/lib/TelemetryRuntime.js +4 -3
  449. package/lib/TelemetryRuntime.js.map +1 -1
  450. package/lib/Util/ConsoleSink.d.ts +23 -2
  451. package/lib/Util/ConsoleSink.d.ts.map +1 -1
  452. package/lib/Util/ConsoleSink.js +54 -14
  453. package/lib/Util/ConsoleSink.js.map +1 -1
  454. package/lib/Util/LogAnnotation.d.ts +19 -0
  455. package/lib/Util/LogAnnotation.d.ts.map +1 -0
  456. package/lib/Util/LogAnnotation.js +19 -0
  457. package/lib/Util/LogAnnotation.js.map +1 -0
  458. package/lib/Util/LogRecord.d.ts +281 -0
  459. package/lib/Util/LogRecord.d.ts.map +1 -0
  460. package/lib/Util/LogRecord.js +267 -0
  461. package/lib/Util/LogRecord.js.map +1 -0
  462. package/lib/Util/Node.d.ts +9 -0
  463. package/lib/Util/Node.d.ts.map +1 -1
  464. package/lib/Util/Node.js +10 -6
  465. package/lib/Util/Node.js.map +1 -1
  466. package/lib/Util/PlatformServices.d.ts +3 -2
  467. package/lib/Util/PlatformServices.d.ts.map +1 -1
  468. package/lib/Util/PlatformServices.js +6 -2
  469. package/lib/Util/PlatformServices.js.map +1 -1
  470. package/lib/Util/ResourceOutput.d.ts +18 -10
  471. package/lib/Util/ResourceOutput.d.ts.map +1 -1
  472. package/lib/Util/ResourceOutput.js +22 -23
  473. package/lib/Util/ResourceOutput.js.map +1 -1
  474. package/lib/Util/Shutdown.d.ts +10 -0
  475. package/lib/Util/Shutdown.d.ts.map +1 -0
  476. package/lib/Util/Shutdown.js +32 -0
  477. package/lib/Util/Shutdown.js.map +1 -0
  478. package/lib/Util/Terminal.d.ts +2 -4
  479. package/lib/Util/Terminal.d.ts.map +1 -1
  480. package/lib/Util/Terminal.js +3 -11
  481. package/lib/Util/Terminal.js.map +1 -1
  482. package/lib/Util/TraceParent.d.ts +32 -0
  483. package/lib/Util/TraceParent.d.ts.map +1 -0
  484. package/lib/Util/TraceParent.js +42 -0
  485. package/lib/Util/TraceParent.js.map +1 -0
  486. package/lib/Util/base64.d.ts +7 -0
  487. package/lib/Util/base64.d.ts.map +1 -0
  488. package/lib/Util/base64.js +24 -0
  489. package/lib/Util/base64.js.map +1 -0
  490. package/lib/Util/cached-function.d.ts +5 -0
  491. package/lib/Util/cached-function.d.ts.map +1 -1
  492. package/lib/Util/cached-function.js +13 -8
  493. package/lib/Util/cached-function.js.map +1 -1
  494. package/lib/Util/data.d.ts +1 -1
  495. package/lib/Util/data.d.ts.map +1 -1
  496. package/lib/Util/data.js +1 -1
  497. package/lib/Util/data.js.map +1 -1
  498. package/lib/Util/equal.d.ts.map +1 -1
  499. package/lib/Util/equal.js +3 -2
  500. package/lib/Util/equal.js.map +1 -1
  501. package/lib/Util/extraFiles.d.ts.map +1 -1
  502. package/lib/Util/extraFiles.js +5 -5
  503. package/lib/Util/extraFiles.js.map +1 -1
  504. package/lib/Util/interactive.js +1 -1
  505. package/lib/Website/AstroOutput.d.ts +42 -0
  506. package/lib/Website/AstroOutput.d.ts.map +1 -0
  507. package/lib/Website/AstroOutput.js +34 -0
  508. package/lib/Website/AstroOutput.js.map +1 -0
  509. package/lib/Website/FrontendCore.d.ts +1 -1
  510. package/lib/Workflows.d.ts +9 -0
  511. package/lib/Workflows.d.ts.map +1 -1
  512. package/lib/Workflows.js +8 -0
  513. package/lib/Workflows.js.map +1 -1
  514. package/lib/index.d.ts +1 -0
  515. package/lib/index.d.ts.map +1 -1
  516. package/lib/index.js +1 -0
  517. package/lib/index.js.map +1 -1
  518. package/package.json +21 -28
  519. package/src/AdoptPolicy.ts +76 -0
  520. package/src/Alchemist/AuthRegistry.ts +164 -0
  521. package/src/Alchemist/Drift.ts +103 -0
  522. package/src/Alchemist/Entrypoint.ts +51 -3
  523. package/src/Alchemist/Errors.ts +1 -1
  524. package/src/Alchemist/{routes/logs.ts → Logs.ts} +28 -30
  525. package/src/Alchemist/Nuke.ts +90 -0
  526. package/src/Alchemist/Operations.ts +309 -0
  527. package/src/Alchemist/{routes/profile.ts → Profile.ts} +22 -22
  528. package/src/Alchemist/{routes/provider.ts → Provider.ts} +7 -6
  529. package/src/Alchemist/Runtime.ts +46 -12
  530. package/src/Alchemist/{routes/state.ts → State.ts} +78 -21
  531. package/src/Alchemist/index.ts +32 -15
  532. package/src/Apply.ts +513 -274
  533. package/src/Auth/AuthProvider.ts +76 -23
  534. package/src/Auth/BrowserOAuth.ts +37 -60
  535. package/src/Auth/Credentials.ts +2 -4
  536. package/src/Auth/Demand.ts +27 -18
  537. package/src/Auth/Env.ts +13 -8
  538. package/src/Auth/Inspect.ts +5 -2
  539. package/src/Auth/Lock.ts +4 -8
  540. package/src/Auth/OAuthFlow.ts +12 -26
  541. package/src/Auth/Paths.ts +3 -2
  542. package/src/Auth/Profile.ts +30 -2
  543. package/src/Auth/Registry.ts +27 -0
  544. package/src/Auth/Resolve.ts +75 -3
  545. package/src/Auth/StoredAuthProvider.ts +1 -2
  546. package/src/Binding.ts +3 -4
  547. package/src/Bundle/Bundle.ts +58 -7
  548. package/src/Bundle/NamespaceImportPlugin.ts +259 -0
  549. package/src/Bundle/index.ts +1 -0
  550. package/src/Cli/Format.ts +2 -1
  551. package/src/Cli/GlobalLog.ts +206 -68
  552. package/src/Cli/LoggingCli.ts +33 -20
  553. package/src/Cli/PlainCliFormatter.ts +4 -1
  554. package/src/Cli/Present.ts +34 -0
  555. package/src/Cli/SigilRenderer.ts +75 -0
  556. package/src/Cli/checkVersion.ts +25 -78
  557. package/src/Cli/commands/confirm.ts +3 -3
  558. package/src/Cli/commands/deploy.ts +53 -44
  559. package/src/Cli/commands/dev.ts +65 -7
  560. package/src/Cli/commands/drift.ts +20 -16
  561. package/src/Cli/commands/errors.ts +2 -3
  562. package/src/Cli/commands/instrument.ts +39 -8
  563. package/src/Cli/commands/logs.ts +22 -30
  564. package/src/Cli/commands/nuke.ts +25 -26
  565. package/src/Cli/commands/profile/commands.ts +34 -34
  566. package/src/Cli/commands/profile/flows.ts +26 -20
  567. package/src/Cli/commands/profile/hub.ts +16 -18
  568. package/src/Cli/commands/provider.ts +4 -4
  569. package/src/Cli/commands/render.ts +43 -71
  570. package/src/Cli/commands/state.ts +113 -33
  571. package/src/Cli/components/capabilities.ts +20 -0
  572. package/src/Cli/components/types.ts +13 -99
  573. package/src/Cli/components/ui/Environment.tsx +5 -5
  574. package/src/Cli/components/ui/Interactive.tsx +24 -15
  575. package/src/Cli/components/ui/Layout.tsx +1 -1
  576. package/src/Cli/components/ui/Typography.tsx +1 -1
  577. package/src/Cli/components/ui/index.ts +2 -2
  578. package/src/Cli/components/view/ApprovePlan.tsx +2 -1
  579. package/src/Cli/components/view/Format.tsx +58 -0
  580. package/src/Cli/components/view/Help.tsx +14 -17
  581. package/src/Cli/components/view/Logo.tsx +1 -1
  582. package/src/Cli/components/view/Nuke.tsx +74 -49
  583. package/src/Cli/components/view/PlanDecision.tsx +1 -1
  584. package/src/Cli/components/view/PlanRow.tsx +1 -1
  585. package/src/Cli/components/view/PlanTree.ts +2 -2
  586. package/src/Cli/components/view/PlanView.tsx +2 -2
  587. package/src/Cli/components/view/Profile.tsx +2 -2
  588. package/src/Cli/components/view/ProfileDashboard.tsx +12 -11
  589. package/src/Cli/components/view/Prompts.tsx +37 -75
  590. package/src/Cli/components/view/Runtime.tsx +132 -238
  591. package/src/Cli/components/view/SigilCli.tsx +12 -12
  592. package/src/Cli/components/view/StateExplorer.tsx +2 -1
  593. package/src/Cli/components/view/statusStyle.ts +2 -2
  594. package/src/Cli/exec.ts +48 -41
  595. package/src/Cli/main.ts +52 -33
  596. package/src/Cli/selectCli.ts +3 -3
  597. package/src/Command/Command.ts +1 -1
  598. package/src/Command/Dev.ts +129 -36
  599. package/src/Command/Memo.ts +1 -1
  600. package/src/Contributions.ts +42 -8
  601. package/src/DNS/Adapter.ts +289 -0
  602. package/src/DNS/index.ts +1 -0
  603. package/src/Deploy.ts +11 -3
  604. package/src/Destroy.ts +19 -13
  605. package/src/Diff.ts +17 -4
  606. package/src/Drift.ts +256 -127
  607. package/src/EvalStack.ts +97 -0
  608. package/src/Events.ts +296 -0
  609. package/src/Interaction.ts +332 -97
  610. package/src/Local/LocalProvider.ts +40 -9
  611. package/src/Local/RpcProvider.ts +11 -1
  612. package/src/Local/RpcProviderProxy.ts +29 -21
  613. package/src/Local/RpcSerialization.ts +32 -17
  614. package/src/Local/RpcServer.ts +25 -17
  615. package/src/Local/RpcServerBun.ts +10 -6
  616. package/src/Local/RpcServerEnvironment.ts +2 -2
  617. package/src/Local/RpcServerNode.ts +8 -1
  618. package/src/Local/RpcServerSession.ts +2 -2
  619. package/src/Local/RpcSpawner.ts +61 -37
  620. package/src/Local/Sidecar.ts +10 -1
  621. package/src/Nuke.ts +66 -43
  622. package/src/Output.ts +120 -7
  623. package/src/Plan.ts +140 -52
  624. package/src/Platform.ts +47 -18
  625. package/src/Provider.ts +48 -3
  626. package/src/Report.ts +77 -275
  627. package/src/Runtime/ManagedHttpShutdown.ts +21 -4
  628. package/src/RuntimeContext.ts +1 -1
  629. package/src/Stack.ts +113 -135
  630. package/src/State/BucketState.ts +53 -21
  631. package/src/State/LocalState.ts +7 -9
  632. package/src/State/Provisioning.ts +8 -1
  633. package/src/State/ResourceState.ts +2 -0
  634. package/src/State/State.ts +30 -0
  635. package/src/State/StateEncoding.ts +22 -0
  636. package/src/State/index.ts +2 -2
  637. package/src/Telemetry/Layer.ts +3 -24
  638. package/src/Telemetry/Metrics.ts +1 -1
  639. package/src/TelemetryRelay.ts +1 -1
  640. package/src/TelemetryRuntime.ts +8 -8
  641. package/src/Util/ConsoleSink.ts +76 -13
  642. package/src/Util/LogAnnotation.ts +18 -0
  643. package/src/Util/LogRecord.ts +386 -0
  644. package/src/Util/Node.ts +20 -6
  645. package/src/Util/PlatformServices.ts +17 -4
  646. package/src/Util/ResourceOutput.ts +26 -25
  647. package/src/Util/Shutdown.ts +52 -0
  648. package/src/Util/Terminal.ts +3 -20
  649. package/src/Util/TraceParent.ts +70 -0
  650. package/src/Util/base64.ts +22 -0
  651. package/src/Util/cached-function.ts +30 -19
  652. package/src/Util/data.ts +2 -2
  653. package/src/Util/equal.ts +3 -2
  654. package/src/Util/extraFiles.ts +9 -8
  655. package/src/Util/interactive.ts +1 -1
  656. package/src/Website/AstroOutput.ts +83 -0
  657. package/src/Workflows.ts +11 -0
  658. package/src/index.ts +1 -0
  659. package/lib/Alchemist/Progress.d.ts +0 -16
  660. package/lib/Alchemist/Progress.d.ts.map +0 -1
  661. package/lib/Alchemist/Progress.js +0 -123
  662. package/lib/Alchemist/Progress.js.map +0 -1
  663. package/lib/Alchemist/Session.d.ts +0 -116
  664. package/lib/Alchemist/Session.d.ts.map +0 -1
  665. package/lib/Alchemist/Session.js +0 -212
  666. package/lib/Alchemist/Session.js.map +0 -1
  667. package/lib/Alchemist/routes/drift.d.ts +0 -55
  668. package/lib/Alchemist/routes/drift.d.ts.map +0 -1
  669. package/lib/Alchemist/routes/drift.js +0 -52
  670. package/lib/Alchemist/routes/drift.js.map +0 -1
  671. package/lib/Alchemist/routes/logs.d.ts +0 -41
  672. package/lib/Alchemist/routes/logs.d.ts.map +0 -1
  673. package/lib/Alchemist/routes/logs.js.map +0 -1
  674. package/lib/Alchemist/routes/nuke.d.ts +0 -46
  675. package/lib/Alchemist/routes/nuke.d.ts.map +0 -1
  676. package/lib/Alchemist/routes/nuke.js +0 -80
  677. package/lib/Alchemist/routes/nuke.js.map +0 -1
  678. package/lib/Alchemist/routes/profile.d.ts +0 -133
  679. package/lib/Alchemist/routes/profile.d.ts.map +0 -1
  680. package/lib/Alchemist/routes/profile.js.map +0 -1
  681. package/lib/Alchemist/routes/provider.d.ts.map +0 -1
  682. package/lib/Alchemist/routes/provider.js.map +0 -1
  683. package/lib/Alchemist/routes/stack.d.ts +0 -95
  684. package/lib/Alchemist/routes/stack.d.ts.map +0 -1
  685. package/lib/Alchemist/routes/stack.js +0 -73
  686. package/lib/Alchemist/routes/stack.js.map +0 -1
  687. package/lib/Alchemist/routes/state.d.ts.map +0 -1
  688. package/lib/Alchemist/routes/state.js.map +0 -1
  689. package/lib/Cli/CliKit/CliKit.d.ts +0 -92
  690. package/lib/Cli/CliKit/CliKit.d.ts.map +0 -1
  691. package/lib/Cli/CliKit/CliKit.js +0 -27
  692. package/lib/Cli/CliKit/CliKit.js.map +0 -1
  693. package/lib/Cli/CliKit/index.d.ts +0 -9
  694. package/lib/Cli/CliKit/index.d.ts.map +0 -1
  695. package/lib/Cli/CliKit/index.js +0 -9
  696. package/lib/Cli/CliKit/index.js.map +0 -1
  697. package/lib/Cli/CliKit/interaction.d.ts +0 -13
  698. package/lib/Cli/CliKit/interaction.d.ts.map +0 -1
  699. package/lib/Cli/CliKit/interaction.js +0 -17
  700. package/lib/Cli/CliKit/interaction.js.map +0 -1
  701. package/lib/Cli/CliKit/layer.d.ts +0 -7
  702. package/lib/Cli/CliKit/layer.d.ts.map +0 -1
  703. package/lib/Cli/CliKit/layer.js +0 -33
  704. package/lib/Cli/CliKit/layer.js.map +0 -1
  705. package/lib/Local/DevLog.d.ts +0 -32
  706. package/lib/Local/DevLog.d.ts.map +0 -1
  707. package/lib/Local/DevLog.js +0 -112
  708. package/lib/Local/DevLog.js.map +0 -1
  709. package/lib/Test/Alchemy.d.ts +0 -79
  710. package/lib/Test/Alchemy.d.ts.map +0 -1
  711. package/lib/Test/Alchemy.js +0 -193
  712. package/lib/Test/Alchemy.js.map +0 -1
  713. package/lib/Test/Bun.d.ts +0 -69
  714. package/lib/Test/Bun.d.ts.map +0 -1
  715. package/lib/Test/Bun.js +0 -126
  716. package/lib/Test/Bun.js.map +0 -1
  717. package/lib/Test/Core.d.ts +0 -277
  718. package/lib/Test/Core.d.ts.map +0 -1
  719. package/lib/Test/Core.js +0 -362
  720. package/lib/Test/Core.js.map +0 -1
  721. package/lib/Test/Http.d.ts +0 -109
  722. package/lib/Test/Http.d.ts.map +0 -1
  723. package/lib/Test/Http.js +0 -123
  724. package/lib/Test/Http.js.map +0 -1
  725. package/lib/Test/TestState.d.ts +0 -12
  726. package/lib/Test/TestState.d.ts.map +0 -1
  727. package/lib/Test/TestState.js +0 -15
  728. package/lib/Test/TestState.js.map +0 -1
  729. package/lib/Test/Vitest.d.ts +0 -60
  730. package/lib/Test/Vitest.d.ts.map +0 -1
  731. package/lib/Test/Vitest.js +0 -132
  732. package/lib/Test/Vitest.js.map +0 -1
  733. package/lib/Test/index.d.ts +0 -3
  734. package/lib/Test/index.d.ts.map +0 -1
  735. package/lib/Test/index.js +0 -3
  736. package/lib/Test/index.js.map +0 -1
  737. package/lib/Util/FileLogger.d.ts +0 -7
  738. package/lib/Util/FileLogger.d.ts.map +0 -1
  739. package/lib/Util/FileLogger.js +0 -16
  740. package/lib/Util/FileLogger.js.map +0 -1
  741. package/src/Alchemist/Progress.ts +0 -167
  742. package/src/Alchemist/Session.ts +0 -415
  743. package/src/Alchemist/routes/drift.ts +0 -87
  744. package/src/Alchemist/routes/nuke.ts +0 -131
  745. package/src/Alchemist/routes/stack.ts +0 -173
  746. package/src/Cli/CliKit/CliKit.ts +0 -159
  747. package/src/Cli/CliKit/index.ts +0 -41
  748. package/src/Cli/CliKit/interaction.ts +0 -19
  749. package/src/Cli/CliKit/layer.ts +0 -44
  750. package/src/Local/DevLog.ts +0 -122
  751. package/src/Test/Alchemy.ts +0 -334
  752. package/src/Test/Bun.ts +0 -230
  753. package/src/Test/Core.ts +0 -785
  754. package/src/Test/Http.ts +0 -201
  755. package/src/Test/TestState.ts +0 -35
  756. package/src/Test/Vitest.ts +0 -239
  757. package/src/Test/index.ts +0 -2
  758. package/src/Util/FileLogger.ts +0 -20
package/lib/Apply.js CHANGED
@@ -2,28 +2,30 @@ import * as Cause from "effect/Cause";
2
2
  import * as Data from "effect/Data";
3
3
  import * as Deferred from "effect/Deferred";
4
4
  import * as Effect from "effect/Effect";
5
- import * as Exit from "effect/Exit";
5
+ import * as Formatter from "effect/Formatter";
6
6
  import * as Layer from "effect/Layer";
7
7
  import * as Option from "effect/Option";
8
8
  import * as Predicate from "effect/Predicate";
9
9
  import { makeResolveContext } from "./ActionRuntimeContext.js";
10
- import { OwnedBySomeoneElse, stripUnowned, Unowned } from "./AdoptPolicy.js";
10
+ import { OwnedBySomeoneElse, stripUnowned, Unowned, Unresolved, UnverifiableReplacement, } from "./AdoptPolicy.js";
11
11
  import { AlchemyContext } from "./AlchemyContext.js";
12
12
  import { Artifacts, ArtifactStore, createArtifactStore, ensureArtifactStore, makeScopedArtifacts, } from "./Artifacts.js";
13
13
  import { failCredentialsRequired, demandPlanCredentials, } from "./Auth/Demand.js";
14
- import { havePropsChanged, stripUnresolved } from "./Diff.js";
14
+ import { havePropsChanged, isResolved, stripEffects, stripUnresolved } from "./Diff.js";
15
+ import { captureEmit } from "./Events.js";
15
16
  import { generateInstanceId } from "./InstanceId.js";
16
17
  import * as Output from "./Output.js";
17
18
  import {} from "./Plan.js";
18
19
  import { findProviderByType, missingProviderError, tryFindProviderByType, } from "./Provider.js";
19
20
  import { stampedMode } from "./ProviderMode.js";
20
- import { Cli, noopSession, } from "./Report.js";
21
+ import { resourceSession } from "./Report.js";
21
22
  import { ResourceContext } from "./ResourceContext.js";
22
23
  import { RuntimeContext } from "./RuntimeContext.js";
23
24
  import { Stack } from "./Stack.js";
24
25
  import { Stage } from "./Stage.js";
25
26
  import { State, StateStoreError, } from "./State/index.js";
26
27
  import { recordResourceOp } from "./Telemetry/Metrics.js";
28
+ import { LogAnnotation } from "./Util/LogAnnotation.js";
27
29
  import { hashInput } from "./Util/sha256.js";
28
30
  /**
29
31
  * Record a resource's result in `tracker` and its output in `outputs`, the
@@ -35,6 +37,20 @@ const track = (tracker, outputs, fqn, entry) => {
35
37
  tracker[fqn] = entry;
36
38
  outputs[fqn] = entry.output;
37
39
  };
40
+ /**
41
+ * Whether an attr-less checkpoint lost props to `stripUnresolved`. Its stored
42
+ * props no longer identify the physical resource it was creating (e.g. a
43
+ * stripped namespace makes a name match a different resource), so recovery
44
+ * must not look the resource up from them.
45
+ *
46
+ * Effect-valued props don't count: `Output.evaluate` passes them through
47
+ * untouched, so even fully resolved props carry them (a Function's runtime
48
+ * wiring). They never name a physical resource, and treating them as holes
49
+ * would mark every create of such a resource and orphan it on interruption.
50
+ */
51
+ const propsIncomplete = (value) => value.attr === undefined && (value.propsIncomplete || !isResolved(stripEffects(value.props)))
52
+ ? true
53
+ : undefined;
38
54
  const provideLifecycleScope = (resource) => (effect) => Effect.serviceOption(ArtifactStore).pipe(Effect.map(Option.getOrElse(createArtifactStore)), Effect.flatMap((store) => effect.pipe(failCredentialsRequired(resource.fqn), Effect.provide([
39
55
  Layer.succeed(Artifacts, makeScopedArtifacts(store, resource.fqn)),
40
56
  Layer.succeed(ResourceContext, resource),
@@ -49,7 +65,9 @@ const provideLifecycleScope = (resource) => (effect) => Effect.serviceOption(Art
49
65
  * are dispatched, so wrapping it here gives us a fully-instrumented
50
66
  * toolchain without touching any individual provider implementation.
51
67
  */
52
- const instrumentLifecycle = (op, fqn, resourceType, logicalId, instanceId) => (effect) => effect.pipe(provideLifecycleScope({ logicalId, fqn, instanceId, type: resourceType }), recordResourceOp(resourceType, op), Effect.withSpan(`provider.${op}`, {
68
+ const instrumentLifecycle = (op, fqn, resourceType, logicalId, instanceId) => (effect) => effect.pipe(provideLifecycleScope({ logicalId, fqn, instanceId, type: resourceType }),
69
+ // Every log a provider writes during the op carries its resource.
70
+ Effect.annotateLogs(LogAnnotation.fqn, fqn), recordResourceOp(resourceType, op), Effect.withSpan(`provider.${op}`, {
53
71
  attributes: {
54
72
  "alchemy.resource.fqn": fqn,
55
73
  "alchemy.resource.type": resourceType,
@@ -58,7 +76,64 @@ const instrumentLifecycle = (op, fqn, resourceType, logicalId, instanceId) => (e
58
76
  "alchemy.resource.op": op,
59
77
  },
60
78
  }));
61
- export const apply = (plan, options = {}) => Effect.gen(function* () {
79
+ /**
80
+ * A dependency cycle precreates on raw props, before `read` can check
81
+ * ownership. Ask the provider's `observe` what exists at the identity
82
+ * precreate would claim, and refuse a foreign resource unless adoption is
83
+ * allowed. A provider without `observe` precreates `unchecked`; one whose
84
+ * identity has not resolved yet reports it `unresolved`, so the engine must
85
+ * check the resolved identity before reconcile claims it.
86
+ */
87
+ const observeBeforePrecreate = Effect.fn(function* (node, news, fqn, logicalId, instanceId, previous) {
88
+ if (node.provider.observe === undefined || node.deferredAdoption === undefined) {
89
+ return "unchecked";
90
+ }
91
+ const observed = yield* node.provider
92
+ .observe({ id: logicalId, fqn, instanceId, news, previous })
93
+ .pipe(instrumentLifecycle("observe", fqn, node.resource.Type, logicalId, instanceId));
94
+ if (observed === Unresolved)
95
+ return "unresolved";
96
+ if (observed !== undefined && Unowned.is(observed) && !node.deferredAdoption.adopt) {
97
+ return yield* new OwnedBySomeoneElse({
98
+ message: `Cannot pre-create resource '${fqn}' (${node.resource.Type}): ` +
99
+ "it exists in the cloud but is not owned by this " +
100
+ "stack/stage/logical-id. Re-run with `--adopt` (or " +
101
+ "wrap the effect in `adopt(true)`) to take it over.",
102
+ resourceType: node.resource.Type,
103
+ logicalId,
104
+ });
105
+ }
106
+ return "admitted";
107
+ });
108
+ /** A provider's `observe` reported `Unresolved` for fully resolved props. */
109
+ class UnresolvedObservation extends Data.TaggedError("UnresolvedObservation") {
110
+ }
111
+ /**
112
+ * Reports what exists at the resolved identity reconcile will claim: `read`
113
+ * when the provider implements it, `observe` otherwise. A replacement passes
114
+ * its `previous` generation's attributes, so the provider can recognize it.
115
+ */
116
+ const observeResolved = Effect.fn(function* (node, news, fqn, logicalId, instanceId, previous) {
117
+ if (node.provider.read) {
118
+ return yield* node.provider
119
+ .read({ id: logicalId, fqn, instanceId, olds: news, output: undefined, previous })
120
+ .pipe(instrumentLifecycle("read", fqn, node.resource.Type, logicalId, instanceId));
121
+ }
122
+ const observed = yield* node.provider.observe({
123
+ id: logicalId,
124
+ fqn,
125
+ instanceId,
126
+ news,
127
+ previous,
128
+ }).pipe(instrumentLifecycle("observe", fqn, node.resource.Type, logicalId, instanceId));
129
+ if (observed === Unresolved) {
130
+ return yield* Effect.die(new UnresolvedObservation({
131
+ message: `The provider for '${fqn}' (${node.resource.Type}) reported its identity as Unresolved, but its props are resolved.`,
132
+ }));
133
+ }
134
+ return observed;
135
+ });
136
+ export const apply = (plan) => Effect.gen(function* () {
62
137
  // Credential-free dev: a dev-mode plan that needs the real cloud
63
138
  // (`Alchemy.remote()` rows, remote-proxied bindings, deletions of rows
64
139
  // stamped `providerMode: "live"`) demands cloud credentials exactly
@@ -72,93 +147,99 @@ export const apply = (plan, options = {}) => Effect.gen(function* () {
72
147
  if (Option.isSome(alchemy) && alchemy.value.dev) {
73
148
  yield* demandPlanCredentials(plan);
74
149
  }
75
- // Renderer resolution: an explicit session wins, then the ambient Cli
76
- // renderer service (the bundled CLI, LoggingCli in tests, or a custom
77
- // implementation), else events are dropped.
78
- const session = options.session ??
79
- (yield* Effect.serviceOption(Cli).pipe(Effect.flatMap(Option.match({
80
- onNone: () => Effect.succeed(noopSession),
81
- onSome: (cli) => cli.startApplySession(plan, options.planDisplay),
82
- }))));
83
- // The nested gen exists so `onExit` can settle the session on every
84
- // exit path without introducing a scope: local dev providers start
85
- // long-running processes in the AMBIENT scope during reconcile, so
86
- // wrapping this body in Effect.scoped would kill them when apply
87
- // returns.
88
- return yield* Effect.gen(function* () {
89
- const state = yield* yield* State;
90
- const stack = yield* Stack;
91
- const stage = yield* Stage;
92
- const stackName = stack.name;
93
- const tracker = {};
94
- const outputs = {};
95
- const terminalStatuses = new Map();
96
- // ── FQN migrations (renamedFrom) ──
97
- // Persist renames before any lifecycle operation runs: a node whose row
98
- // was found under a former FQN carries that row pre-remapped in
99
- // `node.state` (see Plan's rename resolution). Commit it at the current
100
- // FQN FIRST, then drop the former row — in that order, so an
101
- // interruption leaves rows at both FQNs with the same instanceId, which
102
- // the next plan recognizes as an in-flight migration (and never as an
103
- // orphan to delete).
104
- //
105
- // In a same-deploy shift (A→B while B→C), C's former FQN `B` is
106
- // simultaneously B's migration TARGET. C must NOT delete it: B's own
107
- // `state.set` supersedes the stale copy, and the migrations run
108
- // concurrently — the delete could land after B's write and destroy the
109
- // freshly migrated row.
110
- const migrationTargets = new Set(Object.values(plan.resources)
111
- .filter((node) => node.renamedFrom?.length && node.state !== undefined)
112
- .map((node) => node.resource.FQN));
113
- yield* Effect.forEach(Object.values(plan.resources), (node) => {
114
- const { renamedFrom, state: row } = node;
115
- return renamedFrom === undefined || renamedFrom.length === 0 || row === undefined
116
- ? Effect.void
117
- : Effect.gen(function* () {
118
- yield* state.set({ stack: stackName, stage, fqn: node.resource.FQN, value: row });
119
- yield* Effect.forEach(renamedFrom.filter((formerFqn) => !migrationTargets.has(formerFqn)), (formerFqn) => state.delete({ stack: stackName, stage, fqn: formerFqn }), { concurrency: "unbounded" });
120
- });
121
- }, { concurrency: "unbounded" });
122
- yield* executePlan(plan, tracker, outputs, terminalStatuses, session, state, stackName, stage);
123
- // TODO(sam): support roll back to previous state if errors occur during expansion
124
- // -> RISK: some UPDATEs may not be reversible (i.e. trigger replacements)
125
- // TODO(sam): should pivot be done separately? E.g shift traffic?
126
- yield* collectGarbage(plan, session);
127
- yield* converge(plan, tracker, outputs, terminalStatuses, session, state, stackName, stage);
128
- yield* Effect.forEach(Array.from(terminalStatuses.values()), ({ fqn, id, type, status, providerMode }) => session.emit({ _tag: "apply.resource.status", fqn, id, type, status, providerMode }), { concurrency: "unbounded" });
129
- if (plan.destroy) {
130
- // The destroy converged: every resource row was deleted above. Drop
131
- // the rest of the stage's persisted state — notably the stack output
132
- // record written by the last deploy — so `getOutput` returns
133
- // undefined and `listStages` no longer reports the stage.
134
- // https://github.com/alchemy-run/alchemy/issues/961
135
- yield* state.deleteStack({ stack: stackName, stage });
136
- // Invariant: a successful destroy leaves the stage EMPTY. If rows
137
- // survive, this destroy session could not actually see (or delete)
138
- // the stack's state — e.g. its plan listed an empty store while
139
- // committed rows existed — and reporting success here would silently
140
- // leak every cloud resource those rows track. Fail loudly instead so
141
- // the leak surfaces in the run that caused it.
142
- const remaining = yield* state.list({ stack: stackName, stage });
143
- if (remaining.length > 0) {
144
- return yield* new StateStoreError({
145
- message: `destroy of ${stackName}/${stage} reported success but ${remaining.length} ` +
146
- `state row(s) remain (${remaining.join(", ")}) — the destroy session could ` +
147
- `not see the stack's persisted state, so its cloud resources were NOT deleted`,
148
- });
149
- }
150
- return undefined;
151
- }
152
- if (plan.selectedFqns !== undefined || !plan.output) {
153
- return undefined;
150
+ const emitEvent = yield* captureEmit;
151
+ // The last status each resource announced, so the post-convergence
152
+ // flush below re-emits only what is still unannounced (cycle members).
153
+ const announced = new Map();
154
+ const reportEvent = (event) => {
155
+ if (event.type === "apply.resource.status")
156
+ announced.set(event.fqn, event.status);
157
+ return emitEvent(event);
158
+ };
159
+ // No Effect.scoped around apply: local dev providers start long-running
160
+ // processes in the AMBIENT scope during reconcile, which a scope here
161
+ // would kill when apply returns.
162
+ const state = yield* yield* State;
163
+ const stack = yield* Stack;
164
+ const stage = yield* Stage;
165
+ const stackName = stack.name;
166
+ const tracker = {};
167
+ const outputs = {};
168
+ const terminalStatuses = new Map();
169
+ // ── FQN migrations (renamedFrom) ──
170
+ // Persist renames before any lifecycle operation runs: a node whose row
171
+ // was found under a former FQN carries that row pre-remapped in
172
+ // `node.state` (see Plan's rename resolution). Commit it at the current
173
+ // FQN FIRST, then drop the former row — in that order, so an
174
+ // interruption leaves rows at both FQNs with the same instanceId, which
175
+ // the next plan recognizes as an in-flight migration (and never as an
176
+ // orphan to delete).
177
+ //
178
+ // In a same-deploy shift (A→B while B→C), C's former FQN `B` is
179
+ // simultaneously B's migration TARGET. C must NOT delete it: B's own
180
+ // `state.set` supersedes the stale copy, and the migrations run
181
+ // concurrently — the delete could land after B's write and destroy the
182
+ // freshly migrated row.
183
+ const migrationTargets = new Set(Object.values(plan.resources)
184
+ .filter((node) => node.renamedFrom?.length && node.state !== undefined)
185
+ .map((node) => node.resource.FQN));
186
+ yield* Effect.forEach(Object.values(plan.resources), (node) => {
187
+ const { renamedFrom, state: row } = node;
188
+ return renamedFrom === undefined || renamedFrom.length === 0 || row === undefined
189
+ ? Effect.void
190
+ : Effect.gen(function* () {
191
+ yield* state.set({ stack: stackName, stage, fqn: node.resource.FQN, value: row });
192
+ yield* Effect.forEach(renamedFrom.filter((formerFqn) => !migrationTargets.has(formerFqn)), (formerFqn) => state.delete({ stack: stackName, stage, fqn: formerFqn }), { concurrency: "unbounded" });
193
+ });
194
+ }, { concurrency: "unbounded" });
195
+ yield* executePlan(plan, tracker, outputs, terminalStatuses, reportEvent, state, stackName, stage);
196
+ // TODO(sam): support roll back to previous state if errors occur during expansion
197
+ // -> RISK: some UPDATEs may not be reversible (i.e. trigger replacements)
198
+ // TODO(sam): should pivot be done separately? E.g shift traffic?
199
+ yield* collectGarbage(plan, reportEvent);
200
+ yield* converge(plan, tracker, outputs, terminalStatuses, reportEvent, state, stackName, stage);
201
+ // Cycle members hold their terminal status until `converge` settles
202
+ // it; everything else announced it as it finished.
203
+ yield* Effect.forEach(Array.from(terminalStatuses.values()).filter(({ fqn, status }) => announced.get(fqn) !== status), ({ fqn, id, type, status, providerMode }) => reportEvent({
204
+ type: "apply.resource.status",
205
+ fqn,
206
+ id,
207
+ resourceType: type,
208
+ status,
209
+ providerMode,
210
+ }), { concurrency: "unbounded" });
211
+ if (plan.destroy) {
212
+ // The destroy converged: every resource row was deleted above. Drop
213
+ // the rest of the stage's persisted state — notably the stack output
214
+ // record written by the last deploy — so `getOutput` returns
215
+ // undefined and `listStages` no longer reports the stage.
216
+ // https://github.com/alchemy-run/alchemy/issues/961
217
+ yield* state.deleteStack({ stack: stackName, stage });
218
+ // Invariant: a successful destroy leaves the stage EMPTY. If rows
219
+ // survive, this destroy session could not actually see (or delete)
220
+ // the stack's state — e.g. its plan listed an empty store while
221
+ // committed rows existed — and reporting success here would silently
222
+ // leak every cloud resource those rows track. Fail loudly instead so
223
+ // the leak surfaces in the run that caused it.
224
+ const remaining = yield* state.list({ stack: stackName, stage });
225
+ if (remaining.length > 0) {
226
+ return yield* new StateStoreError({
227
+ message: `destroy of ${stackName}/${stage} reported success but ${remaining.length} ` +
228
+ `state row(s) remain (${remaining.join(", ")}) — the destroy session could ` +
229
+ `not see the stack's persisted state, so its cloud resources were NOT deleted`,
230
+ });
154
231
  }
155
- const resolved = yield* Output.evaluate(plan.output, outputs);
156
- // Persist the stack's evaluated outputs so cross-stack references
157
- // (`yield* OtherStack` / `OtherStack.stage.<name>` / `Output.stackRef`)
158
- // can read them back out of the state store.
159
- yield* state.setOutput({ stack: stackName, stage, value: resolved });
160
- return resolved;
161
- }).pipe(Effect.onExit((exit) => session.done(Exit.isSuccess(exit) ? "success" : "failure")));
232
+ return undefined;
233
+ }
234
+ if (plan.selectedFqns !== undefined || !plan.output) {
235
+ return undefined;
236
+ }
237
+ const resolved = yield* Output.evaluate(plan.output, outputs);
238
+ // Persist the stack's evaluated outputs so cross-stack references
239
+ // (`yield* OtherStack` / `OtherStack.stage.<name>` / `Output.stackRef`)
240
+ // can read them back out of the state store.
241
+ yield* state.setOutput({ stack: stackName, stage, value: resolved });
242
+ return resolved;
162
243
  }).pipe(ensureArtifactStore, Effect.withSpan("apply", {
163
244
  attributes: {
164
245
  "alchemy.resources.count": Object.keys(plan.resources).length,
@@ -171,20 +252,18 @@ export const apply = (plan, options = {}) => Effect.gen(function* () {
171
252
  // available in `tracker`." Resources with `precreate` signal early so that
172
253
  // downstream resources can resolve stable identifiers without deadlocking.
173
254
  // The actual output lives in the mutable `tracker` map, not in the Deferred.
174
- const executePlan = Effect.fn(function* (plan, tracker, outputs, terminalStatuses, session, state, stackName, stage) {
255
+ const executePlan = Effect.fn(function* (plan, tracker, outputs, terminalStatuses, reportEvent, state, stackName, stage) {
175
256
  // Resources and tasks share the same FQN namespace and DAG, so the
176
257
  // scheduler tracks them together. Each entry gets a single Deferred that
177
258
  // signals "my output is available in `tracker`."
178
259
  const allNodes = { ...plan.resources, ...plan.actions };
179
- const ready = Object.fromEntries(yield* Effect.all(Object.keys(allNodes).map((fqn) => Effect.map(Deferred.make(), (d) => [fqn, d]))));
260
+ const ready = Object.fromEntries(yield* Effect.forEach(Object.keys(allNodes), (fqn) => Effect.map(Deferred.make(), (d) => [fqn, d])));
180
261
  // `readyStable` fires only when a node has reached its TERMINAL output —
181
262
  // resources after `reconcile`, tasks after the body completes. Resource
182
263
  // precreate stubs do NOT signal `readyStable`, so any consumer that
183
264
  // requires stable inputs (e.g. Tasks) waits past the precreate phase.
184
- const readyStable = Object.fromEntries(yield* Effect.all(Object.keys(allNodes).map((fqn) => Effect.map(Deferred.make(), (d) => [fqn, d]))));
185
- const waitForDeps = (downstreamFqn, fqns) => Effect.all(fqns
186
- .filter((fqn) => fqn in ready)
187
- .map((fqn) =>
265
+ const readyStable = Object.fromEntries(yield* Effect.forEach(Object.keys(allNodes), (fqn) => Effect.map(Deferred.make(), (d) => [fqn, d])));
266
+ const waitForDeps = (downstreamFqn, fqns) => Effect.forEach(fqns.filter((fqn) => fqn in ready), (fqn) =>
188
267
  // Non-cycle upstreams must be observed at their TERMINAL output
189
268
  // (`readyStable`), not their early precreate signal (`ready`). This
190
269
  // is what makes a failed upstream actually interrupt its downstream:
@@ -202,12 +281,12 @@ const executePlan = Effect.fn(function* (plan, tracker, outputs, terminalStatuse
202
281
  // consumer cannot attach to a Worker's fetch-only precreate stub.
203
282
  plan.cycleMembers.has(downstreamFqn) && plan.cycleMembers.has(fqn)
204
283
  ? Deferred.await(ready[fqn])
205
- : Deferred.await(readyStable[fqn])), { concurrency: "unbounded" });
206
- const waitForStableDeps = (fqns) => Effect.all(fqns.filter((fqn) => fqn in readyStable).map((fqn) => Deferred.await(readyStable[fqn])), { concurrency: "unbounded" });
284
+ : Deferred.await(readyStable[fqn]), { concurrency: "unbounded" });
285
+ const waitForStableDeps = (fqns) => Effect.forEach(fqns.filter((fqn) => fqn in readyStable), (fqn) => Deferred.await(readyStable[fqn]), { concurrency: "unbounded" });
207
286
  const failures = [];
208
- yield* Effect.all(Object.entries(allNodes).map(([fqn, node]) => node.kind === "action"
209
- ? executeActionNode(fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, session, state, stackName, stage, waitForStableDeps, failures)
210
- : executeNode(fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, session, state, stackName, stage, (fqns) => waitForDeps(fqn, fqns), failures, plan.cycleMembers.has(fqn))), { concurrency: "unbounded" });
287
+ yield* Effect.forEach(Object.entries(allNodes), ([fqn, node]) => node.kind === "action"
288
+ ? executeActionNode(fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, reportEvent, state, stackName, stage, waitForStableDeps, failures)
289
+ : executeNode(fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, reportEvent, state, stackName, stage, (fqns) => waitForDeps(fqn, fqns), failures, plan.cycleMembers), { concurrency: "unbounded" });
211
290
  if (failures.length > 0) {
212
291
  // Aggregate every collected lifecycle failure into a single parallel Cause
213
292
  // so the apply ends with one combined error containing every distinct
@@ -237,13 +316,16 @@ const failureMessage = (cause) => {
237
316
  : undefined;
238
317
  const message = Predicate.hasProperty(error, "message") && typeof error.message === "string"
239
318
  ? error.message
240
- : String(error);
319
+ : typeof error === "string"
320
+ ? error
321
+ : Formatter.format(error);
241
322
  const line = message.split("\n", 1)[0];
242
323
  return tag !== undefined && !line.includes(tag) ? `${tag}: ${line}` : line;
243
324
  }
244
325
  return undefined;
245
326
  };
246
- const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, session, state, stackName, stage, waitForDeps, failures, inCycle) => Effect.gen(function* () {
327
+ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, reportEvent, state, stackName, stage, waitForDeps, failures, cycleMembers) => Effect.gen(function* () {
328
+ const inCycle = cycleMembers.has(fqn);
247
329
  const logicalId = node.resource.LogicalId;
248
330
  const namespace = node.resource.Namespace;
249
331
  const commit = (value) => state.set({
@@ -266,21 +348,13 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
266
348
  value: {
267
349
  ...value,
268
350
  adoptionBlocked: value.adoptionBlocked ?? node.adoptionBlocked,
351
+ propsIncomplete: propsIncomplete(value),
269
352
  props: stripUnresolved(value.props),
270
353
  bindings: stripUnresolved(value.bindings),
271
354
  namespace,
272
355
  },
273
356
  });
274
- const scopedSession = {
275
- ...session,
276
- note: (note, options) => session.emit({
277
- fqn,
278
- id: logicalId,
279
- _tag: "apply.resource.note",
280
- message: note,
281
- kind: options?.kind,
282
- }),
283
- };
357
+ const scopedSession = resourceSession(reportEvent, fqn, logicalId);
284
358
  // On a mode-switch replacement (local ⇄ live) surface the transition:
285
359
  // the old generation's stamped mode → the mode resolved for this run.
286
360
  const fromProviderMode = node.action === "replace" &&
@@ -289,11 +363,11 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
289
363
  node.state.providerMode !== node.mode
290
364
  ? node.state.providerMode
291
365
  : undefined;
292
- const report = (status) => session.emit({
293
- _tag: "apply.resource.status",
366
+ const report = (status) => reportEvent({
367
+ type: "apply.resource.status",
294
368
  fqn,
295
369
  id: logicalId,
296
- type: node.resource.Type,
370
+ resourceType: node.resource.Type,
297
371
  status,
298
372
  providerMode: node.mode,
299
373
  fromProviderMode,
@@ -330,11 +404,11 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
330
404
  // `terminalStatuses` after `converge` completes.
331
405
  if (inCycle)
332
406
  return;
333
- yield* session.emit({
334
- _tag: "apply.resource.status",
407
+ yield* reportEvent({
408
+ type: "apply.resource.status",
335
409
  fqn,
336
410
  id: logicalId,
337
- type: node.resource.Type,
411
+ resourceType: node.resource.Type,
338
412
  status,
339
413
  providerMode: node.mode,
340
414
  });
@@ -400,6 +474,17 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
400
474
  const bindingDeps = Object.keys(Output.resolveUpstream(node.bindings));
401
475
  return [...new Set([...propDeps, ...bindingDeps])];
402
476
  };
477
+ // A cycle precreates before its peers reconcile. An upstream outside the
478
+ // cycle cannot depend on it, so wait for those upstreams and resolve the
479
+ // props they determine: only values derived from cycle peers stay
480
+ // unresolved when precreate and `observe` run.
481
+ const resolvePrecreateProps = Effect.gen(function* () {
482
+ const outside = allUpstreamFqns().filter((upstream) => !cycleMembers.has(upstream));
483
+ yield* waitForDeps(outside);
484
+ return yield* Output.evaluateAvailable(node.props, Object.fromEntries(outside
485
+ .filter((upstream) => Object.hasOwn(outputs, upstream))
486
+ .map((upstream) => [upstream, outputs[upstream]])));
487
+ });
403
488
  // ── instance ID ──
404
489
  const resolveInstanceId = Effect.gen(function* () {
405
490
  if (node.action === "create" && !node.state?.instanceId) {
@@ -475,6 +560,8 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
475
560
  });
476
561
  }
477
562
  let attr = node.state?.attr;
563
+ // Whether the identity reconcile claims has passed the ownership check.
564
+ let admitted = node.deferredAdoption === undefined;
478
565
  if (attr !== undefined) {
479
566
  // Precreate/read may already have produced a usable output snapshot. Publish
480
567
  // it early so downstream resources can start resolving against it.
@@ -486,6 +573,10 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
486
573
  // Durable Object classes are empty) can serve traffic while the real
487
574
  // version propagates.
488
575
  if (inCycle && node.provider.precreate && attr === undefined) {
576
+ const props = yield* resolvePrecreateProps;
577
+ // Without `observe`, precreate and reconcile claim the identity unchecked.
578
+ admitted =
579
+ (yield* observeBeforePrecreate(node, props, fqn, logicalId, instanceId)) !== "unresolved";
489
580
  // Some resources need a placeholder physical resource before their real
490
581
  // create can finish. Persist that stub so downstream evaluation can proceed.
491
582
  yield* report("pre-creating");
@@ -493,7 +584,7 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
493
584
  .precreate({
494
585
  id: logicalId,
495
586
  fqn,
496
- news: node.props,
587
+ news: props,
497
588
  session: scopedSession,
498
589
  instanceId,
499
590
  bindings: excludeDeletedBindings(node.bindings),
@@ -506,7 +597,9 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
506
597
  instanceId,
507
598
  resourceType: node.resource.Type,
508
599
  props: node.props,
509
- attr,
600
+ // A stub for an unresolved identity claims nothing. Leave the
601
+ // checkpoint without it, so a retry checks the identity again.
602
+ attr: admitted ? attr : undefined,
510
603
  providerVersion: node.provider.version ?? 0,
511
604
  bindings: excludeDeletedBindings(node.bindings),
512
605
  downstream: node.downstream,
@@ -526,8 +619,8 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
526
619
  yield* report("creating");
527
620
  const news = (yield* Output.evaluate(node.props, outputs));
528
621
  const bindingOutputs = excludeDeletedBindings(yield* Output.evaluate(node.bindings, outputs));
529
- if (attr === undefined && node.deferredAdoption && node.provider.read) {
530
- const checkpoint = () => commit({
622
+ if (!admitted) {
623
+ const checkpoint = (attr) => commit({
531
624
  status: "creating",
532
625
  fqn,
533
626
  logicalId,
@@ -542,13 +635,12 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
542
635
  providerMode: node.mode,
543
636
  adoptionBlocked: node.adoptionBlocked,
544
637
  });
545
- // Refusal or interruption must retain identity, never foreign attributes.
546
- yield* checkpoint();
547
- const observed = yield* node.provider
548
- .read({ id: logicalId, fqn, instanceId, olds: news, output: undefined })
549
- .pipe(instrumentLifecycle("read", fqn, node.resource.Type, logicalId, instanceId));
638
+ // Refusal or interruption must retain identity, never foreign
639
+ // attributes, nor a stub for an identity not yet checked.
640
+ yield* checkpoint(undefined);
641
+ const observed = yield* observeResolved(node, news, fqn, logicalId, instanceId);
550
642
  if (observed !== undefined) {
551
- if (Unowned.is(observed) && !node.deferredAdoption.adopt) {
643
+ if (Unowned.is(observed) && !node.deferredAdoption?.adopt) {
552
644
  return yield* new OwnedBySomeoneElse({
553
645
  message: `Cannot adopt resource '${fqn}' (${node.resource.Type}): ` +
554
646
  "it exists in the cloud but is not owned by this " +
@@ -558,9 +650,10 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
558
650
  logicalId,
559
651
  });
560
652
  }
561
- attr = stripUnowned(observed);
653
+ // Reconcile keeps a precreated stub as its output.
654
+ attr ??= stripUnowned(observed);
562
655
  // A creating checkpoint retains olds: undefined on retry.
563
- yield* checkpoint();
656
+ yield* checkpoint(attr);
564
657
  }
565
658
  }
566
659
  attr = yield* node.provider
@@ -824,11 +917,76 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
824
917
  yield* deleteOldGenerations(old.old);
825
918
  }
826
919
  });
827
- if (node.deleteFirst) {
920
+ const deleteFirst = Effect.fn(function* () {
828
921
  yield* scopedSession.note("Deleting previous resource before creating its replacement (deleteFirst)...");
829
922
  yield* deleteOldGenerations(replState.old);
830
- }
923
+ });
831
924
  let attr = replState.attr;
925
+ // ── replacement admission ──
926
+ //
927
+ // The replacement may resolve to a physical identity that already
928
+ // exists and belongs to someone else (e.g. a renamed Worker pointing at
929
+ // a foreign script). Read it before anything is mutated — before
930
+ // precreate, reconcile, and delete-first cleanup of the previous
931
+ // generation — and refuse an unowned target unless adoption is allowed,
932
+ // exactly like a fresh create.
933
+ let admitted = attr !== undefined || node.deferredAdoption === undefined;
934
+ const admit = Effect.fn(function* (props) {
935
+ admitted = true;
936
+ const observed = yield* observeResolved(node, props, fqn, logicalId, instanceId, replState.old?.attr);
937
+ if (observed === undefined)
938
+ return;
939
+ if (Unowned.is(observed) && !node.deferredAdoption?.adopt) {
940
+ return yield* new OwnedBySomeoneElse({
941
+ message: `Cannot replace resource '${fqn}' (${node.resource.Type}): ` +
942
+ "its replacement exists in the cloud but is not owned by this " +
943
+ "stack/stage/logical-id. Re-run with `--adopt` (or " +
944
+ "wrap the effect in `adopt(true)`) to take it over.",
945
+ resourceType: node.resource.Type,
946
+ logicalId,
947
+ });
948
+ }
949
+ // A delete-first target may be the previous generation itself, which
950
+ // is about to be deleted — never hand its attributes to reconcile.
951
+ // Reconcile keeps a precreated stub as its output.
952
+ if (!node.deleteFirst)
953
+ attr ??= stripUnowned(observed);
954
+ });
955
+ // A cycle precreates on the props its upstreams outside the cycle
956
+ // determine; anything else waits for every upstream.
957
+ const precreateProps = inCycle ? yield* resolvePrecreateProps : node.props;
958
+ if (!admitted && isResolved(precreateProps)) {
959
+ yield* admit(precreateProps);
960
+ }
961
+ // A cycle precreates before its props resolve, so `observe` admits the
962
+ // identity precreate will claim — before delete-first, too. Without
963
+ // `observe`, precreate and reconcile claim it unchecked. An unresolved
964
+ // identity is admitted once it resolves, before reconcile.
965
+ if (!admitted && inCycle) {
966
+ const observation = yield* observeBeforePrecreate(node, precreateProps, fqn, logicalId, instanceId, replState.old?.attr);
967
+ admitted = observation !== "unresolved";
968
+ if (!admitted && node.deleteFirst && !node.deferredAdoption?.adopt) {
969
+ return yield* new UnverifiableReplacement({
970
+ message: `Cannot replace resource '${fqn}' (${node.resource.Type}): ` +
971
+ "it must be deleted before its replacement is pre-created, but " +
972
+ "the replacement's identity depends on outputs that are not " +
973
+ "resolved yet, so its ownership cannot be checked first. Re-run " +
974
+ "with `--adopt` (or wrap the effect in `adopt(true)`) to replace it anyway.",
975
+ resourceType: node.resource.Type,
976
+ logicalId,
977
+ });
978
+ }
979
+ }
980
+ // A cycle must delete before precreate claims the identity. Plan has
981
+ // already refused one whose identity could not be admitted first
982
+ // without `observe`; the check above refuses an unresolved one.
983
+ // Otherwise the previous generation survives until reconcile is
984
+ // about to run, so a failed upstream never leaves the resource missing.
985
+ let deletedFirst = false;
986
+ if (node.deleteFirst && inCycle) {
987
+ yield* deleteFirst();
988
+ deletedFirst = true;
989
+ }
832
990
  if (attr !== undefined) {
833
991
  // If precreate already ran, expose that intermediate output immediately so
834
992
  // downstream resources can resolve against the same in-flight replacement.
@@ -840,7 +998,7 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
840
998
  .precreate({
841
999
  id: logicalId,
842
1000
  fqn,
843
- news: node.props,
1001
+ news: precreateProps,
844
1002
  session: scopedSession,
845
1003
  instanceId,
846
1004
  bindings: excludeDeletedBindings(node.bindings),
@@ -853,7 +1011,9 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
853
1011
  instanceId,
854
1012
  resourceType: node.resource.Type,
855
1013
  props: node.props,
856
- attr,
1014
+ // A stub for an unresolved identity claims nothing. Leave the
1015
+ // checkpoint without it, so a retry checks the identity again.
1016
+ attr: admitted ? attr : undefined,
857
1017
  providerVersion: node.provider.version ?? 0,
858
1018
  bindings: excludeDeletedBindings(node.bindings),
859
1019
  downstream: node.downstream,
@@ -873,6 +1033,12 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
873
1033
  yield* report("creating replacement");
874
1034
  const news = (yield* Output.evaluate(node.props, outputs));
875
1035
  const bindingOutputs = excludeDeletedBindings(yield* Output.evaluate(node.bindings, outputs));
1036
+ if (!admitted) {
1037
+ yield* admit(news);
1038
+ }
1039
+ if (node.deleteFirst && !deletedFirst) {
1040
+ yield* deleteFirst();
1041
+ }
876
1042
  attr = yield* node.provider
877
1043
  .reconcile({
878
1044
  id: logicalId,
@@ -945,18 +1111,18 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
945
1111
  }).pipe(Effect.catchCause((cause) =>
946
1112
  // Record the failure, propagate it to any downstream resources waiting on
947
1113
  // our Deferred (so their waitForDeps short-circuits instead of deadlocking),
948
- // emit a "fail" status to the session, and resolve to void so Effect.all
1114
+ // emit a "fail" status, and resolve to void so Effect.all
949
1115
  // does not interrupt sibling fibers. The aggregated cause is raised at
950
1116
  // the end of executePlan.
951
1117
  Effect.gen(function* () {
952
1118
  failures.push({ fqn, logicalId: node.resource.LogicalId, type: node.resource.Type, cause });
953
1119
  yield* Deferred.failCause(ready[fqn], cause);
954
1120
  yield* Deferred.failCause(readyStable[fqn], cause);
955
- yield* session.emit({
956
- _tag: "apply.resource.status",
1121
+ yield* reportEvent({
1122
+ type: "apply.resource.status",
957
1123
  fqn,
958
1124
  id: node.resource.LogicalId,
959
- type: node.resource.Type,
1125
+ resourceType: node.resource.Type,
960
1126
  status: "fail",
961
1127
  message: failureMessage(cause),
962
1128
  providerMode: node.mode,
@@ -989,12 +1155,18 @@ const runAction = Effect.fn("apply.runAction")(function* (task, input, outputs)
989
1155
  .Run(input)
990
1156
  .pipe(Effect.provideService(RuntimeContext, makeResolveContext(resolved)));
991
1157
  });
992
- const executeActionNode = (fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, session, state, stackName, stage, waitForDeps, failures) => Effect.gen(function* () {
1158
+ const executeActionNode = (fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, reportEvent, state, stackName, stage, waitForDeps, failures) => Effect.gen(function* () {
993
1159
  const task = node.def;
994
1160
  const logicalId = task.LogicalId;
995
1161
  const namespace = task.Namespace;
996
1162
  const commit = (value) => state.set({ stack: stackName, stage, fqn, value: { ...value, namespace } });
997
- const report = (status) => session.emit({ _tag: "apply.resource.status", fqn, id: logicalId, type: task.Type, status });
1163
+ const report = (status) => reportEvent({
1164
+ type: "apply.resource.status",
1165
+ fqn,
1166
+ id: logicalId,
1167
+ resourceType: task.Type,
1168
+ status,
1169
+ });
998
1170
  const signalReady = Deferred.succeed(ready[fqn], void 0);
999
1171
  const signalReadyStable = Deferred.succeed(readyStable[fqn], void 0);
1000
1172
  const skip = (state) => Effect.gen(function* () {
@@ -1070,11 +1242,11 @@ const executeActionNode = (fqn, node, tracker, outputs, ready, readyStable, term
1070
1242
  failures.push({ fqn, logicalId: node.def.LogicalId, type: node.def.Type, cause });
1071
1243
  yield* Deferred.failCause(ready[fqn], cause);
1072
1244
  yield* Deferred.failCause(readyStable[fqn], cause);
1073
- yield* session.emit({
1074
- _tag: "apply.resource.status",
1245
+ yield* reportEvent({
1246
+ type: "apply.resource.status",
1075
1247
  fqn,
1076
1248
  id: node.def.LogicalId,
1077
- type: node.def.Type,
1249
+ resourceType: node.def.Type,
1078
1250
  status: "fail",
1079
1251
  message: failureMessage(cause),
1080
1252
  });
@@ -1094,7 +1266,7 @@ const executeActionNode = (fqn, node, tracker, outputs, ready, readyStable, term
1094
1266
  // against the current tracker outputs. Call provider.reconcile for any
1095
1267
  // resource whose resolved inputs differ from what it was last applied with.
1096
1268
  // Repeat until no resource needs updating.
1097
- const converge = Effect.fn(function* (plan, tracker, outputs, terminalStatuses, session, state, stackName, stage) {
1269
+ const converge = Effect.fn(function* (plan, tracker, outputs, terminalStatuses, reportEvent, state, stackName, stage) {
1098
1270
  for (;;) {
1099
1271
  let anyUpdated = false;
1100
1272
  for (const [fqn, node] of Object.entries(plan.resources)) {
@@ -1114,16 +1286,24 @@ const converge = Effect.fn(function* (plan, tracker, outputs, terminalStatuses,
1114
1286
  const logicalId = node.resource.LogicalId;
1115
1287
  const namespace = node.resource.Namespace;
1116
1288
  const instanceId = tracker[fqn].instanceId;
1117
- const scopedSession = {
1118
- ...session,
1119
- note: (note, options) => session.emit({
1120
- fqn,
1121
- id: logicalId,
1122
- _tag: "apply.resource.note",
1123
- message: note,
1124
- kind: options?.kind,
1125
- }),
1126
- };
1289
+ const scopedSession = resourceSession(reportEvent, fqn, logicalId);
1290
+ // A cycle peer resolves against its peers' first outputs, so an
1291
+ // identity checked then may resolve differently now. Check the identity
1292
+ // these props resolve to before reconcile claims it.
1293
+ const deferredAdoption = "deferredAdoption" in node ? node.deferredAdoption : undefined;
1294
+ if (propsChanged && deferredAdoption !== undefined) {
1295
+ const observed = yield* observeResolved(node, newProps, fqn, logicalId, instanceId, tracker[fqn].output);
1296
+ if (observed !== undefined && Unowned.is(observed) && !deferredAdoption.adopt) {
1297
+ return yield* new OwnedBySomeoneElse({
1298
+ message: `Cannot converge resource '${fqn}' (${node.resource.Type}): ` +
1299
+ "its final identity exists in the cloud but is not owned by this " +
1300
+ "stack/stage/logical-id. Re-run with `--adopt` (or " +
1301
+ "wrap the effect in `adopt(true)`) to take it over.",
1302
+ resourceType: node.resource.Type,
1303
+ logicalId,
1304
+ });
1305
+ }
1306
+ }
1127
1307
  const attr = yield* node.provider
1128
1308
  .reconcile({
1129
1309
  id: logicalId,
@@ -1264,7 +1444,7 @@ export class DestroyError extends Data.TaggedError("DestroyError") {
1264
1444
  ].join("\n");
1265
1445
  }
1266
1446
  }
1267
- const collectGarbage = Effect.fn(function* (plan, session) {
1447
+ const collectGarbage = Effect.fn(function* (plan, reportEvent) {
1268
1448
  const state = yield* yield* State;
1269
1449
  const stack = yield* Stack;
1270
1450
  const stackName = stack.name;
@@ -1272,25 +1452,25 @@ const collectGarbage = Effect.fn(function* (plan, session) {
1272
1452
  // Task deletions are pure state drops — no body is invoked. Run them in
1273
1453
  // parallel before resource GC; tasks never have provider-side dependencies
1274
1454
  // to wait on.
1275
- yield* Effect.all(Object.entries(plan.actionDeletions ?? {}).map(([fqn, node]) => node === undefined
1455
+ yield* Effect.forEach(Object.entries(plan.actionDeletions ?? {}), ([fqn, node]) => node === undefined
1276
1456
  ? Effect.void
1277
1457
  : Effect.gen(function* () {
1278
- yield* session.emit({
1279
- _tag: "apply.resource.status",
1458
+ yield* reportEvent({
1459
+ type: "apply.resource.status",
1280
1460
  fqn,
1281
1461
  id: node.def.LogicalId,
1282
- type: node.def.Type,
1462
+ resourceType: node.def.Type,
1283
1463
  status: "deleting",
1284
1464
  });
1285
1465
  yield* state.delete({ stack: stackName, stage, fqn });
1286
- yield* session.emit({
1287
- _tag: "apply.resource.status",
1466
+ yield* reportEvent({
1467
+ type: "apply.resource.status",
1288
1468
  fqn,
1289
1469
  id: node.def.LogicalId,
1290
- type: node.def.Type,
1470
+ resourceType: node.def.Type,
1291
1471
  status: "deleted",
1292
1472
  });
1293
- })), { concurrency: "unbounded" });
1473
+ }), { concurrency: "unbounded" });
1294
1474
  // Failures are collected — not propagated — so one bad delete never
1295
1475
  // strands unrelated siblings. `unresolved` tracks every FQN whose delete
1296
1476
  // failed or was blocked this run: later passes must not retry them (a
@@ -1356,6 +1536,9 @@ const collectGarbage = Effect.fn(function* (plan, session) {
1356
1536
  const adoptionBlocked = isDeleteNode(node)
1357
1537
  ? node.state.adoptionBlocked
1358
1538
  : generation.adoptionBlocked;
1539
+ const incompleteProps = isDeleteNode(node)
1540
+ ? node.state.propsIncomplete
1541
+ : generation.propsIncomplete;
1359
1542
  // Mutable: an attr-less row (interrupted create) may recover its
1360
1543
  // attributes from `provider.read` below, right before deletion.
1361
1544
  let attr = persistedAttr;
@@ -1375,31 +1558,22 @@ const collectGarbage = Effect.fn(function* (plan, session) {
1375
1558
  namespace,
1376
1559
  },
1377
1560
  });
1378
- const report = (status) => session.emit({
1379
- _tag: "apply.resource.status",
1561
+ const report = (status) => reportEvent({
1562
+ type: "apply.resource.status",
1380
1563
  fqn,
1381
1564
  id: logicalId,
1382
- type: resourceType,
1565
+ resourceType,
1383
1566
  status,
1384
1567
  providerMode,
1385
1568
  });
1386
- const scopedSession = {
1387
- ...session,
1388
- note: (note, options) => session.emit({
1389
- fqn,
1390
- id: logicalId,
1391
- _tag: "apply.resource.note",
1392
- message: note,
1393
- kind: options?.kind,
1394
- }),
1395
- };
1569
+ const scopedSession = resourceSession(reportEvent, fqn, logicalId);
1396
1570
  return yield* (deletions[fqn] ??= yield* Effect.cached(Effect.gen(function* () {
1397
1571
  // Dependents (`downstream`) are deleted before this resource. A
1398
1572
  // dependent whose delete failed (or was itself blocked) may make
1399
1573
  // this resource legitimately undeletable (dependency violation),
1400
1574
  // so it is skipped with a "blocked by" note instead of surfacing
1401
1575
  // a spurious second error.
1402
- const dependents = yield* Effect.all(downstream.map((dep) => dep !== fqn && !ancestors.has(dep)
1576
+ const dependents = yield* Effect.forEach(downstream, (dep) => dep !== fqn && !ancestors.has(dep)
1403
1577
  ? dep in deletionGraph
1404
1578
  ? deleteResource(deletionGraph[dep], nextAncestors).pipe(Effect.map((outcome) => ({ dep, outcome })))
1405
1579
  : // Not in this pass's graph — but it may have failed in
@@ -1408,7 +1582,7 @@ const collectGarbage = Effect.fn(function* (plan, session) {
1408
1582
  dep,
1409
1583
  outcome: unresolved.has(dep) ? "failed" : "deleted",
1410
1584
  }))
1411
- : Effect.succeed({ dep, outcome: "deleted" })), { concurrency: "unbounded" });
1585
+ : Effect.succeed({ dep, outcome: "deleted" }), { concurrency: "unbounded" });
1412
1586
  const blockedBy = dependents
1413
1587
  .filter(({ outcome }) => outcome === "failed" || outcome === "blocked")
1414
1588
  .map(({ dep }) => dep);
@@ -1470,6 +1644,12 @@ const collectGarbage = Effect.fn(function* (plan, session) {
1470
1644
  "migrated predecessor. Any interrupted new physical " +
1471
1645
  "resource must be identified and cleaned up manually.");
1472
1646
  }
1647
+ else if (incompleteProps) {
1648
+ yield* scopedSession.note("Skipping recovery: unresolved properties were omitted from " +
1649
+ "this interrupted create's state, so they cannot identify it. " +
1650
+ "Any interrupted physical resource must be identified and " +
1651
+ "cleaned up manually.");
1652
+ }
1473
1653
  else if (provider.read) {
1474
1654
  const recovered = yield* provider
1475
1655
  .read({ id: logicalId, fqn, instanceId, olds: props, output: undefined })
@@ -1522,6 +1702,7 @@ const collectGarbage = Effect.fn(function* (plan, session) {
1522
1702
  removalPolicy: node.resource.RemovalPolicy,
1523
1703
  providerMode,
1524
1704
  adoptionBlocked,
1705
+ propsIncomplete: incompleteProps,
1525
1706
  });
1526
1707
  }
1527
1708
  if (attr !== undefined && !retainOldGeneration) {
@@ -1583,6 +1764,7 @@ const collectGarbage = Effect.fn(function* (plan, session) {
1583
1764
  bindings: excludeDeletedBindings(node.bindings),
1584
1765
  removalPolicy: node.removalPolicy,
1585
1766
  providerMode: node.providerMode,
1767
+ propsIncomplete: node.propsIncomplete,
1586
1768
  });
1587
1769
  }
1588
1770
  yield* scopedSession.note(retainOldGeneration
@@ -1605,9 +1787,7 @@ const collectGarbage = Effect.fn(function* (plan, session) {
1605
1787
  // retained) inside each node's delete effect — the effects resolve to
1606
1788
  // outcomes and never fail, so one bad resource never interrupts sibling
1607
1789
  // deletions mid-flight.
1608
- yield* Effect.all(Object.values(deletionGraph)
1609
- .filter((node) => node !== undefined)
1610
- .map((node) => deleteResource(node)), { concurrency: "unbounded" });
1790
+ yield* Effect.forEach(Object.values(deletionGraph).filter((node) => node !== undefined), (node) => deleteResource(node), { concurrency: "unbounded" });
1611
1791
  });
1612
1792
  // Drain one old generation per FQN per pass, preserving that generation's
1613
1793
  // dependency edges. Planned deletions remain queued until their chains drain.