@plurnk/plurnk-service 1.28.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 +7 -18
- package/INSTALL.md +65 -15
- package/README.md +8 -5
- package/SPEC.md +217 -449
- package/dist/build-info.json +1 -1
- package/dist/content/body-preview.d.ts +5 -0
- package/dist/content/body-preview.d.ts.map +1 -1
- package/dist/content/body-preview.js +25 -0
- 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/ChannelWrite.d.ts +5 -0
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/ChannelWrite.js +5 -0
- package/dist/core/ChannelWrite.js.map +1 -1
- package/dist/core/ChannelWrite.sql +10 -0
- package/dist/core/DataStatementRunner.d.ts.map +1 -1
- package/dist/core/DataStatementRunner.js +8 -3
- package/dist/core/DataStatementRunner.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 +21 -15
- 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/KillHandler.d.ts.map +1 -1
- package/dist/core/KillHandler.js +9 -3
- package/dist/core/KillHandler.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +8 -2
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/ResourceSelector.d.ts.map +1 -1
- package/dist/core/ResourceSelector.js +4 -2
- package/dist/core/ResourceSelector.js.map +1 -1
- package/dist/core/ResourceTransfers.d.ts.map +1 -1
- package/dist/core/ResourceTransfers.js +2 -2
- package/dist/core/ResourceTransfers.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/WorkerControlHandler.d.ts.map +1 -1
- package/dist/core/WorkerControlHandler.js +5 -1
- package/dist/core/WorkerControlHandler.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/core/plurnk-uri.d.ts +7 -0
- package/dist/core/plurnk-uri.d.ts.map +1 -1
- package/dist/core/plurnk-uri.js +21 -0
- package/dist/core/plurnk-uri.js.map +1 -1
- package/dist/core/unregistered-scheme.d.ts +4 -0
- package/dist/core/unregistered-scheme.d.ts.map +1 -0
- package/dist/core/unregistered-scheme.js +14 -0
- package/dist/core/unregistered-scheme.js.map +1 -0
- 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 +17 -6
- 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.d.ts.map +1 -1
- package/dist/schemes/File.js +11 -6
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +49 -5
- 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.js +9 -9
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-crud.sql +1 -1
- package/dist/schemes/_entry-find.js +5 -5
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-find.sql +1 -1
- package/dist/schemes/_entry-fts.d.ts.map +1 -1
- package/dist/schemes/_entry-fts.js +7 -3
- package/dist/schemes/_entry-fts.js.map +1 -1
- package/dist/schemes/_entry-manifest.d.ts.map +1 -1
- package/dist/schemes/_entry-manifest.js +3 -5
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/schemes/_entry-ops.js +4 -4
- package/dist/schemes/_entry-ops.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 -1035
- 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
|
|------|--------------------|-----------------|
|
|
@@ -1583,7 +1579,7 @@ Every fact names the canonical key, never the host root or an echo of the
|
|
|
1583
1579
|
model's spelling. These classes let a caller distinguish a wrong address, an
|
|
1584
1580
|
invalid range, read-only authority, and occupied hidden state without guessing.
|
|
1585
1581
|
|
|
1586
|
-
§membership-read-refusal **A file miss speaks of membership, never of the disk.** A file is read only as a member, so every `file` miss — READ, FIND of an exact path, KILL, a COPY or MOVE source — is 404 `entry-not-found`, `No member of this workspace is at '<key>'
|
|
1582
|
+
§membership-read-refusal **A file miss speaks of membership, never of the disk.** A file is read only as a member, so every `file` miss — READ, FIND of an exact path, KILL, a pattern EDIT's source, a COPY or MOVE source — is 404 `entry-not-found`, `No member of this workspace is at '<key>'.`, its target rendered as the member key, never a `file://` URI. Recovery treats path correction with FIND, creation with EDIT, and admission with `members (add)` as alternatives; it must not presume a missing READ requires creation or admission. Admission takes a `{"glob": "<path>"}` body. The sentence is about the address and is true whether or not a file is there: it neither claims absence nor hints at presence. Beyond the root the engine does not look at the disk at all, so two reads of `../` paths differ only in the name they echo, and their recovery speaks of the address too, true under every members scope: `'<key>' is outside the project root: only a members definition under the operator's namespace scope admits it, so keep working files inside the root.` Inside the root occupancy is not secret ({§fs-write-nonmember}), so an exact-path READ of a path that exists on disk but is not a member says so instead — 404 `entry-not-member`, `'<key>' exists on disk but is not a member of this workspace.`, with admission-only recovery; a path the repository ignores, which no model definition admits, carries the members discovery verdict instead: `The repository ignores it: a client or operator members definition can include it, a model definition cannot.` Occupancy may surface there; content never does ({§membership}).
|
|
1587
1583
|
|
|
1588
1584
|
§file-directory-target **A directory is named as a directory.** Inside the root, a READ (or other exact-path read), KILL or EDIT whose target is a directory on disk — with or without a trailing slash — is refused `path-is-directory`, never as a missing or non-member file, since admitting it is not what the model needs: READ and KILL answer 404, EDIT 403. The detail is `'<key>' is a directory, not a file; <OP> reads/removes/writes one file.` and the recovery names the listing that reaches its files, `` List its files with `FIND (<key>/)`, then READ one by its path. `` (KILL: `then KILL each by its path`; EDIT: `` Name a file inside it, as `EDIT (<key>/<file>)`; list its files with `FIND (<key>/)`. ``). Beyond the root the disk stays dark and {§membership-read-refusal} holds unchanged.
|
|
1589
1585
|
|
|
@@ -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 in a closed fence.
|
|
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, complete ({§
|
|
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,6 +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`).
|
|
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).
|
|
2470
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}).
|
|
2471
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`.
|
|
2472
2470
|
|
|
@@ -2686,12 +2684,12 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2686
2684
|
|
|
2687
2685
|
### §find FIND
|
|
2688
2686
|
|
|
2689
|
-
- §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.
|
|
2690
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.
|
|
2691
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.
|
|
2692
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.
|
|
2693
2691
|
|
|
2694
|
-
- §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.
|
|
2695
2693
|
|
|
2696
2694
|
Resource-authority globs select authorities independently of the path scope.
|
|
2697
2695
|
Matching resources retain their full addresses through pattern matching,
|
|
@@ -2706,7 +2704,7 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2706
2704
|
matches the selected channel's content or derivation; path globs select
|
|
2707
2705
|
resources through `(target)` ({§path-glob}).
|
|
2708
2706
|
- §find-fulltext-selection Every matcher operates only over the candidate set selected by `(target)`; indexed matchers do not bypass that selection. `~query` passes the native FTS5 expression to SQLite and ranks matching candidates by ascending BM25, with resource identity breaking ties. Native BM25 uses the shared index's term statistics; candidate visibility, owner, channel and target filters determine which resources can be returned. The ordinary FIND pager selects resources for broad targets or match locations for exact targets: markerless search uses {§markerless-first-page}, `<N>` selects position N and `<N,M>` selects an inclusive range. Fractions are invalid result coordinates, not similarity thresholds. Results expose addressable matched text regions; neither cosine scores nor percentage similarity is invented. Native query-syntax failures return 400 with SQLite's diagnostic; database and implementation failures propagate.
|
|
2709
|
-
- §fts-word-phrase **A word with inner punctuation is the phrase of its tokens.** FTS5 barewords hold only letters, digits, `_` and non-ASCII, so before the query reaches SQLite each word outside a quoted string or `NEAR(…)` group that is not a bareword (with optional leading `^` and trailing `*`) is quoted as a phrase: `~inherited-members` searches `"inherited-members"` — the adjacent tokens `inherited members` — instead of failing as `no such column: members`, and `c++`, `x.y`, `a/b` likewise. FTS5's own syntax passes untouched: `AND`/`OR`/`NOT`/`NEAR`, `+`, quoted phrases, parentheses, and column filters (a word containing `:`, `{` or `}`, or opening with `-`). A column-filter failure keeps SQLite's diagnostic and its recovery says what the filter is and gives the bare-word and `NOT` forms: `` `members:` and `-members` are FTS5 column filters, and the index has one column; to search for a word write it bare, as `~members`, and to exclude one write `NOT` between terms, as `~a NOT members`. ``
|
|
2707
|
+
- §fts-word-phrase **A word with inner punctuation is the phrase of its tokens.** FTS5 barewords hold only letters, digits, `_` and non-ASCII, so before the query reaches SQLite each word outside a quoted string or `NEAR(…)` group that is not a bareword (with optional leading `^` and trailing `*`) is quoted as a phrase: `~inherited-members` searches `"inherited-members"` — the adjacent tokens `inherited members` — instead of failing as `no such column: members`, and `c++`, `x.y`, `a/b` likewise. FTS5's own syntax passes untouched: `AND`/`OR`/`NOT`/`NEAR`, `+`, quoted phrases, parentheses, and column filters (a word containing `:`, `{` or `}`, or opening with `-`). A column-filter failure keeps SQLite's diagnostic and its recovery says what the filter is and gives the bare-word and `NOT` forms: `` `members:` and `-members` are FTS5 column filters, and the index has one column; to search for a word write it bare, as `~members`, and to exclude one write `NOT` between terms, as `~a NOT members`. `` A syntax error over parentheses or quotes, which FTS5 reads as its own syntax, recovers to the phrase and to the regex for the same characters: `` FTS5 reads parentheses and quotes as query syntax: quote the phrase, as `~"all("`, or match the characters with a regex, as `/all\(/`. `` (#1005).
|
|
2710
2708
|
- §find-scoped-isolation Workspace + scheme scoped — no cross-workspace/cross-scheme leakage.
|
|
2711
2709
|
- §find-result-projection **The resolved target selection determines the result unit; result cardinality never changes it** ({§find-result-unit}). Returns `FindResult { status, content, mimetype, results, range, matchingPathCount, matchLocationCount, itemsWeightTotal, returnedItemsWeightTotal }`:
|
|
2712
2710
|
|
|
@@ -2741,7 +2739,7 @@ Log history preserved — `log_entries` stores path tuple as text, not FK to `en
|
|
|
2741
2739
|
derivation's `{§mimetype-summary}`. Prose is clipped to at most `PLURNK_SERVICE_CATALOG_SUMMARY_CHARS` Unicode
|
|
2742
2740
|
code points including a visible terminal ellipsis, so a row stays one line
|
|
2743
2741
|
of orientation; an invocation-form witness — a summary that is one fenced
|
|
2744
|
-
operation, the shape
|
|
2742
|
+
operation, the shape a runtime's tool summary takes
|
|
2745
2743
|
({§tools-resource-materialization}) — is shown whole, every tool named,
|
|
2746
2744
|
because the discovery row exists so the model can invoke without a READ and
|
|
2747
2745
|
a menu that is cut is no menu. Absent metadata is omitted.
|
|
@@ -2967,7 +2965,7 @@ of which Worker launched it ({§execution-output-identity}).
|
|
|
2967
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. |
|
|
2968
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. |
|
|
2969
2967
|
|
|
2970
|
-
|
|
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
|
|
2971
2969
|
control capabilities, not exceptions granting write access to stdout/resources.
|
|
2972
2970
|
|
|
2973
2971
|
### §exec Executions
|
|
@@ -3125,6 +3123,11 @@ catalogue.
|
|
|
3125
3123
|
|
|
3126
3124
|
Per-tool programs such as `go`, `cargo`, `make`, and `npm` do not earn executor tags merely because they are executables; they are complete shell commands in a `sh` executable fence. Registered tags exist only for tools that own a distinct body, target, or output contract. {§exec-registry-resolves}
|
|
3127
3125
|
|
|
3126
|
+
§exec-near-miss **An execution id under the wrong runtime names its address.** A KILL or input
|
|
3127
|
+
addressed to `<runtime>:///<id>` when the id holds an execution only under another runtime refuses
|
|
3128
|
+
`stream-not-found` as before, and its recovery names every address the id holds:
|
|
3129
|
+
`` The execution at /5e8ea474 is `python3:///5e8ea474`. `` (#1005).
|
|
3130
|
+
|
|
3128
3131
|
§exec-lifetime **How long a spawn may live is the fence's metadata, one field.**
|
|
3129
3132
|
`[{"lifetime": …}]` takes a duration (`30s`, `30m`, `2h`), or one of three words;
|
|
3130
3133
|
absent is `loop`. The key is one of the service's reserved metadata keys, withheld
|
|
@@ -3133,7 +3136,7 @@ executor target is refused `scope-unsupported` (400), naming the field.
|
|
|
3133
3136
|
|
|
3134
3137
|
| `lifetime` | The spawn |
|
|
3135
3138
|
| ------------ | --------- |
|
|
3136
|
-
| a duration | Aborted at the deadline — a bounded reap, polite signal then SIGKILL after `PLURNK_SERVICE_EXEC_KILL_GRACE_MS` — and the stream is stamped **504
|
|
3139
|
+
| a duration | Aborted at the deadline — a bounded reap, polite signal then SIGKILL after `PLURNK_SERVICE_EXEC_KILL_GRACE_MS` — and the stream is stamped **504** `execution-timeout`, distinct from a deliberate kill (499) or a clean exit (200): `` Execution of '*runtime*' outlived its *lifetime* lifetime. `` Recovery: `` Run it again with a longer lifetime, such as [{"lifetime": "30m"}], or with none to let it run as long as the loop. `` |
|
|
3137
3140
|
| `loop` (absent) | Loop-life bounded: reaped on every loop terminal except 202, the background-stream behavior. |
|
|
3138
3141
|
| `turn` | Reaped at the worker's next pre-turn via the registry abort, before the turn's own spawns, so it never survives into the subsequent turn; its terminal output surfaces born visible like any close ({§exec-stream}). |
|
|
3139
3142
|
| `detached` | Outlives its loop's terminal, 200 included. It never binds to the loop's teardown and is nobody's obligation — completion is not gated by it, WAIT does not park on it, optimistic settlement looks past it — and it ends only by KILL, the worker's total reap, or daemon shutdown; its late conclusion surfaces without opening a loop. |
|
|
@@ -3339,7 +3342,7 @@ body prefixes.
|
|
|
3339
3342
|
wholesale ({§log-sensitive-request-evidence}); the spawn's record names each such value's
|
|
3340
3343
|
provenance as the modifier's.
|
|
3341
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.
|
|
3342
|
-
- §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.
|
|
3343
3346
|
|
|
3344
3347
|
| Input / effect | Consumer behavior |
|
|
3345
3348
|
| --- | --- |
|
|
@@ -3347,7 +3350,7 @@ body prefixes.
|
|
|
3347
3350
|
| Null path + supplied content | Publish beneath the invocation's `resources/` using {§resource-publication-names}, owned by the calling Worker. |
|
|
3348
3351
|
| Supplied bytes | Retain the original bytes and declared mimetype in an ordinary channel ({§binary-parity}). |
|
|
3349
3352
|
| Supplied text | Preserve text resources; HTTP/HTML materialization retains source and derived channels under {§html-materialization}. |
|
|
3350
|
-
| 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}). |
|
|
3351
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. |
|
|
3352
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. |
|
|
3353
3356
|
|
|
@@ -3532,7 +3535,7 @@ Capability admission precedes this decision, so proposal disposition cannot gran
|
|
|
3532
3535
|
|
|
3533
3536
|
### §subscriptions Subscriptions
|
|
3534
3537
|
|
|
3535
|
-
§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.
|
|
3536
3539
|
|
|
3537
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.
|
|
3538
3541
|
|
|
@@ -3553,7 +3556,7 @@ the producer's already obtained outcome into a fictitious cancellation result.
|
|
|
3553
3556
|
At process restart every still-open row is necessarily missing its callable owner. Boot
|
|
3554
3557
|
settles it as interruption (`500`) and errors active channels before evaluating parked
|
|
3555
3558
|
loops ({§worker-lifecycle-restart-recovery}); it never reports cancellation (`499`) or
|
|
3556
|
-
pretends to reconstruct an opaque
|
|
3559
|
+
pretends to reconstruct an opaque extension connection.
|
|
3557
3560
|
|
|
3558
3561
|
§subscriptions-causal-resource A subscription's causal Worker belongs to the
|
|
3559
3562
|
entry's workspace. The active entry has
|
|
@@ -3639,7 +3642,7 @@ No generator. SQLite-optimal: STRICT (3.37+), `INTEGER PRIMARY KEY` aliasing, ex
|
|
|
3639
3642
|
- Tokenization (provider-bound; hot-swap re-tokenizes per {§tokenomics}).
|
|
3640
3643
|
- Provider dispatch, request-accounting validation, and exact-decimal aggregate projection through the shared contracts-owned path.
|
|
3641
3644
|
- Scheme-handler invocation (connections, subprocesses, fetch).
|
|
3642
|
-
-
|
|
3645
|
+
- Extension loading ({§extension-discovery}).
|
|
3643
3646
|
- Stream AbortController lifecycle.
|
|
3644
3647
|
- CLI + daemon.
|
|
3645
3648
|
|
|
@@ -3647,16 +3650,16 @@ When SQL becomes onerous for a specific case, retreat for that case and document
|
|
|
3647
3650
|
|
|
3648
3651
|
---
|
|
3649
3652
|
|
|
3650
|
-
## §core-
|
|
3653
|
+
## §core-extension-composition Extension composition
|
|
3651
3654
|
|
|
3652
3655
|
The metaproject contract owns installed membership, the one-family manifest
|
|
3653
|
-
shape, and the shared pre-import trust boundary ({§
|
|
3654
|
-
|
|
3656
|
+
shape, and the shared pre-import trust boundary ({§extension-discovery}). Each
|
|
3657
|
+
framework owns its typed discovery result and trusted loading path.
|
|
3655
3658
|
Core owns only cross-family composition, arbitration, and operator presentation
|
|
3656
3659
|
of skipped-package evidence.
|
|
3657
3660
|
|
|
3658
|
-
§
|
|
3659
|
-
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
|
|
3660
3663
|
package name. Core's bundled names are reserved claims. A daemon module's
|
|
3661
3664
|
runtime registration names its module owner and makes one composite executor
|
|
3662
3665
|
claim: its ordinary output scheme and optional resource facet do not compete
|
|
@@ -3667,8 +3670,8 @@ claiming either name, for process-wide and workspace-scoped registrations alike.
|
|
|
3667
3670
|
|--------------------------------|---------------------------------------------------------|---------|
|
|
3668
3671
|
| None | Any valid claim | Register it. |
|
|
3669
3672
|
| Same installed family/package | Rescan of the same name | No-op; retain the one registered handler. |
|
|
3670
|
-
| Reserved core name | Any
|
|
3671
|
-
| 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. |
|
|
3672
3675
|
| Module runtime | Its optional same-registration scheme facet | Compose one handler under the runtime's single claim. |
|
|
3673
3676
|
|
|
3674
3677
|
Arbitration precedes host registry mutation. External scheme descriptors are
|
|
@@ -3684,15 +3687,21 @@ registration.
|
|
|
3684
3687
|
|
|
3685
3688
|
## §bundled-set Bundled Set
|
|
3686
3689
|
|
|
3687
|
-
Family discovery ({§
|
|
3690
|
+
Family discovery ({§extension-discovery}) scans installed scoped and unscoped
|
|
3688
3691
|
packages carrying the applicable `plurnk.kind` declaration.
|
|
3689
3692
|
|
|
3690
|
-
§default-
|
|
3691
|
-
of the default
|
|
3692
|
-
|
|
3693
|
-
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
|
|
3694
3697
|
framework consumer may intentionally omit leaves and receives that framework's
|
|
3695
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
|
+
|
|
3696
3705
|
Packed executor coverage distinguishes installation from enablement: verify
|
|
3697
3706
|
the package floor, explicit opt-in, and composed allowlist/disable behavior
|
|
3698
3707
|
through discovery and registration outside the development dependency graph
|
|
@@ -3705,19 +3714,19 @@ the checkout's development dependency graph, and proves each optional language
|
|
|
3705
3714
|
degrades by name when its leaf is absent.
|
|
3706
3715
|
|
|
3707
3716
|
§install-root-advisory-ownership **The composed service install owns
|
|
3708
|
-
third-party advisory detection.** Only that install resolves the default
|
|
3717
|
+
third-party advisory detection.** Only that install resolves the default extensions
|
|
3709
3718
|
and their combined transitive tree. Its audit reports advisories at the
|
|
3710
3719
|
moderate floor without blocking by default; strict mode makes the same floor a
|
|
3711
3720
|
gate. A chain rooted through an `@plurnk/*` dependency routes to that package's
|
|
3712
3721
|
owner, while other direct roots remain service-owned. First-party package-pin
|
|
3713
3722
|
freshness remains the owning family's concern.
|
|
3714
3723
|
|
|
3715
|
-
|
|
|
3724
|
+
| Kind | Lean framework | Service-owned default extensions |
|
|
3716
3725
|
|-----------|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
|
|
3717
3726
|
| Schemes | `@plurnk/plurnk-schemes` | `@plurnk/plurnk-schemes-http` |
|
|
3718
3727
|
| Mimetypes | `@plurnk/plurnk-mimetypes` | `application-ipynb`, `application-json`, `application-jsonl`, and `application-xml` format leaves. |
|
|
3719
3728
|
| | | `text-csv`, `text-diff`, `text-dotenv`, `text-html`, `text-ini`, `text-markdown`, and `text-plain` format leaves. |
|
|
3720
|
-
| | | `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-*`. |
|
|
3721
3730
|
| Executors | `@plurnk/plurnk-execs` | `common`, `jq`, and `sqlite` leaves under the `@plurnk/plurnk-execs-*` prefix. |
|
|
3722
3731
|
|
|
3723
3732
|
The independently published `tokenizers` artifact is an opt-in leaf. Installing
|
|
@@ -3727,7 +3736,7 @@ native attachment like an image, and the daemon does no extraction (#542).
|
|
|
3727
3736
|
|
|
3728
3737
|
**Providers:** `@plurnk/plurnk-providers` resolves the Models.dev catalog,
|
|
3729
3738
|
operator declarations, local adapters, and finally installed AI SDK provider
|
|
3730
|
-
|
|
3739
|
+
extensions. `Mock` is its integration fixture. Core contains no vendor protocol.
|
|
3731
3740
|
|
|
3732
3741
|
**Core schemes:** `file`, `log`, `prompt`, `skill`, and `worker` expose daemon
|
|
3733
3742
|
state or filesystem orchestration owned by core. `exec` is internal dispatch
|
|
@@ -3738,8 +3747,8 @@ dispatcher contract.
|
|
|
3738
3747
|
|
|
3739
3748
|
The executor registry discovers installed runtimes, probes availability, and
|
|
3740
3749
|
routes ```` ```<runtime> ````; core contributes orchestration and the output-scheme
|
|
3741
|
-
adapter, not runtime implementations. Optional and third-party
|
|
3742
|
-
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
|
|
3743
3752
|
service manifest edit.
|
|
3744
3753
|
|
|
3745
3754
|
---
|
|
@@ -3807,11 +3816,11 @@ Node's pre-script env-file form and the executable's post-script form share the
|
|
|
3807
3816
|
|
|
3808
3817
|
| Source | Panel | Admission |
|
|
3809
3818
|
|---|---|---|
|
|
3810
|
-
|
|
|
3811
|
-
| 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 |
|
|
3812
3821
|
|
|
3813
3822
|
Root and trust flags apply before collection. A project plugin contributes no native panel.
|
|
3814
|
-
Non-module native panels follow their npm-only family discovery ({§
|
|
3823
|
+
Non-module native panels follow their npm-only family discovery ({§extension-manifest-read});
|
|
3815
3824
|
a plain-folder declaration does not suppress an installed capability's panel.
|
|
3816
3825
|
Linked packages resolve panels against the same canonical root as native code;
|
|
3817
3826
|
an absent panel is optional, but a panel escaping that root is rejected.
|
|
@@ -3865,6 +3874,7 @@ names the offending variable or file/entry and retains its cause.
|
|
|
3865
3874
|
| A2A | Whole outbound definitions and controls, timeout/diagnostic bounds, configured inbound exposure |
|
|
3866
3875
|
| Schedule | Whole definitions and controls, recurrence syntax, time zone and preview count |
|
|
3867
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}) |
|
|
3868
3878
|
|
|
3869
3879
|
Disabled definitions and controls without a resource are validated, not skipped.
|
|
3870
3880
|
Checking creates no database, starts no process or listener, arms no schedule,
|
|
@@ -3893,7 +3903,7 @@ Each knob's value lives on its panel and nowhere else (`plurnk-service config de
|
|
|
3893
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. |
|
|
3894
3904
|
| `PLURNK_SERVICE_FILE_MATERIALIZE_MAX_BYTES` | Byte ceiling in `1..104857600` for one workspace-file snapshot ({§membership-materialization-limit}). |
|
|
3895
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. |
|
|
3896
|
-
| `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). |
|
|
3897
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. |
|
|
3898
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}. |
|
|
3899
3909
|
| `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF` | First recovery delay (ms); doubles per failure up to `PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF_MAX` ({§provider-recovery}). |
|
|
@@ -3904,8 +3914,6 @@ Each knob's value lives on its panel and nowhere else (`plurnk-service config de
|
|
|
3904
3914
|
| `PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES` | Surrounding and landed lines shown at each EDIT result boundary ({§edit-result-receipt-projection}). |
|
|
3905
3915
|
| `PLURNK_SERVICE_MIN_CYCLES` | Min repetitions before cycle detection fires ({§engine-rails}). |
|
|
3906
3916
|
| `PLURNK_SERVICE_MAX_CYCLE_PERIOD` | Max period length cycle detection examines ({§engine-rails}). |
|
|
3907
|
-
| `PLURNK_SERVICE_REQUIEM_MAX_TOKENS` | Initial forensic witness output allowance ({§digest-requiem}). |
|
|
3908
|
-
| `PLURNK_SERVICE_REQUIEM_RETRY_MAX_TOKENS` | Retry allowance; must be at least the initial requiem allowance ({§digest-requiem}). |
|
|
3909
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}). |
|
|
3910
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}). |
|
|
3911
3919
|
| `PLURNK_SERVICE_EXEC_CONCURRENCY` | Executions admitted at once per workspace; the rest queue FIFO with `202 queued` receipts; `-1` unbounded ({§exec-concurrency}). |
|
|
@@ -3929,9 +3937,9 @@ instead of a user's boot, and a dead knob cannot ship.
|
|
|
3929
3937
|
|
|
3930
3938
|
Feature-flag bools use `process.env.X === "1"` exactly — never `=== "true"`.
|
|
3931
3939
|
|
|
3932
|
-
External
|
|
3940
|
+
External extensions declare their own env vars in their own `.env.defaults`, assembled at boot ({§operator-config-env-defaults}).
|
|
3933
3941
|
|
|
3934
|
-
§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.
|
|
3935
3943
|
|
|
3936
3944
|
### Loop limits
|
|
3937
3945
|
|
|
@@ -3978,9 +3986,9 @@ leak into another.
|
|
|
3978
3986
|
workspace: a client tightens the runaway-op guard and never raises it past
|
|
3979
3987
|
the operator's.
|
|
3980
3988
|
- §operator-config-workspace-max-commands-floor The cap bounds *actions* only.
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
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}.
|
|
3984
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.
|
|
3985
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`.
|
|
3986
3994
|
- `settings.membersModelScope` narrows `PLURNK_SERVICE_MEMBERS_MODEL_SCOPE` ({§members-model-scope}).
|
|
@@ -4037,9 +4045,10 @@ a fresh-user configuration.
|
|
|
4037
4045
|
|
|
4038
4046
|
## §rpc Module seam
|
|
4039
4047
|
|
|
4040
|
-
Core implements the contracts-owned {§application-port} and
|
|
4041
|
-
|
|
4042
|
-
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
|
|
4043
4052
|
client-interface module such as `plurnk-agui` owns its public protocol, action
|
|
4044
4053
|
names, request validation, discovery result, and event projection.
|
|
4045
4054
|
|
|
@@ -4047,13 +4056,13 @@ names, request validation, discovery result, and event projection.
|
|
|
4047
4056
|
|
|
4048
4057
|
```mermaid
|
|
4049
4058
|
flowchart LR
|
|
4050
|
-
bind["Host
|
|
4051
|
-
register["
|
|
4059
|
+
bind["Host binds the daemon's listener<br/>unadmitted"] --> register
|
|
4060
|
+
register["Register explicit, then discovered modules"] --> setup["module.setup(ModuleSetupSeam)"]
|
|
4052
4061
|
setup --> capabilities["Register static capabilities,<br/>workspace activators, and actions"]
|
|
4053
4062
|
capabilities --> ready["Process-wide schemes ready"]
|
|
4054
4063
|
ready --> recovery["Reconcile durable lifecycle"]
|
|
4055
4064
|
recovery --> start["module.start(ApplicationPort)"]
|
|
4056
|
-
start --> interface["
|
|
4065
|
+
start --> interface["Listener admitted:<br/>module-owned client protocol ready"]
|
|
4057
4066
|
recovery -->|durable workspace work| demand["First workspace demand"]
|
|
4058
4067
|
interface -->|client workspace work| demand
|
|
4059
4068
|
demand --> lease["Acquire capability residency"]
|
|
@@ -4070,17 +4079,17 @@ flowchart LR
|
|
|
4070
4079
|
```
|
|
4071
4080
|
|
|
4072
4081
|
Every registered module's `setup` runs in registration order before any
|
|
4073
|
-
module's `start
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
{§startup-listener-admission}
|
|
4077
|
-
|
|
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
|
|
4078
4087
|
no durable work stay passive until first demand; activation publishes their
|
|
4079
4088
|
complete capabilities and documentation before the demanding operation
|
|
4080
4089
|
proceeds. `setup` is the readiness boundary for every capability registered
|
|
4081
|
-
with Core: recovery may demand a workspace provider before `start`.
|
|
4082
|
-
|
|
4083
|
-
|
|
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
|
|
4084
4093
|
registered capability may depend on exterior ingress. A module, and any distinct
|
|
4085
4094
|
lifetime object returned by `start`, may implement the following phases:
|
|
4086
4095
|
|
|
@@ -4097,21 +4106,26 @@ even if setup fails. A returned object identical to its module is tracked once.
|
|
|
4097
4106
|
|
|
4098
4107
|
| Source | Declaration | Lifetime |
|
|
4099
4108
|
|---|---|---|
|
|
4100
|
-
|
|
|
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 |
|
|
4101
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 |
|
|
4102
4111
|
| Project Agent Plugin | Portable components only | Workspace-scoped; native code is not imported |
|
|
4103
4112
|
|
|
4104
|
-
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
|
|
4105
4117
|
{§agent-plugins-hosting} source order, then other installed module packages load in package-name
|
|
4106
|
-
order. All trusted modules register before setup
|
|
4107
|
-
|
|
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
|
|
4108
4121
|
declarations, unavailable module files and configuration errors during construction are diagnosed
|
|
4109
|
-
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
|
|
4110
4124
|
configuration before `setup` acquires resources. Failures after registration begins follow
|
|
4111
4125
|
{§module-lifecycle} cleanup, not a partial-registration fallback.
|
|
4112
4126
|
An invalid module object, factory result or lifecycle member is an implementation contract failure,
|
|
4113
|
-
not configuration, and fails loudly.
|
|
4114
|
-
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.
|
|
4115
4129
|
|
|
4116
4130
|
§module-shutdown-order `Daemon.stop()` first rejects new capability demand and
|
|
4117
4131
|
aborts proposals, branches, derivations, and worker scopes. It begins module
|
|
@@ -4157,18 +4171,21 @@ flowchart LR
|
|
|
4157
4171
|
observers --> database[Maintain and release database]
|
|
4158
4172
|
```
|
|
4159
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
|
+
|
|
4160
4180
|
| Setup function | Contract |
|
|
4161
4181
|
|---|---|
|
|
4162
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. |
|
|
4163
|
-
| `registerScheme(name, handler)` | Adds one process-wide addressable scheme handler; scheme readiness and model-facing capability publication remain core-owned. |
|
|
4164
|
-
| §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. |
|
|
4165
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. |
|
|
4166
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}). |
|
|
4167
|
-
| `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. |
|
|
4168
|
-
| §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. |
|
|
4169
|
-
| §module-functionality-adapter `registerFunctionalityAdapter(adapter)` | Registers one family beneath the shared coordinator ({§functionality-coordinator}). |
|
|
4170
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. |
|
|
4171
4186
|
|
|
4187
|
+
Core keys each {§module-workspace-directory} by a stable random workspace
|
|
4188
|
+
storage key in its own `workspace_module_state` row.
|
|
4172
4189
|
Module directory allocation is lazy, atomic in SQLite, and independent of the
|
|
4173
4190
|
project root, daemon CWD, and workspace/worker environment overrides. New
|
|
4174
4191
|
directories use mode `0700`; existing permissions are not rewritten. Module
|
|
@@ -4180,6 +4197,14 @@ workspace forgets its storage key through the existing foreign key; old disk
|
|
|
4180
4197
|
state is not reassigned or automatically purged. A database copy preserves its
|
|
4181
4198
|
storage identities; the directory is operational state, not a backup of it.
|
|
4182
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
|
+
|
|
4183
4208
|
§workspace-environment-sharing **The workspace owns its shared environment.**
|
|
4184
4209
|
Workers own their logs; delegation retains its existing lifecycle.
|
|
4185
4210
|
Creating, attaching, forking, cancelling, or deleting a worker does not create,
|
|
@@ -4319,7 +4344,10 @@ composition boundaries, not arbitrary exceptions:
|
|
|
4319
4344
|
| Internal invariant, state, or implementation failure | Preserve the exception; never reclassify it as an operator configuration error. |
|
|
4320
4345
|
|
|
4321
4346
|
Client discovery and passive synchronization report startup diagnostics through the
|
|
4322
|
-
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
|
|
4323
4351
|
thereafter, reports unresolved configuration to both client and model. An
|
|
4324
4352
|
unchanged diagnostic is not repeated every turn. Operation failures remain Problems.
|
|
4325
4353
|
|
|
@@ -4350,32 +4378,6 @@ publication contract, and creates no log entries or model Notices. Published
|
|
|
4350
4378
|
failures retain their exact Problems in `list`. Concurrent consumers share the
|
|
4351
4379
|
workspace activity; a client disconnect does not clear another consumer's work.
|
|
4352
4380
|
|
|
4353
|
-
§functionality-adapter **An adapter owns protocol truth.** It declares its
|
|
4354
|
-
family, namespace owner, definition schema, contributed defaults, discovery,
|
|
4355
|
-
admission, preparation, and teardown, and its alias grammar when that is not
|
|
4356
|
-
the shared lowercase-hyphen one: the coordinator enforces whichever grammar the
|
|
4357
|
-
family declares, at admission, in the service projection, and on persisted
|
|
4358
|
-
state, so an environment variable's name is an alias exactly as a skill name
|
|
4359
|
-
is. Admission distinguishes explicit client
|
|
4360
|
-
actions from model operations where the family contract requires it
|
|
4361
|
-
({§members-model-scope}). Preparation receives each complete definition with optional
|
|
4362
|
-
adapter-owned interpretation context. Context is source semantics, not policy or provenance;
|
|
4363
|
-
it participates in runtime identity and hot-load comparisons, is never projected as configuration
|
|
4364
|
-
or persisted into a workspace override, and cannot survive replacement by a local definition.
|
|
4365
|
-
Removing that override restores the current inherited definition and context together.
|
|
4366
|
-
Descriptive provenance alone does not change runtime identity. Preparation returns runtimes, documents, per-alias
|
|
4367
|
-
outcomes, and a snapshot with `commit`/`abort`. Successful publication commits;
|
|
4368
|
-
failure aborts; cooling tears down. Protocol continuations remain ordinary
|
|
4369
|
-
module actions. Optional `forget` releases an installed or provisioned
|
|
4370
|
-
definition before removal; failure rejects removal. The
|
|
4371
|
-
seam's shapes — the identity a verb acts under, its options, definition
|
|
4372
|
-
sources, outcomes, preparation, the prepared result and the family handle —
|
|
4373
|
-
are declared once in `plurnk-contracts` and imported by core and every
|
|
4374
|
-
module; core adds only its own face of the seam, the runtime registration a
|
|
4375
|
-
resident family prepares and the scheme facet it may expose.
|
|
4376
|
-
An adapter may expose current partial-source `configurationNotices`; these join the ordinary
|
|
4377
|
-
workspace diagnostics without preventing independently valid definitions from preparing.
|
|
4378
|
-
|
|
4379
4381
|
§functionality-hotload **Out-of-band state is admitted before the next turn.** An adapter whose
|
|
4380
4382
|
`available` reads state that changes outside the daemon, such as skill roots ({§skills-hotload}) or
|
|
4381
4383
|
installed plugins ({§agent-plugins-hosting}), implements `refreshIfChanged`. Turn admission calls it
|
|
@@ -4415,9 +4417,10 @@ its discovery roots explicitly ({§operator-config-real-model-profile}), so
|
|
|
4415
4417
|
operator roots do not shape a gate. Root selection does not restrict explicit
|
|
4416
4418
|
source definitions. Skills mutations change workspace bindings, not these roots
|
|
4417
4419
|
({§skills-functionality}); MCP mutations likewise remain workspace-owned. The module setup seam's
|
|
4418
|
-
`
|
|
4419
|
-
|
|
4420
|
-
|
|
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.
|
|
4421
4424
|
|
|
4422
4425
|
An adapter may expose a `scheme` facet beneath its family's runtime namespace
|
|
4423
4426
|
({§runtime-resource-binding}). A facet claims a path subtree and is the scheme's
|
|
@@ -4853,13 +4856,13 @@ adding a loop to it. LOOK text anchors resolve through the same
|
|
|
4853
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. |
|
|
4854
4857
|
| §notifications-workspace-created `workspace/created` | `{ id, name, projectRoot }` | A workspace is created. This is the only current global event. |
|
|
4855
4858
|
| `workspace/preparation` | `{ workspaceId, preparation: FunctionalityPreparationActivity[] }` | Workspace capability preparation changes; snapshot and clearing semantics follow {§functionality-preparation-visibility}. |
|
|
4856
|
-
| §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. |
|
|
4857
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. |
|
|
4858
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. |
|
|
4859
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. |
|
|
4860
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. |
|
|
4861
4864
|
|
|
4862
|
-
§notifications-stream-event-failure-isolation The
|
|
4865
|
+
§notifications-stream-event-failure-isolation The extension-facing
|
|
4863
4866
|
`NotifyCaps.streamEvent()` remains a synchronous advisory call while core
|
|
4864
4867
|
resolves its entry identity asynchronously.
|
|
4865
4868
|
|
|
@@ -4897,7 +4900,7 @@ without an origin filter ({§actor-boundary-isolation}).
|
|
|
4897
4900
|
## §packet-assembly Packet assembly
|
|
4898
4901
|
|
|
4899
4902
|
`PacketBuilder.buildRequestPacket` owns the engine's default ordered section
|
|
4900
|
-
list. Trusted scheme
|
|
4903
|
+
list. Trusted scheme extensions may transform that first-class list before it is
|
|
4901
4904
|
rendered or measured; {§context-fit} remains an engine-owned post-build rail.
|
|
4902
4905
|
|
|
4903
4906
|
```mermaid
|
|
@@ -4922,11 +4925,12 @@ The packet reaches the provider as a transcript, under the roles the model was t
|
|
|
4922
4925
|
Only role boundaries are added: joined by blank lines, the user messages are the user slot's
|
|
4923
4926
|
bytes, in record order. An emission is placed exactly when its row is present in the final log
|
|
4924
4927
|
section, so curation governs the transcript: a KILLed emission row, or one a trusted transform
|
|
4925
|
-
removed ({§packet-
|
|
4928
|
+
removed ({§packet-extension-transform}), takes its emission with it, and a log without emission rows
|
|
4926
4929
|
is one user message. An emission of only NOTE and WAIT delivers nothing, so its record runs on
|
|
4927
4930
|
into the next user message. The Worker block and the status clump always follow the log, so a
|
|
4928
4931
|
request never ends on an emission, and the projection refuses one that would. The digest's packet
|
|
4929
|
-
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.
|
|
4930
4934
|
|
|
4931
4935
|
### §packet-cache-monotone Default order and cache locality
|
|
4932
4936
|
|
|
@@ -4957,7 +4961,7 @@ operator notes and policies can change. Trust is a separate
|
|
|
4957
4961
|
admission rule. The system slot contains trusted control-plane material;
|
|
4958
4962
|
attacker-reachable content stays in the user slot.
|
|
4959
4963
|
|
|
4960
|
-
### §packet-
|
|
4964
|
+
### §packet-extension-transform Trusted whole-list extension seam
|
|
4961
4965
|
|
|
4962
4966
|
`SchemeRegistry.transformSections` pipes the complete default list through
|
|
4963
4967
|
every registered scheme implementing `transformSections(sections) -> sections`,
|
|
@@ -4970,7 +4974,7 @@ sections. It receives no separate engine, database, actor, or request context.
|
|
|
4970
4974
|
Emission placement reads the final log section, so a transform that removes an
|
|
4971
4975
|
emission row's record removes its emission from the transcript ({§packet-wire-envelope}).
|
|
4972
4976
|
|
|
4973
|
-
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
|
|
4974
4978
|
trust gate; an external client action cannot invoke it. Whole-list transformation is
|
|
4975
4979
|
the fork-avoidance valve for alternate packet shapes, while
|
|
4976
4980
|
overflow recovery and packet projection remain closed engine concerns.
|
|
@@ -5123,8 +5127,8 @@ header. A null header renders only its content. Empty content is omitted, traili
|
|
|
5123
5127
|
newlines are removed from each section, and rendered sections are separated by one
|
|
5124
5128
|
blank line. Any node whose content is empty is absent from the wire, except the
|
|
5125
5129
|
child-orientation sections, which state emptiness as `[]` ({§packet-empty-sections}).
|
|
5126
|
-
Core owns the order at {§packet-cache-monotone}; a trusted
|
|
5127
|
-
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
|
|
5128
5132
|
the evidence section owners supply: paths, URI fragments, log coordinates, scopes and
|
|
5129
5133
|
coordinate-prefixed body lines remain usable without translation; curation and log-row
|
|
5130
5134
|
measurements stay attached to what they measure ({§tokenomics-agnostic-ruler});
|
|
@@ -5173,7 +5177,7 @@ whose INSTEAD OF trigger refuses a turn that is not an open model inference turn
|
|
|
5173
5177
|
items, the composition, the bag, and the provider metadata together. Readers of a whole packet
|
|
5174
5178
|
select from `turn_packets`, which assembles `sections` back into the bag byte for byte (the digest,
|
|
5175
5179
|
and every test that inspects a stored packet); statements that need one field read the bag
|
|
5176
|
-
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
|
|
5177
5181
|
item. Items no composition references are transient data: `retention_collect_packet_items`
|
|
5178
5182
|
collects them under the retention policy ({§retention-policy}), which is how a deleted worker's or
|
|
5179
5183
|
workspace's packets release their space while shared items survive. A fork copies the composition
|
|
@@ -5197,42 +5201,12 @@ operation turns and therefore store `NULL`. Digest projects exact operation
|
|
|
5197
5201
|
source independently from this optional model-exchange record; a request-only
|
|
5198
5202
|
turn receives a note instead of a fabricated response.
|
|
5199
5203
|
|
|
5200
|
-
|
|
5201
|
-
After selectors are applied, digest retains every turn with exact content or reasoning source, a
|
|
5202
|
-
valid stored provider request, or malformed stored packet evidence; orders those
|
|
5203
|
-
turns by durable chronology; and names each by its log coordinate ({§share-packet-names}). The
|
|
5204
|
-
producer does not affect projection.
|
|
5205
|
-
|
|
5206
|
-
§share-packet-names **Packet artifacts carry the coordinate the log uses.** A turn's files are named
|
|
5207
|
-
`<worker>-<loop>-<turn>`, the worker's name and the loop and turn sequences that `log:///<loop>/<turn>/…`
|
|
5208
|
-
addresses: the model's first turn in its first loop is `<worker>-1-2`, because the initialization
|
|
5209
|
-
survey is turn 1 and writes no packet. A digest spanning several workspaces nests each workspace's
|
|
5210
|
-
files in a folder named for it. `digest.json` records each turn's stem as `artifact`, so no
|
|
5211
|
-
consumer reconstructs a name. A name that cannot be a file name, or two turns sharing one, fails.
|
|
5212
|
-
|
|
5213
|
-
| Artifact | Present when | Authority |
|
|
5214
|
-
|----------|--------------|-----------|
|
|
5215
|
-
| `<stem>.assistant.md` | The turn has an `ops` source | Exact `turn_sources.content`, independent of log rows |
|
|
5216
|
-
| `<stem>.reasoning.md` | The turn has a `reasoning` source | Exact `turn_sources.content`, without relabeling it as content |
|
|
5217
|
-
| `<stem>.system.md`, `<stem>.user.md` | The turn stored a provider request | Stored text sections projected through `PacketWire`; native parts are not Markdown |
|
|
5218
|
-
| `<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 |
|
|
5219
|
-
| `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. |
|
|
5220
|
-
| `<stem>.assistantRaw.json` | The request has an admitted provider response | Stored opaque provider response |
|
|
5221
|
-
| `<stem>.response.md`, attempt artifacts | The request received no admitted response | Stored request and attempt state |
|
|
5222
|
-
| `<stem>.packet.raw.txt` | The stored packet fails typed validation | Exact stored packet text |
|
|
5223
|
-
| `<stem>.packet.invalid.json` | The stored packet fails typed validation | Turn identity and complete validation error chain |
|
|
5224
|
-
|
|
5225
|
-
A source-backed turn without provider participation produces only its source-channel
|
|
5226
|
-
artifacts; a request-only turn produces no fabricated assistant. A
|
|
5227
|
-
source-less programmatic turn with no provider request has no forensic payload
|
|
5228
|
-
to project and writes no files.
|
|
5229
|
-
|
|
5230
|
-
The external tokenless draft and transformation boundary is owned by
|
|
5204
|
+
he external tokenless draft and transformation boundary is owned by
|
|
5231
5205
|
{§scheme-packet-transform}. Core alone extends each validated draft with its
|
|
5232
5206
|
measured `weight` field for storage. #74 tracks coverage that mistakes the sum
|
|
5233
5207
|
of section weights for the rendered request weight.
|
|
5234
5208
|
|
|
5235
|
-
§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.
|
|
5236
5210
|
|
|
5237
5211
|
§lexicon **Vocabulary follows the standard of its audience.**
|
|
5238
5212
|
|
|
@@ -5261,11 +5235,11 @@ Retired terms stay retired: the lexicon guard rejects `thinking`, the unqualifie
|
|
|
5261
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}) |
|
|
5262
5236
|
| structured `EDIT` receipt or textual `COPY`/`MOVE` effects | complete receipt-owned join context |
|
|
5263
5237
|
| every other nonempty body | the model's own: complete; what it did not author: its first page ({§markerless-first-page}); then {§context-fit} |
|
|
5264
|
-
| the `reasoning` row | the
|
|
5238
|
+
| the `reasoning` row | the optional reasoning preview under {§reasoning-row} |
|
|
5265
5239
|
| a row the wall took | its size and address, no body and no native part ({§context-own-rows-fit}) |
|
|
5266
5240
|
| bodyless row | heading and any facts; no coordinate lines; `tokens` includes any selected native part |
|
|
5267
5241
|
|
|
5268
|
-
§markerless-first-page **What the model did not ask for in size arrives as its first page.** A READ or FIND without a scope, a stream delivered when a command closes, a peer worker's message, an environment delta, an extension's body and a rejected emission shown back all arrive as their first page: `PLURNK_SERVICE_PREVIEW_LINES` lines and at most `PLURNK_SERVICE_PREVIEW_CHARS` characters, in the projection's own units — lines of text, bytes of a byte view ({§read-bytes}), results of a FIND — with one fact in one notation stating the page and the whole, `<1,100> of 4812 lines` (`range` on a retrieval, `preview` on a stored body, {§packet-extent-metadata}). What the model authored stands whole: a NOTE, a WAIT, the body of its SEND, the prompt of its WORK or FORK, the command it handed an executor
|
|
5242
|
+
§markerless-first-page **What the model did not ask for in size arrives as its first page.** A READ or FIND without a scope, a stream delivered when a command closes, a peer worker's message, an environment delta, an extension's body and a rejected emission shown back all arrive as their first page: `PLURNK_SERVICE_PREVIEW_LINES` lines and at most `PLURNK_SERVICE_PREVIEW_CHARS` characters, in the projection's own units — lines of text, bytes of a byte view ({§read-bytes}), results of a FIND — with one fact in one notation stating the page and the whole, `<1,100> of 4812 lines` (`range` on a retrieval, `preview` on a stored body, {§packet-extent-metadata}). What the model authored stands whole: a NOTE, a WAIT, the body of its SEND, the prompt of its WORK or FORK, and the command it handed an executor. Its own reasoning, when it lands as a row, stands whole only when it fits the row's page and otherwise takes its last page ({§reasoning-row}). What it asked for exactly stands whole: an explicit scope — `<a,b>`, `<1,-1>`, a pattern — and an EDIT receipt, bounded by its own rule ({§edit-result-receipt-truth}). The operator's message keeps its own rule ({§message-projection}) and an emission row its head ({§emission-row}); those are the only exceptions, so the model can reason about every page the same way. A page lands under {§context-fit} like any result: whole when it fits the remaining budget, otherwise the prefix and receipt. Retrievals take their page at the source, before storage, and the packet applies no second cut to a stored result; a stored body takes its page in the packet, and the rest stays readable at the row's address. No operation carries a page size of its own.
|
|
5269
5243
|
|
|
5270
5244
|
READ and FIND own their range or pagination before packet rendering; the packet never applies a second hidden substring bound to their selected result. Reasoning arrives through ordinary scoped READs ({§reasoning-history}). When a visible projection differs from its canonical body, metadata carries `preview` under {§packet-extent-metadata}; complete and fully suppressed bodies omit it. ```` ```READ (log:///<coordinate>/<OP>) ```` selects untrimmed lines in original coordinates under {§log-readable-projection}; the unsuffixed exact shorthand and authoritative suffix behavior are defined by {§log-coordinate-hierarchy}. ```` ```FIND (log:///...) ```` and search match that same readable view. System/policy sections are not log bodies. Notices are transient non-log observations; they share the ordinary line/character bounds but have no durable body or recovery URI.
|
|
5271
5245
|
|
|
@@ -5416,83 +5390,14 @@ the same deadline through {§application-loop-observation}, not a restarted cloc
|
|
|
5416
5390
|
|
|
5417
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.
|
|
5418
5392
|
|
|
5419
|
-
§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.
|
|
5420
|
-
|
|
5421
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.
|
|
5422
5394
|
|
|
5423
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`.
|
|
5424
5396
|
|
|
5425
|
-
§
|
|
5426
|
-
|
|
5427
|
-
| Surface | Contract |
|
|
5428
|
-
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
5429
|
-
| 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. |
|
|
5430
|
-
| `run({ dbPath })` | Reads the required database and writes a complete digest to `./test/digest` relative to the caller's working directory. |
|
|
5431
|
-
| `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. |
|
|
5432
|
-
| 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. |
|
|
5433
|
-
| §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. |
|
|
5434
|
-
| 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. |
|
|
5435
|
-
| `workerId` | Narrows workers and every dependent loop, turn, turn-attached logical inference, specialization, physical request, and log row to that one worker. |
|
|
5436
|
-
| `workspaceId` | Narrows workers plus every logical inference and dependent evidence owned by one workspace, when both selectors are present they intersect. |
|
|
5437
|
-
|
|
5438
|
-
§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.
|
|
5439
5398
|
|
|
5440
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.
|
|
5441
5400
|
|
|
5442
|
-
§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.
|
|
5443
|
-
|
|
5444
|
-
§digest-cache-ledger **Measured cache reuse and estimated prompt overlap are separate.**
|
|
5445
|
-
|
|
5446
|
-
| Projection | Meaning |
|
|
5447
|
-
|---|---|
|
|
5448
|
-
| `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. |
|
|
5449
|
-
| Turn `cache=<cached>/<input>` | Sum each measured quantity over that turn's requests. If any request omits a quantity, that sum is `?`. |
|
|
5450
|
-
| 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)`. |
|
|
5451
|
-
| `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. |
|
|
5452
|
-
|
|
5453
|
-
The prefix estimate uses the stored emission packet's wire message order, roles
|
|
5454
|
-
and content. A BARE request's input is not that packet; its prefix estimate and
|
|
5455
|
-
the following request's comparison are unknown. The estimate is
|
|
5456
|
-
neither provider tokenization nor a cache ceiling, and never supplies a cache-ratio
|
|
5457
|
-
denominator. Caching across loops or against other provider-resident prefixes
|
|
5458
|
-
does not make the measured counters inconsistent.
|
|
5459
|
-
|
|
5460
|
-
§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.
|
|
5461
|
-
|
|
5462
|
-
§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.
|
|
5463
|
-
|
|
5464
|
-
Unrecognized actionless log rows are retained and labelled as such, not
|
|
5465
|
-
interpreted as executable turnOps or allowed to prevent the remaining digest.
|
|
5466
|
-
|
|
5467
|
-
§digest-executor-evidence **A red command is work, not a defect.** Engine-materialized
|
|
5468
|
-
completion rows for a failed command carry the executor's problem identity
|
|
5469
|
-
(`https://problems.plurnk.xyz/executor/*`), and the digest classifies them as
|
|
5470
|
-
evidence: they render like any row but never count toward a loop's error total,
|
|
5471
|
-
its health verdict, or the per-turn `errs=` badge — a loop that concluded green
|
|
5472
|
-
over red test runs is CLEAN, not DEGENERATE-WIN. This is the digest mirror of the
|
|
5473
|
-
strike rail's exemption ({§engine-rails}, #425 F1): structural violations count,
|
|
5474
|
-
executor evidence never does.
|
|
5475
|
-
|
|
5476
|
-
§digest-requiem **A requiem is an out-of-band forensic interview, not a worker
|
|
5477
|
-
turn.** It cannot execute operations or alter the audited history.
|
|
5478
|
-
|
|
5479
|
-
| Aspect | Contract |
|
|
5480
|
-
|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
5481
|
-
| Scope | One interview for each worker with model-bearing inference turns; workers without inference evidence are omitted. |
|
|
5482
|
-
| 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}). |
|
|
5483
|
-
| Witness | An explicitly supplied provider or the active configured provider; absence fails hard. |
|
|
5484
|
-
| Identity | The worker's durable provider identity ({§worker-provider-identity}) is sent as the `workerId`, without asserting a live worker topology. |
|
|
5485
|
-
| 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`. |
|
|
5486
|
-
| 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. |
|
|
5487
|
-
|
|
5488
|
-
§digest-requiem-evidence-budget **Quoted evidence fits the witness.** The
|
|
5489
|
-
interview's user message is budgeted against the witness provider's context
|
|
5490
|
-
window minus the retry output allowance and system framing (chars/2, the
|
|
5491
|
-
capacity gate's own estimator). Overflow elides the oldest provider attempts
|
|
5492
|
-
behind an explicit `elidedOldestAttempts` count marker, never silently; the
|
|
5493
|
-
final packet and the newest attempts always testify. A windowless witness
|
|
5494
|
-
(`contextWindow` null) quotes unbudgeted.
|
|
5495
|
-
|
|
5496
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}).
|
|
5497
5402
|
|
|
5498
5403
|
§turn-accounting-notice **The completion beat carries the spend.** `turn_generated`
|
|
@@ -5510,9 +5415,9 @@ content-offset position: reasoning coordinates do not address the content source
|
|
|
5510
5415
|
§tools-resource-discovery **Executable capability discovery uses ordinary
|
|
5511
5416
|
Plurnk resources.** No generated tool table rides the system packet. Every
|
|
5512
5417
|
runtime enabled for the current worker with an admitted invocation materializes one
|
|
5513
|
-
|
|
5418
|
+
runtime document at `worker:///_plurnk/plurnk/<runtime>.md`. A general runtime's
|
|
5514
5419
|
document contains its {§executor-tool-document}; a runtime with an exact
|
|
5515
|
-
{§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
|
|
5516
5421
|
the server or runtime, lists every enabled target as a directly copyable
|
|
5517
5422
|
executable fence named for the runtime, with its input preview ({§operation-aside} carries the
|
|
5518
5423
|
target one-liner; no invocation dispatch would reject is ever advertised).
|
|
@@ -5523,13 +5428,13 @@ preserve the full tool description and raw input schema under
|
|
|
5523
5428
|
Turn0 rows. A schema-backed general runtime uses `<runtime>/input.md`.
|
|
5524
5429
|
Non-schema targets retain supplemental details in family sections.
|
|
5525
5430
|
Tool-result/output schemas remain ordinary evidence, not teaching. Unknown-target
|
|
5526
|
-
recovery names the published
|
|
5431
|
+
recovery names the published runtime document through the same path owner as
|
|
5527
5432
|
materialization, including a runtime's declared `resourcesPath`.
|
|
5528
5433
|
|
|
5529
5434
|
```mermaid
|
|
5530
5435
|
flowchart LR
|
|
5531
|
-
Survey["Turn 0 FIND<br/>tools/*.md"] -->
|
|
5532
|
-
|
|
5436
|
+
Survey["Turn 0 FIND<br/>tools/*.md"] --> Runtimes["runtime paths + summaries"]
|
|
5437
|
+
Runtimes --> Read["READ selected runtime<br/>only when needed"]
|
|
5533
5438
|
Read --> Exec["execution with an aside"]
|
|
5534
5439
|
Read --> Schema["READ linked input schema<br/>when the preview is insufficient"]
|
|
5535
5440
|
Schema --> Exec
|
|
@@ -5538,19 +5443,19 @@ flowchart LR
|
|
|
5538
5443
|
§tools-resource-materialization The runtime registry, workspace capability policy,
|
|
5539
5444
|
tool resources, and dispatch use one effective workspace snapshot. A
|
|
5540
5445
|
disabled, unavailable, detached, replaced, or removed runtime has no
|
|
5541
|
-
tool resource; an exact registry's empty set publishes no
|
|
5446
|
+
tool resource; an exact registry's empty set publishes no runtime and
|
|
5542
5447
|
admits no invocation. Reconciliation deletes stale documents
|
|
5543
5448
|
before upserting the current set. `PLURNK_SERVICE_DOCS_EXCLUDE` does not hide an
|
|
5544
5449
|
enabled executable; executor enablement is the sole user-configured filter
|
|
5545
5450
|
shared by discovery and dispatch. A runtime declaration may carry
|
|
5546
5451
|
`resourcesPath` — its generated-doc root relative to the workspace's generated
|
|
5547
5452
|
subtree ({§worker-generated-subtree}). Absent, its docs live in the internal
|
|
5548
|
-
`_plurnk/plurnk` namespace; present (attached MCP
|
|
5549
|
-
the
|
|
5550
|
-
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
|
|
5551
5456
|
(worker:///_plurnk/tools/*.md)`, one row per
|
|
5552
5457
|
server carrying its summary) and, for each server named in
|
|
5553
|
-
`PLURNK_MCP_EXPANDED`, adds one FIND over its
|
|
5458
|
+
`PLURNK_MCP_EXPANDED`, adds one FIND over its runtime document matching the
|
|
5554
5459
|
complete executable blocks (`FIND (worker:///_plurnk/tools/<server>.md)`
|
|
5555
5460
|
with a multiline regex over matching fences), so turn 0 names every tool with its aside and
|
|
5556
5461
|
signature — one row per tool, paged like every survey. Capability attenuation
|
|
@@ -5630,155 +5535,27 @@ definitions ({§actor-boundary-catalog-preview}), so the model sees why a file i
|
|
|
5630
5535
|
not a member before it asks. There is no other membership path: the client's `/members`
|
|
5631
5536
|
verbs are these verbs.
|
|
5632
5537
|
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
its adapter owns protocol truth for standard Agent Skills and nothing else. A
|
|
5636
|
-
definition is `SkillDefinition`: the standard skill `name`, its `source`, and
|
|
5637
|
-
optional Git `ref`/resolved `commit` ({§skills-sources}). Only a host-provided
|
|
5638
|
-
resource tree omits `source`. Source location is not mutation ownership: standard
|
|
5639
|
-
project/global roots are read-only configuration inputs; live changes belong to
|
|
5640
|
-
the workspace. Plurnk neither installs into nor deletes from those roots.
|
|
5641
|
-
|
|
5642
|
-
*Available definitions.* The filesystem is the only truth about installation:
|
|
5643
|
-
every `<root>/<name>/SKILL.md` directory under the project, plurnk, then global
|
|
5644
|
-
root is one service-origin definition, a nearer root shadowing a farther one and
|
|
5645
|
-
all of them shadowing host-provided trees by name. Each filesystem definition
|
|
5646
|
-
names its actual source directory. The workspace's durable state owns
|
|
5647
|
-
enablement ({§functionality-state}); a disabled skill stays client-visible and
|
|
5648
|
-
leaves no model-facing trace.
|
|
5649
|
-
|
|
5650
|
-
§skills-configuration **Skills use the shared definition cascade.**
|
|
5651
|
-
|
|
5652
|
-
| Layer, low to high | Definition source |
|
|
5653
|
-
|---|---|
|
|
5654
|
-
| Service | Host-provided trees |
|
|
5655
|
-
| Standard locations | Global, plurnk, then project roots selected by {§agent-roots} |
|
|
5656
|
-
| Cascading environment | `PLURNK_SKILLS_<name>={"name":"<name>","source":"…","ref"?:"…"}` replaces the complete definition |
|
|
5657
|
-
| Live workspace | `skills (add)` creates a workspace definition through {§functionality-coordinator} |
|
|
5658
|
-
|
|
5659
|
-
`PLURNK_SKILLS_ENABLED` supplies default enabledness; `<name>_ENABLED` overrides
|
|
5660
|
-
it independently ({§resource-environment}). The decoded environment alias must
|
|
5661
|
-
equal the standard skill name, including digit-leading and Unicode names.
|
|
5662
|
-
Blank definitions are invalid; controls may precede a definition. Environment
|
|
5663
|
-
validation checks shape, names, remote URL rules, and Git-only `ref` without
|
|
5664
|
-
fetching or opening a source; `commit` is service-recorded, not an input.
|
|
5665
|
-
|
|
5666
|
-
*Discovery is inert.* `discover {source}` lists the standard skills one source
|
|
5667
|
-
carries, each a candidate with `source` provenance and the exact definition to
|
|
5668
|
-
add; it never installs, persists, or enables. Agent Skills have no standard
|
|
5669
|
-
registry, so `discover {query}` is 400 `query-unsupported`, naming the source
|
|
5670
|
-
forms. Client `configuration` contributes nothing and is refused with 400.
|
|
5671
|
-
|
|
5672
|
-
*Admission.* `add {alias, definition}` requires `alias = name` and a `source`;
|
|
5673
|
-
the workspace definition may shadow a service skill of the same name. Relative
|
|
5674
|
-
sources require a project root; absolute sources work in headless workspaces.
|
|
5675
|
-
A local source is recorded as its absolute path.
|
|
5676
|
-
A git source records the `commit` its `ref` names at admission, or its default
|
|
5677
|
-
branch's when no `ref` is given; `ref` belongs to git sources, and a supplied
|
|
5678
|
-
`commit` is refused because the service records it. The family's aliases use
|
|
5679
|
-
the standard skill-name grammar ({§agent-skills-name}), including digit-leading
|
|
5680
|
-
and Unicode names, rather than the coordinator's generic default.
|
|
5681
|
-
|
|
5682
|
-
*Preparation.* For each enabled alias the adapter selects the host-provided
|
|
5683
|
-
tree or resolves the complete source definition ({§skills-sources}). Local
|
|
5684
|
-
folders and their `SKILL.md` files remain live references, including supporting
|
|
5685
|
-
resources and symlink retargeting. Git/archive sources are materialized only
|
|
5686
|
-
inside {§module-workspace-directory}; different workspaces and complete source
|
|
5687
|
-
definitions cannot reuse each other's materializations accidentally.
|
|
5688
|
-
The first fetched Git/archive copy remains stable across enable, cooling, and
|
|
5689
|
-
restart until the complete source definition changes. In particular, an
|
|
5690
|
-
operator-configured symbolic Git ref is not an implicit update subscription.
|
|
5691
|
-
Each admitted skill requires standard `name` and `description` frontmatter
|
|
5692
|
-
with `name` matching its directory. A missing, uninstallable, or invalid skill
|
|
5693
|
-
is `unavailable` with its exact Problem ({§problems-functionality}) under the
|
|
5694
|
-
coordinator's failure policy ({§functionality-model-mutation}); one bad skill
|
|
5695
|
-
never fails the family.
|
|
5696
|
-
|
|
5697
|
-
Removal follows {§skills-remove}.
|
|
5698
|
-
|
|
5699
|
-
§skills-sources **A source is a git remote, a folder, or a file, read with standard tools.**
|
|
5700
|
-
Fetching runs nothing it fetched. Materialized copies cannot contain references
|
|
5701
|
-
outside their skill; live resources retain {§agent-skills-directory} containment.
|
|
5702
|
-
|
|
5703
|
-
| Source | How it is read |
|
|
5704
|
-
|---|---|
|
|
5705
|
-
| 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` |
|
|
5706
|
-
| Folder: absolute, `~/`, or relative to the project root | Live reference; standard directory/name matching applies |
|
|
5707
|
-
| A file named `SKILL.md` | Live reference to its skill directory and supporting resources |
|
|
5708
|
-
| 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 |
|
|
5709
|
-
|
|
5710
|
-
Any other scheme, plain `http`, `owner/repo` shorthand, and an https URL carrying
|
|
5711
|
-
credentials are refused with `source-invalid` or `source-missing`: shorthand names no
|
|
5712
|
-
forge, and a recorded source is listed to every client. Git runs with the
|
|
5713
|
-
operator's configuration, credentials, and SSH agent, never plurnk's secrets, and
|
|
5714
|
-
never prompts; `PLURNK_SERVICE_SKILLS_FETCH_TIMEOUT_MS` bounds each fetch. The
|
|
5715
|
-
retired vendor-installer knobs (`PLURNK_SERVICE_SKILLS_CLI`, `_CLI_TIMEOUT_MS`,
|
|
5716
|
-
`_REGISTRY_URL`, `_REGISTRY_LIMIT`, `_REGISTRY_TIMEOUT_MS`) make the skills family
|
|
5717
|
-
unavailable when set, each naming what replaced it ({§configuration-repair-path}).
|
|
5718
|
-
|
|
5719
|
-
A source's skills are the directories holding a `SKILL.md`, found by walking
|
|
5720
|
-
from its root without entering `.git` or a skill already found. A fetched skill at
|
|
5721
|
-
the root is named by its frontmatter ({§agent-skills-name}); local references and
|
|
5722
|
-
directories below the root use the standard folder rule. A source with `plugin.json` at its root is an
|
|
5723
|
-
Agent Plugin and is refused with 422 `source-is-plugin`, so its skills keep the
|
|
5724
|
-
plugin's identity. Materialization copies the named skill beside its workspace-owned destination
|
|
5725
|
-
and renames it to `<root>/<name>`; a copy that holds a link out of the skill, or
|
|
5726
|
-
anything but files, directories, and inward links, is refused with 422
|
|
5727
|
-
`source-unsafe` and leaves nothing behind.
|
|
5728
|
-
|
|
5729
|
-
§skills-resources **A skill is a resource tree, not a rewritten document.**
|
|
5730
|
-
The family exposes enabled, available {§agent-skills-tree} sources through
|
|
5731
|
-
`skill://<name>/`. The source owns its bytes; commons entries are demand-loaded
|
|
5732
|
-
projections, not writable installations. Filesystem skills retain their original
|
|
5733
|
-
directories; service-provided trees need no generated filesystem directory.
|
|
5734
|
-
The authority is the name's WHATWG URI representation, including percent-encoding
|
|
5735
|
-
for non-ASCII names. Installation names remain unchanged; a raw spelling and its
|
|
5736
|
-
serialized URI address the same resource, not separate skill identities.
|
|
5737
|
-
|
|
5738
|
-
| Operation | Contract |
|
|
5739
|
-
| --- | --- |
|
|
5740
|
-
| 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. |
|
|
5741
|
-
| `READ (skill://<name>/SKILL.md)` | Original frontmatter and Markdown, unchanged; relative links remain relative to the source layout. |
|
|
5742
|
-
| `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. |
|
|
5743
|
-
| ```` ```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. |
|
|
5744
|
-
| Model mutation | Read-only; no EDIT, SEND, or KILL of skill resources. Manage definitions and enablement through ```` ```skills ````. |
|
|
5745
|
-
| Disable / unavailable / remove | Withdraw the authority from new resource access and discovery. Existing log receipts remain historical evidence. |
|
|
5746
|
-
| WORK / FORK | Use the same workspace Functionality, not copied definitions or resource caches. |
|
|
5747
|
-
|
|
5748
|
-
Explicit skill URIs address these resources; bare operation paths still address
|
|
5749
|
-
project files, with no implicit current-skill directory. Source resolution follows
|
|
5750
|
-
{§agent-skills-directory}, including symlinked skill directories and containment of references.
|
|
5751
|
-
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}.
|
|
5752
5540
|
|
|
5753
5541
|
§plurnk-skill **Plurnk's own reference is an ordinary service-provided skill.**
|
|
5754
5542
|
`skill://plurnk/SKILL.md` is the standard frontmatter entry point, catalogued with
|
|
5755
|
-
other enabled skills. It links package-owned configuration, model,
|
|
5756
|
-
the complete `.env.defaults` aggregate at `skill://plurnk/.env.defaults`,
|
|
5757
|
-
|
|
5758
|
-
|
|
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
|
|
5759
5553
|
same {§operator-config-env-defaults} renderer as the operator command, never the
|
|
5760
5554
|
effective environment. Native chapter files retain their owners and locations;
|
|
5761
5555
|
runtime-generated bytes have no invented disk location. Disable/enable,
|
|
5762
5556
|
shared workspace visibility, and project/global shadowing use the ordinary Skills lifecycle.
|
|
5763
5557
|
Service-provided skills are not installer targets; removal follows {§skills-remove}.
|
|
5764
5558
|
|
|
5765
|
-
§skills-remove **`remove` forgets the workspace binding, not the source.**
|
|
5766
|
-
It withdraws that definition and restores any inherited definition and enabledness
|
|
5767
|
-
({§functionality-coordinator}). External folders are never deleted. Fetched
|
|
5768
|
-
materializations remain workspace-owned operational state, reusable only for the
|
|
5769
|
-
same complete definition; they confer no availability without a definition.
|
|
5770
|
-
Inherited definitions cannot be removed here; their enabledness can be overridden.
|
|
5771
|
-
|
|
5772
|
-
§skills-hotload **Skills placed out of band are admitted at the next turn** ({§functionality-hotload}). The
|
|
5773
|
-
family keeps one signature of the discovered roots, configured definitions, source locations, and `SKILL.md` sources
|
|
5774
|
-
per resident workspace, read before a publication loads the skills it describes. Turn admission
|
|
5775
|
-
recomputes it under the workspace gate before packet assembly: a changed signature republishes the
|
|
5776
|
-
family, and an unchanged one republishes only when the skills the coordinator would publish differ
|
|
5777
|
-
from the published ones. A skill installed, edited or removed by any other tool is therefore
|
|
5778
|
-
discoverable in the first subsequent model turn, while an unchanged set dispatches nothing. The model manages skills
|
|
5779
|
-
only through the generated ```` ```skills ```` family
|
|
5780
|
-
({§functionality-model-projection}); it is never taught a package manager.
|
|
5781
|
-
|
|
5782
5559
|
The catalog and Turn0 describe Functionality under the current workspace
|
|
5783
5560
|
capability policy and service ceiling. A direct denied attempt receives the
|
|
5784
5561
|
same exact 403 from dispatch rather than a second documentation policy.
|
|
@@ -5800,7 +5577,7 @@ section because they are language extensions rather than executable tools.
|
|
|
5800
5577
|
|
|
5801
5578
|
### §inject system.inject — the operator injection
|
|
5802
5579
|
|
|
5803
|
-
§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.
|
|
5804
5581
|
|
|
5805
5582
|
### §policy system.policy — the client's policy injection
|
|
5806
5583
|
|
|
@@ -6193,12 +5970,12 @@ caller's own run directory.
|
|
|
6193
5970
|
|
|
6194
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.
|
|
6195
5972
|
|
|
6196
|
-
§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).
|
|
6197
5974
|
|
|
6198
5975
|
| code | status | contract |
|
|
6199
5976
|
|---|---:|---|
|
|
6200
5977
|
| `target-required` | 400 | *OP* requires a target path. Recovery: Write the target in parentheses on the opening fence line: `OP (path)`. |
|
|
6201
|
-
| `scheme-not-found` | 501 | Scheme '*name*' is not registered. |
|
|
5978
|
+
| `scheme-not-found` | 501 | Scheme '*name*' is not registered. Recovery: ({§unregistered-scheme-recovery}) `` `*host*` is an executor: run ```*host* (*tool*)``` with its input in the body. `` when the address's authority is one, else `Registered schemes: *names*.` |
|
|
6202
5979
|
| `scheme-metadata-unsupported` | 400 | *OP* on '*scheme*' does not accept the [metadata] modifier. |
|
|
6203
5980
|
| `operation-not-implemented` | 501 | Scheme '*name*' does not implement *OP* (or exec). |
|
|
6204
5981
|
| `entry-read-not-implemented` | 501 | The '*scheme*' scheme does not provide entry reads. |
|
|
@@ -6209,7 +5986,7 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6209
5986
|
| `exec-source-not-data` | 501 | Scheme '*name*' is not a data source for an execution. |
|
|
6210
5987
|
| `writer-forbidden` | 403 | Writer '*origin*' cannot modify scheme '*name*'. |
|
|
6211
5988
|
| `capability-denied` | 403 | Capability '*route*' is denied by *scope* policy. |
|
|
6212
|
-
| `spawn-prompt-empty` | 422 | *OP* has no prompt text: the resource is empty and there is no body. |
|
|
5989
|
+
| `spawn-prompt-empty` | 422 | *OP* has no prompt text. Recovery: Write the prompt on the lines beneath the *OP* fence line. A prompt resource that is empty with no body says so: *OP* has no prompt text: the resource is empty and there is no body. Recovery: Write the prompt on the lines beneath the *OP* fence line, or name a resource that holds it. |
|
|
6213
5990
|
| `message-not-found` | 404 | No accepted message exists at *address*. |
|
|
6214
5991
|
| `edit-collision` | 409 | EDIT collided with the current resource state ({§edit-collision}). Recovery: *n* of *m* edits applied. READ the target for current coordinates. |
|
|
6215
5992
|
| `edit-target-required` | 400 | A line-anchored EDIT requires a target resource. Recovery: Provide the target that rendered the line anchor. |
|
|
@@ -6225,7 +6002,13 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6225
6002
|
| `no-operation` | 422 | The turn performed no operation ({§empty-turn}). |
|
|
6226
6003
|
| `send-target-not-a-recipient` | 400 | The addressed scheme is not a SEND recipient. Recovery: A targetless SEND answers the open messages; a directed SEND requires a recipient that implements SEND. |
|
|
6227
6004
|
|
|
6228
|
-
§
|
|
6005
|
+
§unregistered-scheme-recovery **An unregistered scheme's refusal names what does exist.** When the
|
|
6006
|
+
address's authority is an executor available to the workspace — an MCP server's tool written as
|
|
6007
|
+
`tool://gh/get_me` — the recovery is that executor's fence with the address's path as its target;
|
|
6008
|
+
otherwise it lists the schemes the workspace registers. READ, FIND, KILL and resource selection share
|
|
6009
|
+
the sentence.
|
|
6010
|
+
|
|
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).
|
|
6229
6012
|
|
|
6230
6013
|
| code | status | contract |
|
|
6231
6014
|
|---|---:|---|
|
|
@@ -6242,7 +6025,7 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6242
6025
|
| `proposal-apply-missing` | 500 | The source scheme accepted its MOVE proposal without applying the source mutation. |
|
|
6243
6026
|
| `line-anchor-collision` | 409 | READ coordinates collided with current content at *target*. |
|
|
6244
6027
|
|
|
6245
|
-
§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).
|
|
6246
6029
|
|
|
6247
6030
|
| code | status | contract |
|
|
6248
6031
|
|---|---:|---|
|
|
@@ -6259,18 +6042,18 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6259
6042
|
| `file-create-excluded` | 403 | A members exclusion (`!_glob_`) covers '*path*'. Recovery: Remove or disable the excluding members definition, or choose another path. |
|
|
6260
6043
|
| `file-create-gitignored` | 403 | Active Git policy ignores '*path*', and no members definition includes it. Recovery: Choose a Git-admitted path or add a members definition that includes it. |
|
|
6261
6044
|
| `file-materialization-limit` | 413 | The file exceeds the materialization byte limit and is not read into the workspace. |
|
|
6262
|
-
| `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. |
|
|
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. |
|
|
6263
6046
|
|
|
6264
|
-
§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).
|
|
6265
6048
|
|
|
6266
6049
|
| code | status | contract |
|
|
6267
6050
|
|---|---:|---|
|
|
6268
6051
|
| `invalid-input-target` | 400 | SEND input addresses an execution, without a channel or scope. |
|
|
6269
6052
|
| `input-unavailable` | 409 | This execution's input receiver is no longer enabled. |
|
|
6270
|
-
| `stream-not-found` | 404 | No execution exists at the requested address. |
|
|
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*`. |
|
|
6271
6054
|
| `input-closed` | 410 | Execution input is closed. |
|
|
6272
6055
|
|
|
6273
|
-
§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).
|
|
6274
6057
|
|
|
6275
6058
|
| code | status | contract |
|
|
6276
6059
|
|---|---:|---|
|
|
@@ -6283,7 +6066,7 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6283
6066
|
| `message-empty` | 400 | SEND has no message text or attachments. |
|
|
6284
6067
|
| `scope-unsupported` | 400 | A worker SEND takes no scope. |
|
|
6285
6068
|
|
|
6286
|
-
§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).
|
|
6287
6070
|
|
|
6288
6071
|
| code | status | contract |
|
|
6289
6072
|
|---|---:|---|
|
|
@@ -6295,21 +6078,8 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6295
6078
|
| `env-invalid` | 400 | `env` must be an object of string values; '*name*' is not a name a shell can export. |
|
|
6296
6079
|
| `query-required` | 400 | discover takes a path or a glob. Recovery: Supply `{ "query": "<path or glob>" }`. |
|
|
6297
6080
|
| `headless` | 409 | The workspace has no project root, so there are no file members. Recovery: Open the workspace on a project root. |
|
|
6298
|
-
| `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. |
|
|
6299
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. |
|
|
6300
|
-
| `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. |
|
|
6301
|
-
| `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. |
|
|
6302
|
-
| `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). |
|
|
6303
|
-
| `source-unreadable` | 422 | '*source*' cannot be read: *cause*; or '*path*' could not be unpacked: *reason*. |
|
|
6304
|
-
| `source-unreachable` | 502 | git could not reach '*remote*', or fetch it (at '*ref*'): *reason*. |
|
|
6305
|
-
| `ref-missing` | 404 | '*remote*' has no branch or tag '*ref*', or names no default branch. |
|
|
6306
|
-
| `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. |
|
|
6307
|
-
| `source-is-plugin` | 422 | '*source*' is an Agent Plugin; install it as a plugin, so its skills keep the plugin's identity and servers. |
|
|
6308
|
-
| `source-unsafe` | 422 | '*path*' links outside its skill, or is neither a file, a directory, nor an inward link. |
|
|
6309
|
-
| `skill-not-found` | 404 | '*source*' carries no Agent Skill named '*name*'. |
|
|
6310
|
-
| `skill-ambiguous` | 409 | '*source*' carries *count* skills named '*name*'. |
|
|
6311
|
-
| `alias-mismatch` | 400 | Alias '*alias*' must equal the skill name '*name*'. |
|
|
6312
|
-
| `source-required` | 400 | Adding '*alias*' requires the source that provides it. |
|
|
6313
6083
|
| `workspace-not-found` | 404 | Workspace *id* does not exist. |
|
|
6314
6084
|
| `state-not-json` | 400 | Worker module state is not JSON-serializable. |
|
|
6315
6085
|
| `workspace-busy` | 409 | Workspace *id* is running an operation or another capability change. Recovery: Settle the current operation and retry the capability change. |
|
|
@@ -6322,9 +6092,6 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6322
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. |
|
|
6323
6093
|
| `scope-cancelled` | 499 | The worker scope was cancelled: *reason*. |
|
|
6324
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. |
|
|
6325
|
-
| `install-failed` | 500 | Agent Skill '*name*' could not be placed under *root*: *cause*. |
|
|
6326
|
-
| `skill-missing` | 404 | Agent Skill '*alias*' is not provided by this service. |
|
|
6327
|
-
| `skill-invalid` | 422 | Agent Skill '*alias*' is not a valid standard skill: *cause*. |
|
|
6328
6095
|
|
|
6329
6096
|
§pinned-wording-core **Pinned wording.** Verbatim sentences tests pin: each is contract, and a change here is a change of contract.
|
|
6330
6097
|
|
|
@@ -6343,3 +6110,4 @@ Every Problem code core mints is named here under its family ({§problem-error-c
|
|
|
6343
6110
|
| The execution at ops://*worker*/*loop* has not concluded. | a bare READ of a running worker's result (425) |
|
|
6344
6111
|
| The child provider failed. | a child's provider failure read back by its parent |
|
|
6345
6112
|
| '*path*' exists on disk but is not a member of this workspace. Recovery: Admit it with `members (add)` and a `{"glob": "<path>"}` body. | a non-member on disk at the addressed path |
|
|
6113
|
+
| '*path*' exists on disk but is not a member of this workspace. Recovery: The repository ignores it: a client or operator members definition can include it, a model definition cannot. | a non-member the repository ignores ({§membership-read-refusal}) |
|