@plurnk/plurnk-service 1.14.2 → 1.16.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 (308) hide show
  1. package/.env.defaults +2 -2
  2. package/SPEC.md +243 -173
  3. package/digest-sql/curation/curation.sql +1 -1
  4. package/dist/build-info.json +1 -1
  5. package/dist/content/byte-view.d.ts +14 -0
  6. package/dist/content/byte-view.d.ts.map +1 -0
  7. package/dist/content/byte-view.js +33 -0
  8. package/dist/content/byte-view.js.map +1 -0
  9. package/dist/content/edit-receipt.d.ts.map +1 -1
  10. package/dist/content/edit-receipt.js +12 -1
  11. package/dist/content/edit-receipt.js.map +1 -1
  12. package/dist/content/line-marker.d.ts +2 -1
  13. package/dist/content/line-marker.d.ts.map +1 -1
  14. package/dist/content/line-marker.js +1 -0
  15. package/dist/content/line-marker.js.map +1 -1
  16. package/dist/content/matcher.d.ts +1 -0
  17. package/dist/content/matcher.d.ts.map +1 -1
  18. package/dist/content/matcher.js +1 -0
  19. package/dist/content/matcher.js.map +1 -1
  20. package/dist/content/read-projector.d.ts +4 -1
  21. package/dist/content/read-projector.d.ts.map +1 -1
  22. package/dist/content/read-projector.js +80 -3
  23. package/dist/content/read-projector.js.map +1 -1
  24. package/dist/core/AdmittedTurnExecutor.d.ts +43 -0
  25. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -0
  26. package/dist/core/AdmittedTurnExecutor.js +245 -0
  27. package/dist/core/AdmittedTurnExecutor.js.map +1 -0
  28. package/dist/core/BareBatchRunner.d.ts +26 -0
  29. package/dist/core/BareBatchRunner.d.ts.map +1 -0
  30. package/dist/core/BareBatchRunner.js +104 -0
  31. package/dist/core/BareBatchRunner.js.map +1 -0
  32. package/dist/core/BudgetReadout.d.ts +1 -1
  33. package/dist/core/BudgetReadout.d.ts.map +1 -1
  34. package/dist/core/BudgetReadout.js +42 -47
  35. package/dist/core/BudgetReadout.js.map +1 -1
  36. package/dist/core/CapabilityResolver.d.ts +2 -1
  37. package/dist/core/CapabilityResolver.d.ts.map +1 -1
  38. package/dist/core/CapabilityResolver.js +8 -9
  39. package/dist/core/CapabilityResolver.js.map +1 -1
  40. package/dist/core/ChannelWrite.d.ts +1 -1
  41. package/dist/core/ChannelWrite.d.ts.map +1 -1
  42. package/dist/core/DataStatementRunner.d.ts +35 -0
  43. package/dist/core/DataStatementRunner.d.ts.map +1 -0
  44. package/dist/core/DataStatementRunner.js +252 -0
  45. package/dist/core/DataStatementRunner.js.map +1 -0
  46. package/dist/core/Dispatcher.d.ts +8 -3
  47. package/dist/core/Dispatcher.d.ts.map +1 -1
  48. package/dist/core/Dispatcher.js +88 -738
  49. package/dist/core/Dispatcher.js.map +1 -1
  50. package/dist/core/EditMutations.d.ts +39 -0
  51. package/dist/core/EditMutations.d.ts.map +1 -0
  52. package/dist/core/EditMutations.js +418 -0
  53. package/dist/core/EditMutations.js.map +1 -0
  54. package/dist/core/Engine.d.ts +2 -23
  55. package/dist/core/Engine.d.ts.map +1 -1
  56. package/dist/core/Engine.js +18 -240
  57. package/dist/core/Engine.js.map +1 -1
  58. package/dist/core/Engine.sql +24 -23
  59. package/dist/core/KillHandler.d.ts +32 -0
  60. package/dist/core/KillHandler.d.ts.map +1 -0
  61. package/dist/core/KillHandler.js +179 -0
  62. package/dist/core/KillHandler.js.map +1 -0
  63. package/dist/core/LogVisibility.d.ts +1 -1
  64. package/dist/core/LogVisibility.d.ts.map +1 -1
  65. package/dist/core/LogVisibility.js +3 -4
  66. package/dist/core/LogVisibility.js.map +1 -1
  67. package/dist/core/LogWriter.d.ts +42 -0
  68. package/dist/core/LogWriter.d.ts.map +1 -0
  69. package/dist/core/LogWriter.js +136 -0
  70. package/dist/core/LogWriter.js.map +1 -0
  71. package/dist/core/LoopDriver.d.ts +46 -0
  72. package/dist/core/LoopDriver.d.ts.map +1 -0
  73. package/dist/core/LoopDriver.js +263 -0
  74. package/dist/core/LoopDriver.js.map +1 -0
  75. package/dist/core/LoopLifecycle.d.ts +2 -1
  76. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  77. package/dist/core/MembershipMaterialization.d.ts +7 -0
  78. package/dist/core/MembershipMaterialization.d.ts.map +1 -0
  79. package/dist/core/MembershipMaterialization.js +283 -0
  80. package/dist/core/MembershipMaterialization.js.map +1 -0
  81. package/dist/core/MutationEffects.d.ts +29 -0
  82. package/dist/core/MutationEffects.d.ts.map +1 -0
  83. package/dist/core/MutationEffects.js +318 -0
  84. package/dist/core/MutationEffects.js.map +1 -0
  85. package/dist/core/OverflowTurn.d.ts +4 -4
  86. package/dist/core/OverflowTurn.d.ts.map +1 -1
  87. package/dist/core/OverflowTurn.js +6 -7
  88. package/dist/core/OverflowTurn.js.map +1 -1
  89. package/dist/core/PacketBuilder.d.ts.map +1 -1
  90. package/dist/core/PacketBuilder.js +31 -9
  91. package/dist/core/PacketBuilder.js.map +1 -1
  92. package/dist/core/ResourceMutations.d.ts +12 -36
  93. package/dist/core/ResourceMutations.d.ts.map +1 -1
  94. package/dist/core/ResourceMutations.js +27 -1351
  95. package/dist/core/ResourceMutations.js.map +1 -1
  96. package/dist/core/ResourceSelector.d.ts +21 -0
  97. package/dist/core/ResourceSelector.d.ts.map +1 -0
  98. package/dist/core/ResourceSelector.js +233 -0
  99. package/dist/core/ResourceSelector.js.map +1 -0
  100. package/dist/core/ResourceTransfers.d.ts +55 -0
  101. package/dist/core/ResourceTransfers.d.ts.map +1 -0
  102. package/dist/core/ResourceTransfers.js +525 -0
  103. package/dist/core/ResourceTransfers.js.map +1 -0
  104. package/dist/core/SchemeRegistry.js +2 -2
  105. package/dist/core/SchemeRegistry.js.map +1 -1
  106. package/dist/core/SendBroadcastHandler.d.ts +40 -0
  107. package/dist/core/SendBroadcastHandler.d.ts.map +1 -0
  108. package/dist/core/SendBroadcastHandler.js +159 -0
  109. package/dist/core/SendBroadcastHandler.js.map +1 -0
  110. package/dist/core/StoredPacket.d.ts +11 -0
  111. package/dist/core/StoredPacket.d.ts.map +1 -1
  112. package/dist/core/StoredPacket.js +22 -1
  113. package/dist/core/StoredPacket.js.map +1 -1
  114. package/dist/core/StrikeRail.d.ts.map +1 -1
  115. package/dist/core/StrikeRail.js +19 -9
  116. package/dist/core/StrikeRail.js.map +1 -1
  117. package/dist/core/TokenCalibration.d.ts +16 -0
  118. package/dist/core/TokenCalibration.d.ts.map +1 -0
  119. package/dist/core/TokenCalibration.js +35 -0
  120. package/dist/core/TokenCalibration.js.map +1 -0
  121. package/dist/core/ToolResources.d.ts.map +1 -1
  122. package/dist/core/ToolResources.js +15 -12
  123. package/dist/core/ToolResources.js.map +1 -1
  124. package/dist/core/TurnMaterialization.d.ts +37 -0
  125. package/dist/core/TurnMaterialization.d.ts.map +1 -0
  126. package/dist/core/TurnMaterialization.js +296 -0
  127. package/dist/core/TurnMaterialization.js.map +1 -0
  128. package/dist/core/TurnOps.d.ts.map +1 -1
  129. package/dist/core/TurnOps.js +6 -8
  130. package/dist/core/TurnOps.js.map +1 -1
  131. package/dist/core/TurnRunner.d.ts +15 -27
  132. package/dist/core/TurnRunner.d.ts.map +1 -1
  133. package/dist/core/TurnRunner.js +76 -670
  134. package/dist/core/TurnRunner.js.map +1 -1
  135. package/dist/core/WorkerControlHandler.d.ts +15 -0
  136. package/dist/core/WorkerControlHandler.d.ts.map +1 -0
  137. package/dist/core/WorkerControlHandler.js +89 -0
  138. package/dist/core/WorkerControlHandler.js.map +1 -0
  139. package/dist/core/attachments.d.ts +14 -0
  140. package/dist/core/attachments.d.ts.map +1 -0
  141. package/dist/core/attachments.js +18 -0
  142. package/dist/core/attachments.js.map +1 -0
  143. package/dist/core/fork.d.ts.map +1 -1
  144. package/dist/core/fork.js +0 -4
  145. package/dist/core/fork.js.map +1 -1
  146. package/dist/core/fork.sql +5 -16
  147. package/dist/core/git-membership.d.ts +15 -0
  148. package/dist/core/git-membership.d.ts.map +1 -1
  149. package/dist/core/git-membership.js +4 -273
  150. package/dist/core/git-membership.js.map +1 -1
  151. package/dist/core/git-state.d.ts +2 -1
  152. package/dist/core/git-state.d.ts.map +1 -1
  153. package/dist/core/mutation-types.d.ts +102 -0
  154. package/dist/core/mutation-types.d.ts.map +1 -0
  155. package/dist/core/mutation-types.js +2 -0
  156. package/dist/core/mutation-types.js.map +1 -0
  157. package/dist/core/operation-target-groups.js +1 -1
  158. package/dist/core/operation-target-groups.js.map +1 -1
  159. package/dist/core/packet-wire.d.ts +7 -6
  160. package/dist/core/packet-wire.d.ts.map +1 -1
  161. package/dist/core/packet-wire.js +96 -68
  162. package/dist/core/packet-wire.js.map +1 -1
  163. package/dist/core/plurnk-uri.d.ts +0 -1
  164. package/dist/core/plurnk-uri.d.ts.map +1 -1
  165. package/dist/core/plurnk-uri.js +1 -1
  166. package/dist/core/plurnk-uri.js.map +1 -1
  167. package/dist/core/statement-primary.d.ts +4 -0
  168. package/dist/core/statement-primary.d.ts.map +1 -0
  169. package/dist/core/statement-primary.js +3 -0
  170. package/dist/core/statement-primary.js.map +1 -0
  171. package/dist/core/teaching-corpus.d.ts +0 -1
  172. package/dist/core/teaching-corpus.d.ts.map +1 -1
  173. package/dist/core/teaching-corpus.js +0 -9
  174. package/dist/core/teaching-corpus.js.map +1 -1
  175. package/dist/core/turn-scheduler.js +3 -3
  176. package/dist/core/turn-scheduler.js.map +1 -1
  177. package/dist/core/turn-signals.d.ts +15 -0
  178. package/dist/core/turn-signals.d.ts.map +1 -0
  179. package/dist/core/turn-signals.js +19 -0
  180. package/dist/core/turn-signals.js.map +1 -0
  181. package/dist/core/worker-settings.d.ts +0 -1
  182. package/dist/core/worker-settings.d.ts.map +1 -1
  183. package/dist/core/worker-settings.js +1 -1
  184. package/dist/core/worker-settings.js.map +1 -1
  185. package/dist/digest/Digest.d.ts +3 -16
  186. package/dist/digest/Digest.d.ts.map +1 -1
  187. package/dist/digest/Digest.js +10 -958
  188. package/dist/digest/Digest.js.map +1 -1
  189. package/dist/digest/DigestRender.d.ts +12 -0
  190. package/dist/digest/DigestRender.d.ts.map +1 -0
  191. package/dist/digest/DigestRender.js +641 -0
  192. package/dist/digest/DigestRender.js.map +1 -0
  193. package/dist/digest/DigestRequiem.d.ts +13 -0
  194. package/dist/digest/DigestRequiem.d.ts.map +1 -0
  195. package/dist/digest/DigestRequiem.js +332 -0
  196. package/dist/digest/DigestRequiem.js.map +1 -0
  197. package/dist/digest/digest-rows.d.ts +303 -0
  198. package/dist/digest/digest-rows.d.ts.map +1 -0
  199. package/dist/digest/digest-rows.js +2 -0
  200. package/dist/digest/digest-rows.js.map +1 -0
  201. package/dist/digest/digest.sql +1 -7
  202. package/dist/observe/api.d.ts +0 -2
  203. package/dist/observe/api.d.ts.map +1 -1
  204. package/dist/observe/api.js +2 -2
  205. package/dist/observe/api.js.map +1 -1
  206. package/dist/observe/metrics.d.ts +0 -1
  207. package/dist/observe/metrics.d.ts.map +1 -1
  208. package/dist/observe/metrics.js +0 -1
  209. package/dist/observe/metrics.js.map +1 -1
  210. package/dist/schemes/Exec.d.ts +4 -1
  211. package/dist/schemes/Exec.d.ts.map +1 -1
  212. package/dist/schemes/Exec.js +89 -48
  213. package/dist/schemes/Exec.js.map +1 -1
  214. package/dist/schemes/ExecOutputScheme.d.ts +2 -1
  215. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  216. package/dist/schemes/ExecOutputScheme.js +3 -3
  217. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  218. package/dist/schemes/File.d.ts +4 -1
  219. package/dist/schemes/File.d.ts.map +1 -1
  220. package/dist/schemes/File.js +100 -13
  221. package/dist/schemes/File.js.map +1 -1
  222. package/dist/schemes/Log.d.ts +4 -5
  223. package/dist/schemes/Log.d.ts.map +1 -1
  224. package/dist/schemes/Log.js +26 -118
  225. package/dist/schemes/Log.js.map +1 -1
  226. package/dist/schemes/Log.sql +1 -66
  227. package/dist/schemes/Prompt.js +1 -1
  228. package/dist/schemes/Prompt.js.map +1 -1
  229. package/dist/schemes/Worker.d.ts.map +1 -1
  230. package/dist/schemes/Worker.js +1 -13
  231. package/dist/schemes/Worker.js.map +1 -1
  232. package/dist/schemes/_entry-crud.d.ts +3 -1
  233. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  234. package/dist/schemes/_entry-crud.js +18 -3
  235. package/dist/schemes/_entry-crud.js.map +1 -1
  236. package/dist/schemes/_entry-find.d.ts +4 -2
  237. package/dist/schemes/_entry-find.d.ts.map +1 -1
  238. package/dist/schemes/_entry-find.js +79 -10
  239. package/dist/schemes/_entry-find.js.map +1 -1
  240. package/dist/schemes/_entry-manifest.d.ts +1 -2
  241. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  242. package/dist/schemes/_entry-ops.d.ts +2 -1
  243. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  244. package/dist/schemes/_entry-ops.js +20 -2
  245. package/dist/schemes/_entry-ops.js.map +1 -1
  246. package/dist/schemes/_entry-semantic.d.ts +1 -0
  247. package/dist/schemes/_entry-semantic.d.ts.map +1 -1
  248. package/dist/schemes/_entry-semantic.js +3 -0
  249. package/dist/schemes/_entry-semantic.js.map +1 -1
  250. package/dist/schemes/_entry-semantic.sql +2 -2
  251. package/dist/schemes/_entry-send.d.ts +0 -1
  252. package/dist/schemes/_entry-send.d.ts.map +1 -1
  253. package/dist/schemes/_entry-send.js +5 -80
  254. package/dist/schemes/_entry-send.js.map +1 -1
  255. package/dist/schemes/exec-runtime.d.ts +7 -0
  256. package/dist/schemes/exec-runtime.d.ts.map +1 -0
  257. package/dist/schemes/exec-runtime.js +2 -0
  258. package/dist/schemes/exec-runtime.js.map +1 -0
  259. package/dist/server/ClientReads.d.ts +34 -0
  260. package/dist/server/ClientReads.d.ts.map +1 -0
  261. package/dist/server/ClientReads.js +210 -0
  262. package/dist/server/ClientReads.js.map +1 -0
  263. package/dist/server/Daemon.d.ts +12 -22
  264. package/dist/server/Daemon.d.ts.map +1 -1
  265. package/dist/server/Daemon.js +31 -362
  266. package/dist/server/Daemon.js.map +1 -1
  267. package/dist/server/DaemonModule.d.ts +6 -5
  268. package/dist/server/DaemonModule.d.ts.map +1 -1
  269. package/dist/server/DrainSupervisor.d.ts +3 -2
  270. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  271. package/dist/server/DrainSupervisor.js +7 -3
  272. package/dist/server/DrainSupervisor.js.map +1 -1
  273. package/dist/server/Functionality.d.ts +0 -12
  274. package/dist/server/Functionality.d.ts.map +1 -1
  275. package/dist/server/Functionality.js.map +1 -1
  276. package/dist/server/FunctionalityManager.d.ts +0 -1
  277. package/dist/server/FunctionalityManager.d.ts.map +1 -1
  278. package/dist/server/FunctionalityManager.js +3 -3
  279. package/dist/server/FunctionalityManager.js.map +1 -1
  280. package/dist/server/MembersFunctionality.d.ts +2 -13
  281. package/dist/server/MembersFunctionality.d.ts.map +1 -1
  282. package/dist/server/MembersFunctionality.js +4 -4
  283. package/dist/server/MembersFunctionality.js.map +1 -1
  284. package/dist/server/SkillsFunctionality.d.ts +1 -7
  285. package/dist/server/SkillsFunctionality.d.ts.map +1 -1
  286. package/dist/server/SkillsFunctionality.js +3 -3
  287. package/dist/server/SkillsFunctionality.js.map +1 -1
  288. package/dist/server/WorkerModelResolver.d.ts +17 -0
  289. package/dist/server/WorkerModelResolver.d.ts.map +1 -0
  290. package/dist/server/WorkerModelResolver.js +166 -0
  291. package/dist/server/WorkerModelResolver.js.map +1 -0
  292. package/dist/server/daemon-results.d.ts +5 -0
  293. package/dist/server/daemon-results.d.ts.map +1 -0
  294. package/dist/server/daemon-results.js +7 -0
  295. package/dist/server/daemon-results.js.map +1 -0
  296. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  297. package/dist/server/dispatch-as-plurnk.js +4 -6
  298. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  299. package/dist/server/logEntry.d.ts +0 -1
  300. package/dist/server/logEntry.d.ts.map +1 -1
  301. package/dist/server/logEntry.js +1 -13
  302. package/dist/server/logEntry.js.map +1 -1
  303. package/dist/server/logEntry.sql +1 -5
  304. package/dist/server/loopDocs.d.ts.map +1 -1
  305. package/dist/server/loopDocs.js +11 -2
  306. package/dist/server/loopDocs.js.map +1 -1
  307. package/migrations/001_schema.sql +30 -347
  308. package/package.json +30 -30
@@ -1,17 +1,14 @@
1
- var _a;
2
1
  import { PathSyntax, PlurnkParser, PlurnkParseError, UNKNOWN_POSITION } from "@plurnk/plurnk-contracts";
3
2
  import { setTimeout as delay } from "node:timers/promises";
4
3
  import { aggregateProviderAccounting } from "@plurnk/plurnk-providers";
5
- const TERMINAL_SEND_SIGNALS = new Set([102, 200, 202, 499]);
6
4
  const comparePosition = (a, b) => a.line - b.line || a.column - b.column;
7
5
  import Meta from "@plurnk/plurnk-meta";
8
6
  import EntryCrud from "../schemes/_entry-crud.js";
9
7
  import GitMembership from "./git-membership.js";
8
+ import { acceptedKinds } from "./attachments.js";
10
9
  import GitState from "./git-state.js";
11
10
  import WorkspaceSettings from "./workspace-settings.js";
12
- import { editedSpan } from "../content/index.js";
13
- import ReadResolve from "../content/read-resolve.js";
14
- import { authorityParts, generatedPathname, promptPathname, promptLoopPrefix } from "./plurnk-uri.js";
11
+ import { generatedPathname, promptPathname, promptLoopPrefix } from "./plurnk-uri.js";
15
12
  import { readFile } from "node:fs/promises";
16
13
  // {§grammar-rail-registration} — bare names are the built-in rail namespace;
17
14
  // everything else is an import specifier resolved through the Node chain.
@@ -22,44 +19,22 @@ export const resolveGrammarRailPath = (variant) => variant.startsWith("/") || va
22
19
  : fileURLToPath(import.meta.resolve(variant)))
23
20
  : fileURLToPath(import.meta.resolve(`@plurnk/plurnk-contracts/${variant}`));
24
21
  import { fileURLToPath } from "node:url";
25
- import { randomUUID } from "node:crypto";
26
22
  // Shared module imported by both Engine and bin/digest.ts, so wire
27
23
  // projection and digest projection are structurally one function — no
28
24
  // drift between wire and digest possible.
29
25
  import PacketWire from "./packet-wire.js";
30
26
  import Results, { OperationFailureError } from "./results.js";
31
- import TerminalResult from "./TerminalResult.js";
32
- import LoopLifecycle from "./LoopLifecycle.js";
33
- import WorkerControlAddress from "./WorkerControlAddress.js";
34
27
  import Turn from "./Turn.js";
35
- import LogBody from "./LogBody.js";
36
- import LogVisibility from "./LogVisibility.js";
37
- import StrikeRail from "./StrikeRail.js";
38
28
  import StoredPacket from "./StoredPacket.js";
39
29
  import { observed, observedSync } from "../observe/spans.js";
40
- import { GEN_AI_REQUEST_SPAN, genAiRequestOptions, settleGenAiResponse, } from "../observe/genai.js";
41
- import { OPS_DISPATCHED, PROVIDER_CALLS, recordCounter } from "../observe/metrics.js";
42
- import { scheduleTurnOps } from "./turn-scheduler.js";
43
- import { expandSafeUriTargetGroup } from "./operation-target-groups.js";
44
- import { readOptimisticSettlementMs } from "./optimistic-settlement.js";
45
- import ModelCall, { ModelCallPersistenceError, ProviderAccountingIntegrityError, } from "./ModelCall.js";
30
+ import { GEN_AI_REQUEST_SPAN, genAiRequestOptions, settleGenAiResponse } from "../observe/genai.js";
31
+ import { PROVIDER_CALLS, recordCounter } from "../observe/metrics.js";
32
+ import ModelCall, { ModelCallPersistenceError, ProviderAccountingIntegrityError } from "./ModelCall.js";
46
33
  import OverflowTurn from "./OverflowTurn.js";
47
34
  import TurnOps from "./TurnOps.js";
48
35
  import CapabilityPolicies from "./CapabilityPolicies.js";
49
36
  import CapabilityResolver from "./CapabilityResolver.js";
50
37
  import LoopPolicyReader from "./LoopPolicyReader.js";
51
- const ENGINE_PROBLEMS = Object.freeze({
52
- max_commands_exceeded: {
53
- status: 429,
54
- code: "max-commands-exceeded",
55
- detail: "Later operations were not executed because the turn exceeded its operation limit.",
56
- },
57
- idle_turn: {
58
- status: 409,
59
- code: "idle-turn",
60
- detail: "`## SEND0 [102]` was emitted without an operation to continue from.",
61
- },
62
- });
63
38
  // The prompt entry target - prompt:///<loop>/<N>, self-only ({§prompt-self-only}):
64
39
  // the owner rides the owner_id column, the address carries only the loop coordinate.
65
40
  const promptTarget = (loopSeq, promptOrdinal) => {
@@ -139,9 +114,13 @@ const readFilesItems = () => {
139
114
  return null;
140
115
  return normalizeFilesItems(Number.parseInt(raw, 10));
141
116
  };
142
- import { ProviderError, scopeEnvToAlias, } from "@plurnk/plurnk-providers";
117
+ import { ProviderError, scopeEnvToAlias } from "@plurnk/plurnk-providers";
143
118
  import { validateGbnf } from "@plurnk/gbnf";
144
119
  import ProviderInstantiate from "./ProviderInstantiate.js";
120
+ import TurnMaterialization from "./TurnMaterialization.js";
121
+ import BareBatchRunner from "./BareBatchRunner.js";
122
+ import { TERMINAL_SEND_SIGNALS, TURN_STATUS_IMPLICIT_CONTINUE } from "./turn-signals.js";
123
+ import AdmittedTurnExecutor from "./AdmittedTurnExecutor.js";
145
124
  // A generated rail may constrain only the sampled continuation while the chat
146
125
  // template contributes a prefix that llama-server preserves in its response.
147
126
  // The artifact names the alternate root that composes those bytes for evidence
@@ -170,10 +149,6 @@ const curationOverflowFailure = (pressure) => Results.failure("engine:context",
170
149
  ceiling: pressure.budget,
171
150
  deficit: pressure.excess,
172
151
  });
173
- // Runtime normalization for a disposition the engine refuses or resolves as a
174
- // continue after dispatch ({§send}). Every admitted emission itself ends in an
175
- // explicit disposition SEND ({§emission-admission}).
176
- const TURN_STATUS_IMPLICIT_CONTINUE = 102;
177
152
  const INVALID_EMISSION_RECOVERY_MESSAGE = "Response rejected before dispatch; no operations were performed.";
178
153
  // {§output-allowance-notice} — THE single derivation of a ceiling cut: a
179
154
  // `length` finish is the engine's own allowance ending the emission, and it
@@ -205,7 +180,7 @@ const readProviderRecoveryBackoff = () => readMilliseconds("PLURNK_SERVICE_PROVI
205
180
  const RECOVERABLE_PROVIDER_FAILURES = new Set(["rate_limit", "network_failure", "deadline_exceeded", "resource_interrupted"]);
206
181
  // The wall's abort reason — runLoop branches a mid-turn teardown to the 504 terminal on it.
207
182
  export const LOOP_TIMEOUT_REASON = "loop_timeout";
208
- class TurnRunner {
183
+ export default class TurnRunner {
209
184
  #db;
210
185
  #schemes;
211
186
  #mimetypes;
@@ -228,6 +203,9 @@ class TurnRunner {
228
203
  #dispatch;
229
204
  #resolveWorkerProviderIdentity;
230
205
  #gbnfCache = new Map();
206
+ #materialization;
207
+ #bareBatch;
208
+ #admitted;
231
209
  constructor({ db, schemes, mimetypes, weigh, notices, problems, strikes, packets, dispatcher, liveSubscriptions, streamEventNotify, reasoningEventNotify, loopPacketNotify, wakeWorkerNotify, executors, loopSignal, interactions, warmWorkspace, dispatch, resolveWorkerProviderIdentity, }) {
232
210
  this.#db = db;
233
211
  this.#schemes = schemes;
@@ -250,6 +228,9 @@ class TurnRunner {
250
228
  this.#warmWorkspace = warmWorkspace;
251
229
  this.#dispatch = dispatch;
252
230
  this.#resolveWorkerProviderIdentity = resolveWorkerProviderIdentity;
231
+ this.#materialization = new TurnMaterialization({ db: this.#db, schemes: this.#schemes, weighContent: this.#weighContent });
232
+ this.#bareBatch = new BareBatchRunner({ db: this.#db, providerAttributions: this.#providerAttributions.bind(this), providerFailure: TurnRunner.#providerFailure });
233
+ this.#admitted = new AdmittedTurnExecutor({ db: this.#db, schemes: this.#schemes, notices: this.#notices, problems: this.#problems, dispatcher: this.#dispatcher, bareBatch: this.#bareBatch });
253
234
  }
254
235
  async #recordInference(args) {
255
236
  await Turn.recordInference(this.#db, args.turnId, args.evidence);
@@ -268,9 +249,9 @@ class TurnRunner {
268
249
  // parse): warn once per message, never per turn; the turn records railsVerdict "unverifiable".
269
250
  static #railGapWarned = new Set();
270
251
  static #warnRailVerdictGapOnce(message) {
271
- if (_a.#railGapWarned.has(message))
252
+ if (TurnRunner.#railGapWarned.has(message))
272
253
  return;
273
- _a.#railGapWarned.add(message);
254
+ TurnRunner.#railGapWarned.add(message);
274
255
  process.stderr.write(`plurnk-engine: rail verdict unavailable — the configured grammar did not parse in @plurnk/gbnf (${message})\n`);
275
256
  }
276
257
  static #requireGrammarEvidence(response, allowWithheld) {
@@ -345,93 +326,6 @@ class TurnRunner {
345
326
  console.error("Provider failed outside its Problem Details contract:", error);
346
327
  return Results.failure("engine:provider", "provider-contract-violation", 502, "The provider failed without returning its required Problem Details.", {}, { stage: "provider-request", retryable: false });
347
328
  }
348
- async #runBareBatch({ statements, provider, turnId, workspaceId, workerId, primaryWorkerId, loopSequence, turnSequence, signal, }) {
349
- const prepared = [];
350
- for (const statement of statements) {
351
- const providerWorkerId = randomUUID();
352
- const attributionContext = Object.freeze({
353
- workspaceId: String(workspaceId),
354
- workerId: providerWorkerId,
355
- primaryWorkerId,
356
- loop: loopSequence,
357
- turn: turnSequence,
358
- attempt: 1,
359
- });
360
- const attributions = this.#providerAttributions(provider, attributionContext);
361
- const modelCall = await ModelCall.open(this.#db, {
362
- turnId,
363
- kind: "bare",
364
- attributions,
365
- model: provider.model,
366
- });
367
- prepared.push({ statement, modelCall, attributions, providerWorkerId });
368
- }
369
- const settlements = await Promise.allSettled(prepared.map(async ({ statement, modelCall, attributions, providerWorkerId }) => {
370
- try {
371
- const response = await observed(GEN_AI_REQUEST_SPAN, { model: provider.model, attempt: 1, kind: "bare" }, async (span) => {
372
- try {
373
- const generated = await provider.generate({
374
- messages: [{ role: "user", content: statement.body }],
375
- workerId: providerWorkerId,
376
- primaryWorkerId,
377
- signal,
378
- attributions: attributions.length > 0 ? attributions : undefined,
379
- workspaceId: String(workspaceId),
380
- loop: loopSequence,
381
- turn: turnSequence,
382
- observeRequest: modelCall.observeRequest,
383
- callKind: "bare",
384
- });
385
- modelCall.assertAccounting(generated.accounting);
386
- recordCounter(PROVIDER_CALLS, {
387
- model: provider.model,
388
- attempt: 1,
389
- status: "resolved",
390
- });
391
- span.setAttribute("status", "resolved");
392
- settleGenAiResponse(span, generated);
393
- return generated;
394
- }
395
- catch (error) {
396
- if (error instanceof ProviderError) {
397
- modelCall.assertAccounting(error.accounting);
398
- }
399
- throw error;
400
- }
401
- }, genAiRequestOptions(ProviderInstantiate.aliasOf(provider) ?? "plurnk", provider.model));
402
- await modelCall.observeResponse(response);
403
- return {
404
- statement,
405
- modelCallId: modelCall.id,
406
- result: Results.assert({
407
- status: 200,
408
- content: response.assistant.content,
409
- mimetype: "text/plain",
410
- }),
411
- };
412
- }
413
- catch (error) {
414
- if (error instanceof ModelCallPersistenceError || error instanceof ProviderAccountingIntegrityError) {
415
- throw error;
416
- }
417
- const failure = _a.#providerFailure(error, signal);
418
- if (error instanceof ProviderError && error.attempt !== undefined) {
419
- await modelCall.observeResponse(error.attempt, failure);
420
- }
421
- else {
422
- await modelCall.fail(failure);
423
- }
424
- return { statement, modelCallId: modelCall.id, result: failure };
425
- }
426
- }));
427
- const internalFailure = settlements.find((settlement) => settlement.status === "rejected");
428
- if (internalFailure !== undefined)
429
- throw internalFailure.reason;
430
- signal?.throwIfAborted();
431
- return settlements.map((settlement) => settlement.value);
432
- }
433
- // {§attribution} — reporting derives from exact provider-request evidence;
434
- // malformed durable tags fail here instead of being silently filtered.
435
329
  #offsetToLineColumn(content, offset) {
436
330
  const cps = Array.from(content);
437
331
  const clamped = Math.max(0, Math.min(offset, cps.length));
@@ -448,226 +342,22 @@ class TurnRunner {
448
342
  }
449
343
  return { line, column };
450
344
  }
451
- // {§turn-ops-admission-path} — source acquisition ends before this seam.
452
- // Every admitted producer program is scheduled, dispatched, recorded, and
453
- // completed here; inference is only the model-specific way one program is
454
- // acquired and supplied with BARE capability.
455
- async executeAdmittedTurn({ statements, source, sourceFolded, sourceModelCallId = null, sourceReasoningItems, origin, workspaceId, workerId, loopId, turnId, fromSequence, maxCommands = Number.POSITIVE_INFINITY, enforceIdle = false, failOnOperationError = false, recoverableParseErrors = [], bare, signal, onDispatch, onSettled, }) {
456
- const plan = statements[0];
457
- const finalOp = statements.at(-1);
458
- if (finalOp?.op !== "SEND") {
459
- throw new Error("an admitted operation batch must end in a disposition SEND");
460
- }
461
- if (source !== null && plan?.op !== "PLAN") {
462
- throw new Error("an admitted source-backed turnOps program must begin with PLAN");
463
- }
464
- const dispositionSignal = finalOp.signal;
465
- if (typeof dispositionSignal !== "number" || !TERMINAL_SEND_SIGNALS.has(dispositionSignal)) {
466
- throw new Error("an admitted turnOps program must end in a terminal disposition SEND");
467
- }
468
- let sendOp = finalOp;
469
- let turnStatus = dispositionSignal;
470
- let steerStruck = false;
471
- const pendingEngineErrors = [];
472
- const middleCount = statements.filter((statement) => statement.op !== "PLAN" && statement.op !== "SEND").length
473
- + recoverableParseErrors.length;
474
- if (enforceIdle && turnStatus === TURN_STATUS_IMPLICIT_CONTINUE && middleCount === 0) {
475
- // {§send-idle-turn} — an empty [102] while the worker holds a live stream or child is a
476
- // mis-spelled wait, not idleness: it parks as [202] and no strike (#441). The correction
477
- // rides the SEND row's annotation — a park drops transient notices, the row survives the
478
- // wake. With nothing in flight the idle-turn 409 stands.
479
- if (await this.#dispatcher.hasLiveWork(workerId)) {
480
- const note = "empty [102] while a stream or child is in flight waits like [202] - say [202] to wait on it";
481
- sendOp = { ...finalOp, signal: 202, annotation: finalOp.annotation === null ? note : `${finalOp.annotation} · ${note}` };
482
- turnStatus = 202;
483
- }
484
- else {
485
- steerStruck = true;
486
- pendingEngineErrors.push("idle_turn");
487
- }
488
- }
489
- const turnStatements = sendOp === finalOp ? statements : statements.map((statement) => statement === finalOp ? sendOp : statement);
490
- let realCommands = 0;
491
- const admitted = turnStatements.filter((statement) => statement.op === "PLAN"
492
- || statement === sendOp
493
- || realCommands++ < maxCommands);
494
- const scheduled = scheduleTurnOps(admitted.flatMap(expandSafeUriTargetGroup));
495
- await this.#dispatcher.prepareEditBatches(scheduled.filter((statement) => statement.op === "EDIT"), { workspaceId, workerId, loopId, turnId, origin, onDispatch, onSettled });
496
- const droppedCount = statements.length - admitted.length;
497
- const bareStatements = scheduled.filter((statement) => statement.op === "BARE");
498
- let bareResults = null;
499
- const outcomes = [];
500
- let rowSequence = fromSequence;
501
- let parseErrorsRecorded = false;
502
- const recordRecoverableParseErrors = async () => {
503
- if (parseErrorsRecorded)
504
- return;
505
- parseErrorsRecorded = true;
506
- for (const error of recoverableParseErrors) {
507
- const envelopeDefault = error.message === PlurnkParser.MISSING_PLAN
508
- || error.message === PlurnkParser.MISSING_SEND;
509
- const recorded = await this.#problems.record({
510
- workerId,
511
- loopId,
512
- turnId,
513
- sequence: rowSequence++,
514
- origin,
515
- source: "grammar",
516
- result: Results.failure("grammar:parser", "invalid-operation-syntax", 400, error.message, {}, {
517
- line: error.line,
518
- column: error.column,
519
- source: error.source,
520
- stage: "parse",
521
- ...(envelopeDefault ? {} : { siblingsRetained: true }),
522
- retryable: false,
523
- }),
524
- });
525
- outcomes.push({ op: null, status: recorded.result.status, problemType: recorded.result.problem?.type ?? null });
526
- onDispatch?.(recorded.id);
527
- await onSettled?.(recorded.id);
528
- }
529
- };
530
- for (const statement of scheduled) {
531
- if (statement === sendOp) {
532
- await recordRecoverableParseErrors();
533
- const execHandler = this.#schemes.get("exec");
534
- await execHandler?.settleTurnSpawns?.(workerId, turnId, readOptimisticSettlementMs(), signal);
535
- }
536
- const result = await observed("op.dispatch", { op: statement.op }, async (span) => {
537
- let dispatchResult;
538
- if (statement.op === "BARE") {
539
- if (bare === undefined) {
540
- throw new Error(`${origin} turnOps cannot execute BARE without provider acquisition context`);
541
- }
542
- if (bareResults === null) {
543
- const batch = await this.#runBareBatch({
544
- statements: bareStatements,
545
- provider: bare.provider,
546
- turnId,
547
- workspaceId,
548
- workerId,
549
- primaryWorkerId: bare.primaryWorkerId,
550
- loopSequence: bare.loopSequence,
551
- turnSequence: bare.turnSequence,
552
- signal: bare.signal,
553
- });
554
- bareResults = new Map(batch.map((item) => [item.statement, item]));
555
- }
556
- const bareResult = bareResults.get(statement);
557
- if (bareResult === undefined) {
558
- throw new Error("BARE statement reached dispatch without its batch result");
559
- }
560
- dispatchResult = await this.#dispatcher.recordBareResult({
561
- statement,
562
- workspaceId,
563
- workerId,
564
- loopId,
565
- turnId,
566
- sequence: rowSequence,
567
- origin,
568
- onDispatch,
569
- onSettled,
570
- }, bareResult.result, bareResult.modelCallId);
571
- }
572
- else {
573
- dispatchResult = await this.#dispatcher.dispatch({
574
- statement,
575
- workspaceId,
576
- workerId,
577
- loopId,
578
- turnId,
579
- sequence: rowSequence,
580
- origin,
581
- onDispatch,
582
- onSettled,
583
- });
584
- }
585
- span.setAttribute("status", dispatchResult.status);
586
- recordCounter(OPS_DISPATCHED, { op: statement.op, status: dispatchResult.status });
587
- return dispatchResult;
588
- });
589
- outcomes.push({ op: statement.op, status: result.status, problemType: result.problem?.type ?? null });
590
- if (failOnOperationError && result.status >= 400)
591
- throw new OperationFailureError(result);
592
- for (const normalization of result.scopeNormalizations ?? []) {
593
- this.#notices.push(workspaceId, workerId, loopId, {
594
- source: "engine:slicer",
595
- kind: "scope_normalized",
596
- level: "warn",
597
- message: `Scope <${normalization.requested.join(",")}> was normalized to <${normalization.canonical.join(",")}>.`,
598
- });
599
- }
600
- // {§edit-batch-merges} — every applied resolution is also a notice, so the row's
601
- // `merged` fact is never the only place it is said.
602
- for (const merge of result.merged ?? []) {
603
- this.#notices.push(workspaceId, workerId, loopId, {
604
- source: "engine:slicer",
605
- kind: "edit_merged",
606
- level: "warn",
607
- message: `EDIT resolution applied: ${merge.rule} - the row's merged fact has the coordinates; verify before building on it.`,
608
- });
609
- }
610
- if (statement === sendOp && result.status === 409) {
611
- steerStruck = true;
612
- turnStatus = TURN_STATUS_IMPLICIT_CONTINUE;
613
- }
614
- if (statement === sendOp
615
- && result.status !== 409
616
- && sendOp.target === null
617
- && sendOp.signal === 202
618
- && result.status !== 202) {
619
- turnStatus = result.status;
620
- }
621
- rowSequence += result.rowsWritten ?? 1;
622
- }
623
- await recordRecoverableParseErrors();
624
- if (droppedCount > 0)
625
- pendingEngineErrors.push("max_commands_exceeded");
626
- for (const kind of pendingEngineErrors) {
627
- const problem = ENGINE_PROBLEMS[kind];
628
- const extensions = kind === "max_commands_exceeded"
629
- ? {
630
- operationLimit: maxCommands,
631
- omittedOperations: droppedCount,
632
- stage: "dispatch-admission",
633
- recovery: "Continue with no more than the configured operation limit.",
634
- retryable: false,
635
- }
636
- : {
637
- stage: "turn",
638
- recovery: "Perform an operation before continuing with `## SEND0 [102]`.",
639
- retryable: false,
640
- };
641
- await this.#problems.record({
642
- workerId,
643
- loopId,
644
- turnId,
645
- sequence: rowSequence++,
646
- origin: "_plurnk",
647
- source: "rail",
648
- result: Results.failure("engine:rail", problem.code, problem.status, problem.detail, {}, extensions),
649
- });
650
- }
651
- if (source !== null) {
652
- await this.#dispatcher.writeTurnOps({
653
- verbatim: source,
654
- workerId,
655
- loopId,
656
- turnId,
657
- sequence: rowSequence,
658
- origin,
659
- folded: sourceFolded,
660
- modelCallId: sourceModelCallId,
661
- ...(sourceReasoningItems !== undefined ? { reasoningItems: sourceReasoningItems } : {}),
662
- });
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) {
349
+ const accepted = acceptedKinds(provider.inputModalities);
350
+ if (accepted.length === 0 || !(packet.attachments ?? []).some((attachment) => accepted.includes(attachment.kind))) {
351
+ return PacketWire.packetToWireMessages(packet);
663
352
  }
664
- await Turn.complete(this.#db, turnId, turnStatus);
665
- return {
666
- status: turnStatus,
667
- outcomes,
668
- fingerprint: StrikeRail.fingerprintTurn(statements),
669
- steerStruck,
670
- };
353
+ return PacketWire.wireMessages(packet, async (attachment) => {
354
+ const handler = this.#schemes.get(attachment.scheme);
355
+ const source = handler?.byteSource?.(attachment.pathname, { db: this.#db, workspaceId });
356
+ if (source === undefined)
357
+ return null;
358
+ const total = await source.size();
359
+ return total === null || total === 0 ? null : source.read(1, total);
360
+ }, (kind) => accepted.includes(kind));
671
361
  }
672
362
  async runTurn({ provider, childProvider = provider, messages, recap = "", workspaceId, workerId, loopId, signal, onDispatch, onSettled, turnNumber = 1, maxTurns = 50, invalidEmissionRecoveryEntryId, }) {
673
363
  const transientOpenLogEntryId = typeof invalidEmissionRecoveryEntryId === "number"
@@ -764,10 +454,10 @@ class TurnRunner {
764
454
  if (initializationTurn !== null) {
765
455
  const plan = {
766
456
  op: "PLAN", delimiter: "", annotation: null,
767
- signal: null, target: null, metadata: null, lineMarker: null,
457
+ target: null, metadata: null, lineMarker: null,
768
458
  body: [
769
459
  {
770
- content: "Persist Determinations and Decisions",
460
+ content: "Determinations and Decisions must be persisted as `memory` items.",
771
461
  status: "memory",
772
462
  },
773
463
  {
@@ -785,7 +475,7 @@ class TurnRunner {
785
475
  // ({§op-mode-phases}: Mutate precedes Observe).
786
476
  if (promptPublication !== null) {
787
477
  const archive = {
788
- op: "COPY", delimiter: "", annotation: null, signal: ["+_plurnk", "+backup"],
478
+ op: "COPY", delimiter: "", annotation: null,
789
479
  source: { target: promptPublication.path, metadata: null, lineMarker: null },
790
480
  destination: {
791
481
  target: { kind: "url", raw: "worker://~/prompts.md", scheme: "worker", username: null, password: null, hostname: "~", port: null, pathname: "/prompts.md", query: null, fragment: null },
@@ -815,7 +505,7 @@ class TurnRunner {
815
505
  pathname: generatedPathname("/agents.md"), query: null, fragment: null,
816
506
  };
817
507
  const agentsRead = {
818
- op: "READ", delimiter: "", annotation: null, signal: ["+_plurnk", "+init", "+policy"], target: agentsTarget,
508
+ op: "READ", delimiter: "", annotation: null, target: agentsTarget,
819
509
  metadata: null, lineMarker: null, body: null, position: UNKNOWN_POSITION,
820
510
  };
821
511
  initializationStatements.push(agentsRead);
@@ -846,7 +536,7 @@ class TurnRunner {
846
536
  // {§packet-git-status} — one post-reconciliation snapshot supplies both
847
537
  // the compact packet summary and each causal file event's exact XY state.
848
538
  const gitStatus = await GitState.status(this.#db, workspaceId, this.#loopSignal(loopId));
849
- await this.#logFsFictions(workspaceId, fsDivergences, gitStatus);
539
+ await this.#materialization.logFsFictions(workspaceId, fsDivergences, gitStatus);
850
540
  // The refresh above may have changed bodies (including model/client edits
851
541
  // since the startup warm). Re-derive to completion before packet/model
852
542
  // construction. Membership is already current, so this pass does not
@@ -867,7 +557,7 @@ class TurnRunner {
867
557
  const fileCap = filesItems > 0 && fileItems > 0 ? Math.min(filesItems, fileItems) : null;
868
558
  // {§tools-resource-materialization} — a PLURNK_MCP_EXPANDED server
869
559
  // contributes one FIND over its family document matching the
870
- // `## EXEC0` headings: one row per tool — heading, annotation,
560
+ // `### EXEC0` headings: one row per tool — heading, annotation,
871
561
  // signature — paged like every survey. No document is delivered
872
562
  // unasked; per-target child documents do not exist.
873
563
  const registry = this.#executors();
@@ -911,13 +601,13 @@ class TurnRunner {
911
601
  if (admittedTools.length === 0)
912
602
  continue;
913
603
  const pattern = tools !== null && tools !== undefined && admittedTools.length !== tools.tools.length
914
- ? `^## EXEC0 \\[${regexLiteral(tag)}\\] \\((?:${admittedTools
604
+ ? `^### EXEC0 \\[${regexLiteral(tag)}\\] \\((?:${admittedTools
915
605
  .map((tool) => regexLiteral(PathSyntax.escapeTarget(tool.target)))
916
606
  .join("|")})\\).*\\n.*$`
917
- : "^## EXEC0 .*\\n.*$";
607
+ : "^### EXEC0 .*\\n.*$";
918
608
  toolExpansions.push({
919
609
  statement: {
920
- op: "FIND", delimiter: "", annotation: null, signal: ["+_plurnk", "+init", "+tools"],
610
+ op: "FIND", delimiter: "", annotation: null,
921
611
  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 },
922
612
  metadata: null,
923
613
  body: { dialect: "regex", raw: `/${pattern.replaceAll("/", "\\/")}/m`, pattern, flags: "m" },
@@ -928,7 +618,7 @@ class TurnRunner {
928
618
  const surveys = [
929
619
  {
930
620
  statement: {
931
- op: "FIND", delimiter: "", annotation: null, signal: ["+_plurnk", "+init", "+skills"],
621
+ op: "FIND", delimiter: "", annotation: null,
932
622
  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 },
933
623
  metadata: null,
934
624
  body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
@@ -936,7 +626,7 @@ class TurnRunner {
936
626
  },
937
627
  ...(plurnkCatalog === null ? [] : [{
938
628
  statement: {
939
- op: "FIND", delimiter: "", annotation: null, signal: ["+_plurnk", "+init", "+plurnk"],
629
+ op: "FIND", delimiter: "", annotation: null,
940
630
  target: plurnkCatalog,
941
631
  metadata: null,
942
632
  body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
@@ -950,7 +640,7 @@ class TurnRunner {
950
640
  // PLURNK_MCP_EXPANDED add a second survey of their complete
951
641
  // tool tree.
952
642
  statement: {
953
- op: "FIND", delimiter: "", annotation: null, signal: ["+_plurnk", "+init", "+tools"],
643
+ op: "FIND", delimiter: "", annotation: null,
954
644
  target: toolsCatalog,
955
645
  metadata: null,
956
646
  body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
@@ -962,7 +652,7 @@ class TurnRunner {
962
652
  // alias level; each row's summary is the agent's identity line,
963
653
  // the exact card stays pullable through READ a2a://<alias>.
964
654
  statement: {
965
- op: "FIND", delimiter: "", annotation: null, signal: ["+_plurnk", "+init", "+agents"],
655
+ op: "FIND", delimiter: "", annotation: null,
966
656
  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 },
967
657
  metadata: null,
968
658
  body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
@@ -972,7 +662,7 @@ class TurnRunner {
972
662
  // {§members-projection} — enabled members definitions survey at alias
973
663
  // level; each row's summary is what its glob resolved to.
974
664
  statement: {
975
- op: "FIND", delimiter: "", annotation: null, signal: ["+_plurnk", "+init", "+members"],
665
+ op: "FIND", delimiter: "", annotation: null,
976
666
  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 },
977
667
  metadata: null,
978
668
  body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
@@ -980,7 +670,7 @@ class TurnRunner {
980
670
  },
981
671
  {
982
672
  statement: {
983
- op: "FIND", delimiter: "", annotation: "workspace files", signal: ["+_plurnk", "+init"],
673
+ op: "FIND", delimiter: "", annotation: "workspace files",
984
674
  target: { kind: "local", raw: "*" },
985
675
  metadata: null,
986
676
  body: null,
@@ -990,7 +680,7 @@ class TurnRunner {
990
680
  },
991
681
  {
992
682
  statement: {
993
- op: "FIND", delimiter: "", annotation: "workspace entries", signal: ["+_plurnk", "+init"],
683
+ op: "FIND", delimiter: "", annotation: "workspace entries",
994
684
  target: { kind: "url", raw: "worker:///*", scheme: "worker", username: null, password: null, hostname: null, port: null, pathname: "/*", query: null, fragment: null },
995
685
  metadata: null,
996
686
  body: null, lineMarker: null, position: UNKNOWN_POSITION,
@@ -998,7 +688,7 @@ class TurnRunner {
998
688
  },
999
689
  {
1000
690
  statement: {
1001
- op: "FIND", delimiter: "", annotation: "private worker entries", signal: ["+_plurnk", "+init"],
691
+ op: "FIND", delimiter: "", annotation: "private worker entries",
1002
692
  target: { kind: "url", raw: "worker://~/*", scheme: "worker", username: null, password: null, hostname: "~", port: null, pathname: "/*", query: null, fragment: null },
1003
693
  metadata: null,
1004
694
  body: null, lineMarker: null, position: UNKNOWN_POSITION,
@@ -1009,7 +699,7 @@ class TurnRunner {
1009
699
  }
1010
700
  const send = {
1011
701
  op: "SEND", delimiter: "", annotation: null,
1012
- signal: 102, target: null, metadata: null, lineMarker: null,
702
+ status: 102, target: null, metadata: null, lineMarker: null,
1013
703
  body: { raw: "Next: Address the prompt.", json: null },
1014
704
  position: UNKNOWN_POSITION,
1015
705
  };
@@ -1053,7 +743,7 @@ class TurnRunner {
1053
743
  const turnOpenPaths = [];
1054
744
  if (promptPublication !== null) { // {§prompt-entry} — one durable publication per loop
1055
745
  turnOpenPaths.push(...promptPublication.openPaths);
1056
- const promptLogId = await this.#writePromptLog({
746
+ const promptLogId = await this.#materialization.writePromptLog({
1057
747
  workerId,
1058
748
  loopId,
1059
749
  turnId,
@@ -1084,7 +774,7 @@ class TurnRunner {
1084
774
  turnOpenPaths.push(...assertOpenPaths(attributes.openPaths, `Prompt ${injectedRow.pathname} openPaths`));
1085
775
  }
1086
776
  const ordinal = Number(injectedRow.pathname.split("/").filter(Boolean).at(-1));
1087
- const promptLogId = await this.#writePromptLog({
777
+ const promptLogId = await this.#materialization.writePromptLog({
1088
778
  workerId,
1089
779
  loopId,
1090
780
  turnId,
@@ -1103,7 +793,7 @@ class TurnRunner {
1103
793
  for (const raw of turnOpenPaths) {
1104
794
  const pathname = raw.startsWith("/") ? raw : `/${raw}`;
1105
795
  const fileRead = {
1106
- op: "READ", delimiter: "", annotation: null, signal: null, lineMarker: null,
796
+ op: "READ", delimiter: "", annotation: null, lineMarker: null,
1107
797
  target: {
1108
798
  kind: "url", raw: `file://${pathname}`, scheme: "file",
1109
799
  username: null, password: null, hostname: null, port: null,
@@ -1125,8 +815,8 @@ class TurnRunner {
1125
815
  // from a prior turn — this runs before the turn's own spawns) so a `<0>` never survives into
1126
816
  // the subsequent turn. The terminal output then surfaces born-OPEN via the stream-delta path.
1127
817
  await this.#reapTurnScopedStreams(workerId);
1128
- nextActionIndex += await this.#materializeEnvironmentDeltas({ workspaceId, workerId, loopId, turnId, fromSequence: nextActionIndex });
1129
- nextActionIndex += await this.#materializeStreamDeltas({ workerId, loopId, turnId, fromSequence: nextActionIndex });
818
+ nextActionIndex += await this.#materialization.materializeEnvironmentDeltas({ workspaceId, workerId, loopId, turnId, fromSequence: nextActionIndex });
819
+ nextActionIndex += await this.#materialization.materializeStreamDeltas({ workerId, loopId, turnId, fromSequence: nextActionIndex });
1130
820
  // The post-reconciliation Git snapshot above is threaded into the packet
1131
821
  // and every budget rebuild; overflow never shells again.
1132
822
  // Notices are non-terminal observations, never operation-failure truth.
@@ -1205,7 +895,7 @@ class TurnRunner {
1205
895
  ...(curationFailure === undefined ? {} : { curationFailure }),
1206
896
  };
1207
897
  }
1208
- let modelMessages = PacketWire.packetToWireMessages(requestPacket);
898
+ let modelMessages = await this.#wireMessages(requestPacket, workspaceId, provider);
1209
899
  // Curation pressure and provider generation are independent. The
1210
900
  // provider owns its configured total output envelope.
1211
901
  let response;
@@ -1250,7 +940,7 @@ class TurnRunner {
1250
940
  if (promptProjection === "automatic") {
1251
941
  promptProjection = "withheld";
1252
942
  const candidate = await buildPacket();
1253
- const candidateMessages = PacketWire.packetToWireMessages(candidate);
943
+ const candidateMessages = await this.#wireMessages(candidate, workspaceId, provider);
1254
944
  if (JSON.stringify(candidateMessages) !== JSON.stringify(baselineMessages)) {
1255
945
  requestPacket = candidate;
1256
946
  modelMessages = candidateMessages;
@@ -1412,7 +1102,7 @@ class TurnRunner {
1412
1102
  throw error;
1413
1103
  }
1414
1104
  recoveryFailures += 1;
1415
- const failure = _a.#providerFailure(error, providerSignal);
1105
+ const failure = TurnRunner.#providerFailure(error, providerSignal);
1416
1106
  if (error.attempt !== undefined) {
1417
1107
  // {§provider-interrupted-attempt} — the interrupted response stays durable
1418
1108
  // as an unaccepted attempt; it is never admitted or replayed.
@@ -1452,7 +1142,7 @@ class TurnRunner {
1452
1142
  || !await recoverCapacityPacket()) {
1453
1143
  throw error;
1454
1144
  }
1455
- const failure = _a.#providerFailure(error, providerSignal);
1145
+ const failure = TurnRunner.#providerFailure(error, providerSignal);
1456
1146
  await currentModelCall.fail(failure, error.capacity ?? null);
1457
1147
  providerCallInFlight = false;
1458
1148
  await this.#problems.record({
@@ -1467,7 +1157,7 @@ class TurnRunner {
1467
1157
  // Include the durable recovery signal in the replacement
1468
1158
  // request while preserving the selected recovery posture.
1469
1159
  requestPacket = await buildPacket();
1470
- modelMessages = PacketWire.packetToWireMessages(requestPacket);
1160
+ modelMessages = await this.#wireMessages(requestPacket, workspaceId, provider);
1471
1161
  continue;
1472
1162
  }
1473
1163
  finally {
@@ -1488,7 +1178,7 @@ class TurnRunner {
1488
1178
  await currentModelCall.observeResponse(completedResponse);
1489
1179
  railEvidence = railGrammar === undefined
1490
1180
  ? undefined
1491
- : _a.#requireGrammarEvidence(completedResponse, railAllowWithheld);
1181
+ : TurnRunner.#requireGrammarEvidence(completedResponse, railAllowWithheld);
1492
1182
  splitResponse = this.#splitResponse(completedResponse);
1493
1183
  await classifyProviderAttempt(attemptRow.id, splitResponse, attempt, splitResponse.emissionValid);
1494
1184
  if (splitResponse.emissionValid)
@@ -1526,7 +1216,7 @@ class TurnRunner {
1526
1216
  if (providerAttemptId === null || providerModelCall === null) {
1527
1217
  throw new Error("provider call failed without durable model-call and attempt identities", { cause: err });
1528
1218
  }
1529
- const failure = _a.#providerFailure(err, providerSignal);
1219
+ const failure = TurnRunner.#providerFailure(err, providerSignal);
1530
1220
  const capacityFailure = err instanceof ProviderError && err.kind === "capacity_exceeded";
1531
1221
  // {§provider-interrupted-attempt} — a provider-declared interruption
1532
1222
  // carries response evidence without becoming a completed exchange.
@@ -1773,7 +1463,7 @@ class TurnRunner {
1773
1463
  verdict = validateGbnf(railResponseGrammar, railEvidence.input);
1774
1464
  }
1775
1465
  catch (cause) {
1776
- _a.#warnRailVerdictGapOnce(cause.message);
1466
+ TurnRunner.#warnRailVerdictGapOnce(cause.message);
1777
1467
  }
1778
1468
  railKeys = {
1779
1469
  railsAttached: railEvidence.transported ? "client" : "withheld",
@@ -1957,21 +1647,20 @@ class TurnRunner {
1957
1647
  const plan = ops[0]?.op === "PLAN" ? ops[0] : undefined;
1958
1648
  const finalOp = ops.at(-1);
1959
1649
  const terminalSend = finalOp?.op === "SEND"
1960
- && typeof finalOp.signal === "number"
1961
- && TERMINAL_SEND_SIGNALS.has(finalOp.signal)
1650
+ && finalOp.status !== null
1651
+ && TERMINAL_SEND_SIGNALS.has(finalOp.status)
1962
1652
  ? finalOp
1963
1653
  : undefined;
1964
- const recoveredPlan = plan?.position.line === 0;
1965
1654
  const recoveredSend = terminalSend?.position.line === 0;
1966
- const recoverableParseErrors = plan !== undefined && terminalSend !== undefined && !hasUnparsedTail
1967
- ? parseErrors.filter((error) => (error.message === PlurnkParser.MISSING_PLAN
1968
- || error.message === PlurnkParser.MISSING_SEND
1969
- || ((recoveredPlan || comparePosition(error, plan.position) > 0)
1655
+ // {§turn-shape} — PLAN is a SHOULD: a turn without one is complete once it ends in a
1656
+ // terminal SEND, and the recoverable window then starts at the turn's first statement.
1657
+ const recoverableParseErrors = terminalSend !== undefined && !hasUnparsedTail
1658
+ ? parseErrors.filter((error) => (error.message === PlurnkParser.MISSING_SEND
1659
+ || ((plan === undefined || comparePosition(error, plan.position) > 0)
1970
1660
  && (recoveredSend || comparePosition(error, terminalSend.position) < 0)))).toSorted(comparePosition)
1971
1661
  : [];
1972
1662
  const emissionValid = preParsedOps !== undefined
1973
- || (plan !== undefined
1974
- && terminalSend !== undefined
1663
+ || (terminalSend !== undefined
1975
1664
  && sourceStatementCount > 0
1976
1665
  && !hasUnparsedTail
1977
1666
  && recoverableParseErrors.length === parseErrors.length);
@@ -1984,7 +1673,7 @@ class TurnRunner {
1984
1673
  recoverableParseErrors: emissionValid ? recoverableParseErrors : [],
1985
1674
  parseNotices,
1986
1675
  // The ANTLR model-turn parser is authoritative. At least one source
1987
- // operation lets omitted PLAN/SEND ceremony default around it; the
1676
+ // operation lets an omitted terminal SEND default around it; the
1988
1677
  // exact defaults and bounded statement failures become durable
1989
1678
  // operation results. Boundary loss and an unparsed tail still reject
1990
1679
  // wholesale. Pre-parsed ops are Mock's trusted test seam.
@@ -1993,102 +1682,6 @@ class TurnRunner {
1993
1682
  }
1994
1683
  // #note12 — plugin reference docs are materialized beneath
1995
1684
  // worker://~/_plurnk/plurnk/ by LoopDocs.
1996
- async #materializeEnvironmentDeltas(args) {
1997
- const { workspaceId, workerId, loopId, turnId, fromSequence } = args;
1998
- const rows = await this.#db.engine_pull_ambient_events.all({ workspace_id: workspaceId, worker_id: workerId });
1999
- const window = rows[0];
2000
- if (window === undefined)
2001
- throw new Error(`ambient pull: worker ${workerId} has no observation window`);
2002
- let written = 0;
2003
- for (const r of rows) {
2004
- if (r.event_id === null || r.producer_worker_id === null || r.producer_worker_name === null || r.kind === null
2005
- || r.at === null || r.op === null || r.delimiter === null || r.tx === null || r.mimetype_tx === null
2006
- || r.rx === null || r.mimetype_rx === null || r.status_rx === null || r.state === null)
2007
- continue;
2008
- const termination = r.kind === "loop_termination";
2009
- const terminal = termination
2010
- ? TerminalResult.parse(r.rx, `ambient loop-termination event ${r.event_id}`)
2011
- : null;
2012
- if (terminal !== null && terminal.status !== r.status_rx) {
2013
- throw new Error(`ambient loop-termination event ${r.event_id} status ${r.status_rx} does not match its terminal result status ${terminal.status}`);
2014
- }
2015
- let attrs = r.attrs ?? "{}";
2016
- const parsedTags = JSON.parse(r.tags ?? "[]");
2017
- if (!Array.isArray(parsedTags) || !parsedTags.every((tag) => typeof tag === "string" && tag.length > 0)) {
2018
- throw new TypeError(`ambient event ${r.event_id} tags must be an array of nonempty strings`);
2019
- }
2020
- const tags = [...new Set(parsedTags)].toSorted();
2021
- if (tags.length !== parsedTags.length || tags.some((tag, index) => tag !== parsedTags[index])) {
2022
- throw new TypeError(`ambient event ${r.event_id} tags must be unique and sorted`);
2023
- }
2024
- if (terminal !== null) {
2025
- const inherited = JSON.parse(attrs);
2026
- if (inherited === null || typeof inherited !== "object" || Array.isArray(inherited)) {
2027
- throw new TypeError(`ambient loop-termination event ${r.event_id} attrs must be an object`);
2028
- }
2029
- attrs = JSON.stringify({
2030
- ...inherited,
2031
- kind: "loop_termination",
2032
- ...(r.terminated_by === null ? {} : { terminatedBy: r.terminated_by }),
2033
- });
2034
- }
2035
- const inserted = await this.#db.engine_insert_ambient_delta.get({
2036
- worker_id: workerId, loop_id: loopId, turn_id: turnId, sequence: fromSequence + written,
2037
- at: r.at,
2038
- event_id: r.event_id,
2039
- source: WorkerControlAddress.render(r.producer_worker_name),
2040
- op: r.op,
2041
- delimiter: r.delimiter,
2042
- signal: r.signal,
2043
- scheme: r.scheme,
2044
- username: r.username,
2045
- password: r.password,
2046
- hostname: r.hostname,
2047
- port: r.port,
2048
- pathname: r.pathname,
2049
- query: r.query,
2050
- fragment: r.fragment,
2051
- line_marker: r.line_marker,
2052
- tx: r.tx,
2053
- mimetype_tx: r.mimetype_tx,
2054
- rx: r.rx,
2055
- mimetype_rx: r.mimetype_rx,
2056
- status: r.status_rx,
2057
- weight: LogBody.weight({
2058
- op: r.op,
2059
- attrs,
2060
- tx: r.tx,
2061
- rx: r.rx,
2062
- mimetypeTx: r.mimetype_tx,
2063
- mimetypeRx: r.mimetype_rx,
2064
- }, this.#weighContent),
2065
- state: r.state,
2066
- outcome: r.outcome,
2067
- folded: LogVisibility.serialize(terminal !== null && terminal.status >= 200 && terminal.status < 300
2068
- ? LogVisibility.OPEN
2069
- : LogVisibility.FOLDED),
2070
- attrs,
2071
- });
2072
- const materialized = inserted ?? await this.#db.engine_ambient_delta_id.get({
2073
- worker_id: workerId,
2074
- event_id: r.event_id,
2075
- });
2076
- if (materialized === undefined)
2077
- throw new Error(`ambient event ${r.event_id} has no observer log row after materialization`);
2078
- for (const tag of tags) {
2079
- await this.#db.log_write_tag.run({ log_entry_id: materialized.id, tag });
2080
- }
2081
- if (inserted !== undefined)
2082
- written++;
2083
- }
2084
- await this.#db.engine_advance_ambient_cursor.get({
2085
- workspace_id: workspaceId,
2086
- worker_id: workerId,
2087
- cursor: window.cursor,
2088
- boundary: window.boundary,
2089
- });
2090
- return written;
2091
- }
2092
1685
  // {§exec-poll} — EXEC `<0>` is turn-scoped: abort the worker's open turn-scoped streams via their
2093
1686
  // owning scheme (the same registry-routed abort the total reap uses). Called at each pre-turn
2094
1687
  // before the turn's own spawns, so every open turn-scoped sub here is from a prior turn — it
@@ -2098,195 +1691,8 @@ class TurnRunner {
2098
1691
  const open = await this.#db.find_open_turn_scoped_subscriptions_for_worker.all({ worker_id: workerId });
2099
1692
  await Promise.all(open.map(({ id }) => this.#liveSubscriptions.cancel(id)));
2100
1693
  }
2101
- async #materializeStreamDeltas(args) {
2102
- const { workerId, loopId, turnId, fromSequence } = args;
2103
- const channels = await this.#db.engine_worker_stream_channels.all({ worker_id: workerId });
2104
- let written = 0;
2105
- for (const ch of channels) {
2106
- // Default channels are an implementation detail. Preserve the
2107
- // channel internally on the entry/subscription, but present the
2108
- // ordinary address to the model; only an explicitly non-default
2109
- // channel earns a fragment in the log.
2110
- const visibleFragment = ch.published_channel !== null
2111
- && ch.channel === this.#schemes.defaultChannelFor(ch.runtime, workerId)
2112
- ? null
2113
- : ch.channel;
2114
- const targetParts = authorityParts(ch.authority);
2115
- // {§exec-stream} — nothing publishes while a stream is active: the Child Streams
2116
- // section reports its size and growth ({§child-orientation}); the model READs any
2117
- // range it wants. At close, ONE foisted READ that is exactly a markerless READ —
2118
- // the first page, the extent, the terminal status and Problem — born OPEN. {§exec-stream-page}
2119
- if (ch.state !== "closed" && ch.state !== "errored")
2120
- continue;
2121
- const terminal = Results.assert(JSON.parse(ch.producer_result ?? "null"));
2122
- const sequence = fromSequence + written;
2123
- const source = this.#schemes.isRuntimeScheme(ch.runtime, workerId)
2124
- && /^\/[1-9]\d*\/[1-9]\d*\/[1-9]\d*$/.test(ch.coord)
2125
- ? `log://${ch.coord}/EXEC`
2126
- : null;
2127
- const page = await ReadResolve.resolve({ content: ch.content, mimetype: ch.mimetype, lineMarker: null });
2128
- const result = Results.assert({
2129
- ...terminal,
2130
- ...(terminal.problem === undefined ? {} : { problem: { ...terminal.problem } }),
2131
- content: page.content ?? "",
2132
- mimetype: page.mimetype,
2133
- ...(page.startLine === undefined || page.startLine === null ? {} : { startLine: page.startLine }),
2134
- ...(page.range === undefined ? {} : { range: page.range }),
2135
- });
2136
- if (result.problem !== undefined) {
2137
- const seqs = await this.#db.engine_loop_turn_seqs.get({
2138
- loop_id: loopId,
2139
- turn_id: turnId,
2140
- });
2141
- if (seqs === undefined)
2142
- throw new Error(`stream delta has no log coordinate for loop=${loopId} turn=${turnId}`);
2143
- Results.attachInstance(result, `log:///${seqs.loop_seq}/${seqs.turn_seq}/${sequence}/READ`);
2144
- }
2145
- const rx = JSON.stringify(result);
2146
- await this.#db.engine_insert_stream_delta.run({
2147
- worker_id: workerId, loop_id: loopId, turn_id: turnId, sequence,
2148
- subscription_publication_id: ch.publication_id,
2149
- source,
2150
- scheme: ch.runtime, hostname: targetParts.hostname, port: targetParts.port,
2151
- pathname: ch.coord, fragment: visibleFragment,
2152
- rx,
2153
- weight: LogBody.weight({
2154
- op: "READ",
2155
- attrs: {},
2156
- tx: "",
2157
- rx,
2158
- mimetypeTx: "text/plain",
2159
- mimetypeRx: "application/json",
2160
- }, this.#weighContent),
2161
- status: terminal.status,
2162
- attrs: JSON.stringify({ streamEnd: ch.content.length, terminal: true }),
2163
- folded: LogVisibility.serialize(LogVisibility.OPEN), // {§exec-stream} — the conclusion is born OPEN
2164
- });
2165
- written++;
2166
- }
2167
- return written;
2168
- }
2169
- // {§env-delta-filesystem-narration} {§membership-emi-divergence-signal}
2170
- // — record project-file divergence once through the reserved actor.
2171
- async #logFsFictions(workspaceId, divergences, gitStatus) {
2172
- if (divergences.length === 0)
2173
- return;
2174
- const gitByPath = new Map(gitStatus?.files.map(({ path, status }) => [path, status]) ?? []);
2175
- const worker = await this.#db.envelope_get_worker_by_name.get({ workspace_id: workspaceId, name: "plurnk" })
2176
- ?? await this.#db.envelope_insert_worker.get({ workspace_id: workspaceId, name: "plurnk", origin: "_plurnk" });
2177
- if (worker === undefined)
2178
- throw new Error("logFsFictions: plurnk worker resolution returned no row");
2179
- const loop = await this.#db.envelope_insert_client_loop.get({ worker_id: worker.id });
2180
- if (loop === undefined)
2181
- throw new Error("logFsFictions: loop insert returned no row");
2182
- const turn = await Turn.open(this.#db, { loopId: loop.id, producer: "_plurnk", kind: "operation" });
2183
- let turnOpen = true;
2184
- try {
2185
- let sequence = 1;
2186
- for (const d of divergences) {
2187
- const span = editedSpan(d.before, d.after);
2188
- const rx = JSON.stringify({ status: 200, entryId: d.entryId, channel: d.channel, span });
2189
- const attrs = gitByPath.has(d.pathname)
2190
- ? JSON.stringify({ git: gitByPath.get(d.pathname) })
2191
- : "{}";
2192
- await this.#db.engine_insert_log_entry.get({
2193
- worker_id: worker.id, loop_id: loop.id, turn_id: turn.id, sequence: sequence++,
2194
- origin: "_plurnk", source: "file", model_call_id: null,
2195
- op: "EDIT", delimiter: "", signal: null,
2196
- // Match Dispatcher.#extractTarget: a bare file address has NULL scheme
2197
- // only in log target metadata; its entry identity remains `file`.
2198
- scheme: null, username: null, password: null, hostname: null, port: null,
2199
- pathname: d.pathname, query: null, fragment: null, lineMarker: null,
2200
- tx: "", mimetype_tx: "text/plain",
2201
- rx, mimetype_rx: "application/json",
2202
- status_rx: 200,
2203
- weight: LogBody.weight({
2204
- op: "EDIT",
2205
- attrs,
2206
- tx: "",
2207
- rx,
2208
- mimetypeTx: "text/plain",
2209
- mimetypeRx: "application/json",
2210
- }, this.#weighContent),
2211
- state: "resolved", outcome: null,
2212
- attrs,
2213
- initial_folded: LogVisibility.serialize(LogVisibility.OPEN),
2214
- });
2215
- }
2216
- await Turn.complete(this.#db, turn.id, 200);
2217
- turnOpen = false;
2218
- const closed = await new LoopLifecycle(this.#db).finish(loop.id, { status: 200 });
2219
- if (closed === null)
2220
- throw new Error(`logFsFictions: narration loop ${loop.id} was not open at completion`);
2221
- }
2222
- catch (cause) {
2223
- const settlementFailures = [];
2224
- const failure = Results.failure("engine:filesystem-narration", "narration-failed", 500, "Filesystem divergence narration failed before its operation turn settled.", {}, { stage: "filesystem-narration", retryable: false });
2225
- if (turnOpen) {
2226
- try {
2227
- await Turn.complete(this.#db, turn.id, failure.status);
2228
- }
2229
- catch (turnCause) {
2230
- settlementFailures.push(turnCause);
2231
- }
2232
- }
2233
- try {
2234
- await new LoopLifecycle(this.#db).finish(loop.id, failure);
2235
- }
2236
- catch (loopCause) {
2237
- settlementFailures.push(loopCause);
2238
- }
2239
- if (settlementFailures.length > 0) {
2240
- throw new AggregateError([cause, ...settlementFailures], `filesystem narration ${turn.id} failed to settle`);
2241
- }
2242
- throw cause;
2243
- }
2244
- }
2245
- async #writePromptLog({ workerId, loopId, turnId, sequence, target, content, source, }) {
2246
- const rx = JSON.stringify({ content, mimetype: "text/markdown" });
2247
- const row = await this.#db.engine_insert_log_entry.get({
2248
- worker_id: workerId,
2249
- loop_id: loopId,
2250
- turn_id: turnId,
2251
- sequence,
2252
- origin: "_plurnk",
2253
- source,
2254
- model_call_id: null,
2255
- op: "prompt",
2256
- delimiter: "",
2257
- signal: null,
2258
- scheme: target.scheme,
2259
- username: target.username,
2260
- password: target.password,
2261
- hostname: target.hostname,
2262
- port: target.port,
2263
- pathname: target.pathname,
2264
- query: target.query,
2265
- fragment: target.fragment,
2266
- lineMarker: null,
2267
- tx: "",
2268
- mimetype_tx: "text/plain",
2269
- rx,
2270
- mimetype_rx: "application/json",
2271
- status_rx: 200,
2272
- weight: LogBody.weight({
2273
- op: "prompt",
2274
- attrs: {},
2275
- tx: "",
2276
- rx,
2277
- mimetypeTx: "text/plain",
2278
- mimetypeRx: "application/json",
2279
- }, this.#weighContent),
2280
- state: "resolved",
2281
- outcome: null,
2282
- attrs: "{}",
2283
- initial_folded: LogVisibility.serialize(LogVisibility.OPEN),
2284
- });
2285
- if (row === undefined)
2286
- throw new Error("TurnRunner.#writePromptLog: INSERT ... RETURNING produced no row");
2287
- return row.id;
1694
+ async executeAdmittedTurn(...args) {
1695
+ return this.#admitted.executeAdmittedTurn(...args);
2288
1696
  }
2289
1697
  }
2290
- _a = TurnRunner;
2291
- export default TurnRunner;
2292
1698
  //# sourceMappingURL=TurnRunner.js.map