@plurnk/plurnk-service 3.2.0 → 4.0.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 +3 -3
- package/INSTALL.md +6 -0
- package/README.md +2 -2
- package/SPEC.md +489 -186
- package/dist/build-info.json +1 -1
- package/dist/completions/_plurnk-service +1 -1
- package/dist/completions/plurnk-service.bash +1 -1
- package/dist/completions/plurnk-service.fish +2 -0
- package/dist/content/read-projector.js +1 -1
- package/dist/content/read-projector.js.map +1 -1
- package/dist/core/AdministrativeLoop.d.ts +1 -1
- package/dist/core/AdministrativeLoop.d.ts.map +1 -1
- package/dist/core/AdministrativeLoop.js +4 -1
- package/dist/core/AdministrativeLoop.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +8 -0
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BareBatchRunner.js +2 -1
- package/dist/core/BareBatchRunner.js.map +1 -1
- package/dist/core/BudgetReadout.d.ts +1 -3
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +43 -46
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/ChannelWrite.d.ts +10 -0
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/ChannelWrite.js +10 -0
- package/dist/core/ChannelWrite.js.map +1 -1
- package/dist/core/ChannelWrite.sql +14 -2
- package/dist/core/ClientInteractions.d.ts.map +1 -1
- package/dist/core/ClientInteractions.js +2 -1
- package/dist/core/ClientInteractions.js.map +1 -1
- package/dist/core/CoreSchemeServices.d.ts.map +1 -1
- package/dist/core/CoreSchemeServices.js +6 -0
- package/dist/core/CoreSchemeServices.js.map +1 -1
- package/dist/core/DataStatementRunner.js +4 -6
- package/dist/core/DataStatementRunner.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +3 -7
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +53 -73
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/Dispatcher.sql +2 -2
- package/dist/core/EditMutations.js +1 -0
- package/dist/core/EditMutations.js.map +1 -1
- package/dist/core/Engine.d.ts +8 -14
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +22 -24
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Engine.sql +6 -6
- package/dist/core/ExecutorRegistry.d.ts +0 -5
- package/dist/core/ExecutorRegistry.d.ts.map +1 -1
- package/dist/core/ExecutorRegistry.js +10 -18
- package/dist/core/ExecutorRegistry.js.map +1 -1
- package/dist/core/FileAddress.js +1 -1
- package/dist/core/FileAddress.js.map +1 -1
- package/dist/core/FilePublication.js +10 -74
- package/dist/core/FilePublication.js.map +1 -1
- package/dist/core/FileSnapshot.js +36 -100
- package/dist/core/FileSnapshot.js.map +1 -1
- package/dist/core/HostPaths.d.ts +1 -0
- package/dist/core/HostPaths.d.ts.map +1 -1
- package/dist/core/HostPaths.js +11 -1
- package/dist/core/HostPaths.js.map +1 -1
- package/dist/core/KillHandler.js +3 -1
- package/dist/core/KillHandler.js.map +1 -1
- package/dist/core/LiveSubscription.js +1 -1
- package/dist/core/LiveSubscription.js.map +1 -1
- package/dist/core/LogBody.js +1 -1
- package/dist/core/LogBody.js.map +1 -1
- package/dist/core/LogWriter.js +1 -1
- package/dist/core/LogWriter.js.map +1 -1
- package/dist/core/LoopDriver.d.ts +3 -3
- package/dist/core/LoopDriver.d.ts.map +1 -1
- package/dist/core/LoopDriver.js +15 -13
- package/dist/core/LoopDriver.js.map +1 -1
- package/dist/core/LoopLifecycle.d.ts +5 -0
- package/dist/core/LoopLifecycle.d.ts.map +1 -1
- package/dist/core/LoopLifecycle.js +14 -1
- package/dist/core/LoopLifecycle.js.map +1 -1
- package/dist/core/LoopLifecycle.sql +11 -2
- package/dist/core/MembershipMaterialization.js +2 -2
- package/dist/core/MembershipMaterialization.js.map +1 -1
- package/dist/core/MessageResources.d.ts +3 -0
- package/dist/core/MessageResources.d.ts.map +1 -1
- package/dist/core/MessageResources.js +15 -1
- package/dist/core/MessageResources.js.map +1 -1
- package/dist/core/OperatorConfig.d.ts +1 -2
- package/dist/core/OperatorConfig.d.ts.map +1 -1
- package/dist/core/OperatorConfig.js +26 -92
- package/dist/core/OperatorConfig.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +21 -18
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/PacketBuilder.sql +18 -5
- package/dist/core/ProblemLog.d.ts +1 -0
- package/dist/core/ProblemLog.d.ts.map +1 -1
- package/dist/core/ProblemLog.js +2 -2
- package/dist/core/ProblemLog.js.map +1 -1
- package/dist/core/ProposalLifecycle.d.ts +1 -0
- package/dist/core/ProposalLifecycle.d.ts.map +1 -1
- package/dist/core/ProposalLifecycle.js +14 -8
- package/dist/core/ProposalLifecycle.js.map +1 -1
- package/dist/core/ProposalPolicies.d.ts +4 -1
- package/dist/core/ProposalPolicies.d.ts.map +1 -1
- package/dist/core/ProposalPolicies.js +5 -2
- package/dist/core/ProposalPolicies.js.map +1 -1
- package/dist/core/ResourceMutations.js +2 -0
- package/dist/core/ResourceMutations.js.map +1 -1
- package/dist/core/ResourceSelector.js +1 -1
- package/dist/core/ResourceSelector.js.map +1 -1
- package/dist/core/SchemeRegistry.js +1 -1
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/ServiceHelp.js +1 -1
- package/dist/core/ServiceHelp.js.map +1 -1
- package/dist/core/ServiceTeardown.js +9 -12
- package/dist/core/ServiceTeardown.js.map +1 -1
- package/dist/core/StrikeRail.d.ts +2 -1
- package/dist/core/StrikeRail.d.ts.map +1 -1
- package/dist/core/StrikeRail.js +11 -6
- package/dist/core/StrikeRail.js.map +1 -1
- package/dist/core/TerminalResult.js +1 -1
- package/dist/core/TerminalResult.js.map +1 -1
- package/dist/core/TurnDispositionHandler.d.ts +1 -1
- package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
- package/dist/core/TurnDispositionHandler.js +8 -5
- package/dist/core/TurnDispositionHandler.js.map +1 -1
- package/dist/core/TurnMaterialization.js +6 -4
- package/dist/core/TurnMaterialization.js.map +1 -1
- package/dist/core/TurnMaterialization.sql +1 -1
- package/dist/core/TurnOps.js +1 -0
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.d.ts +4 -2
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +63 -51
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/WorkerControlHandler.d.ts +2 -0
- package/dist/core/WorkerControlHandler.d.ts.map +1 -1
- package/dist/core/WorkerControlHandler.js +84 -16
- package/dist/core/WorkerControlHandler.js.map +1 -1
- package/dist/core/WorkerName.d.ts +0 -4
- package/dist/core/WorkerName.d.ts.map +1 -1
- package/dist/core/WorkerName.js +5 -30
- package/dist/core/WorkerName.js.map +1 -1
- package/dist/core/WorkerName.sql +4 -20
- package/dist/core/WorkerOwners.d.ts +1 -0
- package/dist/core/WorkerOwners.d.ts.map +1 -1
- package/dist/core/WorkerOwners.js +6 -0
- package/dist/core/WorkerOwners.js.map +1 -1
- package/dist/core/WorkerOwners.sql +7 -0
- package/dist/core/WorkspaceGate.d.ts +3 -1
- package/dist/core/WorkspaceGate.d.ts.map +1 -1
- package/dist/core/WorkspaceGate.js +59 -10
- package/dist/core/WorkspaceGate.js.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.d.ts +3 -0
- package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.js +14 -0
- package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
- package/dist/core/env-catalog.js +1 -1
- package/dist/core/env-catalog.js.map +1 -1
- package/dist/core/fork.js +1 -1
- package/dist/core/fork.js.map +1 -1
- package/dist/core/fork.sql +7 -6
- package/dist/core/mutation-types.d.ts +1 -0
- package/dist/core/mutation-types.d.ts.map +1 -1
- package/dist/core/mutation-types.js +4 -1
- package/dist/core/mutation-types.js.map +1 -1
- package/dist/core/namespace.js +1 -1
- package/dist/core/namespace.js.map +1 -1
- package/dist/core/packet-wire.d.ts +1 -1
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +24 -15
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/plurnk-uri.d.ts +1 -1
- package/dist/core/plurnk-uri.d.ts.map +1 -1
- package/dist/core/plurnk-uri.js +1 -1
- package/dist/core/plurnk-uri.js.map +1 -1
- package/dist/core/scheme-types.d.ts +5 -0
- package/dist/core/scheme-types.d.ts.map +1 -1
- package/dist/core/turn-signals.d.ts +4 -0
- package/dist/core/turn-signals.d.ts.map +1 -1
- package/dist/core/turn-signals.js +1 -0
- package/dist/core/turn-signals.js.map +1 -1
- package/dist/core/workspace-settings.js +1 -1
- package/dist/core/workspace-settings.js.map +1 -1
- package/dist/evidence/EvidenceReader.js +5 -5
- package/dist/evidence/EvidenceReader.js.map +1 -1
- package/dist/man/plurnk-service.1 +27 -6
- package/dist/schemes/Env.d.ts +7 -3
- package/dist/schemes/Env.d.ts.map +1 -1
- package/dist/schemes/Env.js +12 -6
- package/dist/schemes/Env.js.map +1 -1
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +37 -25
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.js +3 -3
- package/dist/schemes/ExecOutputScheme.js.map +1 -1
- package/dist/schemes/ExecutionInput.d.ts +2 -1
- package/dist/schemes/ExecutionInput.d.ts.map +1 -1
- package/dist/schemes/ExecutionInput.js +45 -7
- package/dist/schemes/ExecutionInput.js.map +1 -1
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +32 -23
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +23 -5
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Log.sql +24 -1
- package/dist/schemes/ResourceTreeScheme.js +2 -5
- package/dist/schemes/ResourceTreeScheme.js.map +1 -1
- package/dist/schemes/TurnSource.js +1 -1
- package/dist/schemes/TurnSource.js.map +1 -1
- package/dist/schemes/Worker.d.ts.map +1 -1
- package/dist/schemes/Worker.js +10 -3
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.d.ts.map +1 -1
- package/dist/schemes/_entry-crud.js +2 -4
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-crud.sql +5 -3
- package/dist/schemes/_entry-find.js +3 -3
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-manifest.d.ts.map +1 -1
- package/dist/schemes/_entry-manifest.js +3 -3
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/schemes/_entry-manifest.sql +2 -0
- package/dist/schemes/_entry-ops.js +1 -1
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/schemes/_entry-send.js +1 -1
- package/dist/schemes/_entry-send.js.map +1 -1
- package/dist/server/ClientReads.d.ts +1 -0
- package/dist/server/ClientReads.d.ts.map +1 -1
- package/dist/server/ClientReads.js +7 -2
- package/dist/server/ClientReads.js.map +1 -1
- package/dist/server/Credentials.d.ts +48 -0
- package/dist/server/Credentials.d.ts.map +1 -0
- package/dist/server/Credentials.js +203 -0
- package/dist/server/Credentials.js.map +1 -0
- package/dist/server/Daemon.d.ts +44 -39
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +287 -172
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DrainSupervisor.d.ts +8 -3
- package/dist/server/DrainSupervisor.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.js +44 -32
- package/dist/server/DrainSupervisor.js.map +1 -1
- package/dist/server/EnvFunctionality.d.ts.map +1 -1
- package/dist/server/EnvFunctionality.js +2 -1
- package/dist/server/EnvFunctionality.js.map +1 -1
- package/dist/server/Functionality.d.ts +4 -2
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js +192 -96
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/FunctionalityManager.d.ts +1 -4
- package/dist/server/FunctionalityManager.d.ts.map +1 -1
- package/dist/server/FunctionalityManager.js +6 -6
- package/dist/server/FunctionalityManager.js.map +1 -1
- package/dist/server/HttpListener.d.ts +1 -1
- package/dist/server/HttpListener.d.ts.map +1 -1
- package/dist/server/HttpListener.js.map +1 -1
- package/dist/server/MembersFunctionality.d.ts +7 -8
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js +90 -56
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/MessageAbandonment.d.ts +7 -0
- package/dist/server/MessageAbandonment.d.ts.map +1 -0
- package/dist/server/MessageAbandonment.js +57 -0
- package/dist/server/MessageAbandonment.js.map +1 -0
- package/dist/server/ModuleHost.d.ts +2 -1
- package/dist/server/ModuleHost.d.ts.map +1 -1
- package/dist/server/PlurnkSkill.js +4 -7
- package/dist/server/PlurnkSkill.js.map +1 -1
- package/dist/server/Rollback.d.ts +29 -0
- package/dist/server/Rollback.d.ts.map +1 -0
- package/dist/server/Rollback.js +111 -0
- package/dist/server/Rollback.js.map +1 -0
- package/dist/server/WorkerModelResolver.js +1 -0
- package/dist/server/WorkerModelResolver.js.map +1 -1
- package/dist/server/WorkerReferences.d.ts +14 -0
- package/dist/server/WorkerReferences.d.ts.map +1 -0
- package/dist/server/WorkerReferences.js +24 -0
- package/dist/server/WorkerReferences.js.map +1 -0
- package/dist/server/WorkerReferences.sql +31 -0
- package/dist/server/WorkspaceCapabilities.d.ts +2 -0
- package/dist/server/WorkspaceCapabilities.d.ts.map +1 -1
- package/dist/server/WorkspaceCapabilities.js +35 -18
- package/dist/server/WorkspaceCapabilities.js.map +1 -1
- package/dist/server/WorkspacePlugins.js +1 -0
- package/dist/server/WorkspacePlugins.js.map +1 -1
- package/dist/server/WorkspaceResidency.d.ts +3 -1
- package/dist/server/WorkspaceResidency.d.ts.map +1 -1
- package/dist/server/WorkspaceResidency.js +12 -5
- package/dist/server/WorkspaceResidency.js.map +1 -1
- package/dist/server/client-input.d.ts +2 -0
- package/dist/server/client-input.d.ts.map +1 -1
- package/dist/server/client-input.js +28 -0
- package/dist/server/client-input.js.map +1 -1
- package/dist/server/drain.sql +46 -40
- package/dist/server/envelope.d.ts +5 -9
- package/dist/server/envelope.d.ts.map +1 -1
- package/dist/server/envelope.js +21 -84
- package/dist/server/envelope.js.map +1 -1
- package/dist/server/envelope.sql +17 -17
- package/dist/server/lifecycle-recovery.sql +5 -15
- package/dist/server/logEntry.d.ts.map +1 -1
- package/dist/server/logEntry.js +6 -0
- package/dist/server/logEntry.js.map +1 -1
- package/dist/server/logEntry.sql +94 -6
- package/dist/server/module-discovery.d.ts +1 -1
- package/dist/server/module-discovery.d.ts.map +1 -1
- package/dist/server/module-discovery.js +1 -0
- package/dist/server/module-discovery.js.map +1 -1
- package/dist/server/seam-loop.sql +15 -7
- package/dist/server/seam-proposal-list.sql +10 -4
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +7 -1
- package/dist/service.js.map +1 -1
- package/docs/members.md +20 -13
- package/migrations/002_workers.sql +2 -2
- package/migrations/006_log.sql +1 -1
- package/migrations/018_worker_owners.sql +1 -1
- package/migrations/026_message_obligations.sql +32 -0
- package/migrations/027_members_identity.sql +20 -0
- package/migrations/028_mutation_patch.sql +20 -0
- package/migrations/029_default_worker.sql +9 -0
- package/migrations/030_client_workers.sql +105 -0
- package/migrations/031_message_openers.sql +83 -0
- package/migrations/032_worker_references.sql +29 -0
- package/package.json +24 -24
- package/plurnk.nginx.conf +71 -0
- package/plurnk.service +2 -0
package/SPEC.md
CHANGED
|
@@ -40,11 +40,11 @@ Canonical meanings. When a doc, comment, test name, or commit message uses one o
|
|
|
40
40
|
|
|
41
41
|
```mermaid
|
|
42
42
|
flowchart LR
|
|
43
|
-
W["Workspace<br/>shared
|
|
43
|
+
W["Workspace<br/>shared resources and configuration"] --> K["Worker<br/>actor and history"]
|
|
44
44
|
K --> L["Loop<br/>queued-to-terminal work"]
|
|
45
45
|
L --> T["Turn<br/>one admitted scheduling unit"]
|
|
46
46
|
T --> O["Op<br/>one statement / action row"]
|
|
47
|
-
H["AG-UI thread<br/>
|
|
47
|
+
H["AG-UI thread<br/>names a worker"] -. resolves to .-> K
|
|
48
48
|
R["AG-UI Run<br/>client stream envelope"] -. binds to .-> L
|
|
49
49
|
R -. or executes .-> A["Management action<br/>no core loop required"]
|
|
50
50
|
```
|
|
@@ -52,7 +52,7 @@ flowchart LR
|
|
|
52
52
|
| Term | Layer | Meaning |
|
|
53
53
|
|-------------------|-----------------------|---------|
|
|
54
54
|
| **agent** | PLURNK | The plurnk runtime. Acts in-workspace as the `_plurnk` worker ({§actor-boundary} self-hosting), never a privileged singleton owning its own entries ({§entry-owner}, {§machine-processes}). |
|
|
55
|
-
| **workspace** | Core | Durable
|
|
55
|
+
| **workspace** | Core | Durable shared resources and configuration, with an optional project folder. Identity: `workspaces.id`; mutable label: unique `workspaces.name`. Persists across workers and process restarts. |
|
|
56
56
|
| **worker** | Core | Durable actor and history over one workspace. Owns its loops and log rows, may carry a `parent_worker_id`, and has one process-local cancellation scope while active. |
|
|
57
57
|
| **loop** | Core | Queued-to-terminal unit of model or client work within a worker. Status ∈ {100 pending · 102 running · 200 done · 202 waiting (blocked on a live obligation, {§send}) · 413 input-capacity failure · 429 model-turn ceiling · 499 cancelled · 500 failed · 504 execution timeout ({§operator-config-loop-timeout}) · 508 runaway}. Many loops may belong to one worker. |
|
|
58
58
|
| **turn** | Core | One durable, producer-neutral batch of ordered operations. A turn may be authored by a model, client, or `_plurnk`; only a model turn assembles a packet and owns an emission call. Many turns may belong to one loop. Identity: `(loop_id, sequence)`. |
|
|
@@ -62,7 +62,7 @@ flowchart LR
|
|
|
62
62
|
| **action** | Core | One executed op. Execution normally produces a `log_entries` row at `log:///<L>/<T>/<S>/<op>`; an engine rail may instead record an `op='error'` row ({§operation-results}). A source artifact carries no fabricated operation. |
|
|
63
63
|
| **dispatch** | Core | Routing a statement to its scheme's op handler. |
|
|
64
64
|
| **AG-UI Run** | AG-UI protocol | A client request/stream envelope identified by the client's `runId`. A message or resume AG-UI Run binds to one core loop; a management-action AG-UI Run may complete without creating a core loop. |
|
|
65
|
-
| **AG-UI thread** | AG-UI protocol |
|
|
65
|
+
| **AG-UI thread** | AG-UI protocol | Message history identity. Within an explicitly selected workspace, `threadId` resolves to one model worker. |
|
|
66
66
|
|
|
67
67
|
### Storage terms
|
|
68
68
|
|
|
@@ -202,7 +202,8 @@ early ownership introduces neither traffic nor a close/rebind race.
|
|
|
202
202
|
§http-host **The daemon opens exactly one transport.** Core binds the HTTP
|
|
203
203
|
listener on `PLURNK_HOST:PLURNK_PORT` and offers it to every exterior adapter as
|
|
204
204
|
`registerHttpRoute(prefix, handler)` and `httpAddress()` on the application port
|
|
205
|
-
({§application-port}).
|
|
205
|
+
({§application-port}). The listener is bound before any module sets up, so the setup seam
|
|
206
|
+
offers `httpAddress()` too ({§module-host-capabilities}). A prefix is an absolute pathname. Each request goes to the
|
|
206
207
|
longest mounted prefix; a prefix claims itself and the subtree beneath it, never
|
|
207
208
|
a longer sibling name; `/` is the root and receives whatever nothing more
|
|
208
209
|
specific claimed when a module mounts it. An admitted listener returns an HTTP
|
|
@@ -215,6 +216,67 @@ none opens a socket of its own. The standards
|
|
|
215
216
|
address by URL, never by port (#641): AG-UI mounts only `/agui`, A2A the
|
|
216
217
|
well-known card and its endpoint path, on the same address.
|
|
217
218
|
|
|
219
|
+
§http-request-origin **What the daemon advertises follows the address a caller used.** A request's
|
|
220
|
+
origin is the address its `Host` names, over http, or the listener's own for a request that names
|
|
221
|
+
none (`requestOrigin`). Every address the daemon advertises to a caller, the authority's issuer
|
|
222
|
+
({§agui-oauth-endpoints}) and the A2A card's endpoint, is its configured public origin or the origin
|
|
223
|
+
of the request that asked, so a daemon bound to every interface answers each caller at the address
|
|
224
|
+
that caller used; a module that asks with no request in hand, as one reading the issuer at its
|
|
225
|
+
start does, is answered with the configured origin or the listener's own. A configured origin is for
|
|
226
|
+
a front the daemon cannot see, such as a TLS proxy. No request is refused for the name it uses.
|
|
227
|
+
|
|
228
|
+
§credential-authority **The daemon is one credential authority.** Every credential presented
|
|
229
|
+
to its listener, whatever protocol is mounted there, was issued by the daemon's `credentials`
|
|
230
|
+
authority on the application port ({§application-port}): an opaque random token held in memory
|
|
231
|
+
with its kind (`access`, presented as a bearer; `refresh`, exchanged and never presented), its
|
|
232
|
+
subject, its client, its scopes, its family and its expiry. A restart revokes every credential.
|
|
233
|
+
Revocation is by family, so an access token and the refresh token that renews it fall together;
|
|
234
|
+
a refresh token is consumed once, and a second presentation revokes its family and says so. The
|
|
235
|
+
authority has no HTTP face and no policy of its own: the issuing module publishes the one face
|
|
236
|
+
(`publish({ issuer })`, at setup) that names where a request's caller obtains credentials
|
|
237
|
+
({§http-request-origin}) and answers from its publication, so any module may read the issuer from its own `start` on ({§module-phases}), an
|
|
238
|
+
exterior adapter
|
|
239
|
+
verifies through it ({§agui-http-authorization}), and the client protocol issues through it
|
|
240
|
+
({§agui-oauth}). The posture is the shared `PLURNK_AUTH` ({§operator-config-shared-keys}) and is
|
|
241
|
+
never inferred from what else is set. Under `1` the authority holds the operator's client secret,
|
|
242
|
+
`PLURNK_SECRET` when set, else one minted for this boot and written to the file `secret` beside the
|
|
243
|
+
database, 0600 and complete or absent, before any mount is admitted, where a tool running as the
|
|
244
|
+
operator reads it; a configured secret and a daemon that does not authenticate leave no such file. A
|
|
245
|
+
listening daemon under `1` refuses to start until a module publishes the face. Under `0` no
|
|
246
|
+
credential exists, no face is published and every mounted resource admits anonymously. Credentials
|
|
247
|
+
the daemon presents to others follow the remote party's declared scheme and are never minted here.
|
|
248
|
+
|
|
249
|
+
§credential-module-client **A module of this daemon is a confidential client by registration.** At
|
|
250
|
+
setup a module registers its own client on the authority, `registerClient({ id, redirectPaths, scopes, stylesheetPath })`:
|
|
251
|
+
an id of letters, digits, `.`, `_` or `-` other than `operator`, the absolute pathnames under its own
|
|
252
|
+
mounts it may be answered at, each as a URL carries it, with no query and no fragment, the scopes it
|
|
253
|
+
may ask for and, optionally, the pathname in the same form of a stylesheet under its own mounts,
|
|
254
|
+
which the issuing face links on the documents it serves that client's requests
|
|
255
|
+
({§agui-oauth-documents}). A module states no origin: it serves only on the daemon's one listener
|
|
256
|
+
({§http-host}), so its address is its path on the issuer, and registration needs nothing from the
|
|
257
|
+
listener, the issuer or another module. The issuing face answers the client at exactly the issuer
|
|
258
|
+
followed by a registered path ({§agui-oauth-endpoints}), and the module forms the same address from
|
|
259
|
+
`credentials.face().issuer()`, from its `start` on ({§credential-authority}). The authority mints the client's
|
|
260
|
+
secret for this boot, holds it in memory, answers it to the registrant and to nobody else, and
|
|
261
|
+
checks it in constant time (`authenticateClient`); `client(id)` tells any module the registration
|
|
262
|
+
without the secret. A second registration of one id and a malformed registration are faults and
|
|
263
|
+
register nothing. Nothing is configured, printed or persisted, so installing a module adds no
|
|
264
|
+
operator step. The issuing face authenticates such a client as it does any confidential one
|
|
265
|
+
({§agui-oauth-clients}). A module's own browser session is a credential of this authority too: a
|
|
266
|
+
`session` credential it issues in the family of the authorization grant it stands on, which is the
|
|
267
|
+
family of the browser's sign-in that authorized it ({§agui-oauth-session}), so revoking that family
|
|
268
|
+
from either side ends the module's session, its tokens and the browser's standing at the issuing
|
|
269
|
+
face together.
|
|
270
|
+
|
|
271
|
+
§credential-sessions **A browser sign-in is a family, and a subject's sign-ins are listed without a
|
|
272
|
+
token.** `sessions(subject)` answers every family of that subject that holds a live `session`
|
|
273
|
+
credential, oldest first: the family, which is the sign-in's handle and is never admitted as a
|
|
274
|
+
credential; the subject; when a credential was first issued into the family; when the last of its
|
|
275
|
+
session credentials expires; and the clients holding credentials in it. A grant with no session
|
|
276
|
+
credential, such as a client's `client_credentials` token or a consented client's code grant, is no
|
|
277
|
+
sign-in and is not listed. Revoking a listed family ({§credential-authority}) is signing that browser
|
|
278
|
+
out. Nothing records last activity or a device, and a restart ends every sign-in.
|
|
279
|
+
|
|
218
280
|
§startup-admission-order After listener ownership, database admission completes
|
|
219
281
|
before capability initialization can perform external work. Provider construction
|
|
220
282
|
and endpoint verification occur on worker selection or first use, never merely
|
|
@@ -262,7 +324,7 @@ not access to workspace resources ({§actor-boundary-no-mutex}).
|
|
|
262
324
|
| Root creation | Explicit owner, otherwise the runtime `_plurnk`. |
|
|
263
325
|
| WORK, FORK, or a fresh child | Inherit the parent's owner. |
|
|
264
326
|
| SEND, schedule occurrence, or other incoming message | Preserve the recipient's owner. |
|
|
265
|
-
| Explicit client control attachment | Claim a runtime-owned
|
|
327
|
+
| Explicit client control attachment | Claim a runtime-owned model worker and its runtime-owned descendants; never claim the runtime actor or replace another owner. |
|
|
266
328
|
| Observation or disconnect | No change. |
|
|
267
329
|
|
|
268
330
|
An owner declares its capability set: the client tool names it implements, and whether it
|
|
@@ -313,12 +375,12 @@ filter over workspace resources.
|
|
|
313
375
|
**attribution** — the delta's provenance ({§env-delta}) — and is never read to
|
|
314
376
|
filter a row.
|
|
315
377
|
|
|
316
|
-
§actor-boundary-attached-functionality **Attachment selects a
|
|
378
|
+
§actor-boundary-attached-functionality **Attachment selects a worker,
|
|
317
379
|
not an environment owner.** Client management commands mutate workspace
|
|
318
380
|
Functionality ({§module-workspace-capabilities}); runtimes, runtime
|
|
319
|
-
schemes, and tools resolve by `workspaceId`.
|
|
320
|
-
|
|
321
|
-
|
|
381
|
+
schemes, and tools resolve by `workspaceId`. A model's operations journal in its
|
|
382
|
+
worker, and a person's client operations in the workspace's runtime worker
|
|
383
|
+
({§connection-lifecycle}). Runtime and policy resolution require no second worker identity.
|
|
322
384
|
Attachment remains many-to-one and unrelated to parentage. Explicit control
|
|
323
385
|
attachment may claim approval ownership under {§worker-ownership}.
|
|
324
386
|
|
|
@@ -422,7 +484,7 @@ direct-entry-plus-directory count; `-1` enables the ordinary markerless page;
|
|
|
422
484
|
unset / `0` disables previews. `log://` is absent because the current worker's
|
|
423
485
|
log already renders in present mode.
|
|
424
486
|
|
|
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,
|
|
487
|
+
§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, opened by one NOTE and closed by another 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 two NOTEs show the card's NOTE practice in the example turn: the opening one carries the aside of the card's first NOTE example, `<!-- plan -->`, and is the worker's plan in numbered steps, each with its purpose: survey what exists, read the Open Message and restate what it asks for and what will show it is done, then do the work recording each finding, decision and next action in a NOTE; the closing one carries the aside of the card's last NOTE example, `<!-- next -->`, and reads `Read and resolve the Open Message.` No emission row is fabricated ({§emission-row}): the first request sees the NOTEs 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}.
|
|
426
488
|
|
|
427
489
|
Incoming messages publish once as inbound SEND rows in the first model turn
|
|
428
490
|
({§message-arrival}); initialization neither READs nor archives them. The turn
|
|
@@ -481,8 +543,8 @@ for a loop, `(loop, sequence)` for a turn, `(turn, sequence)` for a log row —
|
|
|
481
543
|
outside the database, every copied row passes the same table triggers the original did, and a fork
|
|
482
544
|
either lands whole or not at all. Nothing else runs: `Fork.fork` is the claim.
|
|
483
545
|
|
|
484
|
-
§machine-processes-worker-is-its-log **A worker's
|
|
485
|
-
the shared
|
|
546
|
+
§machine-processes-worker-is-its-log **A worker's memory of
|
|
547
|
+
the shared workspace is its log, with no hidden per-worker snapshot beside it.**
|
|
486
548
|
A scoped KILL suppresses canonical body intervals on that worker's rows ({§log-kill-scope});
|
|
487
549
|
lineage activity and explicit commons broadcasts arrive as attributed log
|
|
488
550
|
entries ({§env-delta}). Named scratch and evidence follow {§machine-processes-entry-inheritance}. They are not an invisible mirror of shared state. Workspace
|
|
@@ -497,9 +559,9 @@ the parent after that boundary is sibling activity, not fork history. Global
|
|
|
497
559
|
commons broadcasts remain live after the fork because the branch is then an
|
|
498
560
|
existing workspace worker in its own right.
|
|
499
561
|
|
|
500
|
-
§machine-processes-model-worker-readable **Packet membership is per-worker, not an access policy.** A packet contains its worker's log plus explicitly delivered activity ({§actor-boundary}). `readLog({ workspaceId, workerId })` may inspect any worker belonging to that workspace, and `listWorkers` enumerates them. A client-interface module chooses its
|
|
562
|
+
§machine-processes-model-worker-readable **Packet membership is per-worker, not an access policy.** A packet contains its worker's log plus explicitly delivered activity ({§actor-boundary}). `readLog({ workspaceId, workerId })` may inspect any worker belonging to that workspace, and `listWorkers` enumerates them. A client-interface module chooses its worker binding. Inspection does not inject another log into a model's packet.
|
|
501
563
|
|
|
502
|
-
§machine-processes-worker-origin **A worker carries its actor.** Each worker records its `origin
|
|
564
|
+
§machine-processes-worker-origin **A worker carries its actor.** Each worker records its `origin`, set once at creation: `model` (a model's identity) or `_plurnk` (the workspace's runtime worker, where the daemon's own work and a person's client operations journal, {§connection-lifecycle}). Every worker WORK or FORK creates is a model worker: a model's is its child, and a person's operation starts a root worker or branches the worker it acts for ({§actor-boundary-client-operations}). `listWorkers` returns actor class without interpreting names; a retained worker's name is immutable ({§machine-processes-worker-is-its-log}).
|
|
503
565
|
|
|
504
566
|
§worker-provider-identity **A worker owns a durable provider identity distinct
|
|
505
567
|
from its database id.** Creation mints a globally unique, opaque 128-bit value;
|
|
@@ -508,7 +570,7 @@ emission ({§provider-cache-identity}). Database ids remain the internal relatio
|
|
|
508
570
|
client coordinate. BARE calls use isolated per-call provider identities rather
|
|
509
571
|
than either worker value.
|
|
510
572
|
|
|
511
|
-
§machine-processes-fork-shares-
|
|
573
|
+
§machine-processes-fork-shares-workspace **A fork copies history and named
|
|
512
574
|
scratch while sharing the workspace.** It is a new worker in the
|
|
513
575
|
same workspace (`workers.parent_worker_id`, {§lifecycle-terms}); project files,
|
|
514
576
|
shared entries, and membership remain live and uncopied.
|
|
@@ -523,9 +585,10 @@ or membership overlay requires a new workspace.
|
|
|
523
585
|
§worker-authority-carving **Authority is a literal namespace, not a principal.** `worker:///notes.md` is shared scratch; `worker://alice/draft.md` is named scratch. Both belong directly to the workspace ({§entry-owner}). Entry addresses require no namesake Worker row and survive its deletion; only pathless worker controls resolve an actor. The caller never alters an address, and `~` has no alias semantics.
|
|
524
586
|
|
|
525
587
|
§worker-name-minting **URI ingestion is permissive; worker minting is not.**
|
|
526
|
-
Every model
|
|
588
|
+
Every model worker-creation door applies the contracts-owned
|
|
527
589
|
`WORKER_NAME` predicate ({§worker-name}) through one core admission path. Generic URL parsing
|
|
528
|
-
continues to decompose other authorities without treating them as mintable
|
|
590
|
+
continues to decompose other authorities without treating them as mintable, and an exact read by
|
|
591
|
+
name ({§methods-worker-read}) is no creation door: it resolves `_plurnk` like any listed name.
|
|
529
592
|
|
|
530
593
|
| Candidate | Minting result |
|
|
531
594
|
| ---------------------------------------------- | --------------------------------------------------------------------- |
|
|
@@ -566,7 +629,7 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
|
|
|
566
629
|
| `READ` | existing literal name | Collect the named worker's deliverable. |
|
|
567
630
|
| `KILL` | existing literal name | Terminate the named worker or caller. |
|
|
568
631
|
|
|
569
|
-
- §worker-scheme-spawn **Spawn** — ```` ```WORK (worker://<name>)? ```` with a task body creates a new child worker (empty log) and starts it with that task on its first loop. WORK/FORK are the worker-creation verbs: EDIT is file/entry only, so EDIT on the bare worker entity is a **400** steering to WORK/FORK — the entity is not an entry. Names remain unique within a workspace for the lifetime of retained Worker rows, including after termination.
|
|
632
|
+
- §worker-scheme-spawn **Spawn** — ```` ```WORK (worker://<name>)? ```` with a task body creates a new child worker (empty log) and starts it with that task on its first loop; a person's operation starts a root worker that person owns instead ({§actor-boundary-client-operations}). WORK/FORK are the worker-creation verbs: EDIT is file/entry only, so EDIT on the bare worker entity is a **400** steering to WORK/FORK — the entity is not an entry. Names remain unique within a workspace for the lifetime of retained Worker rows, including after termination. A WORK whose name a worker already holds is the voice door ({§worker-scheme-irc}): its body is delivered to that worker as a message, nothing is created, the receipt names the worker and `delivered: message`, and an `env` option is refused by name since a message takes none. A FORK whose name a worker holds is `409 worker-name-conflict` whose recovery names the working forms, WORK or `SEND (worker://<name>)` to message the live worker, or a name no worker holds to branch; concurrent claims cannot redirect a published address or expose a raw uniqueness failure.
|
|
570
633
|
- §worker-spawn-prompt-resource **The spawn slot is overloaded by scheme.** A `worker://` path is
|
|
571
634
|
the child's address and keeps the address rules ({§worker-control-addressing}). A path of any
|
|
572
635
|
other scheme is the child's prompt resource: it is read whole (`<1,-1>`) under the caller's read capabilities, composed with
|
|
@@ -580,7 +643,8 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
|
|
|
580
643
|
- §worker-scheme-fork **Fork** — ```` ```FORK (worker://<name>)? ```` with a task body branches the
|
|
581
644
|
current worker into a **named** child: its log is deep-copied
|
|
582
645
|
({§machine-processes-fork-copies-the-log}), which continues with `task`; the
|
|
583
|
-
|
|
646
|
+
workspace is shared, never copied ({§machine-processes-fork-shares-workspace}). A
|
|
647
|
+
person's operation branches the worker it acts for ({§actor-boundary-client-operations}).
|
|
584
648
|
WORK and FORK are distinct verbs — WORK spawns a fresh worker, FORK branches
|
|
585
649
|
the log. Both report the resulting `worker://name` address in receipt
|
|
586
650
|
metadata `worker`, whether named explicitly or allocated automatically.
|
|
@@ -618,11 +682,11 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
|
|
|
618
682
|
A failure reports its problem even when the loop answered earlier: the failure is the news.
|
|
619
683
|
READs and completion observations use the same resolution, representation and projector.
|
|
620
684
|
- §child-orientation **Child orientation.** Beyond the conclusion delta, every
|
|
621
|
-
turn the packet's status clump surfaces the
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
the errors section). Body-suppressed child activity is durable
|
|
685
|
+
turn the packet's status clump surfaces the work this worker currently holds
|
|
686
|
+
open, beside the messages it owes: `## Open Work` is one JSON object, `{"workers": [...], "streams": [...], "messages": [...]}`, its
|
|
687
|
+
unconcluded child workers, its open streams and the messages it sent that await
|
|
688
|
+
completion ({§worker-obligations}) as `{status, path}` pointers (the same shape as
|
|
689
|
+
the errors section); a message pointer carries the recipient loop's status. Body-suppressed child activity is durable
|
|
626
690
|
history; this section is the current inventory that keeps an active obligation
|
|
627
691
|
visible even when no new activity arrived. Each open stream pointer carries
|
|
628
692
|
elapsed runtime, output inactivity, and its channels' sizes and growth since
|
|
@@ -642,22 +706,24 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
|
|
|
642
706
|
Workspace schedules are not held work: an occurrence arrives as a message
|
|
643
707
|
({§schedule-delivery}).
|
|
644
708
|
- §packet-empty-sections **Emptiness is stated where the model decides on it.**
|
|
645
|
-
`##
|
|
709
|
+
`## Open Work` renders every turn, each of its lists `[]` when empty: the
|
|
646
710
|
model decides whether to wait or complete on exactly these facts, so their
|
|
647
711
|
emptiness is stated rather than inferred from a missing heading. This is the
|
|
648
712
|
deliberate exception to the wire rule that empty content is absent; errors,
|
|
649
713
|
notices, and the rest keep that rule. The parent is not a section: the
|
|
650
714
|
`## Worker` identity block carries `"parent": "worker://<name>"`, or
|
|
651
715
|
`"parent": null` at a root, so a worker never infers its rank from silence.
|
|
652
|
-
- §packet-current-turn **The packet says who and
|
|
716
|
+
- §packet-current-turn **The packet says who, which turn and who attends, below the log.** The
|
|
653
717
|
`## Worker` block, in the status clump below the log ({§packet-cache-monotone}), carries
|
|
654
|
-
`{"path": "worker://<name>", "parent": <address or null>, "loop": L, "turn": T
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
or
|
|
660
|
-
|
|
718
|
+
`{"path": "worker://<name>", "parent": <address or null>, "loop": L, "turn": T, "owner":
|
|
719
|
+
{"address": "<owner>", "interactive": <boolean>}}`: the actor, whose child it is, the coordinate
|
|
720
|
+
this packet's response becomes, so `reasoning://<worker>/L/T` and `ops://<worker>/L/T` are the
|
|
721
|
+
model's own and `log:///L/T/*` its rows, and its approval owner ({§worker-ownership}) with whether
|
|
722
|
+
a person attends that owner; a model never infers the present from the last row's coordinate,
|
|
723
|
+
which may or may not be its own turn, and never infers from a missing tool alone that nobody can
|
|
724
|
+
answer. The block changes every turn, so nothing of it precedes the log, and the packet carries no
|
|
725
|
+
date, time or zone anywhere. The coordinate only; the source addresses stay documented, not
|
|
726
|
+
taught.
|
|
661
727
|
|
|
662
728
|
Worker control rides the daemon's inject seam (active→fold, idle→enqueue+drain), so the handler creates/branches the worker and hands off; the daemon owns provider + system prompt. FORK/WORK carry the seed task in the body and are their own ops, dispatched to worker control — never the entry-copy path.
|
|
663
729
|
|
|
@@ -864,7 +930,7 @@ pass.
|
|
|
864
930
|
|
|
865
931
|
§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`.
|
|
866
932
|
|
|
867
|
-
**Rationale.** Workspace is the right scope unit and the containing Git repository is its ordinary development boundary. Membership curation is tiered: Git bounds it by tracking, the client supersedes by overlay, and the model curates its render by READ/KILL. Supporting several independent repositories as one
|
|
933
|
+
**Rationale.** Workspace is the right scope unit and the containing Git repository is its ordinary development boundary. Membership curation is tiered: Git bounds it by tracking, the client supersedes by overlay, and the model curates its render by READ/KILL. Supporting several independent repositories as one workspace would require Plurnk-owned topology, synchronization, and model teaching that Git already solves cleanly by treating them as separate workspaces.
|
|
868
934
|
|
|
869
935
|
**Schema.** The version-1 baseline stores the normalized {§inference-ledger},
|
|
870
936
|
its model-response evidence, emission admission, and cardinal
|
|
@@ -1141,7 +1207,7 @@ boundary.
|
|
|
1141
1207
|
- §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.
|
|
1142
1208
|
- §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.
|
|
1143
1209
|
- §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.
|
|
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.
|
|
1210
|
+
- §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. Database-only owner-loss settlement commits atomically before drains or process-local observation resume; a failed settlement leaves no partial transitions. 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 or unanswered inter-worker messages; 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.
|
|
1145
1211
|
|
|
1146
1212
|
---
|
|
1147
1213
|
|
|
@@ -1238,7 +1304,9 @@ alone are not a cycle: changing inputs or observations distinguish activity.
|
|
|
1238
1304
|
A turn that executed nothing has no activity to identify, so an empty turn's
|
|
1239
1305
|
identity is its **text** ({§empty-turn}) — the same principle, applied to the only
|
|
1240
1306
|
output it produced. Identifying it by its absent program instead makes every empty
|
|
1241
|
-
turn identical, and changing words then read as a repeating one.
|
|
1307
|
+
turn identical, and changing words then read as a repeating one. A turn whose final emission the
|
|
1308
|
+
output allowance cut has no identity: the engine's ceiling, not the model, ended its output, so it
|
|
1309
|
+
is no repetition evidence and closes the window ({§loop-rail-continuity}).
|
|
1242
1310
|
This is an exact-repetition backstop, not a semantic judgment of task progress;
|
|
1243
1311
|
new asynchronous invocation identities do not prove repetition of their eventual
|
|
1244
1312
|
effects. Ordinary contract strikes and operator budgets remain independent.
|
|
@@ -1309,12 +1377,13 @@ independent turn ceiling terminates at **429** ({§loop-terminals}). The streak
|
|
|
1309
1377
|
and cycle verdict are absent from model packets; only the concrete occurrences
|
|
1310
1378
|
in the table are shown. The streak never leaves the daemon.
|
|
1311
1379
|
|
|
1312
|
-
A crossing terminal names the source that struck the crossing turn — `
|
|
1313
|
-
`no_operation`, then `operation` — in its detail, in that order when a turn matches
|
|
1314
|
-
than one. The three are not interchangeable: a turn that authored no operation did not *fail*
|
|
1380
|
+
A crossing terminal names the source that struck the crossing turn — `output_allowance`,
|
|
1381
|
+
`repetition`, `no_operation`, then `operation` — in its detail, in that order when a turn matches
|
|
1382
|
+
more than one. The three are not interchangeable: a turn that authored no operation did not *fail*
|
|
1315
1383
|
one, and reporting it as a failed turn misreads a model answering without the fence as a model
|
|
1316
1384
|
whose operations broke. A cycle of empty turns names repeated responses without operations,
|
|
1317
|
-
not repeated operations or results.
|
|
1385
|
+
not repeated operations or results. A turn whose final emission the output allowance cut names
|
|
1386
|
+
the allowance and its grant ({§output-allowance-notice}), whatever else it struck on. This is the crossing turn's source, not the streak's composition; the
|
|
1318
1387
|
rail rules on the crossing and does not retain the kinds behind it. What the crossing turn
|
|
1319
1388
|
actually said is cited, not discarded ({§terminal-evidence}). Naming the source is not the
|
|
1320
1389
|
private accounting {§rail-accounting-private} withholds: the streak, the cycle verdict and
|
|
@@ -1330,6 +1399,7 @@ restart; curation of log evidence cannot alter them.
|
|
|
1330
1399
|
| Assessed turn with a violation | Increment once. | Include its exact activity. |
|
|
1331
1400
|
| Clean assessed turn | Reset to zero. | Include its exact activity. |
|
|
1332
1401
|
| Actual park, including an immediate wake/reclaim in the same drain | Preserve the assessed streak. | Close the window; the next turn starts a new one. |
|
|
1402
|
+
| Assessed turn whose final emission the output allowance cut | As any assessed turn. | Exclude it and close the window; the next turn starts a new one. |
|
|
1333
1403
|
| Recoverable provider outage | No assessment; preserve the streak. | Preserve until an actual park. |
|
|
1334
1404
|
| New loop | Start at zero. | Start empty. |
|
|
1335
1405
|
|
|
@@ -1411,7 +1481,9 @@ completion before the model sees them in the next packet.
|
|
|
1411
1481
|
WAIT without a live obligation continues to those results.
|
|
1412
1482
|
This is operation recovery, not provider
|
|
1413
1483
|
resampling. A malformed statement's Problem records the factual
|
|
1414
|
-
`siblingsRetained: true` extension
|
|
1484
|
+
`siblingsRetained: true` extension, and its row's `attrs` record the statement the parser refused,
|
|
1485
|
+
its `attempt` ({§parse-attempt}), outside the row's body and weight, so the packet shows the model
|
|
1486
|
+
nothing new.
|
|
1415
1487
|
|
|
1416
1488
|
§invalid-emission-attempts Each exhausted emission-attempt budget contributes
|
|
1417
1489
|
one frame-contract strike to the same streak as other contract violations
|
|
@@ -1655,7 +1727,7 @@ Every fact names the canonical key, never the host root or an echo of the
|
|
|
1655
1727
|
model's spelling. These classes let a caller distinguish a wrong address, an
|
|
1656
1728
|
invalid range, read-only authority, and occupied hidden state without guessing.
|
|
1657
1729
|
|
|
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 `{"
|
|
1730
|
+
§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 `{"files": ["<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}).
|
|
1659
1731
|
|
|
1660
1732
|
§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.
|
|
1661
1733
|
|
|
@@ -1680,6 +1752,9 @@ cross-scheme SQL transaction. Core's create-only publication claims the same
|
|
|
1680
1752
|
identity atomically: an existing identity returns 409 without changing its
|
|
1681
1753
|
metadata or channels.
|
|
1682
1754
|
|
|
1755
|
+
Removing a channel preserves its siblings. Pruning the resulting entry requires
|
|
1756
|
+
it to be empty at the deletion boundary, not merely at an earlier observation.
|
|
1757
|
+
|
|
1683
1758
|
### Op methods
|
|
1684
1759
|
|
|
1685
1760
|
§op-methods-op-dispatch Engine operation ownership follows the public scheme contract:
|
|
@@ -1697,7 +1772,7 @@ Registration precedes loop affinity:
|
|
|
1697
1772
|
| Registered but inactive under flag | The flag gate returns `403 scheme-unavailable`. |
|
|
1698
1773
|
| Registered and active | Dispatch continues to the operation owner. |
|
|
1699
1774
|
|
|
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.
|
|
1775
|
+
- §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. Cancellation stops before the next resolved operation, including remaining glob targets, while preserving already-settled effects, receipts, source, and provider accounting.
|
|
1701
1776
|
|
|
1702
1777
|
§bare-inference **BARE is isolated, synchronous retrieval over the durable child-provider policy.**
|
|
1703
1778
|
|
|
@@ -1711,7 +1786,7 @@ Registration precedes loop affinity:
|
|
|
1711
1786
|
| Failure | A source/admission/provider failure affects its own operation, not successful siblings. Accounting or persistence failure is internal and fails hard. |
|
|
1712
1787
|
| Observation | Responses are unseen retrieval work; completion follows {§send-premature-terminate}. |
|
|
1713
1788
|
|
|
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,
|
|
1789
|
+
- §op-synchronous **Decisive operations settle before the next operation.** The dispatcher awaits each operation and its proposal resolution, including subsystem commands ({§functionality-model-mutation}). Work remains in flight only when the operation's contract deliberately creates concurrency: FORK, WORK, external 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 external 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.
|
|
1715
1790
|
- §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.
|
|
1716
1791
|
- §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.
|
|
1717
1792
|
- §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.
|
|
@@ -2111,7 +2186,7 @@ source line therefore retains the same prefix across projections of one revision
|
|
|
2111
2186
|
An explicit default-channel fragment and its fragmentless spelling share that
|
|
2112
2187
|
identity; a selected non-default channel retains its canonical `#channel`.
|
|
2113
2188
|
|
|
2114
|
-
For READ
|
|
2189
|
+
For READ and COPY/MOVE source or destination selection, core resolves every
|
|
2115
2190
|
anchor against the addressed current complete content before applying the
|
|
2116
2191
|
ordinary numeric text-coordinate contract. Exactly one current match lowers to
|
|
2117
2192
|
its numeric line; zero or multiple matches return 409 `line-anchor-collision`,
|
|
@@ -2388,6 +2463,32 @@ The `## Log` section is a sequence of ordinary Markdown records separated by one
|
|
|
2388
2463
|
|
|
2389
2464
|
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.
|
|
2390
2465
|
|
|
2466
|
+
§log-mutation-patch **A settled file mutation's row keeps what it did.** When an accepted EDIT,
|
|
2467
|
+
COPY, MOVE or KILL writes or removes a text member, the file scheme appends the unified diff of
|
|
2468
|
+
that write, `current` to `proposed`, to the operation row it is settling (`log_entries.patch`); a
|
|
2469
|
+
row that settles several writes keeps them in application order. The row serves it as its `patch`
|
|
2470
|
+
channel, `log:///<loop>/<turn>/<item>/<OP>#patch`, `text/x-diff`, for the life of the row: a fork
|
|
2471
|
+
copies it with the row, and it never enters a receipt or a packet unasked. Nothing is kept for a
|
|
2472
|
+
byte write, a member past the materialization bound, or a row settled before this version, and
|
|
2473
|
+
nothing is reconstructed for them: such a row has no `patch` channel, and whatever reads one, a
|
|
2474
|
+
rollback included, fails by name rather than inventing one.
|
|
2475
|
+
|
|
2476
|
+
§rollback **Rollback reverses a worker's settled file mutations, latest first, through ordinary
|
|
2477
|
+
operations.** `rollback({ workspaceId, workerId, actor, to })` (`workspace.rollback { to,
|
|
2478
|
+
workerId? }` for a client) names a log coordinate of `workerId`, `<loop>/<turn>/<item>`; the state
|
|
2479
|
+
after that item is what remains. Every settled EDIT, COPY, MOVE or KILL row after it, latest first,
|
|
2480
|
+
has its patch ({§log-mutation-patch}) reversed against the file as it is now and written back within
|
|
2481
|
+
one client operation of `actor` ({§connection-lifecycle}), that person's decision already: a rewrite
|
|
2482
|
+
as `EDIT <1,-1>`, a removed file as a creating `EDIT`, a created file as `KILL`. Each reversal is a
|
|
2483
|
+
row and a patch of its own, so a rollback is inspectable afterwards and reversible by the same
|
|
2484
|
+
means. The report (`RollbackReport`) lists what was restored, the rows skipped because they
|
|
2485
|
+
kept no patch or were reversed already (the file is in the state before that mutation, as an earlier
|
|
2486
|
+
rollback left it), and where it stopped: `drift`, the file no longer holds what that mutation wrote,
|
|
2487
|
+
leaves that file and everything earlier untouched; `refused` carries the reversing operation's
|
|
2488
|
+
Problem. A coordinate that is not one of the worker's rows is `404 coordinate-not-found`, a
|
|
2489
|
+
malformed one `400 coordinate-invalid`, and a workspace without a project root `400
|
|
2490
|
+
project-root-required`. Nothing is reconstructed for a patchless row, and the log is never rewritten.
|
|
2491
|
+
|
|
2391
2492
|
§log-address-metadata **Addresses name their relationship, not the row's producer.**
|
|
2392
2493
|
|
|
2393
2494
|
| Spelling | Meaning | Where |
|
|
@@ -2438,9 +2539,9 @@ complete non-retrieval body retains `lines` where no other field supplies its
|
|
|
2438
2539
|
navigable extent. None of these spellings changes acquisition, delivery,
|
|
2439
2540
|
curation, admission, or immutable evidence.
|
|
2440
2541
|
|
|
2441
|
-
Field absence carries defaults: `origin` is omitted for the owning model, `source` for the owning worker, and `status` for a routine 200. An emission row renders its author, the turn's producer, as its `origin` ({§emission-row}).
|
|
2542
|
+
Field absence carries defaults: `origin` is omitted for the owning model, `source` for the owning worker, and `status` for a routine 200, regardless of operation. Every non-200 stays explicit. This presentation rule does not alter message completion, durable results or protocol responses. An emission row renders its author, the turn's producer, as its `origin` ({§emission-row}). A present authored aside appears as `aside`. Every row's accounting follows {§packet-token-accounting}.
|
|
2442
2543
|
|
|
2443
|
-
Authored `metadata` retains its opaque ordered block strings under {§scheme-metadata-modifier}; COPY/MOVE pair them as `{from,to}`. Packet rendering does not interpret scheme options or discard malformed input from a failed operation.
|
|
2544
|
+
Authored `metadata` retains its opaque ordered block strings under {§scheme-metadata-modifier}, as stored under {§log-sensitive-request-evidence}; COPY/MOVE pair them as `{from,to}`. Packet rendering does not interpret scheme options or discard malformed input from a failed operation.
|
|
2444
2545
|
|
|
2445
2546
|
- §operation-resource-receipt A result's nonempty `resource` address remains visible in receipt metadata when distinct from its `path` and `stream`. It identifies returned material without replacing the addressed operand or injecting that material into context; ordinary READ acquires it.
|
|
2446
2547
|
- §packet-attachment-parts A successful READ of an attachable resource carries projection facts with its
|
|
@@ -2979,10 +3080,27 @@ When all messages are resolved but new results require another packet, the engin
|
|
|
2979
3080
|
reports only: `All Open Messages resolved. Review new results; emit no OPs if finished.`
|
|
2980
3081
|
The notice creates no state and does not demand another final reply.
|
|
2981
3082
|
|
|
2982
|
-
§worker-obligations A worker holds its unresolved children
|
|
2983
|
-
streams
|
|
2984
|
-
|
|
2985
|
-
|
|
3083
|
+
§worker-obligations A worker holds its unresolved children, its open non-detached
|
|
3084
|
+
streams, and the messages it sent to other workers that await completion while the
|
|
3085
|
+
recipient's loop is live (`worker_obligations`); `loop_obligations` names them per
|
|
3086
|
+
loop. Each obligation records the operation that opened it, by identity: a stream its
|
|
3087
|
+
execution ({§subscriptions-causal-resource}), a message the SEND, WORK or FORK that sent it,
|
|
3088
|
+
by the row that operation writes; a child's loop is opened by its first message's. The
|
|
3089
|
+
opening row names what it opened: an execution's `attrs.stream`, a message's `attrs.message`
|
|
3090
|
+
(its durable address). A message holds, and its reply reaches, the worker whose own operation
|
|
3091
|
+
sent it; a message a person, a client or the daemon sends opens no worker's obligation. The packet's Open Work list, WAIT, completion and drain wake settlement use
|
|
3092
|
+
that same durable liveness: a worker that messaged another worker parks on an
|
|
3093
|
+
authored WAIT until the completion arrives ({§message-completion}), and with no WAIT
|
|
3094
|
+
joins that work with the bounded park rather than concluding idle.
|
|
3095
|
+
|
|
3096
|
+
§message-abandonment **An ended loop answers what it left open.** When a loop ends,
|
|
3097
|
+
every message another worker sent it that has no completion is completed `499` by the
|
|
3098
|
+
daemon: one `_plurnk` SEND to the message's address in a maintenance turn of the
|
|
3099
|
+
recipient, "Loop *N* ended with status *S*; this message was not answered.",
|
|
3100
|
+
delivered to the sender like any reply ({§message-reply-delivery}). A message the
|
|
3101
|
+
ending loop had not yet published is re-homed first ({§message-loop-containment}) and
|
|
3102
|
+
is not abandoned. The sender's hold ends with the recipient's loop either way; the
|
|
3103
|
+
completion is what wakes it and tells it.
|
|
2986
3104
|
|
|
2987
3105
|
§wait-obligation-matrix **End-of-program resolution.** Execute all admitted operations and settle optimistic work before applying this table. WAIT is an optional yield, not an end-of-program delimiter.
|
|
2988
3106
|
|
|
@@ -3078,7 +3196,7 @@ accounting and model-visible failure evidence remain separately owned by
|
|
|
3078
3196
|
The strike sends no notice of its own: the turn records one `_plurnk`
|
|
3079
3197
|
error row, `422` `The turn performed no operation.`, which rides the next packet's errors like
|
|
3080
3198
|
any failure ({§operation-result-uniform-error-channel}); the threshold terminal still says why ({§engine-rails}).
|
|
3081
|
-
An empty turn uses its exact text as the cycle fingerprint ({§engine-cycle-evidence});
|
|
3199
|
+
An empty turn the output allowance did not cut uses its exact text as the cycle fingerprint ({§engine-cycle-evidence});
|
|
3082
3200
|
different empty programs are not a repeated cycle merely because neither contained
|
|
3083
3201
|
operations. Lost-boundary handling remains {§unparsed-tail-boundary}; no confirmation
|
|
3084
3202
|
token or private retry is invented here.
|
|
@@ -3144,7 +3262,9 @@ of which Worker launched it ({§execution-output-identity}).
|
|
|
3144
3262
|
| --- | --- |
|
|
3145
3263
|
| Admission | Require SEND control and the original invocation's runtime/tool capabilities. Preserve its classified effect: host input proposes; pure/read input uses the same effect policy as launch. |
|
|
3146
3264
|
| Acceptance | Recheck both capabilities, workspace, and the exact live subscription. Stale approval cannot reach a replacement invocation. |
|
|
3147
|
-
|
|
|
3265
|
+
| Launched without input | The invocation's preparation declared no receiver ({§executor-live-input}): `409 input-unavailable`, immediately, naming the launch form that opens input. |
|
|
3266
|
+
| Queued for a slot | `409 input-unavailable`, immediately and `retryable`; never wait for an execution slot while blocking another input-dependent execution. |
|
|
3267
|
+
| Admitted, receiver declared, not yet open | Delivery waits for the receiver to register, within the backpressure bound; the execution settling first returns `410 input-closed`. A receiver registered without the declaration is the executor's defect and fails its run. |
|
|
3148
3268
|
| Unknown address | `404 stream-not-found`. A terminal execution or retired input returns `410 input-closed`. |
|
|
3149
3269
|
| Delivery | Serialize accepted inputs per invocation. Preserve authored body and receiver-owned metadata. Receiver success means delivery only, not completion. |
|
|
3150
3270
|
| Backpressure | `PLURNK_SERVICE_EXEC_INPUT_TIMEOUT_MS` bounds each accepted delivery, including its queue residence. Expiry returns `504 input-timeout`; cancellation returns `499 input-cancelled`. Once delivery has begun, retire and abort input on either; delivery may be partial and is never replayed. The execution itself is not implicitly killed. |
|
|
@@ -3282,8 +3402,12 @@ unchanged for proposal policy, application, stream registration, and
|
|
|
3282
3402
|
effect-qualified hold policy. The post-acceptance materialization path never
|
|
3283
3403
|
triggers reclassification.
|
|
3284
3404
|
|
|
3285
|
-
§exec-registry-resolves The
|
|
3286
|
-
the workspace snapshot.
|
|
3405
|
+
§exec-registry-resolves The execution's `runtime` selects an executor from
|
|
3406
|
+
the workspace snapshot at its dispatch point. Explicit invocations parse without requiring
|
|
3407
|
+
registration ({§executor-heading}); a preceding accepted subsystem command may publish the
|
|
3408
|
+
name they invoke in that same program ({§functionality-model-mutation}). A failed or rejected
|
|
3409
|
+
command grants nothing; subsequent invocations resolve the unchanged snapshot, unless the
|
|
3410
|
+
producer requested fail-on-error and stopped the program. Installed siblings form the immutable base:
|
|
3287
3411
|
they are discovered and probed at startup, and availability is cached.
|
|
3288
3412
|
Workspace Functionality providers may atomically overlay additional names under
|
|
3289
3413
|
{§module-workspace-capabilities}; a name has one owner within a workspace, while
|
|
@@ -3319,7 +3443,7 @@ execution is refused `scope-unsupported` (400).
|
|
|
3319
3443
|
| `lifetime` | The spawn |
|
|
3320
3444
|
| ------------ | --------- |
|
|
3321
3445
|
| a duration | Aborted at the deadline — a bounded reap, polite signal then SIGKILL after `PLURNK_SERVICE_EXEC_KILL_GRACE_MS` — and the stream is stamped **504** `execution-timeout`, distinct from a deliberate kill (499) or a clean exit (200): `` Execution of '*runtime*' outlived its *lifetime* lifetime. `` |
|
|
3322
|
-
| `loop` (absent) | Loop-life bounded: reaped on every loop terminal except 202, the background-stream behavior. |
|
|
3446
|
+
| `loop` (absent) | Loop-life bounded: reaped on every loop terminal except 202, the background-stream behavior. A person's client operation answers once its command starts, so its execution belongs to the operation instead: it outlives the operation loop's 200 and is reaped when that operation is cancelled or the daemon stops ({§connection-lifecycle}). |
|
|
3323
3447
|
| `turn` | Reaped at the worker's next pre-turn via the registry abort, before the turn's own spawns, so it never survives into the subsequent turn; its terminal output surfaces born visible like any close ({§exec-stream}). |
|
|
3324
3448
|
| `detached` | Outlives its loop's terminal, 200 included. It never binds to the loop's teardown and is nobody's obligation — completion is not gated by it, WAIT does not park on it, optimistic settlement looks past it — and it ends only by KILL, the worker's total reap, or daemon shutdown; its late conclusion surfaces without opening a loop. |
|
|
3325
3449
|
|
|
@@ -3365,18 +3489,53 @@ lifecycle teardown still reaps its work. No new delegation semantics follow.
|
|
|
3365
3489
|
|
|
3366
3490
|
§worker-auto-name **Automatic names are eight random lowercase hexadecimal
|
|
3367
3491
|
characters**, e.g. `worker://ab3d5678`; a colliding draw is retried. All unnamed
|
|
3368
|
-
workers use this allocator, including WORK, FORK, clients, and
|
|
3492
|
+
workers use this allocator, including WORK, FORK, clients, and model workers.
|
|
3369
3493
|
Names encode neither machine identity nor topology or role; those remain
|
|
3370
3494
|
separate durable fields.
|
|
3371
3495
|
Automatic names never reuse an existing literal. Name selection and worker
|
|
3372
3496
|
creation share one atomic claim: concurrent allocations receive distinct
|
|
3373
|
-
addresses
|
|
3374
|
-
worker. Generated addresses appear in ordinary operation receipts and child
|
|
3497
|
+
addresses. Generated addresses appear in ordinary operation receipts and child
|
|
3375
3498
|
inventory; allocation never rewrites the submitted operation's target.
|
|
3376
3499
|
|
|
3377
|
-
§workspace-
|
|
3378
|
-
|
|
3379
|
-
|
|
3500
|
+
§workspace-name **A workspace's name is an opaque handle; its identity is its id; its folder is a
|
|
3501
|
+
separate fact.** A name is a unique non-empty string compared by exact bytes, the same comparison for
|
|
3502
|
+
creation, rename and lookup; nothing in it is normalized or decoded, and it authorizes
|
|
3503
|
+
nothing: only `projectRoot` selects a folder, and a workspace may have none. Admission, at creation
|
|
3504
|
+
and rename, refuses these spellings as `name-invalid` (400):
|
|
3505
|
+
|
|
3506
|
+
- ASCII decimal digits alone (`[0-9]+`, including zero and leading zeroes): reserved for workspace IDs.
|
|
3507
|
+
- Text that is not well-formed Unicode: an unpaired surrogate has no encoding.
|
|
3508
|
+
- A slash-delimited segment exactly `.` or `..`: a URL parser resolves it away, encoded or not.
|
|
3509
|
+
|
|
3510
|
+
None is repaired or resolved. Every other spelling
|
|
3511
|
+
is admitted as written: spaces, Unicode, `~`, `@`, `%` and a literal `%2E%2E`, query and fragment
|
|
3512
|
+
punctuation, and a dot within a segment (`.config`, `file.txt`, `...`). A refused rename changes
|
|
3513
|
+
nothing. Admission governs new names only: a workspace already carrying a refused spelling keeps it,
|
|
3514
|
+
its id, its folder and its workers, stays listed and attachable, and is renamed like any other. Rename
|
|
3515
|
+
({§methods-workspace-rename}) changes the name alone; {§methods-workspace-attach} selects an existing workspace. With a project
|
|
3516
|
+
root and no name, `workspace.create` names the workspace after the root, the root's path with the daemon's
|
|
3517
|
+
home abbreviated to `~` (`~` for the home itself, the absolute path outside it), and selects the
|
|
3518
|
+
workspace of that name when one exists instead of creating a second, so two default launches on the
|
|
3519
|
+
same project and daemon share one workspace and a concurrent pair resolves to one. The root is resolved
|
|
3520
|
+
before it is named, so a root spelled with `.` or `..` components derives the name of the folder it
|
|
3521
|
+
reaches and no default is ever refused; a root that is not well-formed Unicode is
|
|
3522
|
+
`project-root-invalid` (400), since it names no folder. The default is a
|
|
3523
|
+
convention, not a mapping: a renamed workspace is not re-selected by its old default, and a workspace may
|
|
3524
|
+
carry any name over any folder. An explicit name that exists is `409 name-conflict`, never a
|
|
3525
|
+
selection.
|
|
3526
|
+
|
|
3527
|
+
§workspace-label **A folder's display spelling is the daemon's.** Wherever the application port
|
|
3528
|
+
returns a workspace's folder it returns its label beside it: `projectLabel` on a client envelope and
|
|
3529
|
+
the `workspace/created` notice, `project_label` on a `listWorkspaces` row. The label is the folder as
|
|
3530
|
+
a default name spells it: the daemon's home is `~`, a path beneath it `~/<rest>`, and any other path,
|
|
3531
|
+
one that merely shares the home's prefix included, its absolute spelling. A workspace without a
|
|
3532
|
+
folder has a null label. It is derived from the folder on every read and never stored, and it never
|
|
3533
|
+
rewrites a name, so a client compares a workspace's name with its label by equality and derives
|
|
3534
|
+
neither from its own home.
|
|
3535
|
+
|
|
3536
|
+
§workspace-auto-name **A workspace with neither name nor project root gets five alphanumeric characters, at least one a letter.** Such a `workspace.create` draws uniformly from the {§line-anchors} alphabet `0-9A-Za-z` using a cryptographic source, redrawing digit-only names and collisions. No prefix, timestamp, or origin marker: a name never encodes where a workspace came from.
|
|
3537
|
+
|
|
3538
|
+
§exec-readpure-ungated A `read` runtime (observes external state, e.g. search) or `pure` runtime (no observable effect, e.g. `:memory:` sqlite) is side-effect-free → **auto-run**: no proposal, no human gate, no notification. Core persists the prepared operation before applying it; that write-ahead staging has no resolution waiter and therefore cannot enter proposal discovery ({§proposal-list}). Admission does not determine settlement: external executions background and stream, while subsystem commands settle under {§functionality-model-mutation}. Both expose output through ordinary environment observation ({§exec-stream}), not a second inline body path.
|
|
3380
3539
|
|
|
3381
3540
|
§effect-policy-tunable **Effect admission is one knob per effect.**
|
|
3382
3541
|
`PLURNK_SERVICE_EFFECT_HOST`, `PLURNK_SERVICE_EFFECT_READ` and
|
|
@@ -3392,7 +3551,7 @@ two states and no others:
|
|
|
3392
3551
|
|
|
3393
3552
|
| state | what the model receives |
|
|
3394
3553
|
|---|---|
|
|
3395
|
-
| active | nothing in the Log. The `##
|
|
3554
|
+
| active | nothing in the Log. The `## Open Work` stream pointer reports timing and channel activity ({§child-orientation}); the model READs any range it wants, and every READ of a stream channel carries `terminal: false` while it runs and `terminal: true` once it has concluded, so an empty page is never mistaken for a finished command that printed nothing. |
|
|
3396
3555
|
| terminal | ONE `origin=_plurnk` READ at the execution's channel address, born visible, that is exactly a markerless READ of the channel — its bounded first page ({§read-selection-projection}, the whole channel when it fits, the channel's own mimetype), the `range` or `region`, terminal status and Problem, `terminal: true`, and any producer-supplied integer `exitCode`. The packet writes the read resource as its operand, exactly as an explicit READ does ({§log-address-metadata}). |
|
|
3397
3556
|
|
|
3398
3557
|
§stream-observation-result **One liveness fact.** The durable READ result owns
|
|
@@ -3407,7 +3566,7 @@ publishes only once subscription settlement has installed its terminal result;
|
|
|
3407
3566
|
until then the stream is still in flight and publishes on the turn after it settles.
|
|
3408
3567
|
|
|
3409
3568
|
§exec-concurrency **Bounded admission per workspace (#389).** At most
|
|
3410
|
-
`PLURNK_SERVICE_EXEC_CONCURRENCY` executions run at once in one workspace (`-1`
|
|
3569
|
+
`PLURNK_SERVICE_EXEC_CONCURRENCY` external executions run at once in one workspace (`-1`
|
|
3411
3570
|
unbounded); the scope is the workspace, so neither delegation nor later turns
|
|
3412
3571
|
bypass it and no other workspace can starve it. Every admitted execution still creates its
|
|
3413
3572
|
entry, channels, and open subscription before its receipt returns, so queued work is
|
|
@@ -3419,7 +3578,8 @@ it: an immediate slot is `200 { outcome: "started" }`; delayed work is
|
|
|
3419
3578
|
current truth. Admission is FIFO within the workspace; queue residence does not consume
|
|
3420
3579
|
the execution timeout; a KILL while queued never invokes the executor and concludes the
|
|
3421
3580
|
stream as any KILL does ({§stream-control}). The scheduler is the exec scheme's; the knob is the
|
|
3422
|
-
service's ({§operator-config}), fail-hard on any other value.
|
|
3581
|
+
service's ({§operator-config}), fail-hard on any other value. Ordered subsystem
|
|
3582
|
+
commands use {§functionality-model-mutation}, not this background-work queue.
|
|
3423
3583
|
|
|
3424
3584
|
§exec-stream-page **An unrequested delivery never exceeds the retrieval page.** The
|
|
3425
3585
|
terminal observation is the same page a markerless READ returns, whatever the
|
|
@@ -3434,7 +3594,7 @@ records stop at the last complete line that fits, or at an exact Unicode region
|
|
|
3434
3594
|
when even the first line exceeds the character bound. Explicit READ scopes stay exact.
|
|
3435
3595
|
|
|
3436
3596
|
The durable per-subscription, per-channel cursor records the size last reported
|
|
3437
|
-
to the model — by the
|
|
3597
|
+
to the model — by the Open Work stream pointer while active, by the terminal
|
|
3438
3598
|
observation at close — so the pointer can state growth and no partial document
|
|
3439
3599
|
or record ever reaches the model. The terminal observation and its cursor
|
|
3440
3600
|
transition commit atomically. A concluded stream lands one conclusion row per
|
|
@@ -3578,6 +3738,9 @@ Core derives the contracts-owned `ProposalProjection` from the durable proposed
|
|
|
3578
3738
|
| Projection field | Durable authority |
|
|
3579
3739
|
| --------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
3580
3740
|
| identity | proposed log row `id`, `worker_id`, `loop_id`, `turn_id`, and validated `op` |
|
|
3741
|
+
| `worker` | the worker's name ({§worker-name}) |
|
|
3742
|
+
| `coordinate` | the row's log coordinate `L/T/S` ({§methods-log-coordinate}) |
|
|
3743
|
+
| `expiresAt` | when the operator's decision deadline cancels the proposal ({§proposal-timeout-cancels}); absent for an untimed wait |
|
|
3581
3744
|
| `target` | canonical `{ scheme, authority, pathname }` from `attrs.proposalTarget` for staged COPY/MOVE, otherwise the log row target |
|
|
3582
3745
|
| `body` | proposed operation result `rx.body`; absent means the empty review body |
|
|
3583
3746
|
| `attrs` | proposed log row `attrs` object |
|
|
@@ -3631,6 +3794,7 @@ operation, message sender, or attrs.
|
|
|
3631
3794
|
| Runtime bookkeeping | reject, `runtime_bookkeeping` |
|
|
3632
3795
|
| Server `accept` | accept |
|
|
3633
3796
|
| Server `reject` | reject, `policy_veto` |
|
|
3797
|
+
| Server `review`, a person's client operation ({§connection-lifecycle}) | accept, `client_operation` |
|
|
3634
3798
|
| Server `review`, owner implements `request_approval` | review |
|
|
3635
3799
|
| Server `review`, owner has no reviewer | reject, `no_review_channel` |
|
|
3636
3800
|
|
|
@@ -3638,8 +3802,9 @@ Core selects the disposition once for the pending gate. Its live event and
|
|
|
3638
3802
|
reconnect projection use that same decision. Automatic settlement precedes
|
|
3639
3803
|
observational notification; an observer failure cannot change authority or orphan
|
|
3640
3804
|
a waiter. Invalid configuration is diagnosed at the proposal boundary without
|
|
3641
|
-
substituting authority ({§configuration-repair-path}).
|
|
3642
|
-
|
|
3805
|
+
substituting authority ({§configuration-repair-path}). A person's client operation is
|
|
3806
|
+
already that person's decision, so review never routes it; the server's `accept` and
|
|
3807
|
+
`reject` still apply.
|
|
3643
3808
|
|
|
3644
3809
|
§runtime-bookkeeping-policy Runtime bookkeeping cannot acquire new authority.
|
|
3645
3810
|
Generated reference publication and audit narration have no reviewer and do not
|
|
@@ -4083,6 +4248,13 @@ systemd user unit. Installation and enablement are explicit operator actions;
|
|
|
4083
4248
|
package installation performs neither. The template documents executable-path
|
|
4084
4249
|
and environment adjustments instead of introducing a service-management command.
|
|
4085
4250
|
|
|
4251
|
+
§nginx-example The service package ships `plurnk.nginx.conf`, an example nginx front, beside
|
|
4252
|
+
the unit and under the same terms. Hardening belongs there, not in the daemon: TLS, security
|
|
4253
|
+
headers, sign-in throttling by real client address and an optional network allow-list. The
|
|
4254
|
+
daemon answers every caller at the address it used ({§http-request-origin}); behind TLS it is
|
|
4255
|
+
told the public origin (`PLURNK_AGUI_ISSUER`, and `PLURNK_A2A_ENDPOINT_URL` when it exposes A2A),
|
|
4256
|
+
which it cannot see.
|
|
4257
|
+
|
|
4086
4258
|
Model selection uses one selector vocabulary in `ProviderRegistry` ({§provider-instantiation}). `PLURNK_MODEL_<alias>=<provider>/<model-id>` optionally declares a friendly route and tuning scope; `PLURNK_MODEL=<selector>` selects either that alias or an exact provider/model route. `PLURNK_MODEL_CHILD=<selector>` uses the same vocabulary for the default child provider; unset means inherit the spawning loop's provider. Operator selections and alias declarations live in `.env`, not `.env.defaults`.
|
|
4087
4259
|
|
|
4088
4260
|
Each knob's value lives on its panel and nowhere else (`plurnk-service config defaults` prints them all); this table says what the service's knobs mean.
|
|
@@ -4092,7 +4264,7 @@ Each knob's value lives on its panel and nowhere else (`plurnk-service config de
|
|
|
4092
4264
|
| `PLURNK_SERVICE_DB_PATH` | SQLite file path; an explicit non-empty value overrides the derived default. |
|
|
4093
4265
|
| `PLURNK_SERVICE_SQLITE_SYNCHRONOUS` | Connection-time WAL durability: `OFF`, `NORMAL`, `FULL` or `EXTRA` ({§db-durability}). |
|
|
4094
4266
|
| `PLURNK_SERVICE_SHARE_FOLDER` | Parent of the shares written when no folder is named ({§share-folder}); empty is `$XDG_STATE_HOME/plurnk/shares`. |
|
|
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
|
|
4267
|
+
| §operator-config-shared-keys `PLURNK_HOST`, `PLURNK_PORT`, `PLURNK_AUTH`, `PLURNK_SECRET`, `PLURNK_PASS` | The daemon-owned listener's bind address and TCP port; modules mount their paths on that one listener ({§http-host}). The daemon's authentication posture, the operator's client secret and the operator's browser sign-in ({§credential-authority}, {§agui-oauth}). **A key the daemon and its clients both read has a shared owner**: `@plurnk/plurnk-contracts` declares these, 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`, `--port`, `--auth`, `--user` and `--pass` flags are generated from that panel. |
|
|
4096
4268
|
| §operator-config-git-ceiling `PLURNK_SERVICE_GIT_ALLOWED` | Hard service ceiling: only `1` admits Git membership and status; every other value denies them. |
|
|
4097
4269
|
| §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. |
|
|
4098
4270
|
| `PLURNK_SERVICE_FILE_MATERIALIZE_MAX_BYTES` | Byte ceiling in `1..104857600` for one workspace-file snapshot ({§membership-materialization-limit}). |
|
|
@@ -4103,7 +4275,7 @@ Each knob's value lives on its panel and nowhere else (`plurnk-service config de
|
|
|
4103
4275
|
| `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF` | First recovery delay (ms); doubles per failure up to `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF_MAX` ({§provider-recovery}). |
|
|
4104
4276
|
| `PLURNK_SERVICE_MAX_STRIKES` | Consecutive turn-contract strike threshold ({§engine-rails}). |
|
|
4105
4277
|
| `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}. |
|
|
4106
|
-
| `PLURNK_SERVICE_BUDGET_PRESSURE` | Budget percentage above which the gauge names its largest rows ({§context-gauge})
|
|
4278
|
+
| `PLURNK_SERVICE_BUDGET_PRESSURE` | Budget percentage above which the gauge names its largest rows ({§context-gauge}); measured before adding the inventory. |
|
|
4107
4279
|
| `PLURNK_SERVICE_BUDGET_LARGEST_ITEMS` | How many of the heaviest retained log rows the pressured gauge names ({§context-gauge}). |
|
|
4108
4280
|
| `PLURNK_SERVICE_LINE_ANCHOR_CONTEXT_LINES` | Minimum neighboring lines hashed on each side; repeated handles expand their context ({§line-anchor-disambiguation}). |
|
|
4109
4281
|
| `PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES` | Surrounding and landed lines shown at each EDIT result boundary ({§edit-result-receipt-projection}). |
|
|
@@ -4279,7 +4451,7 @@ flowchart LR
|
|
|
4279
4451
|
release --> warm["Bounded warm grace / idle LRU"]
|
|
4280
4452
|
warm -->|new demand| lease
|
|
4281
4453
|
warm -->|idle bound| cool["Deactivate providers;<br/>withdraw runtime projections"]
|
|
4282
|
-
interface -->|
|
|
4454
|
+
interface -->|daemon call| calls
|
|
4283
4455
|
calls --> core["Core state and orchestration"]
|
|
4284
4456
|
core --> events["subscribeToEvents<br/>(workspaceId, event, payload)"]
|
|
4285
4457
|
events --> interface
|
|
@@ -4293,7 +4465,8 @@ modules in registration order. The daemon's listener is bound before durable adm
|
|
|
4293
4465
|
({§module-http-mounts}). Persisted workspaces with
|
|
4294
4466
|
no durable work stay passive until first demand; activation publishes their
|
|
4295
4467
|
complete capabilities and documentation before the demanding operation
|
|
4296
|
-
proceeds.
|
|
4468
|
+
proceeds. An owner's arrival is such a demand ({§methods-workspace-activate}), so a first prompt
|
|
4469
|
+
waits only for what remains of it. `setup` is the readiness boundary for every capability registered
|
|
4297
4470
|
with Core: recovery may demand a workspace provider before `start`. Requests on
|
|
4298
4471
|
the listener remain unavailable until it is admitted; a module opens any other exterior
|
|
4299
4472
|
ingress only after recovery. No
|
|
@@ -4334,11 +4507,12 @@ An invalid module object, factory result or lifecycle member is an implementatio
|
|
|
4334
4507
|
not configuration, and fails loudly. What a module contributes registers through its owning public
|
|
4335
4508
|
interfaces and is released during {§module-lifecycle} resource teardown.
|
|
4336
4509
|
|
|
4337
|
-
§module-shutdown-order `Daemon.stop()` first rejects new capability demand
|
|
4510
|
+
§module-shutdown-order `Daemon.stop()` first rejects new capability demand, cancels preparation
|
|
4511
|
+
under {§functionality-preparation-cancellation}, and
|
|
4338
4512
|
aborts proposals, branches, derivations, and worker scopes. It begins module
|
|
4339
4513
|
`stop()` calls in reverse registration order without serially awaiting them,
|
|
4340
4514
|
so every producer is asked to stop even if another stalls. Core settles drains,
|
|
4341
|
-
capability publications, module producers, streaming producers, derivations,
|
|
4515
|
+
whole workspace activation and cooling transitions, capability publications, module producers, streaming producers, derivations,
|
|
4342
4516
|
mimetypes, schemes, and the final worker-settlement barrier while observers
|
|
4343
4517
|
remain subscribed. Only then does it begin and join module `close()` calls in
|
|
4344
4518
|
reverse order. Failures do not skip later phases and join one shutdown aggregate.
|
|
@@ -4349,6 +4523,9 @@ After asynchronous selection, the supervisor rechecks shutdown before creating
|
|
|
4349
4523
|
a drain or installing a timer; parked-loop wake mutations also recheck worker
|
|
4350
4524
|
cancellation under {§worker-lifecycle-durable-disposition}.
|
|
4351
4525
|
The database remains available through observer closure and final maintenance.
|
|
4526
|
+
Residency transitions are retained from stop admission through settlement, including failed
|
|
4527
|
+
transitions; one failure does not stop the join of other workspaces. Expected preparation
|
|
4528
|
+
cancellation is not a shutdown failure; genuine preparation and cleanup failures are.
|
|
4352
4529
|
The shared deadline bounds every phase, including observer delivery; forced
|
|
4353
4530
|
shutdown may therefore lose notifications and reports the unfinished phase.
|
|
4354
4531
|
|
|
@@ -4369,7 +4546,8 @@ flowchart LR
|
|
|
4369
4546
|
stop[Begin stop] --> abort[Abort core producers]
|
|
4370
4547
|
stop --> moduleStop[Begin reverse module stop]
|
|
4371
4548
|
abort --> drains[Settle worker drains]
|
|
4372
|
-
drains -->
|
|
4549
|
+
drains --> residency[Join workspace transitions<br/>and capability publications]
|
|
4550
|
+
residency --> joined[Settle module producers]
|
|
4373
4551
|
moduleStop --> joined
|
|
4374
4552
|
joined --> producers[Settle streaming producers]
|
|
4375
4553
|
producers --> resources[Dispose derivations,<br/>mimetypes, and schemes]
|
|
@@ -4386,6 +4564,8 @@ published module contract.
|
|
|
4386
4564
|
|
|
4387
4565
|
| Setup function | Contract |
|
|
4388
4566
|
|---|---|
|
|
4567
|
+
| `credentials` | The {§credential-authority} on the setup seam: the issuing module publishes its face (`publish({ issuer })`) before any module starts, and every module may `verify` through it. |
|
|
4568
|
+
| `httpAddress()` | The address of the listener the host bound before any module set up ({§http-host}), as on the application port: the issuing module derives its issuer from it at setup, so the face it publishes answers from publication. |
|
|
4389
4569
|
| `registerRuntimes([{ decl, executor, availability, scheme? }, ...])` | Validates the complete canonical tag set under {§executor-runtime-declaration}, then publishes every process-wide executor and optional claimed scheme facet atomically. |
|
|
4390
4570
|
| §module-workspace-provider `registerWorkspaceCapabilityProvider(namespaceOwner, provider)` | Registers one extension-unique Functionality provider. `activate({ workspaceId, retain })` reconstructs the workspace snapshot; idempotent `deactivate({ workspaceId })` releases process resources. Core coalesces demand and supplies residency leases for work that outlives its caller. |
|
|
4391
4571
|
| §module-workspace-state `readWorkspaceModuleState(workspaceId, namespaceOwner)` | Reads one nullable JSON state value per workspace and provider. Core owns storage and lifecycle; the provider owns its schema. Store symbolic credential references, not copied secrets. A worker-scoped family's coordinator reads and replaces the same shape per worker in `worker_module_state` ({§functionality-scope}). |
|
|
@@ -4428,7 +4608,10 @@ Settling the coordinator includes accepted refreshes waiting for that gate,
|
|
|
4428
4608
|
not only work already inside a family lane.
|
|
4429
4609
|
Explicit client mutations use `try` and fail 409 before effects while the workspace is held.
|
|
4430
4610
|
Refused mutations reserve no queue position; a client retry is a new admission.
|
|
4431
|
-
An accepted
|
|
4611
|
+
An accepted operation mutation uses `wait`: its turn yields the shared lease
|
|
4612
|
+
at that operation, awaits exclusive publication, and reacquires its lease before
|
|
4613
|
+
dispatching the next operation. Concurrent publishers yield independently; no
|
|
4614
|
+
publisher waits while retaining the shared lease it needs released. Activation and turn-admission refresh use `none` inside
|
|
4432
4615
|
their already-held demand boundary. Providers reject replacement while active
|
|
4433
4616
|
requests, input exchanges, or Tasks depend on the old snapshot; infrastructure
|
|
4434
4617
|
watches may be replaced. These are concurrency constraints, not creator privileges.
|
|
@@ -4450,8 +4633,11 @@ bound. Concurrent demand coalesces; cooling never closes a leased connection.
|
|
|
4450
4633
|
|
|
4451
4634
|
Cooling withdraws live capability and releases process resources at the
|
|
4452
4635
|
workspace boundary. Durable configuration, history, and saved entries remain.
|
|
4453
|
-
New demand reconstructs the one shared snapshot. Shutdown cancels warm timers
|
|
4454
|
-
and
|
|
4636
|
+
New demand reconstructs the one shared snapshot. Shutdown cancels warm timers and preparation,
|
|
4637
|
+
refuses new leases before database access, and joins whole activation and cooling transitions
|
|
4638
|
+
before releasing resources. An interrupted acquisition rejects with `AbortError`, never a usable
|
|
4639
|
+
lease. Cooling and activation cleanup remain joined, not cancelled.
|
|
4640
|
+
Cooling failures are reported; demand awaiting that transition receives its failure, not a lease.
|
|
4455
4641
|
|
|
4456
4642
|
§module-workspace-residency-facet **Residency is the workspace's; processes are
|
|
4457
4643
|
one family's facet.** The workspace is the lease unit, and every family's
|
|
@@ -4503,6 +4689,20 @@ It neither removes the old definition first nor merges omitted fields.
|
|
|
4503
4689
|
| Authorization required | Publish the existing authorization-required handoff; this is not a failed preparation. |
|
|
4504
4690
|
| Identical definition | Retain enabledness and normal attachment reuse; this is not an explicit enable/restart. |
|
|
4505
4691
|
|
|
4692
|
+
§functionality-addressing **A family may name definitions by their content.** An adapter that
|
|
4693
|
+
declares `addressing` supplies the input of `add` and the input of `enable`, `disable` and `remove`,
|
|
4694
|
+
and reads from a select input the alias it names; its alias grammar ({§functionality-adapter}) is
|
|
4695
|
+
the identity's own, and the generated teaching's `add` example is that input. Every other rule of
|
|
4696
|
+
the coordinator — ownership, enabledness, `alias-exists`, `alias-unknown`, publication, documents —
|
|
4697
|
+
reads the alias as that identity. The members family names its definitions by their glob
|
|
4698
|
+
({§members-functionality}).
|
|
4699
|
+
|
|
4700
|
+
| Verb | Addressing family |
|
|
4701
|
+
|---|---|
|
|
4702
|
+
| `add` | Admits every definition the body names, or none: one refusal refuses the whole body. Reapplying a definition the scope holds is idempotent; a different definition under the same name is `alias-exists` (409), whose recovery is remove and add. The receipt lists the admitted definitions in body order (`definitions`) and names no one `alias`. Preparation receives them all as its admissions. |
|
|
4703
|
+
| `replace` | Not served: when the name is the definition there is nothing to reassign, so neither projection offers it ({§functionality-discover-advertisement}). |
|
|
4704
|
+
| `enable`, `disable`, `remove` | Take the family's select input; the receipt names the one alias it concerned. |
|
|
4705
|
+
|
|
4506
4706
|
§functionality-mutation-status **Mutation status describes the committed resource
|
|
4507
4707
|
outcome, not the management invocation's stream lifetime.** Apply these rows in
|
|
4508
4708
|
order; refusals retain their own Problems and do not commit a replacement.
|
|
@@ -4510,10 +4710,10 @@ order; refusals retain their own Problems and do not commit a replacement.
|
|
|
4510
4710
|
| Outcome | Status |
|
|
4511
4711
|
|---|---:|
|
|
4512
4712
|
| 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 |
|
|
4713
|
+
| `add` or `replace` creates a local definition, including an override of an inherited definition; an `add` naming several ({§functionality-addressing}) creates any of them | 201 |
|
|
4714
|
+
| `add` reapplies the identical local definition, every one it names; `replace` assigns an existing local definition; `enable`, `disable`, or `remove` settles | 200 |
|
|
4515
4715
|
|
|
4516
|
-
`add` of a different local definition remains `alias-exists` (409); `replace` is explicit.
|
|
4716
|
+
`add` of a different local definition remains `alias-exists` (409); `replace` is explicit where a family serves it.
|
|
4517
4717
|
Model invocation settlement follows {§functionality-model-mutation} independently.
|
|
4518
4718
|
|
|
4519
4719
|
§functionality-discover-advertisement **A family's `discover` advertises exactly the inputs it
|
|
@@ -4616,7 +4816,7 @@ state without demand; `workspace/preparation` broadcasts
|
|
|
4616
4816
|
| Boundary | Visible state |
|
|
4617
4817
|
|---|---|
|
|
4618
4818
|
| Preparation begins | Family, `phase: preparing`, `alias: null`, UTC `since` |
|
|
4619
|
-
| Adapter
|
|
4819
|
+
| Adapter reports the aliases it is preparing | One activity per alias, each keeping the `since` it began; an alias leaves when a later report omits it, so aliases prepared at once are listed together |
|
|
4620
4820
|
| Prepared candidate enters publication | `phase: publishing`, `alias: null` |
|
|
4621
4821
|
| Commit, rejection, or rollback settles | Family removed; empty array means no preparation |
|
|
4622
4822
|
|
|
@@ -4727,7 +4927,8 @@ reserved or masked name is no resource. The family's manager exposes it as the f
|
|
|
4727
4927
|
the value its commands receive now, FIND lists the names in effect and a pattern on it matches
|
|
4728
4928
|
values, COPY carries a value out. The manager's own output streams, eight hexadecimal characters
|
|
4729
4929
|
({§execution-output-identity}), stay the executor's. A write is the Worker's own layer, never the
|
|
4730
|
-
workspace's or the operator's
|
|
4930
|
+
workspace's or the operator's (the runtime worker keeps none, so a person's write is the workspace's,
|
|
4931
|
+
{§actor-boundary-client-operations}): EDIT sets the whole value through the family's `replace` for the
|
|
4731
4932
|
Worker, and KILL retires the name from the Worker's commands — `remove` for an entry the Worker
|
|
4732
4933
|
owns, which restores an inherited value, `disable` for an inherited one, which keeps its
|
|
4733
4934
|
definition. Admission is the family's ({§env-functionality}) and its refusal is the operation's
|
|
@@ -4739,7 +4940,9 @@ effect is `entry-not-found` (404) on READ and KILL alike.
|
|
|
4739
4940
|
§functionality-scope **A family declares its supported scopes.** Skills, MCP, members
|
|
4740
4941
|
and outbound A2A describe what exists in a **workspace**: a capability, resident or installable,
|
|
4741
4942
|
that every Worker there shares. Environment describes how one **Worker** works — context rather
|
|
4742
|
-
than capability — with worker overrides above workspace defaults.
|
|
4943
|
+
than capability — with worker overrides above workspace defaults. A context family's definitions are read where they
|
|
4944
|
+
are used, so a change at either scope holds nothing resident and takes no workspace exclusivity: it serializes on
|
|
4945
|
+
the family's lane. The adapter declares
|
|
4743
4946
|
`scopes` (absent means `["workspace"]`; the first is the model default), and the
|
|
4744
4947
|
coordinator keys durable state and the locally-owned `origin`
|
|
4745
4948
|
by it: a workspace-scoped family's own entries carry origin `workspace`, a worker-scoped
|
|
@@ -4826,20 +5029,27 @@ A family that ships no file has a header-only document. Registration also
|
|
|
4826
5029
|
validates the adapter's taught `add` example against the `add` input schema it
|
|
4827
5030
|
teaches, so a wrong example fails boot rather than the model.
|
|
4828
5031
|
|
|
4829
|
-
§functionality-model-mutation **
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
5032
|
+
§functionality-model-mutation **Subsystem commands settle in authored order.**
|
|
5033
|
+
Every manager verb, including inspection, completes before dispatch proceeds;
|
|
5034
|
+
later operations observe earlier successful configuration changes. These
|
|
5035
|
+
core-owned commands use ordinary proposals and durable execution outputs, but
|
|
5036
|
+
not the background-execution slot pool. Preparation and publication share the
|
|
5037
|
+
family's serialized lane. Resident publication uses the lease handoff in
|
|
5038
|
+
{§module-workspace-quiescence}; context-only families retain their existing
|
|
5039
|
+
scope-local serialization. The invoking operation and its output remain pending
|
|
5040
|
+
until settlement; they never acknowledge merely starting a future commit.
|
|
4833
5041
|
It then reports `active`, `unavailable`, or `authorization-required`, or the exact
|
|
4834
5042
|
publication failure. Resource readiness is not execution liveness: a mutation's
|
|
4835
5043
|
`202 authorization-required` body remains exact, while the finished manager
|
|
4836
5044
|
execution closes with `200`. It does not wait for sign-in. A preparation failure may publish enabled-but-unavailable
|
|
4837
|
-
state for other mutations, but `replace` rejects it ({§functionality-replacement}); a publication failure never reports a successful mutation.
|
|
4838
|
-
waiting, and result observation use the ordinary execution lifecycle, without a
|
|
5045
|
+
state for other mutations, but `replace` rejects it ({§functionality-replacement}); a publication failure never reports a successful mutation. Result observation uses the ordinary execution lifecycle, without a
|
|
4839
5046
|
separate deferred-commit queue. An explicit client action publishes now, rejects
|
|
4840
5047
|
a failed preparation, and fails 409 while the workspace is held
|
|
4841
5048
|
({§module-workspace-quiescence}). Rejecting a proposal prepares, persists, and
|
|
4842
|
-
publishes nothing.
|
|
5049
|
+
publishes nothing. Cancellation removes queued publication and aborts preparation
|
|
5050
|
+
before publication; an already-started atomic publication is joined, never
|
|
5051
|
+
abandoned partway through. Shell commands, remote tools, WORK/FORK and streaming
|
|
5052
|
+
READ retain their deliberately asynchronous contracts ({§op-synchronous}).
|
|
4843
5053
|
|
|
4844
5054
|
## §methods Application interface
|
|
4845
5055
|
|
|
@@ -4851,34 +5061,36 @@ Core's behavior behind them.
|
|
|
4851
5061
|
| Area | Function | Core contract |
|
|
4852
5062
|
|---------------------------------------------------|----------|---------------|
|
|
4853
5063
|
| §methods-event-subscribe Events | `subscribeToEvents(handler) -> unsubscribe` | Subscribes to the raw event source in {§notifications}. A subscriber failure is logged and cannot re-enter engine control flow. |
|
|
5064
|
+
| §methods-credentials Credentials | `credentials` | The {§credential-authority}: `issue`, `verify`, `consume`, `revokeFamily`, `onRevoked` and the sign-ins of a subject by `sessions` ({§credential-sessions}), and a module's own client by `registerClient`, `client` and `authenticateClient` ({§credential-module-client}); one in-memory authority per daemon, offered to every module on the seam. |
|
|
4854
5065
|
| §proposal-list Proposals | `pendingProposals(workspaceId)` | Intersects durable proposed rows with the lifecycle owner's live resolution waiters, then returns their validated {§proposal-projection}; persistence alone cannot advertise an unresolvable client interrupt. |
|
|
4855
5066
|
| §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. |
|
|
4856
5067
|
| §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. |
|
|
4857
5068
|
| §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. |
|
|
4858
5069
|
| §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. |
|
|
4859
|
-
| §
|
|
4860
|
-
| §methods-
|
|
4861
|
-
| Client
|
|
4862
|
-
| §methods-log-read Reads | `readLog({ workspaceId, workerId, ...coordinate })` | Ownership-checks the worker, then reads by ids, recency, or the complete `loopSeq`/`turnSeq`/`sequence` display coordinate. An omitted `limit` is `PLURNK_SERVICE_LOG_READ_PAGE`, and any `limit` is capped at `PLURNK_SERVICE_LOG_READ_MAX`. |
|
|
5070
|
+
| §message-idempotency Message admission | `messageAdmission({ workspaceId, address, body })` | A client message's address is its idempotency key ({§message-source-scheme}): `new` when nothing is accepted there, `accepted` when the same body is, so a repeat attaches to what the message started instead of admitting it twice; another body under an accepted address is refused, 422 `message-address-reused`, creating nothing. `runLoop` refuses every repeat it is handed: other words 422 `message-address-reused`, the same words 409 `message-already-accepted`, a duplicate racing the original. |
|
|
5071
|
+
| §methods-loop-cancel Loops | `cancelDrain(workerId, reason?)`; `cancelWorker({ workspaceId, workerId, reason? })`; `cancelLoop({ workspaceId, loopId, 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. `cancelLoop` cancels exactly one client operation ({§connection-lifecycle}): its dispatch while that runs, and every attached execution its rows started that still runs, then reports whether any of it was running; nothing else in the runtime worker shares its scope. |
|
|
5072
|
+
| §methods-op-mirror Client dispatch | `dispatchClientAction({ workspaceId, actor, contextWorkerId?, statements, onLoop? })` | Dispatches already-parsed grammar statements as one client operation of `actor` ({§connection-lifecycle}), in the workspace's Functionality ({§actor-boundary-attached-functionality}), reading `log:///` in `contextWorkerId`'s log ({§actor-boundary-client-operations}). `onLoop` hears the operation's loop before any statement runs. Every statement is an ordered client/operation turn, and every committed `log/entry` is emitted before the promise resolves. Core exposes no per-op method family. |
|
|
5073
|
+
| §methods-log-read Reads | `readLog({ workspaceId, workerId, ...coordinate })` | Ownership-checks the worker, then reads by ids, recency, or the complete `loopSeq`/`turnSeq`/`sequence` display coordinate, newest first. `sinceId` keeps rows after an id and `beforeId` rows before one, so a reader pages back through the whole log one page at a time. An omitted `limit` is `PLURNK_SERVICE_LOG_READ_PAGE`, and any `limit` is capped at `PLURNK_SERVICE_LOG_READ_MAX`. |
|
|
4863
5074
|
| §methods-entry-read Reads | `readEntry({ workspaceId, workerId, target, channel?, offset? })` | Resolves the selector from that worker's perspective and returns {§entry-read-result}, either complete or as one channel suffix, without creating action evidence. |
|
|
4864
5075
|
| Providers | `listProviders()` | Lists configured aliases with provider/model identity, active state, and the effective provider-derived `inputCapacity` when known. |
|
|
4865
5076
|
| Model catalog | `listModels(query)` | Returns one validated bounded {§model-catalog-wire} page under {§model-catalog}; performs no provider request or selection. |
|
|
4866
5077
|
| Client capabilities | `listClientDisplayCapabilities()` | Composes sorted scheme declarations ({§manifest-client-display}) followed by sorted MIME declarations ({§mimetype-client-display}) into the validated shared wire ({§client-display-capabilities}). The internal `exec` operation handler is excluded; its addressable runtime-tag scheme faces remain included. |
|
|
4867
|
-
| §methods-workspace-create Workspace lifecycle | `createWorkspace({ name?, projectRoot?, settings? })` | Validates `settings` through {§operator-config-workspace-settings}, creates the
|
|
4868
|
-
| §methods-workspace-attach Workspace lifecycle | `attachWorkspace({ workspaceId
|
|
4869
|
-
| §methods-
|
|
4870
|
-
| §methods-
|
|
5078
|
+
| §methods-workspace-create Workspace lifecycle | `createWorkspace({ name?, projectRoot?, settings? })` | Validates `settings` through {§operator-config-workspace-settings}, creates the workspace and returns its client envelope, minting no worker, and emits global `workspace/created`; with a project root and no name it names and selects the workspace under {§workspace-name}, emitting `workspace/created` only for a workspace it created. Creation and attachment are passive: neither starts derivation nor activates workspace Functionality. `projectRoot` is established here or the workspace remains headless. |
|
|
5079
|
+
| §methods-workspace-attach Workspace lifecycle | `attachWorkspace({ workspaceId } \| { name } \| { projectRoot })` | Exactly one selector returns an existing workspace's client envelope, minting and activating nothing. Names are literal lookups, including previously admitted names. An absolute project root selects its folder-derived default name ({§workspace-name}), not a workspace by its stored folder. An absent target is `404 workspace-not-found`; ambiguous or absent selectors are `400 identity-invalid`. It retains no caller or transport binding state. |
|
|
5080
|
+
| §methods-workspace-activate Workspace lifecycle | `activateWorkspace({ workspaceId })` | Makes the demand a turn makes, without a turn: a cold workspace activates and publishes its complete capabilities; a concurrent demand shares that one activation; it resolves once the workspace is active and leaves it warm under `PLURNK_SERVICE_WORKSPACE_WARM_MS`. Creation and attachment stay passive; an owner's arrival calls it ({§agui-owner-activation}). |
|
|
5081
|
+
| §methods-worker-create Workspace lifecycle | `createWorker({ workspaceId, name?, parentWorkerId?, owner? })` | Creates a distinct model-origin worker with empty history. A root may name a registered owner; a child names its parent and inherits ownership. Supplying both parent and owner is invalid ({§worker-owner-creation}). |
|
|
4871
5082
|
| Worker ownership | `registerWorkerOwner(workspaceId, { address, tools, interactive })` | Declares or replaces an owner's supported client-tool names and whether a person attends it, in that workspace; `_plurnk` is reserved. |
|
|
4872
5083
|
| Worker ownership | `claimWorkerOwner({ workspaceId, workerId, owner })` | Claims only runtime-owned work under {§worker-ownership}, returning its effective owner. The owner must already be registered. |
|
|
4873
5084
|
| Runtime actor | `ensureRuntimeWorker(workspaceId)` | Returns the workspace's `_plurnk` actor, creating it if absent; it always retains runtime ownership. |
|
|
4874
|
-
| Workspace lifecycle | `forkWorker({ workspaceId, workerId, name? })` | Creates a child worker that branches the source worker's history while sharing workspace state. |
|
|
4875
|
-
| §methods-workspace-rename Workspace metadata | `renameWorkspace(workspaceId, name)` | Changes only the
|
|
4876
|
-
| §methods-workspace-
|
|
4877
|
-
| Workspace metadata
|
|
4878
|
-
|
|
|
4879
|
-
| §methods-worker-
|
|
4880
|
-
| §methods-worker-
|
|
4881
|
-
| §methods-worker-
|
|
5085
|
+
| Workspace lifecycle | `forkWorker({ workspaceId, workerId, name? })` | Creates a child worker that branches the source worker's history while sharing workspace state. The source is a model worker, else `409 model-worker-required` ({§machine-processes-worker-origin}). |
|
|
5086
|
+
| §methods-workspace-rename Workspace metadata | `renameWorkspace(workspaceId, name)` | Changes only the workspace's unique mutable name, under the admission of {§workspace-name}; workers, log, and membership remain intact, and a refused name changes nothing. |
|
|
5087
|
+
| §methods-workspace-rollback Workspace files | `rollback({ workspaceId, workerId, actor, to })` | Reverses `workerId`'s settled file mutations after its coordinate `to` as one client operation of `actor` ({§rollback}, {§connection-lifecycle}); answers a `RollbackReport`. |
|
|
5088
|
+
| §methods-workspace-prompts Workspace metadata | `listPrompts(workspaceId, limit?, workerId?)` | Returns nonempty loop-seed prompts a client addressed to the workspace's model workers, newest-first; `workerId` narrows to one worker. Authorship is the seed message's address ({§message-arrival}): a worker-issued seed (WORK, FORK, SEND to a worker) has none and is never history, whichever worker it seeded; a client prompt at a forked model worker is. An omitted limit is `PLURNK_SERVICE_PROMPTS_PAGE`. |
|
|
5089
|
+
| Workspace metadata | `listWorkspaces()`, `workspaceDerivationStatus(...)` | Reads current workspace identity, with each folder and its label ({§workspace-label}), and derivation progress. |
|
|
5090
|
+
| §methods-worker-read Worker topology | `readWorker({ workspaceId, identity })` | Ownership-bounds an exact id-or-name lookup and returns one durable Worker projection or `null` under {§application-worker-observation}. Supplying both identities or neither is invalid. Any non-empty name is looked up, the runtime worker's `_plurnk` included: the lookup is no minting door ({§worker-name-minting}). |
|
|
5091
|
+
| §methods-worker-list Worker topology | `listWorkers(workspaceId, query?)` | Returns the workspace's durable Worker projections under {§application-worker-observation}. The origin filter is exact; an explicitly present `parentWorkerId` filters roots (`null`) or one immediate parent (id), while omission returns every lineage position. Each projection carries `kind` (`root` for a worker with no parent, `fork` for a child with a fork boundary, `work` for any other child) and `lifecycle`, the representative work loop's status through {§loop-lifecycle-vocabulary} (`idle` with no work loop), so a directory row shows the same lifecycle glyph the bound worker's own status gauge shows; clients infer neither (#523). |
|
|
5092
|
+
| §methods-worker-loops Loop lifecycle | `listWorkerLoops({ workspaceId, workerId })` | Ownership-checks the Worker and returns its Loops in sequence order under {§application-loop-observation}, including the validated exact terminal result when one exists, and each Loop's `invocation`: `{ workerId, address }`, the Worker and the log address ({§methods-invocation}) of the operation that sent the Loop's first message ({§worker-obligations}), or null when a person, a client, a peer or the daemon sent it. It performs no scheduling or event replay. |
|
|
5093
|
+
| §methods-worker-accounting Worker spend | `workerAccounting({ workspaceId, workerId })` | Ownership-checks the Worker and returns the {§provider-accounting} projection of every settled request on any loop the Worker or a descendant of it (`parent_worker_id`, to any depth) ran, since the Worker began: its own spend and its delegations', the same tree the turn cap counts ({§turn-cap-counts-the-tree}). Nothing spent is explicit zero. One loop's own accounting stays {§notifications-loop-terminated}'s. Derived from the request ledger on every read ({§tokenomics-provider-usage}); no rollup, no second store. |
|
|
4882
5094
|
| Extension actions | `listModuleActions()`, `invokeModuleAction(name, params, context)` | Lists setup-registered `{ name, scope, inputSchema, outputSchema }` descriptors in sorted order. Invocation requires a context matching the registered scope; missing names, forged scope, and missing workspace identity fail before the owner runs. Handler values remain opaque to core. |
|
|
4883
5095
|
|
|
4884
5096
|
§methods-loop-run-fold-consistency **A folded prompt cannot silently reconfigure
|
|
@@ -4914,19 +5126,17 @@ If an unpublished message is promoted into subsequent work under
|
|
|
4914
5126
|
{§message-loop-containment}, its selected paths travel with it.
|
|
4915
5127
|
|
|
4916
5128
|
§methods-rebind **Binding belongs to the client-interface module.** Core's
|
|
4917
|
-
workspace lifecycle calls return exactly the workspace
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
§
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
name lies outside `WORKER_NAME`), insert a non-mintable spelling, or make the
|
|
4929
|
-
client registry diverge from model worker control.
|
|
5129
|
+
workspace lifecycle calls return exactly the workspace (`workspaceId`,
|
|
5130
|
+
`workspaceName`, `projectRoot`, `projectLabel`); they carry no worker, bound-worker
|
|
5131
|
+
or operation-loop binding. Core retains no connection, thread, or current-workspace
|
|
5132
|
+
mapping. A module may replace its own binding with a later create or attach result
|
|
5133
|
+
without requiring a new transport; it resolves the bound worker separately, while
|
|
5134
|
+
each client operation allocates its own administrative loop under {§connection-lifecycle}.
|
|
5135
|
+
|
|
5136
|
+
§methods-worker-name-admission **Worker-name admission.** Worker
|
|
5137
|
+
creation and fork apply {§worker-name-minting} before lookup or creation. A client therefore cannot forge or resume the runtime actor (its
|
|
5138
|
+
name lies outside `WORKER_NAME`) or create a worker under a spelling model worker control
|
|
5139
|
+
could not mint.
|
|
4930
5140
|
|
|
4931
5141
|
§capability-admission **One admission path owns external authority.** Core
|
|
4932
5142
|
derives one or more `CapabilityDescriptor` demands from each routed statement,
|
|
@@ -4963,7 +5173,7 @@ resolver.** Workspace capability actions return the contracts-owned
|
|
|
4963
5173
|
their normalized effective intersection. The same resolver governs dispatch
|
|
4964
5174
|
and packet shaping. Replacement preserves unrelated workspace settings. Before their next operation
|
|
4965
5175
|
or observation, existing workers reconcile generated references against it. It requires no selected
|
|
4966
|
-
|
|
5176
|
+
bound worker and returns the complete fresh projection.
|
|
4967
5177
|
|
|
4968
5178
|
§question-tool **The native request-user-input tool.** Core registers one
|
|
4969
5179
|
in-process `question` runtime at boot and offers it only to a worker whose owner
|
|
@@ -5026,7 +5236,7 @@ packets or state snapshots.
|
|
|
5026
5236
|
owns one durable model, persisted as a nullable `model_routes` foreign key.
|
|
5027
5237
|
Concurrent first selections of the same resolved tuple share one identity;
|
|
5028
5238
|
an insertion conflict returns the existing route without changing its fields.
|
|
5029
|
-
|
|
5239
|
+
A root model worker is seeded once — from an explicit selection, else
|
|
5030
5240
|
the daemon default — and never re-seeded from a later default change. A
|
|
5031
5241
|
deliberately modelless daemon leaves the worker unset and rejects model work
|
|
5032
5242
|
until an explicit selection. Starting a loop snapshots the worker's resolved
|
|
@@ -5035,7 +5245,7 @@ continue from the loop snapshot and never re-resolve through the alias
|
|
|
5035
5245
|
cascade. A WORK/FORK child copies the spawning loop's effective spawn model
|
|
5036
5246
|
(spawn override ?? model) onto the new worker by value at creation; it retains
|
|
5037
5247
|
no live link and begins with no override, so a later parent change affects
|
|
5038
|
-
only that worker's future loops and descendants.
|
|
5248
|
+
only that worker's future loops and descendants. The runtime worker and other
|
|
5039
5249
|
Plurnk-owned bookkeeping workers run no model loops and own no model
|
|
5040
5250
|
selection; the model, spawn-override, and effort controls refuse them with
|
|
5041
5251
|
`409 model-worker-required` before any policy row is initialized or written. An explicit model, spawn-override, or effort change while
|
|
@@ -5117,26 +5327,40 @@ beside database ids, so a client can render and resolve the logical `L/T/S`
|
|
|
5117
5327
|
coordinate without fetching all rows and matching locally.
|
|
5118
5328
|
|
|
5119
5329
|
§methods-log-entry-wire **Log entry wire fidelity.** `readLog` and `log/entry`
|
|
5120
|
-
preserve causal `source` and
|
|
5330
|
+
preserve causal `source` and the row's lifecycle `state` (`proposed` while a proposal awaits its
|
|
5331
|
+
decision, then `resolved`, `failed` or `cancelled`), and parse the row's JSON `attrs` into structured data.
|
|
5121
5332
|
Client interfaces do not reconstruct these fields from operation or origin.
|
|
5122
5333
|
|
|
5123
5334
|
§methods-readable-reasoning **Readable provider reasoning remains derived
|
|
5124
|
-
provider evidence.** On
|
|
5125
|
-
project
|
|
5126
|
-
`reasoning` field
|
|
5335
|
+
provider evidence.** On a turn's first model operation row, `readLog` and `log/entry`
|
|
5336
|
+
project the turn's nonempty admitted `packet.assistant.reasoning` as the optional
|
|
5337
|
+
`reasoning` field, from the row's first announcement; no other row repeats it. Beside it,
|
|
5338
|
+
`reasoning_model_call_id` and `reasoning_request_sequence` name the request that streamed it (the
|
|
5339
|
+
turn's accepted model call and that call's response request), so a client can match the reasoning it
|
|
5340
|
+
watched stream; history a FORK inherited was streamed by no request of this worker and names none. The durable packet remains the sole stored representation;
|
|
5127
5341
|
core does not copy readable reasoning into log attributes or bodies. A turn
|
|
5128
5342
|
without readable reasoning omits the field.
|
|
5129
5343
|
|
|
5130
|
-
§
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5344
|
+
§methods-invocation **A row that discharges an obligation names the operation that opened it.** `readLog`
|
|
5345
|
+
and `log/entry` project `invocation`, the log address of that operation ({§worker-obligations}), on every
|
|
5346
|
+
row that discharges one, so a client pairs the answer with its call without matching addresses:
|
|
5347
|
+
|
|
5348
|
+
| Discharging row | Its invocation |
|
|
5349
|
+
|---|---|
|
|
5350
|
+
| A stream observation ({§exec-stream}) | The execution, as its subscription recorded it ({§subscriptions-causal-resource}) |
|
|
5351
|
+
| A child's conclusion ({§env-delta-child-termination}) | The operation that sent the first message of the concluded loop |
|
|
5352
|
+
| A completion reply delivered to the sender ({§message-reply-delivery}), including {§message-abandonment} | The operation that sent the message it completed |
|
|
5353
|
+
|
|
5354
|
+
Each is derived from what the row records: the publication it advanced, or the occurrence it materialized.
|
|
5355
|
+
A message names an invocation only to the worker whose operation sent it; history a FORK inherited names the
|
|
5356
|
+
same invocation as its original, at the same coordinate. The row's own `source` keeps its attribution meaning
|
|
5357
|
+
({§env-delta-attribution}). An obligation whose opener was not recorded, and every other row, omits the field.
|
|
5358
|
+
|
|
5359
|
+
§methods-answering **A reply names the operation that sent the message it answers.** `readLog` and `log/entry`
|
|
5360
|
+
project `answering` on a reply delivered to the worker whose operation sent the message ({§message-reply-delivery}):
|
|
5361
|
+
that operation's log address, whether the reply completes the message or reports progress. A completion reply
|
|
5362
|
+
names the same address as its `invocation`. A reply to a message this worker did not send, such as another actor
|
|
5363
|
+
answering a message in this worker's inbox, omits the field, as does every other row.
|
|
5140
5364
|
|
|
5141
5365
|
### §notifications Core events
|
|
5142
5366
|
|
|
@@ -5144,13 +5368,13 @@ adding a loop to it. LOOK text anchors resolve through the same
|
|
|
5144
5368
|
|--------------------------------------------------------------|---------|------------|
|
|
5145
5369
|
| §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. |
|
|
5146
5370
|
| §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. |
|
|
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. |
|
|
5371
|
+
| §notifications-loop-terminated `loop/terminated` | `{ workerId, loopId, result, hitMaxTurns, turnIds, usage: { accounting, curationWeight, curationBudget, contextTokens, contextCapacity, meta }, attributions, terminatedAt }` | One loop reaches a terminal state. `terminatedAt` is the loop's own stamp in Unix milliseconds, the one a projection reads ({§application-loop-observation}). `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. |
|
|
5148
5372
|
| §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. |
|
|
5149
5373
|
| §notifications-loop-proposal `loop/proposal` | contracts-owned `ProposalProjection` | Dispatch pauses on a durable 202 proposal. `disposition` is the sole authority for whether a client presents review UI; live and reconnect share {§proposal-projection}. |
|
|
5150
5374
|
| §notifications-loop-interaction `loop/interaction` | contracts-owned `ClientInteractionProjection` | An operation is paused on client input. Live delivery and reconnect discovery share {§client-interactions}; workspace scope remains the event envelope. |
|
|
5151
5375
|
| §notifications-workspace-created `workspace/created` | `{ id, name, projectRoot }` | A workspace is created. This is the only current global event. |
|
|
5152
5376
|
| `workspace/preparation` | `{ workspaceId, preparation: FunctionalityPreparationActivity[] }` | Workspace capability preparation changes; snapshot and clearing semantics follow {§functionality-preparation-visibility}. |
|
|
5153
|
-
| §notifications-stream-event-on-channel-change `stream/event` | `{ entryId, workerId, target, channel, state, contentLength, mimetype?, loop_seq?, turn_seq?, sequence? }` | Channel content grows or channel state transitions. `workerId` is the initiating actor used for
|
|
5377
|
+
| §notifications-stream-event-on-channel-change `stream/event` | `{ entryId, workerId, target, channel, state, contentLength, mimetype?, loop_seq?, turn_seq?, sequence? }` | Channel content grows or channel state transitions. `workerId` is the initiating actor used for routing to the bound worker, never entry ownership or access control. `target` is the canonical resource URI. Optional numeric coordinates identify the causal log item, independently of that URI. Core-managed channel writes include the current stored `mimetype`, which may change per call ({§channel-mimetype}); the generic extension notification capability does not require it. It carries metadata, not content; consumers read bytes by canonical workspace address. |
|
|
5154
5378
|
| §notifications-stream-concluded `stream/concluded` | `{ entryId, workerId, target, subscriptionId, scheme, result, summary, wakeAction, loop_seq?, turn_seq?, sequence? }` | A subscription closes. `workerId` identifies the initiating actor; `target` is the canonical resource URI. Optional numeric fields identify the causal log item, never parsed from `target`. Exact result truth is preserved. `wakeAction` reports `wake-pending` before settlement, `no-op-active-loop` when work is already executing, `no-loop`, or `skipped-aborted`/`skipped-cancelled` for an aborted worker scope. A pending wake predicts neither execution nor recipient count; subsequent ordinary loop events report actual progress and completion. |
|
|
5155
5379
|
| §notifications-notice-event `notice/event` | `{ workerId, loopId, notice: Notice }` | A transient observation or progress notice occurs. `workerId` owns loop activity; only workspace derivation progress uses `null` with `loopId=0`. It cannot alter durable history, scheduling, recovery, or model-visible failure truth. |
|
|
5156
5380
|
| §notifications-outside-event `outside/event` | `{ workerId, loopId, turnId, coordinate, text, tokens }` | An admitted emission carried text outside every operation ({§outside-text}): once per admitted emission, the exact stored text, its packet weight, and the turn's `<worker>-<loop>-<turn>` coordinate. It is transient presentation evidence; the turn's `outside` source remains the durable authority. |
|
|
@@ -5173,21 +5397,66 @@ the authoritative scope and is `null` only for a global event. Core does not
|
|
|
5173
5397
|
mutate each payload to repeat it. A transport module stamps that scope onto any
|
|
5174
5398
|
outward envelope that requires it and owns workspace fan-out.
|
|
5175
5399
|
|
|
5176
|
-
### §
|
|
5400
|
+
### §worker-external-reference External worker references
|
|
5401
|
+
|
|
5402
|
+
An adapter's `(namespace, reference)` identifies one durable model worker. Both strings are opaque
|
|
5403
|
+
to core; protocol syntax belongs to the adapter. `readWorkerReference` returns its workspace and
|
|
5404
|
+
worker IDs or null, without creating anything. `ensureWorkerReference` returns the same identity,
|
|
5405
|
+
atomically creating an ordinary folderless workspace and root model worker if absent. Names follow
|
|
5406
|
+
{§workspace-auto-name} and {§worker-auto-name}; no owner is claimed and no work starts.
|
|
5177
5407
|
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
one
|
|
5183
|
-
|
|
5184
|
-
interrupt/resume, but those records preserve durable evidence rather than
|
|
5185
|
-
defining the public client lifecycle. Multiple client actors have distinct workers.
|
|
5408
|
+
The association is immutable while its worker exists. Concurrent allocation creates exactly one
|
|
5409
|
+
workspace, worker and association; failure leaves none. Renaming a workspace, changing approval
|
|
5410
|
+
ownership, reconnecting or restarting does not change the association. Worker deletion removes it
|
|
5411
|
+
through its foreign key. Namespaces isolate adapter identities, not authorization: the daemon
|
|
5412
|
+
remains one trust domain. `listWorkerReferences` inspects one namespace's references to a worker,
|
|
5413
|
+
bounded by its workspace. New workspace creation emits the ordinary `workspace/created` event.
|
|
5186
5414
|
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5415
|
+
### §connection-lifecycle Client operations
|
|
5416
|
+
|
|
5417
|
+
A worker is a model's identity. A person's client operations (an execution, typed
|
|
5418
|
+
statements, a rollback's compensations) are the workspace's, so each journals in the
|
|
5419
|
+
workspace's runtime worker `_plurnk`, created when absent, and executes in the workspace's
|
|
5420
|
+
Functionality ({§actor-boundary-attached-functionality}). Binding a workspace mints nothing.
|
|
5421
|
+
|
|
5422
|
+
| | A model worker | A client operation in `_plurnk` |
|
|
5423
|
+
|---|---|---|
|
|
5424
|
+
| Who acted | the worker | the person its loop names ({§actor-boundary-client-operations}) |
|
|
5425
|
+
| Who answers its proposals | the worker's owner reviews them | nobody: it is that person's decision already ({§proposal-disposition}) |
|
|
5426
|
+
| Who answers its clarifications | its owner, while it can ({§client-interaction-routing}) | nobody: the runtime's owner receives no client tool, so an interaction the operation needs fails at once as unsupported |
|
|
5427
|
+
| What is cancelled and observed together | the worker's loops | the operation's own administrative loop |
|
|
5428
|
+
| What its `env:///` means | its own layer, above the workspace's | the workspace's layer; `_plurnk` keeps none ({§env-scheme}) |
|
|
5429
|
+
| Whose voice its messages carry | its own | the person's, as a thread message's is |
|
|
5430
|
+
| Whose log its log addresses and FORK mean | its own | the worker the person acts for: read and branched, never curated |
|
|
5431
|
+
| What its WORK starts | its own child | a root worker the person owns |
|
|
5432
|
+
|
|
5433
|
+
One client operation owns one administrative loop, and its statements become ordered
|
|
5434
|
+
`client` operation turns inside it. The loop carries its own cancellation scope, and
|
|
5435
|
+
nothing else in `_plurnk` (another person's operation, the daemon's narration, a hosted A2A
|
|
5436
|
+
task) shares it. `cancelLoop` cancels that operation alone: a dispatch still running
|
|
5437
|
+
ends `operation-cancelled`, as does its loop, and every attached execution its rows started
|
|
5438
|
+
that still runs is reaped ({§worker-lifecycle-total-reap}), its stream concluding aborted even
|
|
5439
|
+
after the loop settled. A detached execution is nobody's obligation, and `cancelLoop` leaves it
|
|
5440
|
+
running. Shutdown cancels every operation the same way.
|
|
5441
|
+
|
|
5442
|
+
`runLoop` targets a model worker with `origin="model"`. A packet renders only that
|
|
5443
|
+
worker's private log, so a client operation's rows are structurally absent from every
|
|
5444
|
+
model's packet ({§actor-boundary-isolation}); a person reaches a model through a message.
|
|
5445
|
+
|
|
5446
|
+
§actor-boundary-client-operations **A client operation acts on workspace resources, attributes messages
|
|
5447
|
+
to its person, and reads a log in the context of one worker.** Its loop's `promptSource`
|
|
5448
|
+
({§methods-worker-loops}) is the acting person's canonical address, the form arrivals use
|
|
5449
|
+
({§message-causal-source}); the daemon's own loops in `_plurnk` have none. Its rows are acts, not arrivals:
|
|
5450
|
+
they keep writer `origin: "client"`, so a person never writes as the runtime
|
|
5451
|
+
({§scheme-surface-writableby-403}), and `source` null, so a person's SEND replies and completes as any
|
|
5452
|
+
author's does. Acting for no worker, an operation names no log: `log:///` is 404 `log-unaddressed` and
|
|
5453
|
+
FORK is 404 `fork-unaddressed`.
|
|
5454
|
+
|
|
5455
|
+
| Frame | Covers | So |
|
|
5456
|
+
|---|---|---|
|
|
5457
|
+
| Workspace resources | files, executions, Functionality, `env:///` | `_plurnk` keeps no layer of its own, so a person's `env:///` reads and writes the workspace's ({§env-scheme}) |
|
|
5458
|
+
| The person's voice | messages and delegated prompts | a message the operation delivers (SEND, or WORK to a worker that exists) arrives from the person, as a thread message does; WORK to a new worker starts a root model worker the person owns, its first prompt from them |
|
|
5459
|
+
| The worker it acts for | `log:///`, and the log FORK branches | READ and FIND answer from that worker's log as it reads it; FORK branches it as `forkWorker` does, its task from the person; curating the log is a client write it refuses ({§scheme-surface-writableby-403}) |
|
|
5191
5460
|
|
|
5192
5461
|
---
|
|
5193
5462
|
|
|
@@ -5261,7 +5530,7 @@ Conditional absence never reorders the surviving default sections.
|
|
|
5261
5530
|
| 6 | user | `git` | Per-turn workspace status; empty content is omitted. |
|
|
5262
5531
|
| 7 | user | `budget` | `Context Curation`; omitted when capacity is unknown. |
|
|
5263
5532
|
| 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 | `
|
|
5533
|
+
| 9 | user | `work` | `Open Work`: per-turn `{workers, streams, messages}` pointers; always present, each list `[]` when empty ({§packet-empty-sections}). |
|
|
5265
5534
|
| 10 | user | `messages` | `Open Messages`: immutable message addresses and causal sources ({§message-arrival}). |
|
|
5266
5535
|
| 11 | user | `notices` | Per-turn observations; empty content is omitted. |
|
|
5267
5536
|
| 12 | user | `errors` | Per-turn failure pointers; empty content is omitted. |
|
|
@@ -5271,7 +5540,7 @@ The order favors prefix-cache locality where semantics permit: the definition
|
|
|
5271
5540
|
and privileged policy lead operator notes, while the append-mostly
|
|
5272
5541
|
log and interpolated programs lead the volatile user-status clump. That clump is never cached
|
|
5273
5542
|
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,
|
|
5543
|
+
it runs from ambient state (Git Status, Context, Worker, Open Work) to what the turn owes (Open
|
|
5275
5544
|
Messages) to feedback on the last turn (Notices, then Errors), and closes with the Recap. The nearer
|
|
5276
5545
|
the end, the more a section asks of this turn. With `all`, appending new
|
|
5277
5546
|
observations and programs preserves the existing history's roles and text prefix; no old program
|
|
@@ -5332,8 +5601,7 @@ flowchart TD
|
|
|
5332
5601
|
```
|
|
5333
5602
|
|
|
5334
5603
|
- §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,
|
|
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}).
|
|
5604
|
+
- §context-gauge **One gauge.** Every packet carries one `## Context` section holding one JSON object: `tokens`, the packet's weight as rendered, `budget`, the known room, and `percent`, `floor(100 × tokens / budget)` over the gauge's own final figures, so the share never disagrees with the counts beside it; a zero budget states no share. 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 `budget`, `percent` 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.
|
|
5337
5605
|
- §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.
|
|
5338
5606
|
- §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.
|
|
5339
5607
|
- §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.
|
|
@@ -5397,7 +5665,7 @@ flowchart LR
|
|
|
5397
5665
|
log --> packet["Packet lists coordinate;<br/>READ recalls exact body"]
|
|
5398
5666
|
```
|
|
5399
5667
|
|
|
5400
|
-
§env-delta-log-pull **Pull the event record, never a
|
|
5668
|
+
§env-delta-log-pull **Pull the event record, never a workspace snapshot.** At
|
|
5401
5669
|
pre-turn, a worker materializes only occurrences whose structural audience
|
|
5402
5670
|
includes that worker. The set is exhaustive, unranked, and exactly once; the
|
|
5403
5671
|
engine makes no relevance decision. Each copied event retains the operation,
|
|
@@ -5591,9 +5859,9 @@ another admission is a 409 conflict, not a second message or an implicit content
|
|
|
5591
5859
|
|
|
5592
5860
|
| Audience | Delivery | Effect |
|
|
5593
5861
|
|---|---|---|
|
|
5594
|
-
| Assigned worker | Its
|
|
5862
|
+
| Assigned worker | Its own log, even when another actor answered | Visible reply; wakes eligible parked work without a new Open Message or loop. |
|
|
5595
5863
|
| Original native sender | That worker, if distinct from the assigned worker; original delegated-task answers use {§worker-scheme-collect} instead | Other replies use the same wake and observation path. |
|
|
5596
|
-
| Exterior sender | The assigned
|
|
5864
|
+
| Exterior sender | The assigned worker's protocol adapter | The adapter delivers the answer through its standard message channel. |
|
|
5597
5865
|
| Replying actor | Its own executed SEND | No duplicate ambient occurrence. |
|
|
5598
5866
|
|
|
5599
5867
|
The successful SEND and its addressed occurrences commit together. Reply occurrences use
|
|
@@ -5624,7 +5892,9 @@ published, oldest first, and stamps each with the row it became. Ordinal 1 is th
|
|
|
5624
5892
|
own assignment and shares the loop's fate: a loop that fails before its first turn does
|
|
5625
5893
|
not replay it. Every other still-unpublished message at conclusion moves into one
|
|
5626
5894
|
source-keyed recovery loop, renumbered from its first, whose headline it becomes; that loop's first turn publishes the complete
|
|
5627
|
-
ordered set exactly once.
|
|
5895
|
+
ordered set exactly once. The recovery loop retains the source loop's model routes,
|
|
5896
|
+
effort, and call ceiling; message bodies and attribution are preserved directly from
|
|
5897
|
+
their durable rows. Recovery retries complete the same queued loop and never
|
|
5628
5898
|
mint duplicate work. Output withholding preserves readable arrival rows; explicit
|
|
5629
5899
|
KILL follows the ordinary log contract.
|
|
5630
5900
|
|
|
@@ -5690,10 +5960,9 @@ retain distinct contracts and lifetimes.
|
|
|
5690
5960
|
| `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
5961
|
| `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
5962
|
| `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
|
|
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 |
|
|
5963
|
+
| `continued_without_note` | engine turn — a continuing or parked model turn that admitted no NOTE ({§continued-without-note}); `level: warn` | YOU MUST emit at least one NOTE in every turn. | none |
|
|
5695
5964
|
| `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
|
|
5965
|
+
| `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
5966
|
| `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
5967
|
| `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
5968
|
| `provider_retry` | a provider stream that failed after output began and was answered by a complete retry; `level: warn` | none | none |
|
|
@@ -5705,13 +5974,13 @@ retain distinct contracts and lifetimes.
|
|
|
5705
5974
|
| `scope_normalized` | engine slicer — a scope normalized to its canonical form; `level: warn` | YOU SHOULD write the normalized scope. | none |
|
|
5706
5975
|
| `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
5976
|
|
|
5708
|
-
§continued-without-note **A continuing turn that
|
|
5977
|
+
§continued-without-note **A continuing turn that carried no NOTE is told so.** The card teaches NOTE as the register of every plan, finding, decision and next action; the notice's directive is the command `YOU MUST emit at least one NOTE in every turn.` 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.` It 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
5978
|
|
|
5710
5979
|
§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
5980
|
|
|
5712
5981
|
```text
|
|
5713
5982
|
> [!WARNING]
|
|
5714
|
-
> YOU
|
|
5983
|
+
> YOU SHOULD write the normalized scope. Scope <0,120> was normalized to <1,120>. [scope_normalized]
|
|
5715
5984
|
```
|
|
5716
5985
|
|
|
5717
5986
|
§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.
|
|
@@ -5721,7 +5990,10 @@ retain distinct contracts and lifetimes.
|
|
|
5721
5990
|
§notice-event-notify **Client surface.** Engine Notices broadcast live via the `notice/event` notification — `{ workerId, loopId, notice: { source, kind, level, message?, position?, …kind-specific } }` per the grammar's `Notice` schema — the moment they land. A loop Notice names its owning Worker; workspace derivation progress alone carries `workerId=null, loopId=0`. AG-UI projects the same observation as the custom `plurnk.notice` event. Failures do not broadcast on this surface: they are log rows, and the client reads them through `log.read` / the `log/entry` notification, the durable log.
|
|
5722
5991
|
|
|
5723
5992
|
§loop-status-notice **The drain publishes lifecycle and its observation deadline together.**
|
|
5724
|
-
`notice/event` carries `{ workerId, loopId, notice: { source: "engine:lifecycle", kind: "loop_status", level: "info", status, waitUntil } }
|
|
5993
|
+
`notice/event` carries `{ workerId, loopId, notice: { source: "engine:lifecycle", kind: "loop_status", level: "info", status, waitUntil, packetCount, claimedAt } }`:
|
|
5994
|
+
with its status, every beat carries its loop's packet count and claim stamp (Unix milliseconds, `null`
|
|
5995
|
+
before the first claim), the ones a projection reads ({§application-loop-observation}), so a client
|
|
5996
|
+
updates the loop's identity, count and stamp together.
|
|
5725
5997
|
|
|
5726
5998
|
| Edge | `status` | `waitUntil` |
|
|
5727
5999
|
|---|---|---|
|
|
@@ -5743,7 +6015,7 @@ the same deadline through {§application-loop-observation}, not a restarted cloc
|
|
|
5743
6015
|
|
|
5744
6016
|
§candidate-pinned-runtime **Candidate runtime stays pinned.** At launch, after its optional build, the candidate copies every workspace's package projection (`files`) into `<state>/runtime`, links third-party dependencies, and resolves `@plurnk/*` to those copies. Its daemon and its digest export both run from that copy, never the shared checkout, so neither source edits nor a concurrent candidate's or developer's rebuild after launch changes the code a run finishes on. The copy is removed once the digest is written.
|
|
5745
6017
|
|
|
5746
|
-
§output-allowance-notice **The output allowance is not disclosed; a ceiling cut names its cause.** The packet's budget section carries the curation state and no response allowance: a model does not plan in tokens and no harness tells it its output ceiling, so the number is a fact without a use (#826). Overflow tolerance (#482) is likewise never advertised; a cut's notice names the true per-call grant from the response's own capacity record. When a provider finish is `length`, the engine emits an `output_truncated` notice (source `engine:capacity`) naming the allowance — the fact alone, never advice on what to do about it — on every path — railed or not — and the rails verdict never blames the model
|
|
6018
|
+
§output-allowance-notice **The output allowance is not disclosed; a ceiling cut names its cause.** The packet's budget section carries the curation state and no response allowance: a model does not plan in tokens and no harness tells it its output ceiling, so the number is a fact without a use (#826). Overflow tolerance (#482) is likewise never advertised; a cut's notice names the true per-call grant from the response's own capacity record. When a provider finish is `length`, the engine emits an `output_truncated` notice (source `engine:capacity`) naming the allowance — the fact alone, never advice on what to do about it — on every path — railed or not — and the rails verdict never blames the model for a cut the engine's own ceiling made: a cut turn is no repetition evidence ({§engine-cycle-evidence}), and a strike threshold crossed on one names the allowance ({§engine-rails}). The same precedence governs a cut so deep no operation parses: the rejection notice names the truncation as the cause, not the parser's symptom, overriding {§invalid-emission-attempts}'s parser diagnostic for `length` finishes.
|
|
5747
6019
|
|
|
5748
6020
|
§turn-lifecycle **Turn-lifecycle liveness.** Provider generation is the long, opaque window in a turn — one or more same-packet emission attempts may occur before the first committed op. A static client screen there is indistinguishable from a hang. The engine brackets the complete attempt window with two `notice/event` notices (`source: "engine:turn"`, `level: "info"`): `turn_awaiting_model` before the first call and `turn_generated` when an emission is accepted or the attempt budget is exhausted. The completion beat carries the spend ({§turn-accounting-notice}). Rejected content never rides the notice channel. Both are suppressed on an aborted loop and broadcast to the workspace like any notice ({§notice-event-notify}).
|
|
5749
6021
|
|
|
@@ -5831,15 +6103,18 @@ remain one compact orientation line, not an expansion of every tool's signature.
|
|
|
5831
6103
|
|
|
5832
6104
|
§members-functionality **File membership is one workspace Functionality family.**
|
|
5833
6105
|
Core registers the `members` family with the coordinator ({§functionality-coordinator}):
|
|
5834
|
-
the model, the client, and the operator learn one surface — `list | discover | add |
|
|
6106
|
+
the model, the client, and the operator learn one surface — `list | discover | add |
|
|
5835
6107
|
enable | disable | remove`, `workspace.members.<verb>` for the client,
|
|
5836
6108
|
```` ```members (<verb>) ```` for the model — for what the model may see, exactly as they do for skills and
|
|
5837
|
-
MCP servers. A definition is one shell-path glob ({§path-glob-matching})
|
|
5838
|
-
root; a leading `!` excludes matching members, and an exclusion wins over every inclusion.
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
6109
|
+
MCP servers. A definition is one shell-path glob ({§path-glob-matching}) relative to the project
|
|
6110
|
+
root; a leading `!` excludes matching members, and an exclusion wins over every inclusion. The glob
|
|
6111
|
+
is the definition's identity ({§functionality-addressing}): `add` takes `{"files": ["<glob>", …]}`
|
|
6112
|
+
and admits each glob, trimmed, as one definition, a glob named twice being one; `enable`, `disable`
|
|
6113
|
+
and `remove` take `{"file": "<glob>"}`, the glob as `list` shows it. A bare `!` is 400
|
|
6114
|
+
`definition-invalid`. Admission provenance (`service-configuration`, `client-action`,
|
|
6115
|
+
`model-proposal`) rides the persisted definition, `{ glob, provenance }`, to enforce
|
|
6116
|
+
{§members-model-scope}; configuration-source provenance belongs to the shared inspection projection
|
|
6117
|
+
({§configuration-provenance}). `list` shows each
|
|
5843
6118
|
definition with what it resolved to — `include` or `exclude`, the pattern, the members it
|
|
5844
6119
|
admits or removes (count and a bounded sample), and for a model's inclusion the matches the
|
|
5845
6120
|
repository's ignore rules refused — so the model sees what its glob did and adapts.
|
|
@@ -5850,7 +6125,9 @@ or exclude. A query that names neither, blank or a bare `!`, is 400 `query-inval
|
|
|
5850
6125
|
never content; nothing is added.
|
|
5851
6126
|
|
|
5852
6127
|
§members-configuration *Available definitions.* `PLURNK_MEMBERS_<alias>=<glob>`
|
|
5853
|
-
declares one service-origin rule (`!glob` excludes)
|
|
6128
|
+
declares one service-origin rule (`!glob` excludes), named by its glob like every definition; the
|
|
6129
|
+
key is its configuration provenance, which `list` shows, and two keys declaring one glob fail by
|
|
6130
|
+
name. The shared naming and
|
|
5854
6131
|
enabledness dialect is {§resource-environment}; `PLURNK_MEMBERS_ENABLED` supplies
|
|
5855
6132
|
the panel default and `PLURNK_MEMBERS_<alias>_ENABLED` overrides one rule.
|
|
5856
6133
|
An empty glob or a bare `!` fails validation. Controls may precede their rule;
|
|
@@ -5877,7 +6154,8 @@ the repository ignores ({§membership-model-universe}). The engine's creation re
|
|
|
5877
6154
|
overwrites or retires them. Projection happens at the family's publication commit and
|
|
5878
6155
|
re-resolves membership; workspace cooling changes nothing, because desired state is
|
|
5879
6156
|
durable. Each enabled definition is one generated document at
|
|
5880
|
-
`worker:///_plurnk/members/<
|
|
6157
|
+
`worker:///_plurnk/members/<glob>.md` ({§functionality-documents}), the glob percent-encoded as
|
|
6158
|
+
one path segment (RFC 3986 unreserved characters and parentheses stay literal) — its glob, origin,
|
|
5881
6159
|
provenance, and what it resolved to — surveyed at turn 0 like every family's enabled
|
|
5882
6160
|
definitions ({§actor-boundary-catalog-preview}), so the model sees why a file is or is
|
|
5883
6161
|
not a member before it asks. There is no other membership path: the client's `/members`
|
|
@@ -6309,7 +6587,25 @@ lane's run directory and the lane's reclaim takes all of it; an unnamed run is C
|
|
|
6309
6587
|
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
|
|
6310
6588
|
caller's own run directory.
|
|
6311
6589
|
|
|
6312
|
-
§
|
|
6590
|
+
§tier-census **A real-model tier run is one directory with its census.** The live and demo drivers
|
|
6591
|
+
stamp `PLURNK_TIER_RUN` as `<kind>-<UTC stamp>`; every worker the run claims lands inside
|
|
6592
|
+
`PLURNK_BENCHMARKS/tier-<kind>-<stamp>/`, each in its own `<label>-XXXXXX/` with its database, its own
|
|
6593
|
+
host, its digest and a `census.json` naming the specimen that drove it, its loops, turns, requests,
|
|
6594
|
+
tokens and cost. The run's `census.md` and `census.json`, written by the tier's node:test reporter
|
|
6595
|
+
when the run ends, carry one row per specimen: verdict, skip reason or first failure line, the
|
|
6596
|
+
workers it claimed, turns, requests and cost; a run never deletes or moves any of it. A specimen
|
|
6597
|
+
declares what it requires of the route and the host (`input:<image|pdf|audio|video>`, `reasoning`,
|
|
6598
|
+
`output-budget`, `env:<NAME>`, `url:<http(s) URL>`, `bin:<name>` on PATH, `checkout:<client|a2a-tck>`
|
|
6599
|
+
at `PLURNK_CLIENT_CHECKOUT` or `PLURNK_A2A_TCK_CHECKOUT`, else beside the repository); an unmet
|
|
6600
|
+
requirement is a skip, before anything boots or is spent, whose reason names the requirement and what
|
|
6601
|
+
was observed, and the census answers each unmet route-bound requirement with the declared aliases
|
|
6602
|
+
whose catalog entry satisfies it. A route the harness cannot resolve is a failure, never a skip. No
|
|
6603
|
+
test surface is an opt-in flag or a script of its own: the third-party MCP composition, the
|
|
6604
|
+
llama-server rails, the upstream A2A TCK and the client's real-model TUI tier are live specimens that
|
|
6605
|
+
run wherever their requirements hold. `tier:history` ledgers every census under the home: per
|
|
6606
|
+
specimen, its verdicts over runs and its last reason.
|
|
6607
|
+
|
|
6608
|
+
§fs-resource-state **The resource-state harness — coverage that closes the class.** Op-outcome tests check what an op returned; the harness checks the resulting resource state. `ResourceState.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.
|
|
6313
6609
|
|
|
6314
6610
|
## Problem codes and pinned wording
|
|
6315
6611
|
|
|
@@ -6341,11 +6637,15 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6341
6637
|
| `kill-target-scheme-required` | 400 | KILL target requires a scheme. |
|
|
6342
6638
|
| `worker-not-found` | 404 | Worker '*name*' does not exist in this workspace. |
|
|
6343
6639
|
| `entry-operation-unsupported` | 400 | KILL requires an entry-bearing target; '*scheme*' does not provide one. |
|
|
6640
|
+
| `coordinate-invalid` | 400 | '*to*' is not a log coordinate ({§rollback}). Recovery: Name the coordinate as `<loop>/<turn>/<item>`, as the log shows it. |
|
|
6641
|
+
| `coordinate-not-found` | 404 | No log entry exists at log:///*coordinate* ({§rollback}). |
|
|
6642
|
+
| `project-root-required` | 400 | Rollback restores files, and this workspace has no project root ({§rollback}). |
|
|
6344
6643
|
| `resource-scheme-required` | 400 | Resource selection requires an address. |
|
|
6345
6644
|
| `channel-required` | 400 | The '*scheme*' scheme has no default channel. Recovery: Address a named channel with a URI fragment. |
|
|
6346
6645
|
| `binary-source-unsupported` | 415 | Channel #*name* is binary and its scheme keeps no bytes to transfer. |
|
|
6347
|
-
| `metadata-unsupported` | 400 | *OP* takes only the env option; '*key*' is not one. |
|
|
6348
|
-
| `
|
|
6646
|
+
| `metadata-unsupported` | 400 | *OP* takes only the env option; '*key*' is not one. A WORK to a held name with env: WORK to the existing worker '*name*' carries env; a message takes none. |
|
|
6647
|
+
| `fork-unaddressed` | 404 | This client operation acts for no worker, so FORK has no log to branch ({§actor-boundary-client-operations}). |
|
|
6648
|
+
| `worker-name-conflict` | 409 | Worker '*name*' already exists in this workspace. Recovery: WORK or SEND (worker://*name*) delivers a message to the live worker; FORK with a name no worker holds. ({§worker-scheme-spawn}) |
|
|
6349
6649
|
| `no-operation` | 422 | The turn performed no operation ({§empty-turn}). |
|
|
6350
6650
|
| `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
6651
|
| `invalid-operation-syntax` | 400 | The parser's diagnostic for an invalid operation in an admitted turn. |
|
|
@@ -6408,7 +6708,7 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6408
6708
|
| `file-create-excluded` | 403 | A members exclusion (`!_glob_`) covers '*path*'. Recovery: Remove or disable the excluding members definition, or choose another path. |
|
|
6409
6709
|
| `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. |
|
|
6410
6710
|
| `file-materialization-limit` | 413 | The file exceeds the materialization byte limit and is not read into the workspace. |
|
|
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 `{"
|
|
6711
|
+
| `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 `{"files": ["<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
6712
|
| `body-channel-required` | 400 | A file write requires a body channel. |
|
|
6413
6713
|
| `write-failed` | 500 | Publication or its settlement failed; the result distinguishes an unpublished write from an already-published one. |
|
|
6414
6714
|
| `creation-rollback-failed` | 500 | Incorporating a newly created file failed, and rollback was incomplete. |
|
|
@@ -6421,7 +6721,7 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6421
6721
|
| code | status | contract |
|
|
6422
6722
|
|---|---:|---|
|
|
6423
6723
|
| `invalid-input-target` | 400 | SEND input addresses an execution, without a channel or scope. |
|
|
6424
|
-
| `input-unavailable` | 409 | This execution's input receiver is no longer enabled. |
|
|
6724
|
+
| `input-unavailable` | 409 | This execution was launched without input. Recovery: Launch it with `[{"stdin": "open"}]` when its runtime takes input, then SEND to that execution. — This execution is queued for an execution slot; its input opens when it starts. Recovery: SEND again once the execution has started. — This execution's input receiver is no longer enabled. |
|
|
6425
6725
|
| `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*`. |
|
|
6426
6726
|
| `input-closed` | 410 | Execution input is closed. |
|
|
6427
6727
|
| `executor-not-registered` | 400 | No executor or MCP service named '*runtime*' is registered for this worker. |
|
|
@@ -6444,6 +6744,7 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6444
6744
|
|---|---:|---|
|
|
6445
6745
|
| `read-target-required` | 400 | READ requires a log coordinate. Recovery: Provide one exact log coordinate. |
|
|
6446
6746
|
| `coordinate-malformed` | 400 | The log coordinate '*path*' is malformed. Recovery: Use one exact loop/turn/sequence coordinate. |
|
|
6747
|
+
| `log-unaddressed` | 404 | This client operation acts for no worker, so `log:///` names no log ({§actor-boundary-client-operations}). |
|
|
6447
6748
|
| `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
6749
|
| `curation-failed` | 400 | A scoped KILL's selection could not be read: the same sentences and recovery as `kill-failed`. |
|
|
6449
6750
|
| `worker-target-required` | 400 | EDIT requires a worker:// target. Recovery: Provide the worker target. |
|
|
@@ -6464,14 +6765,16 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6464
6765
|
| code | status | condition |
|
|
6465
6766
|
|---|---:|---|
|
|
6466
6767
|
| `interaction-not-pending` | 409 | The requested client interaction is not pending. |
|
|
6467
|
-
| `interaction-unsupported` | 501 | No recipient implements the requested tool for this
|
|
6768
|
+
| `interaction-unsupported` | 501 | No recipient implements the requested tool for this worker. |
|
|
6468
6769
|
| `recipient-mismatch` | 403 | Only the interaction's recipient may answer it. |
|
|
6469
6770
|
| `interaction-response-invalid` | 400 | The response does not satisfy the pending interaction's schema. |
|
|
6470
6771
|
| `invalid-body` | 400 | A question body is not JSON, or lacks its nonempty message or requested schema. |
|
|
6471
6772
|
| `offset-invalid` | 400 | An entry offset is not a nonnegative safe integer. |
|
|
6472
6773
|
| `userinfo-not-allowed` | 400 | An entry target URL contains userinfo. |
|
|
6473
6774
|
| `action-threw` | 500 | The client action failed outside its operation result contract. |
|
|
6775
|
+
| `operation-cancelled` | 499 | The client operation was cancelled: *reason*. Its loop settles with this result ({§connection-lifecycle}). |
|
|
6474
6776
|
| `message-already-accepted` | 409 | The message address was already accepted in this workspace. |
|
|
6777
|
+
| `message-address-reused` | 422 | The message address was already accepted in this workspace with other words. |
|
|
6475
6778
|
| `source-not-running` | 409 | The originating task is not running; no message was admitted. |
|
|
6476
6779
|
| `loop-not-open` | 409 | The named loop is not an unfinished recipient of the worker; no message was admitted. |
|
|
6477
6780
|
|
|
@@ -6518,18 +6821,18 @@ lists the schemes the workspace registers, and rebuilds the address into nothing
|
|
|
6518
6821
|
| Nothing is in flight. Continuing. | a WAIT (or a premature terminal) with no live work ({§wait-obligation-matrix}) |
|
|
6519
6822
|
| All Open Messages resolved. Review new results; emit no OPs if finished. | resolved messages with unobserved results ({§loop-completion}) |
|
|
6520
6823
|
| Context exceeds budget. YOU MUST ONLY KILL, MOVE or NOTE this turn. | the over-budget row ({§context-over-budget-row}) |
|
|
6521
|
-
| YOU MUST
|
|
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}) |
|
|
6824
|
+
| YOU MUST emit at least one NOTE in every turn. The turn continued without a NOTE. | a continuing or parked model turn without a NOTE ({§continued-without-note}) |
|
|
6523
6825
|
| Each directive in the notice table | a notice of the model's own output ({§notice-directive}) |
|
|
6524
6826
|
| Context window overflow: the packet cannot fit the model's window even as receipts. | the wall ({§context-wall}) |
|
|
6525
6827
|
| No recipient implements the requested interaction. | The worker's owner is not interactive or does not declare the required client tool ({§client-interaction-routing}). |
|
|
6526
6828
|
| 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}) |
|
|
6527
6829
|
| 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 |
|
|
6528
6830
|
| 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 |
|
|
6831
|
+
| name '*name*' has the path segment '*segment*'. Recovery: Provide a name with no '.' or '..' between its slashes; a dot within a segment is ordinary. / name is not well-formed Unicode: it holds an unpaired surrogate. | a workspace name refused at creation or rename ({§workspace-name}) |
|
|
6529
6832
|
| The stream was cancelled by KILL. | a stream terminal after KILL |
|
|
6530
6833
|
| '*runtime*' exited with code 127; `*program*` is a registered tool of `*owner*`. | a tool run as a shell command ({§exec-tool-fall-through}) |
|
|
6531
6834
|
| '*path*' is a directory, not a file; READ reads one file. Recovery: `FIND (_path_/)` lists its files. | READ of a directory |
|
|
6532
6835
|
| The execution at ops://*worker*/*loop* has not concluded. | a bare READ of a running worker's result (425) |
|
|
6533
6836
|
| The child provider failed. | a child's provider failure read back by its parent |
|
|
6534
|
-
| '*path*' exists on disk but is not a member of this workspace. Recovery: Admit it with `members (add)` and a `{"
|
|
6837
|
+
| '*path*' exists on disk but is not a member of this workspace. Recovery: Admit it with `members (add)` and a `{"files": ["<path>"]}` body. | a non-member on disk at the addressed path |
|
|
6535
6838
|
| '*path*' exists on disk but is not a member of this workspace. Recovery: The repository ignores it: a client or operator members definition can include it, a model definition cannot. | a non-member the repository ignores ({§membership-read-refusal}) |
|