@plurnk/plurnk-service 3.0.0 → 3.2.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 +38 -21
- package/INSTALL.md +38 -1
- package/README.md +3 -0
- package/SPEC.md +681 -268
- package/dist/build-info.json +1 -1
- package/dist/completions/_plurnk-service +13 -0
- package/dist/completions/plurnk-service.bash +19 -0
- package/dist/completions/plurnk-service.fish +94 -0
- package/dist/content/path-mimetype.d.ts.map +1 -1
- package/dist/content/path-mimetype.js +2 -8
- package/dist/content/path-mimetype.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts +2 -2
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +36 -32
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BudgetReadout.d.ts +7 -2
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +36 -5
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/{schemes/_derivation-use.d.ts → core/ContentUse.d.ts} +3 -3
- package/dist/core/ContentUse.d.ts.map +1 -0
- package/dist/{schemes/_derivation-use.js → core/ContentUse.js} +8 -7
- package/dist/core/ContentUse.js.map +1 -0
- package/dist/core/DataStatementRunner.d.ts.map +1 -1
- package/dist/core/DataStatementRunner.js +8 -20
- package/dist/core/DataStatementRunner.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +11 -3
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +186 -109
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/EditMutations.js +1 -1
- package/dist/core/EditMutations.js.map +1 -1
- package/dist/core/Engine.d.ts +1 -1
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +4 -7
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/EnvFlags.js +1 -1
- package/dist/core/EnvFlags.js.map +1 -1
- package/dist/core/FabricatedLog.d.ts +1 -0
- package/dist/core/FabricatedLog.d.ts.map +1 -1
- package/dist/core/FabricatedLog.js +8 -0
- package/dist/core/FabricatedLog.js.map +1 -1
- package/dist/core/FileAddress.d.ts +12 -0
- package/dist/core/FileAddress.d.ts.map +1 -0
- package/dist/core/FileAddress.js +73 -0
- package/dist/core/FileAddress.js.map +1 -0
- package/dist/core/FilePublication.d.ts +15 -0
- package/dist/core/FilePublication.d.ts.map +1 -0
- package/dist/core/FilePublication.js +143 -0
- package/dist/core/FilePublication.js.map +1 -0
- package/dist/core/FileSnapshot.d.ts +26 -0
- package/dist/core/FileSnapshot.d.ts.map +1 -0
- package/dist/core/FileSnapshot.js +179 -0
- package/dist/core/FileSnapshot.js.map +1 -0
- package/dist/core/KillHandler.d.ts.map +1 -1
- package/dist/core/KillHandler.js +4 -1
- package/dist/core/KillHandler.js.map +1 -1
- package/dist/core/LiveSubscription.d.ts.map +1 -1
- package/dist/core/LiveSubscription.js +14 -2
- package/dist/core/LiveSubscription.js.map +1 -1
- package/dist/core/LiveSubscriptions.d.ts +3 -1
- package/dist/core/LiveSubscriptions.d.ts.map +1 -1
- package/dist/core/LiveSubscriptions.js +16 -1
- package/dist/core/LiveSubscriptions.js.map +1 -1
- package/dist/core/LogBody.d.ts.map +1 -1
- package/dist/core/LogBody.js +3 -1
- package/dist/core/LogBody.js.map +1 -1
- package/dist/core/LoopDriver.d.ts.map +1 -1
- package/dist/core/LoopDriver.js +3 -0
- package/dist/core/LoopDriver.js.map +1 -1
- package/dist/core/LoopLifecycle.sql +1 -0
- package/dist/core/MembershipMaterialization.d.ts.map +1 -1
- package/dist/core/MembershipMaterialization.js +87 -143
- package/dist/core/MembershipMaterialization.js.map +1 -1
- package/dist/core/MessageResources.sql +31 -0
- package/dist/core/MutationEffects.d.ts +2 -1
- package/dist/core/MutationEffects.d.ts.map +1 -1
- package/dist/core/MutationEffects.js +14 -1
- package/dist/core/MutationEffects.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts +2 -2
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +123 -51
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/PacketBuilder.sql +21 -14
- package/dist/core/PathGlob.d.ts +6 -0
- package/dist/core/PathGlob.d.ts.map +1 -0
- package/dist/core/PathGlob.js +24 -0
- package/dist/core/PathGlob.js.map +1 -0
- package/dist/core/ProposalLifecycle.d.ts +2 -1
- package/dist/core/ProposalLifecycle.d.ts.map +1 -1
- package/dist/core/ProposalLifecycle.js +45 -33
- package/dist/core/ProposalLifecycle.js.map +1 -1
- package/dist/core/ProposalLifecycle.sql +4 -0
- package/dist/core/ReplyMetadata.d.ts +10 -0
- package/dist/core/ReplyMetadata.d.ts.map +1 -0
- package/dist/core/ReplyMetadata.js +20 -0
- package/dist/core/ReplyMetadata.js.map +1 -0
- package/dist/core/ResourceBindings.d.ts.map +1 -1
- package/dist/core/ResourceBindings.js +4 -3
- package/dist/core/ResourceBindings.js.map +1 -1
- package/dist/core/ResourceSelector.d.ts +1 -2
- package/dist/core/ResourceSelector.d.ts.map +1 -1
- package/dist/core/ResourceSelector.js +30 -9
- package/dist/core/ResourceSelector.js.map +1 -1
- package/dist/core/ResourceTransfers.d.ts +1 -1
- package/dist/core/ResourceTransfers.d.ts.map +1 -1
- package/dist/core/ResourceTransfers.js +26 -11
- package/dist/core/ResourceTransfers.js.map +1 -1
- package/dist/core/ServiceHelp.d.ts +6 -0
- package/dist/core/ServiceHelp.d.ts.map +1 -0
- package/dist/core/ServiceHelp.js +35 -0
- package/dist/core/ServiceHelp.js.map +1 -0
- package/dist/core/StoredPacket.d.ts +1 -0
- package/dist/core/StoredPacket.d.ts.map +1 -1
- package/dist/core/StoredPacket.js +4 -1
- package/dist/core/StoredPacket.js.map +1 -1
- package/dist/core/StrikeRail.d.ts.map +1 -1
- package/dist/core/StrikeRail.js +2 -2
- package/dist/core/StrikeRail.js.map +1 -1
- package/dist/core/TokenCalibration.d.ts +2 -2
- package/dist/core/TokenCalibration.d.ts.map +1 -1
- package/dist/core/TokenCalibration.js +12 -16
- package/dist/core/TokenCalibration.js.map +1 -1
- package/dist/core/TokenCalibration.sql +29 -6
- package/dist/core/TurnDispositionHandler.d.ts +1 -2
- package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
- package/dist/core/TurnDispositionHandler.js +30 -26
- package/dist/core/TurnDispositionHandler.js.map +1 -1
- package/dist/core/TurnMaterialization.d.ts.map +1 -1
- package/dist/core/TurnMaterialization.js +11 -1
- package/dist/core/TurnMaterialization.js.map +1 -1
- package/dist/core/TurnOps.d.ts +5 -1
- package/dist/core/TurnOps.d.ts.map +1 -1
- package/dist/core/TurnOps.js +29 -2
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +122 -56
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/TurnSources.sql +2 -2
- package/dist/core/caps/SchemeCtxImpl.d.ts +1 -0
- package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.js +5 -0
- package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
- package/dist/core/git-membership.d.ts +1 -0
- package/dist/core/git-membership.d.ts.map +1 -1
- package/dist/core/git-membership.js +9 -11
- package/dist/core/git-membership.js.map +1 -1
- package/dist/core/glob_match.js +3 -3
- package/dist/core/glob_match.js.map +1 -1
- package/dist/core/mutation-types.d.ts +3 -0
- package/dist/core/mutation-types.d.ts.map +1 -1
- package/dist/core/namespace.d.ts +4 -1
- package/dist/core/namespace.d.ts.map +1 -1
- package/dist/core/namespace.js +14 -3
- package/dist/core/namespace.js.map +1 -1
- package/dist/core/packet-wire.d.ts +7 -1
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +98 -36
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/plurnk-uri.d.ts +3 -2
- package/dist/core/plurnk-uri.d.ts.map +1 -1
- package/dist/core/plurnk-uri.js +23 -11
- package/dist/core/plurnk-uri.js.map +1 -1
- package/dist/core/recap-lines.d.ts +4 -0
- package/dist/core/recap-lines.d.ts.map +1 -0
- package/dist/core/recap-lines.js +11 -0
- package/dist/core/recap-lines.js.map +1 -0
- package/dist/core/scheme-types.d.ts +1 -0
- package/dist/core/scheme-types.d.ts.map +1 -1
- package/dist/core/sql-functions.d.ts +2 -0
- package/dist/core/sql-functions.d.ts.map +1 -0
- package/dist/core/sql-functions.js +5 -0
- package/dist/core/sql-functions.js.map +1 -0
- package/dist/core/sqlite-synchronous.d.ts +2 -0
- package/dist/core/sqlite-synchronous.d.ts.map +1 -0
- package/dist/core/sqlite-synchronous.js +4 -0
- package/dist/core/sqlite-synchronous.js.map +1 -0
- package/dist/core/turn-scheduler.d.ts.map +1 -1
- package/dist/core/turn-scheduler.js +1 -1
- package/dist/core/turn-scheduler.js.map +1 -1
- package/dist/evidence/EvidenceReader.d.ts.map +1 -1
- package/dist/evidence/EvidenceReader.js +23 -3
- package/dist/evidence/EvidenceReader.js.map +1 -1
- package/dist/evidence/digest.sql +7 -1
- package/dist/man/plurnk-service.1 +499 -0
- package/dist/schemes/Env.d.ts +26 -0
- package/dist/schemes/Env.d.ts.map +1 -0
- package/dist/schemes/Env.js +133 -0
- package/dist/schemes/Env.js.map +1 -0
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +15 -15
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts +3 -2
- package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
- package/dist/schemes/ExecOutputScheme.js +9 -0
- package/dist/schemes/ExecOutputScheme.js.map +1 -1
- package/dist/schemes/File.d.ts +1 -0
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +233 -268
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +97 -17
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Log.sql +9 -0
- package/dist/schemes/Worker.js +1 -1
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.d.ts +2 -0
- package/dist/schemes/_entry-crud.d.ts.map +1 -1
- package/dist/schemes/_entry-crud.js +8 -5
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-crud.sql +15 -15
- package/dist/schemes/_entry-find.d.ts +2 -1
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +31 -19
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-manifest.d.ts +2 -2
- package/dist/schemes/_entry-manifest.d.ts.map +1 -1
- package/dist/schemes/_entry-manifest.js +10 -8
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/schemes/_entry-ops.d.ts.map +1 -1
- package/dist/schemes/_entry-ops.js +9 -7
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/schemes/_path-scope.d.ts.map +1 -1
- package/dist/schemes/_path-scope.js +12 -4
- package/dist/schemes/_path-scope.js.map +1 -1
- package/dist/schemes/_search-index.js +3 -3
- package/dist/schemes/_search-index.js.map +1 -1
- package/dist/schemes/exec-abort.js +2 -2
- package/dist/schemes/exec-abort.js.map +1 -1
- package/dist/schemes/exec-env.d.ts.map +1 -1
- package/dist/schemes/exec-env.js +7 -22
- package/dist/schemes/exec-env.js.map +1 -1
- package/dist/server/Daemon.d.ts +1 -0
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +45 -68
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DrainSupervisor.d.ts +2 -3
- package/dist/server/DrainSupervisor.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.js +34 -6
- package/dist/server/DrainSupervisor.js.map +1 -1
- package/dist/server/EnvFunctionality.d.ts +4 -2
- package/dist/server/EnvFunctionality.d.ts.map +1 -1
- package/dist/server/EnvFunctionality.js +23 -12
- package/dist/server/EnvFunctionality.js.map +1 -1
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js +15 -8
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/FunctionalityManager.d.ts +1 -1
- package/dist/server/FunctionalityManager.d.ts.map +1 -1
- package/dist/server/FunctionalityManager.js +5 -1
- package/dist/server/FunctionalityManager.js.map +1 -1
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js +12 -12
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/Retention.d.ts.map +1 -1
- package/dist/server/Retention.js +5 -5
- package/dist/server/Retention.js.map +1 -1
- package/dist/server/Retention.sql +49 -23
- package/dist/server/client-input.d.ts.map +1 -1
- package/dist/server/client-input.js +12 -3
- package/dist/server/client-input.js.map +1 -1
- package/dist/server/drain.sql +10 -9
- package/dist/server/lifecycle-recovery.sql +4 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +9 -31
- package/dist/service.js.map +1 -1
- package/docs/copy-move.md +3 -0
- package/docs/env.md +32 -4
- package/docs/members.md +16 -1
- package/migrations/018_worker_owners.sql +1 -0
- package/migrations/019_interactive_owners.sql +1 -0
- package/migrations/020_log_projection.sql +1 -0
- package/migrations/021_packet_roles.sql +86 -0
- package/migrations/022_message_completion.sql +24 -0
- package/migrations/023_file_revisions.sql +54 -0
- package/migrations/024_proposal_decisions.sql +34 -0
- package/migrations/025_response_retention.sql +30 -0
- package/package.json +38 -34
- package/dist/schemes/_derivation-use.d.ts.map +0 -1
- package/dist/schemes/_derivation-use.js.map +0 -1
package/SPEC.md
CHANGED
|
@@ -349,7 +349,7 @@ plus a broadcast duplicate. Runtime maintenance turns produce no broadcast ({§a
|
|
|
349
349
|
and remote resources do not acquire ambient attention merely because they are
|
|
350
350
|
workspace-addressable.
|
|
351
351
|
|
|
352
|
-
§actor-boundary-no-mutex
|
|
352
|
+
§actor-boundary-no-mutex Workers share workspace state without worker-owned locks or reservations. Coordination is cooperative; membership bounds their visible surface uniformly ({§machine-processes}). Stale writes reject at their anchor or commit boundary ({§line-anchors}, {§membership-edit-write-revision}). Internal storage serialization does not confer ownership: {§file-commit-serialization} holds no file across reasoning, operation selection, or approval.
|
|
353
353
|
|
|
354
354
|
§actor-boundary-passive-wake **Passive wake follows ownership.** A directed
|
|
355
355
|
voice wakes an idle worker. A parked continuation resumes when an obligation it
|
|
@@ -388,13 +388,14 @@ Maintenance turns create neither lineage nor commons broadcasts. Their loops are
|
|
|
388
388
|
|
|
389
389
|
§actor-boundary-catalog-preview **Catalog preview.** `PLURNK_SERVICE_FILES_ITEMS`
|
|
390
390
|
foists turn-0 discovery into the worker's first turn, so a worker opens with a
|
|
391
|
-
navigable map instead of blank. Its baseline
|
|
392
|
-
order; unregistered schemes contribute no survey, and workspace capabilities may
|
|
391
|
+
navigable map instead of blank. Its baseline surveys follow this
|
|
392
|
+
order: one READ of the program itself, then bodyless FINDs; unregistered schemes contribute no survey, and workspace capabilities may
|
|
393
393
|
narrow or omit the reference catalogs under {§capability-admission}.
|
|
394
394
|
|
|
395
|
-
| Surface |
|
|
395
|
+
| Surface | Target | Scope / aside |
|
|
396
396
|
| --- | --- | --- |
|
|
397
|
-
|
|
|
397
|
+
| This program | READ `ops://<worker>/<loop>/1` | `this program`; the log carries one program verbatim, and every `ops://` turn is shown readable ({§turn-source-resources}) |
|
|
398
|
+
| Agent Skills | FIND `skill://*/SKILL.md` | `<1,-1>`; {§skills-resources} |
|
|
398
399
|
| Plurnk references: executors, schemes, family managers | `worker:///_plurnk/plurnk/*.md` | `<1,-1>` |
|
|
399
400
|
| Enabled tools | `worker:///_plurnk/tools/*.md` | `<1,-1>`; configured expansions follow under {§tools-resource-materialization} |
|
|
400
401
|
| Enabled agents | `worker:///_plurnk/a2a/*.md` | `<1,-1>`; {§a2a-catalog} |
|
|
@@ -421,7 +422,7 @@ direct-entry-plus-directory count; `-1` enables the ordinary markerless page;
|
|
|
421
422
|
unset / `0` disables previews. `log://` is absent because the current worker's
|
|
422
423
|
log already renders in present mode.
|
|
423
424
|
|
|
424
|
-
§worker-initialization-entry **Model-worker initialization is a real `_plurnk` operation turn.** A model worker's first loop begins with one packetless `{ producer="_plurnk", kind="initialization" }` turn submitted through {§turn-ops-admission-path}. Its program — the READ/FIND surveys,
|
|
425
|
+
§worker-initialization-entry **Model-worker initialization is a real `_plurnk` operation turn.** A model worker's first loop begins with one packetless `{ producer="_plurnk", kind="initialization" }` turn submitted through {§turn-ops-admission-path}. Its program — the READ/FIND surveys, led by one NOTE when the surveys run — is recorded as the turn's `ops://` source and executed through {§op-execution-order} exactly as a model's program is; it authors no reasoning and reads none back. The NOTE keeps the example turn within the card's NOTE-per-turn teaching: it carries the aside of the card's first NOTE example, `<!-- summary -->`, and reads, exactly, `Surveyed tooling, documentation, extended context, and project root.` No emission row is fabricated ({§emission-row}): the first request sees the NOTE and the surveys' ordinary results, never an assistant-content copy of the program. The initial message arrives as an inbound SEND in the first model turn ({§message-arrival}); initialization never READs it, and neither initialization nor later turns manufacture a task inventory. Every orienting row is structurally classified `_plurnk` and `init`. The namespace surveys and their asides follow {§actor-boundary-catalog-preview}.
|
|
425
426
|
|
|
426
427
|
Incoming messages publish once as inbound SEND rows in the first model turn
|
|
427
428
|
({§message-arrival}); initialization neither READs nor archives them. The turn
|
|
@@ -621,7 +622,7 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
|
|
|
621
622
|
holds under the teaching's own word for handing work out: `## Delegation` is
|
|
622
623
|
one JSON object, `{"workers": [...], "streams": [...]}`, its unconcluded child
|
|
623
624
|
workers and its open streams as `{status, path}` pointers (the same shape as
|
|
624
|
-
the errors section)
|
|
625
|
+
the errors section). Body-suppressed child activity is durable
|
|
625
626
|
history; this section is the current inventory that keeps an active obligation
|
|
626
627
|
visible even when no new activity arrived. Each open stream pointer carries
|
|
627
628
|
elapsed runtime, output inactivity, and its channels' sizes and growth since
|
|
@@ -649,7 +650,7 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
|
|
|
649
650
|
`## Worker` identity block carries `"parent": "worker://<name>"`, or
|
|
650
651
|
`"parent": null` at a root, so a worker never infers its rank from silence.
|
|
651
652
|
- §packet-current-turn **The packet says who and which turn, below the log.** The
|
|
652
|
-
`## Worker` block
|
|
653
|
+
`## Worker` block, in the status clump below the log ({§packet-cache-monotone}), carries
|
|
653
654
|
`{"path": "worker://<name>", "parent": <address or null>, "loop": L, "turn": T}`: the actor,
|
|
654
655
|
whose child it is, and the coordinate this packet's response becomes, so `reasoning://<worker>/L/T`
|
|
655
656
|
and `ops://<worker>/L/T` are the model's own and `log:///L/T/*` its rows; a model never infers the
|
|
@@ -676,7 +677,7 @@ flowchart LR
|
|
|
676
677
|
materialize --> read["READ snapshot"]
|
|
677
678
|
materialize --> edit["EDIT against snapshot"]
|
|
678
679
|
edit --> proposal["Proposal"]
|
|
679
|
-
proposal -->|"client accepts or loop auto"| cas["
|
|
680
|
+
proposal -->|"client accepts or loop auto"| cas["Validate captured file revision"]
|
|
680
681
|
cas -->|"file snapshot → disk"| project["Project file"]
|
|
681
682
|
project --> materialize
|
|
682
683
|
```
|
|
@@ -760,18 +761,18 @@ and never re-fetch a match.
|
|
|
760
761
|
`engine:membership` / `git_inspection_refused` notice names the key, once per
|
|
761
762
|
workspace until it changes or clears. User- and model-requested Git commands
|
|
762
763
|
stay on their explicit execution path.
|
|
763
|
-
- §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
|
|
764
|
+
- §membership-edit-membership-gate **Membership-gated edits.** EDIT is bounded by membership exactly as READ is. An existing **member**'s baseline is its materialized entry snapshot, not an empty body or a fresh disk read at approval ({§membership-edit-write-revision}). An existing **non-member** is refused (403) *before* any content read or write: its bytes never leak into the proposal. A **new path** crosses the creation matrix in {§fs-write-surface}; proposal acceptance cannot bypass its scope, exclusion, or incorporation rules. Shell execution reaches beyond file membership; the file scheme does not.
|
|
764
765
|
- §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.
|
|
765
766
|
|
|
766
767
|
**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`.
|
|
767
768
|
|
|
768
769
|
- §membership-auto-add **Auto-add** — the project repository's ambient membership is its tracked `ls-files`, with `git` origin; an untracked file is never an ambient member ({§membership-baseline}). An accepted creation is incorporated by an exact creation record, never by `git add` ({§membership-model-universe}); a record that cannot be written fails the creation transaction, never an orphan ({§file-create-no-orphans}).
|
|
769
770
|
- §membership-overlay-include **`include`** — admit a file Git misses through a targeted pattern scan (files only), with `constraint` origin. `source: "members"` is a projected human definition, `source: "model"` a projected model definition, `source: "create"` the exact durable record of an accepted creation. Only `members` inclusions override active Git ignore. In a Git-absent root, inclusions are the sole file-membership source.
|
|
770
|
-
- §membership-overlay-exclude **`exclude`** — a `!glob` definition removes a tracked or included file: resolution drops matches (
|
|
771
|
+
- §membership-overlay-exclude **`exclude`** — a `!glob` definition removes a tracked or included file: resolution drops matches ({§path-glob-matching}) and reconciles so the entry set *equals* the member set. The lever to exclude a committed-but-oversized or sensitive tracked file; exclusions mask creation records without deleting their provenance ({§fs-create-masked}).
|
|
771
772
|
- §membership-reconcile-sets **Reconciliation is two set statements.** Once the desired set is composed — `(git ls-files ∪ include) − exclude`, glob evaluation and Git shell-outs being the process's own — it lands as one `INSERT … SELECT FROM json_each` with the same idempotent provenance update as a single registration, and every overlay-owned member outside it leaves in one `DELETE … WHERE pathname NOT IN (json_each) RETURNING`, its prior body riding out of the statement. A path that also left disk truth (no longer a candidate at all) becomes a divergence from that prior content; an exclusion is silent. No per-path statement, no set difference outside the database.
|
|
772
|
-
- §membership-glob-in-sql **A constraint is evaluated where it lives.** `glob_match(pathname, glob)`
|
|
773
|
+
- §membership-glob-in-sql **A constraint is evaluated where it lives.** `glob_match(pathname, glob)` exposes {§path-glob-matching} to SQLite (`src/core/glob_match.ts`, deterministic), the same matcher every overlay decision uses, so a lookup that asks the constraints table a question — which exclusion covers this key, whether a members definition includes it, which inclusion owns each untracked path — is one statement over `workspace_constraints`, never a listing filtered in the process. Transient inputs the process already holds (a `git ls-files` listing against the exclude globs) stay filtered in the process; the function exists so the database's own rows can be asked, not so process data makes a round trip.
|
|
773
774
|
|
|
774
|
-
**File ops act on the entry, not the disk; the two reconcile
|
|
775
|
+
**File ops act on the entry, not the disk; the two reconcile at gates.** A `file:///` member's body is its materialized model-readable snapshot. READ returns that channel; EDIT computes against it, not a newly read replacement. Pre-turn materialization acquires disk state; accepted write-back validates the captured revision before changing disk ({§proposal}, {§membership-edit-write-revision}).
|
|
775
776
|
|
|
776
777
|
§membership-source-projection Binary acquisition is transient and bounded by
|
|
777
778
|
{§mimetype-binary-input}; durable entry channels remain Unicode text. Core-private
|
|
@@ -794,10 +795,12 @@ with an empty body channel carrying a durable 413 producer result; no diagnostic
|
|
|
794
795
|
sentinel impersonates file content. READ therefore names the path, observed bytes,
|
|
795
796
|
ceiling, and recovery through the ordinary result contract, while EDIT returns the
|
|
796
797
|
same 413 instead of diffing against a fictitious empty baseline. Core records the
|
|
797
|
-
materialization disposition and ceiling privately
|
|
798
|
-
reconsidered when the
|
|
799
|
-
|
|
798
|
+
materialization disposition and ceiling privately; an unchanged oversized marker
|
|
799
|
+
is reconsidered when the policy changes and otherwise remains stat-gated.
|
|
800
|
+
Ordinary members follow {§membership-change-gated-sync}.
|
|
801
|
+
The file write gate independently stats the source against the same ceiling,
|
|
800
802
|
so safety does not depend on a background warm winning a client-operation race.
|
|
803
|
+
Whole-file deletion does not need a materialized body ({§file-delete-revision}).
|
|
801
804
|
|
|
802
805
|
§derivation-dedup-parallel **The index dedups then parallelizes.** The derivation identity hashes the exact READ channel representation, mimetype, reader behavior, and applicable search exclusion. A channel or log projection attaches the immutable artifact only after it is complete; identical projections therefore share one FTS row and one symbol graph without copying, and the FTS index reads its text from the content store ({§content-store}) instead of keeping a copy. The identity hashes the representation's own SHA-256 ({§tokenomics-content-hash-identity}), never its body, so a maintenance pass judges an entry channel from its stored `content_hash` without the body crossing into the process; a body is acquired only for a derivation that runs, under that same identity (a representation that moved on since it was judged returns nothing and is judged again next pass), or for a channel with no stored identity, an open or streamed channel, which must be read to be judged. Log rows and turn sources still arrive whole. The pass reports the bytes it acquired beside the derivations it ran, and an unchanged workspace acquires none of its channel bodies at any concurrency. Distinct artifacts run with bounded producer concurrency (`PLURNK_SERVICE_DERIVE_CONCURRENCY`). Pending artifacts sort by readable content length before entering that pool, so small resources start first while every outlier still derives fully. Unset uses a host-relative square-root fan-out; a positive integer is an exact operator budget and `-1` claims every core. Graph persistence writes at most `PLURNK_SERVICE_DERIVE_STORE_BATCH` definitions or references per SQLite statement. Every launched worker settles before the maintenance pass reports success or failure, so one failed artifact cannot orphan sibling derivations. Every representation completed by a successful pass attaches a terminal classified artifact, identically at concurrency 1 and N. A changed pass emits one immediate `preparing` state, intermediate `indexing` heartbeats at `PLURNK_SERVICE_DERIVE_PROGRESS_HEARTBEAT_MS`, and one immediate `complete` or `failed` state. A no-op pass emits no lifecycle, an indexing heartbeat never claims 100%, and the model-facing Notice buffer retains only the current derivation state while live clients observe each heartbeat.
|
|
803
806
|
|
|
@@ -835,15 +838,29 @@ with their reasons. Successful optional projection degradations continue indexin
|
|
|
835
838
|
and surface their framework Notice once per identical observation in a maintenance
|
|
836
839
|
pass.
|
|
837
840
|
|
|
838
|
-
§membership-change-gated-sync **
|
|
841
|
+
§membership-change-gated-sync **Projection is idempotent and change-gated.** Membership checks every member's physical identity and raw-byte digest within the materialization ceiling; timestamps alone never establish content identity. Unchanged source revision and policy avoid projection and database publication. Binary projections also compare their reader identity. Input-limited markers remain stat-gated because they expose no acquired body. An acquisition whose observed file identity or metadata changes is discarded and retried on the next pass. An observed absence removes stale channels and records `absent`; reappearance is a divergence, not first sight. This is observed state subject to {§file-external-race}, not an instantaneous snapshot of a concurrently changing project.
|
|
839
842
|
|
|
840
|
-
§membership-emi-divergence-signal **EMI divergence evidence.** The
|
|
843
|
+
§membership-emi-divergence-signal **EMI divergence evidence.** The materialization pass records observed source changes as an `EDIT`-shaped row naming the file with `source="file"`; it does not broadcast them into unrelated workers' logs ({§env-delta-filesystem-narration}). A native write publishes its own projection and revision, so unchanged landed bytes are not narrated as external divergence. Later external changes remain independently detectable. A stale anchored edit rejects under {§line-anchors}; write-back protection and its external race limit are defined by {§membership-edit-write-revision} and {§file-external-race}.
|
|
841
844
|
|
|
842
|
-
§membership-edit-write-
|
|
845
|
+
§membership-edit-write-revision **File write-back is conditional on its captured revision.** EDIT computes against the materialized text; COPY/MOVE mutations retain the revision of the state they selected. Approval never substitutes a newer baseline. Immediately before publication, physical identity and exact content must still match; otherwise the operation returns `edit-collision` (409) without changing the target. A member without a recorded source revision must be materialized before mutation, not treated as permission to overwrite. New-path publication is exclusive. Anchors separately protect the addressed text neighborhood before proposal ({§line-anchors}); an unanchored edit does not claim to preserve an earlier READ's view.
|
|
843
846
|
|
|
844
|
-
|
|
847
|
+
§file-snapshot-revision A materialized source revision records its physical path, filesystem identity/change fingerprint and raw-byte digest, distinct from the derived readable body. Its revision and channels publish in one database statement. An input-limited marker has no acquired digest; it cannot authorize a content replacement. Successful writes stamp the revision acquired from their own bytes, never a later pathname stat. Unversioned projections are rematerialized, including those retained through an upgrade.
|
|
845
848
|
|
|
846
|
-
|
|
849
|
+
§file-commit-serialization Final validation, publication/deletion, and projection settlement are serialized per physical path within one daemon, across workers and workspaces. Unrelated paths remain concurrent. No reservation survives a commit, and no lock is held awaiting model inference, approval, or MIME projection. Membership acquires and projects outside this boundary, then revalidates its source inside it before publishing; an older projection cannot overwrite a newer daemon write.
|
|
850
|
+
|
|
851
|
+
§file-publication A native file write stages complete bytes beside the target, then publishes them atomically; failures before publication leave the original intact. Creation never replaces an occupied name. Existing-file replacement preserves permission bits and ownership, but replaces the inode: other hard-link names and already-open descriptors retain their previous file. Inode-specific extended attributes are not a promised projection. The file/directory operations and SQLite commit are not one transaction or a filesystem power-loss durability guarantee. If publication succeeds but incorporation/projection fails, the result identifies that partial effect; it never claims nothing happened.
|
|
852
|
+
|
|
853
|
+
§file-delete-revision KILL and MOVE source removal validate the captured source revision immediately before unlinking or editing. Whole-file KILL of an input-limited member acquires a streaming digest before proposal without materializing its body. Deferred MOVE retains its original source selection through destination approval. A changed source is preserved; a destination already written remains reported under {§move-cross-scheme-move}. Creation rollback may remove only the unchanged file that creation published; a changed or replaced path is retained and reported as incomplete rollback.
|
|
854
|
+
|
|
855
|
+
§file-external-race The file boundary is optimistic with respect to external programs, executors and other daemons. Portable filesystem APIs provide no atomic expected-content-and-replace/unlink primitive. Plurnk detects drift through its final validation, but cannot exclude a writer racing after that check. It neither advertises such exclusion nor silently merges changed files. Physical-path revalidation prevents a changed symlink from redirecting an approved operation to a different target, subject to the same external race limit.
|
|
856
|
+
|
|
857
|
+
| Commit boundary | Filesystem effect | Result and settlement |
|
|
858
|
+
| --- | --- | --- |
|
|
859
|
+
| Unknown baseline or observed drift | No mutation | 409; refresh and prepare again ({§membership-edit-write-revision}). |
|
|
860
|
+
| Staging or prepublication I/O failure | Original target remains intact | Failure; retain cleanup failures too ({§file-publication}). |
|
|
861
|
+
| Existing file published; projection fails | Complete replacement remains | Failure identifies the update; ordinary reconciliation reads disk truth ({§file-publication}). |
|
|
862
|
+
| New file published; incorporation fails | Remove only the unchanged creation | Report rollback, or partial failure if another writer changed it or cleanup fails ({§file-delete-revision}). |
|
|
863
|
+
| MOVE destination published; source changed | Keep destination and changed source | Conflict identifies the completed destination effect ({§move-cross-scheme-move}). |
|
|
847
864
|
|
|
848
865
|
§membership-git-flags **Permission flags.** Service-wide Git admission comes from {§operator-config-git-ceiling}. `PLURNK_SERVICE_GIT_AUTO=1` includes the repository containing `project_root`; `=0` disables automatic Git membership, leaving member definitions as the only membership source. `ALLOWED` gates `AUTO`.
|
|
849
866
|
|
|
@@ -885,7 +902,7 @@ all use that one definition.
|
|
|
885
902
|
|
|
886
903
|
With live work—an open stream or a live child worker—the loop parks until an
|
|
887
904
|
ordinary wake or its maximum wait elapses. `PLURNK_SERVICE_WAIT_SEC` supplies the
|
|
888
|
-
bound; `WAIT
|
|
905
|
+
bound; `WAIT [seconds]` overrides that one park ({§send-wait-scope}). The wake time
|
|
889
906
|
commits atomically with the wait revision, rounded up to the next millisecond.
|
|
890
907
|
Expiry queues the same loop through normal worker/provider admission; it never
|
|
891
908
|
cancels work or fabricates a result.
|
|
@@ -974,7 +991,7 @@ never replay interrupted effects to reconstruct time. Future messages use
|
|
|
974
991
|
the separate schedule contract ({§schedule-delivery}).
|
|
975
992
|
|
|
976
993
|
§worker-message-admission **Recipient selection and admission are one decision.**
|
|
977
|
-
An arrival to a worker selects its running loop, otherwise its oldest parked
|
|
994
|
+
An unaddressed arrival to a worker selects its running loop, otherwise its oldest parked
|
|
978
995
|
loop, otherwise a new queued loop. Compatibility is checked against the exact
|
|
979
996
|
loop that receives the message; the writer does not reselect another recipient.
|
|
980
997
|
The worker's admission lock covers selection, compatibility, message admission,
|
|
@@ -989,6 +1006,15 @@ atomically; no drain may claim partially configured work.
|
|
|
989
1006
|
| Cancelled as part of the worker scope | Preserve the frame as evidence; never promote it into executable work, including after restart. |
|
|
990
1007
|
| Explicit new arrival after cancellation | Admit under ordinary current worker policy; never revive a terminal loop. |
|
|
991
1008
|
|
|
1009
|
+
§loop-addressed-admission **An explicit Loop recipient never falls back to new work.**
|
|
1010
|
+
`runLoop` may name `loopId` alongside its owning `workerId`. Selection requires that
|
|
1011
|
+
exact Loop to belong to the Worker and remain queued, running or parked. The inbox
|
|
1012
|
+
insert atomically requires the recipient to remain unfinished; completion winning
|
|
1013
|
+
that race leaves the message unadmitted. Missing, foreign or terminal recipients
|
|
1014
|
+
produce `409 daemon/admission/loop-not-open`, without creating another Loop or
|
|
1015
|
+
delivering to a different one. Compatibility checks and wake behavior are the same
|
|
1016
|
+
as ordinary Worker delivery. This is address selection, not a lifecycle policy.
|
|
1017
|
+
|
|
992
1018
|
§stream-catalog-lifecycle Streams are independently durable subscriptions owned by a worker. Payload and
|
|
993
1019
|
lifecycle are orthogonal: zero bytes is a valid payload for both success and
|
|
994
1020
|
failure, while the closed subscription and its status are the terminal fact.
|
|
@@ -1094,8 +1120,8 @@ whose obligations settled during reconciliation is requeued in place so it can
|
|
|
1094
1120
|
observe their terminal results. No effect is replayed across an unknown
|
|
1095
1121
|
boundary.
|
|
1096
1122
|
|
|
1097
|
-
- §worker-lifecycle-single-drain **One drain advances a worker.** At most one drain is registered for a worker at any instant: a `runLoop` request or wake on a worker with a live drain folds in (active→next-turn) or enqueues a loop that drain claims, never a second parallel drain. A drain's start and its empty-queue teardown relinquish the worker under one per-worker lock, so the teardown's re-claim cannot race a concurrent start into a double-drain. Fresh-loop sequence allocation and insertion are one mutation under that same lock;
|
|
1098
|
-
- §worker-lifecycle-total-reap **Cancellation is recursive and reaps every held stream.** `loop.cancel` and worker `KILL` terminalize every unresolved loop in the cancelled worker subtree and iterate each worker's durable open-subscription rows, invoking each exact callable owner from the process-local live registry. The durable rows answer *what is held*; the live registry answers *how this process tears it down*; the abort signal is a fast-path optimization. There is no implicit detachment. Shutdown reaps process-local streams while preserving parked work under {§worker-lifecycle-durable-disposition}. Before shutdown awaits drains, it cancels every process-local proposal waiter through {§proposal-cancel-aborts} with outcome `daemon_stopping`, so a stopped-world dispatch cannot hold teardown open. A stream that is running, mid-spawn (its row written before it is killable), or spawned after the cancel is reaped alike. The teardown abort is bounded: the executor sends a polite signal then SIGKILL after a consumer-set grace (`PLURNK_SERVICE_EXEC_KILL_GRACE_MS`). A model ```` ```KILL [code] ```` on one live stream instead delivers exactly that signal once (
|
|
1123
|
+
- §worker-lifecycle-single-drain **One drain advances a worker.** At most one drain is registered for a worker at any instant: a `runLoop` request or wake on a worker with a live drain folds in (active→next-turn) or enqueues a loop that drain claims, never a second parallel drain. A drain's start and its empty-queue teardown relinquish the worker under one per-worker lock, so the teardown's re-claim cannot race a concurrent start into a double-drain. Fresh-loop sequence allocation and insertion are one mutation under that same lock; fresh loops receive distinct increasing sequence numbers. Recipient selection follows {§worker-message-admission}, not whether callers started concurrently.
|
|
1124
|
+
- §worker-lifecycle-total-reap **Cancellation is recursive and reaps every held stream.** `loop.cancel` and worker `KILL` terminalize every unresolved loop in the cancelled worker subtree and iterate each worker's durable open-subscription rows, invoking each exact callable owner from the process-local live registry. The durable rows answer *what is held*; the live registry answers *how this process tears it down*; the abort signal is a fast-path optimization. There is no implicit detachment. Shutdown reaps process-local streams while preserving parked work under {§worker-lifecycle-durable-disposition}. Before shutdown awaits drains, it cancels every process-local proposal waiter through {§proposal-cancel-aborts} with outcome `daemon_stopping`, so a stopped-world dispatch cannot hold teardown open. A stream that is running, mid-spawn (its row written before it is killable), or spawned after the cancel is reaped alike. The teardown abort is bounded: the executor sends a polite signal then SIGKILL after a consumer-set grace (`PLURNK_SERVICE_EXEC_KILL_GRACE_MS`). A model ```` ```KILL (sh:///stream) [code] ```` on one live stream instead delivers exactly that signal once (without a signal override it uses the executor's SIGHUP default; `[9]` uses SIGKILL).
|
|
1099
1125
|
- §worker-lifecycle-exec-epoch-bound **A stream's kill binds to the scope it captured at spawn.** A stream captures the worker's cancellation scope as it registers and wires its kill to it, re-checking `aborted` AFTER wiring — no check-then-listen gap can drop an abort that lands mid-registration. Because the scope is replaced only once aborted, a captured-then-replaced scope is necessarily already aborted, so replacement never strands a live stream.
|
|
1100
1126
|
- §worker-lifecycle-no-resurrection **Cancelled work does not revive its scope.** A cancelled worker cannot be woken by its torn-down streams, stale timers, or cancelled unpublished messages. The evidence remains readable. A `499` result from cancelling only one stream is still a completion owed to a live waiting worker: result status is not proof of worker cancellation. Only an explicit new arrival admits new work after scope cancellation; terminal loops themselves remain immutable.
|
|
1101
1127
|
- §worker-cancel-trigger **A cancellation is one bound statement.** `lifecycle_cancel_workers` writes the causal cutoff and the cancellation Problem onto every worker of the scope; `workers_cancel_live_loops` (an `INIT` process trigger beside the lifecycle statements, {§db-process-triggers}) retires each worker's live loops inside that statement — 499, waits cleared, message evidence left unchanged, the Problem instanced `loop://<worker>/<sequence>`, `terminated_by = 'cancel'` — so cutoff and cancellation cannot land apart and no value is string-interpolated. Execution consumption is measured by the process-local monotonic timers ({§loop-execution-allowance}) and lands first through `lifecycle_checkpoint_executions`; a wall clock cannot stand in for it, so the timer stays outside the database by design.
|
|
@@ -1112,7 +1138,7 @@ boundary.
|
|
|
1112
1138
|
- §worker-lifecycle-wake-liveness **A stream conclusion always reaches its worker.** The stream first persists its terminal state. A worker **blocked on a 202 wait** for that stream ({§wait-obligation-matrix}) then **awakens that loop in place** — the blocked loop *is* the continuation. An already-active worker's next packet reads the durable terminal state. Ambient stream closure starts no loop for a concluded worker. The result remains available in the stream's own state under every case.
|
|
1113
1139
|
- §worker-lifecycle-child-wake **Each child task completion notifies its parent.** Terminal-task publication, including failure and cancellation of a parked task, notifies the direct parent without injecting a prompt. Other unfinished tasks or streams in that child remain independent obligations; they cannot suppress notification. The parent's eligible waits requeue in place under {§loop-wake-identity} and the bounded {§worker-optimistic-settlement} opportunity. Durable revisioning covers completion-before-park and restart; drain teardown and whole-worker quiescence are not completion identities.
|
|
1114
1140
|
- §worker-optimistic-settlement **Asynchronous settlement receives one bounded worker-local opportunity before model dispatch.** An initiating turn lets only the streams it started settle before program completion; separately, a stream conclusion, direct-child conclusion or addressed reply persists and publishes immediately but holds eligible parked loops' `202→100` requeues while another stream or direct child remains live. Both use `PLURNK_SERVICE_OPTIMISTIC_WAIT_MS`, shipped at five seconds; zero disables the opportunity. The wake hold ends as soon as no sibling obligation remains, never extends its original deadline, and coalesces arrivals within that window into at most one requeue per eligible loop. With no sibling obligation the wake is immediate; at the deadline, surviving work follows the ordinary monitored lifecycle. An arrival after provider dispatch begins retains its next wake, while poll, new-request and operator wakes never open this hold. Only packet/provider dispatch waits: durable state, client events, cancellation and the replying program do not. One redaction-safe span records elapsed time, quiescence versus deadline, and arrival count without entering the packet.
|
|
1115
|
-
- §worker-lifecycle-idle-is-concluded **Idle is not completion.**
|
|
1141
|
+
- §worker-lifecycle-idle-is-concluded **Idle is not completion.** A loop concludes only under {§loop-completion}; an unanswered message remains an obligation even when nothing is running. A concluded worker retains durable history; a later addressed arrival starts a new loop.
|
|
1116
1142
|
- §worker-lifecycle-no-lost-loop **A loop is never stranded by a drain's exit.** A drain relinquishes its registry slot only after a lock-held re-claim confirms the queue is empty; a loop enqueued during that teardown is either re-claimed by the exiting drain or claimed by a fresh drain that a later inject starts. The relinquish and the start are serialized, so neither the lost-loop hang nor a transient double-drain can occur.
|
|
1117
1143
|
- §worker-lifecycle-durable-disposition **Durable disposition wins cancellation races.** At a turn boundary, the engine reads the loop's durable status before interpreting a process-local abort. A committed `202` park survives a later daemon-shutdown signal; only a loop still durably running at `102` can be terminalized by that cancellation. Wake selection rechecks shutdown and worker cancellation before requeuing each parked loop.
|
|
1118
1144
|
- §worker-lifecycle-restart-recovery **Restart is owner-loss reconciliation, not replay.** Before opening client transports, the service holds an exclusive database-adjacent daemon lock; a second live owner fails before touching SQLite, while a dead-PID crash claim is replaced atomically without a timeout lease. Boot preserves accepted `100` loops and restores their drains. A `102` loop belonged to a vanished drain/provider call, so it settles `500` with the interruption on its durable row—never replayed across an unknown effect boundary. Every pending physical provider request first settles as an error with absent usage and explicitly unknown cost; then its logical model call closes. Recovery never fabricates zero evidence. Every durable proposed operation likewise lost its process-local resolution waiter and settles as a visible `500 owner_vanished` occurrence rather than an unresolvable interrupt ({§proposal-list}). A pending client interaction also lost its exact awaiting operation, so boot removes the orphan instead of replaying work or inventing a response ({§client-interactions}). Every durable-open subscription belonged to a vanished callable: active channels become errored and its row closes `500`. A `202` continuation requeues on an unseen completion or when no live obligation remains. Otherwise it stays parked on surviving children; the drain restores inherited stream observation through the same guarded scheduler ({§worker-wait-timing}). Child terminalization wakes its parked parent on every outcome, including provider exceptions, cancellation, and restart interruption, recursively through the durable parent edges. These operations are idempotent, so an interrupted recovery safely repeats.
|
|
@@ -1190,7 +1216,7 @@ These are the complete strike sources:
|
|
|
1190
1216
|
|---------------------|------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|
|
|
1191
1217
|
| Hard result | An admitted non-execution operation or bounded parse-error status is `>= 400`, except the soft set `404`, `409`, `416`, `425`, `501`, in a turn where no operation succeeded ({§strike-progress-immunity}). | The originating failure row. |
|
|
1192
1218
|
| Cycle | The executed operations and their observed results repeat under {§engine-cycle-evidence}. | None; cycle detection itself is private engine accounting. |
|
|
1193
|
-
| Empty turn | An
|
|
1219
|
+
| Empty turn | An operation-free turn with unresolved messages or incomplete emission evidence ({§empty-turn}). | The turn's `422` error row. |
|
|
1194
1220
|
|
|
1195
1221
|
Execution results remain exact model-visible evidence but are always soft: an
|
|
1196
1222
|
executor error is not a PLURNK contract violation. Cycle detection remains an
|
|
@@ -1250,7 +1276,7 @@ failures keep their exact rows, but the turn counts as progress — it earns no
|
|
|
1250
1276
|
and clears the streak. A successful operation is any admitted operation that acts on the
|
|
1251
1277
|
task — executions included — whose result status is `< 400`. Operations that steer the
|
|
1252
1278
|
loop never qualify: NOTE (it cannot fail; reasoning NOTEs are filed as NOTEs, and outside
|
|
1253
|
-
text is no operation at all, {§outside-text}), WAIT
|
|
1279
|
+
text is no operation at all, {§outside-text}), WAIT and a targetless SEND; a turn
|
|
1254
1280
|
of failures beside a WAIT still strikes. The cycle source is not exempted: a repeating
|
|
1255
1281
|
turn's operations succeed by construction, and the backstop exists to catch exactly
|
|
1256
1282
|
that ({§engine-cycle-evidence}).
|
|
@@ -1354,7 +1380,7 @@ The parser owns its boundaries; core admits determinate work and exposes its fai
|
|
|
1354
1380
|
| Lost boundary before any closed operation | Reject the attempt; outside text is no substitute for a closed operational statement. An admitted reasoning operation is one ({§reasoning-operations}). |
|
|
1355
1381
|
| Outside text carrying a log-entry heading, other than an emission row's | Reject the attempt ({§fabricated-log-entry}). |
|
|
1356
1382
|
|
|
1357
|
-
§fabricated-log-entry **Only the harness writes the log.** A line of outside response text that begins with a log-entry heading, `### log:///<loop>/<turn>/<sequence>/` ({§log-wire-format}), is the model continuing the packet's transcript instead of answering it: it writes the receipts it expects and then acts on them. The attempt is rejected under {§invalid-emission-attempts}, so neither that text nor any operation beside it runs or is stored as outside text ({§outside-text}), and its one diagnostic, at the heading's line, reads `` `### log:///2/1/5/READ` is a log entry, and only the harness writes the log. `` Text inside an operation body is not examined, so a SEND or KILL may quote a receipt. A heading whose leaf is `emission` is exempt: it names the worker's own source ({§emission-row}), and repeating it invents no receipt, so the attempt is admitted and the heading
|
|
1383
|
+
§fabricated-log-entry **Only the harness writes the log.** A line of outside response text that begins with a log-entry heading, `### log:///<loop>/<turn>/<sequence>/` ({§log-wire-format}), is the model continuing the packet's transcript instead of answering it: it writes the receipts it expects and then acts on them. The attempt is rejected under {§invalid-emission-attempts}, so neither that text nor any operation beside it runs or is stored as outside text ({§outside-text}), and its one diagnostic, at the heading's line, reads `` `### log:///2/1/5/READ` is a log entry, and only the harness writes the log. `` Text inside an operation body is not examined, so a SEND or KILL may quote a receipt. A heading whose leaf is `emission` is exempt: it names the worker's own source ({§emission-row}), and repeating it invents no receipt, so the attempt is admitted and the heading is dropped from the text beside the operations ({§outside-text}), counted by the digest as an echo. In 10,486 recorded emissions, 101 carried such a heading in outside text, every one a fabrication: 85 of 1,675 from deepseek-flash, 81 of them opening with one, and 16 from glm-5.3-flash, deepseek-v4-pro and qwen3.8-flash, which appended an invented `## Log` after their own operations.
|
|
1358
1384
|
|
|
1359
1385
|
Warnings and closer recovery ({§closer-fallback}) do not reject. `finish=length`
|
|
1360
1386
|
discloses truncation and precludes completion; it is not independently a rejection.
|
|
@@ -1457,10 +1483,9 @@ unrelated suffixes.
|
|
|
1457
1483
|
does nothing with it (#588).** `PLURNK_PROVIDERS_GBNF[_<alias>]` is a file
|
|
1458
1484
|
path — absolute, `~`-relative, or relative to the daemon's working directory —
|
|
1459
1485
|
whose text is read once per daemon and handed to the provider verbatim
|
|
1460
|
-
({§provider-grammar-transport}).
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
becomes unconstrained. Nothing generates, validates, or grades a grammar, and
|
|
1486
|
+
({§provider-grammar-transport}). A filename without a path separator is relative
|
|
1487
|
+
to the daemon's working directory too. An unreadable file fails the constrained
|
|
1488
|
+
generation; it never silently becomes unconstrained. Nothing generates, validates, or grades a grammar, and
|
|
1464
1489
|
no effort is implied by one. The turn records transport as evidence:
|
|
1465
1490
|
`railsAttached: "client"` when the provider reports it sent the grammar, or
|
|
1466
1491
|
`"withheld"` when it reports it did not ({§provider-grammar-evidence}); there
|
|
@@ -1546,16 +1571,30 @@ historical execution. No address grants ownership or access restrictions.
|
|
|
1546
1571
|
| `src/x.md`, `./src/x.md`, `/work/project/src/x.md` | `src/x.md` |
|
|
1547
1572
|
| `/src/x.md` | `../../src/x.md` |
|
|
1548
1573
|
| `../policy.md`, `/work/policy.md` | `../policy.md` |
|
|
1574
|
+
| `~/x.md` (daemon home `/home/user`) | `../../home/user/x.md` |
|
|
1575
|
+
| `./~/x.md` | Key `~/x.md`, addressed as `./~/x.md` |
|
|
1549
1576
|
| `.`, `/work/project/` | The project collection, not a file entry |
|
|
1550
1577
|
| `/` | `../../`, the operating-system root collection |
|
|
1551
1578
|
|
|
1552
|
-
At `project_root=/`, `/src/x.md` and `src/x.md` resolve to the same key. Without a project root, absolute
|
|
1579
|
+
At `project_root=/`, `/src/x.md` and `src/x.md` resolve to the same key. Without a project root, absolute and home-relative spellings cannot be translated; no implicit filesystem base is supplied.
|
|
1553
1580
|
|
|
1554
|
-
|
|
1581
|
+
§fs-home **Home expansion belongs to authored file spellings, not resource identities.** A leading `~` or `~/` resolves from the daemon user's home (`os.homedir()`) before project-relative translation. Bare `~` names that directory. Other tilde-prefixed names, `./~` and embedded tilde segments are literal. This applies to file operations and client attachments regardless of producer; pattern-slot `~` remains full-text search. Bound entry addresses, Git paths, stored keys and membership patterns remain literal. Expansion grants neither membership nor write authority. A literal key `~` or `~/…` is rendered with a leading `./`, so resolving the displayed address recovers the same key without expanding it again. Existing identities and historical evidence are unchanged.
|
|
1555
1582
|
|
|
1556
|
-
§file-
|
|
1583
|
+
§file-url **Explicit file URLs have native URL meaning; stored keys stay literal.** Reads, mutations, client attachments and rendered addresses share this boundary:
|
|
1557
1584
|
|
|
1558
|
-
|
|
1585
|
+
| Surface | Contract |
|
|
1586
|
+
|---|---|
|
|
1587
|
+
| `file://` input | Native `fileURLToPath` interpretation, once, before {§fs-namei}; `%2528` names literal `%28`, not `(`. Query does not change the native filename; fragment selects a channel, while `%23` names a literal `#`. |
|
|
1588
|
+
| Invalid URL | Invalid encoding, host-unsupported authorities or encoded separators, and NUL refuse the operation with 400. |
|
|
1589
|
+
| Bare input / bound key | Bare spelling retains {§path-parentheses}, not general URI decoding. Bound keys are never decoded or home-expanded again. |
|
|
1590
|
+
| Resource rendering | Ordinary names stay project-relative. Names that bare target syntax would reinterpret use absolute native file URLs from `project_root`; no identity or membership changes. |
|
|
1591
|
+
| Selectors | Encoded metacharacters are filename data, separate from authored glob syntax ({§path-glob-matching}). URL selector receipts preserve that distinction; generated folder links quote the literal folder before appending `/**`. Literal backslashes remain within their filename segment, including beside glob syntax. |
|
|
1592
|
+
|
|
1593
|
+
Folders and globs select members in those same filesystem coordinates. Parent-directory selectors may include in-root and outside-root members; they never scan or admit unrelated disk contents. Catalog paths and grouped subtree selectors use the reusable spelling in {§file-url}.
|
|
1594
|
+
|
|
1595
|
+
§file-path-normalization An authored model file operation using an absolute or home-relative path receives a `scheme:file/path_normalized` warning Notice naming its project-relative address. COPY/MOVE cover each such operand. The Notice neither changes the operation result nor causes a strike, and does not repeat for automatic observations or already-relative paths. Root-mounted workspaces and spellings that must remain file URLs ({§file-url}) need no such notice. It never suggests that an unadmitted path has become a member.
|
|
1596
|
+
|
|
1597
|
+
§fs-canonical-name **One canonical identity: the literal Git-relative key.** Member keys follow gitformat-index(5) verbatim (reference edition: git 2.47.3): relative to the workspace `project_root`, without leading slash, `/`-separated, no trailing slash or NUL. Directories are never entries and the root needs no name. When `project_root` is below the containing repository's top level, Git members above it naturally use the same `../`-prefixed CWD-relative names that `git ls-files` emits without `--full-name`; these are not outside-repository mounts. The database stores that root-relative key directly because workspace identity is rooted at the access point. Authored spellings resolve before storage or comparison; stored keys are lexical fixpoints, never reinterpreted as authored input. Rendering quotes target-slot syntax ({§path-parentheses}) and home-like literal names ({§fs-home}), using a file URL where necessary ({§file-url}); resolving the rendered spelling returns the same key.
|
|
1559
1598
|
|
|
1560
1599
|
§fs-visibility-grantors **File visibility has two represented grantors; Plurnk never invents a private third one.** A file member is admitted by the active Git substrate or by an ordinary `include` row of the overlay. An `include` is either a projected `members` definition ({§members-projection}) or the exact, inspectable record of an accepted creation ({§fs-create-record}); both resolve to `constraint` membership. AGENTS.md remains auto-pulled as POLICY ({§policy-sections}), deliberately not a file member. A physically existing path that neither Git nor an `include` admits does not exist for the model and cannot be overwritten.
|
|
1561
1600
|
|
|
@@ -1596,12 +1635,12 @@ where the invariant closes an architectural failure mode:
|
|
|
1596
1635
|
- §file-create-scope The effective creation scope is the minimum of the service ceiling and workspace setting; no call site or producer may widen it.
|
|
1597
1636
|
- §file-create-producer-neutral The file contract depends on the operation and target, never the producer identity.
|
|
1598
1637
|
- §file-create-single-owner File membership owns prospective admission, incorporation choice, and creation-record lifecycle; file operations consume that decision rather than re-deriving Git and constraint policy.
|
|
1599
|
-
- §file-create-transaction Success requires both exclusive disk creation and durable incorporation. Approval re-resolves physical containment and policy
|
|
1638
|
+
- §file-create-transaction Success requires both exclusive disk creation and durable incorporation. Approval re-resolves physical containment and policy. Incorporation failure rolls back only the unchanged creation ({§file-delete-revision}); incomplete rollback is an explicit partial-failure Problem. Publication and its filesystem limits are defined by {§file-publication} and {§file-external-race}.
|
|
1600
1639
|
|
|
1601
1640
|
Refusing an occupied non-member follows the POSIX exclusive-create precedent:
|
|
1602
1641
|
namespace occupancy is not secret, but content remains dark.
|
|
1603
1642
|
|
|
1604
|
-
§fs-answer-in-canon **The engine answers
|
|
1643
|
+
§fs-answer-in-canon **The engine answers with the resolved identity.** Log-row pathname columns retain literal canonical keys. Model-facing addresses in receipts, FIND results, the catalog and recovery use their round-trippable spelling ({§fs-canonical-name}); filename facts and native diffs may name the literal key. A miss names the resolved identity, never an echo of the model's spelling. The model's own emission text remains verbatim — history is never rewritten. Rendering does not create another resource identity.
|
|
1605
1644
|
|
|
1606
1645
|
§fs-errno **errno discipline — one error, one meaning, each with its fact.** Error facts speak wire canon and state the occurrence, never a tutorial.
|
|
1607
1646
|
|
|
@@ -1616,7 +1655,7 @@ Every fact names the canonical key, never the host root or an echo of the
|
|
|
1616
1655
|
model's spelling. These classes let a caller distinguish a wrong address, an
|
|
1617
1656
|
invalid range, read-only authority, and occupied hidden state without guessing.
|
|
1618
1657
|
|
|
1619
|
-
§membership-read-refusal **A file miss speaks of membership, never of the disk.** A file is read only as a member, so every `file` miss — READ, FIND of an exact path, KILL, a pattern EDIT's source, a COPY or MOVE source — is 404 `entry-not-found`, `No member of this workspace is at '<key>'.`, its target rendered as the member
|
|
1658
|
+
§membership-read-refusal **A file miss speaks of membership, never of the disk.** A file is read only as a member, so every `file` miss — READ, FIND of an exact path, KILL, a pattern EDIT's source, a COPY or MOVE source — is 404 `entry-not-found`, `No member of this workspace is at '<key>'.`, its target rendered as the reusable member address ({§fs-answer-in-canon}, {§file-url}). Recovery offers listing with FIND, creation with EDIT, and admission with `members (add)` as alternatives and presumes none ({§diagnostic-observation}): `` FIND lists paths. EDIT creates files; `members (add)` admits existing files with a `{"glob": "<path>"}` body. `` The sentence is about the address and is true whether or not a file is there: it neither claims absence nor hints at presence. Beyond the root the engine does not look at the disk at all, so two reads of `../` paths differ only in the name they echo, and their recovery speaks of the address too, true under every members scope: `'<key>' is outside the project root: only a members definition under the operator's namespace scope admits it.` Inside the root occupancy is not secret ({§fs-write-nonmember}), so an exact-path READ of a path that exists on disk but is not a member says so instead — 404 `entry-not-member`, `'<key>' exists on disk but is not a member of this workspace.`, with admission-only recovery; a path the repository ignores, which no model definition admits, carries the members discovery verdict instead: `The repository ignores it: a client or operator members definition can include it, a model definition cannot.` Occupancy may surface there; content never does ({§membership}).
|
|
1620
1659
|
|
|
1621
1660
|
§file-directory-target **A directory is named as a directory.** Inside the root, a READ (or other exact-path read), KILL or EDIT whose target is a directory on disk — with or without a trailing slash — is refused `path-is-directory`, never as a missing or non-member file: READ and KILL answer 404, EDIT 403. The detail is `'<key>' is a directory, not a file; <OP> reads/removes/writes one file.`; a READ or KILL carries the listing as its recovery, `` `FIND (<key>/)` lists its files. ``, and an EDIT carries none. Beyond the root the disk stays dark and {§membership-read-refusal} holds unchanged.
|
|
1622
1661
|
|
|
@@ -1645,7 +1684,7 @@ metadata or channels.
|
|
|
1645
1684
|
|
|
1646
1685
|
§op-methods-op-dispatch Engine operation ownership follows the public scheme contract:
|
|
1647
1686
|
|
|
1648
|
-
- Each
|
|
1687
|
+
- Each resolved EDIT target dispatches through `editBatch` with one statement.
|
|
1649
1688
|
- 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.
|
|
1650
1689
|
- Other delegated operations use the corresponding lowercase `SchemeHandler` method, with standard FIND supplied for a data scheme that omits a custom implementation.
|
|
1651
1690
|
- COPY and MOVE are engine-owned compositions over CRUD primitives ({§copy}/{§move}).
|
|
@@ -1658,7 +1697,7 @@ Registration precedes loop affinity:
|
|
|
1658
1697
|
| Registered but inactive under flag | The flag gate returns `403 scheme-unavailable`. |
|
|
1659
1698
|
| Registered and active | Dispatch continues to the operation owner. |
|
|
1660
1699
|
|
|
1661
|
-
- §op-execution-order **An admitted turn is an ordered program.** Model, client, and harness operations execute in authored order. WAIT
|
|
1700
|
+
- §op-execution-order **An admitted turn is an ordered program.** Model, client, and harness operations execute in authored order. WAIT is deferred until all other admitted operations settle or establish their explicitly asynchronous work ({§disposition-anywhere}). The complete program then settles under {§wait-obligation-matrix}, whether or not it contains a lifecycle request; no completion operation or inventory is invented. Existing cycle, no-operation, and resource rails remain effective. An observation records the resource state at its execution point; the model sees that receipt in the next packet. Exact submitted source and actual operation outcomes remain durable. Earlier successful effects survive a later operation failure; a producer requesting fail-on-error stops before subsequent operations.
|
|
1662
1701
|
|
|
1663
1702
|
§bare-inference **BARE is isolated, synchronous retrieval over the durable child-provider policy.**
|
|
1664
1703
|
|
|
@@ -1673,10 +1712,10 @@ Registration precedes loop affinity:
|
|
|
1673
1712
|
| Observation | Responses are unseen retrieval work; completion follows {§send-premature-terminate}. |
|
|
1674
1713
|
|
|
1675
1714
|
- §op-synchronous **Decisive operations settle before the next operation.** The dispatcher awaits each operation and its proposal resolution. Work remains in flight only when the operation's contract deliberately creates concurrency: FORK, WORK, a stream-producing execution, and streaming READ after acquisition. Such a READ first establishes its durable subscription and returns `102`; a later operation may address that live owner. Dispatching an execution before KILL does not wait for the process to finish using a resource. KILL of a worker synchronously ends its live loops before disposition checks the pending set; physical scope cleanup remains asynchronous.
|
|
1676
|
-
- §edit-execution **One
|
|
1715
|
+
- §edit-execution **One resolved EDIT target is one mutation.** Each EDIT resolves against current resource state when dispatch reaches it, owns its proposal when gated, and records its own resulting revision. No later EDIT is prepared or applied in advance. Numeric scopes address current coordinates; an earlier EDIT may change what those numbers select. Rejection applies only to that operation, not its successful siblings.
|
|
1677
1716
|
- §edit-anchor-continuity **Own EDITs preserve untouched hash targets within one program.** Core carries an anchor through exact, successfully applied EDIT splices when its line survives unchanged, even if its ordinal or neighborhood changes. Scoped entry KILL uses the same deletion path. Target-line replacement or deletion invalidates that binding. Continuity is private to the admitted program and canonical resource/channel; it is not a new published anchor format. The complete normalized line content must match the expected result of the preceding recorded EDIT, otherwise retained bindings are discarded and ordinary current-state validation applies. Reviewer replacement and results without an applied EDIT receipt do not carry bindings forward. A retained binding resolves alone: a twin neighbourhood this program's own splice created elsewhere does not make the carried anchor ambiguous, and an anchor the program never bound resolves against current state. Normalization is the same line-content representation used by READ and line hashing; file-write revision checks remain independent. No approximate text matching is used. Lowered coordinates retain a current-anchor precondition at the mutation owner; ambiguous matches and concurrent changes remain collisions.
|
|
1678
1717
|
- §anchor-offset **An anchor offset is tolerated, never taught (#749).** A line mark may carry an offset from its anchor (`@abcde+1`, `@abcde-2`), and a bare `+N` after an anchor counts from that anchor (`<@abcde,+1>`). The anchor resolves as usual and the offset is added; a result before line 1 is an invalid mark, and past the end is the ordinary range refusal. Continuity and current-anchor preconditions check the anchor's own line. `plurnk.md` keeps its two anchor forms. Numeric relative endpoints normalize under {§scope-range-recovery}; a reversed range produced by anchor resolution is never reinterpreted as a count.
|
|
1679
|
-
- §edit-batch **One compound operation may require atomic splices.** The scheme's `editBatch` primitive validates all supplied numeric edits against one snapshot and commits one revision or none. Core supplies one statement
|
|
1718
|
+
- §edit-batch **One compound operation may require atomic splices.** The scheme's `editBatch` primitive validates all supplied numeric edits against one snapshot and commits one revision or none. Core supplies one statement per resolved EDIT target; same-resource MOVE can supply multiple splices as one operation. This primitive does not group separate targets or authored operations. Its replacement, insertion, conflict, and receipt rules remain owned by the shared Slicer.
|
|
1680
1719
|
- §edit-batch-receipt **A refusal describes its own unapplied work.** An anchor collision lists every distinct unresolved anchor in that EDIT, including both range endpoints, in `unresolvedAnchors` (`anchor`, `kind: missing | ambiguous`, and matching `lines` when ambiguous). Missing is not proof of earlier validity or subsequent change. It carries `editCount: 1`, `applied: 0`, and recovery directing a READ for current coordinates; it makes no claim about other operations. A refused compound splice batch lists all conflicting pairs in `conflicts`, non-conflicting regions in `cleanRegions`, its first pair in `conflictingRegions`, and its own `editCount` and `applied: 0`.
|
|
1681
1720
|
- §edit-batch-merges **Normalizations require evidence and a receipt.** An EDIT body carrying only this resource's published `L<@xxxxx>` prefixes (the number right-aligned) is stripped when those prefixes verify against current anchors or this worker's preserved READ receipts (`rendered-prefix-stripped`); otherwise it remains literal content (`rendered-prefix-unverified`). Within a single atomic splice batch, the Slicer can deduplicate identical regions/bodies, concatenate same-boundary insertions, assign a shared endpoint to the sole body reproducing that line, or relocate an inner change when its original content occurs exactly once in the outer body. An already-applied inner body can be dropped. Unevidenced overlap remains a collision. These batch resolutions never reinterpret separate authored EDITs. Applied normalizations carry their exact merge facts and a notice; receipts describe only the applied effects.
|
|
1682
1721
|
|
|
@@ -1688,6 +1727,34 @@ a resource, channel, and optional text scope ({§transfer-resource-selections}).
|
|
|
1688
1727
|
Source acquisition follows {§universal-read-composition}; landed mutation
|
|
1689
1728
|
effects follow {§edit-result-copy-move-effects}.
|
|
1690
1729
|
|
|
1730
|
+
§bulk-resource-targeting **Path selectors resolve before resource operations.** Core
|
|
1731
|
+
uses ordinary FIND selection, without a FIND receipt, to resolve glob/extglob
|
|
1732
|
+
operands ({§path-glob-matching}). Resolution occurs when dispatch reaches the
|
|
1733
|
+
operation, not when the turn is parsed. Each selected address retains the
|
|
1734
|
+
authored channel; scopes and content matchers belong to the selected resource.
|
|
1735
|
+
|
|
1736
|
+
| Operation | Selection and execution |
|
|
1737
|
+
|---|---|
|
|
1738
|
+
| READ | The ordinary FIND resource page, optionally filtered by the content matcher; each target receives an exact READ ({§read-fan-out}). |
|
|
1739
|
+
| EDIT, resource KILL | The complete matching path set, not the FIND preview page. Content matchers do not filter this set: each target independently validates and applies its scope, matcher and body through the ordinary mutation owner. No paths means one 204 receipt and no mutation. |
|
|
1740
|
+
| COPY, MOVE | Each glob operand must resolve to exactly one resource. Zero or multiple matches refuse the pair with `target-cardinality` before either side changes. Exact destinations retain ordinary creation semantics. Explicit pairs express bulk transfers; no implicit concatenation, folder mapping or positional pairing. |
|
|
1741
|
+
| Log KILL | The existing curation selector owns the complete operation ({§log-kill-scope}), including its snapshot and distillation. |
|
|
1742
|
+
|
|
1743
|
+
Fan-out resolves the address set once and executes in FIND order. Each target
|
|
1744
|
+
has its own admission, current-state validation, proposal and durable receipt;
|
|
1745
|
+
successful siblings survive a later refusal. Fail-on-error stops before the
|
|
1746
|
+
next target ({§op-execution-order}). No cross-resource transaction is implied.
|
|
1747
|
+
Per-target rows carry `attrs.fanout` (`target`, the authored selector; `matched`,
|
|
1748
|
+
the selected resource count; zero-based `index`; `count`, the admitted target
|
|
1749
|
+
count). One authored operation still produces one lifecycle notification pair.
|
|
1750
|
+
The configured command ceiling counts each admitted concrete operation; WAIT
|
|
1751
|
+
remains exempt ({§operator-config-workspace-max-commands}). It never counts an
|
|
1752
|
+
internal survey or a distillation as another command. An entirely omitted
|
|
1753
|
+
statement is not surveyed just to count its possible targets.
|
|
1754
|
+
Dispatch returns core-owned `commandsExecuted` and `commandsOmitted` totals to
|
|
1755
|
+
the turn executor outside operation results, receipts and lifecycle events;
|
|
1756
|
+
scheme result extensions cannot supply these counts.
|
|
1757
|
+
|
|
1691
1758
|
### SEND dispatch (a message to a recipient)
|
|
1692
1759
|
|
|
1693
1760
|
Targetless and exact-message SENDs follow the reply accounting at
|
|
@@ -1904,7 +1971,7 @@ Every entry is uniformly listed in the catalog (```` ```FIND (scheme:///**) ````
|
|
|
1904
1971
|
|
|
1905
1972
|
Mimetype is declared by scheme manifest ({§scheme-manifest}) or supplied per-call for dynamic schemes. Writing a channel without a declared mimetype throws. No default mimetype anywhere.
|
|
1906
1973
|
|
|
1907
|
-
- §channel-mimetype-cross-mimetype-415 COPY/MOVE compatibility follows {§mimetype-verbatim-transfer}; incompatible pairs return 415. Transfers preserve content verbatim and retain the destination's declared type, resolving
|
|
1974
|
+
- §channel-mimetype-cross-mimetype-415 COPY/MOVE compatibility follows {§mimetype-verbatim-transfer}; incompatible pairs return 415. Transfers preserve content verbatim and retain the destination's declared type, resolving an absent channel under {§copy-destination-mimetype}.
|
|
1908
1975
|
|
|
1909
1976
|
### §channel-selection Channel selection in the DSL
|
|
1910
1977
|
|
|
@@ -1953,7 +2020,7 @@ Client-interface target parameters carry fragments inline (`{ target: "sh:///a3b
|
|
|
1953
2020
|
MOVE out of it are 400 `channel-derived`; COPY from it is an ordinary read. Binary sources
|
|
1954
2021
|
keep {§membership-source-projection}, where the source is not text and the projection is the
|
|
1955
2022
|
body; a fetched web page keeps its scheme's own two channels ({§html-materialization}).
|
|
1956
|
-
- §channel-selection-visibility **Channel selection is decision-time information, not a guess** — every multi-channel resource presents its channels with extents wherever FIND presents the resource: broad results list each channel's path, projection `mimetype`, tokens, and lines (default channel first), and matcher
|
|
2023
|
+
- §channel-selection-visibility **Channel selection is decision-time information, not a guess** — every multi-channel resource presents its channels with extents wherever FIND presents the resource: broad results list each channel's path, projection `mimetype`, tokens, and lines (default channel first), and a matcher location names the channel its line coordinates address whenever that is not the resource's default channel. A READ of a multi-channel resource names its other channels with their tokens in `channels`, keyed by the fragment the model appends (`{"#readable": 812}`), so first contact — a fetched page, a stream's stdout — carries the same choice without a listing; a single-channel resource names none. When the default channel is a readable projection of a differently typed source, it also names `sourceMimetype` once; this is representation evidence, not a different READ workflow. The packet never presents channels as equal and indistinguishable; extents derive from the stored channels by construction. Budget enforcement stays with {§context-fit} — this is information, not a second guard.
|
|
1957
2024
|
|
|
1958
2025
|
### §channel-state Channel state — metadata, not gating
|
|
1959
2026
|
|
|
@@ -2117,14 +2184,14 @@ AST: `{ op: "EDIT", target, body: string | null, signal: tags | null, lineMarker
|
|
|
2117
2184
|
({§edit-anchor-continuity}) does not carry through a pattern batch; the next
|
|
2118
2185
|
anchored EDIT validates against current state.
|
|
2119
2186
|
|
|
2120
|
-
A `file:///` member EDIT
|
|
2187
|
+
A `file:///` member EDIT computes against its materialized body and **proposes** (202) conditional file publication under {§membership-edit-write-revision}, {§file-external-race}, and {§proposal}. The marker-required rule applies identically: an existing file is never markerlessly replaced.
|
|
2121
2188
|
|
|
2122
2189
|
### §read READ
|
|
2123
2190
|
|
|
2124
2191
|
AST: `{ op: "READ", target, body: null, signal: tags | null, lineMarker? }`.
|
|
2125
2192
|
|
|
2126
2193
|
A READ is never rewritten into a FIND ({§read-find-normalization}); a path-glob
|
|
2127
|
-
READ
|
|
2194
|
+
READ uses the common resource selector ({§bulk-resource-targeting}, {§read-fan-out}).
|
|
2128
2195
|
|
|
2129
2196
|
- §read-read-content Returns channel content and mimetype.
|
|
2130
2197
|
- §read-read-404 Returns 404 when the channel is absent.
|
|
@@ -2166,16 +2233,16 @@ READ is the one fan-out core performs ({§read-fan-out}).
|
|
|
2166
2233
|
scope, matcher and aside ({§read-selection-projection}, {§read-pattern}), one
|
|
2167
2234
|
receipt row per path in the FIND's order, so every rendered line keeps its path,
|
|
2168
2235
|
physical ordinal and anchor and remains a coordinate source for EDIT and KILL.
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
statement once and folds the paths beneath it without inferring the group.
|
|
2236
|
+
Rows use the shared `attrs.fanout` identity ({§bulk-resource-targeting}), so a
|
|
2237
|
+
client can group the exact receipts under the authored statement.
|
|
2172
2238
|
Without a scope each path uses {§markerless-first-page}; with a pattern
|
|
2173
2239
|
only the matching lines, `grep -n` style. The authored statement contributes
|
|
2174
2240
|
`rowsWritten`, the receipt count, to its turn's sequence. No path is one 204
|
|
2175
2241
|
receipt on the authored glob (`matched: 0` when a pattern selected nothing); a
|
|
2176
2242
|
FIND failure is that failure on the authored glob. The FIND's resource page bounds
|
|
2177
|
-
the fan-out: when more paths matched than
|
|
2178
|
-
notice names both counts.
|
|
2243
|
+
the fan-out: when more paths matched than its page selected, one
|
|
2244
|
+
`read_fanout_bounded` notice names both counts. A separate command ceiling may
|
|
2245
|
+
further limit dispatch ({§bulk-resource-targeting}). Every dialect follows this same READ fan-out;
|
|
2179
2246
|
none substitutes a FIND receipt for the requested content.
|
|
2180
2247
|
|
|
2181
2248
|
§read-pattern-evidence **Match regions survive line-oriented presentation.** A patterned
|
|
@@ -2267,7 +2334,11 @@ AST: `{ op: "KILL", target, matcher: MatcherBody | null, lineMarker: TextLineMar
|
|
|
2267
2334
|
|
|
2268
2335
|
§log-kill-distillation **A log KILL may say what it keeps.** A body on a `log:///` KILL is the model's distillation of what the KILL retires. Whatever the kill's outcome, the body lands as the model's own NOTE row at the next sequence of the same turn — written after the kill's receipt, so it never falls inside the kill's own selection — carrying `attrs.distilled` with the KILL's target as written, so a distillation is distinguishable from a free NOTE while it renders, weighs and curates exactly as one; the dispatch reports two rows written. A kill that misses keeps its distillation beside its visible receipt: what the model wrote about its environment is recorded for the model to possess and retire, never dropped for where the kill aimed. A whitespace-only body is a plain KILL. The kill's own receipt stays hidden as any successful log KILL's does ({§context-verbs}).
|
|
2269
2336
|
|
|
2270
|
-
KILL deletes context from the **log** (`log:///`, {§packet}). Without a scope it retires the selected rows from the active projection ({§log-history-projection}). With a one-line or inclusive two-line scope it removes only that body's intersecting body-relative physical lines from the readable projection, and the row stays active. An anchor may be one published on that body or one returned by READing its `log:///` coordinate ({§line-anchors}); an anchor absent from the current body selects no line, as with an out-of-bounds numeric line. Scoped KILL is one-way: intervals accumulate, the durable body is untouched, and subsequent access follows {§log-readable-projection}. A scoped KILL on a bodyless row is a friendly 200 no-op with `matched` reported. An emission row is curated whole ({§emission-row}): a scope
|
|
2337
|
+
KILL deletes context from the **log** (`log:///`, {§packet}). Without a scope it retires the selected rows from the active projection ({§log-history-projection}). With a one-line or inclusive two-line scope it removes only that body's intersecting body-relative physical lines from the readable projection, and the row stays active. An anchor may be one published on that body or one returned by READing its `log:///` coordinate ({§line-anchors}); an anchor absent from the current body selects no line, as with an out-of-bounds numeric line. Scoped KILL is one-way: intervals accumulate, the durable body is untouched, and subsequent access follows {§log-readable-projection}. A scoped KILL on a bodyless row is a friendly 200 no-op with `matched` reported. An emission row is curated whole ({§emission-row}): the unscoped KILL retires it; a line scope on its exact coordinate addresses its legend and retires the NOTEs on the lines it selects, the row staying; on a row with no legend lines the scope is 422 `emission-curated-whole`, whose recovery names the unscoped KILL; a sweep leaves it intact. A KILL that addresses no row is 404 on an exact coordinate and 204 on a sweep ({§log-curation-folder-idiom}). Selection composes target/glob with an optional heading pattern ({§log-curation-set-selection}).
|
|
2338
|
+
|
|
2339
|
+
§log-target-tolerances **The log target reader accepts four near-misses of the taught form and reads each as the one target it can only have meant.** The card teaches `KILL (log:///1/[1-7]/*/{READ,emission})`; none of the following is taught, and no diagnostic text accompanies any of them. A `|` between complete KILL targets, each a coordinate, prefix or glob ({§log-coordinate-hierarchy}) written bare or as a full `log:///` address, is their union: `log:///1/25/2/EDIT|log:///1/24/3/EDIT` retires both rows; a piece that is none of those refuses the whole target, 400 `kill-failed`, naming the piece; a list that selects nothing is the sweep's 204 unless every piece is an exact coordinate, when it is the exact miss's 404. `|` is not a character of a coordinate, and file paths, where it is one, are untouched. For KILL and FIND alike: a bracketed comma list in a numeric slot is a set, `log:///1/[19,24]/**/sh` reading as `log:///1/{19,24}/**/sh`, since a character class can never match a turn number; a non-numeric literal in a numeric slot, after at least one numeric slot, is the leaf with the missing slots `*`, `log:///1/*/READ` reading as `log:///1/*/*/READ`; and `*` segments between the sequence and the leaf are dropped, `log:///1/3/3/*/READ` reading as `log:///1/3/3/READ`, since no coordinate holds a segment there.
|
|
2340
|
+
|
|
2341
|
+
§log-target-shape **The refusal of a log target nothing can read shows the working form.** A malformed KILL or FIND target, 400, carries as its recovery the one sentence `` A log target is `log:///<loop>/<turn>/<sequence>` with an optional `/<op>` leaf; a shorter path is a prefix, and `*`, `**`, `[1-7]` or `{a,b}` may stand in any segment. `` It names the shape and presumes nothing about what the author meant ({§diagnostic-observation}). A sweep that matches nothing stays the bare 204 of {§log-curation-folder-idiom} and an exact miss beside rows that exist names them ({§log-near-miss}); neither carries the sentence, so no text rides the packet for the ordinary case.
|
|
2271
2342
|
|
|
2272
2343
|
§log-scope-recovery A log-body scope follows the file slicer's range rule ({§range-starts-at-one} in the schemes SPEC): a range starting at 0 — `<0,-1>` included — is refused 416 `range-not-satisfiable` on every body, empty ones too, and never clamped; its detail is the slicer's own sentence, `Range <0,-1> starts at 0, which is not a line; lines are numbered from 1.`, and its recovery names the forms a log body takes — `Trim one line with <L> or lines L through M with <L,M>; KILL (log:///1/9/2/READ) with no scope retires the whole row.` — never the insert and append positions a body cannot take. Every other scope that names no line is 400 `curation-scope-invalid` with the same recovery: the forms that work on that row, never a rebuild of the written scope ({§diagnostic-observation}).
|
|
2273
2344
|
|
|
@@ -2277,7 +2348,7 @@ A READ carrying active native media is atomic: any KILL scope is ignored and the
|
|
|
2277
2348
|
|
|
2278
2349
|
| Fact | Owner | Effect |
|
|
2279
2350
|
| --- | --- | --- |
|
|
2280
|
-
| Initial body suppression | Immutable event `initial_folded` | Packet presentation only; explicit retrieval can read an initially hidden body. An emission row remains folded; its program is separately eligible for {§
|
|
2351
|
+
| Initial body suppression | Immutable event `initial_folded` | Packet presentation only; explicit retrieval can read an initially hidden body. An emission row remains folded; its program is separately eligible for {§emission-history}. |
|
|
2281
2352
|
| Deliberate scoped KILL | Current projection `folded`, initially empty | Packet, READ, FIND, COPY, and search omit those lines; later retrieval cannot undo trimming. |
|
|
2282
2353
|
|
|
2283
2354
|
Packet display combines both masks. Other consumers use only deliberate trimming.
|
|
@@ -2315,7 +2386,7 @@ The `## Log` section is a sequence of ordinary Markdown records separated by one
|
|
|
2315
2386
|
| facts | One strict JSON object in stable alphabetical order. | Present only when a fact exists. Asides, scopes, opaque invocation metadata and result facts belong here, not on the H3. |
|
|
2316
2387
|
| body | Coordinate-prefixed lines. | Present when the row is visible. |
|
|
2317
2388
|
|
|
2318
|
-
An emission row's body is not in its record ({§emission-row});
|
|
2389
|
+
An emission row's body is not in its record ({§emission-row}); its eligible program follows it as a separate assistant message ({§emission-history}). Patterns retain their literal spelling; a pattern containing a line break is JSON-quoted to keep the H3 on one physical line. Receipts are descriptive records, not reconstructed operation headings. Absent fields are not invented. Every physical body line retains its canonical numeric `N:` or anchored `@hash N:` coordinate, so source text cannot create a record boundary. The section contains records only, with no leading prose or enclosing fence.
|
|
2319
2390
|
|
|
2320
2391
|
§log-address-metadata **Addresses name their relationship, not the row's producer.**
|
|
2321
2392
|
|
|
@@ -2359,7 +2430,9 @@ cropping ({§packet-attachment-parts}).
|
|
|
2359
2430
|
|
|
2360
2431
|
Retrieval results omit redundant requested coordinates; durable results and
|
|
2361
2432
|
submitted programs retain them. Failed selections keep requested coordinates
|
|
2362
|
-
and available extent in their owning Problem
|
|
2433
|
+
and available extent in their owning Problem; a channel READ that carries its
|
|
2434
|
+
execution's failure retrieved successfully and formats its extent like any
|
|
2435
|
+
other. Projection never parses its
|
|
2363
2436
|
display strings to recover typed facts. A hidden body has no `preview`; a
|
|
2364
2437
|
complete non-retrieval body retains `lines` where no other field supplies its
|
|
2365
2438
|
navigable extent. None of these spellings changes acquisition, delivery,
|
|
@@ -2382,8 +2455,11 @@ Authored `metadata` retains its opaque ordered block strings under {§scheme-met
|
|
|
2382
2455
|
byte sequence once; the result's `nativeContentHash`, enforced by the log's foreign key, identifies it.
|
|
2383
2456
|
This is retained evidence, not a separate visibility or delivery lifecycle. Source mutation/deletion
|
|
2384
2457
|
cannot change a retained observation. Explicit READ of its still-active log source can acquire the same media again.
|
|
2385
|
-
Every compatible-model packet includes one file part per retained, admitted READ observation,
|
|
2386
|
-
|
|
2458
|
+
Every compatible-model packet includes one file part per retained, admitted READ observation, directly
|
|
2459
|
+
after the user section ending at that READ record, in observation order. The attachment retains that
|
|
2460
|
+
section's name in request evidence; later log records or emissions never move ahead of it. Packets
|
|
2461
|
+
stored without a section binding retain their recorded whole-log placement. Each file part is
|
|
2462
|
+
preceded by a text part that names the observation's log
|
|
2387
2463
|
coordinate, source path and projection facts and states that the bytes are that READ's own, retained
|
|
2388
2464
|
until its row is KILLed: an uncaptioned native part on the user turn reads as a fresh arrival (#899).
|
|
2389
2465
|
Model-response settlement never consumes an observation. KILL follows
|
|
@@ -2397,7 +2473,7 @@ Authored `metadata` retains its opaque ordered block strings under {§scheme-met
|
|
|
2397
2473
|
records the exact READ coordinates sent without controlling retention. Missing immutable bytes are an
|
|
2398
2474
|
internal integrity failure, never silently dropped content. No ejection message or permanent teaching is
|
|
2399
2475
|
added. These stable curation weights are not provider-token measurements ({§tokenomics-render-weight-budget}).
|
|
2400
|
-
- §packet-token-accounting Every row reports one `tokens` charge on its H3 ({§log-wire-format}): its complete materialized H3, facts, visible body and selected native attachment. The
|
|
2476
|
+
- §packet-token-accounting Every row reports one `tokens` charge on its H3 ({§log-wire-format}): its complete materialized H3, facts, visible body and selected native attachment. The emission-history section is charged separately as assistant-message text ({§emission-history}). The completed record is measured to a fixed point, including the accounting field itself. Hidden text is not charged; metadata-only rows still have a reclaimable charge. Source/FIND-item `tokens` measure source content, not the observation's context footprint. A FIND's nonzero `itemsTokenTotal` weighs the complete matched set; a nonzero `returnedItemsTokenTotal` appears only when the returned page differs. All use stable curation weights, not provider tokens or dollars. Native component accounting follows {§packet-attachment-parts}; ordinary addressability and truthful errors follow {§log-wire-format}.
|
|
2401
2477
|
|
|
2402
2478
|
### §retrieval-packet-metadata READ/FIND packet metadata
|
|
2403
2479
|
|
|
@@ -2448,25 +2524,25 @@ single line past the end, a reversed range, empty content, a command's log row
|
|
|
2448
2524
|
### §emission-row The emission row
|
|
2449
2525
|
|
|
2450
2526
|
Every admitted content emission is announced by one curatable row of its own turn.
|
|
2451
|
-
|
|
2527
|
+
Eligible programs supply {§emission-history}; every source remains readable regardless of replay.
|
|
2452
2528
|
|
|
2453
2529
|
| Surface | Contract |
|
|
2454
2530
|
|---|---|
|
|
2455
2531
|
| When | An inference turn that admitted at least one content statement. Reasoning-only turns, including initialization ({§worker-initialization-entry}), a programmatic batch, an empty turn ({§empty-turn}), a client operation and a rejected attempt ({§rejected-emission-entry}) announce nothing. |
|
|
2456
2532
|
| Place | After the turn's inputs (arrivals, deltas, open-path READs) and before its reasoning NOTEs and operations, written after the selection snapshot ({§turn-ops-selection-snapshot}): the emission sits between what the worker had seen and what it caused. |
|
|
2457
2533
|
| Row | A `_plurnk` READ of the turn's own source, `ops://<worker>/L/T`, with `attrs.kind="emission"` and the canonical leaf `/emission`: `### log:///L/T/S/emission → ops://<worker>/L/T · N`. It renders its author, the turn's producer, as `origin`, so a model's row carries none. It is no operation: no receipt, tool call or strike, and outside the op mix. |
|
|
2458
|
-
| Body | Frozen at announcement: the canonical rendering ({§statement-rendering}) of the admitted content statements, each whole in a closed fence. All heading operands, scopes, metadata, patterns and asides remain.
|
|
2459
|
-
| Wire | The record appears in the log; its complete program
|
|
2534
|
+
| Body | Frozen at announcement: the canonical rendering ({§statement-rendering}) of the admitted content statements, each whole in a closed fence, text beside them as the NOTEs it became ({§outside-text}). All heading operands, scopes, metadata, patterns and asides remain. Unadmitted forms are absent; a recovered native call ({§native-tool-calls}) appears as the operation it was read as; an operation whose receipt failed stays. Reasoning operations retain their own source and normal receipts, never an assistant-content copy. No body text is inspected for nested operations. |
|
|
2535
|
+
| Wire | The record appears in the log; its complete program supplies the readback projection in {§emission-history}. The frozen body and immutable `ops://` source keep every operation and body ({§turn-source-resources}); an explicit READ returns them. |
|
|
2460
2536
|
| Stability | The projection is fixed from its first appearance, never aged or resized under budget pressure. Already frozen announcements and historical request captures are not rewritten. |
|
|
2461
|
-
| Presentation | Born folded: the log record shows its header, never an assistant message. |
|
|
2462
|
-
| Accounting | The row's `tokens` charges only its rendered record. The optional
|
|
2463
|
-
| Curation | Curated whole ({§log-kill-scope}): KILL retires it
|
|
2537
|
+
| Presentation | Born folded: the log record shows its header, never an assistant message. When its turn is replayed ({§emission-history}), the record's lines are the legend of that turn's NOTEs, one numbered line per NOTE with its `log:///` path and weight, and those NOTE rows render nowhere else. |
|
|
2538
|
+
| Accounting | The row's `tokens` charges only its rendered record, legend included. The optional emission-history section is measured once as assistant-message text ({§packet-token-accounting}); replacing it never changes older row weights. An explicit source READ has its own ordinary charge. |
|
|
2539
|
+
| Curation | Curated whole ({§log-kill-scope}): the unscoped KILL retires it. A line scope on its exact coordinate addresses the legend: the NOTEs on the selected lines retire and the row stays; on a row with no legend lines the scope is 422 `emission-curated-whole`, whose recovery names the unscoped KILL; a sweep whose scope would only trim it leaves it intact. |
|
|
2464
2540
|
| Schema | Migration 12 admits `kind="emission"` only on this shape: one per turn, the turn's newest row when written, frozen, and curated whole; it backfills no announcement for earlier turns. FORK copies it with the inherited turns, still naming its writer. |
|
|
2465
2541
|
| Echoes | A worker that repeats the heading in its own text is tolerated ({§fabricated-log-entry}); the digest counts the echoes. |
|
|
2466
2542
|
|
|
2467
2543
|
### §reasoning-row The reasoning row
|
|
2468
2544
|
|
|
2469
|
-
The model's memory of its own reasoning, behind `PLURNK_SERVICE_REASONING_ROWS` (default `
|
|
2545
|
+
The model's optional memory of its own reasoning, behind `PLURNK_SERVICE_REASONING_ROWS` (default `0`):
|
|
2470
2546
|
when it is `1`, every model turn that reasoned lands its reasoning as one row of its
|
|
2471
2547
|
own, `log:///<loop>/<turn>/<sequence>/reasoning → reasoning://<worker>/<loop>/<turn>`, the harness's
|
|
2472
2548
|
READ of the turn's reasoning source, immediately before the turn's emission row (or its first
|
|
@@ -2477,10 +2553,10 @@ reads what the model thought and where its content program can be found
|
|
|
2477
2553
|
| Concern | Rule |
|
|
2478
2554
|
|---|---|
|
|
2479
2555
|
| Room | Admission occurs after all mandatory turn rows, including the emission and diagnostics, using the remaining room under {§context-fit}. Its earlier chronological coordinate is reserved without inserting a placeholder; if it does not fit, that coordinate remains unused. Nothing else changes: no partial preview, refusal, or other row touched. Reasoning-only and empty model turns follow the same rule; content operations are not required. |
|
|
2480
|
-
| Body |
|
|
2556
|
+
| Body | `PLURNK_SERVICE_REASONING_TRAILING_LINES=-1` selects the complete reasoning without either shared preview bound. A positive value selects that many trailing lines within `PLURNK_SERVICE_PREVIEW_CHARS`; unset/empty uses `PLURNK_SERVICE_PREVIEW_LINES`. Zero is invalid. Keep complete final lines where possible; if the last line alone exceeds the character bound, select its suffix with the ordinary exact column scope. Unicode code points count once and CRLF is one indivisible separator, as in {§body-projection}. The statement carries the scope it took and the receipt its `range` ({§packet-extent-metadata}); the complete reasoning stays readable at its address by any scope ({§turn-source-resources}). This setting does not change ordinary READ/FIND previews. |
|
|
2481
2557
|
| Weight | Charged like any row, visible in the gauge and its `largest` ({§context-gauge}). |
|
|
2482
2558
|
| Curation | The verbs alone: a KILL retires it like any row ({§context-verbs}); the daemon reorders nothing and un-bodies nothing on its account. |
|
|
2483
|
-
| Absence |
|
|
2559
|
+
| Absence | Disabled, no room, or no reasoning. The setting does not affect reasoning-operation admission or the readable `reasoning://` source ({§reasoning-operations}, {§turn-source-resources}). |
|
|
2484
2560
|
|
|
2485
2561
|
### §turn-source-resources Immutable turn-source resources
|
|
2486
2562
|
|
|
@@ -2499,7 +2575,7 @@ reads what the model thought and where its content program can be found
|
|
|
2499
2575
|
|
|
2500
2576
|
- §log-coordinate-hierarchy **Log coordinates are a hierarchical prefix; the trailing slash is optional** — a coordinate is `loop/turn/sequence`, and a PARTIAL coordinate selects its descendants: `log:///1` = loop 1's rows, `log:///1/2` = turn 1/2's rows, `log:///1/2/3` = the one row. A full coordinate is always three parts, so a one- or two-part path is unambiguously a prefix — the trailing slash is an optional alias (`log:///1/2` ≡ `log:///1/2/`), uniform with ```` ```READ (worker:///docs/) ````. A complete `[start-end]` segment in any numeric coordinate slot selects that inclusive decimal interval; brackets elsewhere retain ordinary path-glob meaning. Every rendered row appends one canonical model-facing leaf: the native operation name or invoked executor name, `/attempt` for a rejected emission, `/emission` for an admitted one's announcement ({§emission-row}). An executor leaf is derived from the durable submitted statement (its `runtime`), never an internal dispatch type or the current tool registry. Digits and punctuation in executor names remain part of the leaf. The leaf names identity rather than adding a resource level. Exact consumers tolerate the unsuffixed three-part shorthand; when supplied, the case-insensitive leaf is authoritative and a disagreement resolves 404. READ anchors use the canonical suffixed identity even when addressed by shorthand. Typed entry materialization therefore resolves as `/READ` while retaining its durable `EDIT` event ({§exec-entry-sink}). `log:///1/2/*` still selects the turn's item rows, while `log:///**/READ`, `log:///**/python3`, `log:///**/attempt`, and `log:///**/emission` deliberately filter canonical leaves. Executor outputs instead use workspace-wide claims such as `sh:///ab3d5678#stdout` ({§execution-output-identity}); their source operation has log coordinates, but resource lifetime and identity are independent of that observation. Error pointers, Problem instances, source attribution, and search use this same identity; client stream coordinates retain the numeric triple. Within a turn, sequence is arrival order. Inbound SEND rows publish before the program runs ({§message-arrival}); a turn receiving messages holds the first at `log:///L/T/1/SEND`, followed by further arrivals oldest first, then its emission's announcement, then the model's operations ({§packet-current-turn} names `L/T`).
|
|
2501
2577
|
- §log-near-miss **A log miss beside rows that exist names them.** A READ, FIND or KILL of an exact coordinate that names no row carries a recovery from the worker's own active rows: the turn's rows carrying the leaf written come first, since the leaf is what the model asked for and the sequence its guess, followed by the row at that coordinate under its own leaf (`` Turn 1/44's reasoning is `log:///1/44/2/reasoning`; the entry at log:///1/44/1 is `log:///1/44/1/READ`. ``); with no row of that leaf, the row at the coordinate alone (`` The entry at log:///1/25/8 is `log:///1/25/8/sh`. ``), else the turn's rows, at most six named, else the loop's latest turn. A coordinate in a loop with no rows carries none. Recorded misses were near misses every time: a READ of `1/25/8/READ` when the row was `sh`, an EDIT one sequence off, and a KILL under the 413 that must curate (#1005).
|
|
2502
|
-
- §log-curation-folder-idiom **Log curation speaks the folder idiom; a zero-match sweep is a no-op success** — KILL takes a concrete coordinate or a path-glob, and a **trailing slash or a partial coordinate means "the contents"** ({§log-coordinate-hierarchy}), like a folder-scoped FIND: ```` ```KILL (log:///1/2) <1,-1> ```` suppresses turn 1/2's bodies and retires its emission ({§emission-row}). A **well-formed selection that matches nothing is 204 with `matched: 0`**; a successful sweep's rx carries `matched: N`.
|
|
2578
|
+
- §log-curation-folder-idiom **Log curation speaks the folder idiom; a zero-match sweep is a no-op success** — KILL takes a concrete coordinate or a path-glob, and a **trailing slash or a partial coordinate means "the contents"** ({§log-coordinate-hierarchy}), like a folder-scoped FIND: ```` ```KILL (log:///1/2) <1,-1> ```` suppresses turn 1/2's bodies and retires its emission ({§emission-row}). A **well-formed selection that matches nothing is 204 with `matched: 0`**; a successful sweep's rx carries `matched: N`.
|
|
2503
2579
|
- §log-curation-set-selection **Row selection and body scope are independent** — target/glob and an optional heading pattern (```` ```KILL (log:///**) [{"pattern": "~stale"}] ````, every dialect a FIND over rows accepts) compose by intersection into the affected row set. An optional `<L>` or `<SL,EL>` then intersects each selected canonical body; it never paginates or changes the selected set. An emission row is curated whole instead: the scope retires it when it covers every line and otherwise leaves it ({§emission-row}). Thus ```` ```KILL (log:///**/READ) <17,-1> ```` may change long READs and no-op on short ones while reporting every selected row in `matched`.
|
|
2504
2580
|
|
|
2505
2581
|
§log-kill-meta-operation **A log KILL changes working context, never the underlying resources or execution history.** Receipt visibility depends on the target and result, not the producer, attribution, or age of the turn:
|
|
@@ -2510,6 +2586,7 @@ reads what the model thought and where its content program can be found
|
|
|
2510
2586
|
| A curation that matched nothing (204) | Shown once, in the packet of the very next turn, then retired like any other row. A success and a mismatch are not both silent: the model cannot otherwise tell that its earlier KILL is what emptied the selection (#779). |
|
|
2511
2587
|
| Failed log curation | Visible with its ordinary Problem. |
|
|
2512
2588
|
| Non-log target: file, worker, stream, or other resource | Ordinary scheme-owned receipt. |
|
|
2589
|
+
| The over-budget mandate row ({§context-over-budget-row}) | The same once-shown lifetime: the packet it describes, then retired from the projection, durable and readable at its coordinate. |
|
|
2513
2590
|
|
|
2514
2591
|
This packet filter does not retire the receipt: the operation, result, authored
|
|
2515
2592
|
`turnOps`, and each target's curation effects remain durable under
|
|
@@ -2574,7 +2651,7 @@ per-operation projection on `rx`; the aggregate remains inside dispatch.
|
|
|
2574
2651
|
| `unit`, `before`, `after` | `extent` | Whole-line batches use line counts. A batch containing any exact four-coordinate edit uses Unicode code-point counts. |
|
|
2575
2652
|
| `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. |
|
|
2576
2653
|
| `effect.source`, `result` | `effect` as `<source> -> <result>` | Resolved scopes mapping the source snapshot into the landed body; the admitted marker stays in durable `requested` and `tx`. |
|
|
2577
|
-
| `effect.removed`, `inserted` | `change` | Removed and inserted counts
|
|
2654
|
+
| `effect.removed`, `inserted` | `change` | Removed and inserted counts led by the receipt unit, as `extent` is: `lines -7 +7`. |
|
|
2578
2655
|
| `effect.removedText` | `removed` | {§edit-receipt-removed-text}: a pure deletion's removed text, its first `PLURNK_SERVICE_EDIT_RECEIPT_REMOVED_LINES` lines; absent when the edit inserted anything. |
|
|
2579
2656
|
| `effect.context` | Canonical row body | Numbered physical lines at each landed boundary, bounded symmetrically by `PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES`. A pattern batch's `last` context follows the first's when it differs, with no blank line between: every line of a row body carries its coordinate. |
|
|
2580
2657
|
| `disposition`, `requested` | `disposition`, `requested` | A reviewer-replaced batch preserves the authored marker while stating that its attributed effect was superseded. |
|
|
@@ -2680,6 +2757,23 @@ Operand syntax: {§transfer-resource-selections}. Result projection: {§copy-mov
|
|
|
2680
2757
|
202 when the owning scheme requires proposal review. Same- and cross-scheme
|
|
2681
2758
|
COPY use this one orchestrator.
|
|
2682
2759
|
|
|
2760
|
+
§copy-destination-mimetype **A transfer carries a type into an untyped destination.**
|
|
2761
|
+
Resolve the destination channel's type in this order, then apply
|
|
2762
|
+
{§mimetype-verbatim-transfer}; a refusal leaves both operands unchanged.
|
|
2763
|
+
|
|
2764
|
+
| Destination evidence | Type |
|
|
2765
|
+
| --- | --- |
|
|
2766
|
+
| Existing channel | Its stored source type, not a derived readable projection. |
|
|
2767
|
+
| Absent channel with a recognized pathname extension | The extension's type under {§ext-mimetype}. |
|
|
2768
|
+
| Absent channel without a recognized extension, with a declared manifest type | The declared channel type, including explicit `text/plain`. |
|
|
2769
|
+
| Absent channel without either declaration | The source's declared type, with automatic `text/plain` normalization under {§markdown-primitive}. |
|
|
2770
|
+
|
|
2771
|
+
The admitted type accompanies the content through proposal review and publication.
|
|
2772
|
+
This rule applies to whole and scoped transfers across entry-bearing schemes;
|
|
2773
|
+
the scheme's text-creation fallback does not override a transfer's supplied type.
|
|
2774
|
+
Filesystem reconciliation retains that type while the verified source revision is
|
|
2775
|
+
unchanged, including readable reprojection; a changed disk source is detected afresh.
|
|
2776
|
+
|
|
2683
2777
|
### §move MOVE (engine-orchestrated)
|
|
2684
2778
|
|
|
2685
2779
|
- §move-relocation-deletes-source MOVE first performs the destination mutation under {§copy}, then removes only
|
|
@@ -2707,7 +2801,10 @@ COPY use this one orchestrator.
|
|
|
2707
2801
|
- A cross-resource destination failure leaves the source untouched. A source
|
|
2708
2802
|
failure after destination success is an explicit partial failure with
|
|
2709
2803
|
`destinationWritten: true` and the destination's identity. Proposal
|
|
2710
|
-
acceptance/rejection follows the same ordered rule.
|
|
2804
|
+
acceptance/rejection follows the same ordered rule. Each approval uses the
|
|
2805
|
+
operand whose effect is pending: its target, metadata, authority and manifest.
|
|
2806
|
+
Source removal retains this binding whether the destination wrote immediately
|
|
2807
|
+
or required its own approval.
|
|
2711
2808
|
- §move-cross-scheme-move Same- and cross-scheme resources use the same
|
|
2712
2809
|
contract; there is no global cross-scheme transaction.
|
|
2713
2810
|
- §move-missing-source-404 A missing source is 404.
|
|
@@ -2723,7 +2820,7 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2723
2820
|
- §find-line-anchors **A FIND regex anchors each line**, as READ, EDIT and KILL do ({§read-pattern}, {§edit-pattern}): `^` and `$` are a line's ends in every FIND content match — over entries, log rows, turn sources and a binary channel's bytes — so ```` ```FIND (django/urls/resolvers.py) /^from|^import/ ```` locates the same import lines a READ with that pattern shows, never a false 204.
|
|
2724
2821
|
- §find-candidate-containment **One candidate's crash is that candidate's problem** — arbitrary member content can crash a mimetype handler mid-match (an unbalanced template partial crashed Readability and killed a 1,916-file FIND as a blank 500, #449). `Matcher.matchCandidates` contains a per-candidate handler throw: the candidate drops out exactly like unsupported content, the cause goes to daemon stderr, and only a FIND whose every candidate crashed reports a 415 whose Problem names the first crashing member and handler. The operation's other candidates always answer.
|
|
2725
2822
|
|
|
2726
|
-
- §find-scope-prefix-filter Filters entries within scope. A **bare** path is the exact entry unless the file scheme resolves a directory under {§file-find-directory}; an explicit **shell glob**, classified once by {§path-glob}, expands to a scope. Path globs use segment semantics: `*` and `?` never cross `/`; `**` does — in every spelling: a `**` glued to a name (`**.go`, `src/**.ts`) is matched as `**/*.go` / `src/**/*.ts`, never demoted to a one-level `*` the way a
|
|
2823
|
+
- §find-scope-prefix-filter Filters entries within scope. A **bare** path is the exact entry unless the file scheme resolves a directory under {§file-find-directory}; an explicit **shell glob**, classified once by {§path-glob}, expands to a scope. Path globs use segment semantics: `*` and `?` never cross `/`; `**` does — in every spelling: a `**` glued to a name (`**.go`, `src/**.ts`) is matched as `**/*.go` / `src/**/*.ts`, never demoted to a one-level `*` the way a standard matcher reads it. Terminal `*` and `**` are structural catalog selectors and include dot-prefixed entries, so a complete map does not hide `.env.defaults` or `.github`; richer patterns use {§path-glob-matching}. SQLite prefix queries may reduce the candidate set but never decide the match. A trailing slash is a recursive FIND scope only for a scheme whose manifest declares `folderScopes: true`; otherwise it is ordinary resource syntax. This is an explicit extension contract, never inferred from URL punctuation.
|
|
2727
2824
|
|
|
2728
2825
|
Resource-authority globs select authorities independently of the path scope.
|
|
2729
2826
|
Matching resources retain their full addresses through pattern matching,
|
|
@@ -2754,8 +2851,8 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2754
2851
|
with no addressable location is status 200 with `matchingPathCount: 1`,
|
|
2755
2852
|
`matchLocationCount: 0`, and no fabricated row; a matcher selecting no
|
|
2756
2853
|
resource is 204. A matcher-less broad empty catalog survey is status 200; an
|
|
2757
|
-
absent exact resource is 404. Every entry-channel location
|
|
2758
|
-
|
|
2854
|
+
absent exact resource is 404. Every entry-channel location in `results` names
|
|
2855
|
+
its `channel`; log rows carry none.
|
|
2759
2856
|
|
|
2760
2857
|
Inside `FindResult`, `matchingPathCount` and `matchLocationCount` describe the
|
|
2761
2858
|
complete selection before pagination; the packet curates those facts under
|
|
@@ -2774,9 +2871,11 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2774
2871
|
code points including a visible terminal ellipsis, so a row stays one line
|
|
2775
2872
|
of orientation; an invocation-form witness — a summary that is one fenced
|
|
2776
2873
|
operation, the shape a runtime's tool summary takes
|
|
2777
|
-
({§tools-resource-materialization})
|
|
2778
|
-
|
|
2779
|
-
|
|
2874
|
+
({§tools-resource-materialization}), kept on one summary line by writing each
|
|
2875
|
+
newline as `\n` — is shown whole, every tool named and its newlines restored
|
|
2876
|
+
so the row's JSON escapes each once, because the discovery row exists so the
|
|
2877
|
+
model can invoke without a READ and a menu that is cut is no menu. Absent
|
|
2878
|
+
metadata is omitted.
|
|
2780
2879
|
|
|
2781
2880
|
Resource-level `stream` and broad-match
|
|
2782
2881
|
`matchLocationCount` live only on `[0]`. A single-channel resource is therefore
|
|
@@ -2794,22 +2893,91 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2794
2893
|
rank for `~`full-text and candidate order otherwise; location order is dialect
|
|
2795
2894
|
order and exact duplicates deduplicate. The intended drill-down is broad FIND
|
|
2796
2895
|
to choose paths, exact-target FIND to choose locations, then exact READ.
|
|
2797
|
-
`content` uses the shared generated-JSON projection
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2896
|
+
`content` uses the shared generated-JSON projection ({§json-result-rendering}),
|
|
2897
|
+
so universal packet numbering makes result ordinal N addressable as line N,
|
|
2898
|
+
matching `<N>` pagination without a second coordinate system. It translates
|
|
2899
|
+
only this final model-facing representation: `weight` reads `tokens`, a
|
|
2900
|
+
`region` or `enclosingRegion` reads in the one scope notation `<SL,SC,EL,EC>`
|
|
2901
|
+
({§packet-extent-metadata}), and a location names its `channel` only when that
|
|
2902
|
+
is not the resource's default channel ({§channel-selection-visibility}). A
|
|
2903
|
+
location therefore reads `{"region":"<48,1,48,25>","matched":"class BaseCrossValidator"}`.
|
|
2904
|
+
A returned page begins at `range.returned[0]`, and every
|
|
2802
2905
|
page left-pads its ordinals to the decimal width of `range.total`; content
|
|
2803
2906
|
therefore keeps one stable column across the complete result set. Pagination is the only FIND materialization bound; no
|
|
2804
2907
|
hidden complete row or location collection is retained behind the public
|
|
2805
2908
|
projection.
|
|
2806
2909
|
|
|
2910
|
+
§path-glob-matching Core's `PathGlob` owns shell-path matching and targeted disk
|
|
2911
|
+
traversal through the public `minimatch` and `glob` packages. Resource selection,
|
|
2912
|
+
membership scans, inspection and the membership SQL predicate share this dialect.
|
|
2913
|
+
|
|
2914
|
+
| Input | Meaning |
|
|
2915
|
+
| --- | --- |
|
|
2916
|
+
| `/` | Segment separator; `*` and `?` do not cross it. |
|
|
2917
|
+
| `\*`, `\?`, `\[`, `\\` | Literal wildcard, bracket or backslash, after target-slot decoding ({§path-parentheses}). A backslash is never a pattern's directory separator. |
|
|
2918
|
+
| Braces, character classes, extglobs, `**` | Standard matcher semantics; operation catalogs additionally apply {§find-scope-prefix-filter}. |
|
|
2919
|
+
| Leading `#` or `!` | Filename syntax, not matcher-level comment or negation. The members family owns its leading `!` exclusion marker. |
|
|
2920
|
+
| Dot-prefixed entries | Require an explicit dot except in the complete structural catalogs above. |
|
|
2921
|
+
| Filesystem base | Literal, outside the pattern; its metacharacters and backslashes never become selector syntax. |
|
|
2922
|
+
|
|
2923
|
+
Matching retains the host's conventional case behavior (case-insensitive on
|
|
2924
|
+
Windows/macOS, case-sensitive otherwise). Membership traversal remains
|
|
2925
|
+
pattern-bounded and admits files only; it does not become an unrestricted walk.
|
|
2926
|
+
|
|
2807
2927
|
### §send Messaging and turn disposition
|
|
2808
2928
|
|
|
2809
2929
|
SEND AST: `{ op: "SEND", target: ParsedPath | null, body: SendBody | null, metadata, lineMarker }`.
|
|
2810
2930
|
|
|
2811
|
-
- **Message:** SEND delivers to an actor, endpoint or exact message address. Targetless SEND
|
|
2812
|
-
- **Workflow:** WAIT yields.
|
|
2931
|
+
- **Message:** SEND delivers to an actor, endpoint or exact message address. Targetless SEND selects the oldest published Open Message. Only explicit completion metadata resolves a message ({§message-completion}).
|
|
2932
|
+
- **Workflow:** WAIT yields. The loop concludes from resolved messages, settled work and observed results ({§loop-completion}). NOTE retains memory; KILL names something to cancel or curate.
|
|
2933
|
+
|
|
2934
|
+
§message-completion **Reply delivery and message completion are distinct.**
|
|
2935
|
+
|
|
2936
|
+
| Reply metadata | Delivery | Message obligation |
|
|
2937
|
+
|---|---|---|
|
|
2938
|
+
| No completion code | Deliver the authored text and attachments | Remains open |
|
|
2939
|
+
| `[200]` | Deliver the final answer | Completed |
|
|
2940
|
+
| `[499]` | Deliver the cancellation explanation | Cancelled; no worker or execution is cancelled implicitly |
|
|
2941
|
+
|
|
2942
|
+
The numeric modifier belongs to SEND's reply metadata, not its text scope. It
|
|
2943
|
+
composes with attachment metadata. Completion applies only to replies: an exact
|
|
2944
|
+
message address selects that message. Targetless SEND selects the oldest published
|
|
2945
|
+
Open Message in its loop at dispatch time. Progress leaves it open; `[200]` or
|
|
2946
|
+
`[499]` resolves it, so the next targetless SEND selects the next Open Message.
|
|
2947
|
+
With none open, a targetless SEND is speech to the loop's latest published message: it is
|
|
2948
|
+
delivered to that message's originating client and recorded in `answers`, and a completion
|
|
2949
|
+
code on it changes no outcome. Only a loop with no published message refuses it. It never
|
|
2950
|
+
broadcasts; a correction that changes an outcome names the message explicitly. Empty completion replies
|
|
2951
|
+
resolve their selected messages without inventing speech or erasing an earlier
|
|
2952
|
+
answer. An empty addressed progress reply adds no speech. Failed delivery resolves nothing.
|
|
2953
|
+
The latest explicit completion reply determines each message's outcome; ordinary
|
|
2954
|
+
progress replies never reopen a completed message. Curation changes neither
|
|
2955
|
+
delivery nor completion. Replies and ambient observations do not become requests.
|
|
2956
|
+
|
|
2957
|
+
Completion replies execute in authored order, including alongside mutations and
|
|
2958
|
+
other replies. Their bodies are delivered immediately, never held as drafts to
|
|
2959
|
+
replay. Later results can require further work or a corrected answer without
|
|
2960
|
+
retracting an earlier delivery. The message outcome is distinct from the SEND
|
|
2961
|
+
operation's delivery status and from the loop's execution outcome.
|
|
2962
|
+
After all obligations settle, the loop succeeds if any message completed; it is
|
|
2963
|
+
cancelled only when every message was cancelled. This does not invoke worker-tree
|
|
2964
|
+
cancellation. Engine failures retain their own outcomes.
|
|
2965
|
+
|
|
2966
|
+
§loop-completion **The loop concludes from discharged obligations, not a terminating operation.**
|
|
2967
|
+
A model loop is eligible only when all its messages have explicit completion
|
|
2968
|
+
replies, every held child and non-detached stream has settled, and every required
|
|
2969
|
+
result has crossed a packet boundary. New arrivals guard the terminal transition
|
|
2970
|
+
atomically. An operation-free turn creates no additional observation obligation;
|
|
2971
|
+
it is neither a completion command nor a separate acknowledgement mode. NOTE and
|
|
2972
|
+
successful curation retain the observation exemptions in {§send-premature-terminate}.
|
|
2973
|
+
With unresolved messages, no-operation recovery still applies. Malformed emissions,
|
|
2974
|
+
known output truncation, omitted operations and provider failures cannot conclude
|
|
2975
|
+
the loop by absence of operations. Administrative programs close only their own
|
|
2976
|
+
transaction.
|
|
2977
|
+
|
|
2978
|
+
When all messages are resolved but new results require another packet, the engine
|
|
2979
|
+
reports only: `All Open Messages resolved. Review new results; emit no OPs if finished.`
|
|
2980
|
+
The notice creates no state and does not demand another final reply.
|
|
2813
2981
|
|
|
2814
2982
|
§worker-obligations A worker holds its unresolved children and open non-detached
|
|
2815
2983
|
streams (`worker_obligations`); `loop_obligations` names them per loop. The
|
|
@@ -2823,19 +2991,19 @@ same durable liveness.
|
|
|
2823
2991
|
| Worker or loop already cancelled/terminal | Preserve that result. |
|
|
2824
2992
|
| Administrative program | Finish its transaction without adjudicating another model loop's work. |
|
|
2825
2993
|
| New unpublished message | Continue; publish it in the next packet. |
|
|
2826
|
-
| Fresh operation/parser failure, without an authored WAIT | Continue before any automatic parking. |
|
|
2827
|
-
|
|
|
2828
|
-
|
|
|
2829
|
-
|
|
|
2994
|
+
| Fresh operation/parser failure or incomplete emission, without an authored WAIT | Continue before any automatic parking. |
|
|
2995
|
+
| Authored WAIT and live work | Park the same loop; message arrival, child or stream settlement, or wait expiry wakes it ({§worker-wait-timing}). |
|
|
2996
|
+
| Fresh failure or incomplete emission after an empty WAIT | Continue; the WAIT cannot conceal the failure. |
|
|
2997
|
+
| Any unresolved message | Continue; an operation-free turn receives {§empty-turn} recovery. |
|
|
2830
2998
|
| Unobserved operation results, failures, child results or stream conclusions | Continue; the next packet presents them. |
|
|
2831
|
-
|
|
|
2999
|
+
| All messages resolved and results observed, live work remains | Join that work with the configured bounded park. Replies remain delivered. |
|
|
3000
|
+
| All messages resolved, results observed, no live work | Conclude with the aggregate message outcome ({§message-completion}). |
|
|
2832
3001
|
|
|
2833
3002
|
An empty emission is handled by {§empty-turn}. Ordinary strikes, cycles and
|
|
2834
|
-
execution limits remain independent.
|
|
2835
|
-
|
|
2836
|
-
and every other operational result require observation.
|
|
3003
|
+
execution limits remain independent. Observation exemptions follow
|
|
3004
|
+
{§send-premature-terminate}; they never resolve a message implicitly.
|
|
2837
3005
|
|
|
2838
|
-
§loop-response-messages **A response is a recorded delivery.** A successful SEND reply
|
|
3006
|
+
§loop-response-messages **A response is a recorded delivery.** A successful SEND reply records
|
|
2839
3007
|
the exact message addresses it answers. All replies remain independently recoverable in
|
|
2840
3008
|
message history, in execution order, regardless of producer. An actor-addressed SEND that
|
|
2841
3009
|
does not answer a message, WAIT, NOTE, asides, inherited rows and ambient observations are
|
|
@@ -2862,69 +3030,52 @@ accounting and model-visible failure evidence remain separately owned by
|
|
|
2862
3030
|
or a scheme that implements SEND (an `https://` POST). A SEND to a scheme the model may not write (the
|
|
2863
3031
|
log) is refused 400 `send-target-not-a-recipient`, never the unrelated writer
|
|
2864
3032
|
rule. The detail states only that the addressed scheme is not a recipient;
|
|
2865
|
-
|
|
2866
|
-
|
|
3033
|
+
recovery names valid recipients without guessing which was intended.
|
|
3034
|
+
A scheme that does not implement SEND
|
|
2867
3035
|
answers its ordinary factual 501 without grafting a guessed recovery onto it.
|
|
2868
3036
|
- §send-response-receipt **A reply records exactly which messages it answers.** A successful
|
|
2869
|
-
reply carries `answers`, the immutable message addresses it answered, not recipient actors.
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
delivers nothing, carries no `answers`, and cannot erase an earlier reply. An accepted
|
|
2874
|
-
parameterless KILL answer uses the same reply routing and empty-body rules. SEND to an exact message
|
|
3037
|
+
reply carries `answers`, the immutable message addresses it answered, not recipient actors.
|
|
3038
|
+
Targetless replies select the oldest published Open Message or, with none open, the
|
|
3039
|
+
loop's latest published message as speech only ({§message-completion}); they never broadcast.
|
|
3040
|
+
Empty completion replies still name their messages. SEND to an exact message
|
|
2875
3041
|
address answers only that message; SEND to an actor endpoint remains ordinary communication
|
|
2876
3042
|
and answers no assignment implicitly. An unpublished arrival cannot be answered by the
|
|
2877
3043
|
targetless shorthand. Failed delivery answers nothing. Reply accounting reads executed
|
|
2878
3044
|
delivery evidence, never log visibility or the mere existence of a later SEND.
|
|
2879
|
-
- §
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
completion or returns a non-striking continuation/parking receipt explaining the
|
|
2890
|
-
outstanding condition. Valid sibling operations always execute. Only an admitted
|
|
2891
|
-
KILL delivers its literal body through {§send-response-receipt}; a deferred body
|
|
2892
|
-
remains forensic evidence, never a stored draft to replay automatically. An empty
|
|
2893
|
-
KILL concludes silently even when an observed message has no delivered answer. It neither
|
|
2894
|
-
invents delivery nor replaces an earlier answer; immutable input and reply history remain intact.
|
|
2895
|
-
SEND, NOTE and targeted KILL never request successful
|
|
2896
|
-
completion. New arrivals still guard the terminal transition atomically
|
|
2897
|
-
({§completion-defers-to-messages}); an unobserved arrival concurrent with completion
|
|
2898
|
-
keeps the loop running. No implicit successful exit exists.
|
|
2899
|
-
- §outside-text **Text outside the operations is the turn's `outside` source: stored, weighed, never a row.**
|
|
2900
|
-
The spans {§response-text} supplies are stored verbatim as one immutable `outside` turn source
|
|
2901
|
-
per admitted emission, in source order joined by a blank line ({§turn-source-resources}); no
|
|
2902
|
-
operation is minted for them, a repetitive or length-cut response stays one source, and nothing
|
|
2903
|
-
filters what is stored. The model hears only the weight: the next packet's Notices section
|
|
2904
|
-
carries `outside_text: N tokens emitted outside OPs. Discarded.`, N by {§tokenomics-agnostic-ruler};
|
|
2905
|
-
the text itself never enters a packet, not even inside its turn's emission ({§emission-row}), is never delivered and never concludes.
|
|
2906
|
-
{§empty-turn} still strikes a turn that holds only text, with unchanged
|
|
2907
|
-
reply accounting and completion rules. A log-entry heading in
|
|
3045
|
+
- §outside-text **Text outside the operations is annotation beside them, and an empty turn without them.**
|
|
3046
|
+
The spans {§response-text} supplies are read with the turn's fenced operations. Beside at least one
|
|
3047
|
+
fenced content operation, each span is one `NOTE` at its position: it joins the admitted program as the
|
|
3048
|
+
model's own NOTE, frozen in the emission ({§emission-row}), lands as a NOTE row, replays with its turn
|
|
3049
|
+
({§emission-history}) and draws no notice; the card's annotation register is where such text belongs.
|
|
3050
|
+
With no fenced operation in the turn, no operation is minted: the spans are stored verbatim as one
|
|
3051
|
+
immutable `outside` turn source per admitted emission, in source order joined by a blank line
|
|
3052
|
+
({§turn-source-resources}), a repetitive or length-cut response stays one source, nothing filters what
|
|
3053
|
+
is stored, and the turn is an empty turn ({§empty-turn}) whose error row is the one thing the model
|
|
3054
|
+
hears of it; the text never enters a packet, is never delivered and never concludes. A log-entry heading in
|
|
2908
3055
|
outside text still rejects the attempt unless it echoes an emission row ({§fabricated-log-entry}); an unfenced operation line is
|
|
2909
|
-
not response text ({§unfenced-operation}) and so
|
|
3056
|
+
not response text ({§unfenced-operation}) and so reaches neither home. Clients receive an outside source once through
|
|
2910
3057
|
`outside/event` ({§notifications-outside-event}, {§agui-outside-text}); FORK snapshots the
|
|
2911
3058
|
source with the turn's others; the digest names its weight. It has no address: there is no
|
|
2912
3059
|
`outside://` scheme, and exact emissions remain at `ops://`. This is evidence, not an alternate
|
|
2913
3060
|
authoring format: the `plurnk.md` requirement to use only valid Plurnk OPs remains, and
|
|
2914
3061
|
{§response-text} alone owns which bytes are operations, quotations or outside text.
|
|
2915
3062
|
- §loop-answer **A loop's address is what it said.** READ `ops://<worker>/<loop>` resolves to
|
|
2916
|
-
the latest reply the loop gave to the message that started it: the body of a SEND
|
|
2917
|
-
|
|
3063
|
+
the latest nonempty reply the loop gave to the message that started it: the body of a SEND
|
|
3064
|
+
that answered that message. A failed terminal takes precedence over
|
|
2918
3065
|
an earlier reply and retains its exact Problem, including {§terminal-evidence}. A running loop
|
|
2919
3066
|
without a reply is 425; a concluded loop without one returns its terminal outcome, including
|
|
2920
3067
|
successful silence. Completion never fabricates an answer or a missing-resource failure.
|
|
2921
3068
|
`ops://<worker>/<loop>/<turn>`
|
|
2922
3069
|
remains that turn's emission. A concluded child's `loop_termination` row to its parent
|
|
2923
3070
|
READs this same loop resource. Witness: `test/intg/loop-answer.test.ts`.
|
|
2924
|
-
- §empty-turn **No
|
|
3071
|
+
- §empty-turn **No operations resolve no messages.**
|
|
2925
3072
|
Count parsed content operations and admitted reasoning operations ({§reasoning-operations}), a NOTE in
|
|
2926
|
-
either channel among them; outside text ({§outside-text}) never enters the count. When none exist
|
|
2927
|
-
|
|
3073
|
+
either channel among them; outside text ({§outside-text}) never enters the count. When none exist,
|
|
3074
|
+
no boundary was lost, and messages remain unresolved or the emission is known incomplete,
|
|
3075
|
+
retain the turn and its raw sources and count one progress-contract strike, whether or not
|
|
3076
|
+
the turn carried text. Once messages are resolved, an intact operation-free turn is adjudicated
|
|
3077
|
+
normally under {§loop-completion}; absence of operations is not a new lifecycle signal.
|
|
3078
|
+
The strike sends no notice of its own: the turn records one `_plurnk`
|
|
2928
3079
|
error row, `422` `The turn performed no operation.`, which rides the next packet's errors like
|
|
2929
3080
|
any failure ({§operation-result-uniform-error-channel}); the threshold terminal still says why ({§engine-rails}).
|
|
2930
3081
|
An empty turn uses its exact text as the cycle fingerprint ({§engine-cycle-evidence});
|
|
@@ -2943,7 +3094,7 @@ accounting and model-visible failure evidence remain separately owned by
|
|
|
2943
3094
|
({§turn-ops-entry}: the reader READs the source, and an emission of any length never rides
|
|
2944
3095
|
wholesale into a parent's packet). The member is named for what it is — an emission left
|
|
2945
3096
|
unconcluded — and never `answer`: the harness cannot warrant that text is complete or final,
|
|
2946
|
-
because
|
|
3097
|
+
because its obligations did not settle under {§loop-completion}. Earlier deliveries remain delivered;
|
|
2947
3098
|
the citation neither sends them again nor destroys them. A terminal whose last inference
|
|
2948
3099
|
turn performed authored operations carries no `unconcluded`: an absent member is not an
|
|
2949
3100
|
empty one. Attachment is owned by the one terminal seam.
|
|
@@ -2955,25 +3106,22 @@ accounting and model-visible failure evidence remain separately owned by
|
|
|
2955
3106
|
executions, WORK and FORK own their input and receive it whole ({§send-resource-attachments},
|
|
2956
3107
|
{§env-option}); a key they do not take is their own 400.
|
|
2957
3108
|
- §send-idle-turn **NOTE is memory, not a yield.** NOTE does not imply parking.
|
|
2958
|
-
A NOTE-only response does not
|
|
3109
|
+
A NOTE-only response does not resolve a message or create an observation obligation.
|
|
3110
|
+
The ordinary obligation check still runs ({§loop-completion}).
|
|
2959
3111
|
Repetition remains subject to {§engine-cycle-evidence}.
|
|
2960
3112
|
- §send-premature-terminate **Completion follows observation.** Every fired operation except
|
|
2961
3113
|
SEND, NOTE, WAIT and successful KILL requires a subsequent packet. This barrier uses durable
|
|
2962
3114
|
executed evidence, not curated rows. Fast completion, an empty result or curation cannot
|
|
2963
3115
|
erase it. New arrivals are protected by {§completion-defers-to-messages}; no terminal verb
|
|
2964
3116
|
or prose overrides this rule.
|
|
2965
|
-
- §completion-joins-live-work **
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
own disposition. Only targeted KILL owns cancellation; parameterless KILL never
|
|
2970
|
-
cancels work and delivers no final answer while joining.
|
|
3117
|
+
- §completion-joins-live-work **Resolved messages do not abandon held work.** Once messages
|
|
3118
|
+
and observation obligations are resolved, the loop joins live children and non-detached
|
|
3119
|
+
streams through the existing bounded wait. Each wake presents newly settled state.
|
|
3120
|
+
Neither completion nor message cancellation cancels that work.
|
|
2971
3121
|
- §completion-defers-to-results **Results keep the loop running until observed.** Same-turn
|
|
2972
3122
|
operations and failures, plus undelivered child or stream conclusions, require the next
|
|
2973
|
-
packet. This is ordinary continuation, not a strike.
|
|
2974
|
-
|
|
2975
|
-
replies remain delivered. If observation warrants no further work or revision, a
|
|
2976
|
-
lone empty parameterless KILL requests completion without repeating an earlier answer.
|
|
3123
|
+
packet. This is ordinary continuation, not a strike. SEND replies remain delivered.
|
|
3124
|
+
If observation warrants no further work or revision, no additional operation is needed.
|
|
2977
3125
|
- §send-administrative-terminal **Administrative programs close their own transaction.**
|
|
2978
3126
|
Their caller closes the administrative loop after execution; no terminal operation is
|
|
2979
3127
|
manufactured. Initialization runs in the model loop without concluding it.
|
|
@@ -2982,7 +3130,8 @@ accounting and model-visible failure evidence remain separately owned by
|
|
|
2982
3130
|
observed only after crossing a packet boundary. WAIT parks only on
|
|
2983
3131
|
live obligations. If work has completed but is unobserved, it continues
|
|
2984
3132
|
directly to the next packet because the wake edge has already fired. A genuinely
|
|
2985
|
-
empty wait
|
|
3133
|
+
empty wait creates no future wake; ordinary obligation adjudication still applies
|
|
3134
|
+
under {§wait-obligation-matrix}.
|
|
2986
3135
|
|
|
2987
3136
|
### §exec-input SEND to a running execution
|
|
2988
3137
|
|
|
@@ -3052,8 +3201,9 @@ site.** A bare shell command whose program is the name of a tool published by
|
|
|
3052
3201
|
another enabled runtime (`brave_web_search {…}` under the default shell) exits
|
|
3053
3202
|
127; the stream's terminal receipt then says the program is a tool of that
|
|
3054
3203
|
runtime, names the tool's own document, and carries `toolRuntimes` and `tool`;
|
|
3055
|
-
it builds no invocation ({§diagnostic-observation}).
|
|
3056
|
-
|
|
3204
|
+
it builds no invocation ({§diagnostic-observation}). That receipt is core's `404 program-is-a-tool` with
|
|
3205
|
+
`exitCode: 127`: the named program did not run. Nothing is rerouted, and a program the
|
|
3206
|
+
registry does not know keeps the shell's own answer, a 200 receipt with `exitCode: 127`.
|
|
3057
3207
|
|
|
3058
3208
|
| Declared target kind | Authored target | Canonical effect target | Executor realization |
|
|
3059
3209
|
| -------------------- | --------------------------------------- | ----------------------- | --------------------------------------------------------- |
|
|
@@ -3267,8 +3417,8 @@ it: an immediate slot is `200 { outcome: "started" }`; delayed work is
|
|
|
3267
3417
|
`202 { outcome: "queued", executionsAhead, concurrency }`, and the channel stays
|
|
3268
3418
|
`active` in the existing live sense — output growth and terminal settlement are the
|
|
3269
3419
|
current truth. Admission is FIFO within the workspace; queue residence does not consume
|
|
3270
|
-
the execution timeout; a KILL while queued never invokes the executor and
|
|
3271
|
-
stream
|
|
3420
|
+
the execution timeout; a KILL while queued never invokes the executor and concludes the
|
|
3421
|
+
stream as any KILL does ({§stream-control}). The scheduler is the exec scheme's; the knob is the
|
|
3272
3422
|
service's ({§operator-config}), fail-hard on any other value.
|
|
3273
3423
|
|
|
3274
3424
|
§exec-stream-page **An unrequested delivery never exceeds the retrieval page.** The
|
|
@@ -3292,7 +3442,10 @@ channel that holds content, and an empty sibling channel is a fact on that row
|
|
|
3292
3442
|
(`channels: {"#stderr": 0}`), never a row of its own; only a stream that printed
|
|
3293
3443
|
nothing on any channel lands one bodyless conclusion row, on its default
|
|
3294
3444
|
channel, whose terminal fact, causal execution link, and available exit code make
|
|
3295
|
-
completion explicit without invented narration. A
|
|
3445
|
+
completion explicit without invented narration. A failed execution is one failure: its
|
|
3446
|
+
terminal status and Problem ride its default channel's row when that row landed, else its
|
|
3447
|
+
first, and its other rows are 200 reads of their channels, so it puts one pointer in Errors
|
|
3448
|
+
({§operation-results}). A skipped channel's publication is still marked
|
|
3296
3449
|
terminal, so the stream's termination is delivered and never left pending. KILL may curate
|
|
3297
3450
|
that log row without rewinding the cursor or publishing the terminal result
|
|
3298
3451
|
again; the exact terminal result and channel content remain READable at the
|
|
@@ -3310,7 +3463,7 @@ The runtime scheme participates in the durable lookup; a completed `sh:///`
|
|
|
3310
3463
|
stream cannot fall through an internal `exec`-only query. {§stream-control}
|
|
3311
3464
|
|
|
3312
3465
|
§workspace-env **Workspace environment.** The `env` family has workspace defaults and
|
|
3313
|
-
worker overrides. Its
|
|
3466
|
+
worker overrides. Its management verbs accept `scope: "workspace" | "worker"`; model calls
|
|
3314
3467
|
default to `worker`. Client actions bind the scope in `workspace.env.*` or
|
|
3315
3468
|
`worker.env.*`. An explicit scope must agree with that action's context.
|
|
3316
3469
|
|
|
@@ -3328,35 +3481,26 @@ lower entry and its enabledness ({§configuration-definition-resolution}). Forki
|
|
|
3328
3481
|
affect subsequent launches, not existing processes or other workspaces. A shared
|
|
3329
3482
|
capability never acquires an invoking worker's overrides or ownership.
|
|
3330
3483
|
|
|
3331
|
-
§exec-env-scoped **
|
|
3332
|
-
environment
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
`NPM_TOKEN` to every command a model writes. Membership is an allowlist: the shipped
|
|
3352
|
-
`INHERIT` is what a shell, git, node and python need to run, and an operator who wants a
|
|
3353
|
-
tool's credential reachable by model-written commands adds it by name. An empty policy admits
|
|
3354
|
-
nothing ambient — the allowlist is declared in `.env.defaults`, so an empty one is a cleared
|
|
3355
|
-
policy rather than an unconfigured install.
|
|
3356
|
-
|
|
3357
|
-
The full composition for one spawn, nearest setter winning for defaults and ceilings immune,
|
|
3358
|
-
is package floors → operator cascade → ambient policy → workspace entries → worker entries → the op's modifier →
|
|
3359
|
-
body prefixes.
|
|
3484
|
+
§exec-env-scoped **Command environment admission.** Core composes an ordinary executor's
|
|
3485
|
+
environment; the executor spawns with the environment it is handed ({§workspace-env}).
|
|
3486
|
+
|
|
3487
|
+
| Input | Admission |
|
|
3488
|
+
|---|---|
|
|
3489
|
+
| Ambient host values | `PLURNK_SERVICE_EXEC_ENV_INHERIT` admits exact names or one trailing-`*` prefix glob; `_EXCLUDE` removes names with the same syntax. An empty inherit list admits nothing. |
|
|
3490
|
+
| Reserved names | `PLURNK_*` and provider credential names from the model catalog or `PLURNK_PROVIDERS_PROVIDER_<ID>_API_KEY_ENV` are excluded from the ambient base regardless of those selectors. |
|
|
3491
|
+
| Workspace and worker entries | Explicit non-reserved values and masks compose at spawn under {§env-functionality}. Reserved names are refused at admission. |
|
|
3492
|
+
| Invocation `env` | Explicit non-reserved values override the composed environment under {§env-option}; the same reserved-name refusal applies. |
|
|
3493
|
+
|
|
3494
|
+
Explicit values do not widen ambient inheritance. The allowlist is declared under
|
|
3495
|
+
{§operator-config-env-defaults}; it limits other host credentials too, not only provider keys.
|
|
3496
|
+
Each spawn records admitted values and their provenance (host, workspace, worker, inherited
|
|
3497
|
+
worker, modifier, or masked); the digest renders that record beside the operation.
|
|
3498
|
+
|
|
3499
|
+
This is environment admission, not process containment or a prohibition on an approved
|
|
3500
|
+
program setting its own variables. Module-owned launches use the owning module's contract:
|
|
3501
|
+
the host supplies a filtered ambient base through {§module-seam-slices}, while explicit
|
|
3502
|
+
MCP bindings resolve under {§mcp-launch-environment}. The env family's reservation does not
|
|
3503
|
+
filter those explicit bindings or create a second approval path.
|
|
3360
3504
|
|
|
3361
3505
|
- §env-option **The op's environment.** `env` is the service's key in the heading's `[metadata]`
|
|
3362
3506
|
({§scheme-metadata-modifier}): `[{"env": {"NAME": "value"}}]`, an object of string values.
|
|
@@ -3366,7 +3510,8 @@ body prefixes.
|
|
|
3366
3510
|
retain explicit launch overrides when adding a process-backed definition; it never
|
|
3367
3511
|
persists the composed ambient environment. On
|
|
3368
3512
|
WORK and FORK it is the child's starting environment: after the copy the child inherits
|
|
3369
|
-
({§functionality-scope}), each name
|
|
3513
|
+
({§functionality-scope}), each supplied name replaces its copied definition as an enabled child-owned entry
|
|
3514
|
+
through the family's `replace` and `enable`,
|
|
3370
3515
|
so a parent hands down its registry and overrides specific names for one child in one heading.
|
|
3371
3516
|
Names follow the family's admission — a name a shell can export, never plurnk's own — and a
|
|
3372
3517
|
refusal names the key and the reason at the operation, before anything runs or is created; a
|
|
@@ -3398,7 +3543,21 @@ body prefixes.
|
|
|
3398
3543
|
- **Loop disposition** ({§proposal-disposition}) — core applies the exact automatic accept/reject before observational subscribers run; automatic policy is not an event listener or client fallback.
|
|
3399
3544
|
- §proposal-timeout-cancels **Timeout is OPT-IN; an empty deadline WAITS** - an empty `PLURNK_SERVICE_PROPOSAL_TIMEOUT_MS` means a pending proposal - a file edit awaiting review - waits indefinitely for its human: absence is not an answer, so the service does not synthesize a cancellation. A finite positive millisecond value establishes the bound; then elapsing synthesizes `cancel` (outcome `timeout`), server-side, needing no client. Every other explicit value fails at the proposal lifecycle owner and terminalizes an already-written proposal rather than silently choosing an indefinite wait. Indefinite is with respect to the clock alone: the wait ends with its loop. A loop whose signal aborts — its own timeout, `loop.cancel`, worker `KILL` — settles every proposal it is holding through {§proposal-cancel-aborts}, carrying the abort's reason as the outcome, because a cancelled loop is not a loop awaiting a decision.
|
|
3400
3545
|
|
|
3401
|
-
|
|
3546
|
+
§proposal-decision-evidence Each proposal has at most one immutable decision record,
|
|
3547
|
+
committed before application. It contains the original accept/reject/cancel,
|
|
3548
|
+
resolver identity, decision time, and any submitted body override and outcome.
|
|
3549
|
+
Client decisions name the authenticated worker owner; automatic policy, timeout,
|
|
3550
|
+
abort, and shutdown decisions name `_plurnk`. This records the resolving authority,
|
|
3551
|
+
not an assertion that a human reviewed the operation. A failed decision write
|
|
3552
|
+
prevents application and surfaces its cause. The applied result is separate:
|
|
3553
|
+
acceptance followed by failure remains acceptance. Restart preserves recorded
|
|
3554
|
+
decisions, marks interrupted application uncertain, and never replays it
|
|
3555
|
+
({§worker-lifecycle-restart-recovery}). Decision evidence follows its operation's
|
|
3556
|
+
history lifetime, survives log curation, and appears in forensic output, not in
|
|
3557
|
+
the model packet. Historical rows receive no invented decisions.
|
|
3558
|
+
|
|
3559
|
+
**The decision drives a one-way state transition** on `log_entries.state`.
|
|
3560
|
+
A second resolution is refused with `409 proposal-not-pending`:
|
|
3402
3561
|
|
|
3403
3562
|
| decision | state | `status_rx` | default outcome | effect |
|
|
3404
3563
|
|---------------------------------|---|---|---|---|
|
|
@@ -3549,6 +3708,7 @@ Model sees lifecycle events in the `log` section per turn.
|
|
|
3549
3708
|
|
|
3550
3709
|
- **Cancel:** ```` ```KILL (https://feed.example/x) ```` — the service invokes the handle registered by `subscriptions.open()` and aborts the composed subscription signal.
|
|
3551
3710
|
- **Kill:** ```` ```KILL (sh:///ab3d5678) ```` — the model terminates the addressed workspace stream. This is stream control, not a write: the output scheme's `writableBy` never gates it. A stream that already ended, killed or not, answers 200 with its recorded `terminalStatus`: the process is not running, which is what KILL asks for (#757); a stream that never existed answers 404 ({§runtime-resource-binding}). A queued execution ({§exec-concurrency}) is cancelled the same way and never enters its executor.
|
|
3711
|
+
- §stream-asked-stop **A stop that was asked for is no failure.** A stream stopped by a model KILL of either form from the worker that holds it concludes 200, with its `exitCode` when its producer reported one: the producer's 499 cancellation is replaced before the subscription settles, so the KILL's 200 receipt is the record and the conclusion row brings nothing into Errors ({§operation-results}). A cancellation its holder did not ask for — a peer's or a client's KILL, loop end, worker teardown, daemon stop — keeps its 499, and a lifetime keeps its 504.
|
|
3552
3712
|
- **WebSocket write:** ```` ```EDIT (wss://feed/x) ```` or ```` ```SEND (wss://feed/x) ```` with a body sends one whole text frame through the active owner. Either write can follow the opening READ in the same turn under {§op-execution-order}.
|
|
3553
3713
|
- **Other stream write:** ```` ```SEND (…) ```` remains scheme-defined, including exec stdin.
|
|
3554
3714
|
|
|
@@ -3570,6 +3730,26 @@ The model is NOT a stream/event consumer — turn-based only; sees whatever's in
|
|
|
3570
3730
|
|
|
3571
3731
|
SQLite (`node:sqlite`) with WAL mode and STRICT tables. Hand-written DDL; CI-aligned against grammar schemas.
|
|
3572
3732
|
|
|
3733
|
+
### §db-durability Connection durability
|
|
3734
|
+
|
|
3735
|
+
The service launcher applies `PLURNK_SERVICE_SQLITE_SYNCHRONOUS` through SqlRite's
|
|
3736
|
+
connection options before migrations or `INIT` write anything. The same policy
|
|
3737
|
+
reaches the writer and read pool on every open, including `migrate` and reopening
|
|
3738
|
+
an existing database. Its default lives in `.env.defaults`; an invalid value is
|
|
3739
|
+
diagnosed by `config check` and refuses database admission, never silently choosing
|
|
3740
|
+
a weaker mode. Configuration inspection and editing remain available.
|
|
3741
|
+
|
|
3742
|
+
| Mode | WAL guarantee |
|
|
3743
|
+
| --- | --- |
|
|
3744
|
+
| `FULL` | Each committed transaction is synchronized to storage, surviving application/OS crashes and power loss when the filesystem and device honor synchronization. |
|
|
3745
|
+
| `EXTRA` | Same guarantee as `FULL` in WAL mode. |
|
|
3746
|
+
| `NORMAL` | Consistent after a crash, but recent commits may be lost after an OS crash or power loss. |
|
|
3747
|
+
| `OFF` | Unsynchronized writes; a crash may corrupt the database. |
|
|
3748
|
+
|
|
3749
|
+
These are [SQLite's guarantees](https://www.sqlite.org/pragma.html#pragma_synchronous),
|
|
3750
|
+
not filesystem-write atomicity, external-effect rollback, a backup, or protection
|
|
3751
|
+
against storage hardware that fails to honor synchronization.
|
|
3752
|
+
|
|
3573
3753
|
### DDL strategy
|
|
3574
3754
|
|
|
3575
3755
|
No generator. SQLite-optimal: STRICT (3.37+), `INTEGER PRIMARY KEY` aliasing, explicit `NOT NULL`, indexed query paths, deliberate FK `ON DELETE`/`ON UPDATE`, `WITHOUT ROWID` where access pattern warrants, generated columns, FTS5.
|
|
@@ -3577,7 +3757,7 @@ No generator. SQLite-optimal: STRICT (3.37+), `INTEGER PRIMARY KEY` aliasing, ex
|
|
|
3577
3757
|
| Concern | Rule |
|
|
3578
3758
|
|---|---|
|
|
3579
3759
|
| §db-schema-baseline Baseline | Versions 1–8 of `migrations/` are the released baseline, as domain chapters — `001_workspaces`, `002_workers`, `003_loops`, `004_inference`, `005_entries`, `006_log`, `007_subscriptions`, `008_interactions` — each one `MIGRATE` block whose version is the file's numeric prefix. They create the shape 1.21.1 shipped: tables, indexes, views, the constraint triggers that are a table's invariants (guards that only `RAISE`), and a view's `INSTEAD OF` write path. No migration holds an `INIT` block or a trigger that writes a row. |
|
|
3580
|
-
| §db-migrations Evolution | A released version is frozen: only its comments may change. Every shape change is one new file at the next version, applied by sqlrite above the database's `PRAGMA user_version`, ascending, each in its own transaction with its version bump. A fresh database takes the same path as an existing one. Each migration carries upgrade coverage: `test/intg/schema-baseline.test.ts` pins the released shape's fingerprint and migrates a released database, asserting its rows survive. A process trigger's change needs no migration: its `INIT` block re-declares it on the next open ({§db-process-triggers}).
|
|
3760
|
+
| §db-migrations Evolution | A released version is frozen: only its comments may change. Every shape change is one new file at the next version, applied by sqlrite above the database's `PRAGMA user_version`, ascending, each in its own transaction with its version bump. A fresh database takes the same path as an existing one. Each migration carries upgrade coverage: `test/intg/schema-baseline.test.ts` pins the released shape's fingerprint and migrates a released database, asserting its rows survive. A process trigger's change needs no migration: its `INIT` block re-declares it on the next open ({§db-process-triggers}). Foreign keys stay enforced. Prefer column changes or guard-trigger replacement; rebuilding a referenced table requires copying its complete referencing subgraph first and replacing children before parents, with retained-row and foreign-key coverage. Dropping a parent alone would cascade away its children. |
|
|
3581
3761
|
| §validation-topology Where an invariant is enforced | The SQL core owns each invariant: a chapter's CHECK constraints and guard triggers are its one statement, and a rule two tables share is the same expression over each column (`entry_channel_producer_result_contract` and `subscriptions_result_contract_update` hold the settled-result rule as one text, `011_settled`). Contracts (JSON Schema) are enforced at the gates: a scheme's result entering core (`Results` in plurnk-schemes) and the wire leaving to clients (plurnk-agui's `Validator` calls). Everything between trusts core and the gates and carries no defensive re-validation: a result read back from a row is parsed, never re-asserted. Witness: `test/intg/validation-topology.test.ts` applies one corpus of settled results to the gate, to chapter 5 and to chapter 7 and asserts the three agree on every row. |
|
|
3582
3762
|
| Open failure | A missing table or column after migration means the file's shape disagrees with its version: a database from a newer release, or one from an unreleased development build. The daemon refuses to open it and names both remedies. |
|
|
3583
3763
|
| §db-process-triggers Processes beside their owners | A trigger that writes rows — a cascade, a capture, an ambient event, a publication cursor, a landed curation — is a process, not shape. It is declared as an `-- INIT: <trigger name>` block in the `.sql` file beside the statements that fire it (`ambient.sql` for the ambient feed, `LoopLifecycle.sql`, `Turn.sql`, `Engine.sql` for model calls, `_entry-crud.sql`, `Log.sql`, `ChannelWrite.sql`), as `DROP TRIGGER IF EXISTS` then `CREATE TRIGGER`, so the definition is current on every open of a database whose shape is current. `MIGRATE` always precedes `INIT` and `INIT` runs on the writer only, so a process may reference any table regardless of file order and never runs on the read pool. `test/intg/schema-composition.test.ts` fails on a baseline trigger that writes, an `INIT` trigger that only guards, a block not named after its trigger or not dropping first, and a live trigger set that differs from the declared set after a first and a second open. |
|
|
@@ -3586,11 +3766,43 @@ No generator. SQLite-optimal: STRICT (3.37+), `INTEGER PRIMARY KEY` aliasing, ex
|
|
|
3586
3766
|
| §db-maintenance-optimize Statistics at shutdown | The daemon's last database step before the caller closes SQLite is `PRAGMA optimize` on the writer (`maintenance_optimize`), so `sqlite_stat1` reflects tables the connection planned against, bounded by SQLite's own analysis limit; a failure there is a reported shutdown error, never silent. Retention runs before it under the operator's policy ({§retention-policy}) and ends with a WAL truncation ({§db-space-reclamation}); no periodic `ANALYZE` runs. |
|
|
3587
3767
|
| §db-space-reclamation The daemon keeps its own file healthy | `PLURNK_SERVICE_AUTO_VACUUM` (`incremental` or `none`) names the mode the daemon keeps its file in. At start, before any drain, a database in another mode is converted (set the mode, one `VACUUM`, which rewrites the file and needs free disk about its size) and the journal says so with page counts before and after. Under `incremental`, every retention pass ends by stepping `PRAGMA incremental_vacuum` to completion once free pages reach `PLURNK_SERVICE_RECLAIM_MIN_FREE_BYTES` (0 = every pass), and reports `reclaimedPages`; below the floor, free pages stay for SQLite to reuse. Under `none` the file never shrinks and freed pages are reused. No operator step is involved beyond the knobs. The WAL stays bounded by SQLite's automatic checkpoint (#764). |
|
|
3588
3768
|
| §content-store Every body is stored once | `contents` holds each settled body once, addressed by its SHA-256, however many channels, workspaces, forks or derivations carry it; rows are immutable. `entry_channel_rows` points a settled channel at its body and keeps an active stream's body as a private buffer until it settles, when it is interned. Every reader and writer uses the `entry_channels` view, whose `INSTEAD OF` triggers intern bodies, refuse a bound `content_hash` that is not the content's, and write each column group only when it changed, so a search attachment is never a representation write. SQLite counts no changes for a view, so a write that must know whether its channel exists returns the channel's name; an outer join cannot flatten the view, so the two statements that need one read `entry_channel_rows` and `contents` directly. `derivation_fts` is an external-content index over `derivation_texts` (a derivation joined to its body); `derivations.content_id` names the indexed text, and the triggers in `_entry-fts.sql` move the index with it and forget it on delete. A body no channel holds and no derivation indexes is collected by retention under `PLURNK_SERVICE_COLLECT_CONTENTS`. Witnesses: `test/intg/retention.test.ts`, `test/intg/entries.test.ts`, `test/intg/fulltext-index.test.ts`. |
|
|
3589
|
-
| §retention-policy Retention
|
|
3769
|
+
| §retention-policy Retention separates evidence classes | `Retention` reads the owning `.env.defaults` policy at daemon start and runs on its configured cadence and at shutdown. Packet count/age controls retire completed turns' `turn_sections`. Response controls atomically retire a logical call's normalized response and every physical-request payload, including failed retries; its immutable retirement timestamp remains. Count means the newest payload-bearing logical calls per loop, not individual retries, and retired calls retain their chronological place. Either bound can expire an item; `-1` disables only that bound. Open turns, calls and requests are excluded. Messages, log rows, turn sources, approval decisions, request identities, status, admission, failure, capacity and accounting follow their containing history's lifetime. Collectors remove unreferenced packet items, derivations, text and native contents ({§native-content-lifetime}); derivation deletion removes its search projections. These controls are not a whole-database size bound or content-erasure policy: canonical history can retain text also captured in a retired payload. Invalid policy withholds retention and storage conversion, reports a configuration diagnostic and leaves the repair environment available ({§configuration-repair-path}); storage I/O failures remain failures. Reclamation follows {§db-space-reclamation}. |
|
|
3770
|
+
|
|
3771
|
+
§native-content-lifetime Native snapshots remain while any retained READ result,
|
|
3772
|
+
message attachment (inbound or outbound), or stored packet references their hash.
|
|
3773
|
+
Log curation, reply completion, source replacement and source deletion do not
|
|
3774
|
+
release those historical references. `COLLECT_CONTENTS` removes only unreferenced
|
|
3775
|
+
native bytes, alongside unreferenced text. Resource operations and message
|
|
3776
|
+
admission share the in-flight content-use boundary with derivation work
|
|
3777
|
+
({§derivation-in-flight}): collection skips a busy boundary, new producers wait
|
|
3778
|
+
for an active collection, and success or failure releases the use. Operations
|
|
3779
|
+
remain concurrent; this boundary grants neither file ownership nor reservation.
|
|
3780
|
+
Interrupted, unpublished snapshots become collectible after restart. Containing
|
|
3781
|
+
history deletion releases its references normally.
|
|
3590
3782
|
|
|
3591
3783
|
- DDL = storage truth; JSON Schemas = wire truth. They are allowed to differ where ergonomics demand.
|
|
3592
3784
|
- §entry-identity-no-null **Identity components are never NULL.** `(workspace_id, scheme, authority, pathname)` is a unique key. `workspace_id` references the workspace directly with cascading deletion. Namespace schemes use empty authority; resource schemes retain their canonical authority. File members use nonempty `scheme="file"` and render as bare paths. Registration refuses `storedScheme: null`.
|
|
3593
3785
|
|
|
3786
|
+
### §db-query-report Workload query report
|
|
3787
|
+
|
|
3788
|
+
`report:sql <database.db> [specimens.json]` is an on-demand diagnostic, not a gate.
|
|
3789
|
+
It snapshots only the named database under {§share-snapshot}, registers the production
|
|
3790
|
+
SQL functions, and plans the source PREPs through SqlRite's own parser. It neither
|
|
3791
|
+
migrates nor runs application INIT blocks on that snapshot. Schema mismatch and query
|
|
3792
|
+
errors remain report failures, not empty successful results.
|
|
3793
|
+
|
|
3794
|
+
| Evidence | Meaning |
|
|
3795
|
+
|---|---|
|
|
3796
|
+
| `plans` | Unbound `EXPLAIN QUERY PLAN` rows for every effective PREP, including mutations; no mutation is executed. |
|
|
3797
|
+
| `scans` | Conservative hints: named table/view, indexed, virtual, or unresolved alias/intermediate. Raw details remain authoritative; a scan is not itself a defect. |
|
|
3798
|
+
| `measurements` | Only supplied `{statement, parameters}` specimens execute, with SQLite's query-only guard. Each retains its bound plan, row count, and one elapsed measurement; row bodies are not retained. |
|
|
3799
|
+
|
|
3800
|
+
Timings cover SQLite stepping and row conversion in the report process against the
|
|
3801
|
+
compacted private snapshot, not daemon IPC, application work, cold-cache latency, or a
|
|
3802
|
+
statistical distribution. No implicit workload discovery, synthetic corpus, automatic
|
|
3803
|
+
sampling, or performance threshold is applied. The report changes neither source data
|
|
3804
|
+
nor the existing query-plan gate.
|
|
3805
|
+
|
|
3594
3806
|
### §sql-ts-boundary SQL/TS responsibility boundary
|
|
3595
3807
|
|
|
3596
3808
|
**Lives in SQL:**
|
|
@@ -3878,19 +4090,21 @@ Each knob's value lives on its panel and nowhere else (`plurnk-service config de
|
|
|
3878
4090
|
| Var | Purpose |
|
|
3879
4091
|
|---|---|
|
|
3880
4092
|
| `PLURNK_SERVICE_DB_PATH` | SQLite file path; an explicit non-empty value overrides the derived default. |
|
|
4093
|
+
| `PLURNK_SERVICE_SQLITE_SYNCHRONOUS` | Connection-time WAL durability: `OFF`, `NORMAL`, `FULL` or `EXTRA` ({§db-durability}). |
|
|
3881
4094
|
| `PLURNK_SERVICE_SHARE_FOLDER` | Parent of the shares written when no folder is named ({§share-folder}); empty is `$XDG_STATE_HOME/plurnk/shares`. |
|
|
3882
4095
|
| §operator-config-shared-keys `PLURNK_HOST`, `PLURNK_PORT` | The daemon-owned listener's bind address and TCP port; modules mount their paths on that one listener ({§http-host}). **A key the daemon and its clients both read has a shared owner**: `@plurnk/plurnk-contracts` declares these two and the optional `PLURNK_AGUI_URL` on its own panel, the one package every side depends on. The daemon folds it like any installed member's, a client folds it beneath its own, and so neither holds the other's default. The service's `--host` and `--port` flags are generated from that panel. |
|
|
3883
4096
|
| §operator-config-git-ceiling `PLURNK_SERVICE_GIT_ALLOWED` | Hard service ceiling: only `1` admits Git membership and status; every other value denies them. |
|
|
3884
4097
|
| §operator-config-file-create-scope `PLURNK_SERVICE_FILE_CREATE_SCOPE` | Hard file-creation ceiling: `none < root < namespace`. `none` denies new filesystem files, `root` admits only paths inside `project_root`, and `namespace` also admits canonical outside-root paths. Existing-member writes are unaffected. |
|
|
3885
4098
|
| `PLURNK_SERVICE_FILE_MATERIALIZE_MAX_BYTES` | Byte ceiling in `1..104857600` for one workspace-file snapshot ({§membership-materialization-limit}). |
|
|
3886
4099
|
| `PLURNK_SERVICE_MAX_TURNS` | Operator model-call **ceiling** — `-1` = no cap; a positive value clamps `runLoop({maxTurns})`. The durable worker-tree budget includes descendant calls, BARE, and park/resume under {§turn-cap-counts-the-tree}; non-model chronology consumes none. |
|
|
3887
|
-
| `PLURNK_SERVICE_MAX_COMMANDS` | Per-emission action ceiling; `-1` = no cap — every
|
|
4100
|
+
| `PLURNK_SERVICE_MAX_COMMANDS` | Per-emission action ceiling; `-1` = no cap — every resolved op dispatches. Each concrete operation counts once, whether authored separately, in a group ({§target-group}), or selected by a glob ({§bulk-resource-targeting}). Overflow ops drop with one durable `max-commands-exceeded` error row on the next packet. Lifecycle operations remain exempt ({§operator-config-workspace-max-commands-floor}). Tightened per workspace via `settings.maxCommands` (min wins). |
|
|
3888
4101
|
| §operator-config-loop-timeout `PLURNK_SERVICE_LOOP_TIMEOUT` | Positive ms of cumulative active execution per loop ({§loop-execution-allowance}); excludes parked/queued time. Snapshotted on first execution, retained across wakes. Exhaustion aborts in-flight work and terminates `504 loop_timeout`, including a stuck provider call. |
|
|
3889
4102
|
| `PLURNK_SERVICE_PROVIDER_RECOVERY` | ms of recovery after the first recoverable provider failure; `0` disables reissue. Expiry parks workers with a reviewer, otherwise concludes their loop, or returns BARE's failure under {§provider-recovery}. |
|
|
3890
4103
|
| `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF` | First recovery delay (ms); doubles per failure up to `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF_MAX` ({§provider-recovery}). |
|
|
3891
4104
|
| `PLURNK_SERVICE_MAX_STRIKES` | Consecutive turn-contract strike threshold ({§engine-rails}). |
|
|
3892
4105
|
| `PLURNK_SERVICE_EMISSION_ATTEMPTS` | Completed provider responses allowed beneath one engine turn before frame admission is exhausted. Bounded interior operation errors are admitted without spending this budget. Exhaustion contributes one frame-contract strike under {§invalid-emission-attempts}. |
|
|
3893
|
-
| `
|
|
4106
|
+
| `PLURNK_SERVICE_BUDGET_PRESSURE` | Budget percentage above which the gauge names its largest rows ({§context-gauge}) and a packet within its budget carries the `budget_pressure` notice ({§context-pressure-notice}); measured before adding either. |
|
|
4107
|
+
| `PLURNK_SERVICE_BUDGET_LARGEST_ITEMS` | How many of the heaviest retained log rows the pressured gauge names ({§context-gauge}). |
|
|
3894
4108
|
| `PLURNK_SERVICE_LINE_ANCHOR_CONTEXT_LINES` | Minimum neighboring lines hashed on each side; repeated handles expand their context ({§line-anchor-disambiguation}). |
|
|
3895
4109
|
| `PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES` | Surrounding and landed lines shown at each EDIT result boundary ({§edit-result-receipt-projection}). |
|
|
3896
4110
|
| `PLURNK_SERVICE_MIN_CYCLES` | Min repetitions before cycle detection fires ({§engine-rails}). |
|
|
@@ -3920,7 +4134,14 @@ Feature-flag bools use `process.env.X === "1"` exactly — never `=== "true"`.
|
|
|
3920
4134
|
|
|
3921
4135
|
External extensions declare their own env vars in their own `.env.defaults`, assembled at boot ({§operator-config-env-defaults}).
|
|
3922
4136
|
|
|
3923
|
-
§operator-config-cli-flags **Admin CLI flags derive
|
|
4137
|
+
§operator-config-cli-flags **Admin CLI configuration flags derive from the service panel and the contracts-owned shared keys ({§operator-config-shared-keys}).** Each active `PLURNK_*` declaration becomes `--<kebab-cased-name>` (prefix stripped, lowercased, underscores → dashes). A comment immediately above the declaration becomes its `-h` description; undescribed flags still show their environment name and default. Installed extension defaults join the environment floor and catalog but do not implicitly expand the service executable's flag surface.
|
|
4138
|
+
|
|
4139
|
+
§service-posix-artifacts The service package ships `dist/man/plurnk-service.1`
|
|
4140
|
+
and Bash, Zsh and Fish scripts in `dist/completions/`, generated at build time
|
|
4141
|
+
from the same help and panel descriptors as the executable. Completion supplies
|
|
4142
|
+
command and long-option names plus ordinary filename completion; it does not
|
|
4143
|
+
start the service, inspect configuration values, or contact a provider. Installing
|
|
4144
|
+
the manual or enabling completion is explicit and documented in `INSTALL.md`.
|
|
3924
4145
|
|
|
3925
4146
|
### Loop limits
|
|
3926
4147
|
|
|
@@ -3972,7 +4193,7 @@ leak into another.
|
|
|
3972
4193
|
workspace: a client tightens the runaway-op guard and never raises it past
|
|
3973
4194
|
the operator's.
|
|
3974
4195
|
- §operator-config-workspace-max-commands-floor The cap bounds *actions* only.
|
|
3975
|
-
WAIT
|
|
4196
|
+
WAIT is never counted and always dispatch, so `0` is a valid
|
|
3976
4197
|
floor, admitting lifecycle intent with zero actions. Dropped actions still prevent
|
|
3977
4198
|
successful completion under {§turn-disposition}.
|
|
3978
4199
|
- §operator-config-workspace-git `settings.git` (`false`) **denies** git for the workspace (`PLURNK_SERVICE_GIT_ALLOWED` AND workspace) — the client opts its workspace out of git membership and working-tree status; it can never re-enable git past the operator's service-wide lockout.
|
|
@@ -4250,7 +4471,7 @@ registry. Deleting the workspace cascades its state; worker lifecycle does not.
|
|
|
4250
4471
|
|
|
4251
4472
|
§functionality-coordinator **One coordinator owns the common lifecycle.**
|
|
4252
4473
|
Functionality families are adapters beneath
|
|
4253
|
-
`list | discover | add | enable | disable | remove`. State and mutations
|
|
4474
|
+
`list | discover | add | replace | enable | disable | remove`. State and mutations
|
|
4254
4475
|
serialize per workspace and family. Scope-bound client actions
|
|
4255
4476
|
`workspace.<family>.<verb>` / `worker.<family>.<verb>` and model manager executors invoke the same
|
|
4256
4477
|
coordinator. Families do not invent another management grammar, proposal
|
|
@@ -4263,10 +4484,38 @@ Retryability describes the actual failed condition, not its numeric status.
|
|
|
4263
4484
|
| `list` | Project definitions, ownership (`origin`), winning configuration source (`provenance`), enabledness, and published preparation outcome: disabled, dormant, active, unavailable with its Problem, or authorization-required. No credential values. |
|
|
4264
4485
|
| `discover` | Return inert candidates for the inputs the family serves ({§functionality-discover-advertisement}). Never install, persist, enable, or execute them. |
|
|
4265
4486
|
| `add` | Admit and persist a local definition, prepare it, and enable it atomically. It may override an inherited definition. Reapplying the same local definition enables it idempotently (200); a different local definition for that alias fails 409 without replacing it. |
|
|
4487
|
+
| `replace` | Assign a complete definition to an explicit alias through {§functionality-replacement}. Preserve existing enabledness; a new alias is enabled. |
|
|
4266
4488
|
| `enable` | Publish an available definition; retry preparation if unavailable. |
|
|
4267
4489
|
| `disable` | Withdraw live capability; retain its definition and saved results. |
|
|
4268
4490
|
| `remove` | Forget the locally owned definition and its enabledness override. Restore any inherited definition with its inherited enabledness. Inherited definitions cannot be removed at this scope. Saved results remain. |
|
|
4269
4491
|
|
|
4492
|
+
§functionality-replacement **Replacement is a named whole-definition assignment.**
|
|
4493
|
+
The shared coordinator admits it through the family's existing schema and adapter,
|
|
4494
|
+
then uses the same serialized preparation and publication path as other mutations.
|
|
4495
|
+
It neither removes the old definition first nor merges omitted fields.
|
|
4496
|
+
|
|
4497
|
+
| Boundary | Outcome |
|
|
4498
|
+
|---|---|
|
|
4499
|
+
| Existing local or inherited alias | Persist the complete admitted definition in the selected scope, retaining the alias's effective enabledness. A local override replaces inherited interpretation context and provenance. |
|
|
4500
|
+
| Absent alias | Create the named local definition, enabled. The alias is required; replacement never derives one. |
|
|
4501
|
+
| Disabled candidate | Persist without preparing that alias. Editing a definition does not enable it. |
|
|
4502
|
+
| Admission, preparation, or publication refuses | Keep the preceding definition, enabledness, attachment and documents. Return the exact failure to either client or model caller. External effects of preparation retain the limits of {§functionality-publication}. |
|
|
4503
|
+
| Authorization required | Publish the existing authorization-required handoff; this is not a failed preparation. |
|
|
4504
|
+
| Identical definition | Retain enabledness and normal attachment reuse; this is not an explicit enable/restart. |
|
|
4505
|
+
|
|
4506
|
+
§functionality-mutation-status **Mutation status describes the committed resource
|
|
4507
|
+
outcome, not the management invocation's stream lifetime.** Apply these rows in
|
|
4508
|
+
order; refusals retain their own Problems and do not commit a replacement.
|
|
4509
|
+
|
|
4510
|
+
| Outcome | Status |
|
|
4511
|
+
|---|---:|
|
|
4512
|
+
| The resulting definition requires authorization | 202 |
|
|
4513
|
+
| `add` or `replace` creates a local definition, including an override of an inherited definition | 201 |
|
|
4514
|
+
| `add` reapplies the identical local definition; `replace` assigns an existing local definition; `enable`, `disable`, or `remove` settles | 200 |
|
|
4515
|
+
|
|
4516
|
+
`add` of a different local definition remains `alias-exists` (409); `replace` is explicit.
|
|
4517
|
+
Model invocation settlement follows {§functionality-model-mutation} independently.
|
|
4518
|
+
|
|
4270
4519
|
§functionality-discover-advertisement **A family's `discover` advertises exactly the inputs it
|
|
4271
4520
|
serves.** The coordinator builds the family's discover input schema from its declared discovery
|
|
4272
4521
|
({§functionality-discovery-inputs}): the declared inputs with their shared
|
|
@@ -4422,14 +4671,15 @@ core owns discovery roots.
|
|
|
4422
4671
|
|
|
4423
4672
|
An adapter may expose a `scheme` facet beneath its family's runtime namespace
|
|
4424
4673
|
({§runtime-resource-binding}). A facet claims a path subtree and is the scheme's
|
|
4425
|
-
whole live half there: READ and FIND preparation, FIND, SEND, WAIT and KILL
|
|
4426
|
-
its own wherever it implements them. A claimed KILL the facet does not implement
|
|
4674
|
+
whole live half there: READ and FIND preparation, FIND, EDIT, SEND, WAIT and KILL
|
|
4675
|
+
are its own wherever it implements them. A claimed KILL the facet does not implement
|
|
4427
4676
|
is the ordinary entry KILL ({§stream-control}); an unclaimed coordinate keeps the
|
|
4428
4677
|
stored-execution behaviour, SEND to a process included. Where its resources are
|
|
4429
4678
|
not shaped like the executor's output, the facet states their representation —
|
|
4430
|
-
resource authority, channels, the default channel — and that
|
|
4431
|
-
every claimed coordinate: its address, its fragmentless READ, the
|
|
4432
|
-
subscription publishes
|
|
4679
|
+
resource authority, channels, the default channel, who may write them — and that
|
|
4680
|
+
manifest governs every claimed coordinate: its address, its fragmentless READ, the
|
|
4681
|
+
channel a subscription publishes, the writer gate ({§scheme-surface}) an EDIT or a
|
|
4682
|
+
COPY into it passes. An adapter states the `traits` of its runtime — `web`
|
|
4433
4683
|
for a family that reaches the network — so {§capability-admission} selects its
|
|
4434
4684
|
manager and its resources alike.
|
|
4435
4685
|
|
|
@@ -4459,13 +4709,33 @@ set any name it lists or none of them — it answers which names have a **consum
|
|
|
4459
4709
|
a Worker learns the name of a value only the operator can supply. The catalog projects
|
|
4460
4710
|
declarations, never the host environment, so a credential the operator has filled in appears by
|
|
4461
4711
|
name with its documentation and an empty value ({§exec-env-scoped}: referred to by name, never
|
|
4462
|
-
read). `source` selects one declaring package
|
|
4463
|
-
catalog. A
|
|
4712
|
+
read). `source` selects one declaring package; an unknown source is `source-unknown`
|
|
4713
|
+
(400), not an empty catalog. A known source with no matching settable declarations
|
|
4714
|
+
returns an empty candidate list. A request naming neither input is the whole
|
|
4715
|
+
catalog. Files are read with READ; variables are set with `add` or `EDIT (env:///NAME)`.
|
|
4716
|
+
A client's own environment is no input: contributing candidates, it would be a second
|
|
4464
4717
|
door past the ceiling.
|
|
4465
4718
|
|
|
4466
4719
|
The family publishes no process runtimes. Its values are read at the spawn that uses them,
|
|
4467
4720
|
not from a live process or a cached worker environment.
|
|
4468
4721
|
|
|
4722
|
+
§env-scheme **The registry is an address space.** Every name in effect for a Worker's commands —
|
|
4723
|
+
the ambient names the ceiling admits, workspace defaults and the Worker's own entries, exactly
|
|
4724
|
+
what `list` projects — is a resource at `env:///NAME` whose body is the value, verbatim; a
|
|
4725
|
+
reserved or masked name is no resource. The family's manager exposes it as the facet of its own
|
|
4726
|
+
`env://` namespace ({§runtime-resource-binding}), read for the dispatching Worker: READ projects
|
|
4727
|
+
the value its commands receive now, FIND lists the names in effect and a pattern on it matches
|
|
4728
|
+
values, COPY carries a value out. The manager's own output streams, eight hexadecimal characters
|
|
4729
|
+
({§execution-output-identity}), stay the executor's. A write is the Worker's own layer, never the
|
|
4730
|
+
workspace's or the operator's: EDIT sets the whole value through the family's `replace` for the
|
|
4731
|
+
Worker, and KILL retires the name from the Worker's commands — `remove` for an entry the Worker
|
|
4732
|
+
owns, which restores an inherited value, `disable` for an inherited one, which keeps its
|
|
4733
|
+
definition. Admission is the family's ({§env-functionality}) and its refusal is the operation's
|
|
4734
|
+
result. A value has no lines: a line scope on EDIT or KILL is `value-whole` (400), and a pattern
|
|
4735
|
+
on EDIT is the dispatcher's refusal for any scheme without text scopes; a target that is not
|
|
4736
|
+
`env:///NAME` is `name-invalid` (400), or `target-required` (400) when absent; a name not in
|
|
4737
|
+
effect is `entry-not-found` (404) on READ and KILL alike.
|
|
4738
|
+
|
|
4469
4739
|
§functionality-scope **A family declares its supported scopes.** Skills, MCP, members
|
|
4470
4740
|
and outbound A2A describe what exists in a **workspace**: a capability, resident or installable,
|
|
4471
4741
|
that every Worker there shares. Environment describes how one **Worker** works — context rather
|
|
@@ -4494,7 +4764,7 @@ reach the other, and depth is transitive with no further rule. Each copied entry
|
|
|
4494
4764
|
`inherited`, the Worker that set it, preserved across generations until the child changes that
|
|
4495
4765
|
entry, so `list` never claims the child set what it inherited; a parent's masking of an
|
|
4496
4766
|
ambient name travels the same way. WORK and FORK may hand the child more: the heading's `env`
|
|
4497
|
-
option
|
|
4767
|
+
option replaces and enables the child's own entries after the copy ({§env-option}).
|
|
4498
4768
|
|
|
4499
4769
|
§functionality-state **One durable value per workspace and family.**
|
|
4500
4770
|
`{ version: 1, definitions: { [alias]: { origin, enabled, definition? } } }`
|
|
@@ -4564,7 +4834,7 @@ It then reports `active`, `unavailable`, or `authorization-required`, or the exa
|
|
|
4564
4834
|
publication failure. Resource readiness is not execution liveness: a mutation's
|
|
4565
4835
|
`202 authorization-required` body remains exact, while the finished manager
|
|
4566
4836
|
execution closes with `200`. It does not wait for sign-in. A preparation failure may publish enabled-but-unavailable
|
|
4567
|
-
state; a publication failure never reports a successful mutation. Stream polling,
|
|
4837
|
+
state for other mutations, but `replace` rejects it ({§functionality-replacement}); a publication failure never reports a successful mutation. Stream polling,
|
|
4568
4838
|
waiting, and result observation use the ordinary execution lifecycle, without a
|
|
4569
4839
|
separate deferred-commit queue. An explicit client action publishes now, rejects
|
|
4570
4840
|
a failed preparation, and fails 409 while the workspace is held
|
|
@@ -4585,7 +4855,7 @@ Core's behavior behind them.
|
|
|
4585
4855
|
| §methods-proposal-resolve Proposals | `resolveProposal(logEntryId, resolution, owner)` | Validates the workspace-scoped owner before delivering one accept, reject, or cancel decision. Unknown, mismatched, and already-resolved identities fail without consuming the gate; the adapter authenticates its owner identity. |
|
|
4586
4856
|
| §client-interaction-list Client interactions | `pendingClientInteractions(workspaceId)` | Intersects durable interaction rows with their live operation waiters and returns the contracts-owned projection; a row alone is not a resumable interaction. |
|
|
4587
4857
|
| §methods-client-interaction-resolve Client interactions | `resolveClientInteraction(interactionId, resolution, respondent, message?)` | Validates the recorded recipient before delivering one resolved payload or cancellation. Unknown, mismatched, and already-resolved identities fail before affecting an operation. |
|
|
4588
|
-
| §methods-loop-run Loops | `runLoop({ workspaceId, workerId, prompt, source?, maxTurns?, openPaths?, selector?, childSelector? })` | Validates a model worker and persists the request with the effective turn ceiling, then returns an immediate status-100 acknowledgement with `loopId` and `action`. A trusted adapter may identify the prompt's causal actor with one canonical `source`; ordinary clients cannot author it through their protocol surface. Messages carry no approval authority. The exact terminal result arrives only through `loop/terminated`; parking and resuming do not replace the loop. |
|
|
4858
|
+
| §methods-loop-run Loops | `runLoop({ workspaceId, workerId, loopId?, prompt, source?, maxTurns?, openPaths?, selector?, childSelector? })` | Validates a model worker and persists the request with the effective turn ceiling, then returns an immediate status-100 acknowledgement with `loopId` and `action`. An explicit Loop recipient follows {§loop-addressed-admission}. A trusted adapter may identify the prompt's causal actor with one canonical `source`; ordinary clients cannot author it through their protocol surface. Messages carry no approval authority. The exact terminal result arrives only through `loop/terminated`; parking and resuming do not replace the loop. |
|
|
4589
4859
|
| §methods-loop-cancel Loops | `cancelDrain(workerId, reason?)`; `cancelWorker({ workspaceId, workerId, reason? })` | `cancelDrain` begins durable structured cancellation and reports whether process-local work existed when called; queued or parked durable work is still terminalized when it is `false`. The ownership-bounded `cancelWorker` awaits that same tree cancellation and stream reap, so an exterior protocol can project the settled durable result without polling or fabricating state. |
|
|
4590
4860
|
| §methods-op-mirror Client dispatch | `dispatchClientAction({ workspaceId, workerId, statements })` | Dispatches already-parsed grammar statements as one client action in one administrative loop in the client worker, executing in the workspace's Functionality ({§actor-boundary-attached-functionality}). Every statement is an ordered client/operation turn, and every committed `log/entry` is emitted before the action promise resolves; a proposal may keep its turn, loop, and action promise open until resolution. Core exposes no per-op method family. |
|
|
4591
4861
|
| Client observation | `look({ workspaceId, workerId, statement, perspectiveWorkerId? })` | Runs an already-parsed READ through the full resolver in the workspace's Functionality without a log row. A non-READ statement is rejected ({§op-look}). |
|
|
@@ -4627,9 +4897,12 @@ the requested configuration normally.
|
|
|
4627
4897
|
|
|
4628
4898
|
§methods-loop-run-open-paths **Workspace paths are core-owned context reads.**
|
|
4629
4899
|
`openPaths` belongs to the message submitted by the client. The client
|
|
4630
|
-
sends paths, never duplicated
|
|
4900
|
+
sends local paths or scheme URIs, never duplicated resource bytes; core dispatches one ordinary
|
|
4631
4901
|
`plurnk`-origin READ per path from inside the owning workspace, and successes
|
|
4632
4902
|
and failures surface through the normal operation-result contract.
|
|
4903
|
+
Path spelling follows {§path-syntax}, including channel fragments and literal
|
|
4904
|
+
delimiters. Malformed URI syntax is rejected before message admission; a valid
|
|
4905
|
+
address whose resource is absent produces the ordinary READ failure.
|
|
4633
4906
|
|
|
4634
4907
|
| `runLoop` disposition | Message and path behavior |
|
|
4635
4908
|
|-----------------------|------------------------------------------------------------------------------------------------------|
|
|
@@ -4751,6 +5024,8 @@ packets or state snapshots.
|
|
|
4751
5024
|
|
|
4752
5025
|
§worker-model-selection **Worker-owned model selection.** Every model worker
|
|
4753
5026
|
owns one durable model, persisted as a nullable `model_routes` foreign key.
|
|
5027
|
+
Concurrent first selections of the same resolved tuple share one identity;
|
|
5028
|
+
an insertion conflict returns the existing route without changing its fields.
|
|
4754
5029
|
The root conversation worker is seeded once — from an explicit selection, else
|
|
4755
5030
|
the daemon default — and never re-seeded from a later default change. A
|
|
4756
5031
|
deliberately modelless daemon leaves the worker unset and rejects model work
|
|
@@ -4867,7 +5142,7 @@ adding a loop to it. LOOK text anchors resolve through the same
|
|
|
4867
5142
|
|
|
4868
5143
|
| Event | Payload | When fired |
|
|
4869
5144
|
|--------------------------------------------------------------|---------|------------|
|
|
4870
|
-
| §notifications-operation-event `operation/event` | `ApplicationOperationEvent`: `{ workerId, loopId, turnId, sequence, origin, projectRoot, statement, phase, result? }` | One admitted dispatch starts before capability/proposal admission and settles after its durable receipt(s). Only the settled phase has `result`, the exact returned operation result.
|
|
5145
|
+
| §notifications-operation-event `operation/event` | `ApplicationOperationEvent`: `{ workerId, loopId, turnId, sequence, origin, projectRoot, statement, phase, result? }` | One admitted dispatch starts before capability/proposal admission and settles after its durable receipt(s). Only the settled phase has `result`, the exact returned operation result. Resource fan-out is one dispatch ({§bulk-resource-targeting}); BARE starts before prompt preparation and settles after ordered receipt persistence. Automatic stream observations and log writes are not dispatches. An asynchronous executor's successful dispatch does not assert process exit. An internal exception that prevents settlement has no invented result event. |
|
|
4871
5146
|
| §notifications-log-entry-notify `log/entry` | `{ entry: LogEntry }` | A non-proposed `log_entries` row is committed, or a proposed row reaches terminal settlement under {§proposal-proposed-hidden}. Delivery completes before a later event may terminate the owning Loop. |
|
|
4872
5147
|
| §notifications-loop-terminated `loop/terminated` | `{ workerId, loopId, result, hitMaxTurns, turnIds, usage: { accounting, curationWeight, curationBudget, contextTokens, contextCapacity, meta }, attributions }` | One loop reaches a terminal state. `result` is the exact universal operation result, including its RFC 9457 Problem Details on failure. `accounting` is the loop's contracts-owned {§provider-accounting}; the two curation facts and two physical-context facts follow {§tokenomics-client-gauge}; `meta` is that turn's opaque provider bag. `attributions` is the sorted union of exact provider-request evidence ({§attribution}), separate from accounting. Worker and loop are an inseparable owning coordinate. |
|
|
4873
5148
|
| §notifications-loop-packet `loop/packet` | `{ workerId, loopId, packetCount }` | One provider packet becomes durable. `packetCount` is the exact count of packet-bearing turns in that Loop; packetless producer turns and physical provider retries never contribute. |
|
|
@@ -4924,35 +5199,54 @@ rendered or measured; {§context-fit} remains an engine-owned post-build rail.
|
|
|
4924
5199
|
|
|
4925
5200
|
```mermaid
|
|
4926
5201
|
flowchart LR
|
|
4927
|
-
defaults[Engine
|
|
4928
|
-
transforms --> render[Render
|
|
5202
|
+
defaults[Engine sections<br/>log records interleaved with complete programs] --> transforms[Trusted scheme transforms<br/>and boundary validation]
|
|
5203
|
+
transforms --> render[Render ordered message roles]
|
|
4929
5204
|
render --> measure[Budget substitution and<br/>core-owned measurement]
|
|
4930
5205
|
measure --> rail[Engine budget admission and dispatch]
|
|
4931
5206
|
```
|
|
4932
5207
|
|
|
4933
5208
|
### §packet-wire-envelope The wire envelope
|
|
4934
5209
|
|
|
4935
|
-
|
|
5210
|
+
Sections retain their message roles and order. System sections form the leading system message;
|
|
5211
|
+
adjacent nonempty sections of the same remaining role form one message. With an eligible
|
|
5212
|
+
{§emission-history}, the default envelope is:
|
|
4936
5213
|
|
|
4937
5214
|
| Message | Role | Content |
|
|
4938
5215
|
|:--|:--|:--|
|
|
4939
5216
|
| 1 | `system` | the system slot, as rendered |
|
|
4940
|
-
| 2 | `user` |
|
|
5217
|
+
| 2 | `user` | initial retained log records through the first selected emission record |
|
|
5218
|
+
| 3… | alternating `assistant`, `user` | each selected complete content program, then the following log records through the next selected emission record; native parts remain beside their READ records ({§packet-attachment-parts}) |
|
|
5219
|
+
| last | `user` | remaining log records and the current-status footer, from Worker through Open Messages and optional Recap |
|
|
5220
|
+
|
|
5221
|
+
Without selected programs, the log and footer coalesce into one user message: system + user.
|
|
5222
|
+
Each program follows its own emission record and precedes its subsequent results.
|
|
5223
|
+
Log records retain their order; interpolation never groups or relocates their bodies.
|
|
5224
|
+
Stored sections retain their original roles and order: reading evidence
|
|
5225
|
+
never converts an earlier request into a different envelope.
|
|
4941
5226
|
|
|
4942
5227
|
The digest's packet artifacts record the sections, and `.wire.json` reconstructs their text-message
|
|
4943
5228
|
envelope ({§share-packet-names}); it is not a serialized HTTP capture.
|
|
4944
5229
|
|
|
4945
|
-
### §
|
|
5230
|
+
### §emission-history The turn's NOTEs, in the model's voice
|
|
4946
5231
|
|
|
4947
5232
|
| Concern | Contract |
|
|
4948
5233
|
|---|---|
|
|
4949
|
-
|
|
|
4950
|
-
|
|
|
4951
|
-
|
|
|
4952
|
-
|
|
|
4953
|
-
|
|
|
4954
|
-
|
|
|
4955
|
-
|
|
|
5234
|
+
| Choice | `PLURNK_SERVICE_EMISSION_HISTORY`: `none`, `latest`, or `all` (default). Reasoning return is independent ({§reasoning-row}). |
|
|
5235
|
+
| Selection | `latest` considers only the immediately preceding completed model inference turn in this loop, never falling back to an older eligible program. `all` considers every completed model inference turn in this loop, in ascending turn order. |
|
|
5236
|
+
| Eligibility | An admitted content program with no syntax errors and an active emission row. Rejected attempts, syntactically partial emissions, empty or reasoning-only turns, initialization and other loops supply none. Runtime failures do not disqualify an admitted program. |
|
|
5237
|
+
| Vocabulary | Executor identities come from that turn's admitted operation evidence ({§packet-stored-shape}), not the current registry. Disabling or removing a runtime never changes its admitted history. |
|
|
5238
|
+
| Content | A replayed turn is its NOTEs: every content NOTE the program admitted, whole and in program order, as the model wrote it, including a NOTE that stood outside its fence ({§outside-text}). Every other operation is omitted; its receipt in the log is its record, and the program stays readable at `ops://`. A NOTE whose log row has been retired is omitted from the replay from the next packet on, so one KILL retires the memory everywhere it shows. Selection uses parsed operations, never text inside their bodies. Join retained NOTEs within each program with one blank line. No placeholders, body redaction or preview. Reasoning operations remain in their own source and receipts. |
|
|
5239
|
+
| Legend | The emission row of a replayed turn carries no program preview: its body is the legend of that turn's replayed NOTEs, one numbered line per NOTE, `N:log:///<loop>/<turn>/<sequence>/NOTE · <weight>`, in log order ({§emission-row}). Those NOTE rows render nowhere else in the packet; their text is read in the replay and their handle in the legend. A line scope on the emission row retires the NOTEs on those lines; the unscoped KILL retires the row ({§log-kill-scope}). A NOTE of a turn that is not replayed — an earlier loop, a program omitted at the wall, a reasoning NOTE — renders as an ordinary row with its body. |
|
|
5240
|
+
| Placement | Interpolate each selected program immediately after its durable emission record, as an assistant message without a heading or wrapper. Split the user log at that record; following observations stay after the program. No history is collected at the end. With `none` or no retained NOTEs, no assistant section is added; filtering does not make `latest` fall back to an older turn. |
|
|
5241
|
+
| Authority | Core assembles the chronological sections before the trusted whole-list transform ({§packet-extension-transform}). Each active emission row owns its program's curation lifetime; retiring it removes only that program, never its immutable source. |
|
|
5242
|
+
| Capacity | At the hard context wall, omit the selected history whole before suppressing any result body or native part ({§context-own-rows-fit}). A turn whose replay is omitted is not replayed: its NOTE rows stand in the log as ordinary bodied rows, and the wall's shedding then treats them as any other. A NOTE's text is in the packet once, as replay or as row, never both. Omission lasts through rebuilds of that request; the next request decides afresh. No source, receipt, or stored historical packet is changed. |
|
|
5243
|
+
| Accounting | Each program is charged once as its assistant message; the emission row charges only its record, legend included. |
|
|
5244
|
+
|
|
5245
|
+
The initial user segment is `log`; later segments are `log/<first-record-coordinate>`.
|
|
5246
|
+
Programs are `emission-history/<emission-record-coordinate>`. These are durable, unique section
|
|
5247
|
+
names, not model-facing headings. Only the initial segment has the `Log` header. Section-family
|
|
5248
|
+
inspection joins segments in recorded order; wire projection uses their individual roles and
|
|
5249
|
+
positions. Stored packets retain the sections actually sent, including older packet layouts.
|
|
4956
5250
|
|
|
4957
5251
|
### §packet-cache-monotone Default order and cache locality
|
|
4958
5252
|
|
|
@@ -4963,26 +5257,31 @@ Conditional absence never reorders the surviving default sections.
|
|
|
4963
5257
|
| 1 | system | `definition` | Framework definition; leads the most stable prefix. |
|
|
4964
5258
|
| 2 | system | `system-policy` | Operator policy; empty content is omitted on the wire. |
|
|
4965
5259
|
| 3 | system | `inject` | Present only when operator notes are configured. |
|
|
4966
|
-
|
|
|
4967
|
-
|
|
|
4968
|
-
|
|
|
4969
|
-
|
|
|
4970
|
-
|
|
|
4971
|
-
|
|
|
4972
|
-
|
|
|
4973
|
-
|
|
|
4974
|
-
|
|
|
4975
|
-
| 13 | user | `previous-emission` | Complete previous program, if eligible and within capacity ({§previous-emission}); always last. |
|
|
5260
|
+
| 4–5 | user / assistant | `log` and `emission-history` segments | Append-mostly chronological history: each selected program follows its emission record and precedes its results ({§emission-history}). |
|
|
5261
|
+
| 6 | user | `git` | Per-turn workspace status; empty content is omitted. |
|
|
5262
|
+
| 7 | user | `budget` | `Context Curation`; omitted when capacity is unknown. |
|
|
5263
|
+
| 8 | user | `worker` | `Worker`: `{"path": "worker://alice", "parent": <address or null>, "loop": L, "turn": T}`, the actor and the coordinate this packet's response becomes ({§packet-current-turn}). |
|
|
5264
|
+
| 9 | user | `delegation` | `Delegation`: per-turn `{workers, streams}` pointers; always present, each list `[]` when empty ({§packet-empty-sections}). |
|
|
5265
|
+
| 10 | user | `messages` | `Open Messages`: immutable message addresses and causal sources ({§message-arrival}). |
|
|
5266
|
+
| 11 | user | `notices` | Per-turn observations; empty content is omitted. |
|
|
5267
|
+
| 12 | user | `errors` | Per-turn failure pointers; empty content is omitted. |
|
|
5268
|
+
| 13 | user | `recap` | Optional authored operational recap. |
|
|
4976
5269
|
|
|
4977
5270
|
The order favors prefix-cache locality where semantics permit: the definition
|
|
4978
5271
|
and privileged policy lead operator notes, while the append-mostly
|
|
4979
|
-
log
|
|
4980
|
-
|
|
4981
|
-
|
|
5272
|
+
log and interpolated programs lead the volatile user-status clump. That clump is never cached
|
|
5273
|
+
across turns, since the next turn's log grows into its place, so its order serves attention alone:
|
|
5274
|
+
it runs from ambient state (Git Status, Context, Worker, Delegation) to what the turn owes (Open
|
|
5275
|
+
Messages) to feedback on the last turn (Notices, then Errors), and closes with the Recap. The nearer
|
|
5276
|
+
the end, the more a section asks of this turn. With `all`, appending new
|
|
5277
|
+
observations and programs preserves the existing history's roles and text prefix; no old program
|
|
5278
|
+
moves past newly appended observations. Changing selection or curating a row may invalidate the
|
|
5279
|
+
prefix at the affected position. It does **not** claim that every system byte is
|
|
4982
5280
|
immutable or that the complete packet is globally monotone in volatility:
|
|
4983
5281
|
operator notes and policies can change. Trust is a separate
|
|
4984
5282
|
admission rule. The system slot contains trusted control-plane material;
|
|
4985
|
-
|
|
5283
|
+
observations stay in the user role, and only the model's admitted content program is replayed
|
|
5284
|
+
under assistant authorship.
|
|
4986
5285
|
|
|
4987
5286
|
### §packet-extension-transform Trusted whole-list extension seam
|
|
4988
5287
|
|
|
@@ -4994,8 +5293,10 @@ Each initial or returned list passes the schemes-owned validator, including
|
|
|
4994
5293
|
unique-name enforcement, before the next transformer or renderer. Each
|
|
4995
5294
|
transformer may inspect the section content and add, remove, or reorder
|
|
4996
5295
|
sections. It receives no separate engine, database, actor, or request context.
|
|
4997
|
-
|
|
4998
|
-
section drafts, not the worker's source evidence.
|
|
5296
|
+
The complete default list already includes the interpolated programs ({§emission-history}) and
|
|
5297
|
+
native READ boundaries. Transforms own section drafts, not the worker's immutable source evidence.
|
|
5298
|
+
Removing a section removes its native deliveries too; a retained native delivery requires its
|
|
5299
|
+
named section to remain user-authored. Core measures the transformed composition.
|
|
4999
5300
|
|
|
5000
5301
|
This is strictly a trusted in-process seam, admitted through the common extension
|
|
5001
5302
|
trust gate; an external client action cannot invoke it. Whole-list transformation is
|
|
@@ -5009,7 +5310,7 @@ time of measurement.
|
|
|
5009
5310
|
|
|
5010
5311
|
| Fact | Owner and unit | Time | Contract |
|
|
5011
5312
|
|:-----|:---------------|:-----|:---------|
|
|
5012
|
-
| Core curation weight | `contentWeight = ceil(chars/2)` over channel content, canonical log bodies, rendered
|
|
5313
|
+
| Core curation weight | `contentWeight = ceil(chars/2)` over channel content, canonical log bodies, and each rendered message (including the optional emission history) | Write/build | Stable, model-independent measure; never a tokenizer claim. The model meets it as `tokens`. |
|
|
5013
5314
|
| §tokenomics-context-envelope-admission Provider input capacity | Provider model limits, the configured output reservation and the output floor, in provider tokens | Before every logical request | The reservation `min(maxInputTokens, contextWindow − outputBudget)` sizes the room; the wall `min(maxInputTokens, contextWindow − outputFloor)` decides admission ({§provider-capacity-admission}). The provider alone measures the complete request and admits it — with the grant flexed when the prompt is over the reservation — defers it, or rejects it at the wall. |
|
|
5014
5315
|
| Provider generation envelope | Provider response grant and optional reasoning subset, in provider tokens | Before every logical request | The reservation includes hidden reasoning; its strict reasoning subset is never additive. The response grant follows {§provider-flexed-allowance}. |
|
|
5015
5316
|
| 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. |
|
|
@@ -5019,7 +5320,7 @@ time of measurement.
|
|
|
5019
5320
|
```mermaid
|
|
5020
5321
|
flowchart TD
|
|
5021
5322
|
build["Build the packet at the budget"] --> wall{"Estimate over the wall?"}
|
|
5022
|
-
wall -- yes --> shed["Shed: the
|
|
5323
|
+
wall -- yes --> shed["Shed: the emission history whole, then the newest rows bodiless"]
|
|
5023
5324
|
shed --> wall
|
|
5024
5325
|
wall -- no --> over{"Over budget, no row yet?"}
|
|
5025
5326
|
over -- yes --> row["One over-budget row at the head of the turn"]
|
|
@@ -5030,17 +5331,18 @@ flowchart TD
|
|
|
5030
5331
|
shed -. "nothing left to take" .-> overflow["window-overflow 413, no inference request"]
|
|
5031
5332
|
```
|
|
5032
5333
|
|
|
5033
|
-
- §context-budget **One room.** The budget is the provider's input capacity through the
|
|
5034
|
-
- §context-gauge **One gauge.** Every packet carries one `## Context` section holding one JSON object: `tokens`, the packet's weight as rendered
|
|
5035
|
-
- §context-
|
|
5334
|
+
- §context-budget **One room.** The budget is the provider's input capacity through the loop's calibration, `floor(inputCapacity / factor)` ({§tokenomics-calibrated-readout}), and it bounds the whole packet — teaching, catalog, log and gauge together. Nothing on the service panel sizes a part of it: no projection share or preview page. When the loop's first response fixes its factor, the budget follows it either way; a room that shrinks under the model is announced by the over-budget row ({§context-over-budget-row}), never hidden by keeping a larger figure.
|
|
5335
|
+
- §context-gauge **One gauge.** Every packet carries one `## Context` section holding one JSON object: `tokens`, the packet's weight as rendered, and `budget`, the known room. Only when the packet without an inventory strictly exceeds `PLURNK_SERVICE_BUDGET_PRESSURE` of its budget does `largest` name the `PLURNK_SERVICE_BUDGET_LARGEST_ITEMS` heaviest retained log rows as `{path, tokens}`, ranked by weight then path. Unknown budget omits both `budget` and `largest`. The final `tokens` includes the inventory; over budget, its full configured count remains available for curation ({§context-over-budget-row}). Each log row heading carries its own `tokens`. The gauge is state: it never presents `budget − tokens` as response allowance and carries no mandate.
|
|
5336
|
+
- §context-pressure-notice **Pressure is one notice.** When the gauge names its inventory ({§context-gauge}) and the packet, with the notice in it, stays within its budget, the packet's notices section carries one `engine:context` notice `budget_pressure`, `level: warn`, whose directive is "YOU MUST NOT exceed budget." and whose message is "Context is at *N*% of budget." *N* is `floor(100 × tokens / budget)` over the gauge's final figures, so the share never disagrees with the gauge, and the notice carries no count of its own. It is decided and rendered with the packet it describes, recurs on every such packet, and is never buffered or sent to clients, which read their own pair ({§tokenomics-client-gauge}). An over-budget packet carries the row instead ({§context-over-budget-row}).
|
|
5337
|
+
- §context-fit **One rule: whole if it fits, otherwise as much as fits, then its size and address.** A result the model asked for — a READ without a scope, a FIND, an exec result delivered on close — arrives complete when its weight fits within `budget − tokens` as of that turn, less the room the turn still owes — one receipt's measured weight for each result still to land in it and the emission record that answers it, so that the receipts of a batch and the answer always fit. Otherwise the complete result stays where it was read from and the row is a `413` receipt naming the result's size, its weight, the remaining budget, and the two verbs: `READ` a range, or `KILL` first. A READ of lines carries, above its receipt, the longest prefix of those lines whose row fits that room — the lines with their anchors, the returned range closed on the last line delivered, and the receipt naming the lines delivered; a result whose first line does not fit, a FIND, a stream page and a byte view are bodiless receipts. An arrival the model did not ask for — an inbound `SEND`, a child's conclusion — takes the same bodiless receipt as a fact, not an error: its size and its address. Explicit scopes (`<a,b>`, a pattern, `<1,-1>`) are exact and take the same test. Result cuts are named where they happen: the first page of what came back unasked in size ({§markerless-first-page}) and the cut at the room in the receipt. The optional emission history is whole or absent ({§emission-history}), never a cut.
|
|
5036
5338
|
- §context-verbs **The verbs are the curation.** `READ` with a range takes a piece of what did not fit ({§read-selection-projection}); `NOTE` keeps what the model learned; `KILL` retires rows, ranges and bodies ({§log-kill-scope}) and may carry what it keeps of them as its own NOTE ({§log-kill-distillation}). The daemon adds no other mechanism.
|
|
5037
|
-
- §context-over-budget-row **Over budget is a row and a request, not an ending.** A packet whose weight exceeds `budget` is still submitted when it fits the window ({§context-wall}), and it carries one `_plurnk` error row at the head of its turn, `engine/context/packet-exceeds-budget` 413: "Context exceeds budget. YOU MUST ONLY KILL, MOVE or NOTE this turn." The row is the mandate and carries no figure: the gauge is the one home for `tokens` and `budget` ({§context-gauge}), and it shows the packet over with the row in it. The row
|
|
5339
|
+
- §context-over-budget-row **Over budget is a row and a request, not an ending.** A packet whose weight exceeds `budget` is still submitted when it fits the window ({§context-wall}), and it carries one `_plurnk` error row at the head of its turn, `engine/context/packet-exceeds-budget` 413: "Context exceeds budget. YOU MUST ONLY KILL, MOVE or NOTE this turn." The row is the mandate and carries no figure: the gauge is the one home for `tokens` and `budget` ({§context-gauge}), and it shows the packet over with the row in it. The row is shown once, in the packet it describes, then retired from the projection as a no-match KILL receipt is ({§log-kill-meta-operation}): it stays durable and readable at its coordinate, and a later packet that is over carries its own row. Nothing is hidden to make the packet smaller; the response grant is the window's remainder above the provider's output floor ({§provider-output-floor}). The limit protects a loop; it never ends one.
|
|
5038
5340
|
- §context-wall **Only the window ends a loop.** The wall is the provider's physical input limit: `maxInputTokens`, and the context window less the output floor ({§provider-output-floor}). A request over the wall sheds ({§context-own-rows-fit}) and is measured again ({§context-wall-measure}); a packet that cannot fit even as receipts ends its loop with the exact `engine/context/window-overflow` 413 Problem, and no inference request is made. An unknown window has no wall ({§tokenomics-window-unpollable-deliberate}).
|
|
5039
5341
|
- §context-wall-measure **The wall measures the request that will be sent.** The estimate is the packet's weight through its calibration factor ({§tokenomics-calibrated-readout}) and is never assumed to overestimate. A packet that fits by the estimate is assessed by the provider as the exact wire request ({§provider-capacity-admission}): an admission sends it; an exact refusal is the wall's verdict, and the request sheds by the refusal's excess and is assessed again. A provider that can only estimate defers, and the upstream provider is then the capacity oracle: its refusal ends the loop with the provider's own 413.
|
|
5040
|
-
- §context-own-rows-fit **The model's own rows take the same receipt.** When a request is over the wall by either measure ({§context-wall-measure}), its newest rows that still carry a body or a native part — NOTEs, receipts, delivered results, pictures — render bodiless in the fit rule's receipt shape, newest first and only as many as it takes for the request to fit: the heading, the facts, and `size`, the lines and tokens of what the row stood for. The optional
|
|
5342
|
+
- §context-own-rows-fit **The model's own rows take the same receipt.** When a request is over the wall by either measure ({§context-wall-measure}), its newest rows that still carry a body or a native part — NOTEs, receipts, delivered results, pictures — render bodiless in the fit rule's receipt shape, newest first and only as many as it takes for the request to fit: the heading, the facts, and `size`, the lines and tokens of what the row stood for. The optional emission history has already been omitted whole ({§emission-history}); an emission record has no body to take. A row whose receipt would weigh no less than its body stays whole. Every body stays stored and readable at its address, the verbs restore the room ({§context-verbs}), and each packet decides afresh from its own newest rows. The daemon chooses nothing to summarize and hides nothing silently.
|
|
5041
5343
|
- §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. `entry_channels.lines` is the channel's line count beside it, a stored generated column SQLite keeps on every write as the persisted mirror of {§logical-line-count} (a trailing newline terminates the last line; empty content has none), so a catalog lists extent without reading bodies.
|
|
5042
|
-
- §tokenomics-render-weight-budget **Packet curation budget.** `tokens` measures the *complete assembled packet* after section transforms and readout substitution,
|
|
5043
|
-
- §tokenomics-calibrated-readout **Convert capacity, never content costs
|
|
5344
|
+
- §tokenomics-render-weight-budget **Packet curation budget.** `tokens` measures the *complete assembled packet* after section transforms and readout substitution, each rendered message (including {§emission-history}) and native attachments; it is not a sum of stored row weights ({§tokenomics-weight-stored-at-write}). 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. Receipt, FIND-item, pressure-inventory, total, and ceiling figures all use the same curation ruler. A `SUM` of stored content weights measures a different artifact and cannot substitute for packet render weight.
|
|
5345
|
+
- §tokenomics-calibrated-readout **Convert capacity, never content costs; one factor per loop.** A sample is a settled emission response pairing its request's measured packet weight with the provider-reported prompt count, both positive. A loop's first sample from the answering model fixes the conversion factor `reported / weight` for the rest of that loop. Until then the loop's packets use that model's most recently fixed factor, from any loop or worker, and a model that has none uses 1. The budget therefore changes at most once in a loop, when its first response settles. `floor(inputCapacity / factor)` converts provider capacity into curation units, the budget ({§context-budget}); the same factor converts the packet's weight into the wall's estimate ({§context-wall-measure}). Zero means no whole curation unit fits; unknown input capacity remains `null`. The built packet captures this allowance and its factor once for its readout, pressure inventory, wall estimate, and persisted client gauge; later responses cannot change that packet's allowance. Calibration never changes stored weights, rendered receipt costs, or the immutable request history ({§tokenomics-agnostic-ruler}).
|
|
5044
5346
|
- §tokenomics-window-partition **One capacity derivation; no service-side token budget.** The provider owns model limits, the configured output reservation, and each call's response grant. Its resolved `inputCapacity` supplies the physical denominator exposed to clients and the boundary conversion into curation units ({§tokenomics-calibrated-readout}). Core shapes context in curation units; provider request-shaped evidence alone admits or rejects physical I/O. Local and custom deployments tune context window, total output budget and optional reasoning subset at their owning layers.
|
|
5045
5347
|
- §tokenomics-window-unpollable-deliberate **Unknown provider capacity stays unknown.** When the provider cannot derive `inputCapacity`, there is no budget: the gauge carries `tokens` alone, every result arrives whole, and the provider remains the capacity oracle ({§provider-capacity-admission}). Core never invents a stand-in.
|
|
5046
5348
|
|
|
@@ -5128,7 +5430,7 @@ ordinary operation evidence still reaches that child's direct parent.
|
|
|
5128
5430
|
|
|
5129
5431
|
| Producer / event | Durable occurrence | Observer projection |
|
|
5130
5432
|
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
5131
|
-
| §env-delta-child-activity Direct-child activity | Child-authored final EDIT, COPY, MOVE, SEND, executor invocation, WORK, FORK, and targeted non-log KILL receipts, including failures. `_plurnk` initialization, maintenance, and operation turns stay with the worker. A reply already delivered to the parent uses its reply occurrence instead ({§message-reply-delivery}). | Direct parent only; one exact attributed row born body-suppressed. Incoming message projections ({§message-arrival}),
|
|
5433
|
+
| §env-delta-child-activity Direct-child activity | Child-authored final EDIT, COPY, MOVE, SEND, executor invocation, WORK, FORK, and targeted non-log KILL receipts, including failures. `_plurnk` initialization, maintenance, and operation turns stay with the worker. A reply already delivered to the parent uses its reply occurrence instead ({§message-reply-delivery}). | Direct parent only; one exact attributed row born body-suppressed. Incoming message projections ({§message-arrival}), NOTE, READ (including executor-output READs), FIND, BARE, WAIT, and log KILL never create activity occurrences. Provider reasoning, calls, rejected emissions, and turn sources do not cross automatically. |
|
|
5132
5434
|
| §env-delta-child-termination Direct-child termination | The child's exact terminal loop result, except loops containing only `_plurnk` operation or maintenance turns. A conclusion before the first turn still reports, including failed spawns. `source` names the actor; the READ selects the exact loop ({§loop-answer}). | Direct parent only; bounded, initially visible READ under {§worker-scheme-collect}, never the child's potentially newer loop. Excluded administrative loops create no pending child-result edge. |
|
|
5133
5435
|
| §env-delta-commons-mutation Commons mutation | One successful resolved operation whose landed effects touch `worker:///...`. | Every existing worker; one body-suppressed row per observer, deduplicated with any lineage audience. |
|
|
5134
5436
|
| §env-delta-filesystem-narration Project-file divergence | Runtime-owned reconciliation evidence remains in the runtime actor's own log. | No ambient observer row. Current content remains addressable and stale hash edits reject at their owned boundary. |
|
|
@@ -5159,7 +5461,7 @@ Stream progress remains owned by {§exec-stream}.
|
|
|
5159
5461
|
## §packet Packet shape
|
|
5160
5462
|
|
|
5161
5463
|
§packet-markdown **The packet's Markdown projection (#626).** Core renders the transformed section list
|
|
5162
|
-
into
|
|
5464
|
+
into the ordered messages of {§packet-wire-envelope}. Within each message, section order is
|
|
5163
5465
|
preserved. A nonempty section with a header renders as an H2 immediately followed
|
|
5164
5466
|
by its JSON object/array content; non-JSON content has one blank line after the
|
|
5165
5467
|
header. A null header renders only its content. Empty content is omitted, trailing
|
|
@@ -5180,16 +5482,16 @@ their boundaries ({§log-wire-format}).
|
|
|
5180
5482
|
| `definition` | system | Bare `plurnk.md`; no wrapper heading | {§definition-table-projection} |
|
|
5181
5483
|
| `system-policy` | system | Authored Markdown | {§policy-sections} |
|
|
5182
5484
|
| `inject` | system | Authored Markdown | {§packet-inject} |
|
|
5183
|
-
| `log`
|
|
5485
|
+
| `log`, `log/<coordinate>` | user | Chronological Markdown H3 records with JSON metadata | {§log-wire-format} |
|
|
5184
5486
|
| `worker` | user | JSON `path` with the literal Worker address, `parent` (address or `null`), `loop`, `turn` | {§packet-current-turn} |
|
|
5185
5487
|
| `delegation` | user | JSON `{workers, streams}` | {§child-orientation} |
|
|
5186
5488
|
| `errors` | user | JSON status/log-path pointers | {§operation-results} |
|
|
5187
|
-
| `notices` | user |
|
|
5489
|
+
| `notices` | user | One alert callout per notice, directive first | {§notice-callout} |
|
|
5188
5490
|
| `git` | user | Working-tree state in a NOTE blockquote | {§packet-cache-monotone} |
|
|
5189
5491
|
| `budget` | user | JSON curation usage and ceiling | {§context-gauge} |
|
|
5190
5492
|
| `messages` | user | JSON pointers to the loop's unanswered immutable messages, path and source | {§message-arrival} |
|
|
5191
5493
|
| `recap` | user | Optional authored operational recap | {§recap} |
|
|
5192
|
-
| `
|
|
5494
|
+
| `emission-history/<coordinate>` | assistant | Complete retained operations at their emission records; replay omitted whole at capacity | {§emission-history} |
|
|
5193
5495
|
|
|
5194
5496
|
§packet-stored-shape **A model packet preserves the rendered request and, only
|
|
5195
5497
|
when an emission is admitted, its response.** Core assembles and measures the
|
|
@@ -5202,7 +5504,7 @@ leaves the request-only record, while rejected exchanges remain in their
|
|
|
5202
5504
|
| Turn state | `turns.packet` (the bag) + `turn_sections` rows |
|
|
5203
5505
|
| ----------------------------- | ----------------------------------------------- |
|
|
5204
5506
|
| No admitted model request (including initialization and local capacity rejection) | SQL `NULL`, no rows |
|
|
5205
|
-
| Request assembled | `{ weight, attributions }` + the sections as items;
|
|
5507
|
+
| Request assembled | `{ weight, attributions }` + the ordered sections as items; each selected program is stored at its emission boundary, with no empty placeholder ({§emission-history}) |
|
|
5206
5508
|
| Response admitted | `{ weight, attributions, assistant, assistantRaw }` + the sections as items |
|
|
5207
5509
|
|
|
5208
5510
|
§packet-items **Sections are rows over content-addressed items; the bag never holds them.**
|
|
@@ -5371,7 +5673,7 @@ retain distinct contracts and lifetimes.
|
|
|
5371
5673
|
- **Self-explaining rows.** A problem `title` names the stable class and `detail` states the occurrence-specific cause. Producer-known operands belong in factual extensions. `stage` appears only when neighboring stages imply different recovery; `recovery` states one generally valid next action; `retryable` is true only when the producer recommends automatically retrying the identical request. Unknown recovery or retryability is omitted rather than guessed. General workflow teaching stays in the packet rather than being duplicated into every failure. The runtime-neutral writing contract is owned by `@plurnk/plurnk-contracts`.
|
|
5372
5674
|
- **Exact Problems cross durable and external boundaries.** Scheme capabilities, proposal application, subscription conclusion, loop settlement, AG-UI, clients, digests, and benchmark records preserve the originating Problem object. The model packet alone derives `{§problem-projection}` without mutating that object. An adapter may add a missing durable `instance`, never replace an existing one; it must not rebuild failure truth from `status`, `detail`, `RUN_ERROR`, or a scheduler projection. A failed boundary without a valid Problem is a contract violation and fails hard.
|
|
5373
5675
|
- **Caught diagnostics are bounded.** Core-owned Problems may include a bounded preview of a caught runtime diagnostic when it states the occurrence-specific cause. `PLURNK_SERVICE_ERROR_DETAIL_LIMIT` owns that model-facing character bound; complete errors remain in daemon diagnostics. Input validation and stable contract failures do not spend this allowance on implementation text.
|
|
5374
|
-
- §notice-drain-on-read **Notices** - the few observations that are not log rows render one
|
|
5676
|
+
- §notice-drain-on-read **Notices** - the few observations that are not log rows render one callout each under their distinct `## Notices` section ({§notice-callout}), never a JSON dump. Packet rendering normalizes whitespace, bounds the producer message with the shared preview limits, and appends any typed position. The notice buffer drains on read; event Notices appear on at most one packet. Parking preserves pending notices for that loop's next packet; another loop cannot consume them. Terminal cleanup, including cancellation while parked, discards undelivered notices. This buffer is process-local, not restart-persistent. Stateful derivation progress and provider availability coalesce in the buffer, so clients observe every checkpoint live while a later model packet receives only the current state under ordinary level filtering.
|
|
5375
5677
|
- §rail-accounting-private **Rail accounting is private.** Visibility is owned by {§engine-rails}: the model sees concrete failures from admitted turns, never rejected emissions, attempt counts, the strike streak, or cycle detection. Surfacing internal state creates a gamification surface where the model optimizes for engine metrics instead of the task.
|
|
5376
5678
|
|
|
5377
5679
|
**The error rows (one channel) + the only non-log notices:**
|
|
@@ -5382,12 +5684,35 @@ retain distinct contracts and lifetimes.
|
|
|
5382
5684
|
| provider input capacity | `op='error'`, origin `_plurnk`, source `provider`; exact provider-owned `capacity-exceeded` Problem Details | 413 |
|
|
5383
5685
|
| max commands exceeded | `op='error'`, origin `_plurnk`, source `rail`; `engine/rail/max-commands-exceeded` Problem Details | 429 |
|
|
5384
5686
|
|
|
5385
|
-
| notice `kind` | Source | Position |
|
|
5386
|
-
|
|
5387
|
-
| `output_unaccounted` | a provider whose billed output tokens exceed those its content and reasoning hold | content-offset at the end of the content |
|
|
5388
|
-
| `parse_advisory` | grammar parser — recoverable near-miss which did not invalidate the parsed statements | content-offset into the model's emission |
|
|
5389
|
-
| `search_progress` | repository materialization/indexing lifecycle ({§persistent-search-index}); structured phase, count, and percent; `level: info`, `warn` when a completed pass carries failed members ({§derivation-member-failure}), `error` on terminal failure | none |
|
|
5390
|
-
| `git_inspection_refused` | engine membership — automatic Git inspection refused a supplied repository whose config declares a `filter.*` program ({§membership-git-hermetic}); names the key; `level: warn`, once per workspace until the key changes or clears | none |
|
|
5687
|
+
| notice `kind` | Source | Directive ({§notice-directive}) | Position |
|
|
5688
|
+
|---|---|---|---|
|
|
5689
|
+
| `output_unaccounted` | a provider whose billed output tokens exceed those its content and reasoning hold | none | content-offset at the end of the content |
|
|
5690
|
+
| `parse_advisory` | grammar parser — recoverable near-miss which did not invalidate the parsed statements | YOU SHOULD write the canonical form. | content-offset into the model's emission |
|
|
5691
|
+
| `search_progress` | repository materialization/indexing lifecycle ({§persistent-search-index}); structured phase, count, and percent; `level: info`, `warn` when a completed pass carries failed members ({§derivation-member-failure}), `error` on terminal failure | none | none |
|
|
5692
|
+
| `git_inspection_refused` | engine membership — automatic Git inspection refused a supplied repository whose config declares a `filter.*` program ({§membership-git-hermetic}); names the key; `level: warn`, once per workspace until the key changes or clears | none | none |
|
|
5693
|
+
| `continued_without_note` | engine turn — a continuing or parked model turn that admitted no NOTE ({§continued-without-note}); `level: warn` | YOU MUST record at least one NOTE along with other operations. | none |
|
|
5694
|
+
| `budget_pressure` | engine context — a packet within its budget whose gauge is under pressure ({§context-pressure-notice}); `level: warn`; rendered with that packet, never buffered | YOU MUST NOT exceed budget. | none |
|
|
5695
|
+
| `outside_text` | engine turn — text the emission carried outside its operations, discarded ({§outside-text}); `level: warn` | YOU MUST NOT emit anything except whitespace between fenced operations. | none |
|
|
5696
|
+
| `invalid_emission` | engine grammar — a response rejected before dispatch; `level: error` | YOU MUST ONLY emit fenced operations; with the parameters, pattern, and terse aside on the fenced Operation line. | content-offset of the parser diagnostic, when it has one |
|
|
5697
|
+
| `output_truncated` | engine capacity or turn — an emission cut at the output allowance ({§output-allowance-notice}); `level: error` when the cut response was rejected, otherwise `warn` | YOU SHOULD emit fewer or shorter operations per turn. | none |
|
|
5698
|
+
| `provider_warning` | a provider warning: an SDK compatibility note, or native tool calls in a response that declared none; `level: warn` | YOU MUST NOT emit native tool calls. on the native tool calls; none on a compatibility note | none |
|
|
5699
|
+
| `provider_retry` | a provider stream that failed after output began and was answered by a complete retry; `level: warn` | none | none |
|
|
5700
|
+
| `provider_unavailable` | engine provider — a provider failure retried within its recovery budget | none | none |
|
|
5701
|
+
| `path_normalized` | file scheme — a path resolved to its canonical spelling; `level: warn` | YOU SHOULD address the resolved path. | none |
|
|
5702
|
+
| `read_fanout_bounded` | engine dispatcher — a READ whose glob matched more paths than its resource page selected; `level: warn` | YOU SHOULD narrow the glob, or FIND first. | none |
|
|
5703
|
+
| `parse_issues_unavailable` | engine mimetype — parser recovery evidence unavailable for a mimetype; `level: warn` | none | none |
|
|
5704
|
+
| `metadata_ignored` | engine dispatcher — `[metadata]` on an operation whose scheme takes none, run without it; `level: warn` | YOU SHOULD NOT write [metadata] on an operation that takes none. | none |
|
|
5705
|
+
| `scope_normalized` | engine slicer — a scope normalized to its canonical form; `level: warn` | YOU SHOULD write the normalized scope. | none |
|
|
5706
|
+
| `edit_merged` | engine slicer — an EDIT resolution rule applied to a batch ({§edit-batch-merges}); `level: warn` | YOU SHOULD verify the merged EDIT before building on it. | none |
|
|
5707
|
+
|
|
5708
|
+
§continued-without-note **A continuing turn that lapsed from the per-turn rule is told so.** The card's rule is one line, `YOU MUST record at least one NOTE along with other operations.`, and the daemon's directive quotes it. When a model turn settles at 102 or 202, so the loop continues past it or parks on it, and it admitted no NOTE in its program or from its reasoning ({§reasoning-operations}), the next packet carries one `engine:turn` notice, `continued_without_note`, `level: warn`, with that directive and the message `The turn continued without a NOTE.`; when its program was NOTEs and nothing else, the next packet carries `noted_without_operation`, the same directive and the message `The turn carried NOTEs and no other operation.` Each is a notice, never a failure: it mints no row, never counts toward the strike rail, and never ends or alters a loop. A turn that concludes its loop, an empty turn, which carries its own no-operation row, and every non-model turn take none.
|
|
5709
|
+
|
|
5710
|
+
§notice-callout **A notice speaks in the card's callout form.** Each renders as one alert callout, its level choosing the callout: `> [!CAUTION]` for `error`, `> [!WARNING]` for `warn`, and `> [!NOTE]` for `info`, which no model packet carries. Inside it stand the directive ({§notice-directive}), then the message, any typed position as `@ line:column`, and the kind in brackets; a blank line separates consecutive callouts:
|
|
5711
|
+
|
|
5712
|
+
```text
|
|
5713
|
+
> [!WARNING]
|
|
5714
|
+
> YOU MUST record at least one NOTE along with other operations. The turn continued without a NOTE. [continued_without_note]
|
|
5715
|
+
```
|
|
5391
5716
|
|
|
5392
5717
|
§notice-level **Severity on the wire (`level`, required).** Every `Notice` carries `level: "error" | "warn" | "info"`, set by the **producer** at the emit site. The level is client presentation, not operation status: even an `error` notice cannot terminalize work or substitute for a durable Problem. A forwarded `output_unaccounted` is `warn`; ordinary lifecycle and progress notices are `info`. Clients color straight off `level` without interpreting the open `kind` vocabulary.
|
|
5393
5718
|
|
|
@@ -5428,7 +5753,7 @@ USD and token totals with separately named known subtotals across every physical
|
|
|
5428
5753
|
calls included. It is the shared exact derivation from the ledger, never a second
|
|
5429
5754
|
stored fact, so a live watcher accrues running loop cost per turn (#465).
|
|
5430
5755
|
|
|
5431
|
-
§notice-content-offset-pointer **Content-offset position.** A non-fatal diagnosis on an accepted emission (for example `output_unaccounted` or `parse_advisory`) carries `position: { type: "content-offset", line, column }` into the model's exact `ops://<worker>/<loop>/<turn>` source; the optional
|
|
5756
|
+
§notice-content-offset-pointer **Content-offset position.** A non-fatal diagnosis on an accepted emission (for example `output_unaccounted` or `parse_advisory`) carries `position: { type: "content-offset", line, column }` into the model's exact `ops://<worker>/<loop>/<turn>` source; the optional emission-history section shows a canonical program ({§emission-history}), so the position names a line of the source, which READ of its address shows. A bounded hard parse error becomes a durable failed operation whose Problem Details preserve its line, column, source, and parser-owned diagnostic. Hard errors that make the frame untrustworthy remain only with their rejected forensic attempt.
|
|
5432
5757
|
Reasoning normalization notices use source `grammar:reasoning` and omit the
|
|
5433
5758
|
content-offset position: reasoning coordinates do not address the content source.
|
|
5434
5759
|
|
|
@@ -5506,10 +5831,10 @@ remain one compact orientation line, not an expansion of every tool's signature.
|
|
|
5506
5831
|
|
|
5507
5832
|
§members-functionality **File membership is one workspace Functionality family.**
|
|
5508
5833
|
Core registers the `members` family with the coordinator ({§functionality-coordinator}):
|
|
5509
|
-
the model, the client, and the operator learn one surface — `list | discover | add |
|
|
5834
|
+
the model, the client, and the operator learn one surface — `list | discover | add | replace |
|
|
5510
5835
|
enable | disable | remove`, `workspace.members.<verb>` for the client,
|
|
5511
5836
|
```` ```members (<verb>) ```` for the model — for what the model may see, exactly as they do for skills and
|
|
5512
|
-
MCP servers. A definition is one
|
|
5837
|
+
MCP servers. A definition is one shell-path glob ({§path-glob-matching}), `{ glob }`, relative to the project
|
|
5513
5838
|
root; a leading `!` excludes matching members, and an exclusion wins over every inclusion.
|
|
5514
5839
|
Admission provenance (`service-configuration`, `client-action`, `model-proposal`)
|
|
5515
5840
|
rides the definition to enforce {§members-model-scope}; configuration-source
|
|
@@ -5646,6 +5971,13 @@ one dormant authored source. A failed read fails packet assembly with its cause.
|
|
|
5646
5971
|
The footer is one projection path and one authored source, not a second language
|
|
5647
5972
|
contract.
|
|
5648
5973
|
|
|
5974
|
+
§recap-lines The operator's recap lines lead the footer: every non-empty
|
|
5975
|
+
`PLURNK_SERVICE_RECAP_LINE_<alias>`, in alias order, renders as one callout ahead of the recap
|
|
5976
|
+
source, `> [!IMPORTANT]` for a `YOU MUST` line and `> [!TIP]` for `YOU SHOULD` and `YOU MAY`. A line
|
|
5977
|
+
that does not open with `YOU MUST`, `YOU MUST NOT`, `YOU MUST ONLY`, `YOU SHOULD`, `YOU SHOULD NOT` or
|
|
5978
|
+
`YOU MAY` is a configuration error naming its key, and an empty value turns a shipped line off. The
|
|
5979
|
+
shipped `recap.md` stays empty: it is the extension contract's source, not a home for core's lines.
|
|
5980
|
+
|
|
5649
5981
|
## Matcher selection and text regions
|
|
5650
5982
|
|
|
5651
5983
|
Matchers select resources and report evidence; text scopes independently
|
|
@@ -5836,12 +6168,12 @@ repair neighboring punctuation. Readable projections have their own coordinates.
|
|
|
5836
6168
|
|
|
5837
6169
|
### §ext-mimetype Path-extension declares mimetype
|
|
5838
6170
|
|
|
5839
|
-
`
|
|
6171
|
+
`PathMimetype.resolve` (exported from `@plurnk/plurnk-schemes`): pathname extension → `Mimetypes.detect({ ext })` (with `text/plain` normalized to `text/markdown` per {§markdown-primitive}); an unrecognized or absent extension uses the caller's supplied type. Text EDIT creation supplies the scheme's declared channel type or the Markdown primitive for a dynamically typed channel. Transfers follow {§copy-destination-mimetype}.
|
|
5840
6172
|
|
|
5841
6173
|
- `worker:///users.json` → `application/json` (extension wins)
|
|
5842
6174
|
- `worker:///notes.md` → `text/markdown` (extension; matches default)
|
|
5843
6175
|
- `worker:///config.yaml` → `application/yaml`
|
|
5844
|
-
- `worker:///users` (no suffix) → `text/markdown` (
|
|
6176
|
+
- Text EDIT of `worker:///users` (no suffix) → `text/markdown` (text primitive)
|
|
5845
6177
|
|
|
5846
6178
|
§ext-mimetype-extension-mimetype The same rule applies to every entry-bearing scheme when
|
|
5847
6179
|
creating a channel without a per-call type declaration. EDIT and COPY/MOVE into
|
|
@@ -5971,8 +6303,10 @@ database is a benchmark artifact like any other: the lane's run directory lives
|
|
|
5971
6303
|
checkout holds source only — never run output. `test:intg` stamps `PLURNK_TEST_RUN` once and every
|
|
5972
6304
|
test process inherits it, so one suite's databases land in one directory without a pretest step, a
|
|
5973
6305
|
marker file or a sweep; an unstamped invocation is not a special case with its own rules, it is
|
|
5974
|
-
simply an unstamped run with its own directory. A
|
|
5975
|
-
|
|
6306
|
+
simply an unstamped run with its own directory. A lane whose suite boots Core through Core's test
|
|
6307
|
+
harness also exports `PLURNK_TEST_LANE`, its own lane name, so the daemon it boots writes into that
|
|
6308
|
+
lane's run directory and the lane's reclaim takes all of it; an unnamed run is Core's. A stamped run
|
|
6309
|
+
that passes is reclaimed when it exits; a failed suite's evidence is never touched and stays exactly where the run reported it. A cross-package test may reuse Core's migration fixture only by passing a path inside the
|
|
5976
6310
|
caller's own run directory.
|
|
5977
6311
|
|
|
5978
6312
|
§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.
|
|
@@ -5986,6 +6320,7 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
5986
6320
|
| code | status | contract |
|
|
5987
6321
|
|---|---:|---|
|
|
5988
6322
|
| `target-required` | 400 | *OP* requires a target path. Recovery: Write the target in parentheses on the opening fence line: `OP (path)`. |
|
|
6323
|
+
| `target-cardinality` | 400 | *OP* *operand* matched *n* resources; expected one. Recovery: Name one source and one destination per pair. |
|
|
5989
6324
|
| `scheme-not-found` | 501 | Scheme '*name*' is not registered. Recovery: ({§unregistered-scheme-recovery}) `Registered schemes: *names*.` |
|
|
5990
6325
|
| `scheme-metadata-unsupported` | 400 | *OP* on '*scheme*' does not accept the [metadata] modifier. |
|
|
5991
6326
|
| `operation-not-implemented` | 501 | Scheme '*name*' does not implement *OP* (or exec). |
|
|
@@ -5999,6 +6334,7 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
5999
6334
|
| `capability-denied` | 403 | Capability '*route*' is denied by *scope* policy. |
|
|
6000
6335
|
| `spawn-prompt-empty` | 422 | *OP* has no prompt text. Recovery: Write the prompt on the lines beneath the *OP* fence line. A prompt resource that is empty with no body says so: *OP* has no prompt text: the resource is empty and there is no body. Recovery: Write the prompt on the lines beneath the *OP* fence line, or name a resource that holds it. |
|
|
6001
6336
|
| `message-not-found` | 404 | No accepted message exists at *address*. |
|
|
6337
|
+
| `send-target-required` | 400 | SEND has no recipient and its loop has no published message. Recovery: Name a recipient address. |
|
|
6002
6338
|
| `edit-collision` | 409 | EDIT collided with the current resource state ({§edit-collision}). Recovery: *n* of *m* edits applied. READ the target for current coordinates. |
|
|
6003
6339
|
| `edit-target-required` | 400 | A line-anchored EDIT requires a target resource. Recovery: Provide the target that rendered the line anchor. |
|
|
6004
6340
|
| `kill-target-required` | 400 | KILL requires a target path. |
|
|
@@ -6011,7 +6347,27 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6011
6347
|
| `metadata-unsupported` | 400 | *OP* takes only the env option; '*key*' is not one. |
|
|
6012
6348
|
| `worker-name-conflict` | 409 | Worker '*name*' already exists in this workspace. |
|
|
6013
6349
|
| `no-operation` | 422 | The turn performed no operation ({§empty-turn}). |
|
|
6014
|
-
| `send-target-not-a-recipient` | 400 | The addressed scheme is not a SEND recipient. Recovery:
|
|
6350
|
+
| `send-target-not-a-recipient` | 400 | The addressed scheme is not a SEND recipient. Recovery: Name a message address or a recipient that implements SEND. |
|
|
6351
|
+
| `invalid-operation-syntax` | 400 | The parser's diagnostic for an invalid operation in an admitted turn. |
|
|
6352
|
+
| `unreadable-pattern` | 400 | The pattern reader's diagnostic for an unreadable matcher. |
|
|
6353
|
+
| `completion-invalid` | 400 | A reply accepts one completion code: 200 or 499. |
|
|
6354
|
+
| `attachment-address-invalid` | 400 | An attachment selects one exact resource address. |
|
|
6355
|
+
|
|
6356
|
+
§problems-loop **Loop and context Problems.** These codes identify the failed boundary; lifecycle and recovery remain governed by their owning contracts.
|
|
6357
|
+
|
|
6358
|
+
| code | status | condition |
|
|
6359
|
+
|---|---:|---|
|
|
6360
|
+
| `result-exceeds-budget` | 413 | A result exceeds the remaining log budget; detail names its size, delivered portion, and a smaller selection or curation ({§context-fit}). |
|
|
6361
|
+
| `window-overflow` | 413 | The packet cannot fit the model's window even as receipts ({§context-wall}). |
|
|
6362
|
+
| `packet-exceeds-budget` | 413 | Context exceeds budget; the curation mandate is the pinned sentence below ({§context-over-budget-row}). |
|
|
6363
|
+
| `loop-timeout` | 504 | The loop exhausted its active execution allowance. |
|
|
6364
|
+
| `strike-threshold` | 508 / 500 | Repetition crossed the strike threshold (508), or another strike source crossed it (500), under {§engine-rails}. |
|
|
6365
|
+
| `loop-running` | 425 | The addressed execution has not concluded. |
|
|
6366
|
+
| `loop-cancelled` | 499 | The loop was cancelled; detail preserves the cancellation reason. |
|
|
6367
|
+
| `loop-threw` | 500 | The loop failed outside its operation result contract. |
|
|
6368
|
+
| `narration-failed` | 500 | Filesystem divergence narration failed before its operation turn settled. |
|
|
6369
|
+
| `provider-contract-violation` | 502 | The provider failed without returning its required Problem Details. |
|
|
6370
|
+
| `active-worker-limit-reached` | 508 | The workspace's active workers reach its configured limit. |
|
|
6015
6371
|
|
|
6016
6372
|
§unregistered-scheme-recovery **An unregistered scheme's refusal names what does exist.** Its recovery
|
|
6017
6373
|
lists the schemes the workspace registers, and rebuilds the address into nothing else
|
|
@@ -6038,6 +6394,7 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6038
6394
|
|
|
6039
6395
|
| code | status | contract |
|
|
6040
6396
|
|---|---:|---|
|
|
6397
|
+
| `invalid-file-url` | 400 | The native file-URL diagnostic, or `File URL path must not include NUL characters.` ({§file-url}). |
|
|
6041
6398
|
| `edit-empty` | 400 | EDIT requires at least one statement. Recovery: Provide an EDIT statement. |
|
|
6042
6399
|
| `edit-batch-mismatch` | 400 | The EDIT batch spans multiple resources. Recovery: Submit a separate EDIT batch for each resource. |
|
|
6043
6400
|
| `line-marker-required` | 400 | EDIT of an existing file requires a line marker ({§edit-marker-required-on-existing}). Recovery: Name the lines to replace with `<@hash>` or `<@start,@end>` from a READ of the file; `<L,1,L,1>` inserts before line L, and `<1,-1>` replaces the whole file. |
|
|
@@ -6052,6 +6409,12 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6052
6409
|
| `file-create-gitignored` | 403 | Active Git policy ignores '*path*', and no members definition includes it. Recovery: Choose a Git-admitted path or add a members definition that includes it. |
|
|
6053
6410
|
| `file-materialization-limit` | 413 | The file exceeds the materialization byte limit and is not read into the workspace. |
|
|
6054
6411
|
| `entry-not-found` | 404 | No member of this workspace is at '*path*'. Recovery: FIND lists paths. EDIT creates files; `members (add)` admits existing files with a `{"glob": "<path>"}` body. A path beyond the root recovers instead to: '*path*' is outside the project root: only a members definition under the operator's namespace scope admits it. |
|
|
6412
|
+
| `body-channel-required` | 400 | A file write requires a body channel. |
|
|
6413
|
+
| `write-failed` | 500 | Publication or its settlement failed; the result distinguishes an unpublished write from an already-published one. |
|
|
6414
|
+
| `creation-rollback-failed` | 500 | Incorporating a newly created file failed, and rollback was incomplete. |
|
|
6415
|
+
| `creation-incorporation-failed` | 500 | Incorporating a newly created file failed; its exclusive creation was rolled back. |
|
|
6416
|
+
| `materialization-failed` | 500 | The file was written to disk but could not be registered. |
|
|
6417
|
+
| `delete-failed` | 500 | Deletion or projection settlement failed; the result distinguishes an undeleted file from an already-deleted one. |
|
|
6055
6418
|
|
|
6056
6419
|
§problems-exec **Execution Problems.** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6057
6420
|
|
|
@@ -6061,6 +6424,19 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6061
6424
|
| `input-unavailable` | 409 | This execution's input receiver is no longer enabled. |
|
|
6062
6425
|
| `stream-not-found` | 404 | No execution exists at the requested address. Recovery, when the id holds an execution under another runtime ({§exec-near-miss}): The execution at /*id* is `*runtime*:///*id*`. |
|
|
6063
6426
|
| `input-closed` | 410 | Execution input is closed. |
|
|
6427
|
+
| `executor-not-registered` | 400 | No executor or MCP service named '*runtime*' is registered for this worker. |
|
|
6428
|
+
| `runtime-unavailable` | 501 | Executable tool '*runtime*' is unavailable; detail includes the availability diagnostic. |
|
|
6429
|
+
| `lifetime-invalid` | 400 | The execution lifetime directive is invalid; detail identifies the invalid form. |
|
|
6430
|
+
| `target-classification-failed` | 500 | The execution target could not be inspected; detail includes a bounded cause. |
|
|
6431
|
+
| `source-content-unavailable` | 422 | The source scheme did not supply execution content. |
|
|
6432
|
+
| `stream-entry-write-failed` | 500 | The execution's stream entry could not be created. |
|
|
6433
|
+
| `program-is-a-tool` | 404 | The command exited 127 and names a registered tool of another runtime ({§exec-tool-fall-through}). |
|
|
6434
|
+
| `executor-did-not-conclude` | 500 | The executor did not produce a terminal result. |
|
|
6435
|
+
| `execution-cancelled` | 499 | Execution was cancelled by the service. |
|
|
6436
|
+
| `executor-invalid-result` | 500 | The executor returned an invalid operation result. |
|
|
6437
|
+
| `executor-threw` | 500 | The executor failed outside its operation result contract. |
|
|
6438
|
+
| `entry-narration-failed` | 500 | An executor entry could not be materialized or narrated. |
|
|
6439
|
+
| `input-receiver-failed` | 500 | The input receiver failed outside its result contract; delivery may be partial. |
|
|
6064
6440
|
|
|
6065
6441
|
§problems-entries **Entry scheme Problems (log, worker, entries).** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6066
6442
|
|
|
@@ -6068,12 +6444,36 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6068
6444
|
|---|---:|---|
|
|
6069
6445
|
| `read-target-required` | 400 | READ requires a log coordinate. Recovery: Provide one exact log coordinate. |
|
|
6070
6446
|
| `coordinate-malformed` | 400 | The log coordinate '*path*' is malformed. Recovery: Use one exact loop/turn/sequence coordinate. |
|
|
6447
|
+
| `kill-failed` | 400 | The log target '*path*' is malformed. (A glob the matcher cannot read: The log glob '*glob*' is malformed.) Recovery: the {§log-target-shape} sentence. |
|
|
6448
|
+
| `curation-failed` | 400 | A scoped KILL's selection could not be read: the same sentences and recovery as `kill-failed`. |
|
|
6071
6449
|
| `worker-target-required` | 400 | EDIT requires a worker:// target. Recovery: Provide the worker target. |
|
|
6072
6450
|
| `binary-edit-unsupported` | 415 | The #*channel* channel is binary and cannot be edited. |
|
|
6073
6451
|
| `message-not-implemented` | 501 | SEND does not deliver messages to *scheme* entries. Recovery: To reply, SEND to an Open Message address or omit the target. `SEND (worker://<name>)` sends a new message. |
|
|
6074
6452
|
| `worker-entity-not-editable` | 400 | A worker entity is not an editable entry. Recovery: EDIT requires an entry path, such as worker:///example.md. |
|
|
6075
6453
|
| `message-empty` | 400 | SEND has no message text or attachments. |
|
|
6076
6454
|
| `scope-unsupported` | 400 | A worker SEND takes no scope. |
|
|
6455
|
+
| `control-address-invalid` | 400 | The operation requires an authority-only worker control address. |
|
|
6456
|
+
| `named-worker-required` | 400 | A worker deliverable READ requires a named worker. |
|
|
6457
|
+
| `emission-curated-whole` | 422 | An emission has no legend lines, so a line scope selects nothing on it. |
|
|
6458
|
+
| `entry-exists` | 409 | An entry already exists at the addressed resource. |
|
|
6459
|
+
| `invalid-expression` | 400 | The full-text or graph matcher expression is invalid. |
|
|
6460
|
+
| `delete-target-required` | 400 | KILL requires a target path. |
|
|
6461
|
+
|
|
6462
|
+
§problems-client **Client interactions and message admission Problems.** Refused admission creates no replacement message or interaction.
|
|
6463
|
+
|
|
6464
|
+
| code | status | condition |
|
|
6465
|
+
|---|---:|---|
|
|
6466
|
+
| `interaction-not-pending` | 409 | The requested client interaction is not pending. |
|
|
6467
|
+
| `interaction-unsupported` | 501 | No recipient implements the requested tool for this conversation. |
|
|
6468
|
+
| `recipient-mismatch` | 403 | Only the interaction's recipient may answer it. |
|
|
6469
|
+
| `interaction-response-invalid` | 400 | The response does not satisfy the pending interaction's schema. |
|
|
6470
|
+
| `invalid-body` | 400 | A question body is not JSON, or lacks its nonempty message or requested schema. |
|
|
6471
|
+
| `offset-invalid` | 400 | An entry offset is not a nonnegative safe integer. |
|
|
6472
|
+
| `userinfo-not-allowed` | 400 | An entry target URL contains userinfo. |
|
|
6473
|
+
| `action-threw` | 500 | The client action failed outside its operation result contract. |
|
|
6474
|
+
| `message-already-accepted` | 409 | The message address was already accepted in this workspace. |
|
|
6475
|
+
| `source-not-running` | 409 | The originating task is not running; no message was admitted. |
|
|
6476
|
+
| `loop-not-open` | 409 | The named loop is not an unfinished recipient of the worker; no message was admitted. |
|
|
6077
6477
|
|
|
6078
6478
|
§problems-functionality **Server and Functionality Problems.** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6079
6479
|
|
|
@@ -6082,12 +6482,13 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6082
6482
|
| `service-starting` | 503 | The PLURNK service owns this listener but has not admitted its client interface yet. |
|
|
6083
6483
|
| `route-not-found` | 404 | The requested HTTP route does not exist. |
|
|
6084
6484
|
| `configuration-invalid` | 503 | The owning configuration reader's diagnostic, naming the invalid key. Recovery: Correct the named configuration input. Other capabilities remain available. |
|
|
6085
|
-
| `name-reserved` | 400 | '*alias*' is
|
|
6485
|
+
| `name-reserved` | 400 | '*alias*' is reserved in env entries and invocation overrides. Recovery: READ worker:///_plurnk/plurnk/env.md for supported configuration paths. |
|
|
6086
6486
|
| `value-invalid` | 400 | '*alias*' needs a string value. |
|
|
6087
6487
|
| `env-invalid` | 400 | `env` must be an object of string values; '*name*' is not a name a shell can export. |
|
|
6488
|
+
| `source-unknown` | 400 | '*source*' is not a package in the configuration catalog. Recovery: Omit source to list the catalog. READ files; set variables with add or EDIT (env:///NAME). |
|
|
6088
6489
|
| `query-invalid` | 400 | '*query*' names no path or pattern. Recovery: Supply a path such as `docs/guide.md` or a pattern such as `docs/**`. |
|
|
6089
6490
|
| `headless` | 409 | The workspace has no project root, so there are no file members. Recovery: Open the workspace on a project root. |
|
|
6090
|
-
| `definition-invalid` | 400 | A members definition is { glob }: a
|
|
6491
|
+
| `definition-invalid` | 400 | A members definition is { glob }: a shell-path pattern, `!glob` to exclude. |
|
|
6091
6492
|
| `model-scope` | 403 | The model may not change membership here: the members scope is none. Recovery: `git add` the file so git tracks it, or ask the operator to add it (/members add) or raise PLURNK_SERVICE_MEMBERS_MODEL_SCOPE. |
|
|
6092
6493
|
| `workspace-not-found` | 404 | Workspace *id* does not exist. |
|
|
6093
6494
|
| `state-not-json` | 400 | Worker module state is not JSON-serializable. |
|
|
@@ -6098,23 +6499,35 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6098
6499
|
| `offset-channel-required` | 400 | Recovery: Select the channel to read from the offset. |
|
|
6099
6500
|
| `target-invalid` | 400 | Recovery: Use a scheme://path target. |
|
|
6100
6501
|
| `proposal-not-pending` | 409 | Recovery: Refresh pending proposals before resolving one. |
|
|
6502
|
+
| `proposal-decision-unrecorded` | 500 | The approval decision could not be saved; the operation was not applied. |
|
|
6101
6503
|
| `scope-cancelled` | 499 | The worker scope was cancelled: *reason*. |
|
|
6102
6504
|
| `range-not-satisfiable` | 416 | `Range <0,-1>` starts at 0, which is not a line; lines are numbered from 1. Recovery: Trim one line with `<L>` or lines L through M with `<L,M>`; `KILL (log:///…/READ)` with no scope retires the whole row. |
|
|
6505
|
+
| `runtime-owner-reserved` | 409 | The runtime owner cannot be registered by a client. |
|
|
6506
|
+
| `owner-not-found` | 404 | The owner address is not registered in the workspace. |
|
|
6507
|
+
| `proposal-policy-failed` | 500 | Core could not establish the proposal's settlement policy. |
|
|
6508
|
+
| `handler-unavailable` | 410 | The proposed scheme handler is no longer available. |
|
|
6509
|
+
| `proposal-apply-threw` | 500 | The scheme failed outside its proposal application contract. |
|
|
6510
|
+
| `verb-unknown` | 400 | The requested verb is not a lifecycle verb of the addressed family. |
|
|
6511
|
+
| `arguments-not-json` | 400 | The lifecycle verb's body must be a JSON object. |
|
|
6512
|
+
| `dispatch-threw` | 500 | The Plurnk actor failed outside its operation result contract. |
|
|
6103
6513
|
|
|
6104
6514
|
§pinned-wording-core **Pinned wording.** Verbatim sentences tests pin: each is contract, and a change here is a change of contract.
|
|
6105
6515
|
|
|
6106
6516
|
| sentence | arises when |
|
|
6107
6517
|
|---|---|
|
|
6108
6518
|
| Nothing is in flight. Continuing. | a WAIT (or a premature terminal) with no live work ({§wait-obligation-matrix}) |
|
|
6109
|
-
|
|
|
6519
|
+
| All Open Messages resolved. Review new results; emit no OPs if finished. | resolved messages with unobserved results ({§loop-completion}) |
|
|
6110
6520
|
| Context exceeds budget. YOU MUST ONLY KILL, MOVE or NOTE this turn. | the over-budget row ({§context-over-budget-row}) |
|
|
6521
|
+
| YOU MUST NOT exceed budget. Context is at *N*% of budget. | a packet within its budget under pressure ({§context-pressure-notice}) |
|
|
6522
|
+
| YOU MUST record at least one NOTE along with other operations. The turn continued without a NOTE. | a continuing or parked model turn without a NOTE ({§continued-without-note}) |
|
|
6523
|
+
| Each directive in the notice table | a notice of the model's own output ({§notice-directive}) |
|
|
6111
6524
|
| Context window overflow: the packet cannot fit the model's window even as receipts. | the wall ({§context-wall}) |
|
|
6112
6525
|
| No recipient implements the requested interaction. | The worker's owner is not interactive or does not declare the required client tool ({§client-interaction-routing}). |
|
|
6113
6526
|
| Nobody is present to answer. Decide from what you already have, or conclude stating what you could not resolve. | dispatch of an interaction tool the worker's owner would not receive ({§owner-interaction-ring}) |
|
|
6114
6527
|
| Worker name '*name*' must match `[A-Za-z0-9][A-Za-z0-9_-]{0,62}`. Recovery: Use 1–63 ASCII letters, digits, '_' or '-', starting with a letter or digit. | an invalid worker name |
|
|
6115
6528
|
| Provide the client identifier. / Provide an absolute project path. / Use a positive integer limit. / prompt is not a non-empty string. | client input validation on the daemon's methods |
|
|
6116
6529
|
| The stream was cancelled by KILL. | a stream terminal after KILL |
|
|
6117
|
-
| '*
|
|
6530
|
+
| '*runtime*' exited with code 127; `*program*` is a registered tool of `*owner*`. | a tool run as a shell command ({§exec-tool-fall-through}) |
|
|
6118
6531
|
| '*path*' is a directory, not a file; READ reads one file. Recovery: `FIND (_path_/)` lists its files. | READ of a directory |
|
|
6119
6532
|
| The execution at ops://*worker*/*loop* has not concluded. | a bare READ of a running worker's result (425) |
|
|
6120
6533
|
| The child provider failed. | a child's provider failure read back by its parent |
|