@plurnk/plurnk-service 1.16.4 → 1.17.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 (636) hide show
  1. package/.env.defaults +122 -246
  2. package/INSTALL.md +84 -138
  3. package/README.md +9 -5
  4. package/SPEC.md +1710 -1015
  5. package/dist/Paths.d.ts +2 -0
  6. package/dist/Paths.d.ts.map +1 -1
  7. package/dist/Paths.js +2 -0
  8. package/dist/Paths.js.map +1 -1
  9. package/dist/build-info.d.ts.map +1 -1
  10. package/dist/build-info.js +7 -1
  11. package/dist/build-info.js.map +1 -1
  12. package/dist/build-info.json +1 -1
  13. package/dist/content/body-preview.d.ts +8 -0
  14. package/dist/content/body-preview.d.ts.map +1 -0
  15. package/dist/content/body-preview.js +39 -0
  16. package/dist/content/body-preview.js.map +1 -0
  17. package/dist/content/byte-view.d.ts +1 -4
  18. package/dist/content/byte-view.d.ts.map +1 -1
  19. package/dist/content/byte-view.js.map +1 -1
  20. package/dist/content/edit-collision.d.ts.map +1 -1
  21. package/dist/content/edit-collision.js +3 -4
  22. package/dist/content/edit-collision.js.map +1 -1
  23. package/dist/content/line-anchors.d.ts +2 -2
  24. package/dist/content/line-anchors.d.ts.map +1 -1
  25. package/dist/content/line-anchors.js +4 -3
  26. package/dist/content/line-anchors.js.map +1 -1
  27. package/dist/content/line-selection.d.ts +9 -0
  28. package/dist/content/line-selection.d.ts.map +1 -0
  29. package/dist/content/line-selection.js +29 -0
  30. package/dist/content/line-selection.js.map +1 -0
  31. package/dist/content/matcher.d.ts +0 -1
  32. package/dist/content/matcher.d.ts.map +1 -1
  33. package/dist/content/matcher.js +2 -3
  34. package/dist/content/matcher.js.map +1 -1
  35. package/dist/content/pattern-edits.d.ts +39 -0
  36. package/dist/content/pattern-edits.d.ts.map +1 -0
  37. package/dist/content/pattern-edits.js +121 -0
  38. package/dist/content/pattern-edits.js.map +1 -0
  39. package/dist/content/read-projector.d.ts +18 -9
  40. package/dist/content/read-projector.d.ts.map +1 -1
  41. package/dist/content/read-projector.js +132 -35
  42. package/dist/content/read-projector.js.map +1 -1
  43. package/dist/content/read-resolve.d.ts +3 -1
  44. package/dist/content/read-resolve.d.ts.map +1 -1
  45. package/dist/content/read-resolve.js +39 -7
  46. package/dist/content/read-resolve.js.map +1 -1
  47. package/dist/core/AdmittedTurnExecutor.d.ts +3 -5
  48. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
  49. package/dist/core/AdmittedTurnExecutor.js +91 -83
  50. package/dist/core/AdmittedTurnExecutor.js.map +1 -1
  51. package/dist/core/BareBatchRunner.d.ts +6 -1
  52. package/dist/core/BareBatchRunner.d.ts.map +1 -1
  53. package/dist/core/BareBatchRunner.js +20 -5
  54. package/dist/core/BareBatchRunner.js.map +1 -1
  55. package/dist/core/BudgetReadout.d.ts +2 -3
  56. package/dist/core/BudgetReadout.d.ts.map +1 -1
  57. package/dist/core/BudgetReadout.js +23 -32
  58. package/dist/core/BudgetReadout.js.map +1 -1
  59. package/dist/core/CapabilityPolicies.d.ts +3 -8
  60. package/dist/core/CapabilityPolicies.d.ts.map +1 -1
  61. package/dist/core/CapabilityPolicies.js +2 -28
  62. package/dist/core/CapabilityPolicies.js.map +1 -1
  63. package/dist/core/CapabilityResolver.d.ts +10 -10
  64. package/dist/core/CapabilityResolver.d.ts.map +1 -1
  65. package/dist/core/CapabilityResolver.js +87 -65
  66. package/dist/core/CapabilityResolver.js.map +1 -1
  67. package/dist/core/ChannelWrite.d.ts +14 -11
  68. package/dist/core/ChannelWrite.d.ts.map +1 -1
  69. package/dist/core/ChannelWrite.js +11 -12
  70. package/dist/core/ChannelWrite.js.map +1 -1
  71. package/dist/core/ChannelWrite.sql +99 -9
  72. package/dist/core/ClientInteractions.d.ts.map +1 -1
  73. package/dist/core/ClientInteractions.js +7 -0
  74. package/dist/core/ClientInteractions.js.map +1 -1
  75. package/dist/core/CoreSchemeServices.d.ts +13 -10
  76. package/dist/core/CoreSchemeServices.d.ts.map +1 -1
  77. package/dist/core/CoreSchemeServices.js +13 -5
  78. package/dist/core/CoreSchemeServices.js.map +1 -1
  79. package/dist/core/DataStatementRunner.d.ts +2 -2
  80. package/dist/core/DataStatementRunner.d.ts.map +1 -1
  81. package/dist/core/DataStatementRunner.js +36 -39
  82. package/dist/core/DataStatementRunner.js.map +1 -1
  83. package/dist/core/Dispatcher.d.ts +19 -26
  84. package/dist/core/Dispatcher.d.ts.map +1 -1
  85. package/dist/core/Dispatcher.js +369 -219
  86. package/dist/core/Dispatcher.js.map +1 -1
  87. package/dist/core/Dispatcher.sql +66 -0
  88. package/dist/core/DurableStatement.d.ts.map +1 -1
  89. package/dist/core/DurableStatement.js +2 -1
  90. package/dist/core/DurableStatement.js.map +1 -1
  91. package/dist/core/EditMutations.d.ts +14 -18
  92. package/dist/core/EditMutations.d.ts.map +1 -1
  93. package/dist/core/EditMutations.js +211 -280
  94. package/dist/core/EditMutations.js.map +1 -1
  95. package/dist/core/EditMutations.sql +15 -0
  96. package/dist/core/EditSequence.d.ts +13 -0
  97. package/dist/core/EditSequence.d.ts.map +1 -0
  98. package/dist/core/EditSequence.js +73 -0
  99. package/dist/core/EditSequence.js.map +1 -0
  100. package/dist/core/Engine.d.ts +17 -23
  101. package/dist/core/Engine.d.ts.map +1 -1
  102. package/dist/core/Engine.js +73 -163
  103. package/dist/core/Engine.js.map +1 -1
  104. package/dist/core/Engine.sql +0 -724
  105. package/dist/core/EntryAddressBinding.d.ts +7 -17
  106. package/dist/core/EntryAddressBinding.d.ts.map +1 -1
  107. package/dist/core/EntryAddressBinding.js +12 -72
  108. package/dist/core/EntryAddressBinding.js.map +1 -1
  109. package/dist/core/ExecutionOutputs.d.ts +9 -0
  110. package/dist/core/ExecutionOutputs.d.ts.map +1 -0
  111. package/dist/core/ExecutionOutputs.js +36 -0
  112. package/dist/core/ExecutionOutputs.js.map +1 -0
  113. package/dist/core/ExecutionOutputs.sql +13 -0
  114. package/dist/core/ExecutorRegistry.d.ts +7 -5
  115. package/dist/core/ExecutorRegistry.d.ts.map +1 -1
  116. package/dist/core/ExecutorRegistry.js +36 -32
  117. package/dist/core/ExecutorRegistry.js.map +1 -1
  118. package/dist/core/HostPaths.d.ts +1 -0
  119. package/dist/core/HostPaths.d.ts.map +1 -1
  120. package/dist/core/HostPaths.js +4 -0
  121. package/dist/core/HostPaths.js.map +1 -1
  122. package/dist/core/InferenceCall.d.ts.map +1 -1
  123. package/dist/core/InferenceCall.js +1 -2
  124. package/dist/core/InferenceCall.js.map +1 -1
  125. package/dist/core/InferenceCall.sql +29 -0
  126. package/dist/core/KillHandler.d.ts +1 -0
  127. package/dist/core/KillHandler.d.ts.map +1 -1
  128. package/dist/core/KillHandler.js +24 -21
  129. package/dist/core/KillHandler.js.map +1 -1
  130. package/dist/core/LogBody.d.ts +8 -1
  131. package/dist/core/LogBody.d.ts.map +1 -1
  132. package/dist/core/LogBody.js +42 -11
  133. package/dist/core/LogBody.js.map +1 -1
  134. package/dist/core/LogEntryProjection.d.ts +1 -0
  135. package/dist/core/LogEntryProjection.d.ts.map +1 -1
  136. package/dist/core/LogEntryProjection.js +18 -10
  137. package/dist/core/LogEntryProjection.js.map +1 -1
  138. package/dist/core/LogVisibility.d.ts +1 -0
  139. package/dist/core/LogVisibility.d.ts.map +1 -1
  140. package/dist/core/LogVisibility.js +3 -0
  141. package/dist/core/LogVisibility.js.map +1 -1
  142. package/dist/core/LogWriter.d.ts +2 -3
  143. package/dist/core/LogWriter.d.ts.map +1 -1
  144. package/dist/core/LogWriter.js +25 -32
  145. package/dist/core/LogWriter.js.map +1 -1
  146. package/dist/core/LogWriter.sql +23 -0
  147. package/dist/core/LoopDriver.d.ts +11 -8
  148. package/dist/core/LoopDriver.d.ts.map +1 -1
  149. package/dist/core/LoopDriver.js +163 -189
  150. package/dist/core/LoopDriver.js.map +1 -1
  151. package/dist/core/LoopDriver.sql +11 -0
  152. package/dist/core/LoopLifecycle.d.ts +32 -2
  153. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  154. package/dist/core/LoopLifecycle.js +88 -4
  155. package/dist/core/LoopLifecycle.js.map +1 -1
  156. package/dist/core/LoopLifecycle.sql +145 -28
  157. package/dist/core/LoopPolicyReader.sql +6 -0
  158. package/dist/core/MembershipMaterialization.d.ts.map +1 -1
  159. package/dist/core/MembershipMaterialization.js +6 -28
  160. package/dist/core/MembershipMaterialization.js.map +1 -1
  161. package/dist/core/ModelCall.sql +70 -0
  162. package/dist/core/MutationEffects.d.ts +5 -3
  163. package/dist/core/MutationEffects.d.ts.map +1 -1
  164. package/dist/core/MutationEffects.js +10 -28
  165. package/dist/core/MutationEffects.js.map +1 -1
  166. package/dist/core/NativeContent.d.ts +6 -0
  167. package/dist/core/NativeContent.d.ts.map +1 -0
  168. package/dist/core/NativeContent.js +16 -0
  169. package/dist/core/NativeContent.js.map +1 -0
  170. package/dist/core/NativeContent.sql +6 -0
  171. package/dist/core/NoticeChannel.js +1 -1
  172. package/dist/core/NoticeChannel.js.map +1 -1
  173. package/dist/core/OperatorConfig.js +5 -5
  174. package/dist/core/OperatorConfig.js.map +1 -1
  175. package/dist/core/PacketBuilder.d.ts +8 -5
  176. package/dist/core/PacketBuilder.d.ts.map +1 -1
  177. package/dist/core/PacketBuilder.js +117 -81
  178. package/dist/core/PacketBuilder.js.map +1 -1
  179. package/dist/core/PacketBuilder.sql +146 -0
  180. package/dist/core/PatternSelection.d.ts +28 -0
  181. package/dist/core/PatternSelection.d.ts.map +1 -0
  182. package/dist/core/PatternSelection.js +42 -0
  183. package/dist/core/PatternSelection.js.map +1 -0
  184. package/dist/core/ProblemLog.d.ts.map +1 -1
  185. package/dist/core/ProblemLog.js +0 -1
  186. package/dist/core/ProblemLog.js.map +1 -1
  187. package/dist/core/PromptFrames.d.ts +12 -0
  188. package/dist/core/PromptFrames.d.ts.map +1 -0
  189. package/dist/core/PromptFrames.js +28 -0
  190. package/dist/core/PromptFrames.js.map +1 -0
  191. package/dist/core/ProposalLifecycle.d.ts +0 -1
  192. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  193. package/dist/core/ProposalLifecycle.js +20 -19
  194. package/dist/core/ProposalLifecycle.js.map +1 -1
  195. package/dist/core/ProposalLifecycle.sql +33 -0
  196. package/dist/core/ProviderInstantiate.d.ts +1 -1
  197. package/dist/core/ProviderInstantiate.d.ts.map +1 -1
  198. package/dist/core/ProviderInstantiate.js +7 -14
  199. package/dist/core/ProviderInstantiate.js.map +1 -1
  200. package/dist/core/ReasoningView.d.ts +9 -0
  201. package/dist/core/ReasoningView.d.ts.map +1 -0
  202. package/dist/core/ReasoningView.js +47 -0
  203. package/dist/core/ReasoningView.js.map +1 -0
  204. package/dist/core/ResourceBindings.d.ts +16 -0
  205. package/dist/core/ResourceBindings.d.ts.map +1 -0
  206. package/dist/core/ResourceBindings.js +45 -0
  207. package/dist/core/ResourceBindings.js.map +1 -0
  208. package/dist/core/ResourceMutations.d.ts +5 -8
  209. package/dist/core/ResourceMutations.d.ts.map +1 -1
  210. package/dist/core/ResourceMutations.js +6 -7
  211. package/dist/core/ResourceMutations.js.map +1 -1
  212. package/dist/core/ResourceSelector.d.ts +2 -2
  213. package/dist/core/ResourceSelector.d.ts.map +1 -1
  214. package/dist/core/ResourceSelector.js +122 -62
  215. package/dist/core/ResourceSelector.js.map +1 -1
  216. package/dist/core/ResourceTransfers.d.ts +4 -2
  217. package/dist/core/ResourceTransfers.d.ts.map +1 -1
  218. package/dist/core/ResourceTransfers.js +95 -26
  219. package/dist/core/ResourceTransfers.js.map +1 -1
  220. package/dist/core/RuntimeWorker.d.ts +5 -0
  221. package/dist/core/RuntimeWorker.d.ts.map +1 -0
  222. package/dist/core/RuntimeWorker.js +10 -0
  223. package/dist/core/RuntimeWorker.js.map +1 -0
  224. package/dist/core/RuntimeWorker.sql +5 -0
  225. package/dist/core/SchemeRegistry.d.ts +12 -16
  226. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  227. package/dist/core/SchemeRegistry.js +58 -84
  228. package/dist/core/SchemeRegistry.js.map +1 -1
  229. package/dist/core/StoredPacket.d.ts +6 -1
  230. package/dist/core/StoredPacket.d.ts.map +1 -1
  231. package/dist/core/StoredPacket.js +30 -10
  232. package/dist/core/StoredPacket.js.map +1 -1
  233. package/dist/core/StrikeRail.d.ts +9 -6
  234. package/dist/core/StrikeRail.d.ts.map +1 -1
  235. package/dist/core/StrikeRail.js +60 -113
  236. package/dist/core/StrikeRail.js.map +1 -1
  237. package/dist/core/StrikeRail.sql +12 -0
  238. package/dist/core/TerminalResult.d.ts +1 -1
  239. package/dist/core/TerminalResult.d.ts.map +1 -1
  240. package/dist/core/TerminalResult.js +2 -2
  241. package/dist/core/TerminalResult.js.map +1 -1
  242. package/dist/core/TokenCalibration.d.ts +1 -6
  243. package/dist/core/TokenCalibration.d.ts.map +1 -1
  244. package/dist/core/TokenCalibration.js +13 -9
  245. package/dist/core/TokenCalibration.js.map +1 -1
  246. package/dist/core/TokenCalibration.sql +15 -0
  247. package/dist/core/ToolInputSchema.d.ts +6 -0
  248. package/dist/core/ToolInputSchema.d.ts.map +1 -0
  249. package/dist/core/ToolInputSchema.js +43 -0
  250. package/dist/core/ToolInputSchema.js.map +1 -0
  251. package/dist/core/ToolResources.d.ts.map +1 -1
  252. package/dist/core/ToolResources.js +76 -52
  253. package/dist/core/ToolResources.js.map +1 -1
  254. package/dist/core/Turn.d.ts +5 -2
  255. package/dist/core/Turn.d.ts.map +1 -1
  256. package/dist/core/Turn.js +13 -11
  257. package/dist/core/Turn.js.map +1 -1
  258. package/dist/core/Turn.sql +25 -39
  259. package/dist/core/{SendBroadcastHandler.d.ts → TurnDispositionHandler.d.ts} +25 -17
  260. package/dist/core/TurnDispositionHandler.d.ts.map +1 -0
  261. package/dist/core/TurnDispositionHandler.js +198 -0
  262. package/dist/core/TurnDispositionHandler.js.map +1 -0
  263. package/dist/core/TurnMaterialization.d.ts +2 -3
  264. package/dist/core/TurnMaterialization.d.ts.map +1 -1
  265. package/dist/core/TurnMaterialization.js +40 -15
  266. package/dist/core/TurnMaterialization.js.map +1 -1
  267. package/dist/core/TurnMaterialization.sql +44 -0
  268. package/dist/core/TurnOps.d.ts.map +1 -1
  269. package/dist/core/TurnOps.js +8 -64
  270. package/dist/core/TurnOps.js.map +1 -1
  271. package/dist/core/TurnRunner.d.ts +9 -12
  272. package/dist/core/TurnRunner.d.ts.map +1 -1
  273. package/dist/core/TurnRunner.js +232 -408
  274. package/dist/core/TurnRunner.js.map +1 -1
  275. package/dist/core/TurnRunner.sql +74 -0
  276. package/dist/core/TurnSources.sql +39 -0
  277. package/dist/core/WorkerControlAddress.d.ts +1 -0
  278. package/dist/core/WorkerControlAddress.d.ts.map +1 -1
  279. package/dist/core/WorkerControlAddress.js +5 -0
  280. package/dist/core/WorkerControlAddress.js.map +1 -1
  281. package/dist/core/WorkerControlHandler.d.ts +1 -3
  282. package/dist/core/WorkerControlHandler.d.ts.map +1 -1
  283. package/dist/core/WorkerControlHandler.js +41 -48
  284. package/dist/core/WorkerControlHandler.js.map +1 -1
  285. package/dist/core/WorkerName.d.ts +8 -6
  286. package/dist/core/WorkerName.d.ts.map +1 -1
  287. package/dist/core/WorkerName.js +33 -24
  288. package/dist/core/WorkerName.js.map +1 -1
  289. package/dist/core/WorkerName.sql +7 -10
  290. package/dist/core/WorkspaceGate.d.ts +1 -1
  291. package/dist/core/WorkspaceGate.d.ts.map +1 -1
  292. package/dist/core/WorkspaceGate.js +29 -6
  293. package/dist/core/WorkspaceGate.js.map +1 -1
  294. package/dist/core/ambient.sql +236 -0
  295. package/dist/core/attachments.d.ts +2 -1
  296. package/dist/core/attachments.d.ts.map +1 -1
  297. package/dist/core/attachments.js +5 -4
  298. package/dist/core/attachments.js.map +1 -1
  299. package/dist/core/caps/CapsResolve.d.ts +2 -3
  300. package/dist/core/caps/CapsResolve.d.ts.map +1 -1
  301. package/dist/core/caps/CapsResolve.js +5 -5
  302. package/dist/core/caps/CapsResolve.js.map +1 -1
  303. package/dist/core/caps/DbChannelCaps.d.ts +1 -1
  304. package/dist/core/caps/DbChannelCaps.d.ts.map +1 -1
  305. package/dist/core/caps/DbChannelCaps.js +4 -6
  306. package/dist/core/caps/DbChannelCaps.js.map +1 -1
  307. package/dist/core/caps/DbEntryCaps.d.ts +2 -1
  308. package/dist/core/caps/DbEntryCaps.d.ts.map +1 -1
  309. package/dist/core/caps/DbEntryCaps.js +11 -17
  310. package/dist/core/caps/DbEntryCaps.js.map +1 -1
  311. package/dist/core/caps/DbNotifyCaps.d.ts +1 -1
  312. package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -1
  313. package/dist/core/caps/DbNotifyCaps.js +3 -5
  314. package/dist/core/caps/DbNotifyCaps.js.map +1 -1
  315. package/dist/core/caps/DbProjectionCaps.js +1 -1
  316. package/dist/core/caps/DbProjectionCaps.js.map +1 -1
  317. package/dist/core/caps/DbSubscriptionCaps.d.ts +1 -1
  318. package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
  319. package/dist/core/caps/DbSubscriptionCaps.js +5 -7
  320. package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
  321. package/dist/core/caps/SchemeCtxImpl.d.ts +0 -2
  322. package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
  323. package/dist/core/caps/SchemeCtxImpl.js +4 -20
  324. package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
  325. package/dist/core/env-defaults.d.ts.map +1 -1
  326. package/dist/core/env-defaults.js +4 -2
  327. package/dist/core/env-defaults.js.map +1 -1
  328. package/dist/core/file-materialization.d.ts +4 -1
  329. package/dist/core/file-materialization.d.ts.map +1 -1
  330. package/dist/core/file-materialization.js +14 -0
  331. package/dist/core/file-materialization.js.map +1 -1
  332. package/dist/core/fork.d.ts +1 -6
  333. package/dist/core/fork.d.ts.map +1 -1
  334. package/dist/core/fork.js +9 -153
  335. package/dist/core/fork.js.map +1 -1
  336. package/dist/core/fork.sql +162 -185
  337. package/dist/core/git-env.d.ts +1 -0
  338. package/dist/core/git-env.d.ts.map +1 -1
  339. package/dist/core/git-env.js +39 -2
  340. package/dist/core/git-env.js.map +1 -1
  341. package/dist/core/git-membership.d.ts.map +1 -1
  342. package/dist/core/git-membership.js +64 -48
  343. package/dist/core/git-membership.js.map +1 -1
  344. package/dist/core/git-state.d.ts.map +1 -1
  345. package/dist/core/git-state.js +25 -19
  346. package/dist/core/git-state.js.map +1 -1
  347. package/dist/core/glob_match.d.ts +4 -0
  348. package/dist/core/glob_match.d.ts.map +1 -0
  349. package/dist/core/glob_match.js +7 -0
  350. package/dist/core/glob_match.js.map +1 -0
  351. package/dist/core/maintenance.sql +6 -0
  352. package/dist/core/mutation-types.d.ts +7 -28
  353. package/dist/core/mutation-types.d.ts.map +1 -1
  354. package/dist/core/packet-inject.d.ts.map +1 -1
  355. package/dist/core/packet-inject.js +2 -3
  356. package/dist/core/packet-inject.js.map +1 -1
  357. package/dist/core/packet-wire.d.ts +8 -6
  358. package/dist/core/packet-wire.d.ts.map +1 -1
  359. package/dist/core/packet-wire.js +131 -163
  360. package/dist/core/packet-wire.js.map +1 -1
  361. package/dist/core/plurnk-uri.d.ts +1 -1
  362. package/dist/core/plurnk-uri.d.ts.map +1 -1
  363. package/dist/core/plurnk-uri.js +5 -12
  364. package/dist/core/plurnk-uri.js.map +1 -1
  365. package/dist/core/scheme-types.d.ts +3 -3
  366. package/dist/core/scheme-types.d.ts.map +1 -1
  367. package/dist/core/scheme-types.js.map +1 -1
  368. package/dist/core/sha256.d.ts +4 -0
  369. package/dist/core/sha256.d.ts.map +1 -0
  370. package/dist/core/sha256.js +6 -0
  371. package/dist/core/sha256.js.map +1 -0
  372. package/dist/core/teaching.js +1 -1
  373. package/dist/core/teaching.js.map +1 -1
  374. package/dist/core/turn-scheduler.d.ts.map +1 -1
  375. package/dist/core/turn-scheduler.js +5 -18
  376. package/dist/core/turn-scheduler.js.map +1 -1
  377. package/dist/core/turn-signals.d.ts +0 -6
  378. package/dist/core/turn-signals.d.ts.map +1 -1
  379. package/dist/core/turn-signals.js +1 -7
  380. package/dist/core/turn-signals.js.map +1 -1
  381. package/dist/core/worker-ops.sql +15 -22
  382. package/dist/core/workspace-settings.d.ts.map +1 -1
  383. package/dist/core/workspace-settings.js +18 -2
  384. package/dist/core/workspace-settings.js.map +1 -1
  385. package/dist/core/workspace-settings.sql +6 -0
  386. package/dist/digest/Digest.d.ts.map +1 -1
  387. package/dist/digest/Digest.js +27 -90
  388. package/dist/digest/Digest.js.map +1 -1
  389. package/dist/digest/DigestRender.d.ts.map +1 -1
  390. package/dist/digest/DigestRender.js +14 -54
  391. package/dist/digest/DigestRender.js.map +1 -1
  392. package/dist/digest/digest-rows.d.ts +10 -32
  393. package/dist/digest/digest-rows.d.ts.map +1 -1
  394. package/dist/digest/digest.sql +43 -18
  395. package/dist/schemes/Exec.d.ts +6 -12
  396. package/dist/schemes/Exec.d.ts.map +1 -1
  397. package/dist/schemes/Exec.js +256 -188
  398. package/dist/schemes/Exec.js.map +1 -1
  399. package/dist/schemes/ExecOutputScheme.d.ts +8 -6
  400. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  401. package/dist/schemes/ExecOutputScheme.js +33 -61
  402. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  403. package/dist/schemes/ExecutionInput.d.ts +12 -0
  404. package/dist/schemes/ExecutionInput.d.ts.map +1 -0
  405. package/dist/schemes/ExecutionInput.js +94 -0
  406. package/dist/schemes/ExecutionInput.js.map +1 -0
  407. package/dist/schemes/File.d.ts +5 -2
  408. package/dist/schemes/File.d.ts.map +1 -1
  409. package/dist/schemes/File.js +62 -92
  410. package/dist/schemes/File.js.map +1 -1
  411. package/dist/schemes/Log.d.ts.map +1 -1
  412. package/dist/schemes/Log.js +84 -79
  413. package/dist/schemes/Log.js.map +1 -1
  414. package/dist/schemes/Log.sql +183 -15
  415. package/dist/schemes/Prompt.d.ts.map +1 -1
  416. package/dist/schemes/Prompt.js +3 -12
  417. package/dist/schemes/Prompt.js.map +1 -1
  418. package/dist/schemes/QuestionTool.d.ts +5 -0
  419. package/dist/schemes/QuestionTool.d.ts.map +1 -1
  420. package/dist/schemes/QuestionTool.js +6 -14
  421. package/dist/schemes/QuestionTool.js.map +1 -1
  422. package/dist/schemes/Skill.d.ts +12 -7
  423. package/dist/schemes/Skill.d.ts.map +1 -1
  424. package/dist/schemes/Skill.js +149 -21
  425. package/dist/schemes/Skill.js.map +1 -1
  426. package/dist/schemes/TurnSource.d.ts +12 -0
  427. package/dist/schemes/TurnSource.d.ts.map +1 -0
  428. package/dist/schemes/TurnSource.js +116 -0
  429. package/dist/schemes/TurnSource.js.map +1 -0
  430. package/dist/schemes/Worker.d.ts +3 -3
  431. package/dist/schemes/Worker.d.ts.map +1 -1
  432. package/dist/schemes/Worker.js +61 -208
  433. package/dist/schemes/Worker.js.map +1 -1
  434. package/dist/schemes/_entry-crud.d.ts +12 -15
  435. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  436. package/dist/schemes/_entry-crud.js +63 -63
  437. package/dist/schemes/_entry-crud.js.map +1 -1
  438. package/dist/schemes/_entry-crud.sql +142 -46
  439. package/dist/schemes/_entry-find.d.ts +1 -3
  440. package/dist/schemes/_entry-find.d.ts.map +1 -1
  441. package/dist/schemes/_entry-find.js +111 -112
  442. package/dist/schemes/_entry-find.js.map +1 -1
  443. package/dist/schemes/_entry-find.sql +22 -14
  444. package/dist/schemes/_entry-fts.d.ts +14 -0
  445. package/dist/schemes/_entry-fts.d.ts.map +1 -0
  446. package/dist/schemes/_entry-fts.js +82 -0
  447. package/dist/schemes/_entry-fts.js.map +1 -0
  448. package/dist/schemes/_entry-fts.sql +31 -0
  449. package/dist/schemes/_entry-graph.d.ts.map +1 -1
  450. package/dist/schemes/_entry-graph.js +6 -14
  451. package/dist/schemes/_entry-graph.js.map +1 -1
  452. package/dist/schemes/_entry-graph.sql +29 -44
  453. package/dist/schemes/_entry-manifest.d.ts +2 -1
  454. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  455. package/dist/schemes/_entry-manifest.js +15 -12
  456. package/dist/schemes/_entry-manifest.js.map +1 -1
  457. package/dist/schemes/_entry-manifest.sql +26 -0
  458. package/dist/schemes/_entry-ops.d.ts +3 -5
  459. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  460. package/dist/schemes/_entry-ops.js +30 -43
  461. package/dist/schemes/_entry-ops.js.map +1 -1
  462. package/dist/schemes/_entry-ops.sql +5 -6
  463. package/dist/schemes/_entry-readable.d.ts +8 -0
  464. package/dist/schemes/_entry-readable.d.ts.map +1 -0
  465. package/dist/schemes/_entry-readable.js +38 -0
  466. package/dist/schemes/_entry-readable.js.map +1 -0
  467. package/dist/schemes/_entry-send.d.ts +1 -1
  468. package/dist/schemes/_entry-send.d.ts.map +1 -1
  469. package/dist/schemes/_entry-send.js +3 -3
  470. package/dist/schemes/_entry-send.js.map +1 -1
  471. package/dist/schemes/_search-index.d.ts +1 -3
  472. package/dist/schemes/_search-index.d.ts.map +1 -1
  473. package/dist/schemes/_search-index.js +79 -110
  474. package/dist/schemes/_search-index.js.map +1 -1
  475. package/dist/schemes/_search-index.sql +30 -0
  476. package/dist/schemes/exec-runtime.d.ts +1 -1
  477. package/dist/schemes/exec-runtime.d.ts.map +1 -1
  478. package/dist/schemes/exec-runtime.js.map +1 -1
  479. package/dist/server/ClientReads.d.ts +2 -2
  480. package/dist/server/ClientReads.d.ts.map +1 -1
  481. package/dist/server/ClientReads.js +5 -8
  482. package/dist/server/ClientReads.js.map +1 -1
  483. package/dist/server/Daemon.d.ts +14 -21
  484. package/dist/server/Daemon.d.ts.map +1 -1
  485. package/dist/server/Daemon.js +135 -156
  486. package/dist/server/Daemon.js.map +1 -1
  487. package/dist/server/DaemonModule.d.ts +23 -21
  488. package/dist/server/DaemonModule.d.ts.map +1 -1
  489. package/dist/server/DrainSupervisor.d.ts +8 -21
  490. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  491. package/dist/server/DrainSupervisor.js +278 -306
  492. package/dist/server/DrainSupervisor.js.map +1 -1
  493. package/dist/server/Functionality.d.ts +11 -12
  494. package/dist/server/Functionality.d.ts.map +1 -1
  495. package/dist/server/Functionality.js +129 -101
  496. package/dist/server/Functionality.js.map +1 -1
  497. package/dist/server/FunctionalityManager.d.ts +3 -5
  498. package/dist/server/FunctionalityManager.d.ts.map +1 -1
  499. package/dist/server/FunctionalityManager.js +20 -58
  500. package/dist/server/FunctionalityManager.js.map +1 -1
  501. package/dist/server/MembersFunctionality.d.ts +5 -4
  502. package/dist/server/MembersFunctionality.d.ts.map +1 -1
  503. package/dist/server/MembersFunctionality.js +24 -37
  504. package/dist/server/MembersFunctionality.js.map +1 -1
  505. package/dist/server/PlurnkSkill.d.ts +11 -0
  506. package/dist/server/PlurnkSkill.d.ts.map +1 -0
  507. package/dist/server/PlurnkSkill.js +41 -0
  508. package/dist/server/PlurnkSkill.js.map +1 -0
  509. package/dist/server/Retention.d.ts +22 -0
  510. package/dist/server/Retention.d.ts.map +1 -0
  511. package/dist/server/Retention.js +54 -0
  512. package/dist/server/Retention.js.map +1 -0
  513. package/dist/server/Retention.sql +36 -0
  514. package/dist/server/ServiceModules.d.ts +5 -0
  515. package/dist/server/ServiceModules.d.ts.map +1 -0
  516. package/dist/server/ServiceModules.js +10 -0
  517. package/dist/server/ServiceModules.js.map +1 -0
  518. package/dist/server/SkillsFunctionality.d.ts +14 -19
  519. package/dist/server/SkillsFunctionality.d.ts.map +1 -1
  520. package/dist/server/SkillsFunctionality.js +97 -104
  521. package/dist/server/SkillsFunctionality.js.map +1 -1
  522. package/dist/server/WorkerModelResolver.d.ts +4 -0
  523. package/dist/server/WorkerModelResolver.d.ts.map +1 -1
  524. package/dist/server/WorkerModelResolver.js +72 -39
  525. package/dist/server/WorkerModelResolver.js.map +1 -1
  526. package/dist/server/WorkspaceCapabilities.d.ts +21 -0
  527. package/dist/server/WorkspaceCapabilities.d.ts.map +1 -0
  528. package/dist/server/{WorkerCapabilities.js → WorkspaceCapabilities.js} +40 -40
  529. package/dist/server/WorkspaceCapabilities.js.map +1 -0
  530. package/dist/server/WorkspaceResidency.d.ts +36 -0
  531. package/dist/server/WorkspaceResidency.d.ts.map +1 -0
  532. package/dist/server/WorkspaceResidency.js +199 -0
  533. package/dist/server/WorkspaceResidency.js.map +1 -0
  534. package/dist/server/client-input.d.ts +1 -4
  535. package/dist/server/client-input.d.ts.map +1 -1
  536. package/dist/server/client-input.js +4 -45
  537. package/dist/server/client-input.js.map +1 -1
  538. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  539. package/dist/server/dispatch-as-plurnk.js +4 -22
  540. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  541. package/dist/server/drain.sql +65 -42
  542. package/dist/server/envelope.d.ts +8 -0
  543. package/dist/server/envelope.d.ts.map +1 -1
  544. package/dist/server/envelope.js +9 -7
  545. package/dist/server/envelope.js.map +1 -1
  546. package/dist/server/envelope.sql +49 -13
  547. package/dist/server/lifecycle-recovery.sql +14 -17
  548. package/dist/server/logEntry.d.ts +1 -1
  549. package/dist/server/logEntry.d.ts.map +1 -1
  550. package/dist/server/logEntry.js +4 -1
  551. package/dist/server/logEntry.js.map +1 -1
  552. package/dist/server/logEntry.sql +25 -1
  553. package/dist/server/loopDocs.d.ts +2 -2
  554. package/dist/server/loopDocs.d.ts.map +1 -1
  555. package/dist/server/loopDocs.js +38 -31
  556. package/dist/server/loopDocs.js.map +1 -1
  557. package/dist/server/loopDocs.sql +1 -3
  558. package/dist/server/model-catalog.d.ts.map +1 -1
  559. package/dist/server/model-catalog.js +2 -1
  560. package/dist/server/model-catalog.js.map +1 -1
  561. package/dist/server/model-route.d.ts +1 -1
  562. package/dist/server/model-route.d.ts.map +1 -1
  563. package/dist/server/model-route.js +4 -2
  564. package/dist/server/model-route.js.map +1 -1
  565. package/dist/server/seam-entry-read.sql +3 -4
  566. package/dist/server/seam-loop.sql +2 -9
  567. package/dist/server/workspace-capabilities.sql +19 -0
  568. package/dist/service.d.ts.map +1 -1
  569. package/dist/service.js +5 -17
  570. package/dist/service.js.map +1 -1
  571. package/docs/members.md +83 -0
  572. package/docs/skills.md +50 -0
  573. package/migrations/001_workspaces.sql +53 -0
  574. package/migrations/002_workers.sql +183 -0
  575. package/migrations/003_loops.sql +326 -0
  576. package/migrations/004_inference.sql +360 -0
  577. package/migrations/005_entries.sql +207 -0
  578. package/migrations/006_log.sql +578 -0
  579. package/migrations/007_subscriptions.sql +175 -0
  580. package/migrations/008_interactions.sql +29 -0
  581. package/package.json +33 -40
  582. package/digest-sql/channel-dispositions/dispositions.sql +0 -15
  583. package/digest-sql/channel-state/state.sql +0 -6
  584. package/digest-sql/curation/curation.sql +0 -6
  585. package/digest-sql/derivations/derivations.sql +0 -4
  586. package/digest-sql/embeddings/embeddings.sql +0 -4
  587. package/digest-sql/entry-dispositions/dispositions.sql +0 -15
  588. package/digest-sql/entry-state/state.sql +0 -6
  589. package/digest-sql/token-counts/token-counts.sql +0 -2
  590. package/dist/core/EmbeddingCall.d.ts +0 -23
  591. package/dist/core/EmbeddingCall.d.ts.map +0 -1
  592. package/dist/core/EmbeddingCall.js +0 -149
  593. package/dist/core/EmbeddingCall.js.map +0 -1
  594. package/dist/core/OverflowTurn.d.ts +0 -11
  595. package/dist/core/OverflowTurn.d.ts.map +0 -1
  596. package/dist/core/OverflowTurn.js +0 -80
  597. package/dist/core/OverflowTurn.js.map +0 -1
  598. package/dist/core/Owner.d.ts +0 -8
  599. package/dist/core/Owner.d.ts.map +0 -1
  600. package/dist/core/Owner.js +0 -46
  601. package/dist/core/Owner.js.map +0 -1
  602. package/dist/core/SendBroadcastHandler.d.ts.map +0 -1
  603. package/dist/core/SendBroadcastHandler.js +0 -159
  604. package/dist/core/SendBroadcastHandler.js.map +0 -1
  605. package/dist/core/VectorPump.d.ts +0 -28
  606. package/dist/core/VectorPump.d.ts.map +0 -1
  607. package/dist/core/VectorPump.js +0 -130
  608. package/dist/core/VectorPump.js.map +0 -1
  609. package/dist/core/owner.sql +0 -11
  610. package/dist/core/worker-settings.d.ts +0 -10
  611. package/dist/core/worker-settings.d.ts.map +0 -1
  612. package/dist/core/worker-settings.js +0 -53
  613. package/dist/core/worker-settings.js.map +0 -1
  614. package/dist/schemes/_entry-chunk.d.ts +0 -14
  615. package/dist/schemes/_entry-chunk.d.ts.map +0 -1
  616. package/dist/schemes/_entry-chunk.js +0 -165
  617. package/dist/schemes/_entry-chunk.js.map +0 -1
  618. package/dist/schemes/_entry-semantic.d.ts +0 -63
  619. package/dist/schemes/_entry-semantic.d.ts.map +0 -1
  620. package/dist/schemes/_entry-semantic.js +0 -299
  621. package/dist/schemes/_entry-semantic.js.map +0 -1
  622. package/dist/schemes/_entry-semantic.sql +0 -99
  623. package/dist/schemes/cosine.d.ts +0 -4
  624. package/dist/schemes/cosine.d.ts.map +0 -1
  625. package/dist/schemes/cosine.js +0 -9
  626. package/dist/schemes/cosine.js.map +0 -1
  627. package/dist/server/WorkerCapabilities.d.ts +0 -21
  628. package/dist/server/WorkerCapabilities.d.ts.map +0 -1
  629. package/dist/server/WorkerCapabilities.js.map +0 -1
  630. package/dist/server/WorkerResidency.d.ts +0 -40
  631. package/dist/server/WorkerResidency.d.ts.map +0 -1
  632. package/dist/server/WorkerResidency.js +0 -283
  633. package/dist/server/WorkerResidency.js.map +0 -1
  634. package/dist/server/seam-log-read.sql +0 -21
  635. package/dist/server/worker-capabilities.sql +0 -28
  636. package/migrations/001_schema.sql +0 -2207
@@ -1,10 +1,11 @@
1
1
  var _a;
2
- import { foldAuthorityIntoPath, renderAddress, renderTarget, schemeNameOf } from "./plurnk-uri.js";
2
+ import { PlurnkParser, TurnDisposition, parsePath } from "@plurnk/plurnk-contracts";
3
+ import { foldAuthorityIntoPath, promptLoopPrefix, renderAddress, renderTarget, schemeNameOf } from "./plurnk-uri.js";
3
4
  import { PathSyntax } from "@plurnk/plurnk-contracts";
4
5
  import Namespace from "./namespace.js";
5
6
  import CapabilityResolver from "./CapabilityResolver.js";
7
+ import LoopPolicyReader from "./LoopPolicyReader.js";
6
8
  import SchemeCtxImpl from "./caps/SchemeCtxImpl.js";
7
- import LoopLifecycle from "./LoopLifecycle.js";
8
9
  import Results from "./results.js";
9
10
  import { OperationFailureError } from "./results.js";
10
11
  import EffectPolicy from "../schemes/EffectPolicy.js";
@@ -14,11 +15,15 @@ import ResourceMutations from "./ResourceMutations.js";
14
15
  import { primaryTargetOf } from "./statement-primary.js";
15
16
  import LogBody from "./LogBody.js";
16
17
  import LogVisibility from "./LogVisibility.js";
18
+ import EntryAddressBinding from "./EntryAddressBinding.js";
17
19
  import WorkerControlHandler from "./WorkerControlHandler.js";
20
+ import WorkerControlAddress from "./WorkerControlAddress.js";
18
21
  import KillHandler from "./KillHandler.js";
19
- import SendBroadcastHandler from "./SendBroadcastHandler.js";
22
+ import TurnDispositionHandler from "./TurnDispositionHandler.js";
20
23
  import LogWriter from "./LogWriter.js";
24
+ import LogEntryProjection from "./LogEntryProjection.js";
21
25
  import DataStatementRunner from "./DataStatementRunner.js";
26
+ import ResourceBindings from "./ResourceBindings.js";
22
27
  // SPEC {§scheme-surface}: writer must be in target scheme's manifest.writableBy.
23
28
  // READ/FIND are not gated — they read, never mutating an entry.
24
29
  const MUTATING_OPS = new Set(["EDIT", "SEND", "COPY", "MOVE", "EXEC", "KILL", "FORK", "WORK"]);
@@ -47,17 +52,12 @@ class Dispatcher {
47
52
  // {§relation-indexed-dialects} — the engine's derivation pump, awaited by a scheme whose
48
53
  // indexed dialect met a still-deriving index.
49
54
  #settleDerivations;
50
- #settleVectors;
51
55
  #streamEventNotify;
52
56
  #wakeWorkerNotify;
53
57
  #injectWorker;
54
58
  #cancelWorker;
55
59
  #cancelDescendants;
56
- // {§send-premature-terminate}/SEND signal 202 with scope — the engine-owned park-deadline registry (loopId → seconds;
57
- // -1 = indefinite). The dispatcher WRITES at park; the daemon's drain park-exit consumes.
58
- #parkDeadlines;
59
60
  // Per-turn running-worker READ obligations. {§join-blocking-collect}
60
- #joinTargets;
61
61
  #liveSubscriptions;
62
62
  #lifecycle;
63
63
  #resourceMutations;
@@ -65,10 +65,10 @@ class Dispatcher {
65
65
  #capabilities;
66
66
  #workerControl;
67
67
  #kill;
68
- #sendBroadcast;
68
+ #disposition;
69
69
  #logWriter;
70
70
  #dataRun;
71
- constructor({ db, schemes, mimetypes, weigh, notices, proposals, interactions, executors, loopSignal, settleDerivations, settleVectors, streamEventNotify, wakeWorkerNotify, injectWorker, cancelWorker, cancelDescendants, parkDeadlines, joinTargets, liveSubscriptions, entryAddresses }) {
71
+ constructor({ db, lifecycle, schemes, mimetypes, weigh, notices, proposals, interactions, executors, loopSignal, settleDerivations, streamEventNotify, wakeWorkerNotify, injectWorker, cancelWorker, cancelDescendants, liveSubscriptions, entryAddresses }) {
72
72
  this.#db = db;
73
73
  this.#schemes = schemes;
74
74
  this.#mimetypes = mimetypes;
@@ -79,24 +79,21 @@ class Dispatcher {
79
79
  this.#executors = executors;
80
80
  this.#loopSignal = loopSignal;
81
81
  this.#settleDerivations = settleDerivations;
82
- this.#settleVectors = settleVectors;
83
82
  this.#streamEventNotify = streamEventNotify;
84
83
  this.#wakeWorkerNotify = wakeWorkerNotify;
85
84
  this.#injectWorker = injectWorker;
86
85
  this.#cancelWorker = cancelWorker;
87
86
  this.#cancelDescendants = cancelDescendants;
88
- this.#parkDeadlines = parkDeadlines ?? new Map();
89
- this.#joinTargets = joinTargets ?? new Set();
90
87
  this.#liveSubscriptions = liveSubscriptions;
91
88
  this.#entryAddresses = entryAddresses;
92
89
  this.#capabilities = new CapabilityResolver(db, schemes, executors);
93
- this.#lifecycle = new LoopLifecycle(db);
90
+ this.#lifecycle = lifecycle;
94
91
  this.#resourceMutations = new ResourceMutations({
95
92
  schemes,
96
93
  liveSubscriptions,
97
94
  run: (schemeName, statement, ctx) => this.#dataRun.run(schemeName, statement, ctx),
98
- checkWritable: (statement, origin, workerId) => this.#checkWritable(statement, origin, workerId),
99
- checkCapabilities: (statement, workspaceId, loopId, workerId) => this.#checkCapabilities(statement, workspaceId, loopId, workerId),
95
+ checkWritable: (statement, origin, workspaceId) => this.#checkWritable(statement, origin, workspaceId),
96
+ checkCapabilities: (statement, ctx) => this.#checkCapabilities(statement, ctx),
100
97
  editTargetIdentity: (statement, workspaceId, workerId) => this.#editTargetIdentity(statement, workspaceId, workerId),
101
98
  canonicalFilePath: (pathname, workspaceId) => this.#canonicalFilePath(pathname, workspaceId),
102
99
  prepareDataRepresentation: (args) => this.#prepareDataRepresentation({
@@ -109,11 +106,11 @@ class Dispatcher {
109
106
  deleteChannel: (scheme, address, channel, ctx) => this.#deleteChannel(scheme, address, channel, ctx),
110
107
  applyProposal: (statement, result, resolution, ids) => this.#proposals.workerApply(statement, result, resolution, ids),
111
108
  });
112
- this.#workerControl = new WorkerControlHandler({ db: this.#db, schemes: this.#schemes, failure: _a.#failure });
109
+ this.#workerControl = new WorkerControlHandler({ db: this.#db, failure: _a.#failure });
113
110
  this.#kill = new KillHandler({ db: this.#db, schemes: this.#schemes, liveSubscriptions: this.#liveSubscriptions, cancelWorker: this.#cancelWorker, resolveDataEntryAddress: this.#resolveDataEntryAddress.bind(this), boundEntryContext: this.#boundEntryContext.bind(this), handlerContext: this.#handlerContext.bind(this), deleteEntry: this.#deleteEntry.bind(this), failure: _a.#failure });
114
- this.#sendBroadcast = new SendBroadcastHandler({ db: this.#db, cancelDescendants: this.#cancelDescendants, parkDeadlines: this.#parkDeadlines, joinTargets: this.#joinTargets, lifecycle: this.#lifecycle, nextPacketBoundaries: this.#nextPacketBoundaries.bind(this), unobservedFailureCount: this.#unobservedFailureCount.bind(this), pendingSet: this.#pendingSet.bind(this), hasLiveWork: this.hasLiveWork.bind(this), failure: _a.#failure, statusResult: _a.#statusResult, unobservedFailures: _a.#unobservedFailures });
111
+ this.#disposition = new TurnDispositionHandler({ db: this.#db, cancelDescendants: this.#cancelDescendants, lifecycle: this.#lifecycle, nextPacketBoundaries: this.#nextPacketBoundaries.bind(this), unobservedFailureCount: this.#unobservedFailureCount.bind(this), pendingSet: this.#pendingSet.bind(this), hasLiveWork: this.hasLiveWork.bind(this), failure: _a.#failure, statusResult: _a.#statusResult, unobservedFailures: _a.#unobservedFailures });
115
112
  this.#logWriter = new LogWriter({ db: this.#db, weighContent: this.#weighContent, extractTarget: this.#extractTarget.bind(this), canonColumns: this.#canonColumns.bind(this), signalToJson: this.#signalToJson.bind(this), isProposal: _a.#isProposal });
116
- this.#dataRun = new DataStatementRunner({ schemes: this.#schemes, liveSubscriptions: this.#liveSubscriptions, resolveDataEntryAddress: this.#resolveDataEntryAddress.bind(this), fixedEntryOwnerId: this.#fixedEntryOwnerId.bind(this), prepareDataRepresentation: this.#prepareDataRepresentation.bind(this), failure: _a.#failure });
113
+ this.#dataRun = new DataStatementRunner({ schemes: this.#schemes, liveSubscriptions: this.#liveSubscriptions, resolveDataEntryAddress: this.#resolveDataEntryAddress.bind(this), prepareDataRepresentation: this.#prepareDataRepresentation.bind(this), failure: _a.#failure });
117
114
  }
118
115
  // workspace → project_root, memoized: {§fs-namespace} fixes the root immutably at
119
116
  // workspace creation, so a process-lifetime cache can never go stale.
@@ -121,36 +118,31 @@ class Dispatcher {
121
118
  evictWorkspaceCache(workspaceId) {
122
119
  this.#rootCache.delete(workspaceId);
123
120
  }
124
- async #fixedEntryOwnerId(manifest, ctx) {
125
- return this.#entryAddresses.fixedOwnerId(manifest, ctx);
126
- }
127
121
  async #handlerContext(scheme, ctx, authority = "") {
128
- const manifest = this.#schemes.manifestFor(scheme, ctx.functionalityWorkerId);
122
+ const manifest = this.#schemes.manifestFor(scheme, ctx.workspaceId);
129
123
  return manifest === undefined
130
124
  ? null
131
125
  : new SchemeCtxImpl(ctx, scheme, manifest, this.#liveSubscriptions, {
132
126
  authority,
133
- ownerId: await this.#fixedEntryOwnerId(manifest, ctx),
134
127
  });
135
128
  }
136
129
  #boundEntryContext(routedScheme, address, ctx) {
137
- const manifest = this.#schemes.manifestFor(routedScheme, ctx.functionalityWorkerId);
130
+ const manifest = this.#schemes.manifestFor(routedScheme, ctx.workspaceId);
138
131
  return manifest?.category === "data"
139
132
  ? new SchemeCtxImpl(ctx, address.scheme, manifest, this.#liveSubscriptions, {
140
133
  authority: address.authority,
141
- ownerId: address.ownerId,
142
134
  })
143
135
  : null;
144
136
  }
145
- #coreCrud(scheme, workerId) {
146
- const handler = this.#schemes.get(scheme, workerId);
137
+ #coreCrud(scheme, workspaceId) {
138
+ const handler = this.#schemes.get(scheme, workspaceId);
147
139
  return handler instanceof CoreSchemeAdapterBase
148
140
  ? handler
149
141
  : undefined;
150
142
  }
151
143
  async #readEntry(scheme, address, ctx) {
152
144
  const { pathname } = address;
153
- const handler = this.#coreCrud(scheme, ctx.functionalityWorkerId);
145
+ const handler = this.#coreCrud(scheme, ctx.workspaceId);
154
146
  const handlerCtx = this.#boundEntryContext(scheme, address, ctx);
155
147
  if (typeof handler?.readEntry === "function" && handlerCtx !== null) {
156
148
  return Results.assert(await handler.readEntry(pathname, handlerCtx));
@@ -180,7 +172,7 @@ class Dispatcher {
180
172
  }
181
173
  async #writeEntry(scheme, address, entry, ctx) {
182
174
  const { pathname } = address;
183
- const handler = this.#coreCrud(scheme, ctx.functionalityWorkerId);
175
+ const handler = this.#coreCrud(scheme, ctx.workspaceId);
184
176
  const handlerCtx = this.#boundEntryContext(scheme, address, ctx);
185
177
  if (typeof handler?.writeEntry === "function" && handlerCtx !== null) {
186
178
  return Results.assert(await handler.writeEntry(pathname, entry, handlerCtx));
@@ -198,7 +190,7 @@ class Dispatcher {
198
190
  }
199
191
  async #deleteEntry(scheme, address, ctx) {
200
192
  const { pathname } = address;
201
- const handler = this.#coreCrud(scheme, ctx.functionalityWorkerId);
193
+ const handler = this.#coreCrud(scheme, ctx.workspaceId);
202
194
  const handlerCtx = this.#boundEntryContext(scheme, address, ctx);
203
195
  if (typeof handler?.deleteEntry === "function" && handlerCtx !== null) {
204
196
  return Results.assert(await handler.deleteEntry(pathname, handlerCtx));
@@ -216,7 +208,7 @@ class Dispatcher {
216
208
  }
217
209
  async #deleteChannel(scheme, address, channel, ctx) {
218
210
  const { pathname } = address;
219
- const handler = this.#coreCrud(scheme, ctx.functionalityWorkerId);
211
+ const handler = this.#coreCrud(scheme, ctx.workspaceId);
220
212
  const handlerCtx = this.#boundEntryContext(scheme, address, ctx);
221
213
  if (typeof handler?.deleteChannel === "function" && handlerCtx !== null) {
222
214
  return Results.assert(await handler.deleteChannel(pathname, channel, handlerCtx));
@@ -254,31 +246,23 @@ class Dispatcher {
254
246
  async #canonicalFilePath(pathname, workspaceId) {
255
247
  return Namespace.canonicalizeSpelling(pathname, await this.#workspaceRoot(workspaceId));
256
248
  }
257
- async #editTargetIdentity(statement, workspaceId, workerId) {
258
- const target = this.#extractTarget(statement.target, workerId);
249
+ async #editTargetIdentity(statement, workspaceId, _workerId) {
250
+ const target = this.#extractTarget(statement.target, workspaceId);
259
251
  await this.#canonColumns(target, workspaceId);
260
- return {
261
- key: JSON.stringify([
262
- schemeNameOf(statement.target),
263
- target.scheme,
264
- target.hostname,
265
- target.pathname,
266
- target.fragment,
267
- ]),
268
- identity: renderTarget(target),
269
- };
252
+ return renderTarget(target);
270
253
  }
271
254
  // {§kill-scope-entry} — a scoped KILL on an entry-bearing scheme is one EDIT with an empty
272
255
  // body over the same marker: prepared, gated, and merged as an EDIT while its log row
273
256
  // records the model's KILL. Schemes that implement kill() (streams) take the scope themselves;
274
257
  // the log's scoped KILL is curation.
275
258
  #scopedEntryEdits = new WeakMap();
276
- #scopedEntryEdit(statement, functionalityWorkerId) {
259
+ #scopedEntryEdit(statement, workspaceId) {
277
260
  if (statement.op === "EDIT")
278
261
  return statement;
279
- // A body pattern is a log selector; a scoped KILL carrying one is not an EDIT — the KILL
280
- // handler refuses it ({§kill-scope-entry}).
281
- if (statement.op !== "KILL" || statement.lineMarker === null || statement.body !== null)
262
+ // {§kill-scope-entry} a scoped KILL of an entry empties the span; {§kill-pattern} a KILL with
263
+ // a matcher removes every whole line the pattern selects, inside its scope when one is given.
264
+ // Both are emptying EDITs; the log and every scheme with its own kill() keep their own path.
265
+ if (statement.op !== "KILL" || (statement.lineMarker === null && statement.matcher === null))
282
266
  return null;
283
267
  const cached = this.#scopedEntryEdits.get(statement);
284
268
  if (cached !== undefined)
@@ -286,33 +270,29 @@ class Dispatcher {
286
270
  const schemeName = schemeNameOf(statement.target);
287
271
  if (schemeName === null || schemeName === "log")
288
272
  return null;
289
- const handler = this.#schemes.get(schemeName, functionalityWorkerId);
273
+ const handler = this.#schemes.get(schemeName, workspaceId);
290
274
  if (handler === undefined || typeof handler.kill === "function")
291
275
  return null;
292
276
  const edit = {
293
277
  op: "EDIT",
294
- delimiter: statement.delimiter,
295
- annotation: statement.annotation,
278
+ aside: statement.aside,
296
279
  metadata: statement.metadata,
297
280
  target: statement.target,
298
281
  lineMarker: statement.lineMarker,
282
+ matcher: statement.matcher,
299
283
  body: "",
300
284
  position: statement.position,
301
285
  };
302
286
  this.#scopedEntryEdits.set(statement, edit);
287
+ if (statement.matcher !== null)
288
+ this.#resourceMutations.markLineDeletion(edit);
303
289
  return edit;
304
290
  }
305
- async prepareEditBatches(statements, context) {
306
- const { workspaceId, workerId, functionalityWorkerId, loopId, turnId, origin } = context;
307
- const schemeCtx = this.#buildSchemeCtx({ workspaceId, workerId, functionalityWorkerId, loopId, turnId, origin });
308
- const edits = statements.flatMap((statement) => {
309
- const edit = this.#scopedEntryEdit(statement, schemeCtx.functionalityWorkerId);
310
- return edit === null ? [] : [edit];
311
- });
312
- await this.#resourceMutations.prepareEditBatches(edits, context, schemeCtx);
313
- }
314
291
  async dispatch(context) {
315
- let result = await this.#dispatchOne(context);
292
+ if (context.statement.op === "READ" && _a.#globTarget(context.statement.target)) {
293
+ return this.#fanOutRead(context, context.statement);
294
+ }
295
+ let result = await ResourceBindings.using(this.#schemes, this.#buildSchemeCtx(context), (ctx) => this.#dispatchOne(context, ctx));
316
296
  const edit = context.statement.op === "EDIT" ? context.statement : this.#scopedEntryEdits.get(context.statement);
317
297
  if (edit !== undefined) {
318
298
  // {§edit-batch-merges} — a proposal's apply result replaces the projected one; the
@@ -322,15 +302,65 @@ class Dispatcher {
322
302
  }
323
303
  return result;
324
304
  }
325
- async #dispatchOne(context) {
305
+ static #globTarget(target) {
306
+ return target !== null && PathSyntax.hasGlob(target.kind === "url" ? target.pathname : target.raw);
307
+ }
308
+ // {§read-fan-out} — a READ over a glob reads every matching path: the paths come from the
309
+ // ordinary FIND over the same target (unlogged; a matcher FIND when there is one, the catalog
310
+ // otherwise; its resource page bounds the fan-out), and each is read as an ordinary exact READ
311
+ // with the authored scope and matcher and its own receipt row, so every rendered line keeps its
312
+ // path, ordinal and anchor. No path: one 204 receipt on the authored glob. A resource dialect
313
+ // (`~`, `&`) selects resources, not lines, so that READ is the FIND survey.
314
+ async #fanOutRead(context, statement) {
315
+ const survey = {
316
+ op: "FIND", aside: statement.aside, target: statement.target, metadata: statement.metadata,
317
+ matcher: statement.matcher, lineMarker: null, body: null, position: statement.position,
318
+ };
319
+ if (statement.matcher?.dialect === "fts" || statement.matcher?.dialect === "graph") {
320
+ return this.dispatch({ ...context, statement: survey });
321
+ }
322
+ const found = await ResourceBindings.using(this.#schemes, this.#buildSchemeCtx(context), (ctx) => this.#dataRun.run(schemeNameOf(statement.target), survey, ctx));
323
+ const paths = found.status < 300
324
+ ? (found.results ?? []).flatMap((item) => Array.isArray(item) && !("items" in item[0]) ? [item[0].path] : [])
325
+ : [];
326
+ if (paths.length === 0) {
327
+ const result = found.status >= 400 ? found : Results.assert(statement.matcher === null
328
+ ? { status: 204, detail: `No path matched ${statement.target.raw}.` }
329
+ : { status: 204, matched: 0, matcher: statement.matcher.raw, detail: `No line under ${statement.target.raw} matched the pattern.` });
330
+ const logEntryId = await this.#logWriter.writeLog({
331
+ statement, result, workspaceId: context.workspaceId, workerId: context.workerId, loopId: context.loopId,
332
+ turnId: context.turnId, sequence: context.sequence, origin: context.origin, curationPlan: null, modelCallId: null,
333
+ });
334
+ context.onDispatch?.(logEntryId);
335
+ return result;
336
+ }
337
+ const results = [];
338
+ for (const [index, path] of paths.entries()) {
339
+ const target = parsePath(path);
340
+ if (target === null)
341
+ throw new InvalidOperationResultError(`FIND named an unparseable path: ${path}`);
342
+ results.push(await this.dispatch({ ...context, statement: { ...statement, target }, sequence: context.sequence + index }));
343
+ }
344
+ const matchingPathCount = typeof found.matchingPathCount === "number" ? found.matchingPathCount : paths.length;
345
+ if (matchingPathCount > paths.length) {
346
+ this.#notices.push(context.workspaceId, context.workerId, context.loopId, {
347
+ source: "engine:dispatcher",
348
+ kind: "read_fanout_bounded",
349
+ level: "warn",
350
+ message: `READ ${statement.target.raw} matched ${matchingPathCount} paths; the first ${paths.length} were read. Narrow the glob, or FIND first.`,
351
+ });
352
+ }
353
+ return Results.assert({ ...(results.find(({ status }) => status >= 400) ?? results[results.length - 1]), rowsWritten: results.length });
354
+ }
355
+ async #dispatchOne(context, schemeCtx) {
326
356
  const { statement, workspaceId, workerId, loopId, turnId, sequence, origin, onDispatch, onSettled, } = context;
327
- const schemeCtx = this.#buildSchemeCtx({ workspaceId, workerId, functionalityWorkerId: context.functionalityWorkerId, loopId, turnId, origin });
328
- const { functionalityWorkerId } = schemeCtx;
329
357
  let result;
330
358
  let curationPlan = null;
331
- let denial = this.#checkWritable(statement, origin, functionalityWorkerId);
332
- if (denial === null)
333
- denial = await this.#checkCapabilities(statement, workspaceId, loopId, functionalityWorkerId);
359
+ // {§send-prompt-acceptance} — a model SEND addressed to one of this loop's own prompts
360
+ // means what an untargeted SEND means; the address the packet showed it is accepted.
361
+ const ownPrompt = statement.op === "SEND" && origin === "model" && await this.#isOwnPromptAddress(statement.target, workerId, loopId);
362
+ const denial = ownPrompt ? null : (this.#checkWritable(statement, origin, workspaceId)
363
+ ?? await this.#checkCapabilities(statement, schemeCtx));
334
364
  if (denial !== null) {
335
365
  result = denial;
336
366
  }
@@ -342,16 +372,20 @@ class Dispatcher {
342
372
  // those are system failures.
343
373
  try {
344
374
  if (statement.op === "EDIT") {
345
- result = await this.#resourceMutations.preparedEditResult(statement);
375
+ result = await this.#resourceMutations.edit(statement, schemeCtx, context.editSequence);
376
+ }
377
+ else if (statement.op === "SEND" && (statement.target === null || ownPrompt)) {
378
+ result = await this.#respond(statement, schemeCtx, origin, workerId, loopId);
346
379
  }
347
- else if (statement.op === "SEND" && statement.target === null) {
348
- result = await this.#sendBroadcast.handleSendBroadcast(statement, {
380
+ else if (TurnDisposition.is(statement)) {
381
+ result = await this.#disposition.handle(statement, {
349
382
  workspaceId,
350
383
  workerId,
351
384
  loopId,
352
385
  turnId,
353
386
  sequence,
354
387
  origin,
388
+ allowUnobservedRetrievalCompletion: context.allowUnobservedRetrievalCompletion,
355
389
  });
356
390
  }
357
391
  else if (statement.op === "KILL" && schemeNameOf(statement.target) === "log") {
@@ -360,7 +394,9 @@ class Dispatcher {
360
394
  curationPlan = curation.plan;
361
395
  }
362
396
  else if (statement.op === "FORK" || statement.op === "WORK") {
363
- result = await this.#workerControl.handleWorkerControl(statement, schemeCtx);
397
+ // {§worker-spawn-prompt-resource} — a non-address path is the child's prompt resource.
398
+ const seeded = await this.#seedSpawnPrompt(statement, schemeCtx);
399
+ result = "result" in seeded ? seeded.result : await this.#workerControl.handleWorkerControl(seeded.statement, schemeCtx);
364
400
  }
365
401
  else if (statement.op === "COPY") {
366
402
  result = await this.#resourceMutations.handleCopy(statement, schemeCtx);
@@ -368,15 +404,12 @@ class Dispatcher {
368
404
  else if (statement.op === "MOVE") {
369
405
  result = await this.#resourceMutations.handleMove(statement, schemeCtx);
370
406
  }
371
- else if (statement.op === "KILL" && this.#scopedEntryEdits.has(statement)) {
372
- result = await this.#resourceMutations.preparedEditResult(this.#scopedEntryEdits.get(statement));
407
+ else if (statement.op === "KILL" && this.#scopedEntryEdit(statement, workspaceId) !== null) {
408
+ result = await this.#resourceMutations.edit(this.#scopedEntryEdits.get(statement), schemeCtx, context.editSequence);
373
409
  }
374
410
  else if (statement.op === "KILL") {
375
411
  result = await this.#kill.handleKill(statement, schemeCtx);
376
412
  }
377
- else if (statement.op === "PLAN") {
378
- result = this.#handlePlan(statement);
379
- }
380
413
  else if (statement.op === "EXEC") {
381
414
  // EXEC routes unconditionally to its operation owner after
382
415
  // the shared capability resolver admits its runtime/tool.
@@ -395,7 +428,7 @@ class Dispatcher {
395
428
  else {
396
429
  const scheme = schemeNameOf(primaryTargetOf(statement));
397
430
  console.error(`Scheme '${scheme ?? "unknown"}' ${statement.op} threw outside its operation result contract:`, err);
398
- result = _a.#failure("scheme-handler-threw", 500, `The '${scheme ?? "unknown"}' scheme did not produce a ${statement.op} result.`, {}, {
431
+ result = _a.#failure("scheme-handler-threw", 500, `The '${scheme ?? "unknown"}' scheme did not produce a result for ${statement.op}.`, {}, {
399
432
  stage: "scheme-dispatch",
400
433
  scheme,
401
434
  operation: statement.op,
@@ -407,12 +440,9 @@ class Dispatcher {
407
440
  // successful receipts while the exact state effects remain durable.
408
441
  // A running-worker READ arms this turn's blocking collect.
409
442
  // {§join-blocking-collect}
410
- if (typeof result.awaitWorker === "string")
411
- this.#joinTargets.add(loopId);
412
443
  const logEntryId = await this.#logWriter.writeLog({
413
444
  statement,
414
445
  result,
415
- functionalityWorkerId,
416
446
  workspaceId,
417
447
  workerId,
418
448
  loopId,
@@ -424,8 +454,8 @@ class Dispatcher {
424
454
  });
425
455
  onDispatch?.(logEntryId);
426
456
  // Proposal lifecycle (SPEC.md {§engine-rails} + {§methods-proposal-resolve}; {§proposal-202-pauses}). When a
427
- // side-effecting op returns status 202 (a broadcast SEND signal 202 park is model
428
- // speech, not a proposal — #isProposal), the entry is written
457
+ // side-effecting op returns status 202 (a waiting TASK parks rather
458
+ // than proposing — #isProposal), the entry is written
429
459
  // state='proposed'; dispatch then PAUSES on a per-entry waiter until
430
460
  // resolution arrives via Engine.resolveProposal (from a client-interface resume,
431
461
  // core-owned disposition, or timeout). The post-resolution status replaces 202 in the
@@ -436,20 +466,21 @@ class Dispatcher {
436
466
  // that exact fact here; no human gate or loop/proposal notification.
437
467
  const effect = result.attrs?.effect;
438
468
  let autoAccept = false;
439
- if (statement.op === "EXEC") {
469
+ if (statement.op === "EXEC" || (statement.op === "SEND"
470
+ && this.#schemes.isRuntimeScheme(schemeNameOf(statement.target) ?? "", workspaceId))) {
440
471
  if (!EffectPolicy.isEffect(effect)) {
441
- throw new InvalidOperationResultError("EXEC proposal omitted its canonical effect fact.");
472
+ throw new InvalidOperationResultError("Execution proposal omitted its canonical effect fact.");
442
473
  }
443
474
  autoAccept = EffectPolicy.decide(effect) === "auto";
444
475
  }
445
476
  if (autoAccept) {
446
- const initialSettlement = await this.#proposals.workerApply(statement, result, { decision: "accept" }, { workspaceId, workerId, functionalityWorkerId, loopId, turnId });
477
+ const initialSettlement = await this.#proposals.workerApply(statement, result, { decision: "accept" }, { workspaceId, workerId, loopId, turnId });
447
478
  const effective = await this.#resourceMutations.settleProposal({
448
479
  statement,
449
480
  result,
450
481
  settlement: initialSettlement,
451
482
  ctx: schemeCtx,
452
- ids: { workspaceId, workerId, functionalityWorkerId, loopId, turnId },
483
+ ids: { workspaceId, workerId, loopId, turnId },
453
484
  });
454
485
  const post = await this.#proposals.applyResolution(logEntryId, effective);
455
486
  await onSettled?.(logEntryId);
@@ -481,13 +512,13 @@ class Dispatcher {
481
512
  // file, spawns the process, etc.). Its operation result is
482
513
  // preserved: an apply failure keeps its original status and
483
514
  // Problem Details instead of masquerading as a client rejection.
484
- const initialSettlement = await this.#proposals.workerApply(statement, result, resolution, { workspaceId, workerId, functionalityWorkerId, loopId, turnId });
515
+ const initialSettlement = await this.#proposals.workerApply(statement, result, resolution, { workspaceId, workerId, loopId, turnId });
485
516
  const effective = await this.#resourceMutations.settleProposal({
486
517
  statement,
487
518
  result,
488
519
  settlement: initialSettlement,
489
520
  ctx: schemeCtx,
490
- ids: { workspaceId, workerId, functionalityWorkerId, loopId, turnId },
521
+ ids: { workspaceId, workerId, loopId, turnId },
491
522
  });
492
523
  const post = await this.#proposals.applyResolution(logEntryId, effective);
493
524
  await onSettled?.(logEntryId);
@@ -506,14 +537,21 @@ class Dispatcher {
506
537
  if (statement.op !== "READ")
507
538
  throw new Error(`look resolves READ only; got ${statement.op}`);
508
539
  // turnId is a write-time FK only — a look writes no row, so 0 (no turn) is inert.
509
- const schemeCtx = this.#buildSchemeCtx({ workspaceId, workerId, functionalityWorkerId: context.functionalityWorkerId, loopId, turnId: 0, origin });
510
- const denial = await this.#checkCapabilities(statement, schemeCtx.workspaceId, loopId, schemeCtx.functionalityWorkerId);
511
- if (denial !== null)
512
- return denial;
513
- return this.#dataRun.run(schemeNameOf(statement.target), statement, schemeCtx);
540
+ const schemeCtx = this.#buildSchemeCtx({ workspaceId, workerId, loopId, turnId: 0, origin });
541
+ return ResourceBindings.using(this.#schemes, schemeCtx, async (ctx) => {
542
+ try {
543
+ const denial = await this.#checkCapabilities(statement, ctx);
544
+ return denial ?? await this.#dataRun.run(schemeNameOf(statement.target), statement, ctx);
545
+ }
546
+ catch (error) {
547
+ if (error instanceof OperationFailureError)
548
+ return error.result;
549
+ throw error;
550
+ }
551
+ });
514
552
  }
515
- capabilityProjection(workspaceId, workerId) {
516
- return this.#capabilities.projection(workspaceId, workerId);
553
+ capabilityProjection(workspaceId) {
554
+ return this.#capabilities.projection(workspaceId);
517
555
  }
518
556
  // Resolve the client selector through the owning scheme before persistence
519
557
  // is consulted. Public schemes choose a semantic owner; core-owned authority
@@ -523,7 +561,6 @@ class Dispatcher {
523
561
  const coreCtx = this.#buildSchemeCtx({
524
562
  workspaceId,
525
563
  workerId,
526
- functionalityWorkerId: context.functionalityWorkerId,
527
564
  loopId: 0,
528
565
  turnId: 0,
529
566
  origin: "client",
@@ -539,7 +576,6 @@ class Dispatcher {
539
576
  if (rendered === null)
540
577
  throw new TypeError("Resolved entry target did not render.");
541
578
  return {
542
- ownerId: resolved.address.ownerId,
543
579
  scheme: resolved.address.scheme,
544
580
  authority: resolved.address.authority,
545
581
  pathname: resolved.address.pathname,
@@ -550,23 +586,32 @@ class Dispatcher {
550
586
  const routedScheme = schemeNameOf(target);
551
587
  if (routedScheme === null)
552
588
  return null;
553
- const handler = this.#schemes.get(routedScheme, ctx.functionalityWorkerId);
554
- const manifest = this.#schemes.manifestFor(routedScheme, ctx.functionalityWorkerId);
555
- if (handler === undefined || manifest?.category !== "data")
556
- return null;
557
- return this.#resolveDataEntryAddress({ target, routedScheme, handler, manifest, ctx });
589
+ return ResourceBindings.using(this.#schemes, ctx, async (boundCtx) => {
590
+ try {
591
+ const binding = await ResourceBindings.resolve(target, boundCtx);
592
+ if (binding?.manifest.category !== "data")
593
+ return null;
594
+ return this.#resolveDataEntryAddress({ target, routedScheme,
595
+ handler: binding.handler, manifest: binding.manifest, ctx: boundCtx });
596
+ }
597
+ catch (error) {
598
+ if (error instanceof OperationFailureError)
599
+ return { address: null, result: error.result };
600
+ throw error;
601
+ }
602
+ });
558
603
  }
559
- async #resolveDataEntryAddress({ target, routedScheme, handler, manifest, ctx, }) {
604
+ async #resolveDataEntryAddress({ target, routedScheme, handler, manifest, ctx, access = "read", }) {
560
605
  if (manifest.category !== "data") {
561
606
  throw new TypeError(`Scheme '${routedScheme}' is not entry-bearing.`);
562
607
  }
563
- return this.#entryAddresses.resolve({ target, routedScheme, handler, manifest, ctx });
608
+ return this.#entryAddresses.resolve({ target, routedScheme, handler, manifest, ctx, access });
564
609
  }
565
610
  async #prepareDataRepresentation({ target, metadata, routedScheme, handler, manifest, ctx, publishedChannel, resolved: priorResolution, }) {
566
611
  if (metadata !== null && manifest.metadataModifier !== true) {
567
612
  return {
568
613
  address: null,
569
- result: _a.#failure("scheme-metadata-unsupported", 400, `Scheme '${routedScheme}' does not accept the {metadata} modifier.`, {}, { scheme: routedScheme, retryable: false }),
614
+ result: _a.#failure("scheme-metadata-unsupported", 400, `Scheme '${routedScheme}' does not accept the [metadata] modifier.`, {}, { scheme: routedScheme, retryable: false }),
570
615
  };
571
616
  }
572
617
  const resolved = priorResolution ?? await this.#resolveDataEntryAddress({
@@ -587,7 +632,6 @@ class Dispatcher {
587
632
  : target;
588
633
  const preparationCtx = new SchemeCtxImpl(ctx, target.kind === "url" ? target.scheme : routedScheme, manifest, this.#liveSubscriptions, {
589
634
  authority: address.authority,
590
- ownerId: address.ownerId,
591
635
  publishedChannel,
592
636
  });
593
637
  const prepared = Results.assertRepresentationPreparation(await handler.prepareRepresentation({
@@ -604,16 +648,37 @@ class Dispatcher {
604
648
  // An accepted EXEC reads a non-file source through the same registered
605
649
  // handler and addressed context as an authored READ. {§exec-target-routing}
606
650
  async readExecSource(statement, ctx) {
651
+ return ResourceBindings.using(this.#schemes, ctx, (boundCtx) => this.#readExecSource(statement, boundCtx));
652
+ }
653
+ async #readExecSource(statement, ctx) {
607
654
  const schemeName = schemeNameOf(statement.target);
608
- const manifest = schemeName === null ? undefined : this.#schemes.manifestFor(schemeName, ctx.functionalityWorkerId);
655
+ const binding = await ResourceBindings.resolve(statement.target, ctx);
656
+ const manifest = binding?.manifest;
609
657
  if (manifest !== undefined && manifest.category !== "data") {
610
- return _a.#failure("exec-source-not-data", 501, `Scheme '${schemeName}' is not a data source for EXEC.`, {}, {
611
- scheme: schemeName,
612
- category: manifest.category,
613
- retryable: false,
614
- });
658
+ return { nativePath: null, result: _a.#failure("exec-source-not-data", 501, `Scheme '${schemeName}' is not a data source for EXEC.`, {}, {
659
+ scheme: schemeName,
660
+ category: manifest.category,
661
+ retryable: false,
662
+ }) };
615
663
  }
616
- return Results.assertReadResult(await this.#dataRun.run(schemeName, statement, ctx));
664
+ const result = Results.assertReadResult(await this.#dataRun.run(schemeName, statement, ctx));
665
+ const target = statement.target;
666
+ const handler = binding?.handler;
667
+ const selectedChannel = target?.fragment ?? null;
668
+ if (result.status !== 200 || target === null || handler === undefined || manifest?.category !== "data"
669
+ || (selectedChannel !== null && selectedChannel !== manifest.defaultChannel)) {
670
+ return { result, nativePath: null };
671
+ }
672
+ const resolved = await this.#resolveDataEntryAddress({ target, routedScheme: schemeName, handler, manifest, ctx });
673
+ if (resolved.result !== null)
674
+ return { result: resolved.result, nativePath: null };
675
+ const source = resolved.address === null ? undefined : handler.byteSource?.(resolved.address, EntryAddressBinding.addressContext(ctx));
676
+ if (source?.nativePath === undefined)
677
+ return { result, nativePath: null };
678
+ const nativePath = await source.nativePath();
679
+ if (nativePath === null)
680
+ return { nativePath: null, result: _a.#failure("entry-not-found", 404, "The EXEC source file no longer exists.", {}, { target: target.raw }) };
681
+ return { result, nativePath };
617
682
  }
618
683
  // The one place per-dispatch coordinates are built; a caller that carries no
619
684
  // explicit Functionality coordinate acts in its own Worker's
@@ -621,10 +686,9 @@ class Dispatcher {
621
686
  // PlurnkSchemeContext and never re-derive.
622
687
  #buildSchemeCtx(ids) {
623
688
  const { workspaceId, workerId, loopId, turnId, origin } = ids;
624
- const functionalityWorkerId = ids.functionalityWorkerId ?? workerId;
625
689
  const context = {
626
690
  db: this.#db,
627
- workspaceId, workerId, functionalityWorkerId, loopId, turnId,
691
+ workspaceId, workerId, loopId, turnId,
628
692
  writer: origin,
629
693
  signal: this.#loopSignal(loopId),
630
694
  streamEventNotify: this.#streamEventNotify,
@@ -634,11 +698,10 @@ class Dispatcher {
634
698
  weigh: this.#weighContent,
635
699
  // {§exec-stream} — a runtime scheme's default channel is its own (stdout), never the
636
700
  // catalog fallback `body`; resolved through the same registry the writable gate reads.
637
- defaultChannelFor: (scheme) => this.#schemes.defaultChannelFor(scheme, functionalityWorkerId),
701
+ defaultChannelFor: (scheme) => this.#schemes.defaultChannelFor(scheme, context.workspaceId),
638
702
  settleDerivations: () => this.#settleDerivations(context),
639
- settleVectors: (hashes) => this.#settleVectors(context, hashes),
640
703
  pushNotice: (notice) => this.#notices.push(workspaceId, workerId, loopId, notice),
641
- requestInteraction: (request) => this.#interactions.request(request, { workspaceId, workerId, loopId, turnId }, this.#loopSignal(loopId)),
704
+ requestInteraction: (request, signal = this.#loopSignal(loopId)) => this.#interactions.request(request, { workspaceId, workerId, loopId, turnId }, signal),
642
705
  executors: this.#executors(),
643
706
  };
644
707
  return context;
@@ -649,40 +712,38 @@ class Dispatcher {
649
712
  // - SEND broadcast (path=null) has no target scheme; not gated.
650
713
  // - COPY: dst scheme writableBy applies.
651
714
  // - MOVE: both src (delete) and dst (write) schemes' writableBy apply.
652
- #checkWritable(statement, origin, functionalityWorkerId) {
653
- const workerId = functionalityWorkerId;
715
+ #checkWritable(statement, origin, workspaceId) {
654
716
  if (!MUTATING_OPS.has(statement.op))
655
717
  return null;
656
- if (statement.op === "SEND" && statement.target === null)
718
+ if (TurnDisposition.is(statement) || statement.op === "SEND" && statement.target === null)
657
719
  return null;
658
720
  // EXEC's operation authority always belongs to the exec scheme;
659
721
  // runtime-specific resource authority is gated separately below.
660
722
  if (statement.op === "EXEC") {
661
- return this.#denyIfDisallowed("exec", origin, workerId);
723
+ return this.#denyIfDisallowed("exec", origin, workspaceId);
662
724
  }
663
- // {§stream-control} — a KILL of a runtime stream terminates the caller's own process; it
664
- // writes nothing into that read-only output scheme (writableBy plugin), so the writer rule
665
- // does not speak. Exec.kill scopes the stream to the caller ({§stream-owner-scoped}).
666
- if (statement.op === "KILL") {
725
+ // {§stream-control}, {§exec-input}: process control is not a write to
726
+ // stored output. The workspace execution binding owns KILL and SEND.
727
+ if (statement.op === "KILL" || statement.op === "SEND") {
667
728
  const target = schemeNameOf(statement.target);
668
- if (target !== null && this.#schemes.isRuntimeScheme(target, workerId))
729
+ if (target !== null && this.#schemes.isRuntimeScheme(target, workspaceId))
669
730
  return null;
670
731
  }
671
732
  // Worker control (FORK/WORK → worker://<name>, spawn or fork) is gated by worker://'s writableBy — its
672
733
  // body is a seed prompt, not a dst path, so the entry-COPY dst-parse below doesn't apply.
673
734
  // {§machine-processes}
674
735
  if (this.#isWorkerControl(statement))
675
- return this.#denyIfDisallowed("worker", origin, workerId);
736
+ return this.#denyIfDisallowed("worker", origin, workspaceId);
676
737
  if (statement.op === "COPY" || statement.op === "MOVE") {
677
738
  const dst = statement.destination.target;
678
739
  const dstScheme = schemeNameOf(dst);
679
- const dstDenial = this.#denyIfDisallowed(dstScheme, origin, workerId);
740
+ const dstDenial = this.#denyIfDisallowed(dstScheme, origin, workspaceId);
680
741
  if (dstDenial !== null)
681
742
  return dstDenial;
682
743
  if (statement.op === "MOVE") {
683
744
  const srcScheme = schemeNameOf(statement.source.target);
684
745
  if (srcScheme !== dstScheme) {
685
- const srcDenial = this.#denyIfDisallowed(srcScheme, origin, workerId);
746
+ const srcDenial = this.#denyIfDisallowed(srcScheme, origin, workspaceId);
686
747
  if (srcDenial !== null)
687
748
  return srcDenial;
688
749
  }
@@ -690,7 +751,7 @@ class Dispatcher {
690
751
  return null;
691
752
  }
692
753
  const target = schemeNameOf(statement.target);
693
- const denial = this.#denyIfDisallowed(target, origin, workerId);
754
+ const denial = this.#denyIfDisallowed(target, origin, workspaceId);
694
755
  // {§send-target-recipient} — SEND addresses recipients, not otherwise
695
756
  // read-only resources. State that boundary without guessing whether the
696
757
  // model intended a reply, deletion, or directed message.
@@ -704,13 +765,13 @@ class Dispatcher {
704
765
  }
705
766
  return denial;
706
767
  }
707
- #denyIfDisallowed(schemeName, origin, workerId) {
768
+ #denyIfDisallowed(schemeName, origin, workspaceId) {
708
769
  if (schemeName === null)
709
770
  return null;
710
- const handler = this.#schemes.get(schemeName, workerId);
771
+ const handler = this.#schemes.get(schemeName, workspaceId);
711
772
  if (handler === undefined)
712
773
  return null;
713
- const manifest = this.#schemes.manifestFor(schemeName, workerId);
774
+ const manifest = this.#schemes.manifestFor(schemeName, workspaceId);
714
775
  if (manifest === undefined)
715
776
  throw new Error(`registered scheme '${schemeName}' has no manifest`);
716
777
  if (manifest.writableBy.includes(origin))
@@ -725,8 +786,9 @@ class Dispatcher {
725
786
  // {§capability-admission} — one resolver gates every operation route before
726
787
  // execution or proposal handling. Unknown routes continue to their ordinary
727
788
  // owner; a known policy denial is one factual, non-presumptuous 403.
728
- async #checkCapabilities(statement, workspaceId, loopId, functionalityWorkerId) {
729
- const denied = await this.#capabilities.denial(statement, workspaceId, functionalityWorkerId, loopId);
789
+ async #checkCapabilities(statement, ctx) {
790
+ await LoopPolicyReader.read(this.#db, ctx.loopId);
791
+ const denied = await this.#capabilities.denial(statement, ctx.workspaceId, ctx.writer, async (target) => (await ResourceBindings.resolve(target, ctx))?.manifest);
730
792
  if (denied === null)
731
793
  return null;
732
794
  const { descriptor, scope } = denied;
@@ -742,19 +804,23 @@ class Dispatcher {
742
804
  retryable: false,
743
805
  });
744
806
  }
807
+ capabilityDenial(statement, ctx) {
808
+ return ResourceBindings.using(this.#schemes, ctx, (boundCtx) => this.#checkCapabilities(statement, boundCtx));
809
+ }
745
810
  // Worker control is FORK/WORK (grammar 0.74.55), not COPY — its body
746
811
  // is the new worker's seed prompt, not a destination path. The COPY gates and ResourceMutations.handleCopy
747
812
  // branch on this so they never parse the prompt as a dst path.
748
813
  #isWorkerControl(statement) {
749
814
  return statement.op === "FORK" || statement.op === "WORK"; // worker control targets worker://<name> (grammar 0.74.55)
750
815
  }
751
- async #writeActionlessEntry({ verbatim, workerId, loopId, turnId, sequence, origin, kind, folded, modelCallId = null, attrs = {} }) {
752
- const durableAttrs = { ...attrs, kind };
816
+ // {§rejected-emission-entry} — rejected provider bytes, never an admitted program.
817
+ async writeEmissionAttempt({ verbatim, workerId, loopId, turnId, sequence, modelCallId }) {
818
+ const durableAttrs = { kind: "emissionAttempt" };
753
819
  const rx = JSON.stringify({ content: verbatim, mimetype: "text/vnd.plurnk" });
754
820
  const row = await this.#db.engine_insert_log_entry.get({
755
821
  worker_id: workerId, loop_id: loopId, turn_id: turnId, sequence,
756
- origin, source: null, model_call_id: modelCallId,
757
- op: null, delimiter: "", signal: null,
822
+ origin: "model", source: null, model_call_id: modelCallId,
823
+ op: null, signal: null,
758
824
  scheme: null, username: null, password: null, hostname: null, port: null,
759
825
  pathname: null, query: null, fragment: null, lineMarker: null,
760
826
  tx: "", mimetype_tx: "text/vnd.plurnk",
@@ -771,49 +837,82 @@ class Dispatcher {
771
837
  }, this.#weighContent),
772
838
  state: "resolved", outcome: null,
773
839
  attrs: JSON.stringify(durableAttrs),
774
- initial_folded: LogVisibility.serialize(folded ? LogVisibility.FOLDED : LogVisibility.OPEN),
840
+ initial_folded: LogVisibility.serialize(LogVisibility.FOLDED),
775
841
  });
776
842
  if (row === undefined)
777
- throw new Error("Dispatcher.#writeActionlessEntry: insert returned no row");
843
+ throw new Error("Dispatcher.writeEmissionAttempt: insert returned no row");
778
844
  return row.id;
779
845
  }
780
- // {§turn-ops-entry} — preserve exact admitted source beside, never instead
781
- // of, the ordinary operation-result rows produced by dispatch.
782
- async writeTurnOps({ verbatim, workerId, loopId, turnId, sequence, origin, folded, modelCallId = null, reasoningItems }) {
783
- return this.#writeActionlessEntry({
784
- verbatim, workerId, loopId, turnId, sequence,
785
- origin, kind: "turnOps", folded, modelCallId,
786
- attrs: {
787
- ...(reasoningItems !== undefined && reasoningItems.length > 0 ? { reasoning: reasoningItems } : {}),
788
- },
789
- });
846
+ // {§worker-spawn-prompt-resource} WORK and FORK overload their slot by scheme: a `worker://`
847
+ // path is always the child's address (and keeps the address rules); a path of any other scheme
848
+ // is read whole and becomes the child's prompt, composed with the body as BARE's combined form.
849
+ // The durable row keeps the authored statement; only the handler sees the composed one, with no
850
+ // target, so the child is auto-named exactly as when the slot is empty.
851
+ async #seedSpawnPrompt(statement, ctx) {
852
+ if (statement.target === null || WorkerControlAddress.isWorkerScheme(statement.target))
853
+ return { statement };
854
+ const read = { ...statement, op: "READ", matcher: null, body: null, lineMarker: { marks: [1, -1] } };
855
+ const denial = await this.#checkCapabilities(read, ctx);
856
+ if (denial !== null)
857
+ return { result: denial };
858
+ const result = Results.assertReadResult(await this.#dataRun.run(schemeNameOf(read.target), read, ctx));
859
+ if (result.status !== 200 && result.status !== 204)
860
+ return { result };
861
+ if (result.content !== null && typeof result.content !== "string") {
862
+ throw new InvalidOperationResultError(`${statement.op} prompt resource READ returned non-text content.`);
863
+ }
864
+ const prompt = [result.content ?? "", statement.body ?? ""].filter((part) => part !== "").join("\n\n");
865
+ if (prompt.trim() === "") {
866
+ return { result: _a.#failure("spawn-prompt-empty", 422, `${statement.op} has no prompt text: the resource is empty and there is no body.`, {}, { retryable: false }) };
867
+ }
868
+ return { statement: { ...statement, target: null, body: prompt } };
790
869
  }
791
- // {§rejected-emission-entry} — provider bytes that fail admission are an
792
- // attempt artifact, never a turn program.
793
- async writeEmissionAttempt({ verbatim, workerId, loopId, turnId, sequence, modelCallId, reasoningItems }) {
794
- return this.#writeActionlessEntry({
795
- verbatim, workerId, loopId, turnId, sequence,
796
- origin: "model", kind: "emissionAttempt", folded: true, modelCallId,
797
- attrs: {
798
- ...(reasoningItems !== undefined && reasoningItems.length > 0 ? { reasoning: reasoningItems } : {}),
799
- },
870
+ // {§bare-inference} Reuse exact READ projection without its log/presentation layer.
871
+ async prepareBarePrompt(context) {
872
+ return ResourceBindings.using(this.#schemes, this.#buildSchemeCtx(context), async (ctx) => {
873
+ try {
874
+ return await this.#prepareBarePrompt(context.statement, ctx);
875
+ }
876
+ catch (error) {
877
+ if (error instanceof OperationFailureError)
878
+ return { result: error.result };
879
+ throw error;
880
+ }
800
881
  });
801
882
  }
802
- // PLAN — one installment of the model's running work journal. An ordinary op: dispatched like any
803
- // other, logged, and broadcast to the client as a log entry — but a pure no-op for
804
- // state (PLAN ∉ MUTATING_OPS); its body serializes into the log row's tx, no effect.
805
- #handlePlan(statement) {
806
- if (statement.op !== "PLAN")
807
- throw new Error("unreachable");
808
- return { status: 200 };
883
+ async #prepareBarePrompt(statement, ctx) {
884
+ const denial = await this.#checkCapabilities(statement, ctx);
885
+ if (denial !== null)
886
+ return { result: denial };
887
+ let resource = "";
888
+ if (statement.target !== null) {
889
+ const read = {
890
+ ...statement,
891
+ op: "READ",
892
+ matcher: null,
893
+ body: null,
894
+ lineMarker: { marks: [1, -1] },
895
+ };
896
+ const result = Results.assertReadResult(await this.#dataRun.run(schemeNameOf(read.target), read, ctx));
897
+ if (result.status !== 200 && result.status !== 204)
898
+ return { result };
899
+ if (typeof result.content === "string")
900
+ resource = result.content;
901
+ else if (result.content !== null) {
902
+ throw new InvalidOperationResultError("BARE source READ returned non-text content.");
903
+ }
904
+ }
905
+ const prompt = [resource, statement.body].filter((part) => part !== "").join("\n\n");
906
+ if (prompt.trim() === "") {
907
+ return { result: _a.#failure("bare-prompt-empty", 422, "BARE has no prompt text.", {}, { retryable: false }) };
908
+ }
909
+ return { prompt };
809
910
  }
810
- // {§bare-inference} Provider work is prepared concurrently by Engine; the
811
- // dispatcher owns only the ordinary operation-result commit and notification.
911
+ // {§bare-inference} Provider work runs concurrently; receipts commit in authored order.
812
912
  async recordBareResult(context, result, modelCallId) {
813
913
  Results.assert(result);
814
914
  const logEntryId = await this.#logWriter.writeLog({
815
915
  ...context,
816
- functionalityWorkerId: context.functionalityWorkerId ?? context.workerId,
817
916
  result,
818
917
  curationPlan: null,
819
918
  modelCallId,
@@ -822,41 +921,103 @@ class Dispatcher {
822
921
  await context.onSettled?.(logEntryId);
823
922
  return result;
824
923
  }
825
- // {§send-premature-terminate} — the unified PENDING SET, judged at the terminal's OWN dispatch
826
- // (post-batch: the emission's earlier ops already executed, so a same-turn KILL+[200] repairs in
827
- // ONE turn, and a same-turn WORK+[200] is caught — the spawn is live by the time the SEND lands).
828
- // pending = open streams ∪ live children ∪ THIS turn's retrievals (READ/FIND/BARE, results unseen
829
- // until next packet). Failed operations are the separate next-packet leg shared by explicit
830
- // completion and empty-join completion. Nothing pending may be silently discarded; 499 discards
831
- // BY STATED INTENT and is never gated.
924
+ // {§send-prompt-acceptance} `prompt://<this worker>/<this loop>/<id>` names a prompt the loop
925
+ // contains; a SEND to it is the response, exactly as if untargeted. Another worker's or
926
+ // another loop's prompt is not a recipient and keeps the ordinary refusal.
927
+ // {§send-response-receipt} — a response names the prompts it answers, so the receipt
928
+ // says where the text went. {§send-looks-like-operation} — a model response whose first
929
+ // line is an operation heading is a mis-fenced operation, not a reply: the 2026-09-11
930
+ // dogfood put four operations on the line after their fences, delivered all four to the
931
+ // user as 200 replies, then waited fifteen minutes for receipts that could never come.
932
+ async #respond(statement, schemeCtx, origin, workerId, loopId) {
933
+ if (origin === "model") {
934
+ const heading = this.#operationHeading(statement.body?.raw ?? "", schemeCtx);
935
+ if (heading !== null) {
936
+ return _a.#failure("send-looks-like-operation", 400, `The response begins with the operation heading \`${heading}\`; nothing ran and nothing was delivered.`, {}, {
937
+ heading,
938
+ stage: "dispatch",
939
+ recovery: `An operation goes on the fence line (\`\`\`\`${heading}); a quoted example goes inside a SEND body.`,
940
+ retryable: false,
941
+ });
942
+ }
943
+ }
944
+ return { status: 200, recipients: await this.#activePrompts(workerId, loopId) };
945
+ }
946
+ // The first non-blank line, when it parses alone as one clean heading naming an operation
947
+ // this worker could perform: a Plurnk operation, or a registered executor or MCP service.
948
+ #operationHeading(body, schemeCtx) {
949
+ const line = body.split("\n").find((candidate) => candidate.trim().length > 0)?.trim();
950
+ if (line === undefined || line.startsWith("`"))
951
+ return null;
952
+ const parsed = PlurnkParser.parseStatements(PlurnkParser.frame(line, null), {
953
+ executors: schemeCtx.executors?.availableRuntimes(schemeCtx.workspaceId) ?? [],
954
+ });
955
+ if (parsed.unparsedTail !== undefined || parsed.items.length !== 1 || parsed.items[0].kind !== "statement")
956
+ return null;
957
+ const { statement } = parsed.items[0];
958
+ // {§naked-pattern} lifts prose after the path on FIND, READ and KILL as a literal matcher;
959
+ // on a reply's first line a multi-word literal is prose, not a mis-fenced operation.
960
+ if ("matcher" in statement && statement.matcher?.dialect === "glob" && /\s/u.test(statement.matcher.raw))
961
+ return null;
962
+ if (statement.op !== "EXEC")
963
+ return line;
964
+ const executor = statement.executor;
965
+ if (executor === null || schemeCtx.executors?.entry(executor, schemeCtx.workspaceId) === undefined)
966
+ return null;
967
+ return line;
968
+ }
969
+ // The loop's Active Prompts, oldest first, exactly as the packet lists them.
970
+ async #activePrompts(workerId, loopId) {
971
+ const worker = await this.#db.worker_get.get({ id: workerId });
972
+ if (worker === undefined)
973
+ throw new Error(`worker ${workerId} does not exist`);
974
+ const loopSeq = (await this.#db.engine_loop_sequence.get({ loop_id: loopId }))?.sequence ?? loopId;
975
+ const prefix = promptLoopPrefix(loopSeq);
976
+ const rows = await this.#db.drain_get_all_prompt_bodies_for_loop.all({
977
+ worker_id: workerId,
978
+ pattern: `${prefix}%`,
979
+ prefix_len: prefix.length,
980
+ });
981
+ return rows.map((row) => `prompt://${worker.name}${row.pathname}`);
982
+ }
983
+ async #isOwnPromptAddress(target, workerId, loopId) {
984
+ if (target === null || target.kind !== "url" || target.scheme !== "prompt")
985
+ return false;
986
+ const worker = await this.#db.worker_get.get({ id: workerId });
987
+ if (worker === undefined || target.hostname !== worker.name)
988
+ return false;
989
+ const loopSeq = (await this.#db.engine_loop_sequence.get({ loop_id: loopId }))?.sequence ?? loopId;
990
+ return target.pathname.startsWith(promptLoopPrefix(loopSeq));
991
+ }
992
+ // {§send-premature-terminate} The pending set is judged at TASK's dispatch point,
993
+ // after earlier operations have executed. Every non-SEND/TASK/KILL model operation
994
+ // requires a new packet, independently of its result or log visibility.
832
995
  async #pendingSet(workerId, turnId) {
833
996
  const pending = [];
834
- const execHandler = this.#schemes.get("exec");
835
- // {§exec-timeout} — a `<-1>` spawn outlives the loop and is nobody's obligation.
836
- const openSubs = (await this.#db.find_open_subscriptions_for_worker.all({ worker_id: workerId }))
837
- .filter(({ id }) => execHandler?.isDetachedSpawn?.(id) !== true);
838
- if (openSubs.length > 0 || execHandler?.hasActiveSpawns?.(workerId) === true)
997
+ // {§worker-obligations} — the stream and child legs are one durable row.
998
+ const held = await this.#db.worker_live_obligations.get({ worker_id: workerId });
999
+ if (held === undefined)
1000
+ throw new Error(`worker ${workerId} does not exist`);
1001
+ if (held.streams === 1)
839
1002
  pending.push("streams");
840
- const liveChild = await this.#db.engine_worker_has_live_child.get({ worker_id: workerId });
841
- if (liveChild !== undefined)
1003
+ if (held.workers === 1)
842
1004
  pending.push("workers");
843
1005
  const boundaries = await this.#nextPacketBoundaries(workerId, turnId);
844
- if (boundaries.retrievals)
1006
+ const receipts = [...new Set(boundaries.operations
1007
+ .filter(({ op }) => op !== "KILL")
1008
+ .map((row) => LogEntryProjection.leaf(row)))];
1009
+ if (boundaries.streamTerminations.length > 0)
1010
+ receipts.push("stream completion");
1011
+ if (receipts.length > 0)
845
1012
  pending.push("receipts");
846
- // A stream that closed successfully is banked, not pending: concluding on its own
847
- // success is legitimate and its output stays in the Log. A failed close is an unseen
848
- // failure — named exactly (bench#5 requiem #9) so the model reads it, not guesses.
1013
+ // The final-strike escape hatch cannot discard an unobserved failure.
849
1014
  if (boundaries.streamTerminations.some(({ closeStatus }) => closeStatus >= 400))
850
1015
  pending.push("failed-stream-results");
851
1016
  if (boundaries.childTerminations)
852
1017
  pending.push("worker-results");
853
- return pending;
1018
+ return { pending, receipts };
854
1019
  }
855
- // Results cross an observation boundary only when they have appeared in a packet;
856
- // successful log-curation effects likewise become useful through the curated next packet.
857
- // Keep every next-packet boundary in one classifier while letting the callers apply
858
- // their distinct contracts: retrievals block explicit completion, whereas log curation only
859
- // prevents an empty wait from being inferred as completion.
1020
+ // {§wait-obligation-matrix}: completion and an empty wait use the same execution evidence.
860
1021
  async #nextPacketBoundaries(workerId, turnId) {
861
1022
  const [turnBoundaries, streamTerminations, childTermination] = await Promise.all([
862
1023
  this.#db.engine_turn_packet_boundaries.all({ turn_id: turnId }),
@@ -866,10 +1027,7 @@ class Dispatcher {
866
1027
  .get({ worker_id: workerId }),
867
1028
  ]);
868
1029
  return {
869
- // {§log-kill-scope} — a log KILL is housekeeping: it continues an empty (WAIT) but never
870
- // blocks an explicit (TERM); every other boundary row is a retrieval receipt.
871
- retrievals: turnBoundaries.some(({ op }) => op !== "KILL"),
872
- curations: turnBoundaries.some(({ op }) => op === "KILL"),
1030
+ operations: turnBoundaries,
873
1031
  streamTerminations,
874
1032
  childTerminations: childTermination !== undefined,
875
1033
  };
@@ -883,25 +1041,18 @@ class Dispatcher {
883
1041
  return failedRows.length;
884
1042
  }
885
1043
  static #unobservedFailures(failCount) {
886
- return _a.#failure("unobserved-failures", 409, `This turn produced ${failCount} failed operation result(s) that have not yet entered a packet.`, {}, {
1044
+ return _a.#failure("unobserved-failures", 409, `Completion deferred: ${failCount} operation${failCount === 1 ? "" : "s"} failed in the same turn. The failure${failCount === 1 ? " is" : "s are"} in this packet; address ${failCount === 1 ? "it" : "them"} or complete with a TASK now.`, {}, {
887
1045
  failures: failCount,
888
1046
  stage: "completion",
889
- retryable: false,
1047
+ retryable: true,
890
1048
  });
891
1049
  }
892
- // J — a live obligation to WAIT on: a spawned child or an open stream (NOT retrievals, which land
1050
+ // A live obligation to wait on: a spawned child or an open stream (not retrievals, which land
893
1051
  // next turn regardless). The wait-side twin of #pendingSet's stream+child legs ({§wait-obligation-matrix}).
894
1052
  async hasLiveWork(workerId) {
895
- const execHandler = this.#schemes.get("exec");
896
- // {§exec-timeout} — a `<-1>` spawn outlives the loop and is nobody's obligation.
897
- const openSubs = (await this.#db.find_open_subscriptions_for_worker.all({ worker_id: workerId }))
898
- .filter(({ id }) => execHandler?.isDetachedSpawn?.(id) !== true);
899
- if (openSubs.length > 0)
900
- return true;
901
- if (execHandler?.hasActiveSpawns?.(workerId) === true)
902
- return true;
903
- const liveChild = await this.#db.engine_worker_has_live_child.get({ worker_id: workerId });
904
- return liveChild !== undefined;
1053
+ // {§worker-obligations} — one durable row answers both legs.
1054
+ const held = await this.#db.worker_live_obligations.get({ worker_id: workerId });
1055
+ return held !== undefined && (held.streams === 1 || held.workers === 1);
905
1056
  }
906
1057
  async #runLogCuration(statement, ctx, admittedMaxId) {
907
1058
  const addressedScheme = schemeNameOf(statement.target);
@@ -926,27 +1077,26 @@ class Dispatcher {
926
1077
  if (maxId === undefined) {
927
1078
  throw new Error(`log selection boundary could not be resolved for worker ${ctx.workerId}`);
928
1079
  }
929
- const schemeCtx = new SchemeCtxImpl(ctx, "log", manifest, this.#liveSubscriptions, { ownerId: null });
1080
+ const schemeCtx = new SchemeCtxImpl(ctx, "log", manifest, this.#liveSubscriptions, {});
930
1081
  const outcome = await handler.curate(statement, schemeCtx, maxId);
931
1082
  return { result: Results.assert(outcome.result), plan: outcome.plan };
932
1083
  }
933
- // {§proposal}/{§send} — status 202 is a proposal except for broadcast
934
- // SEND signal 202, which parks the loop. The operation disambiguates the status.
1084
+ // {§proposal}/{§send} — native dispositions park; other 202 results propose.
935
1085
  static #isProposal(statement, result) {
936
1086
  if (result.status !== 202)
937
1087
  return false;
938
- return !(statement.op === "SEND" && statement.target === null);
1088
+ return !TurnDisposition.is(statement);
939
1089
  }
940
1090
  // Normalize a parsed target for log storage. Bare paths and `file:///...`
941
1091
  // inputs collapse to scheme=null in log target metadata because both render
942
1092
  // as bare paths. Addressable file entries separately persist under the
943
1093
  // reserved `file` identity scheme ({§entry-identity-no-null}).
944
- #extractTarget(path, workerId) {
1094
+ #extractTarget(path, workspaceId) {
945
1095
  if (path === null)
946
1096
  return { scheme: null, username: null, password: null, hostname: null, port: null, pathname: null, query: null, fragment: null };
947
1097
  // `local` (bare path) carries no URL parts — store the raw text as the pathname for the log record, scheme=null.
948
1098
  if (path.kind === "local")
949
- return { scheme: null, username: null, password: null, hostname: null, port: null, pathname: PathSyntax.decodeParens(path.raw), query: null, fragment: null }; // {§path-parentheses}
1099
+ return { scheme: null, username: null, password: null, hostname: null, port: null, pathname: PathSyntax.decodeParens(path.raw), query: null, fragment: path.fragment ?? null }; // {§path-parentheses} {§local-path-fragment}
950
1100
  const scheme = path.scheme === "file" ? null : path.scheme;
951
1101
  // The registered scheme owns authority disposition. Namespace authority
952
1102
  // is path syntax; resource and owner authorities remain explicit in the
@@ -954,7 +1104,7 @@ class Dispatcher {
954
1104
  const routedScheme = schemeNameOf(path);
955
1105
  const manifest = routedScheme === null
956
1106
  ? undefined
957
- : this.#schemes.manifestFor(routedScheme, workerId);
1107
+ : this.#schemes.manifestFor(routedScheme, workspaceId);
958
1108
  const foldNs = scheme !== null
959
1109
  && manifest !== undefined
960
1110
  && (manifest.authority ?? "namespace") === "namespace";