@plurnk/plurnk-service 1.27.0 → 1.29.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 (159) hide show
  1. package/.env.defaults +17 -19
  2. package/SPEC.md +105 -149
  3. package/dist/build-info.json +1 -1
  4. package/dist/content/body-preview.d.ts +5 -0
  5. package/dist/content/body-preview.d.ts.map +1 -1
  6. package/dist/content/body-preview.js +16 -0
  7. package/dist/content/body-preview.js.map +1 -1
  8. package/dist/content/line-marker.d.ts +1 -0
  9. package/dist/content/line-marker.d.ts.map +1 -1
  10. package/dist/content/line-marker.js +5 -0
  11. package/dist/content/line-marker.js.map +1 -1
  12. package/dist/content/read-projector.js +3 -3
  13. package/dist/content/read-projector.js.map +1 -1
  14. package/dist/content/read-resolve.d.ts.map +1 -1
  15. package/dist/content/read-resolve.js +7 -4
  16. package/dist/content/read-resolve.js.map +1 -1
  17. package/dist/core/AdmittedTurnExecutor.d.ts +3 -1
  18. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
  19. package/dist/core/AdmittedTurnExecutor.js +19 -4
  20. package/dist/core/AdmittedTurnExecutor.js.map +1 -1
  21. package/dist/core/BudgetReadout.d.ts +4 -4
  22. package/dist/core/BudgetReadout.d.ts.map +1 -1
  23. package/dist/core/BudgetReadout.js +26 -41
  24. package/dist/core/BudgetReadout.js.map +1 -1
  25. package/dist/core/ChannelWrite.d.ts +5 -0
  26. package/dist/core/ChannelWrite.d.ts.map +1 -1
  27. package/dist/core/ChannelWrite.js +5 -0
  28. package/dist/core/ChannelWrite.js.map +1 -1
  29. package/dist/core/ChannelWrite.sql +10 -0
  30. package/dist/core/ContextFit.d.ts +26 -0
  31. package/dist/core/ContextFit.d.ts.map +1 -0
  32. package/dist/core/ContextFit.js +56 -0
  33. package/dist/core/ContextFit.js.map +1 -0
  34. package/dist/core/DataStatementRunner.d.ts.map +1 -1
  35. package/dist/core/DataStatementRunner.js +8 -3
  36. package/dist/core/DataStatementRunner.js.map +1 -1
  37. package/dist/core/Dispatcher.d.ts +13 -0
  38. package/dist/core/Dispatcher.d.ts.map +1 -1
  39. package/dist/core/Dispatcher.js +155 -5
  40. package/dist/core/Dispatcher.js.map +1 -1
  41. package/dist/core/EmissionHead.d.ts +8 -0
  42. package/dist/core/EmissionHead.d.ts.map +1 -0
  43. package/dist/core/EmissionHead.js +29 -0
  44. package/dist/core/EmissionHead.js.map +1 -0
  45. package/dist/core/KillHandler.d.ts.map +1 -1
  46. package/dist/core/KillHandler.js +9 -3
  47. package/dist/core/KillHandler.js.map +1 -1
  48. package/dist/core/LogEntryProjection.d.ts +1 -0
  49. package/dist/core/LogEntryProjection.d.ts.map +1 -1
  50. package/dist/core/LogEntryProjection.js +9 -0
  51. package/dist/core/LogEntryProjection.js.map +1 -1
  52. package/dist/core/LogWriter.d.ts +42 -0
  53. package/dist/core/LogWriter.d.ts.map +1 -1
  54. package/dist/core/LogWriter.js +11 -5
  55. package/dist/core/LogWriter.js.map +1 -1
  56. package/dist/core/PacketBuilder.d.ts +17 -4
  57. package/dist/core/PacketBuilder.d.ts.map +1 -1
  58. package/dist/core/PacketBuilder.js +76 -117
  59. package/dist/core/PacketBuilder.js.map +1 -1
  60. package/dist/core/PacketBuilder.sql +0 -7
  61. package/dist/core/ResourceSelector.d.ts.map +1 -1
  62. package/dist/core/ResourceSelector.js +4 -2
  63. package/dist/core/ResourceSelector.js.map +1 -1
  64. package/dist/core/ResourceTransfers.d.ts.map +1 -1
  65. package/dist/core/ResourceTransfers.js +2 -2
  66. package/dist/core/ResourceTransfers.js.map +1 -1
  67. package/dist/core/StrikeRail.d.ts.map +1 -1
  68. package/dist/core/StrikeRail.js +5 -1
  69. package/dist/core/StrikeRail.js.map +1 -1
  70. package/dist/core/TurnMaterialization.d.ts +6 -2
  71. package/dist/core/TurnMaterialization.d.ts.map +1 -1
  72. package/dist/core/TurnMaterialization.js +64 -16
  73. package/dist/core/TurnMaterialization.js.map +1 -1
  74. package/dist/core/TurnOps.d.ts.map +1 -1
  75. package/dist/core/TurnOps.js +7 -7
  76. package/dist/core/TurnOps.js.map +1 -1
  77. package/dist/core/TurnRunner.d.ts +1 -0
  78. package/dist/core/TurnRunner.d.ts.map +1 -1
  79. package/dist/core/TurnRunner.js +141 -139
  80. package/dist/core/TurnRunner.js.map +1 -1
  81. package/dist/core/TurnRunner.sql +2 -2
  82. package/dist/core/WorkerControlHandler.d.ts.map +1 -1
  83. package/dist/core/WorkerControlHandler.js +5 -1
  84. package/dist/core/WorkerControlHandler.js.map +1 -1
  85. package/dist/core/env-catalog.js +2 -2
  86. package/dist/core/env-catalog.js.map +1 -1
  87. package/dist/core/fork.sql +4 -10
  88. package/dist/core/git-env.d.ts +1 -1
  89. package/dist/core/git-env.d.ts.map +1 -1
  90. package/dist/core/git-env.js +19 -12
  91. package/dist/core/git-env.js.map +1 -1
  92. package/dist/core/git-membership.d.ts.map +1 -1
  93. package/dist/core/git-membership.js +11 -5
  94. package/dist/core/git-membership.js.map +1 -1
  95. package/dist/core/git-state.js +1 -1
  96. package/dist/core/git-state.js.map +1 -1
  97. package/dist/core/operation-target-groups.d.ts +1 -1
  98. package/dist/core/operation-target-groups.d.ts.map +1 -1
  99. package/dist/core/operation-target-groups.js +27 -5
  100. package/dist/core/operation-target-groups.js.map +1 -1
  101. package/dist/core/packet-wire.d.ts +80 -10
  102. package/dist/core/packet-wire.d.ts.map +1 -1
  103. package/dist/core/packet-wire.js +181 -226
  104. package/dist/core/packet-wire.js.map +1 -1
  105. package/dist/core/plurnk-uri.d.ts +7 -0
  106. package/dist/core/plurnk-uri.d.ts.map +1 -1
  107. package/dist/core/plurnk-uri.js +21 -0
  108. package/dist/core/plurnk-uri.js.map +1 -1
  109. package/dist/core/unregistered-scheme.d.ts +4 -0
  110. package/dist/core/unregistered-scheme.d.ts.map +1 -0
  111. package/dist/core/unregistered-scheme.js +14 -0
  112. package/dist/core/unregistered-scheme.js.map +1 -0
  113. package/dist/digest/Digest.d.ts.map +1 -1
  114. package/dist/digest/Digest.js +3 -2
  115. package/dist/digest/Digest.js.map +1 -1
  116. package/dist/digest/DigestRender.d.ts.map +1 -1
  117. package/dist/digest/DigestRender.js +88 -42
  118. package/dist/digest/DigestRender.js.map +1 -1
  119. package/dist/digest/digest-rows.d.ts +7 -0
  120. package/dist/digest/digest-rows.d.ts.map +1 -1
  121. package/dist/digest/digest-rows.js.map +1 -1
  122. package/dist/digest/digest.sql +15 -2
  123. package/dist/schemes/Exec.d.ts.map +1 -1
  124. package/dist/schemes/Exec.js +14 -3
  125. package/dist/schemes/Exec.js.map +1 -1
  126. package/dist/schemes/File.d.ts.map +1 -1
  127. package/dist/schemes/File.js +10 -5
  128. package/dist/schemes/File.js.map +1 -1
  129. package/dist/schemes/Log.d.ts.map +1 -1
  130. package/dist/schemes/Log.js +46 -5
  131. package/dist/schemes/Log.js.map +1 -1
  132. package/dist/schemes/_entry-crud.js +9 -9
  133. package/dist/schemes/_entry-crud.js.map +1 -1
  134. package/dist/schemes/_entry-find.d.ts.map +1 -1
  135. package/dist/schemes/_entry-find.js +5 -3
  136. package/dist/schemes/_entry-find.js.map +1 -1
  137. package/dist/schemes/_entry-fts.d.ts.map +1 -1
  138. package/dist/schemes/_entry-fts.js +7 -3
  139. package/dist/schemes/_entry-fts.js.map +1 -1
  140. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  141. package/dist/schemes/_entry-manifest.js +2 -4
  142. package/dist/schemes/_entry-manifest.js.map +1 -1
  143. package/dist/schemes/_entry-ops.js +4 -4
  144. package/dist/schemes/_entry-ops.js.map +1 -1
  145. package/dist/server/Daemon.d.ts.map +1 -1
  146. package/dist/server/Daemon.js +11 -2
  147. package/dist/server/Daemon.js.map +1 -1
  148. package/migrations/013_graph_regions.sql +1 -0
  149. package/migrations/014_stream_timing.sql +1 -0
  150. package/migrations/015_request_evidence.sql +1 -0
  151. package/package.json +34 -34
  152. package/dist/core/KnownToxins.d.ts +0 -4
  153. package/dist/core/KnownToxins.d.ts.map +0 -1
  154. package/dist/core/KnownToxins.js +0 -22
  155. package/dist/core/KnownToxins.js.map +0 -1
  156. package/dist/core/ReasoningView.d.ts +0 -12
  157. package/dist/core/ReasoningView.d.ts.map +0 -1
  158. package/dist/core/ReasoningView.js +0 -40
  159. package/dist/core/ReasoningView.js.map +0 -1
@@ -2,12 +2,12 @@ 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
12
  import PatternEdits from "../content/pattern-edits.js";
13
13
  import { Results as SchemeResults } from "@plurnk/plurnk-schemes";
@@ -47,8 +47,7 @@ export default class PacketWire {
47
47
  return pointers.length === 0 ? "" : `[${pointers.join(",\n")}]`;
48
48
  }
49
49
  // Non-terminal model-facing observations are deliberately separate from
50
- // operation failures. Producer messages are normalized and bounded by the
51
- // shared preview limit; typed positions remain legible.
50
+ // operation failures. Producer messages are normalized; typed positions remain legible.
52
51
  static renderNotices(notices) {
53
52
  const observations = Array.isArray(notices) ? notices : [];
54
53
  return observations.map((notice) => {
@@ -56,9 +55,7 @@ export default class PacketWire {
56
55
  const rawMessage = typeof notice.message === "string"
57
56
  ? notice.message.replace(/\s+/g, " ").trim()
58
57
  : "";
59
- const message = rawMessage.length > 0
60
- ? PacketWire.#preview(rawMessage).text
61
- : "";
58
+ const message = rawMessage;
62
59
  const position = notice.position?.type === "content-offset"
63
60
  ? ` @ ${String(notice.position.line)}:${String(notice.position.column)}`
64
61
  : "";
@@ -93,12 +90,12 @@ export default class PacketWire {
93
90
  static renderLog(entries, weighContent, options = {}) {
94
91
  return PacketWire.renderLogWithAccounting(entries, weighContent, options).content;
95
92
  }
96
- // {§tokenomics-pressure-inventory} — the wire row and its reclaimable-body
97
- // 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.
98
95
  static renderLogWithAccounting(entries, weighContent, options = {}) {
99
96
  const log = Array.isArray(entries) ? entries : [];
100
97
  if (log.length === 0)
101
- return { content: "", records: [], curationTargets: [], attachments: [], emissions: [], unadmittedOutput: [], newOverflow: false };
98
+ return { content: "", records: [], curationTargets: [], attachments: [], emissions: [], bodied: [] };
102
99
  const rows = PacketWire.#renderLogEntries(log, weighContent, options);
103
100
  const records = rows.map(({ content }) => content);
104
101
  return {
@@ -107,8 +104,7 @@ export default class PacketWire {
107
104
  curationTargets: rows.flatMap(({ curationTarget }) => curationTarget === null ? [] : [curationTarget]),
108
105
  attachments: rows.flatMap(({ attachment }) => attachment === null ? [] : [attachment]),
109
106
  emissions: rows.flatMap(({ emission }) => emission === null ? [] : [emission]),
110
- unadmittedOutput: rows.flatMap(({ unadmittedOutput }) => unadmittedOutput === null ? [] : [unadmittedOutput]),
111
- newOverflow: rows.some(({ newOverflow }) => newOverflow),
107
+ bodied: rows.flatMap(({ bodied }) => bodied === null ? [] : [bodied]),
112
108
  };
113
109
  }
114
110
  // Read one section's content by name off a packet (Engine's or re-parsed).
@@ -332,10 +328,52 @@ export default class PacketWire {
332
328
  throw new TypeError("A packet log row requires an addressable coordinate.");
333
329
  return `log:///${coordinate}/${leaf}`;
334
330
  }
335
- // One preview function for every bounded model-facing projection. Lines
336
- // protect ordinary documents and Unicode characters protect a single-line
337
- // bomb. Once a physical line is complete, a character cut retreats to that
338
- // 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.
339
377
  static #preview(text) {
340
378
  const coordinates = new TextCoordinates(text);
341
379
  const physicalLines = coordinates.logicalLines();
@@ -378,19 +416,16 @@ export default class PacketWire {
378
416
  const runs = [];
379
417
  for (const ordinal of selectedOrdinals) {
380
418
  const previous = runs.at(-1);
381
- if (previous === undefined || ordinal !== previous[1] + 1) {
419
+ if (previous === undefined || ordinal !== previous[1] + 1)
382
420
  runs.push([ordinal, ordinal]);
383
- }
384
- else {
421
+ else
385
422
  previous[1] = ordinal;
386
- }
387
423
  }
388
424
  const selected = runs.map(([start, finish]) => ScopeFormat.lines(start, finish)).join(",");
389
425
  return `${selected} of ${ScopeFormat.count("line", TextCoordinates.logicalLines(completeContent).length)}`;
390
426
  }
391
427
  const local = coordinates.regionFromOffsets(0, end);
392
- const complete = new TextCoordinates(completeContent)
393
- .regionFromOffsets(0, completeContent.length);
428
+ const complete = new TextCoordinates(completeContent).regionFromOffsets(0, completeContent.length);
394
429
  if (local === null || complete === null) {
395
430
  throw new Error("a sparse character-bound chunk must resolve to exact text coordinates");
396
431
  }
@@ -399,140 +434,7 @@ export default class PacketWire {
399
434
  if (startLine === undefined || endLine === undefined) {
400
435
  throw new Error("a sparse character-bound chunk must map to canonical body lines");
401
436
  }
402
- return `${ScopeFormat.region({
403
- ...local,
404
- startLine,
405
- endLine,
406
- })} of ${ScopeFormat.region(complete)}`;
407
- }
408
- static #promptProjection(body, budget, weighContent, render = (content) => PacketWire.#renderContentBody(content, body.startLine, null)) {
409
- const weightAt = (end) => weighContent(render(body.content.slice(0, end)));
410
- if (weightAt(body.content.length) <= budget) {
411
- return { text: body.content, cut: false, chunk: null };
412
- }
413
- if (budget <= 0)
414
- return { text: "", cut: true, chunk: null };
415
- const coordinates = new TextCoordinates(body.content);
416
- const lines = coordinates.logicalLines();
417
- const completeLineEnds = lines
418
- .filter((line) => line.separator.length > 0 && line.end < body.content.length)
419
- .map((line) => line.end);
420
- let low = 0;
421
- let high = completeLineEnds.length;
422
- while (low < high) {
423
- const middle = Math.floor((low + high) / 2);
424
- if (weightAt(completeLineEnds[middle]) <= budget)
425
- low = middle + 1;
426
- else
427
- high = middle;
428
- }
429
- const completeLineEnd = low === 0 ? 0 : completeLineEnds[low - 1];
430
- if (completeLineEnd > 0) {
431
- return {
432
- text: body.content.slice(0, completeLineEnd),
433
- cut: true,
434
- chunk: PacketWire.#chunk(coordinates, lines, completeLineEnd, body.content.length),
435
- };
436
- }
437
- const firstLineEnd = lines[0]?.contentEnd ?? body.content.length;
438
- const offsets = [0];
439
- let offset = 0;
440
- for (const codePoint of body.content.slice(0, firstLineEnd)) {
441
- offset += codePoint.length;
442
- offsets.push(offset);
443
- }
444
- low = 0;
445
- high = offsets.length;
446
- while (low < high) {
447
- const middle = Math.floor((low + high) / 2);
448
- if (weightAt(offsets[middle]) <= budget)
449
- low = middle + 1;
450
- else
451
- high = middle;
452
- }
453
- const characterEnd = low === 0 ? 0 : offsets[low - 1];
454
- if (characterEnd === 0)
455
- return { text: "", cut: true, chunk: null };
456
- return {
457
- text: body.content.slice(0, characterEnd),
458
- cut: true,
459
- chunk: PacketWire.#chunk(coordinates, lines, characterEnd, body.content.length),
460
- };
461
- }
462
- static #visibleBody(entry, body) {
463
- const trimmed = LogVisibility.parse(entry.folded ?? LogVisibility.OPEN);
464
- const folded = LogVisibility.combine(LogVisibility.parse(entry.initial_folded ?? LogVisibility.OPEN), trimmed);
465
- const lines = TextCoordinates.logicalLines(body.content);
466
- const totalLines = lines.length;
467
- const clipped = LogVisibility.clipped(folded, totalLines);
468
- const ordinals = LogVisibility.visibleLineOrdinals(clipped, totalLines);
469
- const readableOrdinals = LogVisibility.visibleLineOrdinals(trimmed, totalLines);
470
- const select = (selected) => selected.map((ordinal) => {
471
- const line = lines[ordinal - 1];
472
- return body.content.slice(line.start, line.end);
473
- }).join("");
474
- return {
475
- content: select(ordinals),
476
- ordinals,
477
- readableContent: select(readableOrdinals),
478
- readableOrdinals,
479
- folded: clipped,
480
- trimmed: LogVisibility.clipped(trimmed, totalLines),
481
- totalLines,
482
- fullyFolded: LogVisibility.fullyFolded(clipped, totalLines),
483
- };
484
- }
485
- // {§message-arrival} — an inbound SEND row: harness-published, the sender's statement as its
486
- // sent side. {§message-causal-source}: a `source` names the actor; absence is the owner.
487
- static isArrival(e) {
488
- if (e.op !== "SEND" || e.origin !== "_plurnk")
489
- return false;
490
- const attrs = typeof e.attrs === "string" ? JSON.parse(e.attrs) : e.attrs;
491
- return attrs !== null && typeof attrs === "object" && attrs.kind === "message";
492
- }
493
- // {§message-projection} — a peer worker's message takes the ordinary bounds; every other
494
- // arrival, the loop's own assignment included, shares the allowance.
495
- static isExteriorArrival(e) {
496
- return PacketWire.isArrival(e) && !(typeof e.source === "string" && e.source.startsWith("worker://"));
497
- }
498
- static #promptProjectionWeights(entries, bodies, visibility, weighContent, budget) {
499
- if (budget === undefined)
500
- return new Map();
501
- if (!Number.isSafeInteger(budget) || budget < 0) {
502
- throw new RangeError(`promptProjectionWeight must be a non-negative safe integer, got ${JSON.stringify(budget)}`);
503
- }
504
- const costs = entries.flatMap((entry, index) => {
505
- // {§message-projection} — an arrival from outside the workspace shares the allowance;
506
- // a peer worker's message takes the ordinary bounds.
507
- if (!PacketWire.isExteriorArrival(entry) || bodies[index].content.length === 0)
508
- return [];
509
- const body = bodies[index];
510
- const visible = visibility[index];
511
- const width = body.startLine === null || visible.totalLines === 0
512
- ? 0
513
- : String(body.startLine + visible.totalLines - 1).length;
514
- const rendered = PacketWire.#renderContentBody(body.content, body.startLine, null, null, width, body.startLine === null ? null : visible.ordinals);
515
- return [{ index, cost: weighContent(rendered) }];
516
- });
517
- const allocations = new Map();
518
- let remaining = budget;
519
- let active = costs;
520
- while (active.length > 0) {
521
- const share = Math.floor(remaining / active.length);
522
- const complete = active.filter(({ cost }) => cost <= share);
523
- if (complete.length === 0) {
524
- const extra = remaining % active.length;
525
- active.forEach(({ index }, position) => allocations.set(index, share + (position < extra ? 1 : 0)));
526
- break;
527
- }
528
- for (const { index, cost } of complete) {
529
- allocations.set(index, cost);
530
- remaining -= cost;
531
- }
532
- const completed = new Set(complete.map(({ index }) => index));
533
- active = active.filter(({ index }) => !completed.has(index));
534
- }
535
- return allocations;
437
+ return `${ScopeFormat.region({ ...local, startLine, endLine })} of ${ScopeFormat.region(complete)}`;
536
438
  }
537
439
  static #renderLogEntries(entries, weighContent, options) {
538
440
  const bodies = entries.map((e) => {
@@ -547,20 +449,75 @@ export default class PacketWire {
547
449
  });
548
450
  });
549
451
  const visibility = entries.map((entry, index) => PacketWire.#visibleBody(entry, bodies[index]));
550
- const visibleBodies = bodies.map((body, index) => ({
551
- ...body,
552
- content: visibility[index].fullyFolded ? "" : visibility[index].content,
553
- }));
554
- const promptProjectionWeights = PacketWire.#promptProjectionWeights(entries, visibleBodies, visibility, weighContent, options.promptProjectionWeight);
555
452
  return entries.map((e, index) => {
556
453
  const identity = PacketWire.#rowIdentity(e, options);
557
454
  // Parse rx once — reused for the matcher/items enrichment and the body.
558
455
  const rx = (typeof e.rx === "string" ? PacketWire.#safeParse(e.rx) : e.rx);
559
456
  const facts = PacketWire.#rowResultFacts(identity, e, rx, bodies[index]);
560
- 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);
561
458
  return PacketWire.#rowAccounting(identity, e, bodies[index], visibility[index], projected, weighContent, options);
562
459
  });
563
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
+ }
564
521
  // The row's identity and authored facts: who wrote it, what it addressed, and the statuses
565
522
  // that stay explicit. `meta` is the metadata line under construction; each later stage adds
566
523
  // to it, and {§log-wire-format}'s canonical JSON sorts the keys, so the order of stages never
@@ -816,21 +773,16 @@ export default class PacketWire {
816
773
  ? { matches: SchemeResults.assertMatchEvidenceList(rx.matches) } : {}),
817
774
  };
818
775
  }
819
- // The body the row shows: the canonical full body is shared with log READ, log FIND, and
820
- // search derivation. READ/FIND own selection bounds, NOTE, lifecycle bodies and admitted programs remain
821
- // complete, and exterior arrivals share their packet allowance. Structured mutation receipts own
822
- // their join bound; every remaining body uses the ordinary fixed preview.
823
- 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) {
824
780
  const { meta, op } = identity;
825
781
  const projectedBody = {
826
782
  ...fullBody,
827
783
  content: bodyVisibility.fullyFolded ? bodyVisibility.readableContent : bodyVisibility.content,
828
784
  };
829
785
  const emptyFind = op === "FIND" && e.status === 200 && facts.findItems === 0;
830
- const previewExempt = op === "READ"
831
- || op === "FIND"
832
- || op === "NOTE" || typeof op === "string" && TurnDisposition.isOp(op)
833
- || facts.structuredMutationReceipt;
834
786
  const lineAnchors = op === "READ" ? e.lineAnchors ?? null : null;
835
787
  const lineNumberWidth = op === "READ" ? e.lineNumberWidth ?? null : null;
836
788
  if (lineAnchors !== null) {
@@ -846,14 +798,13 @@ export default class PacketWire {
846
798
  const sourceOrdinals = bodyVisibility.fullyFolded
847
799
  ? bodyVisibility.readableOrdinals
848
800
  : bodyVisibility.ordinals;
849
- const projection = promptProjectionWeight !== undefined
850
- ? PacketWire.#promptProjection(projectedBody, promptProjectionWeight, weighContent, (content) => PacketWire.#renderContentBody(content, bodyStartLine, null, null, numericLineNumberWidth, bodyStartLine === null
851
- ? null
852
- : sourceOrdinals.slice(0, TextCoordinates.logicalLines(content).length)))
853
- : previewExempt
854
- ? { text: projectedBody.content, cut: false, chunk: null }
855
- : PacketWire.#preview(projectedBody.content);
856
- 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;
857
808
  const projectedOrdinals = sourceOrdinals.slice(0, projectedLineCount);
858
809
  if (facts.matches !== undefined && !bodyVisibility.fullyFolded) {
859
810
  const physicalLines = projectedOrdinals.map((ordinal) => fullBody.lineOrdinals?.[ordinal - 1]
@@ -869,9 +820,9 @@ export default class PacketWire {
869
820
  meta.matchLocationCount = evidence.length;
870
821
  }
871
822
  }
872
- const body = emptyFind || projection.text.length === 0
823
+ const body = emptyFind || projectedText.length === 0
873
824
  ? ""
874
- : 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);
875
826
  // lines beside tokens on a non-retrieval row with a navigable body — the count of
876
827
  // `N:`-numbered lines (fences and unnumbered prose don't count), so the model can plan
877
828
  // a <start,end> slice before paying for a READ. READ/FIND own typed extents instead.
@@ -883,14 +834,13 @@ export default class PacketWire {
883
834
  }
884
835
  const display = bodyVisibility.readableContent.length === 0
885
836
  ? "none"
886
- : bodyVisibility.fullyFolded || e.output_withheld === true
837
+ : bodyVisibility.fullyFolded
887
838
  ? "folded"
888
839
  : body.length === 0
889
840
  ? "none"
890
841
  : "open";
891
- const projectedChunk = projection.chunk !== null
892
- && bodyVisibility.folded.length > 0
893
- && !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
894
844
  ? PacketWire.#sparseChunk(fullBody.content, projectedBody.content, sourceOrdinals, projection.text)
895
845
  : projection.chunk;
896
846
  if (display === "open" && projectedChunk !== null) {
@@ -899,65 +849,70 @@ export default class PacketWire {
899
849
  }
900
850
  return { body, projectedLineCount, display };
901
851
  }
902
- // 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
903
853
  // participates in the row it measures: iterate until its decimal width and therefore the
904
854
  // rendered row's curation weight are stable. {§packet-token-accounting}
905
855
  static #rowAccounting(identity, e, fullBody, bodyVisibility, projected, weighContent, options) {
906
856
  const { meta, op, coordinate, path, target } = identity;
907
- const { body, projectedLineCount, display } = projected;
857
+ const { body, display } = projected;
908
858
  const nativeCandidate = op === "READ" && typeof e.status === "number" && e.status >= 200 && e.status < 300
909
859
  ? PacketWire.#attachmentOf(e.rx, e.target, coordinate, target) : null;
910
860
  const native = nativeCandidate !== null && (options.acceptedAttachmentKinds?.has(nativeCandidate.kind) ?? true)
911
861
  ? nativeCandidate : null;
912
- const outputWithheld = e.output_withheld === true
913
- && ((!bodyVisibility.fullyFolded && body.length > 0) || native !== null);
914
- if (outputWithheld) {
915
- const omitted = body.length > 0
916
- ? `${projectedLineCount} output lines${native === null ? "" : " and native content"}`
917
- : "native content";
918
- meta.overflow = `${omitted} not shown; the log exceeded logTokensMax when this row was withheld`;
919
- }
920
- // {§log-wire-format}: one descriptive heading, the facts, the body.
921
- let logTokens = 0;
922
- const renderRow = () => {
923
- const lines = [`### ${path}${identity.description === null ? "" : ` ${identity.description}`} · ${logTokens}`];
924
- if (Object.keys(meta).length > 0)
925
- lines.push(PacketWire.#canonicalJson(meta));
926
- if (display === "open")
927
- lines.push(body);
928
- return lines.join("\n");
929
- };
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;
930
867
  // {§packet-attachment-parts}: retained native content shares the row's curation lifetime.
931
- const attachment = e.output_withheld !== true
932
- && !(bodyVisibility.totalLines > 0 && bodyVisibility.fullyFolded)
868
+ const attachment = !(bodyVisibility.totalLines > 0 && bodyVisibility.fullyFolded)
933
869
  ? native
934
870
  : null;
935
- if (attachment !== null)
936
- meta.tokensAttachment = attachment.weight;
937
871
  // {§emission-row}: an emission row carries its frozen emission outside its record, and charges what
938
872
  // the wire delivers of it, as the worker's own message, exactly as a native part is charged.
939
873
  const emission = LogEntryProjection.isEmission(e) && coordinate !== null
940
874
  ? { coordinate, content: fullBody.content, weight: weighContent(PacketWire.deliveredEmission(fullBody.content)) }
941
875
  : null;
942
- for (let pass = 0; pass < 8; pass += 1) {
943
- const next = weighContent(renderRow()) + (attachment?.weight ?? 0) + (emission?.weight ?? 0);
944
- if (next === logTokens) {
945
- return {
946
- content: renderRow(),
947
- curationTarget: { path, logTokens },
948
- attachment,
949
- emission,
950
- unadmittedOutput: (display === "open" || attachment !== null)
951
- && fullBody.provenance === "returned"
952
- && e.output_admission_turn_id == null
953
- && typeof e.id === "number"
954
- ? e.id : null,
955
- newOverflow: outputWithheld && e.newOverflow === true,
956
- };
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;
957
896
  }
958
- logTokens = next;
959
- }
960
- 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);
961
916
  }
962
917
  static #attachmentOf(rx, target, coordinate, path) {
963
918
  const view = rx;