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