@plurnk/plurnk-service 1.22.0 → 1.24.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.
Files changed (205) hide show
  1. package/.env.defaults +4 -0
  2. package/SPEC.md +293 -36
  3. package/dist/build-info.json +1 -1
  4. package/dist/content/body-preview.js +1 -1
  5. package/dist/content/body-preview.js.map +1 -1
  6. package/dist/content/edit-receipt.d.ts.map +1 -1
  7. package/dist/content/edit-receipt.js +3 -10
  8. package/dist/content/edit-receipt.js.map +1 -1
  9. package/dist/content/line-anchors.d.ts.map +1 -1
  10. package/dist/content/line-anchors.js +7 -9
  11. package/dist/content/line-anchors.js.map +1 -1
  12. package/dist/content/matcher.js +1 -1
  13. package/dist/content/matcher.js.map +1 -1
  14. package/dist/core/AdmittedTurnExecutor.d.ts +3 -2
  15. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
  16. package/dist/core/AdmittedTurnExecutor.js +16 -1
  17. package/dist/core/AdmittedTurnExecutor.js.map +1 -1
  18. package/dist/core/BudgetReadout.js +1 -1
  19. package/dist/core/BudgetReadout.js.map +1 -1
  20. package/dist/core/Dispatcher.d.ts +13 -8
  21. package/dist/core/Dispatcher.d.ts.map +1 -1
  22. package/dist/core/Dispatcher.js +53 -17
  23. package/dist/core/Dispatcher.js.map +1 -1
  24. package/dist/core/EditMutations.js +2 -2
  25. package/dist/core/EditMutations.js.map +1 -1
  26. package/dist/core/Engine.d.ts +8 -19
  27. package/dist/core/Engine.d.ts.map +1 -1
  28. package/dist/core/Engine.js +22 -19
  29. package/dist/core/Engine.js.map +1 -1
  30. package/dist/core/Engine.sql +22 -0
  31. package/dist/core/ErrorDetail.d.ts +3 -4
  32. package/dist/core/ErrorDetail.d.ts.map +1 -1
  33. package/dist/core/ErrorDetail.js +3 -18
  34. package/dist/core/ErrorDetail.js.map +1 -1
  35. package/dist/core/ExecutorRegistry.js +1 -1
  36. package/dist/core/ExecutorRegistry.js.map +1 -1
  37. package/dist/core/FabricatedLog.d.ts +2 -0
  38. package/dist/core/FabricatedLog.d.ts.map +1 -1
  39. package/dist/core/FabricatedLog.js +18 -7
  40. package/dist/core/FabricatedLog.js.map +1 -1
  41. package/dist/core/HostPaths.d.ts +1 -0
  42. package/dist/core/HostPaths.d.ts.map +1 -1
  43. package/dist/core/HostPaths.js +39 -13
  44. package/dist/core/HostPaths.js.map +1 -1
  45. package/dist/core/LogBody.d.ts.map +1 -1
  46. package/dist/core/LogBody.js +9 -8
  47. package/dist/core/LogBody.js.map +1 -1
  48. package/dist/core/LogEntryProjection.d.ts +1 -0
  49. package/dist/core/LogEntryProjection.d.ts.map +1 -1
  50. package/dist/core/LogEntryProjection.js +10 -0
  51. package/dist/core/LogEntryProjection.js.map +1 -1
  52. package/dist/core/LoopDriver.js +1 -1
  53. package/dist/core/LoopDriver.js.map +1 -1
  54. package/dist/core/LoopPolicies.js +1 -1
  55. package/dist/core/LoopPolicies.js.map +1 -1
  56. package/dist/core/PacketBuilder.d.ts +1 -0
  57. package/dist/core/PacketBuilder.d.ts.map +1 -1
  58. package/dist/core/PacketBuilder.js +23 -3
  59. package/dist/core/PacketBuilder.js.map +1 -1
  60. package/dist/core/PacketBuilder.sql +3 -1
  61. package/dist/core/ProposalLifecycle.d.ts +9 -13
  62. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  63. package/dist/core/ProposalLifecycle.js +5 -7
  64. package/dist/core/ProposalLifecycle.js.map +1 -1
  65. package/dist/core/ProviderRecovery.d.ts.map +1 -1
  66. package/dist/core/ProviderRecovery.js +2 -7
  67. package/dist/core/ProviderRecovery.js.map +1 -1
  68. package/dist/core/SchemeRegistry.d.ts +2 -1
  69. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  70. package/dist/core/SchemeRegistry.js +10 -2
  71. package/dist/core/SchemeRegistry.js.map +1 -1
  72. package/dist/core/TurnRunner.d.ts +10 -10
  73. package/dist/core/TurnRunner.d.ts.map +1 -1
  74. package/dist/core/TurnRunner.js +31 -41
  75. package/dist/core/TurnRunner.js.map +1 -1
  76. package/dist/core/file-materialization.d.ts.map +1 -1
  77. package/dist/core/file-materialization.js +4 -3
  78. package/dist/core/file-materialization.js.map +1 -1
  79. package/dist/core/git-env.d.ts.map +1 -1
  80. package/dist/core/git-env.js +2 -7
  81. package/dist/core/git-env.js.map +1 -1
  82. package/dist/core/git-state.js +1 -1
  83. package/dist/core/git-state.js.map +1 -1
  84. package/dist/core/notifications.d.ts +17 -0
  85. package/dist/core/notifications.d.ts.map +1 -0
  86. package/dist/core/notifications.js +2 -0
  87. package/dist/core/notifications.js.map +1 -0
  88. package/dist/core/packet-inject.d.ts.map +1 -1
  89. package/dist/core/packet-inject.js +2 -3
  90. package/dist/core/packet-inject.js.map +1 -1
  91. package/dist/core/packet-wire.d.ts +10 -2
  92. package/dist/core/packet-wire.d.ts.map +1 -1
  93. package/dist/core/packet-wire.js +97 -22
  94. package/dist/core/packet-wire.js.map +1 -1
  95. package/dist/core/teaching.js +1 -1
  96. package/dist/core/teaching.js.map +1 -1
  97. package/dist/digest/Digest.d.ts.map +1 -1
  98. package/dist/digest/Digest.js +19 -3
  99. package/dist/digest/Digest.js.map +1 -1
  100. package/dist/digest/DigestRender.d.ts +3 -1
  101. package/dist/digest/DigestRender.d.ts.map +1 -1
  102. package/dist/digest/DigestRender.js +219 -1
  103. package/dist/digest/DigestRender.js.map +1 -1
  104. package/dist/digest/DigestRequiem.d.ts.map +1 -1
  105. package/dist/digest/DigestRequiem.js +12 -14
  106. package/dist/digest/DigestRequiem.js.map +1 -1
  107. package/dist/digest/digest-rows.d.ts +34 -0
  108. package/dist/digest/digest-rows.d.ts.map +1 -1
  109. package/dist/digest/digest-rows.js +1 -1
  110. package/dist/digest/digest-rows.js.map +1 -1
  111. package/dist/digest/digest.sql +26 -0
  112. package/dist/launch/Launch.d.ts +49 -0
  113. package/dist/launch/Launch.d.ts.map +1 -0
  114. package/dist/launch/Launch.js +179 -0
  115. package/dist/launch/Launch.js.map +1 -0
  116. package/dist/observe/spans.d.ts +1 -1
  117. package/dist/observe/spans.d.ts.map +1 -1
  118. package/dist/observe/spans.js +5 -64
  119. package/dist/observe/spans.js.map +1 -1
  120. package/dist/schemes/EffectPolicy.js +1 -1
  121. package/dist/schemes/EffectPolicy.js.map +1 -1
  122. package/dist/schemes/Exec.d.ts +2 -2
  123. package/dist/schemes/Exec.d.ts.map +1 -1
  124. package/dist/schemes/Exec.js +20 -16
  125. package/dist/schemes/Exec.js.map +1 -1
  126. package/dist/schemes/ExecutionInput.d.ts.map +1 -1
  127. package/dist/schemes/ExecutionInput.js +2 -5
  128. package/dist/schemes/ExecutionInput.js.map +1 -1
  129. package/dist/schemes/File.d.ts.map +1 -1
  130. package/dist/schemes/File.js +6 -1
  131. package/dist/schemes/File.js.map +1 -1
  132. package/dist/schemes/Log.d.ts.map +1 -1
  133. package/dist/schemes/Log.js +25 -3
  134. package/dist/schemes/Log.js.map +1 -1
  135. package/dist/schemes/_entry-graph.d.ts.map +1 -1
  136. package/dist/schemes/_entry-graph.js +2 -6
  137. package/dist/schemes/_entry-graph.js.map +1 -1
  138. package/dist/schemes/_entry-manifest.js +1 -1
  139. package/dist/schemes/_entry-manifest.js.map +1 -1
  140. package/dist/schemes/_search-index.d.ts.map +1 -1
  141. package/dist/schemes/_search-index.js +2 -8
  142. package/dist/schemes/_search-index.js.map +1 -1
  143. package/dist/schemes/exec-abort.js +1 -1
  144. package/dist/schemes/exec-abort.js.map +1 -1
  145. package/dist/schemes/exec-lifetime.d.ts.map +1 -1
  146. package/dist/schemes/exec-lifetime.js +2 -1
  147. package/dist/schemes/exec-lifetime.js.map +1 -1
  148. package/dist/server/ClientReads.d.ts +1 -1
  149. package/dist/server/ClientReads.d.ts.map +1 -1
  150. package/dist/server/ClientReads.js +1 -1
  151. package/dist/server/ClientReads.js.map +1 -1
  152. package/dist/server/Daemon.d.ts +10 -7
  153. package/dist/server/Daemon.d.ts.map +1 -1
  154. package/dist/server/Daemon.js +12 -3
  155. package/dist/server/Daemon.js.map +1 -1
  156. package/dist/server/DaemonModule.d.ts +2 -63
  157. package/dist/server/DaemonModule.d.ts.map +1 -1
  158. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  159. package/dist/server/DrainSupervisor.js +10 -1
  160. package/dist/server/DrainSupervisor.js.map +1 -1
  161. package/dist/server/EnvFunctionality.d.ts +2 -1
  162. package/dist/server/EnvFunctionality.d.ts.map +1 -1
  163. package/dist/server/EnvFunctionality.js.map +1 -1
  164. package/dist/server/Functionality.d.ts +2 -1
  165. package/dist/server/Functionality.d.ts.map +1 -1
  166. package/dist/server/Functionality.js.map +1 -1
  167. package/dist/server/MembersFunctionality.d.ts +2 -1
  168. package/dist/server/MembersFunctionality.d.ts.map +1 -1
  169. package/dist/server/MembersFunctionality.js +1 -1
  170. package/dist/server/MembersFunctionality.js.map +1 -1
  171. package/dist/server/SkillsFunctionality.d.ts +2 -1
  172. package/dist/server/SkillsFunctionality.d.ts.map +1 -1
  173. package/dist/server/SkillsFunctionality.js +1 -1
  174. package/dist/server/SkillsFunctionality.js.map +1 -1
  175. package/dist/server/WorkspaceResidency.d.ts +2 -1
  176. package/dist/server/WorkspaceResidency.d.ts.map +1 -1
  177. package/dist/server/WorkspaceResidency.js.map +1 -1
  178. package/dist/server/client-input.d.ts +1 -1
  179. package/dist/server/client-input.d.ts.map +1 -1
  180. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  181. package/dist/server/dispatch-as-plurnk.js +1 -0
  182. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  183. package/dist/server/envelope.d.ts +2 -9
  184. package/dist/server/envelope.d.ts.map +1 -1
  185. package/dist/server/envelope.js +2 -2
  186. package/dist/server/envelope.js.map +1 -1
  187. package/dist/server/envelope.sql +6 -3
  188. package/dist/server/logEntry.d.ts +1 -31
  189. package/dist/server/logEntry.d.ts.map +1 -1
  190. package/dist/server/logEntry.js.map +1 -1
  191. package/dist/server/model-catalog.js +1 -1
  192. package/dist/server/model-catalog.js.map +1 -1
  193. package/dist/server/module-discovery.d.ts.map +1 -1
  194. package/dist/server/module-discovery.js +4 -22
  195. package/dist/server/module-discovery.js.map +1 -1
  196. package/dist/service.d.ts.map +1 -1
  197. package/dist/service.js +4 -1
  198. package/dist/service.js.map +1 -1
  199. package/docs/env.md +18 -0
  200. package/migrations/012_emission.sql +77 -0
  201. package/package.json +38 -34
  202. package/dist/core/Knob.d.ts +0 -9
  203. package/dist/core/Knob.d.ts.map +0 -1
  204. package/dist/core/Knob.js +0 -50
  205. package/dist/core/Knob.js.map +0 -1
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 and program READs in {§reasoning-initial-read} execute under {§op-execution-order}. The full `<1,-1>` READ of its own `ops://<worker>/<loop>/<turn>` source supplies the worked program example; no 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}.
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 is announced at `log:///1/1/1/emission` ({§emission-row}) and 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
@@ -586,6 +612,8 @@ Worker control rides the daemon's inject seam (active→fold, idle→enqueue+dra
586
612
 
587
613
  ## §membership File membership and project roots
588
614
 
615
+ 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.
616
+
589
617
  The project-file path has two explicit reconciliation gates. Internal entries do
590
618
  not participate in this disk loop.
591
619
 
@@ -1065,11 +1093,21 @@ append-only log high-water mark. Every log-targeted KILL in the program resolves
1065
1093
  row membership at or below that same boundary, while prior curation effects still
1066
1094
  compose normally. Message arrivals and other pre-program rows already present in the turn
1067
1095
  remain selectable; preceding and later operation rows cannot be captured by
1068
- their own program. A directly dispatched
1096
+ their own program. The emission row ({§emission-row}) is written after the snapshot, so the
1097
+ program it announces cannot select it; a later program can. A directly dispatched
1069
1098
  single operation captures the equivalent boundary before dispatch. This limits
1070
1099
  only log-row selection: operation phasing and same-turn resource effects retain
1071
1100
  their ordinary contracts.
1072
1101
 
1102
+ ### §engine-notifications One bundle of daemon callbacks
1103
+
1104
+ The daemon's observation callbacks — stream, reasoning, outside-text and packet
1105
+ events, worker wake, inject and cancel, operation settlement, notices — are one
1106
+ declared bundle (`EngineNotifications`). The Engine receives them flat, carries
1107
+ them as one value, and every consumer reads the callbacks it uses from that
1108
+ value; adding one is a declaration and a use, never an edit to the constructors
1109
+ between. Scheme contexts still expose the specific callbacks a handler may call.
1110
+
1073
1111
  ### §engine-rails Engine rails
1074
1112
 
1075
1113
  After each admitted turn, one inline verdict decides whether the loop continues.
@@ -1221,7 +1259,7 @@ Three current entry points:
1221
1259
 
1222
1260
  ### Engine → provider guarantees
1223
1261
 
1224
- - `messages` is a complete prompt (the section list, pre-assembled into the system + user messages). Provider does not reorder.
1262
+ - `messages` is a complete prompt (the section list, pre-assembled into the wire envelope, {§packet-wire-envelope}). Provider does not reorder.
1225
1263
  - §provider-guarantees-signal-wired `signal` is wired to the worker's AbortController.
1226
1264
  - §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
1265
  - 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}).
@@ -1240,10 +1278,10 @@ The parser owns its boundaries; core admits determinate work and exposes its fai
1240
1278
  | Outside response text | Store it as the turn's `outside` source under {§outside-text}; never a row, never delivered, never completion. |
1241
1279
  | Lost boundary after a closed operation | Admit the closed operations and record the boundary diagnostic under {§unparsed-tail-boundary}. |
1242
1280
  | Lost boundary before any closed operation | Reject the attempt; neither outside text nor a reasoning NOTE substitutes for a closed response operation. |
1243
- | Outside text carrying a log-entry heading | Reject the attempt ({§fabricated-log-entry}). |
1281
+ | Outside text carrying a log-entry heading, other than an emission row's | Reject the attempt ({§fabricated-log-entry}). |
1244
1282
  | A response the provider stopped at a repeated line | Reject the attempt with the provider's sentence as its diagnostic ({§repetition-stop}); no provider recovery, notice, or problem row. |
1245
1283
 
1246
- §fabricated-log-entry **Only the harness writes the log.** A line of outside response text that begins with a log-entry heading, `### log:///<loop>/<turn>/<sequence>/` ({§log-wire-format}), is the model continuing the packet's transcript instead of answering it: it writes the receipts it expects and then acts on them. The attempt is rejected under {§invalid-emission-attempts}, so neither that text nor any operation beside it runs or is stored as outside text ({§outside-text}), and its one diagnostic, at the heading's line, reads `` `### log:///2/1/5/READ` is a log entry, and only the harness writes the log. Write the operation, then wait for its receipt. `` Text inside an operation body is not examined, so a SEND or KILL may quote a receipt. In 10,486 recorded emissions, 101 carried such a heading in outside text, every one a fabrication: 85 of 1,675 from deepseek-flash, 81 of them opening with one, and 16 from glm-5.3-flash, deepseek-v4-pro and qwen3.8-flash, which appended an invented `## Log` after their own operations.
1284
+ §fabricated-log-entry **Only the harness writes the log.** A line of outside response text that begins with a log-entry heading, `### log:///<loop>/<turn>/<sequence>/` ({§log-wire-format}), is the model continuing the packet's transcript instead of answering it: it writes the receipts it expects and then acts on them. The attempt is rejected under {§invalid-emission-attempts}, so neither that text nor any operation beside it runs or is stored as outside text ({§outside-text}), and its one diagnostic, at the heading's line, reads `` `### log:///2/1/5/READ` is a log entry, and only the harness writes the log. Write the operation, then wait for its receipt. `` Text inside an operation body is not examined, so a SEND or KILL may quote a receipt. A heading whose leaf is `emission` is exempt: the transcript shows it before each of the worker's own emissions ({§emission-row}), and repeating it invents no receipt, so the attempt is admitted and the heading stays outside text, counted by the digest as an echo. In 10,486 recorded emissions, 101 carried such a heading in outside text, every one a fabrication: 85 of 1,675 from deepseek-flash, 81 of them opening with one, and 16 from glm-5.3-flash, deepseek-v4-pro and qwen3.8-flash, which appended an invented `## Log` after their own operations.
1247
1285
 
1248
1286
  Warnings and closer recovery ({§closer-fallback}) do not reject. `finish=length`
1249
1287
  discloses truncation and precludes completion; it is not independently a rejection.
@@ -1547,7 +1585,7 @@ Registration precedes loop affinity:
1547
1585
  - §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
1586
  - §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
1587
  - §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 `@xxxxx L:` prefixes 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.
1588
+ - §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
1589
 
1552
1590
  ### Cross-scheme orchestration
1553
1591
 
@@ -1907,9 +1945,11 @@ anchors from the complete canonical selected channel before applying the
1907
1945
  authored text slice; its durable result retains the canonical derivation
1908
1946
  identity and anchors aligned with returned lines. Packet rendering right-aligns
1909
1947
  `L` to the decimal width of the complete canonical selected channel's final
1910
- addressable line and emits `@xxxxx L:<content>` with one or more ASCII spaces
1911
- before `L`; a source line therefore retains the same prefix across projections
1912
- of one revision.
1948
+ addressable line and emits `L<@xxxxx><content>` with `L` right-aligned to that
1949
+ width, the scope literal as the delimiter, the content beginning after `>`. The anchor
1950
+ stands against its own text and never opens the row after the previous line's text —
1951
+ the placement that reads correctly at long context on every model measured (#893); a
1952
+ source line therefore retains the same prefix across projections of one revision.
1913
1953
  An explicit default-channel fragment and its fragmentless spelling share that
1914
1954
  identity; a selected non-default channel retains its canonical `#channel`.
1915
1955
 
@@ -2134,7 +2174,7 @@ same transitions the dispatcher's atomic curation event makes, without the row.
2134
2174
  The initialization turn records a short `_plurnk`-authored rationale containing
2135
2175
  a fenced NOTE. The shared reasoning extractor ({§reasoning-notes}) executes that
2136
2176
  NOTE through ordinary dispatch, creating its log item and immutable source.
2137
- The program begins with its own NOTE and READs its reasoning and persisted ops,
2177
+ The program begins with its own NOTE and READs its reasoning,
2138
2178
  demonstrating both NOTE placements and their ordinary results. The initial message arrives separately as an
2139
2179
  inbound SEND ({§message-arrival}). Neither initialization nor later turns
2140
2180
  manufacture a task inventory.
@@ -2158,7 +2198,7 @@ a turn whose emission or reasoning carries a foreign tool-call grammar or leaked
2158
2198
 
2159
2199
  AST: `{ op: "KILL", target, matcher: MatcherBody | null, lineMarker: TextLineMarker | null, body: null }` ({§kill-scope} and {§matcher-option} in the contracts SPEC own the grammar).
2160
2200
 
2161
- KILL deletes context from the **log** (`log:///`, {§packet}). Without a scope it retires the selected rows from the active projection ({§log-history-projection}). With a one-line or inclusive two-line scope it removes only that body's intersecting body-relative physical lines from the readable projection, and the row stays active. An anchor may be one published on that body or one returned by READing its `log:///` coordinate ({§line-anchors}); an anchor absent from the current body selects no line, as with an out-of-bounds numeric line. Scoped KILL is one-way: intervals accumulate, the durable body is untouched, and subsequent access follows {§log-readable-projection}. A scoped KILL on a bodyless row is a friendly 200 no-op with `matched` reported. A KILL that addresses no row is 404 on an exact coordinate and 204 on a sweep ({§log-curation-folder-idiom}). Selection composes target/glob with an optional heading pattern ({§log-curation-set-selection}). Parameterless KILL instead requests completion ({§kill-conclusion}).
2201
+ KILL deletes context from the **log** (`log:///`, {§packet}). Without a scope it retires the selected rows from the active projection ({§log-history-projection}). With a one-line or inclusive two-line scope it removes only that body's intersecting body-relative physical lines from the readable projection, and the row stays active. An anchor may be one published on that body or one returned by READing its `log:///` coordinate ({§line-anchors}); an anchor absent from the current body selects no line, as with an out-of-bounds numeric line. Scoped KILL is one-way: intervals accumulate, the durable body is untouched, and subsequent access follows {§log-readable-projection}. A scoped KILL on a bodyless row is a friendly 200 no-op with `matched` reported. An emission row is curated whole ({§emission-row}): a scope covering every line retires it like an unscoped KILL; on its exact coordinate a narrower scope is 422 `emission-curated-whole`, whose recovery names both forms that retire it; a sweep leaves it intact. A KILL that addresses no row is 404 on an exact coordinate and 204 on a sweep ({§log-curation-folder-idiom}). Selection composes target/glob with an optional heading pattern ({§log-curation-set-selection}). Parameterless KILL instead requests completion ({§kill-conclusion}).
2162
2202
 
2163
2203
  §log-scope-recovery A log-body scope follows the file slicer's range rule ({§range-starts-at-one} in the schemes SPEC): a range starting at 0 — `<0,-1>` included — is refused 416 `range-not-satisfiable` on every body, empty ones too, and never clamped; its detail is the slicer's own sentence, `Range <0,-1> starts at 0, which is not a line; lines are numbered from 1.`, and its recovery names the forms a log body takes — `Write <1,-1> to trim every line of the body; KILL (log:///1/9/2/READ) with no scope retires the whole row.`, or `To trim lines 1 through M, write <1,M>; …` — never the insert and append positions a body cannot take. Every other scope that names no line is 400 `curation-scope-invalid` and likewise names the model's mistake in its coordinates and the forms that work on that row: `<0>` offers `<1>`; an end below 1 offers `<L,-1>`; a backward `<5,3>` offers `<3,5>`; anything else offers `<L>`, `<L,M>` and the unscoped row KILL.
2164
2204
 
@@ -2168,7 +2208,7 @@ A READ carrying active native media is atomic: any KILL scope is ignored and the
2168
2208
 
2169
2209
  | Fact | Owner | Effect |
2170
2210
  | --- | --- | --- |
2171
- | Initial body suppression | Immutable event `initial_folded` | Packet presentation only; explicit retrieval can read an initially hidden body. |
2211
+ | Initial body suppression | Immutable event `initial_folded` | Packet presentation only; explicit retrieval can read an initially hidden body. An emission row's hidden body reaches the packet as its assistant message ({§emission-row}). |
2172
2212
  | Deliberate scoped KILL | Current projection `folded`, initially empty | Packet, READ, FIND, COPY, and search omit those lines; later retrieval cannot undo trimming. |
2173
2213
 
2174
2214
  Packet display combines both masks. Other consumers use only deliberate trimming.
@@ -2202,7 +2242,7 @@ The `## Log` section is a sequence of ordinary Markdown records separated by one
2202
2242
  | facts | One strict JSON object in stable alphabetical order. | Present only when a fact exists. Asides, scopes, opaque invocation metadata and result facts belong here, not on the H3. |
2203
2243
  | body | Coordinate-prefixed lines. | Present when the row is visible. |
2204
2244
 
2205
- Patterns retain their literal spelling; a pattern containing a line break is JSON-quoted to keep the H3 on one physical line. Receipts are descriptive records, not reconstructed operation headings. Absent fields are not invented. Every physical body line retains its canonical numeric `N:` or anchored `@hash N:` coordinate, so source text cannot create a record boundary. The section contains records only, with no leading prose or enclosing fence.
2245
+ An emission row's body is not in its record: it follows the record as the worker's assistant message ({§packet-wire-envelope}). Patterns retain their literal spelling; a pattern containing a line break is JSON-quoted to keep the H3 on one physical line. Receipts are descriptive records, not reconstructed operation headings. Absent fields are not invented. Every physical body line retains its canonical numeric `N:` or anchored `@hash N:` coordinate, so source text cannot create a record boundary. The section contains records only, with no leading prose or enclosing fence.
2206
2246
 
2207
2247
  §log-address-metadata **Addresses name their relationship, not the row's producer.**
2208
2248
 
@@ -2252,7 +2292,7 @@ complete non-retrieval body retains `lines` where no other field supplies its
2252
2292
  navigable extent. None of these spellings changes acquisition, delivery,
2253
2293
  curation, admission, or immutable evidence.
2254
2294
 
2255
- Field absence carries defaults: `origin` is omitted for the owning model, `source` for the owning worker, and `status` for a routine 200. Dispositions always carry their lifecycle status, SEND its delivery status, KILL keeps an explicit 200, and every non-200 stays explicit. A present authored aside appears as `aside`. Every row's accounting follows {§packet-token-accounting}.
2295
+ Field absence carries defaults: `origin` is omitted for the owning model, `source` for the owning worker, and `status` for a routine 200. An emission row renders its author, the turn's producer, as its `origin` ({§emission-row}). Dispositions always carry their lifecycle status, SEND its delivery status, KILL keeps an explicit 200, and every non-200 stays explicit. A present authored aside appears as `aside`. Every row's accounting follows {§packet-token-accounting}.
2256
2296
 
2257
2297
  Authored `metadata` retains its opaque ordered block strings under {§scheme-metadata-modifier}; COPY/MOVE pair them as `{from,to}`. Packet rendering does not interpret scheme options or discard malformed input from a failed operation.
2258
2298
 
@@ -2270,7 +2310,10 @@ Authored `metadata` retains its opaque ordered block strings under {§scheme-met
2270
2310
  This is retained evidence, not a separate visibility or delivery lifecycle. Source mutation/deletion
2271
2311
  cannot change a retained observation. Explicit READ of its still-active log source can acquire the same media again.
2272
2312
  Every compatible-model packet includes one file part per retained, admitted READ observation, after the
2273
- packet text, in observation order. Model-response settlement never consumes an observation. KILL follows
2313
+ packet text, in observation order, each preceded by a text part that names the observation's log
2314
+ coordinate, source path and projection facts and states that the bytes are that READ's own, retained
2315
+ until its row is KILLed: an uncaptioned native part on the user turn reads as a fresh arrival (#899).
2316
+ Model-response settlement never consumes an observation. KILL follows
2274
2317
  {§log-kill-scope}; forks inherit the snapshot and ordinary projection state independently. Output withholding
2275
2318
  suppresses the complete native part under {§context-output-admission}. Unsupported routes receive only the
2276
2319
  text projection and no native charge; switching back to a compatible route exposes still-retained media.
@@ -2281,7 +2324,7 @@ Authored `metadata` retains its opaque ordered block strings under {§scheme-met
2281
2324
  records the exact READ coordinates sent without controlling retention. Missing immutable bytes are an
2282
2325
  internal integrity failure, never silently dropped content. No ejection message or permanent teaching is
2283
2326
  added. These stable curation weights are not provider-token measurements ({§tokenomics-render-weight-budget}).
2284
- - §packet-token-accounting Every row reports one `logTokens` charge on its H3 ({§log-wire-format}): its complete materialized H3, facts, visible body, and selected native attachment. The completed record is measured to a fixed point, including the accounting field itself. No `tokensBody`, `tokensMetadata`, or `tokensActive` field is serialized. Hidden text is not charged; metadata-only rows still have a reclaimable charge. Source/FIND-item `tokens` measure source content, not the observation's context footprint. A FIND's nonzero `itemsTokenTotal` weighs the complete matched set; a nonzero `returnedItemsTokenTotal` appears only when the returned page differs. All use stable curation weights, not provider tokens or dollars. Native component accounting follows {§packet-attachment-parts}; ordinary addressability and truthful errors follow {§log-wire-format}.
2327
+ - §packet-token-accounting Every row reports one `logTokens` charge on its H3 ({§log-wire-format}): its complete materialized H3, facts, visible body, selected native attachment, and the emission it delivers outside its record ({§emission-row}). The completed record is measured to a fixed point, including the accounting field itself. No `tokensBody`, `tokensMetadata`, or `tokensActive` field is serialized. Hidden text is not charged; metadata-only rows still have a reclaimable charge. Source/FIND-item `tokens` measure source content, not the observation's context footprint. A FIND's nonzero `itemsTokenTotal` weighs the complete matched set; a nonzero `returnedItemsTokenTotal` appears only when the returned page differs. All use stable curation weights, not provider tokens or dollars. Native component accounting follows {§packet-attachment-parts}; ordinary addressability and truthful errors follow {§log-wire-format}.
2285
2328
 
2286
2329
  ### §retrieval-packet-metadata READ/FIND packet metadata
2287
2330
 
@@ -2327,14 +2370,32 @@ single line past the end, a reversed range, empty content, a command's log row
2327
2370
 
2328
2371
  ### §turn-ops-entry The admitted turn program
2329
2372
 
2330
- §turn-ops-log-curation A source-backed turn preserves its **exact admitted Plurnk program**, including ignored interstitial text, before dispatch. `turn_sources` records that source once, separately from the curatable log and optional provider evidence. Retention does not manufacture a log row. Ordinary READ creates a receipt governed by {§log-readable-projection}; curation of that receipt never changes the source. Initialization reads its own already-persisted source under {§worker-initialization-entry}.
2373
+ §turn-ops-log-curation A source-backed turn preserves its **exact admitted Plurnk program**, including ignored interstitial text, before dispatch. `turn_sources` records that source once, separately from the curatable log and optional provider evidence. Retention does not manufacture a log row; the one row an admitted emission gains is its announcement ({§emission-row}). Ordinary READ creates a receipt governed by {§log-readable-projection}; curation of either never changes the source.
2374
+
2375
+ ### §emission-row The emission row
2376
+
2377
+ Every admitted emission is announced by one row of its own turn, so the transcript carries the
2378
+ worker's emissions in chronological place ({§packet-wire-envelope}) and the worker curates them
2379
+ like any other row.
2380
+
2381
+ | Surface | Contract |
2382
+ |---|---|
2383
+ | When | An inference turn that admitted at least one statement from its provider content, and turn zero's survey ({§worker-initialization-entry}). A programmatic batch, an empty turn ({§empty-turn}), a client operation and a rejected attempt ({§rejected-emission-entry}) announce nothing. |
2384
+ | 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. |
2385
+ | 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. |
2386
+ | Body | Frozen: the canonical rendering ({§statement-rendering}) of every statement the parser admitted, in order. 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. Turn zero's is its survey as authored. `ops://` keeps the exact source ({§turn-source-resources}). |
2387
+ | Presentation | Born folded: the record shows its header, and its body follows the record as the worker's assistant message. |
2388
+ | Accounting | `logTokens` charges the record and the emission it delivers ({§packet-token-accounting}). |
2389
+ | 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. |
2390
+ | 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. |
2391
+ | Echoes | A worker that repeats the heading in its own text is tolerated ({§fabricated-log-entry}); the digest counts the echoes. |
2331
2392
 
2332
2393
  ### §turn-source-resources Immutable turn-source resources
2333
2394
 
2334
2395
  | Surface | Contract |
2335
2396
  |---|---|
2336
2397
  | 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. |
2337
- | Source | `ops` is exact admitted `text/vnd.plurnk`; `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. |
2398
+ | Source | `ops` is exact admitted `text/vnd.plurnk`, and its turn's emission row carries the canonical rendering ({§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. |
2338
2399
  | 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. |
2339
2400
  | 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. |
2340
2401
  | 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. |
@@ -2342,11 +2403,11 @@ single line past the end, a reversed range, empty content, a command's log row
2342
2403
  | FORK | Sources copy with the inherited turns at identical loop/turn/item coordinates under the fork's own authority. Bytes and embedded source references are preserved verbatim; an explicit reference still names its original worker. Branch receipt curation is independent; neither branch can rewrite source evidence. |
2343
2404
  | Forensics | Digest assistant artifacts read source directly, independently of receipt presence or curation. Original provider responses retain all attempts and opaque fields separately. |
2344
2405
 
2345
- §rejected-emission-entry A rejected provider response is not `turnOps`: it never became an admitted turn program. 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.
2406
+ §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.
2346
2407
 
2347
- - §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. 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`, and `log:///**/attempt` 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 the model's operations ({§packet-current-turn} names `L/T`).
2348
- - §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. 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}).
2349
- - §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. Thus ```` ```KILL (log:///**/READ) <17,-1> ```` may change long READs and no-op on short ones while reporting every selected row in `matched`.
2408
+ - §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`).
2409
+ - §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}).
2410
+ - §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`.
2350
2411
 
2351
2412
  §log-kill-meta-operation **A log KILL changes working context, never the underlying resources or execution history.** Receipt visibility depends on the target and result, not the producer, attribution, or age of the turn:
2352
2413
 
@@ -2422,7 +2483,7 @@ per-operation projection on `rx`; the aggregate remains inside dispatch.
2422
2483
  | `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
2484
  | `effect.removed`, `inserted` | `change` | Removed and inserted counts in the receipt unit. |
2424
2485
  | `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`. |
2486
+ | `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
2487
  | `disposition`, `requested` | `disposition`, `requested` | A reviewer-replaced batch preserves the authored marker while stating that its attributed effect was superseded. |
2427
2488
  | `replacement` | `replacement`, `change`, canonical proposal-owner body | The one whole-resource effect actually applied by the reviewer replacement; never duplicated across authored rows. |
2428
2489
 
@@ -2747,10 +2808,10 @@ accounting and model-visible failure evidence remain separately owned by
2747
2808
  operation is minted for them, a repetitive or length-cut response stays one source, and nothing
2748
2809
  filters what is stored. The model hears only the weight: the next packet's Notices section
2749
2810
  carries `outside_text: N tokens emitted outside OPs. Discarded.`, N by {§tokenomics-agnostic-ruler};
2750
- the text itself never enters a packet, is never delivered and never concludes.
2811
+ the text itself never enters a packet, not even inside its turn's emission ({§emission-row}), is never delivered and never concludes.
2751
2812
  {§empty-turn} still strikes a turn that holds only text, with unchanged reasoning recovery
2752
2813
  ({§reasoning-empty-turn-read}), reply accounting and completion rules. A log-entry heading in
2753
- outside text still rejects the attempt ({§fabricated-log-entry}); an unfenced operation line is
2814
+ outside text still rejects the attempt unless it echoes an emission row ({§fabricated-log-entry}); an unfenced operation line is
2754
2815
  not response text ({§unfenced-operation}) and so never reaches the source; `KnownToxins` guards
2755
2816
  only the read-back ({§reasoning-empty-turn-read}). Clients receive the text once through
2756
2817
  `outside/event` ({§notifications-outside-event}, {§agui-outside-text}); FORK snapshots the
@@ -2870,7 +2931,9 @@ anything spawns — a file is the script; a directory is refused `400 target-not
2870
2931
  pointing at `[{"cwd": "…"}]`; an absent path is refused `400 target-not-found`, giving the
2871
2932
  applicable accepted form without inferring what the model meant. When the target is a
2872
2933
  registered tool of another executor, recovery gives that tool's exact bracketed
2873
- invocation; otherwise it points at an existing script or a bare shell-command body. A non-file resource
2934
+ invocation; when it names another available executor (`sh (python3)` over a Python body, #895),
2935
+ recovery names that executor's fence — `` `python3` is its own executor; use that name on the
2936
+ 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
2937
  target that cannot be read keeps the owning READ's failure identity (#163) and states
2875
2938
  the slot contract in its recovery — the resource is the program and the body its stdin;
2876
2939
  a command belongs beneath a targetless heading — without guessing which was meant (#425). The started receipt always
@@ -3002,7 +3065,8 @@ Per-tool programs such as `go`, `cargo`, `make`, and `npm` do not earn executor
3002
3065
 
3003
3066
  §exec-lifetime **How long a spawn may live is the fence's metadata, one field.**
3004
3067
  `[{"lifetime": …}]` takes a duration (`30s`, `30m`, `2h`), or one of three words;
3005
- absent is `loop`. An execution takes no scope: a numeric coordinate on an
3068
+ absent is `loop`. The key is one of the service's reserved metadata keys, withheld
3069
+ from every owner by the framework ({§service-metadata-keys}). An execution takes no scope: a numeric coordinate on an
3006
3070
  executor target is refused `scope-unsupported` (400), naming the field.
3007
3071
 
3008
3072
  | `lifetime` | The spawn |
@@ -3217,7 +3281,7 @@ body prefixes.
3217
3281
  wholesale ({§log-sensitive-request-evidence}); the spawn's record names each such value's
3218
3282
  provenance as the modifier's.
3219
3283
  - §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.
3284
+ - §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
3285
 
3222
3286
  | Input / effect | Consumer behavior |
3223
3287
  | --- | --- |
@@ -3626,6 +3690,14 @@ and is ignored rather than resolved against the working directory.
3626
3690
  | Reproducible cache | `$XDG_CACHE_HOME` (default `~/.cache`) | Reserved; no directory is created without an owned artifact. |
3627
3691
  | Shared global Agent Skills | User home | `.agents/skills/<name>/SKILL.md` |
3628
3692
 
3693
+ §state-root **A private daemon has one root.** `PLURNK_SERVICE_STATE_ROOT` (absolute; a leading
3694
+ `~/` expands; a relative value fails hard by name) replaces the data, state, cache and runtime homes
3695
+ with `<root>/data`, `<root>/state`, `<root>/cache` and `<root>/runtime`, the database with them
3696
+ (`PLURNK_SERVICE_DB_PATH` still names the database exactly). Configuration stays where the cascade
3697
+ reads it and the shared Agent Skills root stays under the user's home: a state root separates what
3698
+ the daemon *writes*, not what the operator supplies, and is no execution sandbox. What a launcher
3699
+ keeps or removes under a root after the daemon stops is that launcher's retention decision.
3700
+
3629
3701
  The service creates only a directory required by the current command. A newly
3630
3702
  created configuration or data directory uses mode `0700`; a newly seeded
3631
3703
  secret-bearing `.env` uses `0600`. Existing user-owned permissions are not
@@ -4048,7 +4120,12 @@ actions from model operations where the family contract requires it
4048
4120
  outcomes, and a snapshot with `commit`/`abort`. Successful publication commits;
4049
4121
  failure aborts; cooling tears down. Protocol continuations remain ordinary
4050
4122
  module actions. Optional `forget` releases an installed or provisioned
4051
- definition before removal; failure rejects removal ({§skills-remove}).
4123
+ definition before removal; failure rejects removal ({§skills-remove}). The
4124
+ seam's shapes — the identity a verb acts under, its options, definition
4125
+ sources, outcomes, preparation, the prepared result and the family handle —
4126
+ are declared once in `plurnk-contracts` and imported by core and every
4127
+ module; core adds only its own face of the seam, the runtime registration a
4128
+ resident family prepares and the scheme facet it may expose.
4052
4129
 
4053
4130
  An adapter may expose a `scheme` facet beneath its family's runtime namespace
4054
4131
  ({§runtime-resource-binding}). A facet claims a path subtree and is the scheme's
@@ -4224,11 +4301,12 @@ Core's behavior behind them.
4224
4301
  | §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
4302
  | Workspace lifecycle | `forkWorker({ workspaceId, workerId, name? })` | Creates a child worker that branches the source worker's history while sharing workspace state. |
4226
4303
  | §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 from the workspace's model-origin root conversations, newest-first. An omitted limit is `PLURNK_SERVICE_PROMPTS_PAGE`; spawned and forked child prompts are excluded. |
4304
+ | §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
4305
  | Workspace metadata | `listWorkspaces()`, `workspaceDerivationStatus(...)` | Reads current workspace identity and derivation progress. |
4229
4306
  | §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
4307
  | §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
4308
  | §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. |
4309
+ | §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
4310
  | 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
4311
 
4234
4312
  §methods-loop-run-fold-consistency **A folded prompt cannot silently reconfigure
@@ -4533,6 +4611,25 @@ flowchart LR
4533
4611
  measure --> rail[Engine budget admission and dispatch]
4534
4612
  ```
4535
4613
 
4614
+ ### §packet-wire-envelope The wire envelope
4615
+
4616
+ The packet reaches the provider as a transcript, under the roles the model was tuned on, its bytes unchanged:
4617
+
4618
+ | Message | Role | Content |
4619
+ |:--|:--|:--|
4620
+ | 1 | `system` | the system slot, as rendered |
4621
+ | 2, 4, … | `user` | the user slot's text up to and including the next placed emission row's record ({§emission-row}); the first opens with `## Log` |
4622
+ | 3, 5, … | `assistant` | that row's emission, as the worker's own message |
4623
+ | last | `user` | the records after the last placed emission, then the remaining user sections in {§packet-cache-monotone} order; native parts ride here ({§packet-attachment-parts}) |
4624
+
4625
+ Only role boundaries are added: joined by blank lines, the user messages are the user slot's
4626
+ bytes, in record order. An emission is placed exactly when its row is present in the final log
4627
+ section, so curation governs the transcript: a KILLed emission row, or one a trusted transform
4628
+ removed ({§packet-plugin-transform}), takes its emission with it, and a log without emission rows
4629
+ is one user message. The Worker block and the status clump always follow the log, so a request
4630
+ never ends on an emission, and the projection refuses one that would. The digest's packet
4631
+ artifacts record the sections, and `.wire.json` the messages ({§share-packet-names}).
4632
+
4536
4633
  ### §packet-cache-monotone Default order and cache locality
4537
4634
 
4538
4635
  Conditional absence never reorders the surviving default sections.
@@ -4554,7 +4651,9 @@ Conditional absence never reorders the surviving default sections.
4554
4651
 
4555
4652
  The order favors prefix-cache locality where semantics permit: the definition
4556
4653
  and privileged policy lead operator notes, while the append-mostly
4557
- log leads the volatile user-status clump. It does **not** claim that every system byte is
4654
+ log leads the volatile user-status clump. An emission sits at the row that announces it
4655
+ ({§packet-wire-envelope}), so the reusable prefix runs through every retained emission, and
4656
+ retiring one breaks the prefix at its row like any other curation. It does **not** claim that every system byte is
4558
4657
  immutable or that the complete packet is globally monotone in volatility:
4559
4658
  operator notes and policies can change. Trust is a separate
4560
4659
  admission rule. The system slot contains trusted control-plane material;
@@ -4570,6 +4669,8 @@ Each initial or returned list passes the schemes-owned validator, including
4570
4669
  unique-name enforcement, before the next transformer or renderer. Each
4571
4670
  transformer may inspect the section content and add, remove, or reorder
4572
4671
  sections. It receives no separate engine, database, actor, or request context.
4672
+ Emission placement reads the final log section, so a transform that removes an
4673
+ emission row's record removes its emission from the transcript ({§packet-wire-envelope}).
4573
4674
 
4574
4675
  This is strictly a trusted in-process seam, admitted through the common plugin
4575
4676
  trust gate; an external client action cannot invoke it. Whole-list transformation is
@@ -4583,13 +4684,13 @@ time of measurement.
4583
4684
 
4584
4685
  | Fact | Owner and unit | Time | Contract |
4585
4686
  |:-----|:---------------|:-----|:---------|
4586
- | Core curation weight | `contentWeight = ceil(chars/2)` over channel content, canonical log bodies, and rendered packet slots | Write/build | Stable, model-independent pressure and curation savings; never a tokenizer claim. |
4687
+ | Core curation weight | `contentWeight = ceil(chars/2)` over channel content, canonical log bodies, rendered packet slots, and placed emissions | Write/build | Stable, model-independent pressure and curation savings; never a tokenizer claim. |
4587
4688
  | §tokenomics-context-envelope-admission Provider input capacity | Provider model limits and configured output reservation, in provider tokens | Before every logical request | `min(maxInputTokens, contextWindow - outputBudget)` over the known terms. The provider alone measures the complete request and admits, defers, or rejects it. |
4588
4689
  | Provider generation envelope | Provider response grant and optional reasoning subset, in provider tokens | Before every logical request | The reservation includes hidden reasoning; its strict reasoning subset is never additive. The response grant follows {§provider-flexed-allowance}. |
4589
4690
  | Provider usage and cost | Provider-reported input/output/cache/reasoning tokens and monetary evidence | After every physical request | Durable physical-request forensics under {§provider-usage}; never curation state or a preflight estimate. |
4590
4691
 
4591
4692
  - §tokenomics-weight-stored-at-write **Curation weight, stored at write.** `entry_channels.weight` weighs the complete channel content. `log_entries.weight` weighs the complete canonical `LogBody` content before coordinate and packet presentation; persistence `tx`/`rx` envelopes contribute nothing merely by existing, and proposal settlement recomputes the value when the canonical result changes. Bodyless rows therefore weigh zero. The stored number is a stable content-depth measurement, not a provider-token prediction. `entry_channels.lines` is the channel's line count beside it, a stored generated column SQLite keeps on every write as the persisted mirror of {§logical-line-count} (a trailing newline terminates the last line; empty content has none), so a catalog lists extent without reading bodies.
4592
- - §tokenomics-render-weight-budget **Packet curation budget.** `logTokensTotal` measures the *complete assembled packet* after section transforms and readout substitution; it is not a sum of log-row `logTokens` fields. Core measures minimum-width probes, monotonically expands fields that do not fit, then right-aligns final values into those widths; final substitution is length-invariant and the displayed total equals the stored request weight. Receipt, FIND-item, pressure-inventory, total, and ceiling figures all use the same curation ruler. A `SUM` of stored content weights measures a different artifact and cannot substitute for packet render weight.
4693
+ - §tokenomics-render-weight-budget **Packet curation budget.** `logTokensTotal` measures the *complete assembled packet* after section transforms and readout substitution, its rendered slots and the emissions it places ({§emission-row}); it is not a sum of log-row `logTokens` fields. Core measures minimum-width probes, monotonically expands fields that do not fit, then right-aligns final values into those widths; final substitution is length-invariant and the displayed total equals the stored request weight. Receipt, FIND-item, pressure-inventory, total, and ceiling figures all use the same curation ruler. A `SUM` of stored content weights measures a different artifact and cannot substitute for packet render weight.
4593
4694
  - §tokenomics-calibrated-readout **Convert capacity, never content costs.** Before packet assembly, Core obtains the answering model's last five settled emission responses pairing a measured packet weight with a provider-reported prompt count. The conversion factor is `sum(reported) / sum(weight)`; fewer than three samples use 1. `logTokensMax = floor(inputCapacity / factor)` converts provider capacity into curation units. Zero means no whole curation unit fits; unknown input capacity remains `null`. The built packet captures this allowance once for its readout, pressure inventory, overflow admission, and persisted client gauge. Later responses cannot change that packet's allowance. Samples are model-keyed, not worker-local; a model with no samples starts at 1. Calibration never changes stored weights, rendered receipt costs, or the immutable request history ({§tokenomics-agnostic-ruler}).
4594
4695
  - §tokenomics-window-partition **One capacity derivation; no service-side token budget.** The provider owns model limits, the configured output reservation, and each call's response grant. Its resolved `inputCapacity` supplies the physical denominator exposed to clients and the boundary conversion into curation units ({§tokenomics-calibrated-readout}). Core shapes context in curation units; provider request-shaped evidence alone admits or rejects physical I/O. `PLURNK_SERVICE_PROMPT_BUDGET`, `PLURNK_SERVICE_SAFETY`, and the additive reasoning/completion reserve knobs are retired; local and custom deployments tune context window, total output budget, optional reasoning subset, and prompt-projection percentage at their owning layers.
4595
4696
  - §tokenomics-prompt-projection-share **Prompt projection is stable packet policy.**
@@ -4795,7 +4896,7 @@ leaves the request-only record, while rejected exchanges remain in their
4795
4896
  | Turn state | `turns.packet` (the bag) + `turn_sections` rows |
4796
4897
  | ----------------------------- | ----------------------------------------------- |
4797
4898
  | No admitted model request (including initialization and local capacity rejection) | SQL `NULL`, no rows |
4798
- | Request assembled | `{ weight, attributions }` + the sections as items |
4899
+ | Request assembled | `{ weight, attributions }` + the sections as items; the emissions it placed stay in their rows ({§emission-row}) |
4799
4900
  | Response admitted | `{ weight, attributions, assistant, assistantRaw }` + the sections as items |
4800
4901
 
4801
4902
  §packet-items **Sections are rows over content-addressed items; the bag never holds them.**
@@ -4851,6 +4952,7 @@ consumer reconstructs a name. A name that cannot be a file name, or two turns sh
4851
4952
  |----------|--------------|-----------|
4852
4953
  | `<stem>.assistant.md` | The turn has an `ops` source | Exact `turn_sources.content`, independent of log rows |
4853
4954
  | `<stem>.system.md`, `<stem>.user.md` | The turn stored a provider request | Stored text sections projected through `PacketWire`; native parts are not Markdown |
4955
+ | `<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 |
4854
4956
  | `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. |
4855
4957
  | `<stem>.assistantRaw.json` | The request has an admitted provider response | Stored opaque provider response |
4856
4958
  | `<stem>.response.md`, attempt artifacts | The request received no admitted response | Stored request and attempt state |
@@ -5041,6 +5143,8 @@ retain distinct contracts and lifetimes.
5041
5143
 
5042
5144
  §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
5145
 
5146
+ §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.
5147
+
5044
5148
  §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
5149
 
5046
5150
  §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,7 +5172,11 @@ retain distinct contracts and lifetimes.
5068
5172
 
5069
5173
  §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
5174
 
5071
- §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.
5175
+ §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 request's messages in order, each role above its content — the messages `.wire.json` carries) 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.
5176
+
5177
+ §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.
5178
+
5179
+ §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}); the op mix leaves the announcements 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 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
5180
 
5073
5181
  Unrecognized actionless log rows are retained and labelled as such, not
5074
5182
  interpreted as executable turnOps or allowed to prevent the remaining digest.
@@ -5110,7 +5218,7 @@ USD, and token totals across every physical exchange the turn paid for, failed
5110
5218
  calls included. It is the shared exact derivation from the ledger, never a second
5111
5219
  stored fact, so a live watcher accrues running loop cost per turn (#465).
5112
5220
 
5113
- §notice-content-offset-pointer **Content-offset position.** A non-fatal diagnosis on an accepted emission (for example `grammar_unenforced` or `parse_advisory`) carries `position: { type: "content-offset", line, column }` into the model's exact `ops://<worker>/<loop>/<turn>` source. A bounded hard parse error becomes a durable failed operation whose Problem Details preserve its line, column, source, and parser-owned diagnostic. Hard errors that make the frame untrustworthy remain only with their rejected forensic attempt.
5221
+ §notice-content-offset-pointer **Content-offset position.** A non-fatal diagnosis on an accepted emission (for example `grammar_unenforced` or `parse_advisory`) carries `position: { type: "content-offset", line, column }` into the model's exact `ops://<worker>/<loop>/<turn>` source; the transcript shows that turn's canonical emission instead ({§emission-row}), so the position names a line of the source, which READ of its address shows. A bounded hard parse error becomes a durable failed operation whose Problem Details preserve its line, column, source, and parser-owned diagnostic. Hard errors that make the frame untrustworthy remain only with their rejected forensic attempt.
5114
5222
 
5115
5223
  ### Executable tool resources
5116
5224
 
@@ -5687,3 +5795,152 @@ exits; a failed suite's evidence is never touched and stays exactly where the ru
5687
5795
  caller's own run directory.
5688
5796
 
5689
5797
  §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.
5798
+
5799
+ ## Problem codes and pinned wording
5800
+
5801
+ 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.
5802
+
5803
+ §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).
5804
+
5805
+ | code | status | contract |
5806
+ |---|---:|---|
5807
+ | `target-required` | 400 | *OP* requires a target path. Recovery: Write the target in parentheses on the opening fence line: `OP (path)`. |
5808
+ | `scheme-not-found` | 501 | Scheme '*name*' is not registered. |
5809
+ | `scheme-metadata-unsupported` | 400 | *OP* on '*scheme*' does not accept the [metadata] modifier. |
5810
+ | `operation-not-implemented` | 501 | Scheme '*name*' does not implement *OP* (or exec). |
5811
+ | `entry-read-not-implemented` | 501 | The '*scheme*' scheme does not provide entry reads. |
5812
+ | `entry-write-not-implemented` | 501 | The '*scheme*' scheme does not provide entry writes. |
5813
+ | `entry-delete-not-implemented` | 501 | The '*scheme*' scheme does not provide entry deletion. |
5814
+ | `channel-delete-not-implemented` | 501 | The '*scheme*' scheme does not provide channel deletion. |
5815
+ | `scheme-handler-threw` | 500 | The '*scheme*' scheme did not produce a result for *OP*. |
5816
+ | `exec-source-not-data` | 501 | Scheme '*name*' is not a data source for an execution. |
5817
+ | `writer-forbidden` | 403 | Writer '*origin*' cannot modify scheme '*name*'. |
5818
+ | `capability-denied` | 403 | Capability '*route*' is denied by *scope* policy. |
5819
+ | `spawn-prompt-empty` | 422 | *OP* has no prompt text: the resource is empty and there is no body. |
5820
+ | `message-not-found` | 404 | No accepted message exists at *address*. |
5821
+ | `edit-collision` | 409 | EDIT collided with the current resource state ({§edit-collision}). Recovery: *n* of *m* edits applied. READ the target for current coordinates. |
5822
+ | `edit-target-required` | 400 | A line-anchored EDIT requires a target resource. Recovery: Provide the target that rendered the line anchor. |
5823
+ | `kill-target-required` | 400 | KILL requires a target path. |
5824
+ | `kill-target-scheme-required` | 400 | KILL target requires a scheme. |
5825
+ | `worker-not-found` | 404 | Worker '*name*' does not exist in this workspace. |
5826
+ | `entry-operation-unsupported` | 400 | KILL requires an entry-bearing target; '*scheme*' does not provide one. |
5827
+ | `resource-scheme-required` | 400 | Resource selection requires an address. |
5828
+ | `channel-required` | 400 | The '*scheme*' scheme has no default channel. Recovery: Address a named channel with a URI fragment. |
5829
+ | `binary-source-unsupported` | 415 | Channel #*name* is binary and its scheme keeps no bytes to transfer. |
5830
+ | `metadata-unsupported` | 400 | *OP* takes only the env option; '*key*' is not one. |
5831
+ | `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. |
5832
+ | `no-operation` | 422 | The turn performed no operation ({§empty-turn}). |
5833
+ | `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. |
5834
+
5835
+ §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).
5836
+
5837
+ | code | status | contract |
5838
+ |---|---:|---|
5839
+ | `handler-crashed` | 415 | The *mimetype* content handler failed on *key*: *cause*. |
5840
+ | `line-anchor-unsupported` | 400 | The byte view of *target* publishes no anchors. Recovery: Use byte coordinates: `<first,last>`. |
5841
+ | `line-anchor-invalid` | 400 | A line anchor in the marker is malformed or names no current line ({§line-anchors}). |
5842
+ | `channel-not-found` | 404 | The addressed channel does not exist at *target*. Recovery: Use one of the available channels: #*a*, #*b*. |
5843
+ | `binary-read-unsupported` | 415 | The representation at *target* is binary and cannot be rendered. |
5844
+ | `pattern-unapplicable` | 422 | The pattern could not be applied to *target*. |
5845
+ | `move-region-overlap` | 409 | MOVE cannot insert a whole channel into itself and then remove that channel. |
5846
+ | `mimetype-mismatch` | 415 | COPY or MOVE cannot write '*source-mimetype*' into a '*destination-mimetype*' channel. |
5847
+ | `binary-region-unsupported` | 415 | Channel #*name* is binary and cannot receive a textual region. |
5848
+ | `copy-destination-exists` | 409 | COPY or MOVE destination *address* already contains different content. |
5849
+ | `proposal-apply-missing` | 500 | The source scheme accepted its MOVE proposal without applying the source mutation. |
5850
+ | `line-anchor-collision` | 409 | READ coordinates collided with current content at *target*. |
5851
+
5852
+ §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).
5853
+
5854
+ | code | status | contract |
5855
+ |---|---:|---|
5856
+ | `edit-empty` | 400 | EDIT requires at least one statement. Recovery: Provide an EDIT statement. |
5857
+ | `edit-batch-mismatch` | 400 | The EDIT batch spans multiple resources. Recovery: Submit a separate EDIT batch for each resource. |
5858
+ | `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. |
5859
+ | `creation-batch-conflict` | 409 | Multiple EDIT operations attempted to create the same file. Recovery: Create the file with one EDIT before applying additional edits. |
5860
+ | `member-read-only` | 403 | The mounted member '*path*' is read-only. |
5861
+ | `project-root-required` | 400 | The workspace has no project root, so it cannot write files. |
5862
+ | `path-names-no-file` | 403 | The spelling '*path*' does not name a file: it is empty, or it names a directory. |
5863
+ | `path-occupied-by-nonmember` | 403 | A non-member file already occupies '*path*'. Recovery: Choose an unoccupied member path. |
5864
+ | `path-outside-workspace` | 403 | A symlink on '*path*' resolves outside the namespace. |
5865
+ | `binary-write-unsupported` | 415 | A text EDIT cannot author binary '*mimetype*'; COPY or MOVE the bytes instead. |
5866
+ | `file-create-excluded` | 403 | A members exclusion (`!_glob_`) covers '*path*'. Recovery: Remove or disable the excluding members definition, or choose another path. |
5867
+ | `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. |
5868
+ | `file-materialization-limit` | 413 | The file exceeds the materialization byte limit and is not read into the workspace. |
5869
+ | `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. |
5870
+
5871
+ §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).
5872
+
5873
+ | code | status | contract |
5874
+ |---|---:|---|
5875
+ | `invalid-input-target` | 400 | SEND input addresses an execution, without a channel or scope. |
5876
+ | `input-unavailable` | 409 | This execution's input receiver is no longer enabled. |
5877
+ | `stream-not-found` | 404 | No execution exists at the requested address. |
5878
+ | `input-closed` | 410 | Execution input is closed. |
5879
+
5880
+ §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).
5881
+
5882
+ | code | status | contract |
5883
+ |---|---:|---|
5884
+ | `read-target-required` | 400 | READ requires a log coordinate. Recovery: Provide one exact log coordinate. |
5885
+ | `coordinate-malformed` | 400 | The log coordinate '*path*' is malformed. Recovery: Use one exact loop/turn/sequence coordinate. |
5886
+ | `worker-target-required` | 400 | EDIT requires a worker:// target. Recovery: Provide the worker target. |
5887
+ | `binary-edit-unsupported` | 415 | The #*channel* channel is binary and cannot be edited. |
5888
+ | `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. |
5889
+ | `worker-entity-not-editable` | 400 | A worker entity is not an editable entry. Recovery: EDIT requires an entry path, such as worker:///example.md. |
5890
+ | `message-empty` | 400 | SEND has no message text or attachments. |
5891
+ | `scope-unsupported` | 400 | A worker SEND takes no scope. |
5892
+
5893
+ §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).
5894
+
5895
+ | code | status | contract |
5896
+ |---|---:|---|
5897
+ | `service-starting` | 503 | The PLURNK service owns this listener but has not admitted its client interface yet. |
5898
+ | `configuration-unsupported` | 400 | Environment discovery reads this installation's declared configuration; client configuration contributes nothing. |
5899
+ | `name-reserved` | 400 | '*alias*' is plurnk's own: PLURNK_* configuration and provider credential names never reach a subprocess. |
5900
+ | `value-invalid` | 400 | '*alias*' needs a string value. |
5901
+ | `env-invalid` | 400 | `env` must be an object of string values; '*name*' is not a name a shell can export. |
5902
+ | `query-required` | 400 | discover takes a path or a glob. Recovery: Supply `{ "query": "<path or glob>" }`. |
5903
+ | `headless` | 409 | The workspace has no project root, so there are no file members. Recovery: Open the workspace on a project root. |
5904
+ | `definition-invalid` | 400 | A members definition is { glob }: a gitignore-style pattern, `!glob` to exclude; a skill definition names an installable skill. |
5905
+ | `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. |
5906
+ | `registry-unreachable` | 502 | Skills registry *url* could not be reached. |
5907
+ | `registry-rejected` | 502 | Skills registry *url* answered *status*. |
5908
+ | `registry-invalid` | 502 | Skills registry *url* returned no skills array. |
5909
+ | `discover-failed` | 502 | Agent Skills source '*source*' could not be listed: *cause*. |
5910
+ | `alias-mismatch` | 400 | Alias '*alias*' must equal the skill name '*name*'. |
5911
+ | `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. |
5912
+ | `source-required` | 400 | Adding '*alias*' requires the standard installer source that provides it. |
5913
+ | `uninstall-failed` | 502 | Agent Skill '*name*' could not be removed from its *scope* root: *cause*. |
5914
+ | `workspace-not-found` | 404 | Workspace *id* does not exist. |
5915
+ | `state-not-json` | 400 | Worker module state is not JSON-serializable. |
5916
+ | `workspace-busy` | 409 | Workspace *id* is running an operation or another capability change. Recovery: Settle the current operation and retry the capability change. |
5917
+ | `not-configured` | 503 | No provider is configured for this worker. |
5918
+ | `model-worker-required` | 404 | No model worker exists for prompt injection (or to fork). |
5919
+ | `name-conflict` | 409 | The worker name is taken. Recovery: Choose another worker name. |
5920
+ | `offset-channel-required` | 400 | Recovery: Select the channel to read from the offset. |
5921
+ | `target-invalid` | 400 | Recovery: Use a scheme://path target. |
5922
+ | `proposal-not-pending` | 409 | Recovery: Refresh pending proposals before resolving one. |
5923
+ | `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. |
5924
+ | `scope-cancelled` | 499 | The worker scope was cancelled: *reason*. |
5925
+ | `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. |
5926
+ | `registry-not-configured` | 501 | Skills registry search is disabled; PLURNK_SERVICE_SKILLS_REGISTRY_URL is empty. |
5927
+ | `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). |
5928
+ | `skill-missing` | 404 | Agent Skill '*alias*' is not installed under its *scope* root, or is not provided by this service. |
5929
+ | `skill-invalid` | 422 | Agent Skill '*alias*' is not a valid standard skill: *cause*. |
5930
+
5931
+ §pinned-wording-core **Pinned wording.** Verbatim sentences tests pin: each is contract, and a change here is a change of contract.
5932
+
5933
+ | sentence | arises when |
5934
+ |---|---|
5935
+ | Nothing is in flight. Continuing. | a WAIT (or a premature terminal) with no live work ({§wait-obligation-matrix}) |
5936
+ | Completion deferred. Conclude with KILL alone. | a concluding KILL that carries other operations ({§kill-conclusion}) |
5937
+ | Context Token Budget Overflow: logTokensTotal exceeds logTokensMax; retained context cannot be admitted. | output admission over the retained-context ceiling |
5938
+ | This run is unattended: nobody is present to answer. | a capability that needs a present operator in an unattended loop ({§loop-attendance}) |
5939
+ | 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 |
5940
+ | 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 |
5941
+ | The stream was cancelled by KILL. | a stream terminal after KILL |
5942
+ | '*program*' exited with code *n*. | an execution's non-zero exit |
5943
+ | '*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 |
5944
+ | The execution at ops://*worker*/*loop* has not concluded. | a bare READ of a running worker's result (425) |
5945
+ | The child provider failed. | a child's provider failure read back by its parent |
5946
+ | '*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 |