@mysten-incubation/devstack 0.0.1 → 0.1.1

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 (838) hide show
  1. package/README.md +8 -4
  2. package/dashboard-ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  3. package/dashboard-ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  4. package/dashboard-ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  5. package/dashboard-ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  6. package/dashboard-ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
  7. package/dashboard-ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
  8. package/dashboard-ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
  9. package/dashboard-ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
  10. package/dashboard-ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
  11. package/dashboard-ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
  12. package/dashboard-ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  13. package/dashboard-ui/assets/index-Bmi1UtAg.js +1356 -0
  14. package/dashboard-ui/assets/index-D5EShVt4.js +3 -0
  15. package/dashboard-ui/assets/index-Deml9drg.css +1 -0
  16. package/dashboard-ui/index.html +13 -0
  17. package/dist/api/define-capabilities.d.mts +14 -3
  18. package/dist/api/define-capabilities.mjs +18 -1
  19. package/dist/api/define-capabilities.mjs.map +1 -1
  20. package/dist/api/define-devstack.d.mts +1 -1
  21. package/dist/api/define-devstack.mjs +6 -26
  22. package/dist/api/define-devstack.mjs.map +1 -1
  23. package/dist/api/define-plugin.d.mts +1 -0
  24. package/dist/api/define-plugin.mjs +2 -0
  25. package/dist/api/inference-network.d.mts +132 -0
  26. package/dist/api/inference-network.mjs +105 -16
  27. package/dist/api/inference-network.mjs.map +1 -1
  28. package/dist/api/plugin-errors.d.mts +7 -0
  29. package/dist/api/run-stack.d.mts +20 -9
  30. package/dist/api/run-stack.mjs +56 -29
  31. package/dist/api/run-stack.mjs.map +1 -1
  32. package/dist/build-integrations/playwright/config.d.mts +6 -4
  33. package/dist/build-integrations/playwright/config.mjs +5 -3
  34. package/dist/build-integrations/playwright/config.mjs.map +1 -1
  35. package/dist/build-integrations/playwright/errors.d.mts +1 -1
  36. package/dist/build-integrations/playwright/global-setup.d.mts +43 -17
  37. package/dist/build-integrations/playwright/global-setup.mjs +250 -13
  38. package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
  39. package/dist/build-integrations/playwright/index.d.mts +5 -3
  40. package/dist/build-integrations/playwright/index.mjs +4 -2
  41. package/dist/build-integrations/playwright/stack-context.d.mts +0 -1
  42. package/dist/build-integrations/playwright/stack-context.mjs +24 -63
  43. package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
  44. package/dist/build-integrations/playwright/wallet-context.d.mts +7 -10
  45. package/dist/build-integrations/playwright/wallet-context.mjs +8 -13
  46. package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
  47. package/dist/build-integrations/runtime/cold-start-url.d.mts +5 -0
  48. package/dist/build-integrations/runtime/cold-start-url.mjs +4 -3
  49. package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
  50. package/dist/build-integrations/runtime/conventional-routes.d.mts +51 -0
  51. package/dist/build-integrations/runtime/conventional-routes.mjs +92 -0
  52. package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -0
  53. package/dist/build-integrations/runtime/discover.d.mts +38 -30
  54. package/dist/build-integrations/runtime/discover.mjs +73 -70
  55. package/dist/build-integrations/runtime/discover.mjs.map +1 -1
  56. package/dist/build-integrations/runtime/endpoint-registry.d.mts +3 -1
  57. package/dist/build-integrations/runtime/endpoint-registry.mjs +3 -1
  58. package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
  59. package/dist/build-integrations/runtime/index.d.mts +7 -2
  60. package/dist/build-integrations/runtime/index.mjs +9 -2
  61. package/dist/build-integrations/runtime/manifest-types.d.mts +2 -0
  62. package/dist/build-integrations/runtime/manifest-types.mjs +3 -0
  63. package/dist/build-integrations/runtime/playwright-stack-context-slot.d.mts +29 -0
  64. package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs +10 -0
  65. package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs.map +1 -0
  66. package/dist/build-integrations/runtime/read-stack-context.d.mts +1 -1
  67. package/dist/build-integrations/runtime/read-stack-context.mjs +10 -4
  68. package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
  69. package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +48 -0
  70. package/dist/build-integrations/runtime/resolve-discovery-env.mjs +42 -0
  71. package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -0
  72. package/dist/build-integrations/runtime/stack-context.d.mts +1 -1
  73. package/dist/build-integrations/runtime/wallet-paths.mjs +2 -0
  74. package/dist/build-integrations/vite/index.d.mts +51 -0
  75. package/dist/build-integrations/vite/index.mjs +73 -0
  76. package/dist/build-integrations/vite/index.mjs.map +1 -0
  77. package/dist/build-integrations/vitest/env.d.mts +4 -3
  78. package/dist/build-integrations/vitest/env.mjs +6 -4
  79. package/dist/build-integrations/vitest/env.mjs.map +1 -1
  80. package/dist/build-integrations/vitest/errors.d.mts +25 -4
  81. package/dist/build-integrations/vitest/errors.mjs +15 -2
  82. package/dist/build-integrations/vitest/errors.mjs.map +1 -1
  83. package/dist/build-integrations/vitest/index.d.mts +2 -2
  84. package/dist/build-integrations/vitest/index.mjs +3 -3
  85. package/dist/build-integrations/vitest/setup.d.mts +4 -2
  86. package/dist/build-integrations/vitest/setup.mjs +2 -2
  87. package/dist/build-integrations/vitest/setup.mjs.map +1 -1
  88. package/dist/build-integrations/vitest/stack-context.d.mts +0 -1
  89. package/dist/build-integrations/vitest/stack-context.mjs +33 -13
  90. package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
  91. package/dist/cli/bail.mjs +23 -0
  92. package/dist/cli/bail.mjs.map +1 -0
  93. package/dist/{surfaces/cli/commands → cli}/doctor-probes.mjs +26 -16
  94. package/dist/cli/doctor-probes.mjs.map +1 -0
  95. package/dist/cli/main.d.mts +15 -1
  96. package/dist/cli/main.mjs +166 -482
  97. package/dist/cli/main.mjs.map +1 -1
  98. package/dist/cli/prune-direct.mjs +31 -201
  99. package/dist/cli/prune-direct.mjs.map +1 -1
  100. package/dist/cli/snapshot-reader.mjs +14 -11
  101. package/dist/cli/snapshot-reader.mjs.map +1 -1
  102. package/dist/cli/up-lifecycle.mjs +4 -1
  103. package/dist/cli/up-lifecycle.mjs.map +1 -1
  104. package/dist/cli/wirings/apply.mjs +95 -0
  105. package/dist/cli/wirings/apply.mjs.map +1 -0
  106. package/dist/cli/wirings/build-verb-layers.mjs +42 -0
  107. package/dist/cli/wirings/build-verb-layers.mjs.map +1 -0
  108. package/dist/cli/wirings/config-loader.mjs +69 -0
  109. package/dist/cli/wirings/config-loader.mjs.map +1 -0
  110. package/dist/cli/wirings/engine-command.mjs +30 -0
  111. package/dist/cli/wirings/engine-command.mjs.map +1 -0
  112. package/dist/cli/wirings/identity.mjs +72 -0
  113. package/dist/cli/wirings/identity.mjs.map +1 -0
  114. package/dist/cli/wirings/provide-file-system.mjs +7 -0
  115. package/dist/cli/wirings/provide-file-system.mjs.map +1 -0
  116. package/dist/cli/wirings/snapshot.mjs +177 -0
  117. package/dist/cli/wirings/snapshot.mjs.map +1 -0
  118. package/dist/cli/wirings/up.mjs +287 -0
  119. package/dist/cli/wirings/up.mjs.map +1 -0
  120. package/dist/cli/wirings/wipe.mjs +40 -0
  121. package/dist/cli/wirings/wipe.mjs.map +1 -0
  122. package/dist/contracts/capability-decl.d.mts +0 -2
  123. package/dist/contracts/codegenable.d.mts +43 -0
  124. package/dist/contracts/container-runtime.d.mts +26 -1
  125. package/dist/contracts/faucet-strategy.d.mts +25 -0
  126. package/dist/contracts/funding-strategy.d.mts +42 -0
  127. package/dist/contracts/plugin-expander.mjs +60 -0
  128. package/dist/contracts/plugin-expander.mjs.map +1 -0
  129. package/dist/contracts/projection.d.mts +5 -3
  130. package/dist/contracts/renderer.d.mts +23 -0
  131. package/dist/contracts/routable.d.mts +14 -1
  132. package/dist/contracts/snapshotable.d.mts +25 -3
  133. package/dist/contracts/wallet-protocol.d.mts +52 -0
  134. package/dist/contracts/wallet-protocol.mjs +52 -0
  135. package/dist/contracts/wallet-protocol.mjs.map +1 -0
  136. package/dist/index.d.mts +26 -25
  137. package/dist/index.mjs +20 -13
  138. package/dist/{runtime → orchestrators}/built-in-plugin-layers.mjs +10 -5
  139. package/dist/orchestrators/built-in-plugin-layers.mjs.map +1 -0
  140. package/dist/orchestrators/codegen/bindings.d.mts +1 -2
  141. package/dist/orchestrators/codegen/bindings.mjs +52 -186
  142. package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
  143. package/dist/orchestrators/codegen/emit.mjs +19 -1
  144. package/dist/orchestrators/codegen/emit.mjs.map +1 -1
  145. package/dist/orchestrators/codegen/errors.mjs +8 -3
  146. package/dist/orchestrators/codegen/errors.mjs.map +1 -1
  147. package/dist/orchestrators/codegen/format.mjs +47 -39
  148. package/dist/orchestrators/codegen/format.mjs.map +1 -1
  149. package/dist/orchestrators/codegen/gitignore.mjs +3 -1
  150. package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
  151. package/dist/orchestrators/codegen/output-location.mjs +41 -0
  152. package/dist/orchestrators/codegen/output-location.mjs.map +1 -0
  153. package/dist/orchestrators/codegen/paths.d.mts +1 -1
  154. package/dist/orchestrators/codegen/paths.mjs +40 -14
  155. package/dist/orchestrators/codegen/paths.mjs.map +1 -1
  156. package/dist/orchestrators/codegen/permissions.mjs +3 -1
  157. package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
  158. package/dist/orchestrators/codegen/service.mjs +157 -105
  159. package/dist/orchestrators/codegen/service.mjs.map +1 -1
  160. package/dist/orchestrators/lifecycle-prune/errors.mjs +31 -0
  161. package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -0
  162. package/dist/orchestrators/lifecycle-prune/index.mjs +350 -0
  163. package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -0
  164. package/dist/orchestrators/router/cleanup.mjs +26 -27
  165. package/dist/orchestrators/router/cleanup.mjs.map +1 -1
  166. package/dist/orchestrators/router/entrypoints.mjs +2 -2
  167. package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
  168. package/dist/orchestrators/router/file-provider.mjs +14 -5
  169. package/dist/orchestrators/router/file-provider.mjs.map +1 -1
  170. package/dist/orchestrators/router/hostname.mjs +19 -55
  171. package/dist/orchestrators/router/hostname.mjs.map +1 -1
  172. package/dist/orchestrators/router/index.mjs +11 -0
  173. package/dist/orchestrators/router/profile.mjs +2 -2
  174. package/dist/orchestrators/router/sentinels.mjs +26 -0
  175. package/dist/orchestrators/router/sentinels.mjs.map +1 -0
  176. package/dist/orchestrators/router/service.mjs +40 -37
  177. package/dist/orchestrators/router/service.mjs.map +1 -1
  178. package/dist/orchestrators/router/traefik-container.mjs +27 -16
  179. package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
  180. package/dist/{substrate/runtime → orchestrators}/run.mjs +26 -21
  181. package/dist/orchestrators/run.mjs.map +1 -0
  182. package/dist/orchestrators/runtime-composition.d.mts +1 -1
  183. package/dist/orchestrators/runtime-composition.mjs +123 -39
  184. package/dist/orchestrators/runtime-composition.mjs.map +1 -1
  185. package/dist/orchestrators/snapshot/capture-command.d.mts +1 -0
  186. package/dist/orchestrators/snapshot/capture-command.mjs +25 -0
  187. package/dist/orchestrators/snapshot/capture-command.mjs.map +1 -0
  188. package/dist/orchestrators/snapshot/capture.mjs +42 -28
  189. package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
  190. package/dist/orchestrators/snapshot/descriptor.mjs +35 -10
  191. package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
  192. package/dist/orchestrators/snapshot/identity-guard.mjs +1 -1
  193. package/dist/orchestrators/snapshot/index.mjs +13 -0
  194. package/dist/orchestrators/snapshot/integrity.d.mts +1 -1
  195. package/dist/orchestrators/snapshot/integrity.mjs +73 -17
  196. package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
  197. package/dist/orchestrators/snapshot/pending-marker.d.mts +1 -0
  198. package/dist/orchestrators/snapshot/pending-marker.mjs +99 -0
  199. package/dist/orchestrators/snapshot/pending-marker.mjs.map +1 -0
  200. package/dist/orchestrators/snapshot/phase-error.mjs +23 -0
  201. package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -0
  202. package/dist/orchestrators/snapshot/prune.mjs +20 -55
  203. package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
  204. package/dist/orchestrators/snapshot/recover-pending.d.mts +1 -0
  205. package/dist/orchestrators/snapshot/recover-pending.mjs +223 -0
  206. package/dist/orchestrators/snapshot/recover-pending.mjs.map +1 -0
  207. package/dist/orchestrators/snapshot/restore.mjs +118 -84
  208. package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
  209. package/dist/orchestrators/snapshot/service.mjs +53 -56
  210. package/dist/orchestrators/snapshot/service.mjs.map +1 -1
  211. package/dist/orchestrators/snapshot/state-document.d.mts +1 -0
  212. package/dist/orchestrators/snapshot/state-document.mjs +47 -7
  213. package/dist/orchestrators/snapshot/state-document.mjs.map +1 -1
  214. package/dist/orchestrators/snapshot/wipe.mjs +67 -10
  215. package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
  216. package/dist/plugins/account/codegen.mjs +9 -8
  217. package/dist/plugins/account/codegen.mjs.map +1 -1
  218. package/dist/plugins/account/errors.d.mts +33 -6
  219. package/dist/plugins/account/errors.mjs.map +1 -1
  220. package/dist/plugins/account/funding.d.mts +29 -19
  221. package/dist/plugins/account/funding.mjs +84 -66
  222. package/dist/plugins/account/funding.mjs.map +1 -1
  223. package/dist/plugins/account/index.d.mts +2 -4
  224. package/dist/plugins/account/index.mjs +64 -31
  225. package/dist/plugins/account/index.mjs.map +1 -1
  226. package/dist/plugins/account/keypair.mjs +6 -9
  227. package/dist/plugins/account/keypair.mjs.map +1 -1
  228. package/dist/plugins/account/lease.mjs +1 -0
  229. package/dist/plugins/account/lease.mjs.map +1 -1
  230. package/dist/plugins/account/registry.d.mts +14 -1
  231. package/dist/plugins/account/registry.mjs +18 -18
  232. package/dist/plugins/account/registry.mjs.map +1 -1
  233. package/dist/plugins/account/service.d.mts +23 -4
  234. package/dist/plugins/account/service.mjs +83 -45
  235. package/dist/plugins/account/service.mjs.map +1 -1
  236. package/dist/plugins/account/snapshot.mjs +2 -5
  237. package/dist/plugins/account/snapshot.mjs.map +1 -1
  238. package/dist/plugins/account/spans.mjs +16 -0
  239. package/dist/plugins/account/spans.mjs.map +1 -0
  240. package/dist/plugins/account/variants/keystore.mjs +6 -8
  241. package/dist/plugins/account/variants/keystore.mjs.map +1 -1
  242. package/dist/plugins/action/build-context.d.mts +3 -2
  243. package/dist/plugins/action/errors.d.mts +16 -12
  244. package/dist/plugins/action/errors.mjs.map +1 -1
  245. package/dist/plugins/action/execute.mjs +65 -103
  246. package/dist/plugins/action/execute.mjs.map +1 -1
  247. package/dist/plugins/action/index.d.mts +0 -2
  248. package/dist/plugins/action/index.mjs +17 -13
  249. package/dist/plugins/action/index.mjs.map +1 -1
  250. package/dist/plugins/action/service.mjs +38 -35
  251. package/dist/plugins/action/service.mjs.map +1 -1
  252. package/dist/plugins/action/spans.mjs +11 -0
  253. package/dist/plugins/action/spans.mjs.map +1 -0
  254. package/dist/plugins/coin/codegen.mjs +9 -8
  255. package/dist/plugins/coin/codegen.mjs.map +1 -1
  256. package/dist/plugins/coin/discovery.mjs +8 -4
  257. package/dist/plugins/coin/discovery.mjs.map +1 -1
  258. package/dist/plugins/coin/index.d.mts +11 -29
  259. package/dist/plugins/coin/index.mjs +56 -27
  260. package/dist/plugins/coin/index.mjs.map +1 -1
  261. package/dist/plugins/coin/metadata.mjs +8 -15
  262. package/dist/plugins/coin/metadata.mjs.map +1 -1
  263. package/dist/plugins/coin/mint.d.mts +30 -11
  264. package/dist/plugins/coin/mint.mjs +78 -74
  265. package/dist/plugins/coin/mint.mjs.map +1 -1
  266. package/dist/plugins/coin/registry.mjs +4 -7
  267. package/dist/plugins/coin/registry.mjs.map +1 -1
  268. package/dist/plugins/coin/service.d.mts +39 -1
  269. package/dist/plugins/coin/service.mjs +11 -4
  270. package/dist/plugins/coin/service.mjs.map +1 -1
  271. package/dist/plugins/coin/spans.mjs +20 -0
  272. package/dist/plugins/coin/spans.mjs.map +1 -0
  273. package/dist/plugins/dashboard/domain.mjs +402 -0
  274. package/dist/plugins/dashboard/domain.mjs.map +1 -0
  275. package/dist/plugins/dashboard/index.d.mts +29 -0
  276. package/dist/plugins/dashboard/index.mjs +91 -0
  277. package/dist/plugins/dashboard/index.mjs.map +1 -0
  278. package/dist/plugins/dashboard/origin-policy.mjs +36 -0
  279. package/dist/plugins/dashboard/origin-policy.mjs.map +1 -0
  280. package/dist/plugins/dashboard/routable.mjs +27 -0
  281. package/dist/plugins/dashboard/routable.mjs.map +1 -0
  282. package/dist/plugins/dashboard/schema/builder.mjs +21 -0
  283. package/dist/plugins/dashboard/schema/builder.mjs.map +1 -0
  284. package/dist/plugins/dashboard/schema/enums.mjs +72 -0
  285. package/dist/plugins/dashboard/schema/enums.mjs.map +1 -0
  286. package/dist/plugins/dashboard/schema/root.mjs +351 -0
  287. package/dist/plugins/dashboard/schema/root.mjs.map +1 -0
  288. package/dist/plugins/dashboard/schema/types.mjs +508 -0
  289. package/dist/plugins/dashboard/schema/types.mjs.map +1 -0
  290. package/dist/plugins/dashboard/schema.mjs +11 -0
  291. package/dist/plugins/dashboard/schema.mjs.map +1 -0
  292. package/dist/plugins/dashboard/server.mjs +166 -0
  293. package/dist/plugins/dashboard/server.mjs.map +1 -0
  294. package/dist/plugins/deepbook/deploy.mjs +53 -115
  295. package/dist/plugins/deepbook/deploy.mjs.map +1 -1
  296. package/dist/plugins/deepbook/errors.mjs +1 -0
  297. package/dist/plugins/deepbook/errors.mjs.map +1 -1
  298. package/dist/plugins/deepbook/faucet-strategy.mjs +47 -34
  299. package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
  300. package/dist/plugins/deepbook/hash.mjs +9 -0
  301. package/dist/plugins/deepbook/hash.mjs.map +1 -0
  302. package/dist/plugins/deepbook/index.d.mts +1 -10
  303. package/dist/plugins/deepbook/index.mjs +25 -22
  304. package/dist/plugins/deepbook/index.mjs.map +1 -1
  305. package/dist/plugins/deepbook/pyth/index.mjs +26 -55
  306. package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
  307. package/dist/plugins/deepbook/snapshot.mjs +17 -29
  308. package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
  309. package/dist/plugins/deepbook/spans.mjs +18 -0
  310. package/dist/plugins/deepbook/spans.mjs.map +1 -0
  311. package/dist/plugins/deepbook/type-strings.mjs +65 -0
  312. package/dist/plugins/deepbook/type-strings.mjs.map +1 -0
  313. package/dist/plugins/deepbook/types.d.mts +2 -3
  314. package/dist/plugins/deepbook/types.mjs.map +1 -1
  315. package/dist/plugins/faucet/dispatcher.d.mts +21 -2
  316. package/dist/plugins/faucet/dispatcher.mjs +1 -2
  317. package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
  318. package/dist/plugins/faucet/errors.d.mts +11 -24
  319. package/dist/plugins/faucet/errors.mjs.map +1 -1
  320. package/dist/plugins/faucet/http.mjs +33 -14
  321. package/dist/plugins/faucet/http.mjs.map +1 -1
  322. package/dist/plugins/faucet/index.d.mts +15 -5
  323. package/dist/plugins/faucet/index.mjs +3 -0
  324. package/dist/plugins/faucet/index.mjs.map +1 -1
  325. package/dist/plugins/faucet/spans.mjs +12 -0
  326. package/dist/plugins/faucet/spans.mjs.map +1 -0
  327. package/dist/plugins/host-service/errors.d.mts +1 -1
  328. package/dist/plugins/host-service/index.mjs +34 -8
  329. package/dist/plugins/host-service/index.mjs.map +1 -1
  330. package/dist/plugins/host-service/routable.mjs +2 -1
  331. package/dist/plugins/host-service/routable.mjs.map +1 -1
  332. package/dist/plugins/host-service/service.d.mts +21 -0
  333. package/dist/plugins/host-service/service.mjs +136 -81
  334. package/dist/plugins/host-service/service.mjs.map +1 -1
  335. package/dist/plugins/internal/acquire-on-chain-artifact.mjs +23 -0
  336. package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -0
  337. package/dist/plugins/internal/codegen-helpers.mjs +18 -0
  338. package/dist/plugins/internal/codegen-helpers.mjs.map +1 -0
  339. package/dist/plugins/internal/funding-failure-error.mjs +32 -0
  340. package/dist/plugins/internal/funding-failure-error.mjs.map +1 -0
  341. package/dist/plugins/package/build.mjs +1 -1
  342. package/dist/plugins/package/build.mjs.map +1 -1
  343. package/dist/plugins/package/codegen.mjs +26 -0
  344. package/dist/plugins/package/codegen.mjs.map +1 -1
  345. package/dist/plugins/package/errors.d.mts +16 -6
  346. package/dist/plugins/package/errors.mjs.map +1 -1
  347. package/dist/plugins/package/index.d.mts +0 -4
  348. package/dist/plugins/package/index.mjs +27 -21
  349. package/dist/plugins/package/index.mjs.map +1 -1
  350. package/dist/plugins/package/mode-known.mjs +26 -12
  351. package/dist/plugins/package/mode-known.mjs.map +1 -1
  352. package/dist/plugins/package/mode-local.mjs +47 -41
  353. package/dist/plugins/package/mode-local.mjs.map +1 -1
  354. package/dist/plugins/package/publish-executor.mjs +55 -114
  355. package/dist/plugins/package/publish-executor.mjs.map +1 -1
  356. package/dist/plugins/package/registry.mjs +2 -1
  357. package/dist/plugins/package/registry.mjs.map +1 -1
  358. package/dist/plugins/package/service.mjs.map +1 -1
  359. package/dist/plugins/package/spans.mjs +14 -0
  360. package/dist/plugins/package/spans.mjs.map +1 -0
  361. package/dist/plugins/postgres/db-ensure.mjs +19 -12
  362. package/dist/plugins/postgres/db-ensure.mjs.map +1 -1
  363. package/dist/plugins/postgres/errors.d.mts +5 -0
  364. package/dist/plugins/postgres/errors.mjs.map +1 -1
  365. package/dist/plugins/postgres/index.mjs +10 -17
  366. package/dist/plugins/postgres/index.mjs.map +1 -1
  367. package/dist/plugins/postgres/service.mjs +58 -24
  368. package/dist/plugins/postgres/service.mjs.map +1 -1
  369. package/dist/plugins/postgres/snapshot.mjs.map +1 -1
  370. package/dist/plugins/postgres/spans.mjs +11 -0
  371. package/dist/plugins/postgres/spans.mjs.map +1 -0
  372. package/dist/plugins/router-entrypoints.mjs +4 -4
  373. package/dist/plugins/router-entrypoints.mjs.map +1 -1
  374. package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +15 -13
  375. package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
  376. package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +15 -19
  377. package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
  378. package/dist/plugins/seal/codegen.d.mts +2 -3
  379. package/dist/plugins/seal/codegen.mjs.map +1 -1
  380. package/dist/plugins/seal/config-render.mjs +35 -8
  381. package/dist/plugins/seal/config-render.mjs.map +1 -1
  382. package/dist/plugins/seal/deploy.mjs +31 -39
  383. package/dist/plugins/seal/deploy.mjs.map +1 -1
  384. package/dist/plugins/seal/errors.d.mts +1 -3
  385. package/dist/plugins/seal/errors.mjs +7 -1
  386. package/dist/plugins/seal/errors.mjs.map +1 -1
  387. package/dist/plugins/seal/index.d.mts +1 -6
  388. package/dist/plugins/seal/index.mjs +40 -14
  389. package/dist/plugins/seal/index.mjs.map +1 -1
  390. package/dist/plugins/seal/key-manager.d.mts +1 -9
  391. package/dist/plugins/seal/key-manager.mjs +2 -18
  392. package/dist/plugins/seal/key-manager.mjs.map +1 -1
  393. package/dist/plugins/seal/key-server.mjs +37 -36
  394. package/dist/plugins/seal/key-server.mjs.map +1 -1
  395. package/dist/plugins/seal/keygen.mjs +16 -17
  396. package/dist/plugins/seal/keygen.mjs.map +1 -1
  397. package/dist/plugins/seal/mode/fork-known.mjs +36 -14
  398. package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
  399. package/dist/plugins/seal/mode/live.d.mts +6 -4
  400. package/dist/plugins/seal/mode/live.mjs +14 -21
  401. package/dist/plugins/seal/mode/live.mjs.map +1 -1
  402. package/dist/plugins/seal/mode/local-keygen.mjs +57 -21
  403. package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
  404. package/dist/plugins/seal/registry-publish.mjs +1 -0
  405. package/dist/plugins/seal/registry-publish.mjs.map +1 -1
  406. package/dist/plugins/seal/routable.mjs.map +1 -1
  407. package/dist/plugins/seal/service.mjs.map +1 -1
  408. package/dist/plugins/seal/spans.mjs +18 -0
  409. package/dist/plugins/seal/spans.mjs.map +1 -0
  410. package/dist/plugins/sui/auto-tick.mjs +17 -23
  411. package/dist/plugins/sui/auto-tick.mjs.map +1 -1
  412. package/dist/plugins/sui/chain-build-container.mjs +18 -0
  413. package/dist/plugins/sui/chain-build-container.mjs.map +1 -0
  414. package/dist/plugins/sui/chain-probe.d.mts +5 -5
  415. package/dist/plugins/sui/chain-probe.mjs +28 -58
  416. package/dist/plugins/sui/chain-probe.mjs.map +1 -1
  417. package/dist/plugins/sui/codegen.mjs +26 -0
  418. package/dist/plugins/sui/codegen.mjs.map +1 -1
  419. package/dist/plugins/sui/errors.d.mts +2 -29
  420. package/dist/plugins/sui/errors.mjs +1 -3
  421. package/dist/plugins/sui/errors.mjs.map +1 -1
  422. package/dist/plugins/sui/fork-faucet-strategy.d.mts +1 -0
  423. package/dist/plugins/sui/fork-faucet-strategy.mjs +55 -0
  424. package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -0
  425. package/dist/plugins/sui/fork-orchestration.d.mts +1 -0
  426. package/dist/plugins/sui/fork-orchestration.mjs +170 -2
  427. package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
  428. package/dist/plugins/sui/fork-transaction.d.mts +2 -0
  429. package/dist/plugins/sui/fork-transaction.mjs +92 -28
  430. package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
  431. package/dist/plugins/sui/index.d.mts +33 -70
  432. package/dist/plugins/sui/index.mjs +58 -35
  433. package/dist/plugins/sui/index.mjs.map +1 -1
  434. package/dist/plugins/{faucet/strategies/sui-local.mjs → sui/local-faucet-strategy.mjs} +10 -7
  435. package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -0
  436. package/dist/plugins/sui/mode/external.mjs +7 -13
  437. package/dist/plugins/sui/mode/external.mjs.map +1 -1
  438. package/dist/plugins/sui/mode/fork.mjs +136 -59
  439. package/dist/plugins/sui/mode/fork.mjs.map +1 -1
  440. package/dist/plugins/sui/mode/live.mjs +10 -16
  441. package/dist/plugins/sui/mode/live.mjs.map +1 -1
  442. package/dist/plugins/sui/mode/local.mjs +37 -36
  443. package/dist/plugins/sui/mode/local.mjs.map +1 -1
  444. package/dist/plugins/sui/mode/shared-boot.mjs +38 -115
  445. package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
  446. package/dist/plugins/sui/mode/shared.d.mts +1 -5
  447. package/dist/plugins/sui/mode/shared.mjs.map +1 -1
  448. package/dist/plugins/sui/mode/spec.d.mts +18 -0
  449. package/dist/plugins/sui/move-summary-runner.mjs +207 -0
  450. package/dist/plugins/sui/move-summary-runner.mjs.map +1 -0
  451. package/dist/plugins/sui/network-resolver.d.mts +4 -3
  452. package/dist/plugins/sui/service.mjs.map +1 -1
  453. package/dist/plugins/sui/snapshot.mjs +3 -0
  454. package/dist/plugins/sui/snapshot.mjs.map +1 -1
  455. package/dist/plugins/sui/spans.mjs +17 -0
  456. package/dist/plugins/sui/spans.mjs.map +1 -0
  457. package/dist/plugins/wallet/codegen.d.mts +0 -1
  458. package/dist/plugins/wallet/codegen.mjs +8 -9
  459. package/dist/plugins/wallet/codegen.mjs.map +1 -1
  460. package/dist/plugins/wallet/index.d.mts +6 -8
  461. package/dist/plugins/wallet/index.mjs +46 -35
  462. package/dist/plugins/wallet/index.mjs.map +1 -1
  463. package/dist/plugins/wallet/origin-policy.mjs +12 -28
  464. package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
  465. package/dist/plugins/wallet/pairing.mjs +6 -4
  466. package/dist/plugins/wallet/pairing.mjs.map +1 -1
  467. package/dist/plugins/wallet/protocol.d.mts +1 -0
  468. package/dist/plugins/wallet/protocol.mjs +5 -44
  469. package/dist/plugins/wallet/protocol.mjs.map +1 -1
  470. package/dist/plugins/wallet/routable.mjs +2 -8
  471. package/dist/plugins/wallet/routable.mjs.map +1 -1
  472. package/dist/plugins/wallet/server.mjs +36 -44
  473. package/dist/plugins/wallet/server.mjs.map +1 -1
  474. package/dist/plugins/wallet/service.d.mts +1 -5
  475. package/dist/plugins/wallet/service.mjs +22 -18
  476. package/dist/plugins/wallet/service.mjs.map +1 -1
  477. package/dist/plugins/wallet/spans.mjs +22 -0
  478. package/dist/plugins/wallet/spans.mjs.map +1 -0
  479. package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +33 -8
  480. package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
  481. package/dist/plugins/walrus/codegen.d.mts +3 -3
  482. package/dist/plugins/walrus/codegen.mjs.map +1 -1
  483. package/dist/plugins/walrus/deploy-paths.mjs +21 -5
  484. package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
  485. package/dist/plugins/walrus/deploy.mjs +67 -69
  486. package/dist/plugins/walrus/deploy.mjs.map +1 -1
  487. package/dist/plugins/walrus/errors.mjs +1 -0
  488. package/dist/plugins/walrus/errors.mjs.map +1 -1
  489. package/dist/plugins/walrus/faucet-strategy.mjs +12 -7
  490. package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
  491. package/dist/plugins/walrus/index.d.mts +2 -13
  492. package/dist/plugins/walrus/index.mjs +18 -23
  493. package/dist/plugins/walrus/index.mjs.map +1 -1
  494. package/dist/plugins/walrus/mode/known-deploy.mjs +7 -5
  495. package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
  496. package/dist/plugins/walrus/mode/local-cluster.mjs +26 -7
  497. package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
  498. package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
  499. package/dist/plugins/walrus/routable.mjs +7 -23
  500. package/dist/plugins/walrus/routable.mjs.map +1 -1
  501. package/dist/plugins/walrus/service.mjs.map +1 -1
  502. package/dist/plugins/walrus/spans.mjs +18 -0
  503. package/dist/plugins/walrus/spans.mjs.map +1 -0
  504. package/dist/plugins/walrus/storage-nodes.d.mts +6 -2
  505. package/dist/plugins/walrus/storage-nodes.mjs +15 -8
  506. package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
  507. package/dist/plugins/walrus/wal-swap.mjs +58 -15
  508. package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
  509. package/dist/primitives/artifact-publisher.d.mts +1 -1
  510. package/dist/primitives/artifact-publisher.mjs +15 -0
  511. package/dist/primitives/artifact-publisher.mjs.map +1 -0
  512. package/dist/runtime/docker/client.mjs +17 -4
  513. package/dist/runtime/docker/client.mjs.map +1 -1
  514. package/dist/runtime/docker/container.mjs +219 -132
  515. package/dist/runtime/docker/container.mjs.map +1 -1
  516. package/dist/runtime/docker/errors.mjs +0 -6
  517. package/dist/runtime/docker/errors.mjs.map +1 -1
  518. package/dist/runtime/docker/exec.mjs +21 -18
  519. package/dist/runtime/docker/exec.mjs.map +1 -1
  520. package/dist/runtime/docker/image.mjs +36 -13
  521. package/dist/runtime/docker/image.mjs.map +1 -1
  522. package/dist/runtime/docker/index.mjs +14 -0
  523. package/dist/runtime/docker/inspect-and-decode.mjs +51 -0
  524. package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -0
  525. package/dist/runtime/docker/inventory.mjs +14 -11
  526. package/dist/runtime/docker/inventory.mjs.map +1 -1
  527. package/dist/runtime/docker/labels.mjs +38 -5
  528. package/dist/runtime/docker/labels.mjs.map +1 -1
  529. package/dist/runtime/docker/logs.d.mts +1 -1
  530. package/dist/runtime/docker/logs.mjs.map +1 -1
  531. package/dist/runtime/docker/network.mjs +83 -47
  532. package/dist/runtime/docker/network.mjs.map +1 -1
  533. package/dist/runtime/docker/render-run-args.mjs +82 -0
  534. package/dist/runtime/docker/render-run-args.mjs.map +1 -0
  535. package/dist/runtime/docker/service.d.mts +1 -1
  536. package/dist/runtime/docker/service.mjs +12 -7
  537. package/dist/runtime/docker/service.mjs.map +1 -1
  538. package/dist/runtime/docker/sweep.mjs +118 -43
  539. package/dist/runtime/docker/sweep.mjs.map +1 -1
  540. package/dist/runtime/docker/volume.mjs +2 -0
  541. package/dist/runtime/docker/volume.mjs.map +1 -1
  542. package/dist/runtime/docker/wrap.mjs +30 -1
  543. package/dist/runtime/docker/wrap.mjs.map +1 -1
  544. package/dist/substrate/cross-process.mjs +14 -8
  545. package/dist/substrate/cross-process.mjs.map +1 -1
  546. package/dist/substrate/event-time.mjs +33 -0
  547. package/dist/substrate/event-time.mjs.map +1 -0
  548. package/dist/substrate/events.d.mts +28 -8
  549. package/dist/substrate/identity.d.mts +2 -1
  550. package/dist/substrate/manifest.d.mts +68 -5
  551. package/dist/substrate/manifest.mjs +34 -5
  552. package/dist/substrate/manifest.mjs.map +1 -1
  553. package/dist/substrate/network.d.mts +3 -5
  554. package/dist/substrate/options.d.mts +0 -2
  555. package/dist/substrate/plugin.d.mts +13 -0
  556. package/dist/substrate/plugin.mjs +4 -2
  557. package/dist/substrate/plugin.mjs.map +1 -1
  558. package/dist/substrate/projection.d.mts +35 -3
  559. package/dist/substrate/runtime/artifact-publisher/index.mjs +19 -9
  560. package/dist/substrate/runtime/artifact-publisher/index.mjs.map +1 -1
  561. package/dist/substrate/runtime/atomic-write.mjs +97 -32
  562. package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
  563. package/dist/substrate/runtime/cache/index.mjs +3 -0
  564. package/dist/substrate/runtime/cache/schema.mjs +2 -2
  565. package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
  566. package/dist/substrate/runtime/cache/service.mjs +9 -7
  567. package/dist/substrate/runtime/cache/service.mjs.map +1 -1
  568. package/dist/substrate/runtime/capability-sinks/index.d.mts +1 -1
  569. package/dist/substrate/runtime/capability-sinks/index.mjs +3 -0
  570. package/dist/substrate/runtime/capability-sinks/layer.mjs +1 -1
  571. package/dist/substrate/runtime/capability-sinks/service.d.mts +61 -2
  572. package/dist/substrate/runtime/capability-sinks/service.mjs +21 -26
  573. package/dist/substrate/runtime/capability-sinks/service.mjs.map +1 -1
  574. package/dist/substrate/runtime/config-validation.d.mts +1 -13
  575. package/dist/substrate/runtime/config-validation.mjs +2 -91
  576. package/dist/substrate/runtime/config-validation.mjs.map +1 -1
  577. package/dist/substrate/runtime/container-runtime.d.mts +1 -0
  578. package/dist/substrate/runtime/container-runtime.mjs +2 -0
  579. package/dist/substrate/runtime/control-plane/domain.mjs +101 -0
  580. package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -0
  581. package/dist/substrate/runtime/control-plane/service.mjs +7 -0
  582. package/dist/substrate/runtime/control-plane/service.mjs.map +1 -0
  583. package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +46 -19
  584. package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
  585. package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs +30 -12
  586. package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
  587. package/dist/substrate/runtime/cross-process/command-channel/index.mjs +5 -0
  588. package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs +11 -2
  589. package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -1
  590. package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs +1 -1
  591. package/dist/substrate/runtime/cross-process/index.mjs +11 -0
  592. package/dist/substrate/runtime/cross-process/live-clock.mjs +34 -0
  593. package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -0
  594. package/dist/substrate/runtime/cross-process/liveness.mjs +52 -10
  595. package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
  596. package/dist/substrate/runtime/cross-process/lock.d.mts +1 -0
  597. package/dist/substrate/runtime/cross-process/lock.mjs +23 -0
  598. package/dist/substrate/runtime/cross-process/lock.mjs.map +1 -0
  599. package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +64 -0
  600. package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -0
  601. package/dist/substrate/runtime/cross-process/roster.mjs +97 -83
  602. package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
  603. package/dist/substrate/runtime/cross-process/self-pid.mjs +8 -0
  604. package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -0
  605. package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +24 -28
  606. package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +1 -1
  607. package/dist/substrate/runtime/cross-process/stack-lock.mjs +41 -20
  608. package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
  609. package/dist/substrate/runtime/current-plugin.mjs +2 -2
  610. package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
  611. package/dist/substrate/runtime/errors.mjs +12 -6
  612. package/dist/substrate/runtime/errors.mjs.map +1 -1
  613. package/dist/substrate/runtime/format-unknown-error.mjs +30 -0
  614. package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -0
  615. package/dist/substrate/runtime/host-bind-mount-owner.mjs +10 -0
  616. package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -0
  617. package/dist/substrate/runtime/host-gateway.mjs +20 -0
  618. package/dist/substrate/runtime/host-gateway.mjs.map +1 -0
  619. package/dist/substrate/runtime/host-tree-tar/index.mjs +61 -50
  620. package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
  621. package/dist/substrate/runtime/http-probe.d.mts +1 -1
  622. package/dist/substrate/runtime/index.mjs +14 -0
  623. package/dist/substrate/runtime/lease-broker/index.d.mts +1 -1
  624. package/dist/substrate/runtime/lease-broker/index.mjs +2 -0
  625. package/dist/substrate/runtime/lease-broker/service.d.mts +1 -64
  626. package/dist/substrate/runtime/lease-broker/service.mjs +1 -1
  627. package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
  628. package/dist/substrate/runtime/lifecycle/dep-graph.mjs +22 -3
  629. package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
  630. package/dist/substrate/runtime/lifecycle/index.mjs +9 -0
  631. package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +1 -1
  632. package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +20 -3
  633. package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
  634. package/dist/substrate/runtime/lifecycle/selective-restart.mjs +1 -1
  635. package/dist/substrate/runtime/lifecycle/signals.mjs +5 -5
  636. package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
  637. package/dist/substrate/runtime/lifecycle/state-machine.mjs +1 -1
  638. package/dist/substrate/runtime/managed-container.d.mts +19 -1
  639. package/dist/substrate/runtime/managed-container.mjs +20 -1
  640. package/dist/substrate/runtime/managed-container.mjs.map +1 -1
  641. package/dist/substrate/runtime/manifest/index.mjs +3 -0
  642. package/dist/substrate/runtime/manifest/manifest.mjs +15 -11
  643. package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
  644. package/dist/substrate/runtime/mode-errors.mjs +20 -0
  645. package/dist/substrate/runtime/mode-errors.mjs.map +1 -0
  646. package/dist/substrate/runtime/observability/cascade-formatter.mjs +9 -13
  647. package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
  648. package/dist/substrate/runtime/observability/formatter-registry.mjs +19 -36
  649. package/dist/substrate/runtime/observability/formatter-registry.mjs.map +1 -1
  650. package/dist/substrate/runtime/observability/ignore-with-log.d.mts +1 -0
  651. package/dist/substrate/runtime/observability/ignore-with-log.mjs +17 -0
  652. package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -0
  653. package/dist/substrate/runtime/observability/index.d.mts +1 -1
  654. package/dist/substrate/runtime/observability/index.mjs +13 -0
  655. package/dist/substrate/runtime/observability/log-store.d.mts +1 -0
  656. package/dist/substrate/runtime/observability/log-store.mjs +175 -0
  657. package/dist/substrate/runtime/observability/log-store.mjs.map +1 -0
  658. package/dist/substrate/runtime/observability/logger.d.mts +2 -1
  659. package/dist/substrate/runtime/observability/logger.mjs +5 -9
  660. package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
  661. package/dist/substrate/runtime/observability/output-truncate.mjs +35 -0
  662. package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -0
  663. package/dist/substrate/runtime/observability/pretty-error.mjs +9 -12
  664. package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
  665. package/dist/substrate/runtime/observability/redaction.d.mts +2 -13
  666. package/dist/substrate/runtime/observability/redaction.mjs +8 -14
  667. package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
  668. package/dist/substrate/runtime/observability/span-store.d.mts +1 -0
  669. package/dist/substrate/runtime/observability/span-store.mjs +110 -0
  670. package/dist/substrate/runtime/observability/span-store.mjs.map +1 -0
  671. package/dist/substrate/runtime/observability/spans.mjs +14 -14
  672. package/dist/substrate/runtime/observability/spans.mjs.map +1 -1
  673. package/dist/substrate/runtime/observability/subprocess-capture.mjs +1 -1
  674. package/dist/substrate/runtime/passthrough-or-wrap.mjs +33 -0
  675. package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -0
  676. package/dist/substrate/runtime/paths.d.mts +1 -1
  677. package/dist/substrate/runtime/paths.mjs +4 -3
  678. package/dist/substrate/runtime/paths.mjs.map +1 -1
  679. package/dist/substrate/runtime/phase-preserving-produce.mjs +40 -0
  680. package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -0
  681. package/dist/substrate/runtime/port-broker/index.mjs +3 -0
  682. package/dist/substrate/runtime/port-broker/service.mjs +170 -126
  683. package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
  684. package/dist/substrate/runtime/post-acquire-tasks.mjs +1 -1
  685. package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
  686. package/dist/substrate/runtime/probes.d.mts +7 -5
  687. package/dist/substrate/runtime/probes.mjs +3 -1
  688. package/dist/substrate/runtime/probes.mjs.map +1 -1
  689. package/dist/substrate/runtime/projection/index.mjs +4 -0
  690. package/dist/substrate/runtime/projection/operational-endpoints.mjs +1 -2
  691. package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
  692. package/dist/substrate/runtime/projection/persisted.mjs +33 -15
  693. package/dist/substrate/runtime/projection/persisted.mjs.map +1 -1
  694. package/dist/substrate/runtime/projection/state-ref.mjs +26 -2
  695. package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
  696. package/dist/substrate/runtime/projection/update.mjs +88 -24
  697. package/dist/substrate/runtime/projection/update.mjs.map +1 -1
  698. package/dist/substrate/runtime/random-suffix.mjs +11 -0
  699. package/dist/substrate/runtime/random-suffix.mjs.map +1 -0
  700. package/dist/substrate/runtime/retry-policy.d.mts +59 -1
  701. package/dist/substrate/runtime/retry-policy.mjs +66 -1
  702. package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
  703. package/dist/substrate/runtime/routed-url.d.mts +1 -0
  704. package/dist/substrate/runtime/routed-url.mjs +79 -0
  705. package/dist/substrate/runtime/routed-url.mjs.map +1 -0
  706. package/dist/substrate/runtime/runtime-decode.d.mts +1 -1
  707. package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
  708. package/dist/substrate/runtime/scoped-http-server.mjs +2 -3
  709. package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
  710. package/dist/substrate/runtime/scoped-multimap/index.mjs +2 -0
  711. package/dist/substrate/runtime/scoped-multimap/service.mjs +52 -0
  712. package/dist/substrate/runtime/scoped-multimap/service.mjs.map +1 -0
  713. package/dist/substrate/runtime/scoped-ref-map/index.mjs +2 -0
  714. package/dist/substrate/runtime/scoped-ref-map/service.mjs +2 -2
  715. package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +1 -1
  716. package/dist/substrate/runtime/stage-and-swap/index.mjs +72 -4
  717. package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
  718. package/dist/substrate/runtime/state-store/index.d.mts +1 -0
  719. package/dist/substrate/runtime/state-store/index.mjs +3 -0
  720. package/dist/substrate/runtime/state-store/schema.d.mts +1 -0
  721. package/dist/substrate/runtime/state-store/schema.mjs +19 -14
  722. package/dist/substrate/runtime/state-store/schema.mjs.map +1 -1
  723. package/dist/substrate/runtime/state-store/service.d.mts +1 -0
  724. package/dist/substrate/runtime/state-store/service.mjs +145 -0
  725. package/dist/substrate/runtime/state-store/service.mjs.map +1 -0
  726. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.d.mts +1 -0
  727. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs +33 -0
  728. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -0
  729. package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs +1 -1
  730. package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
  731. package/dist/substrate/runtime/strategy-registry/index.mjs +4 -0
  732. package/dist/substrate/runtime/strategy-registry/service.mjs +19 -33
  733. package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
  734. package/dist/substrate/runtime/subnet-broker.mjs +60 -0
  735. package/dist/substrate/runtime/subnet-broker.mjs.map +1 -0
  736. package/dist/substrate/runtime/sui-execute/index.d.mts +21 -1
  737. package/dist/substrate/runtime/sui-execute/index.mjs +84 -20
  738. package/dist/substrate/runtime/sui-execute/index.mjs.map +1 -1
  739. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.d.mts +1 -0
  740. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs +32 -0
  741. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +1 -0
  742. package/dist/substrate/runtime/sui-ledger/object-ref.mjs +32 -0
  743. package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +1 -0
  744. package/dist/substrate/runtime/sui-move-build/index.mjs +93 -19
  745. package/dist/substrate/runtime/sui-move-build/index.mjs.map +1 -1
  746. package/dist/substrate/runtime/supervisor/acquire-node.mjs +181 -0
  747. package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -0
  748. package/dist/substrate/runtime/supervisor/background-tasks.mjs +144 -0
  749. package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -0
  750. package/dist/substrate/runtime/supervisor/command-loop.mjs +68 -0
  751. package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -0
  752. package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +151 -0
  753. package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +1 -0
  754. package/dist/substrate/runtime/supervisor/errors.d.mts +1 -0
  755. package/dist/substrate/runtime/supervisor/errors.mjs +9 -0
  756. package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -0
  757. package/dist/substrate/runtime/supervisor/index.d.mts +1 -0
  758. package/dist/substrate/runtime/supervisor/index.mjs +3 -0
  759. package/dist/substrate/runtime/supervisor/shutdown.mjs +51 -0
  760. package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -0
  761. package/dist/substrate/runtime/supervisor/start-supervisor.d.mts +1 -0
  762. package/dist/substrate/runtime/supervisor/start-supervisor.mjs +250 -0
  763. package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -0
  764. package/dist/substrate/runtime/supervisor/state.d.mts +1 -0
  765. package/dist/substrate/runtime/supervisor/state.mjs +22 -0
  766. package/dist/substrate/runtime/supervisor/state.mjs.map +1 -0
  767. package/dist/substrate/runtime/supervisor/teardown.mjs +57 -0
  768. package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -0
  769. package/dist/substrate/runtime/supervisor/types.d.mts +1 -0
  770. package/dist/substrate/runtime/supervisor/wiring.mjs +133 -0
  771. package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -0
  772. package/dist/substrate/runtime/typed-env.mjs +8 -0
  773. package/dist/substrate/runtime/typed-env.mjs.map +1 -0
  774. package/dist/substrate/state-store.d.mts +1 -0
  775. package/dist/substrate/versioned-doc-schema.mjs +17 -0
  776. package/dist/substrate/versioned-doc-schema.mjs.map +1 -0
  777. package/dist/substrate/versioned-doc-sync.mjs +94 -0
  778. package/dist/substrate/versioned-doc-sync.mjs.map +1 -0
  779. package/dist/surfaces/cli/command-tree.mjs.map +1 -1
  780. package/dist/surfaces/cli/commands/index.mjs +9 -0
  781. package/dist/surfaces/cli/commands/prune-picker-entry.mjs +13 -0
  782. package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -0
  783. package/dist/surfaces/cli/commands/prune-picker.mjs +3 -2
  784. package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
  785. package/dist/surfaces/cli/commands/prune.mjs +34 -17
  786. package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
  787. package/dist/surfaces/cli/commands/status.mjs +2 -2
  788. package/dist/surfaces/cli/commands/status.mjs.map +1 -1
  789. package/dist/surfaces/cli/commands/supervisor-presence.mjs +5 -3
  790. package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
  791. package/dist/surfaces/cli/commands/wipe.mjs +38 -4
  792. package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
  793. package/dist/surfaces/cli/errors.mjs +1 -1
  794. package/dist/surfaces/cli/errors.mjs.map +1 -1
  795. package/dist/surfaces/cli/flags.mjs +0 -1
  796. package/dist/surfaces/cli/flags.mjs.map +1 -1
  797. package/dist/surfaces/cli/index.mjs +98 -18
  798. package/dist/surfaces/cli/index.mjs.map +1 -1
  799. package/dist/surfaces/cli/output.mjs +1 -0
  800. package/dist/surfaces/cli/output.mjs.map +1 -1
  801. package/dist/surfaces/cli/sysexits.mjs +2 -1
  802. package/dist/surfaces/cli/sysexits.mjs.map +1 -1
  803. package/dist/surfaces/tui/app.mjs +25 -3
  804. package/dist/surfaces/tui/app.mjs.map +1 -1
  805. package/dist/surfaces/tui/display-derivation.mjs +23 -74
  806. package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
  807. package/dist/surfaces/tui/event-log.mjs +35 -23
  808. package/dist/surfaces/tui/event-log.mjs.map +1 -1
  809. package/dist/surfaces/tui/input.mjs +5 -1
  810. package/dist/surfaces/tui/input.mjs.map +1 -1
  811. package/dist/surfaces/tui/plain-renderer.mjs +70 -34
  812. package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
  813. package/package.json +24 -4
  814. package/dist/contracts/liveness-classifier.d.mts +0 -19
  815. package/dist/contracts/network-resolver.d.mts +0 -15
  816. package/dist/contracts/network-resolver.mjs +0 -7
  817. package/dist/contracts/network-resolver.mjs.map +0 -1
  818. package/dist/orchestrators/codegen/extras.mjs +0 -16
  819. package/dist/orchestrators/codegen/extras.mjs.map +0 -1
  820. package/dist/plugins/deepbook/routable.mjs +0 -21
  821. package/dist/plugins/deepbook/routable.mjs.map +0 -1
  822. package/dist/plugins/faucet/service.d.mts +0 -20
  823. package/dist/plugins/faucet/strategies/sui-local.d.mts +0 -23
  824. package/dist/plugins/faucet/strategies/sui-local.mjs.map +0 -1
  825. package/dist/plugins/sui/seed-objects.d.mts +0 -18
  826. package/dist/plugins/sui/seed-objects.mjs +0 -25
  827. package/dist/plugins/sui/seed-objects.mjs.map +0 -1
  828. package/dist/runtime/built-in-plugin-layers.mjs.map +0 -1
  829. package/dist/substrate/runtime/context-helpers.mjs +0 -32
  830. package/dist/substrate/runtime/context-helpers.mjs.map +0 -1
  831. package/dist/substrate/runtime/run.mjs.map +0 -1
  832. package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs +0 -30
  833. package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs.map +0 -1
  834. package/dist/substrate/runtime/supervisor.d.mts +0 -1
  835. package/dist/substrate/runtime/supervisor.mjs +0 -831
  836. package/dist/substrate/runtime/supervisor.mjs.map +0 -1
  837. package/dist/surfaces/cli/commands/doctor-probes.mjs.map +0 -1
  838. /package/dist/{substrate/runtime/strategy-registry/faucet-capability-for.d.mts → plugins/faucet/http.d.mts} +0 -0
@@ -5,6 +5,7 @@ var probes_exports = /* @__PURE__ */ __exportAll({
5
5
  ProbeAttemptTimeoutError: () => ProbeAttemptTimeoutError,
6
6
  ProbeTimeoutError: () => ProbeTimeoutError,
7
7
  exitCodeProbeResult: () => exitCodeProbeResult,
8
+ probeManyLenient: () => probeManyLenient,
8
9
  waitForProbe: () => waitForProbe
9
10
  });
10
11
  var ProbeAttemptTimeoutError = class extends Data.TaggedError("ProbeAttemptTimeoutError") {};
@@ -78,7 +79,8 @@ const exitCodeProbeResult = (result) => {
78
79
  }
79
80
  };
80
81
  };
82
+ const probeManyLenient = (probes, options) => Effect.forEach(probes, (probe) => probe, { concurrency: options?.concurrency ?? "unbounded" });
81
83
  //#endregion
82
- export { ProbeTimeoutError, exitCodeProbeResult, probes_exports, waitForProbe };
84
+ export { ProbeTimeoutError, exitCodeProbeResult, probeManyLenient, probes_exports, waitForProbe };
83
85
 
84
86
  //# sourceMappingURL=probes.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"probes.mjs","names":[],"sources":["../../../src/substrate/runtime/probes.ts"],"sourcesContent":["import { Data, Duration, Effect } from 'effect';\n\nexport type ProbeAttemptResult =\n\t| void\n\t| boolean\n\t| {\n\t\t\treadonly ready: boolean;\n\t\t\treadonly detail?: unknown;\n\t };\n\nexport interface ProbeOptions<E = unknown, R = never> {\n\treadonly label: string;\n\treadonly timeoutMs: number;\n\treadonly intervalMs?: number;\n\treadonly attemptTimeoutMs?: number;\n\treadonly probe: () => Effect.Effect<ProbeAttemptResult, E, R>;\n\treadonly isRetryableError?: (error: E) => boolean;\n}\n\nexport class ProbeAttemptTimeoutError extends Data.TaggedError('ProbeAttemptTimeoutError')<{\n\treadonly label: string;\n\treadonly attemptTimeoutMs: number;\n\treadonly message: string;\n}> {}\n\nexport class ProbeTimeoutError extends Data.TaggedError('ProbeTimeoutError')<{\n\treadonly label: string;\n\treadonly timeoutMs: number;\n\treadonly intervalMs: number;\n\treadonly attemptTimeoutMs?: number;\n\treadonly attempts: number;\n\treadonly message: string;\n\treadonly lastError?: unknown;\n\treadonly lastNotReady?: unknown;\n}> {}\n\nconst DEFAULT_INTERVAL_MS = 250;\n\nconst normalizeAttempt = (\n\tresult: ProbeAttemptResult,\n): { readonly ready: boolean; readonly detail?: unknown } => {\n\tif (result === undefined || result === true) return { ready: true };\n\tif (result === false) return { ready: false };\n\treturn result;\n};\n\nconst withAttemptTimeout = <A, E, R>(\n\teffect: Effect.Effect<A, E, R>,\n\toptions: {\n\t\treadonly label: string;\n\t\treadonly attemptTimeoutMs?: number;\n\t\treadonly remainingMs: number;\n\t},\n): Effect.Effect<A, E | ProbeAttemptTimeoutError, R> => {\n\tif (options.attemptTimeoutMs === undefined) return effect;\n\tconst timeoutMs = Math.max(1, Math.min(options.attemptTimeoutMs, options.remainingMs));\n\treturn effect.pipe(\n\t\tEffect.timeoutOrElse({\n\t\t\tduration: Duration.millis(timeoutMs),\n\t\t\torElse: () =>\n\t\t\t\tEffect.fail(\n\t\t\t\t\tnew ProbeAttemptTimeoutError({\n\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\tattemptTimeoutMs: timeoutMs,\n\t\t\t\t\t\tmessage: `Probe ${options.label} attempt did not complete within ${timeoutMs}ms`,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}),\n\t);\n};\n\nexport const waitForProbe = <E, R = never>(\n\toptions: ProbeOptions<E, R>,\n): Effect.Effect<void, E | ProbeTimeoutError, R> =>\n\tEffect.gen(function* () {\n\t\tconst timeoutMs = options.timeoutMs;\n\t\tconst intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n\t\tconst started = Date.now();\n\t\tconst deadline = started + timeoutMs;\n\t\tlet attempts = 0;\n\t\tlet lastError: unknown;\n\t\tlet lastNotReady: unknown;\n\n\t\tfor (;;) {\n\t\t\tconst remainingMs = deadline - Date.now();\n\t\t\tif (remainingMs <= 0) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew ProbeTimeoutError({\n\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\ttimeoutMs,\n\t\t\t\t\t\tintervalMs,\n\t\t\t\t\t\t...(options.attemptTimeoutMs === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { attemptTimeoutMs: options.attemptTimeoutMs }),\n\t\t\t\t\t\tattempts,\n\t\t\t\t\t\tmessage: `Probe ${options.label} did not become ready within ${timeoutMs}ms`,\n\t\t\t\t\t\t...(lastError === undefined ? {} : { lastError }),\n\t\t\t\t\t\t...(lastNotReady === undefined ? {} : { lastNotReady }),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tattempts += 1;\n\t\t\tconst ready = yield* withAttemptTimeout(options.probe(), {\n\t\t\t\tlabel: options.label,\n\t\t\t\tattemptTimeoutMs: options.attemptTimeoutMs,\n\t\t\t\tremainingMs,\n\t\t\t}).pipe(\n\t\t\t\tEffect.matchEffect({\n\t\t\t\t\tonFailure: (error) => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!(error instanceof ProbeAttemptTimeoutError) &&\n\t\t\t\t\t\t\toptions.isRetryableError?.(error as E) === false\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn Effect.fail(error as E);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlastError = error;\n\t\t\t\t\t\treturn Effect.succeed(false);\n\t\t\t\t\t},\n\t\t\t\t\tonSuccess: (result) => {\n\t\t\t\t\t\tconst normalized = normalizeAttempt(result);\n\t\t\t\t\t\tif (!normalized.ready) lastNotReady = normalized.detail ?? false;\n\t\t\t\t\t\treturn Effect.succeed(normalized.ready);\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (ready) return;\n\n\t\t\tconst sleepMs = Math.min(intervalMs, Math.max(1, deadline - Date.now()));\n\t\t\tyield* Effect.sleep(Duration.millis(sleepMs));\n\t\t}\n\t});\n\nexport interface ExitCodeProbeResult {\n\treadonly exitCode: number;\n\treadonly stdout?: string;\n\treadonly stderr?: string;\n}\n\nexport const exitCodeProbeResult = (result: ExitCodeProbeResult): ProbeAttemptResult => {\n\tif (result.exitCode === 0) return true;\n\treturn {\n\t\tready: false,\n\t\tdetail: {\n\t\t\texitCode: result.exitCode,\n\t\t\t...(result.stdout === undefined ? {} : { stdout: result.stdout }),\n\t\t\t...(result.stderr === undefined ? {} : { stderr: result.stderr }),\n\t\t},\n\t};\n};\n"],"mappings":";;;;;;;;;AAmBA,IAAa,2BAAb,cAA8C,KAAK,YAAY,2BAA2B,CAIvF;AAEH,IAAa,oBAAb,cAAuC,KAAK,YAAY,oBAAoB,CASzE;AAEH,MAAM,sBAAsB;AAE5B,MAAM,oBACL,WAC4D;AAC5D,KAAI,WAAW,KAAA,KAAa,WAAW,KAAM,QAAO,EAAE,OAAO,MAAM;AACnE,KAAI,WAAW,MAAO,QAAO,EAAE,OAAO,OAAO;AAC7C,QAAO;;AAGR,MAAM,sBACL,QACA,YAKuD;AACvD,KAAI,QAAQ,qBAAqB,KAAA,EAAW,QAAO;CACnD,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,kBAAkB,QAAQ,YAAY,CAAC;AACtF,QAAO,OAAO,KACb,OAAO,cAAc;EACpB,UAAU,SAAS,OAAO,UAAU;EACpC,cACC,OAAO,KACN,IAAI,yBAAyB;GAC5B,OAAO,QAAQ;GACf,kBAAkB;GAClB,SAAS,SAAS,QAAQ,MAAM,mCAAmC,UAAU;GAC7E,CAAC,CACF;EACF,CAAC,CACF;;AAGF,MAAa,gBACZ,YAEA,OAAO,IAAI,aAAa;CACvB,MAAM,YAAY,QAAQ;CAC1B,MAAM,aAAa,QAAQ,cAAc;CAEzC,MAAM,WADU,KAAK,KACG,GAAG;CAC3B,IAAI,WAAW;CACf,IAAI;CACJ,IAAI;AAEJ,UAAS;EACR,MAAM,cAAc,WAAW,KAAK,KAAK;AACzC,MAAI,eAAe,EAClB,QAAO,OAAO,OAAO,KACpB,IAAI,kBAAkB;GACrB,OAAO,QAAQ;GACf;GACA;GACA,GAAI,QAAQ,qBAAqB,KAAA,IAC9B,EAAE,GACF,EAAE,kBAAkB,QAAQ,kBAAkB;GACjD;GACA,SAAS,SAAS,QAAQ,MAAM,+BAA+B,UAAU;GACzE,GAAI,cAAc,KAAA,IAAY,EAAE,GAAG,EAAE,WAAW;GAChD,GAAI,iBAAiB,KAAA,IAAY,EAAE,GAAG,EAAE,cAAc;GACtD,CAAC,CACF;AAGF,cAAY;AAwBZ,MAAI,OAvBiB,mBAAmB,QAAQ,OAAO,EAAE;GACxD,OAAO,QAAQ;GACf,kBAAkB,QAAQ;GAC1B;GACA,CAAC,CAAC,KACF,OAAO,YAAY;GAClB,YAAY,UAAU;AACrB,QACC,EAAE,iBAAiB,6BACnB,QAAQ,mBAAmB,MAAW,KAAK,MAE3C,QAAO,OAAO,KAAK,MAAW;AAE/B,gBAAY;AACZ,WAAO,OAAO,QAAQ,MAAM;;GAE7B,YAAY,WAAW;IACtB,MAAM,aAAa,iBAAiB,OAAO;AAC3C,QAAI,CAAC,WAAW,MAAO,gBAAe,WAAW,UAAU;AAC3D,WAAO,OAAO,QAAQ,WAAW,MAAM;;GAExC,CAAC,CACF,CACU;EAEX,MAAM,UAAU,KAAK,IAAI,YAAY,KAAK,IAAI,GAAG,WAAW,KAAK,KAAK,CAAC,CAAC;AACxE,SAAO,OAAO,MAAM,SAAS,OAAO,QAAQ,CAAC;;EAE7C;AAQH,MAAa,uBAAuB,WAAoD;AACvF,KAAI,OAAO,aAAa,EAAG,QAAO;AAClC,QAAO;EACN,OAAO;EACP,QAAQ;GACP,UAAU,OAAO;GACjB,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,GAAG,EAAE,QAAQ,OAAO,QAAQ;GAChE,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,GAAG,EAAE,QAAQ,OAAO,QAAQ;GAChE;EACD"}
1
+ {"version":3,"file":"probes.mjs","names":[],"sources":["../../../src/substrate/runtime/probes.ts"],"sourcesContent":["import { Data, Duration, Effect, Types } from 'effect';\n\nexport type ProbeAttemptResult =\n\t| void\n\t| boolean\n\t| {\n\t\t\treadonly ready: boolean;\n\t\t\treadonly detail?: unknown;\n\t };\n\nexport interface ProbeOptions<E = unknown, R = never> {\n\treadonly label: string;\n\treadonly timeoutMs: number;\n\treadonly intervalMs?: number;\n\treadonly attemptTimeoutMs?: number;\n\treadonly probe: () => Effect.Effect<ProbeAttemptResult, E, R>;\n\treadonly isRetryableError?: (error: E) => boolean;\n}\n\nexport class ProbeAttemptTimeoutError extends Data.TaggedError('ProbeAttemptTimeoutError')<{\n\treadonly label: string;\n\treadonly attemptTimeoutMs: number;\n\treadonly message: string;\n}> {}\n\nexport class ProbeTimeoutError extends Data.TaggedError('ProbeTimeoutError')<{\n\treadonly label: string;\n\treadonly timeoutMs: number;\n\treadonly intervalMs: number;\n\treadonly attemptTimeoutMs?: number;\n\treadonly attempts: number;\n\treadonly message: string;\n\treadonly lastError?: unknown;\n\treadonly lastNotReady?: unknown;\n}> {}\n\nconst DEFAULT_INTERVAL_MS = 250;\n\nconst normalizeAttempt = (\n\tresult: ProbeAttemptResult,\n): { readonly ready: boolean; readonly detail?: unknown } => {\n\tif (result === undefined || result === true) return { ready: true };\n\tif (result === false) return { ready: false };\n\treturn result;\n};\n\nconst withAttemptTimeout = <A, E, R>(\n\teffect: Effect.Effect<A, E, R>,\n\toptions: {\n\t\treadonly label: string;\n\t\treadonly attemptTimeoutMs?: number;\n\t\treadonly remainingMs: number;\n\t},\n): Effect.Effect<A, E | ProbeAttemptTimeoutError, R> => {\n\tif (options.attemptTimeoutMs === undefined) return effect;\n\tconst timeoutMs = Math.max(1, Math.min(options.attemptTimeoutMs, options.remainingMs));\n\treturn effect.pipe(\n\t\tEffect.timeoutOrElse({\n\t\t\tduration: Duration.millis(timeoutMs),\n\t\t\torElse: () =>\n\t\t\t\tEffect.fail(\n\t\t\t\t\tnew ProbeAttemptTimeoutError({\n\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\tattemptTimeoutMs: timeoutMs,\n\t\t\t\t\t\tmessage: `Probe ${options.label} attempt did not complete within ${timeoutMs}ms`,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}),\n\t);\n};\n\nexport const waitForProbe = <E, R = never>(\n\toptions: ProbeOptions<E, R>,\n): Effect.Effect<void, E | ProbeTimeoutError, R> =>\n\tEffect.gen(function* () {\n\t\tconst timeoutMs = options.timeoutMs;\n\t\tconst intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n\t\tconst started = Date.now();\n\t\tconst deadline = started + timeoutMs;\n\t\tlet attempts = 0;\n\t\tlet lastError: unknown;\n\t\tlet lastNotReady: unknown;\n\n\t\tfor (;;) {\n\t\t\tconst remainingMs = deadline - Date.now();\n\t\t\tif (remainingMs <= 0) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew ProbeTimeoutError({\n\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\ttimeoutMs,\n\t\t\t\t\t\tintervalMs,\n\t\t\t\t\t\t...(options.attemptTimeoutMs === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { attemptTimeoutMs: options.attemptTimeoutMs }),\n\t\t\t\t\t\tattempts,\n\t\t\t\t\t\tmessage: `Probe ${options.label} did not become ready within ${timeoutMs}ms`,\n\t\t\t\t\t\t...(lastError === undefined ? {} : { lastError }),\n\t\t\t\t\t\t...(lastNotReady === undefined ? {} : { lastNotReady }),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tattempts += 1;\n\t\t\tconst ready = yield* withAttemptTimeout(options.probe(), {\n\t\t\t\tlabel: options.label,\n\t\t\t\tattemptTimeoutMs: options.attemptTimeoutMs,\n\t\t\t\tremainingMs,\n\t\t\t}).pipe(\n\t\t\t\tEffect.matchEffect({\n\t\t\t\t\tonFailure: (error) => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!(error instanceof ProbeAttemptTimeoutError) &&\n\t\t\t\t\t\t\toptions.isRetryableError?.(error as E) === false\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn Effect.fail(error as E);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlastError = error;\n\t\t\t\t\t\treturn Effect.succeed(false);\n\t\t\t\t\t},\n\t\t\t\t\tonSuccess: (result) => {\n\t\t\t\t\t\tconst normalized = normalizeAttempt(result);\n\t\t\t\t\t\tif (!normalized.ready) lastNotReady = normalized.detail ?? false;\n\t\t\t\t\t\treturn Effect.succeed(normalized.ready);\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (ready) return;\n\n\t\t\tconst sleepMs = Math.min(intervalMs, Math.max(1, deadline - Date.now()));\n\t\t\tyield* Effect.sleep(Duration.millis(sleepMs));\n\t\t}\n\t});\n\nexport interface ExitCodeProbeResult {\n\treadonly exitCode: number;\n\treadonly stdout?: string;\n\treadonly stderr?: string;\n}\n\nexport const exitCodeProbeResult = (result: ExitCodeProbeResult): ProbeAttemptResult => {\n\tif (result.exitCode === 0) return true;\n\treturn {\n\t\tready: false,\n\t\tdetail: {\n\t\t\texitCode: result.exitCode,\n\t\t\t...(result.stdout === undefined ? {} : { stdout: result.stdout }),\n\t\t\t...(result.stderr === undefined ? {} : { stderr: result.stderr }),\n\t\t},\n\t};\n};\n\n// ---------------------------------------------------------------------------\n// probeManyLenient — run a set of lenient `T | null` probes and surface\n// each probe's verdict so the caller can fold the array however it likes.\n// ---------------------------------------------------------------------------\n//\n// Lenient probes (per `ChainProbe`'s `'lenient'` contract) return `T | null`\n// where `null` is a non-authoritative \"not yet\" signal. Several plugins\n// (walrus deploy, deepbook deploy, pyth init) hand-roll a sequential loop\n// that early-returns `null` on the first non-ready probe. This helper\n// centralizes the iteration so the call sites collapse to a `.every()`\n// or `.find()` against the returned array.\n//\n// Concurrency defaults to `'unbounded'`. Callers that need sequential\n// short-circuit semantics (e.g. RPC backoff politeness) can pass\n// `concurrency: 1`. The return shape is the full array even when concurrency\n// is 1 — callers that want \"any null aborts and returns null\" should fold\n// with `.every((x) => x !== null) ? array : null` themselves.\n\nexport const probeManyLenient = <T, E, R>(\n\tprobes: ReadonlyArray<Effect.Effect<T | null, E, R>>,\n\toptions?: { readonly concurrency?: Types.Concurrency },\n): Effect.Effect<ReadonlyArray<T | null>, E, R> =>\n\tEffect.forEach(probes, (probe) => probe, {\n\t\tconcurrency: options?.concurrency ?? 'unbounded',\n\t});\n"],"mappings":";;;;;;;;;;AAmBA,IAAa,2BAAb,cAA8C,KAAK,YAAY,2BAA2B,CAIvF;AAEH,IAAa,oBAAb,cAAuC,KAAK,YAAY,oBAAoB,CASzE;AAEH,MAAM,sBAAsB;AAE5B,MAAM,oBACL,WAC4D;AAC5D,KAAI,WAAW,KAAA,KAAa,WAAW,KAAM,QAAO,EAAE,OAAO,MAAM;AACnE,KAAI,WAAW,MAAO,QAAO,EAAE,OAAO,OAAO;AAC7C,QAAO;;AAGR,MAAM,sBACL,QACA,YAKuD;AACvD,KAAI,QAAQ,qBAAqB,KAAA,EAAW,QAAO;CACnD,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,kBAAkB,QAAQ,YAAY,CAAC;AACtF,QAAO,OAAO,KACb,OAAO,cAAc;EACpB,UAAU,SAAS,OAAO,UAAU;EACpC,cACC,OAAO,KACN,IAAI,yBAAyB;GAC5B,OAAO,QAAQ;GACf,kBAAkB;GAClB,SAAS,SAAS,QAAQ,MAAM,mCAAmC,UAAU;GAC7E,CAAC,CACF;EACF,CAAC,CACF;;AAGF,MAAa,gBACZ,YAEA,OAAO,IAAI,aAAa;CACvB,MAAM,YAAY,QAAQ;CAC1B,MAAM,aAAa,QAAQ,cAAc;CAEzC,MAAM,WADU,KAAK,KACG,GAAG;CAC3B,IAAI,WAAW;CACf,IAAI;CACJ,IAAI;AAEJ,UAAS;EACR,MAAM,cAAc,WAAW,KAAK,KAAK;AACzC,MAAI,eAAe,EAClB,QAAO,OAAO,OAAO,KACpB,IAAI,kBAAkB;GACrB,OAAO,QAAQ;GACf;GACA;GACA,GAAI,QAAQ,qBAAqB,KAAA,IAC9B,EAAE,GACF,EAAE,kBAAkB,QAAQ,kBAAkB;GACjD;GACA,SAAS,SAAS,QAAQ,MAAM,+BAA+B,UAAU;GACzE,GAAI,cAAc,KAAA,IAAY,EAAE,GAAG,EAAE,WAAW;GAChD,GAAI,iBAAiB,KAAA,IAAY,EAAE,GAAG,EAAE,cAAc;GACtD,CAAC,CACF;AAGF,cAAY;AAwBZ,MAAI,OAvBiB,mBAAmB,QAAQ,OAAO,EAAE;GACxD,OAAO,QAAQ;GACf,kBAAkB,QAAQ;GAC1B;GACA,CAAC,CAAC,KACF,OAAO,YAAY;GAClB,YAAY,UAAU;AACrB,QACC,EAAE,iBAAiB,6BACnB,QAAQ,mBAAmB,MAAW,KAAK,MAE3C,QAAO,OAAO,KAAK,MAAW;AAE/B,gBAAY;AACZ,WAAO,OAAO,QAAQ,MAAM;;GAE7B,YAAY,WAAW;IACtB,MAAM,aAAa,iBAAiB,OAAO;AAC3C,QAAI,CAAC,WAAW,MAAO,gBAAe,WAAW,UAAU;AAC3D,WAAO,OAAO,QAAQ,WAAW,MAAM;;GAExC,CAAC,CACF,CACU;EAEX,MAAM,UAAU,KAAK,IAAI,YAAY,KAAK,IAAI,GAAG,WAAW,KAAK,KAAK,CAAC,CAAC;AACxE,SAAO,OAAO,MAAM,SAAS,OAAO,QAAQ,CAAC;;EAE7C;AAQH,MAAa,uBAAuB,WAAoD;AACvF,KAAI,OAAO,aAAa,EAAG,QAAO;AAClC,QAAO;EACN,OAAO;EACP,QAAQ;GACP,UAAU,OAAO;GACjB,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,GAAG,EAAE,QAAQ,OAAO,QAAQ;GAChE,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,GAAG,EAAE,QAAQ,OAAO,QAAQ;GAChE;EACD;;AAqBF,MAAa,oBACZ,QACA,YAEA,OAAO,QAAQ,SAAS,UAAU,OAAO,EACxC,aAAa,SAAS,eAAe,aACrC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import "./state-ref.mjs";
2
+ import "./persisted.mjs";
3
+ import "./update.mjs";
4
+ export {};
@@ -6,20 +6,19 @@ const SAFE_URL_FIELDS = {
6
6
  faucetUrl: "faucet",
7
7
  graphqlUrl: "graphql"
8
8
  };
9
- const SENSITIVE_URL_FIELD = /pair|token|secret|password|private|bearer/i;
10
9
  const operationalEndpointEventsFromResolvedValue = (pluginKey, value, registeredAt, options = {}) => {
11
10
  if (options.routablesPresent === true) return [];
12
11
  if (value === null || typeof value !== "object") return [];
13
12
  const record = value;
14
13
  const events = [];
15
14
  for (const [field, name] of Object.entries(SAFE_URL_FIELDS)) {
16
- if (SENSITIVE_URL_FIELD.test(field)) continue;
17
15
  const raw = record[field];
18
16
  if (typeof raw !== "string" || !isHttpUrl(raw)) continue;
19
17
  events.push({
20
18
  tag: "endpoint.registered",
21
19
  endpoint: {
22
20
  endpointKey: endpointKey(`${pluginKey}:${field}`),
21
+ pluginKey,
23
22
  name,
24
23
  url: raw,
25
24
  displayUrl: null,
@@ -1 +1 @@
1
- {"version":3,"file":"operational-endpoints.mjs","names":[],"sources":["../../../../src/substrate/runtime/projection/operational-endpoints.ts"],"sourcesContent":["import { endpointKey, type PluginKey } from '../../brand.ts';\nimport type { EngineEvent } from '../../events.ts';\n\ntype EndpointRegisteredEvent = Extract<EngineEvent, { readonly tag: 'endpoint.registered' }>;\n\nconst SAFE_URL_FIELDS = {\n\turl: 'http',\n\trpcUrl: 'rpc',\n\tfaucetUrl: 'faucet',\n\tgraphqlUrl: 'graphql',\n} as const;\n\nconst SENSITIVE_URL_FIELD = /pair|token|secret|password|private|bearer/i;\n\nexport interface OperationalEndpointProjectionOptions {\n\t/** Routable capabilities are the authoritative public endpoint\n\t * source. Resolved-value URL scraping is only a fallback for\n\t * plugins with no router contribution, such as live/local-rpc\n\t * network modes. */\n\treadonly routablesPresent?: boolean;\n}\n\nexport const operationalEndpointEventsFromResolvedValue = (\n\tpluginKey: PluginKey,\n\tvalue: unknown,\n\tregisteredAt: number,\n\toptions: OperationalEndpointProjectionOptions = {},\n): ReadonlyArray<EndpointRegisteredEvent> => {\n\tif (options.routablesPresent === true) return [];\n\tif (value === null || typeof value !== 'object') return [];\n\tconst record = value as Readonly<Record<string, unknown>>;\n\tconst events: Array<EndpointRegisteredEvent> = [];\n\tfor (const [field, name] of Object.entries(SAFE_URL_FIELDS)) {\n\t\tif (SENSITIVE_URL_FIELD.test(field)) continue;\n\t\tconst raw = record[field];\n\t\tif (typeof raw !== 'string' || !isHttpUrl(raw)) continue;\n\t\tevents.push({\n\t\t\ttag: 'endpoint.registered',\n\t\t\tendpoint: {\n\t\t\t\tendpointKey: endpointKey(`${pluginKey}:${field}`),\n\t\t\t\tname,\n\t\t\t\turl: raw,\n\t\t\t\tdisplayUrl: null,\n\t\t\t\twireProtocol: 'http',\n\t\t\t\tregisteredAt,\n\t\t\t},\n\t\t});\n\t}\n\treturn events;\n};\n\nconst isHttpUrl = (value: string): boolean => {\n\ttry {\n\t\tconst parsed = new URL(value);\n\t\treturn parsed.protocol === 'http:' || parsed.protocol === 'https:';\n\t} catch {\n\t\treturn false;\n\t}\n};\n"],"mappings":";;AAKA,MAAM,kBAAkB;CACvB,KAAK;CACL,QAAQ;CACR,WAAW;CACX,YAAY;CACZ;AAED,MAAM,sBAAsB;AAU5B,MAAa,8CACZ,WACA,OACA,cACA,UAAgD,EAAE,KACN;AAC5C,KAAI,QAAQ,qBAAqB,KAAM,QAAO,EAAE;AAChD,KAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,EAAE;CAC1D,MAAM,SAAS;CACf,MAAM,SAAyC,EAAE;AACjD,MAAK,MAAM,CAAC,OAAO,SAAS,OAAO,QAAQ,gBAAgB,EAAE;AAC5D,MAAI,oBAAoB,KAAK,MAAM,CAAE;EACrC,MAAM,MAAM,OAAO;AACnB,MAAI,OAAO,QAAQ,YAAY,CAAC,UAAU,IAAI,CAAE;AAChD,SAAO,KAAK;GACX,KAAK;GACL,UAAU;IACT,aAAa,YAAY,GAAG,UAAU,GAAG,QAAQ;IACjD;IACA,KAAK;IACL,YAAY;IACZ,cAAc;IACd;IACA;GACD,CAAC;;AAEH,QAAO;;AAGR,MAAM,aAAa,UAA2B;AAC7C,KAAI;EACH,MAAM,SAAS,IAAI,IAAI,MAAM;AAC7B,SAAO,OAAO,aAAa,WAAW,OAAO,aAAa;SACnD;AACP,SAAO"}
1
+ {"version":3,"file":"operational-endpoints.mjs","names":[],"sources":["../../../../src/substrate/runtime/projection/operational-endpoints.ts"],"sourcesContent":["import { endpointKey, type PluginKey } from '../../brand.ts';\nimport type { EngineEvent } from '../../events.ts';\n\ntype EndpointRegisteredEvent = Extract<EngineEvent, { readonly tag: 'endpoint.registered' }>;\n\n// Endpoint-projection policy is closed-allowlist:\n// only the fields enumerated below are projected as operational\n// endpoints. Anything else — including legitimate sensitive URLs\n// (`pairUrl`, `walletPairingToken`, OAuth `tokenUrl`, etc.) and any\n// future field a plugin adds — is ignored by default. A plugin that\n// wants a new field projected must extend this list AND ship a\n// projection test pinning its display name. The previous loose\n// \"skip-if-matches-sensitive-regex\" check dropped legitimate OAuth\n// fields like `tokenUrl` and missed novel sensitive names; the\n// allowlist removes that whole class of false-negative/false-positive\n// pair.\nconst SAFE_URL_FIELDS = {\n\turl: 'http',\n\trpcUrl: 'rpc',\n\tfaucetUrl: 'faucet',\n\tgraphqlUrl: 'graphql',\n} as const;\n\nexport interface OperationalEndpointProjectionOptions {\n\t/** Routable capabilities are the authoritative public endpoint\n\t * source. Resolved-value URL scraping is only a fallback for\n\t * plugins with no router contribution, such as live/local-rpc\n\t * network modes. */\n\treadonly routablesPresent?: boolean;\n}\n\nexport const operationalEndpointEventsFromResolvedValue = (\n\tpluginKey: PluginKey,\n\tvalue: unknown,\n\tregisteredAt: number,\n\toptions: OperationalEndpointProjectionOptions = {},\n): ReadonlyArray<EndpointRegisteredEvent> => {\n\tif (options.routablesPresent === true) return [];\n\tif (value === null || typeof value !== 'object') return [];\n\tconst record = value as Readonly<Record<string, unknown>>;\n\tconst events: Array<EndpointRegisteredEvent> = [];\n\tfor (const [field, name] of Object.entries(SAFE_URL_FIELDS)) {\n\t\tconst raw = record[field];\n\t\tif (typeof raw !== 'string' || !isHttpUrl(raw)) continue;\n\t\tevents.push({\n\t\t\ttag: 'endpoint.registered',\n\t\t\tendpoint: {\n\t\t\t\tendpointKey: endpointKey(`${pluginKey}:${field}`),\n\t\t\t\tpluginKey,\n\t\t\t\tname,\n\t\t\t\turl: raw,\n\t\t\t\tdisplayUrl: null,\n\t\t\t\twireProtocol: 'http',\n\t\t\t\tregisteredAt,\n\t\t\t},\n\t\t});\n\t}\n\treturn events;\n};\n\nconst isHttpUrl = (value: string): boolean => {\n\ttry {\n\t\tconst parsed = new URL(value);\n\t\treturn parsed.protocol === 'http:' || parsed.protocol === 'https:';\n\t} catch {\n\t\treturn false;\n\t}\n};\n"],"mappings":";;AAgBA,MAAM,kBAAkB;CACvB,KAAK;CACL,QAAQ;CACR,WAAW;CACX,YAAY;CACZ;AAUD,MAAa,8CACZ,WACA,OACA,cACA,UAAgD,EAAE,KACN;AAC5C,KAAI,QAAQ,qBAAqB,KAAM,QAAO,EAAE;AAChD,KAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,EAAE;CAC1D,MAAM,SAAS;CACf,MAAM,SAAyC,EAAE;AACjD,MAAK,MAAM,CAAC,OAAO,SAAS,OAAO,QAAQ,gBAAgB,EAAE;EAC5D,MAAM,MAAM,OAAO;AACnB,MAAI,OAAO,QAAQ,YAAY,CAAC,UAAU,IAAI,CAAE;AAChD,SAAO,KAAK;GACX,KAAK;GACL,UAAU;IACT,aAAa,YAAY,GAAG,UAAU,GAAG,QAAQ;IACjD;IACA;IACA,KAAK;IACL,YAAY;IACZ,cAAc;IACd;IACA;GACD,CAAC;;AAEH,QAAO;;AAGR,MAAM,aAAa,UAA2B;AAC7C,KAAI;EACH,MAAM,SAAS,IAAI,IAAI,MAAM;AAC7B,SAAO,OAAO,aAAa,WAAW,OAAO,aAAa;SACnD;AACP,SAAO"}
@@ -1,11 +1,13 @@
1
- import { decodeJsonTextSync } from "../runtime-decode.mjs";
2
1
  import { endpointKey, pluginKey } from "../../brand.mjs";
2
+ import { versionedDocSchema } from "../../versioned-doc-schema.mjs";
3
3
  import { atomicWriteJson } from "../atomic-write.mjs";
4
+ import { logWarningAndIgnore } from "../observability/ignore-with-log.mjs";
5
+ import { decodeJsonTextSync } from "../runtime-decode.mjs";
4
6
  import { Effect, Schema, Stream, SubscriptionRef } from "effect";
5
7
  import { existsSync, readFileSync } from "node:fs";
6
8
  import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem";
7
9
  //#region src/substrate/runtime/projection/persisted.ts
8
- const PROJECTION_SNAPSHOT_FILE_NAME = "projection.v3.json";
10
+ const PROJECTION_SNAPSHOT_FILE_NAME = "projection.v4.json";
9
11
  const projectionSnapshotPath = (stackRoot) => `${stackRoot}/${PROJECTION_SNAPSHOT_FILE_NAME}`;
10
12
  const SeveritySchema = Schema.Literals([
11
13
  "warn",
@@ -33,6 +35,14 @@ const CyclePhaseSchema = Schema.Literals([
33
35
  "restarting",
34
36
  "shutting-down"
35
37
  ]);
38
+ const RowSectionSchema = Schema.Literals([
39
+ "service",
40
+ "package",
41
+ "account",
42
+ "action",
43
+ "app",
44
+ "other"
45
+ ]);
36
46
  const StructuredErrorSchema = Schema.Struct({
37
47
  at: Schema.Number,
38
48
  pluginKey: Schema.NullOr(Schema.String),
@@ -43,10 +53,15 @@ const StructuredErrorSchema = Schema.Struct({
43
53
  });
44
54
  const EndpointSchema = Schema.Struct({
45
55
  endpointKey: Schema.String,
56
+ pluginKey: Schema.String,
46
57
  name: Schema.String,
47
58
  url: Schema.String,
48
59
  displayUrl: Schema.NullOr(Schema.String),
49
- wireProtocol: Schema.String,
60
+ wireProtocol: Schema.Literals([
61
+ "http",
62
+ "h2c",
63
+ "tcp"
64
+ ]),
50
65
  registeredAt: Schema.Number
51
66
  });
52
67
  const AccountProjectionSchema = Schema.Struct({
@@ -74,7 +89,11 @@ const AccountProjectionSchema = Schema.Struct({
74
89
  coin: Schema.String,
75
90
  fullCoinType: Schema.String,
76
91
  amount: Schema.String,
77
- status: Schema.Literals(["funded", "skipped"])
92
+ status: Schema.Literals([
93
+ "funded",
94
+ "already-satisfied",
95
+ "skipped"
96
+ ])
78
97
  })))
79
98
  }),
80
99
  walletVisible: Schema.Boolean,
@@ -103,7 +122,9 @@ const RowSchema = Schema.Struct({
103
122
  truncated: Schema.Boolean
104
123
  }),
105
124
  endpoints: Schema.Array(Schema.String),
106
- selectiveRestartHighlight: Schema.Boolean
125
+ selectiveRestartHighlight: Schema.Boolean,
126
+ section: RowSectionSchema,
127
+ endpointSection: RowSectionSchema
107
128
  });
108
129
  const BuildEntrySchema = Schema.Struct({
109
130
  pluginKey: Schema.NullOr(Schema.String),
@@ -111,7 +132,7 @@ const BuildEntrySchema = Schema.Struct({
111
132
  progress: Schema.String,
112
133
  startedAt: Schema.Number
113
134
  });
114
- const SubscribableStateSchema = Schema.Struct({
135
+ const ProjectionSnapshotSchema = versionedDocSchema(4, { state: Schema.Struct({
115
136
  identity: Schema.Struct({
116
137
  app: Schema.String,
117
138
  stack: Schema.String,
@@ -132,11 +153,7 @@ const SubscribableStateSchema = Schema.Struct({
132
153
  at: Schema.Number
133
154
  }),
134
155
  stackBuild: Schema.Array(BuildEntrySchema)
135
- });
136
- const ProjectionSnapshotSchema = Schema.Struct({
137
- version: Schema.Literal(3),
138
- state: SubscribableStateSchema
139
- });
156
+ }) });
140
157
  const rebrandStructuredError = (error) => ({
141
158
  ...error,
142
159
  pluginKey: error.pluginKey === null ? null : pluginKey(error.pluginKey)
@@ -151,7 +168,8 @@ const rebrandPersistedState = (state) => ({
151
168
  })),
152
169
  endpoints: state.endpoints.map((endpoint) => ({
153
170
  ...endpoint,
154
- endpointKey: endpointKey(endpoint.endpointKey)
171
+ endpointKey: endpointKey(endpoint.endpointKey),
172
+ pluginKey: pluginKey(endpoint.pluginKey)
155
173
  })),
156
174
  accounts: state.accounts.map((account) => ({
157
175
  ...account,
@@ -170,9 +188,9 @@ const rebrandPersistedState = (state) => ({
170
188
  }))
171
189
  });
172
190
  const writeProjectionSnapshot = (stackRoot, state) => atomicWriteJson(projectionSnapshotPath(stackRoot), ProjectionSnapshotSchema, {
173
- version: 3,
191
+ version: 4,
174
192
  state
175
- }).pipe(Effect.provide(NodeFileSystem.layer), Effect.catch(() => Effect.void));
193
+ }).pipe(Effect.provide(NodeFileSystem.layer), logWarningAndIgnore("projection snapshot write failed", { path: projectionSnapshotPath(stackRoot) }));
176
194
  const persistProjectionChanges = (stackRoot, ref) => Effect.gen(function* () {
177
195
  yield* writeProjectionSnapshot(stackRoot, yield* SubscriptionRef.get(ref));
178
196
  yield* Stream.runForEach(SubscriptionRef.changes(ref), (state) => writeProjectionSnapshot(stackRoot, state));
@@ -190,6 +208,6 @@ const readProjectionSnapshot = (stackRoot) => {
190
208
  }
191
209
  };
192
210
  //#endregion
193
- export { persistProjectionChanges, readProjectionSnapshot, writeProjectionSnapshot };
211
+ export { AccountProjectionSchema, PROJECTION_SNAPSHOT_FILE_NAME, PackageProjectionSchema, ProjectionSnapshotSchema, persistProjectionChanges, projectionSnapshotPath, readProjectionSnapshot, writeProjectionSnapshot };
194
212
 
195
213
  //# sourceMappingURL=persisted.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"persisted.mjs","names":[],"sources":["../../../../src/substrate/runtime/projection/persisted.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\n\nimport { Effect, Schema, Stream, SubscriptionRef } from 'effect';\nimport * as NodeFileSystem from '@effect/platform-node/NodeFileSystem';\n\nimport type { SubscribableState } from '../../projection.ts';\nimport { endpointKey, pluginKey } from '../../brand.ts';\nimport { atomicWriteJson } from '../atomic-write.ts';\nimport { decodeJsonTextSync } from '../runtime-decode.ts';\n\nexport const PROJECTION_SNAPSHOT_FILE_NAME = 'projection.v3.json';\n\nexport const projectionSnapshotPath = (stackRoot: string): string =>\n\t`${stackRoot}/${PROJECTION_SNAPSHOT_FILE_NAME}`;\n\nconst SeveritySchema = Schema.Literals(['warn', 'error', 'fatal']);\nconst LogLevelSchema = Schema.Literals(['info', 'warn', 'error']);\nconst LifecycleStatusSchema = Schema.Literals([\n\t'pending',\n\t'acquiring',\n\t'ready',\n\t'failed',\n\t'stopping',\n\t'stopped',\n\t'done',\n]);\nconst PluginRoleSchema = Schema.Literals(['service', 'task']);\nconst CyclePhaseSchema = Schema.Literals(['booting', 'running', 'restarting', 'shutting-down']);\n\nconst StructuredErrorSchema = Schema.Struct({\n\tat: Schema.Number,\n\tpluginKey: Schema.NullOr(Schema.String),\n\ttag: Schema.String,\n\tsummary: Schema.String,\n\tchain: Schema.Array(Schema.String),\n\tseverity: SeveritySchema,\n});\n\nconst EndpointSchema = Schema.Struct({\n\tendpointKey: Schema.String,\n\tname: Schema.String,\n\turl: Schema.String,\n\tdisplayUrl: Schema.NullOr(Schema.String),\n\twireProtocol: Schema.String,\n\tregisteredAt: Schema.Number,\n});\n\nconst AccountProjectionSchema = Schema.Struct({\n\tkey: Schema.String,\n\trowKey: Schema.NullOr(Schema.String),\n\tname: Schema.String,\n\taddress: Schema.NullOr(Schema.String),\n\tscheme: Schema.NullOr(Schema.Literals(['ed25519', 'secp256k1', 'secp256r1'])),\n\tsource: Schema.NullOr(Schema.Literals(['real', 'impersonate'])),\n\tfunding: Schema.Struct({\n\t\tstatus: Schema.Literals(['pending', 'funded', 'skipped', 'failed', 'unknown']),\n\t\tbalanceMist: Schema.NullOr(Schema.String),\n\t\trequestedMist: Schema.NullOr(Schema.String),\n\t\tentries: Schema.optional(\n\t\t\tSchema.Array(\n\t\t\t\tSchema.Struct({\n\t\t\t\t\tcoin: Schema.String,\n\t\t\t\t\tfullCoinType: Schema.String,\n\t\t\t\t\tamount: Schema.String,\n\t\t\t\t\tstatus: Schema.Literals(['funded', 'skipped']),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t}),\n\twalletVisible: Schema.Boolean,\n\tupdatedAt: Schema.Number,\n});\n\nconst PackageProjectionSchema = Schema.Struct({\n\tkey: Schema.String,\n\trowKey: Schema.NullOr(Schema.String),\n\tname: Schema.String,\n\tkind: Schema.Literals(['local', 'known']),\n\tpackageId: Schema.String,\n\tupgradeCapId: Schema.NullOr(Schema.String),\n\tmvrPlaceholder: Schema.String,\n\tsourcePath: Schema.NullOr(Schema.String),\n\tupdatedAt: Schema.Number,\n});\n\nconst RowSchema = Schema.Struct({\n\tkey: Schema.String,\n\trole: PluginRoleSchema,\n\tstatus: LifecycleStatusSchema,\n\tphase: Schema.NullOr(Schema.String),\n\tlastError: Schema.NullOr(StructuredErrorSchema),\n\tlogTail: Schema.Struct({\n\t\tlines: Schema.Array(Schema.String),\n\t\tlevel: LogLevelSchema,\n\t\ttruncated: Schema.Boolean,\n\t}),\n\tendpoints: Schema.Array(Schema.String),\n\tselectiveRestartHighlight: Schema.Boolean,\n});\n\nconst BuildEntrySchema = Schema.Struct({\n\tpluginKey: Schema.NullOr(Schema.String),\n\tphase: Schema.String,\n\tprogress: Schema.String,\n\tstartedAt: Schema.Number,\n});\n\nconst SubscribableStateSchema = Schema.Struct({\n\tidentity: Schema.Struct({\n\t\tapp: Schema.String,\n\t\tstack: Schema.String,\n\t\tnetwork: Schema.String,\n\t}),\n\tcycle: Schema.Struct({\n\t\tid: Schema.Number,\n\t\tstartedAt: Schema.Number,\n\t\tphase: CyclePhaseSchema,\n\t}),\n\trows: Schema.Array(RowSchema),\n\tendpoints: Schema.Array(EndpointSchema),\n\taccounts: Schema.Array(AccountProjectionSchema),\n\tpackages: Schema.Array(PackageProjectionSchema),\n\terrors: Schema.Array(StructuredErrorSchema),\n\tlastEvent: Schema.Struct({\n\t\tseq: Schema.Number,\n\t\tat: Schema.Number,\n\t}),\n\tstackBuild: Schema.Array(BuildEntrySchema),\n});\n\nexport const ProjectionSnapshotSchema = Schema.Struct({\n\tversion: Schema.Literal(3),\n\tstate: SubscribableStateSchema,\n});\n\ntype PersistedSubscribableState = Schema.Schema.Type<typeof SubscribableStateSchema>;\ntype PersistedStructuredError = PersistedSubscribableState['errors'][number];\n\nconst rebrandStructuredError = (error: PersistedStructuredError) => ({\n\t...error,\n\tpluginKey: error.pluginKey === null ? null : pluginKey(error.pluginKey),\n});\n\nconst rebrandPersistedState = (state: PersistedSubscribableState): SubscribableState => ({\n\t...state,\n\trows: state.rows.map((row) => ({\n\t\t...row,\n\t\tkey: pluginKey(row.key),\n\t\tlastError: row.lastError === null ? null : rebrandStructuredError(row.lastError),\n\t\tendpoints: row.endpoints.map(endpointKey),\n\t})),\n\tendpoints: state.endpoints.map((endpoint) => ({\n\t\t...endpoint,\n\t\tendpointKey: endpointKey(endpoint.endpointKey),\n\t})),\n\taccounts: state.accounts.map((account) => ({\n\t\t...account,\n\t\tkey: account.key as `account/${string}`,\n\t\trowKey: account.rowKey === null ? null : pluginKey(account.rowKey),\n\t})),\n\tpackages: state.packages.map((pkg) => ({\n\t\t...pkg,\n\t\tkey: pkg.key as `package/${string}`,\n\t\trowKey: pkg.rowKey === null ? null : pluginKey(pkg.rowKey),\n\t})),\n\terrors: state.errors.map(rebrandStructuredError),\n\tstackBuild: state.stackBuild.map((entry) => ({\n\t\t...entry,\n\t\tpluginKey: entry.pluginKey === null ? null : pluginKey(entry.pluginKey),\n\t})),\n});\n\nexport const writeProjectionSnapshot = (\n\tstackRoot: string,\n\tstate: SubscribableState,\n): Effect.Effect<void> =>\n\tatomicWriteJson(projectionSnapshotPath(stackRoot), ProjectionSnapshotSchema, {\n\t\tversion: 3 as const,\n\t\tstate,\n\t}).pipe(\n\t\tEffect.provide(NodeFileSystem.layer),\n\t\tEffect.catch(() => Effect.void),\n\t);\n\nexport const persistProjectionChanges = (\n\tstackRoot: string,\n\tref: SubscriptionRef.SubscriptionRef<SubscribableState>,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tyield* writeProjectionSnapshot(stackRoot, yield* SubscriptionRef.get(ref));\n\t\tyield* Stream.runForEach(SubscriptionRef.changes(ref), (state) =>\n\t\t\twriteProjectionSnapshot(stackRoot, state),\n\t\t);\n\t});\n\nexport const readProjectionSnapshot = (stackRoot: string): SubscribableState | null => {\n\tconst path = projectionSnapshotPath(stackRoot);\n\tif (!existsSync(path)) return null;\n\ttry {\n\t\tconst snapshot = decodeJsonTextSync(ProjectionSnapshotSchema, readFileSync(path, 'utf8'), {\n\t\t\tsource: path,\n\t\t\tmkError: (issue) => issue,\n\t\t});\n\t\treturn rebrandPersistedState(snapshot.state);\n\t} catch {\n\t\treturn null;\n\t}\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"persisted.mjs","names":[],"sources":["../../../../src/substrate/runtime/projection/persisted.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\n\nimport { Effect, Schema, Stream, SubscriptionRef } from 'effect';\nimport * as NodeFileSystem from '@effect/platform-node/NodeFileSystem';\n\nimport type { SubscribableState } from '../../projection.ts';\nimport { endpointKey, pluginKey } from '../../brand.ts';\nimport { versionedDocSchema } from '../../versioned-doc-schema.ts';\nimport { atomicWriteJson } from '../atomic-write.ts';\nimport { logWarningAndIgnore } from '../observability/ignore-with-log.ts';\nimport { decodeJsonTextSync } from '../runtime-decode.ts';\n\nexport const PROJECTION_SNAPSHOT_FILE_NAME = 'projection.v4.json';\n\nexport const projectionSnapshotPath = (stackRoot: string): string =>\n\t`${stackRoot}/${PROJECTION_SNAPSHOT_FILE_NAME}`;\n\nconst SeveritySchema = Schema.Literals(['warn', 'error', 'fatal']);\nconst LogLevelSchema = Schema.Literals(['info', 'warn', 'error']);\nconst LifecycleStatusSchema = Schema.Literals([\n\t'pending',\n\t'acquiring',\n\t'ready',\n\t'failed',\n\t'stopping',\n\t'stopped',\n\t'done',\n]);\nconst PluginRoleSchema = Schema.Literals(['service', 'task']);\nconst CyclePhaseSchema = Schema.Literals(['booting', 'running', 'restarting', 'shutting-down']);\nconst RowSectionSchema = Schema.Literals([\n\t'service',\n\t'package',\n\t'account',\n\t'action',\n\t'app',\n\t'other',\n]);\n\nconst StructuredErrorSchema = Schema.Struct({\n\tat: Schema.Number,\n\tpluginKey: Schema.NullOr(Schema.String),\n\ttag: Schema.String,\n\tsummary: Schema.String,\n\tchain: Schema.Array(Schema.String),\n\tseverity: SeveritySchema,\n});\n\nconst EndpointSchema = Schema.Struct({\n\tendpointKey: Schema.String,\n\tpluginKey: Schema.String,\n\tname: Schema.String,\n\turl: Schema.String,\n\tdisplayUrl: Schema.NullOr(Schema.String),\n\twireProtocol: Schema.Literals(['http', 'h2c', 'tcp']),\n\tregisteredAt: Schema.Number,\n});\n\nexport const AccountProjectionSchema = Schema.Struct({\n\tkey: Schema.String,\n\trowKey: Schema.NullOr(Schema.String),\n\tname: Schema.String,\n\taddress: Schema.NullOr(Schema.String),\n\tscheme: Schema.NullOr(Schema.Literals(['ed25519', 'secp256k1', 'secp256r1'])),\n\tsource: Schema.NullOr(Schema.Literals(['real', 'impersonate'])),\n\tfunding: Schema.Struct({\n\t\tstatus: Schema.Literals(['pending', 'funded', 'skipped', 'failed', 'unknown']),\n\t\tbalanceMist: Schema.NullOr(Schema.String),\n\t\trequestedMist: Schema.NullOr(Schema.String),\n\t\tentries: Schema.optional(\n\t\t\tSchema.Array(\n\t\t\t\tSchema.Struct({\n\t\t\t\t\tcoin: Schema.String,\n\t\t\t\t\tfullCoinType: Schema.String,\n\t\t\t\t\tamount: Schema.String,\n\t\t\t\t\t// Mirrors `AccountProjection.funding.entries[].status` in\n\t\t\t\t\t// `substrate/projection.ts`. `'already-satisfied'` is\n\t\t\t\t\t// the pre-existing-balance short-circuit emitted by the\n\t\t\t\t\t// account funding pass — semantically a success, kept\n\t\t\t\t\t// distinct from `'funded'` so renderers can surface the\n\t\t\t\t\t// cached-vs-fresh distinction.\n\t\t\t\t\tstatus: Schema.Literals(['funded', 'already-satisfied', 'skipped']),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t}),\n\twalletVisible: Schema.Boolean,\n\tupdatedAt: Schema.Number,\n});\n\nexport const PackageProjectionSchema = Schema.Struct({\n\tkey: Schema.String,\n\trowKey: Schema.NullOr(Schema.String),\n\tname: Schema.String,\n\tkind: Schema.Literals(['local', 'known']),\n\tpackageId: Schema.String,\n\tupgradeCapId: Schema.NullOr(Schema.String),\n\tmvrPlaceholder: Schema.String,\n\tsourcePath: Schema.NullOr(Schema.String),\n\tupdatedAt: Schema.Number,\n});\n\nconst RowSchema = Schema.Struct({\n\tkey: Schema.String,\n\trole: PluginRoleSchema,\n\tstatus: LifecycleStatusSchema,\n\tphase: Schema.NullOr(Schema.String),\n\tlastError: Schema.NullOr(StructuredErrorSchema),\n\tlogTail: Schema.Struct({\n\t\tlines: Schema.Array(Schema.String),\n\t\tlevel: LogLevelSchema,\n\t\ttruncated: Schema.Boolean,\n\t}),\n\tendpoints: Schema.Array(Schema.String),\n\tselectiveRestartHighlight: Schema.Boolean,\n\tsection: RowSectionSchema,\n\tendpointSection: RowSectionSchema,\n});\n\nconst BuildEntrySchema = Schema.Struct({\n\tpluginKey: Schema.NullOr(Schema.String),\n\tphase: Schema.String,\n\tprogress: Schema.String,\n\tstartedAt: Schema.Number,\n});\n\nconst SubscribableStateSchema = Schema.Struct({\n\tidentity: Schema.Struct({\n\t\tapp: Schema.String,\n\t\tstack: Schema.String,\n\t\tnetwork: Schema.String,\n\t}),\n\tcycle: Schema.Struct({\n\t\tid: Schema.Number,\n\t\tstartedAt: Schema.Number,\n\t\tphase: CyclePhaseSchema,\n\t}),\n\trows: Schema.Array(RowSchema),\n\tendpoints: Schema.Array(EndpointSchema),\n\taccounts: Schema.Array(AccountProjectionSchema),\n\tpackages: Schema.Array(PackageProjectionSchema),\n\terrors: Schema.Array(StructuredErrorSchema),\n\tlastEvent: Schema.Struct({\n\t\tseq: Schema.Number,\n\t\tat: Schema.Number,\n\t}),\n\tstackBuild: Schema.Array(BuildEntrySchema),\n});\n\nexport const ProjectionSnapshotSchema = versionedDocSchema(4, {\n\tstate: SubscribableStateSchema,\n});\n\ntype PersistedSubscribableState = Schema.Schema.Type<typeof SubscribableStateSchema>;\ntype PersistedStructuredError = PersistedSubscribableState['errors'][number];\n\nconst rebrandStructuredError = (error: PersistedStructuredError) => ({\n\t...error,\n\tpluginKey: error.pluginKey === null ? null : pluginKey(error.pluginKey),\n});\n\nconst rebrandPersistedState = (state: PersistedSubscribableState): SubscribableState => ({\n\t...state,\n\trows: state.rows.map((row) => ({\n\t\t...row,\n\t\tkey: pluginKey(row.key),\n\t\tlastError: row.lastError === null ? null : rebrandStructuredError(row.lastError),\n\t\tendpoints: row.endpoints.map(endpointKey),\n\t})),\n\tendpoints: state.endpoints.map((endpoint) => ({\n\t\t...endpoint,\n\t\tendpointKey: endpointKey(endpoint.endpointKey),\n\t\tpluginKey: pluginKey(endpoint.pluginKey),\n\t})),\n\taccounts: state.accounts.map((account) => ({\n\t\t...account,\n\t\tkey: account.key as `account/${string}`,\n\t\trowKey: account.rowKey === null ? null : pluginKey(account.rowKey),\n\t})),\n\tpackages: state.packages.map((pkg) => ({\n\t\t...pkg,\n\t\tkey: pkg.key as `package/${string}`,\n\t\trowKey: pkg.rowKey === null ? null : pluginKey(pkg.rowKey),\n\t})),\n\terrors: state.errors.map(rebrandStructuredError),\n\tstackBuild: state.stackBuild.map((entry) => ({\n\t\t...entry,\n\t\tpluginKey: entry.pluginKey === null ? null : pluginKey(entry.pluginKey),\n\t})),\n});\n\nexport const writeProjectionSnapshot = (\n\tstackRoot: string,\n\tstate: SubscribableState,\n): Effect.Effect<void> =>\n\tatomicWriteJson(projectionSnapshotPath(stackRoot), ProjectionSnapshotSchema, {\n\t\tversion: 4 as const,\n\t\tstate,\n\t}).pipe(\n\t\tEffect.provide(NodeFileSystem.layer),\n\t\t// Best-effort: a snapshot write failure must not fail the caller\n\t\t// (the projection is a re-derivable read model). But a bare\n\t\t// `Effect.catch(() => Effect.void)` hid disk-full / permission\n\t\t// faults entirely — leave the cause in the log stream (§18) so a\n\t\t// persistently-failing snapshot is diagnosable.\n\t\tlogWarningAndIgnore('projection snapshot write failed', {\n\t\t\tpath: projectionSnapshotPath(stackRoot),\n\t\t}),\n\t);\n\nexport const persistProjectionChanges = (\n\tstackRoot: string,\n\tref: SubscriptionRef.SubscriptionRef<SubscribableState>,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tyield* writeProjectionSnapshot(stackRoot, yield* SubscriptionRef.get(ref));\n\t\tyield* Stream.runForEach(SubscriptionRef.changes(ref), (state) =>\n\t\t\twriteProjectionSnapshot(stackRoot, state),\n\t\t);\n\t});\n\nexport const readProjectionSnapshot = (stackRoot: string): SubscribableState | null => {\n\tconst path = projectionSnapshotPath(stackRoot);\n\tif (!existsSync(path)) return null;\n\ttry {\n\t\tconst snapshot = decodeJsonTextSync(ProjectionSnapshotSchema, readFileSync(path, 'utf8'), {\n\t\t\tsource: path,\n\t\t\tmkError: (issue) => issue,\n\t\t});\n\t\treturn rebrandPersistedState(snapshot.state);\n\t} catch {\n\t\treturn null;\n\t}\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { SubscriptionRef } from "effect";
1
+ import { Effect, SubscriptionRef } from "effect";
2
2
  //#region src/substrate/runtime/projection/state-ref.ts
3
3
  /**
4
4
  * Empty initial projection. Cycle starts at `id: 0`, `phase:
@@ -42,7 +42,31 @@ const emptyProjection = () => ({
42
42
  * lifetime from engine cycle.
43
43
  */
44
44
  const makeProjectionRef = () => SubscriptionRef.make(emptyProjection());
45
+ /**
46
+ * Sync-only constructor for the subscribable projection ref. The
47
+ * `runStack(...)` API allocates the ref BEFORE the supervised
48
+ * Effect runs so callers can subscribe to `state.changes` ahead of
49
+ * boot — that allocation path has no Effect runtime to run under and
50
+ * must complete synchronously.
51
+ *
52
+ * Callers that already live inside an Effect should use the
53
+ * Effect-wrapped `makeProjectionRef()` so future changes to the
54
+ * constructor stay Effect-correct without breaking those call
55
+ * sites. This sync variant is pinned at the substrate boundary: any
56
+ * future refactor of `makeProjectionRef` (e.g. layering a `withSpan`
57
+ * or annotation) MUST keep `makeProjectionRefSync` synchronous — if
58
+ * that ever becomes impossible the boot-time call site needs a
59
+ * different signaling strategy (Deferred-handoff), not a silent
60
+ * `Effect.runSync` crash on an async effect.
61
+ *
62
+ * `SubscriptionRef.make` is sync-effect today (no async, no
63
+ * side-effects beyond an `unbounded` `PubSub.unbounded({ replay:
64
+ * 1 })`), so `Effect.runSync` is safe right now; the indirection
65
+ * exists so the constraint is documented at the constructor, not
66
+ * inferred from the caller.
67
+ */
68
+ const makeProjectionRefSync = () => Effect.runSync(makeProjectionRef());
45
69
  //#endregion
46
- export { makeProjectionRef };
70
+ export { emptyProjection, makeProjectionRef, makeProjectionRefSync };
47
71
 
48
72
  //# sourceMappingURL=state-ref.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"state-ref.mjs","names":[],"sources":["../../../../src/substrate/runtime/projection/state-ref.ts"],"sourcesContent":["// Subscribable projection state-ref.\n//\n// Architecture § Renderer § \"Subscribable projection — exact field\n// enumeration\" (G2) + § \"Renderer mount lifetime vs engine cycle\n// lifetime\" (decision #8). The state-ref is process-scoped (mounted\n// once); the engine cycle re-runs many times and never re-creates the\n// ref. The renderer subscribes once at mount; the engine updates\n// in-place across cycles.\n//\n// The projection's TypeScript shape is enforced closed by\n// `__ProjectionFieldsClosed` in `../../projection.ts`. Adding a\n// display-vocabulary field (`title`, `primary`, `extras`) at this\n// layer would fail to assign into `SubscribableState` — renderers\n// derive those from `rows[*].kind` + display rules.\n\nimport { Effect, SubscriptionRef } from 'effect';\n\nimport type {\n\tBuildEntry,\n\tAccountProjection,\n\tEndpoint,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n\tSubscribableState,\n} from '../../projection.ts';\n\n/**\n * Empty initial projection. Cycle starts at `id: 0`, `phase:\n * 'booting'`. Identity fields are placeholder; the engine MUST\n * replace via `update.ts::setIdentity` before any renderer is\n * notified of anything user-visible.\n *\n * The shape here is the entire contract the renderer sees — no\n * service names, no display vocabulary. If a future field needs\n * adding, the architecture-revision discipline kicks in via\n * `__ProjectionFieldsClosed`.\n */\nexport const emptyProjection = (): SubscribableState => ({\n\tidentity: { app: '', stack: '', network: '' },\n\tcycle: { id: 0, startedAt: 0, phase: 'booting' },\n\trows: [],\n\tendpoints: [],\n\taccounts: [],\n\tpackages: [],\n\terrors: [],\n\tlastEvent: { seq: 0, at: 0 },\n\tstackBuild: [],\n});\n\n/**\n * Create the subscribable projection ref. One per process.\n *\n * Engine cycle: the ref outlives the engine cycle. Stop-and-restart\n * keeps the same ref; only `cycle.id` increments. Renderers see a\n * continuous stream — that's the whole point of decoupling renderer\n * lifetime from engine cycle.\n */\nexport const makeProjectionRef = (): Effect.Effect<\n\tSubscriptionRef.SubscriptionRef<SubscribableState>\n> => SubscriptionRef.make(emptyProjection());\n\n/**\n * Compile-time guard: the projection shape MUST NOT contain display\n * vocabulary. These conditional types resolve to `never` (and would\n * fail to assign anywhere they're used) if `title`/`primary`/\n * `extras` were ever added to `SubscribableState` or `Row`.\n *\n * The architecture's invariant becomes a TS error at the boundary\n * — the projection layer can't be wired up if a renderer-display\n * concept leaks into the engine's data model.\n */\ntype _NoDisplayVocabAtTop = 'title' extends keyof SubscribableState\n\t? never\n\t: 'primary' extends keyof SubscribableState\n\t\t? never\n\t\t: 'extras' extends keyof SubscribableState\n\t\t\t? never\n\t\t\t: true;\ntype _NoDisplayVocabInRow = 'title' extends keyof Row\n\t? never\n\t: 'primary' extends keyof Row\n\t\t? never\n\t\t: 'extras' extends keyof Row\n\t\t\t? never\n\t\t\t: true;\nexport type __NoDisplayVocab = _NoDisplayVocabAtTop & _NoDisplayVocabInRow extends true\n\t? true\n\t: never;\n\n// Re-export the sub-types renderers reach for so they don't import\n// across the substrate boundary directly — `state-ref.ts` is the\n// renderer-facing entry point.\nexport type {\n\tAccountProjection,\n\tBuildEntry,\n\tEndpoint,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n\tSubscribableState,\n};\n"],"mappings":";;;;;;;;;;;;;AAsCA,MAAa,yBAA4C;CACxD,UAAU;EAAE,KAAK;EAAI,OAAO;EAAI,SAAS;EAAI;CAC7C,OAAO;EAAE,IAAI;EAAG,WAAW;EAAG,OAAO;EAAW;CAChD,MAAM,EAAE;CACR,WAAW,EAAE;CACb,UAAU,EAAE;CACZ,UAAU,EAAE;CACZ,QAAQ,EAAE;CACV,WAAW;EAAE,KAAK;EAAG,IAAI;EAAG;CAC5B,YAAY,EAAE;CACd;;;;;;;;;AAUD,MAAa,0BAER,gBAAgB,KAAK,iBAAiB,CAAC"}
1
+ {"version":3,"file":"state-ref.mjs","names":[],"sources":["../../../../src/substrate/runtime/projection/state-ref.ts"],"sourcesContent":["// Subscribable projection state-ref.\n//\n// Architecture § Renderer § \"Subscribable projection — exact field\n// enumeration\" (G2) + § \"Renderer mount lifetime vs engine cycle\n// lifetime\" (decision #8). The state-ref is process-scoped (mounted\n// once); the engine cycle re-runs many times and never re-creates the\n// ref. The renderer subscribes once at mount; the engine updates\n// in-place across cycles.\n//\n// The projection's TypeScript shape is enforced closed by\n// `__ProjectionFieldsClosed` in `../../projection.ts`. Adding a\n// display-vocabulary field (`title`, `primary`, `extras`) at this\n// layer would fail to assign into `SubscribableState` — renderers\n// derive those from `rows[*].kind` + display rules.\n\nimport { Effect, SubscriptionRef } from 'effect';\n\nimport type {\n\tBuildEntry,\n\tAccountProjection,\n\tEndpoint,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n\tSubscribableState,\n} from '../../projection.ts';\n\n/**\n * Empty initial projection. Cycle starts at `id: 0`, `phase:\n * 'booting'`. Identity fields are placeholder; the engine MUST\n * replace via `update.ts::setIdentity` before any renderer is\n * notified of anything user-visible.\n *\n * The shape here is the entire contract the renderer sees — no\n * service names, no display vocabulary. If a future field needs\n * adding, the architecture-revision discipline kicks in via\n * `__ProjectionFieldsClosed`.\n */\nexport const emptyProjection = (): SubscribableState => ({\n\tidentity: { app: '', stack: '', network: '' },\n\tcycle: { id: 0, startedAt: 0, phase: 'booting' },\n\trows: [],\n\tendpoints: [],\n\taccounts: [],\n\tpackages: [],\n\terrors: [],\n\tlastEvent: { seq: 0, at: 0 },\n\tstackBuild: [],\n});\n\n/**\n * Create the subscribable projection ref. One per process.\n *\n * Engine cycle: the ref outlives the engine cycle. Stop-and-restart\n * keeps the same ref; only `cycle.id` increments. Renderers see a\n * continuous stream — that's the whole point of decoupling renderer\n * lifetime from engine cycle.\n */\nexport const makeProjectionRef = (): Effect.Effect<\n\tSubscriptionRef.SubscriptionRef<SubscribableState>\n> => SubscriptionRef.make(emptyProjection());\n\n/**\n * Sync-only constructor for the subscribable projection ref. The\n * `runStack(...)` API allocates the ref BEFORE the supervised\n * Effect runs so callers can subscribe to `state.changes` ahead of\n * boot — that allocation path has no Effect runtime to run under and\n * must complete synchronously.\n *\n * Callers that already live inside an Effect should use the\n * Effect-wrapped `makeProjectionRef()` so future changes to the\n * constructor stay Effect-correct without breaking those call\n * sites. This sync variant is pinned at the substrate boundary: any\n * future refactor of `makeProjectionRef` (e.g. layering a `withSpan`\n * or annotation) MUST keep `makeProjectionRefSync` synchronous — if\n * that ever becomes impossible the boot-time call site needs a\n * different signaling strategy (Deferred-handoff), not a silent\n * `Effect.runSync` crash on an async effect.\n *\n * `SubscriptionRef.make` is sync-effect today (no async, no\n * side-effects beyond an `unbounded` `PubSub.unbounded({ replay:\n * 1 })`), so `Effect.runSync` is safe right now; the indirection\n * exists so the constraint is documented at the constructor, not\n * inferred from the caller.\n */\nexport const makeProjectionRefSync = (): SubscriptionRef.SubscriptionRef<SubscribableState> =>\n\tEffect.runSync(makeProjectionRef());\n\n/**\n * Compile-time guard: the projection shape MUST NOT contain display\n * vocabulary. These conditional types resolve to `never` (and would\n * fail to assign anywhere they're used) if `title`/`primary`/\n * `extras` were ever added to `SubscribableState` or `Row`.\n *\n * The architecture's invariant becomes a TS error at the boundary\n * — the projection layer can't be wired up if a renderer-display\n * concept leaks into the engine's data model.\n */\ntype _NoDisplayVocabAtTop = 'title' extends keyof SubscribableState\n\t? never\n\t: 'primary' extends keyof SubscribableState\n\t\t? never\n\t\t: 'extras' extends keyof SubscribableState\n\t\t\t? never\n\t\t\t: true;\ntype _NoDisplayVocabInRow = 'title' extends keyof Row\n\t? never\n\t: 'primary' extends keyof Row\n\t\t? never\n\t\t: 'extras' extends keyof Row\n\t\t\t? never\n\t\t\t: true;\nexport type __NoDisplayVocab = _NoDisplayVocabAtTop & _NoDisplayVocabInRow extends true\n\t? true\n\t: never;\n\n// Re-export the sub-types renderers reach for so they don't import\n// across the substrate boundary directly — `state-ref.ts` is the\n// renderer-facing entry point.\nexport type {\n\tAccountProjection,\n\tBuildEntry,\n\tEndpoint,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n\tSubscribableState,\n};\n"],"mappings":";;;;;;;;;;;;;AAsCA,MAAa,yBAA4C;CACxD,UAAU;EAAE,KAAK;EAAI,OAAO;EAAI,SAAS;EAAI;CAC7C,OAAO;EAAE,IAAI;EAAG,WAAW;EAAG,OAAO;EAAW;CAChD,MAAM,EAAE;CACR,WAAW,EAAE;CACb,UAAU,EAAE;CACZ,UAAU,EAAE;CACZ,QAAQ,EAAE;CACV,WAAW;EAAE,KAAK;EAAG,IAAI;EAAG;CAC5B,YAAY,EAAE;CACd;;;;;;;;;AAUD,MAAa,0BAER,gBAAgB,KAAK,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AAyB5C,MAAa,8BACZ,OAAO,QAAQ,mBAAmB,CAAC"}
@@ -1,5 +1,8 @@
1
+ import { SpanAttr } from "../observability/spans.mjs";
2
+ import { AccountProjectionSchema, PackageProjectionSchema } from "./persisted.mjs";
3
+ import { eventAtOrNull } from "../../event-time.mjs";
1
4
  import { applyLifecycleFact, factFromEvent } from "../lifecycle/lifecycle-fact.mjs";
2
- import { SubscriptionRef } from "effect";
5
+ import { Effect, Schema, SubscriptionRef } from "effect";
3
6
  //#region src/substrate/runtime/projection/update.ts
4
7
  /** Bounded buffer for the top-level errors list. */
5
8
  const MAX_ERRORS_KEPT = 100;
@@ -15,14 +18,24 @@ const MAX_ROW_LOG_LINES = 100;
15
18
  * The `tag` switch is exhaustive against `EngineEvent['tag']`; the
16
19
  * trailing `_exhaustive: never` causes TS to flag any new tag that
17
20
  * isn't handled here.
21
+ *
22
+ * @param prevalidated - Optional pre-flight decode result for
23
+ * `projection.updated` payloads. When the Effect-aware `updateRef`
24
+ * seam has already decoded the payload (to drive the warning
25
+ * emission inside the fiber's logger Layer), it threads the result
26
+ * here so the reducer doesn't decode the same payload twice on
27
+ * the hot path. Direct `applyEvent` callers (tests, in-process
28
+ * projection consumers) leave this undefined and the reducer
29
+ * re-decodes — the schema is sync + deterministic so the cached
30
+ * result and a fresh decode agree.
18
31
  */
19
- const applyEvent = (state, event) => {
32
+ const applyEvent = (state, event, prevalidated) => {
20
33
  const withTouched = (next) => ({
21
34
  ...state,
22
35
  ...next,
23
36
  lastEvent: {
24
37
  seq: state.lastEvent.seq,
25
- at: eventAt(event) ?? state.lastEvent.at
38
+ at: eventAtOrNull(event) ?? state.lastEvent.at
26
39
  }
27
40
  });
28
41
  const fact = factFromEvent(event);
@@ -35,8 +48,10 @@ const applyEvent = (state, event) => {
35
48
  endpoints: upsertEndpoint(state.endpoints, event.endpoint),
36
49
  rows: attachEndpoint(state.rows, event.endpoint)
37
50
  });
38
- case "account.updated": return withTouched({ accounts: upsertAccount(state.accounts, event.account) });
39
- case "package.updated": return withTouched({ packages: upsertPackage(state.packages, event.package) });
51
+ case "projection.updated":
52
+ if (event.kind === "account") return (prevalidated ?? tryDecodeProjectionPayload(AccountProjectionSchema, event.payload)).ok ? withTouched({ accounts: upsertAccount(state.accounts, event.payload) }) : withTouched({});
53
+ if (event.kind === "package") return (prevalidated ?? tryDecodeProjectionPayload(PackageProjectionSchema, event.payload)).ok ? withTouched({ packages: upsertPackage(state.packages, event.payload) }) : withTouched({});
54
+ return withTouched({});
40
55
  case "endpoint.released": return withTouched({});
41
56
  case "strategy.registered":
42
57
  case "strategy.unregistered":
@@ -83,6 +98,7 @@ const applyEvent = (state, event) => {
83
98
  selectiveRestartHighlight: false
84
99
  }))
85
100
  });
101
+ case "engine.orchestrator.dispatchFailed": return withTouched({});
86
102
  default: return state;
87
103
  }
88
104
  };
@@ -104,26 +120,75 @@ const declareAccount = (state, account) => ({
104
120
  * boundaries.
105
121
  *
106
122
  * Uses `state.lastEvent.seq + 1` for monotonic per-process counts.
123
+ *
124
+ * Side-channel: when the event is a `projection.updated` with a
125
+ * malformed payload, the reducer drops the slice and we emit a
126
+ * structured warning here, inside the surrounding fiber, so it lands
127
+ * on the fiber's structured-logging path (`Effect.logWarning`). This
128
+ * is the only place in the reducer where a warning is emitted; the
129
+ * pure `applyEvent` reducer never touches the logger.
107
130
  */
108
- const updateRef = (ref, event) => SubscriptionRef.update(ref, (state) => {
109
- const next = applyEvent(state, event);
110
- return {
111
- ...next,
112
- lastEvent: {
113
- seq: state.lastEvent.seq + 1,
114
- at: next.lastEvent.at
131
+ const updateRef = (ref, event) => Effect.gen(function* () {
132
+ let prevalidated;
133
+ if (event.tag === "projection.updated") {
134
+ if (event.kind === "account" || event.kind === "package") {
135
+ prevalidated = tryDecodeProjectionPayload(event.kind === "account" ? AccountProjectionSchema : PackageProjectionSchema, event.payload);
136
+ if (!prevalidated.ok) yield* Effect.logWarning(`projection.updated: dropping malformed ${event.kind} payload for key=${event.key}`).pipe(Effect.annotateLogs({ [SpanAttr.errorMessage]: formatDecodeIssue(prevalidated.cause) }));
115
137
  }
116
- };
138
+ }
139
+ yield* SubscriptionRef.update(ref, (state) => {
140
+ const next = applyEvent(state, event, prevalidated);
141
+ return {
142
+ ...next,
143
+ lastEvent: {
144
+ seq: state.lastEvent.seq + 1,
145
+ at: next.lastEvent.at
146
+ }
147
+ };
148
+ });
117
149
  });
118
- const eventAt = (event) => {
119
- if ("at" in event) return event.at;
120
- switch (event.tag) {
121
- case "endpoint.registered": return event.endpoint.registeredAt;
122
- case "error.reported": return event.error.at;
123
- case "build.statusChanged": return event.entry.startedAt;
124
- default: return null;
150
+ /**
151
+ * Sync per-kind validator for `projection.updated` payloads. Returns
152
+ * an `ok` decode result on success or a non-`ok` one on decode
153
+ * failure. Pure-data sync: no logger access, no `Effect.runSync` —
154
+ * the reducer is documented as pure, and earlier versions of this
155
+ * seam called `Effect.runSync(Effect.logWarning(...))` outside any
156
+ * fiber context, which logged off-fiber (bypassing the supervisor's
157
+ * structured-logging context). The Effect-aware `updateRef` wrapper
158
+ * now emits the warning inside the fiber so the warning is captured
159
+ * consistently with the rest of the supervisor's logs.
160
+ *
161
+ * On success callers still pass `event.payload` to the upsert (not the
162
+ * decoded copy) — the runtime brand types (`account/${string}`,
163
+ * `package/${string}`) are TS-only and the decoded copy would strip
164
+ * them. The schema acts as a structural guard only.
165
+ */
166
+ const tryDecodeProjectionPayload = (schema, payload) => {
167
+ try {
168
+ return {
169
+ ok: true,
170
+ value: Schema.decodeUnknownSync(schema)(payload)
171
+ };
172
+ } catch (cause) {
173
+ return {
174
+ ok: false,
175
+ cause
176
+ };
125
177
  }
126
178
  };
179
+ /**
180
+ * Render a `Schema.decodeUnknownSync` throw into a human-readable
181
+ * string for the warn annotation. `SchemaError` in Effect v4 stores
182
+ * the parse issue and exposes `.message` (= `issue.toString()`); using
183
+ * that surfaces the actual decode-issue path/expectation. Fallback to
184
+ * `String(cause)` for non-SchemaError throws (defensive — the schema's
185
+ * sync decoder should always throw `SchemaError`).
186
+ */
187
+ const formatDecodeIssue = (cause) => {
188
+ if (Schema.isSchemaError(cause)) return cause.message;
189
+ if (cause instanceof Error) return cause.message;
190
+ return String(cause);
191
+ };
127
192
  const upsertRow = (rows, key, update) => {
128
193
  const idx = rows.findIndex((r) => r.key === key);
129
194
  if (idx === -1) return rows;
@@ -184,10 +249,9 @@ const upsertPackage = (packages, pkg) => {
184
249
  return next;
185
250
  };
186
251
  const attachEndpoint = (rows, endpoint) => {
187
- const probableKey = endpoint.endpointKey;
188
- return rows.map((row) => probableKey.startsWith(row.key) ? row.endpoints.includes(probableKey) ? row : {
252
+ return rows.map((row) => endpoint.pluginKey === row.key ? row.endpoints.includes(endpoint.endpointKey) ? row : {
189
253
  ...row,
190
- endpoints: [...row.endpoints, probableKey]
254
+ endpoints: [...row.endpoints, endpoint.endpointKey]
191
255
  } : row);
192
256
  };
193
257
  const pushBounded = (xs, value, max) => {
@@ -195,6 +259,6 @@ const pushBounded = (xs, value, max) => {
195
259
  return next.length > max ? next.slice(-max) : next;
196
260
  };
197
261
  //#endregion
198
- export { declareAccount, setIdentity, updateRef };
262
+ export { applyEvent, declareAccount, setIdentity, updateRef };
199
263
 
200
264
  //# sourceMappingURL=update.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.mjs","names":[],"sources":["../../../../src/substrate/runtime/projection/update.ts"],"sourcesContent":["// Projection updater.\n//\n// Architecture § Renderer § \"Subscribable projection — exact field\n// enumeration\" (G2). The updater is a typed event-handler: each\n// `EngineEvent` produces a structurally-typed projection mutation.\n// Renderers never see the event taxonomy here; they only see the\n// resulting state.\n//\n// The updater is *pure data*: it takes the old state + an event,\n// returns the new state. Atomicity comes from\n// `SubscriptionRef.update` at the call site.\n//\n// Discipline:\n// - No display vocabulary (`title`, `primary`, `extras`) anywhere\n// in the produced state.\n// - All fields the architecture enumerates are reachable; new\n// event tags are picked up via exhaustive `tag` match (the\n// `_exhaustive: never` line will fail to type-check if a new\n// tag is added without a handler here).\n\nimport { Effect, SubscriptionRef } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport type { EngineEvent } from '../../events.ts';\nimport type { LifecycleStatus } from '../../lifecycle.ts';\nimport type {\n\tAccountProjection,\n\tBuildEntry,\n\tEndpoint,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n\tSubscribableState,\n} from '../../projection.ts';\nimport { applyLifecycleFact, factFromEvent } from '../lifecycle/lifecycle-fact.ts';\n\n// -----------------------------------------------------------------------------\n// Capacity policy\n// -----------------------------------------------------------------------------\n\n/** Bounded buffer for the top-level errors list. */\nconst MAX_ERRORS_KEPT = 100;\n/** Bounded buffer for the top-level build-entries list. */\nconst MAX_BUILD_ENTRIES_KEPT = 200;\n/** Per-row bounded log-tail length. Architecture: default 100 lines. */\nconst MAX_ROW_LOG_LINES = 100;\n\n// -----------------------------------------------------------------------------\n// Pure reducer\n// -----------------------------------------------------------------------------\n\n/**\n * Pure projection reducer. One event in, one new state out. All field\n * writes preserve `readonly` invariants by constructing fresh\n * objects/arrays rather than mutating.\n *\n * The `tag` switch is exhaustive against `EngineEvent['tag']`; the\n * trailing `_exhaustive: never` causes TS to flag any new tag that\n * isn't handled here.\n */\nexport const applyEvent = (state: SubscribableState, event: EngineEvent): SubscribableState => {\n\t// Every event advances `lastEvent.at`. `lastEvent.seq` is bumped at\n\t// the `updateRef` wrapper, not here — this reducer is pure data.\n\tconst withTouched = (next: Partial<SubscribableState>): SubscribableState => ({\n\t\t...state,\n\t\t...next,\n\t\tlastEvent: { seq: state.lastEvent.seq, at: eventAt(event) ?? state.lastEvent.at },\n\t});\n\n\t// Lifecycle-shaped events flow through the typed `LifecycleFact`\n\t// bridge — the projection consumes the merge-not-replace fact\n\t// instead of writing each lifecycle field independently. Non-\n\t// lifecycle events take their original specialised paths below.\n\tconst fact = factFromEvent(event);\n\tif (fact !== null) {\n\t\treturn withTouched({\n\t\t\trows: upsertRow(state.rows, fact.pluginKey as PluginKey, (row) =>\n\t\t\t\tapplyLifecycleFact(row, fact.delta),\n\t\t\t),\n\t\t});\n\t}\n\n\tswitch (event.tag) {\n\t\tcase 'lifecycle.statusChanged':\n\t\tcase 'lifecycle.phaseSet':\n\t\t\t// Handled above via `factFromEvent` — kept in the switch for\n\t\t\t// `_exhaustive` discipline.\n\t\t\treturn withTouched({});\n\n\t\tcase 'log.appended':\n\t\t\treturn withTouched({\n\t\t\t\trows: upsertRow(state.rows, event.pluginKey, (row) =>\n\t\t\t\t\tappendLogLine(row, event.line, event.level),\n\t\t\t\t),\n\t\t\t});\n\n\t\tcase 'endpoint.registered':\n\t\t\treturn withTouched({\n\t\t\t\tendpoints: upsertEndpoint(state.endpoints, event.endpoint),\n\t\t\t\trows: attachEndpoint(state.rows, event.endpoint),\n\t\t\t});\n\n\t\tcase 'account.updated':\n\t\t\treturn withTouched({\n\t\t\t\taccounts: upsertAccount(state.accounts, event.account),\n\t\t\t});\n\n\t\tcase 'package.updated':\n\t\t\treturn withTouched({\n\t\t\t\tpackages: upsertPackage(state.packages, event.package),\n\t\t\t});\n\n\t\tcase 'endpoint.released':\n\t\t\t// Renderer projection keeps endpoint history as last-known\n\t\t\t// operator affordance. A released service may no longer be\n\t\t\t// reachable, but hiding the URL during shutdown/restart makes\n\t\t\t// the TUI lose the most useful debugging handle.\n\t\t\treturn withTouched({});\n\n\t\tcase 'strategy.registered':\n\t\tcase 'strategy.unregistered':\n\t\tcase 'manifest.flushed':\n\t\tcase 'codegen.emitted':\n\t\tcase 'snapshot.captureStarted':\n\t\tcase 'snapshot.captureProgress':\n\t\tcase 'snapshot.captureSkipped':\n\t\tcase 'snapshot.captureFailed':\n\t\tcase 'snapshot.captured':\n\t\tcase 'snapshot.restored':\n\t\t\t// Engine-internal events that don't carry a projection slice\n\t\t\t// — surfaced on the live event stream for renderers that care,\n\t\t\t// but contribute no field to the subscribable state. (Adding\n\t\t\t// a projection field for any of these requires an architecture\n\t\t\t// revision per G2.)\n\t\t\treturn withTouched({});\n\n\t\tcase 'shutdown.escalated':\n\t\t\treturn withTouched({\n\t\t\t\tcycle: { ...state.cycle, phase: 'shutting-down' },\n\t\t\t});\n\n\t\tcase 'error.reported':\n\t\t\treturn withTouched({\n\t\t\t\terrors: pushBounded(state.errors, event.error, MAX_ERRORS_KEPT),\n\t\t\t\trows: event.error.pluginKey\n\t\t\t\t\t? upsertRow(state.rows, event.error.pluginKey, (row) => ({\n\t\t\t\t\t\t\t...row,\n\t\t\t\t\t\t\tlastError: event.error,\n\t\t\t\t\t\t}))\n\t\t\t\t\t: state.rows,\n\t\t\t});\n\n\t\tcase 'build.statusChanged':\n\t\t\treturn withTouched({\n\t\t\t\tstackBuild: pushBounded(state.stackBuild, event.entry, MAX_BUILD_ENTRIES_KEPT),\n\t\t\t});\n\n\t\tcase 'restart.requested':\n\t\t\treturn withTouched({\n\t\t\t\tcycle: { ...state.cycle, phase: 'restarting' },\n\t\t\t\trows:\n\t\t\t\t\tevent.target === 'stack'\n\t\t\t\t\t\t? state.rows.map((r) => ({ ...r, selectiveRestartHighlight: false }))\n\t\t\t\t\t\t: state.rows.map((r) =>\n\t\t\t\t\t\t\t\tr.key === (event.target as { pluginKey: PluginKey }).pluginKey\n\t\t\t\t\t\t\t\t\t? { ...r, selectiveRestartHighlight: true }\n\t\t\t\t\t\t\t\t\t: r,\n\t\t\t\t\t\t\t),\n\t\t\t});\n\n\t\tcase 'restart.completed':\n\t\t\treturn withTouched({\n\t\t\t\tcycle: { ...state.cycle, phase: 'running' },\n\t\t\t\trows: state.rows.map((r) => ({ ...r, selectiveRestartHighlight: false })),\n\t\t\t});\n\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = event;\n\t\t\tvoid _exhaustive;\n\t\t\treturn state;\n\t\t}\n\t}\n};\n\n// -----------------------------------------------------------------------------\n// Engine-side mutators (not driven by EngineEvent)\n// -----------------------------------------------------------------------------\n\n/**\n * Replace `identity` on the projection. Called once at boot per cycle;\n * does NOT change on hot-restart.\n */\nexport const setIdentity = (\n\tstate: SubscribableState,\n\tidentity: SubscribableState['identity'],\n): SubscribableState => ({ ...state, identity });\n\n/**\n * Bump the cycle counter. Called at the start of each engine cycle.\n * Resets only fields the architecture says are per-cycle:\n * - `cycle.id`, `cycle.startedAt`, `cycle.phase`\n * - per-row `selectiveRestartHighlight`\n * The error log, endpoints, build log, and `lastEvent.seq` are\n * intentionally preserved across cycles so the renderer sees\n * continuous history.\n */\nexport const bumpCycle = (\n\tstate: SubscribableState,\n\tnow: number,\n\tphase: SubscribableState['cycle']['phase'] = 'booting',\n): SubscribableState => ({\n\t...state,\n\tcycle: { id: state.cycle.id + 1, startedAt: now, phase },\n\trows: state.rows.map((r) => ({ ...r, selectiveRestartHighlight: false })),\n});\n\n/**\n * Register (or replace) a row in the projection. The supervisor wires\n * the call in.\n */\nexport const declareRow = (state: SubscribableState, row: Row): SubscribableState => {\n\tconst idx = state.rows.findIndex((r) => r.key === row.key);\n\tif (idx === -1) return { ...state, rows: [...state.rows, row] };\n\tconst next = state.rows.slice();\n\tnext[idx] = row;\n\treturn { ...state, rows: next };\n};\n\n/**\n * Drop a row. Used during selective-restart when a plugin is being\n * removed (rare; most restarts replay the same row).\n */\nexport const dropRow = (state: SubscribableState, key: PluginKey): SubscribableState => ({\n\t...state,\n\trows: state.rows.filter((r) => r.key !== key),\n});\n\nexport const declareAccount = (\n\tstate: SubscribableState,\n\taccount: AccountProjection,\n): SubscribableState => ({\n\t...state,\n\taccounts: upsertAccount(state.accounts, account),\n});\n\nexport const declarePackage = (\n\tstate: SubscribableState,\n\tpkg: PackageProjection,\n): SubscribableState => ({\n\t...state,\n\tpackages: upsertPackage(state.packages, pkg),\n});\n\n// -----------------------------------------------------------------------------\n// SubscriptionRef-driven updaters\n// -----------------------------------------------------------------------------\n\n/**\n * Apply an `EngineEvent` to the ref, bumping the sequence number\n * atomically. The seq is monotonic per process and survives cycle\n * boundaries.\n *\n * Uses `state.lastEvent.seq + 1` for monotonic per-process counts.\n */\nexport const updateRef = (\n\tref: SubscriptionRef.SubscriptionRef<SubscribableState>,\n\tevent: EngineEvent,\n): Effect.Effect<void> =>\n\tSubscriptionRef.update(ref, (state) => {\n\t\tconst next = applyEvent(state, event);\n\t\treturn {\n\t\t\t...next,\n\t\t\tlastEvent: { seq: state.lastEvent.seq + 1, at: next.lastEvent.at },\n\t\t};\n\t});\n\n// -----------------------------------------------------------------------------\n// Internals\n// -----------------------------------------------------------------------------\n\nconst eventAt = (event: EngineEvent): number | null => {\n\tif ('at' in event) return event.at;\n\t// Events whose payload nests `at` (endpoint, error, build): pull it\n\t// up. Discriminating purely on `tag` keeps this exhaustive.\n\tswitch (event.tag) {\n\t\tcase 'endpoint.registered':\n\t\t\treturn event.endpoint.registeredAt;\n\t\tcase 'error.reported':\n\t\t\treturn event.error.at;\n\t\tcase 'build.statusChanged':\n\t\t\treturn event.entry.startedAt;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\n\nconst upsertRow = (\n\trows: ReadonlyArray<Row>,\n\tkey: PluginKey,\n\tupdate: (row: Row) => Row,\n): ReadonlyArray<Row> => {\n\tconst idx = rows.findIndex((r) => r.key === key);\n\tif (idx === -1) {\n\t\t// Row was never declared. We do NOT auto-create — declaration is\n\t\t// the plugin's job. Drop the event silently; the renderer can't\n\t\t// render a row it doesn't know about.\n\t\treturn rows;\n\t}\n\tconst next = rows.slice();\n\tnext[idx] = update(rows[idx]!);\n\treturn next;\n};\n\nconst appendLogLine = (row: Row, line: string, level: 'info' | 'warn' | 'error'): Row => {\n\tconst nextLines = [...row.logTail.lines, line];\n\tconst truncated = nextLines.length > MAX_ROW_LOG_LINES;\n\tconst trimmed = truncated ? nextLines.slice(-MAX_ROW_LOG_LINES) : nextLines;\n\treturn {\n\t\t...row,\n\t\tlogTail: {\n\t\t\tlines: trimmed,\n\t\t\tlevel: maxLevel(row.logTail.level, level),\n\t\t\ttruncated: row.logTail.truncated || truncated,\n\t\t},\n\t};\n};\n\nconst maxLevel = (\n\ta: 'info' | 'warn' | 'error',\n\tb: 'info' | 'warn' | 'error',\n): 'info' | 'warn' | 'error' => {\n\tconst rank = { info: 0, warn: 1, error: 2 } as const;\n\treturn rank[a] >= rank[b] ? a : b;\n};\n\nconst upsertEndpoint = (\n\tendpoints: ReadonlyArray<Endpoint>,\n\tendpoint: Endpoint,\n): ReadonlyArray<Endpoint> => {\n\tconst idx = endpoints.findIndex((e) => e.endpointKey === endpoint.endpointKey);\n\tif (idx === -1) return [...endpoints, endpoint];\n\tconst next = endpoints.slice();\n\tnext[idx] = endpoint;\n\treturn next;\n};\n\nconst upsertAccount = (\n\taccounts: ReadonlyArray<AccountProjection>,\n\taccount: AccountProjection,\n): ReadonlyArray<AccountProjection> => {\n\tconst idx = accounts.findIndex((entry) => entry.key === account.key);\n\tif (idx === -1) return [...accounts, account];\n\tconst next = accounts.slice();\n\tnext[idx] = {\n\t\t...accounts[idx]!,\n\t\t...account,\n\t\tfunding: {\n\t\t\t...accounts[idx]!.funding,\n\t\t\t...account.funding,\n\t\t},\n\t};\n\treturn next;\n};\n\nconst upsertPackage = (\n\tpackages: ReadonlyArray<PackageProjection>,\n\tpkg: PackageProjection,\n): ReadonlyArray<PackageProjection> => {\n\tconst idx = packages.findIndex((entry) => entry.key === pkg.key);\n\tif (idx === -1) return [...packages, pkg];\n\tconst next = packages.slice();\n\tnext[idx] = {\n\t\t...packages[idx]!,\n\t\t...pkg,\n\t};\n\treturn next;\n};\n\nconst attachEndpoint = (rows: ReadonlyArray<Row>, endpoint: Endpoint): ReadonlyArray<Row> => {\n\t// Endpoint -> Row link is `endpointKey` derived from `pluginKey` + dispatchId.\n\t// The plugin that owns the endpoint must have a row; we look it up by\n\t// the endpoint's pluginKey via a structured field. The current\n\t// `Endpoint` shape (from projection.ts) doesn't carry pluginKey in\n\t// the projection slice — it's derivable from `endpointKey` (prefix match).\n\tconst probableKey = endpoint.endpointKey;\n\treturn rows.map((row) =>\n\t\tprobableKey.startsWith(row.key)\n\t\t\t? row.endpoints.includes(probableKey)\n\t\t\t\t? row\n\t\t\t\t: { ...row, endpoints: [...row.endpoints, probableKey] }\n\t\t\t: row,\n\t);\n};\n\nconst pushBounded = <T>(xs: ReadonlyArray<T>, value: T, max: number): ReadonlyArray<T> => {\n\tconst next = [...xs, value];\n\treturn next.length > max ? next.slice(-max) : next;\n};\n\n// Re-export the bounded-capacity constants for tests / docs.\nexport const __capacities = {\n\tMAX_ERRORS_KEPT,\n\tMAX_BUILD_ENTRIES_KEPT,\n\tMAX_ROW_LOG_LINES,\n} as const;\n\n// Re-export referenced sub-types for downstream consumers (tests,\n// renderer-side wrappers) so they don't reach into substrate/\n// directly.\nexport type {\n\tAccountProjection,\n\tBuildEntry,\n\tEndpoint,\n\tLifecycleStatus,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"update.mjs","names":[],"sources":["../../../../src/substrate/runtime/projection/update.ts"],"sourcesContent":["// Projection updater.\n//\n// Architecture § Renderer § \"Subscribable projection — exact field\n// enumeration\" (G2). The updater is a typed event-handler: each\n// `EngineEvent` produces a structurally-typed projection mutation.\n// Renderers never see the event taxonomy here; they only see the\n// resulting state.\n//\n// The updater is *pure data*: it takes the old state + an event,\n// returns the new state. Atomicity comes from\n// `SubscriptionRef.update` at the call site.\n//\n// Discipline:\n// - No display vocabulary (`title`, `primary`, `extras`) anywhere\n// in the produced state.\n// - All fields the architecture enumerates are reachable; new\n// event tags are picked up via exhaustive `tag` match (the\n// `_exhaustive: never` line will fail to type-check if a new\n// tag is added without a handler here).\n\nimport { Effect, Schema, SubscriptionRef } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport type { EngineEvent } from '../../events.ts';\nimport { eventAtOrNull } from '../../event-time.ts';\nimport type { LifecycleStatus } from '../../lifecycle.ts';\nimport type {\n\tAccountProjection,\n\tBuildEntry,\n\tEndpoint,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n\tSubscribableState,\n} from '../../projection.ts';\nimport { applyLifecycleFact, factFromEvent } from '../lifecycle/lifecycle-fact.ts';\nimport { SpanAttr } from '../observability/spans.ts';\nimport { AccountProjectionSchema, PackageProjectionSchema } from './persisted.ts';\n\n// -----------------------------------------------------------------------------\n// Capacity policy\n// -----------------------------------------------------------------------------\n\n/** Bounded buffer for the top-level errors list. */\nconst MAX_ERRORS_KEPT = 100;\n/** Bounded buffer for the top-level build-entries list. */\nconst MAX_BUILD_ENTRIES_KEPT = 200;\n/** Per-row bounded log-tail length. Architecture: default 100 lines. */\nconst MAX_ROW_LOG_LINES = 100;\n\n// -----------------------------------------------------------------------------\n// Decode-result type — shared between the reducer's optional pre-flight\n// cache and the `tryDecodeProjectionPayload` helper. Hoisted above the\n// reducer so the optional `prevalidated` parameter can reference it.\n// -----------------------------------------------------------------------------\n\ntype DecodeResult<T> =\n\t| { readonly ok: true; readonly value: T }\n\t| { readonly ok: false; readonly cause: unknown };\n\n// -----------------------------------------------------------------------------\n// Pure reducer\n// -----------------------------------------------------------------------------\n\n/**\n * Pure projection reducer. One event in, one new state out. All field\n * writes preserve `readonly` invariants by constructing fresh\n * objects/arrays rather than mutating.\n *\n * The `tag` switch is exhaustive against `EngineEvent['tag']`; the\n * trailing `_exhaustive: never` causes TS to flag any new tag that\n * isn't handled here.\n *\n * @param prevalidated - Optional pre-flight decode result for\n * `projection.updated` payloads. When the Effect-aware `updateRef`\n * seam has already decoded the payload (to drive the warning\n * emission inside the fiber's logger Layer), it threads the result\n * here so the reducer doesn't decode the same payload twice on\n * the hot path. Direct `applyEvent` callers (tests, in-process\n * projection consumers) leave this undefined and the reducer\n * re-decodes — the schema is sync + deterministic so the cached\n * result and a fresh decode agree.\n */\nexport const applyEvent = (\n\tstate: SubscribableState,\n\tevent: EngineEvent,\n\tprevalidated?: DecodeResult<unknown>,\n): SubscribableState => {\n\t// Every event advances `lastEvent.at`. `lastEvent.seq` is bumped at\n\t// the `updateRef` wrapper, not here — this reducer is pure data.\n\tconst withTouched = (next: Partial<SubscribableState>): SubscribableState => ({\n\t\t...state,\n\t\t...next,\n\t\tlastEvent: { seq: state.lastEvent.seq, at: eventAtOrNull(event) ?? state.lastEvent.at },\n\t});\n\n\t// Lifecycle-shaped events flow through the typed `LifecycleFact`\n\t// bridge — the projection consumes the merge-not-replace fact\n\t// instead of writing each lifecycle field independently. Non-\n\t// lifecycle events take their original specialised paths below.\n\tconst fact = factFromEvent(event);\n\tif (fact !== null) {\n\t\treturn withTouched({\n\t\t\trows: upsertRow(state.rows, fact.pluginKey, (row) => applyLifecycleFact(row, fact.delta)),\n\t\t});\n\t}\n\n\tswitch (event.tag) {\n\t\tcase 'lifecycle.statusChanged':\n\t\tcase 'lifecycle.phaseSet':\n\t\t\t// Handled above via `factFromEvent` — kept in the switch for\n\t\t\t// `_exhaustive` discipline.\n\t\t\treturn withTouched({});\n\n\t\tcase 'log.appended':\n\t\t\treturn withTouched({\n\t\t\t\trows: upsertRow(state.rows, event.pluginKey, (row) =>\n\t\t\t\t\tappendLogLine(row, event.line, event.level),\n\t\t\t\t),\n\t\t\t});\n\n\t\tcase 'endpoint.registered':\n\t\t\treturn withTouched({\n\t\t\t\tendpoints: upsertEndpoint(state.endpoints, event.endpoint),\n\t\t\t\trows: attachEndpoint(state.rows, event.endpoint),\n\t\t\t});\n\n\t\tcase 'projection.updated':\n\t\t\t// Substrate stays name-blind on the event vocabulary; the\n\t\t\t// reducer is the projection orchestrator and owns the per-\n\t\t\t// `kind` decode. New plugin-author projection kinds slot in\n\t\t\t// here without a new event variant — extending this switch\n\t\t\t// is the load-bearing knob.\n\t\t\t//\n\t\t\t// Per STYLE_GUIDE §20: a misbehaving plugin emitting a\n\t\t\t// malformed payload must NOT crash the reducer or the\n\t\t\t// surrounding projection stream. Decode per-kind via the\n\t\t\t// canonical Schema; on failure, drop the slice update\n\t\t\t// (`lastEvent.at` still advances so the renderer sees the\n\t\t\t// event was observed). Warning emission is handled by the\n\t\t\t// Effect-aware seam at the `updateRef` call site so it runs\n\t\t\t// inside the fiber's structured-logging context — the\n\t\t\t// reducer itself stays pure-data sync (no logger access),\n\t\t\t// just signaling a decode failure via a non-`ok` decode\n\t\t\t// result.\n\t\t\tif (event.kind === 'account') {\n\t\t\t\tconst decoded =\n\t\t\t\t\tprevalidated ?? tryDecodeProjectionPayload(AccountProjectionSchema, event.payload);\n\t\t\t\t// `event.payload` (not `decoded.value`) is forwarded once the\n\t\t\t\t// schema has confirmed the structural shape — the runtime brand\n\t\t\t\t// (`account/${string}`) is TS-only and Schema can't express\n\t\t\t\t// it. The cast is justified by the preceding decode, not a\n\t\t\t\t// `Schema.decodeUnknownSync(...) as A` bare-cast (§20).\n\t\t\t\treturn decoded.ok\n\t\t\t\t\t? withTouched({\n\t\t\t\t\t\t\taccounts: upsertAccount(state.accounts, event.payload as AccountProjection),\n\t\t\t\t\t\t})\n\t\t\t\t\t: withTouched({});\n\t\t\t}\n\t\t\tif (event.kind === 'package') {\n\t\t\t\tconst decoded =\n\t\t\t\t\tprevalidated ?? tryDecodeProjectionPayload(PackageProjectionSchema, event.payload);\n\t\t\t\treturn decoded.ok\n\t\t\t\t\t? withTouched({\n\t\t\t\t\t\t\tpackages: upsertPackage(state.packages, event.payload as PackageProjection),\n\t\t\t\t\t\t})\n\t\t\t\t\t: withTouched({});\n\t\t\t}\n\t\t\treturn withTouched({});\n\n\t\tcase 'endpoint.released':\n\t\t\t// Renderer projection keeps endpoint history as last-known\n\t\t\t// operator affordance. A released service may no longer be\n\t\t\t// reachable, but hiding the URL during shutdown/restart makes\n\t\t\t// the TUI lose the most useful debugging handle.\n\t\t\treturn withTouched({});\n\n\t\tcase 'strategy.registered':\n\t\tcase 'strategy.unregistered':\n\t\tcase 'manifest.flushed':\n\t\tcase 'codegen.emitted':\n\t\tcase 'snapshot.captureStarted':\n\t\tcase 'snapshot.captureProgress':\n\t\tcase 'snapshot.captureSkipped':\n\t\tcase 'snapshot.captureFailed':\n\t\tcase 'snapshot.captured':\n\t\tcase 'snapshot.restored':\n\t\t\t// Engine-internal events that don't carry a projection slice\n\t\t\t// — surfaced on the live event stream for renderers that care,\n\t\t\t// but contribute no field to the subscribable state. (Adding\n\t\t\t// a projection field for any of these requires an architecture\n\t\t\t// revision per G2.)\n\t\t\treturn withTouched({});\n\n\t\tcase 'shutdown.escalated':\n\t\t\treturn withTouched({\n\t\t\t\tcycle: { ...state.cycle, phase: 'shutting-down' },\n\t\t\t});\n\n\t\tcase 'error.reported':\n\t\t\treturn withTouched({\n\t\t\t\terrors: pushBounded(state.errors, event.error, MAX_ERRORS_KEPT),\n\t\t\t\trows: event.error.pluginKey\n\t\t\t\t\t? upsertRow(state.rows, event.error.pluginKey, (row) => ({\n\t\t\t\t\t\t\t...row,\n\t\t\t\t\t\t\tlastError: event.error,\n\t\t\t\t\t\t}))\n\t\t\t\t\t: state.rows,\n\t\t\t});\n\n\t\tcase 'build.statusChanged':\n\t\t\treturn withTouched({\n\t\t\t\tstackBuild: pushBounded(state.stackBuild, event.entry, MAX_BUILD_ENTRIES_KEPT),\n\t\t\t});\n\n\t\tcase 'restart.requested':\n\t\t\treturn withTouched({\n\t\t\t\tcycle: { ...state.cycle, phase: 'restarting' },\n\t\t\t\trows:\n\t\t\t\t\tevent.target === 'stack'\n\t\t\t\t\t\t? state.rows.map((r) => ({ ...r, selectiveRestartHighlight: false }))\n\t\t\t\t\t\t: state.rows.map((r) =>\n\t\t\t\t\t\t\t\tr.key === (event.target as { pluginKey: PluginKey }).pluginKey\n\t\t\t\t\t\t\t\t\t? { ...r, selectiveRestartHighlight: true }\n\t\t\t\t\t\t\t\t\t: r,\n\t\t\t\t\t\t\t),\n\t\t\t});\n\n\t\tcase 'restart.completed':\n\t\t\treturn withTouched({\n\t\t\t\tcycle: { ...state.cycle, phase: 'running' },\n\t\t\t\trows: state.rows.map((r) => ({ ...r, selectiveRestartHighlight: false })),\n\t\t\t});\n\n\t\tcase 'engine.orchestrator.dispatchFailed':\n\t\t\t// Orchestrator-side dispatch failure surfaced for renderers /\n\t\t\t// log consumers; carries no projection slice (the originating\n\t\t\t// plugin remains in its current lifecycle state — sink failure\n\t\t\t// is orchestrator-fault, not plugin-fault).\n\t\t\treturn withTouched({});\n\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = event;\n\t\t\tvoid _exhaustive;\n\t\t\treturn state;\n\t\t}\n\t}\n};\n\n// -----------------------------------------------------------------------------\n// Engine-side mutators (not driven by EngineEvent)\n// -----------------------------------------------------------------------------\n\n/**\n * Replace `identity` on the projection. Called once at boot per cycle;\n * does NOT change on hot-restart.\n */\nexport const setIdentity = (\n\tstate: SubscribableState,\n\tidentity: SubscribableState['identity'],\n): SubscribableState => ({ ...state, identity });\n\n/**\n * Bump the cycle counter. Called at the start of each engine cycle.\n * Resets only fields the architecture says are per-cycle:\n * - `cycle.id`, `cycle.startedAt`, `cycle.phase`\n * - per-row `selectiveRestartHighlight`\n * The error log, endpoints, build log, and `lastEvent.seq` are\n * intentionally preserved across cycles so the renderer sees\n * continuous history.\n */\nexport const bumpCycle = (\n\tstate: SubscribableState,\n\tnow: number,\n\tphase: SubscribableState['cycle']['phase'] = 'booting',\n): SubscribableState => ({\n\t...state,\n\tcycle: { id: state.cycle.id + 1, startedAt: now, phase },\n\trows: state.rows.map((r) => ({ ...r, selectiveRestartHighlight: false })),\n});\n\n/**\n * Register (or replace) a row in the projection. The supervisor wires\n * the call in.\n */\nexport const declareRow = (state: SubscribableState, row: Row): SubscribableState => {\n\tconst idx = state.rows.findIndex((r) => r.key === row.key);\n\tif (idx === -1) return { ...state, rows: [...state.rows, row] };\n\tconst next = state.rows.slice();\n\tnext[idx] = row;\n\treturn { ...state, rows: next };\n};\n\n/**\n * Drop a row. Used during selective-restart when a plugin is being\n * removed (rare; most restarts replay the same row).\n */\nexport const dropRow = (state: SubscribableState, key: PluginKey): SubscribableState => ({\n\t...state,\n\trows: state.rows.filter((r) => r.key !== key),\n});\n\nexport const declareAccount = (\n\tstate: SubscribableState,\n\taccount: AccountProjection,\n): SubscribableState => ({\n\t...state,\n\taccounts: upsertAccount(state.accounts, account),\n});\n\nexport const declarePackage = (\n\tstate: SubscribableState,\n\tpkg: PackageProjection,\n): SubscribableState => ({\n\t...state,\n\tpackages: upsertPackage(state.packages, pkg),\n});\n\n// -----------------------------------------------------------------------------\n// SubscriptionRef-driven updaters\n// -----------------------------------------------------------------------------\n\n/**\n * Apply an `EngineEvent` to the ref, bumping the sequence number\n * atomically. The seq is monotonic per process and survives cycle\n * boundaries.\n *\n * Uses `state.lastEvent.seq + 1` for monotonic per-process counts.\n *\n * Side-channel: when the event is a `projection.updated` with a\n * malformed payload, the reducer drops the slice and we emit a\n * structured warning here, inside the surrounding fiber, so it lands\n * on the fiber's structured-logging path (`Effect.logWarning`). This\n * is the only place in the reducer where a warning is emitted; the\n * pure `applyEvent` reducer never touches the logger.\n */\nexport const updateRef = (\n\tref: SubscriptionRef.SubscriptionRef<SubscribableState>,\n\tevent: EngineEvent,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\t// Pre-flight: detect malformed projection-updated payloads so the\n\t\t// warning runs inside the fiber's logger context. We thread the\n\t\t// decode result into the reducer below so the hot path decodes\n\t\t// the payload exactly once per event — the previous shape ran\n\t\t// the same `Schema.decodeUnknownSync` pass twice (once here,\n\t\t// once inside `applyEvent`) on every projection.updated event.\n\t\tlet prevalidated: DecodeResult<unknown> | undefined;\n\t\tif (event.tag === 'projection.updated') {\n\t\t\tif (event.kind === 'account' || event.kind === 'package') {\n\t\t\t\tconst schema = event.kind === 'account' ? AccountProjectionSchema : PackageProjectionSchema;\n\t\t\t\tprevalidated = tryDecodeProjectionPayload(schema, event.payload);\n\t\t\t\tif (!prevalidated.ok) {\n\t\t\t\t\tyield* Effect.logWarning(\n\t\t\t\t\t\t`projection.updated: dropping malformed ${event.kind} payload for key=${event.key}`,\n\t\t\t\t\t).pipe(\n\t\t\t\t\t\tEffect.annotateLogs({\n\t\t\t\t\t\t\t[SpanAttr.errorMessage]: formatDecodeIssue(prevalidated.cause),\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tyield* SubscriptionRef.update(ref, (state) => {\n\t\t\tconst next = applyEvent(state, event, prevalidated);\n\t\t\treturn {\n\t\t\t\t...next,\n\t\t\t\tlastEvent: { seq: state.lastEvent.seq + 1, at: next.lastEvent.at },\n\t\t\t};\n\t\t});\n\t});\n\n// -----------------------------------------------------------------------------\n// Internals\n// -----------------------------------------------------------------------------\n\n/**\n * Sync per-kind validator for `projection.updated` payloads. Returns\n * an `ok` decode result on success or a non-`ok` one on decode\n * failure. Pure-data sync: no logger access, no `Effect.runSync` —\n * the reducer is documented as pure, and earlier versions of this\n * seam called `Effect.runSync(Effect.logWarning(...))` outside any\n * fiber context, which logged off-fiber (bypassing the supervisor's\n * structured-logging context). The Effect-aware `updateRef` wrapper\n * now emits the warning inside the fiber so the warning is captured\n * consistently with the rest of the supervisor's logs.\n *\n * On success callers still pass `event.payload` to the upsert (not the\n * decoded copy) — the runtime brand types (`account/${string}`,\n * `package/${string}`) are TS-only and the decoded copy would strip\n * them. The schema acts as a structural guard only.\n */\nconst tryDecodeProjectionPayload = <S extends Schema.Decoder<unknown>>(\n\tschema: S,\n\tpayload: unknown,\n): DecodeResult<S['Type']> => {\n\ttry {\n\t\treturn { ok: true, value: Schema.decodeUnknownSync(schema)(payload) };\n\t} catch (cause) {\n\t\treturn { ok: false, cause };\n\t}\n};\n\n/**\n * Render a `Schema.decodeUnknownSync` throw into a human-readable\n * string for the warn annotation. `SchemaError` in Effect v4 stores\n * the parse issue and exposes `.message` (= `issue.toString()`); using\n * that surfaces the actual decode-issue path/expectation. Fallback to\n * `String(cause)` for non-SchemaError throws (defensive — the schema's\n * sync decoder should always throw `SchemaError`).\n */\nconst formatDecodeIssue = (cause: unknown): string => {\n\tif (Schema.isSchemaError(cause)) {\n\t\treturn cause.message;\n\t}\n\tif (cause instanceof Error) {\n\t\treturn cause.message;\n\t}\n\treturn String(cause);\n};\n\nconst upsertRow = (\n\trows: ReadonlyArray<Row>,\n\tkey: PluginKey,\n\tupdate: (row: Row) => Row,\n): ReadonlyArray<Row> => {\n\tconst idx = rows.findIndex((r) => r.key === key);\n\tif (idx === -1) {\n\t\t// Row was never declared. We do NOT auto-create — declaration is\n\t\t// the plugin's job. Drop the event silently; the renderer can't\n\t\t// render a row it doesn't know about.\n\t\treturn rows;\n\t}\n\tconst next = rows.slice();\n\tnext[idx] = update(rows[idx]!);\n\treturn next;\n};\n\nconst appendLogLine = (row: Row, line: string, level: 'info' | 'warn' | 'error'): Row => {\n\tconst nextLines = [...row.logTail.lines, line];\n\tconst truncated = nextLines.length > MAX_ROW_LOG_LINES;\n\tconst trimmed = truncated ? nextLines.slice(-MAX_ROW_LOG_LINES) : nextLines;\n\treturn {\n\t\t...row,\n\t\tlogTail: {\n\t\t\tlines: trimmed,\n\t\t\tlevel: maxLevel(row.logTail.level, level),\n\t\t\ttruncated: row.logTail.truncated || truncated,\n\t\t},\n\t};\n};\n\nconst maxLevel = (\n\ta: 'info' | 'warn' | 'error',\n\tb: 'info' | 'warn' | 'error',\n): 'info' | 'warn' | 'error' => {\n\tconst rank = { info: 0, warn: 1, error: 2 } as const;\n\treturn rank[a] >= rank[b] ? a : b;\n};\n\nconst upsertEndpoint = (\n\tendpoints: ReadonlyArray<Endpoint>,\n\tendpoint: Endpoint,\n): ReadonlyArray<Endpoint> => {\n\tconst idx = endpoints.findIndex((e) => e.endpointKey === endpoint.endpointKey);\n\tif (idx === -1) return [...endpoints, endpoint];\n\tconst next = endpoints.slice();\n\tnext[idx] = endpoint;\n\treturn next;\n};\n\nconst upsertAccount = (\n\taccounts: ReadonlyArray<AccountProjection>,\n\taccount: AccountProjection,\n): ReadonlyArray<AccountProjection> => {\n\tconst idx = accounts.findIndex((entry) => entry.key === account.key);\n\tif (idx === -1) return [...accounts, account];\n\tconst next = accounts.slice();\n\tnext[idx] = {\n\t\t...accounts[idx]!,\n\t\t...account,\n\t\tfunding: {\n\t\t\t...accounts[idx]!.funding,\n\t\t\t...account.funding,\n\t\t},\n\t};\n\treturn next;\n};\n\nconst upsertPackage = (\n\tpackages: ReadonlyArray<PackageProjection>,\n\tpkg: PackageProjection,\n): ReadonlyArray<PackageProjection> => {\n\tconst idx = packages.findIndex((entry) => entry.key === pkg.key);\n\tif (idx === -1) return [...packages, pkg];\n\tconst next = packages.slice();\n\tnext[idx] = {\n\t\t...packages[idx]!,\n\t\t...pkg,\n\t};\n\treturn next;\n};\n\nconst attachEndpoint = (rows: ReadonlyArray<Row>, endpoint: Endpoint): ReadonlyArray<Row> => {\n\treturn rows.map((row) =>\n\t\tendpoint.pluginKey === row.key\n\t\t\t? row.endpoints.includes(endpoint.endpointKey)\n\t\t\t\t? row\n\t\t\t\t: { ...row, endpoints: [...row.endpoints, endpoint.endpointKey] }\n\t\t\t: row,\n\t);\n};\n\nconst pushBounded = <T>(xs: ReadonlyArray<T>, value: T, max: number): ReadonlyArray<T> => {\n\tconst next = [...xs, value];\n\treturn next.length > max ? next.slice(-max) : next;\n};\n\n// Re-export the bounded-capacity constants for tests / docs.\nexport const __capacities = {\n\tMAX_ERRORS_KEPT,\n\tMAX_BUILD_ENTRIES_KEPT,\n\tMAX_ROW_LOG_LINES,\n} as const;\n\n// Re-export referenced sub-types for downstream consumers (tests,\n// renderer-side wrappers) so they don't reach into substrate/\n// directly.\nexport type {\n\tAccountProjection,\n\tBuildEntry,\n\tEndpoint,\n\tLifecycleStatus,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n};\n"],"mappings":"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"}