@plurnk/plurnk-service 1.26.0 → 1.28.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 (293) hide show
  1. package/.env.defaults +16 -25
  2. package/SPEC.md +338 -263
  3. package/dist/build-info.json +1 -1
  4. package/dist/content/body-preview.d.ts +1 -0
  5. package/dist/content/body-preview.d.ts.map +1 -1
  6. package/dist/content/body-preview.js +7 -0
  7. package/dist/content/body-preview.js.map +1 -1
  8. package/dist/content/byte-view.d.ts +19 -2
  9. package/dist/content/byte-view.d.ts.map +1 -1
  10. package/dist/content/byte-view.js +67 -14
  11. package/dist/content/byte-view.js.map +1 -1
  12. package/dist/content/edit-receipt.js +1 -1
  13. package/dist/content/edit-receipt.js.map +1 -1
  14. package/dist/content/line-marker.d.ts +1 -0
  15. package/dist/content/line-marker.d.ts.map +1 -1
  16. package/dist/content/line-marker.js +6 -1
  17. package/dist/content/line-marker.js.map +1 -1
  18. package/dist/content/line-selection.d.ts +3 -1
  19. package/dist/content/line-selection.d.ts.map +1 -1
  20. package/dist/content/line-selection.js +27 -3
  21. package/dist/content/line-selection.js.map +1 -1
  22. package/dist/content/matcher.d.ts +9 -14
  23. package/dist/content/matcher.d.ts.map +1 -1
  24. package/dist/content/matcher.js +51 -45
  25. package/dist/content/matcher.js.map +1 -1
  26. package/dist/content/pattern-edits.d.ts +7 -26
  27. package/dist/content/pattern-edits.d.ts.map +1 -1
  28. package/dist/content/pattern-edits.js +54 -91
  29. package/dist/content/pattern-edits.js.map +1 -1
  30. package/dist/content/read-projector.d.ts +2 -1
  31. package/dist/content/read-projector.d.ts.map +1 -1
  32. package/dist/content/read-projector.js +42 -10
  33. package/dist/content/read-projector.js.map +1 -1
  34. package/dist/content/read-resolve.d.ts.map +1 -1
  35. package/dist/content/read-resolve.js +7 -4
  36. package/dist/content/read-resolve.js.map +1 -1
  37. package/dist/core/AdmittedTurnExecutor.d.ts +3 -1
  38. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
  39. package/dist/core/AdmittedTurnExecutor.js +22 -7
  40. package/dist/core/AdmittedTurnExecutor.js.map +1 -1
  41. package/dist/core/BudgetReadout.d.ts +4 -4
  42. package/dist/core/BudgetReadout.d.ts.map +1 -1
  43. package/dist/core/BudgetReadout.js +26 -41
  44. package/dist/core/BudgetReadout.js.map +1 -1
  45. package/dist/core/ChannelWrite.d.ts +2 -3
  46. package/dist/core/ChannelWrite.d.ts.map +1 -1
  47. package/dist/core/ChannelWrite.js +21 -22
  48. package/dist/core/ChannelWrite.js.map +1 -1
  49. package/dist/core/ChannelWrite.sql +26 -0
  50. package/dist/core/ContextFit.d.ts +26 -0
  51. package/dist/core/ContextFit.d.ts.map +1 -0
  52. package/dist/core/ContextFit.js +56 -0
  53. package/dist/core/ContextFit.js.map +1 -0
  54. package/dist/core/DataStatementRunner.d.ts.map +1 -1
  55. package/dist/core/DataStatementRunner.js +1 -0
  56. package/dist/core/DataStatementRunner.js.map +1 -1
  57. package/dist/core/Dispatcher.d.ts +15 -2
  58. package/dist/core/Dispatcher.d.ts.map +1 -1
  59. package/dist/core/Dispatcher.js +148 -16
  60. package/dist/core/Dispatcher.js.map +1 -1
  61. package/dist/core/EditMutations.d.ts +5 -5
  62. package/dist/core/EditMutations.d.ts.map +1 -1
  63. package/dist/core/EditMutations.js +44 -50
  64. package/dist/core/EditMutations.js.map +1 -1
  65. package/dist/core/EditSequence.js +2 -2
  66. package/dist/core/EditSequence.js.map +1 -1
  67. package/dist/core/EmissionHead.d.ts +8 -0
  68. package/dist/core/EmissionHead.d.ts.map +1 -0
  69. package/dist/core/EmissionHead.js +29 -0
  70. package/dist/core/EmissionHead.js.map +1 -0
  71. package/dist/core/Engine.d.ts +1 -0
  72. package/dist/core/Engine.d.ts.map +1 -1
  73. package/dist/core/Engine.js +3 -0
  74. package/dist/core/Engine.js.map +1 -1
  75. package/dist/core/InferenceCall.js +2 -2
  76. package/dist/core/InferenceCall.js.map +1 -1
  77. package/dist/core/InferenceCall.sql +1 -0
  78. package/dist/core/LiveSubscription.d.ts +20 -0
  79. package/dist/core/LiveSubscription.d.ts.map +1 -0
  80. package/dist/core/LiveSubscription.js +68 -0
  81. package/dist/core/LiveSubscription.js.map +1 -0
  82. package/dist/core/LiveSubscriptions.d.ts +1 -0
  83. package/dist/core/LiveSubscriptions.d.ts.map +1 -1
  84. package/dist/core/LiveSubscriptions.js +8 -0
  85. package/dist/core/LiveSubscriptions.js.map +1 -1
  86. package/dist/core/LogBody.js +1 -1
  87. package/dist/core/LogBody.js.map +1 -1
  88. package/dist/core/LogEntryProjection.d.ts +1 -0
  89. package/dist/core/LogEntryProjection.d.ts.map +1 -1
  90. package/dist/core/LogEntryProjection.js +9 -0
  91. package/dist/core/LogEntryProjection.js.map +1 -1
  92. package/dist/core/LogWriter.d.ts +42 -0
  93. package/dist/core/LogWriter.d.ts.map +1 -1
  94. package/dist/core/LogWriter.js +11 -5
  95. package/dist/core/LogWriter.js.map +1 -1
  96. package/dist/core/LoopDriver.js +2 -1
  97. package/dist/core/LoopDriver.js.map +1 -1
  98. package/dist/core/LoopLifecycle.d.ts +2 -2
  99. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  100. package/dist/core/LoopLifecycle.js +2 -4
  101. package/dist/core/LoopLifecycle.js.map +1 -1
  102. package/dist/core/LoopLifecycle.sql +1 -6
  103. package/dist/core/MutationEffects.d.ts +1 -3
  104. package/dist/core/MutationEffects.d.ts.map +1 -1
  105. package/dist/core/MutationEffects.js +2 -1
  106. package/dist/core/MutationEffects.js.map +1 -1
  107. package/dist/core/PacketBuilder.d.ts +17 -4
  108. package/dist/core/PacketBuilder.d.ts.map +1 -1
  109. package/dist/core/PacketBuilder.js +80 -120
  110. package/dist/core/PacketBuilder.js.map +1 -1
  111. package/dist/core/PacketBuilder.sql +4 -12
  112. package/dist/core/PatternSelection.d.ts +5 -10
  113. package/dist/core/PatternSelection.d.ts.map +1 -1
  114. package/dist/core/PatternSelection.js +9 -16
  115. package/dist/core/PatternSelection.js.map +1 -1
  116. package/dist/core/ResourceMutations.d.ts +2 -4
  117. package/dist/core/ResourceMutations.d.ts.map +1 -1
  118. package/dist/core/ResourceMutations.js +2 -5
  119. package/dist/core/ResourceMutations.js.map +1 -1
  120. package/dist/core/ResourceSelector.d.ts +2 -2
  121. package/dist/core/ResourceSelector.d.ts.map +1 -1
  122. package/dist/core/ResourceSelector.js +64 -33
  123. package/dist/core/ResourceSelector.js.map +1 -1
  124. package/dist/core/ResourceTransfers.d.ts +2 -4
  125. package/dist/core/ResourceTransfers.d.ts.map +1 -1
  126. package/dist/core/ResourceTransfers.js +74 -50
  127. package/dist/core/ResourceTransfers.js.map +1 -1
  128. package/dist/core/SchemeRegistry.d.ts +1 -0
  129. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  130. package/dist/core/SchemeRegistry.js +11 -9
  131. package/dist/core/SchemeRegistry.js.map +1 -1
  132. package/dist/core/ServiceTeardown.d.ts +3 -2
  133. package/dist/core/ServiceTeardown.d.ts.map +1 -1
  134. package/dist/core/ServiceTeardown.js +17 -8
  135. package/dist/core/ServiceTeardown.js.map +1 -1
  136. package/dist/core/StopDeadline.d.ts +5 -0
  137. package/dist/core/StopDeadline.d.ts.map +1 -0
  138. package/dist/core/StopDeadline.js +20 -0
  139. package/dist/core/StopDeadline.js.map +1 -0
  140. package/dist/core/StrikeRail.d.ts.map +1 -1
  141. package/dist/core/StrikeRail.js +5 -1
  142. package/dist/core/StrikeRail.js.map +1 -1
  143. package/dist/core/ToolResources.d.ts.map +1 -1
  144. package/dist/core/ToolResources.js +11 -2
  145. package/dist/core/ToolResources.js.map +1 -1
  146. package/dist/core/TurnDispositionHandler.d.ts +4 -2
  147. package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
  148. package/dist/core/TurnDispositionHandler.js +24 -6
  149. package/dist/core/TurnDispositionHandler.js.map +1 -1
  150. package/dist/core/TurnMaterialization.d.ts +6 -2
  151. package/dist/core/TurnMaterialization.d.ts.map +1 -1
  152. package/dist/core/TurnMaterialization.js +64 -16
  153. package/dist/core/TurnMaterialization.js.map +1 -1
  154. package/dist/core/TurnOps.js +7 -7
  155. package/dist/core/TurnOps.js.map +1 -1
  156. package/dist/core/TurnRunner.d.ts +1 -0
  157. package/dist/core/TurnRunner.d.ts.map +1 -1
  158. package/dist/core/TurnRunner.js +155 -160
  159. package/dist/core/TurnRunner.js.map +1 -1
  160. package/dist/core/TurnRunner.sql +2 -2
  161. package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
  162. package/dist/core/caps/DbSubscriptionCaps.js +13 -19
  163. package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
  164. package/dist/core/content-hash.d.ts +1 -1
  165. package/dist/core/content-hash.d.ts.map +1 -1
  166. package/dist/core/content-hash.js.map +1 -1
  167. package/dist/core/env-catalog.js +2 -2
  168. package/dist/core/env-catalog.js.map +1 -1
  169. package/dist/core/fork.sql +4 -10
  170. package/dist/core/git-env.d.ts +1 -1
  171. package/dist/core/git-env.d.ts.map +1 -1
  172. package/dist/core/git-env.js +19 -12
  173. package/dist/core/git-env.js.map +1 -1
  174. package/dist/core/git-membership.d.ts.map +1 -1
  175. package/dist/core/git-membership.js +11 -5
  176. package/dist/core/git-membership.js.map +1 -1
  177. package/dist/core/git-state.js +1 -1
  178. package/dist/core/git-state.js.map +1 -1
  179. package/dist/core/mutation-types.d.ts +6 -4
  180. package/dist/core/mutation-types.d.ts.map +1 -1
  181. package/dist/core/operation-target-groups.d.ts +1 -1
  182. package/dist/core/operation-target-groups.d.ts.map +1 -1
  183. package/dist/core/operation-target-groups.js +27 -5
  184. package/dist/core/operation-target-groups.js.map +1 -1
  185. package/dist/core/packet-wire.d.ts +80 -10
  186. package/dist/core/packet-wire.d.ts.map +1 -1
  187. package/dist/core/packet-wire.js +211 -227
  188. package/dist/core/packet-wire.js.map +1 -1
  189. package/dist/core/provider-accounting.d.ts +1 -1
  190. package/dist/core/provider-accounting.d.ts.map +1 -1
  191. package/dist/core/provider-accounting.js +2 -1
  192. package/dist/core/provider-accounting.js.map +1 -1
  193. package/dist/digest/Digest.d.ts.map +1 -1
  194. package/dist/digest/Digest.js +3 -2
  195. package/dist/digest/Digest.js.map +1 -1
  196. package/dist/digest/DigestEvidence.d.ts +1 -0
  197. package/dist/digest/DigestEvidence.d.ts.map +1 -1
  198. package/dist/digest/DigestEvidence.js +6 -0
  199. package/dist/digest/DigestEvidence.js.map +1 -1
  200. package/dist/digest/DigestRender.d.ts +1 -0
  201. package/dist/digest/DigestRender.d.ts.map +1 -1
  202. package/dist/digest/DigestRender.js +107 -48
  203. package/dist/digest/DigestRender.js.map +1 -1
  204. package/dist/digest/DigestRequiem.js +4 -4
  205. package/dist/digest/DigestRequiem.js.map +1 -1
  206. package/dist/digest/digest-rows.d.ts +8 -0
  207. package/dist/digest/digest-rows.d.ts.map +1 -1
  208. package/dist/digest/digest-rows.js.map +1 -1
  209. package/dist/digest/digest.sql +20 -2
  210. package/dist/schemes/Exec.d.ts.map +1 -1
  211. package/dist/schemes/Exec.js +28 -27
  212. package/dist/schemes/Exec.js.map +1 -1
  213. package/dist/schemes/File.d.ts.map +1 -1
  214. package/dist/schemes/File.js +1 -2
  215. package/dist/schemes/File.js.map +1 -1
  216. package/dist/schemes/Log.d.ts.map +1 -1
  217. package/dist/schemes/Log.js +4 -17
  218. package/dist/schemes/Log.js.map +1 -1
  219. package/dist/schemes/TurnSource.js +2 -2
  220. package/dist/schemes/TurnSource.js.map +1 -1
  221. package/dist/schemes/_derivation-use.d.ts +7 -0
  222. package/dist/schemes/_derivation-use.d.ts.map +1 -0
  223. package/dist/schemes/_derivation-use.js +40 -0
  224. package/dist/schemes/_derivation-use.js.map +1 -0
  225. package/dist/schemes/_entry-crud.d.ts +6 -1
  226. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  227. package/dist/schemes/_entry-crud.js.map +1 -1
  228. package/dist/schemes/_entry-find.d.ts.map +1 -1
  229. package/dist/schemes/_entry-find.js +15 -49
  230. package/dist/schemes/_entry-find.js.map +1 -1
  231. package/dist/schemes/_entry-find.sql +0 -11
  232. package/dist/schemes/_entry-fts.d.ts.map +1 -1
  233. package/dist/schemes/_entry-fts.js +9 -3
  234. package/dist/schemes/_entry-fts.js.map +1 -1
  235. package/dist/schemes/_entry-fts.sql +14 -8
  236. package/dist/schemes/_entry-graph.d.ts +5 -8
  237. package/dist/schemes/_entry-graph.d.ts.map +1 -1
  238. package/dist/schemes/_entry-graph.js +33 -72
  239. package/dist/schemes/_entry-graph.js.map +1 -1
  240. package/dist/schemes/_entry-graph.sql +30 -48
  241. package/dist/schemes/_entry-manifest.d.ts +5 -0
  242. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  243. package/dist/schemes/_entry-manifest.js +5 -0
  244. package/dist/schemes/_entry-manifest.js.map +1 -1
  245. package/dist/schemes/_entry-ops.d.ts +1 -1
  246. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  247. package/dist/schemes/_entry-ops.js +4 -11
  248. package/dist/schemes/_entry-ops.js.map +1 -1
  249. package/dist/schemes/_search-index.d.ts +10 -0
  250. package/dist/schemes/_search-index.d.ts.map +1 -1
  251. package/dist/schemes/_search-index.js +33 -1
  252. package/dist/schemes/_search-index.js.map +1 -1
  253. package/dist/schemes/exec-lifetime.d.ts.map +1 -1
  254. package/dist/schemes/exec-lifetime.js +1 -2
  255. package/dist/schemes/exec-lifetime.js.map +1 -1
  256. package/dist/server/Daemon.d.ts +2 -1
  257. package/dist/server/Daemon.d.ts.map +1 -1
  258. package/dist/server/Daemon.js +31 -35
  259. package/dist/server/Daemon.js.map +1 -1
  260. package/dist/server/DrainSupervisor.d.ts +2 -1
  261. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  262. package/dist/server/DrainSupervisor.js +37 -56
  263. package/dist/server/DrainSupervisor.js.map +1 -1
  264. package/dist/server/Functionality.d.ts +1 -1
  265. package/dist/server/Functionality.d.ts.map +1 -1
  266. package/dist/server/Functionality.js +24 -11
  267. package/dist/server/Functionality.js.map +1 -1
  268. package/dist/server/FunctionalityManager.js +2 -2
  269. package/dist/server/FunctionalityManager.js.map +1 -1
  270. package/dist/server/Retention.d.ts.map +1 -1
  271. package/dist/server/Retention.js +7 -3
  272. package/dist/server/Retention.js.map +1 -1
  273. package/dist/server/drain.sql +0 -6
  274. package/dist/server/seam-loop.sql +1 -1
  275. package/dist/service.js +1 -1
  276. package/dist/service.js.map +1 -1
  277. package/docs/env.md +4 -3
  278. package/migrations/013_graph_regions.sql +32 -0
  279. package/migrations/014_stream_timing.sql +4 -0
  280. package/migrations/015_request_evidence.sql +4 -0
  281. package/package.json +34 -34
  282. package/dist/core/KnownToxins.d.ts +0 -4
  283. package/dist/core/KnownToxins.d.ts.map +0 -1
  284. package/dist/core/KnownToxins.js +0 -22
  285. package/dist/core/KnownToxins.js.map +0 -1
  286. package/dist/core/ReasoningView.d.ts +0 -12
  287. package/dist/core/ReasoningView.d.ts.map +0 -1
  288. package/dist/core/ReasoningView.js +0 -40
  289. package/dist/core/ReasoningView.js.map +0 -1
  290. package/dist/server/exec-poll-backoff.d.ts +0 -2
  291. package/dist/server/exec-poll-backoff.d.ts.map +0 -1
  292. package/dist/server/exec-poll-backoff.js +0 -6
  293. package/dist/server/exec-poll-backoff.js.map +0 -1
@@ -2,13 +2,15 @@ import { TurnDisposition } from "@plurnk/plurnk-contracts";
2
2
  import { relative, sep } from "node:path";
3
3
  import { Problems, Validator } from "@plurnk/plurnk-contracts";
4
4
  import { TextCoordinates } from "@plurnk/plurnk-mimetypes";
5
+ import BodyPreview from "../content/body-preview.js";
5
6
  import { renderTarget } from "./plurnk-uri.js";
6
7
  import GitState from "./git-state.js";
7
8
  import LogBody from "./LogBody.js";
8
9
  import LogEntryProjection from "./LogEntryProjection.js";
9
10
  import LogVisibility from "./LogVisibility.js";
10
- import BodyPreview from "../content/body-preview.js";
11
11
  import ScopeFormat from "../content/scope-format.js";
12
+ import PatternEdits from "../content/pattern-edits.js";
13
+ import { Results as SchemeResults } from "@plurnk/plurnk-schemes";
12
14
  import { assertEditReceipt, assertResourceEffects, LineAnchors, } from "../content/index.js";
13
15
  // {§packet-attachment-parts} — the attachment kinds and their readout weights live in one table.
14
16
  import { audioWeight, imageWeight, pdfWeight } from "./attachments.js";
@@ -45,8 +47,7 @@ export default class PacketWire {
45
47
  return pointers.length === 0 ? "" : `[${pointers.join(",\n")}]`;
46
48
  }
47
49
  // Non-terminal model-facing observations are deliberately separate from
48
- // operation failures. Producer messages are normalized and bounded by the
49
- // shared preview limit; typed positions remain legible.
50
+ // operation failures. Producer messages are normalized; typed positions remain legible.
50
51
  static renderNotices(notices) {
51
52
  const observations = Array.isArray(notices) ? notices : [];
52
53
  return observations.map((notice) => {
@@ -54,9 +55,7 @@ export default class PacketWire {
54
55
  const rawMessage = typeof notice.message === "string"
55
56
  ? notice.message.replace(/\s+/g, " ").trim()
56
57
  : "";
57
- const message = rawMessage.length > 0
58
- ? PacketWire.#preview(rawMessage).text
59
- : "";
58
+ const message = rawMessage;
60
59
  const position = notice.position?.type === "content-offset"
61
60
  ? ` @ ${String(notice.position.line)}:${String(notice.position.column)}`
62
61
  : "";
@@ -91,12 +90,12 @@ export default class PacketWire {
91
90
  static renderLog(entries, weighContent, options = {}) {
92
91
  return PacketWire.renderLogWithAccounting(entries, weighContent, options).content;
93
92
  }
94
- // {§tokenomics-pressure-inventory} — the wire row and its reclaimable-body
95
- // accounting come from one render pass; packet assembly never re-parses its text.
93
+ // {§context-gauge} — the wire row and its reclaimable-body accounting come from one render
94
+ // pass; packet assembly never re-parses its text.
96
95
  static renderLogWithAccounting(entries, weighContent, options = {}) {
97
96
  const log = Array.isArray(entries) ? entries : [];
98
97
  if (log.length === 0)
99
- return { content: "", records: [], curationTargets: [], attachments: [], emissions: [], unadmittedOutput: [], newOverflow: false };
98
+ return { content: "", records: [], curationTargets: [], attachments: [], emissions: [], bodied: [] };
100
99
  const rows = PacketWire.#renderLogEntries(log, weighContent, options);
101
100
  const records = rows.map(({ content }) => content);
102
101
  return {
@@ -105,8 +104,7 @@ export default class PacketWire {
105
104
  curationTargets: rows.flatMap(({ curationTarget }) => curationTarget === null ? [] : [curationTarget]),
106
105
  attachments: rows.flatMap(({ attachment }) => attachment === null ? [] : [attachment]),
107
106
  emissions: rows.flatMap(({ emission }) => emission === null ? [] : [emission]),
108
- unadmittedOutput: rows.flatMap(({ unadmittedOutput }) => unadmittedOutput === null ? [] : [unadmittedOutput]),
109
- newOverflow: rows.some(({ newOverflow }) => newOverflow),
107
+ bodied: rows.flatMap(({ bodied }) => bodied === null ? [] : [bodied]),
110
108
  };
111
109
  }
112
110
  // Read one section's content by name off a packet (Engine's or re-parsed).
@@ -330,10 +328,52 @@ export default class PacketWire {
330
328
  throw new TypeError("A packet log row requires an addressable coordinate.");
331
329
  return `log:///${coordinate}/${leaf}`;
332
330
  }
333
- // One preview function for every bounded model-facing projection. Lines
334
- // protect ordinary documents and Unicode characters protect a single-line
335
- // bomb. Once a physical line is complete, a character cut retreats to that
336
- // line boundary rather than exposing a partial coordinate prefix.
331
+ static #visibleBody(entry, body) {
332
+ const trimmed = LogVisibility.parse(entry.folded ?? LogVisibility.OPEN);
333
+ const folded = LogVisibility.combine(LogVisibility.parse(entry.initial_folded ?? LogVisibility.OPEN), trimmed);
334
+ const lines = TextCoordinates.logicalLines(body.content);
335
+ const totalLines = lines.length;
336
+ const clipped = LogVisibility.clipped(folded, totalLines);
337
+ const ordinals = LogVisibility.visibleLineOrdinals(clipped, totalLines);
338
+ const readableOrdinals = LogVisibility.visibleLineOrdinals(trimmed, totalLines);
339
+ const select = (selected) => selected.map((ordinal) => {
340
+ const line = lines[ordinal - 1];
341
+ return body.content.slice(line.start, line.end);
342
+ }).join("");
343
+ return {
344
+ content: select(ordinals),
345
+ ordinals,
346
+ readableContent: select(readableOrdinals),
347
+ readableOrdinals,
348
+ folded: clipped,
349
+ trimmed: LogVisibility.clipped(trimmed, totalLines),
350
+ totalLines,
351
+ fullyFolded: LogVisibility.fullyFolded(clipped, totalLines),
352
+ };
353
+ }
354
+ // {§message-arrival} — an inbound SEND row: harness-published, the sender's statement as its
355
+ // sent side. {§message-causal-source}: a `source` names the actor; absence is the owner.
356
+ static isArrival(e) {
357
+ if (e.op !== "SEND" || e.origin !== "_plurnk")
358
+ return false;
359
+ const attrs = typeof e.attrs === "string" ? JSON.parse(e.attrs) : e.attrs;
360
+ return attrs !== null && typeof attrs === "object" && attrs.kind === "message";
361
+ }
362
+ // {§markerless-first-page} — a body the model did not author or ask for exactly takes its first page in
363
+ // the packet: not the model's own row, not a retrieval (paged at its source), not an emission row,
364
+ // and not the operator's message, which keeps its own rule ({§message-projection}).
365
+ static #receivedBody(e, op) {
366
+ if (e.origin === "model" || op === "READ" || op === "FIND" || LogEntryProjection.isEmission(e))
367
+ return false;
368
+ if (PacketWire.isArrival(e)) {
369
+ const source = typeof e.source === "string" ? e.source : null;
370
+ return source !== null && source.startsWith("worker://");
371
+ }
372
+ return true;
373
+ }
374
+ // One preview function for every bounded model-facing projection. Lines protect ordinary
375
+ // documents and Unicode characters protect a single-line bomb. Once a physical line is complete,
376
+ // a character cut retreats to that line boundary rather than exposing a partial coordinate prefix.
337
377
  static #preview(text) {
338
378
  const coordinates = new TextCoordinates(text);
339
379
  const physicalLines = coordinates.logicalLines();
@@ -376,19 +416,16 @@ export default class PacketWire {
376
416
  const runs = [];
377
417
  for (const ordinal of selectedOrdinals) {
378
418
  const previous = runs.at(-1);
379
- if (previous === undefined || ordinal !== previous[1] + 1) {
419
+ if (previous === undefined || ordinal !== previous[1] + 1)
380
420
  runs.push([ordinal, ordinal]);
381
- }
382
- else {
421
+ else
383
422
  previous[1] = ordinal;
384
- }
385
423
  }
386
424
  const selected = runs.map(([start, finish]) => ScopeFormat.lines(start, finish)).join(",");
387
425
  return `${selected} of ${ScopeFormat.count("line", TextCoordinates.logicalLines(completeContent).length)}`;
388
426
  }
389
427
  const local = coordinates.regionFromOffsets(0, end);
390
- const complete = new TextCoordinates(completeContent)
391
- .regionFromOffsets(0, completeContent.length);
428
+ const complete = new TextCoordinates(completeContent).regionFromOffsets(0, completeContent.length);
392
429
  if (local === null || complete === null) {
393
430
  throw new Error("a sparse character-bound chunk must resolve to exact text coordinates");
394
431
  }
@@ -397,140 +434,7 @@ export default class PacketWire {
397
434
  if (startLine === undefined || endLine === undefined) {
398
435
  throw new Error("a sparse character-bound chunk must map to canonical body lines");
399
436
  }
400
- return `${ScopeFormat.region({
401
- ...local,
402
- startLine,
403
- endLine,
404
- })} of ${ScopeFormat.region(complete)}`;
405
- }
406
- static #promptProjection(body, budget, weighContent, render = (content) => PacketWire.#renderContentBody(content, body.startLine, null)) {
407
- const weightAt = (end) => weighContent(render(body.content.slice(0, end)));
408
- if (weightAt(body.content.length) <= budget) {
409
- return { text: body.content, cut: false, chunk: null };
410
- }
411
- if (budget <= 0)
412
- return { text: "", cut: true, chunk: null };
413
- const coordinates = new TextCoordinates(body.content);
414
- const lines = coordinates.logicalLines();
415
- const completeLineEnds = lines
416
- .filter((line) => line.separator.length > 0 && line.end < body.content.length)
417
- .map((line) => line.end);
418
- let low = 0;
419
- let high = completeLineEnds.length;
420
- while (low < high) {
421
- const middle = Math.floor((low + high) / 2);
422
- if (weightAt(completeLineEnds[middle]) <= budget)
423
- low = middle + 1;
424
- else
425
- high = middle;
426
- }
427
- const completeLineEnd = low === 0 ? 0 : completeLineEnds[low - 1];
428
- if (completeLineEnd > 0) {
429
- return {
430
- text: body.content.slice(0, completeLineEnd),
431
- cut: true,
432
- chunk: PacketWire.#chunk(coordinates, lines, completeLineEnd, body.content.length),
433
- };
434
- }
435
- const firstLineEnd = lines[0]?.contentEnd ?? body.content.length;
436
- const offsets = [0];
437
- let offset = 0;
438
- for (const codePoint of body.content.slice(0, firstLineEnd)) {
439
- offset += codePoint.length;
440
- offsets.push(offset);
441
- }
442
- low = 0;
443
- high = offsets.length;
444
- while (low < high) {
445
- const middle = Math.floor((low + high) / 2);
446
- if (weightAt(offsets[middle]) <= budget)
447
- low = middle + 1;
448
- else
449
- high = middle;
450
- }
451
- const characterEnd = low === 0 ? 0 : offsets[low - 1];
452
- if (characterEnd === 0)
453
- return { text: "", cut: true, chunk: null };
454
- return {
455
- text: body.content.slice(0, characterEnd),
456
- cut: true,
457
- chunk: PacketWire.#chunk(coordinates, lines, characterEnd, body.content.length),
458
- };
459
- }
460
- static #visibleBody(entry, body) {
461
- const trimmed = LogVisibility.parse(entry.folded ?? LogVisibility.OPEN);
462
- const folded = LogVisibility.combine(LogVisibility.parse(entry.initial_folded ?? LogVisibility.OPEN), trimmed);
463
- const lines = TextCoordinates.logicalLines(body.content);
464
- const totalLines = lines.length;
465
- const clipped = LogVisibility.clipped(folded, totalLines);
466
- const ordinals = LogVisibility.visibleLineOrdinals(clipped, totalLines);
467
- const readableOrdinals = LogVisibility.visibleLineOrdinals(trimmed, totalLines);
468
- const select = (selected) => selected.map((ordinal) => {
469
- const line = lines[ordinal - 1];
470
- return body.content.slice(line.start, line.end);
471
- }).join("");
472
- return {
473
- content: select(ordinals),
474
- ordinals,
475
- readableContent: select(readableOrdinals),
476
- readableOrdinals,
477
- folded: clipped,
478
- trimmed: LogVisibility.clipped(trimmed, totalLines),
479
- totalLines,
480
- fullyFolded: LogVisibility.fullyFolded(clipped, totalLines),
481
- };
482
- }
483
- // {§message-arrival} — an inbound SEND row: harness-published, the sender's statement as its
484
- // sent side. {§message-causal-source}: a `source` names the actor; absence is the owner.
485
- static isArrival(e) {
486
- if (e.op !== "SEND" || e.origin !== "_plurnk")
487
- return false;
488
- const attrs = typeof e.attrs === "string" ? JSON.parse(e.attrs) : e.attrs;
489
- return attrs !== null && typeof attrs === "object" && attrs.kind === "message";
490
- }
491
- // {§message-projection} — a peer worker's message takes the ordinary bounds; every other
492
- // arrival, the loop's own assignment included, shares the allowance.
493
- static isExteriorArrival(e) {
494
- return PacketWire.isArrival(e) && !(typeof e.source === "string" && e.source.startsWith("worker://"));
495
- }
496
- static #promptProjectionWeights(entries, bodies, visibility, weighContent, budget) {
497
- if (budget === undefined)
498
- return new Map();
499
- if (!Number.isSafeInteger(budget) || budget < 0) {
500
- throw new RangeError(`promptProjectionWeight must be a non-negative safe integer, got ${JSON.stringify(budget)}`);
501
- }
502
- const costs = entries.flatMap((entry, index) => {
503
- // {§message-projection} — an arrival from outside the workspace shares the allowance;
504
- // a peer worker's message takes the ordinary bounds.
505
- if (!PacketWire.isExteriorArrival(entry) || bodies[index].content.length === 0)
506
- return [];
507
- const body = bodies[index];
508
- const visible = visibility[index];
509
- const width = body.startLine === null || visible.totalLines === 0
510
- ? 0
511
- : String(body.startLine + visible.totalLines - 1).length;
512
- const rendered = PacketWire.#renderContentBody(body.content, body.startLine, null, null, width, body.startLine === null ? null : visible.ordinals);
513
- return [{ index, cost: weighContent(rendered) }];
514
- });
515
- const allocations = new Map();
516
- let remaining = budget;
517
- let active = costs;
518
- while (active.length > 0) {
519
- const share = Math.floor(remaining / active.length);
520
- const complete = active.filter(({ cost }) => cost <= share);
521
- if (complete.length === 0) {
522
- const extra = remaining % active.length;
523
- active.forEach(({ index }, position) => allocations.set(index, share + (position < extra ? 1 : 0)));
524
- break;
525
- }
526
- for (const { index, cost } of complete) {
527
- allocations.set(index, cost);
528
- remaining -= cost;
529
- }
530
- const completed = new Set(complete.map(({ index }) => index));
531
- active = active.filter(({ index }) => !completed.has(index));
532
- }
533
- return allocations;
437
+ return `${ScopeFormat.region({ ...local, startLine, endLine })} of ${ScopeFormat.region(complete)}`;
534
438
  }
535
439
  static #renderLogEntries(entries, weighContent, options) {
536
440
  const bodies = entries.map((e) => {
@@ -545,20 +449,75 @@ export default class PacketWire {
545
449
  });
546
450
  });
547
451
  const visibility = entries.map((entry, index) => PacketWire.#visibleBody(entry, bodies[index]));
548
- const visibleBodies = bodies.map((body, index) => ({
549
- ...body,
550
- content: visibility[index].fullyFolded ? "" : visibility[index].content,
551
- }));
552
- const promptProjectionWeights = PacketWire.#promptProjectionWeights(entries, visibleBodies, visibility, weighContent, options.promptProjectionWeight);
553
452
  return entries.map((e, index) => {
554
453
  const identity = PacketWire.#rowIdentity(e, options);
555
454
  // Parse rx once — reused for the matcher/items enrichment and the body.
556
455
  const rx = (typeof e.rx === "string" ? PacketWire.#safeParse(e.rx) : e.rx);
557
456
  const facts = PacketWire.#rowResultFacts(identity, e, rx, bodies[index]);
558
- const projected = PacketWire.#rowBody(identity, e, bodies[index], visibility[index], facts, promptProjectionWeights.get(index), weighContent);
457
+ const projected = PacketWire.#rowBody(identity, e, bodies[index], visibility[index], facts);
559
458
  return PacketWire.#rowAccounting(identity, e, bodies[index], visibility[index], projected, weighContent, options);
560
459
  });
561
460
  }
461
+ static #attrsOf(e) {
462
+ const attrs = typeof e.attrs === "string" ? PacketWire.#safeParse(e.attrs) : e.attrs;
463
+ return attrs !== null && typeof attrs === "object" && !Array.isArray(attrs) ? attrs : {};
464
+ }
465
+ // One stored log row as the renderer sees it: the durable columns decoded once, a transient
466
+ // open row rendered open ({§invalid-emission-attempts}).
467
+ static entryView(r, transientOpenLogEntryId = null) {
468
+ const tx = (r.mimetype_tx === "application/json" ? JSON.parse(r.tx) : r.tx);
469
+ const rx = r.mimetype_rx === "application/json" ? JSON.parse(r.rx) : r.rx;
470
+ // {§context-fit} — a READ row's anchors ride with its lines whatever its status: a receipt that
471
+ // carries a prefix carries the prefix's anchors.
472
+ const readResult = LogEntryProjection.op(r) === "READ" && rx !== null && typeof rx === "object" && typeof rx.content === "string";
473
+ const rawLineAnchors = readResult && Object.hasOwn(rx, "lineAnchors") ? rx.lineAnchors : undefined;
474
+ if (rawLineAnchors !== undefined && !Array.isArray(rawLineAnchors)) {
475
+ throw new TypeError("A READ result's lineAnchors field must be an array.");
476
+ }
477
+ const lineAnchors = rawLineAnchors;
478
+ const rawLineNumberWidth = readResult && Object.hasOwn(rx, "lineNumberWidth") ? rx.lineNumberWidth : undefined;
479
+ if (rawLineNumberWidth !== undefined && !LineAnchors.isLineNumberWidth(rawLineNumberWidth)) {
480
+ throw new TypeError("A READ result's lineNumberWidth field must be a valid decimal line width.");
481
+ }
482
+ if ((rawLineAnchors === undefined) !== (rawLineNumberWidth === undefined)) {
483
+ throw new TypeError("A READ result's lineAnchors and lineNumberWidth fields must appear together.");
484
+ }
485
+ return {
486
+ id: r.id,
487
+ coordinate: `${r.loop_seq}/${r.turn_seq}/${r.sequence}`,
488
+ origin: r.origin,
489
+ op: r.op,
490
+ signal: r.signal === null ? null : JSON.parse(r.signal),
491
+ target: {
492
+ scheme: r.scheme,
493
+ username: r.username, password: r.password,
494
+ hostname: r.hostname, port: r.port,
495
+ pathname: r.pathname,
496
+ query: r.query,
497
+ fragment: r.fragment,
498
+ },
499
+ status: r.status_rx,
500
+ rx,
501
+ mimetype_rx: r.mimetype_rx,
502
+ tx,
503
+ mimetype_tx: r.mimetype_tx,
504
+ initial_folded: r.id === transientOpenLogEntryId ? LogVisibility.OPEN : LogVisibility.parse(r.initial_folded),
505
+ folded: LogVisibility.parse(r.folded),
506
+ source: r.source,
507
+ attrs: r.attrs === null ? null : JSON.parse(r.attrs),
508
+ producer: r.producer,
509
+ ...(lineAnchors === undefined ? {} : { lineAnchors }),
510
+ ...(rawLineNumberWidth === undefined ? {} : { lineNumberWidth: rawLineNumberWidth }),
511
+ };
512
+ }
513
+ // {§context-fit} — the tokens one row would charge the packet, rendered exactly as the log
514
+ // would render it, so the fit test and the gauge agree.
515
+ static rowTokens(view, weighContent, options = {}) {
516
+ const [row] = PacketWire.#renderLogEntries([view], weighContent, options);
517
+ if (row === undefined)
518
+ throw new Error("rowTokens: one view renders one row");
519
+ return row.curationTarget?.tokens ?? 0;
520
+ }
562
521
  // The row's identity and authored facts: who wrote it, what it addressed, and the statuses
563
522
  // that stay explicit. `meta` is the metadata line under construction; each later stage adds
564
523
  // to it, and {§log-wire-format}'s canonical JSON sorts the keys, so the order of stages never
@@ -639,6 +598,15 @@ export default class PacketWire {
639
598
  && typeof e.attrs.worker === "string") {
640
599
  meta.worker = e.attrs.worker;
641
600
  }
601
+ // {§worker-wait-timing} — the accepted bound, not elapsed time or the current configuration.
602
+ if (op === "WAIT" && e.attrs !== null && typeof e.attrs === "object" && "waiting" in e.attrs) {
603
+ const seconds = e.attrs.waiting;
604
+ if (typeof seconds !== "number" || !Number.isFinite(seconds) || (seconds < 0 && seconds !== -1)) {
605
+ throw new TypeError("A WAIT receipt carries a malformed waiting bound.");
606
+ }
607
+ if (seconds >= 0)
608
+ meta.waitSeconds = seconds;
609
+ }
642
610
  // An execution's output is a separate stream entry ({§exec-stream}); its address rides in a
643
611
  // `stream` link, distinct from the runtime-owned invocation target.
644
612
  // {§exec-target-routing} {§fs-namespace} — the receipt names the working directory only
@@ -799,23 +767,22 @@ export default class PacketWire {
799
767
  }));
800
768
  structuredMutationReceipt = effects.some((effect) => effect.receipt !== undefined);
801
769
  }
802
- return { findItems, range, structuredMutationReceipt };
770
+ return {
771
+ findItems, range, structuredMutationReceipt,
772
+ ...(op === "READ" && rx?.matches !== undefined
773
+ ? { matches: SchemeResults.assertMatchEvidenceList(rx.matches) } : {}),
774
+ };
803
775
  }
804
- // The body the row shows: the canonical full body is shared with log READ, log FIND, and
805
- // search derivation. READ/FIND own selection bounds, NOTE, lifecycle bodies and admitted programs remain
806
- // complete, and exterior arrivals share their packet allowance. Structured mutation receipts own
807
- // their join bound; every remaining body uses the ordinary fixed preview.
808
- static #rowBody(identity, e, fullBody, bodyVisibility, facts, promptProjectionWeight, weighContent) {
776
+ // The body the row shows: the canonical full body, shared with log READ, log FIND and search
777
+ // derivation, whole. Whether a result fit was decided where it landed ({§context-fit}); the packet
778
+ // cuts nothing but the emission head ({§emission-row}).
779
+ static #rowBody(identity, e, fullBody, bodyVisibility, facts) {
809
780
  const { meta, op } = identity;
810
781
  const projectedBody = {
811
782
  ...fullBody,
812
783
  content: bodyVisibility.fullyFolded ? bodyVisibility.readableContent : bodyVisibility.content,
813
784
  };
814
785
  const emptyFind = op === "FIND" && e.status === 200 && facts.findItems === 0;
815
- const previewExempt = op === "READ"
816
- || op === "FIND"
817
- || op === "NOTE" || typeof op === "string" && TurnDisposition.isOp(op)
818
- || facts.structuredMutationReceipt;
819
786
  const lineAnchors = op === "READ" ? e.lineAnchors ?? null : null;
820
787
  const lineNumberWidth = op === "READ" ? e.lineNumberWidth ?? null : null;
821
788
  if (lineAnchors !== null) {
@@ -831,18 +798,31 @@ export default class PacketWire {
831
798
  const sourceOrdinals = bodyVisibility.fullyFolded
832
799
  ? bodyVisibility.readableOrdinals
833
800
  : bodyVisibility.ordinals;
834
- const projection = promptProjectionWeight !== undefined
835
- ? PacketWire.#promptProjection(projectedBody, promptProjectionWeight, weighContent, (content) => PacketWire.#renderContentBody(content, bodyStartLine, null, null, numericLineNumberWidth, bodyStartLine === null
836
- ? null
837
- : sourceOrdinals.slice(0, TextCoordinates.logicalLines(content).length)))
838
- : previewExempt
839
- ? { text: projectedBody.content, cut: false, chunk: null }
840
- : PacketWire.#preview(projectedBody.content);
841
- const projectedLineCount = TextCoordinates.logicalLines(projection.text).length;
801
+ // {§markerless-first-page} — what came back unasked in size is its first page here too; what the
802
+ // model authored or asked for exactly, and a retrieval's own page, render whole.
803
+ const projection = PacketWire.#receivedBody(e, op)
804
+ ? PacketWire.#preview(projectedBody.content)
805
+ : { text: projectedBody.content, cut: false, chunk: null };
806
+ const projectedText = projection.text;
807
+ const projectedLineCount = TextCoordinates.logicalLines(projectedText).length;
842
808
  const projectedOrdinals = sourceOrdinals.slice(0, projectedLineCount);
843
- const body = emptyFind || projection.text.length === 0
809
+ if (facts.matches !== undefined && !bodyVisibility.fullyFolded) {
810
+ const physicalLines = projectedOrdinals.map((ordinal) => fullBody.lineOrdinals?.[ordinal - 1]
811
+ ?? (fullBody.startLine ?? 1) + ordinal - 1);
812
+ const evidence = PatternEdits.visible(facts.matches, physicalLines).map(({ region, enclosingRegion, locator }) => ({
813
+ ...(locator === undefined ? {} : { locator }),
814
+ ...(region === undefined ? {} : { region: ScopeFormat.region(region) }),
815
+ ...(enclosingRegion === undefined ? {} : { enclosingRegion: ScopeFormat.region(enclosingRegion) }),
816
+ }));
817
+ if (evidence.length > 0) {
818
+ meta.matches = BodyPreview.items(evidence, JSON.stringify);
819
+ if (meta.matches.length !== evidence.length)
820
+ meta.matchLocationCount = evidence.length;
821
+ }
822
+ }
823
+ const body = emptyFind || projectedText.length === 0
844
824
  ? ""
845
- : PacketWire.#renderContentBody(projection.text, bodyStartLine, lineAnchors, lineNumberWidth, numericLineNumberWidth, bodyStartLine === null ? null : projectedOrdinals, fullBody.lineOrdinals ?? null);
825
+ : PacketWire.#renderContentBody(projectedText, bodyStartLine, lineAnchors, lineNumberWidth, numericLineNumberWidth, bodyStartLine === null ? null : projectedOrdinals, fullBody.lineOrdinals ?? null);
846
826
  // lines beside tokens on a non-retrieval row with a navigable body — the count of
847
827
  // `N:`-numbered lines (fences and unnumbered prose don't count), so the model can plan
848
828
  // a <start,end> slice before paying for a READ. READ/FIND own typed extents instead.
@@ -854,14 +834,13 @@ export default class PacketWire {
854
834
  }
855
835
  const display = bodyVisibility.readableContent.length === 0
856
836
  ? "none"
857
- : bodyVisibility.fullyFolded || e.output_withheld === true
837
+ : bodyVisibility.fullyFolded
858
838
  ? "folded"
859
839
  : body.length === 0
860
840
  ? "none"
861
841
  : "open";
862
- const projectedChunk = projection.chunk !== null
863
- && bodyVisibility.folded.length > 0
864
- && !bodyVisibility.fullyFolded
842
+ // {§packet-extent-metadata} — a page states what it shows of what the row holds.
843
+ const projectedChunk = projection.chunk !== null && bodyVisibility.folded.length > 0 && !bodyVisibility.fullyFolded
865
844
  ? PacketWire.#sparseChunk(fullBody.content, projectedBody.content, sourceOrdinals, projection.text)
866
845
  : projection.chunk;
867
846
  if (display === "open" && projectedChunk !== null) {
@@ -870,65 +849,70 @@ export default class PacketWire {
870
849
  }
871
850
  return { body, projectedLineCount, display };
872
851
  }
873
- // The row's native attachment, its withholding receipt, and the accounting field that
852
+ // The row's native attachment, a landed-unfit arrival's size, and the accounting field that
874
853
  // participates in the row it measures: iterate until its decimal width and therefore the
875
854
  // rendered row's curation weight are stable. {§packet-token-accounting}
876
855
  static #rowAccounting(identity, e, fullBody, bodyVisibility, projected, weighContent, options) {
877
856
  const { meta, op, coordinate, path, target } = identity;
878
- const { body, projectedLineCount, display } = projected;
857
+ const { body, display } = projected;
879
858
  const nativeCandidate = op === "READ" && typeof e.status === "number" && e.status >= 200 && e.status < 300
880
859
  ? PacketWire.#attachmentOf(e.rx, e.target, coordinate, target) : null;
881
860
  const native = nativeCandidate !== null && (options.acceptedAttachmentKinds?.has(nativeCandidate.kind) ?? true)
882
861
  ? nativeCandidate : null;
883
- const outputWithheld = e.output_withheld === true
884
- && ((!bodyVisibility.fullyFolded && body.length > 0) || native !== null);
885
- if (outputWithheld) {
886
- const omitted = body.length > 0
887
- ? `${projectedLineCount} output lines${native === null ? "" : " and native content"}`
888
- : "native content";
889
- meta.overflow = `${omitted} not shown; the log exceeded logTokensMax when this row was withheld`;
890
- }
891
- // {§log-wire-format}: one descriptive heading, the facts, the body.
892
- let logTokens = 0;
893
- const renderRow = () => {
894
- const lines = [`### ${path}${identity.description === null ? "" : ` ${identity.description}`} · ${logTokens}`];
895
- if (Object.keys(meta).length > 0)
896
- lines.push(PacketWire.#canonicalJson(meta));
897
- if (display === "open")
898
- lines.push(body);
899
- return lines.join("\n");
900
- };
862
+ // {§context-fit} — an arrival that did not fit landed folded with its size beside it: the lines
863
+ // and tokens of the body the model can READ at this row's address.
864
+ const unfit = PacketWire.#attrsOf(e).unfit;
865
+ if (unfit !== null && typeof unfit === "object")
866
+ meta.size = unfit;
901
867
  // {§packet-attachment-parts}: retained native content shares the row's curation lifetime.
902
- const attachment = e.output_withheld !== true
903
- && !(bodyVisibility.totalLines > 0 && bodyVisibility.fullyFolded)
868
+ const attachment = !(bodyVisibility.totalLines > 0 && bodyVisibility.fullyFolded)
904
869
  ? native
905
870
  : null;
906
- if (attachment !== null)
907
- meta.tokensAttachment = attachment.weight;
908
871
  // {§emission-row}: an emission row carries its frozen emission outside its record, and charges what
909
872
  // the wire delivers of it, as the worker's own message, exactly as a native part is charged.
910
873
  const emission = LogEntryProjection.isEmission(e) && coordinate !== null
911
874
  ? { coordinate, content: fullBody.content, weight: weighContent(PacketWire.deliveredEmission(fullBody.content)) }
912
875
  : null;
913
- for (let pass = 0; pass < 8; pass += 1) {
914
- const next = weighContent(renderRow()) + (attachment?.weight ?? 0) + (emission?.weight ?? 0);
915
- if (next === logTokens) {
916
- return {
917
- content: renderRow(),
918
- curationTarget: { path, logTokens },
919
- attachment,
920
- emission,
921
- unadmittedOutput: (display === "open" || attachment !== null)
922
- && fullBody.provenance === "returned"
923
- && e.output_admission_turn_id == null
924
- && typeof e.id === "number"
925
- ? e.id : null,
926
- newOverflow: outputWithheld && e.newOverflow === true,
927
- };
876
+ // {§log-wire-format}: one descriptive heading, the facts, the body.
877
+ const render = (open, tokens) => {
878
+ const lines = [`### ${path}${identity.description === null ? "" : ` ${identity.description}`} · ${tokens}`];
879
+ if (Object.keys(meta).length > 0)
880
+ lines.push(PacketWire.#canonicalJson(meta));
881
+ if (open)
882
+ lines.push(body);
883
+ return lines.join("\n");
884
+ };
885
+ const converge = (open, part) => {
886
+ if (part !== null)
887
+ meta.tokensAttachment = part.weight;
888
+ else
889
+ delete meta.tokensAttachment;
890
+ let tokens = 0;
891
+ for (let pass = 0; pass < 8; pass += 1) {
892
+ const next = weighContent(render(open, tokens)) + (part?.weight ?? 0) + (emission?.weight ?? 0);
893
+ if (next === tokens)
894
+ return { content: render(open, tokens), tokens };
895
+ tokens = next;
928
896
  }
929
- logTokens = next;
930
- }
931
- throw new Error("packet log row accounting did not converge");
897
+ throw new Error("packet log row accounting did not converge");
898
+ };
899
+ const row = (rendered, part, bodied) => ({ content: rendered.content, curationTarget: { path, tokens: rendered.tokens }, attachment: part, emission, bodied });
900
+ const whole = converge(display === "open", attachment);
901
+ // {§context-own-rows-fit} — a row the wall may take carries a body or a native part and is not an
902
+ // emission row, whose head-cut program keeps the turn legible.
903
+ if (typeof e.id !== "number" || emission !== null || (display !== "open" && attachment === null))
904
+ return row(whole, attachment, null);
905
+ if (!(options.bodiless?.has(e.id) ?? false))
906
+ return row(whole, attachment, { id: e.id, tokens: whole.tokens });
907
+ // Taken: the fit rule's receipt shape — its size and address, no body, no native part.
908
+ meta.size = { lines: projected.projectedLineCount, tokens: whole.tokens };
909
+ const receipt = converge(false, null);
910
+ if (receipt.tokens < whole.tokens)
911
+ return row(receipt, null, null);
912
+ // A receipt that weighs no less than the body it stands for sheds nothing: the row stays whole and
913
+ // is spent.
914
+ delete meta.size;
915
+ return row(converge(display === "open", attachment), attachment, null);
932
916
  }
933
917
  static #attachmentOf(rx, target, coordinate, path) {
934
918
  const view = rx;