@plurnk/plurnk-service 1.22.0 → 1.23.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 +4 -0
- package/SPEC.md +256 -20
- package/dist/build-info.json +1 -1
- package/dist/content/body-preview.js +1 -1
- package/dist/content/body-preview.js.map +1 -1
- package/dist/content/edit-receipt.d.ts.map +1 -1
- package/dist/content/edit-receipt.js +3 -10
- package/dist/content/edit-receipt.js.map +1 -1
- package/dist/content/line-anchors.d.ts.map +1 -1
- package/dist/content/line-anchors.js +7 -9
- package/dist/content/line-anchors.js.map +1 -1
- package/dist/content/matcher.js +1 -1
- package/dist/content/matcher.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +2 -0
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BudgetReadout.js +1 -1
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +3 -8
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +8 -16
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/EditMutations.js +2 -2
- package/dist/core/EditMutations.js.map +1 -1
- package/dist/core/Engine.d.ts +8 -19
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +22 -19
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Engine.sql +22 -0
- package/dist/core/ErrorDetail.d.ts +3 -4
- package/dist/core/ErrorDetail.d.ts.map +1 -1
- package/dist/core/ErrorDetail.js +3 -18
- package/dist/core/ErrorDetail.js.map +1 -1
- package/dist/core/ExecutorRegistry.js +1 -1
- package/dist/core/ExecutorRegistry.js.map +1 -1
- package/dist/core/HostPaths.d.ts +1 -0
- package/dist/core/HostPaths.d.ts.map +1 -1
- package/dist/core/HostPaths.js +39 -13
- package/dist/core/HostPaths.js.map +1 -1
- package/dist/core/LogBody.d.ts.map +1 -1
- package/dist/core/LogBody.js +9 -8
- package/dist/core/LogBody.js.map +1 -1
- package/dist/core/LoopDriver.js +1 -1
- package/dist/core/LoopDriver.js.map +1 -1
- package/dist/core/LoopPolicies.js +1 -1
- package/dist/core/LoopPolicies.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +5 -1
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/PreviousEmission.d.ts +14 -0
- package/dist/core/PreviousEmission.d.ts.map +1 -0
- package/dist/core/PreviousEmission.js +24 -0
- package/dist/core/PreviousEmission.js.map +1 -0
- package/dist/core/ProposalLifecycle.d.ts +9 -13
- package/dist/core/ProposalLifecycle.d.ts.map +1 -1
- package/dist/core/ProposalLifecycle.js +5 -7
- package/dist/core/ProposalLifecycle.js.map +1 -1
- package/dist/core/ProviderRecovery.d.ts.map +1 -1
- package/dist/core/ProviderRecovery.js +2 -7
- package/dist/core/ProviderRecovery.js.map +1 -1
- package/dist/core/SchemeRegistry.d.ts +2 -1
- package/dist/core/SchemeRegistry.d.ts.map +1 -1
- package/dist/core/SchemeRegistry.js +10 -2
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/TurnRunner.d.ts +4 -10
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +22 -41
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/TurnSources.sql +15 -0
- package/dist/core/file-materialization.d.ts.map +1 -1
- package/dist/core/file-materialization.js +4 -3
- package/dist/core/file-materialization.js.map +1 -1
- package/dist/core/git-env.d.ts.map +1 -1
- package/dist/core/git-env.js +2 -7
- package/dist/core/git-env.js.map +1 -1
- package/dist/core/git-state.js +1 -1
- package/dist/core/git-state.js.map +1 -1
- package/dist/core/notifications.d.ts +17 -0
- package/dist/core/notifications.d.ts.map +1 -0
- package/dist/core/notifications.js +2 -0
- package/dist/core/notifications.js.map +1 -0
- package/dist/core/packet-inject.d.ts.map +1 -1
- package/dist/core/packet-inject.js +2 -3
- package/dist/core/packet-inject.js.map +1 -1
- package/dist/core/packet-wire.d.ts +3 -2
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +92 -13
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/teaching.js +1 -1
- package/dist/core/teaching.js.map +1 -1
- package/dist/digest/Digest.d.ts.map +1 -1
- package/dist/digest/Digest.js +10 -2
- package/dist/digest/Digest.js.map +1 -1
- package/dist/digest/DigestRender.d.ts +3 -1
- package/dist/digest/DigestRender.d.ts.map +1 -1
- package/dist/digest/DigestRender.js +186 -1
- package/dist/digest/DigestRender.js.map +1 -1
- package/dist/digest/DigestRequiem.d.ts.map +1 -1
- package/dist/digest/DigestRequiem.js +2 -10
- package/dist/digest/DigestRequiem.js.map +1 -1
- package/dist/digest/digest-rows.d.ts +26 -0
- package/dist/digest/digest-rows.d.ts.map +1 -1
- package/dist/digest/digest-rows.js +1 -1
- package/dist/digest/digest-rows.js.map +1 -1
- package/dist/digest/digest.sql +10 -0
- package/dist/launch/Launch.d.ts +49 -0
- package/dist/launch/Launch.d.ts.map +1 -0
- package/dist/launch/Launch.js +179 -0
- package/dist/launch/Launch.js.map +1 -0
- package/dist/observe/spans.d.ts +1 -1
- package/dist/observe/spans.d.ts.map +1 -1
- package/dist/observe/spans.js +5 -64
- package/dist/observe/spans.js.map +1 -1
- package/dist/schemes/EffectPolicy.js +1 -1
- package/dist/schemes/EffectPolicy.js.map +1 -1
- package/dist/schemes/Exec.d.ts +2 -2
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +20 -16
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecutionInput.d.ts.map +1 -1
- package/dist/schemes/ExecutionInput.js +2 -5
- package/dist/schemes/ExecutionInput.js.map +1 -1
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +6 -1
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/_entry-graph.d.ts.map +1 -1
- package/dist/schemes/_entry-graph.js +2 -6
- package/dist/schemes/_entry-graph.js.map +1 -1
- package/dist/schemes/_entry-manifest.js +1 -1
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/schemes/_search-index.d.ts.map +1 -1
- package/dist/schemes/_search-index.js +2 -8
- package/dist/schemes/_search-index.js.map +1 -1
- package/dist/schemes/exec-abort.js +1 -1
- package/dist/schemes/exec-abort.js.map +1 -1
- package/dist/schemes/exec-lifetime.d.ts.map +1 -1
- package/dist/schemes/exec-lifetime.js +2 -1
- package/dist/schemes/exec-lifetime.js.map +1 -1
- package/dist/server/ClientReads.d.ts +1 -1
- package/dist/server/ClientReads.d.ts.map +1 -1
- package/dist/server/ClientReads.js +1 -1
- package/dist/server/ClientReads.js.map +1 -1
- package/dist/server/Daemon.d.ts +10 -7
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +12 -3
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DaemonModule.d.ts +2 -63
- package/dist/server/DaemonModule.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.js +10 -1
- package/dist/server/DrainSupervisor.js.map +1 -1
- package/dist/server/EnvFunctionality.d.ts +2 -1
- package/dist/server/EnvFunctionality.d.ts.map +1 -1
- package/dist/server/EnvFunctionality.js.map +1 -1
- package/dist/server/Functionality.d.ts +2 -1
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/MembersFunctionality.d.ts +2 -1
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js +1 -1
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/SkillsFunctionality.d.ts +2 -1
- package/dist/server/SkillsFunctionality.d.ts.map +1 -1
- package/dist/server/SkillsFunctionality.js +1 -1
- package/dist/server/SkillsFunctionality.js.map +1 -1
- package/dist/server/WorkspaceResidency.d.ts +2 -1
- package/dist/server/WorkspaceResidency.d.ts.map +1 -1
- package/dist/server/WorkspaceResidency.js.map +1 -1
- package/dist/server/client-input.d.ts +1 -1
- package/dist/server/client-input.d.ts.map +1 -1
- package/dist/server/envelope.d.ts +2 -9
- package/dist/server/envelope.d.ts.map +1 -1
- package/dist/server/envelope.js +2 -2
- package/dist/server/envelope.js.map +1 -1
- package/dist/server/envelope.sql +6 -3
- package/dist/server/logEntry.d.ts +1 -31
- package/dist/server/logEntry.d.ts.map +1 -1
- package/dist/server/logEntry.js.map +1 -1
- package/dist/server/model-catalog.js +1 -1
- package/dist/server/model-catalog.js.map +1 -1
- package/dist/server/module-discovery.d.ts.map +1 -1
- package/dist/server/module-discovery.js +4 -22
- package/dist/server/module-discovery.js.map +1 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +4 -1
- package/dist/service.js.map +1 -1
- package/docs/env.md +18 -0
- package/package.json +37 -33
- package/dist/core/Knob.d.ts +0 -9
- package/dist/core/Knob.d.ts.map +0 -1
- package/dist/core/Knob.js +0 -50
- package/dist/core/Knob.js.map +0 -1
package/.env.defaults
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
# Database path; empty = $XDG_DATA_HOME/plurnk/plurnk.db (~/.local/share by default).
|
|
11
11
|
# Module operational state: $XDG_STATE_HOME/plurnk (~/.local/state/plurnk by default).
|
|
12
12
|
PLURNK_SERVICE_DB_PATH=
|
|
13
|
+
# A private daemon's root ({§state-root}): empty = the XDG homes; an absolute path (a leading ~/
|
|
14
|
+
# expands) roots data, state, cache and runtime under it as <root>/{data,state,cache,runtime}/plurnk.
|
|
15
|
+
# Configuration and the shared Agent Skills root never move; PLURNK_SERVICE_DB_PATH still wins.
|
|
16
|
+
PLURNK_SERVICE_STATE_ROOT=
|
|
13
17
|
# Where `share` writes when no folder is named: each share is a stamped child folder.
|
|
14
18
|
# A leading ~/ expands; empty = $XDG_STATE_HOME/plurnk/shares (~/.local/state/plurnk/shares by default).
|
|
15
19
|
PLURNK_SERVICE_SHARE_FOLDER=
|
package/SPEC.md
CHANGED
|
@@ -224,6 +224,32 @@ before provider or capability initialization can perform external work. Every
|
|
|
224
224
|
later startup failure closes resources in reverse ownership order while
|
|
225
225
|
preserving the originating failure: daemon, observability, database, listener.
|
|
226
226
|
|
|
227
|
+
§startup-readiness-line **Readiness is one stdout line.** After the client interface is mounted
|
|
228
|
+
the service prints exactly one line, `plurnk-service agui=<url> db=<json string> route=<json string>`:
|
|
229
|
+
the URL brackets an IPv6 host, and the database path and the route (the active model route or
|
|
230
|
+
`no model`) are JSON strings, so a path or route containing spaces is exact and a consumer parses
|
|
231
|
+
the URL as a URL and the strings as JSON; nothing else the service prints on stdout before it has
|
|
232
|
+
that prefix. Before the line the listener answers `503 service-starting`; after it,
|
|
233
|
+
`discover` is the identity check a launcher uses to tell this daemon from any other listener. A bind
|
|
234
|
+
failure is an exit with the originating address error and means *occupied*, not *foreign* — another
|
|
235
|
+
plurnk-service may be starting there, and only `discover` says which.
|
|
236
|
+
|
|
237
|
+
§daemon-launch **The service ships its own launcher; launchers own policy.** `@plurnk/plurnk-service/launch`
|
|
238
|
+
spawns a daemon argv with the caller's environment, an optional {§state-root}, host and port, and
|
|
239
|
+
resolves on the readiness line with the published address, database path, route and a `stop()` that
|
|
240
|
+
is SIGTERM, a stated grace, then SIGKILL, resolving when the process has ended. It holds no timing of
|
|
241
|
+
its own: the caller states the readiness timeout and the stop grace. A start that fails — spawn error,
|
|
242
|
+
exit before readiness, or timeout — is stopped and awaited before the failure is thrown with its kind
|
|
243
|
+
and both output streams; the helper never creates, keeps or removes state. A shared daemon survives
|
|
244
|
+
the launcher that started it (scheduled deliveries, other clients and inbound A2A depend on it); a
|
|
245
|
+
private daemon is its launcher's child and ends with it under managed shutdown. The launcher
|
|
246
|
+
spawns either: `lifetime: "private"` (the default) pipes both streams to the launcher; `lifetime:
|
|
247
|
+
"shared"` puts the daemon in its own process group with both streams appended to the caller's
|
|
248
|
+
`logFile`, reads readiness from that file, and releases the process once ready, so the launcher may
|
|
249
|
+
exit while the daemon runs on and no output accumulates in a launcher that has left; until
|
|
250
|
+
readiness the launcher owns it either way, and `stop()` ends it while the launcher lives. Shell and container
|
|
251
|
+
launchers consume the same contract by reading the line themselves.
|
|
252
|
+
|
|
227
253
|
## §actor-boundary Workers and workspace boundaries
|
|
228
254
|
|
|
229
255
|
```mermaid
|
|
@@ -352,7 +378,7 @@ direct-entry-plus-directory count; `-1` enables the ordinary markerless page;
|
|
|
352
378
|
unset / `0` disables previews. `log://` is absent because the current worker's
|
|
353
379
|
log already renders in present mode.
|
|
354
380
|
|
|
355
|
-
§worker-initialization-entry **Model-worker initialization is a real `_plurnk` turn.** A model worker's first loop begins with one packetless `{ producer="_plurnk", kind="initialization" }` turn submitted through {§turn-ops-admission-path}. Its reasoning and program are stored before execution. NOTEs from its reasoning and program, the orienting READ/FIND surveys, and the reasoning
|
|
381
|
+
§worker-initialization-entry **Model-worker initialization is a real `_plurnk` turn.** A model worker's first loop begins with one packetless `{ producer="_plurnk", kind="initialization" }` turn submitted through {§turn-ops-admission-path}. Its reasoning and program are stored before execution. NOTEs from its reasoning and program, the orienting READ/FIND surveys, and the reasoning READ in {§reasoning-initial-read} execute under {§op-execution-order}. Its program supplies the worked example as the first request's assistant message ({§packet-wire-envelope}); no program READ, actionless source row or simulated READ is added. Every orienting row is structurally classified `_plurnk` and `init`. The namespace surveys and their asides follow {§actor-boundary-catalog-preview}.
|
|
356
382
|
|
|
357
383
|
Incoming messages publish once as inbound SEND rows in the first model turn
|
|
358
384
|
({§message-arrival}); initialization neither READs nor archives them. The turn
|
|
@@ -574,18 +600,22 @@ Every admitted authority is a literal `workers.name`; self-addressing uses the c
|
|
|
574
600
|
`"parent": null` at a root, so a worker never infers its rank from silence.
|
|
575
601
|
- §packet-current-turn **The packet says who and which turn, below the log.** The
|
|
576
602
|
`## Worker` block is the first section after the log, carrying
|
|
577
|
-
`{"path": "worker://<name>", "parent": <address or null>, "loop": L, "turn": T}`:
|
|
578
|
-
whose child it is,
|
|
579
|
-
and `ops://<worker>/L/T` are the model's own and `log:///L/T/*` its rows
|
|
580
|
-
|
|
603
|
+
`{"path": "worker://<name>", "parent": <address or null>, "loop": L, "turn": T, "previousEmission": <ops address or null>}`:
|
|
604
|
+
the actor, whose child it is, the coordinate this packet's response becomes, so `reasoning://<worker>/L/T`
|
|
605
|
+
and `ops://<worker>/L/T` are the model's own and `log:///L/T/*` its rows, and the address of the program
|
|
606
|
+
the envelope's assistant message carries ({§packet-wire-envelope}), so the rows sharing that coordinate
|
|
607
|
+
are its receipts; a model never infers the present from the last row's coordinate, which may or may
|
|
608
|
+
not be its own turn. The block
|
|
581
609
|
changes every turn, so nothing of it precedes the log, and the packet carries no date, time
|
|
582
|
-
or zone anywhere. The
|
|
583
|
-
documented, not taught.
|
|
610
|
+
or zone anywhere. The coordinates and the last program's address only; the other source
|
|
611
|
+
addresses stay documented, not taught.
|
|
584
612
|
|
|
585
613
|
Worker control rides the daemon's inject seam (active→fold, idle→enqueue+drain), so the handler creates/branches the worker and hands off; the daemon owns provider + system prompt. FORK/WORK carry the seed task in the body and are their own ops, dispatched to worker control — never the entry-copy path.
|
|
586
614
|
|
|
587
615
|
## §membership File membership and project roots
|
|
588
616
|
|
|
617
|
+
A file is a member of a workspace when Git tracks it or a members definition includes it and none excludes it; only members can be READ, found by FIND, or changed by EDIT, and every member path resolves under the project root.
|
|
618
|
+
|
|
589
619
|
The project-file path has two explicit reconciliation gates. Internal entries do
|
|
590
620
|
not participate in this disk loop.
|
|
591
621
|
|
|
@@ -1070,6 +1100,15 @@ single operation captures the equivalent boundary before dispatch. This limits
|
|
|
1070
1100
|
only log-row selection: operation phasing and same-turn resource effects retain
|
|
1071
1101
|
their ordinary contracts.
|
|
1072
1102
|
|
|
1103
|
+
### §engine-notifications One bundle of daemon callbacks
|
|
1104
|
+
|
|
1105
|
+
The daemon's observation callbacks — stream, reasoning, outside-text and packet
|
|
1106
|
+
events, worker wake, inject and cancel, operation settlement, notices — are one
|
|
1107
|
+
declared bundle (`EngineNotifications`). The Engine receives them flat, carries
|
|
1108
|
+
them as one value, and every consumer reads the callbacks it uses from that
|
|
1109
|
+
value; adding one is a declaration and a use, never an edit to the constructors
|
|
1110
|
+
between. Scheme contexts still expose the specific callbacks a handler may call.
|
|
1111
|
+
|
|
1073
1112
|
### §engine-rails Engine rails
|
|
1074
1113
|
|
|
1075
1114
|
After each admitted turn, one inline verdict decides whether the loop continues.
|
|
@@ -1221,7 +1260,7 @@ Three current entry points:
|
|
|
1221
1260
|
|
|
1222
1261
|
### Engine → provider guarantees
|
|
1223
1262
|
|
|
1224
|
-
- `messages` is a complete prompt (the section list, pre-assembled into the
|
|
1263
|
+
- `messages` is a complete prompt (the section list, pre-assembled into the wire envelope, {§packet-wire-envelope}). Provider does not reorder.
|
|
1225
1264
|
- §provider-guarantees-signal-wired `signal` is wired to the worker's AbortController.
|
|
1226
1265
|
- §provider-guarantees-serial-attempts Emission attempts for one engine turn are serial. They reuse the exact messages, coordinates, generation limits, and strike state; two attempts for that turn never overlap.
|
|
1227
1266
|
- BARE calls admitted by one turn launch as one parallel batch; each call retains independent observer and failure state, and the engine awaits the complete batch before committing results in authored order ({§bare-inference}).
|
|
@@ -1547,7 +1586,7 @@ Registration precedes loop affinity:
|
|
|
1547
1586
|
- §anchor-offset **An anchor offset is tolerated, never taught (#749).** A line mark may carry an offset from its anchor (`@abcde+1`, `@abcde-2`), and a bare `+N` after an anchor counts from that anchor (`<@abcde,+1>`). The anchor resolves as usual and the offset is added; a result before line 1 is an invalid mark, and past the end is the ordinary range refusal. Continuity and current-anchor preconditions check the anchor's own line. No teaching text, scope table or receipt mentions offsets; `plurnk.md` keeps its two anchor forms. A bare `+N` with no anchor before it is refused as before.
|
|
1548
1587
|
- §edit-batch **One compound operation may require atomic splices.** The scheme's `editBatch` primitive validates all supplied numeric edits against one snapshot and commits one revision or none. Core supplies one statement for an authored EDIT; same-resource MOVE can supply multiple splices as one operation. This primitive does not group separate authored operations. Its replacement, insertion, conflict, and receipt rules remain owned by the shared Slicer.
|
|
1549
1588
|
- §edit-batch-receipt **A refusal describes its own unapplied work.** An anchor collision lists every distinct unresolved anchor in that EDIT, including both range endpoints, in `unresolvedAnchors` (`anchor`, `kind: missing | ambiguous`, and matching `lines` when ambiguous). Missing is not proof of earlier validity or subsequent change. It carries `editCount: 1`, `applied: 0`, and recovery directing a READ for current coordinates; it makes no claim about other operations. A refused compound splice batch lists all conflicting pairs in `conflicts`, non-conflicting regions in `cleanRegions`, its first pair in `conflictingRegions`, and its own `editCount` and `applied: 0`.
|
|
1550
|
-
- §edit-batch-merges **Normalizations require evidence and a receipt.** An EDIT body carrying only this resource's published
|
|
1589
|
+
- §edit-batch-merges **Normalizations require evidence and a receipt.** An EDIT body carrying only this resource's published `L<@xxxxx>` prefixes (the number right-aligned) is stripped when those prefixes verify against current anchors or this worker's preserved READ receipts (`rendered-prefix-stripped`); otherwise it remains literal content (`rendered-prefix-unverified`). Within a single atomic splice batch, the Slicer can deduplicate identical regions/bodies, concatenate same-boundary insertions, assign a shared endpoint to the sole body reproducing that line, or relocate an inner change when its original content occurs exactly once in the outer body. An already-applied inner body can be dropped. Unevidenced overlap remains a collision. These batch resolutions never reinterpret separate authored EDITs. Applied normalizations carry their exact merge facts and a notice; receipts describe only the applied effects.
|
|
1551
1590
|
|
|
1552
1591
|
### Cross-scheme orchestration
|
|
1553
1592
|
|
|
@@ -1907,9 +1946,11 @@ anchors from the complete canonical selected channel before applying the
|
|
|
1907
1946
|
authored text slice; its durable result retains the canonical derivation
|
|
1908
1947
|
identity and anchors aligned with returned lines. Packet rendering right-aligns
|
|
1909
1948
|
`L` to the decimal width of the complete canonical selected channel's final
|
|
1910
|
-
addressable line and emits
|
|
1911
|
-
|
|
1912
|
-
|
|
1949
|
+
addressable line and emits `L<@xxxxx><content>` with `L` right-aligned to that
|
|
1950
|
+
width, the scope literal as the delimiter, the content beginning after `>`. The anchor
|
|
1951
|
+
stands against its own text and never opens the row after the previous line's text —
|
|
1952
|
+
the placement that reads correctly at long context on every model measured (#893); a
|
|
1953
|
+
source line therefore retains the same prefix across projections of one revision.
|
|
1913
1954
|
An explicit default-channel fragment and its fragmentless spelling share that
|
|
1914
1955
|
identity; a selected non-default channel retains its canonical `#channel`.
|
|
1915
1956
|
|
|
@@ -2270,7 +2311,10 @@ Authored `metadata` retains its opaque ordered block strings under {§scheme-met
|
|
|
2270
2311
|
This is retained evidence, not a separate visibility or delivery lifecycle. Source mutation/deletion
|
|
2271
2312
|
cannot change a retained observation. Explicit READ of its still-active log source can acquire the same media again.
|
|
2272
2313
|
Every compatible-model packet includes one file part per retained, admitted READ observation, after the
|
|
2273
|
-
packet text, in observation order
|
|
2314
|
+
packet text, in observation order, each preceded by a text part that names the observation's log
|
|
2315
|
+
coordinate, source path and projection facts and states that the bytes are that READ's own, retained
|
|
2316
|
+
until its row is KILLed: an uncaptioned native part on the user turn reads as a fresh arrival (#899).
|
|
2317
|
+
Model-response settlement never consumes an observation. KILL follows
|
|
2274
2318
|
{§log-kill-scope}; forks inherit the snapshot and ordinary projection state independently. Output withholding
|
|
2275
2319
|
suppresses the complete native part under {§context-output-admission}. Unsupported routes receive only the
|
|
2276
2320
|
text projection and no native charge; switching back to a compatible route exposes still-retained media.
|
|
@@ -2422,7 +2466,7 @@ per-operation projection on `rx`; the aggregate remains inside dispatch.
|
|
|
2422
2466
|
| `effect.source`, `result` | `effect` as `<source> -> <result>` | Resolved scopes mapping the source snapshot into the landed body; the admitted marker stays in durable `requested` and `tx`. |
|
|
2423
2467
|
| `effect.removed`, `inserted` | `change` | Removed and inserted counts in the receipt unit. |
|
|
2424
2468
|
| `effect.removedText` | `removed` | {§edit-receipt-removed-text}: a pure deletion's removed text, its first `PLURNK_SERVICE_EDIT_RECEIPT_REMOVED_LINES` lines; absent when the edit inserted anything. |
|
|
2425
|
-
| `effect.context` | Canonical row body | Numbered physical lines at each landed boundary, bounded symmetrically by `PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES`.
|
|
2469
|
+
| `effect.context` | Canonical row body | Numbered physical lines at each landed boundary, bounded symmetrically by `PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES`. A pattern batch's `last` context follows the first's when it differs, with no blank line between: every line of a row body carries its coordinate. |
|
|
2426
2470
|
| `disposition`, `requested` | `disposition`, `requested` | A reviewer-replaced batch preserves the authored marker while stating that its attributed effect was superseded. |
|
|
2427
2471
|
| `replacement` | `replacement`, `change`, canonical proposal-owner body | The one whole-resource effect actually applied by the reviewer replacement; never duplicated across authored rows. |
|
|
2428
2472
|
|
|
@@ -2870,7 +2914,9 @@ anything spawns — a file is the script; a directory is refused `400 target-not
|
|
|
2870
2914
|
pointing at `[{"cwd": "…"}]`; an absent path is refused `400 target-not-found`, giving the
|
|
2871
2915
|
applicable accepted form without inferring what the model meant. When the target is a
|
|
2872
2916
|
registered tool of another executor, recovery gives that tool's exact bracketed
|
|
2873
|
-
invocation;
|
|
2917
|
+
invocation; when it names another available executor (`sh (python3)` over a Python body, #895),
|
|
2918
|
+
recovery names that executor's fence — `` `python3` is its own executor; use that name on the
|
|
2919
|
+
opening fence and put the program in the body. ``; otherwise it points at an existing script or a bare shell-command body. A non-file resource
|
|
2874
2920
|
target that cannot be read keeps the owning READ's failure identity (#163) and states
|
|
2875
2921
|
the slot contract in its recovery — the resource is the program and the body its stdin;
|
|
2876
2922
|
a command belongs beneath a targetless heading — without guessing which was meant (#425). The started receipt always
|
|
@@ -3002,7 +3048,8 @@ Per-tool programs such as `go`, `cargo`, `make`, and `npm` do not earn executor
|
|
|
3002
3048
|
|
|
3003
3049
|
§exec-lifetime **How long a spawn may live is the fence's metadata, one field.**
|
|
3004
3050
|
`[{"lifetime": …}]` takes a duration (`30s`, `30m`, `2h`), or one of three words;
|
|
3005
|
-
absent is `loop`.
|
|
3051
|
+
absent is `loop`. The key is one of the service's reserved metadata keys, withheld
|
|
3052
|
+
from every owner by the framework ({§service-metadata-keys}). An execution takes no scope: a numeric coordinate on an
|
|
3006
3053
|
executor target is refused `scope-unsupported` (400), naming the field.
|
|
3007
3054
|
|
|
3008
3055
|
| `lifetime` | The spawn |
|
|
@@ -3217,7 +3264,7 @@ body prefixes.
|
|
|
3217
3264
|
wholesale ({§log-sensitive-request-evidence}); the spawn's record names each such value's
|
|
3218
3265
|
provenance as the modifier's.
|
|
3219
3266
|
- §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.
|
|
3220
|
-
- §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.
|
|
3267
|
+
- §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 leaf package.
|
|
3221
3268
|
|
|
3222
3269
|
| Input / effect | Consumer behavior |
|
|
3223
3270
|
| --- | --- |
|
|
@@ -3626,6 +3673,14 @@ and is ignored rather than resolved against the working directory.
|
|
|
3626
3673
|
| Reproducible cache | `$XDG_CACHE_HOME` (default `~/.cache`) | Reserved; no directory is created without an owned artifact. |
|
|
3627
3674
|
| Shared global Agent Skills | User home | `.agents/skills/<name>/SKILL.md` |
|
|
3628
3675
|
|
|
3676
|
+
§state-root **A private daemon has one root.** `PLURNK_SERVICE_STATE_ROOT` (absolute; a leading
|
|
3677
|
+
`~/` expands; a relative value fails hard by name) replaces the data, state, cache and runtime homes
|
|
3678
|
+
with `<root>/data`, `<root>/state`, `<root>/cache` and `<root>/runtime`, the database with them
|
|
3679
|
+
(`PLURNK_SERVICE_DB_PATH` still names the database exactly). Configuration stays where the cascade
|
|
3680
|
+
reads it and the shared Agent Skills root stays under the user's home: a state root separates what
|
|
3681
|
+
the daemon *writes*, not what the operator supplies, and is no execution sandbox. What a launcher
|
|
3682
|
+
keeps or removes under a root after the daemon stops is that launcher's retention decision.
|
|
3683
|
+
|
|
3629
3684
|
The service creates only a directory required by the current command. A newly
|
|
3630
3685
|
created configuration or data directory uses mode `0700`; a newly seeded
|
|
3631
3686
|
secret-bearing `.env` uses `0600`. Existing user-owned permissions are not
|
|
@@ -4048,7 +4103,12 @@ actions from model operations where the family contract requires it
|
|
|
4048
4103
|
outcomes, and a snapshot with `commit`/`abort`. Successful publication commits;
|
|
4049
4104
|
failure aborts; cooling tears down. Protocol continuations remain ordinary
|
|
4050
4105
|
module actions. Optional `forget` releases an installed or provisioned
|
|
4051
|
-
definition before removal; failure rejects removal ({§skills-remove}).
|
|
4106
|
+
definition before removal; failure rejects removal ({§skills-remove}). The
|
|
4107
|
+
seam's shapes — the identity a verb acts under, its options, definition
|
|
4108
|
+
sources, outcomes, preparation, the prepared result and the family handle —
|
|
4109
|
+
are declared once in `plurnk-contracts` and imported by core and every
|
|
4110
|
+
module; core adds only its own face of the seam, the runtime registration a
|
|
4111
|
+
resident family prepares and the scheme facet it may expose.
|
|
4052
4112
|
|
|
4053
4113
|
An adapter may expose a `scheme` facet beneath its family's runtime namespace
|
|
4054
4114
|
({§runtime-resource-binding}). A facet claims a path subtree and is the scheme's
|
|
@@ -4224,11 +4284,12 @@ Core's behavior behind them.
|
|
|
4224
4284
|
| §methods-conversation-worker Workspace lifecycle | `createConversationWorker({ workspaceId, name? })` | Creates a distinct model-origin root worker with empty history: a fresh conversation over the same world, not a fork or the stable default. |
|
|
4225
4285
|
| Workspace lifecycle | `forkWorker({ workspaceId, workerId, name? })` | Creates a child worker that branches the source worker's history while sharing workspace state. |
|
|
4226
4286
|
| §methods-workspace-rename Workspace metadata | `renameWorkspace(workspaceId, name)` | Changes only the world's unique mutable name; workers, log, and membership remain intact. |
|
|
4227
|
-
| §methods-workspace-prompts Workspace metadata | `listPrompts(workspaceId, limit?)` | Returns nonempty loop-seed prompts
|
|
4287
|
+
| §methods-workspace-prompts Workspace metadata | `listPrompts(workspaceId, limit?, workerId?)` | Returns nonempty loop-seed prompts a client addressed to the workspace's model workers, newest-first; `workerId` narrows to one worker. Authorship is the seed message's address ({§message-arrival}): a worker-issued seed (WORK, FORK, SEND to a worker) has none and is never history, whichever worker it seeded; a client prompt at a forked conversation worker is. An omitted limit is `PLURNK_SERVICE_PROMPTS_PAGE`. |
|
|
4228
4288
|
| Workspace metadata | `listWorkspaces()`, `workspaceDerivationStatus(...)` | Reads current workspace identity and derivation progress. |
|
|
4229
4289
|
| §methods-worker-read Worker topology | `readWorker({ workspaceId, identity })` | Ownership-bounds an exact id-or-name lookup and returns one durable Worker projection or `null` under {§application-worker-observation}. Supplying both identities or neither is invalid. |
|
|
4230
4290
|
| §methods-worker-list Worker topology | `listWorkers(workspaceId, query?)` | Returns the workspace's durable Worker projections under {§application-worker-observation}. The origin filter is exact; an explicitly present `parentWorkerId` filters roots (`null`) or one immediate parent (id), while omission returns every lineage position. Each projection carries `kind` (`conversation`, `fork` for a child with a fork boundary, `work` for any other child) and `lifecycle`, the representative work loop's status through {§loop-lifecycle-vocabulary} (`idle` with no work loop), so a directory row shows the same lifecycle glyph the bound worker's own status gauge shows; clients infer neither (#523). |
|
|
4231
4291
|
| §methods-worker-loops Loop lifecycle | `listWorkerLoops({ workspaceId, workerId })` | Ownership-checks the Worker and returns its Loops in sequence order under {§application-loop-observation}, including the validated exact terminal result when one exists. It performs no scheduling or event replay. |
|
|
4292
|
+
| §methods-worker-descendants Descendant spend | `descendantAccounting({ workspaceId, workerId, loopId })` | Ownership-checks the Worker and returns the {§provider-accounting} projection of every settled request on a loop that a descendant of the Worker (`parent_worker_id`, to any depth) ran after `loopId` — this delegation's spend, the same tree the turn cap counts ({§turn-cap-counts-the-tree}). The Worker's own loop is never included: its accounting stays {§notifications-loop-terminated}'s. `loopId: null` is the empty projection, explicit zero. Derived from the request ledger on every read ({§tokenomics-provider-usage}); no rollup, no second store. |
|
|
4232
4293
|
| Extension actions | `listModuleActions()`, `invokeModuleAction(name, params, context)` | Lists setup-registered `{ name, scope, inputSchema, outputSchema }` descriptors in sorted order. Invocation requires a context matching the registered scope; missing names, forged scope, and missing workspace identity fail before the owner runs. Handler values remain opaque to core. |
|
|
4233
4294
|
|
|
4234
4295
|
§methods-loop-run-fold-consistency **A folded prompt cannot silently reconfigure
|
|
@@ -4533,6 +4594,26 @@ flowchart LR
|
|
|
4533
4594
|
measure --> rail[Engine budget admission and dispatch]
|
|
4534
4595
|
```
|
|
4535
4596
|
|
|
4597
|
+
### §packet-wire-envelope The wire envelope
|
|
4598
|
+
|
|
4599
|
+
The packet reaches the provider under the roles the model was tuned on, its bytes unchanged:
|
|
4600
|
+
|
|
4601
|
+
| Message | Role | Content |
|
|
4602
|
+
|:--|:--|:--|
|
|
4603
|
+
| 1 | `system` | the system slot, as rendered |
|
|
4604
|
+
| 2 … | `user` | the log's records, one message per completed turn in record order; the first opens with `## Log` |
|
|
4605
|
+
| next | `assistant` | the canonical rendering ({§statement-rendering}) of every statement the parser admitted from the worker's most recent program that admitted any ({§turn-source-resources}, kind `ops`), in order and alone: free text and unadmitted forms are absent, a recovered native call ({§native-tool-calls}) appears as the operation it was read as, and an operation whose receipt failed stays, since it produced its row; turn zero's survey ({§worker-initialization-entry}) is the first, so every model request carries one |
|
|
4606
|
+
| last | `user` | the current turn's records, then the remaining user sections in {§packet-cache-monotone} order; native parts ride here ({§packet-attachment-parts}) |
|
|
4607
|
+
|
|
4608
|
+
Only role boundaries are added. Curation governs every record as before, so a KILLed
|
|
4609
|
+
row is absent from its turn's message; the one program is bounded and the model's own last operations,
|
|
4610
|
+
a demonstration of the grammar beside what the log made of it. Whatever sits under the assistant marker
|
|
4611
|
+
is what the model writes next, for better and for worse: shown its own slip, a model repeats it, so the
|
|
4612
|
+
slot carries the grammar's reading and never the bytes as typed. On the first request it is turn zero's
|
|
4613
|
+
survey, the worked example in the model's own place. The prefix through the last completed
|
|
4614
|
+
turn stays reusable across requests; the assistant message and the closing user message are the
|
|
4615
|
+
changing tail. The digest's packet artifacts record the packet; the envelope is its projection (#903).
|
|
4616
|
+
|
|
4536
4617
|
### §packet-cache-monotone Default order and cache locality
|
|
4537
4618
|
|
|
4538
4619
|
Conditional absence never reorders the surviving default sections.
|
|
@@ -4543,7 +4624,7 @@ Conditional absence never reorders the surviving default sections.
|
|
|
4543
4624
|
| 2 | system | `system-policy` | Operator policy; empty content is omitted on the wire. |
|
|
4544
4625
|
| 3 | system | `inject` | Present only when operator notes are configured. |
|
|
4545
4626
|
| 4 | user | `log` | Append-mostly model-visible history; the first user section, so the cached prefix ends inside it. |
|
|
4546
|
-
| 5 | user | `worker` | `Worker`: `{"path": "worker://alice", "parent": <address or null>, "loop": L, "turn": T}`, the actor
|
|
4627
|
+
| 5 | user | `worker` | `Worker`: `{"path": "worker://alice", "parent": <address or null>, "loop": L, "turn": T, "previousEmission": <ops address or null>}`, the actor, the coordinate this packet's response becomes and the address of its previous program ({§packet-current-turn}). |
|
|
4547
4628
|
| 6 | user | `delegation` | `Delegation`: per-turn `{workers, streams}` pointers; always present, each list `[]` when empty ({§packet-empty-sections}). |
|
|
4548
4629
|
| 7 | user | `errors` | Per-turn failure pointers; empty content is omitted. |
|
|
4549
4630
|
| 8 | user | `notices` | Per-turn observations; empty content is omitted. |
|
|
@@ -5041,6 +5122,8 @@ retain distinct contracts and lifetimes.
|
|
|
5041
5122
|
|
|
5042
5123
|
§notice-event-notify **Client surface.** Engine Notices broadcast live via the `notice/event` notification — `{ workerId, loopId, notice: { source, kind, level, message?, position?, …kind-specific } }` per the grammar's `Notice` schema — the moment they land. A loop Notice names its owning Worker; workspace derivation progress alone carries `workerId=null, loopId=0`. AG-UI projects the same observation as the custom `plurnk.notice` event. Failures do not broadcast on this surface: they are log rows, and the client reads them through `log.read` / the `log/entry` notification, the durable log.
|
|
5043
5124
|
|
|
5125
|
+
§loop-status-notice **The drain beats the loop's lifecycle on the notice channel.** When the drain claims a loop to run it broadcasts `notice/event` `{ workerId, loopId, notice: { source: "engine:lifecycle", kind: "loop_status", level: "info", status: 102 } }`, and when it leaves a loop parked ({§loop-wake-identity}) the same with `status: 202`; a wake that the drain claims again is another `102`. The beat is transient: broadcast to the workspace like any notice ({§notice-event-notify}), never a log row, never in a packet. Terminals stay `loop/terminated`'s; a client that reads the beat has the running/parked edges a parked delegation otherwise never publishes.
|
|
5126
|
+
|
|
5044
5127
|
§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.
|
|
5045
5128
|
|
|
5046
5129
|
§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.
|
|
@@ -5068,6 +5151,10 @@ retain distinct contracts and lifetimes.
|
|
|
5068
5151
|
|
|
5069
5152
|
§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.
|
|
5070
5153
|
|
|
5154
|
+
§digest-cache-ledger **Cacheable versus cached, per request.** For every physical provider request the digest computes its cacheable prefix: the longest common prefix, in characters, between the prompt its turn stored (the packet's rendered `system` text followed by its `user` text — the bytes `.system.md` and `.user.md` carry) and the prompt of the previous provider request in the same loop, taken as that prefix's share of the whole prompt in the packet's own token estimate ({§tokenomics-agnostic-ruler}) and applied to the provider's reported input count, so `cacheableTokens` sits in the same units as the cache read beside it; a loop's first request has 0, and a request whose turn stores no valid packet or whose provider reported no input count has none. Beside it sit the provider's reported cache read as `cachedTokens` (`provider_requests.usage_input_cache_read`) and `inputTokens` (`usage_input`). `digest.json` carries the three on every provider-request row; an inference turn line carries `cache=<cached>/<cacheable>` summed over the turn's requests; each workspace heading is followed by `Cache: <cached> of <cacheable> cacheable tokens reported (<pct>%) over <n> requests`. A provider that reported no cache field at all (null, not 0) renders `?` on the turn line and is counted apart on the workspace line (`· <k> unreported (cached=?)`), outside both sums and the percentage; a request without a stored packet or without a reported input count is likewise counted apart. The prefix measures what the daemon kept identical between consecutive requests; it is no claim about the provider's tokenization or cache-block alignment, so a provider that under-caches an identical prefix reads as such, apart from a prefix the daemon itself broke.
|
|
5155
|
+
|
|
5156
|
+
§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.
|
|
5157
|
+
|
|
5071
5158
|
§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 stored packet validates independently: one malformed historical packet remains exact raw evidence with its complete validation error chain and never prevents healthy turns from being projected. Accounting on broader rows is the shared exact derivation from that ledger, never a second stored fact. A worker's Cost line names how many settled requests carry no usage at all (errored or aborted exchanges) — their server-side spend is unrecorded rather than silently priced as zero. The reasoning chronology distinguishes readable reasoning content from provider-reported reasoning usage: when tokens were reported but no readable content was returned, it states both facts instead of implying that no reasoning occurred. The human Markdown waterfall shows a present causal source and may preview only the Problem detail because it remains a triage projection, not the machine record. Targets reconstruct the model-visible address, including hostname, port, serialized query, and fragment; an authority-bearing URL must never degrade from `https://host/path` to `https:///path`, and durable resource coordinates render back to their authority form. Its human Markdown waterfall groups identical per-turn op outcomes and typed `entry_materialized` narrations, reporting the exact count and sequence span (`xN (seq A-B)`). Grouping keys include source and the complete target, so distinct causes, authorities, or channels never collapse. Thus amplification is conspicuous without making the diagnostic artifact itself pathological; valid packet files remain byte-identical records of what the model saw.
|
|
5072
5159
|
|
|
5073
5160
|
Unrecognized actionless log rows are retained and labelled as such, not
|
|
@@ -5687,3 +5774,152 @@ exits; a failed suite's evidence is never touched and stays exactly where the ru
|
|
|
5687
5774
|
caller's own run directory.
|
|
5688
5775
|
|
|
5689
5776
|
§fs-world-state **The world-state harness — coverage that closes the class.** Op-outcome tests check what an op returned; the harness checks the resulting world. `WorldState.check(db)` asserts, pure-db and read-only: identity uniqueness in practice (no tuple holds two rows), the canonical fixpoint on every file-class key, channel orphan-freedom, the closed admission set (every file row's origin is Git or constraint), and sig-coherence. Generated-pick incorporation and lifecycle require filesystem/Git evidence and are covered by the composed creation matrix rather than a false pure-database proxy. The harness runs as a lifecycle-test epilogue and at every soak turn boundary, where the delta half applies: an idle turn grows the entries table by ZERO. A violation names its law and its row.
|
|
5777
|
+
|
|
5778
|
+
## Problem codes and pinned wording
|
|
5779
|
+
|
|
5780
|
+
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.
|
|
5781
|
+
|
|
5782
|
+
§problems-dispatch **Dispatch Problems.** Every code this family mints, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
5783
|
+
|
|
5784
|
+
| code | status | contract |
|
|
5785
|
+
|---|---:|---|
|
|
5786
|
+
| `target-required` | 400 | *OP* requires a target path. Recovery: Write the target in parentheses on the opening fence line: `OP (path)`. |
|
|
5787
|
+
| `scheme-not-found` | 501 | Scheme '*name*' is not registered. |
|
|
5788
|
+
| `scheme-metadata-unsupported` | 400 | *OP* on '*scheme*' does not accept the [metadata] modifier. |
|
|
5789
|
+
| `operation-not-implemented` | 501 | Scheme '*name*' does not implement *OP* (or exec). |
|
|
5790
|
+
| `entry-read-not-implemented` | 501 | The '*scheme*' scheme does not provide entry reads. |
|
|
5791
|
+
| `entry-write-not-implemented` | 501 | The '*scheme*' scheme does not provide entry writes. |
|
|
5792
|
+
| `entry-delete-not-implemented` | 501 | The '*scheme*' scheme does not provide entry deletion. |
|
|
5793
|
+
| `channel-delete-not-implemented` | 501 | The '*scheme*' scheme does not provide channel deletion. |
|
|
5794
|
+
| `scheme-handler-threw` | 500 | The '*scheme*' scheme did not produce a result for *OP*. |
|
|
5795
|
+
| `exec-source-not-data` | 501 | Scheme '*name*' is not a data source for an execution. |
|
|
5796
|
+
| `writer-forbidden` | 403 | Writer '*origin*' cannot modify scheme '*name*'. |
|
|
5797
|
+
| `capability-denied` | 403 | Capability '*route*' is denied by *scope* policy. |
|
|
5798
|
+
| `spawn-prompt-empty` | 422 | *OP* has no prompt text: the resource is empty and there is no body. |
|
|
5799
|
+
| `message-not-found` | 404 | No accepted message exists at *address*. |
|
|
5800
|
+
| `edit-collision` | 409 | EDIT collided with the current resource state ({§edit-collision}). Recovery: *n* of *m* edits applied. READ the target for current coordinates. |
|
|
5801
|
+
| `edit-target-required` | 400 | A line-anchored EDIT requires a target resource. Recovery: Provide the target that rendered the line anchor. |
|
|
5802
|
+
| `kill-target-required` | 400 | KILL requires a target path. |
|
|
5803
|
+
| `kill-target-scheme-required` | 400 | KILL target requires a scheme. |
|
|
5804
|
+
| `worker-not-found` | 404 | Worker '*name*' does not exist in this workspace. |
|
|
5805
|
+
| `entry-operation-unsupported` | 400 | KILL requires an entry-bearing target; '*scheme*' does not provide one. |
|
|
5806
|
+
| `resource-scheme-required` | 400 | Resource selection requires an address. |
|
|
5807
|
+
| `channel-required` | 400 | The '*scheme*' scheme has no default channel. Recovery: Address a named channel with a URI fragment. |
|
|
5808
|
+
| `binary-source-unsupported` | 415 | Channel #*name* is binary and its scheme keeps no bytes to transfer. |
|
|
5809
|
+
| `metadata-unsupported` | 400 | *OP* takes only the env option; '*key*' is not one. |
|
|
5810
|
+
| `worker-name-conflict` | 409 | Worker '*name*' already exists in this workspace. Recovery: To give '*name*' more work, write `SEND (worker://_name_)` with the task as the body; to start another worker, choose a name no worker holds. |
|
|
5811
|
+
| `no-operation` | 422 | The turn performed no operation ({§empty-turn}). |
|
|
5812
|
+
| `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. |
|
|
5813
|
+
|
|
5814
|
+
§problems-content **Content and transfer Problems.** Every code this family mints, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
5815
|
+
|
|
5816
|
+
| code | status | contract |
|
|
5817
|
+
|---|---:|---|
|
|
5818
|
+
| `handler-crashed` | 415 | The *mimetype* content handler failed on *key*: *cause*. |
|
|
5819
|
+
| `line-anchor-unsupported` | 400 | The byte view of *target* publishes no anchors. Recovery: Use byte coordinates: `<first,last>`. |
|
|
5820
|
+
| `line-anchor-invalid` | 400 | A line anchor in the marker is malformed or names no current line ({§line-anchors}). |
|
|
5821
|
+
| `channel-not-found` | 404 | The addressed channel does not exist at *target*. Recovery: Use one of the available channels: #*a*, #*b*. |
|
|
5822
|
+
| `binary-read-unsupported` | 415 | The representation at *target* is binary and cannot be rendered. |
|
|
5823
|
+
| `pattern-unapplicable` | 422 | The pattern could not be applied to *target*. |
|
|
5824
|
+
| `move-region-overlap` | 409 | MOVE cannot insert a whole channel into itself and then remove that channel. |
|
|
5825
|
+
| `mimetype-mismatch` | 415 | COPY or MOVE cannot write '*source-mimetype*' into a '*destination-mimetype*' channel. |
|
|
5826
|
+
| `binary-region-unsupported` | 415 | Channel #*name* is binary and cannot receive a textual region. |
|
|
5827
|
+
| `copy-destination-exists` | 409 | COPY or MOVE destination *address* already contains different content. |
|
|
5828
|
+
| `proposal-apply-missing` | 500 | The source scheme accepted its MOVE proposal without applying the source mutation. |
|
|
5829
|
+
| `line-anchor-collision` | 409 | READ coordinates collided with current content at *target*. |
|
|
5830
|
+
|
|
5831
|
+
§problems-file **File scheme Problems.** Every code this family mints, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
5832
|
+
|
|
5833
|
+
| code | status | contract |
|
|
5834
|
+
|---|---:|---|
|
|
5835
|
+
| `edit-empty` | 400 | EDIT requires at least one statement. Recovery: Provide an EDIT statement. |
|
|
5836
|
+
| `edit-batch-mismatch` | 400 | The EDIT batch spans multiple resources. Recovery: Submit a separate EDIT batch for each resource. |
|
|
5837
|
+
| `line-marker-required` | 400 | EDIT of an existing file requires a line marker ({§edit-marker-required-on-existing}). Recovery: Name the lines to replace with `<@hash>` or `<@start,@end>` from a READ of the file; `<L,1,L,1>` inserts before line L, and `<1,-1>` replaces the whole file. |
|
|
5838
|
+
| `creation-batch-conflict` | 409 | Multiple EDIT operations attempted to create the same file. Recovery: Create the file with one EDIT before applying additional edits. |
|
|
5839
|
+
| `member-read-only` | 403 | The mounted member '*path*' is read-only. |
|
|
5840
|
+
| `project-root-required` | 400 | The workspace has no project root, so it cannot write files. |
|
|
5841
|
+
| `path-names-no-file` | 403 | The spelling '*path*' does not name a file: it is empty, or it names a directory. |
|
|
5842
|
+
| `path-occupied-by-nonmember` | 403 | A non-member file already occupies '*path*'. Recovery: Choose an unoccupied member path. |
|
|
5843
|
+
| `path-outside-workspace` | 403 | A symlink on '*path*' resolves outside the namespace. |
|
|
5844
|
+
| `binary-write-unsupported` | 415 | A text EDIT cannot author binary '*mimetype*'; COPY or MOVE the bytes instead. |
|
|
5845
|
+
| `file-create-excluded` | 403 | A members exclusion (`!_glob_`) covers '*path*'. Recovery: Remove or disable the excluding members definition, or choose another path. |
|
|
5846
|
+
| `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. |
|
|
5847
|
+
| `file-materialization-limit` | 413 | The file exceeds the materialization byte limit and is not read into the workspace. |
|
|
5848
|
+
| `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. |
|
|
5849
|
+
|
|
5850
|
+
§problems-exec **Execution Problems.** Every code this family mints, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
5851
|
+
|
|
5852
|
+
| code | status | contract |
|
|
5853
|
+
|---|---:|---|
|
|
5854
|
+
| `invalid-input-target` | 400 | SEND input addresses an execution, without a channel or scope. |
|
|
5855
|
+
| `input-unavailable` | 409 | This execution's input receiver is no longer enabled. |
|
|
5856
|
+
| `stream-not-found` | 404 | No execution exists at the requested address. |
|
|
5857
|
+
| `input-closed` | 410 | Execution input is closed. |
|
|
5858
|
+
|
|
5859
|
+
§problems-entries **Entry scheme Problems (log, worker, entries).** Every code this family mints, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
5860
|
+
|
|
5861
|
+
| code | status | contract |
|
|
5862
|
+
|---|---:|---|
|
|
5863
|
+
| `read-target-required` | 400 | READ requires a log coordinate. Recovery: Provide one exact log coordinate. |
|
|
5864
|
+
| `coordinate-malformed` | 400 | The log coordinate '*path*' is malformed. Recovery: Use one exact loop/turn/sequence coordinate. |
|
|
5865
|
+
| `worker-target-required` | 400 | EDIT requires a worker:// target. Recovery: Provide the worker target. |
|
|
5866
|
+
| `binary-edit-unsupported` | 415 | The #*channel* channel is binary and cannot be edited. |
|
|
5867
|
+
| `message-not-implemented` | 501 | SEND does not deliver messages to *scheme* entries. Recovery: To reply, SEND to an Open Message address or omit the target. `SEND (worker://<name>)` sends a new message. |
|
|
5868
|
+
| `worker-entity-not-editable` | 400 | A worker entity is not an editable entry. Recovery: EDIT requires an entry path, such as worker:///example.md. |
|
|
5869
|
+
| `message-empty` | 400 | SEND has no message text or attachments. |
|
|
5870
|
+
| `scope-unsupported` | 400 | A worker SEND takes no scope. |
|
|
5871
|
+
|
|
5872
|
+
§problems-functionality **Server and Functionality Problems.** Every code this family mints, its status, and the sentence that is its contract (placeholders in *italics* are filled at emission; a fixed recovery follows its detail).
|
|
5873
|
+
|
|
5874
|
+
| code | status | contract |
|
|
5875
|
+
|---|---:|---|
|
|
5876
|
+
| `service-starting` | 503 | The PLURNK service owns this listener but has not admitted its client interface yet. |
|
|
5877
|
+
| `configuration-unsupported` | 400 | Environment discovery reads this installation's declared configuration; client configuration contributes nothing. |
|
|
5878
|
+
| `name-reserved` | 400 | '*alias*' is plurnk's own: PLURNK_* configuration and provider credential names never reach a subprocess. |
|
|
5879
|
+
| `value-invalid` | 400 | '*alias*' needs a string value. |
|
|
5880
|
+
| `env-invalid` | 400 | `env` must be an object of string values; '*name*' is not a name a shell can export. |
|
|
5881
|
+
| `query-required` | 400 | discover takes a path or a glob. Recovery: Supply `{ "query": "<path or glob>" }`. |
|
|
5882
|
+
| `headless` | 409 | The workspace has no project root, so there are no file members. Recovery: Open the workspace on a project root. |
|
|
5883
|
+
| `definition-invalid` | 400 | A members definition is { glob }: a gitignore-style pattern, `!glob` to exclude; a skill definition names an installable skill. |
|
|
5884
|
+
| `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. |
|
|
5885
|
+
| `registry-unreachable` | 502 | Skills registry *url* could not be reached. |
|
|
5886
|
+
| `registry-rejected` | 502 | Skills registry *url* answered *status*. |
|
|
5887
|
+
| `registry-invalid` | 502 | Skills registry *url* returned no skills array. |
|
|
5888
|
+
| `discover-failed` | 502 | Agent Skills source '*source*' could not be listed: *cause*. |
|
|
5889
|
+
| `alias-mismatch` | 400 | Alias '*alias*' must equal the skill name '*name*'. |
|
|
5890
|
+
| `scope-not-installable` | 400 | Service-provided skills can be enabled or disabled; adding a skill requires project or global scope. Recovery: Add it with scope "global" or open a workspace rooted in a project. |
|
|
5891
|
+
| `source-required` | 400 | Adding '*alias*' requires the standard installer source that provides it. |
|
|
5892
|
+
| `uninstall-failed` | 502 | Agent Skill '*name*' could not be removed from its *scope* root: *cause*. |
|
|
5893
|
+
| `workspace-not-found` | 404 | Workspace *id* does not exist. |
|
|
5894
|
+
| `state-not-json` | 400 | Worker module state is not JSON-serializable. |
|
|
5895
|
+
| `workspace-busy` | 409 | Workspace *id* is running an operation or another capability change. Recovery: Settle the current operation and retry the capability change. |
|
|
5896
|
+
| `not-configured` | 503 | No provider is configured for this worker. |
|
|
5897
|
+
| `model-worker-required` | 404 | No model worker exists for prompt injection (or to fork). |
|
|
5898
|
+
| `name-conflict` | 409 | The worker name is taken. Recovery: Choose another worker name. |
|
|
5899
|
+
| `offset-channel-required` | 400 | Recovery: Select the channel to read from the offset. |
|
|
5900
|
+
| `target-invalid` | 400 | Recovery: Use a scheme://path target. |
|
|
5901
|
+
| `proposal-not-pending` | 409 | Recovery: Refresh pending proposals before resolving one. |
|
|
5902
|
+
| `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. |
|
|
5903
|
+
| `scope-cancelled` | 499 | The worker scope was cancelled: *reason*. |
|
|
5904
|
+
| `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. |
|
|
5905
|
+
| `registry-not-configured` | 501 | Skills registry search is disabled; PLURNK_SERVICE_SKILLS_REGISTRY_URL is empty. |
|
|
5906
|
+
| `install-failed` | 502 | Agent Skill '*name*' could not be installed from '*source*': *cause* (or the installer reported it but its SKILL.md does not exist). |
|
|
5907
|
+
| `skill-missing` | 404 | Agent Skill '*alias*' is not installed under its *scope* root, or is not provided by this service. |
|
|
5908
|
+
| `skill-invalid` | 422 | Agent Skill '*alias*' is not a valid standard skill: *cause*. |
|
|
5909
|
+
|
|
5910
|
+
§pinned-wording-core **Pinned wording.** Verbatim sentences tests pin: each is contract, and a change here is a change of contract.
|
|
5911
|
+
|
|
5912
|
+
| sentence | arises when |
|
|
5913
|
+
|---|---|
|
|
5914
|
+
| Nothing is in flight. Continuing. | a WAIT (or a premature terminal) with no live work ({§wait-obligation-matrix}) |
|
|
5915
|
+
| Completion deferred. Conclude with KILL alone. | a concluding KILL that carries other operations ({§kill-conclusion}) |
|
|
5916
|
+
| Context Token Budget Overflow: logTokensTotal exceeds logTokensMax; retained context cannot be admitted. | output admission over the retained-context ceiling |
|
|
5917
|
+
| This run is unattended: nobody is present to answer. | a capability that needs a present operator in an unattended loop ({§loop-attendance}) |
|
|
5918
|
+
| Worker name '*name*' must match `[A-Za-z0-9][A-Za-z0-9_-]{0,62}`. Recovery: Use 1–63 ASCII letters, digits, '_' or '-', starting with a letter or digit. | an invalid worker name |
|
|
5919
|
+
| Provide the client identifier. / Provide an absolute project path. / Use a positive integer limit. / prompt is not a non-empty string. | client input validation on the daemon's methods |
|
|
5920
|
+
| The stream was cancelled by KILL. | a stream terminal after KILL |
|
|
5921
|
+
| '*program*' exited with code *n*. | an execution's non-zero exit |
|
|
5922
|
+
| '*path*' is a directory, not a file; READ reads one file. Recovery: List its files with `FIND (_path_/)`, then READ one by its path. | READ of a directory |
|
|
5923
|
+
| The execution at ops://*worker*/*loop* has not concluded. | a bare READ of a running worker's result (425) |
|
|
5924
|
+
| The child provider failed. | a child's provider failure read back by its parent |
|
|
5925
|
+
| '*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 |
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"package":"@plurnk/plurnk-service","version":"1.
|
|
1
|
+
{"package":"@plurnk/plurnk-service","version":"1.23.0","revision":"e00d5d950a3dbcffcfb030716253491edcdee430","dirty":false}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TextCoordinates } from "@plurnk/plurnk-mimetypes";
|
|
2
|
-
import Knob from "
|
|
2
|
+
import { Knob } from "@plurnk/plurnk-meta";
|
|
3
3
|
// {§body-projection} — one selector for ordinary packet previews and implicit
|
|
4
4
|
// text acquisition. Explicit operation scopes never pass through this policy.
|
|
5
5
|
export default class BodyPreview {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body-preview.js","sourceRoot":"","sources":["../../src/content/body-preview.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"body-preview.js","sourceRoot":"","sources":["../../src/content/body-preview.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C,8EAA8E;AAC9E,8EAA8E;AAC9E,MAAM,CAAC,OAAO,OAAO,WAAW;IAC5B,gGAAgG;IAChG,6FAA6F;IAC7F,MAAM,CAAC,SAAS;QACZ,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,8BAA8B,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,IAAY;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,8BAA8B,EAAE,CAAC,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,8BAA8B,EAAE,CAAC,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACjF,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,GAAG,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC;YACnF,2EAA2E;YAC3E,YAAY,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC;gBACjD,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAE,CAAC,CAAC,MAAM,CAAC;QACvE,CAAC;QACD,IAAI,YAAY,GAAG,IAAI,CAAC,MAAM,IAAI,YAAY,IAAI,OAAO,EAAE,CAAC;YACxD,MAAM,YAAY,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,YAAY,CAAC,CAAC;YAC1G,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;gBACtB,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,YAAY,CAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;YACvF,CAAC;YACD,MAAM,MAAM,GAAG,WAAW,CAAC,iBAAiB,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;YAC9D,IAAI,MAAM,KAAK,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;YACnG,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAC9H,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC;IAC9D,CAAC;CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit-receipt.d.ts","sourceRoot":"","sources":["../../src/content/edit-receipt.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACR,uBAAuB,EACvB,gBAAgB,EAEhB,WAAW,EAEX,oBAAoB,EACpB,mCAAmC,EACtC,MAAM,wBAAwB,CAAC;AAMhC,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED,YAAY,EACR,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,mCAAmC,GACtC,MAAM,wBAAwB,CAAC;AAEhC,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElE,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;CAClC;AA+DD,eAAO,MAAM,gBAAgB,8FAA8F,CAAC;AAqD5H,eAAO,MAAM,iBAAiB,UAAW,OAAO,KAAG,WAuBlD,CAAC;AAEF,eAAO,MAAM,sBAAsB,UAAW,OAAO,KAAG,gBA4BvD,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAW,OAAO,KAAG,SAAS,cAAc,EAqC7E,CAAC;AAEF,eAAO,MAAM,kBAAkB,YAAa,gBAAgB,SAAS,MAAM,KAAG,WA0B7E,CAAC;
|
|
1
|
+
{"version":3,"file":"edit-receipt.d.ts","sourceRoot":"","sources":["../../src/content/edit-receipt.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACR,uBAAuB,EACvB,gBAAgB,EAEhB,WAAW,EAEX,oBAAoB,EACpB,mCAAmC,EACtC,MAAM,wBAAwB,CAAC;AAMhC,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED,YAAY,EACR,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,mCAAmC,GACtC,MAAM,wBAAwB,CAAC;AAEhC,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElE,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;CAClC;AA+DD,eAAO,MAAM,gBAAgB,8FAA8F,CAAC;AAqD5H,eAAO,MAAM,iBAAiB,UAAW,OAAO,KAAG,WAuBlD,CAAC;AAEF,eAAO,MAAM,sBAAsB,UAAW,OAAO,KAAG,gBA4BvD,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAW,OAAO,KAAG,SAAS,cAAc,EAqC7E,CAAC;AAEF,eAAO,MAAM,kBAAkB,YAAa,gBAAgB,SAAS,MAAM,KAAG,WA0B7E,CAAC;AAgNF,eAAO,MAAM,WAAW,aACV,MAAM,WACP,MAAM,SACR,SAAS,WAAW,EAAE,gBACf,oBAAoB,aACvB,MAAM,KAClB,uBAoBF,CAAC;AAEF,eAAO,MAAM,0BAA0B,YAC1B,gBAAgB,eACZ,oBAAoB,GAAG,SAAS,KAC9C,gBAQF,CAAC;AAEF,eAAO,MAAM,0BAA0B,aACzB,MAAM,WACP,MAAM,YACL,gBAAgB,gBACZ,oBAAoB,aACvB,MAAM,KAClB,mCA4BF,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { InvalidOperationResultError } from "@plurnk/plurnk-contracts";
|
|
|
4
4
|
import LineMarkerOps from "./line-marker.js";
|
|
5
5
|
import ScopeFormat from "./scope-format.js";
|
|
6
6
|
import { TextCoordinates } from "@plurnk/plurnk-mimetypes";
|
|
7
|
-
import Knob from "
|
|
7
|
+
import { Knob } from "@plurnk/plurnk-meta";
|
|
8
8
|
const receiptRecord = (value, label) => {
|
|
9
9
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
10
10
|
throw new InvalidOperationResultError(`${label} must be an object.`);
|
|
@@ -314,14 +314,7 @@ const codePointEffects = (original, updated, edits) => {
|
|
|
314
314
|
return effect;
|
|
315
315
|
});
|
|
316
316
|
};
|
|
317
|
-
const contextRadius = () =>
|
|
318
|
-
const raw = process.env.PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES;
|
|
319
|
-
const value = Number(raw);
|
|
320
|
-
if (!Number.isSafeInteger(value) || value < 0) {
|
|
321
|
-
throw new Error(`PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES must be a non-negative safe integer, got ${JSON.stringify(raw)}`);
|
|
322
|
-
}
|
|
323
|
-
return value;
|
|
324
|
-
};
|
|
317
|
+
const contextRadius = () => Knob.integer("PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES", 0);
|
|
325
318
|
// {§edit-receipt-anchored-context} — with the resource's anchor identity, the resulting context
|
|
326
319
|
// renders exactly as a READ does (`@xxxxx L:text`), so the next batch can cite the landed
|
|
327
320
|
// lines by anchor without a READ. Without an identity it stays line-numbered.
|
|
@@ -332,7 +325,7 @@ const addContext = (effects, updated, identity) => {
|
|
|
332
325
|
const width = LineAnchors.lineNumberWidth(updated);
|
|
333
326
|
const prefix = (line) => anchors === null
|
|
334
327
|
? `${line}:`
|
|
335
|
-
: `${
|
|
328
|
+
: `${String(line).padStart(width)}<${anchors[line - 1]}>`;
|
|
336
329
|
return effects.map((effect) => {
|
|
337
330
|
const selected = new Set();
|
|
338
331
|
const addRange = (first, last) => {
|