@plurnk/plurnk-service 1.19.3 → 1.21.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 (124) hide show
  1. package/.env.defaults +8 -5
  2. package/INSTALL.md +3 -2
  3. package/SPEC.md +221 -122
  4. package/dist/build-info.json +1 -1
  5. package/dist/content/line-anchors.d.ts.map +1 -1
  6. package/dist/content/line-anchors.js +5 -1
  7. package/dist/content/line-anchors.js.map +1 -1
  8. package/dist/core/AdmittedTurnExecutor.d.ts +2 -2
  9. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
  10. package/dist/core/AdmittedTurnExecutor.js +32 -27
  11. package/dist/core/AdmittedTurnExecutor.js.map +1 -1
  12. package/dist/core/BareBatchRunner.d.ts +6 -1
  13. package/dist/core/BareBatchRunner.d.ts.map +1 -1
  14. package/dist/core/BareBatchRunner.js +105 -50
  15. package/dist/core/BareBatchRunner.js.map +1 -1
  16. package/dist/core/BudgetReadout.d.ts +1 -1
  17. package/dist/core/BudgetReadout.d.ts.map +1 -1
  18. package/dist/core/BudgetReadout.js +4 -7
  19. package/dist/core/BudgetReadout.js.map +1 -1
  20. package/dist/core/Dispatcher.d.ts +2 -2
  21. package/dist/core/Dispatcher.d.ts.map +1 -1
  22. package/dist/core/Dispatcher.js +24 -58
  23. package/dist/core/Dispatcher.js.map +1 -1
  24. package/dist/core/Dispatcher.sql +7 -0
  25. package/dist/core/Engine.d.ts +1 -0
  26. package/dist/core/Engine.d.ts.map +1 -1
  27. package/dist/core/Engine.js.map +1 -1
  28. package/dist/core/KnownToxins.d.ts +5 -0
  29. package/dist/core/KnownToxins.d.ts.map +1 -0
  30. package/dist/core/KnownToxins.js +31 -0
  31. package/dist/core/KnownToxins.js.map +1 -0
  32. package/dist/core/LogBody.js +2 -2
  33. package/dist/core/LogBody.js.map +1 -1
  34. package/dist/core/LogEntryProjection.d.ts.map +1 -1
  35. package/dist/core/LogEntryProjection.js +0 -4
  36. package/dist/core/LogEntryProjection.js.map +1 -1
  37. package/dist/core/LoopDriver.d.ts.map +1 -1
  38. package/dist/core/LoopDriver.js +27 -7
  39. package/dist/core/LoopDriver.js.map +1 -1
  40. package/dist/core/LoopLifecycle.d.ts +5 -0
  41. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  42. package/dist/core/LoopLifecycle.js +10 -0
  43. package/dist/core/LoopLifecycle.js.map +1 -1
  44. package/dist/core/LoopLifecycle.sql +36 -0
  45. package/dist/core/PacketBuilder.d.ts +1 -0
  46. package/dist/core/PacketBuilder.d.ts.map +1 -1
  47. package/dist/core/PacketBuilder.js +9 -11
  48. package/dist/core/PacketBuilder.js.map +1 -1
  49. package/dist/core/PacketBuilder.sql +5 -0
  50. package/dist/core/ProviderRecovery.d.ts +9 -0
  51. package/dist/core/ProviderRecovery.d.ts.map +1 -0
  52. package/dist/core/ProviderRecovery.js +22 -0
  53. package/dist/core/ProviderRecovery.js.map +1 -0
  54. package/dist/core/ReasoningView.d.ts +5 -1
  55. package/dist/core/ReasoningView.d.ts.map +1 -1
  56. package/dist/core/ReasoningView.js +9 -4
  57. package/dist/core/ReasoningView.js.map +1 -1
  58. package/dist/core/ServiceTeardown.d.ts +1 -1
  59. package/dist/core/ServiceTeardown.d.ts.map +1 -1
  60. package/dist/core/ServiceTeardown.js +4 -2
  61. package/dist/core/ServiceTeardown.js.map +1 -1
  62. package/dist/core/StrikeRail.d.ts +3 -0
  63. package/dist/core/StrikeRail.d.ts.map +1 -1
  64. package/dist/core/StrikeRail.js +16 -1
  65. package/dist/core/StrikeRail.js.map +1 -1
  66. package/dist/core/TurnDispositionHandler.d.ts +3 -2
  67. package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
  68. package/dist/core/TurnDispositionHandler.js +48 -15
  69. package/dist/core/TurnDispositionHandler.js.map +1 -1
  70. package/dist/core/TurnMaterialization.d.ts.map +1 -1
  71. package/dist/core/TurnMaterialization.js +7 -1
  72. package/dist/core/TurnMaterialization.js.map +1 -1
  73. package/dist/core/TurnOps.d.ts.map +1 -1
  74. package/dist/core/TurnOps.js +4 -0
  75. package/dist/core/TurnOps.js.map +1 -1
  76. package/dist/core/TurnRunner.d.ts +0 -4
  77. package/dist/core/TurnRunner.d.ts.map +1 -1
  78. package/dist/core/TurnRunner.js +76 -101
  79. package/dist/core/TurnRunner.js.map +1 -1
  80. package/dist/core/TurnSources.sql +1 -1
  81. package/dist/core/ambient.sql +2 -2
  82. package/dist/core/packet-wire.d.ts.map +1 -1
  83. package/dist/core/packet-wire.js +67 -47
  84. package/dist/core/packet-wire.js.map +1 -1
  85. package/dist/core/results.d.ts +1 -0
  86. package/dist/core/results.d.ts.map +1 -1
  87. package/dist/core/results.js +7 -0
  88. package/dist/core/results.js.map +1 -1
  89. package/dist/core/turn-scheduler.js +1 -1
  90. package/dist/core/turn-scheduler.js.map +1 -1
  91. package/dist/core/turn-signals.d.ts +5 -0
  92. package/dist/core/turn-signals.d.ts.map +1 -1
  93. package/dist/core/turn-signals.js +6 -0
  94. package/dist/core/turn-signals.js.map +1 -1
  95. package/dist/core/unconcluded-emission.d.ts +7 -0
  96. package/dist/core/unconcluded-emission.d.ts.map +1 -0
  97. package/dist/core/unconcluded-emission.js +11 -0
  98. package/dist/core/unconcluded-emission.js.map +1 -0
  99. package/dist/core/unconcluded-emission.sql +14 -0
  100. package/dist/digest/DigestRender.d.ts +1 -0
  101. package/dist/digest/DigestRender.d.ts.map +1 -1
  102. package/dist/digest/DigestRender.js +18 -1
  103. package/dist/digest/DigestRender.js.map +1 -1
  104. package/dist/schemes/Log.d.ts.map +1 -1
  105. package/dist/schemes/Log.js +1 -0
  106. package/dist/schemes/Log.js.map +1 -1
  107. package/dist/server/Functionality.d.ts +1 -0
  108. package/dist/server/Functionality.d.ts.map +1 -1
  109. package/dist/server/Functionality.js +7 -4
  110. package/dist/server/Functionality.js.map +1 -1
  111. package/dist/server/Retention.d.ts.map +1 -1
  112. package/dist/server/Retention.js +2 -0
  113. package/dist/server/Retention.js.map +1 -1
  114. package/dist/server/Retention.sql +5 -0
  115. package/dist/server/logEntry.sql +2 -2
  116. package/dist/service.d.ts.map +1 -1
  117. package/dist/service.js +4 -1
  118. package/dist/service.js.map +1 -1
  119. package/docs/copy-move.md +6 -6
  120. package/docs/env.md +9 -14
  121. package/docs/members.md +28 -23
  122. package/docs/skills.md +22 -22
  123. package/migrations/006_log.sql +10 -4
  124. package/package.json +162 -163
package/SPEC.md CHANGED
@@ -496,7 +496,7 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
496
496
  | `READ` | existing literal name | Collect the named worker's deliverable. |
497
497
  | `KILL` | existing literal name | Terminate the named worker or caller. |
498
498
 
499
- - §worker-scheme-spawn **Spawn** — ```` ```WORK (worker://<name>)? ```` with a task body creates a new worker sister (empty log) and starts it with that task on its first loop. WORK/FORK are the worker-creation verbs: EDIT is file/entry only, so EDIT on the bare worker entity is a **400** steering to WORK/FORK — the entity is not an entry. Names remain unique within a workspace for the lifetime of retained Worker rows, including after termination. An existing name returns 409; concurrent claims cannot redirect a published address or expose a raw uniqueness failure.
499
+ - §worker-scheme-spawn **Spawn** — ```` ```WORK (worker://<name>)? ```` with a task body creates a new child worker (empty log) and starts it with that task on its first loop. WORK/FORK are the worker-creation verbs: EDIT is file/entry only, so EDIT on the bare worker entity is a **400** steering to WORK/FORK — the entity is not an entry. Names remain unique within a workspace for the lifetime of retained Worker rows, including after termination. An existing name returns 409; concurrent claims cannot redirect a published address or expose a raw uniqueness failure.
500
500
  - §worker-spawn-prompt-resource **The spawn slot is overloaded by scheme.** A `worker://` path is
501
501
  the child's address and keeps the address rules ({§worker-control-addressing}). A path of any
502
502
  other scheme is the child's prompt resource: it is read whole (`<1,-1>`) under the caller's read capabilities, composed with
@@ -506,9 +506,9 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
506
506
  resource with no body is `422 spawn-prompt-empty`. Naming the child and giving a resource in one
507
507
  statement is not expressible; the body can READ the resource instead. Taught in the deep
508
508
  reference only.
509
- - §worker-scheme-irc **irc** — ```` ```SEND (worker://<name>) ```` with a message body delivers it to an existing sister, the **voice door** ({§actor-boundary-two-doors}): an active sister folds it into its next turn, an idle one wakes ({§actor-boundary-passive-wake}). A fresh receiving loop retains that worker's durable model, spawn override, and reasoning policy; the sender and daemon default do not re-select it. The caller addresses itself by its literal name; a literal name with no worker in the workspace is 404.
509
+ - §worker-scheme-irc **irc** — ```` ```SEND (worker://<name>) ```` with a message body delivers it to an existing worker, the **voice door** ({§actor-boundary-two-doors}): an active worker folds it into its next turn, an idle one wakes ({§actor-boundary-passive-wake}). A fresh receiving loop retains that worker's durable model, spawn override, and reasoning policy; the sender and daemon default do not re-select it. The caller addresses itself by its literal name; a literal name with no worker in the workspace is 404.
510
510
  - §worker-scheme-fork **Fork** — ```` ```FORK (worker://<name>)? ```` with a task body branches the
511
- current worker into a **named** sister: its log is deep-copied
511
+ current worker into a **named** child: its log is deep-copied
512
512
  ({§machine-processes-fork-copies-the-log}), which continues with `task`; the
513
513
  world is shared, never copied ({§machine-processes-fork-shares-the-world}).
514
514
  WORK and FORK are distinct verbs — WORK spawns a fresh worker, FORK branches
@@ -527,8 +527,9 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
527
527
  parent as an `_plurnk` READ of `ops://<name>/<sequence>` ({§loop-answer}), not a message,
528
528
  and that row carries what the child said.
529
529
  The occurrence retains that loop's exact terminal result; the READ uses ordinary
530
- bounded projection. Its body, when present, is initially visible. Replies are
531
- independent deliveries ({§message-reply-delivery}), never copied into this outcome. Failures and
530
+ bounded projection of {§loop-answer}. The original delegated answer reaches the
531
+ parent here, not as a duplicate reply ({§message-reply-delivery}); other message
532
+ replies remain independent deliveries. Failures and
532
533
  cancellations retain their exact status, Problem, and visible explanation,
533
534
  including a spawn that fails before its first turn. Observation and wake-up
534
535
  follow {§env-delta-child-termination}; a later child loop cannot replace the
@@ -632,7 +633,7 @@ and never re-fetch a match.
632
633
  project file is exactly one of three things: **invisible**, **added**, or **tracked
633
634
  by git**. There is no fourth category. Membership — what the model can READ and
634
635
  FIND, what is materialized into the store, what a packet can ship to a provider — is
635
- the allowlist `(tracked ∪ include) − exclude` and nothing else. No file is a member because
636
+ the allowlist `(tracked ∪ include ∪ created) − exclude` and nothing else. No file is a member because
636
637
  it exists on disk, because git does not ignore it, or because a model would find it
637
638
  convenient: ambient admission of untracked files is prohibited, so a workspace rooted
638
639
  in a home directory or a monorepo exposes exactly what was committed or added (the
@@ -1023,7 +1024,7 @@ boundary.
1023
1024
  - §worker-lifecycle-wake-liveness **A stream conclusion always reaches its worker.** The stream first persists its terminal state. A worker **blocked on a 202 wait** for that stream ({§wait-obligation-matrix}) then **awakens that loop in place** — the blocked loop *is* the continuation, so there is no fresh loop and no summary-as-prompt fiction. An already-active worker needs no injected prompt or second wake because its next packet reads the durable terminal state. A concluded worker receives no synthetic loop from ambient stream closure. The result remains available in the stream's own state under every case.
1024
1025
  - §worker-lifecycle-child-wake **Each child task completion notifies its parent.** Terminal-task publication, including failure and cancellation of a parked task, notifies the direct parent without injecting a prompt. Other unfinished tasks or streams in that child remain independent obligations; they cannot suppress notification. The parent's eligible waits requeue in place under {§loop-wake-identity} and the bounded {§worker-optimistic-settlement} opportunity. Durable revisioning covers completion-before-park and restart; drain teardown and whole-worker quiescence are not completion identities.
1025
1026
  - §worker-optimistic-settlement **Asynchronous settlement receives one bounded worker-local opportunity before model dispatch.** An initiating turn lets only the streams it started settle before program completion; separately, a stream conclusion, direct-child conclusion or addressed reply persists and publishes immediately but holds eligible parked loops' `202→100` requeues while another stream or direct child remains live. Both use `PLURNK_SERVICE_OPTIMISTIC_WAIT_MS`, shipped at five seconds; zero disables the opportunity. The wake hold ends as soon as no sibling obligation remains, never extends its original deadline, and coalesces arrivals within that window into at most one requeue per eligible loop. With no sibling obligation the wake is immediate; at the deadline, surviving work follows the ordinary monitored lifecycle. An arrival after provider dispatch begins retains its next wake, while poll, new-request and operator wakes never open this hold. Only packet/provider dispatch waits: durable state, client events, cancellation and the replying program do not. One redaction-safe span records elapsed time, quiescence versus deadline, and arrival count without entering the packet.
1026
- - §worker-lifecycle-idle-is-concluded **Idle is not unanswered.** An empty WAIT continues; an answered, observed program without held work concludes under {§wait-obligation-matrix}. A concluded worker retains durable history; a later addressed arrival starts a new loop.
1027
+ - §worker-lifecycle-idle-is-concluded **Idle is not unanswered.** An empty WAIT continues; an eligible final response with answered messages, observed results and no held work concludes under {§wait-obligation-matrix}. A concluded worker retains durable history; a later addressed arrival starts a new loop.
1027
1028
  - §worker-lifecycle-no-lost-loop **A loop is never stranded by a drain's exit.** A drain relinquishes its registry slot only after a lock-held re-claim confirms the queue is empty; a loop enqueued during that teardown is either re-claimed by the exiting drain or claimed by a fresh drain that a later inject starts. The relinquish and the start are serialized, so neither the lost-loop hang nor a transient double-drain can occur.
1028
1029
  - §worker-lifecycle-durable-disposition **Durable disposition wins cancellation races.** At a turn boundary, the engine reads the loop's durable status before interpreting a process-local abort. A committed `202` park survives a later daemon-shutdown signal; only a loop still durably running at `102` can be terminalized by that cancellation. Wake selection rechecks shutdown and worker cancellation before requeuing each parked loop.
1029
1030
  - §worker-lifecycle-restart-recovery **Restart is owner-loss reconciliation, not replay.** Before opening client transports, the service holds an exclusive database-adjacent daemon lock; a second live owner fails before touching SQLite, while a dead-PID crash claim is replaced atomically without a timeout lease. Boot preserves accepted `100` loops and restores their drains. A `102` loop belonged to a vanished drain/provider call, so it settles `500` with the interruption on its durable row—never replayed across an unknown effect boundary. Every pending physical provider request first settles as an error with absent usage and explicitly unknown cost; then its logical model call closes. Recovery never fabricates zero evidence. Every durable proposed operation likewise lost its process-local resolution waiter and settles as a visible `500 owner_vanished` occurrence rather than an unresolvable interrupt ({§proposal-list}). A pending client interaction also lost its exact awaiting operation, so boot removes the orphan instead of replaying work or inventing a response ({§client-interactions}). Every durable-open subscription belonged to a vanished callable: active channels become errored and its row closes `500`. A `202` continuation requeues on an unseen completion or when no live obligation remains. Otherwise it stays parked on surviving children; the drain restores inherited stream observation through the same guarded scheduler ({§worker-wait-timing}). Child terminalization wakes its parked parent on every outcome, including provider exceptions, cancellation, and restart interruption, recursively through the durable parent edges. These operations are idempotent, so an interrupted recovery safely repeats.
@@ -1082,6 +1083,7 @@ These are the complete strike sources:
1082
1083
  |---------------------|------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|
1083
1084
  | Hard result | An admitted non-execution operation or bounded parse-error status is `>= 400`, except the soft set `404`, `409`, `416`, `425`, `501`. | The originating failure row. |
1084
1085
  | Cycle | The executed operations and their observed results repeat under {§engine-cycle-evidence}. | None; cycle detection itself is private engine accounting. |
1086
+ | Empty turn | An admitted turn with no authored response operation ({§empty-turn}). | The turn's `422` error row, and its reasoning read back ({§reasoning-empty-turn-read}). |
1085
1087
 
1086
1088
  Execution results remain exact model-visible evidence but are always soft: an
1087
1089
  executor error is not a PLURNK contract violation. Cycle detection remains an
@@ -1100,11 +1102,18 @@ are excluded from results; the complete note body still distinguishes activity.
1100
1102
  irrelevant; operation and array order are preserved. Only the configured
1101
1103
  `MIN_CYCLES × MAX_CYCLE_PERIOD` history window is retained. Repeated addresses
1102
1104
  alone are not a cycle: changing inputs or observations distinguish activity.
1105
+ A turn that executed nothing has no activity to identify, so an empty turn's
1106
+ identity is its **text** ({§empty-turn}) — the same principle, applied to the only
1107
+ output it produced. Identifying it by its absent program instead makes every empty
1108
+ turn identical, and changing words then read as a repeating one.
1103
1109
  This is an exact-repetition backstop, not a semantic judgment of task progress;
1104
1110
  new asynchronous invocation identities do not prove repetition of their eventual
1105
1111
  effects. Ordinary contract strikes and operator budgets remain independent.
1106
1112
 
1107
- §provider-recovery **A recoverable provider failure never ends a loop.** When a model
1113
+ §provider-recovery **A recoverable provider failure never ends a loop.** An isolated BARE
1114
+ call ({§bare-inference}) takes the same recovery as the loop's own inference: each re-issue
1115
+ is its own model call on the ledger, and a spent window leaves the operation's result as the
1116
+ provider's exact failure. When a model
1108
1117
  call fails with a network failure, rate limit, deadline, or interrupted resource after
1109
1118
  the provider's own retries, the turn records the exact Problem as a `_plurnk` row,
1110
1119
  notices the client (`engine:provider` / `provider_unavailable`), waits with
@@ -1137,7 +1146,7 @@ The contracts, and the violation of each that strikes:
1137
1146
  | Contract | Violation that strikes |
1138
1147
  |---|---|
1139
1148
  | operation contract | a hard operation failure (status ≥ 400) in an admitted turn — soft statuses below excluded |
1140
- | review contract | none: answered work joins live obligations ({§completion-joins-live-work}) or continues to observe results ({§completion-defers-to-results}) |
1149
+ | review contract | none: an eligible final response joins live obligations ({§completion-joins-live-work}) or continues to observe results ({§completion-defers-to-results}) |
1141
1150
  | progress contract | a detected operation cycle (`MIN_CYCLES` × period), or an admitted turn with no operation ({§empty-turn}) |
1142
1151
  | frame contract | emission attempts exhausted with no admissible turn |
1143
1152
  | provider response contract | the provider returned an invalid response |
@@ -1156,6 +1165,17 @@ independent turn ceiling terminates at **429** ({§loop-terminals}). The streak
1156
1165
  and cycle verdict are absent from model packets; only the concrete occurrences
1157
1166
  in the table are shown. The streak never leaves the daemon.
1158
1167
 
1168
+ A crossing terminal names the source that struck the crossing turn — `repetition`,
1169
+ `no_operation`, then `operation` — in its detail, in that order when a turn matches more
1170
+ than one. The three are not interchangeable: a turn that authored no operation did not *fail*
1171
+ one, and reporting it as a failed turn misreads a model answering without the fence as a model
1172
+ whose operations broke. This is the crossing turn's source, not the streak's composition; the
1173
+ rail rules on the crossing and does not retain the kinds behind it. What the crossing turn
1174
+ actually said is cited, not discarded ({§terminal-evidence}). Naming the source is not the
1175
+ private accounting {§rail-accounting-private} withholds: the streak, the cycle verdict and
1176
+ attempt counts stay inside the daemon — this is the terminal telling the truth about its own
1177
+ cause, which the reader already sees the shape of.
1178
+
1159
1179
  §loop-rail-continuity Rail state belongs to the durable loop, not its execution
1160
1180
  segment. The strike streak and bounded cycle history survive driver cleanup and
1161
1181
  restart; curation of log evidence cannot alter them.
@@ -1204,7 +1224,21 @@ Three current entry points:
1204
1224
 
1205
1225
  ### §emission-admission Provider emission admission
1206
1226
 
1207
- A completed provider exchange is an **emission attempt**, not necessarily an engine turn. **The harness admits every program whose meaning it can determine, runs what it admitted, and reports — never refuses — what it could not read**; a refusal is for undecidable text alone. ANTLR admits at least one parsed source operation. WAIT is optional under {§turn-shape}; omission invents no operation, diagnostic, warning or strike; any number of WAITs are one park, scheduled last ({§disposition-anywhere}), and statements after them remain admitted in authored order. Bounded operation errors retain useful siblings and participate in the ordinary struck turn. An unfinished heading slot ({§unparsed-tail-boundary}) refuses only what follows it: the statements that closed before it run, and the loss is one more hard diagnostic — a failed row with the lexer's own reason; an exchange that lost its boundary before any statement closed has nothing admissible and is rejected. A missing closer never rejects ({§closer-fallback}). An exchange with no operation and no other hard error is not rejected: it is admitted as an empty turn ({§empty-turn}). Parser warnings remain admissible. `finish=length` is evidence of likely truncation, not an independent rejection rule. Provider-declared interruption never reaches admission ({§provider-interrupted-attempt}). Accepted source bytes and statement positions remain exact in response evidence and `turnOps`. Execution follows {§op-execution-order}.
1227
+ A completed provider exchange is an **emission attempt**, not necessarily an engine turn.
1228
+ The parser owns its boundaries; core admits determinate work and exposes its failures.
1229
+
1230
+ | Parsed response | Admission |
1231
+ |---|---|
1232
+ | Bounded program, including malformed operations | Admit valid operations and record parser failures; with no authored operation, apply {§empty-turn}. |
1233
+ | Outside response text | Keep it as the model's NOTE under {§response-text-note}; never deliver it or infer completion. |
1234
+ | Lost boundary after a closed operation | Admit the closed operations and record the boundary diagnostic under {§unparsed-tail-boundary}. |
1235
+ | Lost boundary before any closed operation | Reject the attempt; neither outside text nor a reasoning NOTE substitutes for a closed response operation. |
1236
+
1237
+ Warnings and closer recovery ({§closer-fallback}) do not reject. `finish=length`
1238
+ discloses truncation and precludes completion; it is not independently a rejection.
1239
+ Provider interruption is owned by {§provider-interrupted-attempt}. Accepted source
1240
+ and positions remain exact; execution follows {§op-execution-order}. WAIT remains
1241
+ optional, with no omission warning or invented operation ({§turn-shape}).
1208
1242
 
1209
1243
  §safe-uri-target-groups After source and authored-command admission, Core tolerates one target group on READ or KILL only when splitting its raw target at top-level comma or whitespace separators produces at least two members and every member independently parses as an explicit `scheme://` URI. Request-metadata blocks are opaque to this split. Each member becomes one ordinary statement with an independent dispatch outcome and log row, in authored member order at that operation's position under {§op-execution-order}. Otherwise the target remains exactly singular, including local filenames containing spaces or commas. The stored `turnOps` and authored command count remain unexpanded, and no other operation admits target groups.
1210
1244
 
@@ -1481,14 +1515,14 @@ Registration precedes loop affinity:
1481
1515
  | Registered but inactive under flag | The flag gate returns `403 scheme-unavailable`. |
1482
1516
  | Registered and active | Dispatch continues to the operation owner. |
1483
1517
 
1484
- - §op-execution-order **An admitted turn is an ordered program.** Model, client, and harness operations execute in authored order. Only WAIT is deferred until all other admitted operations settle or establish their explicitly asynchronous work ({§disposition-anywhere}). The complete program then settles under {§wait-obligation-matrix}, whether or not it contains WAIT; no completion operation or inventory is invented. Existing cycle, no-operation, and resource rails remain effective. An observation records the resource state at its execution point; the model sees that receipt in the next packet. Exact submitted source and actual operation outcomes remain durable. Earlier successful effects survive a later operation failure; a producer requesting fail-on-error stops before subsequent operations.
1518
+ - §op-execution-order **An admitted turn is an ordered program.** Model, client, and harness operations execute in authored order. WAIT and parameterless KILL are deferred until all other admitted operations settle or establish their explicitly asynchronous work ({§disposition-anywhere}). The complete program then settles under {§wait-obligation-matrix}, whether or not it contains a lifecycle request; no completion operation or inventory is invented. Existing cycle, no-operation, and resource rails remain effective. An observation records the resource state at its execution point; the model sees that receipt in the next packet. Exact submitted source and actual operation outcomes remain durable. Earlier successful effects survive a later operation failure; a producer requesting fail-on-error stops before subsequent operations.
1485
1519
 
1486
1520
  §bare-inference **BARE is isolated, synchronous retrieval over the durable child-provider policy.**
1487
1521
 
1488
1522
  | Boundary | Contract |
1489
1523
  |---|---|
1490
1524
  | Prompt | A resource path, an inline body, or both ({§bare-statement}). The sole user message contains the complete addressed READ representation followed by the body, separated by two newlines when both are nonempty. Resource resolution occurs at the operation's execution point through {§universal-read-composition}, including source preparation, identity, channel selection, and retained log lines. No preview limit, presentation prefixes, or extra READ receipt. |
1491
- | Admission | Ordinary {§capability-admission} checks BARE execution and, for a path, source observation before acquisition or inference. An unsuccessful source result becomes the BARE receipt unchanged; the inline tail is not a fallback. Empty combined text yields 422 `bare-prompt-empty`. Neither refusal creates a model call. |
1525
+ | Admission | Ordinary {§capability-admission} checks BARE execution and, for a path, source observation before acquisition or inference. An unsuccessful source result becomes the BARE receipt unchanged; the inline tail is not a fallback. Empty combined text yields 422 `bare-prompt-empty`, whose detail names where a prompt goes: the fence body, a resource path, or both, never the aside. Neither refusal creates a model call. |
1492
1526
  | Isolation | No inherited PLURNK packet, context, tools, GBNF, parser, or persistent child worker. Non-prompt call identity and accounting remain ordinary provider metadata. |
1493
1527
  | Provider | Exactly the loop's WORK/FORK child provider; durable inherit policy falls back to the parent. |
1494
1528
  | Execution | A contiguous group's prompt acquisition precedes model-call creation; interrupted acquisition leaves no unstarted inference records. Admitted calls acquire identities in authored order and launch concurrently under the loop cancellation signal. Core awaits the group and records results and notifications in authored order, regardless of completion order. An intervening operation is an execution boundary. |
@@ -1497,7 +1531,7 @@ Registration precedes loop affinity:
1497
1531
 
1498
1532
  - §op-synchronous **Decisive operations settle before the next operation.** The dispatcher awaits each operation and its proposal resolution. Work remains in flight only when the operation's contract deliberately creates concurrency: FORK, WORK, a stream-producing execution, and streaming READ after acquisition. Such a READ first establishes its durable subscription and returns `102`; a later operation may address that live owner. Dispatching an execution before KILL does not wait for the process to finish using a resource. KILL of a worker synchronously ends its live loops before disposition checks the pending set; physical scope cleanup remains asynchronous.
1499
1533
  - §edit-execution **One authored EDIT is one mutation.** Each EDIT resolves against current resource state when dispatch reaches it, owns its proposal when gated, and records its own resulting revision. No later EDIT is prepared or applied in advance. Numeric scopes address current coordinates; an earlier EDIT may change what those numbers select. Rejection applies only to that operation, not its successful siblings.
1500
- - §edit-anchor-continuity **Own EDITs preserve untouched hash targets within one program.** Core carries an anchor through exact, successfully applied EDIT splices when its line survives unchanged, even if its ordinal or neighborhood changes. Scoped entry KILL uses the same deletion path. Target-line replacement or deletion invalidates that binding. Continuity is private to the admitted program and canonical resource/channel; it is not a new published anchor format. The complete normalized line content must match the expected result of the preceding recorded EDIT, otherwise retained bindings are discarded and ordinary current-state validation applies. Reviewer replacement and results without an applied EDIT receipt do not carry bindings forward. Normalization is the same line-content representation used by READ and line hashing; file-write revision checks remain independent. No approximate text matching is used. Lowered coordinates retain a current-anchor precondition at the mutation owner; ambiguous matches and concurrent changes remain collisions.
1534
+ - §edit-anchor-continuity **Own EDITs preserve untouched hash targets within one program.** Core carries an anchor through exact, successfully applied EDIT splices when its line survives unchanged, even if its ordinal or neighborhood changes. Scoped entry KILL uses the same deletion path. Target-line replacement or deletion invalidates that binding. Continuity is private to the admitted program and canonical resource/channel; it is not a new published anchor format. The complete normalized line content must match the expected result of the preceding recorded EDIT, otherwise retained bindings are discarded and ordinary current-state validation applies. Reviewer replacement and results without an applied EDIT receipt do not carry bindings forward. A retained binding resolves alone: a twin neighbourhood this program's own splice created elsewhere does not make the carried anchor ambiguous, and an anchor the program never bound resolves against current state. Normalization is the same line-content representation used by READ and line hashing; file-write revision checks remain independent. No approximate text matching is used. Lowered coordinates retain a current-anchor precondition at the mutation owner; ambiguous matches and concurrent changes remain collisions.
1501
1535
  - §anchor-offset **An anchor offset is tolerated, never taught (#749).** A line mark may carry an offset from its anchor (`@abcde+1`, `@abcde-2`), and a bare `+N` after an anchor counts from that anchor (`<@abcde,+1>`). The anchor resolves as usual and the offset is added; a result before line 1 is an invalid mark, and past the end is the ordinary range refusal. Continuity and current-anchor preconditions check the anchor's own line. No teaching text, scope table or receipt mentions offsets; `plurnk.md` keeps its two anchor forms. A bare `+N` with no anchor before it is refused as before.
1502
1536
  - §edit-batch **One compound operation may require atomic splices.** The scheme's `editBatch` primitive validates all supplied numeric edits against one snapshot and commits one revision or none. Core supplies one statement for an authored EDIT; same-resource MOVE can supply multiple splices as one operation. This primitive does not group separate authored operations. Its replacement, insertion, conflict, and receipt rules remain owned by the shared Slicer.
1503
1537
  - §edit-batch-receipt **A refusal describes its own unapplied work.** An anchor collision lists every distinct unresolved anchor in that EDIT, including both range endpoints, in `unresolvedAnchors` (`anchor`, `kind: missing | ambiguous`, and matching `lines` when ambiguous). Missing is not proof of earlier validity or subsequent change. It carries `editCount: 1`, `applied: 0`, and recovery directing a READ for current coordinates; it makes no claim about other operations. A refused compound splice batch lists all conflicting pairs in `conflicts`, non-conflicting regions in `cleanRegions`, its first pair in `conflictingRegions`, and its own `editCount` and `applied: 0`.
@@ -2051,7 +2085,7 @@ same transitions the dispatcher's atomic curation event makes, without the row.
2051
2085
  |---|---|
2052
2086
  | Evidence | Original provider reasoning remains verbatim in immutable model-call responses and admitted packets. Resource and log operations never rewrite it. Only an admitted response, or the final exhausted emission attempt, produces a model reasoning source; missing provider reasoning creates no substitute. A non-model producer may record its own authored rationale under {§turn-source-resources}. |
2053
2087
  | Resource | `reasoning://<worker>/<loop>/<turn>` is immutable text/plain source belonging to the named workspace worker's turn under {§turn-source-resources}. Every workspace actor may READ, FIND, search and COPY from it; none may EDIT, KILL, COPY into or MOVE it. |
2054
- | Delivery | Initialization READs its own authored rationale under {§reasoning-initial-read}. Further observations require deliberate READs. The selected model reasoning source is stored before its OPs execute, so an ordinary READ of the current turn resolves immediately and is visible in subsequent packets. Every READ retains its authored scope and ordinary range metadata, without edit anchors. |
2088
+ | Delivery | Initialization READs its own authored rationale under {§reasoning-initial-read}, and an empty turn's reasoning is read back under {§reasoning-empty-turn-read}. Further observations require deliberate READs. The selected model reasoning source is stored before its OPs execute, so an ordinary READ of the current turn resolves immediately and is visible in subsequent packets. Every READ retains its authored scope and ordinary range metadata, without edit anchors. |
2055
2089
  | Curation | Scoped log KILL suppresses receipt lines; whole log KILL retires the receipt. Neither affects the source. Explicit log READs retain ordinary curation anchors. A mutable working copy requires ordinary COPY into an editable resource. |
2056
2090
  | Lifecycle | Restart retains sources and observations. FORK snapshots sources under the child's name at the same loop/turn coordinates and receipts with independent curation. No curation or lifecycle event automatically READs model reasoning. A turn the provider left without reasoning reads empty; absent workers and turns return the ordinary missing result ({§turn-source-resources}). |
2057
2091
  | Client | Standard live reasoning events and replay retain original provider reasoning; working resources and READ receipts never substitute for or replay that stream. |
@@ -2068,13 +2102,24 @@ manufacture a task inventory.
2068
2102
  `PLURNK_REASONING_VIEW_LINES` (default `-1`, alias-scoped) selects this one READ's
2069
2103
  scope: `0` omits it, `-1` reads the complete rationale, and a positive integer
2070
2104
  bounds it to the first N lines. Source retention, deliberate READs, and client
2071
- streaming are independent. No later turn automatically requests reasoning.
2105
+ streaming are independent. The only other automatic reasoning READ follows an empty
2106
+ turn ({§reasoning-empty-turn-read}).
2107
+
2108
+ §reasoning-empty-turn-read **An empty turn's reasoning is read back to the model.** After a
2109
+ turn admitted under {§empty-turn}, one runtime turn of the same loop
2110
+ (`{ producer="_plurnk", kind="operation" }`) dispatches
2111
+ `READ (reasoning://<worker>/<loop>/<turn>) <!-- turn N emitted no OP -->` over that turn's stored
2112
+ reasoning source; its receipt renders in the next packet like any other log row.
2113
+ `PLURNK_REASONING_EMPTY_TURN_LINES` (default `-1`, alias-scoped) selects the scope on the same
2114
+ scale as `PLURNK_REASONING_VIEW_LINES`. No read follows a turn without reasoning, and none follows
2115
+ a turn whose emission or reasoning carries a foreign tool-call grammar ({§response-text-note});
2116
+ the strike and its error row are unchanged.
2072
2117
 
2073
2118
  ### §log-kill-scope KILL on the log: whole items and scoped bodies
2074
2119
 
2075
2120
  AST: `{ op: "KILL", target, matcher: MatcherBody | null, lineMarker: TextLineMarker | null, body: null }` ({§kill-scope} and {§matcher-option} in the contracts SPEC own the grammar).
2076
2121
 
2077
- KILL deletes context from the **log** (`log:///`, {§packet}). Without a scope it retires the selected rows from the active projection ({§log-history-projection}). With a one-line or inclusive two-line scope it removes only that body's intersecting body-relative physical lines from the readable projection, and the row stays active. An anchor may be one published on that body or one returned by READing its `log:///` coordinate ({§line-anchors}); an anchor absent from the current body selects no line, as with an out-of-bounds numeric line. Scoped KILL is one-way: intervals accumulate, the durable body is untouched, and subsequent access follows {§log-readable-projection}. A scoped KILL on a bodyless row is a friendly 200 no-op with `matched` reported. A KILL that addresses no row is 404 on an exact coordinate and 204 on a sweep ({§log-curation-folder-idiom}). Selection composes target/glob with an optional heading pattern ({§log-curation-set-selection}); a targetless KILL is 400.
2122
+ KILL deletes context from the **log** (`log:///`, {§packet}). Without a scope it retires the selected rows from the active projection ({§log-history-projection}). With a one-line or inclusive two-line scope it removes only that body's intersecting body-relative physical lines from the readable projection, and the row stays active. An anchor may be one published on that body or one returned by READing its `log:///` coordinate ({§line-anchors}); an anchor absent from the current body selects no line, as with an out-of-bounds numeric line. Scoped KILL is one-way: intervals accumulate, the durable body is untouched, and subsequent access follows {§log-readable-projection}. A scoped KILL on a bodyless row is a friendly 200 no-op with `matched` reported. A KILL that addresses no row is 404 on an exact coordinate and 204 on a sweep ({§log-curation-folder-idiom}). Selection composes target/glob with an optional heading pattern ({§log-curation-set-selection}). Parameterless KILL instead requests completion ({§kill-conclusion}).
2078
2123
 
2079
2124
  A READ carrying active native media is atomic: any KILL scope is ignored and the entire observation is retired, including its native context contribution ({§packet-attachment-parts}). For a model turn, native activity is the attachment selection in its actual input packet; without a model packet, a native observation is atomic by default. Text-only observations in the same selection retain ordinary scoped behavior. Neither form deletes source data or forensic evidence.
2080
2125
 
@@ -2105,21 +2150,29 @@ type and projection facts under {§read-bytes}.
2105
2150
  The `## Log` section is a sequence of ordinary Markdown records separated by one blank line:
2106
2151
 
2107
2152
  ```text
2108
- ### log:///<loop>/<turn>/<item>/<leaf>
2109
- {"oneLine":"strict JSON metadata"}
2153
+ ### log:///<loop>/<turn>/<item>/<leaf> · <logTokens>
2154
+ OP (operands) <marks> [metadata] <!-- aside -->
2155
+ {"oneLine":"strict JSON result facts"}
2110
2156
  <coordinate-prefixed body lines when visible>
2111
2157
  ```
2112
2158
 
2113
- The H3 is the row's complete model-facing identity and canonical READ address; metadata never repeats that identity or its operation. The following line is one strict JSON object: addressed operands ({§log-address-metadata}) precede `aside`, then all remaining members use stable alphabetical order. Absent fields are not invented. Every physical body line retains its canonical numeric `N:` or anchored `@hash N:` coordinate, so source text cannot create a record boundary. The section contains records only, with no leading prose or enclosing fence.
2159
+ | Line | Content | Rule |
2160
+ |---|---|---|
2161
+ | H3 | The row's complete model-facing identity and canonical READ address, then ` · ` and its `logTokens` charge ({§packet-token-accounting}). | Always present; nothing else repeats the identity, the operation, or the charge. |
2162
+ | written | The request as the language writes it ({§heading-slot-order}): the operation or runtime, every operand in the packet's canonical spelling ({§log-address-metadata}), marks, metadata blocks, matcher, aside. No fence, no body. | Present for every operation and execution row; absent on `error` and `extension` rows. |
2163
+ | facts | One strict JSON object of result facts in stable alphabetical order. | Present only when a fact exists; it never re-encodes the written line. |
2164
+ | body | Coordinate-prefixed lines. | Present when the row is visible. |
2165
+
2166
+ The written line is the model's own request, so a matcher such as `/\bhello\b/i` returns exactly as it was written, never JSON-quoted. Absent fields are not invented. Every physical body line retains its canonical numeric `N:` or anchored `@hash N:` coordinate, so source text cannot create a record boundary. The section contains records only, with no leading prose or enclosing fence.
2114
2167
 
2115
2168
  §log-address-metadata **Addresses name their relationship, not the row's producer.**
2116
2169
 
2117
- | Metadata | Meaning | Order |
2170
+ | Spelling | Meaning | Where |
2118
2171
  |---|---|---|
2119
- | `path` | The operation's addressed operand, matching `OP (path)`: read resource, mutation subject, message recipient, or executor operand. Explicit and automatic READs use the same field. Pathless operations omit it. | First |
2120
- | `from`, `to` | COPY/MOVE's two operand selections, each retaining its optional scope; neither replaces actor attribution or is repeated as `path`. | First, in that order |
2121
- | `stream` | An executor invocation's separately created output address, never a READ's alternative spelling of `path`. | Remaining facts |
2122
- | `resource` | A distinct returned resource under {§operation-resource-receipt}. | Remaining facts |
2172
+ | `OP (path)` | The operation's addressed operand: read resource, mutation subject, message recipient, or executor operand. Explicit and automatic READs are written identically. Pathless operations are written bare. | Written line |
2173
+ | `COPY (from) <marks> (to) <marks>` | COPY/MOVE's two operand selections, each retaining its optional scope; neither replaces actor attribution. | Written line |
2174
+ | `stream` | An executor invocation's separately created output address, never a READ's alternative spelling of its operand. | Facts |
2175
+ | `resource` | A distinct returned resource under {§operation-resource-receipt}. | Facts |
2123
2176
 
2124
2177
  Nested mutation effects and delivered attachments name their resource with `path`.
2125
2178
  These packet spellings do not rename the submitted AST, durable operation results,
@@ -2186,7 +2239,7 @@ Field absence carries defaults: `origin` is omitted for the owning model, `sourc
2186
2239
  records the exact READ coordinates sent without controlling retention. Missing immutable bytes are an
2187
2240
  internal integrity failure, never silently dropped content. No ejection message or permanent teaching is
2188
2241
  added. These stable curation weights are not provider-token measurements ({§tokenomics-render-weight-budget}).
2189
- - §packet-token-accounting Every row reports one `logTokens` charge: its complete materialized H3, metadata, visible body, and selected native attachment. The completed record is measured to a fixed point, including the accounting field itself. No `tokensBody`, `tokensMetadata`, or `tokensActive` field is serialized. Hidden text is not charged; metadata-only rows still have a reclaimable charge. Source/FIND-item `tokens` measure source content, not the observation's context footprint. A FIND's nonzero `itemsTokenTotal` weighs the complete matched set; a nonzero `returnedItemsTokenTotal` appears only when the returned page differs. All use stable curation weights, not provider tokens or dollars. Native component accounting follows {§packet-attachment-parts}; ordinary addressability and truthful errors follow {§log-wire-format}.
2242
+ - §packet-token-accounting Every row reports one `logTokens` charge on its H3 ({§log-wire-format}): its complete materialized H3, written request, facts, visible body, and selected native attachment. The completed record is measured to a fixed point, including the accounting field itself. No `tokensBody`, `tokensMetadata`, or `tokensActive` field is serialized. Hidden text is not charged; metadata-only rows still have a reclaimable charge. Source/FIND-item `tokens` measure source content, not the observation's context footprint. A FIND's nonzero `itemsTokenTotal` weighs the complete matched set; a nonzero `returnedItemsTokenTotal` appears only when the returned page differs. All use stable curation weights, not provider tokens or dollars. Native component accounting follows {§packet-attachment-parts}; ordinary addressability and truthful errors follow {§log-wire-format}.
2190
2243
 
2191
2244
  ### §retrieval-packet-metadata READ/FIND packet metadata
2192
2245
 
@@ -2250,7 +2303,7 @@ single line past the end, a reversed range, empty content, a command's log row
2250
2303
  §rejected-emission-entry A rejected provider response is not `turnOps`: it never became an admitted turn program. The one bounded invalid-emission recovery item under {§emission-admission} has `attrs.kind="emissionAttempt"`, `origin="model"`, the canonical model-facing `/attempt` leaf, and the exact latest rejected response. The packet does not duplicate that identity as `kind` metadata. It is born durably body-suppressed and projected visibly only in the informed recovery packet; every other rejected attempt remains forensic-only.
2251
2304
 
2252
2305
  - §log-coordinate-hierarchy **Log coordinates are a hierarchical prefix; the trailing slash is optional** — a coordinate is `loop/turn/sequence`, and a PARTIAL coordinate selects its descendants: `log:///1` = loop 1's rows, `log:///1/2` = turn 1/2's rows, `log:///1/2/3` = the one row. A full coordinate is always three parts, so a one- or two-part path is unambiguously a prefix — the trailing slash is an optional alias (`log:///1/2` ≡ `log:///1/2/`), uniform with ```` ```READ (worker:///docs/) ````. A complete `[start-end]` segment in any numeric coordinate slot selects that inclusive decimal interval; brackets elsewhere retain ordinary path-glob meaning. Every rendered row appends one canonical model-facing leaf: the native operation name or invoked executor name, `/attempt` for a rejected emission. An executor leaf is derived from the durable submitted statement (its `runtime`), never an internal dispatch type or the current tool registry. Digits and punctuation in executor names remain part of the leaf. The leaf names identity rather than adding a resource level. Exact consumers tolerate the unsuffixed three-part shorthand; when supplied, the case-insensitive leaf is authoritative and a disagreement resolves 404. READ anchors use the canonical suffixed identity even when addressed by shorthand. Typed entry materialization therefore resolves as `/READ` while retaining its durable `EDIT` event ({§exec-entry-sink}). `log:///1/2/*` still selects the turn's item rows, while `log:///**/READ`, `log:///**/python3`, and `log:///**/attempt` deliberately filter canonical leaves. Executor outputs instead use workspace-wide claims such as `sh:///ab3d5678#stdout` ({§execution-output-identity}); their source operation has log coordinates, but resource lifetime and identity are independent of that observation. Error pointers, Problem instances, source attribution, and search use this same identity; client stream coordinates retain the numeric triple. Within a turn, sequence is arrival order. Inbound SEND rows publish before the program runs ({§message-arrival}); a turn receiving messages holds the first at `log:///L/T/1/SEND`, followed by further arrivals oldest first, then the model's operations ({§packet-current-turn} names `L/T`).
2253
- - §log-curation-folder-idiom **Log curation speaks the folder idiom; a zero-match sweep is a no-op success** — KILL takes a concrete coordinate or a path-glob, and a **trailing slash or a partial coordinate means "the contents"** ({§log-coordinate-hierarchy}), like a folder-scoped FIND: ```` ```KILL (log:///1/2) <1,-1> ```` suppresses turn 1/2's bodies. A **well-formed selection that matches nothing is 204 with `matched: 0`**; a successful sweep's rx carries `matched: N`. A targetless KILL is 400.
2306
+ - §log-curation-folder-idiom **Log curation speaks the folder idiom; a zero-match sweep is a no-op success** — KILL takes a concrete coordinate or a path-glob, and a **trailing slash or a partial coordinate means "the contents"** ({§log-coordinate-hierarchy}), like a folder-scoped FIND: ```` ```KILL (log:///1/2) <1,-1> ```` suppresses turn 1/2's bodies. A **well-formed selection that matches nothing is 204 with `matched: 0`**; a successful sweep's rx carries `matched: N`. Parameterless KILL instead requests completion ({§kill-conclusion}).
2254
2307
  - §log-curation-set-selection **Row selection and body scope are independent** — target/glob and an optional heading pattern (```` ```KILL (log:///**) [{"pattern": "~stale"}] ````, every dialect a FIND over rows accepts) compose by intersection into the affected row set. An optional `<L>` or `<SL,EL>` then intersects each selected canonical body; it never paginates or changes the selected set. Thus ```` ```KILL (log:///**/READ) <17,-1> ```` may change long READs and no-op on short ones while reporting every selected row in `matched`.
2255
2308
 
2256
2309
  §log-kill-meta-operation **A log KILL changes working context, never the underlying resources or execution history.** Receipt visibility depends on the target and result, not the producer, attribution, or age of the turn:
@@ -2559,7 +2612,7 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
2559
2612
  SEND AST: `{ op: "SEND", target: ParsedPath | null, body: SendBody | null, metadata, lineMarker }`.
2560
2613
 
2561
2614
  - **Message:** SEND delivers to an actor, endpoint or exact message address. Targetless SEND answers observed Open Messages.
2562
- - **Workflow:** WAIT yields; successful reply delivery and settled work permit completion at the end of the whole program. NOTE retains memory.
2615
+ - **Workflow:** WAIT yields. Parameterless KILL requests successful completion ({§kill-conclusion}). NOTE retains memory.
2563
2616
 
2564
2617
  §worker-obligations A worker holds its unresolved children and open non-detached
2565
2618
  streams (`worker_obligations`); `loop_obligations` names them per loop. The
@@ -2573,17 +2626,20 @@ same durable liveness.
2573
2626
  | Worker or loop already cancelled/terminal | Preserve that result. |
2574
2627
  | Administrative program | Finish its transaction without adjudicating another model loop's work. |
2575
2628
  | New unpublished message | Continue; publish it in the next packet. |
2576
- | Live work and either WAIT or no unanswered messages | Park the same loop; message arrival, child or stream settlement, or stream cadence wakes it. |
2577
- | WAIT without live work | Continue; never invent a future wake. |
2629
+ | Fresh operation/parser failure, without an authored WAIT | Continue before any automatic parking. |
2630
+ | Neither an authored WAIT nor an eligible completion request ({§kill-conclusion}) | Continue, regardless of earlier replies or live work. |
2631
+ | Live work and either WAIT or an eligible completion request | Park the same loop; message arrival, child or stream settlement, or stream cadence wakes it. No final-answer body is delivered while joining. |
2632
+ | WAIT without live work | Continue; never invent a future wake. The first such WAIT is an honest yield and its row says only `Nothing is in flight. Continuing.`; a second in the same loop is the model waiting on a wake nothing can send, so its own row instead names what WAIT is for and what to reach for — `WAIT doesn't wait unless there's a child worker or stream to wait on. Use schedule for specific timing decisions.` The correction rides the operation's own result, which is the surface the model is certain to read (operator, 2026-09-22). |
2578
2633
  | Unanswered messages | Continue. |
2579
2634
  | Unobserved operation results, failures, child results or stream conclusions | Continue; the next packet presents them. |
2580
- | No outstanding messages, live work or unobserved results | Conclude successfully, without a synthetic operation. |
2635
+ | Eligible completion request with no outstanding messages, live work or unobserved results | Conclude successfully. |
2581
2636
 
2582
- An empty emission is handled by {§empty-turn}, not this completion rule. Ordinary strikes,
2583
- cycles and execution limits remain independent. NOTE and successful KILL do not themselves
2584
- require another observation turn. Failed KILL and every other operational result do.
2637
+ An empty emission is handled by {§empty-turn}. Ordinary strikes, cycles and
2638
+ execution limits remain independent. NOTE and successful targeted KILL do not themselves
2639
+ require another observation turn, but neither requests completion. Failed KILL
2640
+ and every other operational result require observation.
2585
2641
 
2586
- §loop-response-messages **A response is a recorded delivery.** A successful SEND reply records
2642
+ §loop-response-messages **A response is a recorded delivery.** A successful SEND reply or admitted final KILL answer records
2587
2643
  the exact message addresses it answers. All replies remain independently recoverable in
2588
2644
  message history, in execution order, regardless of producer. An actor-addressed SEND that
2589
2645
  does not answer a message, WAIT, NOTE, asides, inherited rows and ambient observations are
@@ -2598,7 +2654,7 @@ conclusion carries its execution outcome under {§send-undelivered-child-term},
2598
2654
  | `NULL` | The model's own terminal or an engine verdict whose exact result already carries the story. | No authorship marker. |
2599
2655
  | `cancel` | The structured scope was explicitly cancelled, through the client or worker KILL ({§methods-loop-cancel}). | COLLECT and the termination delta prepend a cancellation marker to the exact Problem's presentation, so cancellation cannot masquerade as a deliverable. The model's prior log rows remain untouched. |
2600
2656
 
2601
- The engine's failure terminals — **500** (strike threshold) and **508** (cycle), {§engine-rails} — are never the model's to pick; they are the engine ruling the loop failed. The model answers, waits or cancels its scope; the engine derives the lifecycle outcome from that state.
2657
+ The engine's failure terminals — **500** (strike threshold) and **508** (cycle), {§engine-rails} — are never the model's to pick; they are the engine ruling the loop failed. The model answers, waits or cancels its scope; the engine derives the lifecycle outcome from that state. The ruling never softens, and it never destroys the evidence: every terminal cites what the model last left unconcluded ({§terminal-evidence}).
2602
2658
 
2603
2659
  Disposition outcomes follow {§wait-obligation-matrix},
2604
2660
  {§completion-joins-live-work}, and {§completion-defers-to-results}. Strike
@@ -2615,47 +2671,85 @@ accounting and model-visible failure evidence remain separately owned by
2615
2671
  answers its ordinary factual 501 without grafting a guessed recovery onto it.
2616
2672
  - §send-response-receipt **A reply records exactly which messages it answers.** A successful
2617
2673
  reply carries `answers`, the immutable message addresses it answered, not recipient actors. Targetless SEND
2618
- answers this loop's published, unanswered messages, oldest first. SEND to an exact message
2674
+ answers this loop's published, unanswered messages, oldest first. When none remain,
2675
+ a nonempty targetless SEND replies to the loop's original published message, so a
2676
+ follow-up can revise its answer. A targetless SEND with no body content or attachments
2677
+ delivers nothing, carries no `answers`, and cannot erase an earlier reply. An accepted
2678
+ parameterless KILL answer uses the same reply routing and empty-body rules. SEND to an exact message
2619
2679
  address answers only that message; SEND to an actor endpoint remains ordinary communication
2620
2680
  and answers no assignment implicitly. An unpublished arrival cannot be answered by the
2621
2681
  targetless shorthand. Failed delivery answers nothing. Reply accounting reads executed
2622
2682
  delivery evidence, never log visibility or the mere existence of a later SEND.
2623
- - §prose-conclusion **A markdown answer is the answer, and concluding is deliberate.** An admitted
2624
- response concludes only when it is wrapped whole in one `markdown` or `md` fence — the form
2625
- `plurnk.md` teaches — and has no operation, attempts none ({§operation-attempt}), was not cut at
2626
- the output allowance, is not empty, and says something outside its quotations ({§quotation}: a
2627
- reply that is nothing but quoted material is a misfenced program) (operator, 2026-09-18, #761;
2628
- fence required 2026-09-21). A response that merely failed to yield an operation is NOT an answer:
2629
- it is non-responsive and falls to {§empty-turn}, taking one strike while the loop continues. That
2630
- asymmetry is the point — a mis-fenced operation costs a turn, never the run, because a weak model
2631
- under pressure fences badly and a whole rollout must not end on a typo. An offset operation fence
2632
- is one of those quotations and disqualifies nothing: `plurnk.md` tells the model to offset an
2633
- example it does not intend to execute (operator, 2026-09-21). The engine
2634
- admits it as a targetless SEND whose body is the trimmed content, positioned on line 1. It
2635
- answers the open messages, reaches clients and a parent exactly as a SEND does, and meets the
2636
- completion barrier as a SEND does ({§completion-joins-live-work},
2637
- {§completion-defers-to-results}). Reasoning NOTEs ride with it. The model is taught
2638
- "respond without performing any OPs" and is never taught the SEND. A reply wrapped whole in one
2639
- `markdown` or `md` fence is delivered as that fence's content ({§quotation}). Its row is stored as the
2640
- SEND that delivers it (reply accounting, delivery and clients read SEND rows) but carries
2641
- `attrs.answer = "prose"` and `resource: ops://<worker>/<loop>`, and is addressed and rendered
2642
- under the leaf `answer` (`log:///1/2/2/answer`), never as a SEND the model did not write.
2683
+ - §kill-conclusion **Successful completion requires an explicit parameterless KILL.** The response
2684
+ contains exactly one KILL without a target, scope, matcher or metadata, no hard
2685
+ parse error or lost boundary, and was not cut at the provider's output allowance.
2686
+ The operation limit must admit the entire program.
2687
+ SEND, NOTE (outside text included, {§response-text-note}) and log-targeted KILL may
2688
+ accompany it; every other operation requires continuation. This tolerance is unadvertised:
2689
+ model teaching requests KILL alone. Reasoning-side NOTEs remain ordinary notes.
2690
+ An aside is allowed. After the program settles, {§wait-obligation-matrix} admits the
2691
+ completion or returns a non-striking continuation/parking receipt explaining the
2692
+ outstanding condition. Valid sibling operations always execute. Only an admitted
2693
+ KILL delivers its literal body through {§send-response-receipt}; a deferred body
2694
+ remains forensic evidence, never a stored draft to replay automatically. An empty
2695
+ KILL concludes without repeating an already-delivered answer, but cannot abandon an
2696
+ unanswered message. SEND, NOTE and targeted KILL never request successful
2697
+ completion. New arrivals still guard the terminal transition atomically
2698
+ ({§completion-defers-to-messages}); an arrival concurrent with an accepted reply
2699
+ remains unanswered and keeps the loop running. No implicit successful exit exists.
2700
+ - §response-text-note **Text outside the operations is the model's NOTE, never delivered.** Each
2701
+ span {§response-text} supplies becomes an ordinary NOTE in source order, unmarked, so the
2702
+ model's own log files its self-narration where it belongs. It is not an authored operation:
2703
+ {§empty-turn} still strikes a turn that holds only text, and the exact emission is retained.
2704
+ Delivered as a SEND, the text read as an answer and confirmed that speaking outside operations
2705
+ works; reported as a count of invalid characters, it sent a model to repair its prose into
2706
+ live operations (`demo-show-dont-run-qdN9u2` executed the KILL it meant to show). A NOTE
2707
+ neither delivers nor concludes (operator, 2026-09-22). Storing interstitial text is a
2708
+ privilege, not a right (operator, 2026-09-23): a span is retained only on a turn that
2709
+ executed at least one operation, and only when it is narration. An empty turn retains no
2710
+ NOTE, and on any turn a span that carries a known foreign tool-call grammar, a leaked
2711
+ template token, or an operation attempt outside its fence retains none either. The exact
2712
+ emission stays at `ops://`, and the packet never echoes the grammar that broke a turn for
2713
+ the next turn to imitate. The registers are mechanism (`KnownToxins`). This is the far end of the teaching
2714
+ scale: text outside every operation breaks the first rule of `plurnk.md` — *"YOU MUST ONLY
2715
+ use valid Plurnk OPs"* — and takes the largest reinterpretation, while a
2716
+ departure as small as a missing closer is read as meant ({§closer-fallback}).
2643
2717
  - §loop-answer **A loop's address is what it said.** READ `ops://<worker>/<loop>` resolves to
2644
- the latest reply the loop gave to the message that started it: a prose conclusion's text or
2645
- the body of a SEND that targeted that message. A running loop without one is 425; a loop that
2646
- ended without one is its terminal problem (404 when it ended 2xx). `ops://<worker>/<loop>/<turn>`
2647
- remains that turn's emission. A concluded child's `loop_termination` row to its parent carries
2648
- `answer: ops://<child>/<loop>` beside its status. Witness: `test/intg/loop-answer.test.ts`.
2649
- - §empty-turn **A response with no operation that is not an answer is a turn, not a retry.**
2650
- When the parser finds no operation and no other hard error, and the response is not an
2651
- answer under {§prose-conclusion} — an operation attempt, prose cut at the output allowance,
2652
- or an empty response — it is admitted as an empty turn (operator, 2026-09-12): its text and
2653
- reasoning are stored like any turn's (`ops://<worker>/`, `reasoning://<worker>/`), the model's own message
2654
- stays in the next packet's history, that packet carries one `turn_no_operations` notice and
2655
- any {§bare-heading-advisory} notices, the turn continues at 102, and the strike rail counts
2656
- one progress-contract strike, so a model that only talks strikes out at the ordinary
2657
- threshold instead of being resampled three times on an identical packet. Its fingerprint is
2658
- the empty program, so repeated empty turns also trip cycle detection.
2718
+ the latest reply the loop gave to the message that started it: the body of a SEND
2719
+ or accepted final KILL that answered that message. A running loop without one is 425; a loop that
2720
+ ended without one is its terminal problem (404 when it ended 2xx) — and that problem cites what
2721
+ the model last left unconcluded, so the loop's own address never reports silence from a loop that
2722
+ spoke ({§terminal-evidence}). `ops://<worker>/<loop>/<turn>`
2723
+ remains that turn's emission. A concluded child's `loop_termination` row to its parent
2724
+ READs this same loop resource. Witness: `test/intg/loop-answer.test.ts`.
2725
+ - §empty-turn **No authored response operation is a recoverable turn, never completion.**
2726
+ Count parsed response operations before outside-text and reasoning NOTEs join them;
2727
+ neither enters the count. When none exist and no boundary was lost, retain the turn and its raw
2728
+ sources and count one progress-contract strike, whether or not the turn carried text
2729
+ ({§response-text-note}). The strike sends no notice of its own: the turn records one `_plurnk`
2730
+ error row, `422` `The turn performed no operation.`, which rides the next packet's errors like
2731
+ any failure ({§operation-result-uniform-error-channel}), and its reasoning is read back to the
2732
+ model under {§reasoning-empty-turn-read}; the threshold terminal still says why ({§engine-rails}).
2733
+ An empty turn uses its exact text as the cycle fingerprint ({§engine-cycle-evidence});
2734
+ different empty programs are not a repeated cycle merely because neither contained
2735
+ operations. Lost-boundary handling remains {§unparsed-tail-boundary}; no confirmation
2736
+ token or private retry is invented here.
2737
+ - §terminal-evidence **A terminal rules the loop over; it does not decide the model said nothing.**
2738
+ Every engine terminal — strike threshold (500), cycle (508), turn ceiling (429), loop timeout
2739
+ (504), provider unavailable ({§provider-recovery}) — keeps its status and its authorship: the
2740
+ engine ruled, the model did not conclude, and no terminal is ever softened into a 200 the model
2741
+ never declared. What a terminal may not do is discard the last thing the model said. When the
2742
+ loop's last inference turn performed no authored operation in either response or
2743
+ reasoning and kept text, its Problem Details
2744
+ carries the extension member `unconcluded`, the
2745
+ `ops://<worker>/<loop>/<turn>` address of that emission. It is a citation, never the bytes
2746
+ ({§turn-ops-entry}: the reader READs the source, and an emission of any length never rides
2747
+ wholesale into a parent's packet). The member is named for what it is — an emission left
2748
+ unconcluded — and never `answer`: the harness cannot warrant that text is complete or final,
2749
+ because it did not conclude under {§kill-conclusion}. Earlier deliveries remain delivered;
2750
+ the citation neither sends them again nor destroys them. A terminal whose last inference
2751
+ turn performed authored operations carries no `unconcluded`: an absent member is not an
2752
+ empty one. Attachment is owned by the one terminal seam.
2659
2753
  - §metadata-ignored **Options a scheme does not take are dropped, not refused.** A READ, FIND,
2660
2754
  EDIT or KILL carrying `[metadata]` for a scheme whose manifest takes none runs without it,
2661
2755
  and the packet carries one `metadata_ignored` notice naming the scheme (operator,
@@ -2663,40 +2757,26 @@ accounting and model-visible failure evidence remain separately owned by
2663
2757
  path; it is lifted into the matcher at parse time ({§matcher-option}). SEND recipients,
2664
2758
  executions, WORK and FORK own their input and receive it whole ({§send-resource-attachments},
2665
2759
  {§env-option}); a key they do not take is their own 400.
2666
- - §send-looks-like-operation **A reply never begins with an operation heading.** When a model's
2667
- untargeted SEND has, as its first non-blank line, a line that parses alone as one clean
2668
- heading naming an operation this worker could perform — a Plurnk operation, or a registered
2669
- executor or MCP service — dispatch refuses it 400 `send-looks-like-operation`, naming the
2670
- `heading`, and delivers nothing. Since the fences chapter's unlabeled-fence SEND was retired
2671
- ({§interstitial-fence}), this guards only an explicit `SEND` block; a heading written outside
2672
- any fence is prose with the parser's own advisory ({§bare-heading-advisory}), and an emission
2673
- made only of such lines is an empty turn carrying those advisories ({§empty-turn}). This is
2674
- admission, not promotion: the line is never run as the operation it resembles, and the neutral
2675
- recovery says only where each intent belongs (an operation on the fence line, a quoted example
2676
- inside a delimited SEND body). A first line that does not parse alone (prose after the word), a
2677
- name no registry knows, or an inner fence is an ordinary reply; so is a heading whose
2678
- only irregularity is a multi-word sigil-less matcher after the path (`READ (belfry.md)
2679
- returned nothing because the file is empty.`), which {§naked-pattern} would otherwise lift
2680
- as a literal — on a reply's first line that is prose. Origin: the 2026-09-11 dogfood,
2681
- where four operations on the line after their fences were delivered as four 200 replies and the
2682
- loop then parked fifteen minutes on receipts that could never arrive.
2683
2760
  - §send-idle-turn **NOTE is memory, not a yield.** NOTE does not imply parking.
2684
- With unanswered messages it continues; after replies and observation it may be the only
2685
- operation in the program that concludes. Repetition remains subject to {§engine-cycle-evidence}.
2761
+ A NOTE-only response does not request completion, even after every message is answered.
2762
+ Repetition remains subject to {§engine-cycle-evidence}.
2686
2763
  - §send-premature-terminate **Completion follows observation.** Every fired operation except
2687
2764
  SEND, NOTE, WAIT and successful KILL requires a subsequent packet. This barrier uses durable
2688
2765
  executed evidence, not curated rows. Fast completion, an empty result or curation cannot
2689
2766
  erase it. New arrivals are protected by {§completion-defers-to-messages}; no terminal verb
2690
2767
  or prose overrides this rule.
2691
- - §completion-joins-live-work **Answered work still joins its live obligations.** Once all
2692
- observed messages are answered, live children, non-detached streams park the same loop
2693
- as WAIT does. Each ordinary wake presents the newly settled state; completion is evaluated
2694
- again after the next program. KILL owns cancellation; a reply never cancels work implicitly.
2768
+ - §completion-joins-live-work **A completion request joins its live obligations.** An eligible
2769
+ parameterless KILL parks on live children or
2770
+ non-detached streams, as WAIT does. Ordinary programs continue regardless of earlier
2771
+ replies. Each wake presents the newly settled state; the next program expresses its
2772
+ own disposition. Only targeted KILL owns cancellation; parameterless KILL never
2773
+ cancels work and delivers no final answer while joining.
2695
2774
  - §completion-defers-to-results **Results keep the loop running until observed.** Same-turn
2696
2775
  operations and failures, plus undelivered child or stream conclusions, require the next
2697
- packet. This is ordinary continuation, not a strike or a synthetic refusal receipt.
2698
- The already-delivered answer remains delivered. If observation warrants no further work
2699
- or revision, a NOTE or curation-only program can conclude without repeating the answer.
2776
+ packet. This is ordinary continuation, not a strike. A premature parameterless KILL
2777
+ receives a factual continuation receipt without delivering its body. Earlier SEND
2778
+ replies remain delivered. If observation warrants no further work or revision, a
2779
+ lone empty parameterless KILL requests completion without repeating an earlier answer.
2700
2780
  - §send-administrative-terminal **Administrative programs close their own transaction.**
2701
2781
  Their caller closes the administrative loop after execution; no terminal operation is
2702
2782
  manufactured. Initialization runs in the model loop without concluding it.
@@ -2951,14 +3031,14 @@ two states and no others:
2951
3031
  | state | what the model receives |
2952
3032
  |---|---|
2953
3033
  | active | nothing in the Log. The `## Delegation` stream pointer names the stream with each channel's size and its growth since the last packet ({§child-orientation}); the model READs any range it wants, and every READ of a stream channel carries `terminal: false` while it runs and `terminal: true` once it has concluded, so an empty page is never mistaken for a finished command that printed nothing (operator, 2026-09-13). |
2954
- | terminal | ONE `origin=_plurnk` READ at the execution's channel address, born visible, that is exactly a markerless READ of the channel — its bounded first page ({§read-selection-projection}, the whole channel when it fits, the channel's own mimetype), the `range` or `region`, terminal status and Problem, `terminal: true`, and any producer-supplied integer `exitCode`. The packet identifies the read resource with `path`, exactly as an explicit READ does ({§log-address-metadata}). |
3034
+ | terminal | ONE `origin=_plurnk` READ at the execution's channel address, born visible, that is exactly a markerless READ of the channel — its bounded first page ({§read-selection-projection}, the whole channel when it fits, the channel's own mimetype), the `range` or `region`, terminal status and Problem, `terminal: true`, and any producer-supplied integer `exitCode`. The packet writes the read resource as its operand, exactly as an explicit READ does ({§log-address-metadata}). |
2955
3035
 
2956
3036
  §stream-observation-result **One liveness fact.** The durable READ result owns
2957
3037
  `terminal`, derived from its selected channel's state, for explicit and automatic
2958
3038
  observations alike, independently of mimetype: `active` gives false, `closed` or
2959
3039
  `errored` gives true, and `static` has no streaming liveness field. Packet
2960
- projection preserves that Boolean and any included
2961
- integer `exitCode`, even for an empty body. An automatic observation's atomic
3040
+ projection preserves that Boolean, any included
3041
+ integer `exitCode`, and a producer's `page` receipt ({§executor-page-receipt}), even for an empty body. An automatic observation's atomic
2962
3042
  publication transition consumes the same result flag; private log attributes
2963
3043
  retain only the publication offset, not a second liveness value.
2964
3044
 
@@ -3334,10 +3414,10 @@ No generator. SQLite-optimal: STRICT (3.37+), `INTEGER PRIMARY KEY` aliasing, ex
3334
3414
  | §db-process-triggers Processes beside their owners | A trigger that writes rows — a cascade, a capture, an ambient event, a publication cursor, a landed curation — is a process, not shape. It is declared as an `-- INIT: <trigger name>` block in the `.sql` file beside the statements that fire it (`ambient.sql` for the ambient feed, `LoopLifecycle.sql`, `Turn.sql`, `Engine.sql` for model calls, `_entry-crud.sql`, `Log.sql`, `ChannelWrite.sql`), as `DROP TRIGGER IF EXISTS` then `CREATE TRIGGER`, so the definition is current on every open of a database whose shape is current. `MIGRATE` always precedes `INIT` and `INIT` runs on the writer only, so a process may reference any table regardless of file order and never runs on the read pool. `test/intg/schema-composition.test.ts` fails on a baseline trigger that writes, an `INIT` trigger that only guards, a block not named after its trigger or not dropping first, and a live trigger set that differs from the declared set after a first and a second open. |
3335
3415
  | §db-fk-indexes Foreign-key check paths | Every foreign-key column a delete, cascade, or parent replacement can check carries an index (partial where the column is nullable), and no registry statement's plan scans a growing table: `test/intg/schema-query-plans.test.ts` runs `EXPLAIN QUERY PLAN` over every `-- PREP` statement against the baseline and fails on a `SCAN` of a growing table, except statements that read a whole table by design (digest, startup recovery, whole-workspace listings, scheduled-loop claims). An index claim is a plan, never a grep of index names. |
3336
3416
  | §db-index-owners Every index has an owner | An explicit index earns its place one of three ways: a registry statement's plan uses it, its leading column is a foreign key whose check it serves, or it enforces uniqueness. The same test fails on any other index, naming it: an index nobody reads is a write on every insert. Duplicates of a `UNIQUE` constraint's own index and sort-only indexes no plan selects were removed on this rule; a column no statement reads (`symbol_refs.col`, `ambient_events.created_at`) is not stored. |
3337
- | §db-maintenance-optimize Statistics at shutdown | The daemon's last database step before the caller closes SQLite is `PRAGMA optimize` on the writer (`maintenance_optimize`), so `sqlite_stat1` reflects tables the connection planned against, bounded by SQLite's own analysis limit; a failure there is a reported shutdown error, never silent. Retention runs before it under the operator's policy ({§retention-policy}); no explicit checkpoint and no periodic `ANALYZE` run. |
3417
+ | §db-maintenance-optimize Statistics at shutdown | The daemon's last database step before the caller closes SQLite is `PRAGMA optimize` on the writer (`maintenance_optimize`), so `sqlite_stat1` reflects tables the connection planned against, bounded by SQLite's own analysis limit; a failure there is a reported shutdown error, never silent. Retention runs before it under the operator's policy ({§retention-policy}) and ends with a WAL truncation ({§db-space-reclamation}); no periodic `ANALYZE` runs. |
3338
3418
  | §db-space-reclamation The daemon keeps its own file healthy | `PLURNK_SERVICE_AUTO_VACUUM` (`incremental`, the default, or `none`) names the mode the daemon keeps its file in. At start, before any drain, a database in another mode is converted (set the mode, one `VACUUM`, which rewrites the file and needs free disk about its size) and the journal says so with page counts before and after. Under `incremental`, every retention pass ends by stepping `PRAGMA incremental_vacuum` to completion once free pages reach `PLURNK_SERVICE_RECLAIM_MIN_FREE_BYTES` (0, the default, = every pass), and reports `reclaimedPages`; below the floor, free pages stay for SQLite to reuse. Under `none` the file never shrinks and freed pages are reused. No operator step is involved beyond the knobs. The WAL stays bounded by SQLite's automatic checkpoint (#764). |
3339
3419
  | §content-store Every body is stored once | `contents` holds each settled body once, addressed by its SHA-256, however many channels, workspaces, forks or derivations carry it; rows are immutable. `entry_channel_rows` points a settled channel at its body and keeps an active stream's body as a private buffer until it settles, when it is interned. Every reader and writer uses the `entry_channels` view, whose `INSTEAD OF` triggers intern bodies, refuse a bound `content_hash` that is not the content's, and write each column group only when it changed, so a search attachment is never a representation write. SQLite counts no changes for a view, so a write that must know whether its channel exists returns the channel's name; an outer join cannot flatten the view, so the two statements that need one read `entry_channel_rows` and `contents` directly. `derivation_fts` is an external-content index over `derivation_texts` (a derivation joined to its body); `derivations.content_id` names the indexed text, and the triggers in `_entry-fts.sql` move the index with it and forget it on delete. A body no channel holds and no derivation indexes is collected by retention under `PLURNK_SERVICE_COLLECT_CONTENTS` (1). Witnesses: `test/intg/retention.test.ts`, `test/intg/entries.test.ts`, `test/intg/fulltext-index.test.ts`. |
3340
- | §retention-policy Retention is the operator's policy; information is kept by default | `Retention` (`src/server/Retention.ts`, statements in `Retention.sql`) reads ten knobs from `.env.defaults` once at daemon construction (the two storage knobs are {§db-space-reclamation}) and runs four set statements in dependency order — on `PLURNK_SERVICE_RETENTION_INTERVAL_MS` cadence while the daemon runs (0 = shutdown only) and once more at shutdown before `PRAGMA optimize`. `PLURNK_SERVICE_RETAIN_PACKET_TURNS` (-1 = every packet) and `PLURNK_SERVICE_RETAIN_PACKET_MS` (-1 = no age limit) retire a completed turn's packet composition (`turn_sections`, {§packet-items}) once it is beyond the newest N packet-bearing turns of its loop or older than the age; the turn, its bag, its log rows and its accounting stay, and an open turn is never retired. `PLURNK_SERVICE_COLLECT_PACKET_ITEMS` (1) collects items no composition references. `PLURNK_SERVICE_COLLECT_CONTENTS` (1) collects stored bodies nothing holds ({§content-store}), after the collectors that release them. `PLURNK_SERVICE_COLLECT_DERIVATIONS` (1) collects derivations no channel, turn source, or log row cites — superseded editions — with their symbols (cascade) and their full-text shadow (`derivations_delete_fts`, a process trigger beside the FTS statements, on every delete path). `PLURNK_SERVICE_RETAIN_RESPONSE_TURNS` (-1) and `PLURNK_SERVICE_RETAIN_RESPONSE_MS` (-1) retire a settled call's response body (`model_call_responses`) once it is beyond the newest N body-bearing calls of its loop or its turn is older than the age; the call's identity, failure, capacity, admission and accounting stay, and the digest renders such a call request-only. Under the shipped defaults nothing that is information leaves; only what no row references. A malformed knob refuses daemon construction. Witness: `test/intg/retention.test.ts`. |
3420
+ | §retention-policy Retention is the operator's policy; information is kept by default | `Retention` (`src/server/Retention.ts`, statements in `Retention.sql`) reads ten knobs from `.env.defaults` once at daemon construction (the two storage knobs are {§db-space-reclamation}) and runs four set statements in dependency order — on `PLURNK_SERVICE_RETENTION_INTERVAL_MS` cadence while the daemon runs (0 = shutdown only) and once more at shutdown before `PRAGMA optimize`. `PLURNK_SERVICE_RETAIN_PACKET_TURNS` (-1 = every packet) and `PLURNK_SERVICE_RETAIN_PACKET_MS` (thirty days; -1 = no age limit) retire a completed turn's packet composition (`turn_sections`, {§packet-items}) once it is beyond the newest N packet-bearing turns of its loop or older than the age; the turn, its bag, its log rows and its accounting stay, and an open turn is never retired. `PLURNK_SERVICE_COLLECT_PACKET_ITEMS` (1) collects items no composition references. `PLURNK_SERVICE_COLLECT_CONTENTS` (1) collects stored bodies nothing holds ({§content-store}), after the collectors that release them. `PLURNK_SERVICE_COLLECT_DERIVATIONS` (1) collects derivations no channel, turn source, or log row cites — superseded editions — with their symbols (cascade) and their full-text shadow (`derivations_delete_fts`, a process trigger beside the FTS statements, on every delete path). `PLURNK_SERVICE_RETAIN_RESPONSE_TURNS` (-1) and `PLURNK_SERVICE_RETAIN_RESPONSE_MS` (thirty days) retire a settled call's response body (`model_call_responses`) once it is beyond the newest N body-bearing calls of its loop or its turn is older than the age; the call's identity, failure, capacity, admission and accounting stay, and the digest renders such a call request-only. Under the shipped defaults the durable record is kept forever, while packets and response bodies — transient evidence — are collected after thirty days, so a daemon left running for months stops growing (#788). A malformed knob refuses daemon construction. Witness: `test/intg/retention.test.ts`. |
3341
3421
 
3342
3422
  - DDL = storage truth; JSON Schemas = wire truth. They are allowed to differ where ergonomics demand.
3343
3423
  - §entry-identity-no-null **Identity components are never NULL.** `(workspace_id, scheme, authority, pathname)` is a unique key. `workspace_id` references the workspace directly with cascading deletion. Namespace schemes use empty authority; resource schemes retain their canonical authority. File members use nonempty `scheme="file"` and render as bare paths. Registration refuses `storedScheme: null`.
@@ -3619,6 +3699,17 @@ The floor reports every removed key. A gate that succeeds only with those pins
3619
3699
  is red because provider capacity did not derive for
3620
3700
  a fresh-user configuration.
3621
3701
 
3702
+ §turn-cap-counts-the-tree **The turn ceiling is the worker tree's budget of model
3703
+ calls.** The owner is the current loop of the topmost ancestor-or-self worker that has
3704
+ one: for a tree a client started, the root worker's loop current when this loop began (its
3705
+ `max_turns`: the client's `maxTurns` clamped by the operator ceiling below); a loop with no
3706
+ such ancestor owns its own budget. Every model call on the owner's loop and on any later
3707
+ loop of the owner's descendants spends it, emission turns and BARE calls alike, open or
3708
+ settled, one per call however many physical requests it took. `LoopDriver` reads the tree's count before each turn and rules the `max-turns` 429
3709
+ terminal ({§loop-terminals}) when the ceiling is met; a BARE beyond the budget is refused
3710
+ 429 `max-turns` before any provider call, so one turn cannot spend past it with a batch. A
3711
+ child loop inherits the value and binds the same count.
3712
+
3622
3713
  §operator-config-max-turns-ceiling Enforcement is per-use-site — no central most-restrictive pass; each ceiling is checked where it bites. `PLURNK_SERVICE_MAX_TURNS` ships **off** (`-1` = no cap; the loop ends via SEND, budget, strikes, or cycle detection) and, when an operator sets a positive value, the per-call request is `min()`-capped against it.
3623
3714
 
3624
3715
  §operator-config-workspace-settings **Client open-context (per workspace).**
@@ -3750,7 +3841,10 @@ The database may be released only after the final settlement barrier resolves.
3750
3841
  (`PLURNK_SERVICE_STOP_TIMEOUT_MS`, default 30000): past the deadline each wait
3751
3842
  is abandoned with a named error instead of hanging the daemon on a child that
3752
3843
  never closes. A wedged child costs a forced shutdown; it must never cost an
3753
- unbounded one.
3844
+ unbounded one. When the teardown settles, success or failure, the process ends
3845
+ itself: `0` after a clean teardown, `1` after a reported one. A handle an abandoned
3846
+ wait left alive never keeps a stopped daemon running; the supervisor's kill is a
3847
+ backstop, not the exit.
3754
3848
 
3755
3849
  ```mermaid
3756
3850
  flowchart LR
@@ -3980,7 +4074,8 @@ publications before inspection or shutdown.
3980
4074
 
3981
4075
  §functionality-documents **Generated documents describe the shared snapshot.**
3982
4076
  Documents are projected through the existing worker generated subtree
3983
- ({§worker-generated-subtree}); the projection does not confer ownership.
4077
+ ({§worker-generated-subtree}); the projection does not confer ownership, and it
4078
+ follows the family's admission ({§schemes-directory}): a denied family projects none.
3984
4079
  Enabled, active definitions are discoverable. Disabled or unavailable
3985
4080
  definitions add no hot-path teaching. Their exact state and Problem remain
3986
4081
  available through `list`.
@@ -4438,7 +4533,7 @@ time of measurement.
4438
4533
  - **Derivation is exhaustive and demand-led.** Explicit searchable-resource changes may start one coalesced warm. Passive creation and attachment do not. The first model turn starts or joins that warm; later turns derive intervening changes before dispatch. No model operation observes partial graph or full-text coverage. Progress notices make the wait visible. {§derivation-exhaustive}
4439
4534
  - §membership-binary-sniff **Binary truth beats a text label.** Filesystem source acquisition, including tracked members and installed skill resources, inspects up to the first 8192 bytes when extension detection does not identify a binary type. NUL marks `application/octet-stream`; existing binary types retain their declared type. Member projections follow {§membership-source-projection}; installed skill projections follow {§skills-resources}.
4440
4535
  - §tokenomics-agnostic-ruler **One model-agnostic curation ruler.** The daemon runs workers on different models in one workspace concurrently, while catalog and log accounting are workspace-wide. `contentWeight = ceil(chars/2)` therefore gives one content one stable number without per-model workspace state or recount passes. It controls curation only; every provider call independently measures the complete request as well as it can.
4441
- - §tokenomics-neutral-telemetry **Curation telemetry is state, not response allowance.** The model-facing `Context Curation` section is one JSON object carrying `logTokensTotal` and `logTokensMax` (and `tokensResponseMax` when an output floor is disclosed). It never presents their difference as free response tokens. The protocol definition directly requires KILL of irrelevant log items and ranges to keep the next packet within the maximum. Per-entry weights remain on log rows where they describe visible cost and curation savings. Generic packet composition and physical-token speculation are absent.
4536
+ - §tokenomics-neutral-telemetry **Curation telemetry is state, not response allowance.** The model-facing `Context Curation` section is one JSON object carrying `logTokensTotal` and `logTokensMax`. It never presents their difference as free response tokens. The protocol definition directly requires KILL of irrelevant log items and ranges to keep the next packet within the maximum. Per-entry weights remain on log rows where they describe visible cost and curation savings. Generic packet composition and physical-token speculation are absent.
4442
4537
  - §tokenomics-pressure-inventory **Pressure identifies its reclaimable concentration.** At `PLURNK_SERVICE_BUDGET_PRESSURE` of `logTokensMax`, a Markdown `> [!WARNING]` block follows the JSON with `> YOU MUST KILL superseded, stale, or irrelevant log items and ranges.` New output withholding replaces that mandate under {§context-output-warning}. The JSON may include `logTokensLargest`: at most `PLURNK_SERVICE_BUDGET_LARGEST_ITEMS` retained log items, each `{path, logTokens}`, ranked by that charge descending and then path. Native-only, suppressed, and metadata-only items remain eligible: whole-item KILL can reclaim their actual contribution. Include the largest prefix that fits; drop the optional list before the warning. Both participate in the final fixed-point total and complete request admission check.
4443
4538
  - §tokenomics-content-hash-identity **Content identity, not per-tokenizer counts.** A settled channel's `content_hash` (SHA-256) is its body's identity in the content store ({§content-store}); a writer may bind it, a bound hash must match the content, and an active stream has none until it settles. `weight` is stored beside that content and is never keyed or recomputed by model.
4444
4539
  - §tokenomics-provider-usage **Provider accounting is physical-request evidence, not curation state.** Every issued physical request has one durable pre-I/O `provider_requests` identity beneath the normalized {§inference-ledger} and settles once as response or error. Each record preserves conventional {§provider-usage} quantities and required {§provider-cost} evidence; an unreported quantity remains absent, including on response-less failures, and is never replaced by zero. `model_calls` own response/failure evidence, `turn_attempts` specialize emission admission, and `provider_requests` are the sole durable accounting representation. Emissions, BARE calls, rejected responses, retries, failovers, and errors therefore remain cardinal and ordered. Turn, loop, worker, workspace, digest, and protocol accounting are derived from those records through the shared {§provider-accounting} projection; only emission calls contribute the latest-packet context gauge. The baseline stores no floating-point money, denormalized totals, or rollup triggers. A documented direct charge becomes `charged`; otherwise the provider may compute an exact-decimal USD `estimated` amount from complete usage and the exact model's Models.dev rates; insufficient evidence becomes `unknown`. Derived `costUsd` sums every USD-expressible request and is `null` only when no request is expressible; a response-less failure or an uncataloged model is skipped, never allowed to erase the expressible evidence. Each derived aggregate usage field independently sums its reported quantity, so heterogeneous detail coverage remains partial rather than becoming fictitiously complete. This is operational request accounting, not invoice reconciliation. Output and reasoning are quantities the model cannot KILL, so they never alter the model-facing Budget ledger.
@@ -4487,7 +4582,7 @@ flowchart TD
4487
4582
  | Status | Outcome |
4488
4583
  |---|---|
4489
4584
  | 100 / 102 | Queued / running |
4490
- | 202 | WAIT or answered work joining a live obligation ({§wait-obligation-matrix}, {§worker-wait-timing}) |
4585
+ | 202 | WAIT or an eligible final response joining a live obligation ({§wait-obligation-matrix}, {§worker-wait-timing}) |
4491
4586
  | 200 | Messages answered, results observed, held work settled |
4492
4587
  | 499 | Worker-scope or client cancellation |
4493
4588
  | 429 | Turn allowance exhausted |
@@ -4496,7 +4591,9 @@ flowchart TD
4496
4591
  | 504 | Loop timeout or exec-timeout restamp |
4497
4592
 
4498
4593
  An empty WAIT continues at 102. The exact terminal result retains its Problem;
4499
- status classes are not catch-all replacements for that evidence.
4594
+ status classes are not catch-all replacements for that evidence. No failing status
4595
+ here is ever softened because the model wrote something the harness could not read;
4596
+ every one of them cites it instead ({§terminal-evidence}).
4500
4597
 
4501
4598
  ### §env-delta The environment delta: what changed since the model last looked
4502
4599
 
@@ -4549,8 +4646,8 @@ ordinary operation evidence still reaches that child's direct parent.
4549
4646
 
4550
4647
  | Producer / event | Durable occurrence | Observer projection |
4551
4648
  | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
4552
- | §env-delta-child-activity Direct-child activity | Child-authored final EDIT, COPY, MOVE, SEND, executor invocation, WORK, FORK, and non-log KILL receipts, including failures. `_plurnk` initialization, maintenance, and operation turns stay with the worker. A reply already delivered to the parent uses its reply occurrence instead ({§message-reply-delivery}). | Direct parent only; one exact attributed row born body-suppressed. Incoming message projections ({§message-arrival}), NOTE, READ (including executor-output READs), FIND, BARE, WAIT, and log KILL never create activity occurrences. Provider reasoning, calls, rejected emissions, and turn sources do not cross automatically. |
4553
- | §env-delta-child-termination Direct-child termination | The child's exact terminal loop result, except loops containing only `_plurnk` operation or maintenance turns. A conclusion before the first turn still reports, including failed spawns. `source` names the actor; the READ target selects its exact loop result ({§worker-loop-result}). | Direct parent only; an ordinary bounded READ projection of the retained occurrence, never a fresh lookup of the child's latest loop. The outcome's own body is visible within the ordinary READ bound; replies are separate messages and are never copied or deduplicated by content ({§worker-scheme-collect}). Excluded administrative loops create no pending child-result edge. |
4649
+ | §env-delta-child-activity Direct-child activity | Child-authored final EDIT, COPY, MOVE, SEND, executor invocation, WORK, FORK, and targeted non-log KILL receipts, including failures. `_plurnk` initialization, maintenance, and operation turns stay with the worker. A reply already delivered to the parent uses its reply occurrence instead ({§message-reply-delivery}). | Direct parent only; one exact attributed row born body-suppressed. Incoming message projections ({§message-arrival}), successful targetless SEND without delivery ({§send-response-receipt}), NOTE, READ (including executor-output READs), FIND, BARE, WAIT, parameterless KILL, and log KILL never create activity occurrences. Provider reasoning, calls, rejected emissions, and turn sources do not cross automatically. |
4650
+ | §env-delta-child-termination Direct-child termination | The child's exact terminal loop result, except loops containing only `_plurnk` operation or maintenance turns. A conclusion before the first turn still reports, including failed spawns. `source` names the actor; the READ selects the exact loop ({§loop-answer}). | Direct parent only; bounded, initially visible READ under {§worker-scheme-collect}, never the child's potentially newer loop. Excluded administrative loops create no pending child-result edge. |
4554
4651
  | §env-delta-commons-mutation Commons mutation | One successful resolved operation whose landed effects touch `worker:///...`. | Every existing worker; one body-suppressed row per observer, deduplicated with any lineage audience. |
4555
4652
  | §env-delta-filesystem-narration Project-file divergence | Runtime-owned reconciliation evidence remains in the runtime actor's own log. | No ambient observer row. Current content remains addressable and stale hash edits reject at their owned boundary. |
4556
4653
  | §env-delta-entry-materialization Executor `entry()` sink | The runtime records typed materialization evidence under its owning actor. | No ambient observer row unless the resulting operation itself is direct-child activity or a commons mutation ({§exec-entry-sink}). |
@@ -4718,7 +4815,7 @@ Retired terms stay retired: the lexicon guard rejects `thinking`, the unqualifie
4718
4815
  | inbound `SEND` from outside the workspace | budgeted head under {§message-projection} |
4719
4816
  | structured `EDIT` receipt or textual `COPY`/`MOVE` effects | complete receipt-owned join context |
4720
4817
  | every other nonempty body | head bounded independently by `PLURNK_SERVICE_PREVIEW_LINES` and `PLURNK_SERVICE_PREVIEW_CHARS` |
4721
- | bodyless row | metadata only; no coordinate lines; `logTokens` includes any selected native part |
4818
+ | bodyless row | heading, written request, and any facts; no coordinate lines; `logTokens` includes any selected native part |
4722
4819
 
4723
4820
  §markerless-first-page **Every markerless retrieval takes the same implicit marker.** A marker's
4724
4821
  unit is whatever its projection counts, so `PLURNK_SERVICE_PREVIEW_LINES` is the first page of
@@ -4743,8 +4840,8 @@ READ and FIND own their range or pagination before packet rendering; the packet
4743
4840
 
4744
4841
  Every accepted message enters its recipient loop's inbox in arrival order, with its selected
4745
4842
  paths, and publishes exactly once at the next turn boundary. **Open Messages** lists the
4746
- unanswered messages by their immutable source address (`path`) and optional causal `source`,
4747
- not a log coordinate. Each arrival receipt's `resource` names that same retained source.
4843
+ unanswered messages by their immutable source address (`path`) and their sender — a causal
4844
+ `source`, or `"origin": "user"` for the operator's own ({§message-causal-source}) — not a log coordinate. Each arrival receipt's `resource` names that same retained source.
4748
4845
  Trusted protocol modules supply message addresses in their own scheme;
4749
4846
  native arrivals use `message://<recipient>/<opaque-id>`, separate from the worker's
4750
4847
  actor and scratch addresses. Ordinary worker scratch remains writable. Source bodies
@@ -4758,15 +4855,17 @@ another admission is a 409 conflict, not a second message or an implicit content
4758
4855
  | Audience | Delivery | Effect |
4759
4856
  |---|---|---|
4760
4857
  | Assigned worker | Its conversation, even when another actor answered | Visible reply; wakes eligible parked work without a new Open Message or loop. |
4761
- | Original native sender | That worker, if distinct from the assigned worker | The same reply, through the same wake and observation path. |
4858
+ | Original native sender | That worker, if distinct from the assigned worker; original delegated-task answers use {§worker-scheme-collect} instead | Other replies use the same wake and observation path. |
4762
4859
  | Exterior sender | The assigned conversation's protocol adapter | The adapter delivers the answer through its standard message channel. |
4763
4860
  | Replying actor | Its own executed SEND | No duplicate ambient occurrence. |
4764
4861
 
4765
4862
  The successful SEND and its addressed occurrences commit together. Reply occurrences use
4766
4863
  the ordinary durable ambient cursor and wake revision; curation cannot revoke delivery or
4767
4864
  replay it. An addressed reply replaces the same parent's generic activity observation.
4768
- Child completion is a separate READ of its execution outcome; replies are not outcome bodies.
4769
- The complete outcome remains available at its {§worker-loop-result} address.
4865
+ The child's reply to its original parent-delegated message reaches that parent once,
4866
+ through the conclusion READ under {§worker-scheme-collect}; it is not a separate reply
4867
+ occurrence. Other replies remain ordinary messages. The exact loop remains addressable
4868
+ under {§loop-answer}.
4770
4869
  Unobserved replies prevent conclusion just as unobserved child results do. All operation
4771
4870
  producers notify the same settlement path after durable execution; reply wake-up shares
4772
4871
  {§worker-optimistic-settlement}, without delaying the replying program.
@@ -4780,7 +4879,7 @@ additional alias. Answering either reaches the same message. Origin (operator, 2
4780
4879
  packet showed a 77-character `agui://anonymous/threads/…/messages/<uuid>` twice per open message,
4781
4880
  while the docs taught the short form.
4782
4881
 
4783
- §message-causal-source **Message authorship and delivery are distinct facts.** The harness publishes every arrival row; the row's `source` carries the canonical address of the causal actor. Native WORK, FORK, and directed worker SEND derive `worker://<sender>` from the authenticated sender worker ID. A trusted exterior adapter supplies its own canonical actor address through {§methods-loop-run}: the AG-UI bridge names the client's message under `agui://` ({§agui-run-source}), the inbound A2A adapter under `a2a://`. An absent source means the owning worker itself. Attribution persists with the message through the inbox, parking, orphan recovery, restart, and later log projection; model syntax cannot author it. The wire renders the row's `source` and omits its `origin`, which is constant for every arrival; the Open Messages pointer carries the same source ({§message-arrival}) — except where the source is the transport that minted this very message, which says nothing the address does not ({§message-short-identity}).
4882
+ §message-causal-source **Message authorship and delivery are distinct facts.** The harness publishes every arrival row; the row's `source` carries the canonical address of the causal actor. Native WORK, FORK, and directed worker SEND derive `worker://<sender>` from the authenticated sender worker ID. A trusted exterior adapter supplies its own canonical actor address through {§methods-loop-run}: the AG-UI bridge names the client's message under `agui://` ({§agui-run-source}), the inbound A2A adapter under `a2a://`. An absent source is the operator. Attribution persists with the message through the inbox, parking, orphan recovery, restart, and later log projection; model syntax cannot author it. The wire renders the row's `source` in place of its `origin`, which is constant for every arrival, except where the source is the transport that minted this very message, which says nothing the address does not ({§message-short-identity}). The operator's message is then the one arrival with no sender to show, so it renders `"origin": "user"`: left bare, it read as the model's own SEND, and a model that had finished the work could no longer find the request it was answering (operator, 2026-09-22). The Open Messages pointer carries the same attribution ({§message-arrival}).
4784
4883
 
4785
4884
  §message-projection **Message storage is unbounded by model context; automatic materialization is not.** Core persists every accepted message completely before packet assembly. The selected provider's derived `inputCapacity` and the alias-resolved percentage from `PLURNK_SERVICE_PROMPT_PROJECTION` derive one aggregate curation-weight allowance for the visible bodies of arrivals other than a peer worker's — every `source` that is not a `worker://` address, the loop's own assignment included. Complete bodies render when their aggregate weight fits. Otherwise all such visible rows share the allowance: full bodies consume only their required share, unused shares are redistributed, and partial bodies render the largest leading complete-line region that fits their share or an exact character-bound prefix when the first physical line alone is larger. The sum of their rendered body weights never exceeds the allowance. Every partial body carries `preview` under {§packet-extent-metadata}. The row remains complete and READable by coordinate; its `log:///` body additionally obeys deliberate curation under {§log-readable-projection}. A peer worker's message takes the ordinary bounds. When provider input capacity is unknown the percentage is underivable, so arrival rows retain the ordinary bounded projection rather than inventing capacity. This policy never rejects, summarizes, or discards a message because it exceeds a context window.
4786
4885
 
@@ -4876,7 +4975,7 @@ retain distinct contracts and lifetimes.
4876
4975
 
4877
4976
  §digest-cost-kind **Cost basis named.** A rendered Cost line carries the basis of its dollar figure: `(charged)` only when every settled request's cost is provider-charged; `(estimated — catalog rates)` when any settled request's cost is an estimate, because a mixed sum is no more trustworthy than its weakest term. A dollar figure without its basis reads as billed truth, and an estimate must never impersonate a charge.
4878
4977
 
4879
- §output-allowance-notice **The output allowance is disclosed, and a ceiling cut names its cause.** The packet's budget section carries `tokensResponseMax: <tokens>` beside the curation ceiling whenever the provider resolves an output budget — the per-turn response allowance is a capacity fact, disclosed rather than discovered by truncation. The disclosed number is the program's guaranteed room — the configured output floor less the reasoning subset, since reasoning spends from the same allowance — never the wire grant: overflow tolerance (#482) is never advertised in the packet, and a cut's notice names the true per-call grant from the response's own capacity record. When a provider finish is `length`, the engine emits an `output_truncated` notice (source `engine:capacity`) naming the allowance — the fact alone, never advice on what to do about it — on every path — railed or not — and the rails verdict never blames the model's grammar for a cut the engine's own ceiling made. The same precedence governs a cut so deep no operation parses: the rejection notice names the truncation as the cause, not the parser's symptom, overriding {§invalid-emission-attempts}'s parser diagnostic for `length` finishes.
4978
+ §output-allowance-notice **The output allowance is not disclosed; a ceiling cut names its cause.** The packet's budget section carries the curation state and no response allowance: a model does not plan in tokens and no harness tells it its output ceiling, so the number was a fact without a use — across 9,124 recorded model turns none was cut at the allowance, while 45 emissions or reasonings spent tokens interpreting it (#826, operator, 2026-09-24). Overflow tolerance (#482) is likewise never advertised; a cut's notice names the true per-call grant from the response's own capacity record. When a provider finish is `length`, the engine emits an `output_truncated` notice (source `engine:capacity`) naming the allowance — the fact alone, never advice on what to do about it — on every path — railed or not — and the rails verdict never blames the model's grammar for a cut the engine's own ceiling made. The same precedence governs a cut so deep no operation parses: the rejection notice names the truncation as the cause, not the parser's symptom, overriding {§invalid-emission-attempts}'s parser diagnostic for `length` finishes.
4880
4979
 
4881
4980
  §digest-wire-line **Wire health aggregated.** Each worker summary renders a `Wire:` line — total physical provider requests, error-outcome count, and the error percentage when nonzero. Provider-level failures are absorbed by retries below the packet stream, so without this aggregate a rate-limit storm is invisible in every summary while the model's experience stays clean.
4882
4981
 
@@ -5160,6 +5259,7 @@ section because they are language extensions rather than executable tools.
5160
5259
  |---|---|
5161
5260
  | Registered and model-visible scheme | Its reference is eligible when at least one supported resource capability is admitted by the effective policy ({§capability-admission}). Illustrative operations never determine admission. |
5162
5261
  | Runtime output scheme | Its runtime's reference owns discovery; no duplicate scheme reference. |
5262
+ | Family manager and its generated documents | Eligible while the family's manager runtime is admitted by the effective policy ({§capability-admission}), by name or by trait: a denied family has no page, no generated document and no runnable verb, so a masked family never stands in the survey empty (#842). |
5163
5263
  | Excluded scheme | `PLURNK_SERVICE_DOCS_EXCLUDE` omits its reference, not its functionality. |
5164
5264
  | Reference content | Required meta-owned content follows {§teaching-corpus}; other schemes may supply optional `manifest.documentation`. Absent optional content contributes nothing; a failed required source read surfaces its cause. |
5165
5265
  | Policy layers | Materialization, Turn0, and direct operations use the same current workspace policy and service ceiling. |
@@ -5388,8 +5488,8 @@ only when its content is already source-numbered, such as an effect receipt.
5388
5488
  An EDIT or scoped entry KILL log row renders its bounded effect receipt (`rx.receipt`) as row
5389
5489
  metadata and join context, not its input statement. Proposal-gated file EDITs
5390
5490
  compute the accepted receipt from what actually lands. Environment-delta EDITs
5391
- render their resulting `rx.span`. COPY/MOVE rows render compact ordered
5392
- `from` and `to` selections ({§log-address-metadata}), compact ordered `effects` metadata, and
5491
+ render their resulting `rx.span`. COPY/MOVE rows write both operand
5492
+ selections ({§log-address-metadata}), render compact ordered `effects` metadata, and
5393
5493
  any scoped textual receipt contexts under their `log:///` address, never under
5394
5494
  one operand's resource address. All generated bodies remain under
5395
5495
  {§body-projection}. {§edit-result-render}
@@ -5483,7 +5583,6 @@ database is a benchmark artifact like any other: the lane's run directory lives
5483
5583
  checkout holds source only — never run output. `test:intg` stamps `PLURNK_TEST_RUN` once and every
5484
5584
  test process inherits it, so one suite's databases land in one directory without a pretest step, a
5485
5585
  marker file or a sweep; an unstamped invocation is not a special case with its own rules, it is
5486
- simply an unstamped run with its own directory. Nothing counts, reuses, moves, hides or
5487
- conditionally clears an artifact, so a failed suite's evidence is exactly where the run reported
5488
- it. A cross-package test may reuse Core's migration fixture only by passing a path inside the
5586
+ simply an unstamped run with its own directory. A stamped run that passes is reclaimed when it
5587
+ exits; a failed suite's evidence is never touched and stays exactly where the run reported it. A cross-package test may reuse Core's migration fixture only by passing a path inside the
5489
5588
  caller's own run directory.