@zlink-systems/framework 0.25.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (557) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Channels/IZLinkFanoutClient.d.ts +0 -6
  3. package/dist/contracts/Common/CoreTypes.d.ts +6 -0
  4. package/dist/contracts/Common/CoreTypes.js +7 -0
  5. package/dist/contracts/Common/index.d.ts +1 -1
  6. package/dist/contracts/Common/index.js +0 -1
  7. package/dist/contracts/Configuration/InternalDefaults.d.ts +8 -0
  8. package/dist/contracts/Configuration/InternalDefaults.js +9 -1
  9. package/dist/contracts/Configuration/Registration.d.ts +13 -2
  10. package/dist/contracts/Configuration/Registration.js +58 -36
  11. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +13 -1
  12. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +38 -1
  13. package/dist/contracts/Configuration/RegistrationBuilders.d.ts +2 -3
  14. package/dist/contracts/Configuration/RegistrationBuilders.js +27 -32
  15. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
  16. package/dist/contracts/Configuration/RegistrationValidators.js +15 -12
  17. package/dist/contracts/Configuration/TimerRegistrationValidator.js +3 -2
  18. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +1 -1
  19. package/dist/contracts/Handlers/JsonContract.js +10 -4
  20. package/dist/contracts/Locations/Authority.d.ts +1 -1
  21. package/dist/contracts/Locations/Authority.js +3 -2
  22. package/dist/contracts/Locations/Options.js +1 -1
  23. package/dist/contracts/Locations/Stores.d.ts +12 -0
  24. package/dist/contracts/Locations/Stores.js +9 -0
  25. package/dist/contracts/RouteMesh/RuntimeTopology.d.ts +8 -0
  26. package/dist/contracts/Spots/Contracts.d.ts +1 -1
  27. package/dist/internal.d.ts +5 -0
  28. package/dist/internal.js +16 -1
  29. package/dist/nest-integration.d.ts +4 -2
  30. package/dist/nest-integration.js +14 -4
  31. package/dist/runtime/abort.d.ts +1 -0
  32. package/dist/runtime/abort.js +8 -5
  33. package/dist/runtime/activation-admission.d.ts +28 -0
  34. package/dist/runtime/activation-admission.js +57 -0
  35. package/dist/runtime/actors/actor-authority-payload-codec.d.ts +1 -2
  36. package/dist/runtime/actors/actor-authority-payload-codec.js +34 -18
  37. package/dist/runtime/actors/actor-client.d.ts +2 -2
  38. package/dist/runtime/actors/actor-client.js +42 -143
  39. package/dist/runtime/actors/actor-context.d.ts +3 -5
  40. package/dist/runtime/actors/actor-context.js +19 -17
  41. package/dist/runtime/actors/actor-handoff.d.ts +13 -7
  42. package/dist/runtime/actors/actor-handoff.js +36 -25
  43. package/dist/runtime/actors/actor-lifecycle-snapshot.js +2 -1
  44. package/dist/runtime/actors/actor-local-native-join.d.ts +11 -6
  45. package/dist/runtime/actors/actor-local-native-join.js +85 -123
  46. package/dist/runtime/actors/actor-native-lookup.js +2 -8
  47. package/dist/runtime/actors/actor-packet-relay-wire.d.ts +3 -3
  48. package/dist/runtime/actors/actor-packet-relay-wire.js +5 -3
  49. package/dist/runtime/actors/actor-remote-joiner.d.ts +3 -3
  50. package/dist/runtime/actors/actor-remote-joiner.js +11 -17
  51. package/dist/runtime/actors/actor-remote-wire.js +5 -3
  52. package/dist/runtime/actors/actor-request-deadline.d.ts +3 -0
  53. package/dist/runtime/actors/actor-request-deadline.js +31 -0
  54. package/dist/runtime/actors/actor-retry-delay.js +2 -1
  55. package/dist/runtime/actors/actor-runtime-contracts.d.ts +4 -2
  56. package/dist/runtime/actors/actor-runtime-state.d.ts +9 -21
  57. package/dist/runtime/actors/actor-runtime-state.js +70 -187
  58. package/dist/runtime/actors/actor-source-transfer.d.ts +5 -5
  59. package/dist/runtime/actors/bound-session-wire.js +2 -7
  60. package/dist/runtime/actors/deferred-join-completion.d.ts +19 -0
  61. package/dist/runtime/actors/deferred-join-completion.js +21 -0
  62. package/dist/runtime/actors/index.d.ts +10 -8
  63. package/dist/runtime/actors/index.js +101 -73
  64. package/dist/runtime/actors/spot-actor-dispatch.d.ts +3 -3
  65. package/dist/runtime/actors/spot-actor-dispatch.js +25 -10
  66. package/dist/runtime/actors/transferred-actor-rollback.d.ts +3 -5
  67. package/dist/runtime/actors/transferred-actor-rollback.js +9 -42
  68. package/dist/runtime/admission.d.ts +7 -1
  69. package/dist/runtime/admission.js +11 -1
  70. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +1 -1
  71. package/dist/runtime/application-jobs/application-job-queue-scope.js +1 -1
  72. package/dist/runtime/backend/contracts/index.d.ts +8 -33
  73. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +3 -26
  74. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +1 -2
  75. package/dist/runtime/backend/mesh-dispatch-pump.js +95 -107
  76. package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +1 -2
  77. package/dist/runtime/backend/node/node-backend-adapter-factory.js +4 -18
  78. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +7 -4
  79. package/dist/runtime/backend/node/node-backend-adapter-support.js +28 -34
  80. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +2 -2
  81. package/dist/runtime/backend/node/node-event-loop-poller.js +11 -6
  82. package/dist/runtime/backend/node/node-monitor-backend-adapter.js +1 -0
  83. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +1 -1
  84. package/dist/runtime/backend/node/node-raw-binding-port.js +51 -19
  85. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +21 -19
  86. package/dist/runtime/backend/node/node-raw-mesh-backend.js +171 -111
  87. package/dist/runtime/backend/node/node-socket-backend-adapter.js +4 -3
  88. package/dist/runtime/backend/raw-binding-port.d.ts +13 -1
  89. package/dist/runtime/backend/runtime-values.d.ts +4 -1
  90. package/dist/runtime/backend/runtime-values.js +2 -0
  91. package/dist/runtime/channels/channel-clients.d.ts +20 -9
  92. package/dist/runtime/channels/channel-clients.js +68 -60
  93. package/dist/runtime/channels/channel-envelope-inspection.js +2 -1
  94. package/dist/runtime/channels/channel-envelope.js +47 -29
  95. package/dist/runtime/channels/channel-outbound-operations.d.ts +3 -0
  96. package/dist/runtime/channels/channel-outbound-operations.js +9 -18
  97. package/dist/runtime/channels/channel-receive-loops.d.ts +8 -3
  98. package/dist/runtime/channels/channel-receive-loops.js +27 -6
  99. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +12 -1
  100. package/dist/runtime/channels/channel-runtime-lifecycle.js +48 -28
  101. package/dist/runtime/channels/channel-runtime-manager.d.ts +2 -5
  102. package/dist/runtime/channels/channel-runtime-manager.js +4 -12
  103. package/dist/runtime/channels/channel-socket-options.js +3 -2
  104. package/dist/runtime/channels/channel-socket-registry.d.ts +30 -32
  105. package/dist/runtime/channels/channel-socket-registry.js +296 -235
  106. package/dist/runtime/channels/channel-transports.d.ts +11 -20
  107. package/dist/runtime/channels/channel-transports.js +68 -47
  108. package/dist/runtime/channels/client-server-location-runtime.d.ts +1 -1
  109. package/dist/runtime/channels/client-server-location-runtime.js +10 -11
  110. package/dist/runtime/channels/client-server-service-wire.d.ts +7 -2
  111. package/dist/runtime/channels/client-server-service-wire.js +32 -11
  112. package/dist/runtime/channels/dispatch-error-reporter.d.ts +1 -2
  113. package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
  114. package/dist/runtime/channels/fanout-location-runtime.d.ts +16 -3
  115. package/dist/runtime/channels/fanout-location-runtime.js +133 -81
  116. package/dist/runtime/channels/spot-direct-envelope.d.ts +1 -0
  117. package/dist/runtime/channels/spot-direct-envelope.js +4 -3
  118. package/dist/runtime/channels/spot-node-route-transport.js +3 -2
  119. package/dist/runtime/diagnostics/diagnostic-text.d.ts +2 -0
  120. package/dist/runtime/diagnostics/diagnostic-text.js +7 -0
  121. package/dist/runtime/diagnostics/dispatch-error-details.d.ts +3 -0
  122. package/dist/runtime/diagnostics/dispatch-error-details.js +30 -2
  123. package/dist/runtime/diagnostics/flow-context.d.ts +6 -0
  124. package/dist/runtime/diagnostics/flow-context.js +16 -2
  125. package/dist/runtime/diagnostics/index.d.ts +4 -2
  126. package/dist/runtime/diagnostics/index.js +14 -4
  127. package/dist/runtime/diagnostics/message-flow.d.ts +1 -1
  128. package/dist/runtime/diagnostics/message-flow.js +10 -19
  129. package/dist/runtime/diagnostics/runtime-metrics.d.ts +94 -31
  130. package/dist/runtime/diagnostics/runtime-metrics.js +168 -105
  131. package/dist/runtime/diagnostics/runtime-observation-queue.js +3 -2
  132. package/dist/runtime/diagnostics/topology-runtime-projections.d.ts +2 -4
  133. package/dist/runtime/diagnostics/topology-runtime-projections.js +135 -154
  134. package/dist/runtime/disposal.d.ts +5 -0
  135. package/dist/runtime/disposal.js +22 -0
  136. package/dist/runtime/execution/index.d.ts +22 -9
  137. package/dist/runtime/execution/index.js +107 -37
  138. package/dist/runtime/execution/serial-execution-queue.d.ts +12 -7
  139. package/dist/runtime/execution/serial-execution-queue.js +99 -26
  140. package/dist/runtime/execution/state-lane.d.ts +8 -1
  141. package/dist/runtime/execution/state-lane.js +118 -3
  142. package/dist/runtime/foundation/actor-join-recovery-codec.d.ts +3 -0
  143. package/dist/runtime/foundation/actor-join-recovery-codec.js +15 -11
  144. package/dist/runtime/foundation/event-loop-resources.d.ts +2 -24
  145. package/dist/runtime/foundation/event-loop-resources.js +6 -119
  146. package/dist/runtime/foundation/listener-records.d.ts +11 -0
  147. package/dist/runtime/foundation/listener-records.js +20 -0
  148. package/dist/runtime/foundation/operation-identity.d.ts +2 -0
  149. package/dist/runtime/foundation/operation-identity.js +9 -5
  150. package/dist/runtime/foundation/operation-registry.d.ts +5 -7
  151. package/dist/runtime/foundation/operation-registry.js +34 -44
  152. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +18 -26
  153. package/dist/runtime/foundation/raw-service-mesh-runtime.js +122 -469
  154. package/dist/runtime/foundation/runtime-state-projections.d.ts +3 -1
  155. package/dist/runtime/foundation/runtime-state-projections.js +8 -0
  156. package/dist/runtime/foundation/service-authority-payload-codec.d.ts +1 -0
  157. package/dist/runtime/foundation/service-authority-payload-codec.js +30 -12
  158. package/dist/runtime/foundation/service-discovery-registry.d.ts +4 -0
  159. package/dist/runtime/foundation/service-discovery-registry.js +22 -3
  160. package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +8 -4
  161. package/dist/runtime/foundation/service-liveness-registry.js +2 -1
  162. package/dist/runtime/foundation/service-maintenance-runtime.d.ts +0 -1
  163. package/dist/runtime/foundation/service-maintenance-runtime.js +23 -8
  164. package/dist/runtime/foundation/service-metadata-codec.js +3 -3
  165. package/dist/runtime/foundation/service-relocation-aggregate-committer.d.ts +2 -5
  166. package/dist/runtime/foundation/service-relocation-aggregate-committer.js +1 -48
  167. package/dist/runtime/foundation/service-relocation-coordinator.d.ts +9 -0
  168. package/dist/runtime/foundation/service-relocation-coordinator.js +14 -1
  169. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +8 -0
  170. package/dist/runtime/foundation/service-relocation-object-owner.js +19 -6
  171. package/dist/runtime/foundation/service-relocation-runtime.js +43 -32
  172. package/dist/runtime/foundation/service-runtime-contracts.d.ts +40 -8
  173. package/dist/runtime/foundation/service-runtime-contracts.js +25 -1
  174. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +0 -19
  175. package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
  176. package/dist/runtime/foundation/service-stateful-registry.js +10 -2
  177. package/dist/runtime/foundation/service-stateful-runtime.d.ts +28 -24
  178. package/dist/runtime/foundation/service-stateful-runtime.js +297 -244
  179. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +12 -7
  180. package/dist/runtime/foundation/service-stateful-wire-codec.js +240 -143
  181. package/dist/runtime/foundation/service-topology-registry.d.ts +1 -3
  182. package/dist/runtime/foundation/service-topology-registry.js +22 -61
  183. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +5 -0
  184. package/dist/runtime/foundation/service-wire-binary-primitives.js +6 -0
  185. package/dist/runtime/foundation/service-wire-codec.js +10 -8
  186. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  187. package/dist/runtime/foundation/service-wire-constants.generated.js +2 -1
  188. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
  189. package/dist/runtime/foundation/service-wire-m6a-codec.js +23 -13
  190. package/dist/runtime/framework-errors-internal.d.ts +2 -1
  191. package/dist/runtime/framework-errors-internal.js +343 -122
  192. package/dist/runtime/handlers/handler-instance-scope.d.ts +3 -1
  193. package/dist/runtime/handlers/handler-instance-scope.js +61 -74
  194. package/dist/runtime/host/actor-packet-relay.d.ts +9 -6
  195. package/dist/runtime/host/actor-packet-relay.js +48 -91
  196. package/dist/runtime/host/actor-placement-coordinator.js +7 -5
  197. package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -0
  198. package/dist/runtime/host/actor-runtime-options-factory.js +17 -4
  199. package/dist/runtime/host/actor-transfer-runtime.d.ts +28 -28
  200. package/dist/runtime/host/actor-transfer-runtime.js +210 -256
  201. package/dist/runtime/host/application-job-queue.js +16 -33
  202. package/dist/runtime/host/bound-session-relay.js +1 -1
  203. package/dist/runtime/host/channel-runtime-options-factory.js +1 -1
  204. package/dist/runtime/host/index.d.ts +19 -14
  205. package/dist/runtime/host/index.js +234 -175
  206. package/dist/runtime/host/instance-activation-authority.d.ts +2 -3
  207. package/dist/runtime/host/instance-activation-authority.js +17 -45
  208. package/dist/runtime/host/location-runtime-owner.d.ts +1 -1
  209. package/dist/runtime/host/location-runtime-owner.js +2 -2
  210. package/dist/runtime/host/remote-actor-join-receiver.d.ts +2 -2
  211. package/dist/runtime/host/remote-actor-join-receiver.js +1 -14
  212. package/dist/runtime/host/remote-actor-packet-target-store.d.ts +3 -2
  213. package/dist/runtime/host/remote-actor-packet-target-store.js +8 -47
  214. package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -3
  215. package/dist/runtime/host/remote-bound-session-relay.js +11 -23
  216. package/dist/runtime/host/route-mesh-runtime.d.ts +14 -10
  217. package/dist/runtime/host/route-mesh-runtime.js +178 -257
  218. package/dist/runtime/host/runtime-shutdown.d.ts +2 -0
  219. package/dist/runtime/host/runtime-shutdown.js +18 -21
  220. package/dist/runtime/host/service-relocation-control.js +6 -1
  221. package/dist/runtime/host/service-relocation-host-runtime.d.ts +71 -38
  222. package/dist/runtime/host/service-relocation-host-runtime.js +816 -651
  223. package/dist/runtime/host/spot-address-transport.d.ts +2 -3
  224. package/dist/runtime/host/spot-address-transport.js +34 -136
  225. package/dist/runtime/host/spot-node-runtime-options-factory.d.ts +1 -1
  226. package/dist/runtime/host/spot-node-runtime-options-factory.js +3 -2
  227. package/dist/runtime/host/spot-runtime-options-factory.d.ts +4 -7
  228. package/dist/runtime/host/spot-runtime-options-factory.js +53 -21
  229. package/dist/runtime/host/stateful-authority-route-runtime.js +6 -2
  230. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +14 -6
  231. package/dist/runtime/host/user-spot-creation-coordinator.js +96 -95
  232. package/dist/runtime/locations/aggregate-inventory-store.js +13 -10
  233. package/dist/runtime/locations/authority-key-codec.js +4 -3
  234. package/dist/runtime/locations/auto-connect-reconciler.d.ts +4 -0
  235. package/dist/runtime/locations/auto-connect-reconciler.js +37 -25
  236. package/dist/runtime/locations/creation-operation-id.js +6 -4
  237. package/dist/runtime/locations/domain-store-contract.d.ts +3 -3
  238. package/dist/runtime/locations/in-memory-authority-store.js +31 -15
  239. package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
  240. package/dist/runtime/locations/in-memory-location-store.js +17 -14
  241. package/dist/runtime/locations/in-memory-provider-location-store.d.ts +1 -0
  242. package/dist/runtime/locations/in-memory-provider-location-store.js +79 -27
  243. package/dist/runtime/locations/key-codec.js +3 -2
  244. package/dist/runtime/locations/lease-tracker.d.ts +3 -5
  245. package/dist/runtime/locations/lease-tracker.js +7 -11
  246. package/dist/runtime/locations/lifecycle.d.ts +5 -10
  247. package/dist/runtime/locations/lifecycle.js +4 -33
  248. package/dist/runtime/locations/location-store-failure.d.ts +2 -0
  249. package/dist/runtime/locations/location-store-failure.js +7 -0
  250. package/dist/runtime/locations/location-store-pages.d.ts +3 -0
  251. package/dist/runtime/locations/location-store-pages.js +13 -0
  252. package/dist/runtime/locations/location-store-repository.d.ts +5 -7
  253. package/dist/runtime/locations/location-store-repository.js +303 -332
  254. package/dist/runtime/locations/relocation-blob.js +18 -5
  255. package/dist/runtime/locations/resolvers.d.ts +5 -5
  256. package/dist/runtime/locations/resolvers.js +44 -30
  257. package/dist/runtime/locations/runtime.d.ts +5 -4
  258. package/dist/runtime/locations/runtime.js +123 -92
  259. package/dist/runtime/locations/spot-location-claims.d.ts +8 -2
  260. package/dist/runtime/locations/spot-location-claims.js +40 -23
  261. package/dist/runtime/messaging/payload-codec.js +26 -20
  262. package/dist/runtime/messaging/submission-result.d.ts +3 -0
  263. package/dist/runtime/messaging/submission-result.js +48 -0
  264. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +2 -0
  265. package/dist/runtime/protocol/service_wire_codec.generated.js +17 -8
  266. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +1 -0
  267. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +3 -2
  268. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +3 -3
  269. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +4 -4
  270. package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +6 -3
  271. package/dist/runtime/spots/index.d.ts +29 -29
  272. package/dist/runtime/spots/index.js +441 -313
  273. package/dist/runtime/spots/spot-activation-registry.d.ts +4 -4
  274. package/dist/runtime/spots/spot-activation-registry.js +27 -60
  275. package/dist/runtime/spots/spot-activation-state.d.ts +2 -11
  276. package/dist/runtime/spots/spot-activation-state.js +4 -17
  277. package/dist/runtime/spots/spot-activation.d.ts +10 -9
  278. package/dist/runtime/spots/spot-activation.js +103 -81
  279. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -2
  280. package/dist/runtime/spots/spot-actor-admission-coordinator.js +3 -40
  281. package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +10 -18
  282. package/dist/runtime/spots/spot-actor-join-dispatch.js +5 -55
  283. package/dist/runtime/spots/spot-actor-lifecycle-drain.js +2 -2
  284. package/dist/runtime/spots/spot-actor-membership.d.ts +7 -5
  285. package/dist/runtime/spots/spot-actor-membership.js +44 -53
  286. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +0 -1
  287. package/dist/runtime/spots/spot-actor-packet-dispatch.js +0 -9
  288. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.d.ts +2 -2
  289. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -7
  290. package/dist/runtime/spots/spot-context.d.ts +2 -2
  291. package/dist/runtime/spots/spot-entry-activation.d.ts +3 -4
  292. package/dist/runtime/spots/spot-entry-activation.js +9 -21
  293. package/dist/runtime/spots/spot-lifecycle-metrics.js +3 -2
  294. package/dist/runtime/spots/spot-manager-public.d.ts +5 -6
  295. package/dist/runtime/spots/spot-manager-public.js +6 -5
  296. package/dist/runtime/spots/spot-node-autoconnect.js +22 -31
  297. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +22 -21
  298. package/dist/runtime/spots/spot-node-runtime-manager.js +73 -82
  299. package/dist/runtime/spots/spot-outbound.d.ts +4 -3
  300. package/dist/runtime/spots/spot-outbound.js +10 -37
  301. package/dist/runtime/spots/spot-remote-codec.js +5 -3
  302. package/dist/runtime/spots/spot-route-packet-dispatch.d.ts +2 -2
  303. package/dist/runtime/spots/spot-route-packet-dispatch.js +8 -8
  304. package/dist/runtime/spots/spot-route-replies.d.ts +2 -2
  305. package/dist/runtime/spots/spot-route-replies.js +3 -1
  306. package/dist/runtime/spots/spot-routed-actor-admission.d.ts +3 -2
  307. package/dist/runtime/spots/spot-routed-actor-admission.js +3 -2
  308. package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +2 -7
  309. package/dist/runtime/spots/spot-routed-frame-dispatch.js +1 -70
  310. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +4 -0
  311. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +65 -15
  312. package/dist/runtime/spots/spot-runtime-ports.d.ts +4 -20
  313. package/dist/runtime/spots/spot-serial-executor.d.ts +5 -0
  314. package/dist/runtime/spots/spot-serial-executor.js +9 -2
  315. package/dist/runtime/spots/spot-serial-turn-executor.d.ts +29 -6
  316. package/dist/runtime/spots/spot-serial-turn-executor.js +89 -13
  317. package/dist/runtime/spots/spot-timer.d.ts +3 -2
  318. package/dist/runtime/streams/actor-session-binding-registry.d.ts +17 -32
  319. package/dist/runtime/streams/actor-session-binding-registry.js +145 -367
  320. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +2 -6
  321. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +6 -2
  322. package/dist/runtime/streams/bound-actor-relay-sender.js +57 -33
  323. package/dist/runtime/streams/bound-session-service.d.ts +7 -0
  324. package/dist/runtime/streams/bound-session-service.js +12 -19
  325. package/dist/runtime/streams/index.d.ts +15 -14
  326. package/dist/runtime/streams/index.js +38 -39
  327. package/dist/runtime/streams/managed-stream.d.ts +3 -0
  328. package/dist/runtime/streams/managed-stream.js +17 -8
  329. package/dist/runtime/streams/native-fallback-bound-session.js +1 -3
  330. package/dist/runtime/streams/protocol.d.ts +6 -33
  331. package/dist/runtime/streams/protocol.js +38 -110
  332. package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -3
  333. package/dist/runtime/streams/session-actor-coordinator.js +12 -4
  334. package/dist/runtime/streams/session-calls.d.ts +1 -1
  335. package/dist/runtime/streams/session-calls.js +5 -4
  336. package/dist/runtime/streams/session-context.d.ts +6 -6
  337. package/dist/runtime/streams/session-context.js +22 -4
  338. package/dist/runtime/streams/session-requests.js +2 -1
  339. package/dist/runtime/streams/session-serial-executor.js +2 -2
  340. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +16 -1
  341. package/dist/runtime/streams/stream-frame-factory.js +2 -2
  342. package/dist/runtime/streams/stream-session-runtime.d.ts +10 -11
  343. package/dist/runtime/streams/stream-session-runtime.js +25 -33
  344. package/dist/runtime/workers/index.d.ts +2 -2
  345. package/dist/runtime/workers/index.js +5 -4
  346. package/package.json +3 -3
  347. package/src/contracts/Channels/IZLinkFanoutClient.ts +0 -7
  348. package/src/contracts/Common/CoreTypes.ts +7 -0
  349. package/src/contracts/Common/index.ts +1 -1
  350. package/src/contracts/Configuration/InternalDefaults.ts +12 -0
  351. package/src/contracts/Configuration/Registration.ts +92 -48
  352. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +44 -2
  353. package/src/contracts/Configuration/RegistrationBuilders.ts +77 -68
  354. package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
  355. package/src/contracts/Configuration/RegistrationValidators.ts +19 -13
  356. package/src/contracts/Configuration/TimerRegistrationValidator.ts +4 -2
  357. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +1 -0
  358. package/src/contracts/Handlers/JsonContract.ts +14 -4
  359. package/src/contracts/Locations/Authority.ts +7 -3
  360. package/src/contracts/Locations/Options.ts +1 -1
  361. package/src/contracts/Locations/Stores.ts +14 -0
  362. package/src/contracts/RouteMesh/RuntimeTopology.ts +10 -0
  363. package/src/contracts/Spots/Contracts.ts +1 -1
  364. package/src/internal.ts +15 -0
  365. package/src/nest-integration.ts +28 -10
  366. package/src/runtime/abort.ts +6 -5
  367. package/src/runtime/activation-admission.ts +72 -0
  368. package/src/runtime/actors/actor-authority-payload-codec.ts +58 -20
  369. package/src/runtime/actors/actor-client.ts +77 -204
  370. package/src/runtime/actors/actor-context.ts +45 -39
  371. package/src/runtime/actors/actor-handoff.ts +55 -45
  372. package/src/runtime/actors/actor-lifecycle-snapshot.ts +2 -1
  373. package/src/runtime/actors/actor-local-native-join.ts +174 -215
  374. package/src/runtime/actors/actor-native-lookup.ts +2 -9
  375. package/src/runtime/actors/actor-packet-relay-wire.ts +18 -12
  376. package/src/runtime/actors/actor-remote-joiner.ts +15 -36
  377. package/src/runtime/actors/actor-remote-wire.ts +5 -3
  378. package/src/runtime/actors/actor-request-deadline.ts +49 -0
  379. package/src/runtime/actors/actor-retry-delay.ts +2 -1
  380. package/src/runtime/actors/actor-runtime-contracts.ts +4 -10
  381. package/src/runtime/actors/actor-runtime-state.ts +85 -247
  382. package/src/runtime/actors/actor-source-transfer.ts +5 -18
  383. package/src/runtime/actors/bound-session-wire.ts +2 -8
  384. package/src/runtime/actors/deferred-join-completion.ts +44 -0
  385. package/src/runtime/actors/index.ts +122 -88
  386. package/src/runtime/actors/spot-actor-dispatch.ts +60 -29
  387. package/src/runtime/actors/transferred-actor-rollback.ts +11 -62
  388. package/src/runtime/admission.ts +13 -2
  389. package/src/runtime/application-jobs/application-job-queue-scope.ts +4 -4
  390. package/src/runtime/backend/contracts/index.ts +15 -42
  391. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +4 -28
  392. package/src/runtime/backend/mesh-dispatch-pump.ts +111 -117
  393. package/src/runtime/backend/node/node-backend-adapter-factory.ts +5 -25
  394. package/src/runtime/backend/node/node-backend-adapter-support.ts +32 -35
  395. package/src/runtime/backend/node/node-event-loop-poller.ts +16 -8
  396. package/src/runtime/backend/node/node-monitor-backend-adapter.ts +1 -0
  397. package/src/runtime/backend/node/node-raw-binding-port.ts +58 -23
  398. package/src/runtime/backend/node/node-raw-mesh-backend.ts +252 -162
  399. package/src/runtime/backend/node/node-socket-backend-adapter.ts +5 -4
  400. package/src/runtime/backend/raw-binding-port.ts +14 -1
  401. package/src/runtime/backend/runtime-values.ts +4 -1
  402. package/src/runtime/channels/channel-clients.ts +132 -96
  403. package/src/runtime/channels/channel-envelope-inspection.ts +2 -1
  404. package/src/runtime/channels/channel-envelope.ts +58 -29
  405. package/src/runtime/channels/channel-outbound-operations.ts +10 -31
  406. package/src/runtime/channels/channel-receive-loops.ts +39 -7
  407. package/src/runtime/channels/channel-runtime-lifecycle.ts +60 -27
  408. package/src/runtime/channels/channel-runtime-manager.ts +8 -15
  409. package/src/runtime/channels/channel-socket-options.ts +8 -2
  410. package/src/runtime/channels/channel-socket-registry.ts +369 -262
  411. package/src/runtime/channels/channel-transports.ts +161 -115
  412. package/src/runtime/channels/client-server-location-runtime.ts +17 -17
  413. package/src/runtime/channels/client-server-service-wire.ts +40 -12
  414. package/src/runtime/channels/dispatch-error-reporter.ts +7 -5
  415. package/src/runtime/channels/fanout-location-runtime.ts +175 -106
  416. package/src/runtime/channels/spot-direct-envelope.ts +1 -1
  417. package/src/runtime/channels/spot-node-route-transport.ts +5 -2
  418. package/src/runtime/diagnostics/diagnostic-text.ts +4 -0
  419. package/src/runtime/diagnostics/dispatch-error-details.ts +36 -1
  420. package/src/runtime/diagnostics/flow-context.ts +16 -2
  421. package/src/runtime/diagnostics/index.ts +27 -17
  422. package/src/runtime/diagnostics/message-flow.ts +15 -25
  423. package/src/runtime/diagnostics/runtime-metrics.ts +181 -113
  424. package/src/runtime/diagnostics/runtime-observation-queue.ts +3 -2
  425. package/src/runtime/diagnostics/topology-runtime-projections.ts +194 -162
  426. package/src/runtime/disposal.ts +19 -0
  427. package/src/runtime/execution/index.ts +116 -38
  428. package/src/runtime/execution/serial-execution-queue.ts +179 -34
  429. package/src/runtime/execution/state-lane.ts +142 -4
  430. package/src/runtime/foundation/actor-join-recovery-codec.ts +13 -8
  431. package/src/runtime/foundation/event-loop-resources.ts +5 -122
  432. package/src/runtime/foundation/listener-records.ts +21 -0
  433. package/src/runtime/foundation/operation-identity.ts +11 -5
  434. package/src/runtime/foundation/operation-registry.ts +33 -50
  435. package/src/runtime/foundation/raw-service-mesh-runtime.ts +170 -571
  436. package/src/runtime/foundation/runtime-state-projections.ts +9 -1
  437. package/src/runtime/foundation/service-authority-payload-codec.ts +41 -13
  438. package/src/runtime/foundation/service-discovery-registry.ts +32 -3
  439. package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +12 -4
  440. package/src/runtime/foundation/service-liveness-registry.ts +2 -1
  441. package/src/runtime/foundation/service-maintenance-runtime.ts +30 -19
  442. package/src/runtime/foundation/service-metadata-codec.ts +2 -2
  443. package/src/runtime/foundation/service-relocation-aggregate-committer.ts +3 -66
  444. package/src/runtime/foundation/service-relocation-coordinator.ts +13 -0
  445. package/src/runtime/foundation/service-relocation-object-owner.ts +23 -7
  446. package/src/runtime/foundation/service-relocation-runtime.ts +57 -35
  447. package/src/runtime/foundation/service-runtime-contracts.ts +46 -10
  448. package/src/runtime/foundation/service-session-binding-ingress-port.ts +0 -25
  449. package/src/runtime/foundation/service-stateful-registry.ts +14 -2
  450. package/src/runtime/foundation/service-stateful-runtime.ts +435 -327
  451. package/src/runtime/foundation/service-stateful-wire-codec.ts +329 -199
  452. package/src/runtime/foundation/service-topology-registry.ts +30 -79
  453. package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -0
  454. package/src/runtime/foundation/service-wire-codec.ts +15 -8
  455. package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
  456. package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -15
  457. package/src/runtime/framework-errors-internal.ts +380 -134
  458. package/src/runtime/handlers/handler-instance-scope.ts +68 -95
  459. package/src/runtime/host/actor-packet-relay.ts +57 -147
  460. package/src/runtime/host/actor-placement-coordinator.ts +8 -5
  461. package/src/runtime/host/actor-runtime-options-factory.ts +27 -8
  462. package/src/runtime/host/actor-transfer-runtime.ts +266 -418
  463. package/src/runtime/host/application-job-queue.ts +28 -34
  464. package/src/runtime/host/bound-session-relay.ts +1 -2
  465. package/src/runtime/host/channel-runtime-options-factory.ts +1 -2
  466. package/src/runtime/host/index.ts +408 -312
  467. package/src/runtime/host/instance-activation-authority.ts +89 -109
  468. package/src/runtime/host/location-runtime-owner.ts +4 -2
  469. package/src/runtime/host/remote-actor-join-receiver.ts +3 -31
  470. package/src/runtime/host/remote-actor-packet-target-store.ts +17 -58
  471. package/src/runtime/host/remote-bound-session-relay.ts +12 -44
  472. package/src/runtime/host/route-mesh-runtime.ts +236 -275
  473. package/src/runtime/host/runtime-shutdown.ts +17 -21
  474. package/src/runtime/host/service-relocation-control.ts +14 -1
  475. package/src/runtime/host/service-relocation-host-runtime.ts +1161 -904
  476. package/src/runtime/host/spot-address-transport.ts +73 -195
  477. package/src/runtime/host/spot-node-runtime-options-factory.ts +6 -3
  478. package/src/runtime/host/spot-runtime-options-factory.ts +92 -30
  479. package/src/runtime/host/stateful-authority-route-runtime.ts +8 -4
  480. package/src/runtime/host/user-spot-creation-coordinator.ts +182 -163
  481. package/src/runtime/locations/aggregate-inventory-store.ts +16 -13
  482. package/src/runtime/locations/authority-key-codec.ts +7 -3
  483. package/src/runtime/locations/auto-connect-reconciler.ts +39 -26
  484. package/src/runtime/locations/creation-operation-id.ts +6 -3
  485. package/src/runtime/locations/domain-store-contract.ts +12 -3
  486. package/src/runtime/locations/in-memory-authority-store.ts +44 -15
  487. package/src/runtime/locations/in-memory-location-store.ts +50 -39
  488. package/src/runtime/locations/in-memory-provider-location-store.ts +110 -31
  489. package/src/runtime/locations/key-codec.ts +3 -2
  490. package/src/runtime/locations/lease-tracker.ts +8 -14
  491. package/src/runtime/locations/lifecycle.ts +16 -45
  492. package/src/runtime/locations/location-store-failure.ts +4 -0
  493. package/src/runtime/locations/location-store-pages.ts +18 -0
  494. package/src/runtime/locations/location-store-repository.ts +450 -478
  495. package/src/runtime/locations/relocation-blob.ts +17 -6
  496. package/src/runtime/locations/resolvers.ts +90 -58
  497. package/src/runtime/locations/runtime.ts +220 -110
  498. package/src/runtime/locations/spot-location-claims.ts +54 -26
  499. package/src/runtime/messaging/payload-codec.ts +35 -24
  500. package/src/runtime/messaging/submission-result.ts +57 -1
  501. package/src/runtime/protocol/service_wire_codec.generated.ts +27 -10
  502. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  503. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +6 -6
  504. package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +6 -3
  505. package/src/runtime/spots/index.ts +687 -437
  506. package/src/runtime/spots/spot-activation-registry.ts +42 -71
  507. package/src/runtime/spots/spot-activation-state.ts +4 -16
  508. package/src/runtime/spots/spot-activation.ts +167 -115
  509. package/src/runtime/spots/spot-actor-admission-coordinator.ts +5 -57
  510. package/src/runtime/spots/spot-actor-join-dispatch.ts +25 -79
  511. package/src/runtime/spots/spot-actor-lifecycle-drain.ts +20 -18
  512. package/src/runtime/spots/spot-actor-membership.ts +107 -75
  513. package/src/runtime/spots/spot-actor-packet-dispatch.ts +0 -16
  514. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +3 -15
  515. package/src/runtime/spots/spot-context.ts +3 -3
  516. package/src/runtime/spots/spot-entry-activation.ts +13 -33
  517. package/src/runtime/spots/spot-lifecycle-metrics.ts +3 -2
  518. package/src/runtime/spots/spot-manager-public.ts +29 -21
  519. package/src/runtime/spots/spot-node-autoconnect.ts +20 -26
  520. package/src/runtime/spots/spot-node-runtime-manager.ts +145 -140
  521. package/src/runtime/spots/spot-outbound.ts +47 -68
  522. package/src/runtime/spots/spot-remote-codec.ts +7 -3
  523. package/src/runtime/spots/spot-route-packet-dispatch.ts +25 -24
  524. package/src/runtime/spots/spot-route-replies.ts +6 -4
  525. package/src/runtime/spots/spot-routed-actor-admission.ts +13 -6
  526. package/src/runtime/spots/spot-routed-frame-dispatch.ts +6 -77
  527. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +95 -22
  528. package/src/runtime/spots/spot-runtime-ports.ts +10 -43
  529. package/src/runtime/spots/spot-serial-executor.ts +10 -2
  530. package/src/runtime/spots/spot-serial-turn-executor.ts +120 -13
  531. package/src/runtime/spots/spot-timer.ts +3 -2
  532. package/src/runtime/streams/actor-session-binding-registry.ts +182 -560
  533. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +1 -19
  534. package/src/runtime/streams/bound-actor-relay-sender.ts +89 -43
  535. package/src/runtime/streams/bound-session-service.ts +23 -37
  536. package/src/runtime/streams/index.ts +102 -88
  537. package/src/runtime/streams/managed-stream.ts +29 -10
  538. package/src/runtime/streams/native-fallback-bound-session.ts +1 -3
  539. package/src/runtime/streams/protocol.ts +34 -88
  540. package/src/runtime/streams/session-actor-coordinator.ts +17 -5
  541. package/src/runtime/streams/session-calls.ts +6 -5
  542. package/src/runtime/streams/session-context.ts +54 -10
  543. package/src/runtime/streams/session-requests.ts +2 -1
  544. package/src/runtime/streams/session-serial-executor.ts +2 -2
  545. package/src/runtime/streams/stream-binding-runtime-ports.ts +22 -1
  546. package/src/runtime/streams/stream-frame-factory.ts +2 -3
  547. package/src/runtime/streams/stream-session-runtime.ts +57 -59
  548. package/src/runtime/workers/index.ts +13 -12
  549. package/dist/runtime/actors/deferred-join-accepted-journal.d.ts +0 -47
  550. package/dist/runtime/actors/deferred-join-accepted-journal.js +0 -992
  551. package/dist/runtime/actors/post-commit-actor-location.d.ts +0 -19
  552. package/dist/runtime/actors/post-commit-actor-location.js +0 -72
  553. package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +0 -26
  554. package/dist/runtime/spots/spot-native-actor-join-admission.js +0 -106
  555. package/src/runtime/actors/deferred-join-accepted-journal.ts +0 -1346
  556. package/src/runtime/actors/post-commit-actor-location.ts +0 -121
  557. package/src/runtime/spots/spot-native-actor-join-admission.ts +0 -155
@@ -1,3 +1,4 @@
1
+ import { dispatchReasonFromError } from '../diagnostics/dispatch-error-details';
1
2
  import type {
2
3
  ActorRef,
3
4
  RoutingId,
@@ -32,6 +33,7 @@ import {
32
33
  ZLinkMessage,
33
34
  ZLinkFrameworkException,
34
35
  ZLinkFrameworkErrorKind,
36
+ ZLinkFrameworkRuntimeState,
35
37
  ZLinkSpotCloseReason,
36
38
  ZLinkSpotKind
37
39
  } from '../../contracts';
@@ -48,6 +50,7 @@ import {
48
50
  runWithFlow,
49
51
  type ZLinkRuntimeEventPublisher
50
52
  } from '../diagnostics';
53
+ import { diagnosticTextOrAbsent } from '../diagnostics/diagnostic-text';
51
54
  import { ZLinkBufferMessage as RuntimeMessage } from '../backend/runtime-message';
52
55
  import { SubmitResult } from '../backend/runtime-values';
53
56
  import {
@@ -59,10 +62,10 @@ import {
59
62
  } from '../foundation/service-runtime-contracts';
60
63
  import { zlinkMetadataByteLength, zlinkSerialWorkOptions } from '../execution/serial-work-size';
61
64
  import { ZLinkConfigurationException } from '../configuration';
65
+ import { releaseApplicationJobPermitBeforeHandler } from '../application-jobs/application-job-queue-scope';
62
66
  import {
63
67
  ZLinkFrameworkInternalErrorKind,
64
68
  createInternalFrameworkException,
65
- internalFrameworkErrorKind,
66
69
  internalFrameworkWireReply
67
70
  } from '../framework-errors-internal';
68
71
  import type { ZLinkBackendSpot, ZLinkBackendSpotNode } from '../backend/contracts';
@@ -72,7 +75,7 @@ import { ZLinkWorkerRuntime } from '../workers';
72
75
  import {
73
76
  type ZLinkActorHandoffPrefixAdmission,
74
77
  type ZLinkActorHandoffPrefixRecord,
75
- type ZLinkDeferredJoinAcceptedRoot,
78
+ type ZLinkDeferredJoinCompletion,
76
79
  type ZLinkRemoteBoundSessionTarget
77
80
  } from '../actors';
78
81
  import type { ZLinkLocationLifecycle } from '../locations';
@@ -130,9 +133,9 @@ export {
130
133
  } from './spot-handler-registry';
131
134
  export { ZLinkRuntimeSpotPublisherTransport } from './spot-publisher-transport';
132
135
  import { ZLinkSpotActivationRegistry } from './spot-activation-registry';
133
- import { ZLinkSpotCloseOccupiedError, type ZLinkSpotActivation } from './spot-activation-state';
136
+ import type { ZLinkSpotActivation } from './spot-activation-state';
134
137
  import { ZLinkSpotActivationLifecycle, type ZLinkNativeSpotAuthority } from './spot-activation';
135
- import { ZLinkSpotActorMembership, type ZLinkActorJoinRollback } from './spot-actor-membership';
138
+ import { ZLinkSpotActorMembership } from './spot-actor-membership';
136
139
  import { ZLinkFormalRemoteActorTransferRegistry } from './formal-remote-actor-transfer-registry';
137
140
  import {
138
141
  ZLinkFormalRemoteActorAdmissionRegistry,
@@ -145,6 +148,7 @@ import type {
145
148
  ZLinkSpotBoundSessionRuntime
146
149
  } from './spot-runtime-ports';
147
150
  import type { ZLinkRuntimeAdmissionGate } from '../admission';
151
+ import type { ZLinkActivationAdmission } from '../activation-admission';
148
152
  import type { ZLinkDetachedTaskRunner } from './spot-actor-join-dispatch';
149
153
  import type { ZLinkLocalSpotCreateResult } from './spot-manager-internal-contracts';
150
154
  export type { ZLinkLocalSpotCreateResult } from './spot-manager-internal-contracts';
@@ -203,6 +207,11 @@ export interface ZLinkSpotManagerOptions {
203
207
  actor: ZLinkActor,
204
208
  handoffBacklog?: readonly ZLinkActorHandoffPacket[]
205
209
  ) => Promise<void>;
210
+ readonly executeEntryActor?: <T>(
211
+ meshName: string,
212
+ actorId: string,
213
+ operation: () => Promise<T>
214
+ ) => Promise<T>;
206
215
  readonly actorCountProvider?: (spotId: RoutingId) => number;
207
216
  readonly userSpotExecutionMode?: (
208
217
  meshName: string,
@@ -216,7 +225,6 @@ export interface ZLinkSpotManagerOptions {
216
225
  readonly actorRef?: ActorRef;
217
226
  readonly spotId?: RoutingId;
218
227
  };
219
- readonly actorBindingGenerationObserver?: (actorId: string, generation: bigint) => void;
220
228
  readonly channelClient?: ZLinkChannelClient;
221
229
  readonly fanoutClient?: ZLinkFanoutClient;
222
230
  readonly spotPublisherClient?: ZLinkSpotPublisherClient;
@@ -224,9 +232,9 @@ export interface ZLinkSpotManagerOptions {
224
232
  readonly routedTransport?: ZLinkSpotRoutedTransport;
225
233
  readonly addressTransport?: import('./spot-outbound').ZLinkSpotAddressTransport;
226
234
  readonly spotRouterChannelIdForMesh?: (meshName: string) => string;
227
- readonly channelMeshNameForChannel?: (channelName: string) => string | undefined;
228
235
  readonly providerResolver?: ZLinkProviderResolver;
229
236
  readonly dispatchErrors?: ZLinkDispatchErrorReporter;
237
+ readonly closeErrorSink?: import('../diagnostics/dispatch-error-port').ZLinkDispatchErrorSink;
230
238
  readonly runtimeEventPublisher?: ZLinkRuntimeEventPublisher;
231
239
  readonly workerRuntime?: ZLinkWorkerRuntime;
232
240
  readonly messageSerializers?: ReadonlyMap<string, ZLinkMessageSerializer>;
@@ -238,12 +246,28 @@ export interface ZLinkSpotManagerOptions {
238
246
  ) => Promise<void>;
239
247
  readonly beginInstanceIdleClosingAuthority?: (
240
248
  meshName: string,
241
- spotId: RoutingId
242
- ) => Promise<{ restoreReady(): Promise<void> } | undefined>;
249
+ spotId: RoutingId,
250
+ onCommitted: () => void
251
+ ) => Promise<
252
+ import('../locations/spot-location-claims').ZLinkInstanceClosingAuthority | undefined
253
+ >;
243
254
  readonly beginInstanceClosingAuthority?: (
244
255
  meshName: string,
245
- spotId: RoutingId
246
- ) => Promise<{ restoreReady(): Promise<void> } | undefined>;
256
+ spotId: RoutingId,
257
+ onCommitted: () => void,
258
+ objectGeneration: bigint
259
+ ) => Promise<
260
+ import('../locations/spot-location-claims').ZLinkInstanceClosingAuthority | undefined
261
+ >;
262
+ /** Moves a local User Spot incarnation's authority to Closing for a context Close. */
263
+ readonly beginUserClosingAuthority?: (
264
+ meshName: string,
265
+ spotId: RoutingId,
266
+ objectGeneration: bigint,
267
+ onCommitted: () => void
268
+ ) => Promise<
269
+ import('../locations/spot-location-claims').ZLinkInstanceClosingAuthority | undefined
270
+ >;
247
271
  readonly instanceSpotApplicationTargetProvider?: (
248
272
  meshName: string,
249
273
  spotId: RoutingId
@@ -261,7 +285,6 @@ export interface ZLinkSpotManagerOptions {
261
285
  spotId: RoutingId,
262
286
  authority?: ZLinkNativeSpotAuthority
263
287
  ) => ZLinkBackendSpot | undefined;
264
- readonly createReceived?: () => import('../backend').ZLinkBackendReceived;
265
288
  readonly createTopicMessage?: () => import('../backend').ZLinkBackendTopicMessage;
266
289
  readonly nativeSpotNodeProvider?: (meshName: string) => ZLinkBackendSpotNode | undefined;
267
290
  readonly actorResolver?: (actorId: string) => ZLinkActor | undefined;
@@ -274,15 +297,33 @@ export interface ZLinkSpotManagerOptions {
274
297
  readonly ownerLeaseGeneration: bigint;
275
298
  }) => Promise<{ readonly actorType: string }>;
276
299
  readonly actorLifecycleResolver?: (actorId: string) => ZLinkActor | undefined;
277
- readonly detachedTaskRunner?: ZLinkDetachedTaskRunner;
300
+ readonly detachedTaskRunner: ZLinkDetachedTaskRunner;
278
301
  readonly actorTransferRuntime?: ZLinkSpotActorTransferRuntime;
279
302
  readonly boundSessionRuntime?: ZLinkSpotBoundSessionRuntime;
280
303
  readonly actorHandoffRuntime?: ZLinkSpotActorHandoffRuntime;
281
304
  readonly metrics?: import('../diagnostics').ZLinkRuntimeMetrics;
282
305
  readonly admission?: ZLinkRuntimeAdmissionGate;
283
- readonly statefulExecutionAllowed?: () => boolean;
284
- readonly activationConcurrencyLimitProvider?: (meshName: string) => number;
285
- readonly onInstanceActivationConcurrencyChanged?: (meshName: string) => void;
306
+ readonly statefulExecution?: {
307
+ readonly admissionOpen: () => boolean;
308
+ readonly hostState: () => ZLinkFrameworkRuntimeState;
309
+ };
310
+ readonly activationAdmission?: ZLinkActivationAdmission;
311
+ }
312
+
313
+ interface ZLinkTargetSpotCloseOperation {
314
+ readonly activation: ZLinkSpotActivation;
315
+ readonly reason: ZLinkSpotCloseReason;
316
+ readonly beginAuthority: (
317
+ onCommitted: () => void
318
+ ) => Promise<
319
+ import('../locations/spot-location-claims').ZLinkInstanceClosingAuthority | undefined
320
+ >;
321
+ authority?: import('../locations/spot-location-claims').ZLinkInstanceClosingAuthority;
322
+ authorityDecision?: Promise<void>;
323
+ ready?: Promise<boolean>;
324
+ canExecuteApplication?(
325
+ record: import('../execution/serial-execution-queue').ZLinkSerialWorkRecord<unknown>
326
+ ): boolean;
286
327
  }
287
328
 
288
329
  export class DefaultZLinkSpotManager {
@@ -306,27 +347,7 @@ export class DefaultZLinkSpotManager {
306
347
  string,
307
348
  Map<string, Promise<ZLinkSpotActivation>>
308
349
  >();
309
- private readonly instanceActivationGates = new Map<
310
- string,
311
- {
312
- readonly meshName: string;
313
- readonly limit: number;
314
- active: number;
315
- // Tombstone slots + head cursor keep abort O(1) and admit O(1) amortized
316
- // instead of indexOf/splice + shift scans under a cancellation storm.
317
- readonly waiters: Array<
318
- | {
319
- resolve: (release: () => void) => void;
320
- reject: (error: unknown) => void;
321
- signal?: AbortSignal;
322
- abort?: () => void;
323
- }
324
- | undefined
325
- >;
326
- waiterHead: number;
327
- }
328
- >();
329
- private readonly pendingInstanceCloses = new Map<string, Promise<boolean>>();
350
+ private readonly closeOperations = new Map<string, ZLinkTargetSpotCloseOperation>();
330
351
  private readonly pendingInstanceTerminals = new Map<string, number>();
331
352
  private readonly pendingInstanceTerminalGenerations = new Map<string, Map<string, number>>();
332
353
  private readonly deferredInstanceAuthorityReleases = new Map<string, Set<bigint>>();
@@ -337,6 +358,9 @@ export class DefaultZLinkSpotManager {
337
358
  private readonly options: ZLinkSpotManagerOptions,
338
359
  timerClock?: import('./spot-timer').ZLinkTimerClock
339
360
  ) {
361
+ if ((options.detachedTaskRunner as unknown) === undefined) {
362
+ throw new ZLinkConfigurationException('Spot manager requires a detached task runner.');
363
+ }
340
364
  this.activations = new ZLinkSpotActivationRegistry(options.metrics);
341
365
  this.factories = new Set(options.spotFactories);
342
366
  this.workerRuntime = options.workerRuntime ?? new ZLinkWorkerRuntime();
@@ -347,7 +371,7 @@ export class DefaultZLinkSpotManager {
347
371
  nodeGenerationProvider: options.nodeGenerationProvider
348
372
  });
349
373
  this.routedSpotPackets = new ZLinkRoutedSpotPacketDispatch({
350
- resolveActivation: (spotId) => this.activations.resolveUnique(spotId),
374
+ resolveActivation: (spotId) => this.resolveApplicationActivation(spotId),
351
375
  claimApplicationWork:
352
376
  options.admission === undefined
353
377
  ? undefined
@@ -392,12 +416,12 @@ export class DefaultZLinkSpotManager {
392
416
  spotRouterChannelIdForMesh: options.spotRouterChannelIdForMesh,
393
417
  providerResolver: options.providerResolver,
394
418
  dispatchErrors: options.dispatchErrors,
419
+ closeErrorSink: options.closeErrorSink,
395
420
  runtimeEventPublisher: options.runtimeEventPublisher,
396
421
  workerRuntime: this.workerRuntime,
397
422
  messageSerializers: options.messageSerializers,
398
423
  locationClaim: this.locationClaim,
399
424
  createNativeSpot: options.createNativeSpot,
400
- createReceived: options.createReceived,
401
425
  createTopicMessage: options.createTopicMessage,
402
426
  nativeSpotNodeProvider: options.nativeSpotNodeProvider,
403
427
  actorResolver: options.actorResolver,
@@ -406,11 +430,11 @@ export class DefaultZLinkSpotManager {
406
430
  boundSessionRuntime: options.boundSessionRuntime,
407
431
  actorHandoffRuntime: options.actorHandoffRuntime,
408
432
  admission: options.admission,
409
- statefulExecutionAllowed: options.statefulExecutionAllowed,
433
+ statefulExecutionAllowed: options.statefulExecution?.admissionOpen,
410
434
  leaveActor: (spotId, actor, signal, meshName) =>
411
435
  this.actorMembership.leaveActor(spotId, actor, signal, meshName),
412
- closeSpot: (meshName, spotId, signal, reason) =>
413
- this.closeWithReason(meshName, spotId, signal, reason),
436
+ requestContextClose: (activation, objectGeneration, signal) =>
437
+ this.closeFromContext(activation, objectGeneration, signal),
414
438
  registerActivation: (activation) => {
415
439
  this.activations.register(activation);
416
440
  this.scheduleIdleSweep();
@@ -470,14 +494,6 @@ export class DefaultZLinkSpotManager {
470
494
  return this.activations.list(meshName).length;
471
495
  }
472
496
 
473
- instanceActivationConcurrency(meshName: string): {
474
- readonly active: number;
475
- readonly limit: number;
476
- } {
477
- const limit = this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128;
478
- return { active: this.instanceActivationGates.get(meshName)?.active ?? 0, limit };
479
- }
480
-
481
497
  resolveRelocationActivation(
482
498
  meshName: string,
483
499
  spotId: RoutingId
@@ -548,7 +564,7 @@ export class DefaultZLinkSpotManager {
548
564
  await awaitWithAbort(existing, signal);
549
565
  return;
550
566
  }
551
- const release = await this.acquireInstanceActivation(meshName, signal);
567
+ const release = await this.options.activationAdmission?.acquire(meshName, signal);
552
568
  try {
553
569
  await this.materializeInstanceCore(
554
570
  meshName,
@@ -559,7 +575,7 @@ export class DefaultZLinkSpotManager {
559
575
  signal
560
576
  );
561
577
  } finally {
562
- release();
578
+ release?.();
563
579
  }
564
580
  }
565
581
 
@@ -590,7 +606,8 @@ export class DefaultZLinkSpotManager {
590
606
  // explicit Instance intent arriving at that boundary must wait for the
591
607
  // old resources to be released before materializing the replacement.
592
608
  // This is lifecycle convergence; it does not resubmit application work.
593
- const pendingClose = this.pendingInstanceCloses.get(key);
609
+ const closeOperation = this.closeOperations.get(key);
610
+ const pendingClose = closeOperation?.ready;
594
611
  if (pendingClose !== undefined) {
595
612
  await awaitWithAbort(pendingClose, signal);
596
613
  continue;
@@ -687,94 +704,50 @@ export class DefaultZLinkSpotManager {
687
704
  }
688
705
  }
689
706
 
690
- private async acquireInstanceActivation(
691
- meshName: string,
692
- signal?: AbortSignal
693
- ): Promise<() => void> {
694
- let gate = this.instanceActivationGates.get(meshName);
695
- if (gate === undefined) {
696
- gate = {
697
- meshName,
698
- limit: this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128,
699
- active: 0,
700
- waiters: [],
701
- waiterHead: 0
702
- };
703
- this.instanceActivationGates.set(meshName, gate);
704
- }
705
- if (signal?.aborted === true) throw signal.reason;
706
- if (gate.active < gate.limit) {
707
- gate.active += 1;
708
- this.options.onInstanceActivationConcurrencyChanged?.(meshName);
709
- return () => this.releaseInstanceActivation(gate!);
710
- }
711
- return new Promise<() => void>((resolve, reject) => {
712
- const waiter = { resolve, reject, signal, abort: undefined as (() => void) | undefined };
713
- const slot = gate!.waiters.length;
714
- waiter.abort = () => {
715
- if (gate!.waiters[slot] === waiter) gate!.waiters[slot] = undefined;
716
- reject(signal?.reason);
717
- };
718
- signal?.addEventListener('abort', waiter.abort, { once: true });
719
- gate!.waiters.push(waiter);
720
- });
721
- }
722
-
723
- private releaseInstanceActivation(gate: {
724
- readonly meshName: string;
725
- readonly limit: number;
726
- active: number;
727
- readonly waiters: Array<
728
- | {
729
- resolve: (release: () => void) => void;
730
- reject: (error: unknown) => void;
731
- signal?: AbortSignal;
732
- abort?: () => void;
733
- }
734
- | undefined
735
- >;
736
- waiterHead: number;
737
- }): void {
738
- while (gate.waiterHead < gate.waiters.length) {
739
- const waiter = gate.waiters[gate.waiterHead];
740
- gate.waiters[gate.waiterHead] = undefined;
741
- gate.waiterHead += 1;
742
- if (gate.waiterHead >= gate.waiters.length) {
743
- gate.waiters.length = 0;
744
- gate.waiterHead = 0;
745
- }
746
- if (waiter === undefined) continue;
747
- if (waiter.abort !== undefined) waiter.signal?.removeEventListener('abort', waiter.abort);
748
- waiter.resolve(() => this.releaseInstanceActivation(gate));
749
- return;
750
- }
751
- gate.waiters.length = 0;
752
- gate.waiterHead = 0;
753
- gate.active -= 1;
754
- this.options.onInstanceActivationConcurrencyChanged?.(gate.meshName);
755
- }
756
-
757
707
  isInstanceMaterialized(meshName: string, instanceType: string, spotId: RoutingId): boolean {
758
- const activation = this.activations.resolve(meshName, spotId);
708
+ const activation = this.resolveApplicationActivation(spotId, meshName);
759
709
  return (
760
710
  activation !== undefined &&
761
711
  activation.spotType === this.requireInstanceFactory(meshName, instanceType)
762
712
  );
763
713
  }
764
714
 
715
+ private resolveApplicationActivation(
716
+ spotId: RoutingId,
717
+ meshName?: string
718
+ ): ZLinkSpotActivation | undefined {
719
+ const current =
720
+ meshName === undefined
721
+ ? this.activations.resolveUnique(spotId)
722
+ : this.activations.resolve(meshName, spotId);
723
+ if (current !== undefined) return current;
724
+ if (meshName !== undefined)
725
+ return this.closeOperations.get(`${meshName}\0${String(spotId)}`)?.activation;
726
+ for (const operation of this.closeOperations.values()) {
727
+ if (String(operation.activation.spotId) === String(spotId)) return operation.activation;
728
+ }
729
+ return undefined;
730
+ }
731
+
765
732
  isInstanceMaterializing(meshName: string, spotId: RoutingId): boolean {
766
733
  const prefix = instanceMaterializationPrefix(meshName, spotId);
767
- return (this.pendingInstanceMaterializationsByPrefix.get(prefix)?.size ?? 0) > 0;
734
+ return (
735
+ (this.pendingInstanceMaterializationsByPrefix.get(prefix)?.size ?? 0) > 0 ||
736
+ this.closeOperations.get(`${meshName}\0${String(spotId)}`)?.authority !== undefined
737
+ );
768
738
  }
769
739
 
770
- isInstanceClosing(meshName: string, spotId: RoutingId): boolean {
771
- const key = `${meshName}\0${String(spotId)}`;
740
+ isSpotClosing(meshName: string, spotId: RoutingId): boolean {
772
741
  return (
773
- this.pendingInstanceCloses.has(key) ||
774
- this.activations.closingOperation(meshName, spotId) !== undefined
742
+ this.closeOperations.get(`${meshName}\0${String(spotId)}`)?.authority !== undefined ||
743
+ this.activations.activationForClose(meshName, spotId)?.executionBarrier.isCloseSealed === true
775
744
  );
776
745
  }
777
746
 
747
+ pendingSpotCloseDecision(meshName: string, spotId: RoutingId): Promise<void> | undefined {
748
+ return this.closeOperations.get(`${meshName}\0${String(spotId)}`)?.authorityDecision;
749
+ }
750
+
778
751
  async discardInstance(meshName: string, spotId: RoutingId): Promise<void> {
779
752
  const activation = this.activations.resolve(meshName, spotId);
780
753
  if (activation === undefined) return;
@@ -835,7 +808,7 @@ export class DefaultZLinkSpotManager {
835
808
  }
836
809
  this.pendingInstanceTerminals.delete(key);
837
810
  this.pendingInstanceTerminalGenerations.delete(key);
838
- const pendingClose = this.pendingInstanceCloses.get(key);
811
+ const pendingClose = this.closeOperations.get(key)?.ready;
839
812
  if (pendingClose !== undefined) {
840
813
  this.deferInstanceAuthorityRelease(key, objectGeneration);
841
814
  await pendingClose;
@@ -950,20 +923,6 @@ export class DefaultZLinkSpotManager {
950
923
  ) {
951
924
  continue;
952
925
  }
953
- let durableClosing: { restoreReady(): Promise<void> } | undefined;
954
- try {
955
- durableClosing = await (this.options.beginInstanceIdleClosingAuthority?.(
956
- activation.meshName,
957
- activation.spotId
958
- ) ?? Promise.resolve({ restoreReady: async () => undefined }));
959
- } catch (error) {
960
- activation.abortIdleEviction();
961
- throw error;
962
- }
963
- if (durableClosing === undefined) {
964
- activation.abortIdleEviction();
965
- continue;
966
- }
967
926
  const close = this.closeWithReason(
968
927
  activation.meshName,
969
928
  activation.spotId,
@@ -973,25 +932,17 @@ export class DefaultZLinkSpotManager {
973
932
  const run = async () => {
974
933
  try {
975
934
  const closed = await close;
976
- if (!closed) {
977
- await durableClosing.restoreReady();
978
- activation.abortIdleEviction();
979
- }
935
+ if (!closed) activation.abortIdleEviction();
980
936
  } catch (error) {
981
- if (error instanceof ZLinkSpotCloseOccupiedError) {
982
- await durableClosing.restoreReady();
983
- }
984
- activation.abortIdleEviction();
937
+ if (!this.isSpotClosing(activation.meshName, activation.spotId))
938
+ activation.abortIdleEviction();
985
939
  throw error;
986
940
  }
987
941
  };
988
- this.options.detachedTaskRunner?.runDetached(
942
+ this.options.detachedTaskRunner.runDetached(
989
943
  `instance idle eviction ${String(activation.spotId)}`,
990
944
  run
991
945
  );
992
- if (this.options.detachedTaskRunner === undefined) {
993
- void run().catch(() => undefined);
994
- }
995
946
  }
996
947
  } finally {
997
948
  this.idleSweepRunning = false;
@@ -1085,8 +1036,9 @@ export class DefaultZLinkSpotManager {
1085
1036
  requireMeshName(meshName);
1086
1037
  const args = normalizeSpotCreateArgs(requestOrSignal, signal);
1087
1038
  throwIfAborted(args.signal);
1039
+ this.options.admission?.requireRequest('SPOT create', meshName);
1088
1040
  const operation = this.activations.getOrBegin(meshName, spotType, spotId, async () => {
1089
- this.options.admission?.requireRequest('SPOT create', meshName);
1041
+ const release = await this.options.activationAdmission?.acquire(meshName, args.signal);
1090
1042
  const ownedRequest =
1091
1043
  args.request === undefined
1092
1044
  ? RuntimeMessage.from(Buffer.alloc(0))
@@ -1102,6 +1054,7 @@ export class DefaultZLinkSpotManager {
1102
1054
  );
1103
1055
  } finally {
1104
1056
  ownedRequest.close();
1057
+ release?.();
1105
1058
  }
1106
1059
  });
1107
1060
  return await awaitWithAbort(operation.ready, args.signal);
@@ -1109,12 +1062,16 @@ export class DefaultZLinkSpotManager {
1109
1062
 
1110
1063
  async find(meshName: string, spotId: RoutingId): Promise<ZLinkSpotInfo | null> {
1111
1064
  requireMeshName(meshName);
1112
- return this.activations.has(meshName, spotId) ? { spotId } : null;
1065
+ return this.activations.has(meshName, spotId) && !this.isSpotClosing(meshName, spotId)
1066
+ ? { spotId }
1067
+ : null;
1113
1068
  }
1114
1069
 
1115
1070
  async list(meshName: string): Promise<readonly ZLinkSpotInfo[]> {
1116
1071
  requireMeshName(meshName);
1117
- return this.activations.list(meshName);
1072
+ return this.activations
1073
+ .list(meshName)
1074
+ .filter(({ spotId }) => !this.isSpotClosing(meshName, spotId));
1118
1075
  }
1119
1076
 
1120
1077
  async drainForShutdown(meshName: string, signal?: AbortSignal, deadline?: Date): Promise<void> {
@@ -1143,120 +1100,289 @@ export class DefaultZLinkSpotManager {
1143
1100
  return await this.closeWithReason(meshName, spotId, signal, ZLinkSpotCloseReason.ExplicitClose);
1144
1101
  }
1145
1102
 
1103
+ async closeUserWithAuthority(
1104
+ meshName: string,
1105
+ spotId: RoutingId,
1106
+ beginAuthority: (
1107
+ onCommitted: () => void
1108
+ ) => Promise<import('../locations/spot-location-claims').ZLinkInstanceClosingAuthority>,
1109
+ signal?: AbortSignal
1110
+ ): Promise<boolean> {
1111
+ return await this.closeWithReason(
1112
+ meshName,
1113
+ spotId,
1114
+ signal,
1115
+ ZLinkSpotCloseReason.ExplicitClose,
1116
+ undefined,
1117
+ beginAuthority
1118
+ );
1119
+ }
1120
+
1121
+ private closeFromContext(
1122
+ activation: ZLinkSpotActivation,
1123
+ objectGeneration: bigint,
1124
+ signal?: AbortSignal
1125
+ ): Promise<boolean> {
1126
+ const { meshName, spotId } = activation;
1127
+ const operation = this.closeOperations.get(`${meshName}\0${String(spotId)}`);
1128
+ const current = operation?.activation ?? this.activations.resolve(meshName, spotId);
1129
+ if (current === undefined) {
1130
+ return Promise.resolve(false);
1131
+ }
1132
+ if (current !== activation || current.objectGeneration !== objectGeneration) {
1133
+ return Promise.reject(
1134
+ createInternalFrameworkException(
1135
+ ZLinkFrameworkInternalErrorKind.InvalidOperation,
1136
+ `Spot '${String(spotId)}' generation is stale.`
1137
+ )
1138
+ );
1139
+ }
1140
+ const beginUserAuthority =
1141
+ activation.domain.kind === 'user' && this.options.beginUserClosingAuthority !== undefined
1142
+ ? (onCommitted: () => void) =>
1143
+ this.options.beginUserClosingAuthority!(meshName, spotId, objectGeneration, onCommitted)
1144
+ : undefined;
1145
+ return this.closeWithReason(
1146
+ meshName,
1147
+ spotId,
1148
+ signal,
1149
+ ZLinkSpotCloseReason.ExplicitClose,
1150
+ undefined,
1151
+ beginUserAuthority
1152
+ );
1153
+ }
1154
+
1146
1155
  private async closeWithReason(
1147
1156
  meshName: string,
1148
1157
  spotId: RoutingId,
1149
1158
  signal?: AbortSignal,
1150
1159
  reason = ZLinkSpotCloseReason.ExplicitClose,
1151
- deadline?: Date
1160
+ deadline?: Date,
1161
+ beginUserAuthority?: (
1162
+ onCommitted: () => void
1163
+ ) => Promise<
1164
+ import('../locations/spot-location-claims').ZLinkInstanceClosingAuthority | undefined
1165
+ >
1152
1166
  ): Promise<boolean> {
1153
1167
  requireMeshName(meshName);
1154
1168
  const key = `${meshName}\0${String(spotId)}`;
1155
- const closing = this.activations.closingOperation(meshName, spotId);
1156
- if (closing !== undefined) {
1157
- return await closing.ready;
1158
- }
1159
- const pendingClose = this.pendingInstanceCloses.get(key);
1160
- if (pendingClose !== undefined) {
1161
- const pendingActivation = this.activations.resolve(meshName, spotId);
1162
- if (pendingActivation?.serial.isCurrentTurn === true) return true;
1163
- return await pendingClose;
1164
- }
1165
- const activation = this.activations.resolve(meshName, spotId);
1166
- if (activation === undefined) {
1167
- return false;
1169
+ let operation = this.closeOperations.get(key);
1170
+ if (operation === undefined) {
1171
+ const activation = this.activations.resolve(meshName, spotId);
1172
+ if (activation === undefined) return false;
1173
+ if (
1174
+ activation.domain.kind === 'user' &&
1175
+ reason === ZLinkSpotCloseReason.ExplicitClose &&
1176
+ beginUserAuthority === undefined
1177
+ ) {
1178
+ throw createInternalFrameworkException(
1179
+ ZLinkFrameworkInternalErrorKind.InvalidOperation,
1180
+ `User Spot '${String(spotId)}' Close requires its authority owner.`
1181
+ );
1182
+ }
1183
+ const domain = activation.domain;
1184
+ const beginAuthority =
1185
+ beginUserAuthority ??
1186
+ (domain.kind === 'instance' &&
1187
+ reason === ZLinkSpotCloseReason.ExplicitClose &&
1188
+ this.options.beginInstanceClosingAuthority !== undefined
1189
+ ? (onCommitted) =>
1190
+ this.options.beginInstanceClosingAuthority!(
1191
+ meshName,
1192
+ spotId,
1193
+ onCommitted,
1194
+ domain.objectGeneration
1195
+ )
1196
+ : domain.kind === 'instance' &&
1197
+ reason === ZLinkSpotCloseReason.IdleEvicted &&
1198
+ this.options.beginInstanceIdleClosingAuthority !== undefined
1199
+ ? (onCommitted) =>
1200
+ this.options.beginInstanceIdleClosingAuthority!(meshName, spotId, onCommitted)
1201
+ : async (onCommitted) => {
1202
+ onCommitted();
1203
+ return { release: async () => undefined };
1204
+ });
1205
+ operation = {
1206
+ activation,
1207
+ reason,
1208
+ beginAuthority
1209
+ };
1210
+ if (reason === ZLinkSpotCloseReason.ExplicitClose) {
1211
+ operation.canExecuteApplication = (record) => {
1212
+ const context = record.context as
1213
+ import('./spot-serial-turn-executor').ZLinkSpotApplicationTurnContext | undefined;
1214
+ return context === undefined;
1215
+ };
1216
+ }
1217
+ this.closeOperations.set(key, operation);
1168
1218
  }
1169
- const currentTurn = activation.serial.isCurrentTurn;
1170
- const isInstance = activation.domain.kind === 'instance';
1171
- const beginClose = () => {
1172
- const seal = activation.sealExecution();
1173
- const operation = this.activations.startClose(
1174
- meshName,
1175
- spotId,
1176
- (target) => this.activationLifecycle.closeAfterSeal(target, seal, signal, reason, deadline),
1177
- (target) => this.activationLifecycle.resourcesReleased(target),
1178
- reason
1219
+ if (operation.ready === undefined) {
1220
+ const active = operation;
1221
+ const run = active.activation.serial.executeControlLifecycleOperation(
1222
+ () => this.runCloseOperation(meshName, spotId, active, signal, deadline),
1223
+ active.canExecuteApplication === undefined
1224
+ ? undefined
1225
+ : (active as import('../execution/serial-execution-queue').ZLinkSerialLifecycleContext)
1179
1226
  );
1180
- if (operation === undefined) {
1181
- activation.abortExecutionSeal(seal);
1182
- }
1183
- return operation;
1184
- };
1227
+ active.ready = run.finally(() => {
1228
+ active.ready = undefined;
1229
+ if (this.closeOperations.get(key) === active) {
1230
+ this.closeOperations.delete(key);
1231
+ }
1232
+ });
1233
+ }
1234
+ return await operation.ready!;
1235
+ }
1185
1236
 
1186
- if (isInstance) {
1187
- const beginAuthorityClose =
1188
- reason === ZLinkSpotCloseReason.ExplicitClose
1189
- ? this.options.beginInstanceClosingAuthority
1237
+ private async runCloseOperation(
1238
+ meshName: string,
1239
+ spotId: RoutingId,
1240
+ operation: ZLinkTargetSpotCloseOperation,
1241
+ signal?: AbortSignal,
1242
+ deadline?: Date
1243
+ ): Promise<boolean> {
1244
+ const seal = await this.beginCloseAuthority(meshName, spotId, operation, signal);
1245
+ if (seal === undefined) return false;
1246
+ if (seal !== true) {
1247
+ await this.activationLifecycle.sealForClose(operation.activation, seal);
1248
+ } else {
1249
+ await operation.activation.executionBarrier.waitForStartedTurns(signal);
1250
+ }
1251
+ const closingFailure = await this.activationLifecycle.cleanupClosedActivation(
1252
+ operation.activation,
1253
+ operation.reason,
1254
+ deadline
1255
+ );
1256
+ this.activations.finishClose(meshName, spotId);
1257
+ const intentRecords: unknown[] = [];
1258
+ operation.activation.serial.visitPendingApplication((record) => {
1259
+ const context = record.context as
1260
+ import('./spot-serial-turn-executor').ZLinkSpotApplicationTurnContext | undefined;
1261
+ if (context?.replay !== undefined) intentRecords.push(record);
1262
+ });
1263
+ const hasIntent = intentRecords.length > 0;
1264
+ // Spot messaging §7 step 3: with no Instance intent message waiting, the
1265
+ // release decision also ends this Instance incarnation's admission in this turn.
1266
+ if (!hasIntent && operation.activation.domain.kind === 'instance')
1267
+ operation.activation.serial.closeAdmission();
1268
+ const hostState = this.options.statefulExecution?.hostState();
1269
+ const intentFailure = !hasIntent
1270
+ ? undefined
1271
+ : hostState === ZLinkFrameworkRuntimeState.Draining
1272
+ ? createInternalFrameworkException(
1273
+ ZLinkFrameworkInternalErrorKind.RuntimeShutdown,
1274
+ 'Instance intent cannot continue while the host is draining.'
1275
+ )
1276
+ : hostState === ZLinkFrameworkRuntimeState.Relocating ||
1277
+ hostState === ZLinkFrameworkRuntimeState.Relocated ||
1278
+ this.options.statefulExecution?.admissionOpen() === false ||
1279
+ (operation.activation.executionBarrier.isSealed &&
1280
+ !operation.activation.executionBarrier.isCloseSealed)
1281
+ ? createInternalFrameworkException(
1282
+ ZLinkFrameworkInternalErrorKind.SpotMoving,
1283
+ 'Instance intent cannot continue on an unavailable or relocating owner.'
1284
+ )
1190
1285
  : undefined;
1191
- // Register the close gate before waiting for the current application
1192
- // and activation-authority terminal completions. A close requested from
1193
- // a handler cannot publish Closing until that handler's durable inbox
1194
- // completion has removed the recovery fence.
1195
- const trackedClosePromise = (async () => {
1196
- const waitForApplication = this.options.instanceSpotApplicationQuiescenceProvider?.(
1197
- meshName,
1198
- spotId,
1199
- signal
1200
- );
1201
- if (waitForApplication !== undefined) {
1202
- await waitForApplication;
1203
- }
1204
- const closingAuthority =
1205
- beginAuthorityClose === undefined
1206
- ? undefined
1207
- : await beginAuthorityClose(meshName, spotId);
1208
- if (beginAuthorityClose !== undefined && closingAuthority === undefined) {
1209
- return false;
1210
- }
1211
- const operation = beginClose();
1212
- if (operation === undefined) {
1213
- await closingAuthority?.restoreReady();
1214
- return false;
1286
+ if (
1287
+ operation.reason === ZLinkSpotCloseReason.ExplicitClose &&
1288
+ hasIntent &&
1289
+ intentFailure === undefined &&
1290
+ operation.authority?.reincarnate !== undefined
1291
+ ) {
1292
+ try {
1293
+ await operation.authority.reincarnate(async (authority) => {
1294
+ await this.activationLifecycle.materializeInstance(
1295
+ meshName,
1296
+ authority.stableType,
1297
+ operation.activation.spotType as Type<ZLinkInstanceSpot>,
1298
+ spotId,
1299
+ authority.objectGeneration,
1300
+ signal,
1301
+ operation.activation
1302
+ );
1303
+ });
1304
+ // The new incarnation shares this serial owner and admits membership work again.
1305
+ operation.activation.serial.setLifecycleAdmissionClosed(false);
1306
+ } catch (error) {
1307
+ const initialized = this.activations.resolve(meshName, spotId);
1308
+ if (initialized !== undefined && initialized !== operation.activation) {
1309
+ await this.activationLifecycle.cleanupFailedIncarnation(initialized);
1215
1310
  }
1216
- const closed = await operation.ready;
1217
- if (!closed) await closingAuthority?.restoreReady();
1218
- return closed;
1219
- })().finally(() => {
1220
- if (this.pendingInstanceCloses.get(key) === trackedClosePromise) {
1221
- this.pendingInstanceCloses.delete(key);
1311
+ this.activations.finishClose(meshName, spotId);
1312
+ operation.activation.serial.visitPendingApplication((record) => {
1313
+ const context = record.context as
1314
+ import('./spot-serial-turn-executor').ZLinkSpotApplicationTurnContext | undefined;
1315
+ if (context?.replay !== undefined) record.operation = () => context.replay!(error);
1316
+ });
1317
+ operation.activation.serial.closeAdmission();
1318
+ throw error;
1319
+ }
1320
+ } else {
1321
+ await operation.authority?.release();
1322
+ operation.activation.serial.closeAdmission();
1323
+ if (!operation.activation.executionBarrier.isSealed) {
1324
+ const closed = operation.activation.sealExecution('close');
1325
+ operation.activation.commitExecutionSeal(closed);
1326
+ }
1327
+ }
1328
+ if (operation.reason === ZLinkSpotCloseReason.ExplicitClose) {
1329
+ operation.activation.serial.visitPendingApplication((record) => {
1330
+ const context = record.context as
1331
+ import('./spot-serial-turn-executor').ZLinkSpotApplicationTurnContext | undefined;
1332
+ if (context?.replay !== undefined) {
1333
+ record.operation =
1334
+ intentFailure === undefined ? context.replay : () => context.replay!(intentFailure);
1222
1335
  }
1223
1336
  });
1224
- this.pendingInstanceCloses.set(key, trackedClosePromise);
1225
- if (currentTurn) {
1226
- // The current turn must return before its terminal completion can
1227
- // release the activation recovery fence and allow the durable close
1228
- // CAS. The registered close gate prevents a second admission while
1229
- // that detached close finishes.
1230
- this.options.detachedTaskRunner?.runDetached(
1231
- `instance spot close ${String(spotId)}`,
1232
- async () => {
1233
- await trackedClosePromise;
1234
- }
1235
- );
1236
- if (this.options.detachedTaskRunner === undefined) {
1237
- void trackedClosePromise.catch(() => undefined);
1238
- }
1239
- return true;
1240
- }
1241
- return await trackedClosePromise;
1242
1337
  }
1338
+ this.closeOperations.delete(`${meshName}\0${String(spotId)}`);
1339
+ // An OnClosing failure never changes a Close result; host shutdown alone
1340
+ // reports it as its teardown outcome after cleanup has finished.
1341
+ if (closingFailure !== undefined && operation.reason === ZLinkSpotCloseReason.HostShutdown) {
1342
+ throw closingFailure;
1343
+ }
1344
+ return true;
1345
+ }
1243
1346
 
1244
- const operation = beginClose();
1245
- if (operation === undefined) {
1246
- return false;
1347
+ private async beginCloseAuthority(
1348
+ meshName: string,
1349
+ spotId: RoutingId,
1350
+ operation: ZLinkTargetSpotCloseOperation,
1351
+ signal?: AbortSignal
1352
+ ): Promise<import('../execution').ZLinkExecutionBarrierSeal | true | undefined> {
1353
+ // Spot messaging §4 step 12 with §7 step 1: a Close of any reason begins its
1354
+ // Closing CAS only after the first terminal record of an activated message.
1355
+ await this.options.instanceSpotApplicationQuiescenceProvider?.(meshName, spotId, signal);
1356
+ if (!operation.activation.canClose(operation.reason)) return undefined;
1357
+ if (operation.activation.executionBarrier.isSealed) {
1358
+ throw createInternalFrameworkException(
1359
+ ZLinkFrameworkInternalErrorKind.SpotMoving,
1360
+ `Spot '${String(spotId)}' is sealed for relocation.`,
1361
+ true
1362
+ );
1247
1363
  }
1248
- if (currentTurn) {
1249
- if (operation.started) {
1250
- this.options.detachedTaskRunner?.runDetached(`spot close ${String(spotId)}`, async () => {
1251
- await operation.ready;
1252
- });
1253
- if (this.options.detachedTaskRunner === undefined) {
1254
- void operation.ready.catch(() => undefined);
1364
+ let seal: import('../execution').ZLinkExecutionBarrierSeal | true | undefined;
1365
+ const authorityPromise = Promise.resolve().then(() =>
1366
+ operation.beginAuthority(() => {
1367
+ if (operation.reason === ZLinkSpotCloseReason.ExplicitClose) {
1368
+ operation.activation.serial.setLifecycleAdmissionClosed(true);
1369
+ seal = true;
1370
+ } else {
1371
+ seal = operation.activation.sealExecution('close');
1255
1372
  }
1256
- }
1257
- return true;
1373
+ })
1374
+ );
1375
+ operation.authorityDecision = authorityPromise.then(
1376
+ () => undefined,
1377
+ () => undefined
1378
+ );
1379
+ const authority = await authorityPromise;
1380
+ if (authority === undefined) return undefined;
1381
+ operation.authority = authority;
1382
+ if (seal === undefined) {
1383
+ throw new Error(`Spot '${String(spotId)}' Closing authority did not confirm its commit.`);
1258
1384
  }
1259
- return await operation.ready;
1385
+ return seal;
1260
1386
  }
1261
1387
 
1262
1388
  async executeOnSpot<TSpot extends ZLinkSpot, TResult>(
@@ -1286,10 +1412,6 @@ export class DefaultZLinkSpotManager {
1286
1412
  return this.activations.resolveUnique(spotId) !== undefined;
1287
1413
  }
1288
1414
 
1289
- canCloseUserSpot(meshName: string, spotId: RoutingId): boolean {
1290
- return this.activations.canClose(meshName, spotId);
1291
- }
1292
-
1293
1415
  beginUserSpotPublication(meshName: string, spotId: RoutingId): void {
1294
1416
  this.activations.stage(meshName, spotId);
1295
1417
  }
@@ -1326,15 +1448,19 @@ export class DefaultZLinkSpotManager {
1326
1448
  spotId: RoutingId,
1327
1449
  actor: ZLinkActor,
1328
1450
  request: Message,
1329
- commit: (
1330
- spot: ZLinkSpot
1331
- ) => Promise<ZLinkActorJoinRollback | void> | ZLinkActorJoinRollback | void,
1451
+ commit: (spot: ZLinkSpot) => Promise<void> | void,
1332
1452
  signal?: AbortSignal,
1333
1453
  leaveSource?: () => Promise<void>,
1334
1454
  contentType = 'application/json'
1335
1455
  ): Promise<ZLinkSpotActorJoinResult> {
1336
1456
  const meshName = this.activations.resolveUnique(spotId)?.meshName;
1337
1457
  this.options.admission?.requireRequest('Actor join admission', meshName);
1458
+ if (meshName !== undefined && this.isSpotClosing(meshName, spotId)) {
1459
+ throw createInternalFrameworkException(
1460
+ ZLinkFrameworkInternalErrorKind.RequestRejected,
1461
+ `Spot '${String(spotId)}' is closing.`
1462
+ );
1463
+ }
1338
1464
  return await this.actorMembership.admitActorJoin(
1339
1465
  spotId,
1340
1466
  actor,
@@ -1562,14 +1688,7 @@ export class DefaultZLinkSpotManager {
1562
1688
  record.reply(encodeChannelReplyParts(envelope.header, response, codecs))
1563
1689
  );
1564
1690
  } catch (error) {
1565
- requireMeshSpotReply(
1566
- record.reply(
1567
- encodeChannelErrorReplyParts(
1568
- envelope.header,
1569
- error instanceof Error ? error.message : String(error)
1570
- )
1571
- )
1572
- );
1691
+ requireMeshSpotReply(record.reply(encodeChannelErrorReplyParts(envelope.header, error)));
1573
1692
  }
1574
1693
  }
1575
1694
 
@@ -1580,7 +1699,7 @@ export class DefaultZLinkSpotManager {
1580
1699
  let target = this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId);
1581
1700
  if (target === undefined) return;
1582
1701
  for (;;) {
1583
- const current = this.activations.resolve(meshName, spotId);
1702
+ const current = this.resolveApplicationActivation(spotId, meshName);
1584
1703
  if (
1585
1704
  current !== undefined &&
1586
1705
  current.objectGeneration === target.objectGeneration &&
@@ -1634,7 +1753,7 @@ export class DefaultZLinkSpotManager {
1634
1753
  );
1635
1754
  try {
1636
1755
  await this.ensureInstanceApplicationActivation(meshName, spotId);
1637
- const activation = this.activations.resolve(meshName, spotId);
1756
+ const activation = this.resolveApplicationActivation(spotId, meshName);
1638
1757
  if (activation === undefined || activation.domain.kind !== 'instance') {
1639
1758
  throw new ZLinkConfigurationException(
1640
1759
  `MeshNode Instance Spot target '${String(spotId)}' is not active.`
@@ -1659,12 +1778,39 @@ export class DefaultZLinkSpotManager {
1659
1778
  channelName: envelope.header.channelName,
1660
1779
  contentType: envelope.header.contentType,
1661
1780
  awaitFirstHandlerTurn: record.kind === ReceiveKind.InstanceSpotActivation,
1781
+ activationRecord: record,
1782
+ onOneWayError:
1783
+ this.options.dispatchErrors?.captureEnabled() === true
1784
+ ? (error: unknown) =>
1785
+ this.reportInstanceDispatchFailure(
1786
+ meshName,
1787
+ spotId,
1788
+ record,
1789
+ envelope,
1790
+ false,
1791
+ error
1792
+ )
1793
+ : undefined,
1662
1794
  workOptions: zlinkSerialWorkOptions(
1663
1795
  envelope.payload.byteLength,
1664
1796
  record.applicationMetadata?.byteLength ??
1665
1797
  zlinkMetadataByteLength(envelope.header.metadata)
1666
1798
  )
1667
1799
  };
1800
+ // Spot messaging §7 step 3: an Instance intent request that reaches an
1801
+ // incarnation whose Close ended admission is refused before admission
1802
+ // with the owner fence terminal, so its caller re-reads authority.
1803
+ const instanceIntent =
1804
+ record.activationRecord?.activation === 'missing' ||
1805
+ (record.activationRecord?.activation === 'ready' &&
1806
+ record.activationRecord.instanceIntent);
1807
+ const refusal = activation.serial.applicationAdmissionRefusal(instanceIntent === true);
1808
+ if (request && refusal !== undefined && record.replyFailure !== undefined) {
1809
+ this.reportInstanceDispatchFailure(meshName, spotId, record, envelope, request, refusal);
1810
+ const terminal = internalFrameworkWireReply(refusal);
1811
+ requireMeshSpotReply(record.replyFailure(terminal.terminalResult, terminal.failureCode));
1812
+ return;
1813
+ }
1668
1814
  this.traceInstanceMessage(
1669
1815
  ZLinkMessageFlowOutcome.Admitted,
1670
1816
  meshName,
@@ -1729,7 +1875,8 @@ export class DefaultZLinkSpotManager {
1729
1875
  target?.stableType
1730
1876
  );
1731
1877
  } catch (error) {
1732
- const reason = instanceDispatchErrorReason(error);
1878
+ this.reportInstanceDispatchFailure(meshName, spotId, record, envelope, request, error);
1879
+ const reason = dispatchReasonFromError(error);
1733
1880
  if (!request) {
1734
1881
  this.traceInstanceMessage(
1735
1882
  ZLinkMessageFlowOutcome.Dropped,
@@ -1743,36 +1890,42 @@ export class DefaultZLinkSpotManager {
1743
1890
  );
1744
1891
  return;
1745
1892
  }
1746
- this.options.dispatchErrors?.report({
1747
- surface: ZLinkDispatchErrorSurface.InstanceSpot,
1748
- messageKind: ZLinkDispatchMessageKind.Request,
1749
- packetName: envelope.packetName,
1750
- channelName: envelope.header.channelName,
1751
- meshName,
1752
- correlationId: envelope.header.correlationId ?? undefined,
1753
- sourceRid: record.sourceNodeRid === null ? undefined : String(record.sourceNodeRid),
1754
- spotId: String(spotId),
1755
- instanceSpotType: this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId)
1756
- ?.stableType,
1757
- activationState: 'closing',
1758
- flowId: envelope.header.flowId,
1759
- flowOrigin: envelope.header.flowOrigin,
1760
- reason,
1761
- action: ZLinkDispatchErrorAction.ReplyError,
1762
- error
1763
- });
1764
- requireMeshSpotReply(
1765
- record.reply(
1766
- encodeChannelErrorReplyParts(
1767
- envelope.header,
1768
- error instanceof Error ? error.message : String(error)
1769
- )
1770
- )
1771
- );
1893
+
1894
+ requireMeshSpotReply(record.reply(encodeChannelErrorReplyParts(envelope.header, error)));
1772
1895
  }
1773
1896
  });
1774
1897
  }
1775
1898
 
1899
+ private reportInstanceDispatchFailure(
1900
+ meshName: string,
1901
+ spotId: RoutingId,
1902
+ record: ReceiveRecord,
1903
+ envelope: ReturnType<typeof decodeChannelEnvelope>,
1904
+ request: boolean,
1905
+ error: unknown
1906
+ ): void {
1907
+ const reporter = this.options.dispatchErrors;
1908
+ if (reporter?.captureEnabled() !== true) return;
1909
+ reporter.report({
1910
+ surface: ZLinkDispatchErrorSurface.InstanceSpot,
1911
+ messageKind: request ? ZLinkDispatchMessageKind.Request : ZLinkDispatchMessageKind.Send,
1912
+ packetName: envelope.packetName,
1913
+ channelName: envelope.header.channelName,
1914
+ meshName,
1915
+ correlationId: envelope.header.correlationId ?? undefined,
1916
+ sourceRid: record.sourceNodeRid === null ? undefined : String(record.sourceNodeRid),
1917
+ spotId: String(spotId),
1918
+ instanceSpotType: this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId)
1919
+ ?.stableType,
1920
+ activationState: 'closing',
1921
+ flowId: envelope.header.flowId,
1922
+ flowOrigin: envelope.header.flowOrigin,
1923
+ reason: dispatchReasonFromError(error),
1924
+ action: request ? ZLinkDispatchErrorAction.ReplyError : ZLinkDispatchErrorAction.Drop,
1925
+ error
1926
+ });
1927
+ }
1928
+
1776
1929
  private traceInstanceMessage(
1777
1930
  outcome: ZLinkMessageFlowOutcome,
1778
1931
  meshName: string,
@@ -1825,9 +1978,6 @@ export class DefaultZLinkSpotManager {
1825
1978
  throw new ZLinkConfigurationException('MeshNode Actor record is missing its Actor owner.');
1826
1979
  }
1827
1980
  const request = record.kind === ReceiveKind.ActorRequest;
1828
- if (record.sourceBindingGeneration > 0n) {
1829
- this.options.actorBindingGenerationObserver?.(actor.actorId, record.sourceBindingGeneration);
1830
- }
1831
1981
  const resolvedOwner = this.options.actorDispatchOwnerResolver?.(actor.actorId);
1832
1982
  const resolvedActorRef = resolvedOwner?.actorRef ?? {
1833
1983
  actorId: actor.actorId,
@@ -1918,10 +2068,7 @@ export class DefaultZLinkSpotManager {
1918
2068
  record.reply(
1919
2069
  this.encodeMeshActorReply(record.parts[0], ZLinkStreamMessageKind.Error, {
1920
2070
  message: error instanceof Error ? error.message : String(error),
1921
- kind:
1922
- error instanceof ZLinkFrameworkException
1923
- ? error.kind
1924
- : ZLinkFrameworkErrorKind.InternalFailure
2071
+ kind: spotActorFailureKind(error)
1925
2072
  })
1926
2073
  )
1927
2074
  );
@@ -1932,6 +2079,54 @@ export class DefaultZLinkSpotManager {
1932
2079
  meshName: string,
1933
2080
  owner: ReadyRecord,
1934
2081
  record: ReceiveRecord
2082
+ ): Promise<void> {
2083
+ const spotId = owner.spotId as unknown as RoutingId | null;
2084
+ const activation = spotId === null ? undefined : this.activations.resolve(meshName, spotId);
2085
+ const replyState = { targetCommitPublished: false };
2086
+ try {
2087
+ if (
2088
+ record.kindData?.kind === 'actorControl' &&
2089
+ record.kindData.canonicalActorJoin !== undefined
2090
+ ) {
2091
+ const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
2092
+ if (
2093
+ spotId !== null && entrySpotId !== undefined && String(spotId) === String(entrySpotId)
2094
+ ? this.options.dispatchEntryActorJoin === undefined
2095
+ : activation === undefined
2096
+ ) {
2097
+ throw createInternalFrameworkException(
2098
+ ZLinkFrameworkInternalErrorKind.RouteNotConnected,
2099
+ `Spot '${String(spotId)}' is not active on this node.`
2100
+ );
2101
+ }
2102
+ }
2103
+ if (activation?.domain.kind === 'user') {
2104
+ await activation.serial.executeLifecycleOperation(() =>
2105
+ this.dispatchMeshActorJoinCore(meshName, owner, record, replyState)
2106
+ );
2107
+ return;
2108
+ }
2109
+ await this.dispatchMeshActorJoinCore(meshName, owner, record, replyState);
2110
+ } catch (error) {
2111
+ if (replyState.targetCommitPublished || record.replyFailure === undefined) throw error;
2112
+ const failure =
2113
+ error instanceof ZLinkFrameworkException
2114
+ ? error
2115
+ : createInternalFrameworkException(
2116
+ ZLinkFrameworkInternalErrorKind.RequestFailed,
2117
+ 'Actor Join target admission failed.',
2118
+ error
2119
+ );
2120
+ const terminal = internalFrameworkWireReply(failure);
2121
+ requireMeshSpotReply(record.replyFailure(terminal.terminalResult, terminal.failureCode));
2122
+ }
2123
+ }
2124
+
2125
+ private async dispatchMeshActorJoinCore(
2126
+ meshName: string,
2127
+ owner: ReadyRecord,
2128
+ record: ReceiveRecord,
2129
+ replyState: { targetCommitPublished: boolean }
1935
2130
  ): Promise<void> {
1936
2131
  const spotId = owner.spotId as unknown as RoutingId | null;
1937
2132
  const control = record.kindData;
@@ -1996,14 +2191,10 @@ export class DefaultZLinkSpotManager {
1996
2191
  admissionRecord = provisional.record;
1997
2192
  canonicalAdmissionCreated = provisional.created;
1998
2193
  try {
2194
+ releaseApplicationJobPermitBeforeHandler();
1999
2195
  canonicalActorType = (await resolver({ actorId, ...control.canonicalActorJoin })).actorType;
2000
2196
  } catch (error) {
2001
2197
  this.formalRemoteActorAdmissions.fail(control.canonicalActorJoin.handoffId, error);
2002
- if (error instanceof ZLinkFrameworkException && record.replyFailure !== undefined) {
2003
- const terminal = internalFrameworkWireReply(error);
2004
- requireMeshSpotReply(record.replyFailure(terminal.terminalResult, terminal.failureCode));
2005
- return;
2006
- }
2007
2198
  throw error;
2008
2199
  }
2009
2200
  }
@@ -2027,12 +2218,11 @@ export class DefaultZLinkSpotManager {
2027
2218
  let ownedCallbackRequest: Message | undefined;
2028
2219
  let materialized = false;
2029
2220
  let reply: Message | undefined;
2030
- let deferredJoinRoot: ZLinkDeferredJoinAcceptedRoot | undefined;
2221
+ let deferredJoinCompletion: ZLinkDeferredJoinCompletion | undefined;
2031
2222
  let preparedTransferState: Message | undefined;
2032
2223
  let admissionOutcome: ZLinkFormalRemoteActorAdmissionResult | undefined;
2033
2224
  let accepted = false;
2034
2225
  let committedAdmissionReplay = isRemoteCommit && admissionRecord?.state === 'committed';
2035
- let targetCommitPublished: boolean | undefined;
2036
2226
  const actorJoinIsCurrent = (): boolean =>
2037
2227
  (record.deadlineUnixMs === undefined || record.deadlineUnixMs > BigInt(Date.now())) &&
2038
2228
  (record.isPending?.() ?? true);
@@ -2093,14 +2283,12 @@ export class DefaultZLinkSpotManager {
2093
2283
  if (canonicalAdmissionCreated) {
2094
2284
  if (targetsEntrySpot) {
2095
2285
  admissionOutcome = {
2096
- accepted: this.options.dispatchEntryActorJoin !== undefined,
2286
+ accepted: true,
2097
2287
  actorRef
2098
2288
  };
2099
- } else if (activation === undefined) {
2100
- admissionOutcome = { accepted: false, actorRef };
2101
2289
  } else {
2102
- const response: ZLinkSpotActorJoinResult = await activation.serial.execute(async () =>
2103
- activation.spot.onActorJoin(
2290
+ const response: ZLinkSpotActorJoinResult = await activation!.serial.execute(async () =>
2291
+ activation!.spot.onActorJoin(
2104
2292
  actorRef.actorId,
2105
2293
  wrapFrameworkPayloadMessage(
2106
2294
  callbackRequest!,
@@ -2176,8 +2364,8 @@ export class DefaultZLinkSpotManager {
2176
2364
  transferRequest.completionOperationId !== undefined &&
2177
2365
  this.options.actorTransferRuntime !== undefined
2178
2366
  ) {
2179
- deferredJoinRoot =
2180
- await this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
2367
+ deferredJoinCompletion =
2368
+ this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
2181
2369
  actorId,
2182
2370
  transferRequest.completionOperationId,
2183
2371
  actorRef,
@@ -2187,7 +2375,7 @@ export class DefaultZLinkSpotManager {
2187
2375
  admissionOutcome = {
2188
2376
  accepted: this.options.dispatchEntryActorJoin !== undefined,
2189
2377
  actorRef,
2190
- ...(deferredJoinRoot === undefined ? {} : { deferredJoinRoot })
2378
+ ...(deferredJoinCompletion === undefined ? {} : { deferredJoinCompletion })
2191
2379
  };
2192
2380
  } else if (activation === undefined) {
2193
2381
  admissionOutcome = { accepted: false, actorRef };
@@ -2220,8 +2408,8 @@ export class DefaultZLinkSpotManager {
2220
2408
  transferRequest.completionOperationId !== undefined &&
2221
2409
  this.options.actorTransferRuntime !== undefined
2222
2410
  ) {
2223
- deferredJoinRoot =
2224
- await this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
2411
+ deferredJoinCompletion =
2412
+ this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
2225
2413
  actorId,
2226
2414
  transferRequest.completionOperationId,
2227
2415
  actorRef,
@@ -2240,7 +2428,7 @@ export class DefaultZLinkSpotManager {
2240
2428
  admissionOutcome = {
2241
2429
  accepted: response.accepted,
2242
2430
  actorRef,
2243
- ...(deferredJoinRoot === undefined ? {} : { deferredJoinRoot }),
2431
+ ...(deferredJoinCompletion === undefined ? {} : { deferredJoinCompletion }),
2244
2432
  ...(encodedReply === undefined
2245
2433
  ? {}
2246
2434
  : {
@@ -2277,7 +2465,7 @@ export class DefaultZLinkSpotManager {
2277
2465
  if ('error' in admissionOutcome) {
2278
2466
  throw admissionOutcome.error;
2279
2467
  }
2280
- deferredJoinRoot = admissionOutcome.deferredJoinRoot;
2468
+ deferredJoinCompletion = admissionOutcome.deferredJoinCompletion;
2281
2469
  }
2282
2470
  if (
2283
2471
  actor === undefined &&
@@ -2361,7 +2549,7 @@ export class DefaultZLinkSpotManager {
2361
2549
  transferRequest?.completionOperationId !== undefined &&
2362
2550
  this.options.actorTransferRuntime !== undefined
2363
2551
  ) {
2364
- deferredJoinRoot = await this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
2552
+ deferredJoinCompletion = this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
2365
2553
  actorId,
2366
2554
  transferRequest.completionOperationId,
2367
2555
  actorRef,
@@ -2424,21 +2612,6 @@ export class DefaultZLinkSpotManager {
2424
2612
  return;
2425
2613
  }
2426
2614
  }
2427
- if (
2428
- accepted &&
2429
- transferRequest !== undefined &&
2430
- this.options.actorTransferRuntime !== undefined &&
2431
- !isRemoteAdmission
2432
- ) {
2433
- // A lightweight Core actor-join notification can create the Actor
2434
- // before the formal transfer request reaches this branch. Preserve
2435
- // the full relocation fence in that race so a later Session bind
2436
- // refresh cannot erase the seal or accepted journal.
2437
- this.options.actorTransferRuntime.rememberRoutedActorTransferTarget(
2438
- actorId,
2439
- transferRequest.remoteBoundSessionTarget
2440
- );
2441
- }
2442
2615
  if (
2443
2616
  accepted &&
2444
2617
  actor !== undefined &&
@@ -2451,7 +2624,8 @@ export class DefaultZLinkSpotManager {
2451
2624
  spotId,
2452
2625
  transferId: transferRequest.transferId,
2453
2626
  handoffBacklog: transferRequest.handoffBacklog,
2454
- deferredJoinRoot
2627
+ deferredJoinCompletion,
2628
+ sealedSession: transferRequest.remoteBoundSessionTarget
2455
2629
  });
2456
2630
  if (isRemoteCommit && admissionRecord !== undefined) {
2457
2631
  this.formalRemoteActorAdmissions.markCommitted(transferRequest.transferId, actor);
@@ -2471,7 +2645,7 @@ export class DefaultZLinkSpotManager {
2471
2645
  // Core commits the target membership while it accepts this reply.
2472
2646
  // From this call onward a later callback/transport failure is
2473
2647
  // post-commit and must not roll the materialized Actor back.
2474
- targetCommitPublished = true;
2648
+ replyState.targetCommitPublished = true;
2475
2649
  }
2476
2650
  requireMeshSpotReply(joinReplyResult);
2477
2651
  return true;
@@ -2496,60 +2670,85 @@ export class DefaultZLinkSpotManager {
2496
2670
  if (!replyActorJoin()) return;
2497
2671
  const commitEntryTransfer = async (): Promise<void> => {
2498
2672
  try {
2499
- await this.options.dispatchEntryActorJoin?.(meshName, entryActor, []);
2500
- } finally {
2501
- this.formalRemoteTransfers.completeTargetLifecycle(
2502
- entryActor.context.actorId,
2503
- pendingTransfer.transferId
2504
- );
2505
- }
2506
- const sourceLeaveSubmitted = await pendingTransfer.sourceLeaveSubmitted;
2507
- if (!sourceLeaveSubmitted) {
2508
- throw new Error(
2509
- `Actor '${entryActor.context.actorId}' source authority commit failed before leave submission.`
2510
- );
2511
- }
2512
- const handoffResults = await replayActorHandoffBacklog(
2513
- pendingTransfer.handoffBacklog,
2514
- async (parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef) => {
2515
- if (this.options.dispatchEntryActorPacket === undefined) {
2516
- throw new Error(
2517
- 'Entry Spot saved handoff replay requires its Actor packet runtime.'
2518
- );
2519
- }
2520
- return await this.options.dispatchEntryActorPacket(
2673
+ try {
2674
+ await this.options.dispatchEntryActorJoin?.(meshName, entryActor, []);
2675
+ } finally {
2676
+ this.formalRemoteTransfers.completeTargetLifecycle(
2521
2677
  entryActor.context.actorId,
2522
- parts,
2523
- returnResponse,
2524
- remoteBoundSessionTarget,
2525
- fallbackActorRef
2678
+ pendingTransfer.transferId
2526
2679
  );
2527
- },
2528
- (index) =>
2529
- this.options.runtimeEventPublisher?.publish({
2530
- sourceName: 'zlink.framework.actor-handoff',
2531
- timestamp: new Date(),
2532
- marker: 'backlog_enqueued',
2533
- actorId: entryActor.context.actorId,
2534
- index
2535
- })
2536
- );
2537
- const failedHandoff = handoffResults.find((result) => !result.ok);
2538
- if (failedHandoff !== undefined) {
2539
- throw new Error(
2540
- `Actor '${entryActor.context.actorId}' saved Entry handoff packet ` +
2541
- `${failedHandoff.index} failed: ${failedHandoff.error ?? 'unknown error'}.`
2680
+ }
2681
+ const sourceLeaveSubmitted = await pendingTransfer.sourceLeaveSubmitted;
2682
+ if (!sourceLeaveSubmitted) {
2683
+ throw new Error(
2684
+ `Actor '${entryActor.context.actorId}' source authority commit failed before leave submission.`
2685
+ );
2686
+ }
2687
+ const handoffResults = await replayActorHandoffBacklog(
2688
+ pendingTransfer.handoffBacklog,
2689
+ async (parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef) => {
2690
+ if (this.options.dispatchEntryActorPacket === undefined) {
2691
+ throw new Error(
2692
+ 'Entry Spot saved handoff replay requires its Actor packet runtime.'
2693
+ );
2694
+ }
2695
+ return await this.options.dispatchEntryActorPacket(
2696
+ entryActor.context.actorId,
2697
+ parts,
2698
+ returnResponse,
2699
+ remoteBoundSessionTarget,
2700
+ fallbackActorRef
2701
+ );
2702
+ },
2703
+ (index) =>
2704
+ this.options.runtimeEventPublisher?.publish({
2705
+ sourceName: 'zlink.framework.actor-handoff',
2706
+ timestamp: new Date(),
2707
+ marker: 'backlog_enqueued',
2708
+ actorId: entryActor.context.actorId,
2709
+ index
2710
+ })
2711
+ );
2712
+ const failedHandoff = handoffResults.find((result) => !result.ok);
2713
+ if (failedHandoff !== undefined) {
2714
+ throw new Error(
2715
+ `Actor '${entryActor.context.actorId}' saved Entry handoff packet ` +
2716
+ `${failedHandoff.index} failed: ${diagnosticTextOrAbsent(failedHandoff.error)}.`
2717
+ );
2718
+ }
2719
+ } catch (error) {
2720
+ const completion = pendingTransfer.deferredJoinCompletion;
2721
+ if (completion !== undefined) {
2722
+ await this.options.actorTransferRuntime?.deliverDeferredJoinCompletion(
2723
+ {
2724
+ ...completion,
2725
+ status: 'failed',
2726
+ kind: spotActorFailureKind(error)
2727
+ },
2728
+ entryActor,
2729
+ completion.actor,
2730
+ (operation) =>
2731
+ this.options.executeEntryActor!(meshName, entryActor.context.actorId, operation)
2732
+ );
2733
+ }
2734
+ throw error;
2735
+ }
2736
+ const completion = pendingTransfer.deferredJoinCompletion;
2737
+ if (completion !== undefined) {
2738
+ await this.options.actorTransferRuntime?.deliverDeferredJoinCompletion(
2739
+ completion,
2740
+ entryActor,
2741
+ completion.actor,
2742
+ (operation) =>
2743
+ this.options.executeEntryActor!(meshName, entryActor.context.actorId, operation)
2542
2744
  );
2543
2745
  }
2544
2746
  this.formalRemoteTransfers.delete(entryActor.context.actorId);
2545
2747
  };
2546
- this.options.detachedTaskRunner?.runDetached(
2748
+ this.options.detachedTaskRunner.runDetached(
2547
2749
  `actor Entry Spot transfer ${entryActor.context.actorId}`,
2548
2750
  commitEntryTransfer
2549
2751
  );
2550
- if (this.options.detachedTaskRunner === undefined) {
2551
- void commitEntryTransfer().catch(() => undefined);
2552
- }
2553
2752
  }
2554
2753
  } else {
2555
2754
  if (!replyActorJoin()) return;
@@ -2558,13 +2757,10 @@ export class DefaultZLinkSpotManager {
2558
2757
  if (control.canonicalActorJoin !== undefined) {
2559
2758
  this.formalRemoteActorAdmissions.fail(control.canonicalActorJoin.handoffId, error);
2560
2759
  }
2561
- if (deferredJoinRoot !== undefined && targetCommitPublished !== true) {
2562
- await this.options.actorTransferRuntime?.discardDeferredJoinAccepted(deferredJoinRoot);
2563
- }
2564
- if (targetCommitPublished !== true) {
2760
+ if (!replyState.targetCommitPublished) {
2565
2761
  this.formalRemoteTransfers.delete(actorId);
2566
2762
  }
2567
- if (materialized && targetCommitPublished !== true) {
2763
+ if (materialized && !replyState.targetCommitPublished) {
2568
2764
  await this.options.actorTransferRuntime?.rollbackRoutedActor(actor!);
2569
2765
  }
2570
2766
  throw error;
@@ -2580,6 +2776,42 @@ export class DefaultZLinkSpotManager {
2580
2776
  meshName: string,
2581
2777
  owner: ReadyRecord,
2582
2778
  record: ReceiveRecord
2779
+ ): Promise<void> {
2780
+ const spotId = owner.spotId as unknown as RoutingId | null;
2781
+ const activation = spotId === null ? undefined : this.activations.resolve(meshName, spotId);
2782
+ if (activation?.domain.kind === 'user') {
2783
+ const transfer = { terminal: undefined as Promise<void> | undefined };
2784
+ const operation = activation.serial.executeLifecycleOperation(async () => {
2785
+ await this.dispatchMeshSpotControlCore(meshName, owner, record, (terminal) => {
2786
+ transfer.terminal = terminal;
2787
+ });
2788
+ await transfer.terminal;
2789
+ });
2790
+ const control = record.kindData;
2791
+ const actorId = control?.kind === 'actorControl' ? control.currentActor?.actorId : undefined;
2792
+ if (
2793
+ control?.kind === 'actorControl' &&
2794
+ control.lifecycleKind === ActorLifecycleKind.Joined &&
2795
+ actorId !== undefined &&
2796
+ this.formalRemoteTransfers.get(actorId) !== undefined
2797
+ ) {
2798
+ this.options.detachedTaskRunner.runDetached(
2799
+ `actor transfer target commit ${actorId}`,
2800
+ async () => await operation
2801
+ );
2802
+ return;
2803
+ }
2804
+ await operation;
2805
+ return;
2806
+ }
2807
+ await this.dispatchMeshSpotControlCore(meshName, owner, record);
2808
+ }
2809
+
2810
+ private async dispatchMeshSpotControlCore(
2811
+ meshName: string,
2812
+ owner: ReadyRecord,
2813
+ record: ReceiveRecord,
2814
+ onDetachedTerminal?: (terminal: Promise<void>) => void
2583
2815
  ): Promise<void> {
2584
2816
  const spotId = owner.spotId as unknown as RoutingId | null;
2585
2817
  const control = record.kindData;
@@ -2664,8 +2896,8 @@ export class DefaultZLinkSpotManager {
2664
2896
  await activation.spot.onJoinedActor(actor);
2665
2897
  };
2666
2898
  const completePublicJoin = async (): Promise<void> => {
2667
- const deferredJoinRoot = pendingTransfer?.deferredJoinRoot;
2668
- if (deferredJoinRoot !== undefined) {
2899
+ const deferredJoinCompletion = pendingTransfer?.deferredJoinCompletion;
2900
+ if (deferredJoinCompletion !== undefined) {
2669
2901
  const currentRef =
2670
2902
  this.options.actorTransferRuntime === undefined
2671
2903
  ? null
@@ -2675,8 +2907,8 @@ export class DefaultZLinkSpotManager {
2675
2907
  `Actor '${actor.context.actorId}' has no target ref for deferred Join completion.`
2676
2908
  );
2677
2909
  }
2678
- await this.options.actorTransferRuntime?.commitAndDeliverDeferredJoinAccepted(
2679
- deferredJoinRoot,
2910
+ await this.options.actorTransferRuntime?.deliverDeferredJoinCompletion(
2911
+ deferredJoinCompletion,
2680
2912
  actor,
2681
2913
  currentRef,
2682
2914
  (operation) =>
@@ -2710,7 +2942,7 @@ export class DefaultZLinkSpotManager {
2710
2942
  if (failedHandoff !== undefined) {
2711
2943
  throw new Error(
2712
2944
  `Actor '${actor.context.actorId}' saved handoff packet ` +
2713
- `${failedHandoff.index} failed: ${failedHandoff.error ?? 'unknown error'}.`
2945
+ `${failedHandoff.index} failed: ${diagnosticTextOrAbsent(failedHandoff.error)}.`
2714
2946
  );
2715
2947
  }
2716
2948
  // Spec 15 §4.2 relocation temporary queue: arrivals parked at
@@ -2724,13 +2956,17 @@ export class DefaultZLinkSpotManager {
2724
2956
  // the Session binding aggregate after this boundary.
2725
2957
  this.formalRemoteTransfers.delete(actor.context.actorId);
2726
2958
  }
2959
+ const sealedSession = pendingTransfer?.sealedSession;
2727
2960
  const updateBoundSessionRoute = async (): Promise<void> => {
2728
- await this.options.actorTransferRuntime?.publishRoutedActorOwnership(actor);
2961
+ await this.options.actorTransferRuntime?.publishRoutedActorOwnership(
2962
+ actor,
2963
+ sealedSession
2964
+ );
2729
2965
  await this.options.actorTransferRuntime?.openRoutedActorSession(actor);
2730
2966
  };
2731
- // Session routing is an independent post-Ready branch. Callback
2732
- // sends are retained by the Session owner seal until this converges.
2733
- if (pendingTransfer !== undefined && this.options.detachedTaskRunner !== undefined) {
2967
+ // Session routing is an independent post-Ready branch. The Session
2968
+ // owner submits current-binding pushes while the route seal remains installed.
2969
+ if (pendingTransfer !== undefined) {
2734
2970
  this.options.detachedTaskRunner.runDetached(
2735
2971
  `actor transfer Session route ${actor.context.actorId}`,
2736
2972
  updateBoundSessionRoute
@@ -2760,12 +2996,14 @@ export class DefaultZLinkSpotManager {
2760
2996
  // them only after the lifecycle turn above has been released.
2761
2997
  await completeTargetReady();
2762
2998
  };
2763
- this.options.detachedTaskRunner?.runDetached(
2764
- `actor transfer target commit ${actor.context.actorId}`,
2765
- resume
2766
- );
2767
- if (this.options.detachedTaskRunner === undefined) {
2768
- void resume().catch(() => undefined);
2999
+ const terminal = resume();
3000
+ if (onDetachedTerminal !== undefined) {
3001
+ onDetachedTerminal(terminal);
3002
+ } else {
3003
+ this.options.detachedTaskRunner.runDetached(
3004
+ `actor transfer target commit ${actor.context.actorId}`,
3005
+ async () => await terminal
3006
+ );
2769
3007
  }
2770
3008
  return;
2771
3009
  }
@@ -2832,43 +3070,64 @@ export class DefaultZLinkSpotManager {
2832
3070
  const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
2833
3071
  const targetsEntry =
2834
3072
  entrySpotId !== undefined && String(admission.admission.spotId) === String(entrySpotId);
2835
- if (targetsEntry) {
2836
- await this.options.dispatchEntryActorJoin?.(meshName, actor, []);
2837
- } else {
2838
- const activation = this.activations.resolve(meshName, admission.admission.spotId);
2839
- if (activation === undefined) {
2840
- throw new Error(`Actor Join relocation '${relocationId}' target Spot is not active.`);
3073
+ const activation = targetsEntry
3074
+ ? undefined
3075
+ : this.activations.resolve(meshName, admission.admission.spotId);
3076
+ let lifecycleFailure: { readonly error: unknown } | undefined;
3077
+ try {
3078
+ if (targetsEntry) {
3079
+ await this.options.dispatchEntryActorJoin?.(meshName, actor, []);
3080
+ } else {
3081
+ if (activation === undefined) {
3082
+ throw new Error(`Actor Join relocation '${relocationId}' target Spot is not active.`);
3083
+ }
3084
+ await activation.serial.execute(() => activation.spot.onJoinedActor(actor));
2841
3085
  }
2842
- await activation.serial.execute(() => activation.spot.onJoinedActor(actor));
3086
+ } catch (error) {
3087
+ lifecycleFailure = { error };
2843
3088
  }
2844
- await submitSourceLeave(admission.admission.actorRef.nodeRid);
2845
- if (outcome.deferredJoinRoot !== undefined && this.options.actorTransferRuntime !== undefined) {
3089
+ if (lifecycleFailure === undefined) {
3090
+ const sourceLeave = submitSourceLeave(admission.admission.actorRef.nodeRid);
3091
+ this.options.detachedTaskRunner.runDetached(
3092
+ `actor Join source leave ${actor.context.actorId}`,
3093
+ () => sourceLeave
3094
+ );
3095
+ }
3096
+ if (
3097
+ outcome.deferredJoinCompletion !== undefined &&
3098
+ this.options.actorTransferRuntime !== undefined
3099
+ ) {
2846
3100
  const submitMailbox = targetsEntry
2847
3101
  ? <T>(operation: () => Promise<T>): Promise<T> => operation()
2848
3102
  : <T>(operation: () => Promise<T>): Promise<T> => {
2849
- const activation = this.activations.resolve(meshName, admission.admission.spotId);
2850
3103
  if (activation === undefined) {
2851
3104
  throw new Error(`Actor Join relocation '${relocationId}' target mailbox is missing.`);
2852
3105
  }
2853
3106
  return activation.executeActor(actor.context.actorId, operation);
2854
3107
  };
2855
- await this.options.actorTransferRuntime.commitAndDeliverDeferredJoinAccepted(
2856
- outcome.deferredJoinRoot,
3108
+ await this.options.actorTransferRuntime.deliverDeferredJoinCompletion(
3109
+ lifecycleFailure === undefined
3110
+ ? outcome.deferredJoinCompletion
3111
+ : {
3112
+ ...outcome.deferredJoinCompletion,
3113
+ status: 'failed',
3114
+ kind: spotActorFailureKind(lifecycleFailure.error)
3115
+ },
2857
3116
  actor,
2858
3117
  actorRef,
2859
3118
  submitMailbox,
2860
3119
  signal
2861
3120
  );
2862
3121
  }
3122
+ if (lifecycleFailure !== undefined) throw lifecycleFailure.error;
2863
3123
  this.formalRemoteActorAdmissions.markCommitted(relocationId, actor);
2864
3124
  return true;
2865
3125
  }
2866
3126
 
2867
3127
  async restoreCanonicalActorJoinRecovery(
2868
3128
  recovery: CanonicalActorJoinRecovery,
2869
- signal?: AbortSignal,
2870
- canonicalInventoryDigest?: string
2871
- ): Promise<ZLinkDeferredJoinAcceptedRoot | undefined> {
3129
+ signal?: AbortSignal
3130
+ ): Promise<void> {
2872
3131
  throwIfAborted(signal);
2873
3132
  const admission = this.formalRemoteActorAdmissions.get(recovery.request.handoffId);
2874
3133
  if (admission === undefined) {
@@ -2930,24 +3189,24 @@ export class DefaultZLinkSpotManager {
2930
3189
  }
2931
3190
  // Command 28 carries a present reply in one outer framework-multipart
2932
3191
  // part. The accepted target admission still owns the inner typed content
2933
- // type, which the durable completion must retain for application decode.
3192
+ // type, which the process-local completion keeps for application decode.
2934
3193
  const admittedContentType =
2935
3194
  admittedReply.byteLength === 0 ? recovery.replyContentType : outcome.replyContentType;
2936
3195
  const transfer = this.options.actorTransferRuntime;
2937
3196
  if (transfer === undefined) {
2938
3197
  throw new Error('Canonical Actor Join recovery requires the Actor transfer runtime.');
2939
3198
  }
2940
- const deferred = await transfer.prepareDeferredJoinAccepted(
3199
+ const deferred = transfer.prepareDeferredJoinAccepted(
2941
3200
  recovery.request.actorId,
2942
3201
  recovery.operationId,
2943
3202
  admitted.actorRef,
2944
3203
  recovery.reply,
2945
- admittedContentType,
2946
- signal,
2947
- canonicalInventoryDigest
3204
+ admittedContentType
3205
+ );
3206
+ this.formalRemoteActorAdmissions.attachDeferredJoinCompletion(
3207
+ recovery.request.handoffId,
3208
+ deferred
2948
3209
  );
2949
- this.formalRemoteActorAdmissions.attachDeferredJoinRoot(recovery.request.handoffId, deferred);
2950
- return deferred;
2951
3210
  }
2952
3211
 
2953
3212
  private encodeMeshActorReply(
@@ -3096,19 +3355,10 @@ export class DefaultZLinkSpotManager {
3096
3355
  }
3097
3356
  }
3098
3357
 
3099
- function instanceDispatchErrorReason(error: unknown): ZLinkDispatchErrorReason {
3100
- if (error instanceof ZLinkFrameworkException) {
3101
- const kind = internalFrameworkErrorKind(error);
3102
- if (
3103
- kind === ZLinkFrameworkInternalErrorKind.SpotGenerationStale ||
3104
- kind === ZLinkFrameworkInternalErrorKind.SpotMoving ||
3105
- kind === ZLinkFrameworkInternalErrorKind.SpotRouteNotFound ||
3106
- kind === ZLinkFrameworkInternalErrorKind.RequestTargetNotFound
3107
- ) {
3108
- return ZLinkDispatchErrorReason.StaleTarget;
3109
- }
3110
- }
3111
- return ZLinkDispatchErrorReason.HandlerException;
3358
+ function spotActorFailureKind(error: unknown): ZLinkFrameworkErrorKind {
3359
+ return error instanceof ZLinkFrameworkException
3360
+ ? error.kind
3361
+ : ZLinkFrameworkErrorKind.InternalFailure;
3112
3362
  }
3113
3363
 
3114
3364
  interface ZLinkFormalRemoteTransferRequest {