@plurnk/plurnk-service 1.14.1 → 1.15.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 +1 -1
- package/SPEC.md +217 -148
- package/dist/build-info.json +1 -1
- package/dist/content/byte-view.d.ts +14 -0
- package/dist/content/byte-view.d.ts.map +1 -0
- package/dist/content/byte-view.js +33 -0
- package/dist/content/byte-view.js.map +1 -0
- package/dist/content/edit-receipt.d.ts.map +1 -1
- package/dist/content/edit-receipt.js +12 -1
- package/dist/content/edit-receipt.js.map +1 -1
- package/dist/content/line-marker.d.ts +2 -1
- package/dist/content/line-marker.d.ts.map +1 -1
- package/dist/content/line-marker.js +1 -0
- package/dist/content/line-marker.js.map +1 -1
- package/dist/content/matcher.d.ts +1 -0
- package/dist/content/matcher.d.ts.map +1 -1
- package/dist/content/matcher.js +1 -0
- package/dist/content/matcher.js.map +1 -1
- package/dist/content/read-projector.d.ts +4 -1
- package/dist/content/read-projector.d.ts.map +1 -1
- package/dist/content/read-projector.js +80 -3
- package/dist/content/read-projector.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts +43 -0
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -0
- package/dist/core/AdmittedTurnExecutor.js +245 -0
- package/dist/core/AdmittedTurnExecutor.js.map +1 -0
- package/dist/core/BareBatchRunner.d.ts +26 -0
- package/dist/core/BareBatchRunner.d.ts.map +1 -0
- package/dist/core/BareBatchRunner.js +104 -0
- package/dist/core/BareBatchRunner.js.map +1 -0
- package/dist/core/BudgetReadout.d.ts +2 -2
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +26 -12
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/CapabilityResolver.d.ts +2 -1
- package/dist/core/CapabilityResolver.d.ts.map +1 -1
- package/dist/core/CapabilityResolver.js +8 -9
- package/dist/core/CapabilityResolver.js.map +1 -1
- package/dist/core/ChannelWrite.d.ts +1 -1
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/DataStatementRunner.d.ts +35 -0
- package/dist/core/DataStatementRunner.d.ts.map +1 -0
- package/dist/core/DataStatementRunner.js +252 -0
- package/dist/core/DataStatementRunner.js.map +1 -0
- package/dist/core/Dispatcher.d.ts +8 -3
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +88 -738
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/EditMutations.d.ts +39 -0
- package/dist/core/EditMutations.d.ts.map +1 -0
- package/dist/core/EditMutations.js +418 -0
- package/dist/core/EditMutations.js.map +1 -0
- package/dist/core/Engine.d.ts +2 -23
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +18 -251
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Engine.sql +22 -15
- package/dist/core/KillHandler.d.ts +32 -0
- package/dist/core/KillHandler.d.ts.map +1 -0
- package/dist/core/KillHandler.js +179 -0
- package/dist/core/KillHandler.js.map +1 -0
- package/dist/core/LogVisibility.d.ts +1 -1
- package/dist/core/LogVisibility.d.ts.map +1 -1
- package/dist/core/LogVisibility.js +3 -4
- package/dist/core/LogVisibility.js.map +1 -1
- package/dist/core/LogWriter.d.ts +42 -0
- package/dist/core/LogWriter.d.ts.map +1 -0
- package/dist/core/LogWriter.js +136 -0
- package/dist/core/LogWriter.js.map +1 -0
- package/dist/core/LoopDriver.d.ts +46 -0
- package/dist/core/LoopDriver.d.ts.map +1 -0
- package/dist/core/LoopDriver.js +263 -0
- package/dist/core/LoopDriver.js.map +1 -0
- package/dist/core/LoopLifecycle.d.ts +2 -1
- package/dist/core/LoopLifecycle.d.ts.map +1 -1
- package/dist/core/MembershipMaterialization.d.ts +7 -0
- package/dist/core/MembershipMaterialization.d.ts.map +1 -0
- package/dist/core/MembershipMaterialization.js +283 -0
- package/dist/core/MembershipMaterialization.js.map +1 -0
- package/dist/core/MutationEffects.d.ts +29 -0
- package/dist/core/MutationEffects.d.ts.map +1 -0
- package/dist/core/MutationEffects.js +318 -0
- package/dist/core/MutationEffects.js.map +1 -0
- package/dist/core/OverflowTurn.d.ts +4 -4
- package/dist/core/OverflowTurn.d.ts.map +1 -1
- package/dist/core/OverflowTurn.js +6 -7
- package/dist/core/OverflowTurn.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +36 -6
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/ResourceMutations.d.ts +12 -36
- package/dist/core/ResourceMutations.d.ts.map +1 -1
- package/dist/core/ResourceMutations.js +27 -1351
- package/dist/core/ResourceMutations.js.map +1 -1
- package/dist/core/ResourceSelector.d.ts +21 -0
- package/dist/core/ResourceSelector.d.ts.map +1 -0
- package/dist/core/ResourceSelector.js +204 -0
- package/dist/core/ResourceSelector.js.map +1 -0
- package/dist/core/ResourceTransfers.d.ts +55 -0
- package/dist/core/ResourceTransfers.d.ts.map +1 -0
- package/dist/core/ResourceTransfers.js +460 -0
- package/dist/core/ResourceTransfers.js.map +1 -0
- package/dist/core/SchemeRegistry.js +2 -2
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/SendBroadcastHandler.d.ts +40 -0
- package/dist/core/SendBroadcastHandler.d.ts.map +1 -0
- package/dist/core/SendBroadcastHandler.js +159 -0
- package/dist/core/SendBroadcastHandler.js.map +1 -0
- package/dist/core/StoredPacket.d.ts +11 -0
- package/dist/core/StoredPacket.d.ts.map +1 -1
- package/dist/core/StoredPacket.js +22 -1
- package/dist/core/StoredPacket.js.map +1 -1
- package/dist/core/StrikeRail.d.ts.map +1 -1
- package/dist/core/StrikeRail.js +19 -9
- package/dist/core/StrikeRail.js.map +1 -1
- package/dist/core/TokenCalibration.d.ts +16 -0
- package/dist/core/TokenCalibration.d.ts.map +1 -0
- package/dist/core/TokenCalibration.js +35 -0
- package/dist/core/TokenCalibration.js.map +1 -0
- package/dist/core/ToolResources.d.ts.map +1 -1
- package/dist/core/ToolResources.js +15 -12
- package/dist/core/ToolResources.js.map +1 -1
- package/dist/core/TurnMaterialization.d.ts +37 -0
- package/dist/core/TurnMaterialization.d.ts.map +1 -0
- package/dist/core/TurnMaterialization.js +307 -0
- package/dist/core/TurnMaterialization.js.map +1 -0
- package/dist/core/TurnOps.d.ts.map +1 -1
- package/dist/core/TurnOps.js +4 -6
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.d.ts +15 -27
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +142 -687
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/WorkerControlHandler.d.ts +15 -0
- package/dist/core/WorkerControlHandler.d.ts.map +1 -0
- package/dist/core/WorkerControlHandler.js +89 -0
- package/dist/core/WorkerControlHandler.js.map +1 -0
- package/dist/core/attachments.d.ts +14 -0
- package/dist/core/attachments.d.ts.map +1 -0
- package/dist/core/attachments.js +18 -0
- package/dist/core/attachments.js.map +1 -0
- package/dist/core/git-membership.d.ts +15 -0
- package/dist/core/git-membership.d.ts.map +1 -1
- package/dist/core/git-membership.js +4 -273
- package/dist/core/git-membership.js.map +1 -1
- package/dist/core/git-state.d.ts +2 -1
- package/dist/core/git-state.d.ts.map +1 -1
- package/dist/core/mutation-types.d.ts +101 -0
- package/dist/core/mutation-types.d.ts.map +1 -0
- package/dist/core/mutation-types.js +2 -0
- package/dist/core/mutation-types.js.map +1 -0
- package/dist/core/operation-target-groups.js +1 -1
- package/dist/core/operation-target-groups.js.map +1 -1
- package/dist/core/packet-wire.d.ts +7 -6
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +57 -6
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/plurnk-uri.d.ts +0 -1
- package/dist/core/plurnk-uri.d.ts.map +1 -1
- package/dist/core/plurnk-uri.js +1 -1
- package/dist/core/plurnk-uri.js.map +1 -1
- package/dist/core/statement-primary.d.ts +4 -0
- package/dist/core/statement-primary.d.ts.map +1 -0
- package/dist/core/statement-primary.js +3 -0
- package/dist/core/statement-primary.js.map +1 -0
- package/dist/core/teaching-corpus.d.ts +0 -1
- package/dist/core/teaching-corpus.d.ts.map +1 -1
- package/dist/core/teaching-corpus.js +0 -9
- package/dist/core/teaching-corpus.js.map +1 -1
- package/dist/core/turn-scheduler.js +3 -3
- package/dist/core/turn-scheduler.js.map +1 -1
- package/dist/core/turn-signals.d.ts +15 -0
- package/dist/core/turn-signals.d.ts.map +1 -0
- package/dist/core/turn-signals.js +19 -0
- package/dist/core/turn-signals.js.map +1 -0
- package/dist/core/worker-settings.d.ts +0 -1
- package/dist/core/worker-settings.d.ts.map +1 -1
- package/dist/core/worker-settings.js +1 -1
- package/dist/core/worker-settings.js.map +1 -1
- package/dist/digest/Digest.d.ts +3 -16
- package/dist/digest/Digest.d.ts.map +1 -1
- package/dist/digest/Digest.js +10 -958
- package/dist/digest/Digest.js.map +1 -1
- package/dist/digest/DigestRender.d.ts +12 -0
- package/dist/digest/DigestRender.d.ts.map +1 -0
- package/dist/digest/DigestRender.js +644 -0
- package/dist/digest/DigestRender.js.map +1 -0
- package/dist/digest/DigestRequiem.d.ts +13 -0
- package/dist/digest/DigestRequiem.d.ts.map +1 -0
- package/dist/digest/DigestRequiem.js +332 -0
- package/dist/digest/DigestRequiem.js.map +1 -0
- package/dist/digest/digest-rows.d.ts +306 -0
- package/dist/digest/digest-rows.d.ts.map +1 -0
- package/dist/digest/digest-rows.js +2 -0
- package/dist/digest/digest-rows.js.map +1 -0
- package/dist/observe/api.d.ts +0 -2
- package/dist/observe/api.d.ts.map +1 -1
- package/dist/observe/api.js +2 -2
- package/dist/observe/api.js.map +1 -1
- package/dist/observe/metrics.d.ts +0 -1
- package/dist/observe/metrics.d.ts.map +1 -1
- package/dist/observe/metrics.js +0 -1
- package/dist/observe/metrics.js.map +1 -1
- package/dist/schemes/Exec.d.ts +4 -1
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +90 -45
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts +2 -1
- package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
- package/dist/schemes/ExecOutputScheme.js +3 -3
- package/dist/schemes/ExecOutputScheme.js.map +1 -1
- package/dist/schemes/File.d.ts +4 -1
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +70 -4
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts +4 -5
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +20 -98
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Worker.d.ts.map +1 -1
- package/dist/schemes/Worker.js +0 -12
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.d.ts +0 -1
- package/dist/schemes/_entry-crud.d.ts.map +1 -1
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-find.d.ts +4 -2
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +68 -10
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-manifest.d.ts +1 -2
- package/dist/schemes/_entry-manifest.d.ts.map +1 -1
- package/dist/schemes/_entry-ops.d.ts +2 -1
- package/dist/schemes/_entry-ops.d.ts.map +1 -1
- package/dist/schemes/_entry-ops.js +12 -2
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/schemes/_entry-semantic.d.ts +1 -0
- package/dist/schemes/_entry-semantic.d.ts.map +1 -1
- package/dist/schemes/_entry-semantic.js +3 -0
- package/dist/schemes/_entry-semantic.js.map +1 -1
- package/dist/schemes/_entry-semantic.sql +2 -2
- package/dist/schemes/_entry-send.d.ts +0 -1
- package/dist/schemes/_entry-send.d.ts.map +1 -1
- package/dist/schemes/_entry-send.js +5 -80
- package/dist/schemes/_entry-send.js.map +1 -1
- package/dist/schemes/exec-runtime.d.ts +7 -0
- package/dist/schemes/exec-runtime.d.ts.map +1 -0
- package/dist/schemes/exec-runtime.js +2 -0
- package/dist/schemes/exec-runtime.js.map +1 -0
- package/dist/server/ClientReads.d.ts +34 -0
- package/dist/server/ClientReads.d.ts.map +1 -0
- package/dist/server/ClientReads.js +210 -0
- package/dist/server/ClientReads.js.map +1 -0
- package/dist/server/Daemon.d.ts +12 -22
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +31 -362
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DaemonModule.d.ts +6 -5
- package/dist/server/DaemonModule.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.d.ts +3 -2
- package/dist/server/DrainSupervisor.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.js +7 -3
- package/dist/server/DrainSupervisor.js.map +1 -1
- package/dist/server/Functionality.d.ts +0 -12
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/FunctionalityManager.d.ts +0 -1
- package/dist/server/FunctionalityManager.d.ts.map +1 -1
- package/dist/server/FunctionalityManager.js +2 -2
- package/dist/server/FunctionalityManager.js.map +1 -1
- package/dist/server/MembersFunctionality.d.ts +2 -13
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js +4 -4
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/SkillsFunctionality.d.ts +1 -7
- package/dist/server/SkillsFunctionality.d.ts.map +1 -1
- package/dist/server/SkillsFunctionality.js +3 -3
- package/dist/server/SkillsFunctionality.js.map +1 -1
- package/dist/server/WorkerModelResolver.d.ts +17 -0
- package/dist/server/WorkerModelResolver.d.ts.map +1 -0
- package/dist/server/WorkerModelResolver.js +166 -0
- package/dist/server/WorkerModelResolver.js.map +1 -0
- package/dist/server/daemon-results.d.ts +5 -0
- package/dist/server/daemon-results.d.ts.map +1 -0
- package/dist/server/daemon-results.js +7 -0
- package/dist/server/daemon-results.js.map +1 -0
- package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
- package/dist/server/dispatch-as-plurnk.js +4 -6
- package/dist/server/dispatch-as-plurnk.js.map +1 -1
- package/dist/server/loopDocs.d.ts.map +1 -1
- package/dist/server/loopDocs.js +11 -2
- package/dist/server/loopDocs.js.map +1 -1
- package/migrations/001_schema.sql +21 -92
- package/package.json +30 -30
package/SPEC.md
CHANGED
|
@@ -131,19 +131,43 @@ 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
|
-
`## SEND0
|
|
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.
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
139
|
+
**Contract Strikes** (operator mandate, 2026-09-01): *Every turn with one or
|
|
140
|
+
more contract violations earns a strike. A turn without any contract violations
|
|
141
|
+
clears the strikes. Three (not four) strikes and you're out, by default.*
|
|
142
|
+
The streak counts consecutive violating turns; `MAX_STRIKES` (default 3) is the
|
|
143
|
+
threshold, crossed ON the third strike; the crossing turn terminates at **508
|
|
144
|
+
Loop Detected** when cycle-detected, otherwise **500**.
|
|
145
|
+
|
|
146
|
+
The contracts, and the violation of each that strikes:
|
|
147
|
+
|
|
148
|
+
| Contract | Violation that strikes |
|
|
149
|
+
|---|---|
|
|
150
|
+
| operation contract | a hard operation failure (status ≥ 400) in an admitted turn — soft statuses below excluded |
|
|
151
|
+
| review contract | a refused final disposition (turntrieval steer) |
|
|
152
|
+
| progress contract | a detected operation cycle (`MIN_CYCLES` × period) |
|
|
153
|
+
| frame contract | emission attempts exhausted with no admissible turn |
|
|
154
|
+
| provider response contract | the provider returned an invalid response |
|
|
155
|
+
|
|
156
|
+
Errors and issues are NOT contract violations. Each keeps its own disposition
|
|
157
|
+
and never strikes: exploration misses (404, 416) and unsupported capability
|
|
158
|
+
(501) are how discovery works; raw 409 outcomes are soft (the review ruling is
|
|
159
|
+
steer's alone); EXEC outcomes and `executor/*` problem rows are world evidence;
|
|
160
|
+
provider weather (rate limit, network failure, deadline, interruption) recovers
|
|
161
|
+
({§provider-recovery}); provider capacity has its own packet recovery and
|
|
162
|
+
terminal ({§provider-capacity-failure}); authorization and quota failures
|
|
163
|
+
terminate immediately (configuration, not behavior); rejected private emission
|
|
164
|
+
attempts are forensic evidence beneath their turn ({§emission-admission}) —
|
|
165
|
+
only their exhaustion surfaces, as one frame-contract violation. The
|
|
166
|
+
independent turn ceiling terminates at **429** ({§loop-terminals}). The streak
|
|
167
|
+
and cycle verdict are absent from model packets; only the concrete occurrences
|
|
168
|
+
in the table are shown. The current streak may ride first-party provider
|
|
169
|
+
metadata ({§strikes-first-party-metadata}), which does not make it
|
|
170
|
+
model-facing.
|
|
147
171
|
|
|
148
172
|
| Term | Meaning |
|
|
149
173
|
|------------------------------|---|
|
|
@@ -440,10 +464,10 @@ executors, schemes, and family managers (`## FIND0 [+init,+plurnk]
|
|
|
440
464
|
(worker://~/_plurnk/plurnk/*.md) <1,-1>`), enabled tools (`## FIND0 [+init,+tools]
|
|
441
465
|
(worker://~/_plurnk/tools/*.md) <1,-1>`), enabled agents (`## FIND0 [+init,+agents]
|
|
442
466
|
(worker://~/_plurnk/agents/*.md) <1,-1>`, {§a2a-agents-catalog}), enabled members
|
|
443
|
-
(`## FIND0
|
|
444
|
-
{§members-projection}), workspace files (`## FIND0
|
|
445
|
-
workspace entries (`## FIND0
|
|
446
|
-
private worker entries (`## FIND0
|
|
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 -->`).
|
|
447
471
|
Only those three namespace surveys carry annotations because the bare targets do not
|
|
448
472
|
name their surface; generated paths and classification tags already name every other
|
|
449
473
|
survey. Naming `~` private prevents a worker from offering its own `~` address to
|
|
@@ -467,7 +491,7 @@ direct-entry-plus-directory count; `-1` enables the ordinary markerless page;
|
|
|
467
491
|
unset / `0` disables previews. `log://` is absent because the current worker's
|
|
468
492
|
log already renders in present mode.
|
|
469
493
|
|
|
470
|
-
§worker-initialization-entry **Model-worker initialization is a real `_plurnk` turn.** A model worker's first loop begins with one packetless `{ producer="_plurnk", kind="initialization" }` turn submitted through {§turn-ops-admission-path}. It preserves one
|
|
494
|
+
§worker-initialization-entry **Model-worker initialization is a real `_plurnk` turn.** A model worker's first loop begins with one packetless `{ producer="_plurnk", kind="initialization" }` turn submitted through {§turn-ops-admission-path}. It preserves one visible exact `turnOps` item and dispatches the same source into ordinary PLAN, one archiving COPY, orienting READ/FIND, and terminal `SEND0 (NEXT)` rows (authored in their {§op-mode-phases} execution order). Every orienting row is structurally classified `_plurnk` and `init`; the archiving `COPY (prompt:///<loop>/1)` onto `worker://~/prompts.md <-1>` is classified `_plurnk` and `backup` — the worked COPY specimen, showing the private space as scratch, emitted whenever the loop publishes a prompt ({§prompt-entry}). The PLAN is the canonical {§plan-value} with two entries in order: the `memory` entry reads "Determinations and Decisions must be persisted as `memory` items.", then `Discover the tooling available and survey the workspace file root.` is `in_progress`; SEND hands off with `Next: Address the prompt.` The first model request occupies the following turn and therefore begins at database/log turn sequence 2; “turn zero” is the initialization phase's model-facing label, not a zero-based database coordinate. Client and `_plurnk` administrative workers execute operation turns and do not receive model initialization.
|
|
471
495
|
|
|
472
496
|
### §machine-processes The machine and its processes: workspace, worker, fork
|
|
473
497
|
|
|
@@ -510,7 +534,7 @@ terminal history.**
|
|
|
510
534
|
|
|
511
535
|
§machine-processes-worker-is-its-log **A worker's conversational memory of
|
|
512
536
|
the shared world is its log, with no hidden per-worker snapshot beside it.**
|
|
513
|
-
|
|
537
|
+
A scoped KILL folds canonical body intervals on that worker's rows ({§log-kill-scope});
|
|
514
538
|
lineage activity and explicit commons broadcasts arrive as attributed log
|
|
515
539
|
entries ({§env-delta}). Worker-owned entries include deliberate scratch and
|
|
516
540
|
other private resources; their manifest declares whether a FORK snapshots,
|
|
@@ -570,7 +594,7 @@ continues to decompose other authorities without treating them as mintable.
|
|
|
570
594
|
|
|
571
595
|
§worker-write-scoping **Writes are own-space-and-commons only**: a model writes `worker://~/` and `worker:///` — every ancestry-readable named authority is read-only to it (403), while an unreadable name remains 404 under {§worker-read-scope}. `owner_id` is engine-stamped from the dispatch context, never model-set. Nothing worker-authored can land under another principal. The entry-copy seam (COPY/MOVE) is pathname-keyed and addresses the commons; a space's content moves via READ + EDIT. The one exception inside a writable space is the generated subtree below.
|
|
572
596
|
|
|
573
|
-
§worker-generated-subtree **`_plurnk/` is Plurnk's generated subtree in every worker space.** Every Plurnk-generated per-Worker document lives under `worker://~/_plurnk/`: the project instructions (`_plurnk/agents.md`, with nested AGENTS.md files under `_plurnk/instructions/**` preserving their subtree paths — the standard's closest-file scope, materialized without any foisted READ or teaching), standard Agent Skills and Plurnk-generated references (`_plurnk/skills/**`), executable families (`_plurnk/tools/**`), and future family catalogs. The subtree is readable exactly like the rest of the space ({§worker-read-scope}) and writable only by the `_plurnk` writer tier: a model, client, or plugin EDIT, KILL, SEND 410, or COPY/MOVE destination whose pathname begins `/_plurnk/` is refused 403 `worker-generated-read-only`, in the commons as well as in own and named spaces. Its documents are materialized through ordinary `_plurnk` **maintenance** turns ({§actor-boundary-doc-injection}), so provenance is legible at the address and durable in the log — but a receipt answers an asker, and maintenance turns have none: their successful rows never render in the packet (failures remain visible), while READ over `log:///` recovers them exactly and the turn's self-
|
|
597
|
+
§worker-generated-subtree **`_plurnk/` is Plurnk's generated subtree in every worker space.** Every Plurnk-generated per-Worker document lives under `worker://~/_plurnk/`: the project instructions (`_plurnk/agents.md`, with nested AGENTS.md files under `_plurnk/instructions/**` preserving their subtree paths — the standard's closest-file scope, materialized without any foisted READ or teaching), standard Agent Skills and Plurnk-generated references (`_plurnk/skills/**`), executable families (`_plurnk/tools/**`), and future family catalogs. The subtree is readable exactly like the rest of the space ({§worker-read-scope}) and writable only by the `_plurnk` writer tier: a model, client, or plugin EDIT, KILL, SEND 410, or COPY/MOVE destination whose pathname begins `/_plurnk/` is refused 403 `worker-generated-read-only`, in the commons as well as in own and named spaces. Its documents are materialized through ordinary `_plurnk` **maintenance** turns ({§actor-boundary-doc-injection}), so provenance is legible at the address and durable in the log — but a receipt answers an asker, and maintenance turns have none: their successful rows never render in the packet (failures remain visible), while READ over `log:///` recovers them exactly and the turn's self-curation keeps client waterfalls tidy. On FORK the subtree is never byte-copied; the child rederives it from its inherited Functionality ({§machine-processes-entry-inheritance}). A runtime's `resourcesPath` is relative to this root ({§tools-resource-materialization}). No world-readable kernel authority exists; there is no `worker://plurnk/`.
|
|
574
598
|
|
|
575
599
|
§worker-control-addressing **Only an exact authority-only address selects worker
|
|
576
600
|
control.** Control is same-workspace only ({§actor-boundary}). Generic URI
|
|
@@ -615,18 +639,16 @@ literal `workers.name` value.
|
|
|
615
639
|
parent's private entries — its own space deep-copied with the owner
|
|
616
640
|
remapped (source → branch) — so the branch opens with the parent's notes and
|
|
617
641
|
diverges on its own edits: *fork = everything-in-common-but-name*.
|
|
618
|
-
- §worker-spawn-no-
|
|
619
|
-
removed outright (#396)
|
|
620
|
-
|
|
621
|
-
branches through ordinary EXEC git, taught by the git skill — never engine
|
|
622
|
-
machinery. No batch, branch, or child comes into being from a signalled spawn.
|
|
642
|
+
- §worker-spawn-no-branch **WORK and FORK take a worker path and a prompt, nothing else.** Branch
|
|
643
|
+
delegation was removed outright (#396). A model manages git branches through ordinary
|
|
644
|
+
EXEC git, taught by the git skill — never engine machinery.
|
|
623
645
|
- §worker-delegation-inherits-policy **Delegation cannot widen authority.** WORK and FORK copy the delegating actor's complete effective capability policy into the child's immutable `capability_bound`; later widening of any parent layer cannot enlarge that child. Every fresh delegated loop carries that complete effective attenuation and the delegating loop's proposal disposition, including a loop created by SEND to an idle Worker. SEND into an active or parked loop leaves that loop's immutable policy untouched. The bound is delegation authority captured by value, not a client binding or a live parent-policy link.
|
|
624
646
|
- §worker-lifecycle-wake-requeue-not-terminal **A wake re-queue is not a terminal.** A conclusion-wake resumes a 202-blocked loop by re-queueing it (202 → 100); when that lands while the loop's own live drain is between turns, the drain **re-claims and continues** (atomic 100 → 102; the injected prompt is already the next turn). The internal re-queue is never reported as an outward terminal.
|
|
625
647
|
|
|
626
648
|
- §worker-scheme-collect **Collect** — a worker's loop reaching a terminal status
|
|
627
649
|
surfaces to its direct parent as an ambient delta ({§env-delta}): a `SEND` from
|
|
628
650
|
`worker://<name>` carrying the loop's exact terminal operation result. A
|
|
629
|
-
**2xx deliverable is born
|
|
651
|
+
**2xx deliverable is born visible** (its body
|
|
630
652
|
materialized into the parent's packet, not hidden behind a fold): a child's
|
|
631
653
|
success must reach the parent open and awakening, never a bodyless row. An
|
|
632
654
|
non-2xx result surfaces folded; a failure retains its exact status and Problem. Every death-path is stamped uniformly —
|
|
@@ -649,10 +671,10 @@ machinery. No batch, branch, or child comes into being from a signalled spawn.
|
|
|
649
671
|
history; this clump is the current inventory that keeps an active obligation
|
|
650
672
|
visible even when no new activity arrived. Each open stream pointer carries
|
|
651
673
|
its channels' sizes and growth since the last packet (`* active
|
|
652
|
-
sh:///1/2/3 — stdout 340 lines (+2048 bytes)`) — the only thing the model
|
|
674
|
+
sh:///1/2/3/EXEC — stdout 340 lines (+2048 bytes)`) — the only thing the model
|
|
653
675
|
learns about a stream before it closes ({§exec-stream}). It is orienting state, never
|
|
654
676
|
advice: the model sees its live subtree (`* 102 worker://worker-x`, `* active
|
|
655
|
-
sh:///1/2/3`) and reasons for itself — READ/
|
|
677
|
+
sh:///1/2/3/EXEC`) and reasons for itself — READ/KILL via the path.
|
|
656
678
|
Empty sections are omitted, like errors.
|
|
657
679
|
|
|
658
680
|
Worker control rides the daemon's inject seam (active→fold, idle→enqueue+drain), so the handler creates/branches the worker and hands off; the daemon owns provider + system prompt. FORK/WORK carry the seed task in the body and are their own ops, dispatched to worker control — never the entry-copy path.
|
|
@@ -851,13 +873,13 @@ latest context gauge.
|
|
|
851
873
|
|
|
852
874
|
### §emission-admission Provider emission admission
|
|
853
875
|
|
|
854
|
-
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
|
|
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.
|
|
855
877
|
|
|
856
|
-
§safe-uri-target-groups After source and authored-command admission, Core tolerates one target group on READ
|
|
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.
|
|
857
879
|
|
|
858
880
|
Core retries a rejected emission against the exact same packet beneath the same engine turn, up to `PLURNK_SERVICE_EMISSION_ATTEMPTS`. Rejected bytes never dispatch or reach the engine strike rail. Before each `generate`, Core opens one durable logical `inference_calls` row with its `model_calls` specialization and emission-specific `turn_attempts` admission row. A call that ends without response evidence leaves that admission row unclassified (`accepted IS NULL`) and does not consume the emission-attempt ceiling. Beneath the logical call, every provider observer invocation opens one cardinal `provider_requests` occurrence immediately before physical I/O and settles it as response or error. Adapter retries and capacity failover append requests in issue order; a response-less failure therefore remains an accounted occurrence rather than disappearing. Normalized response evidence is durable before parser classification and does not duplicate the separately owned accounting. The accepted exchange alone extends `turns.packet` with response evidence; every physical request remains in turn and loop accounting, while the context gauge reads the latest settled emission request on the latest turn. Digest exposes rejected response evidence as `packetNNN.attemptNNN.rejected.*` and every physical request in its machine-readable ledger.
|
|
859
881
|
|
|
860
|
-
The first exhaustion in a consecutive sequence closes that unadmitted turn as a continue and opens exactly one ordinary recovery turn. Its packet projects the latest rejected response
|
|
882
|
+
The first exhaustion in a consecutive sequence closes that unadmitted turn as a continue and opens exactly one ordinary recovery turn. Its packet projects the latest rejected response visibly from a durably folded emission-attempt item under {§rejected-emission-entry} and carries one transient `invalid_emission` Notice: `Response rejected before dispatch; no operations were performed.` followed by `Parser: <the latest attempt's first diagnostic>` with its `content-offset` position — the model sees why, at which line, against its own projected text. The Notice states only observed admission facts; it does not classify the response as unrecoverable, infer why generation ended, or prescribe intent beyond the parser-owned diagnostic. Attempt count and rail state never become model-facing. The recovery turn has its own honestly stored packet and its configured private same-packet attempts. The packet-local projection never changes the row's curation state, so no later packet repeats the malformed body unless the model explicitly OPENs it. Admission clears the recovery state; exhausting the informed turn terminates instead of opening another.
|
|
861
883
|
|
|
862
884
|
An admitted program may contain bounded malformed statements or recovered
|
|
863
885
|
envelope defaults. Parsed operations still dispatch; each hard parser diagnostic
|
|
@@ -870,10 +892,11 @@ resampling. A malformed statement's Problem records the factual
|
|
|
870
892
|
`siblingsRetained: true` extension; an envelope-default Problem states only the
|
|
871
893
|
observed boundary failure and exact default applied.
|
|
872
894
|
|
|
873
|
-
§invalid-emission-attempts Exhausting the emission-attempt budget opens
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
895
|
+
§invalid-emission-attempts Exhausting the emission-attempt budget opens an
|
|
896
|
+
informed recovery turn carrying the rejected emission — every exhaustion, not
|
|
897
|
+
only the first. Each exhaustion is one frame-contract violation on the strike
|
|
898
|
+
rail ({§engine-rails} Contract Strikes); the rail, never a bespoke terminal,
|
|
899
|
+
bounds how many consecutive exhaustions a loop survives.
|
|
877
900
|
|
|
878
901
|
§turn-never-blank An admitted turn whose operation fails — during parsing or
|
|
879
902
|
dispatch — is categorically different: its failed operation row enters
|
|
@@ -1112,6 +1135,8 @@ Every fact names the canonical key, never the host root or an echo of the
|
|
|
1112
1135
|
model's spelling. These classes let a caller distinguish a wrong address, an
|
|
1113
1136
|
invalid range, read-only authority, and occupied hidden state without guessing.
|
|
1114
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 (`## EXEC0 [members] (add)` with a `{"glob": "<path>"}` body); it never claims absence. Occupancy surfaces, content does not ({§membership}).
|
|
1139
|
+
|
|
1115
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.
|
|
1116
1141
|
|
|
1117
1142
|
### §scheme-manifest Manifest
|
|
@@ -1131,7 +1156,7 @@ There is no fictional cross-scheme SQL transaction.
|
|
|
1131
1156
|
§op-methods-op-dispatch Engine operation ownership follows the public scheme contract:
|
|
1132
1157
|
|
|
1133
1158
|
- EDIT resource batches dispatch through `editBatch`.
|
|
1134
|
-
-
|
|
1159
|
+
- A log KILL dispatches only to the core-owned log curation handler ({§log-kill-scope}); an entry scheme's `kill` method never sees a `log:///` target.
|
|
1135
1160
|
- Other delegated operations use the corresponding lowercase `SchemeHandler` method, with standard FIND supplied for a data scheme that omits a custom implementation.
|
|
1136
1161
|
- COPY and MOVE are engine-owned compositions over CRUD primitives ({§copy}/{§move}).
|
|
1137
1162
|
|
|
@@ -1143,9 +1168,9 @@ Registration precedes loop affinity:
|
|
|
1143
1168
|
| Registered but inactive under flag | The flag gate returns `403 scheme-unavailable`. |
|
|
1144
1169
|
| Registered and active | Dispatch continues to the operation owner. |
|
|
1145
1170
|
|
|
1146
|
-
- §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
|
|
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.
|
|
1147
1172
|
|
|
1148
|
-
§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
|
|
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.
|
|
1149
1174
|
|
|
1150
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.
|
|
1151
1176
|
|
|
@@ -1179,12 +1204,12 @@ snapshot. Cross-resource MOVE is ordered destination-then-source and cannot be
|
|
|
1179
1204
|
globally atomic; if source removal fails after destination success, its Problem
|
|
1180
1205
|
Details state `destinationWritten: true` and identify the destination.
|
|
1181
1206
|
|
|
1182
|
-
### §send-dispatch SEND dispatch (
|
|
1183
|
-
|
|
1184
|
-
Directed SEND (non-null path) routes to scheme's `send`. Status = intent:
|
|
1207
|
+
### §send-dispatch SEND dispatch (a message to a recipient)
|
|
1185
1208
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1209
|
+
A recipient SEND (non-null path, `status` null — {§send-label}) routes to the scheme's
|
|
1210
|
+
`send`: the body is the message — a WebSocket frame, exec stdin, an HTTP POST, an A2A
|
|
1211
|
+
message, a worker's next prompt. A label SEND never reaches a scheme: it concludes the
|
|
1212
|
+
turn ({§send}). Cancelling a stream and deleting an entry are KILL ({§stream}, {§move}).
|
|
1188
1213
|
|
|
1189
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}). A FIND signal classifies the FIND result row and never changes this candidate set ({§log-item-tags}). 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.
|
|
1190
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.
|
|
@@ -1193,9 +1218,7 @@ Directed SEND (non-null path) routes to scheme's `send`. Status = intent:
|
|
|
1193
1218
|
|
|
1194
1219
|
- §matcher-selection-signal **Matching carries navigation evidence** - a matcher is a boolean resource predicate. Internally, each selected resource carries `matches: MatchEvidence[]`, where `MatchEvidence` is `{channel?,locator?,region?}`; `channel` names the entry channel the finding was located in and is absent for channel-less resources such as log rows, so line coordinates cannot be mis-attributed across channels of the same resource ({§channel-selection-visibility}). `locator` preserves a structural address without overloading the resource row's `path`; `region` is a complete four-coordinate `TextRegion` only when the finding maps honestly into the exact text the model can READ. Exact duplicate evidence deduplicates. Relation findings map their indexed source spans through the same readable text coordinate index. FIND alone decides whether that grouped selection projects as resource rows or flat locations ({§find-result-projection}); the engine never fabricates a region or guesses which surgical READ the model wants.
|
|
1195
1220
|
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
§send-dispatch-entry-schemes-501-on-non-410 Other status codes return 501 from entry-bearing schemes by default.
|
|
1221
|
+
§send-dispatch-entry-schemes-501 An entry-bearing scheme carries no messages: a recipient SEND aimed at one returns 501.
|
|
1199
1222
|
|
|
1200
1223
|
Null-path SEND is broadcast ({§send}), engine-handled.
|
|
1201
1224
|
|
|
@@ -1433,7 +1456,7 @@ A published default channel renders under the entry's ordinary fragmentless addr
|
|
|
1433
1456
|
|
|
1434
1457
|
### §no-visibility Entries carry no visibility
|
|
1435
1458
|
|
|
1436
|
-
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
|
|
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.
|
|
1437
1460
|
|
|
1438
1461
|
### §channel-mimetype Mimetype is a (scheme, channel) property — never a default
|
|
1439
1462
|
|
|
@@ -1455,8 +1478,8 @@ Rules:
|
|
|
1455
1478
|
| URI | Channel |
|
|
1456
1479
|
| ------------------------------------ | ------------------------------------ |
|
|
1457
1480
|
| `worker:///france/capital` | body (default) |
|
|
1458
|
-
| `sh:///1/1/2#stdout`
|
|
1459
|
-
| `sh:///1/1/2#stderr`
|
|
1481
|
+
| `sh:///1/1/2/EXEC#stdout` | stdout |
|
|
1482
|
+
| `sh:///1/1/2/EXEC#stderr` | stderr |
|
|
1460
1483
|
| `https://feed.example/y#body` | body |
|
|
1461
1484
|
| `log:///N/T/A` | (no channel concept; atomic log row) |
|
|
1462
1485
|
|
|
@@ -1465,7 +1488,7 @@ Op implications:
|
|
|
1465
1488
|
- EDIT to undeclared channel → 400; read-only channel → 405.
|
|
1466
1489
|
- COPY/MOVE source and destination fragments independently select channels.
|
|
1467
1490
|
|
|
1468
|
-
Client-interface target parameters carry fragments inline (`{ target: "sh:///1/1/2#stderr" }`).
|
|
1491
|
+
Client-interface target parameters carry fragments inline (`{ target: "sh:///1/1/2/EXEC#stderr" }`).
|
|
1469
1492
|
|
|
1470
1493
|
**Wire rendering: default channel is path-only.** A rendered target omits `#channel` when channel matches `defaultChannel`. Single-channel entries render path-only; multi-channel entries render the default path-only and only non-default carries `#name`.
|
|
1471
1494
|
|
|
@@ -1537,7 +1560,7 @@ AST: `{ op: "EDIT", target, body: string | null, signal: tags | null, lineMarker
|
|
|
1537
1560
|
- §edit-null-clears Writes the body; `body: null` clears it.
|
|
1538
1561
|
- §edit-status-201-200 Returns `{ status: 201, entryId }` for a new entry and
|
|
1539
1562
|
`{ status: 200, entryId }` for a content update.
|
|
1540
|
-
- §edit-noop-304 A write that changes nothing — identical content — returns `{ status: 304, entryId }`, mirroring
|
|
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. The operation's log classification remains independent ({§log-item-tags}).
|
|
1541
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.
|
|
1542
1565
|
- §edit-line-anchors An anchored EDIT resolves under {§line-anchors} and carries
|
|
1543
1566
|
its endpoint checks as a core-private mutation precondition. Otherwise-valid
|
|
@@ -1575,52 +1598,76 @@ selection or fan-out path.
|
|
|
1575
1598
|
|
|
1576
1599
|
- §read-read-content Returns channel content and mimetype.
|
|
1577
1600
|
- §read-read-404 Returns 404 when the channel is absent.
|
|
1601
|
+
- §read-content-wins A channel that delivered content reads as that content (200); the
|
|
1602
|
+
producer's failure projects onto the READ only when there is nothing to read, so a
|
|
1603
|
+
failed command's stdout and stderr stay readable.
|
|
1578
1604
|
- §read-selection-projection READ applies `lineMarker` as text coordinates to one
|
|
1579
1605
|
exact target under {§read-exact-target}. Markerless READ synthesizes
|
|
1580
1606
|
`<1,16>`; `<1,-1>` explicitly selects all text. Successful positional reads
|
|
1581
1607
|
carry the compact requested/returned extent and available total
|
|
1582
1608
|
({§range-extent}). Anchors resolve under {§line-anchors} before selection. An
|
|
1583
1609
|
invalid text region is 416.
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1610
|
+
- §read-bytes A binary channel with no readable projection, and the `#bytes` view of
|
|
1611
|
+
any resource whose scheme supplies bytes, reads as the source bytes one hexadecimal
|
|
1612
|
+
octet per line: coordinate = line = byte, so `<a,b>` selects bytes, the markerless
|
|
1613
|
+
default is the same `<1,16>`, `<1,-1>` is the whole resource, and the extent carries
|
|
1614
|
+
`unit: "byte"`. The result keeps the source mimetype and names `projection: "hex"`;
|
|
1615
|
+
anchors do not exist there (400). Bytes are read from the source at READ time, sized
|
|
1616
|
+
then windowed, never stored: `file:` supplies them from the member on disk, and a
|
|
1617
|
+
scheme that keeps no bytes answers 501 `bytes-unavailable` for `#bytes` and 415 for a
|
|
1618
|
+
binary channel, as before. An EXEC whose target is a file member already runs the
|
|
1619
|
+
bytes on disk.
|
|
1620
|
+
- §find-bytes A FIND over a binary channel without a readable projection matches the
|
|
1621
|
+
source bytes one character each (Latin-1): a text pattern finds strings, `\xNN`
|
|
1622
|
+
escapes find byte sequences, and every hit is reported in byte coordinates that paste
|
|
1623
|
+
into a byte READ (`region` spans the hexadecimal lines of the matched bytes; `matched`
|
|
1624
|
+
is their hex). The load is bounded by the mimetypes binary input ceiling; a larger
|
|
1625
|
+
resource fails 413 `bytes-too-large` by name rather than being skipped.
|
|
1626
|
+
|
|
1627
|
+
§log-item-tags **Log items carry no model-authored classification.** The tag slot left the
|
|
1628
|
+
grammar with the signal slot ({§legacy-bracket-slot}); the `log_tags` primitive remains for
|
|
1629
|
+
engine policy's own diagnostic classifications, such as `overflow`, and is never a
|
|
1630
|
+
selector the model can address.
|
|
1600
1631
|
|
|
1601
1632
|
### §log-history-projection Durable history and active projection
|
|
1602
1633
|
|
|
1603
1634
|
| Layer | Owner | Curation contract |
|
|
1604
1635
|
|---|---|---|
|
|
1605
1636
|
| Durable event | `log_entries` | One chronological execution fact. Ordinary Plurnk operations never erase it; its original body and initial folded state remain available to the client journal, digest, and fork forensics. Containing turn, worker, or workspace teardown may cascade the history. |
|
|
1606
|
-
| Active projection | `log_entry_projections` | One current worker-facing state per event.
|
|
1637
|
+
| Active projection | `log_entry_projections` | One current worker-facing state per event. A scoped KILL changes folded body intervals while active. Log-KILL atomically changes active to inactive and cannot be reversed; inactive rows are absent from packet rendering, log READ/FIND, failure pointers, semantic discovery, token accounting, and later curation. |
|
|
1607
1638
|
|
|
1608
1639
|
The successful curation operation and every exact target transition are durable
|
|
1609
1640
|
in the same commit. KILL against another scheme retains that scheme's ordinary
|
|
1610
1641
|
resource or process semantics; this projection contract is specific to
|
|
1611
1642
|
`log:///`.
|
|
1612
1643
|
|
|
1613
|
-
### §
|
|
1644
|
+
### §log-kill-scope KILL on the log: whole items and scoped bodies
|
|
1614
1645
|
|
|
1615
|
-
AST: `{ op: "
|
|
1646
|
+
AST: `{ op: "KILL", target, body: MatcherBody | null, lineMarker: TextLineMarker | null }` ({§kill-scope} in the contracts SPEC owns the grammar).
|
|
1616
1647
|
|
|
1617
|
-
|
|
1648
|
+
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.
|
|
1618
1649
|
|
|
1619
1650
|
### §jsonplurnk The Log's wire format
|
|
1620
1651
|
|
|
1621
|
-
The `## Log` section renders as a fixed three-backtick `jsonplurnk` fence - a JSON array of entry objects, otherwise-valid JSON with **exactly one** deviation: an open, nonempty `body` is a raw multiline string. Its opening JSON quote is followed by a physical newline, every visible content line retains its canonical numeric `N:` or anchored `@hash N:` coordinate, and its closing quote appears at column zero before either the object close or a following member. Source quotes, braces, fences, and headings cannot collide with either boundary because source text never occupies column zero after projection; source backticks therefore cannot form a CommonMark closing fence. The fixed opener keeps the packet prefix stable across content changes. The carve-out is localized to `body`, so the strip-parser recognizes `"body":"` followed by a newline, consumes one or more coordinate-prefixed lines, and replaces the raw multiline value with an escaped JSON string while preserving following members to recover strict JSON. The three body states are self-describing through field presence alone: a `body` field means open, `tokensBody` without `body` means folded (the value prices the
|
|
1622
|
-
|
|
1623
|
-
- §packet-
|
|
1652
|
+
The `## Log` section renders as a fixed three-backtick `jsonplurnk` fence - a JSON array of entry objects, otherwise-valid JSON with **exactly one** deviation: an open, nonempty `body` is a raw multiline string. Its opening JSON quote is followed by a physical newline, every visible content line retains its canonical numeric `N:` or anchored `@hash N:` coordinate, and its closing quote appears at column zero before either the object close or a following member. Source quotes, braces, fences, and headings cannot collide with either boundary because source text never occupies column zero after projection; source backticks therefore cannot form a CommonMark closing fence. The fixed opener keeps the packet prefix stable across content changes. The carve-out is localized to `body`, so the strip-parser recognizes `"body":"` followed by a newline, consumes one or more coordinate-prefixed lines, and replaces the raw multiline value with an escaped JSON string while preserving following members to recover strict JSON. The three body states are self-describing through field presence alone: a `body` field means open, `tokensBody` without `body` means folded (the value prices the visible body), and neither means no canonical body; no `display` label exists. Two defaults are likewise field absence: `origin` is omitted for the worker's own model authorship (exactly as `source` absence means the owning worker), and `status` is omitted for a routine 200 on an ordinary row. SEND always carries its submit code, KILL keeps an explicit 200 so destructive completion is decisive, and every non-200 stays explicit. A partially hidden open row also carries `"folded":["<scope>",...]`; coordinate gaps in its body make the omission explicit without renumbering later lines. `path` is the complete model-facing log identity: when a projected operation exists it ends in `/OP`, and no separate `op` field duplicates it. It leads each entry object; the remaining members follow in stable alphabetical order. A present authored operation annotation appears as `annotation`; its absence omits the field. Nonempty `tags` is the row's complete deduplicated, sorted folksonomy; an untagged row omits it. When an automatic bounded projection differs from the visibility-selected body, it appends `"chunk":"showing <selected> of <complete>"` after `body`; otherwise it omits `chunk`. Complete-line extents use inclusive two-coordinate line regions. A cut inside a line uses four-coordinate, start-inclusive and end-exclusive regions with 1-based Unicode code-point columns. The row's `path` remains the canonical READ target. The block is data only - no prose leads the fence. Every row's accounting: {§packet-token-accounting}.
|
|
1653
|
+
|
|
1654
|
+
- §packet-attachment-parts A READ of an attachable member carries its facts from the member's projection
|
|
1655
|
+
({§mimetype-projection-facts}): an image ({§mimetype-image}) as `image: { mimetype, width, height, bytes }`,
|
|
1656
|
+
a PDF ({§mimetype-pdf-facts}) as `document: { mimetype, pages, bytes }`. Its open row weighs the attachment
|
|
1657
|
+
(`tokensAttachment`, inside `tokensActive`) at `ceil(width × height / 750)` for a picture and
|
|
1658
|
+
`pages × 1500` for a document, and the packet lists it as an attachment of that kind. The kinds live in
|
|
1659
|
+
one table (`attachments.ts`): a kind exists only once a handler projects its facts and a scheme still holds
|
|
1660
|
+
its bytes. On a route whose provider declares the kind's modality ({§provider-input-modalities}) the wire
|
|
1661
|
+
form carries the user slot as parts, the text then one native part per accepted attachment read from the
|
|
1662
|
+
scheme's bytes at request time, a picture as an image part and a document as a file part; an attachment of
|
|
1663
|
+
a kind the route does not accept, and every attachment on a route that accepts none, reaches the model as
|
|
1664
|
+
its text projection alone. An attachment follows visibility exactly: a folded or killed row sends nothing.
|
|
1665
|
+
The weights are estimates; the provider's reported usage corrects the readout as it does for text.
|
|
1666
|
+
- §attachment-teaching The system slot teaches attachments only where they apply: an `Attachments` section,
|
|
1667
|
+
rendered between the definition and the policy, carries one `example`-fenced READ line per kind the
|
|
1668
|
+
route accepts and the daemon can attach, from the same table; a route that accepts no attachable kind has
|
|
1669
|
+
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 row, including its accounting field and framing, 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 (`path`/`target`/`#channel`/coordinate-prefixed bodies), weighability (per-item `tokens`), honesty (every 4xx/5xx row and the exact body state). {§jsonplurnk} {§packet-jsonplurnk-exception}
|
|
1624
1671
|
|
|
1625
1672
|
### §retrieval-packet-metadata READ/FIND packet metadata
|
|
1626
1673
|
|
|
@@ -1652,17 +1699,17 @@ ordinary bounded bodies expose their displayed and complete chunk extents there.
|
|
|
1652
1699
|
|
|
1653
1700
|
### §turn-ops-entry The admitted turn program
|
|
1654
1701
|
|
|
1655
|
-
§turn-ops-log-curation A source-backed turn preserves its **exact admitted Plurnk program** as an actionless log item in addition to the ordinary result row for every dispatched statement. `op` is null, `attrs.kind="turnOps"` identifies the durable type, `origin` is the turn producer, no target exists, `tx` is empty, and the source lives in `rx.content`, typed `text/vnd.plurnk`. Its canonical model-facing address appends the lowercase `/ops` leaf to its three-part coordinate. The packet does not duplicate that identity as `kind` metadata. It is line-numbered and READ/FIND/
|
|
1702
|
+
§turn-ops-log-curation A source-backed turn preserves its **exact admitted Plurnk program** as an actionless log item in addition to the ordinary result row for every dispatched statement. `op` is null, `attrs.kind="turnOps"` identifies the durable type, `origin` is the turn producer, no target exists, `tx` is empty, and the source lives in `rx.content`, typed `text/vnd.plurnk`. Its canonical model-facing address appends the lowercase `/ops` leaf to its three-part coordinate. The packet does not duplicate that identity as `kind` metadata. It is line-numbered and READ/FIND/KILL-able like any active log body. The worker-initialization `turnOps` is born visible because it is the worked orientation example; every other `turnOps`, including model inference and overflow recovery, is born FOLDED and remains available on demand. Log-KILL clears the `writableBy` gate for a model-authored item and retires only its active projection under {§log-history-projection}; the exact program remains forensic history. Log's handler surface keeps every other mutating op at 501. The shared executor writes exactly one after every admitted source-backed turn.
|
|
1656
1703
|
|
|
1657
|
-
§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
|
|
1704
|
+
§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.
|
|
1658
1705
|
|
|
1659
|
-
- §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.
|
|
1660
|
-
- §log-curation-folder-idiom **Log curation speaks the folder idiom; a zero-match sweep is a no-op success** —
|
|
1661
|
-
- §log-curation-set-selection **Row selection and body scope are independent** — target/glob
|
|
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 `## 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.
|
|
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: `## 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.
|
|
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 `## KILL0 (log:///**/READ) <17,-1>` may change long READs and no-op on short ones while reporting every selected row in `matched`.
|
|
1662
1709
|
|
|
1663
|
-
§
|
|
1710
|
+
§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).
|
|
1664
1711
|
|
|
1665
|
-
§curation-receipt-dissolves **Successful log-curation receipts dissolve.** A model-authored
|
|
1712
|
+
§curation-receipt-dissolves **Successful log-curation receipts dissolve.** A model-authored KILL of a log item, whole or scoped, renders in exactly the packet immediately after its turn — path, target, and status, no body — and leaves the active projection once a later model turn has rows; history keeps the row, the exact active/folded transition for every target, and the authored `turnOps`. Nothing is left to curate: a receipt that dissolves is not a log item to sweep. A KILL of a log item retires the selected rows from the worker's active projection under {§log-history-projection}; it does not delete their execution history. The dissolving is **scoped to log targets**: a `KILL` of a `worker://` note, an `sh://` stream, or another stored artifact retains its scheme-owned world or process semantics and stays visible. A killed exact coordinate resolves 404 in ordinary log operations; a well-formed broad selection with no active matches remains the 204 no-op of {§log-curation-folder-idiom}, and that 204 renders once like any dissolving receipt. Failed KILLs render like every operation error and persist.
|
|
1666
1713
|
|
|
1667
1714
|
### §log-sensitive-request-evidence Durable request evidence
|
|
1668
1715
|
|
|
@@ -1748,7 +1795,7 @@ AST: `{ op: "FIND", target (scope), body: MatcherBody | null (predicate), signal
|
|
|
1748
1795
|
`(https, example.com, /page)`, never an empty-authority row at `/page`.
|
|
1749
1796
|
- §find-channel-selection The target selects a channel under {§channel-selection}. That channel controls candidate eligibility, every matcher dialect's content or derivation, match-evidence coordinates, and exact producer-result composition. A selected channel absent from an exact entry is 404; a broad scope simply excludes entries lacking it. Successful resource-mode results remain complete default-first channel groups, so sibling channels are navigable catalog metadata rather than additional matches.
|
|
1750
1797
|
- §find-glob-filter-on-content `body` matcher operates on the addressed entry channel (glob/regex/jsonpath/xpath), per `plurnk.md` "Pattern Filtering"; the path-glob lives in the (target), not the body.
|
|
1751
|
-
- §find-semantic-selection Every matcher operates only over the candidate set selected by `(target)`; relation matchers do not bypass that selection. Semantic ranking is exhaustive within that candidate set, then applies the ordinary FIND result scope. Markerless semantic FIND therefore uses the same `<1,16>` default as every other matcher. Integers retain FIND's positional contract: `<N>` selects result N and `<N,M>` selects the inclusive range. A leading decimal first applies a minimum cosine-similarity threshold; following integers select positions within that ranked threshold set. Thus `<0.7,10,20>` means threshold 0.7 followed by results 10 through 20, while `<0.7>` applies the threshold and the ordinary first-16 page.
|
|
1798
|
+
- §find-semantic-selection Every matcher operates only over the candidate set selected by `(target)`; relation matchers do not bypass that selection. Semantic ranking is exhaustive within that candidate set, then applies the ordinary FIND result scope. Markerless semantic FIND therefore uses the same `<1,16>` default as every other matcher. Integers retain FIND's positional contract: `<N>` selects result N and `<N,M>` selects the inclusive range. A leading decimal first applies a minimum cosine-similarity threshold; following integers select positions within that ranked threshold set. Thus `<0.7,10,20>` means threshold 0.7 followed by results 10 through 20, while `<0.7>` applies the threshold and the ordinary first-16 page. Each semantic match carries its best-chunk cosine as `score`, and each ranked resource row surfaces it as `similarity` (three decimals), so a ranked page states why it is ordered; the lexical fallback ranks by BM25 and carries neither.
|
|
1752
1799
|
- §find-scoped-isolation Workspace + scheme scoped — no cross-workspace/cross-scheme leakage.
|
|
1753
1800
|
- §find-result-projection **The authored target shape determines the result unit; result cardinality never changes it** ({§find-result-unit}). Returns `FindResult { status, content, mimetype, results, range, matchingPathCount, matchLocationCount, itemsWeightTotal, returnedItemsWeightTotal }`:
|
|
1754
1801
|
|
|
@@ -1822,9 +1869,9 @@ AST: `{ op: "SEND", target: ParsedPath | null, body: SendBody | null, signal: nu
|
|
|
1822
1869
|
|---|---|---|---|
|
|
1823
1870
|
| **102** continue | next turn | next turn | next turn |
|
|
1824
1871
|
| **200** done | **resolved** — terminal, loop ends | **refused** — Premature-Terminate (KILL to abandon, or wait) | **refused** — forced next turn to see the result |
|
|
1825
|
-
| **202** wait | **resolves like 200**, unless this turn successfully
|
|
1872
|
+
| **202** wait | **resolves like 200**, unless this turn successfully scoped a KILL — an empty wait is satisfied, while curation continues into the curated next packet | **block on the join** — the loop sleeps (`<T>`/`<-1>` bound it, `<P>` polls); its work's conclusion **reawakens the same loop**, prompt intact ({§worker-lifecycle-child-wake}, {§worker-lifecycle-wake-liveness}) | resolves next turn (≈ continue) |
|
|
1826
1873
|
|
|
1827
|
-
§wait-obligation-matrix **499** gives up regardless of obligations and cancels the unresolved descendant scope — the model's one self-decided failure ({§state-terms}). The surface is small on purpose. The **one** non-obvious cell is **200 with an obligation in flight** — a contradiction (you claimed done while you owe work), which the engine holds you to via Premature-Terminate below. A child join is bounded by the child's terminal transition; an external stream may carry an explicit `<T,P>` policy. A successful same-turn
|
|
1874
|
+
§wait-obligation-matrix **499** gives up regardless of obligations and cancels the unresolved descendant scope — the model's one self-decided failure ({§state-terms}). The surface is small on purpose. The **one** non-obvious cell is **200 with an obligation in flight** — a contradiction (you claimed done while you owe work), which the engine holds you to via Premature-Terminate below. A child join is bounded by the child's terminal transition; an external stream may carry an explicit `<T,P>` policy. A successful same-turn scoped KILL is synchronous housekeeping, so it does not block an explicit `200`; with `202`, it instead continues as `102` because its context effect is useful only in the curated next packet.
|
|
1828
1875
|
|
|
1829
1876
|
§loop-terminal-authorship **Terminal authorship is explicit when external.**
|
|
1830
1877
|
|
|
@@ -1853,19 +1900,18 @@ failure) do strike: six in a row is a degenerated run.
|
|
|
1853
1900
|
|
|
1854
1901
|
- §send-target-recipient **A SEND target is a recipient.** A model's directed SEND
|
|
1855
1902
|
addresses a worker (`## SEND0 (worker://<name>)`), an outbound agent (`a2a://`),
|
|
1856
|
-
or a scheme that implements SEND (an `https://` POST)
|
|
1857
|
-
resource to delete. A SEND to a scheme the model may not write (the prompt, the
|
|
1903
|
+
or a scheme that implements SEND (an `https://` POST). A SEND to a scheme the model may not write (the prompt, the
|
|
1858
1904
|
log) is refused 400 `send-target-not-a-recipient`, never the unrelated writer
|
|
1859
1905
|
rule. The detail states only that the addressed scheme is not a recipient;
|
|
1860
1906
|
neutral recovery distinguishes targetless replies from directed SEND without
|
|
1861
1907
|
guessing which one was intended. A scheme that does not implement SEND
|
|
1862
1908
|
answers its ordinary factual 501 without grafting a guessed recovery onto it.
|
|
1863
|
-
- §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
|
|
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 `## 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.
|
|
1864
1910
|
- §send-premature-terminate **Premature terminate — the pending set.**
|
|
1865
1911
|
A model's completion claim is gated by one rule: *nothing pending may be silently
|
|
1866
1912
|
discarded*. Pending work has two states: **live obligations** (open
|
|
1867
1913
|
streams/spawns and live child workers) and **completed-but-unobserved
|
|
1868
|
-
results** (same-turn READ/FIND
|
|
1914
|
+
results** (same-turn READ/FIND results, failed operations, failed
|
|
1869
1915
|
terminal stream output (close status ≥ 400) without a terminal foisted
|
|
1870
1916
|
READ, and child results queued for the next packet). A stream that closed
|
|
1871
1917
|
successfully is banked, not pending: its output stays in the Log and `[200]`
|
|
@@ -1877,7 +1923,7 @@ failure) do strike: six in a row is a degenerated run.
|
|
|
1877
1923
|
`streams`, `workers`, `receipts`, `failed-stream-results`, and
|
|
1878
1924
|
`worker-results`; it never embeds commands, stream handles, result bodies, or
|
|
1879
1925
|
a presumed recovery. The pending kind changes the factual Problem class, not
|
|
1880
|
-
rail accounting. `
|
|
1926
|
+
rail accounting. `(FAIL)` deliberately abandons regardless.
|
|
1881
1927
|
- §send-administrative-terminal **An administrative terminal closes its own
|
|
1882
1928
|
transaction.** A client, plugin, or `_plurnk` operation program runs in its
|
|
1883
1929
|
own administrative loop. Its SEND signal `200` concludes exactly that loop;
|
|
@@ -1887,7 +1933,7 @@ failure) do strike: six in a row is a degenerated run.
|
|
|
1887
1933
|
observed only after crossing a packet boundary. SEND signal `202` parks only on
|
|
1888
1934
|
live obligations. If work has completed but is unobserved, it continues
|
|
1889
1935
|
directly to the next packet because the wake edge has already fired; only a
|
|
1890
|
-
genuinely empty set with no successful same-turn
|
|
1936
|
+
genuinely empty set with no successful same-turn scoped KILL resolves immediately like `(TERM)`.
|
|
1891
1937
|
|
|
1892
1938
|
### §exec EXEC
|
|
1893
1939
|
|
|
@@ -1898,17 +1944,17 @@ resolves the runtime first, selects its static {§executor-invocation} or exact
|
|
|
1898
1944
|
{§executor-tool-registry} entry, and enforces that declaration before effect
|
|
1899
1945
|
admission. Core owns target
|
|
1900
1946
|
realization; neither filesystem type nor body presence may invent a target role
|
|
1901
|
-
the selected runtime did not declare.
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
script;
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
tool
|
|
1911
|
-
|
|
1947
|
+
the selected runtime did not declare. `cwd` is the workspace's `project_root`, where the File scheme writes — never the
|
|
1948
|
+
daemon's own cwd — unless the heading carries a `{cwd=<directory>}` block
|
|
1949
|
+
({§exec-executor-slot}): core resolves that directory against the project root, or the
|
|
1950
|
+
shell's own cwd when the workspace has none, and refuses `400 cwd-not-found` when it is
|
|
1951
|
+
not an existing directory; any other metadata block on a local program is refused
|
|
1952
|
+
`400 metadata-unsupported`. A `script`-kind target ({§executor-invocation}) is the program: core inspects it before
|
|
1953
|
+
anything spawns — a file is the script; a directory is refused `400 target-not-a-program`,
|
|
1954
|
+
pointing at `{cwd=…}`; an absent path is refused `400 target-not-found`, giving the
|
|
1955
|
+
applicable accepted form without inferring what the model meant. When the target is a
|
|
1956
|
+
registered tool of another executor, recovery gives that tool's exact bracketed
|
|
1957
|
+
invocation; otherwise it points at an existing script or a bare shell-command body. A non-file resource
|
|
1912
1958
|
target that cannot be read keeps the owning READ's failure identity (#163) and states
|
|
1913
1959
|
the slot contract in its recovery — the resource is the program and the body its stdin;
|
|
1914
1960
|
a command belongs beneath a targetless heading — without guessing which was meant (#425). The started receipt always
|
|
@@ -1916,11 +1962,9 @@ names the working directory only when it is not the project root, and then in th
|
|
|
1916
1962
|
model's own project-relative form ({§fs-namespace}: the root is the model's `/`, so it
|
|
1917
1963
|
is never rendered, and no receipt or Problem carries a host-absolute path — the
|
|
1918
1964
|
batch of 2026-08-29 showed the absolute `cwd` copied back into the target slot as
|
|
1919
|
-
`(cwd: /host/path)`). The EXEC `(path)` is
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
is taught as targetless bare `EXEC`; `[sh]` remains the explicit form, and an
|
|
1923
|
-
authored directory target remains an optional cwd override.
|
|
1965
|
+
`(cwd: /host/path)`). The EXEC `(path)` is a program — a script for an interpreter, a tool name for a tool
|
|
1966
|
+
family — and neither a command nor a working directory is ever a target. The default
|
|
1967
|
+
shell is taught as targetless bare `EXEC`; `[sh]` remains the explicit form.
|
|
1924
1968
|
|
|
1925
1969
|
| Declared target kind | Authored target | Canonical effect target | Executor realization |
|
|
1926
1970
|
| -------------------- | --------------------------------------- | ----------------------- | --------------------------------------------------------- |
|
|
@@ -2003,21 +2047,27 @@ dispatch admission, and pull-document materialization. Core performs no
|
|
|
2003
2047
|
protocol discovery while building a packet and has no alternate tool
|
|
2004
2048
|
catalogue.
|
|
2005
2049
|
|
|
2006
|
-
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
|
|
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 `## EXEC0` or `## EXEC0 (sh)`. Registered tags exist only for tools that own a distinct body, target, or output contract. {§exec-registry-resolves}
|
|
2007
2051
|
|
|
2008
2052
|
**Timeout and poll — `<T,P>` on the `<L>` slot (grammar 0.74.20).** EXEC
|
|
2009
2053
|
repurposes the line-marker slot as `<timeout, poll>` in **minutes** — agentic
|
|
2010
2054
|
latencies make a sub-minute horizon a trap — converted at the parse boundary to the
|
|
2011
|
-
catalog's internal `stream.seconds`. The
|
|
2055
|
+
catalog's internal `stream.seconds`. The `## SEND0 (WAIT) <T>` wait horizon is minutes too.
|
|
2012
2056
|
|
|
2013
2057
|
§exec-timeout `T` (`mark[0]`) caps the spawn's lifetime. At `T>0` the service
|
|
2014
2058
|
aborts it — a bounded reap, polite signal then SIGKILL after
|
|
2015
2059
|
`PLURNK_SERVICE_EXEC_KILL_GRACE_MS` — and stamps the stream **504**, distinct
|
|
2016
|
-
from a deliberate kill (499) or a clean exit (200).
|
|
2017
|
-
|
|
2060
|
+
from a deliberate kill (499) or a clean exit (200). Absent is unbounded but
|
|
2061
|
+
loop-life bounded — reaped on every loop terminal except 202 — the
|
|
2062
|
+
background-stream behavior. **`-1` is unbounded and detached**: the spawn
|
|
2063
|
+
outlives its loop's terminal, 200 included. It never binds to the loop's
|
|
2064
|
+
teardown and is nobody's obligation — a TERM is not gated by it, a WAIT does
|
|
2065
|
+
not park on it, optimistic settlement looks past it — and it ends only by KILL,
|
|
2066
|
+
the worker's total reap, or daemon shutdown; its late conclusion surfaces
|
|
2067
|
+
without opening a loop. **`0` is turn-scoped**:
|
|
2018
2068
|
the stream is reaped at the worker's next pre-turn via the registry abort,
|
|
2019
2069
|
before the turn's own spawns, so it never survives into the subsequent turn;
|
|
2020
|
-
its terminal output surfaces born
|
|
2070
|
+
its terminal output surfaces born visible like any close ({§exec-stream}).
|
|
2021
2071
|
|
|
2022
2072
|
§exec-poll `P` (`mark[1]`) is the **poll cadence**, stored on the subscription.
|
|
2023
2073
|
While the loop is blocked on a SEND signal `202` wait for that stream, the daemon arms
|
|
@@ -2077,7 +2127,7 @@ two states and no others:
|
|
|
2077
2127
|
| state | what the model receives |
|
|
2078
2128
|
|---|---|
|
|
2079
2129
|
| active | nothing in the Log. The `## Child Streams` pointer names the stream with each channel's size and its growth since the last packet ({§child-orientation}); the model READs any range it wants. |
|
|
2080
|
-
| terminal | ONE `origin=_plurnk` READ at `<runtime>:///<coord>#<channel>`, born
|
|
2130
|
+
| terminal | ONE `origin=_plurnk` READ at `<runtime>:///<coord>#<channel>`, born visible, that is exactly a markerless READ of the channel — its first page ({§read-selection-projection}: lines 1–16, the whole channel when it fits, the channel's own mimetype), the `range` extent, terminal status and Problem, `terminal: true`, any producer-supplied integer `exitCode`, and `source: log:///<coord>/EXEC` linking the causal invocation. The packet renders that address under `stream`, exactly as the invocation row links its output, never under `target`: a stream is observed, not a slot to author. |
|
|
2081
2131
|
|
|
2082
2132
|
§exec-concurrency **Bounded admission per workspace (#389).** At most
|
|
2083
2133
|
`PLURNK_SERVICE_EXEC_CONCURRENCY` executions run at once in one workspace (shipped `12`;
|
|
@@ -2108,7 +2158,7 @@ observation at close — so the pointer can state growth and no partial document
|
|
|
2108
2158
|
or record ever reaches the model. The terminal observation and its cursor
|
|
2109
2159
|
transition commit atomically; a terminal state with an empty channel still
|
|
2110
2160
|
produces one bodyless conclusion row whose terminal fact, causal EXEC link, and
|
|
2111
|
-
available exit code make completion explicit without invented narration.
|
|
2161
|
+
available exit code make completion explicit without invented narration. KILL may curate
|
|
2112
2162
|
that log row without rewinding the cursor or publishing the terminal result
|
|
2113
2163
|
again; the exact terminal result and channel content remain READable at the
|
|
2114
2164
|
stream address. Every READ then obeys {§body-projection} and therefore renders
|
|
@@ -2116,7 +2166,7 @@ its selected result complete. A stream that closes before a same-turn wait
|
|
|
2116
2166
|
remains pending until every selected channel's terminal READ crosses the next
|
|
2117
2167
|
packet boundary. The EXEC row separately records the authored invocation.
|
|
2118
2168
|
|
|
2119
|
-
`## KILL0 (<runtime>:///<loop>/<turn>/<seq
|
|
2169
|
+
`## KILL0 (<runtime>:///<loop>/<turn>/<seq>/EXEC)` cancels an active subprocess via
|
|
2120
2170
|
the subscription registry's stored controller. A terminal stream is immutable:
|
|
2121
2171
|
499 returns 410 (already killed), every other terminal status returns an RFC
|
|
2122
2172
|
9457 409 Problem carrying `terminalStatus`, and an unknown address returns 404.
|
|
@@ -2211,7 +2261,7 @@ settles it as interruption (`500`) and errors active channels before evaluating
|
|
|
2211
2261
|
loops ({§worker-lifecycle-restart-recovery}); it never reports cancellation (`499`) or
|
|
2212
2262
|
pretends to reconstruct an opaque plugin connection.
|
|
2213
2263
|
|
|
2214
|
-
§subscriptions-fold-keeps-subscription
|
|
2264
|
+
§subscriptions-fold-keeps-subscription A scoped KILL changes a log row's folded body intervals ({§log-kill-scope}), never the subscription registry. Curation of a streaming entry's log body leaves the live stream running: visibility is render-only, never cancellation.
|
|
2215
2265
|
|
|
2216
2266
|
### §chunk-accumulation Chunk accumulation
|
|
2217
2267
|
|
|
@@ -2229,9 +2279,9 @@ Model sees lifecycle events in the `log` section per turn.
|
|
|
2229
2279
|
|
|
2230
2280
|
### §stream-control Stream control and writes
|
|
2231
2281
|
|
|
2232
|
-
- **Cancel:** `##
|
|
2233
|
-
- **Kill:** `## KILL0 (sh:///1/2/3)` — 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.
|
|
2234
|
-
- **WebSocket write:** `## EDIT0 (wss://feed/x)` or `## SEND0
|
|
2282
|
+
- **Cancel:** `## KILL0 (https://feed.example/x)` — the service invokes the handle registered by `subscriptions.open()` and aborts the composed subscription signal.
|
|
2283
|
+
- **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.
|
|
2284
|
+
- **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.
|
|
2235
2285
|
- **Other stream write:** `## SEND0 [200] (…)` remains scheme-defined, including exec stdin.
|
|
2236
2286
|
|
|
2237
2287
|
### §stream-constraints Engine constraints
|
|
@@ -2395,8 +2445,8 @@ service manifest edit.
|
|
|
2395
2445
|
|
|
2396
2446
|
- Channel state (`static`/`active`/`closed`/`errored`) — persisted channel metadata owned by core and exposed through the schemes capability contract ({§channel-state}).
|
|
2397
2447
|
- Backpressure caps — none ({§stream-constraints}).
|
|
2398
|
-
- Stream cancel —
|
|
2399
|
-
- Delete — `KILL` (entry-KILL, the canonical delete, {§move});
|
|
2448
|
+
- Stream cancel — `KILL` of the stream address ({§stream-control}).
|
|
2449
|
+
- Delete — `KILL` (entry-KILL, the canonical delete, {§move}); a scoped entry KILL deletes one span through the EDIT path ({§kill-scope-entry}).
|
|
2400
2450
|
- §loop-policy-effective-read Per-loop policy — `loops.policy` persists one complete immutable `LoopPolicy`; every runtime policy read validates that snapshot before use. Missing rows or invalid values fail with the owning loop coordinate and cause. Raw archival copies and forensic rendering do not interpret policy.
|
|
2401
2451
|
- Default-channel wire rendering — {§channel-selection}.
|
|
2402
2452
|
|
|
@@ -2465,7 +2515,7 @@ Model selection uses one selector vocabulary in `ProviderRegistry` ({§provider-
|
|
|
2465
2515
|
| §operator-config-loop-timeout `PLURNK_SERVICE_LOOP_TIMEOUT` | `86400000` | ms wall-clock budget for a single core loop: expiry aborts the loop signal mid-flight (a stuck `generate` included) and the loop terminates `504 loop_timeout` — a legible engine terminal, kin to the exec `<T>` reap's 504 ({§exec-timeout}). |
|
|
2466
2516
|
| `PLURNK_SERVICE_PROVIDER_RECOVERY` | `900000` | ms a turn keeps re-issuing its provider call after a recoverable provider failure before the loop parks ({§provider-recovery}); `0` parks at once. |
|
|
2467
2517
|
| `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF` | `5000` | First recovery delay (ms); doubles per failure, capped at twelve times itself ({§provider-recovery}). |
|
|
2468
|
-
| `PLURNK_SERVICE_MAX_STRIKES` | `
|
|
2518
|
+
| `PLURNK_SERVICE_MAX_STRIKES` | `3` | Consecutive admitted-turn strike threshold ({§engine-rails}). |
|
|
2469
2519
|
| `PLURNK_SERVICE_EMISSION_ATTEMPTS` | `3` | Completed provider responses allowed beneath one engine turn before an untrustworthy model-turn frame exhausts admission. Bounded interior operation errors are admitted and do not spend this budget. Consecutive exhaustion after the one informed recovery turn terminates independently of strikes. |
|
|
2470
2520
|
| `PLURNK_SERVICE_PREVIEW_LINES` | `16` | Maximum lines in an ordinary bounded log-body projection ({§body-projection}). |
|
|
2471
2521
|
| `PLURNK_SERVICE_PREVIEW_CHARS` | `2560` | Maximum Unicode code points in an ordinary bounded log-body projection, with CRLF treated as one indivisible separator; independently contains single-line bodies ({§body-projection}). |
|
|
@@ -2935,8 +2985,8 @@ mutation of its source; resource-backed EXEC demands its runtime plus source
|
|
|
2935
2985
|
observation. Unknown schemes, runtimes,
|
|
2936
2986
|
and tools continue to their ordinary resolver so capability policy cannot turn
|
|
2937
2987
|
absence into a misleading restriction. The same resolver shapes generated
|
|
2938
|
-
resource examples, worker tool documents, and Turn0 surveys. PLAN,
|
|
2939
|
-
|
|
2988
|
+
resource examples, worker tool documents, and Turn0 surveys. PLAN, log KILL,
|
|
2989
|
+
and label or targetless SEND are log/program control rather than routed
|
|
2940
2990
|
external demands and therefore remain outside capability selectors.
|
|
2941
2991
|
|
|
2942
2992
|
§worker-settings **The worker carries its own behavioral rules.** The
|
|
@@ -3218,7 +3268,7 @@ time of measurement.
|
|
|
3218
3268
|
|
|
3219
3269
|
| Fact | Owner and unit | Time | Contract |
|
|
3220
3270
|
|:-----|:---------------|:-----|:---------|
|
|
3221
|
-
| Core curation weight | `contentWeight = ceil(chars/2)` over channel content, canonical log bodies, and rendered packet slots | Write/build | Stable, model-independent pressure and
|
|
3271
|
+
| Core curation weight | `contentWeight = ceil(chars/2)` over channel content, canonical log bodies, and rendered packet slots | Write/build | Stable, model-independent pressure and curation savings; never a tokenizer claim. |
|
|
3222
3272
|
| §tokenomics-context-envelope-admission Provider input capacity | Provider model limits and configured total output envelope, in provider tokens | Before every logical request | `min(maxInputTokens, contextWindow - outputBudget)` over the known terms. The provider alone measures the complete request and admits, defers, or rejects it. |
|
|
3223
3273
|
| Provider generation envelope | Provider total output budget and optional reasoning subset, in provider tokens | Before every logical request | One total output budget includes hidden reasoning. A reasoning budget is a strict subset, never an additive reserve. |
|
|
3224
3274
|
| Provider usage and cost | Provider-reported input/output/cache/reasoning tokens and monetary evidence | After every physical request | Durable physical-request forensics under {§provider-usage}; never curation state or a preflight estimate. |
|
|
@@ -3226,6 +3276,7 @@ time of measurement.
|
|
|
3226
3276
|
- §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.
|
|
3227
3277
|
- §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.
|
|
3228
3278
|
- §tokenomics-context-percent **Curation percent.** `tokensActiveTotal` carries packet weight as a percentage of `tokensActiveMax`. It reads the capacity already resolved by the provider; no extra provider call.
|
|
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}).
|
|
3229
3280
|
- §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.
|
|
3230
3281
|
- §tokenomics-prompt-projection-share **Prompt projection is stable packet policy.**
|
|
3231
3282
|
`PLURNK_SERVICE_PROMPT_PROJECTION` is a required alias-scoped percentage in
|
|
@@ -3241,10 +3292,10 @@ time of measurement.
|
|
|
3241
3292
|
- **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}
|
|
3242
3293
|
- §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.
|
|
3243
3294
|
- §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.
|
|
3244
|
-
- §tokenomics-neutral-telemetry **Curation telemetry is state, not response allowance.** The model-facing `Context Token Budget` section begins with exactly two fields on separate lines: `tokensActiveTotal: N (P%)` and `tokensActiveMax: M`. It never presents their difference as free response tokens. The protocol definition directly requires
|
|
3245
|
-
- §tokenomics-pressure-inventory **Pressure identifies its reclaimable concentration.** When the ordinary two-field packet measurement reaches 80% of `tokensActiveMax`, the budget section may append `YOU MUST
|
|
3295
|
+
- §tokenomics-neutral-telemetry **Curation telemetry is state, not response allowance.** The model-facing `Context Token Budget` section begins with exactly two fields on separate lines: `tokensActiveTotal: N (P%)` and `tokensActiveMax: M`. 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.
|
|
3296
|
+
- §tokenomics-pressure-inventory **Pressure identifies its reclaimable concentration.** When the ordinary two-field packet measurement reaches 80% of `tokensActiveMax`, the budget section may append `YOU MUST KILL superseded, stale, or irrelevant log items and ranges.` followed by `Largest Log Items`: at most five currently visible, addressed log bodies, ordered by `tokensActive` descending and then `log:///` path. Each item repeats only that row's `tokensBody` and `tokensActive`. 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`.
|
|
3246
3297
|
- §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.
|
|
3247
|
-
- §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
|
|
3298
|
+
- §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.
|
|
3248
3299
|
- §tokenomics-negative-pressure **Negative curation pressure is honest but never submitted.** The provisional readout may report `tokensActiveTotal` and its percentage 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.
|
|
3249
3300
|
|
|
3250
3301
|
### §membership Workspace identity, membership, disk co-location
|
|
@@ -3336,7 +3387,7 @@ and never re-fetch a match.
|
|
|
3336
3387
|
- §membership-git-hermetic Native Git runs with ambient `GIT_*` and
|
|
3337
3388
|
global/system config scrubbed, so repository identity follows `project_root`,
|
|
3338
3389
|
never the daemon's launch environment.
|
|
3339
|
-
- §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
|
|
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 `## EXEC0 (sh)`'s job, not the file scheme's.
|
|
3340
3391
|
- §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.
|
|
3341
3392
|
|
|
3342
3393
|
**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`.
|
|
@@ -3413,7 +3464,7 @@ The CAS is the **hard backstop**, at the moment of writing, on every accept path
|
|
|
3413
3464
|
|
|
3414
3465
|
§membership-git-flags **Permission flags.** Service-wide Git admission comes from {§operator-config-git-ceiling}. `PLURNK_SERVICE_GIT_AUTO=1` (default) includes the repository containing `project_root`; `=0` disables automatic Git membership, leaving member definitions as the only membership source. `ALLOWED` gates `AUTO`.
|
|
3415
3466
|
|
|
3416
|
-
**Rationale.** Workspace is the right scope unit and the containing Git repository is its ordinary development boundary. Membership curation is tiered: Git bounds it by tracking, the client supersedes by overlay, and the model curates its render by READ/
|
|
3467
|
+
**Rationale.** Workspace is the right scope unit and the containing Git repository is its ordinary development boundary. Membership curation is tiered: Git bounds it by tracking, the client supersedes by overlay, and the model curates its render by READ/KILL. Supporting several independent repositories as one world would require Plurnk-owned topology, synchronization, and model teaching that Git already solves cleanly by treating them as separate workspaces.
|
|
3417
3468
|
|
|
3418
3469
|
**Schema.** The version-1 baseline stores the normalized {§inference-ledger},
|
|
3419
3470
|
its generation or embedding specialization, emission admission, and cardinal
|
|
@@ -3433,7 +3484,7 @@ flowchart TD
|
|
|
3433
3484
|
assemble["Assemble and measure<br/>candidate request"] --> budget{"Weight ≤ curation ceiling?"}
|
|
3434
3485
|
budget -->|yes| generate["Provider generate"]
|
|
3435
3486
|
budget -->|no| recover["Keep turn packetless<br/>reclassify as `_plurnk` overflow"]
|
|
3436
|
-
recover --> fold["Dispatch PLAN, whole-body
|
|
3487
|
+
recover --> fold["Dispatch PLAN, whole-body scoped KILL ops,<br/>and SEND through ordinary dispatch"]
|
|
3437
3488
|
fold --> verify{"Rebuilt request fits?"}
|
|
3438
3489
|
verify -->|yes| next["Next model turn"]
|
|
3439
3490
|
verify -->|no| stop["Terminal 413"]
|
|
@@ -3459,19 +3510,19 @@ at its first overflow because four embedding calls were counted as history). Pac
|
|
|
3459
3510
|
remain ordinary turn chronology but do not consume `maxTurns`, model-call,
|
|
3460
3511
|
emission-attempt, usage, or cost accounting.
|
|
3461
3512
|
|
|
3462
|
-
- §overflow-turn-script **Recovery is one ordinary admitted `_plurnk` program.** Its canonical {§plan-value} has one `medium`, `in_progress` entry whose content is `Automatically
|
|
3463
|
-
- §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,
|
|
3464
|
-
- §overflow-turn-hard-413 **Recovery fails hard when the causal fold cannot fit.** After the ordinary
|
|
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 `## 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
|
+
- §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
|
+
- §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**.
|
|
3465
3516
|
|
|
3466
3517
|
- §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.
|
|
3467
3518
|
|
|
3468
|
-
- §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
|
|
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 `## 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.
|
|
3469
3520
|
|
|
3470
3521
|
§overflow-turn-surface **The packet is the resulting state, not an account of it.**
|
|
3471
3522
|
The first request after recovery is assembled by the ordinary packet path from
|
|
3472
3523
|
the actual durable log after the recovery turn. It therefore carries the prior
|
|
3473
|
-
causal rows genuinely
|
|
3474
|
-
the recovery `turnOps` genuinely
|
|
3524
|
+
causal rows genuinely folded, the recovery PLAN and SEND genuinely visible, and
|
|
3525
|
+
the recovery `turnOps` genuinely folded. Successful recovery KILL receipts are
|
|
3475
3526
|
absent under the universal curation rule. No notice, reconstruction, auto-open,
|
|
3476
3527
|
or overflow-specific projection simulates what `_plurnk` did; OPENing the exact
|
|
3477
3528
|
`turnOps` reveals the program that did it. The model retains complete authority
|
|
@@ -3492,7 +3543,7 @@ flowchart LR
|
|
|
3492
3543
|
parent --> pull["Pre-turn lossless pull<br/>(cursor, captured high-water]"]
|
|
3493
3544
|
global --> pull
|
|
3494
3545
|
pull --> log["Observer's self-contained log<br/>origin=_plurnk"]
|
|
3495
|
-
log --> packet["Packet lists coordinate;<br/>
|
|
3546
|
+
log --> packet["Packet lists coordinate;<br/>READ recalls exact body"]
|
|
3496
3547
|
```
|
|
3497
3548
|
|
|
3498
3549
|
§env-delta-log-pull **Pull the event record, never a world snapshot.** At
|
|
@@ -3573,6 +3624,8 @@ flowchart LR
|
|
|
3573
3624
|
body --> recall["READ log:///…<br/>recalls canonical body"]
|
|
3574
3625
|
```
|
|
3575
3626
|
|
|
3627
|
+
§edit-receipt-removed-text **A pure deletion's receipt quotes what it removed.** An applied effect that inserted nothing and removed at least one line carries `removedText` — the removed text, first 40 lines — projected on the wire as `removed`; an effect that inserted anything carries no such field, its resulting context shows the change.
|
|
3628
|
+
|
|
3576
3629
|
§edit-receipt-anchored-context **An applied EDIT's resulting context carries anchors.** The bounded resulting context each effect renders (`PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES` around and inside the landed region) is rendered exactly as a READ renders — `@xxxxx L:text`, hashed with the resource's READ identity ({§line-anchors}) — so the next batch cites the landed lines by anchor without a READ; both requiems of 2026-08-29 asked for this. A scheme that supplies no identity keeps the line-numbered form.
|
|
3577
3630
|
|
|
3578
3631
|
§edit-result-receipt-projection **EDIT projects the scheme-owned batch
|
|
@@ -3589,7 +3642,8 @@ the aggregate remains dispatch coordination state.
|
|
|
3589
3642
|
| `unit`, `before`, `after` | `extent` | Whole-line batches use line counts. A batch containing any exact four-coordinate edit uses Unicode code-point counts. |
|
|
3590
3643
|
| `parseIssues.before`, `parseIssues.after` | `parseIssues` as `before→after` | Parser-recovery counts for complete source and landed revisions; omitted when both are clean or either is unavailable. |
|
|
3591
3644
|
| `effect.requested`, `source`, `result` | `range` | The admitted marker and its normalized mapping from the common source snapshot into the landed body. |
|
|
3592
|
-
| `effect.removed`, `inserted` | `change` | Removed and inserted counts in the receipt unit.
|
|
3645
|
+
| `effect.removed`, `inserted` | `change` | Removed and inserted counts in the receipt unit. |
|
|
3646
|
+
| `effect.removedText` | `removed` | {§edit-receipt-removed-text}: a pure deletion's removed text, first 40 lines; absent when the edit inserted anything. |
|
|
3593
3647
|
| `effect.context` | Canonical row body | Numbered physical lines at each landed boundary, bounded symmetrically by `PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES`. |
|
|
3594
3648
|
| `disposition`, `requested` | `disposition`, `requested` | A reviewer-replaced batch preserves the authored marker while stating that its attributed effect was superseded. |
|
|
3595
3649
|
| `replacement` | `replacement`, `change`, canonical proposal-owner body | The one whole-resource effect actually applied by the reviewer replacement; never duplicated across authored rows. |
|
|
@@ -3764,7 +3818,7 @@ evidence when a downstream standard cannot represent the complete list.
|
|
|
3764
3818
|
|
|
3765
3819
|
§body-projection **One full body, one packet projection.** Every durable log row has one canonical full body resolved from its stored tx/rx envelope by `LogBody`. READ and FIND over `log:///`, persistent search derivation, and packet rendering all consume that same meaning. Only packet rendering may project it:
|
|
3766
3820
|
|
|
3767
|
-
| row producer | ordinary
|
|
3821
|
+
| row producer | ordinary visible projection |
|
|
3768
3822
|
|---|---|
|
|
3769
3823
|
| any `READ` or `FIND` | complete selected operation result |
|
|
3770
3824
|
| any `PLAN` | complete canonical Plurnk Plan JSON {§plan-value} |
|
|
@@ -3773,13 +3827,13 @@ evidence when a downstream standard cannot represent the complete list.
|
|
|
3773
3827
|
| every other nonempty body | head bounded independently by `PLURNK_SERVICE_PREVIEW_LINES` and `PLURNK_SERVICE_PREVIEW_CHARS` |
|
|
3774
3828
|
| bodyless row | `"display":"none","body":""` |
|
|
3775
3829
|
|
|
3776
|
-
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
|
|
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, `chunk` follows the displayed `body` with the exact selected and complete extents defined by {§jsonplurnk}; 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.
|
|
3777
3831
|
|
|
3778
|
-
§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
|
|
3832
|
+
§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.
|
|
3779
3833
|
|
|
3780
3834
|
§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.
|
|
3781
3835
|
|
|
3782
|
-
§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
|
|
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` after `body`; 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.
|
|
3783
3837
|
|
|
3784
3838
|
§prompt-self-only The frame is self-only and owner-keyed:
|
|
3785
3839
|
`entries.owner_id` carries worker identity while the address carries only the
|
|
@@ -3872,9 +3926,11 @@ retain distinct contracts and lifetimes.
|
|
|
3872
3926
|
|
|
3873
3927
|
§digest-cost-kind **Cost basis named.** A rendered Cost line carries the basis of its dollar figure: `(charged)` only when every settled request's cost is provider-charged; `(estimated — catalog rates)` when any settled request's cost is an estimate, because a mixed sum is no more trustworthy than its weakest term. A dollar figure without its basis reads as billed truth, and an estimate must never impersonate a charge.
|
|
3874
3928
|
|
|
3929
|
+
§output-allowance-notice **The output allowance is disclosed, and a ceiling cut names its cause.** The packet's budget section carries `tokensResponseMax: <tokens>` beside the curation ceiling whenever the provider resolves an output budget — the per-turn response allowance is a capacity fact, disclosed rather than discovered by truncation. The disclosed number is the program's guaranteed room — the configured output floor less the reasoning subset, since reasoning spends from the same allowance — never the wire grant: overflow tolerance (#482) is never advertised in the packet, and a cut's notice names the true per-call grant from the response's own capacity record. When a provider finish is `length`, the engine emits an `output_truncated` notice (source `engine:capacity`) naming the allowance — the fact alone, never advice on what to do about it — on every path — railed or not — and the rails verdict never blames the model's grammar for a cut the engine's own ceiling made. The same precedence governs a cut so deep no operation parses: the rejection notice names the truncation as the cause, not the parser's symptom, overriding {§invalid-emission-attempts}'s parser diagnostic for `length` finishes.
|
|
3930
|
+
|
|
3875
3931
|
§digest-wire-line **Wire health aggregated.** Each worker summary renders a `Wire:` line — total physical provider requests, error-outcome count, and the error percentage when nonzero. Provider-level failures are absorbed by retries below the packet stream, so without this aggregate a rate-limit storm is invisible in every summary while the model's experience stays clean.
|
|
3876
3932
|
|
|
3877
|
-
§digest-forensic-fidelity **Forensic fidelity and cardinality.** The digest's machine-readable JSON preserves every log event with its initial and current projection, causal `source`, tags, and structured `attrs`; every exact
|
|
3933
|
+
§digest-forensic-fidelity **Forensic fidelity and cardinality.** The digest's machine-readable JSON preserves every log event with its initial and current projection, causal `source`, tags, and structured `attrs`; every exact log-KILL target effect; the exact Problem on every failed row; each loop's exact terminal result; and every ordered physical provider request. KILLed `turnOps` still produce their chronological `assistant.md` artifacts because curation cannot rewrite what a producer submitted. Each stored packet validates independently: one malformed historical packet remains exact raw evidence with its complete validation error chain and never prevents healthy turns from being projected. Accounting on broader rows is the shared exact derivation from that ledger, never a second stored fact. A worker's Cost line names how many settled requests carry no usage at all (errored or aborted exchanges) — their server-side spend is unrecorded rather than silently priced as zero. The reasoning chronology distinguishes readable reasoning content from provider-reported reasoning usage: when tokens were reported but no readable content was returned, it states both facts instead of implying that no reasoning occurred. The human Markdown waterfall shows a present causal source and may preview only the Problem detail because it remains a triage projection, not the machine record. Targets reconstruct the model-visible address, including hostname, port, serialized query, and fragment; an authority-bearing URL must never degrade from `https://host/path` to `https:///path`, and durable resource coordinates render back to their authority form. Its human Markdown waterfall groups identical per-turn op outcomes and typed `entry_materialized` narrations, reporting the exact count and sequence span (`xN (seq A-B)`). Grouping keys include source and the complete target, so distinct causes, authorities, or channels never collapse. Thus amplification is conspicuous without making the diagnostic artifact itself pathological; valid packet files remain byte-identical records of what the model saw.
|
|
3878
3934
|
|
|
3879
3935
|
§digest-executor-evidence **A red command is work, not a defect.** Engine-materialized
|
|
3880
3936
|
completion rows for a failed command carry the executor's problem identity
|
|
@@ -3956,7 +4012,7 @@ worker's private entry space. Turn 0 surveys the families (`## FIND0 [+init,+too
|
|
|
3956
4012
|
(worker://~/_plurnk/tools/*.md)`, one row per
|
|
3957
4013
|
server carrying its summary) and, for each server named in
|
|
3958
4014
|
`PLURNK_MCP_EXPANDED`, adds one FIND over its family document matching the
|
|
3959
|
-
`## EXEC0` headings (`## FIND0
|
|
4015
|
+
`## EXEC0` headings (`## FIND0 (worker://~/_plurnk/tools/<server>.md)`
|
|
3960
4016
|
with `/^## EXEC0 .*\n.*$/m`), so turn 0 names every tool with its annotation and
|
|
3961
4017
|
signature — one row per tool, paged like every survey. No document is delivered
|
|
3962
4018
|
unasked.
|
|
@@ -4020,8 +4076,9 @@ its adapter owns protocol truth for standard Agent Skills and nothing else. A
|
|
|
4020
4076
|
definition is `SkillDefinition` — the standard skill `name`, the universal
|
|
4021
4077
|
root `scope` (`project` = `<projectRoot>/.agents/skills`, `global` =
|
|
4022
4078
|
`~/.agents/skills`), and for a Worker-installed skill the standard installer
|
|
4023
|
-
`source` that provides it. Plurnk
|
|
4024
|
-
|
|
4079
|
+
`source` that provides it. Plurnk seeds no universal root and mutates none
|
|
4080
|
+
absent an explicit `add`/`remove`; its one bundled skill document is never a
|
|
4081
|
+
root at all ({§git-skill}).
|
|
4025
4082
|
|
|
4026
4083
|
*Available definitions.* The filesystem is the only truth about installation:
|
|
4027
4084
|
every `<root>/<name>/SKILL.md` directory under the project then the global
|
|
@@ -4064,6 +4121,17 @@ preserved verbatim ({§functionality-documents}). They are discovered by the
|
|
|
4064
4121
|
turn-0 `+init,+skills` FIND survey; disabled and unavailable skills are
|
|
4065
4122
|
absent from model teaching.
|
|
4066
4123
|
|
|
4124
|
+
§git-skill **The git skill is a bundled document, surfaced where it applies.** `git.md`
|
|
4125
|
+
(the teaching corpus's `skillDocs.git`, shipped by `@plurnk/plurnk-meta`) is a knowledge
|
|
4126
|
+
document, not a tool: it teaches commits as the only shareable state, one branch-shaped child
|
|
4127
|
+
per checkout, worktrees for parallel children, deliberate merging, and the history a worker
|
|
4128
|
+
must not rewrite. The worker documentation reconciliation materializes it as the worker-private
|
|
4129
|
+
entry `worker://~/_plurnk/skills/git.md` when, and only when, the workspace's project root sits
|
|
4130
|
+
inside a git repository ({§membership}); it touches no universal skill root and installs
|
|
4131
|
+
nothing. The turn-0 survey `FIND (worker://~/_plurnk/skills/*.md)` therefore lists it, with
|
|
4132
|
+
its summary, exactly for the workspaces where it applies, and a plain-directory workspace never
|
|
4133
|
+
sees it.
|
|
4134
|
+
|
|
4067
4135
|
§skills-remove **`remove` uninstalls what the Worker installed.** Before the
|
|
4068
4136
|
coordinator forgets a Worker-origin skill definition the adapter removes that
|
|
4069
4137
|
skill from the definition's scope through the standard CLI (`remove <name>
|
|
@@ -4090,7 +4158,7 @@ section because they are language extensions rather than executable tools.
|
|
|
4090
4158
|
|
|
4091
4159
|
### §schemes user.schemes — the resource directory
|
|
4092
4160
|
|
|
4093
|
-
§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
|
|
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 `## 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.
|
|
4094
4162
|
|
|
4095
4163
|
### §inject system.inject — the operator injection
|
|
4096
4164
|
|
|
@@ -4098,7 +4166,7 @@ section because they are language extensions rather than executable tools.
|
|
|
4098
4166
|
|
|
4099
4167
|
### §policy system.policy — the client's policy injection
|
|
4100
4168
|
|
|
4101
|
-
§policy-sections One section rides the system slot **after the definition and before capability teaching**: `## Policy` from `PLURNK_SERVICE_POLICY` (default `$XDG_CONFIG_HOME/plurnk/AGENTS.md`, {§host-path-layout}). Policy is the client's authoritative rules promoted into the privileged zone — NOT a curatable, foldable, READ-able entry; the model cannot
|
|
4169
|
+
§policy-sections One section rides the system slot **after the definition and before capability teaching**: `## Policy` from `PLURNK_SERVICE_POLICY` (default `$XDG_CONFIG_HOME/plurnk/AGENTS.md`, {§host-path-layout}). Policy is the client's authoritative rules promoted into the privileged zone — NOT a curatable, foldable, READ-able entry; the model cannot KILL it away. A default-absent path is silent (the section is omitted); an explicit override (env set) that fails to read fails the turn hard — a deliberate setting with a broken path is a misconfig, surfaced not hidden. Read per-turn so edits take effect live. The PROJECT `AGENTS.md` is local guidance, not policy: it rides turn 0 as the foisted `worker://~/_plurnk/agents.md` entry ({§turn0-agents-stunt}); all other reference material is skills under the worker's private skills tree ({§skills-functionality}).
|
|
4102
4170
|
|
|
4103
4171
|
On first run, and only when `$XDG_CONFIG_HOME/plurnk` itself is absent, the service seeds
|
|
4104
4172
|
`AGENTS.md` from `@plurnk/plurnk-meta/POLICY.md` ({§teaching-corpus}).
|
|
@@ -4353,10 +4421,11 @@ Carried from the contract walk; durable.
|
|
|
4353
4421
|
- **READ rx** prefixes every textual line under {§render-rule}; eligible
|
|
4354
4422
|
editable resources carry `@hash N:`, and all others carry `N:`.
|
|
4355
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). FIND's signal classifies its own log item ({§log-item-tags}).
|
|
4356
|
-
- **
|
|
4357
|
-
- **SEND signal `410`** deletes as a side-effect (not the model idiom; {§move}): with `#fragment`, that channel only; without, the whole entry. **SEND signal `499`** resolves the durable open-subscription row and invokes that subscription's exact callable owner through the process-local live registry ({§subscriptions}).
|
|
4424
|
+
- **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.
|
|
4358
4425
|
- **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.
|
|
4359
4426
|
|
|
4360
|
-
### §
|
|
4427
|
+
### §kill-scope-entry Scoped KILL on an entry
|
|
4428
|
+
|
|
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. `## EDIT0 (path) <scope>` with an empty body remains the same act spelled the other way; the teaching names KILL.
|
|
4361
4430
|
|
|
4362
|
-
|
|
4431
|
+
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.
|