@plurnk/plurnk-service 1.29.0 → 2.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 -18
- package/INSTALL.md +65 -15
- package/README.md +8 -5
- package/SPEC.md +197 -444
- package/dist/build-info.json +1 -1
- package/dist/content/body-preview.d.ts.map +1 -1
- package/dist/content/body-preview.js +11 -2
- package/dist/content/body-preview.js.map +1 -1
- package/dist/content/line-marker.js +1 -1
- package/dist/content/line-marker.js.map +1 -1
- package/dist/content/path-mimetype.js +1 -1
- package/dist/content/path-mimetype.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts +4 -3
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +19 -17
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BareBatchRunner.d.ts +2 -2
- package/dist/core/BareBatchRunner.d.ts.map +1 -1
- package/dist/core/BareBatchRunner.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +2 -2
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +3 -8
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/Engine.d.ts +1 -1
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +1 -1
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/ExecutorRegistry.d.ts +3 -17
- package/dist/core/ExecutorRegistry.d.ts.map +1 -1
- package/dist/core/ExecutorRegistry.js +6 -6
- package/dist/core/ExecutorRegistry.js.map +1 -1
- package/dist/core/HostPaths.d.ts +2 -0
- package/dist/core/HostPaths.d.ts.map +1 -1
- package/dist/core/HostPaths.js +14 -0
- package/dist/core/HostPaths.js.map +1 -1
- package/dist/core/PacketBuilder.js +1 -1
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/SchemeRegistry.d.ts +5 -4
- package/dist/core/SchemeRegistry.d.ts.map +1 -1
- package/dist/core/SchemeRegistry.js +9 -9
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/ToolResources.js +5 -5
- package/dist/core/ToolResources.js.map +1 -1
- package/dist/core/Turn.js +1 -1
- package/dist/core/Turn.js.map +1 -1
- package/dist/core/TurnOps.d.ts +1 -1
- package/dist/core/TurnOps.d.ts.map +1 -1
- package/dist/core/TurnOps.js +4 -12
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.d.ts +1 -2
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +11 -24
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/caps/DbNotifyCaps.js +2 -2
- package/dist/core/caps/DbNotifyCaps.js.map +1 -1
- package/dist/core/caps/DbProjectionCaps.js +1 -1
- package/dist/core/caps/DbProjectionCaps.js.map +1 -1
- package/dist/core/env-defaults.d.ts +2 -1
- package/dist/core/env-defaults.d.ts.map +1 -1
- package/dist/core/env-defaults.js +17 -9
- package/dist/core/env-defaults.js.map +1 -1
- package/dist/core/packet-wire.d.ts +1 -2
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +9 -6
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/evidence/EvidenceReader.d.ts +14 -0
- package/dist/evidence/EvidenceReader.d.ts.map +1 -0
- package/dist/evidence/EvidenceReader.js +134 -0
- package/dist/evidence/EvidenceReader.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +3 -3
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
- package/dist/schemes/File.js +1 -1
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +14 -11
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/{Skill.d.ts → ResourceTreeScheme.d.ts} +5 -6
- package/dist/schemes/ResourceTreeScheme.d.ts.map +1 -0
- package/dist/schemes/{Skill.js → ResourceTreeScheme.js} +63 -43
- package/dist/schemes/ResourceTreeScheme.js.map +1 -0
- package/dist/schemes/Worker.js +1 -1
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.sql +1 -1
- package/dist/schemes/_entry-find.js +2 -2
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-find.sql +1 -1
- package/dist/schemes/_entry-manifest.js +1 -1
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/server/AgentRoots.d.ts +2 -1
- package/dist/server/AgentRoots.d.ts.map +1 -1
- package/dist/server/AgentRoots.js +13 -10
- package/dist/server/AgentRoots.js.map +1 -1
- package/dist/server/ConfigurationDiagnostics.d.ts +4 -3
- package/dist/server/ConfigurationDiagnostics.d.ts.map +1 -1
- package/dist/server/ConfigurationDiagnostics.js +15 -8
- package/dist/server/ConfigurationDiagnostics.js.map +1 -1
- package/dist/server/Daemon.d.ts +13 -8
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +91 -49
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/EnvFunctionality.d.ts +2 -2
- package/dist/server/EnvFunctionality.d.ts.map +1 -1
- package/dist/server/EnvFunctionality.js +2 -2
- package/dist/server/EnvFunctionality.js.map +1 -1
- package/dist/server/Functionality.d.ts +3 -2
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js +1 -1
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/HttpListener.d.ts +2 -0
- package/dist/server/HttpListener.d.ts.map +1 -1
- package/dist/server/HttpListener.js +17 -9
- package/dist/server/HttpListener.js.map +1 -1
- package/dist/server/MembersFunctionality.d.ts +1 -1
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/ModuleHost.d.ts +33 -0
- package/dist/server/ModuleHost.d.ts.map +1 -0
- package/dist/server/ModuleHost.js +2 -0
- package/dist/server/ModuleHost.js.map +1 -0
- package/dist/server/PlurnkSkill.d.ts.map +1 -1
- package/dist/server/PlurnkSkill.js +54 -6
- package/dist/server/PlurnkSkill.js.map +1 -1
- package/dist/server/ServiceModules.d.ts +0 -2
- package/dist/server/ServiceModules.d.ts.map +1 -1
- package/dist/server/ServiceModules.js +5 -9
- package/dist/server/ServiceModules.js.map +1 -1
- package/dist/server/WorkspacePlugins.d.ts +2 -11
- package/dist/server/WorkspacePlugins.d.ts.map +1 -1
- package/dist/server/WorkspacePlugins.js.map +1 -1
- package/dist/server/WorkspaceResidency.d.ts +2 -1
- package/dist/server/WorkspaceResidency.d.ts.map +1 -1
- package/dist/server/WorkspaceStorage.d.ts +1 -0
- package/dist/server/WorkspaceStorage.d.ts.map +1 -1
- package/dist/server/WorkspaceStorage.js +31 -5
- package/dist/server/WorkspaceStorage.js.map +1 -1
- package/dist/server/module-discovery.d.ts +11 -3
- package/dist/server/module-discovery.d.ts.map +1 -1
- package/dist/server/module-discovery.js +32 -18
- package/dist/server/module-discovery.js.map +1 -1
- package/dist/server/workspace-storage.sql +5 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +37 -34
- package/dist/service.js.map +1 -1
- package/migrations/016_selection_statements.sql +43 -0
- package/migrations/017_skills_module.sql +5 -0
- package/package.json +71 -72
- package/dist/core/EmissionHead.d.ts +0 -8
- package/dist/core/EmissionHead.d.ts.map +0 -1
- package/dist/core/EmissionHead.js +0 -29
- package/dist/core/EmissionHead.js.map +0 -1
- package/dist/core/operation-target-groups.d.ts +0 -3
- package/dist/core/operation-target-groups.d.ts.map +0 -1
- package/dist/core/operation-target-groups.js +0 -77
- package/dist/core/operation-target-groups.js.map +0 -1
- package/dist/digest/Digest.d.ts +0 -10
- package/dist/digest/Digest.d.ts.map +0 -1
- package/dist/digest/Digest.js +0 -252
- package/dist/digest/Digest.js.map +0 -1
- package/dist/digest/DigestEvidence.d.ts +0 -11
- package/dist/digest/DigestEvidence.d.ts.map +0 -1
- package/dist/digest/DigestEvidence.js +0 -66
- package/dist/digest/DigestEvidence.js.map +0 -1
- package/dist/digest/DigestRender.d.ts +0 -18
- package/dist/digest/DigestRender.d.ts.map +0 -1
- package/dist/digest/DigestRender.js +0 -1044
- package/dist/digest/DigestRender.js.map +0 -1
- package/dist/digest/DigestRequiem.d.ts +0 -13
- package/dist/digest/DigestRequiem.d.ts.map +0 -1
- package/dist/digest/DigestRequiem.js +0 -337
- package/dist/digest/DigestRequiem.js.map +0 -1
- package/dist/digest/digest-db.d.ts +0 -3
- package/dist/digest/digest-db.d.ts.map +0 -1
- package/dist/digest/digest-db.js +0 -68
- package/dist/digest/digest-db.js.map +0 -1
- package/dist/digest/digest-paths.d.ts +0 -6
- package/dist/digest/digest-paths.d.ts.map +0 -1
- package/dist/digest/digest-paths.js +0 -14
- package/dist/digest/digest-paths.js.map +0 -1
- package/dist/digest/digest-rows.d.ts +0 -346
- package/dist/digest/digest-rows.d.ts.map +0 -1
- package/dist/digest/digest-rows.js +0 -2
- package/dist/digest/digest-rows.js.map +0 -1
- package/dist/schemes/Skill.d.ts.map +0 -1
- package/dist/schemes/Skill.js.map +0 -1
- package/dist/server/DaemonModule.d.ts +0 -101
- package/dist/server/DaemonModule.d.ts.map +0 -1
- package/dist/server/DaemonModule.js +0 -2
- package/dist/server/DaemonModule.js.map +0 -1
- package/dist/server/SkillSource.d.ts +0 -37
- package/dist/server/SkillSource.d.ts.map +0 -1
- package/dist/server/SkillSource.js +0 -267
- package/dist/server/SkillSource.js.map +0 -1
- package/dist/server/SkillsFunctionality.d.ts +0 -45
- package/dist/server/SkillsFunctionality.d.ts.map +0 -1
- package/dist/server/SkillsFunctionality.js +0 -405
- package/dist/server/SkillsFunctionality.js.map +0 -1
- package/dist/server/skills-problems.d.ts +0 -8
- package/dist/server/skills-problems.d.ts.map +0 -1
- package/dist/server/skills-problems.js +0 -18
- package/dist/server/skills-problems.js.map +0 -1
- package/dist/share/Share.d.ts +0 -15
- package/dist/share/Share.d.ts.map +0 -1
- package/dist/share/Share.js +0 -106
- package/dist/share/Share.js.map +0 -1
- package/dist/share/share.sql +0 -6
- package/docs/skills.md +0 -73
- /package/dist/{digest → evidence}/digest.sql +0 -0
package/SPEC.md
CHANGED
|
@@ -18,7 +18,7 @@ Canonical contracts plurnk-service exposes, architecture it implements, promises
|
|
|
18
18
|
- [Proposals and client interactions](#proposal-proposals-and-client-interactions)
|
|
19
19
|
- [Stream Model](#stream-stream-model)
|
|
20
20
|
- [Storage Model](#storage-model)
|
|
21
|
-
- [
|
|
21
|
+
- [Extension composition](#core-extension-composition-extension-composition)
|
|
22
22
|
- [Bundled Set](#bundled-set-bundled-set)
|
|
23
23
|
- [Grammar Dependency](#grammar-dependency)
|
|
24
24
|
- [Operator Configuration](#operator-config-operator-configuration)
|
|
@@ -55,7 +55,7 @@ flowchart LR
|
|
|
55
55
|
| **workspace** | Core | Durable user-named shared world. Persists across workers and process restarts. Identity: `workspaces.id` + unique `workspaces.name`. |
|
|
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
|
-
| **turn** | Core | One durable, producer-neutral batch of ordered operations. A turn may be authored by a model, client,
|
|
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)`. |
|
|
59
59
|
| **model call** | Core/provider | One logical `provider.generate` invocation. Emission attempts and BARE inferences share this durable accounting owner; provider retries remain cardinal physical requests beneath it. Identity: `(turn_id, sequence)`. |
|
|
60
60
|
| **op** | Producer/core | One DSL operation a producer submits, parsed into a `PlurnkStatement`. Admission follows {§turn-ops-admission-path}. |
|
|
61
61
|
| **statement** | Model/core | A parsed op: the `PlurnkStatement` AST from `@plurnk/plurnk-contracts`. |
|
|
@@ -72,7 +72,7 @@ flowchart LR
|
|
|
72
72
|
|---|---|
|
|
73
73
|
| **entry** | The unit of canonical state. Identity: `(workspace_id, scheme, authority, pathname)` ({§entry-identity-no-null}). Holds one or more `channels` of content plus scheme-private `attributes`. |
|
|
74
74
|
| **channel** | A named content buffer on an entry. Examples: `body`, `stdout`, `stderr`, `headers`, `symbols`. Each channel has `content`, `mimetype`, curation `weight`, and lifecycle `state`. |
|
|
75
|
-
| **scheme** | An
|
|
75
|
+
| **scheme** | An addressable namespace and its handler. Built-ins include `worker`, `log`, `ops`, `reasoning`, and bare/file paths; discovered schemes and executor-runtime tags extend that set. Internal `exec` routes executions but is not an addressable model namespace. Consumption surface {§scheme-surface}; author contract: [plurnk-schemes](../plurnk-schemes/SPEC.md). |
|
|
76
76
|
| **mimetype** | A channel's content type. Drives the handler that produces the structural projections (`symbols`, `deepJson`, `deepXml`). Consumption surface {§mimetype}; author contract: [plurnk-mimetypes](../plurnk-mimetypes/SPEC.md). |
|
|
77
77
|
| **provider** | An LLM transport implementing the `@plurnk/plurnk-providers` `Provider` interface. Core supplies an assembled request and generation context; the provider owns endpoint adaptation and normalized response evidence. Consumption surface {§provider-surface}; author contract: [plurnk-providers](../plurnk-providers/SPEC.md). |
|
|
78
78
|
|
|
@@ -91,9 +91,9 @@ Independent axes on entries and channels. Confusion across them is a recurring s
|
|
|
91
91
|
|
|
92
92
|
| Term | Meaning |
|
|
93
93
|
|---|---|
|
|
94
|
-
| **writer** | The identity authoring a write. One of `model \| client \| _plurnk
|
|
94
|
+
| **writer** | The identity authoring a write. One of `model \| client \| _plurnk`. Carried on `ctx.writer` for schemes; engine enforces `manifest.writableBy`. |
|
|
95
95
|
| **origin** | Synonym for writer in log_entries (`log_entries.origin`). Synonym for writer. |
|
|
96
|
-
| **writable_by** | The set of writers a scheme accepts. Subset of `{model, client, _plurnk
|
|
96
|
+
| **writable_by** | The set of writers a scheme accepts. Subset of `{model, client, _plurnk}`; empty means no operation writes the scheme. Engine rejects writes outside the set with 403; the rejection is logged as the action-entry ({§subscriptions} action-entry-as-outcome). |
|
|
97
97
|
|
|
98
98
|
### Execution terms
|
|
99
99
|
|
|
@@ -133,7 +133,7 @@ package map. The default installed composition is specified in {§bundled-set}.
|
|
|
133
133
|
|
|
134
134
|
OpenTelemetry may observe PLURNK; it never becomes product state, failure transport, scheduler input, model teaching, or client protocol. Domain and client activity remain on AG-UI. Reusable packages depend on the OTel API only; the daemon constructs only the explicitly configured trace and metric providers. An unconfigured or standards-valid disabled process loads no SDK or exporter implementation and keeps the API's no-op behavior with bounded overhead. OTel Logs have no provider or initialization path.
|
|
135
135
|
|
|
136
|
-
Configuration uses the standard `OTEL_*` environment: `OTEL_TRACES_EXPORTER` / `OTEL_METRICS_EXPORTER` select `otlp` or `console` per signal (a missing or `none` value keeps that signal off; no SDK default selects an exporter), `OTEL_SERVICE_NAME` names the service (default `plurnk-service`), case-insensitive `true` in `OTEL_SDK_DISABLED` turns the boundary off, and OTLP exporters honor `OTEL_EXPORTER_OTLP_*`. An unknown exporter name makes observability unavailable with a configuration diagnostic ({§configuration-repair-path}); offline checking rejects the same input before loading an SDK. OTel Logs and direct draft semantic-convention use are excluded. HTTP spans carry only an AG-UI-owned bounded route class, never an input pathname or query. Spans otherwise carry high-cardinality identifiers; metric labels stay low-cardinality. Prompts, reasoning, file bodies, arbitrary URLs, secrets, and
|
|
136
|
+
Configuration uses the standard `OTEL_*` environment: `OTEL_TRACES_EXPORTER` / `OTEL_METRICS_EXPORTER` select `otlp` or `console` per signal (a missing or `none` value keeps that signal off; no SDK default selects an exporter), `OTEL_SERVICE_NAME` names the service (default `plurnk-service`), case-insensitive `true` in `OTEL_SDK_DISABLED` turns the boundary off, and OTLP exporters honor `OTEL_EXPORTER_OTLP_*`. An unknown exporter name makes observability unavailable with a configuration diagnostic ({§configuration-repair-path}); offline checking rejects the same input before loading an SDK. OTel Logs and direct draft semantic-convention use are excluded. HTTP spans carry only an AG-UI-owned bounded route class, never an input pathname or query. Spans otherwise carry high-cardinality identifiers; metric labels stay low-cardinality. Prompts, reasoning, file bodies, arbitrary URLs, secrets, and extension payloads are never recorded as attributes or metric values by default. Exporter failure cannot change product results or client lifecycle. Daemon, telemetry, and database teardown are independent reverse-ownership phases; every phase runs and aggregate failure preserves every cause.
|
|
137
137
|
|
|
138
138
|
§observability-genai-conventions **GenAI convention projection.** Provider
|
|
139
139
|
request spans follow the [GenAI registry at `c88d504`](https://github.com/open-telemetry/semantic-conventions-genai/tree/c88d504ab3d9879f8e50d3cc87e69775e11db234),
|
|
@@ -157,39 +157,39 @@ draft convention is projected.
|
|
|
157
157
|
The process and package map is ARCHITECTURE.md's; this package's AGENTS.md maps core's internal
|
|
158
158
|
owners. Capability-specific behavior remains with the owning plug point.
|
|
159
159
|
|
|
160
|
-
§service-worker-composition The service launcher and the live/demo
|
|
161
|
-
helper
|
|
162
|
-
|
|
160
|
+
§service-worker-composition The service launcher composes no module: it and the live/demo
|
|
161
|
+
workspace helper both discover AG-UI, A2A, MCP, Schedule and command hooks ({§module-discovery}). The
|
|
162
|
+
management families and readable reference documents are
|
|
163
163
|
present even with no enabled definitions. Workspace capability policy controls every actor's
|
|
164
164
|
surface; registering a family does not enable its definitions. The real-model
|
|
165
165
|
profile ({§operator-config-real-model-profile}) leaves ambient MCP attachments and
|
|
166
166
|
service schedules disabled by default; specimens may add their own through the
|
|
167
|
-
ordinary management surface.
|
|
168
|
-
|
|
167
|
+
ordinary management surface. The one listener is the launcher's ({§http-host}); the helper binds
|
|
168
|
+
none, so its daemon leaves out AG-UI ({§module-http-mounts}).
|
|
169
169
|
|
|
170
170
|
### §service-package-exports Package export surface
|
|
171
171
|
|
|
172
172
|
| Export path | Current contract |
|
|
173
173
|
|---------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
174
|
-
| `@plurnk/plurnk-service` |
|
|
175
|
-
| `@plurnk/plurnk-service/
|
|
174
|
+
| `@plurnk/plurnk-service` | Legacy internal exports listed below. It gains no new APIs and is not the client boundary. Extracted capabilities belong to their owning packages, without compatibility aliases. |
|
|
175
|
+
| `@plurnk/plurnk-service/evidence` | Canonical evidence reader consumed by the separate report package ({§digest-evidence-reader}). |
|
|
176
176
|
| `@plurnk/plurnk-service/package.json` | Supported package metadata surface. |
|
|
177
177
|
|
|
178
178
|
| Root exports | Names |
|
|
179
179
|
|--------------|-------|
|
|
180
|
-
| Runtime | `Daemon`, `Engine`, `EnvFlags`, `Exec`, `File`, `Log`, `Mimetypes`, `Mock`, `Paths`, `SchemeRegistry
|
|
180
|
+
| Runtime | `Daemon`, `Engine`, `EnvFlags`, `Exec`, `File`, `Log`, `Mimetypes`, `Mock`, `Paths`, `SchemeRegistry` |
|
|
181
181
|
| Types | `ChatMessage`, `EditResult`, `FlagDescriptor`, `MockAssistant`, `MockResponse`, `OpenFoldResult`, `ReadResult` |
|
|
182
182
|
|
|
183
183
|
New clients use AG-UI. A new library contract belongs in its owning package or
|
|
184
|
-
an explicitly specified subpath, not in the
|
|
184
|
+
an explicitly specified subpath, not in the legacy root barrel.
|
|
185
185
|
|
|
186
186
|
### §startup-admission Startup admission
|
|
187
187
|
|
|
188
188
|
```mermaid
|
|
189
189
|
flowchart LR
|
|
190
|
-
LISTENER["Bind
|
|
191
|
-
DB --> DAEMON["
|
|
192
|
-
DAEMON --> CLIENT["
|
|
190
|
+
LISTENER["Bind the daemon's listener<br/>unadmitted: HTTP 503"] --> DB["Acquire daemon lock<br/>and admit SQLite schema"]
|
|
191
|
+
DB --> DAEMON["Start the daemon:<br/>discover and start modules"]
|
|
192
|
+
DAEMON --> CLIENT["Admit the listener"]
|
|
193
193
|
CLIENT --> SELECT["Worker selects or first uses a model"]
|
|
194
194
|
SELECT --> PROVIDER["Construct and verify<br/>selected provider"]
|
|
195
195
|
LISTENER -. failure .-> FAIL["Fail startup<br/>durable state untouched"]
|
|
@@ -202,9 +202,9 @@ flowchart LR
|
|
|
202
202
|
({§http-host}) before creating, opening, replacing, rotating, migrating, or
|
|
203
203
|
otherwise mutating anything in the durable data directory. A process that loses
|
|
204
204
|
the listener race fails with the originating address error and byte-identical
|
|
205
|
-
durable storage. Core owns the socket continuously; it answers 503 until
|
|
206
|
-
|
|
207
|
-
ownership introduces neither traffic nor a close/rebind race.
|
|
205
|
+
durable storage. Core owns the socket continuously; it answers 503 until daemon
|
|
206
|
+
activation admits it after every module has started ({§module-http-mounts}), so
|
|
207
|
+
early ownership introduces neither traffic nor a close/rebind race.
|
|
208
208
|
|
|
209
209
|
§http-host **The daemon opens exactly one transport.** Core binds the HTTP
|
|
210
210
|
listener on `PLURNK_HOST:PLURNK_PORT` and offers it to every exterior adapter as
|
|
@@ -212,11 +212,11 @@ listener on `PLURNK_HOST:PLURNK_PORT` and offers it to every exterior adapter as
|
|
|
212
212
|
({§application-port}). A prefix is an absolute pathname. Each request goes to the
|
|
213
213
|
longest mounted prefix; a prefix claims itself and the subtree beneath it, never
|
|
214
214
|
a longer sibling name; `/` is the root and receives whatever nothing more
|
|
215
|
-
specific claimed. Until
|
|
215
|
+
specific claimed. Until daemon activation admits it the listener answers `503
|
|
216
216
|
service-starting` to every request: the service has not admitted its client
|
|
217
|
-
interface. Adapters
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
interface. Adapters claim their prefixes before setup and mount them at
|
|
218
|
+
`start()`, after durable lifecycle recovery ({§module-http-mounts}), and
|
|
219
|
+
none opens a socket of its own. The standards
|
|
220
220
|
address by URL, never by port (#641): AG-UI mounts `/` and `/agui`, A2A the
|
|
221
221
|
well-known card and its endpoint path, on the same address.
|
|
222
222
|
|
|
@@ -277,7 +277,7 @@ filter a row.
|
|
|
277
277
|
|
|
278
278
|
§actor-boundary-attached-functionality **Attachment selects a conversation,
|
|
279
279
|
not an environment owner.** Client management commands mutate workspace
|
|
280
|
-
Functionality ({§module-workspace-capabilities});
|
|
280
|
+
Functionality ({§module-workspace-capabilities}); runtimes, runtime
|
|
281
281
|
schemes, and tools resolve by `workspaceId`. Operations journal in the
|
|
282
282
|
submitting actor's `workerId` ({§connection-lifecycle}), which must belong to
|
|
283
283
|
the workspace. Runtime and policy resolution require no second worker identity.
|
|
@@ -363,7 +363,6 @@ narrow or omit the reference catalogs under {§capability-admission}.
|
|
|
363
363
|
| Project filesystem | `*` | File cap below; `project root member files` |
|
|
364
364
|
| Workspace entries | `worker:///*` | Markerless; `workspace knowledgebase entries` |
|
|
365
365
|
| Named scratch entries | `worker://<worker>/*` | Markerless; `worker knowledgebase entries` |
|
|
366
|
-
| The worker's own reasoning | `reasoning://<worker>/**` | Markerless; `this worker's reasoning, by loop and turn` |
|
|
367
366
|
|
|
368
367
|
Only the three namespace surveys carry asides; the other targets name
|
|
369
368
|
their surface. The word `skills` names Agent Skills and nothing else.
|
|
@@ -371,7 +370,7 @@ Catalogs select documents independently of their authored bodies; ordinary READ
|
|
|
371
370
|
supplies examples and complete instructions on demand. A shallow
|
|
372
371
|
result renders direct entries normally and every deeper first-segment directory
|
|
373
372
|
as an actionable `dir/**` summary with its recursive `items` and `tokens`;
|
|
374
|
-
|
|
373
|
+
runtime rows also carry the concise `{§scheme-catalog-aside}` that drives
|
|
375
374
|
on-demand capability discovery. Ordinary surveys use FIND without a scope
|
|
376
375
|
({§markerless-first-page}), whose range metadata reports the returned set against the
|
|
377
376
|
complete result total; only the small capability-reference surfaces
|
|
@@ -460,7 +459,7 @@ existing workspace worker in its own right.
|
|
|
460
459
|
|
|
461
460
|
§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 conversation binding. Inspection does not inject another log into a model's packet.
|
|
462
461
|
|
|
463
|
-
§machine-processes-worker-origin **A worker carries its actor.** Each worker records its `origin` — `model` (a conversation), `client` (a client-interface actor), or `_plurnk` (the runtime's self-hosting worker) — set once at creation and inherited by WORK/FORK from the parent. A turn's producer is independent: a
|
|
462
|
+
§machine-processes-worker-origin **A worker carries its actor.** Each worker records its `origin` — `model` (a conversation), `client` (a client-interface actor), or `_plurnk` (the runtime's self-hosting worker) — set once at creation and inherited by WORK/FORK from the parent. A turn's producer is independent: a client-produced program in a model worker still delegates model workers. `listWorkers` returns actor class without interpreting names; a retained worker's name is immutable ({§machine-processes-worker-is-its-log}).
|
|
464
463
|
|
|
465
464
|
§worker-provider-identity **A worker owns a durable provider identity distinct
|
|
466
465
|
from its database id.** Creation mints a globally unique, opaque 128-bit value;
|
|
@@ -914,12 +913,6 @@ move it. The digest reports, per loop, the claim time and how long after it the
|
|
|
914
913
|
first model turn started, so a stall between claim and inference (a heartbeat has
|
|
915
914
|
waited 7.5 h, #703) is a number rather than a gap.
|
|
916
915
|
|
|
917
|
-
§digest-storage **The digest states the file's health.** Beside the database path it
|
|
918
|
-
reports the file size, the free pages it holds, its `auto_vacuum` mode, and the six
|
|
919
|
-
largest tables and indexes by allocated bytes (`dbstat`), so growth is a number in
|
|
920
|
-
every digest (#764). The digest reads loops as stored, so it tolerates databases
|
|
921
|
-
missing later lifecycle columns.
|
|
922
|
-
|
|
923
916
|
§loop-execution-allowance **One task has one execution allowance.** The first
|
|
924
917
|
execution snapshots `PLURNK_SERVICE_LOOP_TIMEOUT` on the loop. Active segments
|
|
925
918
|
consume that allowance cumulatively, measured with a monotonic clock; waits and
|
|
@@ -1093,11 +1086,11 @@ boundary.
|
|
|
1093
1086
|
|
|
1094
1087
|
A turn is the durable container for one producer's ordered operations. Packet
|
|
1095
1088
|
and provider fields are optional evidence belonging only to model inference;
|
|
1096
|
-
their absence never makes a client
|
|
1089
|
+
their absence never makes a client or `_plurnk` turn exceptional.
|
|
1097
1090
|
|
|
1098
1091
|
| Field | Contract |
|
|
1099
1092
|
|---|---|
|
|
1100
|
-
| `producer` | Required actor class: `model`, `client`,
|
|
1093
|
+
| `producer` | Required actor class: `model`, `client`, or `_plurnk`. |
|
|
1101
1094
|
| `kind` | Required purpose: `inference`, `initialization`, `operation`, or `maintenance`. Model iff inference; initialization and maintenance require `_plurnk`. Producer and kind are immutable. A maintenance turn's successful rows are packet-suppressed — a receipt answers an asker, and maintenance has none ({§actor-boundary-doc-injection}). |
|
|
1102
1095
|
| `status`, `completed_at` | A new turn is open at status 102 with `completed_at=NULL`. Completion records the program outcome and timestamp; a completed 102 is distinct from an open 102. A successful administrative program completes at 200 without concluding its host model loop. |
|
|
1103
1096
|
| Operations | Ordered by `(turn_id, sequence)` on one exact worker/loop/turn chain. Each row's `origin` is the turn producer or `_plurnk` making a system observation; the observation does not impersonate the producer. |
|
|
@@ -1106,9 +1099,8 @@ their absence never makes a client, plugin, or `_plurnk` turn exceptional.
|
|
|
1106
1099
|
|
|
1107
1100
|
One lifecycle owner opens, optionally records inference evidence, and completes
|
|
1108
1101
|
every turn. Initialization, maintenance, client dispatch, and model
|
|
1109
|
-
inference use that same path
|
|
1110
|
-
|
|
1111
|
-
parallel record or lifecycle. Producer and kind never change. Process-restart
|
|
1102
|
+
inference use that same path; a new producer joins it without a parallel
|
|
1103
|
+
record or lifecycle. Producer and kind never change. Process-restart
|
|
1112
1104
|
recovery completes any turn whose producer vanished.
|
|
1113
1105
|
|
|
1114
1106
|
§turn-exception-outcome An exceptional inference exit completes every still-open
|
|
@@ -1122,7 +1114,7 @@ The turn owner propagates the original exception unchanged.
|
|
|
1122
1114
|
| An `AggregateError` combining cancellation with other failures | 500; cancellation does not conceal another failure. |
|
|
1123
1115
|
|
|
1124
1116
|
§turn-ops-admission-path **Source acquisition varies; admitted-turn execution does not.**
|
|
1125
|
-
A provider response, deterministic `_plurnk` program, or future client
|
|
1117
|
+
A provider response, deterministic `_plurnk` program, or future client
|
|
1126
1118
|
program crosses one admission boundary into the same executor. That executor
|
|
1127
1119
|
parses once, dispatches the admitted statements in order, records their ordinary
|
|
1128
1120
|
outcomes, and completes the turn from its lifecycle ruling. Exact source is retained before dispatch.
|
|
@@ -1333,7 +1325,11 @@ Provider interruption is owned by {§provider-interrupted-attempt}. Accepted sou
|
|
|
1333
1325
|
and positions remain exact; execution follows {§op-execution-order}. WAIT remains
|
|
1334
1326
|
optional, with no omission warning or invented operation ({§turn-shape}).
|
|
1335
1327
|
|
|
1336
|
-
|
|
1328
|
+
The parser compiles target groups ({§target-group}, {§safe-uri-target-groups}) into ordinary
|
|
1329
|
+
statements before model or client admission. Core does not reinterpret target syntax. Each
|
|
1330
|
+
admitted member receives its independent dispatch outcome and log row, in authored order under
|
|
1331
|
+
{§op-execution-order}; one member's runtime failure does not suppress later members. The original
|
|
1332
|
+
emission in `turn_sources` remains exact and unexpanded.
|
|
1337
1333
|
|
|
1338
1334
|
Core retries a rejected emission against the exact same packet beneath the same engine turn, up to `PLURNK_SERVICE_EMISSION_ATTEMPTS`. Rejected bytes never dispatch or reach the engine strike rail. Before each `generate`, Core opens one durable logical `inference_calls` row with its `model_calls` specialization and emission-specific `turn_attempts` admission row. A call that ends without response evidence leaves that admission row unclassified (`accepted IS NULL`) and does not consume the emission-attempt ceiling. Beneath the logical call, every provider observer invocation opens one cardinal `provider_requests` occurrence immediately before physical I/O and settles it as response or error. Adapter retries and capacity failover append requests in issue order; a response-less failure therefore remains an accounted occurrence rather than disappearing. Normalized response evidence is durable before parser classification and does not duplicate the separately owned accounting. The accepted exchange alone extends `turns.packet` with response evidence; every physical request remains in turn and loop accounting, while the context gauge reads the latest settled emission request on the latest turn. Digest exposes rejected response evidence as `<stem>.attemptNNN.rejected.*` and every physical request in its machine-readable ledger.
|
|
1339
1335
|
|
|
@@ -1371,10 +1367,10 @@ interrupted response evidence, Core stores it unaccepted without duplicating its
|
|
|
1371
1367
|
accounting. The failed turn still stores the exact request and never fabricates
|
|
1372
1368
|
an assistant or a zero-valued observation.
|
|
1373
1369
|
|
|
1374
|
-
### §attribution
|
|
1370
|
+
### §attribution Extension-authored attribution folksonomy
|
|
1375
1371
|
|
|
1376
|
-
|
|
1377
|
-
shared contract {§
|
|
1372
|
+
An extension may declare opaque attribution tags statically or at runtime under the
|
|
1373
|
+
shared contract {§extension-attribution}:
|
|
1378
1374
|
|
|
1379
1375
|
```jsonc
|
|
1380
1376
|
{ "plurnk": { "attribution": "@acme/widgets" } } // always-on string or string[]
|
|
@@ -1382,14 +1378,14 @@ shared contract {§plugin-attribution}:
|
|
|
1382
1378
|
|
|
1383
1379
|
| Stage | Contract |
|
|
1384
1380
|
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1385
|
-
| Collection | Immediately before each emission attempt, Core pulls the admitted scheme, executor, loaded mimetype-handler, and selected provider sources. A BARE call pulls only its selected provider source because it admits no other
|
|
1381
|
+
| Collection | Immediately before each emission attempt, Core pulls the admitted scheme, executor, loaded mimetype-handler, and selected provider sources. A BARE call pulls only its selected provider source because it admits no other extension. |
|
|
1386
1382
|
| Composition | Core flattens, deduplicates, and sorts the tags. The resulting non-empty array rides `generate({ attributions })`; an empty set omits that provider field. |
|
|
1387
|
-
| Meaning | Core neither verifies nor infers contribution. Tags are
|
|
1383
|
+
| Meaning | Core neither verifies nor infers contribution. Tags are extension-authored folksonomy for telemetry, optimization, attribution, or downstream rules. The `@plurnk/` reservation is the only namespace policy ({§extension-attribution}). |
|
|
1388
1384
|
| Request evidence | The stored request packet carries the exact set most recently forwarded for that turn. Every generation-kind `inference_calls` row carries that call's exact set, including response-less failures. |
|
|
1389
1385
|
| Derived reporting | Turn, loop, digest, and client views project the recorded sets. `loop/terminated.attributions` is their deduplicated sorted union and remains separate from provider usage and charge evidence. |
|
|
1390
1386
|
|
|
1391
|
-
Runtime
|
|
1392
|
-
failure is an internal
|
|
1387
|
+
Runtime `attributions` functions are synchronous and receive only the attempt coordinates.
|
|
1388
|
+
A function's failure is an internal extension-contract failure; Core does not silently discard
|
|
1393
1389
|
it or reinterpret a malformed tag list.
|
|
1394
1390
|
|
|
1395
1391
|
§client-metadata **The workspace records which frontend opened it.** A frontend self-identifies (e.g. `@plurnk/plurnk-tui/1.4.0`) at `workspace.create({ settings: { client } })` and the daemon stores it with the workspace. It is validated on write, never forwarded to a provider, and never model-facing. Workspace-stable and self-reported — distinct from attribution's install-grounded tags — and omitted when unset.
|
|
@@ -1402,7 +1398,7 @@ it or reinterpret a malformed tag list.
|
|
|
1402
1398
|
service-side caching, per-loop selection, context-cap handling, and admission
|
|
1403
1399
|
of an operator's grammar. Cataloged providers use Models.dev metadata and official AI SDK
|
|
1404
1400
|
bindings; an operator declaration covers an uncataloged compatible endpoint;
|
|
1405
|
-
|
|
1401
|
+
a provider extension is the last seam for a new protocol. Cache identity includes
|
|
1406
1402
|
the alias, wire route, and complete provider-knob projection; a registered
|
|
1407
1403
|
preconstructed handle occupies that same identity and cannot shadow changed
|
|
1408
1404
|
tuning.
|
|
@@ -1445,7 +1441,7 @@ First path segment = provider name; rest = provider-native model id.
|
|
|
1445
1441
|
|
|
1446
1442
|
### Mock provider (sibling fixture)
|
|
1447
1443
|
|
|
1448
|
-
§mock-provider-mock-fixture `Mock` (exported from `@plurnk/plurnk-providers`) — intg fixture + reference implementation. `{ contextWindow, responses }` constructor; `generate` shifts from the queue. `MockResponse.assistant.ops?: PlurnkStatement[]` is a pre-parsed escape hatch the engine consumes directly when present; production providers don't expose this — and being a
|
|
1444
|
+
§mock-provider-mock-fixture `Mock` (exported from `@plurnk/plurnk-providers`) — intg fixture + reference implementation. `{ contextWindow, responses }` constructor; `generate` shifts from the queue. `MockResponse.assistant.ops?: PlurnkStatement[]` is a pre-parsed escape hatch the engine consumes directly when present; production providers don't expose this — and being a package export, this contract has no service-side `§`-ref.
|
|
1449
1445
|
|
|
1450
1446
|
---
|
|
1451
1447
|
|
|
@@ -1528,7 +1524,7 @@ Folders and globs select members in those same filesystem coordinates. Parent-di
|
|
|
1528
1524
|
|
|
1529
1525
|
### File scheme: creation and misses
|
|
1530
1526
|
|
|
1531
|
-
§fs-write-surface **The write surface — one admission and incorporation path.** Existing writes remain membership-gated. An absent path additionally crosses the effective creation scope and the complete constraint/Git policy before a proposal is issued. EDIT, COPY destinations, and MOVE destinations use this same path regardless of whether the producer is a model, client,
|
|
1527
|
+
§fs-write-surface **The write surface — one admission and incorporation path.** Existing writes remain membership-gated. An absent path additionally crosses the effective creation scope and the complete constraint/Git policy before a proposal is issued. EDIT, COPY destinations, and MOVE destinations use this same path regardless of whether the producer is a model, client, or `_plurnk`. A COPY or MOVE destination scope on an absent channel resolves against its empty pre-mutation value under {§empty-mutation-scope}; a valid scope creates the channel with the selected source as its complete value. A coordinate outside that empty value is 416. Binary scopes remain numeric byte positions or ranges under {§binary-parity}.
|
|
1532
1528
|
|
|
1533
1529
|
| Case | Required admission | Accepted result |
|
|
1534
1530
|
|------|--------------------|-----------------|
|
|
@@ -2425,28 +2421,29 @@ like any other row.
|
|
|
2425
2421
|
| When | An inference turn that admitted at least one content statement. Reasoning-only turns, including initialization ({§worker-initialization-entry}), a programmatic batch, an empty turn ({§empty-turn}), a client operation and a rejected attempt ({§rejected-emission-entry}) announce nothing. |
|
|
2426
2422
|
| Place | After the turn's inputs (arrivals, deltas, open-path READs) and before its reasoning NOTEs and operations, written after the selection snapshot ({§turn-ops-selection-snapshot}): the emission sits between what the worker had seen and what it caused. |
|
|
2427
2423
|
| Row | A `_plurnk` READ of the turn's own source, `ops://<worker>/L/T`, with `attrs.kind="emission"` and the canonical leaf `/emission`: `### log:///L/T/S/emission → ops://<worker>/L/T · N`. It renders its author, the turn's producer, as `origin`, so a model's row carries none. It is no operation: no receipt, tool call or strike, and outside the op mix. |
|
|
2428
|
-
| Body | Frozen at announcement: the canonical rendering ({§statement-rendering}) of admitted content statements, each
|
|
2429
|
-
|
|
|
2424
|
+
| Body | Frozen at announcement: the canonical rendering ({§statement-rendering}) of the admitted content statements, each whole in a closed fence. All heading operands, scopes, metadata, patterns and asides remain. Free text and unadmitted forms are absent; a recovered native call ({§native-tool-calls}) appears as the operation it was read as; an operation whose receipt failed stays. Reasoning operations retain their own source and normal receipts, never an assistant-content copy. No body text is inspected for nested operations. |
|
|
2425
|
+
| Wire | Bodies are logged, never replayed (#1018). The wire shows a statement with a body as its heading and an empty closer, and one without a body as its heading closed on the same line, so the shape says whether a body was left out. A NOTE or WAIT, and a parameterless KILL or SEND, is not replayed at all, since its own row shows it whole ({§body-projection}); an emission of only those delivers nothing, its row stands, and no assistant message follows it ({§packet-wire-envelope}). Dispatch and the immutable `ops://` source keep complete bodies ({§turn-source-resources}); an explicit READ returns them, as it returns a receipt. |
|
|
2430
2426
|
| Stability | The projection is fixed from its first appearance, never aged or resized under budget pressure. Already frozen announcements and historical request captures are not rewritten. |
|
|
2431
2427
|
| Presentation | Born folded: the record shows its header, and its body follows the record as the worker's assistant message. |
|
|
2432
|
-
| Accounting | `tokens` charges the record and the emission the wire delivers,
|
|
2428
|
+
| Accounting | `tokens` charges the record and the emission the wire delivers, never what the wire leaves out ({§packet-token-accounting}). An explicit source READ has its own ordinary charge. |
|
|
2433
2429
|
| Curation | Curated whole ({§log-kill-scope}): KILL retires it, and so does a scope covering every line (`<1,-1>`); on its exact coordinate a narrower scope is 422 `emission-curated-whole`, and a sweep whose scope would only trim it leaves it intact. |
|
|
2434
2430
|
| Schema | Migration 12 admits `kind="emission"` only on this shape: one per turn, the turn's newest row when written, frozen, and curated whole. A database from before version 12 keeps its rows and gains no announcement. FORK copies it with the inherited turns, still naming its writer. |
|
|
2435
|
-
| Echoes | A worker that repeats the heading in its own text is tolerated ({§fabricated-log-entry}); the digest counts the echoes.
|
|
2431
|
+
| Echoes | A worker that repeats the heading in its own text is tolerated ({§fabricated-log-entry}); the digest counts the echoes. |
|
|
2436
2432
|
|
|
2437
2433
|
### §reasoning-row The reasoning row
|
|
2438
2434
|
|
|
2439
2435
|
The model's memory of its own reasoning, behind `PLURNK_SERVICE_REASONING_ROWS` (default `1`):
|
|
2440
2436
|
when it is `1`, every model turn that reasoned lands its reasoning as one row of its
|
|
2441
2437
|
own, `log:///<loop>/<turn>/<sequence>/reasoning → reasoning://<worker>/<loop>/<turn>`, the harness's
|
|
2442
|
-
READ of the turn's reasoning source, immediately before the turn's emission row
|
|
2438
|
+
READ of the turn's reasoning source, immediately before the turn's emission row (or its first
|
|
2439
|
+
operation or diagnostic when there is no content emission), so the transcript
|
|
2443
2440
|
reads what the model thought and then what it emitted, and the assistant message that follows stays
|
|
2444
2441
|
the canonical program ({§emission-row}, {§packet-wire-envelope}).
|
|
2445
2442
|
|
|
2446
2443
|
| Concern | Rule |
|
|
2447
2444
|
|---|---|
|
|
2448
|
-
| Room |
|
|
2449
|
-
| Body | The model's own text when it fits the row's page — `PLURNK_SERVICE_REASONING_TRAILING_LINES` lines, unset meaning the shared `PLURNK_SERVICE_PREVIEW_LINES`, within `PLURNK_SERVICE_PREVIEW_CHARS` — and otherwise its **last page
|
|
2445
|
+
| Room | Admission occurs after all mandatory turn rows, including the emission and diagnostics, using the remaining room under {§context-fit}. Its earlier chronological coordinate is reserved without inserting a placeholder; if it does not fit, that coordinate remains unused. Nothing else changes: no partial preview, refusal, or other row touched. Reasoning-only and empty model turns follow the same rule; content operations are not required. |
|
|
2446
|
+
| Body | The model's own text when it fits the row's page — `PLURNK_SERVICE_REASONING_TRAILING_LINES` lines, unset meaning the shared `PLURNK_SERVICE_PREVIEW_LINES`, within `PLURNK_SERVICE_PREVIEW_CHARS` — and otherwise its **last page**. Keep complete final lines where possible; if the last line alone exceeds the character bound, select its suffix with the ordinary exact column scope. Unicode code points count once and CRLF is one indivisible separator, as in {§body-projection}. The statement carries the scope it took and the receipt its `range` ({§packet-extent-metadata}); the complete reasoning stays readable at its address by any scope ({§turn-source-resources}). |
|
|
2450
2447
|
| Weight | Charged like any row, visible in the gauge and its `largest` ({§context-gauge}). |
|
|
2451
2448
|
| Curation | The verbs alone: a KILL retires it like any row ({§context-verbs}); the daemon reorders nothing and un-bodies nothing on its account. |
|
|
2452
2449
|
| Absence | Means no room or no reasoning; the model tells them apart by reading `reasoning://` for the turn. |
|
|
@@ -2456,7 +2453,7 @@ the canonical program ({§emission-row}, {§packet-wire-envelope}).
|
|
|
2456
2453
|
| Surface | Contract |
|
|
2457
2454
|
|---|---|
|
|
2458
2455
|
| Identity | `ops://<worker>/<loop>/<turn>`, `reasoning://<worker>/<loop>/<turn>`, and `note://<worker>/<loop>/<turn>/<item>` name a worker in the current workspace and its durable coordinates. A note's item is its dispatched NOTE ordinal. The `outside` source ({§outside-text}) has no address: no `outside://` scheme exists, and it is reached only through `outside/event`, FORK and the digest. The worker authority is required and case-sensitive; userinfo, ports, and queries are invalid. Source identity never depends on the reading worker. `log:///` remains local; READ, FIND and KILL reject log authorities, userinfo, ports and queries with 400, never substitute the caller's log. |
|
|
2459
|
-
| Source | `ops` is exact admitted `text/vnd.plurnk`, and its turn's emission row carries
|
|
2456
|
+
| Source | `ops` is exact admitted `text/vnd.plurnk`, and its turn's emission row carries its canonical projection ({§emission-row}); `reasoning` is `text/plain` containing the selected original provider reasoning or a non-model producer's authored rationale. Producer identity comes from the owning turn; a harness rationale is not provider evidence. The turn decides existence and the source decides content: a turn that exists but has no source of that kind reads as the ordinary empty resource (204, empty body), never a fabricated one; a worker or turn that does not exist is 404. |
|
|
2460
2457
|
| Notes | Each dispatched NOTE stores its exact literal body as an immutable `text/plain` source and returns its worker-qualified address. There may be multiple notes in a turn, from reasoning, content, or another producer. A missing note is 404, not an empty invented note. Sharing its URI uses ordinary SEND; the receiver deliberately READs it. NOTE itself sends no ambient update. |
|
|
2461
2458
|
| Retention | One ops source, one reasoning source and one outside source per turn; one note source per NOTE ordinal. An optional inference-call link records provenance. Source removal follows deletion of its owning turn, never log curation. |
|
|
2462
2459
|
| Operations | Ordinary scoped READ, FIND, content search and COPY from any named worker's source within the workspace. FIND accepts authority and path patterns, retaining complete worker-qualified identities in results and folder selectors. READ returns data and never executes it. Sources are read-only for every actor and have no edit hashes. |
|
|
@@ -2467,7 +2464,7 @@ the canonical program ({§emission-row}, {§packet-wire-envelope}).
|
|
|
2467
2464
|
§rejected-emission-entry A rejected provider response is not `turnOps`: it never became an admitted turn program, and no emission row announces it ({§emission-row}). The one bounded invalid-emission recovery item under {§emission-admission} has `attrs.kind="emissionAttempt"`, `origin="model"`, the canonical model-facing `/attempt` leaf, and the exact latest rejected response. The packet does not duplicate that identity as `kind` metadata. It is born durably body-suppressed and projected visibly only in the informed recovery packet; every other rejected attempt remains forensic-only.
|
|
2468
2465
|
|
|
2469
2466
|
- §log-coordinate-hierarchy **Log coordinates are a hierarchical prefix; the trailing slash is optional** — a coordinate is `loop/turn/sequence`, and a PARTIAL coordinate selects its descendants: `log:///1` = loop 1's rows, `log:///1/2` = turn 1/2's rows, `log:///1/2/3` = the one row. A full coordinate is always three parts, so a one- or two-part path is unambiguously a prefix — the trailing slash is an optional alias (`log:///1/2` ≡ `log:///1/2/`), uniform with ```` ```READ (worker:///docs/) ````. A complete `[start-end]` segment in any numeric coordinate slot selects that inclusive decimal interval; brackets elsewhere retain ordinary path-glob meaning. Every rendered row appends one canonical model-facing leaf: the native operation name or invoked executor name, `/attempt` for a rejected emission, `/emission` for an admitted one's announcement ({§emission-row}). An executor leaf is derived from the durable submitted statement (its `runtime`), never an internal dispatch type or the current tool registry. Digits and punctuation in executor names remain part of the leaf. The leaf names identity rather than adding a resource level. Exact consumers tolerate the unsuffixed three-part shorthand; when supplied, the case-insensitive leaf is authoritative and a disagreement resolves 404. READ anchors use the canonical suffixed identity even when addressed by shorthand. Typed entry materialization therefore resolves as `/READ` while retaining its durable `EDIT` event ({§exec-entry-sink}). `log:///1/2/*` still selects the turn's item rows, while `log:///**/READ`, `log:///**/python3`, `log:///**/attempt`, and `log:///**/emission` deliberately filter canonical leaves. Executor outputs instead use workspace-wide claims such as `sh:///ab3d5678#stdout` ({§execution-output-identity}); their source operation has log coordinates, but resource lifetime and identity are independent of that observation. Error pointers, Problem instances, source attribution, and search use this same identity; client stream coordinates retain the numeric triple. Within a turn, sequence is arrival order. Inbound SEND rows publish before the program runs ({§message-arrival}); a turn receiving messages holds the first at `log:///L/T/1/SEND`, followed by further arrivals oldest first, then its emission's announcement, then the model's operations ({§packet-current-turn} names `L/T`).
|
|
2470
|
-
- §log-near-miss **A log miss beside rows that exist names them.** A READ, FIND or KILL of an exact coordinate that names no row carries a recovery from the worker's own active rows: the row at that coordinate under its own leaf (``
|
|
2467
|
+
- §log-near-miss **A log miss beside rows that exist names them.** A READ, FIND or KILL of an exact coordinate that names no row carries a recovery from the worker's own active rows: the turn's rows carrying the leaf written come first, since the leaf is what the model asked for and the sequence its guess, followed by the row at that coordinate under its own leaf (`` Turn 1/44's reasoning is `log:///1/44/2/reasoning`; the entry at log:///1/44/1 is `log:///1/44/1/READ`. ``); with no row of that leaf, the row at the coordinate alone (`` The entry at log:///1/25/8 is `log:///1/25/8/sh`. ``), else the turn's rows, at most six named, else the loop's latest turn. A coordinate in a loop with no rows carries none. Recorded misses were near misses every time: a READ of `1/25/8/READ` when the row was `sh`, an EDIT one sequence off, and a KILL under the 413 that must curate (#1005).
|
|
2471
2468
|
- §log-curation-folder-idiom **Log curation speaks the folder idiom; a zero-match sweep is a no-op success** — KILL takes a concrete coordinate or a path-glob, and a **trailing slash or a partial coordinate means "the contents"** ({§log-coordinate-hierarchy}), like a folder-scoped FIND: ```` ```KILL (log:///1/2) <1,-1> ```` suppresses turn 1/2's bodies and retires its emission ({§emission-row}). A **well-formed selection that matches nothing is 204 with `matched: 0`**; a successful sweep's rx carries `matched: N`. Parameterless KILL instead requests completion ({§kill-conclusion}).
|
|
2472
2469
|
- §log-curation-set-selection **Row selection and body scope are independent** — target/glob and an optional heading pattern (```` ```KILL (log:///**) [{"pattern": "~stale"}] ````, every dialect a FIND over rows accepts) compose by intersection into the affected row set. An optional `<L>` or `<SL,EL>` then intersects each selected canonical body; it never paginates or changes the selected set. An emission row is curated whole instead: the scope retires it when it covers every line and otherwise leaves it ({§emission-row}). Thus ```` ```KILL (log:///**/READ) <17,-1> ```` may change long READs and no-op on short ones while reporting every selected row in `matched`.
|
|
2473
2470
|
|
|
@@ -2687,12 +2684,12 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2687
2684
|
|
|
2688
2685
|
### §find FIND
|
|
2689
2686
|
|
|
2690
|
-
- §log-uniform-query **Log speaks the universal query contract** — ```` ```FIND (log://…) ```` works like every scheme's FIND. Candidates are worker rows scoped by the coordinate hierarchy ({§log-coordinate-hierarchy}) and projected exactly as READ shows them. Content dialects use `Matcher.matchCandidates`; `~` full-text and `&graph` use the same persistent derivation artifacts and candidate rankers as entries. Broad results are one-channel catalog groups whose `[0].path` is `log:///loop/turn/seq/OP`; exact matcher results are flat locations ({§find-result-projection}). Log remains the core event ledger rather than duplicating rows into `entries`; its core-private storage adapter supplies one complete channel representation to the same READ projector. That adapter is not
|
|
2687
|
+
- §log-uniform-query **Log speaks the universal query contract** — ```` ```FIND (log://…) ```` works like every scheme's FIND. Candidates are worker rows scoped by the coordinate hierarchy ({§log-coordinate-hierarchy}) and projected exactly as READ shows them. Content dialects use `Matcher.matchCandidates`; `~` full-text and `&graph` use the same persistent derivation artifacts and candidate rankers as entries. Broad results are one-channel catalog groups whose `[0].path` is `log:///loop/turn/seq/OP`; exact matcher results are flat locations ({§find-result-projection}). Log remains the core event ledger rather than duplicating rows into `entries`; its core-private storage adapter supplies one complete channel representation to the same READ projector. That adapter is not an extension seam and grants no protocol scheme an alternate READ path.
|
|
2691
2688
|
- §find-source-agnostic **The content matcher is source-agnostic** — `Matcher.matchCandidates(body, candidates, mimetypes)` applies a content matcher (regex/jsonpath/xpath/glob) to candidates from ANY source, keyed by the caller's own identity (a pathname for entries, a `loop/turn/seq` coordinate for log). The matcher never cares what table the content came from, so FIND works uniformly across schemes by construction: `EntryFind` and `Log.find` run the one shared primitive rather than re-implementing it per scheme. Log stays its own event stream, but its rows are candidates the shared matcher covers like any entry's content.
|
|
2692
2689
|
- §find-line-anchors **A FIND regex anchors each line**, as READ, EDIT and KILL do ({§read-pattern}, {§edit-pattern}): `^` and `$` are a line's ends in every FIND content match — over entries, log rows, turn sources and a binary channel's bytes — so ```` ```FIND (django/urls/resolvers.py) /^from|^import/ ```` locates the same import lines a READ with that pattern shows, never a false 204.
|
|
2693
2690
|
- §find-candidate-containment **One candidate's crash is that candidate's problem** — arbitrary member content can crash a mimetype handler mid-match (an unbalanced template partial crashed Readability and killed a 1,916-file FIND as a blank 500, #449). `Matcher.matchCandidates` contains a per-candidate handler throw: the candidate drops out exactly like unsupported content, the cause goes to daemon stderr, and only a FIND whose every candidate crashed reports a 415 whose Problem names the first crashing member and handler. The operation's other candidates always answer.
|
|
2694
2691
|
|
|
2695
|
-
- §find-scope-prefix-filter Filters entries within scope. A **bare** path is the exact entry unless the file scheme resolves a directory under {§file-find-directory}; an explicit **shell glob**, classified once by {§path-glob}, expands to a scope. Path globs use segment semantics: `*` and `?` never cross `/`; `**` does — in every spelling: a `**` glued to a name (`**.go`, `src/**.ts`) is matched as `**/*.go` / `src/**/*.ts`, never demoted to a one-level `*` the way a native matcher reads it. Terminal `*` and `**` are structural catalog selectors and include dot-prefixed entries, so a complete map does not hide `.env.defaults` or `.github`; richer patterns retain native shell behavior. SQLite prefix queries may reduce the candidate set but never decide the match. A trailing slash is a recursive FIND scope only for a scheme whose manifest declares `folderScopes: true`; otherwise it is ordinary resource syntax. This is an explicit
|
|
2692
|
+
- §find-scope-prefix-filter Filters entries within scope. A **bare** path is the exact entry unless the file scheme resolves a directory under {§file-find-directory}; an explicit **shell glob**, classified once by {§path-glob}, expands to a scope. Path globs use segment semantics: `*` and `?` never cross `/`; `**` does — in every spelling: a `**` glued to a name (`**.go`, `src/**.ts`) is matched as `**/*.go` / `src/**/*.ts`, never demoted to a one-level `*` the way a native matcher reads it. Terminal `*` and `**` are structural catalog selectors and include dot-prefixed entries, so a complete map does not hide `.env.defaults` or `.github`; richer patterns retain native shell behavior. SQLite prefix queries may reduce the candidate set but never decide the match. A trailing slash is a recursive FIND scope only for a scheme whose manifest declares `folderScopes: true`; otherwise it is ordinary resource syntax. This is an explicit extension contract, never inferred from URL punctuation.
|
|
2696
2693
|
|
|
2697
2694
|
Resource-authority globs select authorities independently of the path scope.
|
|
2698
2695
|
Matching resources retain their full addresses through pattern matching,
|
|
@@ -2742,7 +2739,7 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2742
2739
|
derivation's `{§mimetype-summary}`. Prose is clipped to at most `PLURNK_SERVICE_CATALOG_SUMMARY_CHARS` Unicode
|
|
2743
2740
|
code points including a visible terminal ellipsis, so a row stays one line
|
|
2744
2741
|
of orientation; an invocation-form witness — a summary that is one fenced
|
|
2745
|
-
operation, the shape
|
|
2742
|
+
operation, the shape a runtime's tool summary takes
|
|
2746
2743
|
({§tools-resource-materialization}) — is shown whole, every tool named,
|
|
2747
2744
|
because the discovery row exists so the model can invoke without a READ and
|
|
2748
2745
|
a menu that is cut is no menu. Absent metadata is omitted.
|
|
@@ -2968,7 +2965,7 @@ of which Worker launched it ({§execution-output-identity}).
|
|
|
2968
2965
|
| 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. |
|
|
2969
2966
|
| Settlement or teardown | Retire and abort input immediately when the execution settles or is cancelled. Existing stream completion and worker wake mechanics remain the only completion path. |
|
|
2970
2967
|
|
|
2971
|
-
|
|
2968
|
+
No operation writes a stored runtime entry: its scheme's `writableBy` is empty, and the execution writes its own streams. Input and termination are
|
|
2972
2969
|
control capabilities, not exceptions granting write access to stdout/resources.
|
|
2973
2970
|
|
|
2974
2971
|
### §exec Executions
|
|
@@ -3345,7 +3342,7 @@ body prefixes.
|
|
|
3345
3342
|
wholesale ({§log-sensitive-request-evidence}); the spawn's record names each such value's
|
|
3346
3343
|
provenance as the modifier's.
|
|
3347
3344
|
- §exec-hold-until-concluded **The turn-hold exception** — for runtimes in `PLURNK_SERVICE_EXEC_HOLD` (a decision-table env), an in-flight stream **pauses the cycle**: the next packet does not assemble until the stream concludes, so the model never burns a turn asking "are we there yet" about a result the engine controls end-to-end. This exception is limited to seconds-bounded runtimes whose final result the engine controls end-to-end. Bounded by `PLURNK_SERVICE_EXEC_HOLD_MS` and **fail-open**: at the cap the standard cycle resumes untouched (waits, wakes, polls). Zero grammar or teaching surface — the model emits an executor fence, optionally followed by WAIT; the wake-shaped world simply arrives one packet sooner. It extends selected runtimes beyond the ordinary {§worker-optimistic-settlement} cap before the next packet assembles. A bare entry holds ALL of a runtime's spawns; a `<runtime>:<effect>` suffix (`github:read`) holds only that effect-class — an MCP server is one runtime whose tools split (a `read` `get_issue` is instant; a `host` `run_migration` is a slow mutation), so an operator opts the known-fast read-class in without parking on the mutation. Conservative stays default: an arbitrary third-party server's latency never parks the engine unless a suffix opts a class in.
|
|
3348
|
-
- §exec-entry-sink **The entry() sink** implements {§executor-entry-sink} over ordinary scheme-owned entries. Core owns allocation, materialization, and persistence; executors receive only the returned resource address. Web acquisition and materialization are the `https` handler's {§web-materialization-contract}, reached through the scheme registry; core names no
|
|
3345
|
+
- §exec-entry-sink **The entry() sink** implements {§executor-entry-sink} over ordinary scheme-owned entries. Core owns allocation, materialization, and persistence; executors receive only the returned resource address. Web acquisition and materialization are the `https` handler's {§web-materialization-contract}, reached through the scheme registry; core names no extension package.
|
|
3349
3346
|
|
|
3350
3347
|
| Input / effect | Consumer behavior |
|
|
3351
3348
|
| --- | --- |
|
|
@@ -3353,7 +3350,7 @@ body prefixes.
|
|
|
3353
3350
|
| Null path + supplied content | Publish beneath the invocation's `resources/` using {§resource-publication-names}, owned by the calling Worker. |
|
|
3354
3351
|
| Supplied bytes | Retain the original bytes and declared mimetype in an ordinary channel ({§binary-parity}). |
|
|
3355
3352
|
| Supplied text | Preserve text resources; HTTP/HTML materialization retains source and derived channels under {§html-materialization}. |
|
|
3356
|
-
| Null content | Acquire an HTTP(S) resource through the checked WebFetcher, using the same configured materializers as exact HTTP acquisition ({§http-materializer-
|
|
3353
|
+
| Null content | Acquire an HTTP(S) resource through the checked WebFetcher, using the same configured materializers as exact HTTP acquisition ({§http-materializer-extensions}). |
|
|
3357
3354
|
| Durable evidence | One typed EDIT event in the runtime actor, with the calling Worker as causal source. Binary evidence describes the resource; its complete bytes live in the resource channel. |
|
|
3358
3355
|
| Model orientation | The executor includes returned addresses in its result. Publication does not independently wake inference or broadcast an observer row ({§env-delta-entry-materialization}). READ controls content acquisition and native delivery. |
|
|
3359
3356
|
|
|
@@ -3538,7 +3535,7 @@ Capability admission precedes this decision, so proposal disposition cannot gran
|
|
|
3538
3535
|
|
|
3539
3536
|
### §subscriptions Subscriptions
|
|
3540
3537
|
|
|
3541
|
-
§subscriptions-subscription-registry-routes-cancellation READ on a streaming scheme is a subscription, not a one-shot. The scheme establishes its protocol-specific acquisition boundary, returns `102 Processing`, and stays alive through the `StreamSubscription` returned by `subscriptions.open()`. The service commits that initial operation result normally; later chunk and terminal work cannot rewrite it. Durable terminal truth lives on the subscription and its channels. The service records durable subscription identity and metadata in SQLite and retains the callable `SubscriptionHandle` only in its process-local live registry. Worker cancellation, turn-scoped reap, and shutdown all route through that one live registry; no handler-specific cancellation hook or database access is part of the
|
|
3538
|
+
§subscriptions-subscription-registry-routes-cancellation READ on a streaming scheme is a subscription, not a one-shot. The scheme establishes its protocol-specific acquisition boundary, returns `102 Processing`, and stays alive through the `StreamSubscription` returned by `subscriptions.open()`. The service commits that initial operation result normally; later chunk and terminal work cannot rewrite it. Durable terminal truth lives on the subscription and its channels. The service records durable subscription identity and metadata in SQLite and retains the callable `SubscriptionHandle` only in its process-local live registry. Worker cancellation, turn-scoped reap, and shutdown all route through that one live registry; no handler-specific cancellation hook or database access is part of the extension contract.
|
|
3542
3539
|
|
|
3543
3540
|
The durable row is lifecycle evidence and the lookup key, not a serialized callback. `subscriptions.open()` establishes both halves before yielding a composed `StreamSubscription`: an `AbortSignal` whose fused `notifyChunk` and terminal `close` methods are safe to retain without the operation's general `SchemeCtx`. `close(result, summary?, channelResults?)` validates one universal terminal producer result plus exact named channel overrides. One SQLite transition closes the subscription and installs each channel's terminal `producerResult`; its lifecycle state derives from that result. The transition then wakes the worker when appropriate and unregisters the live handle. `close_status` is a constrained relational projection of `close_result.status`, never an independent result, while `channel_results` preserves historical overrides after a later subscription replaces the channel's current evidence. A durable open row without a live handle is an explicit lifecycle failure, never a fabricated cancellation success. Channel state ({§channel-state}) + log entries ({§no-chunk-rows}) carry lifecycle.
|
|
3544
3541
|
|
|
@@ -3559,7 +3556,7 @@ the producer's already obtained outcome into a fictitious cancellation result.
|
|
|
3559
3556
|
At process restart every still-open row is necessarily missing its callable owner. Boot
|
|
3560
3557
|
settles it as interruption (`500`) and errors active channels before evaluating parked
|
|
3561
3558
|
loops ({§worker-lifecycle-restart-recovery}); it never reports cancellation (`499`) or
|
|
3562
|
-
pretends to reconstruct an opaque
|
|
3559
|
+
pretends to reconstruct an opaque extension connection.
|
|
3563
3560
|
|
|
3564
3561
|
§subscriptions-causal-resource A subscription's causal Worker belongs to the
|
|
3565
3562
|
entry's workspace. The active entry has
|
|
@@ -3645,7 +3642,7 @@ No generator. SQLite-optimal: STRICT (3.37+), `INTEGER PRIMARY KEY` aliasing, ex
|
|
|
3645
3642
|
- Tokenization (provider-bound; hot-swap re-tokenizes per {§tokenomics}).
|
|
3646
3643
|
- Provider dispatch, request-accounting validation, and exact-decimal aggregate projection through the shared contracts-owned path.
|
|
3647
3644
|
- Scheme-handler invocation (connections, subprocesses, fetch).
|
|
3648
|
-
-
|
|
3645
|
+
- Extension loading ({§extension-discovery}).
|
|
3649
3646
|
- Stream AbortController lifecycle.
|
|
3650
3647
|
- CLI + daemon.
|
|
3651
3648
|
|
|
@@ -3653,16 +3650,16 @@ When SQL becomes onerous for a specific case, retreat for that case and document
|
|
|
3653
3650
|
|
|
3654
3651
|
---
|
|
3655
3652
|
|
|
3656
|
-
## §core-
|
|
3653
|
+
## §core-extension-composition Extension composition
|
|
3657
3654
|
|
|
3658
3655
|
The metaproject contract owns installed membership, the one-family manifest
|
|
3659
|
-
shape, and the shared pre-import trust boundary ({§
|
|
3660
|
-
|
|
3656
|
+
shape, and the shared pre-import trust boundary ({§extension-discovery}). Each
|
|
3657
|
+
framework owns its typed discovery result and trusted loading path.
|
|
3661
3658
|
Core owns only cross-family composition, arbitration, and operator presentation
|
|
3662
3659
|
of skipped-package evidence.
|
|
3663
3660
|
|
|
3664
|
-
§
|
|
3665
|
-
For an installed
|
|
3661
|
+
§extension-namespace-arbitration **Every addressable scheme name has one claim.**
|
|
3662
|
+
For an installed extension, claim identity is its kind plus its npm
|
|
3666
3663
|
package name. Core's bundled names are reserved claims. A daemon module's
|
|
3667
3664
|
runtime registration names its module owner and makes one composite executor
|
|
3668
3665
|
claim: its ordinary output scheme and optional resource facet do not compete
|
|
@@ -3673,8 +3670,8 @@ claiming either name, for process-wide and workspace-scoped registrations alike.
|
|
|
3673
3670
|
|--------------------------------|---------------------------------------------------------|---------|
|
|
3674
3671
|
| None | Any valid claim | Register it. |
|
|
3675
3672
|
| Same installed family/package | Rescan of the same name | No-op; retain the one registered handler. |
|
|
3676
|
-
| Reserved core name | Any
|
|
3677
|
-
| Any
|
|
3673
|
+
| Reserved core name | Any extension, a module included | Fail naming the reserved owner and claimant. |
|
|
3674
|
+
| Any extension | A different owner, including scheme/executor either way | Fail naming both owners. |
|
|
3678
3675
|
| Module runtime | Its optional same-registration scheme facet | Compose one handler under the runtime's single claim. |
|
|
3679
3676
|
|
|
3680
3677
|
Arbitration precedes host registry mutation. External scheme descriptors are
|
|
@@ -3690,15 +3687,21 @@ registration.
|
|
|
3690
3687
|
|
|
3691
3688
|
## §bundled-set Bundled Set
|
|
3692
3689
|
|
|
3693
|
-
Family discovery ({§
|
|
3690
|
+
Family discovery ({§extension-discovery}) scans installed scoped and unscoped
|
|
3694
3691
|
packages carrying the applicable `plurnk.kind` declaration.
|
|
3695
3692
|
|
|
3696
|
-
§default-
|
|
3697
|
-
of the default
|
|
3698
|
-
|
|
3699
|
-
default
|
|
3693
|
+
§default-extension-ownership `@plurnk/plurnk-service` is the sole manifest owner
|
|
3694
|
+
of the default extensions. Frameworks own contracts, discovery, and loading;
|
|
3695
|
+
their runtime dependency graphs contain no extension of their kind. A required
|
|
3696
|
+
default extension missing from a service install is a broken install. A direct
|
|
3700
3697
|
framework consumer may intentionally omit leaves and receives that framework's
|
|
3701
3698
|
documented unavailable-capability behavior.
|
|
3699
|
+
|
|
3700
|
+
`@plurnk/plurnk-tavily-plugin` is the separately installed, opt-in plugin showcase,
|
|
3701
|
+
not a service dependency. Its own tests own installation, native discovery,
|
|
3702
|
+
configuration, and HTTP materialization; service installation coverage proves it
|
|
3703
|
+
is absent from the default composition.
|
|
3704
|
+
|
|
3702
3705
|
Packed executor coverage distinguishes installation from enablement: verify
|
|
3703
3706
|
the package floor, explicit opt-in, and composed allowlist/disable behavior
|
|
3704
3707
|
through discovery and registration outside the development dependency graph
|
|
@@ -3711,19 +3714,19 @@ the checkout's development dependency graph, and proves each optional language
|
|
|
3711
3714
|
degrades by name when its leaf is absent.
|
|
3712
3715
|
|
|
3713
3716
|
§install-root-advisory-ownership **The composed service install owns
|
|
3714
|
-
third-party advisory detection.** Only that install resolves the default
|
|
3717
|
+
third-party advisory detection.** Only that install resolves the default extensions
|
|
3715
3718
|
and their combined transitive tree. Its audit reports advisories at the
|
|
3716
3719
|
moderate floor without blocking by default; strict mode makes the same floor a
|
|
3717
3720
|
gate. A chain rooted through an `@plurnk/*` dependency routes to that package's
|
|
3718
3721
|
owner, while other direct roots remain service-owned. First-party package-pin
|
|
3719
3722
|
freshness remains the owning family's concern.
|
|
3720
3723
|
|
|
3721
|
-
|
|
|
3724
|
+
| Kind | Lean framework | Service-owned default extensions |
|
|
3722
3725
|
|-----------|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
|
|
3723
3726
|
| Schemes | `@plurnk/plurnk-schemes` | `@plurnk/plurnk-schemes-http` |
|
|
3724
3727
|
| Mimetypes | `@plurnk/plurnk-mimetypes` | `application-ipynb`, `application-json`, `application-jsonl`, and `application-xml` format leaves. |
|
|
3725
3728
|
| | | `text-csv`, `text-diff`, `text-dotenv`, `text-html`, `text-ini`, `text-markdown`, and `text-plain` format leaves. |
|
|
3726
|
-
| | | `image`, `application-pdf` (header-only, {§mimetype-pdf-facts}), and every `grammar-{slug}`
|
|
3729
|
+
| | | `image`, `application-pdf` (header-only, {§mimetype-pdf-facts}), and every `grammar-{slug}` package in the framework's tree-sitter registry ({§mimetype-grammar-packages}), all under `@plurnk/plurnk-mimetypes-*`. |
|
|
3727
3730
|
| Executors | `@plurnk/plurnk-execs` | `common`, `jq`, and `sqlite` leaves under the `@plurnk/plurnk-execs-*` prefix. |
|
|
3728
3731
|
|
|
3729
3732
|
The independently published `tokenizers` artifact is an opt-in leaf. Installing
|
|
@@ -3733,7 +3736,7 @@ native attachment like an image, and the daemon does no extraction (#542).
|
|
|
3733
3736
|
|
|
3734
3737
|
**Providers:** `@plurnk/plurnk-providers` resolves the Models.dev catalog,
|
|
3735
3738
|
operator declarations, local adapters, and finally installed AI SDK provider
|
|
3736
|
-
|
|
3739
|
+
extensions. `Mock` is its integration fixture. Core contains no vendor protocol.
|
|
3737
3740
|
|
|
3738
3741
|
**Core schemes:** `file`, `log`, `prompt`, `skill`, and `worker` expose daemon
|
|
3739
3742
|
state or filesystem orchestration owned by core. `exec` is internal dispatch
|
|
@@ -3744,8 +3747,8 @@ dispatcher contract.
|
|
|
3744
3747
|
|
|
3745
3748
|
The executor registry discovers installed runtimes, probes availability, and
|
|
3746
3749
|
routes ```` ```<runtime> ````; core contributes orchestration and the output-scheme
|
|
3747
|
-
adapter, not runtime implementations. Optional and third-party
|
|
3748
|
-
each
|
|
3750
|
+
adapter, not runtime implementations. Optional and third-party extensions extend
|
|
3751
|
+
each kind by installation and discovery; they never require a framework or
|
|
3749
3752
|
service manifest edit.
|
|
3750
3753
|
|
|
3751
3754
|
---
|
|
@@ -3813,11 +3816,11 @@ Node's pre-script env-file form and the executable's post-script form share the
|
|
|
3813
3816
|
|
|
3814
3817
|
| Source | Panel | Admission |
|
|
3815
3818
|
|---|---|---|
|
|
3816
|
-
|
|
|
3817
|
-
| Agent Plugin
|
|
3819
|
+
| Extension package | `.env.defaults` at the package root | `@plurnk/*` or a `plurnk` package field; {§extension-trust-boundary} |
|
|
3820
|
+
| Agent Plugin extension | `ai.plurnk/.env.defaults` | The winning daemon-wide plugin in {§agent-plugins-hosting}, a valid native declaration, and the same trust gate |
|
|
3818
3821
|
|
|
3819
3822
|
Root and trust flags apply before collection. A project plugin contributes no native panel.
|
|
3820
|
-
Non-module native panels follow their npm-only family discovery ({§
|
|
3823
|
+
Non-module native panels follow their npm-only family discovery ({§extension-manifest-read});
|
|
3821
3824
|
a plain-folder declaration does not suppress an installed capability's panel.
|
|
3822
3825
|
Linked packages resolve panels against the same canonical root as native code;
|
|
3823
3826
|
an absent panel is optional, but a panel escaping that root is rejected.
|
|
@@ -3871,6 +3874,7 @@ names the offending variable or file/entry and retains its cause.
|
|
|
3871
3874
|
| A2A | Whole outbound definitions and controls, timeout/diagnostic bounds, configured inbound exposure |
|
|
3872
3875
|
| Schedule | Whole definitions and controls, recurrence syntax, time zone and preview count |
|
|
3873
3876
|
| Hooks | Command/argument/event configuration and delivery bounds |
|
|
3877
|
+
| Discovered modules | Each module's own configuration, as its factory constructs it ({§module-self-activation}) |
|
|
3874
3878
|
|
|
3875
3879
|
Disabled definitions and controls without a resource are validated, not skipped.
|
|
3876
3880
|
Checking creates no database, starts no process or listener, arms no schedule,
|
|
@@ -3899,7 +3903,7 @@ Each knob's value lives on its panel and nowhere else (`plurnk-service config de
|
|
|
3899
3903
|
| §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. |
|
|
3900
3904
|
| `PLURNK_SERVICE_FILE_MATERIALIZE_MAX_BYTES` | Byte ceiling in `1..104857600` for one workspace-file snapshot ({§membership-materialization-limit}). |
|
|
3901
3905
|
| `PLURNK_SERVICE_MAX_TURNS` | Operator model-call **ceiling** — `-1` = no cap; a positive value clamps `runLoop({maxTurns})`. The durable worker-tree budget includes descendant calls, BARE, and park/resume under {§turn-cap-counts-the-tree}; non-model chronology consumes none. |
|
|
3902
|
-
| `PLURNK_SERVICE_MAX_COMMANDS` | Per-emission action ceiling; `-1` = no cap — every
|
|
3906
|
+
| `PLURNK_SERVICE_MAX_COMMANDS` | Per-emission action ceiling; `-1` = no cap — every compiled op dispatches. Each resolved target statement counts once, whether authored separately or in a group ({§target-group}). Overflow ops drop with one durable `max-commands-exceeded` error row on the next packet. Lifecycle operations remain exempt ({§operator-config-workspace-max-commands-floor}). Tightened per workspace via `settings.maxCommands` (min wins). |
|
|
3903
3907
|
| §operator-config-loop-timeout `PLURNK_SERVICE_LOOP_TIMEOUT` | Positive ms of cumulative active execution per loop ({§loop-execution-allowance}); excludes parked/queued time. Snapshotted on first execution, retained across wakes. Exhaustion aborts in-flight work and terminates `504 loop_timeout`, including a stuck provider call. |
|
|
3904
3908
|
| `PLURNK_SERVICE_PROVIDER_RECOVERY` | ms of recovery after the first recoverable provider failure; `0` disables reissue. Expiry parks attended loops, concludes unattended loops, or returns BARE's failure under {§provider-recovery}. |
|
|
3905
3909
|
| `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF` | First recovery delay (ms); doubles per failure up to `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF_MAX` ({§provider-recovery}). |
|
|
@@ -3910,8 +3914,6 @@ Each knob's value lives on its panel and nowhere else (`plurnk-service config de
|
|
|
3910
3914
|
| `PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES` | Surrounding and landed lines shown at each EDIT result boundary ({§edit-result-receipt-projection}). |
|
|
3911
3915
|
| `PLURNK_SERVICE_MIN_CYCLES` | Min repetitions before cycle detection fires ({§engine-rails}). |
|
|
3912
3916
|
| `PLURNK_SERVICE_MAX_CYCLE_PERIOD` | Max period length cycle detection examines ({§engine-rails}). |
|
|
3913
|
-
| `PLURNK_SERVICE_REQUIEM_MAX_TOKENS` | Initial forensic witness output allowance ({§digest-requiem}). |
|
|
3914
|
-
| `PLURNK_SERVICE_REQUIEM_RETRY_MAX_TOKENS` | Retry allowance; must be at least the initial requiem allowance ({§digest-requiem}). |
|
|
3915
3917
|
| `PLURNK_SERVICE_FILES_ITEMS` | Turn-0 catalog preview. Folder-capable schemes render a one-level `*` map with `dir/**` rollups; kernel docs remain recursive and explicitly complete. `-1` = markerless first pages; positive `N` explicitly caps only file-map rows; `0` / unset = off ({§actor-boundary-catalog-preview}). |
|
|
3916
3918
|
| `PLURNK_SERVICE_MEMBERS_MODEL_SCOPE` | Ceiling for a model's `members` definitions in the lattice `none < root < namespace`; `none` refuses every model definition ({§members-model-scope}). |
|
|
3917
3919
|
| `PLURNK_SERVICE_EXEC_CONCURRENCY` | Executions admitted at once per workspace; the rest queue FIFO with `202 queued` receipts; `-1` unbounded ({§exec-concurrency}). |
|
|
@@ -3935,9 +3937,9 @@ instead of a user's boot, and a dead knob cannot ship.
|
|
|
3935
3937
|
|
|
3936
3938
|
Feature-flag bools use `process.env.X === "1"` exactly — never `=== "true"`.
|
|
3937
3939
|
|
|
3938
|
-
External
|
|
3940
|
+
External extensions declare their own env vars in their own `.env.defaults`, assembled at boot ({§operator-config-env-defaults}).
|
|
3939
3941
|
|
|
3940
|
-
§operator-config-cli-flags **Admin CLI flags derive only from the service package's `.env.defaults`.** Every `PLURNK_*` declared there becomes `--<kebab-cased-name>` (prefix stripped, lowercased, underscores → dashes). A comment immediately above the declaration becomes its `-h` description. Installed
|
|
3942
|
+
§operator-config-cli-flags **Admin CLI flags derive only from the service package's `.env.defaults`.** Every `PLURNK_*` declared there becomes `--<kebab-cased-name>` (prefix stripped, lowercased, underscores → dashes). A comment immediately above the declaration becomes its `-h` description. Installed extension defaults join the environment floor and catalog but do not implicitly expand the service executable's flag surface.
|
|
3941
3943
|
|
|
3942
3944
|
### Loop limits
|
|
3943
3945
|
|
|
@@ -3984,9 +3986,9 @@ leak into another.
|
|
|
3984
3986
|
workspace: a client tightens the runaway-op guard and never raises it past
|
|
3985
3987
|
the operator's.
|
|
3986
3988
|
- §operator-config-workspace-max-commands-floor The cap bounds *actions* only.
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3989
|
+
WAIT and parameterless KILL are never counted and always dispatch, so `0` is a valid
|
|
3990
|
+
floor, admitting lifecycle intent with zero actions. Dropped actions still prevent
|
|
3991
|
+
successful completion under {§turn-disposition}.
|
|
3990
3992
|
- §operator-config-workspace-git `settings.git` (`false`) **denies** git for the workspace (`PLURNK_SERVICE_GIT_ALLOWED` AND workspace) — the client opts its workspace out of git membership and working-tree status; it can never re-enable git past the operator's service-wide lockout.
|
|
3991
3993
|
- §operator-config-workspace-file-create-scope `settings.fileCreateScope` narrows `PLURNK_SERVICE_FILE_CREATE_SCOPE` by the ordered lattice `none < root < namespace`; a workspace may disable creation or confine a namespace-enabled service to its root, but never widen the operator's ceiling. Unknown service values fail configuration validation and unknown workspace values fail `workspace.create`.
|
|
3992
3994
|
- `settings.membersModelScope` narrows `PLURNK_SERVICE_MEMBERS_MODEL_SCOPE` ({§members-model-scope}).
|
|
@@ -4043,9 +4045,10 @@ a fresh-user configuration.
|
|
|
4043
4045
|
|
|
4044
4046
|
## §rpc Module seam
|
|
4045
4047
|
|
|
4046
|
-
Core implements the contracts-owned {§application-port} and
|
|
4047
|
-
|
|
4048
|
-
action-name catalog
|
|
4048
|
+
Core implements the contracts-owned {§application-port} and hosts the module
|
|
4049
|
+
contract published in `@plurnk/plurnk-modules` ({§module-contract}). It owns the one
|
|
4050
|
+
listener modules mount on ({§http-host}), but no public action-name catalog or generic
|
|
4051
|
+
string-dispatched method registry. A
|
|
4049
4052
|
client-interface module such as `plurnk-agui` owns its public protocol, action
|
|
4050
4053
|
names, request validation, discovery result, and event projection.
|
|
4051
4054
|
|
|
@@ -4053,13 +4056,13 @@ names, request validation, discovery result, and event projection.
|
|
|
4053
4056
|
|
|
4054
4057
|
```mermaid
|
|
4055
4058
|
flowchart LR
|
|
4056
|
-
bind["Host
|
|
4057
|
-
register["
|
|
4059
|
+
bind["Host binds the daemon's listener<br/>unadmitted"] --> register
|
|
4060
|
+
register["Register explicit, then discovered modules"] --> setup["module.setup(ModuleSetupSeam)"]
|
|
4058
4061
|
setup --> capabilities["Register static capabilities,<br/>workspace activators, and actions"]
|
|
4059
4062
|
capabilities --> ready["Process-wide schemes ready"]
|
|
4060
4063
|
ready --> recovery["Reconcile durable lifecycle"]
|
|
4061
4064
|
recovery --> start["module.start(ApplicationPort)"]
|
|
4062
|
-
start --> interface["
|
|
4065
|
+
start --> interface["Listener admitted:<br/>module-owned client protocol ready"]
|
|
4063
4066
|
recovery -->|durable workspace work| demand["First workspace demand"]
|
|
4064
4067
|
interface -->|client workspace work| demand
|
|
4065
4068
|
demand --> lease["Acquire capability residency"]
|
|
@@ -4076,17 +4079,17 @@ flowchart LR
|
|
|
4076
4079
|
```
|
|
4077
4080
|
|
|
4078
4081
|
Every registered module's `setup` runs in registration order before any
|
|
4079
|
-
module's `start
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
{§startup-listener-admission}
|
|
4083
|
-
|
|
4082
|
+
module's `start` ({§module-phases}; failures follow {§module-failure}). Core
|
|
4083
|
+
then readies process-wide schemes, reconciles durable lifecycle, and starts
|
|
4084
|
+
modules in registration order. The daemon's listener is bound before durable admission
|
|
4085
|
+
({§startup-listener-admission}) and admitted once every module has started
|
|
4086
|
+
({§module-http-mounts}). Persisted workspaces with
|
|
4084
4087
|
no durable work stay passive until first demand; activation publishes their
|
|
4085
4088
|
complete capabilities and documentation before the demanding operation
|
|
4086
4089
|
proceeds. `setup` is the readiness boundary for every capability registered
|
|
4087
|
-
with Core: recovery may demand a workspace provider before `start`.
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
+
with Core: recovery may demand a workspace provider before `start`. Requests on
|
|
4091
|
+
the listener remain unavailable until it is admitted; a module opens any other exterior
|
|
4092
|
+
ingress only after recovery. No
|
|
4090
4093
|
registered capability may depend on exterior ingress. A module, and any distinct
|
|
4091
4094
|
lifetime object returned by `start`, may implement the following phases:
|
|
4092
4095
|
|
|
@@ -4103,21 +4106,26 @@ even if setup fails. A returned object identical to its module is tracked once.
|
|
|
4103
4106
|
|
|
4104
4107
|
| Source | Declaration | Lifetime |
|
|
4105
4108
|
|---|---|---|
|
|
4106
|
-
|
|
|
4109
|
+
| Extension package | `package.json#plurnk` with `kind: "module"` and `module`, an export subpath resolved through the package's own exports as in {§executor-dynamic-runtimes} | Daemon-wide; the form every first-party default module uses |
|
|
4107
4110
|
| Agent Plugin | `plugin.json#extensions.ai.plurnk` with `kind: "module"` and a `module` path under `ai.plurnk/` | Daemon-wide; npm and selected user roots only |
|
|
4108
4111
|
| Project Agent Plugin | Portable components only | Workspace-scoped; native code is not imported |
|
|
4109
4112
|
|
|
4110
|
-
The export is one DaemonModule object or no-argument factory.
|
|
4113
|
+
The export is one DaemonModule ({§module-contract}) object or no-argument factory. The host
|
|
4114
|
+
records each module's owner, the package it came from, and its diagnostics name that owner. The
|
|
4115
|
+
service registers no module itself; a host that registers one explicitly, such as a test
|
|
4116
|
+
substituting a package, names it by its package the same way. Standard bundles follow
|
|
4111
4117
|
{§agent-plugins-hosting} source order, then other installed module packages load in package-name
|
|
4112
|
-
order. All trusted modules register before setup
|
|
4113
|
-
|
|
4118
|
+
order. All trusted modules register before setup; a daemon without a listener then leaves out
|
|
4119
|
+
every one that declares mounts ({§module-http-mounts}). A package the host registered explicitly is
|
|
4120
|
+
never also discovered: discovery skips that owner before importing it. Untrusted modules are reported and not imported. Invalid
|
|
4114
4121
|
declarations, unavailable module files and configuration errors during construction are diagnosed
|
|
4115
|
-
at the affected
|
|
4122
|
+
at the affected extension, a declaration's error owned by `extensions` and a
|
|
4123
|
+
module's own configuration error by `module:<package>`; healthy siblings remain available. A factory validates startup
|
|
4116
4124
|
configuration before `setup` acquires resources. Failures after registration begins follow
|
|
4117
4125
|
{§module-lifecycle} cleanup, not a partial-registration fallback.
|
|
4118
4126
|
An invalid module object, factory result or lifecycle member is an implementation contract failure,
|
|
4119
|
-
not configuration, and fails loudly.
|
|
4120
|
-
interfaces and
|
|
4127
|
+
not configuration, and fails loudly. What a module contributes registers through its owning public
|
|
4128
|
+
interfaces and is released during {§module-lifecycle} resource teardown.
|
|
4121
4129
|
|
|
4122
4130
|
§module-shutdown-order `Daemon.stop()` first rejects new capability demand and
|
|
4123
4131
|
aborts proposals, branches, derivations, and worker scopes. It begins module
|
|
@@ -4163,18 +4171,21 @@ flowchart LR
|
|
|
4163
4171
|
observers --> database[Maintain and release database]
|
|
4164
4172
|
```
|
|
4165
4173
|
|
|
4174
|
+
§module-host-capabilities **The coordinator's host interface is core's own.**
|
|
4175
|
+
The daemon passes one object implementing every published slice
|
|
4176
|
+
({§module-seam-slices}); these functions are on it too, for core's
|
|
4177
|
+
Functionality coordinator and core's own witnesses, and are not part of the
|
|
4178
|
+
published module contract.
|
|
4179
|
+
|
|
4166
4180
|
| Setup function | Contract |
|
|
4167
4181
|
|---|---|
|
|
4168
4182
|
| `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. |
|
|
4169
|
-
| `registerScheme(name, handler)` | Adds one process-wide addressable scheme handler; scheme readiness and model-facing capability publication remain core-owned. |
|
|
4170
|
-
| §module-action-registration `registerModuleAction({ name, scope, residency, inputSchema, outputSchema, handler })` | Adds one non-empty, extension-unique action with resolvable JSON Schemas. `scope` is exactly `worldless`, `workspace`, or `worker`; the handler receives schema-validated params and a separate matching context. `residency` is explicitly `required` or `none`: only the former acquires workspace capabilities and reconciles worker documents. Worldless actions require `none`. Scoped contexts contain trusted bound identifiers, never client parameters. A client-interface module decides whether and how the name becomes public, validates successful output, and owns collisions with its built-ins. |
|
|
4171
4183
|
| §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. |
|
|
4172
4184
|
| §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}). |
|
|
4173
|
-
| `readWorkspaceEnvironment(workspaceId)` | Captures the workspace env layer ({§workspace-env}) and returns its composer. No argument uses admitted host values; a supplied environment supplies a module's reference-resolution context. Both apply the same captured values and masks, without worker overrides. |
|
|
4174
|
-
| §module-workspace-directory `workspaceStateDirectory(workspaceId, namespaceOwner)` | Returns and creates the module's absolute operational-state directory under the daemon's XDG state home. Core owns path resolution and a stable random workspace storage key in its own `workspace_module_state` row. The key survives workspace renames and daemon restarts; independently created workspaces, including in other databases, receive different keys. The module owns its contents and child-directory lifetimes. |
|
|
4175
|
-
| §module-functionality-adapter `registerFunctionalityAdapter(adapter)` | Registers one family beneath the shared coordinator ({§functionality-coordinator}). |
|
|
4176
4185
|
| §module-workspace-capabilities `replaceWorkspaceCapabilities({ workspaceId, namespaceOwner, state, runtimes })` | Atomically replaces one provider's durable state and runtime/scheme snapshot at the workspace operation boundary. Namespace claims are validated before mutation. Failure restores the prior state and publication. |
|
|
4177
4186
|
|
|
4187
|
+
Core keys each {§module-workspace-directory} by a stable random workspace
|
|
4188
|
+
storage key in its own `workspace_module_state` row.
|
|
4178
4189
|
Module directory allocation is lazy, atomic in SQLite, and independent of the
|
|
4179
4190
|
project root, daemon CWD, and workspace/worker environment overrides. New
|
|
4180
4191
|
directories use mode `0700`; existing permissions are not rewritten. Module
|
|
@@ -4186,6 +4197,14 @@ workspace forgets its storage key through the existing foreign key; old disk
|
|
|
4186
4197
|
state is not reassigned or automatically purged. A database copy preserves its
|
|
4187
4198
|
storage identities; the directory is operational state, not a backup of it.
|
|
4188
4199
|
|
|
4200
|
+
§skills-storage-upgrade **Skills ownership upgrades without a second identity.**
|
|
4201
|
+
The database migration renames the family state to `@plurnk/plurnk-skills`.
|
|
4202
|
+
Before module setup, core renames the former skills directory within each storage root
|
|
4203
|
+
recorded by this database. Fetched bytes are not refetched or deleted. A missing former
|
|
4204
|
+
directory needs no work; a completed rename is repeatable. Conflicting destinations and
|
|
4205
|
+
filesystem failures stop admission without replacing either directory. No runtime alias
|
|
4206
|
+
recognizes the former owner.
|
|
4207
|
+
|
|
4189
4208
|
§workspace-environment-sharing **The workspace owns its shared environment.**
|
|
4190
4209
|
Workers own their logs; delegation retains its existing lifecycle.
|
|
4191
4210
|
Creating, attaching, forking, cancelling, or deleting a worker does not create,
|
|
@@ -4325,7 +4344,10 @@ composition boundaries, not arbitrary exceptions:
|
|
|
4325
4344
|
| Internal invariant, state, or implementation failure | Preserve the exception; never reclassify it as an operator configuration error. |
|
|
4326
4345
|
|
|
4327
4346
|
Client discovery and passive synchronization report startup diagnostics through the
|
|
4328
|
-
existing Notice channel, even without a usable model.
|
|
4347
|
+
existing Notice channel, even without a usable model. Each is a Notice from `engine:configuration`
|
|
4348
|
+
of kind `configuration_unavailable` that names the failed setting's `key` and its `owner`: the
|
|
4349
|
+
setting's reader (such as `packet`, `model` or `executor:<runtime>`), a family, `extensions` for an
|
|
4350
|
+
extension declaration, or a module as `module:<package>`. The first turn of a drain, and a changed diagnostic
|
|
4329
4351
|
thereafter, reports unresolved configuration to both client and model. An
|
|
4330
4352
|
unchanged diagnostic is not repeated every turn. Operation failures remain Problems.
|
|
4331
4353
|
|
|
@@ -4356,32 +4378,6 @@ publication contract, and creates no log entries or model Notices. Published
|
|
|
4356
4378
|
failures retain their exact Problems in `list`. Concurrent consumers share the
|
|
4357
4379
|
workspace activity; a client disconnect does not clear another consumer's work.
|
|
4358
4380
|
|
|
4359
|
-
§functionality-adapter **An adapter owns protocol truth.** It declares its
|
|
4360
|
-
family, namespace owner, definition schema, contributed defaults, discovery,
|
|
4361
|
-
admission, preparation, and teardown, and its alias grammar when that is not
|
|
4362
|
-
the shared lowercase-hyphen one: the coordinator enforces whichever grammar the
|
|
4363
|
-
family declares, at admission, in the service projection, and on persisted
|
|
4364
|
-
state, so an environment variable's name is an alias exactly as a skill name
|
|
4365
|
-
is. Admission distinguishes explicit client
|
|
4366
|
-
actions from model operations where the family contract requires it
|
|
4367
|
-
({§members-model-scope}). Preparation receives each complete definition with optional
|
|
4368
|
-
adapter-owned interpretation context. Context is source semantics, not policy or provenance;
|
|
4369
|
-
it participates in runtime identity and hot-load comparisons, is never projected as configuration
|
|
4370
|
-
or persisted into a workspace override, and cannot survive replacement by a local definition.
|
|
4371
|
-
Removing that override restores the current inherited definition and context together.
|
|
4372
|
-
Descriptive provenance alone does not change runtime identity. Preparation returns runtimes, documents, per-alias
|
|
4373
|
-
outcomes, and a snapshot with `commit`/`abort`. Successful publication commits;
|
|
4374
|
-
failure aborts; cooling tears down. Protocol continuations remain ordinary
|
|
4375
|
-
module actions. Optional `forget` releases an installed or provisioned
|
|
4376
|
-
definition before removal; failure rejects removal. The
|
|
4377
|
-
seam's shapes — the identity a verb acts under, its options, definition
|
|
4378
|
-
sources, outcomes, preparation, the prepared result and the family handle —
|
|
4379
|
-
are declared once in `plurnk-contracts` and imported by core and every
|
|
4380
|
-
module; core adds only its own face of the seam, the runtime registration a
|
|
4381
|
-
resident family prepares and the scheme facet it may expose.
|
|
4382
|
-
An adapter may expose current partial-source `configurationNotices`; these join the ordinary
|
|
4383
|
-
workspace diagnostics without preventing independently valid definitions from preparing.
|
|
4384
|
-
|
|
4385
4381
|
§functionality-hotload **Out-of-band state is admitted before the next turn.** An adapter whose
|
|
4386
4382
|
`available` reads state that changes outside the daemon, such as skill roots ({§skills-hotload}) or
|
|
4387
4383
|
installed plugins ({§agent-plugins-hosting}), implements `refreshIfChanged`. Turn admission calls it
|
|
@@ -4421,9 +4417,10 @@ its discovery roots explicitly ({§operator-config-real-model-profile}), so
|
|
|
4421
4417
|
operator roots do not shape a gate. Root selection does not restrict explicit
|
|
4422
4418
|
source definitions. Skills mutations change workspace bindings, not these roots
|
|
4423
4419
|
({§skills-functionality}); MCP mutations likewise remain workspace-owned. The module setup seam's
|
|
4424
|
-
`
|
|
4425
|
-
|
|
4426
|
-
|
|
4420
|
+
`workspacePaths` supplies selected `<project>/.agents`, `$XDG_CONFIG_HOME/plurnk`,
|
|
4421
|
+
and `~/.agents` directories in precedence order with their scopes, omitting project
|
|
4422
|
+
when no project is bound ({§module-workspace-paths}). Modules own their file formats;
|
|
4423
|
+
core owns discovery roots.
|
|
4427
4424
|
|
|
4428
4425
|
An adapter may expose a `scheme` facet beneath its family's runtime namespace
|
|
4429
4426
|
({§runtime-resource-binding}). A facet claims a path subtree and is the scheme's
|
|
@@ -4859,13 +4856,13 @@ adding a loop to it. LOOK text anchors resolve through the same
|
|
|
4859
4856
|
| §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. |
|
|
4860
4857
|
| §notifications-workspace-created `workspace/created` | `{ id, name, projectRoot }` | A workspace is created. This is the only current global event. |
|
|
4861
4858
|
| `workspace/preparation` | `{ workspaceId, preparation: FunctionalityPreparationActivity[] }` | Workspace capability preparation changes; snapshot and clearing semantics follow {§functionality-preparation-visibility}. |
|
|
4862
|
-
| §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 conversation routing, 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
|
|
4859
|
+
| §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 conversation routing, 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. |
|
|
4863
4860
|
| §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. |
|
|
4864
4861
|
| §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. |
|
|
4865
4862
|
| §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. |
|
|
4866
4863
|
| §notifications-reasoning-event `reasoning/event` | `{ workerId, loopId, turnId, modelCallId, requestSequence, phase, delta? }` | A main emission call exposes readable reasoning. Each physical request that emits reasoning owns a distinct positive `requestSequence` and balanced start/content/end stream; opening a retry closes the preceding stream before any retry delta. Only content carries a nonempty exact delta. It is transient presentation evidence, never a log row, Notice, packet field, or BARE/child channel. The settled provider response remains the durable authority. |
|
|
4867
4864
|
|
|
4868
|
-
§notifications-stream-event-failure-isolation The
|
|
4865
|
+
§notifications-stream-event-failure-isolation The extension-facing
|
|
4869
4866
|
`NotifyCaps.streamEvent()` remains a synchronous advisory call while core
|
|
4870
4867
|
resolves its entry identity asynchronously.
|
|
4871
4868
|
|
|
@@ -4903,7 +4900,7 @@ without an origin filter ({§actor-boundary-isolation}).
|
|
|
4903
4900
|
## §packet-assembly Packet assembly
|
|
4904
4901
|
|
|
4905
4902
|
`PacketBuilder.buildRequestPacket` owns the engine's default ordered section
|
|
4906
|
-
list. Trusted scheme
|
|
4903
|
+
list. Trusted scheme extensions may transform that first-class list before it is
|
|
4907
4904
|
rendered or measured; {§context-fit} remains an engine-owned post-build rail.
|
|
4908
4905
|
|
|
4909
4906
|
```mermaid
|
|
@@ -4928,11 +4925,12 @@ The packet reaches the provider as a transcript, under the roles the model was t
|
|
|
4928
4925
|
Only role boundaries are added: joined by blank lines, the user messages are the user slot's
|
|
4929
4926
|
bytes, in record order. An emission is placed exactly when its row is present in the final log
|
|
4930
4927
|
section, so curation governs the transcript: a KILLed emission row, or one a trusted transform
|
|
4931
|
-
removed ({§packet-
|
|
4928
|
+
removed ({§packet-extension-transform}), takes its emission with it, and a log without emission rows
|
|
4932
4929
|
is one user message. An emission of only NOTE and WAIT delivers nothing, so its record runs on
|
|
4933
4930
|
into the next user message. The Worker block and the status clump always follow the log, so a
|
|
4934
4931
|
request never ends on an emission, and the projection refuses one that would. The digest's packet
|
|
4935
|
-
artifacts record the sections, and `.wire.json`
|
|
4932
|
+
artifacts record the sections, and `.wire.json` reconstructs their text-message
|
|
4933
|
+
envelope ({§share-packet-names}); it is not a serialized HTTP capture.
|
|
4936
4934
|
|
|
4937
4935
|
### §packet-cache-monotone Default order and cache locality
|
|
4938
4936
|
|
|
@@ -4963,7 +4961,7 @@ operator notes and policies can change. Trust is a separate
|
|
|
4963
4961
|
admission rule. The system slot contains trusted control-plane material;
|
|
4964
4962
|
attacker-reachable content stays in the user slot.
|
|
4965
4963
|
|
|
4966
|
-
### §packet-
|
|
4964
|
+
### §packet-extension-transform Trusted whole-list extension seam
|
|
4967
4965
|
|
|
4968
4966
|
`SchemeRegistry.transformSections` pipes the complete default list through
|
|
4969
4967
|
every registered scheme implementing `transformSections(sections) -> sections`,
|
|
@@ -4976,7 +4974,7 @@ sections. It receives no separate engine, database, actor, or request context.
|
|
|
4976
4974
|
Emission placement reads the final log section, so a transform that removes an
|
|
4977
4975
|
emission row's record removes its emission from the transcript ({§packet-wire-envelope}).
|
|
4978
4976
|
|
|
4979
|
-
This is strictly a trusted in-process seam, admitted through the common
|
|
4977
|
+
This is strictly a trusted in-process seam, admitted through the common extension
|
|
4980
4978
|
trust gate; an external client action cannot invoke it. Whole-list transformation is
|
|
4981
4979
|
the fork-avoidance valve for alternate packet shapes, while
|
|
4982
4980
|
overflow recovery and packet projection remain closed engine concerns.
|
|
@@ -5129,8 +5127,8 @@ header. A null header renders only its content. Empty content is omitted, traili
|
|
|
5129
5127
|
newlines are removed from each section, and rendered sections are separated by one
|
|
5130
5128
|
blank line. Any node whose content is empty is absent from the wire, except the
|
|
5131
5129
|
child-orientation sections, which state emptiness as `[]` ({§packet-empty-sections}).
|
|
5132
|
-
Core owns the order at {§packet-cache-monotone}; a trusted
|
|
5133
|
-
section list before rendering ({§packet-
|
|
5130
|
+
Core owns the order at {§packet-cache-monotone}; a trusted extension may transform the
|
|
5131
|
+
section list before rendering ({§packet-extension-transform}). The projection preserves
|
|
5134
5132
|
the evidence section owners supply: paths, URI fragments, log coordinates, scopes and
|
|
5135
5133
|
coordinate-prefixed body lines remain usable without translation; curation and log-row
|
|
5136
5134
|
measurements stay attached to what they measure ({§tokenomics-agnostic-ruler});
|
|
@@ -5179,7 +5177,7 @@ whose INSTEAD OF trigger refuses a turn that is not an open model inference turn
|
|
|
5179
5177
|
items, the composition, the bag, and the provider metadata together. Readers of a whole packet
|
|
5180
5178
|
select from `turn_packets`, which assembles `sections` back into the bag byte for byte (the digest,
|
|
5181
5179
|
and every test that inspects a stored packet); statements that need one field read the bag
|
|
5182
|
-
directly with `json_extract`. A packet transformed by
|
|
5180
|
+
directly with `json_extract`. A packet transformed by an extension, or any non-log section, is one
|
|
5183
5181
|
item. Items no composition references are transient data: `retention_collect_packet_items`
|
|
5184
5182
|
collects them under the retention policy ({§retention-policy}), which is how a deleted worker's or
|
|
5185
5183
|
workspace's packets release their space while shared items survive. A fork copies the composition
|
|
@@ -5203,44 +5201,12 @@ operation turns and therefore store `NULL`. Digest projects exact operation
|
|
|
5203
5201
|
source independently from this optional model-exchange record; a request-only
|
|
5204
5202
|
turn receives a note instead of a fabricated response.
|
|
5205
5203
|
|
|
5206
|
-
|
|
5207
|
-
After selectors are applied, digest retains every turn with exact content or reasoning source, a
|
|
5208
|
-
valid stored provider request, or malformed stored packet evidence; orders those
|
|
5209
|
-
turns by durable chronology; and names each by its log coordinate ({§share-packet-names}). The
|
|
5210
|
-
producer does not affect projection.
|
|
5211
|
-
|
|
5212
|
-
§share-packet-names **Packet artifacts carry the coordinate the log uses.** A turn's files are named
|
|
5213
|
-
`<worker>-<loop>-<turn>`, the worker's name and the loop and turn sequences that `log:///<loop>/<turn>/…`
|
|
5214
|
-
addresses: the model's first turn in its first loop is `<worker>-1-2`, because the initialization
|
|
5215
|
-
survey is turn 1 and writes no packet. A digest spanning several workspaces nests each workspace's
|
|
5216
|
-
files in a folder named for it; a name that cannot name a file (a workspace named by its path,
|
|
5217
|
-
`~/ptl/x`) is slugged for the folder, `ptl-x`, while the digest text keeps the name verbatim, and
|
|
5218
|
-
two names that slug alike are told apart by the row's id. `digest.json` records each turn's stem as `artifact`, so no
|
|
5219
|
-
consumer reconstructs a name. A name that cannot be a file name, or two turns sharing one, fails.
|
|
5220
|
-
|
|
5221
|
-
| Artifact | Present when | Authority |
|
|
5222
|
-
|----------|--------------|-----------|
|
|
5223
|
-
| `<stem>.assistant.md` | The turn has an `ops` source | Exact `turn_sources.content`, independent of log rows |
|
|
5224
|
-
| `<stem>.reasoning.md` | The turn has a `reasoning` source | Exact `turn_sources.content`, without relabeling it as content |
|
|
5225
|
-
| `<stem>.system.md`, `<stem>.user.md` | The turn stored a provider request | Stored text sections projected through `PacketWire`; native parts are not Markdown |
|
|
5226
|
-
| `<stem>.wire.json` | The turn stored a provider request | The request's text messages in order, its worker's emission rows placed ({§packet-wire-envelope}); `<stem>.wire.invalid.json` names a stored log that cannot be projected |
|
|
5227
|
-
| `digest.json` turn `attachments` | Every turn | Stored native attachment descriptors; `[]` means a request without attachments, `null` means no valid stored request. Selection is not proof of provider acceptance. |
|
|
5228
|
-
| `<stem>.assistantRaw.json` | The request has an admitted provider response | Stored opaque provider response |
|
|
5229
|
-
| `<stem>.response.md`, attempt artifacts | The request received no admitted response | Stored request and attempt state |
|
|
5230
|
-
| `<stem>.packet.raw.txt` | The stored packet fails typed validation | Exact stored packet text |
|
|
5231
|
-
| `<stem>.packet.invalid.json` | The stored packet fails typed validation | Turn identity and complete validation error chain |
|
|
5232
|
-
|
|
5233
|
-
A source-backed turn without provider participation produces only its source-channel
|
|
5234
|
-
artifacts; a request-only turn produces no fabricated assistant. A
|
|
5235
|
-
source-less programmatic turn with no provider request has no forensic payload
|
|
5236
|
-
to project and writes no files.
|
|
5237
|
-
|
|
5238
|
-
The external tokenless draft and transformation boundary is owned by
|
|
5204
|
+
he external tokenless draft and transformation boundary is owned by
|
|
5239
5205
|
{§scheme-packet-transform}. Core alone extends each validated draft with its
|
|
5240
5206
|
measured `weight` field for storage. #74 tracks coverage that mistakes the sum
|
|
5241
5207
|
of section weights for the rendered request weight.
|
|
5242
5208
|
|
|
5243
|
-
§definition-table-projection The authored `plurnk.md` remains human-aligned. Its `definition` section deterministically removes Markdown table-cell padding and shortens separator cells to three dashes before
|
|
5209
|
+
§definition-table-projection The authored `plurnk.md` remains human-aligned. Its `definition` section deterministically removes Markdown table-cell padding and shortens separator cells to three dashes before extension transforms, measurement, storage, and wire rendering; alignment colons survive, while fenced blocks and all non-table whitespace remain exact.
|
|
5244
5210
|
|
|
5245
5211
|
§lexicon **Vocabulary follows the standard of its audience.**
|
|
5246
5212
|
|
|
@@ -5269,7 +5235,7 @@ Retired terms stay retired: the lexicon guard rejects `thinking`, the unqualifie
|
|
|
5269
5235
|
| inbound `SEND` from outside the workspace | the operator's: complete when it fit, otherwise its size and address ({§context-fit}, {§message-projection}); a peer worker's: its first page ({§markerless-first-page}) |
|
|
5270
5236
|
| structured `EDIT` receipt or textual `COPY`/`MOVE` effects | complete receipt-owned join context |
|
|
5271
5237
|
| every other nonempty body | the model's own: complete; what it did not author: its first page ({§markerless-first-page}); then {§context-fit} |
|
|
5272
|
-
| the `reasoning` row | the
|
|
5238
|
+
| the `reasoning` row | the optional reasoning preview under {§reasoning-row} |
|
|
5273
5239
|
| a row the wall took | its size and address, no body and no native part ({§context-own-rows-fit}) |
|
|
5274
5240
|
| bodyless row | heading and any facts; no coordinate lines; `tokens` includes any selected native part |
|
|
5275
5241
|
|
|
@@ -5424,83 +5390,14 @@ the same deadline through {§application-loop-observation}, not a restarted cloc
|
|
|
5424
5390
|
|
|
5425
5391
|
§share **A share is the database's record, ready to send.** `plurnk-service share [<file.db>] [<folder>]`, and `npm run share` from a checkout, take a consistent copy of the database (`VACUUM INTO`; a live database is never read in place), and write its digest into `<folder>`, an ordinary folder the user archives or attaches however they like. Without a database the service's own is shared. Nothing is overwritten: a folder that exists and is not empty is refused, and a caller reusing a place removes it first. The share is the user's bug report and our dogfood, benchmark and forensics artifact alike.
|
|
5426
5392
|
|
|
5427
|
-
§share-snapshot **A database is copied by SQLite, never by the filesystem.** `Share.snapshot(dbPath, copy)`, exported as `@plurnk/plurnk-service/share` with `Share.write`, is the one consistent copy: a byte copy of a WAL-mode database drops every committed page still in its `-wal` file. A harness that keeps the database beside its digest takes it through `snapshot`; an existing `copy` is refused.
|
|
5428
|
-
|
|
5429
5393
|
§share-scope **A share is unredacted.** `--workspace=<id>` limits a share to one workspace; without it the whole database is shared. Nothing is filtered, redacted or scanned: a share holds what the models saw and wrote in scope, including prompts, file contents read, command output and reasoning, and the command says so. `--requiem` adds the forensic interview ({§digest-requiem}), which calls a model; `plurnk-service requiem <file.db> <folder>` adds it later to a digest already written.
|
|
5430
5394
|
|
|
5431
5395
|
§share-folder **Shares land in one place.** With no folder named, a share is a stamped child, `share-<UTC stamp>`, of `PLURNK_SERVICE_SHARE_FOLDER` (a leading `~/` expands, as for every explicit Plurnk path) or of `$XDG_STATE_HOME/plurnk/shares`.
|
|
5432
5396
|
|
|
5433
|
-
§
|
|
5434
|
-
|
|
5435
|
-
| Surface | Contract |
|
|
5436
|
-
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
5437
|
-
| Import `@plurnk/plurnk-service/digest` | Ships `Digest` and its package-owned SqlRite statements; importing performs no I/O or process action. The CLI wrapper alone invokes it. |
|
|
5438
|
-
| `run({ dbPath })` | Reads the required database and writes a complete digest to `./test/digest` relative to the caller's working directory. |
|
|
5439
|
-
| `digestDir` | Selects a nonempty output path. `run` refuses a folder that exists and is not empty, and `requiem` refuses an existing `requiem.json` or `requiem.md`, before database or provider I/O; neither deletes ({§share}). Concurrent callers use distinct folders. |
|
|
5440
|
-
| Reader lifetime | `run` reads heavy evidence on demand while rendering, then closes its reader on success or failure. `requiem` closes its reader before awaiting witness inference. |
|
|
5441
|
-
| §candidate-pinned-runtime Candidate runtime | 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. |
|
|
5442
|
-
| Export completion | Packet and response bodies are read and serialized one record at a time, without discarding evidence. `digest.json` is promoted from a partial file only after every artifact is written; its absence identifies an incomplete export. |
|
|
5443
|
-
| `workerId` | Narrows workers and every dependent loop, turn, turn-attached logical inference, specialization, physical request, and log row to that one worker. |
|
|
5444
|
-
| `workspaceId` | Narrows workers plus every logical inference and dependent evidence owned by one workspace, when both selectors are present they intersect. |
|
|
5445
|
-
|
|
5446
|
-
§digest-cost-kind **Cost basis named.** A rendered Cost line carries the basis of its dollar figure: `(charged)` only when every settled request's cost is provider-charged; `(estimated — catalog rates)` when any settled request's cost is an estimate, because a mixed sum is no more trustworthy than its weakest term. A dollar figure without its basis reads as billed truth, and an estimate must never impersonate a charge.
|
|
5397
|
+
§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.
|
|
5447
5398
|
|
|
5448
5399
|
§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's grammar for a cut the engine's own ceiling made. The same precedence governs a cut so deep no operation parses: the rejection notice names the truncation as the cause, not the parser's symptom, overriding {§invalid-emission-attempts}'s parser diagnostic for `length` finishes.
|
|
5449
5400
|
|
|
5450
|
-
§digest-wire-line **Wire health aggregated.** Each worker summary renders a `Wire:` line — total physical provider requests, error-outcome count, and the error percentage when nonzero. Provider-level failures are absorbed by retries below the packet stream, so without this aggregate a rate-limit storm is invisible in every summary while the model's experience stays clean.
|
|
5451
|
-
|
|
5452
|
-
§digest-cache-ledger **Measured cache reuse and estimated prompt overlap are separate.**
|
|
5453
|
-
|
|
5454
|
-
| Projection | Meaning |
|
|
5455
|
-
|---|---|
|
|
5456
|
-
| `digest.json` provider-request `cachedTokens`, `inputTokens` | Exact provider-reported cache reads and input tokens; absent quantities remain `null`, reported zero remains zero. Every physical request counts, including retries and first requests of new loops. Stored packet availability is irrelevant to these counters. |
|
|
5457
|
-
| Turn `cache=<cached>/<input>` | Sum each measured quantity over that turn's requests. If any request omits a quantity, that sum is `?`. |
|
|
5458
|
-
| Workspace `Cache: <cached> of <input> reported input tokens read from cache (<pct>%) over <n> requests` | Sum only requests reporting both counters. Percentage is cache reads / input, rounded to one decimal; zero input is `n/a`. Requests missing either counter are counted separately as `missing input or cache usage (excluded)`. |
|
|
5459
|
-
| `digest.json` provider-request `adjacentPrefixTokensEstimate` | Optional loop-local diagnostic: the longest common character prefix with the preceding request, weighted under {§tokenomics-agnostic-ruler} as a share of the current stored prompt, multiplied by reported input tokens. First request: `0`; missing current/preceding packet or current input: `null`. Empty prompts have zero overlap. |
|
|
5460
|
-
|
|
5461
|
-
The prefix estimate uses the stored emission packet's wire message order, roles
|
|
5462
|
-
and content. A BARE request's input is not that packet; its prefix estimate and
|
|
5463
|
-
the following request's comparison are unknown. The estimate is
|
|
5464
|
-
neither provider tokenization nor a cache ceiling, and never supplies a cache-ratio
|
|
5465
|
-
denominator. Caching across loops or against other provider-resident prefixes
|
|
5466
|
-
does not make the measured counters inconsistent.
|
|
5467
|
-
|
|
5468
|
-
§digest-edit-census **Every model EDIT by the form it authored, how it landed, and whether it came back.** For each worker the digest reads every model-authored EDIT row and classifies the form from the row's stored marker and the durable statement's pattern: `hash` (one anchor), `line` (one line number), `range` (two marks), `insert` (the zero-width `<L,1,L,1>` form, {§zero-width-column-one-insert}), `column` (any other four-mark region), `prepend` / `append` (`<0>` / `<-1>`), `offset` (a tolerated anchor offset, {§anchor-offset}), `pattern` (a selection matcher), `whole` (no marker: a creation when it lands 201). It counts the EDITs, those refused (status ≥ 400), and the *revisits*: an EDIT of a path the same worker had edited within its previous two model turns — the shape of a repair without the claim of one. Each worker summary renders `EDITs: <n> · <form>=<count>… · refused=<k> · revisits=<r>` (`(no edits)` for none); `digest.json` carries the census as `edit_census` on every worker and stamps every EDIT log entry with its `edit_form` and `edit_revisit`. A form is a fact about what was written, never about intent; the bench sheet reads the counts as friction and leaves the judgement to the reader.
|
|
5469
|
-
|
|
5470
|
-
§digest-forensic-fidelity **Forensic fidelity and cardinality.** The digest's machine-readable JSON preserves every log event with its initial and current projection, causal `source`, and structured `attrs`; every exact log-KILL target effect; the exact Problem on every failed row; each loop's exact terminal result, settlement time, scheduled due time, recurring interval, and recurrence lineage; and every ordered physical provider request. Programs still produce chronological `assistant.md` artifacts after every READ receipt is KILLed; source is independent of log curation. Each worker summary's `Emissions:` line counts its announced emission rows, those the worker KILLed, and the headings it echoed ({§emission-row}); its `Reasonings:` line counts its landed reasoning rows, those the worker KILLed, and the turns that reasoned ({§reasoning-row}); the op mix leaves both harness rows out. Each stored packet validates independently: one malformed historical packet remains exact raw evidence with its complete validation error chain and never prevents healthy turns from being projected. Accounting on broader rows is the shared exact derivation from that ledger, never a second stored fact. A worker's Cost line names how many settled requests carry no usage at all (errored or aborted exchanges) — their server-side spend is unrecorded rather than silently priced as zero. The reasoning chronology distinguishes readable reasoning content from provider-reported reasoning usage: when tokens were reported but no readable content was returned, it states both facts instead of implying that no reasoning occurred. The human Markdown waterfall shows a present causal source and may preview only the Problem detail because it remains a triage projection, not the machine record. Targets reconstruct the model-visible address, including hostname, port, serialized query, and fragment; an authority-bearing URL must never degrade from `https://host/path` to `https:///path`, and durable resource coordinates render back to their authority form. Its human Markdown waterfall groups consecutive identical per-turn op outcomes and typed `entry_materialized` narrations, reporting the exact count and sequence span (`xN (seq A-B)`). Grouping keys include source and the complete target, so distinct causes, authorities, or channels never collapse, and non-consecutive events preserve their chronological order. Thus amplification is conspicuous without making the diagnostic artifact itself pathological; valid packet files remain byte-identical records of what the model saw.
|
|
5471
|
-
|
|
5472
|
-
Unrecognized actionless log rows are retained and labelled as such, not
|
|
5473
|
-
interpreted as executable turnOps or allowed to prevent the remaining digest.
|
|
5474
|
-
|
|
5475
|
-
§digest-executor-evidence **A red command is work, not a defect.** Engine-materialized
|
|
5476
|
-
completion rows for a failed command carry the executor's problem identity
|
|
5477
|
-
(`https://problems.plurnk.xyz/executor/*`), and the digest classifies them as
|
|
5478
|
-
evidence: they render like any row but never count toward a loop's error total,
|
|
5479
|
-
its health verdict, or the per-turn `errs=` badge — a loop that concluded green
|
|
5480
|
-
over red test runs is CLEAN, not DEGENERATE-WIN. This is the digest mirror of the
|
|
5481
|
-
strike rail's exemption ({§engine-rails}, #425 F1): structural violations count,
|
|
5482
|
-
executor evidence never does.
|
|
5483
|
-
|
|
5484
|
-
§digest-requiem **A requiem is an out-of-band forensic interview, not a worker
|
|
5485
|
-
turn.** It cannot execute operations or alter the audited history.
|
|
5486
|
-
|
|
5487
|
-
| Aspect | Contract |
|
|
5488
|
-
|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
5489
|
-
| Scope | One interview for each worker with model-bearing inference turns; workers without inference evidence are omitted. |
|
|
5490
|
-
| Evidence | The worker's final packet plus every attempt's exact normalized response and admission evidence; opaque raw transport remains in durable forensic artifacts. Quoted evidence is budgeted to the witness window ({§digest-requiem-evidence-budget}). |
|
|
5491
|
-
| Witness | An explicitly supplied provider or the active configured provider; absence fails hard. |
|
|
5492
|
-
| Identity | The worker's durable provider identity ({§worker-provider-identity}) is sent as the `workerId`, without asserting a live worker topology. |
|
|
5493
|
-
| Attempts | One call at `PLURNK_SERVICE_REQUIEM_MAX_TOKENS`; only an empty length-limited response receives one retry at `PLURNK_SERVICE_REQUIEM_RETRY_MAX_TOKENS`. |
|
|
5494
|
-
| Artifacts | `requiem.md` carries testimony and exact nullable USD accounting. `requiem.json` is durably materialized before each call and preserves logical call state, messages, normalized responses, every physical request's state and accounting, and their shared aggregate projection. |
|
|
5495
|
-
|
|
5496
|
-
§digest-requiem-evidence-budget **Quoted evidence fits the witness.** The
|
|
5497
|
-
interview's user message is budgeted against the witness provider's context
|
|
5498
|
-
window minus the retry output allowance and system framing (chars/2, the
|
|
5499
|
-
capacity gate's own estimator). Overflow elides the oldest provider attempts
|
|
5500
|
-
behind an explicit `elidedOldestAttempts` count marker, never silently; the
|
|
5501
|
-
final packet and the newest attempts always testify. A windowless witness
|
|
5502
|
-
(`contextWindow` null) quotes unbudgeted.
|
|
5503
|
-
|
|
5504
5401
|
§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}).
|
|
5505
5402
|
|
|
5506
5403
|
§turn-accounting-notice **The completion beat carries the spend.** `turn_generated`
|
|
@@ -5518,9 +5415,9 @@ content-offset position: reasoning coordinates do not address the content source
|
|
|
5518
5415
|
§tools-resource-discovery **Executable capability discovery uses ordinary
|
|
5519
5416
|
Plurnk resources.** No generated tool table rides the system packet. Every
|
|
5520
5417
|
runtime enabled for the current worker with an admitted invocation materializes one
|
|
5521
|
-
|
|
5418
|
+
runtime document at `worker:///_plurnk/plurnk/<runtime>.md`. A general runtime's
|
|
5522
5419
|
document contains its {§executor-tool-document}; a runtime with an exact
|
|
5523
|
-
{§executor-tool-registry} materializes a compact catalog at the same address. The
|
|
5420
|
+
{§executor-tool-registry} materializes a compact catalog at the same address. The runtime document summarizes
|
|
5524
5421
|
the server or runtime, lists every enabled target as a directly copyable
|
|
5525
5422
|
executable fence named for the runtime, with its input preview ({§operation-aside} carries the
|
|
5526
5423
|
target one-liner; no invocation dispatch would reject is ever advertised).
|
|
@@ -5531,13 +5428,13 @@ preserve the full tool description and raw input schema under
|
|
|
5531
5428
|
Turn0 rows. A schema-backed general runtime uses `<runtime>/input.md`.
|
|
5532
5429
|
Non-schema targets retain supplemental details in family sections.
|
|
5533
5430
|
Tool-result/output schemas remain ordinary evidence, not teaching. Unknown-target
|
|
5534
|
-
recovery names the published
|
|
5431
|
+
recovery names the published runtime document through the same path owner as
|
|
5535
5432
|
materialization, including a runtime's declared `resourcesPath`.
|
|
5536
5433
|
|
|
5537
5434
|
```mermaid
|
|
5538
5435
|
flowchart LR
|
|
5539
|
-
Survey["Turn 0 FIND<br/>tools/*.md"] -->
|
|
5540
|
-
|
|
5436
|
+
Survey["Turn 0 FIND<br/>tools/*.md"] --> Runtimes["runtime paths + summaries"]
|
|
5437
|
+
Runtimes --> Read["READ selected runtime<br/>only when needed"]
|
|
5541
5438
|
Read --> Exec["execution with an aside"]
|
|
5542
5439
|
Read --> Schema["READ linked input schema<br/>when the preview is insufficient"]
|
|
5543
5440
|
Schema --> Exec
|
|
@@ -5546,19 +5443,19 @@ flowchart LR
|
|
|
5546
5443
|
§tools-resource-materialization The runtime registry, workspace capability policy,
|
|
5547
5444
|
tool resources, and dispatch use one effective workspace snapshot. A
|
|
5548
5445
|
disabled, unavailable, detached, replaced, or removed runtime has no
|
|
5549
|
-
tool resource; an exact registry's empty set publishes no
|
|
5446
|
+
tool resource; an exact registry's empty set publishes no runtime and
|
|
5550
5447
|
admits no invocation. Reconciliation deletes stale documents
|
|
5551
5448
|
before upserting the current set. `PLURNK_SERVICE_DOCS_EXCLUDE` does not hide an
|
|
5552
5449
|
enabled executable; executor enablement is the sole user-configured filter
|
|
5553
5450
|
shared by discovery and dispatch. A runtime declaration may carry
|
|
5554
5451
|
`resourcesPath` — its generated-doc root relative to the workspace's generated
|
|
5555
5452
|
subtree ({§worker-generated-subtree}). Absent, its docs live in the internal
|
|
5556
|
-
`_plurnk/plurnk` namespace; present (attached MCP
|
|
5557
|
-
the
|
|
5558
|
-
shared scratch. Turn 0 surveys the
|
|
5453
|
+
`_plurnk/plurnk` namespace; present (attached MCP servers: `/tools`),
|
|
5454
|
+
the runtime document materializes at `_plurnk` + that root in the
|
|
5455
|
+
shared scratch. Turn 0 surveys the runtimes (`FIND
|
|
5559
5456
|
(worker:///_plurnk/tools/*.md)`, one row per
|
|
5560
5457
|
server carrying its summary) and, for each server named in
|
|
5561
|
-
`PLURNK_MCP_EXPANDED`, adds one FIND over its
|
|
5458
|
+
`PLURNK_MCP_EXPANDED`, adds one FIND over its runtime document matching the
|
|
5562
5459
|
complete executable blocks (`FIND (worker:///_plurnk/tools/<server>.md)`
|
|
5563
5460
|
with a multiline regex over matching fences), so turn 0 names every tool with its aside and
|
|
5564
5461
|
signature — one row per tool, paged like every survey. Capability attenuation
|
|
@@ -5638,155 +5535,27 @@ definitions ({§actor-boundary-catalog-preview}), so the model sees why a file i
|
|
|
5638
5535
|
not a member before it asks. There is no other membership path: the client's `/members`
|
|
5639
5536
|
verbs are these verbs.
|
|
5640
5537
|
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
its adapter owns protocol truth for standard Agent Skills and nothing else. A
|
|
5644
|
-
definition is `SkillDefinition`: the standard skill `name`, its `source`, and
|
|
5645
|
-
optional Git `ref`/resolved `commit` ({§skills-sources}). Only a host-provided
|
|
5646
|
-
resource tree omits `source`. Source location is not mutation ownership: standard
|
|
5647
|
-
project/global roots are read-only configuration inputs; live changes belong to
|
|
5648
|
-
the workspace. Plurnk neither installs into nor deletes from those roots.
|
|
5649
|
-
|
|
5650
|
-
*Available definitions.* The filesystem is the only truth about installation:
|
|
5651
|
-
every `<root>/<name>/SKILL.md` directory under the project, plurnk, then global
|
|
5652
|
-
root is one service-origin definition, a nearer root shadowing a farther one and
|
|
5653
|
-
all of them shadowing host-provided trees by name. Each filesystem definition
|
|
5654
|
-
names its actual source directory. The workspace's durable state owns
|
|
5655
|
-
enablement ({§functionality-state}); a disabled skill stays client-visible and
|
|
5656
|
-
leaves no model-facing trace.
|
|
5657
|
-
|
|
5658
|
-
§skills-configuration **Skills use the shared definition cascade.**
|
|
5659
|
-
|
|
5660
|
-
| Layer, low to high | Definition source |
|
|
5661
|
-
|---|---|
|
|
5662
|
-
| Service | Host-provided trees |
|
|
5663
|
-
| Standard locations | Global, plurnk, then project roots selected by {§agent-roots} |
|
|
5664
|
-
| Cascading environment | `PLURNK_SKILLS_<name>={"name":"<name>","source":"…","ref"?:"…"}` replaces the complete definition |
|
|
5665
|
-
| Live workspace | `skills (add)` creates a workspace definition through {§functionality-coordinator} |
|
|
5666
|
-
|
|
5667
|
-
`PLURNK_SKILLS_ENABLED` supplies default enabledness; `<name>_ENABLED` overrides
|
|
5668
|
-
it independently ({§resource-environment}). The decoded environment alias must
|
|
5669
|
-
equal the standard skill name, including digit-leading and Unicode names.
|
|
5670
|
-
Blank definitions are invalid; controls may precede a definition. Environment
|
|
5671
|
-
validation checks shape, names, remote URL rules, and Git-only `ref` without
|
|
5672
|
-
fetching or opening a source; `commit` is service-recorded, not an input.
|
|
5673
|
-
|
|
5674
|
-
*Discovery is inert.* `discover {source}` lists the standard skills one source
|
|
5675
|
-
carries, each a candidate with `source` provenance and the exact definition to
|
|
5676
|
-
add; it never installs, persists, or enables. Agent Skills have no standard
|
|
5677
|
-
registry, so `discover {query}` is 400 `query-unsupported`, naming the source
|
|
5678
|
-
forms. Client `configuration` contributes nothing and is refused with 400.
|
|
5679
|
-
|
|
5680
|
-
*Admission.* `add {alias, definition}` requires `alias = name` and a `source`;
|
|
5681
|
-
the workspace definition may shadow a service skill of the same name. Relative
|
|
5682
|
-
sources require a project root; absolute sources work in headless workspaces.
|
|
5683
|
-
A local source is recorded as its absolute path.
|
|
5684
|
-
A git source records the `commit` its `ref` names at admission, or its default
|
|
5685
|
-
branch's when no `ref` is given; `ref` belongs to git sources, and a supplied
|
|
5686
|
-
`commit` is refused because the service records it. The family's aliases use
|
|
5687
|
-
the standard skill-name grammar ({§agent-skills-name}), including digit-leading
|
|
5688
|
-
and Unicode names, rather than the coordinator's generic default.
|
|
5689
|
-
|
|
5690
|
-
*Preparation.* For each enabled alias the adapter selects the host-provided
|
|
5691
|
-
tree or resolves the complete source definition ({§skills-sources}). Local
|
|
5692
|
-
folders and their `SKILL.md` files remain live references, including supporting
|
|
5693
|
-
resources and symlink retargeting. Git/archive sources are materialized only
|
|
5694
|
-
inside {§module-workspace-directory}; different workspaces and complete source
|
|
5695
|
-
definitions cannot reuse each other's materializations accidentally.
|
|
5696
|
-
The first fetched Git/archive copy remains stable across enable, cooling, and
|
|
5697
|
-
restart until the complete source definition changes. In particular, an
|
|
5698
|
-
operator-configured symbolic Git ref is not an implicit update subscription.
|
|
5699
|
-
Each admitted skill requires standard `name` and `description` frontmatter
|
|
5700
|
-
with `name` matching its directory. A missing, uninstallable, or invalid skill
|
|
5701
|
-
is `unavailable` with its exact Problem ({§problems-functionality}) under the
|
|
5702
|
-
coordinator's failure policy ({§functionality-model-mutation}); one bad skill
|
|
5703
|
-
never fails the family.
|
|
5704
|
-
|
|
5705
|
-
Removal follows {§skills-remove}.
|
|
5706
|
-
|
|
5707
|
-
§skills-sources **A source is a git remote, a folder, or a file, read with standard tools.**
|
|
5708
|
-
Fetching runs nothing it fetched. Materialized copies cannot contain references
|
|
5709
|
-
outside their skill; live resources retain {§agent-skills-directory} containment.
|
|
5710
|
-
|
|
5711
|
-
| Source | How it is read |
|
|
5712
|
-
|---|---|
|
|
5713
|
-
| Git remote: a full `https://` or `ssh://` URL, or `user@host:path` | `git ls-remote` resolves the ref at admission; preparation shallow-clones it with hooks and submodules off, and a checkout at any other commit is 409 `source-moved` |
|
|
5714
|
-
| Folder: absolute, `~/`, or relative to the project root | Live reference; standard directory/name matching applies |
|
|
5715
|
-
| A file named `SKILL.md` | Live reference to its skill directory and supporting resources |
|
|
5716
|
-
| A `.zip`, `.tar`, `.tgz`, `.tar.gz`, `.tar.bz2`, `.tar.xz`, or `.tar.zst` archive | Unpacked into private staging with `unzip` or `tar`; a lone top-level directory is the source's root |
|
|
5717
|
-
|
|
5718
|
-
Any other scheme, plain `http`, `owner/repo` shorthand, and an https URL carrying
|
|
5719
|
-
credentials are refused with `source-invalid` or `source-missing`: shorthand names no
|
|
5720
|
-
forge, and a recorded source is listed to every client. Git runs with the
|
|
5721
|
-
operator's configuration, credentials, and SSH agent, never plurnk's secrets, and
|
|
5722
|
-
never prompts; `PLURNK_SERVICE_SKILLS_FETCH_TIMEOUT_MS` bounds each fetch. The
|
|
5723
|
-
retired vendor-installer knobs (`PLURNK_SERVICE_SKILLS_CLI`, `_CLI_TIMEOUT_MS`,
|
|
5724
|
-
`_REGISTRY_URL`, `_REGISTRY_LIMIT`, `_REGISTRY_TIMEOUT_MS`) make the skills family
|
|
5725
|
-
unavailable when set, each naming what replaced it ({§configuration-repair-path}).
|
|
5726
|
-
|
|
5727
|
-
A source's skills are the directories holding a `SKILL.md`, found by walking
|
|
5728
|
-
from its root without entering `.git` or a skill already found. A fetched skill at
|
|
5729
|
-
the root is named by its frontmatter ({§agent-skills-name}); local references and
|
|
5730
|
-
directories below the root use the standard folder rule. A source with `plugin.json` at its root is an
|
|
5731
|
-
Agent Plugin and is refused with 422 `source-is-plugin`, so its skills keep the
|
|
5732
|
-
plugin's identity. Materialization copies the named skill beside its workspace-owned destination
|
|
5733
|
-
and renames it to `<root>/<name>`; a copy that holds a link out of the skill, or
|
|
5734
|
-
anything but files, directories, and inward links, is refused with 422
|
|
5735
|
-
`source-unsafe` and leaves nothing behind.
|
|
5736
|
-
|
|
5737
|
-
§skills-resources **A skill is a resource tree, not a rewritten document.**
|
|
5738
|
-
The family exposes enabled, available {§agent-skills-tree} sources through
|
|
5739
|
-
`skill://<name>/`. The source owns its bytes; commons entries are demand-loaded
|
|
5740
|
-
projections, not writable installations. Filesystem skills retain their original
|
|
5741
|
-
directories; service-provided trees need no generated filesystem directory.
|
|
5742
|
-
The authority is the name's WHATWG URI representation, including percent-encoding
|
|
5743
|
-
for non-ASCII names. Installation names remain unchanged; a raw spelling and its
|
|
5744
|
-
serialized URI address the same resource, not separate skill identities.
|
|
5745
|
-
|
|
5746
|
-
| Operation | Contract |
|
|
5747
|
-
| --- | --- |
|
|
5748
|
-
| Turn0 `FIND (skill://*/SKILL.md)` | One ordinary resource catalog: name, address, and standard frontmatter description via {§mimetype-summary}. No synthetic index, body injection, or execution. |
|
|
5749
|
-
| `READ (skill://<name>/SKILL.md)` | Original frontmatter and Markdown, unchanged; relative links remain relative to the source layout. |
|
|
5750
|
-
| `READ` / `FIND` below the authority | References, scripts, and assets retain their source paths and ordinary pattern, channel, byte, and multimodal semantics. Acquisition observes current source contents, including disappearance. |
|
|
5751
|
-
| ```` ```runtime (skill://<name>/scripts/program.ext) ```` | Ordinary resource execution and proposal policy; preserve the native file and its siblings under {§exec-source-temporary}. Discovery and READ never execute scripts. |
|
|
5752
|
-
| Model mutation | Read-only; no EDIT, SEND, or KILL of skill resources. Manage definitions and enablement through ```` ```skills ````. |
|
|
5753
|
-
| Disable / unavailable / remove | Withdraw the authority from new resource access and discovery. Existing log receipts remain historical evidence. |
|
|
5754
|
-
| WORK / FORK | Use the same workspace Functionality, not copied definitions or resource caches. |
|
|
5755
|
-
|
|
5756
|
-
Explicit skill URIs address these resources; bare operation paths still address
|
|
5757
|
-
project files, with no implicit current-skill directory. Source resolution follows
|
|
5758
|
-
{§agent-skills-directory}, including symlinked skill directories and containment of references.
|
|
5759
|
-
An uninstalled Git skill is not manufactured by repository detection.
|
|
5538
|
+
The skills module owns the Agent Skills family ({§skills-functionality}) and its resource trees
|
|
5539
|
+
({§skills-resources}); core supplies the Plurnk reference through {§provided-skills-module-slice}.
|
|
5760
5540
|
|
|
5761
5541
|
§plurnk-skill **Plurnk's own reference is an ordinary service-provided skill.**
|
|
5762
5542
|
`skill://plurnk/SKILL.md` is the standard frontmatter entry point, catalogued with
|
|
5763
|
-
other enabled skills. It links package-owned configuration, model,
|
|
5764
|
-
the complete `.env.defaults` aggregate at `skill://plurnk/.env.defaults`,
|
|
5765
|
-
|
|
5766
|
-
|
|
5543
|
+
other enabled skills. It links package-owned configuration, model, COPY/MOVE and extensibility
|
|
5544
|
+
chapters, the complete `.env.defaults` aggregate at `skill://plurnk/.env.defaults`, the
|
|
5545
|
+
installed contracts at `skill://plurnk/packages/<package name>/SPEC.md`, and the
|
|
5546
|
+
Worker's existing tool/resource references. The contracts are the service's own `SPEC.md` and
|
|
5547
|
+
each installed ecosystem package's that ships one, the same membership as the defaults
|
|
5548
|
+
aggregate, with that package's published type declarations beside it at
|
|
5549
|
+
`packages/<package name>/dist/**/*.d.ts`; the service's declarations are its internals and are not
|
|
5550
|
+
served. Contracts are listed when the tree is listed and read where each package installed them,
|
|
5551
|
+
never through a symbolic link. No chapter, contract or defaults body is injected merely because the
|
|
5552
|
+
skill is enabled. The defaults bytes come from the
|
|
5767
5553
|
same {§operator-config-env-defaults} renderer as the operator command, never the
|
|
5768
5554
|
effective environment. Native chapter files retain their owners and locations;
|
|
5769
5555
|
runtime-generated bytes have no invented disk location. Disable/enable,
|
|
5770
5556
|
shared workspace visibility, and project/global shadowing use the ordinary Skills lifecycle.
|
|
5771
5557
|
Service-provided skills are not installer targets; removal follows {§skills-remove}.
|
|
5772
5558
|
|
|
5773
|
-
§skills-remove **`remove` forgets the workspace binding, not the source.**
|
|
5774
|
-
It withdraws that definition and restores any inherited definition and enabledness
|
|
5775
|
-
({§functionality-coordinator}). External folders are never deleted. Fetched
|
|
5776
|
-
materializations remain workspace-owned operational state, reusable only for the
|
|
5777
|
-
same complete definition; they confer no availability without a definition.
|
|
5778
|
-
Inherited definitions cannot be removed here; their enabledness can be overridden.
|
|
5779
|
-
|
|
5780
|
-
§skills-hotload **Skills placed out of band are admitted at the next turn** ({§functionality-hotload}). The
|
|
5781
|
-
family keeps one signature of the discovered roots, configured definitions, source locations, and `SKILL.md` sources
|
|
5782
|
-
per resident workspace, read before a publication loads the skills it describes. Turn admission
|
|
5783
|
-
recomputes it under the workspace gate before packet assembly: a changed signature republishes the
|
|
5784
|
-
family, and an unchanged one republishes only when the skills the coordinator would publish differ
|
|
5785
|
-
from the published ones. A skill installed, edited or removed by any other tool is therefore
|
|
5786
|
-
discoverable in the first subsequent model turn, while an unchanged set dispatches nothing. The model manages skills
|
|
5787
|
-
only through the generated ```` ```skills ```` family
|
|
5788
|
-
({§functionality-model-projection}); it is never taught a package manager.
|
|
5789
|
-
|
|
5790
5559
|
The catalog and Turn0 describe Functionality under the current workspace
|
|
5791
5560
|
capability policy and service ceiling. A direct denied attempt receives the
|
|
5792
5561
|
same exact 403 from dispatch rather than a second documentation policy.
|
|
@@ -5808,7 +5577,7 @@ section because they are language extensions rather than executable tools.
|
|
|
5808
5577
|
|
|
5809
5578
|
### §inject system.inject — the operator injection
|
|
5810
5579
|
|
|
5811
|
-
§packet-inject When `PLURNK_SERVICE_PACKET_INJECT` names a readable markdown file, its content renders as an `## Operator Notes` section in the system slot (definition → policy → inject). Read per-turn so the operator's edits take effect live; a set-but-unreadable path fails the turn hard as {§policy-sections} rules. `~/` expands to home. It's the operator-side complement to the
|
|
5580
|
+
§packet-inject When `PLURNK_SERVICE_PACKET_INJECT` names a readable markdown file, its content renders as an `## Operator Notes` section in the system slot (definition → policy → inject). Read per-turn so the operator's edits take effect live; a set-but-unreadable path fails the turn hard as {§policy-sections} rules. `~/` expands to home. It's the operator-side complement to the extension packet transform — a pressure valve so reshaping the packet edits operator content, never the core. Unset → no section.
|
|
5812
5581
|
|
|
5813
5582
|
### §policy system.policy — the client's policy injection
|
|
5814
5583
|
|
|
@@ -6201,7 +5970,7 @@ caller's own run directory.
|
|
|
6201
5970
|
|
|
6202
5971
|
Every Problem code core mints is named here under its family ({§problem-error-carrier} carries it); the root lint (`scripts/problem-codes.mjs`) refuses a code no owning SPEC names.
|
|
6203
5972
|
|
|
6204
|
-
§problems-dispatch **Dispatch Problems.** Every code
|
|
5973
|
+
§problems-dispatch **Dispatch Problems.** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6205
5974
|
|
|
6206
5975
|
| code | status | contract |
|
|
6207
5976
|
|---|---:|---|
|
|
@@ -6239,7 +6008,7 @@ address's authority is an executor available to the workspace — an MCP server'
|
|
|
6239
6008
|
otherwise it lists the schemes the workspace registers. READ, FIND, KILL and resource selection share
|
|
6240
6009
|
the sentence.
|
|
6241
6010
|
|
|
6242
|
-
§problems-content **Content and transfer Problems.** Every code
|
|
6011
|
+
§problems-content **Content and transfer Problems.** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6243
6012
|
|
|
6244
6013
|
| code | status | contract |
|
|
6245
6014
|
|---|---:|---|
|
|
@@ -6256,7 +6025,7 @@ the sentence.
|
|
|
6256
6025
|
| `proposal-apply-missing` | 500 | The source scheme accepted its MOVE proposal without applying the source mutation. |
|
|
6257
6026
|
| `line-anchor-collision` | 409 | READ coordinates collided with current content at *target*. |
|
|
6258
6027
|
|
|
6259
|
-
§problems-file **File scheme Problems.** Every code
|
|
6028
|
+
§problems-file **File scheme Problems.** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6260
6029
|
|
|
6261
6030
|
| code | status | contract |
|
|
6262
6031
|
|---|---:|---|
|
|
@@ -6275,7 +6044,7 @@ the sentence.
|
|
|
6275
6044
|
| `file-materialization-limit` | 413 | The file exceeds the materialization byte limit and is not read into the workspace. |
|
|
6276
6045
|
| `entry-not-found` | 404 | No member of this workspace is at '*path*'. Recovery: Check the path with FIND. EDIT creates files; `members (add)` admits existing files with a `{"glob": "<path>"}` body. A path beyond the root recovers instead to: '*path*' is outside the project root: only a members definition under the operator's namespace scope admits it, so keep working files inside the root. |
|
|
6277
6046
|
|
|
6278
|
-
§problems-exec **Execution Problems.** Every code
|
|
6047
|
+
§problems-exec **Execution Problems.** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6279
6048
|
|
|
6280
6049
|
| code | status | contract |
|
|
6281
6050
|
|---|---:|---|
|
|
@@ -6284,7 +6053,7 @@ the sentence.
|
|
|
6284
6053
|
| `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*`. |
|
|
6285
6054
|
| `input-closed` | 410 | Execution input is closed. |
|
|
6286
6055
|
|
|
6287
|
-
§problems-entries **Entry scheme Problems (log, worker, entries).** Every code
|
|
6056
|
+
§problems-entries **Entry scheme Problems (log, worker, entries).** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6288
6057
|
|
|
6289
6058
|
| code | status | contract |
|
|
6290
6059
|
|---|---:|---|
|
|
@@ -6297,7 +6066,7 @@ the sentence.
|
|
|
6297
6066
|
| `message-empty` | 400 | SEND has no message text or attachments. |
|
|
6298
6067
|
| `scope-unsupported` | 400 | A worker SEND takes no scope. |
|
|
6299
6068
|
|
|
6300
|
-
§problems-functionality **Server and Functionality Problems.** Every code
|
|
6069
|
+
§problems-functionality **Server and Functionality Problems.** Every code minted here, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
6301
6070
|
|
|
6302
6071
|
| code | status | contract |
|
|
6303
6072
|
|---|---:|---|
|
|
@@ -6309,21 +6078,8 @@ the sentence.
|
|
|
6309
6078
|
| `env-invalid` | 400 | `env` must be an object of string values; '*name*' is not a name a shell can export. |
|
|
6310
6079
|
| `query-required` | 400 | discover takes a path or a glob. Recovery: Supply `{ "query": "<path or glob>" }`. |
|
|
6311
6080
|
| `headless` | 409 | The workspace has no project root, so there are no file members. Recovery: Open the workspace on a project root. |
|
|
6312
|
-
| `definition-invalid` | 400 | A members definition is { glob }: a gitignore-style pattern, `!glob` to exclude
|
|
6081
|
+
| `definition-invalid` | 400 | A members definition is { glob }: a gitignore-style pattern, `!glob` to exclude. |
|
|
6313
6082
|
| `model-scope` | 403 | The model may not change membership here: the members scope is none. Recovery: `git add` the file so git tracks it, or ask the operator to add it (/members add) or raise PLURNK_SERVICE_MEMBERS_MODEL_SCOPE. |
|
|
6314
|
-
| `query-unsupported` | 400 | Agent Skills have no standard registry to search; discover takes a source: a git remote as a full https or ssh URL, a folder, a lone SKILL.md, or a zip or tar archive. |
|
|
6315
|
-
| `source-invalid` | 400 | '*source*' is not a valid git remote URL; an https source carries no credentials (git's credential helper supplies them); is not a source: a git remote is a full https or ssh URL; is relative, and this workspace has no project root to resolve it against; or is neither a folder, a SKILL.md, nor a zip or tar archive. |
|
|
6316
|
-
| `source-missing` | 404 | No folder or file is at '*source*' (; owner/repo shorthand names no forge, so give the repository's full https or ssh URL). |
|
|
6317
|
-
| `source-unreadable` | 422 | '*source*' cannot be read: *cause*; or '*path*' could not be unpacked: *reason*. |
|
|
6318
|
-
| `source-unreachable` | 502 | git could not reach '*remote*', or fetch it (at '*ref*'): *reason*. |
|
|
6319
|
-
| `ref-missing` | 404 | '*remote*' has no branch or tag '*ref*', or names no default branch. |
|
|
6320
|
-
| `source-moved` | 409 | '*source*' *ref* now names *current*; this skill was added at *commit*. Recovery: Remove the skill and add it again to take the current commit. |
|
|
6321
|
-
| `source-is-plugin` | 422 | '*source*' is an Agent Plugin; install it as a plugin, so its skills keep the plugin's identity and servers. |
|
|
6322
|
-
| `source-unsafe` | 422 | '*path*' links outside its skill, or is neither a file, a directory, nor an inward link. |
|
|
6323
|
-
| `skill-not-found` | 404 | '*source*' carries no Agent Skill named '*name*'. |
|
|
6324
|
-
| `skill-ambiguous` | 409 | '*source*' carries *count* skills named '*name*'. |
|
|
6325
|
-
| `alias-mismatch` | 400 | Alias '*alias*' must equal the skill name '*name*'. |
|
|
6326
|
-
| `source-required` | 400 | Adding '*alias*' requires the source that provides it. |
|
|
6327
6083
|
| `workspace-not-found` | 404 | Workspace *id* does not exist. |
|
|
6328
6084
|
| `state-not-json` | 400 | Worker module state is not JSON-serializable. |
|
|
6329
6085
|
| `workspace-busy` | 409 | Workspace *id* is running an operation or another capability change. Recovery: Settle the current operation and retry the capability change. |
|
|
@@ -6336,9 +6092,6 @@ the sentence.
|
|
|
6336
6092
|
| `loop-policy-invalid` | 400 | An unattended loop cannot hold a proposal for review: nobody is present to answer. Recovery: State proposals accept or reject, or attend the loop. |
|
|
6337
6093
|
| `scope-cancelled` | 499 | The worker scope was cancelled: *reason*. |
|
|
6338
6094
|
| `range-not-satisfiable` | 416 | `Range <0,-1>` starts at 0, which is not a line; lines are numbered from 1. Recovery: Write `<1,-1>` to trim every line of the body; `KILL (log:///…/READ)` with no scope retires the item. |
|
|
6339
|
-
| `install-failed` | 500 | Agent Skill '*name*' could not be placed under *root*: *cause*. |
|
|
6340
|
-
| `skill-missing` | 404 | Agent Skill '*alias*' is not provided by this service. |
|
|
6341
|
-
| `skill-invalid` | 422 | Agent Skill '*alias*' is not a valid standard skill: *cause*. |
|
|
6342
6095
|
|
|
6343
6096
|
§pinned-wording-core **Pinned wording.** Verbatim sentences tests pin: each is contract, and a change here is a change of contract.
|
|
6344
6097
|
|