@plurnk/plurnk-service 1.16.4 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (636) hide show
  1. package/.env.defaults +122 -246
  2. package/INSTALL.md +84 -138
  3. package/README.md +9 -5
  4. package/SPEC.md +1710 -1015
  5. package/dist/Paths.d.ts +2 -0
  6. package/dist/Paths.d.ts.map +1 -1
  7. package/dist/Paths.js +2 -0
  8. package/dist/Paths.js.map +1 -1
  9. package/dist/build-info.d.ts.map +1 -1
  10. package/dist/build-info.js +7 -1
  11. package/dist/build-info.js.map +1 -1
  12. package/dist/build-info.json +1 -1
  13. package/dist/content/body-preview.d.ts +8 -0
  14. package/dist/content/body-preview.d.ts.map +1 -0
  15. package/dist/content/body-preview.js +39 -0
  16. package/dist/content/body-preview.js.map +1 -0
  17. package/dist/content/byte-view.d.ts +1 -4
  18. package/dist/content/byte-view.d.ts.map +1 -1
  19. package/dist/content/byte-view.js.map +1 -1
  20. package/dist/content/edit-collision.d.ts.map +1 -1
  21. package/dist/content/edit-collision.js +3 -4
  22. package/dist/content/edit-collision.js.map +1 -1
  23. package/dist/content/line-anchors.d.ts +2 -2
  24. package/dist/content/line-anchors.d.ts.map +1 -1
  25. package/dist/content/line-anchors.js +4 -3
  26. package/dist/content/line-anchors.js.map +1 -1
  27. package/dist/content/line-selection.d.ts +9 -0
  28. package/dist/content/line-selection.d.ts.map +1 -0
  29. package/dist/content/line-selection.js +29 -0
  30. package/dist/content/line-selection.js.map +1 -0
  31. package/dist/content/matcher.d.ts +0 -1
  32. package/dist/content/matcher.d.ts.map +1 -1
  33. package/dist/content/matcher.js +2 -3
  34. package/dist/content/matcher.js.map +1 -1
  35. package/dist/content/pattern-edits.d.ts +39 -0
  36. package/dist/content/pattern-edits.d.ts.map +1 -0
  37. package/dist/content/pattern-edits.js +121 -0
  38. package/dist/content/pattern-edits.js.map +1 -0
  39. package/dist/content/read-projector.d.ts +18 -9
  40. package/dist/content/read-projector.d.ts.map +1 -1
  41. package/dist/content/read-projector.js +132 -35
  42. package/dist/content/read-projector.js.map +1 -1
  43. package/dist/content/read-resolve.d.ts +3 -1
  44. package/dist/content/read-resolve.d.ts.map +1 -1
  45. package/dist/content/read-resolve.js +39 -7
  46. package/dist/content/read-resolve.js.map +1 -1
  47. package/dist/core/AdmittedTurnExecutor.d.ts +3 -5
  48. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
  49. package/dist/core/AdmittedTurnExecutor.js +91 -83
  50. package/dist/core/AdmittedTurnExecutor.js.map +1 -1
  51. package/dist/core/BareBatchRunner.d.ts +6 -1
  52. package/dist/core/BareBatchRunner.d.ts.map +1 -1
  53. package/dist/core/BareBatchRunner.js +20 -5
  54. package/dist/core/BareBatchRunner.js.map +1 -1
  55. package/dist/core/BudgetReadout.d.ts +2 -3
  56. package/dist/core/BudgetReadout.d.ts.map +1 -1
  57. package/dist/core/BudgetReadout.js +23 -32
  58. package/dist/core/BudgetReadout.js.map +1 -1
  59. package/dist/core/CapabilityPolicies.d.ts +3 -8
  60. package/dist/core/CapabilityPolicies.d.ts.map +1 -1
  61. package/dist/core/CapabilityPolicies.js +2 -28
  62. package/dist/core/CapabilityPolicies.js.map +1 -1
  63. package/dist/core/CapabilityResolver.d.ts +10 -10
  64. package/dist/core/CapabilityResolver.d.ts.map +1 -1
  65. package/dist/core/CapabilityResolver.js +87 -65
  66. package/dist/core/CapabilityResolver.js.map +1 -1
  67. package/dist/core/ChannelWrite.d.ts +14 -11
  68. package/dist/core/ChannelWrite.d.ts.map +1 -1
  69. package/dist/core/ChannelWrite.js +11 -12
  70. package/dist/core/ChannelWrite.js.map +1 -1
  71. package/dist/core/ChannelWrite.sql +99 -9
  72. package/dist/core/ClientInteractions.d.ts.map +1 -1
  73. package/dist/core/ClientInteractions.js +7 -0
  74. package/dist/core/ClientInteractions.js.map +1 -1
  75. package/dist/core/CoreSchemeServices.d.ts +13 -10
  76. package/dist/core/CoreSchemeServices.d.ts.map +1 -1
  77. package/dist/core/CoreSchemeServices.js +13 -5
  78. package/dist/core/CoreSchemeServices.js.map +1 -1
  79. package/dist/core/DataStatementRunner.d.ts +2 -2
  80. package/dist/core/DataStatementRunner.d.ts.map +1 -1
  81. package/dist/core/DataStatementRunner.js +36 -39
  82. package/dist/core/DataStatementRunner.js.map +1 -1
  83. package/dist/core/Dispatcher.d.ts +19 -26
  84. package/dist/core/Dispatcher.d.ts.map +1 -1
  85. package/dist/core/Dispatcher.js +369 -219
  86. package/dist/core/Dispatcher.js.map +1 -1
  87. package/dist/core/Dispatcher.sql +66 -0
  88. package/dist/core/DurableStatement.d.ts.map +1 -1
  89. package/dist/core/DurableStatement.js +2 -1
  90. package/dist/core/DurableStatement.js.map +1 -1
  91. package/dist/core/EditMutations.d.ts +14 -18
  92. package/dist/core/EditMutations.d.ts.map +1 -1
  93. package/dist/core/EditMutations.js +211 -280
  94. package/dist/core/EditMutations.js.map +1 -1
  95. package/dist/core/EditMutations.sql +15 -0
  96. package/dist/core/EditSequence.d.ts +13 -0
  97. package/dist/core/EditSequence.d.ts.map +1 -0
  98. package/dist/core/EditSequence.js +73 -0
  99. package/dist/core/EditSequence.js.map +1 -0
  100. package/dist/core/Engine.d.ts +17 -23
  101. package/dist/core/Engine.d.ts.map +1 -1
  102. package/dist/core/Engine.js +73 -163
  103. package/dist/core/Engine.js.map +1 -1
  104. package/dist/core/Engine.sql +0 -724
  105. package/dist/core/EntryAddressBinding.d.ts +7 -17
  106. package/dist/core/EntryAddressBinding.d.ts.map +1 -1
  107. package/dist/core/EntryAddressBinding.js +12 -72
  108. package/dist/core/EntryAddressBinding.js.map +1 -1
  109. package/dist/core/ExecutionOutputs.d.ts +9 -0
  110. package/dist/core/ExecutionOutputs.d.ts.map +1 -0
  111. package/dist/core/ExecutionOutputs.js +36 -0
  112. package/dist/core/ExecutionOutputs.js.map +1 -0
  113. package/dist/core/ExecutionOutputs.sql +13 -0
  114. package/dist/core/ExecutorRegistry.d.ts +7 -5
  115. package/dist/core/ExecutorRegistry.d.ts.map +1 -1
  116. package/dist/core/ExecutorRegistry.js +36 -32
  117. package/dist/core/ExecutorRegistry.js.map +1 -1
  118. package/dist/core/HostPaths.d.ts +1 -0
  119. package/dist/core/HostPaths.d.ts.map +1 -1
  120. package/dist/core/HostPaths.js +4 -0
  121. package/dist/core/HostPaths.js.map +1 -1
  122. package/dist/core/InferenceCall.d.ts.map +1 -1
  123. package/dist/core/InferenceCall.js +1 -2
  124. package/dist/core/InferenceCall.js.map +1 -1
  125. package/dist/core/InferenceCall.sql +29 -0
  126. package/dist/core/KillHandler.d.ts +1 -0
  127. package/dist/core/KillHandler.d.ts.map +1 -1
  128. package/dist/core/KillHandler.js +24 -21
  129. package/dist/core/KillHandler.js.map +1 -1
  130. package/dist/core/LogBody.d.ts +8 -1
  131. package/dist/core/LogBody.d.ts.map +1 -1
  132. package/dist/core/LogBody.js +42 -11
  133. package/dist/core/LogBody.js.map +1 -1
  134. package/dist/core/LogEntryProjection.d.ts +1 -0
  135. package/dist/core/LogEntryProjection.d.ts.map +1 -1
  136. package/dist/core/LogEntryProjection.js +18 -10
  137. package/dist/core/LogEntryProjection.js.map +1 -1
  138. package/dist/core/LogVisibility.d.ts +1 -0
  139. package/dist/core/LogVisibility.d.ts.map +1 -1
  140. package/dist/core/LogVisibility.js +3 -0
  141. package/dist/core/LogVisibility.js.map +1 -1
  142. package/dist/core/LogWriter.d.ts +2 -3
  143. package/dist/core/LogWriter.d.ts.map +1 -1
  144. package/dist/core/LogWriter.js +25 -32
  145. package/dist/core/LogWriter.js.map +1 -1
  146. package/dist/core/LogWriter.sql +23 -0
  147. package/dist/core/LoopDriver.d.ts +11 -8
  148. package/dist/core/LoopDriver.d.ts.map +1 -1
  149. package/dist/core/LoopDriver.js +163 -189
  150. package/dist/core/LoopDriver.js.map +1 -1
  151. package/dist/core/LoopDriver.sql +11 -0
  152. package/dist/core/LoopLifecycle.d.ts +32 -2
  153. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  154. package/dist/core/LoopLifecycle.js +88 -4
  155. package/dist/core/LoopLifecycle.js.map +1 -1
  156. package/dist/core/LoopLifecycle.sql +145 -28
  157. package/dist/core/LoopPolicyReader.sql +6 -0
  158. package/dist/core/MembershipMaterialization.d.ts.map +1 -1
  159. package/dist/core/MembershipMaterialization.js +6 -28
  160. package/dist/core/MembershipMaterialization.js.map +1 -1
  161. package/dist/core/ModelCall.sql +70 -0
  162. package/dist/core/MutationEffects.d.ts +5 -3
  163. package/dist/core/MutationEffects.d.ts.map +1 -1
  164. package/dist/core/MutationEffects.js +10 -28
  165. package/dist/core/MutationEffects.js.map +1 -1
  166. package/dist/core/NativeContent.d.ts +6 -0
  167. package/dist/core/NativeContent.d.ts.map +1 -0
  168. package/dist/core/NativeContent.js +16 -0
  169. package/dist/core/NativeContent.js.map +1 -0
  170. package/dist/core/NativeContent.sql +6 -0
  171. package/dist/core/NoticeChannel.js +1 -1
  172. package/dist/core/NoticeChannel.js.map +1 -1
  173. package/dist/core/OperatorConfig.js +5 -5
  174. package/dist/core/OperatorConfig.js.map +1 -1
  175. package/dist/core/PacketBuilder.d.ts +8 -5
  176. package/dist/core/PacketBuilder.d.ts.map +1 -1
  177. package/dist/core/PacketBuilder.js +117 -81
  178. package/dist/core/PacketBuilder.js.map +1 -1
  179. package/dist/core/PacketBuilder.sql +146 -0
  180. package/dist/core/PatternSelection.d.ts +28 -0
  181. package/dist/core/PatternSelection.d.ts.map +1 -0
  182. package/dist/core/PatternSelection.js +42 -0
  183. package/dist/core/PatternSelection.js.map +1 -0
  184. package/dist/core/ProblemLog.d.ts.map +1 -1
  185. package/dist/core/ProblemLog.js +0 -1
  186. package/dist/core/ProblemLog.js.map +1 -1
  187. package/dist/core/PromptFrames.d.ts +12 -0
  188. package/dist/core/PromptFrames.d.ts.map +1 -0
  189. package/dist/core/PromptFrames.js +28 -0
  190. package/dist/core/PromptFrames.js.map +1 -0
  191. package/dist/core/ProposalLifecycle.d.ts +0 -1
  192. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  193. package/dist/core/ProposalLifecycle.js +20 -19
  194. package/dist/core/ProposalLifecycle.js.map +1 -1
  195. package/dist/core/ProposalLifecycle.sql +33 -0
  196. package/dist/core/ProviderInstantiate.d.ts +1 -1
  197. package/dist/core/ProviderInstantiate.d.ts.map +1 -1
  198. package/dist/core/ProviderInstantiate.js +7 -14
  199. package/dist/core/ProviderInstantiate.js.map +1 -1
  200. package/dist/core/ReasoningView.d.ts +9 -0
  201. package/dist/core/ReasoningView.d.ts.map +1 -0
  202. package/dist/core/ReasoningView.js +47 -0
  203. package/dist/core/ReasoningView.js.map +1 -0
  204. package/dist/core/ResourceBindings.d.ts +16 -0
  205. package/dist/core/ResourceBindings.d.ts.map +1 -0
  206. package/dist/core/ResourceBindings.js +45 -0
  207. package/dist/core/ResourceBindings.js.map +1 -0
  208. package/dist/core/ResourceMutations.d.ts +5 -8
  209. package/dist/core/ResourceMutations.d.ts.map +1 -1
  210. package/dist/core/ResourceMutations.js +6 -7
  211. package/dist/core/ResourceMutations.js.map +1 -1
  212. package/dist/core/ResourceSelector.d.ts +2 -2
  213. package/dist/core/ResourceSelector.d.ts.map +1 -1
  214. package/dist/core/ResourceSelector.js +122 -62
  215. package/dist/core/ResourceSelector.js.map +1 -1
  216. package/dist/core/ResourceTransfers.d.ts +4 -2
  217. package/dist/core/ResourceTransfers.d.ts.map +1 -1
  218. package/dist/core/ResourceTransfers.js +95 -26
  219. package/dist/core/ResourceTransfers.js.map +1 -1
  220. package/dist/core/RuntimeWorker.d.ts +5 -0
  221. package/dist/core/RuntimeWorker.d.ts.map +1 -0
  222. package/dist/core/RuntimeWorker.js +10 -0
  223. package/dist/core/RuntimeWorker.js.map +1 -0
  224. package/dist/core/RuntimeWorker.sql +5 -0
  225. package/dist/core/SchemeRegistry.d.ts +12 -16
  226. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  227. package/dist/core/SchemeRegistry.js +58 -84
  228. package/dist/core/SchemeRegistry.js.map +1 -1
  229. package/dist/core/StoredPacket.d.ts +6 -1
  230. package/dist/core/StoredPacket.d.ts.map +1 -1
  231. package/dist/core/StoredPacket.js +30 -10
  232. package/dist/core/StoredPacket.js.map +1 -1
  233. package/dist/core/StrikeRail.d.ts +9 -6
  234. package/dist/core/StrikeRail.d.ts.map +1 -1
  235. package/dist/core/StrikeRail.js +60 -113
  236. package/dist/core/StrikeRail.js.map +1 -1
  237. package/dist/core/StrikeRail.sql +12 -0
  238. package/dist/core/TerminalResult.d.ts +1 -1
  239. package/dist/core/TerminalResult.d.ts.map +1 -1
  240. package/dist/core/TerminalResult.js +2 -2
  241. package/dist/core/TerminalResult.js.map +1 -1
  242. package/dist/core/TokenCalibration.d.ts +1 -6
  243. package/dist/core/TokenCalibration.d.ts.map +1 -1
  244. package/dist/core/TokenCalibration.js +13 -9
  245. package/dist/core/TokenCalibration.js.map +1 -1
  246. package/dist/core/TokenCalibration.sql +15 -0
  247. package/dist/core/ToolInputSchema.d.ts +6 -0
  248. package/dist/core/ToolInputSchema.d.ts.map +1 -0
  249. package/dist/core/ToolInputSchema.js +43 -0
  250. package/dist/core/ToolInputSchema.js.map +1 -0
  251. package/dist/core/ToolResources.d.ts.map +1 -1
  252. package/dist/core/ToolResources.js +76 -52
  253. package/dist/core/ToolResources.js.map +1 -1
  254. package/dist/core/Turn.d.ts +5 -2
  255. package/dist/core/Turn.d.ts.map +1 -1
  256. package/dist/core/Turn.js +13 -11
  257. package/dist/core/Turn.js.map +1 -1
  258. package/dist/core/Turn.sql +25 -39
  259. package/dist/core/{SendBroadcastHandler.d.ts → TurnDispositionHandler.d.ts} +25 -17
  260. package/dist/core/TurnDispositionHandler.d.ts.map +1 -0
  261. package/dist/core/TurnDispositionHandler.js +198 -0
  262. package/dist/core/TurnDispositionHandler.js.map +1 -0
  263. package/dist/core/TurnMaterialization.d.ts +2 -3
  264. package/dist/core/TurnMaterialization.d.ts.map +1 -1
  265. package/dist/core/TurnMaterialization.js +40 -15
  266. package/dist/core/TurnMaterialization.js.map +1 -1
  267. package/dist/core/TurnMaterialization.sql +44 -0
  268. package/dist/core/TurnOps.d.ts.map +1 -1
  269. package/dist/core/TurnOps.js +8 -64
  270. package/dist/core/TurnOps.js.map +1 -1
  271. package/dist/core/TurnRunner.d.ts +9 -12
  272. package/dist/core/TurnRunner.d.ts.map +1 -1
  273. package/dist/core/TurnRunner.js +232 -408
  274. package/dist/core/TurnRunner.js.map +1 -1
  275. package/dist/core/TurnRunner.sql +74 -0
  276. package/dist/core/TurnSources.sql +39 -0
  277. package/dist/core/WorkerControlAddress.d.ts +1 -0
  278. package/dist/core/WorkerControlAddress.d.ts.map +1 -1
  279. package/dist/core/WorkerControlAddress.js +5 -0
  280. package/dist/core/WorkerControlAddress.js.map +1 -1
  281. package/dist/core/WorkerControlHandler.d.ts +1 -3
  282. package/dist/core/WorkerControlHandler.d.ts.map +1 -1
  283. package/dist/core/WorkerControlHandler.js +41 -48
  284. package/dist/core/WorkerControlHandler.js.map +1 -1
  285. package/dist/core/WorkerName.d.ts +8 -6
  286. package/dist/core/WorkerName.d.ts.map +1 -1
  287. package/dist/core/WorkerName.js +33 -24
  288. package/dist/core/WorkerName.js.map +1 -1
  289. package/dist/core/WorkerName.sql +7 -10
  290. package/dist/core/WorkspaceGate.d.ts +1 -1
  291. package/dist/core/WorkspaceGate.d.ts.map +1 -1
  292. package/dist/core/WorkspaceGate.js +29 -6
  293. package/dist/core/WorkspaceGate.js.map +1 -1
  294. package/dist/core/ambient.sql +236 -0
  295. package/dist/core/attachments.d.ts +2 -1
  296. package/dist/core/attachments.d.ts.map +1 -1
  297. package/dist/core/attachments.js +5 -4
  298. package/dist/core/attachments.js.map +1 -1
  299. package/dist/core/caps/CapsResolve.d.ts +2 -3
  300. package/dist/core/caps/CapsResolve.d.ts.map +1 -1
  301. package/dist/core/caps/CapsResolve.js +5 -5
  302. package/dist/core/caps/CapsResolve.js.map +1 -1
  303. package/dist/core/caps/DbChannelCaps.d.ts +1 -1
  304. package/dist/core/caps/DbChannelCaps.d.ts.map +1 -1
  305. package/dist/core/caps/DbChannelCaps.js +4 -6
  306. package/dist/core/caps/DbChannelCaps.js.map +1 -1
  307. package/dist/core/caps/DbEntryCaps.d.ts +2 -1
  308. package/dist/core/caps/DbEntryCaps.d.ts.map +1 -1
  309. package/dist/core/caps/DbEntryCaps.js +11 -17
  310. package/dist/core/caps/DbEntryCaps.js.map +1 -1
  311. package/dist/core/caps/DbNotifyCaps.d.ts +1 -1
  312. package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -1
  313. package/dist/core/caps/DbNotifyCaps.js +3 -5
  314. package/dist/core/caps/DbNotifyCaps.js.map +1 -1
  315. package/dist/core/caps/DbProjectionCaps.js +1 -1
  316. package/dist/core/caps/DbProjectionCaps.js.map +1 -1
  317. package/dist/core/caps/DbSubscriptionCaps.d.ts +1 -1
  318. package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
  319. package/dist/core/caps/DbSubscriptionCaps.js +5 -7
  320. package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
  321. package/dist/core/caps/SchemeCtxImpl.d.ts +0 -2
  322. package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
  323. package/dist/core/caps/SchemeCtxImpl.js +4 -20
  324. package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
  325. package/dist/core/env-defaults.d.ts.map +1 -1
  326. package/dist/core/env-defaults.js +4 -2
  327. package/dist/core/env-defaults.js.map +1 -1
  328. package/dist/core/file-materialization.d.ts +4 -1
  329. package/dist/core/file-materialization.d.ts.map +1 -1
  330. package/dist/core/file-materialization.js +14 -0
  331. package/dist/core/file-materialization.js.map +1 -1
  332. package/dist/core/fork.d.ts +1 -6
  333. package/dist/core/fork.d.ts.map +1 -1
  334. package/dist/core/fork.js +9 -153
  335. package/dist/core/fork.js.map +1 -1
  336. package/dist/core/fork.sql +162 -185
  337. package/dist/core/git-env.d.ts +1 -0
  338. package/dist/core/git-env.d.ts.map +1 -1
  339. package/dist/core/git-env.js +39 -2
  340. package/dist/core/git-env.js.map +1 -1
  341. package/dist/core/git-membership.d.ts.map +1 -1
  342. package/dist/core/git-membership.js +64 -48
  343. package/dist/core/git-membership.js.map +1 -1
  344. package/dist/core/git-state.d.ts.map +1 -1
  345. package/dist/core/git-state.js +25 -19
  346. package/dist/core/git-state.js.map +1 -1
  347. package/dist/core/glob_match.d.ts +4 -0
  348. package/dist/core/glob_match.d.ts.map +1 -0
  349. package/dist/core/glob_match.js +7 -0
  350. package/dist/core/glob_match.js.map +1 -0
  351. package/dist/core/maintenance.sql +6 -0
  352. package/dist/core/mutation-types.d.ts +7 -28
  353. package/dist/core/mutation-types.d.ts.map +1 -1
  354. package/dist/core/packet-inject.d.ts.map +1 -1
  355. package/dist/core/packet-inject.js +2 -3
  356. package/dist/core/packet-inject.js.map +1 -1
  357. package/dist/core/packet-wire.d.ts +8 -6
  358. package/dist/core/packet-wire.d.ts.map +1 -1
  359. package/dist/core/packet-wire.js +131 -163
  360. package/dist/core/packet-wire.js.map +1 -1
  361. package/dist/core/plurnk-uri.d.ts +1 -1
  362. package/dist/core/plurnk-uri.d.ts.map +1 -1
  363. package/dist/core/plurnk-uri.js +5 -12
  364. package/dist/core/plurnk-uri.js.map +1 -1
  365. package/dist/core/scheme-types.d.ts +3 -3
  366. package/dist/core/scheme-types.d.ts.map +1 -1
  367. package/dist/core/scheme-types.js.map +1 -1
  368. package/dist/core/sha256.d.ts +4 -0
  369. package/dist/core/sha256.d.ts.map +1 -0
  370. package/dist/core/sha256.js +6 -0
  371. package/dist/core/sha256.js.map +1 -0
  372. package/dist/core/teaching.js +1 -1
  373. package/dist/core/teaching.js.map +1 -1
  374. package/dist/core/turn-scheduler.d.ts.map +1 -1
  375. package/dist/core/turn-scheduler.js +5 -18
  376. package/dist/core/turn-scheduler.js.map +1 -1
  377. package/dist/core/turn-signals.d.ts +0 -6
  378. package/dist/core/turn-signals.d.ts.map +1 -1
  379. package/dist/core/turn-signals.js +1 -7
  380. package/dist/core/turn-signals.js.map +1 -1
  381. package/dist/core/worker-ops.sql +15 -22
  382. package/dist/core/workspace-settings.d.ts.map +1 -1
  383. package/dist/core/workspace-settings.js +18 -2
  384. package/dist/core/workspace-settings.js.map +1 -1
  385. package/dist/core/workspace-settings.sql +6 -0
  386. package/dist/digest/Digest.d.ts.map +1 -1
  387. package/dist/digest/Digest.js +27 -90
  388. package/dist/digest/Digest.js.map +1 -1
  389. package/dist/digest/DigestRender.d.ts.map +1 -1
  390. package/dist/digest/DigestRender.js +14 -54
  391. package/dist/digest/DigestRender.js.map +1 -1
  392. package/dist/digest/digest-rows.d.ts +10 -32
  393. package/dist/digest/digest-rows.d.ts.map +1 -1
  394. package/dist/digest/digest.sql +43 -18
  395. package/dist/schemes/Exec.d.ts +6 -12
  396. package/dist/schemes/Exec.d.ts.map +1 -1
  397. package/dist/schemes/Exec.js +256 -188
  398. package/dist/schemes/Exec.js.map +1 -1
  399. package/dist/schemes/ExecOutputScheme.d.ts +8 -6
  400. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  401. package/dist/schemes/ExecOutputScheme.js +33 -61
  402. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  403. package/dist/schemes/ExecutionInput.d.ts +12 -0
  404. package/dist/schemes/ExecutionInput.d.ts.map +1 -0
  405. package/dist/schemes/ExecutionInput.js +94 -0
  406. package/dist/schemes/ExecutionInput.js.map +1 -0
  407. package/dist/schemes/File.d.ts +5 -2
  408. package/dist/schemes/File.d.ts.map +1 -1
  409. package/dist/schemes/File.js +62 -92
  410. package/dist/schemes/File.js.map +1 -1
  411. package/dist/schemes/Log.d.ts.map +1 -1
  412. package/dist/schemes/Log.js +84 -79
  413. package/dist/schemes/Log.js.map +1 -1
  414. package/dist/schemes/Log.sql +183 -15
  415. package/dist/schemes/Prompt.d.ts.map +1 -1
  416. package/dist/schemes/Prompt.js +3 -12
  417. package/dist/schemes/Prompt.js.map +1 -1
  418. package/dist/schemes/QuestionTool.d.ts +5 -0
  419. package/dist/schemes/QuestionTool.d.ts.map +1 -1
  420. package/dist/schemes/QuestionTool.js +6 -14
  421. package/dist/schemes/QuestionTool.js.map +1 -1
  422. package/dist/schemes/Skill.d.ts +12 -7
  423. package/dist/schemes/Skill.d.ts.map +1 -1
  424. package/dist/schemes/Skill.js +149 -21
  425. package/dist/schemes/Skill.js.map +1 -1
  426. package/dist/schemes/TurnSource.d.ts +12 -0
  427. package/dist/schemes/TurnSource.d.ts.map +1 -0
  428. package/dist/schemes/TurnSource.js +116 -0
  429. package/dist/schemes/TurnSource.js.map +1 -0
  430. package/dist/schemes/Worker.d.ts +3 -3
  431. package/dist/schemes/Worker.d.ts.map +1 -1
  432. package/dist/schemes/Worker.js +61 -208
  433. package/dist/schemes/Worker.js.map +1 -1
  434. package/dist/schemes/_entry-crud.d.ts +12 -15
  435. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  436. package/dist/schemes/_entry-crud.js +63 -63
  437. package/dist/schemes/_entry-crud.js.map +1 -1
  438. package/dist/schemes/_entry-crud.sql +142 -46
  439. package/dist/schemes/_entry-find.d.ts +1 -3
  440. package/dist/schemes/_entry-find.d.ts.map +1 -1
  441. package/dist/schemes/_entry-find.js +111 -112
  442. package/dist/schemes/_entry-find.js.map +1 -1
  443. package/dist/schemes/_entry-find.sql +22 -14
  444. package/dist/schemes/_entry-fts.d.ts +14 -0
  445. package/dist/schemes/_entry-fts.d.ts.map +1 -0
  446. package/dist/schemes/_entry-fts.js +82 -0
  447. package/dist/schemes/_entry-fts.js.map +1 -0
  448. package/dist/schemes/_entry-fts.sql +31 -0
  449. package/dist/schemes/_entry-graph.d.ts.map +1 -1
  450. package/dist/schemes/_entry-graph.js +6 -14
  451. package/dist/schemes/_entry-graph.js.map +1 -1
  452. package/dist/schemes/_entry-graph.sql +29 -44
  453. package/dist/schemes/_entry-manifest.d.ts +2 -1
  454. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  455. package/dist/schemes/_entry-manifest.js +15 -12
  456. package/dist/schemes/_entry-manifest.js.map +1 -1
  457. package/dist/schemes/_entry-manifest.sql +26 -0
  458. package/dist/schemes/_entry-ops.d.ts +3 -5
  459. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  460. package/dist/schemes/_entry-ops.js +30 -43
  461. package/dist/schemes/_entry-ops.js.map +1 -1
  462. package/dist/schemes/_entry-ops.sql +5 -6
  463. package/dist/schemes/_entry-readable.d.ts +8 -0
  464. package/dist/schemes/_entry-readable.d.ts.map +1 -0
  465. package/dist/schemes/_entry-readable.js +38 -0
  466. package/dist/schemes/_entry-readable.js.map +1 -0
  467. package/dist/schemes/_entry-send.d.ts +1 -1
  468. package/dist/schemes/_entry-send.d.ts.map +1 -1
  469. package/dist/schemes/_entry-send.js +3 -3
  470. package/dist/schemes/_entry-send.js.map +1 -1
  471. package/dist/schemes/_search-index.d.ts +1 -3
  472. package/dist/schemes/_search-index.d.ts.map +1 -1
  473. package/dist/schemes/_search-index.js +79 -110
  474. package/dist/schemes/_search-index.js.map +1 -1
  475. package/dist/schemes/_search-index.sql +30 -0
  476. package/dist/schemes/exec-runtime.d.ts +1 -1
  477. package/dist/schemes/exec-runtime.d.ts.map +1 -1
  478. package/dist/schemes/exec-runtime.js.map +1 -1
  479. package/dist/server/ClientReads.d.ts +2 -2
  480. package/dist/server/ClientReads.d.ts.map +1 -1
  481. package/dist/server/ClientReads.js +5 -8
  482. package/dist/server/ClientReads.js.map +1 -1
  483. package/dist/server/Daemon.d.ts +14 -21
  484. package/dist/server/Daemon.d.ts.map +1 -1
  485. package/dist/server/Daemon.js +135 -156
  486. package/dist/server/Daemon.js.map +1 -1
  487. package/dist/server/DaemonModule.d.ts +23 -21
  488. package/dist/server/DaemonModule.d.ts.map +1 -1
  489. package/dist/server/DrainSupervisor.d.ts +8 -21
  490. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  491. package/dist/server/DrainSupervisor.js +278 -306
  492. package/dist/server/DrainSupervisor.js.map +1 -1
  493. package/dist/server/Functionality.d.ts +11 -12
  494. package/dist/server/Functionality.d.ts.map +1 -1
  495. package/dist/server/Functionality.js +129 -101
  496. package/dist/server/Functionality.js.map +1 -1
  497. package/dist/server/FunctionalityManager.d.ts +3 -5
  498. package/dist/server/FunctionalityManager.d.ts.map +1 -1
  499. package/dist/server/FunctionalityManager.js +20 -58
  500. package/dist/server/FunctionalityManager.js.map +1 -1
  501. package/dist/server/MembersFunctionality.d.ts +5 -4
  502. package/dist/server/MembersFunctionality.d.ts.map +1 -1
  503. package/dist/server/MembersFunctionality.js +24 -37
  504. package/dist/server/MembersFunctionality.js.map +1 -1
  505. package/dist/server/PlurnkSkill.d.ts +11 -0
  506. package/dist/server/PlurnkSkill.d.ts.map +1 -0
  507. package/dist/server/PlurnkSkill.js +41 -0
  508. package/dist/server/PlurnkSkill.js.map +1 -0
  509. package/dist/server/Retention.d.ts +22 -0
  510. package/dist/server/Retention.d.ts.map +1 -0
  511. package/dist/server/Retention.js +54 -0
  512. package/dist/server/Retention.js.map +1 -0
  513. package/dist/server/Retention.sql +36 -0
  514. package/dist/server/ServiceModules.d.ts +5 -0
  515. package/dist/server/ServiceModules.d.ts.map +1 -0
  516. package/dist/server/ServiceModules.js +10 -0
  517. package/dist/server/ServiceModules.js.map +1 -0
  518. package/dist/server/SkillsFunctionality.d.ts +14 -19
  519. package/dist/server/SkillsFunctionality.d.ts.map +1 -1
  520. package/dist/server/SkillsFunctionality.js +97 -104
  521. package/dist/server/SkillsFunctionality.js.map +1 -1
  522. package/dist/server/WorkerModelResolver.d.ts +4 -0
  523. package/dist/server/WorkerModelResolver.d.ts.map +1 -1
  524. package/dist/server/WorkerModelResolver.js +72 -39
  525. package/dist/server/WorkerModelResolver.js.map +1 -1
  526. package/dist/server/WorkspaceCapabilities.d.ts +21 -0
  527. package/dist/server/WorkspaceCapabilities.d.ts.map +1 -0
  528. package/dist/server/{WorkerCapabilities.js → WorkspaceCapabilities.js} +40 -40
  529. package/dist/server/WorkspaceCapabilities.js.map +1 -0
  530. package/dist/server/WorkspaceResidency.d.ts +36 -0
  531. package/dist/server/WorkspaceResidency.d.ts.map +1 -0
  532. package/dist/server/WorkspaceResidency.js +199 -0
  533. package/dist/server/WorkspaceResidency.js.map +1 -0
  534. package/dist/server/client-input.d.ts +1 -4
  535. package/dist/server/client-input.d.ts.map +1 -1
  536. package/dist/server/client-input.js +4 -45
  537. package/dist/server/client-input.js.map +1 -1
  538. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  539. package/dist/server/dispatch-as-plurnk.js +4 -22
  540. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  541. package/dist/server/drain.sql +65 -42
  542. package/dist/server/envelope.d.ts +8 -0
  543. package/dist/server/envelope.d.ts.map +1 -1
  544. package/dist/server/envelope.js +9 -7
  545. package/dist/server/envelope.js.map +1 -1
  546. package/dist/server/envelope.sql +49 -13
  547. package/dist/server/lifecycle-recovery.sql +14 -17
  548. package/dist/server/logEntry.d.ts +1 -1
  549. package/dist/server/logEntry.d.ts.map +1 -1
  550. package/dist/server/logEntry.js +4 -1
  551. package/dist/server/logEntry.js.map +1 -1
  552. package/dist/server/logEntry.sql +25 -1
  553. package/dist/server/loopDocs.d.ts +2 -2
  554. package/dist/server/loopDocs.d.ts.map +1 -1
  555. package/dist/server/loopDocs.js +38 -31
  556. package/dist/server/loopDocs.js.map +1 -1
  557. package/dist/server/loopDocs.sql +1 -3
  558. package/dist/server/model-catalog.d.ts.map +1 -1
  559. package/dist/server/model-catalog.js +2 -1
  560. package/dist/server/model-catalog.js.map +1 -1
  561. package/dist/server/model-route.d.ts +1 -1
  562. package/dist/server/model-route.d.ts.map +1 -1
  563. package/dist/server/model-route.js +4 -2
  564. package/dist/server/model-route.js.map +1 -1
  565. package/dist/server/seam-entry-read.sql +3 -4
  566. package/dist/server/seam-loop.sql +2 -9
  567. package/dist/server/workspace-capabilities.sql +19 -0
  568. package/dist/service.d.ts.map +1 -1
  569. package/dist/service.js +5 -17
  570. package/dist/service.js.map +1 -1
  571. package/docs/members.md +83 -0
  572. package/docs/skills.md +50 -0
  573. package/migrations/001_workspaces.sql +53 -0
  574. package/migrations/002_workers.sql +183 -0
  575. package/migrations/003_loops.sql +326 -0
  576. package/migrations/004_inference.sql +360 -0
  577. package/migrations/005_entries.sql +207 -0
  578. package/migrations/006_log.sql +578 -0
  579. package/migrations/007_subscriptions.sql +175 -0
  580. package/migrations/008_interactions.sql +29 -0
  581. package/package.json +33 -40
  582. package/digest-sql/channel-dispositions/dispositions.sql +0 -15
  583. package/digest-sql/channel-state/state.sql +0 -6
  584. package/digest-sql/curation/curation.sql +0 -6
  585. package/digest-sql/derivations/derivations.sql +0 -4
  586. package/digest-sql/embeddings/embeddings.sql +0 -4
  587. package/digest-sql/entry-dispositions/dispositions.sql +0 -15
  588. package/digest-sql/entry-state/state.sql +0 -6
  589. package/digest-sql/token-counts/token-counts.sql +0 -2
  590. package/dist/core/EmbeddingCall.d.ts +0 -23
  591. package/dist/core/EmbeddingCall.d.ts.map +0 -1
  592. package/dist/core/EmbeddingCall.js +0 -149
  593. package/dist/core/EmbeddingCall.js.map +0 -1
  594. package/dist/core/OverflowTurn.d.ts +0 -11
  595. package/dist/core/OverflowTurn.d.ts.map +0 -1
  596. package/dist/core/OverflowTurn.js +0 -80
  597. package/dist/core/OverflowTurn.js.map +0 -1
  598. package/dist/core/Owner.d.ts +0 -8
  599. package/dist/core/Owner.d.ts.map +0 -1
  600. package/dist/core/Owner.js +0 -46
  601. package/dist/core/Owner.js.map +0 -1
  602. package/dist/core/SendBroadcastHandler.d.ts.map +0 -1
  603. package/dist/core/SendBroadcastHandler.js +0 -159
  604. package/dist/core/SendBroadcastHandler.js.map +0 -1
  605. package/dist/core/VectorPump.d.ts +0 -28
  606. package/dist/core/VectorPump.d.ts.map +0 -1
  607. package/dist/core/VectorPump.js +0 -130
  608. package/dist/core/VectorPump.js.map +0 -1
  609. package/dist/core/owner.sql +0 -11
  610. package/dist/core/worker-settings.d.ts +0 -10
  611. package/dist/core/worker-settings.d.ts.map +0 -1
  612. package/dist/core/worker-settings.js +0 -53
  613. package/dist/core/worker-settings.js.map +0 -1
  614. package/dist/schemes/_entry-chunk.d.ts +0 -14
  615. package/dist/schemes/_entry-chunk.d.ts.map +0 -1
  616. package/dist/schemes/_entry-chunk.js +0 -165
  617. package/dist/schemes/_entry-chunk.js.map +0 -1
  618. package/dist/schemes/_entry-semantic.d.ts +0 -63
  619. package/dist/schemes/_entry-semantic.d.ts.map +0 -1
  620. package/dist/schemes/_entry-semantic.js +0 -299
  621. package/dist/schemes/_entry-semantic.js.map +0 -1
  622. package/dist/schemes/_entry-semantic.sql +0 -99
  623. package/dist/schemes/cosine.d.ts +0 -4
  624. package/dist/schemes/cosine.d.ts.map +0 -1
  625. package/dist/schemes/cosine.js +0 -9
  626. package/dist/schemes/cosine.js.map +0 -1
  627. package/dist/server/WorkerCapabilities.d.ts +0 -21
  628. package/dist/server/WorkerCapabilities.d.ts.map +0 -1
  629. package/dist/server/WorkerCapabilities.js.map +0 -1
  630. package/dist/server/WorkerResidency.d.ts +0 -40
  631. package/dist/server/WorkerResidency.d.ts.map +0 -1
  632. package/dist/server/WorkerResidency.js +0 -283
  633. package/dist/server/WorkerResidency.js.map +0 -1
  634. package/dist/server/seam-log-read.sql +0 -21
  635. package/dist/server/worker-capabilities.sql +0 -28
  636. package/migrations/001_schema.sql +0 -2207
@@ -1,28 +1,35 @@
1
+ import { TurnDisposition } from "@plurnk/plurnk-contracts";
2
+ import NativeContent from "./NativeContent.js";
1
3
  import { PathSyntax, PlurnkParser, PlurnkParseError, UNKNOWN_POSITION } from "@plurnk/plurnk-contracts";
2
4
  import { setTimeout as delay } from "node:timers/promises";
3
5
  import { aggregateProviderAccounting } from "@plurnk/plurnk-providers";
4
6
  const comparePosition = (a, b) => a.line - b.line || a.column - b.column;
5
7
  import Meta from "@plurnk/plurnk-meta";
6
- import EntryCrud from "../schemes/_entry-crud.js";
7
8
  import GitMembership from "./git-membership.js";
8
9
  import { acceptedKinds } from "./attachments.js";
9
10
  import GitState from "./git-state.js";
10
11
  import WorkspaceSettings from "./workspace-settings.js";
11
- import { generatedPathname, promptPathname, promptLoopPrefix } from "./plurnk-uri.js";
12
+ import { taskTiming } from "./LoopLifecycle.js";
13
+ import { generatedPathname, promptLoopPrefix } from "./plurnk-uri.js";
14
+ import PromptFrames from "./PromptFrames.js";
12
15
  import { readFile } from "node:fs/promises";
13
- // {§grammar-rail-registration} — bare names are the built-in rail namespace;
14
- // everything else is an import specifier resolved through the Node chain.
15
- export const resolveGrammarRailPath = (variant) => variant.startsWith("/") || variant.startsWith(".")
16
- || variant.includes("/") || variant.includes(":")
17
- ? (variant.startsWith("/") || variant.startsWith(".")
18
- ? variant
19
- : fileURLToPath(import.meta.resolve(variant)))
20
- : fileURLToPath(import.meta.resolve(`@plurnk/plurnk-contracts/${variant}`));
21
- import { fileURLToPath } from "node:url";
16
+ import { resolve as resolvePath } from "node:path";
17
+ import { homedir } from "node:os";
18
+ // {§operator-grammar} — an operator's own GBNF is a file path: absolute, `~`-relative, or
19
+ // relative to the daemon's working directory. The service ships no grammar profile, so a bare
20
+ // name (no separator) is refused by name rather than resolved against anything.
21
+ export const resolveOperatorGrammarPath = (value) => {
22
+ if (value === "~" || value.startsWith("~/"))
23
+ return resolvePath(homedir(), value.slice(2));
24
+ if (value.startsWith("/") || value.startsWith(".") || value.includes("/"))
25
+ return resolvePath(value);
26
+ throw new Error(`PLURNK_PROVIDERS_GBNF=${value} names a bundled grammar profile; the service ships none (#588). Give the path of a grammar file you wrote.`);
27
+ };
22
28
  // Shared module imported by both Engine and bin/digest.ts, so wire
23
29
  // projection and digest projection are structurally one function — no
24
30
  // drift between wire and digest possible.
25
31
  import PacketWire from "./packet-wire.js";
32
+ import ReasoningView from "./ReasoningView.js";
26
33
  import Results, { OperationFailureError } from "./results.js";
27
34
  import Turn from "./Turn.js";
28
35
  import StoredPacket from "./StoredPacket.js";
@@ -30,39 +37,29 @@ import { observed, observedSync } from "../observe/spans.js";
30
37
  import { GEN_AI_REQUEST_SPAN, genAiRequestOptions, settleGenAiResponse } from "../observe/genai.js";
31
38
  import { PROVIDER_CALLS, recordCounter } from "../observe/metrics.js";
32
39
  import ModelCall, { ModelCallPersistenceError, ProviderAccountingIntegrityError } from "./ModelCall.js";
33
- import OverflowTurn from "./OverflowTurn.js";
40
+ import WorkerName from "./WorkerName.js";
34
41
  import TurnOps from "./TurnOps.js";
35
42
  import CapabilityPolicies from "./CapabilityPolicies.js";
36
43
  import CapabilityResolver from "./CapabilityResolver.js";
37
- import LoopPolicyReader from "./LoopPolicyReader.js";
38
- // The prompt entry target - prompt:///<loop>/<N>, self-only ({§prompt-self-only}):
39
- // the owner rides the owner_id column, the address carries only the loop coordinate.
40
- const promptTarget = (loopSeq, promptOrdinal) => {
41
- const storage = promptPathname(loopSeq, promptOrdinal);
44
+ // {§prompt-address}: the same literal address in every observer's packet.
45
+ const promptTarget = (workerName, storage) => {
42
46
  return {
43
- kind: "url", raw: `prompt://${storage}`,
47
+ kind: "url", raw: `prompt://${workerName}${storage}`,
44
48
  scheme: "prompt", username: null, password: null,
45
- hostname: null, port: null,
49
+ hostname: workerName, port: null,
46
50
  pathname: storage, query: null, fragment: null,
47
51
  };
48
52
  };
49
53
  const regexLiteral = (value) => value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
50
- const workerCatalogTarget = (namespace, availableNames, admittedNames) => {
51
- if (availableNames.length > 0 && admittedNames.length === 0)
52
- return null;
53
- const leaf = availableNames.length === 0 || admittedNames.length === availableNames.length
54
- ? "*.md"
55
- : admittedNames.length === 1
56
- ? `${admittedNames[0]}.md`
57
- : `{${admittedNames.join(",")}}.md`;
58
- const pathname = generatedPathname(`/${namespace}/${leaf}`);
54
+ const workerCatalogTarget = (namespace) => {
55
+ const pathname = generatedPathname(`/${namespace}/*.md`);
59
56
  return {
60
57
  kind: "url",
61
- raw: `worker://~${pathname}`,
58
+ raw: `worker://${pathname}`,
62
59
  scheme: "worker",
63
60
  username: null,
64
61
  password: null,
65
- hostname: "~",
62
+ hostname: null,
66
63
  port: null,
67
64
  pathname,
68
65
  query: null,
@@ -115,35 +112,12 @@ const readFilesItems = () => {
115
112
  return normalizeFilesItems(Number.parseInt(raw, 10));
116
113
  };
117
114
  import { ProviderError, scopeEnvToAlias } from "@plurnk/plurnk-providers";
118
- import { validateGbnf } from "@plurnk/gbnf";
119
115
  import ProviderInstantiate from "./ProviderInstantiate.js";
120
116
  import TurnMaterialization from "./TurnMaterialization.js";
121
117
  import BareBatchRunner from "./BareBatchRunner.js";
122
- import { TERMINAL_SEND_SIGNALS, TURN_STATUS_IMPLICIT_CONTINUE } from "./turn-signals.js";
118
+ import { TURN_STATUS_IMPLICIT_CONTINUE } from "./turn-signals.js";
123
119
  import AdmittedTurnExecutor from "./AdmittedTurnExecutor.js";
124
- // A generated rail may constrain only the sampled continuation while the chat
125
- // template contributes a prefix that llama-server preserves in its response.
126
- // The artifact names the alternate root that composes those bytes for evidence
127
- // grading; arbitrary grammars without the declaration retain their transport root.
128
- const grammarConstraint = (grammar) => {
129
- const declarations = [...grammar.matchAll(/^# @plurnk-response-root ([A-Za-z][A-Za-z0-9-]*)$/gm)];
130
- if (declarations.length === 0)
131
- return { transport: grammar, response: grammar };
132
- if (declarations.length !== 1)
133
- throw new Error("GBNF constraint declares multiple @plurnk-response-root values");
134
- const responseRoot = declarations[0][1];
135
- if (!grammar.split("\n").some((line) => line.startsWith(`${responseRoot} ::=`))) {
136
- throw new Error(`GBNF constraint declares missing response root ${responseRoot}`);
137
- }
138
- const roots = [...grammar.matchAll(/^root ::= ([A-Za-z][A-Za-z0-9-]*)$/gm)];
139
- if (roots.length !== 1)
140
- throw new Error("GBNF constraint must declare exactly one simple root");
141
- return {
142
- transport: grammar,
143
- response: grammar.replace(roots[0][0], `root ::= ${responseRoot}`),
144
- };
145
- };
146
- const TOKEN_BUDGET_OVERFLOW_HARD_DETAIL = "Context Token Budget Overflow: tokensActiveTotal exceeded tokensActiveMax, and the causal overflow turn could not make enough room.";
120
+ const TOKEN_BUDGET_OVERFLOW_HARD_DETAIL = "Context Token Budget Overflow: logTokensTotal exceeds logTokensMax; retained context cannot fit.";
147
121
  const curationOverflowFailure = (pressure) => Results.failure("engine:context", "token-budget-overflow", 413, TOKEN_BUDGET_OVERFLOW_HARD_DETAIL, {}, {
148
122
  usage: pressure.weight,
149
123
  ceiling: pressure.budget,
@@ -202,7 +176,8 @@ export default class TurnRunner {
202
176
  #warmWorkspace;
203
177
  #dispatch;
204
178
  #resolveWorkerProviderIdentity;
205
- #gbnfCache = new Map();
179
+ // {§operator-grammar} — one read per path per daemon; the file is the operator's and static.
180
+ #grammarCache = new Map();
206
181
  #materialization;
207
182
  #bareBatch;
208
183
  #admitted;
@@ -228,7 +203,7 @@ export default class TurnRunner {
228
203
  this.#warmWorkspace = warmWorkspace;
229
204
  this.#dispatch = dispatch;
230
205
  this.#resolveWorkerProviderIdentity = resolveWorkerProviderIdentity;
231
- this.#materialization = new TurnMaterialization({ db: this.#db, schemes: this.#schemes, weighContent: this.#weighContent });
206
+ this.#materialization = new TurnMaterialization({ db: this.#db, weighContent: this.#weighContent });
232
207
  this.#bareBatch = new BareBatchRunner({ db: this.#db, providerAttributions: this.#providerAttributions.bind(this), providerFailure: TurnRunner.#providerFailure });
233
208
  this.#admitted = new AdmittedTurnExecutor({ db: this.#db, schemes: this.#schemes, notices: this.#notices, problems: this.#problems, dispatcher: this.#dispatcher, bareBatch: this.#bareBatch });
234
209
  }
@@ -243,66 +218,31 @@ export default class TurnRunner {
243
218
  workerId: args.workerId,
244
219
  loopId: args.loopId,
245
220
  packetCount: packetCount.count,
221
+ ...taskTiming(packetCount),
246
222
  });
247
223
  }
248
- // {§rail-truth-engine-verdict} — the verify GAP (a configured grammar @plurnk/gbnf can't
249
- // parse): warn once per message, never per turn; the turn records railsVerdict "unverifiable".
250
- static #railGapWarned = new Set();
251
- static #warnRailVerdictGapOnce(message) {
252
- if (TurnRunner.#railGapWarned.has(message))
253
- return;
254
- TurnRunner.#railGapWarned.add(message);
255
- process.stderr.write(`plurnk-engine: rail verdict unavailable — the configured grammar did not parse in @plurnk/gbnf (${message})\n`);
256
- }
257
- static #requireGrammarEvidence(response, allowWithheld) {
258
- const evidence = response.grammarEvidence;
259
- if (evidence === undefined) {
260
- throw new Error("provider contract violation: configured GBNF response omitted grammar evidence");
261
- }
262
- const input = [...evidence.input];
263
- if (!Number.isInteger(evidence.contentStart)
264
- || evidence.contentStart < 0
265
- || evidence.contentStart > input.length
266
- || typeof evidence.transported !== "boolean"
267
- || input.slice(evidence.contentStart).join("") !== response.assistant.content) {
268
- throw new Error("provider contract violation: grammar evidence does not map exactly to assistant.content");
269
- }
270
- if (!allowWithheld && !evidence.transported) {
271
- throw new Error("provider contract violation: configured GBNF was not transported outside explicit debug mode");
272
- }
273
- return evidence;
274
- }
275
- async #grammarConstraint(provider) {
276
- // A real alias scopes its rail; an alias-free direct route uses the
277
- // global provider configuration. Unrelated alias settings never apply.
278
- // {§grammar-configuration-admission}
224
+ // {§operator-grammar} — the operator's grammar text for this provider, or undefined when
225
+ // none is configured. A real alias scopes its knob; an alias-free direct route uses the
226
+ // global provider configuration. Unrelated alias settings never apply
227
+ // ({§grammar-configuration-admission}). An unreadable file throws: a configured grammar
228
+ // never silently degrades.
229
+ async #operatorGrammar(provider) {
279
230
  ProviderInstantiate.assertGrammarConfigurationScope(provider);
280
231
  const alias = ProviderInstantiate.configurationAliasOf(provider);
281
232
  const scoped = alias === undefined
282
233
  ? process.env
283
- : scopeEnvToAlias(process.env, alias, [
284
- "PLURNK_PROVIDERS_GBNF",
285
- "PLURNK_PROVIDERS_GBNF_DEBUG",
286
- ]);
287
- const variant = scoped.PLURNK_PROVIDERS_GBNF;
288
- if (variant === undefined || variant === "" || variant === "0")
234
+ : scopeEnvToAlias(process.env, alias, ["PLURNK_PROVIDERS_GBNF"]);
235
+ const configured = scoped.PLURNK_PROVIDERS_GBNF;
236
+ if (configured === undefined || configured === "" || configured === "0")
289
237
  return undefined;
290
- const allowWithheld = scoped.PLURNK_PROVIDERS_GBNF_DEBUG !== undefined
291
- && scoped.PLURNK_PROVIDERS_GBNF_DEBUG !== ""
292
- && scoped.PLURNK_PROVIDERS_GBNF_DEBUG !== "0";
293
- const hit = this.#gbnfCache.get(variant);
238
+ const path = resolveOperatorGrammarPath(configured);
239
+ const hit = this.#grammarCache.get(path);
294
240
  if (hit !== undefined)
295
- return { ...hit, allowWithheld };
296
- // {§grammar-rail-registration} — a bare name is a built-in rail subpath
297
- // under @plurnk/plurnk-contracts; any other form is an import specifier
298
- // (an operator file path or a package export subpath), so a third-party
299
- // rail package plugs in with no built-in registry change.
300
- const path = resolveGrammarRailPath(variant);
301
- const text = await readFile(path, "utf8"); // unresolvable/unreadable throws — a configured rail never silently degrades
302
- const constraint = grammarConstraint(text);
303
- this.#gbnfCache.set(variant, constraint);
304
- process.stderr.write(`plurnk-engine: GBNF constraint: ${alias || "(bare)"} → ${variant} (${text.length} chars)\n`);
305
- return { ...constraint, allowWithheld };
241
+ return hit;
242
+ const text = await readFile(path, "utf8");
243
+ this.#grammarCache.set(path, text);
244
+ process.stderr.write(`plurnk-engine: operator grammar: ${alias || "(bare)"} → ${path} (${text.length} chars)\n`);
245
+ return text;
306
246
  }
307
247
  // A lineage's no-parent root; a root worker resolves to itself. Fail hard
308
248
  // when corruption leaves a worker without one. {§worker-primary}
@@ -342,10 +282,9 @@ export default class TurnRunner {
342
282
  }
343
283
  return { line, column };
344
284
  }
345
- // {§packet-attachment-parts} — a route receives, as native parts read from the scheme's bytes at
346
- // request time, the packet's attachments of every kind its model accepts; every other attachment
347
- // reaches it as the text projection alone.
348
- async #wireMessages(packet, workspaceId, provider) {
285
+ // {§packet-attachment-parts}: native parts come from the READ's immutable snapshot,
286
+ // never from a source that may have changed since the observation.
287
+ async #wireMessages(packet, ctx, provider) {
349
288
  const accepted = acceptedKinds(provider.inputModalities);
350
289
  if (accepted.length === 0 || !(packet.attachments ?? []).some((attachment) => accepted.includes(attachment.kind))) {
351
290
  return {
@@ -355,20 +294,14 @@ export default class TurnRunner {
355
294
  }
356
295
  const nativeInputs = new Set();
357
296
  const messages = await PacketWire.wireMessages(packet, async (attachment) => {
358
- const handler = this.#schemes.get(attachment.scheme);
359
- const source = handler?.byteSource?.(attachment.pathname, { db: this.#db, workspaceId });
360
- if (source === undefined)
361
- return null;
362
- const total = await source.size();
363
- if (total === null || total === 0)
364
- return null;
365
- const bytes = await source.read(1, total);
297
+ const bytes = await NativeContent.read(ctx.db, attachment.contentHash);
366
298
  nativeInputs.add(attachment.coordinate);
367
299
  return bytes;
368
300
  }, (kind) => accepted.includes(kind));
369
301
  return { messages, nativeInputs: [...nativeInputs] };
370
302
  }
371
- async runTurn({ provider, childProvider = provider, messages, recap = "", workspaceId, workerId, loopId, signal, onDispatch, onSettled, turnNumber = 1, maxTurns = 50, invalidEmissionRecoveryEntryId, }) {
303
+ async runTurn({ provider, childProvider = provider, messages, recap = "", workspaceId, workerId, loopId, signal, onDispatch, onSettled, turnNumber = 1, maxTurns = 50, invalidEmissionRecoveryEntryId, allowUnobservedRetrievalCompletion = false, }) {
304
+ const workerName = await WorkerName.forId(this.#db, workerId);
372
305
  const transientOpenLogEntryId = typeof invalidEmissionRecoveryEntryId === "number"
373
306
  ? invalidEmissionRecoveryEntryId
374
307
  : null;
@@ -404,8 +337,8 @@ export default class TurnRunner {
404
337
  createdTurnIds.push(initializationTurn.id);
405
338
  const initializationPolicies = initializationTurn === null
406
339
  ? []
407
- : (await CapabilityPolicies.layers(this.#db, workspaceId, workerId, await LoopPolicyReader.read(this.#db, loopId))).map((layer) => layer.policy);
408
- const initializationAdmits = (statement) => this.#capabilities.allowsAcross(statement, workerId, initializationPolicies);
340
+ : (await CapabilityPolicies.layers(this.#db, workspaceId)).map((layer) => layer.policy);
341
+ const initializationAdmits = (statement) => this.#capabilities.allowsAcross(statement, workspaceId, initializationPolicies);
409
342
  let modelTurn = initializationTurn === null
410
343
  ? await Turn.open(this.#db, { loopId, producer: "model", kind: "inference" })
411
344
  : null;
@@ -421,109 +354,68 @@ export default class TurnRunner {
421
354
  // Threaded per turn, never engine state, so concurrent loops on
422
355
  // different providers each read their own honest tokenizer values.
423
356
  const systemContext = (contextTurnId) => ({
424
- db: this.#db, workspaceId, workerId, functionalityWorkerId: workerId, loopId, turnId: contextTurnId,
357
+ db: this.#db, workspaceId, workerId, loopId, turnId: contextTurnId,
425
358
  writer: "_plurnk",
426
359
  signal: this.#loopSignal(loopId),
427
360
  streamEventNotify: this.#streamEventNotify,
428
361
  wakeWorkerNotify: this.#wakeWorkerNotify,
429
362
  weigh: this.#weighContent,
430
363
  mimetypes: this.#mimetypes,
431
- defaultChannelFor: (s) => this.#schemes.defaultChannelFor(s, workerId),
364
+ defaultChannelFor: (s) => this.#schemes.defaultChannelFor(s, workspaceId),
432
365
  pushNotice: (notice) => this.#notices.push(workspaceId, workerId, loopId, notice),
433
- requestInteraction: (request) => this.#interactions.request(request, { workspaceId, workerId, loopId, turnId: contextTurnId }, this.#loopSignal(loopId)),
366
+ requestInteraction: (request, signal = this.#loopSignal(loopId)) => this.#interactions.request(request, { workspaceId, workerId, loopId, turnId: contextTurnId }, signal),
434
367
  });
435
368
  let systemCtx = systemContext(initializationTurn?.id ?? modelTurn.id);
436
369
  // {§prompt-entry} — the prompt entry exists before any turn of the loop
437
- // runs, so the initialization COPY archives a real source; its `prompt`
438
- // log row is published to the model turn below (one durable publication
439
- // per loop, decided by that row).
370
+ // runs; its `prompt` log row is published to the model turn below (one
371
+ // durable publication per loop, decided by that row).
440
372
  const promptPublication = turnNumber === 1 && loopRow?.prompt_published === 0
441
373
  && typeof loopRow.prompt === "string" && loopRow.prompt.length > 0
442
374
  ? {
443
375
  content: loopRow.prompt,
444
376
  source: loopRow.prompt_source,
445
- path: promptTarget(loopRow.sequence, 1),
377
+ path: promptTarget(workerName, await PromptFrames.write(systemCtx, {
378
+ loopSequence: loopRow.sequence, ordinal: 1, content: loopRow.prompt,
379
+ source: loopRow.prompt_source, pathname: loopRow.prompt_pathname,
380
+ openPaths: assertOpenPaths(JSON.parse(loopRow.open_paths), `Loop ${loopId} open_paths`),
381
+ })),
446
382
  openPaths: assertOpenPaths(JSON.parse(loopRow.open_paths), `Loop ${loopId} open_paths`),
447
383
  }
448
384
  : null;
449
- if (promptPublication !== null) {
450
- const entry = {
451
- channels: { body: { content: promptPublication.content, mimetype: "text/markdown" } },
452
- attributes: {
453
- openPaths: promptPublication.openPaths,
454
- ...(promptPublication.source === null ? {} : { source: promptPublication.source }),
455
- },
456
- };
457
- await EntryCrud.writeEntry({ authority: "", pathname: promptPublication.path.pathname }, entry, systemCtx, "prompt", workerId);
458
- }
459
385
  const initializationStatements = [];
460
386
  // {§worker-initialization-entry} — the worker's first turn is the worked
461
- // example itself: an ordinary PLAN, the actual orienting operations,
462
- // and an ordinary terminal SEND.
387
+ // example itself: the actual orienting operations and an ordinary TASK.
463
388
  if (initializationTurn !== null) {
464
- const plan = {
465
- op: "PLAN", delimiter: "", annotation: "Determinations and Decisions must be persisted as `memory` items.",
466
- target: null, metadata: null, lineMarker: null,
467
- body: [
468
- {
469
- content: "Discover the tooling available and survey the workspace file root.",
470
- status: "in_progress",
471
- },
472
- ],
473
- position: UNKNOWN_POSITION,
474
- };
475
- initializationStatements.push(plan);
476
- // {§worker-initialization-entry} — the prompt is archived into the
477
- // worker's private space: the worked COPY specimen, and the private
478
- // space shown as scratch. An append onto an absent entry creates it.
479
- // Authored first among the operations because it executes first
480
- // ({§op-mode-phases}: Mutate precedes Observe).
481
- if (promptPublication !== null) {
482
- const archive = {
483
- op: "COPY", delimiter: "", annotation: null,
484
- source: { target: promptPublication.path, metadata: null, lineMarker: null },
485
- destination: {
486
- target: { kind: "url", raw: "worker://~/prompts.md", scheme: "worker", username: null, password: null, hostname: "~", port: null, pathname: "/prompts.md", query: null, fragment: null },
487
- metadata: null,
488
- lineMarker: { marks: [-1] },
489
- },
490
- position: UNKNOWN_POSITION,
491
- };
492
- initializationStatements.push(archive);
493
- }
494
389
  // {§turn0-agents-stunt} — the project AGENTS.md (materialized by LoopDocs as
495
- // worker://~/_plurnk/agents.md) gets one foisted READ on the worker's first
390
+ // worker:///_plurnk/agents.md) gets one foisted READ on the worker's first
496
391
  // loop, so local repo guidance is visible turn-0 content. Global policy
497
392
  // stays in the system prompt; nothing else is force-read.
498
393
  if (workerFirstInference) {
499
394
  const agentsEntry = await this.#db.crud_find_workspace_entry.get({
500
395
  workspace_id: workspaceId,
501
- owner_id: workerId,
502
396
  scheme: "worker",
503
397
  authority: "",
504
398
  pathname: generatedPathname("/agents.md"),
505
399
  });
506
400
  if (agentsEntry !== undefined) {
507
401
  const agentsTarget = {
508
- kind: "url", raw: "worker://~/_plurnk/agents.md", scheme: "worker",
509
- username: null, password: null, hostname: "~", port: null,
402
+ kind: "url", raw: "worker:///_plurnk/agents.md", scheme: "worker",
403
+ username: null, password: null, hostname: null, port: null,
510
404
  pathname: generatedPathname("/agents.md"), query: null, fragment: null,
511
405
  };
512
406
  const agentsRead = {
513
- op: "READ", delimiter: "", annotation: null, target: agentsTarget,
514
- metadata: null, lineMarker: null, body: null, position: UNKNOWN_POSITION,
407
+ op: "READ", aside: null, target: agentsTarget,
408
+ metadata: null, lineMarker: null, matcher: null, body: null, position: UNKNOWN_POSITION,
515
409
  };
516
410
  initializationStatements.push(agentsRead);
517
411
  }
518
412
  }
519
413
  }
520
414
  // The persistent search-index pass (_search-index.maintain) attaches
521
- // every readable entry/log projection to complete graph/FTS/vector derivations.
415
+ // every readable entry/log projection to complete graph/FTS derivations.
522
416
  // NOT an action: no log entry, no sequence slot,
523
417
  // not dispatched. There is no materialized manifest entry — the catalog
524
418
  // is served on demand by FIND: recursive when asked, shallow-mapped below.
525
- // {§semantic-embed-dedup} — one pass-wide semantic plan binds every
526
- // chunk counter to the derivation identity it produces.
527
419
  // SPEC {§membership} D4/D5 — git-ls-files workspace membership, resolved at
528
420
  // prompt-composition (EMI is eager + exhaustive — git is the only bound). When the
529
421
  // workspace's project_root is a git working tree, tracked files are
@@ -550,7 +442,7 @@ export default class TurnRunner {
550
442
  // Turn-0 catalog preview (PLURNK_SERVICE_FILES_ITEMS, {§actor-boundary-catalog-preview}):
551
443
  // Eight bodyless FIND surveys in the worker's packetless initialization turn establish the Agent
552
444
  // Skills, the plurnk references, the enabled tools, agents, and members, then the project, commons,
553
- // and private surfaces, in that order.
445
+ // and named scratch, in that order.
554
446
  // Their `init` classification lets the model curate this opening survey as one log set.
555
447
  if (initializationTurn !== null) {
556
448
  // {§operator-config-workspace-files-items} — workspace filesItems replaces the env default.
@@ -560,81 +452,49 @@ export default class TurnRunner {
560
452
  const catalogSchemes = await this.#db.engine_scheme_catalog_summary.all({ workspace_id: workspaceId });
561
453
  const fileItems = catalogSchemes.find(({ scheme }) => scheme === "file")?.shallow_items ?? 0;
562
454
  const fileCap = filesItems > 0 && fileItems > 0 ? Math.min(filesItems, fileItems) : null;
563
- // {§tools-resource-materialization} — a PLURNK_MCP_EXPANDED server
564
- // contributes one FIND over its family document matching the
565
- // `### EXEC0` headings: one row per tool — heading, annotation,
566
- // signature — paged like every survey. No document is delivered
567
- // unasked; per-target child documents do not exist.
455
+ // {§tools-resource-materialization} — expanded families project complete
456
+ // invocation blocks, paged through ordinary FIND result ranges.
568
457
  const registry = this.#executors();
569
- const references = await this.#packets.referenceEntries(workspaceId, workerId);
570
- const referenceNames = (namespace) => {
571
- const prefix = generatedPathname(`/${namespace}/`);
572
- return [...new Set(references.flatMap(({ pathname }) => {
573
- if (!pathname.startsWith(prefix) || !pathname.endsWith(".md"))
574
- return [];
575
- const name = pathname.slice(prefix.length, -3);
576
- return name.includes("/") ? [] : [name];
577
- }))].toSorted();
578
- };
579
- const schemeExamples = new Map(this.#schemes.examples(workerId).map(({ name, source }) => [name, source]));
580
- const runtimeAdmitted = (runtime) => {
581
- const tools = registry?.toolRegistry(runtime, workerId);
582
- return tools === null || tools === undefined
583
- ? this.#capabilities.allowsRuntimeAcross(runtime, null, workerId, initializationPolicies)
584
- : tools.tools.some((tool) => this.#capabilities.allowsRuntimeAcross(runtime, tool.target, workerId, initializationPolicies));
585
- };
586
- const referenceAdmitted = (namespace, name) => {
587
- const entry = registry?.entry(name, workerId);
588
- const entryNamespace = entry?.resourcesPath === "/tools" ? "tools" : "plurnk";
589
- if (entry !== undefined && entryNamespace === namespace)
590
- return runtimeAdmitted(name);
591
- const source = schemeExamples.get(name);
592
- return source === undefined
593
- || this.#capabilities.allowsExampleAcross(source, workerId, initializationPolicies);
594
- };
595
- const plurnkReferences = referenceNames("plurnk");
596
- const toolReferences = referenceNames("tools");
597
- const plurnkCatalog = workerCatalogTarget("plurnk", plurnkReferences, plurnkReferences.filter((name) => referenceAdmitted("plurnk", name)));
598
- const toolsCatalog = workerCatalogTarget("tools", toolReferences, toolReferences.filter((name) => referenceAdmitted("tools", name)));
458
+ const plurnkCatalog = workerCatalogTarget("plurnk");
459
+ const toolsCatalog = workerCatalogTarget("tools");
599
460
  const toolExpansions = [];
600
- for (const tag of registry?.availableRuntimes(workerId) ?? []) {
601
- const entry = registry?.entry(tag, workerId);
461
+ for (const tag of registry?.availableRuntimes(workspaceId) ?? []) {
462
+ const entry = registry?.entry(tag, workspaceId);
602
463
  if (entry?.resourcesPath !== "/tools" || entry.expandTools !== true)
603
464
  continue;
604
- const tools = registry?.toolRegistry(tag, workerId);
605
- const admittedTools = tools?.tools.filter((tool) => this.#capabilities.allowsRuntimeAcross(tag, tool.target, workerId, initializationPolicies)) ?? [];
465
+ const tools = registry?.toolRegistry(tag, workspaceId);
466
+ const admittedTools = tools?.tools.filter((tool) => this.#capabilities.allowsRuntimeAcross(tag, tool.target, workspaceId, initializationPolicies)) ?? [];
606
467
  if (admittedTools.length === 0)
607
468
  continue;
608
- const pattern = tools !== null && tools !== undefined && admittedTools.length !== tools.tools.length
609
- ? `^### EXEC0 \\[${regexLiteral(tag)}\\] \\((?:${admittedTools
610
- .map((tool) => regexLiteral(PathSyntax.escapeTarget(tool.target)))
611
- .join("|")})\\).*\\n.*$`
612
- : "^### EXEC0 .*\\n.*$";
469
+ const targetFilter = tools !== null && tools !== undefined && admittedTools.length !== tools.tools.length
470
+ ? " \\((?:" + admittedTools.map((tool) => regexLiteral(PathSyntax.escapeTarget(tool.target))).join("|") + ")\\)"
471
+ : " ";
472
+ const pattern = "^(\x60{3,})" + regexLiteral(tag) + targetFilter + "[^\\n]*?(?:\\1|\\n[\\s\\S]*?\\n\\1)$";
613
473
  toolExpansions.push({
614
474
  statement: {
615
- op: "FIND", delimiter: "", annotation: null,
616
- target: { kind: "url", raw: `worker://~/_plurnk/tools/${tag}.md`, scheme: "worker", username: null, password: null, hostname: "~", port: null, pathname: generatedPathname(`/tools/${tag}.md`), query: null, fragment: null },
475
+ op: "FIND", aside: null,
476
+ target: { kind: "url", raw: `worker:///_plurnk/tools/${tag}.md`, scheme: "worker", username: null, password: null, hostname: null, port: null, pathname: generatedPathname(`/tools/${tag}.md`), query: null, fragment: null },
617
477
  metadata: null,
618
- body: { dialect: "regex", raw: `/${pattern.replaceAll("/", "\\/")}/m`, pattern, flags: "m" },
619
- lineMarker: null, position: UNKNOWN_POSITION,
478
+ matcher: { dialect: "regex", raw: `/${pattern.replaceAll("/", "\\/")}/m`, pattern, flags: "m" },
479
+ body: null, lineMarker: null, position: UNKNOWN_POSITION,
620
480
  },
621
481
  });
622
482
  }
623
483
  const surveys = [
624
484
  {
625
485
  statement: {
626
- op: "FIND", delimiter: "", annotation: null,
627
- target: { kind: "url", raw: "worker://~/_plurnk/skills/*.md", scheme: "worker", username: null, password: null, hostname: "~", port: null, pathname: generatedPathname("/skills/*.md"), query: null, fragment: null },
486
+ op: "FIND", aside: null,
487
+ target: { kind: "url", raw: "skill://*/SKILL.md", scheme: "skill", username: null, password: null, hostname: "*", port: null, pathname: "/SKILL.md", query: null, fragment: null },
628
488
  metadata: null,
629
- body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
489
+ matcher: null, body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
630
490
  },
631
491
  },
632
492
  ...(plurnkCatalog === null ? [] : [{
633
493
  statement: {
634
- op: "FIND", delimiter: "", annotation: null,
494
+ op: "FIND", aside: null,
635
495
  target: plurnkCatalog,
636
496
  metadata: null,
637
- body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
497
+ matcher: null, body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
638
498
  },
639
499
  }]),
640
500
  ...(toolsCatalog === null ? [] : [{
@@ -645,10 +505,10 @@ export default class TurnRunner {
645
505
  // PLURNK_MCP_EXPANDED add a second survey of their complete
646
506
  // tool tree.
647
507
  statement: {
648
- op: "FIND", delimiter: "", annotation: null,
508
+ op: "FIND", aside: null,
649
509
  target: toolsCatalog,
650
510
  metadata: null,
651
- body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
511
+ matcher: null, body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
652
512
  },
653
513
  }]),
654
514
  ...toolExpansions,
@@ -657,27 +517,28 @@ export default class TurnRunner {
657
517
  // alias level; each row's summary is the agent's identity line,
658
518
  // the exact card stays pullable through READ a2a://<alias>.
659
519
  statement: {
660
- op: "FIND", delimiter: "", annotation: null,
661
- target: { kind: "url", raw: "worker://~/_plurnk/agents/*.md", scheme: "worker", username: null, password: null, hostname: "~", port: null, pathname: generatedPathname("/agents/*.md"), query: null, fragment: null },
520
+ op: "FIND", aside: null,
521
+ target: { kind: "url", raw: "worker:///_plurnk/agents/*.md", scheme: "worker", username: null, password: null, hostname: null, port: null, pathname: generatedPathname("/agents/*.md"), query: null, fragment: null },
662
522
  metadata: null,
663
- body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
523
+ matcher: null, body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
664
524
  },
665
525
  },
666
526
  {
667
527
  // {§members-projection} — enabled members definitions survey at alias
668
528
  // level; each row's summary is what its glob resolved to.
669
529
  statement: {
670
- op: "FIND", delimiter: "", annotation: null,
671
- target: { kind: "url", raw: "worker://~/_plurnk/members/*.md", scheme: "worker", username: null, password: null, hostname: "~", port: null, pathname: generatedPathname("/members/*.md"), query: null, fragment: null },
530
+ op: "FIND", aside: null,
531
+ target: { kind: "url", raw: "worker:///_plurnk/members/*.md", scheme: "worker", username: null, password: null, hostname: null, port: null, pathname: generatedPathname("/members/*.md"), query: null, fragment: null },
672
532
  metadata: null,
673
- body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
533
+ matcher: null, body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
674
534
  },
675
535
  },
676
536
  {
677
537
  statement: {
678
- op: "FIND", delimiter: "", annotation: "workspace files",
538
+ op: "FIND", aside: "project root member files",
679
539
  target: { kind: "local", raw: "*" },
680
540
  metadata: null,
541
+ matcher: null,
681
542
  body: null,
682
543
  lineMarker: fileCap === null ? null : { marks: [1, fileCap] },
683
544
  position: UNKNOWN_POSITION,
@@ -685,37 +546,52 @@ export default class TurnRunner {
685
546
  },
686
547
  {
687
548
  statement: {
688
- op: "FIND", delimiter: "", annotation: "workspace entries",
549
+ op: "FIND", aside: "shared worker Extended Context",
689
550
  target: { kind: "url", raw: "worker:///*", scheme: "worker", username: null, password: null, hostname: null, port: null, pathname: "/*", query: null, fragment: null },
690
551
  metadata: null,
691
- body: null, lineMarker: null, position: UNKNOWN_POSITION,
552
+ matcher: null, body: null, lineMarker: null, position: UNKNOWN_POSITION,
692
553
  },
693
554
  },
694
555
  {
695
556
  statement: {
696
- op: "FIND", delimiter: "", annotation: "private worker entries",
697
- target: { kind: "url", raw: "worker://~/*", scheme: "worker", username: null, password: null, hostname: "~", port: null, pathname: "/*", query: null, fragment: null },
557
+ op: "FIND", aside: "private worker Extended Context",
558
+ target: { kind: "url", raw: `worker://${workerName}/*`, scheme: "worker", username: null, password: null, hostname: workerName, port: null, pathname: "/*", query: null, fragment: null },
698
559
  metadata: null,
699
- body: null, lineMarker: null, position: UNKNOWN_POSITION,
560
+ matcher: null, body: null, lineMarker: null, position: UNKNOWN_POSITION,
700
561
  },
701
562
  },
702
563
  ];
703
- initializationStatements.push(...surveys.map(({ statement }) => statement));
564
+ initializationStatements.push(...surveys.map(({ statement }) => statement).filter(({ target }) => this.#schemes.get(target?.kind === "url" ? target.scheme : "file", workspaceId) !== undefined));
704
565
  }
705
- const send = {
706
- op: "SEND", delimiter: "", annotation: null,
707
- status: 102, target: null, metadata: null, lineMarker: null,
708
- body: { raw: "Next: Address the prompt.", json: null },
566
+ const task = {
567
+ op: "TASK", aside: null, target: null, metadata: null, lineMarker: null,
568
+ body: [{ content: "Address the prompt.", status: "in_progress" }],
709
569
  position: UNKNOWN_POSITION,
710
570
  };
711
- initializationStatements.push(send);
571
+ const pathname = `/${loopRow.sequence}/${initializationTurn.sequence}`;
572
+ await Turn.recordSource(this.#db, initializationTurn.id, "reasoning", ReasoningView.initialSource());
573
+ // {§reasoning-initial-read} — the pattern READ needs a text/plain projection to run the regex.
574
+ const pluck = await this.#mimetypes.getHandler("text/plain") !== null;
575
+ const reasoningRead = ReasoningView.initialRead(provider, loopRow.sequence, initializationTurn.sequence, pluck);
576
+ if (reasoningRead !== null)
577
+ initializationStatements.push(reasoningRead);
578
+ initializationStatements.push({
579
+ op: "READ", aside: "inspect this turn's emission", matcher: null, body: null, metadata: null,
580
+ target: {
581
+ kind: "url", raw: `ops://${pathname}`, scheme: "ops", pathname,
582
+ username: null, password: null, hostname: null, port: null, query: null, fragment: null,
583
+ },
584
+ lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
585
+ });
586
+ // {§prompt-entry} — the prompt reaches the model as its `prompt` row in the first
587
+ // model turn; initialization does not READ it a second time.
588
+ initializationStatements.push(task);
712
589
  const admittedInitializationStatements = initializationStatements.filter(initializationAdmits);
713
590
  const source = TurnOps.renderInternal(admittedInitializationStatements);
714
591
  const admitted = TurnOps.parseInternal(source);
715
592
  const result = await this.executeAdmittedTurn({
716
593
  statements: admitted,
717
594
  source,
718
- sourceFolded: false,
719
595
  origin: "_plurnk",
720
596
  workspaceId,
721
597
  workerId,
@@ -728,7 +604,7 @@ export default class TurnRunner {
728
604
  onSettled,
729
605
  });
730
606
  if (result.status !== TURN_STATUS_IMPLICIT_CONTINUE) {
731
- throw new Error(`initialization SEND returned ${result.status}; expected ${TURN_STATUS_IMPLICIT_CONTINUE}`);
607
+ throw new Error(`initialization TASK returned ${result.status}; expected ${TURN_STATUS_IMPLICIT_CONTINUE}`);
732
608
  }
733
609
  }
734
610
  // Initialization is a complete preceding turn, not a set of rows
@@ -767,7 +643,7 @@ export default class TurnRunner {
767
643
  const loopSeq = loopSeqRow?.sequence ?? loopId;
768
644
  const prefix = promptLoopPrefix(loopSeq);
769
645
  const undelivered = (await this.#db.drain_undelivered_prompts_for_loop.all({
770
- owner_id: workerId,
646
+ worker_id: workerId,
771
647
  pattern: `${prefix}%`,
772
648
  prefix_len: prefix.length,
773
649
  loop_id: loopId,
@@ -778,13 +654,12 @@ export default class TurnRunner {
778
654
  if (attributes.openPaths !== undefined) {
779
655
  turnOpenPaths.push(...assertOpenPaths(attributes.openPaths, `Prompt ${injectedRow.pathname} openPaths`));
780
656
  }
781
- const ordinal = Number(injectedRow.pathname.split("/").filter(Boolean).at(-1));
782
657
  const promptLogId = await this.#materialization.writePromptLog({
783
658
  workerId,
784
659
  loopId,
785
660
  turnId,
786
661
  sequence: nextActionIndex++,
787
- target: promptTarget(loopSeq, ordinal),
662
+ target: promptTarget(workerName, injectedRow.pathname),
788
663
  content: injectedRow.content,
789
664
  source: promptSourceFromAttributes(attributes, `Prompt ${injectedRow.pathname} attributes`),
790
665
  });
@@ -798,7 +673,7 @@ export default class TurnRunner {
798
673
  for (const raw of turnOpenPaths) {
799
674
  const pathname = raw.startsWith("/") ? raw : `/${raw}`;
800
675
  const fileRead = {
801
- op: "READ", delimiter: "", annotation: null, lineMarker: null,
676
+ op: "READ", aside: null, lineMarker: null, matcher: null,
802
677
  target: {
803
678
  kind: "url", raw: `file://${pathname}`, scheme: "file",
804
679
  username: null, password: null, hostname: null, port: null,
@@ -821,7 +696,7 @@ export default class TurnRunner {
821
696
  // the subsequent turn. The terminal output then surfaces initially visible via the stream-delta path.
822
697
  await this.#reapTurnScopedStreams(workerId);
823
698
  nextActionIndex += await this.#materialization.materializeEnvironmentDeltas({ workspaceId, workerId, loopId, turnId, fromSequence: nextActionIndex });
824
- nextActionIndex += await this.#materialization.materializeStreamDeltas({ workerId, loopId, turnId, fromSequence: nextActionIndex });
699
+ nextActionIndex += await this.#materialization.materializeStreamDeltas({ workspaceId, workerId, loopId, turnId, fromSequence: nextActionIndex });
825
700
  // The post-reconciliation Git snapshot above is threaded into the packet
826
701
  // and every budget rebuild; overflow never shells again.
827
702
  // Notices are non-terminal observations, never operation-failure truth.
@@ -832,6 +707,7 @@ export default class TurnRunner {
832
707
  // queries log_entries scoped to the worker — the prompt entry just
833
708
  // written (if turn 1) is part of that query result.
834
709
  let promptProjection = "automatic";
710
+ const loopSeq = (await this.#db.engine_loop_sequence.get({ loop_id: loopId }))?.sequence ?? loopId;
835
711
  const buildPacket = () => this.#packets.buildRequestPacket({
836
712
  initialMessages: messages,
837
713
  recap,
@@ -844,63 +720,35 @@ export default class TurnRunner {
844
720
  notices,
845
721
  transientOpenLogEntryId,
846
722
  promptProjection,
723
+ turnId,
847
724
  });
848
725
  let requestPacket = await buildPacket();
849
- // {§overflow-turn} — measured overflow diverts this would-be model
850
- // turn into an ordinary packetless `_plurnk` operation batch. Every
851
- // visibility effect goes through an ordinary Dispatcher scoped KILL; provider I/O is
852
- // structurally unreachable on this branch.
853
- const pressure = this.#packets.curationOverflow(requestPacket, provider);
854
- if (pressure !== null) {
855
- const kills = await OverflowTurn.plan(this.#db, loopId, turnId);
856
- await Turn.becomeOverflow(this.#db, turnId);
857
- const internalStatements = [
858
- OverflowTurn.planStatement(),
859
- ...kills.map(({ statement }) => statement),
860
- OverflowTurn.sendStatement(),
861
- ];
862
- const source = TurnOps.renderInternal(internalStatements);
863
- const admitted = TurnOps.parseInternal(source);
864
- const executed = await this.executeAdmittedTurn({
865
- statements: admitted,
866
- source,
867
- sourceFolded: true,
868
- origin: "_plurnk",
869
- workspaceId,
870
- workerId,
871
- loopId,
872
- turnId,
873
- fromSequence: nextActionIndex,
874
- failOnOperationError: true,
875
- signal: this.#loopSignal(loopId),
876
- onDispatch,
877
- onSettled,
878
- });
879
- if (executed.status !== TURN_STATUS_IMPLICIT_CONTINUE) {
880
- throw new Error(`overflow SEND returned ${executed.status}; expected ${TURN_STATUS_IMPLICIT_CONTINUE}`);
881
- }
882
- const rebuilt = await buildPacket();
883
- const remaining = this.#packets.curationOverflow(rebuilt, provider);
884
- const curationFailure = kills.length === 0 || remaining !== null
885
- ? curationOverflowFailure(remaining ?? pressure)
886
- : undefined;
726
+ // {§context-output-admission} — output admission changes no operation
727
+ // outcome, authored inventory, or turn identity.
728
+ if (await this.#packets.admitOutput(requestPacket, turnId))
729
+ requestPacket = await buildPacket();
730
+ const remaining = this.#packets.curationOverflow(requestPacket);
731
+ if (remaining !== null) {
732
+ const curationFailure = curationOverflowFailure(remaining);
733
+ await Turn.complete(this.#db, turnId, curationFailure.status);
887
734
  return {
888
735
  createdTurnIds,
889
736
  turnId,
890
- producer: "_plurnk",
891
- kind: "overflow",
892
- status: curationFailure?.status ?? TURN_STATUS_IMPLICIT_CONTINUE,
737
+ producer: "model",
738
+ kind: "inference",
739
+ status: curationFailure.status,
893
740
  outcomes: [],
894
741
  fingerprint: "",
895
742
  capacityHardStop: false,
896
743
  providerParked: false,
897
744
  steerStruck: false,
745
+ emptyTurn: false,
898
746
  emissionAttempts: 0,
899
747
  emissionExhausted: false,
900
- ...(curationFailure === undefined ? {} : { curationFailure }),
748
+ curationFailure,
901
749
  };
902
750
  }
903
- let materializedRequest = await this.#wireMessages(requestPacket, workspaceId, provider);
751
+ let materializedRequest = await this.#wireMessages(requestPacket, systemCtx, provider);
904
752
  let modelMessages = materializedRequest.messages;
905
753
  let nativeInputs = materializedRequest.nativeInputs;
906
754
  // Curation pressure and provider generation are independent. The
@@ -908,8 +756,6 @@ export default class TurnRunner {
908
756
  let response;
909
757
  let splitResponse;
910
758
  let railGrammar;
911
- let railResponseGrammar;
912
- let railAllowWithheld = false;
913
759
  let railEvidence;
914
760
  let emissionAttempts = 0;
915
761
  let providerCallInFlight = false;
@@ -928,7 +774,6 @@ export default class TurnRunner {
928
774
  const providerSignal = this.#loopSignal(loopId) ?? signal;
929
775
  // {§client-metadata}
930
776
  const { client } = await WorkspaceSettings.read(this.#db, workspaceId);
931
- const loopSeq = (await this.#db.engine_loop_sequence.get({ loop_id: loopId }))?.sequence ?? loopId;
932
777
  const providerIdentity = await this.#resolveWorkerProviderIdentity(workerId);
933
778
  const { workerId: providerWorkerId, primaryWorkerId } = providerIdentity;
934
779
  const classifyProviderAttempt = async (id, attemptSplit, emissionAttempt, accepted) => {
@@ -947,7 +792,7 @@ export default class TurnRunner {
947
792
  if (promptProjection === "automatic") {
948
793
  promptProjection = "withheld";
949
794
  const candidate = await buildPacket();
950
- const candidateRequest = await this.#wireMessages(candidate, workspaceId, provider);
795
+ const candidateRequest = await this.#wireMessages(candidate, systemCtx, provider);
951
796
  if (JSON.stringify(candidateRequest.messages) !== JSON.stringify(baselineMessages)) {
952
797
  requestPacket = candidate;
953
798
  materializedRequest = candidateRequest;
@@ -963,12 +808,9 @@ export default class TurnRunner {
963
808
  // {§turn-lifecycle}: bracket the complete provider-attempt window with liveness notices.
964
809
  if (!signal?.aborted)
965
810
  this.#notices.push(workspaceId, workerId, loopId, { source: "engine:turn", kind: "turn_awaiting_model", level: "info", message: "awaiting model response" });
966
- const railConstraint = await this.#grammarConstraint(provider);
967
- railGrammar = railConstraint?.transport;
968
- railResponseGrammar = railConstraint?.response;
969
- railAllowWithheld = railConstraint?.allowWithheld ?? false;
811
+ railGrammar = await this.#operatorGrammar(provider);
970
812
  const attemptLimit = readEmissionAttempts();
971
- const strikeStreak = this.#strikes.streak(loopId);
813
+ const strikeStreak = await this.#strikes.streak(loopId);
972
814
  // {§turn-accounting-notice} (#465) — every physical exchange this turn pays
973
815
  // for, successes and failed calls alike, so the completion notice carries
974
816
  // the exact settled wire spend.
@@ -1059,6 +901,7 @@ export default class TurnRunner {
1059
901
  completedResponse = await observed(// {§observability-boundary}
1060
902
  GEN_AI_REQUEST_SPAN, { model: provider.model, attempt: modelCallSequence }, async (span) => {
1061
903
  try {
904
+ await this.#packets.recordObservations(requestPacket);
1062
905
  const generated = await provider.generate({
1063
906
  messages: modelMessages,
1064
907
  workerId: providerWorkerId,
@@ -1116,7 +959,7 @@ export default class TurnRunner {
1116
959
  // {§provider-interrupted-attempt} — the interrupted response stays durable
1117
960
  // as an unaccepted attempt; it is never admitted or replayed.
1118
961
  await currentModelCall.observeResponse(error.attempt, failure, nativeInputs);
1119
- await classifyProviderAttempt(providerAttemptId, this.#splitResponse(error.attempt), currentEmissionAttempt, false);
962
+ await classifyProviderAttempt(providerAttemptId, this.#splitResponse(error.attempt, this.#executors()?.availableRuntimes(workspaceId) ?? []), currentEmissionAttempt, false);
1120
963
  }
1121
964
  else {
1122
965
  await currentModelCall.fail(failure, error.capacity ?? null);
@@ -1166,7 +1009,7 @@ export default class TurnRunner {
1166
1009
  // Include the durable recovery signal in the replacement
1167
1010
  // request while preserving the selected recovery posture.
1168
1011
  requestPacket = await buildPacket();
1169
- materializedRequest = await this.#wireMessages(requestPacket, workspaceId, provider);
1012
+ materializedRequest = await this.#wireMessages(requestPacket, systemCtx, provider);
1170
1013
  modelMessages = materializedRequest.messages;
1171
1014
  nativeInputs = materializedRequest.nativeInputs;
1172
1015
  continue;
@@ -1187,10 +1030,8 @@ export default class TurnRunner {
1187
1030
  response = completedResponse;
1188
1031
  turnWireAccounting.push(...completedResponse.accounting);
1189
1032
  await currentModelCall.observeResponse(completedResponse, null, nativeInputs);
1190
- railEvidence = railGrammar === undefined
1191
- ? undefined
1192
- : TurnRunner.#requireGrammarEvidence(completedResponse, railAllowWithheld);
1193
- splitResponse = this.#splitResponse(completedResponse);
1033
+ railEvidence = railGrammar === undefined ? undefined : completedResponse.grammarEvidence;
1034
+ splitResponse = this.#splitResponse(completedResponse, this.#executors()?.availableRuntimes(workspaceId) ?? []);
1194
1035
  await classifyProviderAttempt(attemptRow.id, splitResponse, attempt, splitResponse.emissionValid);
1195
1036
  if (splitResponse.emissionValid)
1196
1037
  break;
@@ -1235,7 +1076,7 @@ export default class TurnRunner {
1235
1076
  if (err instanceof ProviderError && err.attempt !== undefined) {
1236
1077
  response = err.attempt;
1237
1078
  await providerModelCall.observeResponse(response, failure, nativeInputs);
1238
- splitResponse = this.#splitResponse(response);
1079
+ splitResponse = this.#splitResponse(response, this.#executors()?.availableRuntimes(workspaceId) ?? []);
1239
1080
  await classifyProviderAttempt(providerAttemptId, splitResponse, currentEmissionAttempt, false);
1240
1081
  }
1241
1082
  else {
@@ -1244,10 +1085,9 @@ export default class TurnRunner {
1244
1085
  emissionAttempts = currentEmissionAttempt;
1245
1086
  }
1246
1087
  // {§turn-never-blank} — a ProviderError means no completed exchange exists.
1247
- // Persist its exact RFC 9457 result before propagating it. Grammar evidence
1248
- // and its engine-owned verdict exist only on completed responses
1249
- // ({§rail-truth-engine-verdict}). Cancellation is lifecycle truth, not a
1250
- // provider failure. Close the
1088
+ // Persist its exact RFC 9457 result before propagating it. Grammar transport
1089
+ // evidence exists only on completed responses ({§operator-grammar}).
1090
+ // Cancellation is lifecycle truth, not a provider failure. Close the
1251
1091
  // attempted turn without inventing an assistant response, then let
1252
1092
  // runLoop/Daemon settle the exact 504/499 loop result.
1253
1093
  if (providerSignal?.aborted) {
@@ -1256,7 +1096,8 @@ export default class TurnRunner {
1256
1096
  workspaceId, workerId, loopId, turnId,
1257
1097
  evidence: {
1258
1098
  packet: StoredPacket.stringify(requestPacket),
1259
- usageCurationBudget: this.#packets.curationBudgetFor(provider),
1099
+ sections: StoredPacket.sections(requestPacket),
1100
+ usageCurationBudget: this.#packets.curationBudgetFor(requestPacket),
1260
1101
  finishReason: splitResponse?.callMetadata.finishReason ?? null,
1261
1102
  model: splitResponse?.callMetadata.model ?? provider.model,
1262
1103
  meta: JSON.stringify(response?.meta ?? {}),
@@ -1281,7 +1122,8 @@ export default class TurnRunner {
1281
1122
  workspaceId, workerId, loopId, turnId,
1282
1123
  evidence: {
1283
1124
  packet: StoredPacket.stringify(requestPacket),
1284
- usageCurationBudget: this.#packets.curationBudgetFor(provider),
1125
+ sections: StoredPacket.sections(requestPacket),
1126
+ usageCurationBudget: this.#packets.curationBudgetFor(requestPacket),
1285
1127
  finishReason: splitResponse?.callMetadata.finishReason ?? null,
1286
1128
  model: splitResponse?.callMetadata.model ?? provider.model,
1287
1129
  meta: JSON.stringify(response?.meta ?? {}),
@@ -1308,6 +1150,7 @@ export default class TurnRunner {
1308
1150
  capacityHardStop: false, providerParked: true,
1309
1151
  providerFailure: recorded.result,
1310
1152
  steerStruck: false,
1153
+ emptyTurn: false,
1311
1154
  emissionAttempts,
1312
1155
  emissionExhausted: false,
1313
1156
  };
@@ -1325,6 +1168,7 @@ export default class TurnRunner {
1325
1168
  providerParked: false,
1326
1169
  capacityFailure: recorded.result,
1327
1170
  steerStruck: false,
1171
+ emptyTurn: false,
1328
1172
  emissionAttempts,
1329
1173
  emissionExhausted: false,
1330
1174
  };
@@ -1347,6 +1191,7 @@ export default class TurnRunner {
1347
1191
  providerParked: false,
1348
1192
  providerFailure: recorded.result,
1349
1193
  steerStruck: false,
1194
+ emptyTurn: false,
1350
1195
  emissionAttempts,
1351
1196
  emissionExhausted: false,
1352
1197
  };
@@ -1357,6 +1202,9 @@ export default class TurnRunner {
1357
1202
  throw new Error("provider attempt loop completed without a response");
1358
1203
  }
1359
1204
  const emissionModelCallId = providerModelCall.id;
1205
+ if (splitResponse.packetAssistant.reasoning?.length) {
1206
+ await Turn.recordSource(this.#db, turnId, "reasoning", splitResponse.packetAssistant.reasoning, { modelCallId: emissionModelCallId });
1207
+ }
1360
1208
  if (!splitResponse.emissionValid) {
1361
1209
  // {§invalid-emission-attempts} Every exhaustion publishes the raw final
1362
1210
  // response and its recovery fact; {§engine-rails} Contract Strikes rule
@@ -1370,9 +1218,6 @@ export default class TurnRunner {
1370
1218
  turnId,
1371
1219
  sequence: nextActionIndex,
1372
1220
  modelCallId: emissionModelCallId,
1373
- ...(response.assistant.reasoningEncrypted?.length
1374
- ? { reasoningItems: response.assistant.reasoningEncrypted }
1375
- : {}),
1376
1221
  });
1377
1222
  // {§invalid-emission-attempts} — the informed turn carries the parser's own
1378
1223
  // diagnostic and position: the model sees WHY, not only that it was refused.
@@ -1405,7 +1250,8 @@ export default class TurnRunner {
1405
1250
  workspaceId, workerId, loopId, turnId,
1406
1251
  evidence: {
1407
1252
  packet: StoredPacket.stringify(requestPacket),
1408
- usageCurationBudget: this.#packets.curationBudgetFor(provider),
1253
+ sections: StoredPacket.sections(requestPacket),
1254
+ usageCurationBudget: this.#packets.curationBudgetFor(requestPacket),
1409
1255
  finishReason: splitResponse.callMetadata.finishReason,
1410
1256
  model: splitResponse.callMetadata.model,
1411
1257
  meta: JSON.stringify(response.meta ?? {}),
@@ -1423,6 +1269,7 @@ export default class TurnRunner {
1423
1269
  capacityHardStop: false,
1424
1270
  providerParked: false,
1425
1271
  steerStruck: false,
1272
+ emptyTurn: false,
1426
1273
  emissionAttempts,
1427
1274
  emissionExhausted: true,
1428
1275
  ...(rejectedModelEntryId === undefined ? {} : { rejectedModelEntryId }),
@@ -1434,9 +1281,22 @@ export default class TurnRunner {
1434
1281
  for (const notice of parseNotices) {
1435
1282
  this.#notices.push(workspaceId, workerId, loopId, notice);
1436
1283
  }
1284
+ // {§empty-turn} — a response cut at the output allowance with nothing admitted names the
1285
+ // cut, so the model reads the ceiling, never a parser symptom (#478).
1286
+ if (splitResponse.emptyTurn && callMetadata.finishReason === "length") {
1287
+ const cut = allowanceCutMessage(callMetadata.finishReason, response.capacity.responseMax ?? provider.outputBudget);
1288
+ if (cut !== null) {
1289
+ this.#notices.push(workspaceId, workerId, loopId, {
1290
+ source: "engine:turn",
1291
+ kind: "output_truncated",
1292
+ level: "warn",
1293
+ message: `${cut}; no operations were performed`,
1294
+ });
1295
+ }
1296
+ }
1437
1297
  // Non-fatal provider transport notices on an accepted turn. Forward each
1438
1298
  // Notice with a content-offset `line:col`;
1439
- // the model resolves it against its own emission — READ the body-suppressed turnOps row at the
1299
+ // the model resolves it against its own emission — READ ops:///<loop>/<turn> at the
1440
1300
  // cited lines ({§turn-ops-entry}) — not an embedded snippet that would duplicate the emission.
1441
1301
  for (const notice of response.notices ?? []) {
1442
1302
  const located = typeof notice.position === "number"
@@ -1461,45 +1321,12 @@ export default class TurnRunner {
1461
1321
  level: "warn",
1462
1322
  });
1463
1323
  }
1464
- // Grade configured local evidence independently. Endpoint-owned
1465
- // constraints remain provider observations. {§rail-truth-engine-verdict}
1466
- let railKeys;
1467
- if (railGrammar !== undefined) {
1468
- if (railEvidence === undefined)
1469
- throw new Error("configured GBNF response has no final grammar evidence");
1470
- if (railResponseGrammar === undefined)
1471
- throw new Error("configured GBNF has no response grammar");
1472
- let verdict = null;
1473
- try {
1474
- verdict = validateGbnf(railResponseGrammar, railEvidence.input);
1475
- }
1476
- catch (cause) {
1477
- TurnRunner.#warnRailVerdictGapOnce(cause.message);
1478
- }
1479
- railKeys = {
1480
- railsAttached: railEvidence.transported ? "client" : "withheld",
1481
- railsVerdict: verdict?.status ?? "unverifiable",
1482
- };
1483
- if (verdict !== null && verdict.status !== "accept" && allowanceCut === null) {
1484
- const contentPosition = verdict.pos >= railEvidence.contentStart
1485
- ? verdict.pos - railEvidence.contentStart
1486
- : null;
1487
- const located = contentPosition === null
1488
- ? null
1489
- : this.#offsetToLineColumn(packetAssistant.content, contentPosition);
1490
- this.#notices.push(workspaceId, workerId, loopId, {
1491
- source: "engine:rails",
1492
- kind: "grammar_unenforced",
1493
- message: verdict.status === "reject"
1494
- ? `emission rejects the grammar at raw code point ${verdict.pos}`
1495
- : `emission is an incomplete grammar sentence (ends at raw code point ${verdict.pos})`,
1496
- level: "warn",
1497
- ...(located === null
1498
- ? {}
1499
- : { position: { type: "content-offset", line: located.line, column: located.column } }),
1500
- });
1501
- }
1502
- }
1324
+ // {§operator-grammar} — transport evidence only: the turn records whether the operator's
1325
+ // grammar reached the wire. Nothing grades the response against it; the parser's
1326
+ // admission is the one verdict (#588).
1327
+ const railKeys = railGrammar === undefined
1328
+ ? undefined
1329
+ : { railsAttached: railEvidence?.transported === true ? "client" : "withheld" };
1503
1330
  // Attach the admitted inference evidence. The turn remains open until
1504
1331
  // the producer-neutral admitted-turn executor settles every operation
1505
1332
  // and its exact source artifact.
@@ -1508,11 +1335,12 @@ export default class TurnRunner {
1508
1335
  workspaceId, workerId, loopId, turnId,
1509
1336
  evidence: {
1510
1337
  packet: StoredPacket.stringify(packet),
1511
- usageCurationBudget: this.#packets.curationBudgetFor(provider), // {§tokenomics-client-gauge}
1338
+ sections: StoredPacket.sections(packet),
1339
+ usageCurationBudget: this.#packets.curationBudgetFor(requestPacket), // {§tokenomics-client-gauge}
1512
1340
  finishReason: callMetadata.finishReason,
1513
1341
  model: callMetadata.model,
1514
- // Opaque provider metadata plus engine-authored rail keys.
1515
- // {§meta-passthrough}, {§rail-truth-engine-verdict}
1342
+ // Opaque provider metadata plus the grammar transport key.
1343
+ // {§meta-passthrough}, {§operator-grammar}
1516
1344
  meta: JSON.stringify({ ...(response.meta ?? {}), ...(railKeys ?? {}) }),
1517
1345
  },
1518
1346
  });
@@ -1520,15 +1348,10 @@ export default class TurnRunner {
1520
1348
  // narrows the operator ceiling before the admitted program reaches the
1521
1349
  // shared executor.
1522
1350
  const maxCommands = Math.min(readMaxCommands(), (await WorkspaceSettings.read(this.#db, workspaceId)).maxCommands ?? Number.POSITIVE_INFINITY);
1523
- const reasoningItems = response.assistant.reasoningEncrypted?.length
1524
- ? response.assistant.reasoningEncrypted
1525
- : undefined;
1526
1351
  const executed = await this.executeAdmittedTurn({
1527
1352
  statements: packetAssistant.ops,
1528
1353
  source: splitResponse.sourceBacked ? packetAssistant.content : null,
1529
- sourceFolded: true,
1530
1354
  sourceModelCallId: emissionModelCallId,
1531
- ...(reasoningItems !== undefined ? { sourceReasoningItems: reasoningItems } : {}),
1532
1355
  origin: "model",
1533
1356
  workspaceId,
1534
1357
  workerId,
@@ -1536,8 +1359,9 @@ export default class TurnRunner {
1536
1359
  turnId,
1537
1360
  fromSequence: nextActionIndex,
1538
1361
  maxCommands,
1539
- enforceIdle: true,
1362
+ allowUnobservedRetrievalCompletion,
1540
1363
  recoverableParseErrors,
1364
+ emptyTurn: splitResponse.emptyTurn,
1541
1365
  bare: {
1542
1366
  provider: childProvider,
1543
1367
  primaryWorkerId,
@@ -1560,6 +1384,7 @@ export default class TurnRunner {
1560
1384
  capacityHardStop: false,
1561
1385
  providerParked: false,
1562
1386
  steerStruck: executed.steerStruck,
1387
+ emptyTurn: executed.emptyTurn,
1563
1388
  emissionAttempts,
1564
1389
  emissionExhausted: false,
1565
1390
  };
@@ -1592,13 +1417,11 @@ export default class TurnRunner {
1592
1417
  // its assistant payload to skip the parse roundtrip. The wire Provider
1593
1418
  // contract has no `ops` field; only Mock exposes one. Real providers
1594
1419
  // always take the parse path because their `assistant.ops` is undefined.
1595
- #splitResponse(response) {
1420
+ #splitResponse(response, executors = []) {
1596
1421
  const { assistant } = response;
1597
1422
  const preParsedOps = assistant.ops;
1598
1423
  const ops = [];
1599
- // PLAN is an ordinary op — emitted by the model, dispatched, and passed to the
1600
- // client as a log entry. No special hoisting into the reasoning field. Only
1601
- // structured operations are executable; interstitial text is not an operation.
1424
+ // Only structured operations are executable; interstitial text is not an operation.
1602
1425
  // Full PlurnkParseError context is preserved on rejected attempt evidence;
1603
1426
  // warnings remain admissible Notices. {§parse-diagnostics}
1604
1427
  const parseErrors = [];
@@ -1611,7 +1434,9 @@ export default class TurnRunner {
1611
1434
  // {§observability-boundary} — the parse is observed without its input;
1612
1435
  // only the resulting statement count is attributable.
1613
1436
  const parsed = observedSync("contracts.parse", {}, (span) => {
1614
- const result = PlurnkParser.parse(assistant.content);
1437
+ // {§fence-heading-in-body} {§interstitial-fence} — the executors this workspace can run
1438
+ // are heading tags to the parser; anything else tagged is a code block.
1439
+ const result = PlurnkParser.parse(assistant.content, { executors });
1615
1440
  span.setAttribute("statements", result.items.filter((item) => item.kind === "statement").length);
1616
1441
  return result;
1617
1442
  });
@@ -1637,7 +1462,7 @@ export default class TurnRunner {
1637
1462
  });
1638
1463
  }
1639
1464
  else {
1640
- parseErrors.push({ message: err.message, line: err.line, column: err.column, source: err.source });
1465
+ parseErrors.push({ message: err.message, line: err.line, column: err.column, source: err.source, ...(err.code === undefined ? {} : { code: err.code }) });
1641
1466
  }
1642
1467
  }
1643
1468
  else {
@@ -1655,25 +1480,23 @@ export default class TurnRunner {
1655
1480
  }
1656
1481
  }
1657
1482
  const sourceStatementCount = ops.filter(({ position }) => position.line > 0).length;
1658
- const plan = ops[0]?.op === "PLAN" ? ops[0] : undefined;
1659
- const finalOp = ops.at(-1);
1660
- const terminalSend = finalOp?.op === "SEND"
1661
- && finalOp.status !== null
1662
- && TERMINAL_SEND_SIGNALS.has(finalOp.status)
1663
- ? finalOp
1664
- : undefined;
1665
- const recoveredSend = terminalSend?.position.line === 0;
1666
- // {§turn-shape} — PLAN is a SHOULD: a turn without one is complete once it ends in a
1667
- // terminal SEND, and the recoverable window then starts at the turn's first statement.
1668
- const recoverableParseErrors = terminalSend !== undefined && !hasUnparsedTail
1669
- ? parseErrors.filter((error) => (error.message === PlurnkParser.MISSING_SEND
1670
- || ((plan === undefined || comparePosition(error, plan.position) > 0)
1671
- && (recoveredSend || comparePosition(error, terminalSend.position) < 0)))).toSorted(comparePosition)
1483
+ const dispositions = ops.filter(TurnDisposition.is);
1484
+ const trustworthyBoundary = dispositions.length <= 1 && !hasUnparsedTail;
1485
+ // {§turn-shape} — bounded operation errors are recoverable and ride with the
1486
+ // admitted program; document-boundary failures still reject it.
1487
+ const recoverableParseErrors = trustworthyBoundary
1488
+ ? parseErrors.filter((error) => error.code !== "invalid-turn-structure").toSorted(comparePosition)
1672
1489
  : [];
1490
+ // {§empty-turn} — no operation and no other hard error: admitted as an empty turn, never
1491
+ // resampled; its advisories ({§bare-heading-advisory}) ride as notices.
1492
+ const emptyTurn = preParsedOps === undefined
1493
+ && trustworthyBoundary
1494
+ && sourceStatementCount === 0
1495
+ && parseErrors.every((error) => error.message === PlurnkParser.NO_VALID_OPERATION);
1673
1496
  const emissionValid = preParsedOps !== undefined
1674
- || (terminalSend !== undefined
1497
+ || emptyTurn
1498
+ || (trustworthyBoundary
1675
1499
  && sourceStatementCount > 0
1676
- && !hasUnparsedTail
1677
1500
  && recoverableParseErrors.length === parseErrors.length);
1678
1501
  const reasoning = assistant.reasoning ?? null;
1679
1502
  return {
@@ -1681,18 +1504,19 @@ export default class TurnRunner {
1681
1504
  sourceBacked: preParsedOps === undefined,
1682
1505
  callMetadata: { finishReason: assistant.finishReason, model: assistant.model },
1683
1506
  parseErrors,
1684
- recoverableParseErrors: emissionValid ? recoverableParseErrors : [],
1507
+ recoverableParseErrors: emissionValid && !emptyTurn ? recoverableParseErrors : [],
1508
+ emptyTurn,
1685
1509
  parseNotices,
1686
1510
  // The ANTLR model-turn parser is authoritative. At least one source
1687
- // operation lets an omitted terminal SEND default around it; the
1688
- // exact defaults and bounded statement failures become durable
1689
- // operation results. Boundary loss and an unparsed tail still reject
1511
+ // operation is required; TASK omission continues silently. Bounded
1512
+ // statement failures become durable operation results.
1513
+ // Boundary loss and an unparsed tail still reject
1690
1514
  // wholesale. Pre-parsed ops are Mock's trusted test seam.
1691
1515
  emissionValid,
1692
1516
  };
1693
1517
  }
1694
1518
  // #note12 — plugin reference docs are materialized beneath
1695
- // worker://~/_plurnk/plurnk/ by LoopDocs.
1519
+ // worker:///_plurnk/plurnk/ by LoopDocs.
1696
1520
  // {§exec-poll} — EXEC `<0>` is turn-scoped: abort the worker's open turn-scoped streams via their
1697
1521
  // owning scheme (the same registry-routed abort the total reap uses). Called at each pre-turn
1698
1522
  // before the turn's own spawns, so every open turn-scoped sub here is from a prior turn — it