@plurnk/plurnk-service 1.15.0 → 1.16.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 +2 -2
- package/SPEC.md +105 -77
- package/digest-sql/curation/curation.sql +1 -1
- package/dist/build-info.json +1 -1
- package/dist/core/AdmittedTurnExecutor.js +1 -1
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +28 -42
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/Engine.sql +2 -8
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +3 -4
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/ResourceSelector.d.ts.map +1 -1
- package/dist/core/ResourceSelector.js +36 -7
- package/dist/core/ResourceSelector.js.map +1 -1
- package/dist/core/ResourceTransfers.d.ts.map +1 -1
- package/dist/core/ResourceTransfers.js +72 -7
- package/dist/core/ResourceTransfers.js.map +1 -1
- package/dist/core/SendBroadcastHandler.js +2 -2
- package/dist/core/SendBroadcastHandler.js.map +1 -1
- package/dist/core/ToolResources.js +2 -2
- package/dist/core/ToolResources.js.map +1 -1
- package/dist/core/TurnMaterialization.d.ts.map +1 -1
- package/dist/core/TurnMaterialization.js +0 -11
- package/dist/core/TurnMaterialization.js.map +1 -1
- package/dist/core/TurnOps.js +2 -2
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.js +3 -3
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/attachments.js +2 -2
- package/dist/core/attachments.js.map +1 -1
- package/dist/core/fork.d.ts.map +1 -1
- package/dist/core/fork.js +0 -4
- package/dist/core/fork.js.map +1 -1
- package/dist/core/fork.sql +5 -16
- package/dist/core/mutation-types.d.ts +1 -0
- package/dist/core/mutation-types.d.ts.map +1 -1
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +39 -62
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/turn-signals.d.ts +1 -1
- package/dist/core/turn-signals.d.ts.map +1 -1
- package/dist/core/turn-signals.js +1 -1
- package/dist/core/turn-signals.js.map +1 -1
- package/dist/digest/DigestRender.d.ts.map +1 -1
- package/dist/digest/DigestRender.js +1 -4
- package/dist/digest/DigestRender.js.map +1 -1
- package/dist/digest/digest-rows.d.ts +0 -3
- package/dist/digest/digest-rows.d.ts.map +1 -1
- package/dist/digest/digest.sql +1 -7
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +6 -10
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.js +1 -1
- package/dist/schemes/ExecOutputScheme.js.map +1 -1
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +31 -10
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +7 -21
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Log.sql +1 -66
- package/dist/schemes/Prompt.js +1 -1
- package/dist/schemes/Prompt.js.map +1 -1
- package/dist/schemes/Worker.js +1 -1
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.d.ts +3 -0
- package/dist/schemes/_entry-crud.d.ts.map +1 -1
- package/dist/schemes/_entry-crud.js +18 -3
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +16 -5
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-ops.d.ts.map +1 -1
- package/dist/schemes/_entry-ops.js +9 -1
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/schemes/_entry-send.js +1 -1
- package/dist/schemes/_entry-send.js.map +1 -1
- package/dist/server/FunctionalityManager.js +1 -1
- package/dist/server/FunctionalityManager.js.map +1 -1
- package/dist/server/logEntry.d.ts +0 -1
- package/dist/server/logEntry.d.ts.map +1 -1
- package/dist/server/logEntry.js +1 -13
- package/dist/server/logEntry.js.map +1 -1
- package/dist/server/logEntry.sql +1 -5
- package/migrations/001_schema.sql +9 -255
- package/package.json +30 -30
package/SPEC.md
CHANGED
|
@@ -131,7 +131,7 @@ scored. Every recovery checkpoint broadcasts live, while the model-facing Notice
|
|
|
131
131
|
retains only the current provider state; the next completed exchange notices
|
|
132
132
|
`provider_recovered`. Recovery is bounded by `PLURNK_SERVICE_PROVIDER_RECOVERY`; when it
|
|
133
133
|
is spent the turn completes as `202` and the loop parks exactly like a
|
|
134
|
-
|
|
134
|
+
`### SEND0 (WAIT)` wait ({§worker-lifecycle-wake-requeue-not-terminal}), resuming on the
|
|
135
135
|
next prompt or wake with its log intact. Only a client cancel, the loop deadline
|
|
136
136
|
({§operator-config-loop-timeout}), or a non-recoverable provider Problem (refusal,
|
|
137
137
|
authorization, quota, an invalid response) settles a loop on a provider failure.
|
|
@@ -392,7 +392,7 @@ file or ancestry-authorized entry through ordinary dispatch ({§worker-read-scop
|
|
|
392
392
|
| Door | Carries | Wake behavior |
|
|
393
393
|
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
|
|
394
394
|
| Environment | A direct child's durable activity to its parent, plus a successful mutation of the deliberately global `worker:///` commons to every worker. | Intermediate activity and commons never wake; a child's terminal disposition wakes its parent. |
|
|
395
|
-
| Voice | A directed `loop.inject` or
|
|
395
|
+
| Voice | A directed `loop.inject` or `### SEND0 (worker://name)` message. | An active worker folds it into its next turn; an idle one wakes. |
|
|
396
396
|
|
|
397
397
|
§actor-boundary-lineage-attention **Addressability is workspace-wide; attention
|
|
398
398
|
is lineage-scoped.** Project files, registered resources, and permitted worker
|
|
@@ -458,16 +458,16 @@ neither a hidden database write nor a kernel-owned mirror.
|
|
|
458
458
|
§actor-boundary-catalog-preview **Catalog preview.** `PLURNK_SERVICE_FILES_ITEMS`
|
|
459
459
|
foists turn-0 discovery into the worker's first turn, so a worker opens with a
|
|
460
460
|
navigable map instead of blank. An enabled preview executes exactly eight baseline
|
|
461
|
-
bodyless FIND surveys in order: Agent Skills (
|
|
461
|
+
bodyless FIND surveys in order: Agent Skills (`### FIND0
|
|
462
462
|
[+init,+skills] (worker://~/_plurnk/skills/*.md) <1,-1>`), plurnk references — the
|
|
463
|
-
executors, schemes, and family managers (
|
|
464
|
-
(worker://~/_plurnk/plurnk/*.md) <1,-1>`), enabled tools (
|
|
465
|
-
(worker://~/_plurnk/tools/*.md) <1,-1>`), enabled agents (
|
|
463
|
+
executors, schemes, and family managers (`### FIND0 [+init,+plurnk]
|
|
464
|
+
(worker://~/_plurnk/plurnk/*.md) <1,-1>`), enabled tools (`### FIND0 [+init,+tools]
|
|
465
|
+
(worker://~/_plurnk/tools/*.md) <1,-1>`), enabled agents (`### FIND0 [+init,+agents]
|
|
466
466
|
(worker://~/_plurnk/agents/*.md) <1,-1>`, {§a2a-agents-catalog}), enabled members
|
|
467
|
-
(
|
|
468
|
-
{§members-projection}), workspace files (
|
|
469
|
-
workspace entries (
|
|
470
|
-
private worker entries (
|
|
467
|
+
(`### FIND0 (worker://~/_plurnk/members/*.md) <1,-1>`,
|
|
468
|
+
{§members-projection}), workspace files (`### FIND0 (*) <!-- workspace files -->`),
|
|
469
|
+
workspace entries (`### FIND0 (worker:///*) <!-- workspace entries -->`), and
|
|
470
|
+
private worker entries (`### FIND0 (worker://~/*) <!-- private worker entries -->`).
|
|
471
471
|
Only those three namespace surveys carry annotations because the bare targets do not
|
|
472
472
|
name their surface; generated paths and classification tags already name every other
|
|
473
473
|
survey. Naming `~` private prevents a worker from offering its own `~` address to
|
|
@@ -475,8 +475,8 @@ another worker.
|
|
|
475
475
|
The word `skills` names Agent Skills and nothing else.
|
|
476
476
|
The catalogs select every direct document independently of its authored body;
|
|
477
477
|
ordinary READ supplies its examples and complete instructions on demand. Their
|
|
478
|
-
|
|
479
|
-
|
|
478
|
+
opening discovery is one `init` set, and the `skills`, `tools`, and `agents`
|
|
479
|
+
families are addressed by their generated paths. A shallow
|
|
480
480
|
result renders direct entries normally and every deeper first-segment directory
|
|
481
481
|
as an actionable `dir/**` summary with its recursive `items` and `tokens`;
|
|
482
482
|
tool-family rows also carry the concise `{§scheme-catalog-summary}` that drives
|
|
@@ -622,9 +622,9 @@ literal `workers.name` value.
|
|
|
622
622
|
| `READ` | existing literal name | Collect the named worker's deliverable. |
|
|
623
623
|
| `KILL` | existing literal name, `~` | Terminate the named worker or caller. |
|
|
624
624
|
|
|
625
|
-
- §worker-scheme-spawn **Spawn** —
|
|
626
|
-
- §worker-scheme-irc **irc** —
|
|
627
|
-
- §worker-scheme-fork **Fork** —
|
|
625
|
+
- §worker-scheme-spawn **Spawn** — `### WORK0 (worker://<name>)` with a task body creates a new worker sister (empty log) and starts it with that task on its first loop. WORK/FORK are the worker-creation verbs: EDIT is file/entry only, so EDIT on the bare worker entity is a **400** steering to WORK/FORK — the entity is not an entry. A name is **frozen per worker** but **reclaimable across time** ({§machine-processes-worker-origin}): a name held only by a *terminated* sister is free to reuse — a fresh spawn takes a new row and `worker_resolve_by_name` resolves the newest, the corpse keeping its name in permanent history. A name a *live* sister still holds is a conflict — **409 `worker '<name>' is already running`**, legible at the spawn gate, never a raw store-level uniqueness error.
|
|
626
|
+
- §worker-scheme-irc **irc** — `### SEND0 (worker://<name>)` with a message body delivers it to an existing sister, the **voice door** ({§actor-boundary-two-doors}): an active sister folds it into its next turn, an idle one wakes ({§actor-boundary-passive-wake}). A fresh receiving loop retains that worker's durable model, spawn override, and reasoning policy; the sender and daemon default do not re-select it. `### SEND0 (worker://~)` targets the caller; a literal name with no worker in the workspace is 404.
|
|
627
|
+
- §worker-scheme-fork **Fork** — `### FORK0 (worker://<name>)` with a task body branches the
|
|
628
628
|
current worker into a **named** sister: its log is deep-copied
|
|
629
629
|
({§machine-processes-fork-copies-the-log}), which continues with `task`; the
|
|
630
630
|
world is shared, never copied ({§machine-processes-fork-shares-the-world}).
|
|
@@ -656,7 +656,7 @@ EXEC git, taught by the git skill — never engine machinery.
|
|
|
656
656
|
silent to its owner; collection is lineage
|
|
657
657
|
supervision, never a
|
|
658
658
|
verb. The **pull** side mirrors the push: a path-absent
|
|
659
|
-
|
|
659
|
+
`### READ0 (worker://<name>)` collects that same result on demand for a
|
|
660
660
|
concluded worker; a worker **still running** has not delivered, so the READ
|
|
661
661
|
returns **425** (Too Early) and the turn's bare SEND signal `102` **becomes a
|
|
662
662
|
parked loop (202) on the join** ({§join-blocking-collect}) until the worker
|
|
@@ -666,7 +666,7 @@ EXEC git, taught by the git skill — never engine machinery.
|
|
|
666
666
|
- §child-orientation **Child orientation.** Beyond the conclusion delta, every
|
|
667
667
|
turn the packet's status clump surfaces the live things this worker currently
|
|
668
668
|
holds — open streams (`## Child Streams`) and unconcluded child workers
|
|
669
|
-
(`## Active Child Workers`) — as
|
|
669
|
+
(`## Active Child Workers`) — as `{status, path}` JSON pointers (the same
|
|
670
670
|
shape as the errors section), just above it. Folded child activity is durable
|
|
671
671
|
history; this clump is the current inventory that keeps an active obligation
|
|
672
672
|
visible even when no new activity arrived. Each open stream pointer carries
|
|
@@ -681,7 +681,7 @@ Worker control rides the daemon's inject seam (active→fold, idle→enqueue+dra
|
|
|
681
681
|
|
|
682
682
|
### §worker-loop-lifecycle Worker and loop lifecycle: drain, reap, and passive wake
|
|
683
683
|
|
|
684
|
-
- §join-blocking-collect **A `READ` on a running child is a blocking join, not a poll.** A path-absent
|
|
684
|
+
- §join-blocking-collect **A `READ` on a running child is a blocking join, not a poll.** A path-absent `### READ0 (worker://<running-child>)` returns **425** (Too Early) and records a live obligation on the loop. The turn's bare SEND signal `102` is converted into an indefinite parked loop (202) instead of asking the model to poll or drive the scheduler. When the child reaches any terminal status, the same loop resumes with the result in its log. Children are bounded by their own turn and strike limits, terminal failure also wakes the parent, and the owed-wake path covers completion before the parent parks. Any `SEND` clears the per-turn arm; SEND signal `200` with a live child remains a premature-termination error. A `<seconds>` timeout-poll is the explicit polling alternative.
|
|
685
685
|
|
|
686
686
|
A worker is a **log plus a cancellation scope** — one `AbortController` per worker, reused while live and replaced only once aborted, so a cancel ends the worker as a unit and a later `runLoop` request is never born cancelled. A worker's queued loops are advanced by a **drain**: a single per-worker drain that claims loops atomically (status 100→102) and runs each under the worker's scope. A loop may spawn **streams** (execs) that outlive it; each is a row in the subscription registry ({§subscriptions}) — the durable record of what the worker holds open. Cancellation and conclusion are defined against these structures, never wall-clock timing.
|
|
687
687
|
|
|
@@ -814,7 +814,7 @@ observe their terminal results. No effect is replayed across an unknown
|
|
|
814
814
|
boundary.
|
|
815
815
|
|
|
816
816
|
- §worker-lifecycle-single-drain **One drain advances a worker.** At most one drain is registered for a worker at any instant: a `runLoop` request or wake on a worker with a live drain folds in (active→next-turn) or enqueues a loop that drain claims, never a second parallel drain. A drain's start and its empty-queue teardown relinquish the worker under one per-worker lock, so the teardown's re-claim cannot race a concurrent start into a double-drain. Fresh-loop sequence allocation and insertion are one mutation under that same lock; concurrent accepted prompts remain distinct ordered queue items.
|
|
817
|
-
- §worker-lifecycle-total-reap **Cancellation is recursive and reaps every held stream.** `loop.cancel`, worker `KILL`, shutdown, and a worker's SEND signal `499` terminalize every unresolved loop in the cancelled worker subtree and iterate each worker's durable open-subscription rows, invoking each exact callable owner from the process-local live registry. The durable rows answer *what is held*; the live registry answers *how this process tears it down*; the abort signal is a fast-path optimization. There is no implicit detachment. Before shutdown awaits drains, it cancels every process-local proposal waiter through {§proposal-cancel-aborts} with outcome `daemon_stopping`, so a stopped-world dispatch cannot hold teardown open. A stream that is running, mid-spawn (its row written before it is killable), or spawned after the cancel is reaped alike. The teardown abort is bounded: the executor sends a polite signal then SIGKILL after a consumer-set grace (`PLURNK_SERVICE_EXEC_KILL_GRACE_MS`). A model
|
|
817
|
+
- §worker-lifecycle-total-reap **Cancellation is recursive and reaps every held stream.** `loop.cancel`, worker `KILL`, shutdown, and a worker's SEND signal `499` terminalize every unresolved loop in the cancelled worker subtree and iterate each worker's durable open-subscription rows, invoking each exact callable owner from the process-local live registry. The durable rows answer *what is held*; the live registry answers *how this process tears it down*; the abort signal is a fast-path optimization. There is no implicit detachment. Before shutdown awaits drains, it cancels every process-local proposal waiter through {§proposal-cancel-aborts} with outcome `daemon_stopping`, so a stopped-world dispatch cannot hold teardown open. A stream that is running, mid-spawn (its row written before it is killable), or spawned after the cancel is reaped alike. The teardown abort is bounded: the executor sends a polite signal then SIGKILL after a consumer-set grace (`PLURNK_SERVICE_EXEC_KILL_GRACE_MS`). A model `### KILL0 [code]` on one live stream instead delivers exactly that signal once (bare KILL uses the executor's SIGHUP default; `### KILL0 [9]` uses SIGKILL).
|
|
818
818
|
- §worker-lifecycle-exec-epoch-bound **A stream's kill binds to the scope it captured at spawn.** A stream captures the worker's cancellation scope as it registers and wires its kill to it, re-checking `aborted` AFTER wiring — no check-then-listen gap can drop an abort that lands mid-registration. Because the scope is replaced only once aborted, a captured-then-replaced scope is necessarily already aborted, so replacement never strands a live stream.
|
|
819
819
|
- §worker-lifecycle-no-resurrection **A cancelled worker is not resurrected by its own torn-down work.** A stream conclusion delivered to a cancelled, idle worker starts no fresh drain: an aborted (499) conclusion is skipped, and a straggler that concluded cleanly surfaces its deliverable as an environment delta ({§env-delta}), never a revived loop. The cancel was deliberate; only an explicit `runLoop` request resumes the worker.
|
|
820
820
|
- §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.
|
|
@@ -873,7 +873,7 @@ latest context gauge.
|
|
|
873
873
|
|
|
874
874
|
### §emission-admission Provider emission admission
|
|
875
875
|
|
|
876
|
-
A completed provider exchange is an **emission attempt**, not necessarily an engine turn. The provider transports and observes the model's bytes; ANTLR is the admission authority only after provider completion. Admission requires at least one parsed source operation, no `unparsedTail`, and a trustworthy effective envelope. Canonical source begins with PLAN and ends with a terminal SEND. If no valid leading PLAN or terminal SEND was parsed, the parser supplies a bodyless
|
|
876
|
+
A completed provider exchange is an **emission attempt**, not necessarily an engine turn. The provider transports and observes the model's bytes; ANTLR is the admission authority only after provider completion. Admission requires at least one parsed source operation, no `unparsedTail`, and a trustworthy effective envelope. Canonical source begins with PLAN and ends with a terminal SEND. If no valid leading PLAN or terminal SEND was parsed, the parser supplies a bodyless `### SEND0 (NEXT)`, records its exact hard diagnostic, and Core admits the useful operations instead of resampling. Both diagnostics participate in one ordinary struck turn, never one strike apiece. An authored PLAN or terminal SEND remains a real boundary, so an error outside either authored edge, post-terminal content, a boundary-destroying tail, or no source operation rejects the entire exchange regardless of `finishReason`; no recovered prefix dispatches. Parser warnings remain admissible. `finish=length` is forensic evidence of likely truncation, not an independent rejection rule. A provider-declared resource interruption never reaches admission, even when its partial bytes form a complete-looking frame ({§provider-interrupted-attempt}). The accepted packet retains the provider's source bytes exactly in response evidence and `turnOps`; synthetic envelope statements exist only in the normalized operation program and its durable rows.
|
|
877
877
|
|
|
878
878
|
§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; scheduling may still move the complete operation class under {§op-mode-phases}. 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.
|
|
879
879
|
|
|
@@ -1135,7 +1135,7 @@ Every fact names the canonical key, never the host root or an echo of the
|
|
|
1135
1135
|
model's spelling. These classes let a caller distinguish a wrong address, an
|
|
1136
1136
|
invalid range, read-only authority, and occupied hidden state without guessing.
|
|
1137
1137
|
|
|
1138
|
-
§membership-read-refusal **A READ miss that is really a non-member is refused, not denied.** An exact-path READ of an in-root path that exists on disk but is not a member returns 404 `entry-not-member` — `'<key>' exists on disk but is not a member of this workspace.` — with a recovery naming the door (
|
|
1138
|
+
§membership-read-refusal **A READ miss that is really a non-member is refused, not denied.** An exact-path READ of an in-root path that exists on disk but is not a member returns 404 `entry-not-member` — `'<key>' exists on disk but is not a member of this workspace.` — with a recovery naming the door (`### EXEC0 [members] (add)` with a `{"glob": "<path>"}` body); it never claims absence. Occupancy surfaces, content does not ({§membership}).
|
|
1139
1139
|
|
|
1140
1140
|
§fs-world-state **The world-state harness — coverage that closes the class.** Op-outcome tests check what an op returned; the harness checks the resulting world. `WorldState.check(db)` asserts, pure-db and read-only: identity uniqueness in practice (no tuple holds two rows), the canonical fixpoint on every file-class key, channel orphan-freedom, the closed admission set (every file row's origin is Git or constraint), and sig-coherence. Generated-pick incorporation and lifecycle require filesystem/Git evidence and are covered by the composed creation matrix rather than a false pure-database proxy. The harness runs as a lifecycle-test epilogue and at every soak turn boundary, where the delta half applies: an idle turn grows the entries table by ZERO. A violation names its law and its row.
|
|
1141
1141
|
|
|
@@ -1170,7 +1170,7 @@ Registration precedes loop affinity:
|
|
|
1170
1170
|
|
|
1171
1171
|
- §op-mode-phases **A continuing turn executes in MODE phases.** A model turn describes intended effects and requested observations; it is not an imperative program whose later statements can consume invisible same-turn results. The engine therefore performs four stable phases: **Mutate** (`EDIT`, `COPY`, `MOVE`, `KILL`), **Observe** (`FIND`, `READ`, `BARE`), **Do** (all remaining non-terminal actions, including `EXEC`, `WORK`, `FORK`, and directed `SEND`), then **End** (the terminal `SEND`). `PLAN` remains the turn anchor and is recorded before those phases. Authored order is preserved within each phase. A result still lands in the next packet; phasing makes that result describe settled state instead of an accidental intermediate state.
|
|
1172
1172
|
|
|
1173
|
-
§bare-inference **BARE is isolated, synchronous retrieval over the durable child-provider policy.** Its body is the complete prompt and becomes the sole user message; Core supplies no PLURNK system packet, log context, tools, GBNF, parser, target, worker, or persistent child state. The selected provider is exactly the loop's WORK/FORK child provider, falling back to the parent provider when the durable policy is inherit. All BARE statements in one admitted turn receive logical model-call identities in authored order and launch concurrently under the loop cancellation signal. Core awaits the batch, isolates a provider failure to that operation, then records results and notifications in authored order regardless of completion order. Accounting or persistence failure is internal and fails hard. Each response is unseen retrieval work: the canonical label is
|
|
1173
|
+
§bare-inference **BARE is isolated, synchronous retrieval over the durable child-provider policy.** Its body is the complete prompt and becomes the sole user message; Core supplies no PLURNK system packet, log context, tools, GBNF, parser, target, worker, or persistent child state. The selected provider is exactly the loop's WORK/FORK child provider, falling back to the parent provider when the durable policy is inherit. All BARE statements in one admitted turn receive logical model-call identities in authored order and launch concurrently under the loop cancellation signal. Core awaits the batch, isolates a provider failure to that operation, then records results and notifications in authored order regardless of completion order. Accounting or persistence failure is internal and fails hard. Each response is unseen retrieval work: the canonical label is `### SEND0 (NEXT)`, and a same-turn `(TERM)` is refused until the next packet presents it.
|
|
1174
1174
|
|
|
1175
1175
|
- §op-synchronous **Decisive operations settle before the next scheduled operation.** The dispatcher `await`s every decisive operation. Work remains in flight only when the operation's contract deliberately creates concurrency: `FORK`, `WORK`, stream-producing `EXEC`, and a streaming `READ` after its scheme-specific acquisition boundary. Such a READ first establishes its durable subscription, returns `102`, and then retains only its `StreamSubscription`; a later scheduled operation may address that live owner. MODE changes scheduling, not completion semantics. This is why a same-turn KILL followed by SEND signal `200` concludes ({§send-premature-terminate}): KILL synchronously flips the worker's live loops terminal (`engine_terminate_worker_live_loops`) before the End phase judges the pending set, while the physical scope reap rides `cancelWorker` asynchronously and invisibly.
|
|
1176
1176
|
|
|
@@ -1211,7 +1211,7 @@ A recipient SEND (non-null path, `status` null — {§send-label}) routes to the
|
|
|
1211
1211
|
message, a worker's next prompt. A label SEND never reaches a scheme: it concludes the
|
|
1212
1212
|
turn ({§send}). Cancelling a stream and deleting an entry are KILL ({§stream}, {§move}).
|
|
1213
1213
|
|
|
1214
|
-
- §log-uniform-query **Log speaks the universal query contract** —
|
|
1214
|
+
- §log-uniform-query **Log speaks the universal query contract** — `### FIND0 (log://…)` works like every scheme's FIND. Candidates are worker rows scoped by the coordinate hierarchy ({§log-coordinate-hierarchy}) and projected exactly as READ shows them. Content dialects use `Matcher.matchCandidates`; `~semantic` and `&graph` use the same persistent derivation artifacts and candidate rankers as entries. Broad results are one-channel catalog groups whose `[0].path` is `log:///loop/turn/seq/OP`; exact matcher results are flat locations ({§find-result-projection}). Log remains the core event ledger rather than duplicating rows into `entries`; its core-private storage adapter supplies one complete channel representation to the same READ projector. That adapter is not a plugin seam and grants no protocol scheme an alternate READ path.
|
|
1215
1215
|
- §find-source-agnostic **The content matcher is source-agnostic** — `Matcher.matchCandidates(body, candidates, mimetypes)` applies a content matcher (regex/jsonpath/xpath/glob) to candidates from ANY source, keyed by the caller's own identity (a pathname for entries, a `loop/turn/seq` coordinate for log). The matcher never cares what table the content came from, so FIND works uniformly across schemes by construction: `EntryFind` and `Log.find` run the one shared primitive rather than re-implementing it per scheme. Log stays its own event stream, but its rows are candidates the shared matcher covers like any entry's content.
|
|
1216
1216
|
- §find-candidate-containment **One candidate's crash is that candidate's problem** — arbitrary member content can crash a mimetype handler mid-match (an unbalanced template partial crashed Readability and killed a 1,916-file FIND as a blank 500, #449). `Matcher.matchCandidates` contains a per-candidate handler throw: the candidate drops out exactly like unsupported content, the cause goes to daemon stderr, and only a FIND whose every candidate crashed reports a 415 whose Problem names the first crashing member and handler. The operation's other candidates always answer.
|
|
1217
1217
|
- §channel-selection-visibility **Channel selection is decision-time information, not a guess** — every multi-channel resource presents its channels with extents wherever FIND presents the resource: broad results list each channel's path, mimetype, tokens, and lines (default channel first), and matcher locations name the channel their line coordinates address. The packet never presents channels as equal and indistinguishable; extents derive from the stored channels by construction. Budget enforcement stays with {§overflow-turn} — this is information, not a second guard.
|
|
@@ -1456,7 +1456,7 @@ A published default channel renders under the entry's ordinary fragmentless addr
|
|
|
1456
1456
|
|
|
1457
1457
|
### §no-visibility Entries carry no visibility
|
|
1458
1458
|
|
|
1459
|
-
Every entry is uniformly listed in the catalog (
|
|
1459
|
+
Every entry is uniformly listed in the catalog (`### FIND0 (scheme:///**)`, {§packet}) and READable — entries have no per-worker open/folded state. Context curation is the model's, on the **log** (via KILL, {§log-kill-scope}), never on entries.
|
|
1460
1460
|
|
|
1461
1461
|
### §channel-mimetype Mimetype is a (scheme, channel) property — never a default
|
|
1462
1462
|
|
|
@@ -1560,7 +1560,7 @@ AST: `{ op: "EDIT", target, body: string | null, signal: tags | null, lineMarker
|
|
|
1560
1560
|
- §edit-null-clears Writes the body; `body: null` clears it.
|
|
1561
1561
|
- §edit-status-201-200 Returns `{ status: 201, entryId }` for a new entry and
|
|
1562
1562
|
`{ status: 200, entryId }` for a content update.
|
|
1563
|
-
- §edit-noop-304 A write that changes nothing — identical content — returns `{ status: 304, entryId }`, mirroring a scoped KILL's idempotence ({§log-kill-scope}). Its terse detail states the observed equality and the valid empty-body deletion shape; it never presumes that repetition or retrieval is the intended recovery.
|
|
1563
|
+
- §edit-noop-304 A write that changes nothing — identical content — returns `{ status: 304, entryId }`, mirroring a scoped KILL's idempotence ({§log-kill-scope}). Its terse detail states the observed equality and the valid empty-body deletion shape; it never presumes that repetition or retrieval is the intended recovery.
|
|
1564
1564
|
- §edit-marker-required-on-existing **A markerless EDIT is CREATE-ONLY — there is no easy-clobber path on an existing entry.** A `<L>` marker scopes an EDIT to a range; without one, the body becomes the entry's WHOLE content — legitimate and required for a fresh entry (nothing exists to scope into), but on an EXISTING entry a missing marker is refused **400**, never a silent full replace. A deliberate full rewrite states that intent explicitly: `<1,-1>` resolves through the ordinary marker math to the same whole-content replacement, so the capability is available but cannot be selected by omission.
|
|
1565
1565
|
- §edit-line-anchors An anchored EDIT resolves under {§line-anchors} and carries
|
|
1566
1566
|
its endpoint checks as a core-private mutation precondition. Otherwise-valid
|
|
@@ -1623,11 +1623,30 @@ selection or fan-out path.
|
|
|
1623
1623
|
into a byte READ (`region` spans the hexadecimal lines of the matched bytes; `matched`
|
|
1624
1624
|
is their hex). The load is bounded by the mimetypes binary input ceiling; a larger
|
|
1625
1625
|
resource fails 413 `bytes-too-large` by name rather than being skipped.
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1626
|
+
- §binary-parity A binary member is not a second-class resource. It behaves exactly as a text
|
|
1627
|
+
member does for existence, FIND by path, KILL/delete, mimetype, weight, and membership; it
|
|
1628
|
+
READs whole as its byte projection ({§read-bytes}) or as a native attachment ({§packet-attachment-parts}),
|
|
1629
|
+
READs and FINDs by byte range and byte pattern ({§read-bytes}/{§find-bytes}); and COPY or MOVE transfers
|
|
1630
|
+
its bytes exactly, between file members and into or out of a DB-backed `worker://` entry alike. A
|
|
1631
|
+
whole-resource transfer writes the source's bytes ({§read-bytes} `ByteSource`) verbatim to the
|
|
1632
|
+
destination through the ordinary proposal gate, the receipt reporting the byte count rather than a text
|
|
1633
|
+
line diff; "whole-resource" is the markerless selection or `<1,-1>` ({§move-canonical-whole-source}),
|
|
1634
|
+
and a MOVE deletes the source after the destination lands. A **byte range** `<a,b>` transfers exactly
|
|
1635
|
+
those source bytes (coordinate = byte, 1-indexed inclusive). A transfer **into** a destination byte
|
|
1636
|
+
range is a splice: `<c,d>` replaces exactly the destination bytes c..d with the source bytes and a
|
|
1637
|
+
single position `<c>` inserts the source bytes before byte c (`<-1>` appends); every byte outside the
|
|
1638
|
+
window is preserved, and the whole spliced result is re-written through the proposal gate. A binary
|
|
1639
|
+
**lives in a DB entry** as its bytes base64 in the channel's TEXT content; the same READ, byte range,
|
|
1640
|
+
and COPY/MOVE recover them through a byte source synthesized from that content, so a File member and a
|
|
1641
|
+
`worker://` entry hold and yield a binary identically. This supersedes the older blanket refusal (#140)
|
|
1642
|
+
for both the file and the entry case. Two projections stay with the materialized File member, drawn from
|
|
1643
|
+
its source-projection facts: the native image/PDF **attachment** ({§packet-attachment-parts}) and its
|
|
1644
|
+
dimensions; a `worker://` entry binary reads as its byte projection. The exceptions are narrow and
|
|
1645
|
+
defined, each a clear receipt rather than a dead end: a binary region addressed by a **textual anchor**
|
|
1646
|
+
rather than a numeric byte coordinate has no meaning (416 — bytes are not lines), **authoring** binary
|
|
1647
|
+
content from a text EDIT body is impossible (a text emission cannot type bytes), and a scheme that keeps
|
|
1648
|
+
no bytes for a binary channel — no disk file, no stored content — has nothing to transfer and says so
|
|
1649
|
+
(415). None is the entry-storage dead end the older text named; that cell is filled.
|
|
1631
1650
|
|
|
1632
1651
|
### §log-history-projection Durable history and active projection
|
|
1633
1652
|
|
|
@@ -1647,9 +1666,21 @@ AST: `{ op: "KILL", target, body: MatcherBody | null, lineMarker: TextLineMarker
|
|
|
1647
1666
|
|
|
1648
1667
|
KILL is the model's one context-curation verb on 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 folds only that body's intersecting body-relative physical lines away from the packet projection, and the row stays. An anchor may be one already published on that immutable body or one returned by READing its `log:///` coordinate ({§line-anchors}); a stale anchor is 412 and an unrelated one is 422. Scoped KILL is one-way: intervals accumulate under the one-way interval algebra and nothing reopens them — the durable body is untouched, and the model re-READs the source when it needs the text again. 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 matcher body ({§log-curation-set-selection}); a targetless KILL is 400.
|
|
1649
1668
|
|
|
1650
|
-
### §
|
|
1669
|
+
### §log-wire-format The Log's wire format
|
|
1670
|
+
|
|
1671
|
+
The `## Log` section is a sequence of ordinary Markdown records separated by one blank line:
|
|
1672
|
+
|
|
1673
|
+
```text
|
|
1674
|
+
### log:///<loop>/<turn>/<item>/<leaf>
|
|
1675
|
+
{"oneLine":"strict JSON metadata"}
|
|
1676
|
+
<coordinate-prefixed body lines when open>
|
|
1677
|
+
```
|
|
1678
|
+
|
|
1679
|
+
The H3 is the row's complete model-facing identity and canonical READ target; metadata never duplicates `path` or `op`. The following line is one strict JSON object whose members use stable alphabetical order. 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.
|
|
1680
|
+
|
|
1681
|
+
The three body states are self-describing: coordinate lines mean open, `tokensBody` without coordinate lines means folded, and neither means no canonical body. A partially hidden open row carries `"folded":["<scope>",...]`; coordinate gaps expose the omissions without renumbering. A bounded projection carries `"chunk":"showing <selected> of <complete>"` in metadata. Complete-line extents use inclusive two-coordinate regions; a cut inside a line uses four-coordinate, start-inclusive and end-exclusive regions with 1-based Unicode code-point columns.
|
|
1651
1682
|
|
|
1652
|
-
|
|
1683
|
+
Field absence carries defaults: `origin` is omitted for the owning model, `source` for the owning worker, and `status` for a routine 200. SEND always carries its submit code, KILL keeps an explicit 200, and every non-200 stays explicit. A present authored annotation appears as `annotation`. Every row's accounting follows {§packet-token-accounting}.
|
|
1653
1684
|
|
|
1654
1685
|
- §packet-attachment-parts A READ of an attachable member carries its facts from the member's projection
|
|
1655
1686
|
({§mimetype-projection-facts}): an image ({§mimetype-image}) as `image: { mimetype, width, height, bytes }`,
|
|
@@ -1667,7 +1698,7 @@ The `## Log` section renders as a fixed three-backtick `jsonplurnk` fence - a JS
|
|
|
1667
1698
|
rendered between the definition and the policy, carries one `example`-fenced READ line per kind the
|
|
1668
1699
|
route accepts and the daemon can attach, from the same table; a route that accepts no attachable kind has
|
|
1669
1700
|
no section, so no model is told of a capability its route lacks (#497).
|
|
1670
|
-
- §packet-token-accounting Every row reports its real weight so the packet self-reconciles against the budget: `tokensBody` is the projected body's nonzero weight whenever a canonical body would render (never `0` — a priceless visible body is field absence), and `tokensActive` is the complete row's weight in the packet right now. The metadata share is derivable (`tokensActive − tokensBody` when open; `tokensActive` otherwise) and is never serialized — it feeds no curation decision. Thus a scoped KILL removes the rendered body's weight while a whole KILL removes `tokensActive`; on a folded row `tokensBody` previews the body share the fold reclaimed. The completed
|
|
1701
|
+
- §packet-token-accounting Every row reports its real weight so the packet self-reconciles against the budget: `tokensBody` is the projected body's nonzero weight whenever a canonical body would render (never `0` — a priceless visible body is field absence), and `tokensActive` is the complete row's weight in the packet right now. The metadata share is derivable (`tokensActive − tokensBody` when open; `tokensActive` otherwise) and is never serialized — it feeds no curation decision. Thus a scoped KILL removes the rendered body's weight while a whole KILL removes `tokensActive`; on a folded row `tokensBody` previews the body share the fold reclaimed. The completed record, including its H3, metadata, and body, is measured to a fixed point. A FIND's nonzero `itemsTokenTotal` weighs the complete matched set; a nonzero `returnedItemsTokenTotal` appears only when the returned page has a different weight. These are curation weights, not dollars. The invariants bind regardless of shape ({§packet}): addressability (record H3/`target`/`#channel`/coordinate-prefixed bodies), weighability (per-item `tokens`), honesty (every 4xx/5xx row and the exact body state). {§log-wire-format} {§packet-log-records}
|
|
1671
1702
|
|
|
1672
1703
|
### §retrieval-packet-metadata READ/FIND packet metadata
|
|
1673
1704
|
|
|
@@ -1694,7 +1725,7 @@ and its internally resolved whole-line region. Exact READ retains only its
|
|
|
1694
1725
|
region. A failed retrieval's Problem owns its range extension rather than
|
|
1695
1726
|
repeating it at top level. Generic `tokens` always weighs the rendered body;
|
|
1696
1727
|
generic body `lines` remains available on READ-shaped materialization notices
|
|
1697
|
-
that have no retrieval extent. FIND content weights follow {§
|
|
1728
|
+
that have no retrieval extent. FIND content weights follow {§log-wire-format};
|
|
1698
1729
|
ordinary bounded bodies expose their displayed and complete chunk extents there.
|
|
1699
1730
|
|
|
1700
1731
|
### §turn-ops-entry The admitted turn program
|
|
@@ -1703,9 +1734,9 @@ ordinary bounded bodies expose their displayed and complete chunk extents there.
|
|
|
1703
1734
|
|
|
1704
1735
|
§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 folded and projected visibly only in the informed recovery packet; every other rejected attempt remains forensic-only.
|
|
1705
1736
|
|
|
1706
|
-
- §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
|
|
1707
|
-
- §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:
|
|
1708
|
-
- §log-curation-set-selection **Row selection and body scope are independent** — target/glob and an optional body matcher 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
|
|
1737
|
+
- §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 `### READ0 (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: `/OP` for an operation, `/ops` for an admitted turn program, or `/attempt` for a rejected emission. 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. 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:///**/ops`, and `log:///**/attempt` deliberately filter canonical leaves. An EXEC's output stream lives at that same item address under its runtime tag — `sh:///1/2/3/EXEC#stdout` — so one `loop/turn/item/OP` schema addresses every item, log rows and streams alike.
|
|
1738
|
+
- §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: `### KILL0 (log:///1/2) <1,-1>` folds turn 1/2's bodies. A **well-formed selection that matches nothing is 204 with `matched: 0`**; a successful sweep's rx carries `matched: N`. A targetless KILL is 400.
|
|
1739
|
+
- §log-curation-set-selection **Row selection and body scope are independent** — target/glob and an optional body matcher 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 `### KILL0 (log:///**/READ) <17,-1>` may change long READs and no-op on short ones while reporting every selected row in `matched`.
|
|
1709
1740
|
|
|
1710
1741
|
§log-kill-meta-operation **A log KILL is a meta-operation — a log-curation directive, not a world action.** It changes log visibility, never the underlying resources. A **successful** log KILL **is recorded in the log** and **renders exactly once** — in the packet after its turn, as its path, target, and status — then dissolves from the projection ({§curation-receipt-dissolves}): the actor sees its `200` or `204` at the one moment it decides whether to conclude or repeat, and the row exists for forensics (a curation act with NO trace is how a weak model folding its own task frame stayed invisible until a database dig).
|
|
1711
1742
|
|
|
@@ -1747,8 +1778,6 @@ body: ResourceSelection (destination), signal: tags | null }`.
|
|
|
1747
1778
|
channels survive.
|
|
1748
1779
|
- §copy-conflict-409 Different content in that channel is 409.
|
|
1749
1780
|
- §copy-noop-304 Identical content is 304.
|
|
1750
|
-
5. The signal classifies the COPY log item and never changes either resource
|
|
1751
|
-
({§log-item-tags}).
|
|
1752
1781
|
|
|
1753
1782
|
§copy-cross-scheme-copy The result is 201 for a new entry, 200 for a write, 304 for an exact no-op, or
|
|
1754
1783
|
202 when the owning scheme requires proposal review. Same- and cross-scheme
|
|
@@ -1899,14 +1928,14 @@ violations (a missing PLAN or terminal SEND, an operation dropped by a parse
|
|
|
1899
1928
|
failure) do strike: six in a row is a degenerated run.
|
|
1900
1929
|
|
|
1901
1930
|
- §send-target-recipient **A SEND target is a recipient.** A model's directed SEND
|
|
1902
|
-
addresses a worker (
|
|
1931
|
+
addresses a worker (`### SEND0 (worker://<name>)`), an outbound agent (`a2a://`),
|
|
1903
1932
|
or a scheme that implements SEND (an `https://` POST). A SEND to a scheme the model may not write (the prompt, the
|
|
1904
1933
|
log) is refused 400 `send-target-not-a-recipient`, never the unrelated writer
|
|
1905
1934
|
rule. The detail states only that the addressed scheme is not a recipient;
|
|
1906
1935
|
neutral recovery distinguishes targetless replies from directed SEND without
|
|
1907
1936
|
guessing which one was intended. A scheme that does not implement SEND
|
|
1908
1937
|
answers its ordinary factual 501 without grafting a guessed recovery onto it.
|
|
1909
|
-
- §send-idle-turn **Idle turn** — a continuing turn (102) whose ops are only PLAN/SEND — no work op. The model continued with nothing to do. The steer, verbatim: *"If your work is done, conclude with
|
|
1938
|
+
- §send-idle-turn **Idle turn** — a continuing turn (102) whose ops are only PLAN/SEND — no work op. The model continued with nothing to do. The steer, verbatim: *"If your work is done, conclude with `### SEND0 (TERM)`. If you're waiting on a child or stream you spawned, use `### SEND0 (WAIT)` to block on it — a 202 with nothing to wait on simply concludes."* A successful same-turn scoped KILL is the exception: its `202` continues without a strike so the curated packet can support the next reasoning turn. **An empty `(NEXT)` while the worker holds a live stream or child is a mis-spelled wait, not idleness**: the engine parks the turn as `(WAIT)` — the same live-work predicate the `(TERM)` gate uses, so the shift never disagrees with the orientation the model reads — records the SEND as `202` with the correction in that row's annotation (a park drops transient notices; the row survives the wake); no strike. With nothing in flight the idle-turn 409 stands — it is the deterministic recovery for that case.
|
|
1910
1939
|
- §send-premature-terminate **Premature terminate — the pending set.**
|
|
1911
1940
|
A model's completion claim is gated by one rule: *nothing pending may be silently
|
|
1912
1941
|
discarded*. Pending work has two states: **live obligations** (open
|
|
@@ -2047,12 +2076,12 @@ dispatch admission, and pull-document materialization. Core performs no
|
|
|
2047
2076
|
protocol discovery while building a packet and has no alternate tool
|
|
2048
2077
|
catalogue.
|
|
2049
2078
|
|
|
2050
|
-
Per-tool programs such as `go`, `cargo`, `make`, and `npm` do not earn executor tags merely because they are executables; they are complete shell commands under
|
|
2079
|
+
Per-tool programs such as `go`, `cargo`, `make`, and `npm` do not earn executor tags merely because they are executables; they are complete shell commands under `### EXEC0` or `### EXEC0 (sh)`. Registered tags exist only for tools that own a distinct body, target, or output contract. {§exec-registry-resolves}
|
|
2051
2080
|
|
|
2052
2081
|
**Timeout and poll — `<T,P>` on the `<L>` slot (grammar 0.74.20).** EXEC
|
|
2053
2082
|
repurposes the line-marker slot as `<timeout, poll>` in **minutes** — agentic
|
|
2054
2083
|
latencies make a sub-minute horizon a trap — converted at the parse boundary to the
|
|
2055
|
-
catalog's internal `stream.seconds`. The
|
|
2084
|
+
catalog's internal `stream.seconds`. The `### SEND0 (WAIT) <T>` wait horizon is minutes too.
|
|
2056
2085
|
|
|
2057
2086
|
§exec-timeout `T` (`mark[0]`) caps the spawn's lifetime. At `T>0` the service
|
|
2058
2087
|
aborts it — a bounded reap, polite signal then SIGKILL after
|
|
@@ -2147,7 +2176,7 @@ service's ({§operator-config}), fail-hard on any other value.
|
|
|
2147
2176
|
§exec-stream-page **An unrequested delivery never exceeds the retrieval page.** The
|
|
2148
2177
|
terminal observation is the same page a markerless READ returns, whatever the
|
|
2149
2178
|
mimetype and however many turns the stream ran: the channel keeps every line for a
|
|
2150
|
-
scoped READ (
|
|
2179
|
+
scoped READ (`### READ0 (<runtime>:///<coord>#<channel>) <L,M>`), and the extent
|
|
2151
2180
|
tells the model the total. Only the active user prompt and the generated project
|
|
2152
2181
|
instructions are delivered without this bound; the model receives more than a page
|
|
2153
2182
|
only by asking.
|
|
@@ -2166,7 +2195,7 @@ its selected result complete. A stream that closes before a same-turn wait
|
|
|
2166
2195
|
remains pending until every selected channel's terminal READ crosses the next
|
|
2167
2196
|
packet boundary. The EXEC row separately records the authored invocation.
|
|
2168
2197
|
|
|
2169
|
-
|
|
2198
|
+
`### KILL0 (<runtime>:///<loop>/<turn>/<seq>/EXEC)` cancels an active subprocess via
|
|
2170
2199
|
the subscription registry's stored controller. A terminal stream is immutable:
|
|
2171
2200
|
499 returns 410 (already killed), every other terminal status returns an RFC
|
|
2172
2201
|
9457 409 Problem carrying `terminalStatus`, and an unknown address returns 404.
|
|
@@ -2176,7 +2205,7 @@ stream cannot fall through an internal `exec`-only query. {§stream-control}
|
|
|
2176
2205
|
§exec-env-scoped **Scoped environment.** An EXEC subprocess inherits the *project's* environment — its `.env`, the standard shell vars — so the model's commands run as the project expects; but never plurnk's own secrets: the provider API keys and `PLURNK_*` config are stripped before the spawn, so a model-executed command can't `printenv` the engine's keys. The service owns the scoping policy (the denylist); the executor spawns with the env it is handed.
|
|
2177
2206
|
|
|
2178
2207
|
- §exec-hold-until-concluded **The turn-hold exception** — for runtimes in `PLURNK_SERVICE_EXEC_HOLD` (a decision-table env, shipped listing the search family), an in-flight stream **pauses the cycle**: the next packet does not assemble until the stream concludes, so the model never burns a turn asking "are we there yet" about a result the engine controls end-to-end. This exception is limited to seconds-bounded runtimes whose final result the engine controls end-to-end. Bounded by `PLURNK_SERVICE_EXEC_HOLD_MS` and **fail-open**: at the cap the standard cycle resumes untouched (waits, wakes, polls). Zero grammar or teaching surface — the model emits EXEC followed by SEND signal `102` as ever; the wake-shaped world simply arrives one packet sooner. It extends selected runtimes beyond the ordinary {§worker-optimistic-settlement} cap before the next packet assembles. A bare entry holds ALL of a runtime's spawns; a `<runtime>:<effect>` suffix (`github:read`) holds only that effect-class — an MCP server is one runtime whose tools split (a `read` `get_issue` is instant; a `host` `run_migration` is a slow mutation), so an operator opts the known-fast read-class in without parking on the mutation. Conservative stays default: an arbitrary third-party server's latency never parks the engine unless a suffix opts a class in.
|
|
2179
|
-
- §exec-entry-sink **The entry() sink** — an executor may *request* entry materialization (execs SPEC §2.6: every sink is a consumer-implemented callback; the executor owns zero substrate). The service implements it in exec dispatch: `entry(path, content: string | null, {
|
|
2208
|
+
- §exec-entry-sink **The entry() sink** — an executor may *request* entry materialization (execs SPEC §2.6: every sink is a consumer-implemented callback; the executor owns zero substrate). The service implements it in exec dispatch: `entry(path, content: string | null, {mimetype?})` upserts the entry, then records ONE typed `EDIT` row in the reserved `plurnk` worker's log — the fs-fiction pattern, `source` = the calling worker, `weight` = the canonical resulting span's curation weight, and `attrs.kind="entry_materialized"`. Durable replay and clients retain that exact creation event. The model packet projects the typed event as a folded system `READ` of the resulting ordinary resource: its relevant truth is readable state now available in the environment, not an agent-authored mutation. **The executor owns no fetcher:** a `content: null` is a *declaration* — the service acquires the page through schemes-http's checked WebFetcher and accepts its model-facing body and available source/evidence channels {§html-materialization}. Generic public HTML follows the same origin-Markdown, configured materializer, and local-projection routes as exact HTTP acquisition ({§http-materializer-plugins}). A failed acquisition, body-production failure, materialization exception, or absent final projection rejects the sink and produces no HTTP entry, but does not invalidate a search runtime's upstream discovery row; materialization exceptions retain their cause in daemon diagnostics. A non-null `content` is the materialize-given-body path (the caller already holds the bytes and states their mimetype) and grants no provider authority. **No page body ever rides a packet**; the announcement is the folded row's path and weight, and the model READs/~queries what it chooses. Parallel `entry()` calls serialize on a per-spawn chain; a rejected call leaves the chain healthy. The spawn tail settles that complete chain before unregistering, so executor idleness and shutdown are barriers over its materialization writes. The narration context (one plurnk-worker turn) is lazy per spawn, not per entry.
|
|
2180
2209
|
|
|
2181
2210
|
### §proposal The proposal lifecycle
|
|
2182
2211
|
|
|
@@ -2275,14 +2304,14 @@ Model sees lifecycle events in the `log` section per turn.
|
|
|
2275
2304
|
|
|
2276
2305
|
### §deep-slices Deep slices on demand
|
|
2277
2306
|
|
|
2278
|
-
|
|
2307
|
+
`### READ0 (https://feed.example/x#body) <N-M>` pulls a slice into a log row when the model wants a specific line-range of an SSE stream.
|
|
2279
2308
|
|
|
2280
2309
|
### §stream-control Stream control and writes
|
|
2281
2310
|
|
|
2282
|
-
- **Cancel:**
|
|
2283
|
-
- **Kill:**
|
|
2284
|
-
- **WebSocket write:**
|
|
2285
|
-
- **Other stream write:**
|
|
2311
|
+
- **Cancel:** `### KILL0 (https://feed.example/x)` — the service invokes the handle registered by `subscriptions.open()` and aborts the composed subscription signal.
|
|
2312
|
+
- **Kill:** `### KILL0 (sh:///1/2/3/EXEC)` — the model terminates its own runtime stream. This is stream control, not a write: the output scheme's `writableBy` never gates it, `Exec.kill` scopes the address to the caller ({§stream-owner-scoped}), and a finished stream answers 410 under its own tag. A queued execution ({§exec-concurrency}) is cancelled the same way and never enters its executor.
|
|
2313
|
+
- **WebSocket write:** `### EDIT0 (wss://feed/x)` or `### SEND0 (wss://feed/x)` with a body sends one whole text frame through the active owner. SEND can follow the opening READ in the same turn; EDIT runs before READ ({§op-mode-phases}) and therefore addresses an owner already open at turn start.
|
|
2314
|
+
- **Other stream write:** `### SEND0 [200] (…)` remains scheme-defined, including exec stdin.
|
|
2286
2315
|
|
|
2287
2316
|
### §stream-constraints Engine constraints
|
|
2288
2317
|
|
|
@@ -2423,7 +2452,7 @@ scheme. External schemes are discovered through
|
|
|
2423
2452
|
dispatcher contract.
|
|
2424
2453
|
|
|
2425
2454
|
The executor registry discovers installed runtimes, probes availability, and
|
|
2426
|
-
routes
|
|
2455
|
+
routes `### EXEC0 [<runtime>]`; core contributes orchestration and the output-scheme
|
|
2427
2456
|
adapter, not runtime implementations. Optional and third-party leaves extend
|
|
2428
2457
|
each family by installation and discovery; they never require a framework or
|
|
2429
2458
|
service manifest edit.
|
|
@@ -3275,8 +3304,7 @@ time of measurement.
|
|
|
3275
3304
|
|
|
3276
3305
|
- §tokenomics-weight-stored-at-write **Curation weight, stored at write.** `entry_channels.weight` weighs the complete channel content. `log_entries.weight` weighs the complete canonical `LogBody` content before coordinate and packet presentation; persistence `tx`/`rx` envelopes contribute nothing merely by existing, and proposal settlement recomputes the value when the canonical result changes. Bodyless rows therefore weigh zero. The stored number is a stable content-depth measurement, not a provider-token prediction.
|
|
3277
3306
|
- §tokenomics-render-weight-budget **Packet curation budget.** `tokensActiveTotal` measures the *complete assembled packet* after section transforms and readout substitution; it is not a sum of log-row `tokensActive` fields. Core measures minimum-width probes, monotonically expands fields that do not fit, then right-aligns final values into those widths; final substitution is length-invariant and the displayed total equals the stored request weight. `tokensActiveMax` is the provider-derived curation calibration. A `SUM` of stored content weights measures a different artifact and cannot substitute for packet render weight.
|
|
3278
|
-
- §tokenomics-
|
|
3279
|
-
- §tokenomics-calibrated-readout **The readout is calibrated to the answering model.** The model-independent ruler overstates what a tokenizer charges by a model-specific ratio (1.3–1.6× on Qwen3.8 packets, measured 2026-09-02, which fired the pressure mandate at half the real ceiling). Before rendering the readout, Core takes this model's last five settled emission responses that pair a measured packet weight with a provider-reported prompt count and scales `tokensActiveTotal`, its percent, the pressure-inventory figures, and the overflow admission by reported ÷ measured. Fewer than three samples leave the factor at 1. Samples are keyed by the model name the provider reports, so a model change starts from 1 again; stored weights and the client gauge stay in the model-independent ruler ({§tokenomics-agnostic-ruler}).
|
|
3307
|
+
- §tokenomics-calibrated-readout **The readout is calibrated to the answering model.** The model-independent ruler overstates what a tokenizer charges by a model-specific ratio (1.3–1.6× on Qwen3.8 packets, measured 2026-09-02, which fired the pressure mandate at half the real ceiling). Before rendering the readout, Core takes this model's last five settled emission responses that pair a measured packet weight with a provider-reported prompt count and scales `tokensActiveTotal`, the pressure-inventory figures, and the overflow admission by reported ÷ measured. Fewer than three samples leave the factor at 1. Samples are keyed by the model name the provider reports, so a model change starts from 1 again; stored weights and the client gauge stay in the model-independent ruler ({§tokenomics-agnostic-ruler}).
|
|
3280
3308
|
- §tokenomics-window-partition **One capacity derivation; no service-side token budget.** The provider owns model limits and the configured total output envelope. Its resolved `inputCapacity` is the numeric curation-budget calibration as well as the physical denominator exposed to clients. That reuse is policy, not a unit conversion: Core compares stable curation weight with it only to shape context, while provider request-shaped evidence alone admits or rejects I/O. `PLURNK_SERVICE_PROMPT_BUDGET`, `PLURNK_SERVICE_SAFETY`, and the additive reasoning/completion reserve knobs are retired; local and custom deployments tune context window, total output budget, optional reasoning subset, and prompt-projection percentage at their owning layers.
|
|
3281
3309
|
- §tokenomics-prompt-projection-share **Prompt projection is stable packet policy.**
|
|
3282
3310
|
`PLURNK_SERVICE_PROMPT_PROJECTION` is a required alias-scoped percentage in
|
|
@@ -3292,11 +3320,11 @@ time of measurement.
|
|
|
3292
3320
|
- **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 vector coverage. A semantic query ranks every eligible candidate in scope, so lexical overlap never gates vector recall. With no embedder, readable-content FTS is the explicit keyword fallback. Progress notices make the wait visible; latency is never hidden by partial semantics. {§derivation-exhaustive}
|
|
3293
3321
|
- §membership-binary-sniff **Binary truth beats the label; no entry dominates the corpus.** A tracked member whose HEAD bytes contain NUL enters {§membership-source-projection} as `application/octet-stream` **regardless of what extension-based detection claims**; byte-level evidence outranks a default label. Every eligible text is tiled losslessly to the embedder window and every tile is embedded before its derivation attaches; semantic ranking max-pools the best chunk per candidate.
|
|
3294
3322
|
- §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.
|
|
3295
|
-
- §tokenomics-neutral-telemetry **Curation telemetry is state, not response allowance.** The model-facing `Context Token Budget` section
|
|
3296
|
-
- §tokenomics-pressure-inventory **Pressure identifies its reclaimable concentration.** When the ordinary two-field packet measurement reaches 80% of `tokensActiveMax`, the
|
|
3323
|
+
- §tokenomics-neutral-telemetry **Curation telemetry is state, not response allowance.** The model-facing `Context Token Budget` section is one JSON object carrying `tokensActiveTotal` and `tokensActiveMax` (and `tokensResponseMax` when an output floor is disclosed), so the block opens as a JSON payload like `## PLAN0`. 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.
|
|
3324
|
+
- §tokenomics-pressure-inventory **Pressure identifies its reclaimable concentration.** When the ordinary two-field packet measurement reaches 80% of `tokensActiveMax`, the JSON object gains a `tokensActiveLargest` array — at most five currently visible, addressed log bodies, each a flat `{path, tokensBody, tokensActive}` object ordered by `tokensActive` descending and then `log:///` path — and the `YOU MUST KILL superseded, stale, or irrelevant log items and ranges.` mandate follows the object, naming the targets it lists. Folded and bodyless rows cannot enter the list because a scoped KILL would reclaim no body from them. The largest prefix that fits may be shown; this conditional block never pushes an otherwise admissible packet over its maximum. Its own weight participates in the final fixed-point `tokensActiveTotal`.
|
|
3297
3325
|
- §tokenomics-content-hash-identity **Content identity, not per-tokenizer counts.** Static channel writes stamp `content_hash` (SHA-256) as stable content identity. `weight` is stored beside that content and is never keyed or recomputed by model.
|
|
3298
3326
|
- §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` and `embedding_calls` own domain response/failure evidence, `turn_attempts` specialize emission admission, and `provider_requests` are the sole durable accounting representation. Emissions, BARE calls, embeddings, 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.
|
|
3299
|
-
- §tokenomics-negative-pressure **Negative curation pressure is honest but never submitted.** The provisional readout may report `tokensActiveTotal`
|
|
3327
|
+
- §tokenomics-negative-pressure **Negative curation pressure is honest but never submitted.** The provisional readout may report `tokensActiveTotal` above `tokensActiveMax`. Crossing the maximum diverts that would-be model turn into {§overflow-turn}; no over-ceiling packet reaches `provider.generate`. Automatic recovery does not create a strike or consume a model-turn allowance.
|
|
3300
3328
|
|
|
3301
3329
|
### §membership Workspace identity, membership, disk co-location
|
|
3302
3330
|
|
|
@@ -3334,7 +3362,7 @@ query is the absolute identity ({§scheme-address-network}); the sanitized
|
|
|
3334
3362
|
readable projection is the fragmentless default, while faithful DOM, origin
|
|
3335
3363
|
media type, and projection identity remain explicit auxiliary evidence. A
|
|
3336
3364
|
normal
|
|
3337
|
-
|
|
3365
|
+
`### READ0 (https://host/path?query)` therefore publishes only the sanitized body
|
|
3338
3366
|
under that exact URL—never raw HTML, response headers, or a channel-selection
|
|
3339
3367
|
lesson. FIND and embeddings consume the addressed stored channel representation
|
|
3340
3368
|
and never re-fetch a match.
|
|
@@ -3387,7 +3415,7 @@ and never re-fetch a match.
|
|
|
3387
3415
|
- §membership-git-hermetic Native Git runs with ambient `GIT_*` and
|
|
3388
3416
|
global/system config scrubbed, so repository identity follows `project_root`,
|
|
3389
3417
|
never the daemon's launch environment.
|
|
3390
|
-
- §membership-edit-membership-gate **Membership-gated edits.** EDIT is bounded by membership exactly as READ is. An existing **member**'s baseline is its entry snapshot — the body channel the model READ, not a fresh disk read — so the diff is naive against the view the model saw, never empty (the write-side CAS, {§membership-edit-write-cas}, prevents the silent overwrite of out-of-band drift). An existing **non-member** is refused (403) *before* any read or write: the model never reads a file it can't see (no leak into the proposal) and never overwrites one (no wiping a gitignored `.env` it never added). A **new path** crosses the creation matrix in {§fs-write-surface}; proposal acceptance cannot bypass its scope, exclusion, or incorporation rules. Reaching past membership is
|
|
3418
|
+
- §membership-edit-membership-gate **Membership-gated edits.** EDIT is bounded by membership exactly as READ is. An existing **member**'s baseline is its entry snapshot — the body channel the model READ, not a fresh disk read — so the diff is naive against the view the model saw, never empty (the write-side CAS, {§membership-edit-write-cas}, prevents the silent overwrite of out-of-band drift). An existing **non-member** is refused (403) *before* any read or write: the model never reads a file it can't see (no leak into the proposal) and never overwrites one (no wiping a gitignored `.env` it never added). A **new path** crosses the creation matrix in {§fs-write-surface}; proposal acceptance cannot bypass its scope, exclusion, or incorporation rules. Reaching past membership is `### EXEC0 (sh)`'s job, not the file scheme's.
|
|
3391
3419
|
- §membership-create-parents **Parent-complete creation.** An accepted File creation—whether authored as EDIT or as a COPY/MOVE destination—recursively creates missing parent directories before writing and registering the new member.
|
|
3392
3420
|
|
|
3393
3421
|
**The overlay — `include | exclude`.** `workspace_constraints` holds the `members` family's projected definitions and the engine's creation records ({§members-projection}). Resolved membership is `(project repository files ∪ include) − exclude`.
|
|
@@ -3510,13 +3538,13 @@ at its first overflow because four embedding calls were counted as history). Pac
|
|
|
3510
3538
|
remain ordinary turn chronology but do not consume `maxTurns`, model-call,
|
|
3511
3539
|
emission-attempt, usage, or cost accounting.
|
|
3512
3540
|
|
|
3513
|
-
- §overflow-turn-script **Recovery is one ordinary admitted `_plurnk` program.** Its canonical {§plan-value} has one `medium`, `in_progress` entry whose content is `Automatically KILL log bodies newly active at token-budget overflow.`, followed by every causal whole-body scoped KILL and terminal
|
|
3541
|
+
- §overflow-turn-script **Recovery is one ordinary admitted `_plurnk` program.** Its canonical {§plan-value} has one `medium`, `in_progress` entry whose content is `Automatically KILL log bodies newly active at token-budget overflow.`, followed by every causal whole-body scoped KILL and terminal `### SEND0 (NEXT)` with body `Next: YOU MUST ONLY KILL superseded, stale, or irrelevant log content in bulk.` The final sentence requires the successor's substantive operations to be one dedicated, comprehensive bulk-curation program. Core authors this internal program with canonical PLAN and SEND framing. Its exact `turnOps` is born folded; successful KILL rows follow {§log-kill-meta-operation} and therefore remain durable but packet-suppressed. Every recovery row carries `_plurnk` and `overflow`; no model call, synthetic receipt, or parallel explanation exists.
|
|
3514
3542
|
- §overflow-turn-curation **The preceding turn owns the pressure it introduced.** Core deterministically selects every body already created in the packetless candidate turn, every body created by the immediately preceding completed turn in that worker's chronology, Every selected body is KILLed whole (`<1,-1>`) through ordinary dispatch. Already-wholly-folded and bodyless rows require no operation. Core performs no relevance judgment, exempts no operation or resource kind, reconstructs no interval delta, re-runs no authored selector, and chooses no unrelated older history.
|
|
3515
3543
|
- §overflow-turn-hard-413 **Recovery fails hard when the causal fold cannot fit.** After the ordinary scoped KILLs land, Core rebuilds and remeasures once. If the plan changes no visibility or the rebuilt request still exceeds the ceiling, the loop terminalizes with an exact `engine/context/token-budget-overflow` 413 Problem; Core neither submits excess bytes nor chooses unrelated older history. Separately, every `provider.generate` assesses physical capacity under {§provider-surface-capacity}. Core may retry a provider capacity rejection only after withholding automatic prompt-body projection when that changes the request. If it cannot produce changed bytes or the changed request is still rejected, the request-only model turn and provider-owned Problem terminalize at **413 Content Too Large**.
|
|
3516
3544
|
|
|
3517
3545
|
- §tokenomics-fetch-fits-free **A retrieval larger than the available packet room remains addressable.** Its complete row lands in the model turn that requested it. If the following candidate packet exceeds the curation ceiling, {§overflow-turn-curation} FOLDs the new body and classifies it `_plurnk` and `overflow`; the exact body remains durable and selectively re-OPENable.
|
|
3518
3546
|
|
|
3519
|
-
- §loop-terminals **Engine-imposed terminals are HTTP-precise** — the loop-status vocabulary, one meaning each: `200` concluded (the model's SEND signal `200`) · `499` model-abandoned (signal `499`, or a cancel) · `429` maxTurns exhausted · `413` token-ceiling recovery failure or provider input-capacity failure after changed-request recovery · `500` strike threshold or invalid-emission exhaustion (distinct Problem types; `508` when the crossing strike was a detected cycle) · `504` loop timeout / exec-timeout restamp · `202` the bounded wait — a loop blocked on a live obligation (the model's
|
|
3547
|
+
- §loop-terminals **Engine-imposed terminals are HTTP-precise** — the loop-status vocabulary, one meaning each: `200` concluded (the model's SEND signal `200`) · `499` model-abandoned (signal `499`, or a cancel) · `429` maxTurns exhausted · `413` token-ceiling recovery failure or provider input-capacity failure after changed-request recovery · `500` strike threshold or invalid-emission exhaustion (distinct Problem types; `508` when the crossing strike was a detected cycle) · `504` loop timeout / exec-timeout restamp · `202` the bounded wait — a loop blocked on a live obligation (the model's `### SEND0 (WAIT) <T,P>`, {§wait-obligation-matrix}); a wait on nothing resolves to `200` unless a successful same-turn scoped KILL requires the curated next packet · `100`/`102` queued/running. Never a catch-all, never a new value without changing the owning schema.
|
|
3520
3548
|
|
|
3521
3549
|
§overflow-turn-surface **The packet is the resulting state, not an account of it.**
|
|
3522
3550
|
The first request after recovery is assembled by the ordinary packet path from
|
|
@@ -3550,7 +3578,7 @@ flowchart LR
|
|
|
3550
3578
|
pre-turn, a worker materializes only occurrences whose structural audience
|
|
3551
3579
|
includes that worker. The set is exhaustive, unranked, and exactly once; the
|
|
3552
3580
|
engine makes no relevance decision. Each copied event retains the operation,
|
|
3553
|
-
result, typed attributes
|
|
3581
|
+
result, and typed attributes.
|
|
3554
3582
|
Every producer appends to one workspace-scoped occurrence journal with a
|
|
3555
3583
|
monotonic identity. A pull captures one closed `(worker cursor, high-water]`
|
|
3556
3584
|
interval, materializes each addressed identity idempotently, then advances the
|
|
@@ -3793,7 +3821,7 @@ of section weights for the rendered request weight.
|
|
|
3793
3821
|
|--------------------------|------|
|
|
3794
3822
|
| Operator, wire, storage | Use the applicable industry term. Provider quantities follow the OpenAI vocabulary where it is standard: `contextWindow`, `reasoning`, `completion`, `finish_reason`, and usage nouns. |
|
|
3795
3823
|
| Core lifecycle | Use the exact Workspace → Worker → Loop → Turn → Op hierarchy in {§lifecycle-terms}. An AG-UI Run or thread is always protocol-qualified. |
|
|
3796
|
-
| Model-facing packet | Use the model's training distribution: operations mirror HTTP and shell,
|
|
3824
|
+
| Model-facing packet | Use the model's training distribution: operations mirror HTTP and shell, while log records use ordinary Markdown headings, strict JSON metadata, and text coordinates. Renaming this vocabulary to internal API terminology would discard useful resonance for a standard the model never sees. |
|
|
3797
3825
|
|
|
3798
3826
|
| PLURNK-native term | Why it remains |
|
|
3799
3827
|
|--------------------------------|----------------|
|
|
@@ -3825,15 +3853,15 @@ evidence when a downstream standard cannot represent the complete list.
|
|
|
3825
3853
|
| actionless lowercase `prompt` | budgeted head under {§prompt-projection} |
|
|
3826
3854
|
| structured `EDIT` receipt or textual `COPY`/`MOVE` effects | complete receipt-owned join context |
|
|
3827
3855
|
| every other nonempty body | head bounded independently by `PLURNK_SERVICE_PREVIEW_LINES` and `PLURNK_SERVICE_PREVIEW_CHARS` |
|
|
3828
|
-
| bodyless row | `
|
|
3856
|
+
| bodyless row | metadata only; no coordinate lines or `tokensBody` |
|
|
3829
3857
|
|
|
3830
|
-
READ and FIND own their range or pagination before packet rendering; the packet never applies a second hidden substring bound to their selected result. PLAN is likewise complete while visible: it is the model's explicit persistent reasoning inventory, serialized once as compact JSON rather than clipped or reparsed from source text. Prompt rows follow their separate adaptive projection contract. Structured mutation contexts already carry the receipt-owned bound in {§edit-result-receipt-truth}, so packet rendering does not preview them again. Actionless source artifacts, SEND/WORK/FORK bodies, EXEC commands, environment-delta EDIT spans, and extension-produced bodies use the ordinary fixed bound. When a visible projection differs from its canonical body,
|
|
3858
|
+
READ and FIND own their range or pagination before packet rendering; the packet never applies a second hidden substring bound to their selected result. PLAN is likewise complete while visible: it is the model's explicit persistent reasoning inventory, serialized once as compact JSON rather than clipped or reparsed from source text. Prompt rows follow their separate adaptive projection contract. Structured mutation contexts already carry the receipt-owned bound in {§edit-result-receipt-truth}, so packet rendering does not preview them again. Actionless source artifacts, SEND/WORK/FORK bodies, EXEC commands, environment-delta EDIT spans, and extension-produced bodies use the ordinary fixed bound. When a visible projection differs from its canonical body, metadata carries `chunk` with the exact selected and complete extents defined by {§log-wire-format}; complete and FOLDED bodies omit it. `### READ0 (log:///<coordinate>/<OP>)` applies its default or explicit text range to the canonical body; the unsuffixed exact shorthand and authoritative suffix behavior are defined by {§log-coordinate-hierarchy}. `### FIND0 (log:///...)` and search match that same full body. A scoped KILL hides the ordinary projection without changing its bound. System/policy sections are not log bodies. Notices are transient non-log observations; they share the ordinary line/character bounds but have no durable body or recovery URI.
|
|
3831
3859
|
|
|
3832
3860
|
§prompt-entry **Prompt as a first-class entry and log row.** Each prompt is stored once at `prompt:///<loop>/<N>` as an owner-keyed text/markdown entry — written before any turn of its loop executes, so the initialization COPY ({§worker-initialization-entry}) archives a real source — then published to its first model turn as one actionless lowercase `prompt` log row; that row, not the entry, records publication. No synthetic EDIT or READ operation is invented. The row is born visible and obeys {§body-projection}. The **Active User Prompts** section closes the user-slot status clump as a paths-only list (`* prompt:///<loop>/<N>`), so every frame remains directly READable even after its log row is folded or killed.
|
|
3833
3861
|
|
|
3834
3862
|
§prompt-causal-source **Prompt authorship and delivery are distinct facts.** The harness publishes every prompt row with `origin="_plurnk"`; the row's existing `source` carries the canonical address of a different causal actor. Native WORK, FORK, and directed worker SEND derive `worker://<sender>` from the authenticated sender worker ID. A trusted exterior adapter may supply its own canonical actor address through {§methods-loop-run}. An absent source means the owning worker itself. Attribution persists with the prompt frame through active delivery, parking, orphan recovery, restart, and later log projection; model syntax cannot author it.
|
|
3835
3863
|
|
|
3836
|
-
§prompt-projection **Prompt storage is unbounded by model context; automatic materialization is not.** Core persists every accepted prompt 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 visible prompt bodies. Complete prompt bodies render when their aggregate weight fits. Otherwise all visible prompt 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 its exact `chunk`
|
|
3864
|
+
§prompt-projection **Prompt storage is unbounded by model context; automatic materialization is not.** Core persists every accepted prompt 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 visible prompt bodies. Complete prompt bodies render when their aggregate weight fits. Otherwise all visible prompt 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 its exact `chunk` metadata; the canonical `prompt:///` entry and `log:///` body remain complete and READ/FIND-addressable. When provider input capacity is unknown the percentage is underivable, so prompt rows retain the ordinary bounded projection rather than inventing capacity. This policy never rejects, summarizes, or discards a prompt because it exceeds a context window.
|
|
3837
3865
|
|
|
3838
3866
|
§prompt-self-only The frame is self-only and owner-keyed:
|
|
3839
3867
|
`entries.owner_id` carries worker identity while the address carries only the
|
|
@@ -3872,8 +3900,8 @@ retain distinct contracts and lifetimes.
|
|
|
3872
3900
|
`status_rx ≥ 400` and an RFC 9457 Problem Details operation result in `rx`.
|
|
3873
3901
|
There is no per-category handling or bespoke ephemeral relationship. The
|
|
3874
3902
|
`errors` section is a derived index over those rows from the current and
|
|
3875
|
-
immediately prior turn: one
|
|
3876
|
-
nothing else. The Problem lives on the foldable row, READ via the
|
|
3903
|
+
immediately prior turn: one `{status, path}` JSON object per row,
|
|
3904
|
+
nothing else. The Problem lives on the foldable row, READ via the path.
|
|
3877
3905
|
- §log-row-self-explains **Every ≥400 pointer names a record that states its
|
|
3878
3906
|
why.** A model-operation failure is the model's own operation result; its
|
|
3879
3907
|
Problem Details `instance` is that row's `log:///` URI and packet wire renders
|
|
@@ -3981,7 +4009,7 @@ document contains its {§executor-tool-document}; a runtime with an exact
|
|
|
3981
4009
|
{§executor-tool-registry} materializes the same single document — per-target
|
|
3982
4010
|
child documents do not exist, shown or stored. The family document summarizes
|
|
3983
4011
|
the server or runtime, lists every enabled target as a directly copyable
|
|
3984
|
-
|
|
4012
|
+
`### EXEC0` heading with its input signature ({§operation-annotation} carries the
|
|
3985
4013
|
target one-liner; no invocation dispatch would reject is ever advertised), and
|
|
3986
4014
|
carries each detailed target's richer input-side contract as a
|
|
3987
4015
|
`## <target>` section of the same document, that target's own headings demoted
|
|
@@ -4008,12 +4036,12 @@ shared by discovery and dispatch. A runtime declaration may carry
|
|
|
4008
4036
|
subtree ({§worker-generated-subtree}). Absent, its docs live in the internal
|
|
4009
4037
|
`_plurnk/plurnk` namespace; present (attached MCP families: `/tools`),
|
|
4010
4038
|
the family document materializes at `_plurnk` + that root in the
|
|
4011
|
-
worker's private entry space. Turn 0 surveys the families (
|
|
4039
|
+
worker's private entry space. Turn 0 surveys the families (`### FIND0 [+init,+tools]
|
|
4012
4040
|
(worker://~/_plurnk/tools/*.md)`, one row per
|
|
4013
4041
|
server carrying its summary) and, for each server named in
|
|
4014
4042
|
`PLURNK_MCP_EXPANDED`, adds one FIND over its family document matching the
|
|
4015
|
-
|
|
4016
|
-
with
|
|
4043
|
+
`### EXEC0` headings (`### FIND0 (worker://~/_plurnk/tools/<server>.md)`
|
|
4044
|
+
with `/^### EXEC0 .*\n.*$/m`), so turn 0 names every tool with its annotation and
|
|
4017
4045
|
signature — one row per tool, paged like every survey. No document is delivered
|
|
4018
4046
|
unasked.
|
|
4019
4047
|
Attached tools are capabilities like every other runtime; the model never
|
|
@@ -4022,7 +4050,7 @@ learns an origin.
|
|
|
4022
4050
|
§members-functionality **File membership is one Worker Functionality family.**
|
|
4023
4051
|
Core registers the `members` family with the coordinator ({§functionality-coordinator}):
|
|
4024
4052
|
the model, the client, and the operator learn one surface — `list | discover | add |
|
|
4025
|
-
enable | disable | remove`, `worker.members.<verb>` for the client,
|
|
4053
|
+
enable | disable | remove`, `worker.members.<verb>` for the client, `### EXEC0 [members]
|
|
4026
4054
|
(<verb>)` for the model — for what the model may see, exactly as they do for skills and
|
|
4027
4055
|
MCP servers. A definition is one gitignore-style glob, `{ glob }`, relative to the project
|
|
4028
4056
|
root; a leading `!` excludes matching members, and an exclusion wins over every inclusion.
|
|
@@ -4158,7 +4186,7 @@ section because they are language extensions rather than executable tools.
|
|
|
4158
4186
|
|
|
4159
4187
|
### §schemes user.schemes — the resource directory
|
|
4160
4188
|
|
|
4161
|
-
§schemes-directory A `## Resources` section renders in the system slot **after the policy sections** — a terse directory of the scheme families available to this worker, so the model knows what URI resources and operations exist before it acts. Each scheme that ships a `manifest.example` contributes one or more concise canonical ops (no scheme prefix; each example self-documents) into an `example` fence. Scheme example sets are separated by one blank line. The doc is NOT linked inline — it is materialized as the worker-private skill `worker://~/_plurnk/plurnk/<scheme>.md` and discovered via the turn-0
|
|
4189
|
+
§schemes-directory A `## Resources` section renders in the system slot **after the policy sections** — a terse directory of the scheme families available to this worker, so the model knows what URI resources and operations exist before it acts. Each scheme that ships a `manifest.example` contributes one or more concise canonical ops (no scheme prefix; each example self-documents) into an `example` fence. Scheme example sets are separated by one blank line. The doc is NOT linked inline — it is materialized as the worker-private skill `worker://~/_plurnk/plurnk/<scheme>.md` and discovered via the turn-0 `### FIND0 (worker://~/_plurnk/plurnk/*.md)` survey ({§skills-functionality}), keeping the raw packet free of doc links. Meta-owned `worker` depth is required teaching ({§teaching-corpus}); a failed source read rejects materialization with its cause and never falls back. Other core and plugin schemes may supply optional `manifest.documentation`; absence contributes no pull doc. The verbose semantics live in that pull doc (materialized like any entry, READ on demand), not the hot path — terse pushes, depth pulls. A scheme with no example (provisional) is omitted; `PLURNK_SERVICE_DOCS_EXCLUDE` drops a named scheme's examples + doc. The directory includes only examples admitted by the effective worker-level capability layers, and Turn0 further narrows discovery through its loop policy using the same resolver ({§capability-admission}); the packet never baits an operation its own admission path will refuse. Materialized pull docs remain worker state, while their discoverability and execution remain policy-bound.
|
|
4162
4190
|
|
|
4163
4191
|
### §inject system.inject — the operator injection
|
|
4164
4192
|
|
|
@@ -4339,7 +4367,7 @@ SARIF region/replacement algebra for exact spans and same-snapshot ordering, not
|
|
|
4339
4367
|
adoption of the SARIF interchange envelope.
|
|
4340
4368
|
|
|
4341
4369
|
§slice-semantics-compose-pattern **Compose from evidence.** A match region already uses the four-coordinate
|
|
4342
|
-
scope shape. A follow-up
|
|
4370
|
+
scope shape. A follow-up `### READ0 (resource) <SL,SC,EL,EC>` retrieves that exact
|
|
4343
4371
|
region. JSONPath/XPath remain locators and matchers; they do not introduce a
|
|
4344
4372
|
second structural scope or structural EDIT language.
|
|
4345
4373
|
|
|
@@ -4420,12 +4448,12 @@ Carried from the contract walk; durable.
|
|
|
4420
4448
|
{§copy-move-observation}.
|
|
4421
4449
|
- **READ rx** prefixes every textual line under {§render-rule}; eligible
|
|
4422
4450
|
editable resources carry `@hash N:`, and all others carry `N:`.
|
|
4423
|
-
- **FIND body matcher** applies to the addressed entry channel (all dialects), per-candidate via the in-tree `Matcher.matchAgainstContent` ({§matcher-dispatch}; status 200 = content hit → entry selected). The target scope and channel select candidates; the path-glob is the (target).
|
|
4451
|
+
- **FIND body matcher** applies to the addressed entry channel (all dialects), per-candidate via the in-tree `Matcher.matchAgainstContent` ({§matcher-dispatch}; status 200 = content hit → entry selected). The target scope and channel select candidates; the path-glob is the (target).
|
|
4424
4452
|
- **Scoped KILL** on the **log** (`log:///`) folds a body span away ({§log-kill-scope}); on an entry it deletes that span through the EDIT path ({§kill-scope-entry}). A whole-entry KILL deletes the entry, or one `#fragment` channel.
|
|
4425
4453
|
- **File scheme** detects with `Mimetypes.detect({ path })` and classifies with the same configured service ({§mimetype-classification-consumption}). Handler-declared binary sources materialize through {§membership-source-projection}; projected bodies are READ-able, while source-aware EDIT remains 415.
|
|
4426
4454
|
|
|
4427
4455
|
### §kill-scope-entry Scoped KILL on an entry
|
|
4428
4456
|
|
|
4429
|
-
A KILL with a text-coordinate scope aimed at an entry-bearing scheme deletes exactly that span: core prepares and dispatches it as an EDIT with an empty body over the same marker, so anchors resolve, proposals gate it, and the merge facts and receipt are the EDIT path's — while the log row records the model's KILL.
|
|
4457
|
+
A KILL with a text-coordinate scope aimed at an entry-bearing scheme deletes exactly that span: core prepares and dispatches it as an EDIT with an empty body over the same marker, so anchors resolve, proposals gate it, and the merge facts and receipt are the EDIT path's — while the log row records the model's KILL. `### EDIT0 (path) <scope>` with an empty body remains the same act spelled the other way; the teaching names KILL.
|
|
4430
4458
|
|
|
4431
4459
|
A body pattern on an entry KILL is refused (400 `kill-body-log-only`): body patterns select log items ({§log-kill-scope}), and a selector core does not apply is never silently dropped, so a scoped entry KILL can never widen to its whole span.
|