@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.
- package/.env.defaults +8 -5
- package/INSTALL.md +3 -2
- package/SPEC.md +221 -122
- package/dist/build-info.json +1 -1
- package/dist/content/line-anchors.d.ts.map +1 -1
- package/dist/content/line-anchors.js +5 -1
- package/dist/content/line-anchors.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts +2 -2
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +32 -27
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BareBatchRunner.d.ts +6 -1
- package/dist/core/BareBatchRunner.d.ts.map +1 -1
- package/dist/core/BareBatchRunner.js +105 -50
- package/dist/core/BareBatchRunner.js.map +1 -1
- package/dist/core/BudgetReadout.d.ts +1 -1
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +4 -7
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +2 -2
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +24 -58
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/Dispatcher.sql +7 -0
- package/dist/core/Engine.d.ts +1 -0
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/KnownToxins.d.ts +5 -0
- package/dist/core/KnownToxins.d.ts.map +1 -0
- package/dist/core/KnownToxins.js +31 -0
- package/dist/core/KnownToxins.js.map +1 -0
- package/dist/core/LogBody.js +2 -2
- package/dist/core/LogBody.js.map +1 -1
- package/dist/core/LogEntryProjection.d.ts.map +1 -1
- package/dist/core/LogEntryProjection.js +0 -4
- package/dist/core/LogEntryProjection.js.map +1 -1
- package/dist/core/LoopDriver.d.ts.map +1 -1
- package/dist/core/LoopDriver.js +27 -7
- package/dist/core/LoopDriver.js.map +1 -1
- package/dist/core/LoopLifecycle.d.ts +5 -0
- package/dist/core/LoopLifecycle.d.ts.map +1 -1
- package/dist/core/LoopLifecycle.js +10 -0
- package/dist/core/LoopLifecycle.js.map +1 -1
- package/dist/core/LoopLifecycle.sql +36 -0
- package/dist/core/PacketBuilder.d.ts +1 -0
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +9 -11
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/PacketBuilder.sql +5 -0
- package/dist/core/ProviderRecovery.d.ts +9 -0
- package/dist/core/ProviderRecovery.d.ts.map +1 -0
- package/dist/core/ProviderRecovery.js +22 -0
- package/dist/core/ProviderRecovery.js.map +1 -0
- package/dist/core/ReasoningView.d.ts +5 -1
- package/dist/core/ReasoningView.d.ts.map +1 -1
- package/dist/core/ReasoningView.js +9 -4
- package/dist/core/ReasoningView.js.map +1 -1
- package/dist/core/ServiceTeardown.d.ts +1 -1
- package/dist/core/ServiceTeardown.d.ts.map +1 -1
- package/dist/core/ServiceTeardown.js +4 -2
- package/dist/core/ServiceTeardown.js.map +1 -1
- package/dist/core/StrikeRail.d.ts +3 -0
- package/dist/core/StrikeRail.d.ts.map +1 -1
- package/dist/core/StrikeRail.js +16 -1
- package/dist/core/StrikeRail.js.map +1 -1
- package/dist/core/TurnDispositionHandler.d.ts +3 -2
- package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
- package/dist/core/TurnDispositionHandler.js +48 -15
- package/dist/core/TurnDispositionHandler.js.map +1 -1
- package/dist/core/TurnMaterialization.d.ts.map +1 -1
- package/dist/core/TurnMaterialization.js +7 -1
- package/dist/core/TurnMaterialization.js.map +1 -1
- package/dist/core/TurnOps.d.ts.map +1 -1
- package/dist/core/TurnOps.js +4 -0
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.d.ts +0 -4
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +76 -101
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/TurnSources.sql +1 -1
- package/dist/core/ambient.sql +2 -2
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +67 -47
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/results.d.ts +1 -0
- package/dist/core/results.d.ts.map +1 -1
- package/dist/core/results.js +7 -0
- package/dist/core/results.js.map +1 -1
- package/dist/core/turn-scheduler.js +1 -1
- package/dist/core/turn-scheduler.js.map +1 -1
- package/dist/core/turn-signals.d.ts +5 -0
- package/dist/core/turn-signals.d.ts.map +1 -1
- package/dist/core/turn-signals.js +6 -0
- package/dist/core/turn-signals.js.map +1 -1
- package/dist/core/unconcluded-emission.d.ts +7 -0
- package/dist/core/unconcluded-emission.d.ts.map +1 -0
- package/dist/core/unconcluded-emission.js +11 -0
- package/dist/core/unconcluded-emission.js.map +1 -0
- package/dist/core/unconcluded-emission.sql +14 -0
- package/dist/digest/DigestRender.d.ts +1 -0
- package/dist/digest/DigestRender.d.ts.map +1 -1
- package/dist/digest/DigestRender.js +18 -1
- package/dist/digest/DigestRender.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +1 -0
- package/dist/schemes/Log.js.map +1 -1
- package/dist/server/Functionality.d.ts +1 -0
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js +7 -4
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/Retention.d.ts.map +1 -1
- package/dist/server/Retention.js +2 -0
- package/dist/server/Retention.js.map +1 -1
- package/dist/server/Retention.sql +5 -0
- package/dist/server/logEntry.sql +2 -2
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +4 -1
- package/dist/service.js.map +1 -1
- package/docs/copy-move.md +6 -6
- package/docs/env.md +9 -14
- package/docs/members.md +28 -23
- package/docs/skills.md +22 -22
- package/migrations/006_log.sql +10 -4
- 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
|
|
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
|
|
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**
|
|
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
|
|
531
|
-
|
|
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
|
|
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.**
|
|
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:
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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})
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
|
2170
|
+
| Spelling | Meaning | Where |
|
|
2118
2171
|
|---|---|---|
|
|
2119
|
-
| `path` | The operation's addressed operand
|
|
2120
|
-
| `from
|
|
2121
|
-
| `stream` | An executor invocation's separately created output address, never a READ's alternative spelling of
|
|
2122
|
-
| `resource` | A distinct returned resource under {§operation-resource-receipt}. |
|
|
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,
|
|
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`.
|
|
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
|
|
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
|
-
|
|
|
2577
|
-
| WAIT
|
|
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
|
-
|
|
|
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}
|
|
2583
|
-
|
|
2584
|
-
require another observation turn
|
|
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.
|
|
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
|
-
- §
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
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:
|
|
2645
|
-
|
|
2646
|
-
ended without one is its terminal problem (404 when it ended 2xx)
|
|
2647
|
-
|
|
2648
|
-
`
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
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
|
-
|
|
2685
|
-
|
|
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 **
|
|
2692
|
-
|
|
2693
|
-
as WAIT does.
|
|
2694
|
-
|
|
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
|
|
2698
|
-
|
|
2699
|
-
|
|
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
|
|
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
|
|
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})
|
|
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` (
|
|
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
|
|
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
|
|
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
|
|
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 |
|
|
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
|
|
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 |
|
|
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
|
-
|
|
4769
|
-
|
|
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
|
|
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
|
|
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
|
|
5392
|
-
|
|
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.
|
|
5487
|
-
|
|
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.
|