@plurnk/plurnk-service 2.0.0 → 3.1.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 (333) hide show
  1. package/.env.defaults +27 -19
  2. package/INSTALL.md +21 -2
  3. package/README.md +4 -2
  4. package/SPEC.md +644 -467
  5. package/dist/build-info.json +1 -1
  6. package/dist/completions/_plurnk-service +13 -0
  7. package/dist/completions/plurnk-service.bash +19 -0
  8. package/dist/completions/plurnk-service.fish +93 -0
  9. package/dist/content/edit-receipt.d.ts +1 -1
  10. package/dist/content/edit-receipt.d.ts.map +1 -1
  11. package/dist/content/edit-receipt.js +1 -1
  12. package/dist/content/edit-receipt.js.map +1 -1
  13. package/dist/content/read-projector.d.ts.map +1 -1
  14. package/dist/content/read-projector.js +3 -12
  15. package/dist/content/read-projector.js.map +1 -1
  16. package/dist/core/AdministrativeLoop.d.ts +1 -1
  17. package/dist/core/AdministrativeLoop.d.ts.map +1 -1
  18. package/dist/core/AdministrativeLoop.js +2 -6
  19. package/dist/core/AdministrativeLoop.js.map +1 -1
  20. package/dist/core/AdmittedTurnExecutor.d.ts +2 -2
  21. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
  22. package/dist/core/AdmittedTurnExecutor.js +16 -24
  23. package/dist/core/AdmittedTurnExecutor.js.map +1 -1
  24. package/dist/core/BudgetReadout.d.ts +8 -2
  25. package/dist/core/BudgetReadout.d.ts.map +1 -1
  26. package/dist/core/BudgetReadout.js +48 -5
  27. package/dist/core/BudgetReadout.js.map +1 -1
  28. package/dist/core/CapabilityPolicies.d.ts +2 -4
  29. package/dist/core/CapabilityPolicies.d.ts.map +1 -1
  30. package/dist/core/CapabilityPolicies.js +3 -23
  31. package/dist/core/CapabilityPolicies.js.map +1 -1
  32. package/dist/core/CapabilityResolver.d.ts +9 -2
  33. package/dist/core/CapabilityResolver.d.ts.map +1 -1
  34. package/dist/core/CapabilityResolver.js +34 -5
  35. package/dist/core/CapabilityResolver.js.map +1 -1
  36. package/dist/core/ChannelWrite.d.ts +0 -2
  37. package/dist/core/ChannelWrite.d.ts.map +1 -1
  38. package/dist/core/ChannelWrite.js.map +1 -1
  39. package/dist/core/ClientInteractions.d.ts +3 -2
  40. package/dist/core/ClientInteractions.d.ts.map +1 -1
  41. package/dist/core/ClientInteractions.js +21 -12
  42. package/dist/core/ClientInteractions.js.map +1 -1
  43. package/dist/core/ClientInteractions.sql +8 -2
  44. package/dist/core/CoreSchemeServices.d.ts +1 -0
  45. package/dist/core/CoreSchemeServices.d.ts.map +1 -1
  46. package/dist/core/CoreSchemeServices.js +1 -0
  47. package/dist/core/CoreSchemeServices.js.map +1 -1
  48. package/dist/core/DataStatementRunner.js +1 -1
  49. package/dist/core/DataStatementRunner.js.map +1 -1
  50. package/dist/core/Dispatcher.d.ts +3 -2
  51. package/dist/core/Dispatcher.d.ts.map +1 -1
  52. package/dist/core/Dispatcher.js +55 -52
  53. package/dist/core/Dispatcher.js.map +1 -1
  54. package/dist/core/Engine.d.ts +1 -1
  55. package/dist/core/Engine.d.ts.map +1 -1
  56. package/dist/core/Engine.js +4 -6
  57. package/dist/core/Engine.js.map +1 -1
  58. package/dist/core/EnvFlags.d.ts.map +1 -1
  59. package/dist/core/EnvFlags.js +5 -4
  60. package/dist/core/EnvFlags.js.map +1 -1
  61. package/dist/core/FabricatedLog.d.ts +1 -0
  62. package/dist/core/FabricatedLog.d.ts.map +1 -1
  63. package/dist/core/FabricatedLog.js +9 -1
  64. package/dist/core/FabricatedLog.js.map +1 -1
  65. package/dist/core/HostPaths.d.ts +0 -1
  66. package/dist/core/HostPaths.d.ts.map +1 -1
  67. package/dist/core/HostPaths.js +0 -2
  68. package/dist/core/HostPaths.js.map +1 -1
  69. package/dist/core/KillHandler.d.ts.map +1 -1
  70. package/dist/core/KillHandler.js +3 -1
  71. package/dist/core/KillHandler.js.map +1 -1
  72. package/dist/core/LiveSubscription.d.ts.map +1 -1
  73. package/dist/core/LiveSubscription.js +14 -2
  74. package/dist/core/LiveSubscription.js.map +1 -1
  75. package/dist/core/LiveSubscriptions.d.ts +3 -1
  76. package/dist/core/LiveSubscriptions.d.ts.map +1 -1
  77. package/dist/core/LiveSubscriptions.js +16 -1
  78. package/dist/core/LiveSubscriptions.js.map +1 -1
  79. package/dist/core/LogBody.d.ts.map +1 -1
  80. package/dist/core/LogBody.js +3 -1
  81. package/dist/core/LogBody.js.map +1 -1
  82. package/dist/core/LogVisibility.d.ts.map +1 -1
  83. package/dist/core/LogVisibility.js +8 -17
  84. package/dist/core/LogVisibility.js.map +1 -1
  85. package/dist/core/LoopDriver.js +7 -6
  86. package/dist/core/LoopDriver.js.map +1 -1
  87. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  88. package/dist/core/LoopLifecycle.js +4 -9
  89. package/dist/core/LoopLifecycle.js.map +1 -1
  90. package/dist/core/LoopLifecycle.sql +7 -6
  91. package/dist/core/MessageResources.sql +31 -0
  92. package/dist/core/OperatorConfig.d.ts +1 -0
  93. package/dist/core/OperatorConfig.d.ts.map +1 -1
  94. package/dist/core/OperatorConfig.js +10 -2
  95. package/dist/core/OperatorConfig.js.map +1 -1
  96. package/dist/core/PacketBuilder.d.ts +5 -7
  97. package/dist/core/PacketBuilder.d.ts.map +1 -1
  98. package/dist/core/PacketBuilder.js +160 -158
  99. package/dist/core/PacketBuilder.js.map +1 -1
  100. package/dist/core/PacketBuilder.sql +20 -6
  101. package/dist/core/ProposalLifecycle.d.ts +1 -1
  102. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  103. package/dist/core/ProposalLifecycle.js +18 -20
  104. package/dist/core/ProposalLifecycle.js.map +1 -1
  105. package/dist/core/ProposalPolicies.d.ts +6 -0
  106. package/dist/core/ProposalPolicies.d.ts.map +1 -0
  107. package/dist/core/ProposalPolicies.js +28 -0
  108. package/dist/core/ProposalPolicies.js.map +1 -0
  109. package/dist/core/ProviderInstantiate.d.ts.map +1 -1
  110. package/dist/core/ProviderInstantiate.js +3 -4
  111. package/dist/core/ProviderInstantiate.js.map +1 -1
  112. package/dist/core/ReplyMetadata.d.ts +10 -0
  113. package/dist/core/ReplyMetadata.d.ts.map +1 -0
  114. package/dist/core/ReplyMetadata.js +20 -0
  115. package/dist/core/ReplyMetadata.js.map +1 -0
  116. package/dist/core/ResourceSelector.js +2 -2
  117. package/dist/core/ResourceSelector.js.map +1 -1
  118. package/dist/core/ResourceTransfers.js +3 -3
  119. package/dist/core/ResourceTransfers.js.map +1 -1
  120. package/dist/core/RuntimeWorker.sql +1 -2
  121. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  122. package/dist/core/SchemeRegistry.js +4 -5
  123. package/dist/core/SchemeRegistry.js.map +1 -1
  124. package/dist/core/ServiceHelp.d.ts +6 -0
  125. package/dist/core/ServiceHelp.d.ts.map +1 -0
  126. package/dist/core/ServiceHelp.js +35 -0
  127. package/dist/core/ServiceHelp.js.map +1 -0
  128. package/dist/core/StoredPacket.d.ts +1 -0
  129. package/dist/core/StoredPacket.d.ts.map +1 -1
  130. package/dist/core/StoredPacket.js +4 -1
  131. package/dist/core/StoredPacket.js.map +1 -1
  132. package/dist/core/StrikeRail.d.ts.map +1 -1
  133. package/dist/core/StrikeRail.js +2 -2
  134. package/dist/core/StrikeRail.js.map +1 -1
  135. package/dist/core/TokenCalibration.d.ts +2 -2
  136. package/dist/core/TokenCalibration.d.ts.map +1 -1
  137. package/dist/core/TokenCalibration.js +12 -16
  138. package/dist/core/TokenCalibration.js.map +1 -1
  139. package/dist/core/TokenCalibration.sql +29 -6
  140. package/dist/core/ToolInputSchema.d.ts +1 -0
  141. package/dist/core/ToolInputSchema.d.ts.map +1 -1
  142. package/dist/core/ToolInputSchema.js +8 -2
  143. package/dist/core/ToolInputSchema.js.map +1 -1
  144. package/dist/core/ToolResources.d.ts +1 -0
  145. package/dist/core/ToolResources.d.ts.map +1 -1
  146. package/dist/core/ToolResources.js +7 -1
  147. package/dist/core/ToolResources.js.map +1 -1
  148. package/dist/core/TurnDispositionHandler.d.ts +1 -2
  149. package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
  150. package/dist/core/TurnDispositionHandler.js +31 -33
  151. package/dist/core/TurnDispositionHandler.js.map +1 -1
  152. package/dist/core/TurnMaterialization.d.ts.map +1 -1
  153. package/dist/core/TurnMaterialization.js +12 -2
  154. package/dist/core/TurnMaterialization.js.map +1 -1
  155. package/dist/core/TurnOps.d.ts +5 -1
  156. package/dist/core/TurnOps.d.ts.map +1 -1
  157. package/dist/core/TurnOps.js +29 -2
  158. package/dist/core/TurnOps.js.map +1 -1
  159. package/dist/core/TurnRunner.d.ts.map +1 -1
  160. package/dist/core/TurnRunner.js +184 -103
  161. package/dist/core/TurnRunner.js.map +1 -1
  162. package/dist/core/TurnSources.sql +2 -2
  163. package/dist/core/WorkerControlHandler.d.ts.map +1 -1
  164. package/dist/core/WorkerControlHandler.js +1 -8
  165. package/dist/core/WorkerControlHandler.js.map +1 -1
  166. package/dist/core/WorkerName.d.ts +1 -0
  167. package/dist/core/WorkerName.d.ts.map +1 -1
  168. package/dist/core/WorkerName.js +2 -0
  169. package/dist/core/WorkerName.js.map +1 -1
  170. package/dist/core/WorkerName.sql +2 -2
  171. package/dist/core/WorkerOwners.d.ts +13 -0
  172. package/dist/core/WorkerOwners.d.ts.map +1 -0
  173. package/dist/core/WorkerOwners.js +44 -0
  174. package/dist/core/WorkerOwners.js.map +1 -0
  175. package/dist/core/WorkerOwners.sql +55 -0
  176. package/dist/core/env-catalog.d.ts +3 -0
  177. package/dist/core/env-catalog.d.ts.map +1 -1
  178. package/dist/core/env-catalog.js +44 -9
  179. package/dist/core/env-catalog.js.map +1 -1
  180. package/dist/core/fork.sql +3 -4
  181. package/dist/core/packet-inject.js +0 -2
  182. package/dist/core/packet-inject.js.map +1 -1
  183. package/dist/core/packet-wire.d.ts +9 -11
  184. package/dist/core/packet-wire.d.ts.map +1 -1
  185. package/dist/core/packet-wire.js +103 -126
  186. package/dist/core/packet-wire.js.map +1 -1
  187. package/dist/core/plurnk-uri.d.ts +1 -1
  188. package/dist/core/plurnk-uri.d.ts.map +1 -1
  189. package/dist/core/plurnk-uri.js +4 -4
  190. package/dist/core/plurnk-uri.js.map +1 -1
  191. package/dist/core/recap-lines.d.ts +4 -0
  192. package/dist/core/recap-lines.d.ts.map +1 -0
  193. package/dist/core/recap-lines.js +11 -0
  194. package/dist/core/recap-lines.js.map +1 -0
  195. package/dist/core/scheme-types.d.ts +2 -1
  196. package/dist/core/scheme-types.d.ts.map +1 -1
  197. package/dist/core/sql-functions.d.ts +2 -0
  198. package/dist/core/sql-functions.d.ts.map +1 -0
  199. package/dist/core/sql-functions.js +5 -0
  200. package/dist/core/sql-functions.js.map +1 -0
  201. package/dist/core/turn-scheduler.d.ts.map +1 -1
  202. package/dist/core/turn-scheduler.js +1 -1
  203. package/dist/core/turn-scheduler.js.map +1 -1
  204. package/dist/core/types.d.ts +0 -1
  205. package/dist/core/types.d.ts.map +1 -1
  206. package/dist/core/unregistered-scheme.d.ts +1 -3
  207. package/dist/core/unregistered-scheme.d.ts.map +1 -1
  208. package/dist/core/unregistered-scheme.js +3 -11
  209. package/dist/core/unregistered-scheme.js.map +1 -1
  210. package/dist/evidence/EvidenceReader.d.ts.map +1 -1
  211. package/dist/evidence/EvidenceReader.js +18 -2
  212. package/dist/evidence/EvidenceReader.js.map +1 -1
  213. package/dist/evidence/digest.sql +2 -2
  214. package/dist/man/plurnk-service.1 +488 -0
  215. package/dist/schemes/EffectPolicy.d.ts.map +1 -1
  216. package/dist/schemes/EffectPolicy.js +1 -10
  217. package/dist/schemes/EffectPolicy.js.map +1 -1
  218. package/dist/schemes/Env.d.ts +26 -0
  219. package/dist/schemes/Env.d.ts.map +1 -0
  220. package/dist/schemes/Env.js +133 -0
  221. package/dist/schemes/Env.js.map +1 -0
  222. package/dist/schemes/Exec.d.ts.map +1 -1
  223. package/dist/schemes/Exec.js +30 -37
  224. package/dist/schemes/Exec.js.map +1 -1
  225. package/dist/schemes/ExecOutputScheme.d.ts +3 -2
  226. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  227. package/dist/schemes/ExecOutputScheme.js +9 -0
  228. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  229. package/dist/schemes/File.d.ts.map +1 -1
  230. package/dist/schemes/File.js +10 -16
  231. package/dist/schemes/File.js.map +1 -1
  232. package/dist/schemes/Log.d.ts.map +1 -1
  233. package/dist/schemes/Log.js +33 -10
  234. package/dist/schemes/Log.js.map +1 -1
  235. package/dist/schemes/Log.sql +9 -0
  236. package/dist/schemes/QuestionTool.d.ts.map +1 -1
  237. package/dist/schemes/QuestionTool.js +1 -3
  238. package/dist/schemes/QuestionTool.js.map +1 -1
  239. package/dist/schemes/Worker.d.ts.map +1 -1
  240. package/dist/schemes/Worker.js +6 -8
  241. package/dist/schemes/Worker.js.map +1 -1
  242. package/dist/schemes/_entry-find.d.ts +1 -1
  243. package/dist/schemes/_entry-find.d.ts.map +1 -1
  244. package/dist/schemes/_entry-find.js +16 -9
  245. package/dist/schemes/_entry-find.js.map +1 -1
  246. package/dist/schemes/_entry-fts.d.ts.map +1 -1
  247. package/dist/schemes/_entry-fts.js +3 -9
  248. package/dist/schemes/_entry-fts.js.map +1 -1
  249. package/dist/schemes/_entry-manifest.js +3 -3
  250. package/dist/schemes/_entry-manifest.js.map +1 -1
  251. package/dist/schemes/_entry-ops.js +1 -1
  252. package/dist/schemes/_entry-ops.js.map +1 -1
  253. package/dist/schemes/exec-abort.js +2 -2
  254. package/dist/schemes/exec-abort.js.map +1 -1
  255. package/dist/server/ConfigurationDiagnostics.d.ts +1 -0
  256. package/dist/server/ConfigurationDiagnostics.d.ts.map +1 -1
  257. package/dist/server/ConfigurationDiagnostics.js +9 -0
  258. package/dist/server/ConfigurationDiagnostics.js.map +1 -1
  259. package/dist/server/Daemon.d.ts +13 -8
  260. package/dist/server/Daemon.d.ts.map +1 -1
  261. package/dist/server/Daemon.js +57 -53
  262. package/dist/server/Daemon.js.map +1 -1
  263. package/dist/server/DrainSupervisor.d.ts +2 -4
  264. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  265. package/dist/server/DrainSupervisor.js +5 -12
  266. package/dist/server/DrainSupervisor.js.map +1 -1
  267. package/dist/server/EnvFunctionality.d.ts +6 -6
  268. package/dist/server/EnvFunctionality.d.ts.map +1 -1
  269. package/dist/server/EnvFunctionality.js +7 -6
  270. package/dist/server/EnvFunctionality.js.map +1 -1
  271. package/dist/server/Functionality.d.ts.map +1 -1
  272. package/dist/server/Functionality.js +42 -13
  273. package/dist/server/Functionality.js.map +1 -1
  274. package/dist/server/FunctionalityManager.d.ts +3 -4
  275. package/dist/server/FunctionalityManager.d.ts.map +1 -1
  276. package/dist/server/FunctionalityManager.js +17 -9
  277. package/dist/server/FunctionalityManager.js.map +1 -1
  278. package/dist/server/HttpListener.d.ts.map +1 -1
  279. package/dist/server/HttpListener.js +9 -3
  280. package/dist/server/HttpListener.js.map +1 -1
  281. package/dist/server/MembersFunctionality.d.ts +2 -5
  282. package/dist/server/MembersFunctionality.d.ts.map +1 -1
  283. package/dist/server/MembersFunctionality.js +5 -3
  284. package/dist/server/MembersFunctionality.js.map +1 -1
  285. package/dist/server/WorkspaceStorage.d.ts +0 -1
  286. package/dist/server/WorkspaceStorage.d.ts.map +1 -1
  287. package/dist/server/WorkspaceStorage.js +1 -24
  288. package/dist/server/WorkspaceStorage.js.map +1 -1
  289. package/dist/server/client-input.d.ts +1 -2
  290. package/dist/server/client-input.d.ts.map +1 -1
  291. package/dist/server/client-input.js +13 -15
  292. package/dist/server/client-input.js.map +1 -1
  293. package/dist/server/dispatch-as-plurnk.js +1 -1
  294. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  295. package/dist/server/drain.sql +16 -15
  296. package/dist/server/envelope.d.ts +2 -1
  297. package/dist/server/envelope.d.ts.map +1 -1
  298. package/dist/server/envelope.js +7 -17
  299. package/dist/server/envelope.js.map +1 -1
  300. package/dist/server/envelope.sql +5 -5
  301. package/dist/server/seam-proposal-list.sql +6 -4
  302. package/dist/server/workspace-storage.sql +0 -5
  303. package/dist/service.d.ts.map +1 -1
  304. package/dist/service.js +28 -64
  305. package/dist/service.js.map +1 -1
  306. package/docs/env.md +22 -0
  307. package/migrations/003_loops.sql +2 -2
  308. package/migrations/006_log.sql +1 -1
  309. package/migrations/016_selection_statements.sql +1 -0
  310. package/migrations/017_skills_module.sql +1 -0
  311. package/migrations/018_worker_owners.sql +103 -0
  312. package/migrations/019_interactive_owners.sql +7 -0
  313. package/migrations/020_log_projection.sql +144 -0
  314. package/migrations/021_packet_roles.sql +86 -0
  315. package/migrations/022_message_completion.sql +24 -0
  316. package/package.json +41 -43
  317. package/dist/core/LegacyHome.d.ts +0 -10
  318. package/dist/core/LegacyHome.d.ts.map +0 -1
  319. package/dist/core/LegacyHome.js +0 -170
  320. package/dist/core/LegacyHome.js.map +0 -1
  321. package/dist/core/LoopPolicies.d.ts +0 -7
  322. package/dist/core/LoopPolicies.d.ts.map +0 -1
  323. package/dist/core/LoopPolicies.js +0 -42
  324. package/dist/core/LoopPolicies.js.map +0 -1
  325. package/dist/core/LoopPolicyReader.d.ts +0 -7
  326. package/dist/core/LoopPolicyReader.d.ts.map +0 -1
  327. package/dist/core/LoopPolicyReader.js +0 -33
  328. package/dist/core/LoopPolicyReader.js.map +0 -1
  329. package/dist/core/LoopPolicyReader.sql +0 -6
  330. package/dist/index.d.ts +0 -14
  331. package/dist/index.d.ts.map +0 -1
  332. package/dist/index.js +0 -21
  333. package/dist/index.js.map +0 -1
@@ -14,6 +14,8 @@ FROM message_responses e
14
14
  JOIN workers w ON w.id = e.worker_id
15
15
  WHERE w.workspace_id = $workspace_id AND w.id = $worker_id
16
16
  AND ($loop_id IS NULL OR e.loop_id = $loop_id)
17
+ AND (length(trim(e.content, char(9) || char(10) || char(13) || ' ')) > 0
18
+ OR json_array_length(e.rx, '$.attachments') > 0)
17
19
  ORDER BY loop_id, id;
18
20
  -- PREP: message_source_resources
19
21
  -- A message keeps the address its minter gave it (`a2a://…`, `agui://…`), and {§message-short-identity}
@@ -32,5 +34,34 @@ SELECT * FROM message_sources WHERE workspace_id = $workspace_id AND key_path =
32
34
  UNION ALL
33
35
  SELECT * FROM message_sources WHERE workspace_id = $workspace_id AND address = $path;
34
36
 
37
+ -- PREP: message_latest_published
38
+ -- {§message-completion}: with none open, a targetless SEND speaks to the loop's latest published message.
39
+ SELECT path FROM message_sources
40
+ WHERE loop_id = $loop_id AND log_entry_id IS NOT NULL
41
+ ORDER BY ordinal DESC LIMIT 1;
42
+
35
43
  -- PREP: message_unanswered_count
36
44
  SELECT count(*) AS count FROM unanswered_messages WHERE loop_id = $loop_id;
45
+
46
+ -- PREP: message_completion_outcome
47
+ -- {§message-completion}: any completed request wins; all-cancelled is cancellation.
48
+ SELECT CASE WHEN COUNT(*) > 0 AND MIN(c.status) = 499 THEN 499 ELSE 200 END AS status
49
+ FROM message_completions c JOIN loop_messages m ON m.id = c.message_id
50
+ WHERE m.loop_id = $loop_id;
51
+
52
+ -- INIT: message_complete_on_reply
53
+ DROP TRIGGER IF EXISTS message_complete_on_reply;
54
+ CREATE TRIGGER message_complete_on_reply
55
+ AFTER INSERT ON log_entries
56
+ WHEN NEW.op = 'SEND' AND NEW.state = 'resolved' AND NEW.status_rx BETWEEN 200 AND 299
57
+ AND NEW.source IS NULL AND NEW.inherited_history = 0 AND json_valid(NEW.rx)
58
+ AND json_extract(NEW.rx, '$.completion') IN (200, 499)
59
+ BEGIN
60
+ INSERT INTO message_completions (message_id, response_id, status)
61
+ SELECT m.id, NEW.id, json_extract(NEW.rx, '$.completion')
62
+ FROM message_sources m
63
+ JOIN workers w ON w.id = NEW.worker_id AND w.workspace_id = m.workspace_id
64
+ JOIN json_each(NEW.rx, '$.answers') a ON a.value = m.path
65
+ WHERE true
66
+ ON CONFLICT(message_id) DO UPDATE SET response_id = excluded.response_id, status = excluded.status;
67
+ END;
@@ -2,6 +2,7 @@ import type HostPaths from "./HostPaths.ts";
2
2
  export default class OperatorConfig {
3
3
  #private;
4
4
  static renderSeed(token?: string): string;
5
+ static undeclared(text: string, declares: (key: string) => boolean): readonly string[];
5
6
  static ensure(paths: HostPaths, policySource: string): Promise<boolean>;
6
7
  }
7
8
  //# sourceMappingURL=OperatorConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OperatorConfig.d.ts","sourceRoot":"","sources":["../../src/core/OperatorConfig.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAW5C,MAAM,CAAC,OAAO,OAAO,cAAc;;IAU/B,MAAM,CAAC,UAAU,CAAC,KAAK,SAA8B,GAAG,MAAM,CA4C7D;IAED,OAAa,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB5E;CACJ"}
1
+ {"version":3,"file":"OperatorConfig.d.ts","sourceRoot":"","sources":["../../src/core/OperatorConfig.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAc5C,MAAM,CAAC,OAAO,OAAO,cAAc;;IAU/B,MAAM,CAAC,UAAU,CAAC,KAAK,SAA8B,GAAG,MAAM,CA4C7D;IAID,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,MAAM,EAAE,CAErF;IAED,OAAa,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB5E;CACJ"}
@@ -54,6 +54,9 @@ import { randomBytes } from "node:crypto";
54
54
  import { constants } from "node:fs";
55
55
  import { access, mkdir, mkdtempDisposable, readFile, rename, writeFile } from "node:fs/promises";
56
56
  import { basename, dirname, join } from "node:path";
57
+ import { parseEnv } from "node:util";
58
+ // The client and the bench lanes read their own keys from the operator's file, too.
59
+ const FOREIGN = /^PLURNK_(?:CLIENT_|COMPOSITION_|BENCH|SWEBENCH_|PI_|CANDIDATE_)/u;
57
60
  const exists = async (path) => access(path, constants.F_OK)
58
61
  .then(() => true)
59
62
  .catch((cause) => {
@@ -110,13 +113,18 @@ export default class OperatorConfig {
110
113
  "# PLURNK_MEMBERS_no_locks=!**/*.lock",
111
114
  "# PLURNK_MEMBERS_no_locks_ENABLED=0",
112
115
  "",
113
- "# OPTIONAL TAVILY HTML MATERIALIZATION — the plugin ships with the service;",
114
- "# uncomment both lines to select it.",
116
+ "# OPTIONAL TAVILY HTML MATERIALIZATION — install @plurnk/plurnk-tavily-plugin beside the",
117
+ "# service, then uncomment both lines to select it.",
115
118
  "# TAVILY_API_KEY=\"...\"",
116
119
  "# PLURNK_SCHEMES_HTTP_MATERIALIZER=tavily-extract",
117
120
  "",
118
121
  ].join("\n");
119
122
  }
123
+ // {§operator-config-undeclared-key} The daemon's keys an operator file sets that no installed
124
+ // package declares, in file order.
125
+ static undeclared(text, declares) {
126
+ return Object.keys(parseEnv(text)).filter((key) => key.startsWith("PLURNK_") && !FOREIGN.test(key) && !declares(key));
127
+ }
120
128
  static async ensure(paths, policySource) {
121
129
  const env_1 = { stack: [], error: void 0, hasError: false };
122
130
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"OperatorConfig.js","sourceRoot":"","sources":["../../src/core/OperatorConfig.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"OperatorConfig.js","sourceRoot":"","sources":["../../src/core/OperatorConfig.ts"],"names":[],"mappings":"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"}
@@ -5,11 +5,11 @@ import type ExecutorRegistry from "./ExecutorRegistry.ts";
5
5
  import type { GitStatus } from "./git-state.ts";
6
6
  import { type BodiedLogRow } from "./packet-wire.ts";
7
7
  import type { RequestPacket } from "./StoredPacket.ts";
8
- import type { ChatMessage, Provider } from "@plurnk/plurnk-providers";
8
+ import type { ChatMessage, Provider, ProviderRequestCapacity } from "@plurnk/plurnk-providers";
9
9
  export type { ChatMessage } from "@plurnk/plurnk-providers";
10
10
  export interface WindowOverflow {
11
11
  readonly tokens: number;
12
- readonly budget: number;
12
+ readonly budget: number | null;
13
13
  readonly wall: number;
14
14
  readonly excess: number;
15
15
  readonly excessWeight: number;
@@ -31,12 +31,9 @@ export default class PacketBuilder {
31
31
  pathname: string;
32
32
  content: string;
33
33
  }>): void;
34
- static validateConfiguration(env?: NodeJS.ProcessEnv): void;
35
- static assertConfiguration(env?: NodeJS.ProcessEnv): void;
36
- emissionsFor(packet: RequestPacket): ReadonlyMap<string, string>;
37
34
  curationBudgetFor(packet: RequestPacket): number | null;
38
35
  bodiedRowsOf(packet: RequestPacket): readonly BodiedLogRow[];
39
- buildRequestPacket({ initialMessages, recap, workspaceId, workerId, loopId, currentTurnSeq, provider, gitStatus, notices, transientOpenLogEntryId, turnId, bodiless, }: {
36
+ buildRequestPacket({ initialMessages, recap, workspaceId, workerId, loopId, currentTurnSeq, provider, gitStatus, notices, transientOpenLogEntryId, turnId, bodiless, omitEmissionHistory, }: {
40
37
  initialMessages: ChatMessage[];
41
38
  recap?: string;
42
39
  gitStatus: GitStatus | null;
@@ -49,6 +46,7 @@ export default class PacketBuilder {
49
46
  transientOpenLogEntryId?: number | null;
50
47
  turnId?: number | null;
51
48
  bodiless?: ReadonlySet<number>;
49
+ omitEmissionHistory?: boolean;
52
50
  }): Promise<RequestPacket>;
53
51
  recordObservations(packet: RequestPacket): Promise<void>;
54
52
  referenceEntries(workspaceId: number): Promise<Array<{
@@ -57,9 +55,9 @@ export default class PacketBuilder {
57
55
  }>>;
58
56
  curationOverflow(packet: RequestPacket): CurationOverflow | null;
59
57
  windowOverflow(packet: RequestPacket, provider: {
60
- readonly inputCapacity: number | null;
61
58
  readonly inputWall: number | null;
62
59
  }): WindowOverflow | null;
60
+ exactOverflow(packet: RequestPacket, capacity: ProviderRequestCapacity): WindowOverflow | null;
63
61
  buildFailurePointers(loopId: number, currentTurnSeq: number): Promise<Array<{
64
62
  status: number;
65
63
  coordinate: string;
@@ -1 +1 @@
1
- {"version":3,"file":"PacketBuilder.d.ts","sourceRoot":"","sources":["../../src/core/PacketBuilder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PacketBuilder.d.ts","sourceRoot":"","sources":["../../src/core/PacketBuilder.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,14 @@
1
+ import { Knob } from "@plurnk/plurnk-meta";
1
2
  import WorkerName from "./WorkerName.js";
2
3
  import { generatedPathname, renderAddress } from "./plurnk-uri.js";
3
4
  import { contentWeight } from "./content-weight.js";
4
- import LoopPolicyReader from "./LoopPolicyReader.js";
5
5
  import CapabilityPolicies from "./CapabilityPolicies.js";
6
6
  import CapabilityResolver from "./CapabilityResolver.js";
7
7
  import { readPacketInject, readSystemPolicy } from "./packet-inject.js";
8
8
  import { readFile } from "node:fs/promises";
9
- import { readFileSync } from "node:fs";
10
- import { parseEnv } from "node:util";
11
9
  import Paths from "../Paths.js";
12
10
  import { readTeachingSource } from "./teaching-corpus.js";
11
+ import { recapLines } from "./recap-lines.js";
13
12
  import { acceptedKinds } from "./attachments.js";
14
13
  // Shared module imported by both Engine and the digest, so wire
15
14
  // projection and digest projection are structurally one function — no
@@ -19,8 +18,7 @@ import LogEntryProjection from "./LogEntryProjection.js";
19
18
  import BudgetReadout from "./BudgetReadout.js";
20
19
  import TokenCalibration from "./TokenCalibration.js";
21
20
  import ToolResources from "./ToolResources.js";
22
- import { ConfigurationError } from "@plurnk/plurnk-meta";
23
- import Results, { OperationFailureError } from "./results.js";
21
+ import TurnOps from "./TurnOps.js";
24
22
  const trimHorizontal = (value) => value.replace(/^[\t ]+|[\t ]+$/gu, "");
25
23
  const tableCells = (line) => {
26
24
  if (!line.startsWith("|") || !line.endsWith("|"))
@@ -94,12 +92,9 @@ const compactDefinitionTables = (markdown) => {
94
92
  // curation stays in scoped KILL; what fits was decided where each row landed ({§context-fit}).
95
93
  export default class PacketBuilder {
96
94
  #db;
97
- // {§tokenomics-calibrated-readout} — admission and client gauges consume
98
- // the allowance captured before this request can change model evidence.
99
- #curationBudgets = new WeakMap();
100
- // {§context-budget} — each loop's high-water budget, for the input capacity it was derived from.
101
- #loopBudgets = new Map();
102
- #emissions = new WeakMap();
95
+ // {§tokenomics-calibrated-readout} — admission and client gauges consume the allowance and the factor
96
+ // captured before this request can change model evidence.
97
+ #allowances = new WeakMap();
103
98
  // {§context-own-rows-fit} — the rows of each built packet the wall may still take, newest last.
104
99
  #bodiedRows = new WeakMap();
105
100
  #streamObservations = new WeakMap();
@@ -120,72 +115,14 @@ export default class PacketBuilder {
120
115
  setFunctionalityDocuments(documents) {
121
116
  this.#functionalityDocuments = documents;
122
117
  }
123
- static #declaredKnobs;
124
- // {§configuration-repair-path} — retired knobs fail naming what replaced them: the context
125
- // budget has one rule ({§context-fit}) and one gauge ({§context-gauge}).
126
- static validateConfiguration(env = process.env) {
127
- // A commented declaration (`# PLURNK_X=`) is an optional knob, declared like any other
128
- // ({§operator-config-env-defaults}; the catalog reads it the same way) — only its value is absent.
129
- const declared = PacketBuilder.#declaredKnobs ??= (() => {
130
- const text = readFileSync(new URL("../../.env.defaults", import.meta.url), "utf8");
131
- const optional = [...text.matchAll(/^#\s*([A-Za-z_][A-Za-z0-9_]*)=/gmu)].map((m) => m[1]);
132
- return [...Object.keys(parseEnv(text)), ...optional];
133
- })();
134
- const oneRule = "a result arrives whole when it fits the budget and as its size otherwise ({§context-fit}); nothing is previewed, projected or paged";
135
- const retired = {
136
- PLURNK_SERVICE_PROMPT_BUDGET: "provider input capacity is derived from context and output budgets",
137
- PLURNK_SERVICE_SAFETY: "provider request-shaped capacity admission owns physical headroom",
138
- PLURNK_SERVICE_PROMPT_PROJECTION: oneRule,
139
- PLURNK_SERVICE_BUDGET_PRESSURE: "the gauge carries no threshold and no mandate ({§context-gauge})",
140
- PLURNK_REASONING_VIEW_LINES: "initialization authors no reasoning and reads none back ({§worker-initialization-entry})",
141
- PLURNK_REASONING_EMPTY_TURN_LINES: "an empty turn reads nothing back; its 422 row is the whole receipt ({§empty-turn})",
142
- };
143
- const retiredKey = new RegExp(`^(${Object.keys(retired).join("|")})(?:_.*)?$`, "u");
144
- for (const key of Object.keys(env)) {
145
- const match = retiredKey.exec(key);
146
- const reason = match === null ? undefined : retired[match[1]];
147
- if (reason !== undefined)
148
- throw new ConfigurationError(key, `${key} is retired: ${reason}.`);
149
- }
150
- const moved = {
151
- CTX: "PLURNK_PROVIDERS_CONTEXT_WINDOW",
152
- CONTEXT_WINDOW: "PLURNK_PROVIDERS_CONTEXT_WINDOW",
153
- REASONING: "PLURNK_PROVIDERS_REASONING_BUDGET",
154
- ASSISTANT: "PLURNK_PROVIDERS_OUTPUT_BUDGET",
155
- COMPLETION: "PLURNK_PROVIDERS_OUTPUT_BUDGET",
156
- };
157
- for (const key of Object.keys(env)) {
158
- if (declared.some((knob) => key === knob || key.startsWith(`${knob}_`)))
159
- continue;
160
- const match = /^PLURNK_SERVICE_(CTX|CONTEXT_WINDOW|REASONING|ASSISTANT|COMPLETION)(_.*)?$/u.exec(key);
161
- if (match !== null)
162
- throw new ConfigurationError(key, `${key} is retired: the provider-owned knob is ${moved[match[1]]}${match[2] ?? ""}.`);
163
- }
164
- }
165
- // {§configuration-repair-path} — the same refusal as an operation failure: a 503 Problem naming the
166
- // key, so a loop reports the failed demand instead of dying on an unshaped exception.
167
- static assertConfiguration(env = process.env) {
168
- try {
169
- PacketBuilder.validateConfiguration(env);
170
- }
171
- catch (cause) {
172
- if (!(cause instanceof ConfigurationError))
173
- throw cause;
174
- throw new OperationFailureError(Results.configurationFailure(cause), { cause });
175
- }
176
- }
177
- // {§packet-wire-envelope} — the emissions this packet placed, keyed by their rows' coordinates.
178
- emissionsFor(packet) {
179
- const emissions = this.#emissions.get(packet.sections);
180
- if (emissions === undefined)
181
- throw new Error("emissionsFor: the packet was not built by this PacketBuilder");
182
- return emissions;
183
- }
184
118
  curationBudgetFor(packet) {
185
- const budget = this.#curationBudgets.get(packet.sections);
186
- if (budget === undefined)
187
- throw new Error("curationBudgetFor: the packet was not built by this PacketBuilder");
188
- return budget;
119
+ return this.#allowanceOf(packet).budget;
120
+ }
121
+ #allowanceOf(packet) {
122
+ const allowance = this.#allowances.get(packet.sections);
123
+ if (allowance === undefined)
124
+ throw new Error("the packet was not built by this PacketBuilder");
125
+ return allowance;
189
126
  }
190
127
  // {§context-own-rows-fit} — the packet's rows still carrying a body or a native part, in row order.
191
128
  bodiedRowsOf(packet) {
@@ -196,13 +133,8 @@ export default class PacketBuilder {
196
133
  }
197
134
  // {§packet-stored-shape} — assemble the system/user request before the
198
135
  // provider call; complete the same record with the provider response.
199
- async buildRequestPacket({ initialMessages, recap = "", workspaceId, workerId, loopId, currentTurnSeq, provider, gitStatus, notices = [], transientOpenLogEntryId = null, turnId = null, bodiless, }) {
200
- // {§configuration-repair-path} — a retired packet knob refuses packet construction, never startup.
201
- PacketBuilder.assertConfiguration();
202
- // {§loop-policy-effective-read} Validate active-loop policy before any
203
- // packet assembly or provider spend, independently of its presentation.
204
- await LoopPolicyReader.read(this.#db, loopId);
205
- await CapabilityPolicies.layers(this.#db, workspaceId, loopId);
136
+ async buildRequestPacket({ initialMessages, recap = "", workspaceId, workerId, loopId, currentTurnSeq, provider, gitStatus, notices = [], transientOpenLogEntryId = null, turnId = null, bodiless, omitEmissionHistory = false, }) {
137
+ await CapabilityPolicies.layers(this.#db, workspaceId);
206
138
  const byRole = (role) => initialMessages.filter((m) => m.role === role).map((m) => m.content).join("\n\n");
207
139
  // Resource references are discovered through Turn0, not injected. {§schemes-directory}
208
140
  const system_definition = compactDefinitionTables(byRole("system"));
@@ -219,12 +151,14 @@ export default class PacketBuilder {
219
151
  ...(m.source === null ? { origin: "user" } : { source: m.source }),
220
152
  })).join(",\n")}]`
221
153
  : "[]";
222
- // {§recap}: a non-empty override wins; otherwise read the meta-owned source per packet.
223
- const recapContent = recap.length > 0
154
+ // {§recap}: a non-empty override wins; otherwise read the meta-owned source per packet. The operator's
155
+ // recap lines lead it ({§recap-lines}).
156
+ const recapSource = recap.length > 0
224
157
  ? recap
225
158
  : Paths.defaultRecapTeachingSource === null
226
159
  ? await readFile(Paths.defaultRecap, "utf8")
227
160
  : await readTeachingSource(Paths.defaultRecapTeachingSource);
161
+ const recapContent = PacketWire.renderRecap(recapLines(), recapSource);
228
162
  // {§emission-admission}: the definition remains the complete language authority.
229
163
  const log = await this.#buildLog(workerId, transientOpenLogEntryId, turnId);
230
164
  const failures = await this.buildFailurePointers(loopId, currentTurnSeq);
@@ -232,8 +166,8 @@ export default class PacketBuilder {
232
166
  // {§context-budget} — one room: the provider's input capacity in curation weight, bounding the
233
167
  // whole packet. Nothing here sizes a part of it.
234
168
  const inputCapacity = provider.inputCapacity;
235
- const calibration = inputCapacity === null ? 1 : await TokenCalibration.forModel(this.#db, provider.model);
236
- const curationBudget = this.#loopBudget(loopId, inputCapacity, TokenCalibration.capacity(inputCapacity, calibration));
169
+ const factor = inputCapacity === null ? 1 : await TokenCalibration.forLoop(this.#db, provider.model, loopId);
170
+ const curationBudget = TokenCalibration.capacity(inputCapacity, factor);
237
171
  const budgetReadout = BudgetReadout.draft(curationBudget);
238
172
  // The canonical default order, trust boundary, and cache-locality bias are
239
173
  // specified at {§packet-cache-monotone}. Budget placeholders resolve only
@@ -271,12 +205,84 @@ export default class PacketBuilder {
271
205
  const parentPath = parentRow === undefined ? null : `worker://${parentRow.name}`;
272
206
  // {§fs-namespace} Receipt directories are relative to the workspace project root.
273
207
  const workspaceRow = await this.#db.envelope_get_workspace.get({ id: workspaceId });
274
- const renderedLog = PacketWire.renderLogWithAccounting(log, weighContent, {
208
+ // {§emission-history}: the durable emission row, not its turn's first observation,
209
+ // anchors content replay without moving incoming observations or reasoning receipts.
210
+ const history = Knob.choice("PLURNK_SERVICE_EMISSION_HISTORY", ["none", "latest", "all"]);
211
+ const programs = omitEmissionHistory || history === "none" ? [] : await this.#db.engine_emission_history.all({
212
+ loop_id: loopId, current_turn_seq: currentTurnSeq, latest_only: history === "latest" ? 1 : 0,
213
+ });
214
+ const programsById = new Map(programs.map((program) => [program.id, program]));
215
+ // Trial (#1073): a replayed turn is the home of its NOTEs. Their rows render as the emission row's
216
+ // legend, path and weight each, so the model keeps a handle to retire one; a NOTE of a turn that is
217
+ // not replayed (an earlier loop, a shed history, a reasoning NOTE) renders as an ordinary row.
218
+ const turnKey = (entry) => String(entry.coordinate).split("/").slice(0, 2).join("/");
219
+ const ownNote = (entry) => entry.op === "NOTE" && entry.origin === "model";
220
+ const noteBody = (entry) => {
221
+ const tx = entry.tx;
222
+ return tx !== null && typeof tx === "object" && typeof tx.body === "string" ? tx.body : "";
223
+ };
224
+ // A NOTE row joins the legend only when the replayed program carries its body; a NOTE admitted from
225
+ // reasoning is not in the program and stays an ordinary row.
226
+ const programNotes = new Map();
227
+ for (const entry of log) {
228
+ const program = typeof entry.id === "number" ? programsById.get(entry.id) : undefined;
229
+ if (program !== undefined)
230
+ programNotes.set(turnKey(entry), TurnOps.noteBodies(program.content, JSON.parse(program.executors)));
231
+ }
232
+ const legendNotes = new Set();
233
+ for (const entry of log) {
234
+ if (!ownNote(entry))
235
+ continue;
236
+ const pool = programNotes.get(turnKey(entry));
237
+ const at = pool?.indexOf(noteBody(entry)) ?? -1;
238
+ if (pool === undefined || at === -1)
239
+ continue;
240
+ pool.splice(at, 1);
241
+ legendNotes.add(entry);
242
+ }
243
+ const legend = new Map();
244
+ for (const entry of legendNotes) {
245
+ const key = turnKey(entry);
246
+ if (!legend.has(key))
247
+ legend.set(key, []);
248
+ legend.get(key).push({ path: `log:///${entry.coordinate}/NOTE`, tokens: weighContent(TurnOps.noteFence(noteBody(entry))) });
249
+ }
250
+ const shown = log.filter((entry) => !legendNotes.has(entry));
251
+ const renderedLog = PacketWire.renderLogWithAccounting(shown, weighContent, {
275
252
  projectRoot: workspaceRow?.project_root ?? null,
276
253
  acceptedAttachmentKinds: new Set(acceptedKinds(provider.inputModalities)),
277
254
  ...(bodiless === undefined ? {} : { bodiless }),
255
+ legend,
278
256
  });
279
- const attachmentsWeight = renderedLog.attachments.reduce((sum, { weight }) => sum + weight, 0);
257
+ const nativeRows = new Map(renderedLog.attachments.map((attachment) => [attachment.coordinate, attachment]));
258
+ const nativeParts = [];
259
+ const logSections = [];
260
+ const sectionItems = new Map();
261
+ let items = [];
262
+ let name = "log";
263
+ const flush = () => {
264
+ if (items.length === 0 && logSections.length > 0)
265
+ return;
266
+ logSections.push({ name, slot: "user", header: name === "log" ? "Log" : null, content: items.join("\n\n") });
267
+ sectionItems.set(name, items);
268
+ items = [];
269
+ };
270
+ for (const [index, row] of shown.entries()) {
271
+ if (items.length === 0 && logSections.length > 0)
272
+ name = `log/${row.coordinate}`;
273
+ items.push(renderedLog.records[index]);
274
+ const native = nativeRows.get(String(row.coordinate));
275
+ const program = typeof row.id === "number" ? programsById.get(row.id) : undefined;
276
+ const emission = program === undefined ? undefined : TurnOps.renderHistory(program.content, JSON.parse(program.executors), [...legendNotes].filter((entry) => turnKey(entry) === turnKey(row)).map(noteBody));
277
+ if (native !== undefined || emission) {
278
+ flush();
279
+ if (native !== undefined)
280
+ nativeParts.push({ ...native, section: name });
281
+ if (emission)
282
+ logSections.push({ name: `emission-history/${row.coordinate}`, slot: "assistant", header: null, content: emission });
283
+ }
284
+ }
285
+ flush();
280
286
  const defaults = [
281
287
  { name: "definition", slot: "system", header: null, content: system_definition },
282
288
  // Stable privileged policy follows the definition for prefix-cache locality.
@@ -284,74 +290,64 @@ export default class PacketBuilder {
284
290
  ...(inject !== null ? [{ name: "inject", slot: "system", header: "Operator Notes", content: inject }] : []),
285
291
  // The append-mostly log leads the user slot; nothing volatile precedes it
286
292
  // ({§packet-cache-monotone}).
287
- {
288
- name: "log",
289
- slot: "user",
290
- header: "Log",
291
- content: renderedLog.content,
292
- },
293
- // {§packet-current-turn} — the Worker block opens the status clump below the log: who
294
- // the actor is, whose child it is, and the coordinate this packet's response becomes —
295
- // the one fact the sources cannot state about themselves (which `reasoning://<worker>/L/T` is
296
- // the model's own). It changes every turn, so it never precedes the log.
297
- { name: "worker", slot: "user", header: "Worker", content: JSON.stringify({ path: `worker://${workerName}`, parent: parentPath, loop: loopSeqRow?.sequence ?? loopId, turn: currentTurnSeq }) },
298
- // The per-turn status clump follows the log ({§packet-cache-monotone}).
299
- // child-orientation: what this worker holds live — its child workers and its open streams — under
300
- // the teaching's own word, just above errors. Terse pointers (the path is the actionable address
301
- // the model READs, SENDs to, or KILLs), never advice. {§child-orientation}
302
- { name: "delegation", slot: "user", header: "Delegation", content: PacketWire.renderDelegation(childWorkers, childStreams) },
303
- { name: "errors", slot: "user", header: "Errors", content: PacketWire.renderFailurePointers(failures) },
304
- { name: "notices", slot: "user", header: "Notices", content: PacketWire.renderNotices(notices) },
293
+ ...logSections,
294
+ // The per-turn status clump follows the log ({§packet-cache-monotone}) and runs from ambient
295
+ // state to what this turn owes to feedback on the last one, then the Recap: the nearer the end,
296
+ // the more a section asks of this turn.
305
297
  { name: "git", slot: "user", header: "Git Status", content: PacketWire.renderGit(gitStatus) },
306
298
  // {§context-gauge} — the model's word for curation weight is tokens; this is never provider admission.
307
299
  { name: "budget", slot: "user", header: "Context", content: budgetReadout },
308
- // The messages section closes the status clump as a pointer list of open
309
- // arrivals; bodies arrive through their inbound SEND rows ({§message-arrival}).
300
+ // {§packet-current-turn} — the Worker block names who the actor is, whose child it is, and the
301
+ // coordinate this packet's response becomes — the one fact the sources cannot state about
302
+ // themselves (which `reasoning://<worker>/L/T` is the model's own). It changes every turn, so it
303
+ // never precedes the log.
304
+ { name: "worker", slot: "user", header: "Worker", content: JSON.stringify({ path: `worker://${workerName}`, parent: parentPath, loop: loopSeqRow?.sequence ?? loopId, turn: currentTurnSeq }) },
305
+ // child-orientation: what this worker holds live — its child workers and its open streams — under
306
+ // the teaching's own word. Terse pointers (the path is the actionable address the model READs,
307
+ // SENDs to, or KILLs), never advice. {§child-orientation}
308
+ { name: "delegation", slot: "user", header: "Delegation", content: PacketWire.renderDelegation(childWorkers, childStreams) },
309
+ // The open arrivals this turn owes, as pointers; bodies arrive through their inbound SEND rows
310
+ // ({§message-arrival}).
310
311
  { name: "messages", slot: "user", header: "Open Messages", content: prompt },
312
+ { name: "notices", slot: "user", header: "Notices", content: PacketWire.renderNotices(notices) },
313
+ { name: "errors", slot: "user", header: "Errors", content: PacketWire.renderFailurePointers(failures) },
311
314
  { name: "recap", slot: "user", header: "Recap", content: recapContent },
312
315
  ];
313
316
  // Extension packet control ({§packet-assembly}): trusted schemes rewrite the
314
317
  // default list — add, remove, reorder — in-process, before measurement.
315
318
  let drafts = await this.#schemes.transformSections(defaults, workspaceId);
316
- // {§emission-row} {§packet-wire-envelope} — an emission rides with its row: the rows present in
317
- // the final log section place their emissions, and the packet charges exactly those.
318
- const announced = new Map(renderedLog.emissions.map(({ coordinate, content }) => [coordinate, content]));
319
- const placed = PacketWire.placedEmissions(drafts, announced);
320
- const emissions = new Map(placed.map((coordinate) => [coordinate, announced.get(coordinate)]));
321
- const emissionsWeight = renderedLog.emissions
322
- .filter(({ coordinate }) => emissions.has(coordinate))
323
- .reduce((sum, { weight }) => sum + weight, 0);
319
+ const unchangedLog = logSections.filter((section) => section.slot === "user").every((section) => drafts.some((candidate) => candidate.name === section.name && candidate.content === section.content && candidate.slot === section.slot));
320
+ const attachments = nativeParts.filter(({ section }) => drafts.some(({ name }) => name === section));
321
+ const attachmentsWeight = attachments.reduce((sum, { weight }) => sum + weight, 0);
324
322
  const budgetSection = drafts.find((section) => section.name === "budget");
325
323
  if (budgetSection !== undefined) {
326
- const transformedLog = drafts.find((section) => section.name === "log");
327
- const curationTargets = transformedLog?.content === renderedLog.content
328
- ? renderedLog.curationTargets
329
- : [];
330
- const content = BudgetReadout.resolve(budgetSection.content, (candidate) => {
331
- const candidateDrafts = drafts.map((section) => section === budgetSection ? { ...section, content: candidate } : section);
332
- return weighContent(PacketWire.renderSlot(candidateDrafts, "system"))
333
- + weighContent(PacketWire.renderSlot(candidateDrafts, "user"))
334
- + attachmentsWeight
335
- + emissionsWeight;
336
- }, curationTargets);
337
- drafts = drafts.map((section) => section === budgetSection ? { ...section, content } : section);
324
+ const curationTargets = unchangedLog ? renderedLog.curationTargets : [];
325
+ // {§context-pressure-notice} — the pressure notice follows whatever the notices section holds.
326
+ const noticesSection = drafts.find((section) => section.name === "notices");
327
+ const withReadout = (gauge, notice) => drafts.map((section) => {
328
+ if (section === budgetSection)
329
+ return { ...section, content: gauge };
330
+ if (section !== noticesSection || notice === null)
331
+ return section;
332
+ return { ...section, content: [section.content, PacketWire.renderNotices([notice])].filter((part) => part.length > 0).join("\n") };
333
+ });
334
+ const readout = BudgetReadout.resolve(budgetSection.content, (gauge, notice) => PacketWire.packetToWireMessages({ sections: withReadout(gauge, notice) })
335
+ .reduce((sum, { content }) => sum + weighContent(content), attachmentsWeight), curationTargets);
336
+ drafts = withReadout(readout.gauge, readout.notice);
338
337
  }
339
- // Core alone turns validated drafts into measured durable sections. {§packet-items} — the
340
- // log section's items are its records when no transformer touched it; any other section,
341
- // or a transformed log, is one item.
338
+ // {§packet-items}: unchanged log segments retain their content-addressed records.
342
339
  const sections = drafts.map((section) => ({
343
340
  ...section,
344
341
  weight: weighContent(PacketWire.renderSection(section)),
345
- items: section.name === "log" && section.content === renderedLog.content ? renderedLog.records : [section.content],
342
+ items: sectionItems.get(section.name)?.join("\n\n") === section.content ? sectionItems.get(section.name) : [section.content],
346
343
  }));
347
- const renderWeight = weighContent(PacketWire.renderSlot(sections, "system")) + weighContent(PacketWire.renderSlot(sections, "user"));
348
- // {§packet-attachment-parts} — pictures weigh in the packet like everything else it carries,
349
- // and so do the emissions it places ({§emission-row}).
350
- const packet = { weight: renderWeight + attachmentsWeight + emissionsWeight, sections, attributions: [], attachments: [...renderedLog.attachments] };
351
- this.#curationBudgets.set(packet.sections, curationBudget);
352
- this.#emissions.set(packet.sections, emissions);
344
+ const renderWeight = PacketWire.packetToWireMessages({ sections })
345
+ .reduce((sum, { content }) => sum + weighContent(content), 0);
346
+ // {§packet-attachment-parts}: all text is already in the ordered messages.
347
+ const packet = { weight: renderWeight + attachmentsWeight, sections, attributions: [], attachments };
348
+ this.#allowances.set(packet.sections, { budget: curationBudget, factor });
353
349
  // {§context-own-rows-fit} — a transformed log is one item the wall cannot take row by row.
354
- this.#bodiedRows.set(packet.sections, drafts.find((section) => section.name === "log")?.content === renderedLog.content ? renderedLog.bodied : []);
350
+ this.#bodiedRows.set(packet.sections, unchangedLog ? renderedLog.bodied : []);
355
351
  this.#streamObservations.set(packet.sections, openChannels);
356
352
  return packet;
357
353
  }
@@ -409,17 +405,6 @@ export default class PacketBuilder {
409
405
  .map(({ pathname, content }) => ({ pathname, content })));
410
406
  return out.toSorted((left, right) => left.pathname.localeCompare(right.pathname));
411
407
  }
412
- // {§context-budget} — the room never shrinks within a loop: the budget is the greater of the
413
- // calibrated capacity and the loop's high-water for the same input capacity, so a refined conversion
414
- // can enlarge the room but never turns a packet the model already answered into an overflow.
415
- #loopBudget(loopId, inputCapacity, calibrated) {
416
- if (inputCapacity === null || calibrated === null)
417
- return null;
418
- const prior = this.#loopBudgets.get(loopId);
419
- const budget = prior !== undefined && prior.inputCapacity === inputCapacity ? Math.max(prior.budget, calibrated) : calibrated;
420
- this.#loopBudgets.set(loopId, { inputCapacity, budget });
421
- return budget;
422
- }
423
408
  // {§context-over-budget-row} — measurement never mutates visibility; an over-budget packet is a row
424
409
  // and a request, never a silent cut.
425
410
  curationOverflow(packet) {
@@ -431,19 +416,36 @@ export default class PacketBuilder {
431
416
  return null;
432
417
  return { weight, budget, excess: weight - budget };
433
418
  }
434
- // {§context-wall} — the packet's tokens through the loop's conversion (the budget is the capacity
435
- // over the factor, so tokens are weight × capacity ÷ budget) against the provider's input wall;
436
- // null without a wall or a budget: an unknown window has no wall.
419
+ // {§context-wall-measure} — the estimate: the packet's weight through its own calibration factor against
420
+ // the provider's input wall; null without a wall or a budget: an unknown window has no wall.
437
421
  windowOverflow(packet, provider) {
438
- const budget = this.curationBudgetFor(packet);
439
- if (budget === null || provider.inputCapacity === null || provider.inputWall === null)
422
+ const { budget, factor } = this.#allowanceOf(packet);
423
+ if (budget === null || provider.inputWall === null)
440
424
  return null;
441
- const tokens = Math.ceil(packet.weight * provider.inputCapacity / budget);
425
+ const tokens = Math.ceil(packet.weight * factor);
442
426
  if (tokens <= provider.inputWall)
443
427
  return null;
444
- const excessWeight = packet.weight - Math.floor(provider.inputWall * budget / provider.inputCapacity);
428
+ const excessWeight = packet.weight - Math.floor(provider.inputWall / factor);
445
429
  return { tokens, budget, wall: provider.inputWall, excess: tokens - provider.inputWall, excessWeight };
446
430
  }
431
+ // {§context-wall-measure} — the provider's exact refusal of the wire request, in the packet's own terms:
432
+ // the excess it names, shed at the ratio it measured for this packet. Null unless the provider refused.
433
+ exactOverflow(packet, capacity) {
434
+ if (capacity.decision !== "reject")
435
+ return null;
436
+ const { prompt, inputWall } = capacity;
437
+ // {§provider-capacity-admission}: only an exact count over a known wall refuses.
438
+ if (prompt.kind !== "exact" || inputWall === null)
439
+ throw new Error(`a capacity refusal measured ${prompt.kind} against ${inputWall} carries no exact excess`);
440
+ const excess = prompt.tokens - inputWall;
441
+ return {
442
+ tokens: prompt.tokens,
443
+ budget: this.curationBudgetFor(packet),
444
+ wall: inputWall,
445
+ excess,
446
+ excessWeight: Math.ceil(excess * packet.weight / prompt.tokens),
447
+ };
448
+ }
447
449
  // Every prior-turn operation failure is durable before packet assembly.
448
450
  // The model-facing Errors section is only a terse projection of those rows;
449
451
  // it never reconstructs failure truth from an in-memory event.