@plurnk/plurnk-service 1.3.1 → 1.3.3

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 (101) hide show
  1. package/README.md +9 -0
  2. package/SPEC.md +49 -17
  3. package/dist/build-info.json +1 -1
  4. package/dist/core/ChannelWrite.d.ts +2 -1
  5. package/dist/core/ChannelWrite.d.ts.map +1 -1
  6. package/dist/core/ChannelWrite.js +7 -6
  7. package/dist/core/ChannelWrite.js.map +1 -1
  8. package/dist/core/CoreSchemeServices.d.ts +31 -0
  9. package/dist/core/CoreSchemeServices.d.ts.map +1 -0
  10. package/dist/core/CoreSchemeServices.js +37 -0
  11. package/dist/core/CoreSchemeServices.js.map +1 -0
  12. package/dist/core/Dispatcher.d.ts +5 -2
  13. package/dist/core/Dispatcher.d.ts.map +1 -1
  14. package/dist/core/Dispatcher.js +115 -44
  15. package/dist/core/Dispatcher.js.map +1 -1
  16. package/dist/core/Engine.d.ts +4 -2
  17. package/dist/core/Engine.d.ts.map +1 -1
  18. package/dist/core/Engine.js +29 -10
  19. package/dist/core/Engine.js.map +1 -1
  20. package/dist/core/Engine.sql +1 -40
  21. package/dist/core/LiveSubscriptions.d.ts +8 -0
  22. package/dist/core/LiveSubscriptions.d.ts.map +1 -0
  23. package/dist/core/LiveSubscriptions.js +32 -0
  24. package/dist/core/LiveSubscriptions.js.map +1 -0
  25. package/dist/core/LoopLifecycle.d.ts +20 -0
  26. package/dist/core/LoopLifecycle.d.ts.map +1 -0
  27. package/dist/core/LoopLifecycle.js +56 -0
  28. package/dist/core/LoopLifecycle.js.map +1 -0
  29. package/dist/core/LoopLifecycle.sql +60 -0
  30. package/dist/core/ProposalLifecycle.d.ts +3 -1
  31. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  32. package/dist/core/ProposalLifecycle.js +4 -2
  33. package/dist/core/ProposalLifecycle.js.map +1 -1
  34. package/dist/core/SchemeRegistry.d.ts +3 -0
  35. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  36. package/dist/core/SchemeRegistry.js +23 -0
  37. package/dist/core/SchemeRegistry.js.map +1 -1
  38. package/dist/core/caps/DbSubscriptionCaps.d.ts +3 -2
  39. package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
  40. package/dist/core/caps/DbSubscriptionCaps.js +20 -9
  41. package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
  42. package/dist/core/caps/SchemeCtxImpl.d.ts +3 -16
  43. package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
  44. package/dist/core/caps/SchemeCtxImpl.js +4 -23
  45. package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
  46. package/dist/core/run-ops.sql +1 -1
  47. package/dist/core/scheme-types.d.ts.map +1 -1
  48. package/dist/core/scheme-types.js +3 -4
  49. package/dist/core/scheme-types.js.map +1 -1
  50. package/dist/schemes/Exec.d.ts +11 -10
  51. package/dist/schemes/Exec.d.ts.map +1 -1
  52. package/dist/schemes/Exec.js +40 -37
  53. package/dist/schemes/Exec.js.map +1 -1
  54. package/dist/schemes/ExecOutputScheme.d.ts +8 -6
  55. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  56. package/dist/schemes/ExecOutputScheme.js +11 -6
  57. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  58. package/dist/schemes/File.d.ts +11 -9
  59. package/dist/schemes/File.d.ts.map +1 -1
  60. package/dist/schemes/File.js +24 -16
  61. package/dist/schemes/File.js.map +1 -1
  62. package/dist/schemes/Log.d.ts +9 -7
  63. package/dist/schemes/Log.d.ts.map +1 -1
  64. package/dist/schemes/Log.js +12 -8
  65. package/dist/schemes/Log.js.map +1 -1
  66. package/dist/schemes/Prompt.d.ts +0 -3
  67. package/dist/schemes/Prompt.d.ts.map +1 -1
  68. package/dist/schemes/Prompt.js +0 -5
  69. package/dist/schemes/Prompt.js.map +1 -1
  70. package/dist/schemes/Skill.d.ts +0 -5
  71. package/dist/schemes/Skill.d.ts.map +1 -1
  72. package/dist/schemes/Skill.js +0 -10
  73. package/dist/schemes/Skill.js.map +1 -1
  74. package/dist/schemes/Worker.d.ts +12 -10
  75. package/dist/schemes/Worker.d.ts.map +1 -1
  76. package/dist/schemes/Worker.js +30 -28
  77. package/dist/schemes/Worker.js.map +1 -1
  78. package/dist/server/Daemon.d.ts +9 -1
  79. package/dist/server/Daemon.d.ts.map +1 -1
  80. package/dist/server/Daemon.js +161 -74
  81. package/dist/server/Daemon.js.map +1 -1
  82. package/dist/server/DaemonLock.d.ts +7 -0
  83. package/dist/server/DaemonLock.d.ts.map +1 -0
  84. package/dist/server/DaemonLock.js +85 -0
  85. package/dist/server/DaemonLock.js.map +1 -0
  86. package/dist/server/clientTurn.d.ts.map +1 -1
  87. package/dist/server/clientTurn.js +2 -3
  88. package/dist/server/clientTurn.js.map +1 -1
  89. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  90. package/dist/server/dispatch-as-plurnk.js +20 -2
  91. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  92. package/dist/server/drain.sql +4 -8
  93. package/dist/server/envelope.d.ts.map +1 -1
  94. package/dist/server/envelope.js +2 -3
  95. package/dist/server/envelope.js.map +1 -1
  96. package/dist/server/lifecycle-recovery.sql +68 -0
  97. package/dist/service.d.ts.map +1 -1
  98. package/dist/service.js +61 -40
  99. package/dist/service.js.map +1 -1
  100. package/migrations/0000-00-00.01_schema.sql +5 -5
  101. package/package.json +16 -15
package/README.md CHANGED
@@ -51,3 +51,12 @@ Plurnk sees what git sees. The model's file surface is defined by three external
51
51
  Run the root monorepo commands for deterministic lint, unit, and integration
52
52
  coverage. Live-model, demo, and installation tests declare their external
53
53
  requirements separately.
54
+
55
+ For manual client/service drills, create the modest standalone project used by
56
+ the demos instead of digesting this monorepo:
57
+
58
+ ```sh
59
+ npm run fixture:demo -w plurnk-core -- <label>
60
+ ```
61
+
62
+ The command prints the temporary project path. The caller removes it when done.
package/SPEC.md CHANGED
@@ -193,7 +193,7 @@ All three ride one engine seam — the daemon's inject (active→fold, idle→en
193
193
  Beyond the three creation ops:
194
194
 
195
195
  - **Entries (storage)** — entry addressing rides the authority carving above (§worker-authority-carving): `worker:///` the commons, `worker://~/` the own space, a name an ancestry-gated read (§worker-read-scope), writes self-and-commons only (§worker-write-scoping). An entry-path `KILL` deletes under the same write-scoping (200; 404 absent; 403 named) — distinct from the path-ABSENT `KILL(worker://<name>)` which terminates the worker (§worker-scheme-terminate); the discriminator is the entry path, never the op. A worker's own space is catalogued in ITS perspective alone (`FIND(worker://~/**)`, foisted at turn 0 when non-empty); isolation is the owner column, structural.
196
- - **Terminate** — `KILL(worker://<name>)` aborts a worker by address (self is `worker://self`): its active loop closes 499 and its subscriptions tear down; a name with no worker is 404. The override to the fire-and-forget default not a parent-power, whoever holds the address may end it; a worker left alone simply ends at its own `SEND[200]`. {§worker-scheme-terminate}
196
+ - **Terminate** — `KILL(worker://<name>)` aborts a worker by address (self is `worker://self`): every unresolved loop in that worker's subtree closes 499 and every subscription in the subtree tears down; a name with no worker is 404. Cancellation is structured: descendants cannot detach implicitly. The override to the fire-and-forget default is not a parent-power whoever holds the address may end it; a worker left alone simply ends at its own `SEND[200]`. {§worker-scheme-terminate}
197
197
  - **Cap** — `PLURNK_SERVICE_WORKSPACE_WORKERS_MAX_ACTIVE` ceilings the *concurrent* active workers per workspace (a worker with a non-terminal loop); a spawn or fork past it fails hard (508 — no queue, no retry), irc exempt; `-1` disables it. The fork-bomb brake, sized for workspaces that live for months. {§worker-scheme-cap}
198
198
  - **Collect** — a worker's loop reaching a terminal status surfaces to its sisters as an ambient delta (§env-delta): a `SEND` from `worker://<name>` carrying the loop's deliverable — the `SEND[200]` body, or for an abandonment the reason. A **2xx deliverable is born OPEN** (its body materialized into the parent's packet, not hidden behind a fold): a child's success must reach the parent open and awakening, never a bodyless row. An abandonment (non-2xx) surfaces folded. Every death-path is stamped uniformly, so no termination is silent; collection is the shared world moving, never a verb. **Child orientation.** Beyond the conclusion delta, every turn the packet's status clump surfaces the live things THIS worker *currently holds* — open streams (`## Child Streams`) and unconcluded child workers (`## Active Child Workers`) — as terse `* <status> <path>` pointers (the same shape as the errors section), just above it. A worker is otherwise marked only at spawn and at conclusion; in between it goes silent, so a model loses track of what it holds and premature-terminates. This is ORIENTING STATE, never advice: the model SEES its live subtree (`* 102 worker://worker-x`, `* active sh:///1/2/3`) and reasons for itself — READ/OPEN/KILL via the path — the error stays terse. Empty → omitted, like errors. {§child-orientation} The **pull** side mirrors the push: a path-absent `READ(worker://<name>)` collects the same deliverable on demand — the latest loop's terminal message (the result, or the abandonment reason) for a concluded worker; a worker **still running** has not delivered, so the READ returns **425** (Too Early) and the turn's `SEND[202]` **blocks the loop on the join** ({§join-blocking-collect}) until the worker delivers — the engine holds the join, the model never drives a park. A missing name is 404. So the model never needs to guess a scratch path to "check on" a worker — reading the worker itself yields its outcome or a wait. {§worker-scheme-collect}
199
199
 
@@ -203,14 +203,29 @@ Beyond the three creation ops:
203
203
 
204
204
  A worker is a **log plus a cancellation scope** — one `AbortController` per worker, reused while live and replaced only once aborted, so a cancel ends the worker as a unit and a later `loop.run` is never born cancelled. A worker's queued loops are advanced by a **drain**: a single per-worker worker that claims loops atomically (status 100→102) and runs each under the worker's scope. A loop may spawn **streams** (execs) that outlive it; each is a row in the subscription registry (§subscriptions) — the durable record of what the worker holds open. Cancellation and conclusion are defined against these structures, never wall-clock timing.
205
205
 
206
+ ```mermaid
207
+ stateDiagram-v2
208
+ [*] --> Queued: loop.run
209
+ Queued --> Running: drain claims
210
+ Running --> Parked: wait with live obligations
211
+ Parked --> Queued: obligation settles or arrival
212
+ Running --> Terminal: conclude or fail
213
+ Parked --> Terminal: cancel
214
+ Queued --> Terminal: cancel
215
+ Terminal --> [*]
216
+ ```
217
+
218
+ The lifecycle store admits only the guarded transitions shown above: `100 → 102`, `102 → 202`, `202 → 100`, and any unresolved state (`100`, `102`, `202`) to a terminal status. Terminal state is immutable. The queue drain owns claim, the dispatcher owns model-requested park/conclusion, the daemon owns wake/cancellation/restart reconciliation, and the engine owns policy terminals. A racing transition that loses observes the durable winner; it does not overwrite it or report the requested state as fact. {§worker-lifecycle-state-machine}
219
+
206
220
  - **One drain advances a worker.** At most one drain is registered for a worker at any instant: a `loop.run` or wake on a worker with a live drain folds in (active→next-turn) or enqueues a loop that drain claims, never a second parallel drain. A drain's start and its empty-queue teardown relinquish the worker under one per-worker lock, so the teardown's re-claim cannot race a concurrent start into a double-drain. {§worker-lifecycle-single-drain}
207
- - **A cancel reaps every stream the worker holds by the registry.** `loop.cancel` / `KILL` / shutdown abort the worker scope AND iterate the worker's open subscriptions, aborting each via its owning scheme; the registry is the source of truth, the in-process abort signal a fast-path optimization. A stream that is running, mid-spawn (its row written before it is killable), or spawned after the cancel is reaped alike. The teardown abort is a BOUNDED reap — the executor sends a polite signal then SIGKILL after a consumer-set grace (`PLURNK_SERVICE_EXEC_KILL_GRACE_MS`), so a signal-ignoring stream can't wedge it; a model `KILL[code]` on a live stream instead delivers exactly that signal once (bare `KILL` → the executor's SIGHUP default, `KILL[9]` → SIGKILL), the model owning any escalation. {§worker-lifecycle-total-reap}
221
+ - **Cancellation is recursive and reaps every held stream.** `loop.cancel`, worker `KILL`, shutdown, and a worker's `SEND[499]` terminalize every unresolved loop in the cancelled worker subtree and iterate each worker's durable open-subscription rows, invoking each exact callable owner from the process-local live registry. The durable rows answer *what is held*; the live registry answers *how this process tears it down*; the abort signal is a fast-path optimization. There is no implicit detachment. A stream that is running, mid-spawn (its row written before it is killable), or spawned after the cancel is reaped alike. The teardown abort is bounded: the executor sends a polite signal then SIGKILL after a consumer-set grace (`PLURNK_SERVICE_EXEC_KILL_GRACE_MS`). A model `KILL[code]` on one live stream instead delivers exactly that signal once (bare `KILL` → the executor's SIGHUP default, `KILL[9]` → SIGKILL). {§worker-lifecycle-total-reap}
208
222
  - **A stream's kill binds to the scope it captured at spawn.** A stream captures the worker's cancellation scope as it registers and wires its kill to it, re-checking `aborted` AFTER wiring — no check-then-listen gap can drop an abort that lands mid-registration. Because the scope is replaced only once aborted, a captured-then-replaced scope is necessarily already aborted, so replacement never strands a live stream. {§worker-lifecycle-exec-epoch-bound}
209
223
  - **A cancelled run is not resurrected by its own torn-down work.** A stream conclusion delivered to a cancelled, idle worker starts no fresh drain: an aborted (499) conclusion is skipped, and a straggler that concluded cleanly surfaces its deliverable as an environment delta (§env-delta), never a revived loop. The cancel was deliberate; only an explicit `loop.run` resumes the worker. {§worker-lifecycle-no-resurrection}
210
224
  - **A stream conclusion always reaches its worker.** When a backgrounded stream concludes, the daemon routes it through the same inject seam as any loop source (§actor-boundary-passive-wake): an active worker folds the conclusion into its next turn; a worker **blocked on a 202 wait** for that stream (§wait-obligation-matrix) **awakens that loop in place** — the blocked loop *is* the continuation, so there is no fresh loop and no summary-as-prompt fiction. The result is never lost: a blocked loop sleeps rather than ending, and the stream's status-transition is the arrival (§actor-boundary-passive-wake) that wakes it; on resume it reads the concluded stream's own state, not a synthetic prompt. {§worker-lifecycle-wake-liveness}
211
225
  - **A child worker concluding wakes a parent blocked on it — the topology join.** `worker://` spawn/fork records `parent_worker_id` (§lifecycle-terms). When a worker's drain exits having **concluded** — no `202`-blocked loop, no open stream — the daemon resumes its parent **in place** if the parent is blocked on the join (`#onDrainExit` → the shared `#wakeParkedWorker`, the same 202→100 resume a stream conclusion uses). So a parent that spawns work and blocks (`SEND[202]`) is woken the moment its child finishes; on resume it reads the child's deliverable from the §worker-scheme-collect delta in its own log — a control edge, **never an injected prompt**. The wake recurses upward via the parent's own drain-exit. A child still running — or itself blocked at 202 — is not *concluded*, so it does not wake the parent (it's still a live thing the subtree holds). This is the structured-concurrency join: streams and child workers are the same kind of "live thing a worker holds," driving premature-terminate (§send-premature-terminate), the wake edge, and the collect delta identically. A worker conclusion is a **bounded, un-loseable** wake: if the conclusion fires while the parent is mid-turn (before its block commits), `#wakeParkedWorker` finds it not-yet-slept and records an **owed wake**, which the drain honors when the parent blocks — so a wait awaiting workers **always returns**, never dead-blocks on a conclude-before-block race. (Only a live exec stream, unbounded absent a timeout, may legitimately hold a wait open.) {§worker-lifecycle-child-wake}
212
- - **An idle run concludes; it does not park.** A loop with nothing in flight — no live child, no open stream — concludes by SAYING so (`SEND[200]`); a `SEND[202]` there is the ∅-wait contradiction and returns 409 (§wait-obligation-matrix), so there is no held-open `202` loop, no `loop/quiesced` soft signal, and no silent engine-conclusion over a confusion. A concluded worker is *already* reawakable — it is durable working history (§machine-processes-worker-is-its-log, engine_render_log spans the whole worker), and an addressed arrival (a sibling `irc`, an operator inject, a later `loop.run`) reawakens it as a **new loop** carrying that arrival's real prompt. Only a loop that holds a live obligation *blocks* (§wait-obligation-matrix, the `202+J` join); a subtree with any live thing under it is not idle, and that thing's conclusion reawakens the **same** loop with its prompt intact (§worker-lifecycle-child-wake). {§worker-lifecycle-idle-is-concluded}
226
+ - **An idle run concludes; it does not park.** A loop with nothing in flight — no live child, no open stream — concludes through `SEND[200]` or an already-drained `SEND[202]` join (§wait-obligation-matrix). There is no held-open `202` loop and no `loop/quiesced` soft signal. A concluded worker is *already* reawakable — it is durable working history (§machine-processes-worker-is-its-log, engine_render_log spans the whole worker), and an addressed arrival (a sibling `irc`, an operator inject, a later `loop.run`) reawakens it as a **new loop** carrying that arrival's real prompt. Only a loop that holds a live obligation *blocks* (§wait-obligation-matrix, the `202+J` join); a subtree with any live thing under it is not idle, and that thing's conclusion reawakens the **same** loop with its prompt intact (§worker-lifecycle-child-wake). {§worker-lifecycle-idle-is-concluded}
213
227
  - **A loop is never stranded by a drain's exit.** A drain relinquishes its registry slot only after a lock-held re-claim confirms the queue is empty; a loop enqueued during that teardown is either re-claimed by the exiting drain or claimed by a fresh drain that a later inject starts. The relinquish and the start are serialized, so neither the lost-loop hang nor a transient double-drain can occur. {§worker-lifecycle-no-lost-loop}
228
+ - **Restart is owner-loss reconciliation, not replay.** {§worker-lifecycle-restart-recovery} Before opening client transports, the service holds an exclusive database-adjacent daemon lock; a second live owner fails before touching SQLite, while a dead-PID crash claim is replaced atomically without a timeout lease. Boot preserves accepted `100` loops and restores their drains. A `102` loop belonged to a vanished drain/provider call, so it settles `500` with the interruption on its durable row—never replayed across an unknown effect boundary. Every durable-open subscription likewise belonged to a vanished callable: active channels become errored and its row closes `500`. A `202` continuation survives only while a live child obligation remains; after reconciliation, an unblocked park requeues `202→100` and resumes in place. Child terminalization wakes its parked parent on every outcome, including provider exceptions, cancellation, and restart interruption, recursively through the durable parent edges. These operations are idempotent, so an interrupted recovery safely repeats.
214
229
 
215
230
  ---
216
231
 
@@ -318,7 +333,7 @@ Per author contract (`readEntry` / `writeEntry` / `deleteEntry`). Engine drives
318
333
 
319
334
  Per author contract (`edit`/`read`/`open`/`fold`/`find`/`send`/`exec?`). Engine dispatches by `PlurnkStatement.op`. {§op-methods-op-dispatch} COPY and MOVE are NOT scheme methods — engine orchestrates over CRUD primitives (§copy/§move).
320
335
 
321
- - **Every op completes before the next begins — except the three concurrency-creators.** {§op-synchronous} Within a turn ops run in sequence, and each is *decisive*: its effect has fully landed by the time the next op — or the terminal gate — reads it. The dispatch `await`s each, so `KILL`, `EDIT`, `COPY`, `MOVE`, `READ` (including the blocking worker-collect, §worker-scheme-collect), `FIND`, `OPEN`, `FOLD` never leave work "in flight" for a later op to trip over. The ONLY exceptions are the ops whose *job* is to create concurrency and hand it back tracked: **FORK** and **WORK** (spawn a child worker) and **stream-producers** (`EXEC` and friends) return the instant the concurrent thing is launched and registered (the §child-orientation sections), never blocking the turn on its conclusion. This is the OS syscall model exactly — calls block; only `fork`/`spawn`/async-I/O don't — and it is why a same-turn `KILL + SEND[200]` concludes (§send-premature-terminate): `KILL` synchronously flips the worker's live loops terminal (`engine_terminate_worker_live_loops`) so the gate sees it dead at once, while the physical scope reap rides `cancelWorker` asynchronously and invisibly. The obligation is the model's protection: it must never reason about whether its last decisive op has "landed yet."
336
+ - **Every op completes before the next begins — except the three concurrency-creators.** {§op-synchronous} Within a turn ops run in sequence, and each is *decisive*: its effect has fully landed by the time the next op — or the terminal gate — reads it. The dispatch `await`s each, so `KILL`, `EDIT`, `COPY`, `MOVE`, `READ` (including the blocking worker-collect, §worker-scheme-collect), `FIND`, `OPEN`, `FOLD` never leave work "in flight" for a later op to trip over. The ONLY exceptions are the ops whose *job* is to create concurrency and hand it back tracked: **FORK** and **WORK** (spawn a child worker) and **stream-producers** (`EXEC` and friends) return the instant the concurrent thing is launched and registered (the §child-orientation sections), never blocking the turn on its conclusion. This is why a same-turn `KILL + SEND[200]` concludes (§send-premature-terminate): `KILL` synchronously flips the worker's live loops terminal (`engine_terminate_worker_live_loops`) so the gate sees it dead at once, while the physical scope reap rides `cancelWorker` asynchronously and invisibly. The obligation is the model's protection: it must never reason about whether its last decisive op has landed yet.
322
337
 
323
338
  ### §orchestration Cross-scheme orchestration
324
339
 
@@ -638,7 +653,7 @@ AST: `{ op: "SEND", target: ParsedPath | null, body: SendBody | null, signal: nu
638
653
  - **Broadcast** (path null): the loop's disposition verb. `signal` is the model's *claim* about the worker's state — see the terminal contract.
639
654
  - **Directed** (path non-null): routes to `scheme.send` per §send-dispatch — stream control / cross-worker irc, never a loop terminal.
640
655
 
641
- **Terminal contract — the model's surface is `waitpid` in three signals.** A broadcast SEND's status is a claim the engine **verifies against the worker's actual state**, never a verdict it trusts. The model signals one intention — **continue (102)**, **done (200)**, or **wait (202)** — plus **499**, give up; the behavior falls out of that intention **crossed with the loop's obligations**, exactly as `waitpid(&status, options)` resolves against a process's live children, and a structured-concurrency scope refuses to close over them. An **obligation** is live work the loop set going and has not consumed: **J**, a child or stream it spawned (the join), and **R**, this turn's own retrievals (READ/FIND/OPEN, whose results land next turn). `<T,P>` is the standard **timeout / poll** override on a wait a bound and a re-inspection cadence, nothing exotic.
656
+ **Terminal contract — three signals over a structured-concurrency scope.** A broadcast SEND's status is a claim the engine **verifies against the worker's actual state**, never a verdict it trusts. The model signals one intention — **continue (102)**, **done (200)**, or **wait (202)** — plus **499**, give up. An **obligation** is live work the loop set going and has not consumed: **J**, a child or stream it spawned (the join), and **R**, this turn's own retrievals (READ/FIND/OPEN, whose results land next turn). `<T,P>` is an explicit timeout / poll override for external streaming work; ordinary child joins are event-driven and carry no polling fallback.
642
657
 
643
658
  | intention | ∅ (no obligation) | J (live spawned work) | R (pending retrieval) |
644
659
  |---|---|---|---|
@@ -646,9 +661,9 @@ AST: `{ op: "SEND", target: ParsedPath | null, body: SendBody | null, signal: nu
646
661
  | **200** done | **resolved** — terminal, loop ends | **refused** — Premature-Terminate (KILL to abandon, or wait) | **refused** — forced next turn to see what you fetched |
647
662
  | **202** wait | **resolves like 200** — a wait on zero things is satisfied; `<-1>+∅` is a bid to hang the agent, folded to done, never honored | **block on the join** — the loop sleeps (`<T>`/`<-1>` bound it, `<P>` polls); its work's conclusion **reawakens the same loop**, prompt intact (§worker-lifecycle-child-wake, §worker-lifecycle-wake-liveness) | resolves next turn (≈ continue) |
648
663
 
649
- **499** gives up regardless of obligations — the model's one self-decided failure (§state-terms), and the only conclude that discards its live subtree. The surface is small on purpose. The **one** non-obvious cell is **200 with an obligation in flight** — a contradiction (you claimed done while you owe work), which the engine holds you to via Premature-Terminate below. Every wait is **bounded** — by a join guaranteed to conclude, or by a finite `<T>`. A wait with NOTHING pending (∅ — no stream, no child, no unretrieved result) is the wait-side contradiction, the mirror of premature-terminate: **409**, the turn returns to the model with the fact (a satisfied wait is a conclusion, and a believed-pending obligation that does not exist is exactly the confusion the error channel must surface — #502 run113 concluded CLEAN on it). No park-into-the-void, no silent conclude-on-nothing — `waitpid` with `ECHILD`. {§wait-obligation-matrix}
664
+ **499** gives up regardless of obligations and cancels the unresolved descendant scope — the model's one self-decided failure (§state-terms). The surface is small on purpose. The **one** non-obvious cell is **200 with an obligation in flight** — a contradiction (you claimed done while you owe work), which the engine holds you to via Premature-Terminate below. A child join is bounded by the child's terminal transition; an external stream may carry an explicit `<T,P>` policy. {§wait-obligation-matrix}
650
665
 
651
- **An engine-authored terminal is marked as state, never re-worded** (#379, owner ruling). `terminated_by` names who ended a loop when the model did not: `'cancel'` for an externally-cancelled loop (§methods-loop-cancel); `NULL` = the model's own terminal, whose status already carries the story. The COLLECT and the loop-termination delta render the named act as a marker before the model's own last words, unrewritten both truth layers, neither fabricated (run42's parent COLLECTed a worker's "Standing by for user input" as a status-200 stage result and re-spawned blind, nine times). Rows carrying `'collapse'` render the marker `[ concluded on ∅-collapse — waited on nothing; no result was produced ]` — the ∅ wait itself is a 409 (§wait-obligation-matrix), so no new collapse terminal mints; the render contract holds for every row history carries. {§wait-collapse-marked}
666
+ **An externally-authored terminal is marked as state, never re-worded.** `terminated_by` names who ended a loop when the model did not: `'cancel'` for an externally-cancelled loop (§methods-loop-cancel); `NULL` = the model's own terminal, whose status already carries the story. COLLECT renders the named act as a marker before any preserved last words, so cancellation cannot masquerade as a deliverable. An already-drained join is the model's own successful terminal and needs no special marker.
652
667
 
653
668
  The engine's failure terminals — **500** (strike threshold) and **508** (cycle), §engine-rails — are never the model's to pick; they are the engine ruling the loop failed. The surface is small on purpose: the model says done, waiting, or giving up, and is never asked to hold a correct opinion about *how* it failed or *whether* it can be woken — the engine decides those from state.
654
669
 
@@ -666,7 +681,7 @@ Engine routes unconditionally to `exec` scheme (the `(target)` slot is a local p
666
681
 
667
682
  **Runtime fall-through** {§exec-runtime-fallthrough} — an UNREGISTERED runtime tag falls through to the shell with the tag as the command word: `EXEC[go]:test ./...` runs as sh's `go test ./...` (#350, the execs architect's dispatch spec automating the owner's execs#21 ruling: per-tool runtimes — go, cargo, make, npm — never earn tags; sh is the general answer). The fall-through rides sh's OWN policy gate (a workspace that disabled sh gets the refusal, never a side door), its output entry lands under `sh://` (it ran on sh, no phantom scheme), and telemetry records `exec_runtime_fallthrough {requested}` — which tags models reach FOR is the data that would ever justify a real runtime, never guesswork. A typo'd tag becomes the shell's own clear 127. No new surface: anything expressible as `EXEC[foo]:bar` was expressible as `EXEC[sh]:foo bar`. The 501 remains for a fall-through-ineligible dispatch (sh itself unregistered or workspace-disabled).
668
683
 
669
- **Timeout and poll — `<T,P>` on the `<L>` slot (grammar 0.74.20).** EXEC repurposes the line-marker slot as `<timeout, poll>` in **seconds** (consistent with the `seconds=` stream-age render). `T` (mark[0]) caps the spawn's lifetime: at `T>0` the service aborts it (a bounded reap — polite signal then SIGKILL after `PLURNK_SERVICE_EXEC_KILL_GRACE_MS`) and stamps the stream **504**, distinct from a deliberate kill (499) or a clean exit (200). `-1` / absent → unbounded (loop-life bounded), the background-stream behavior. **`0` → turn-scoped**: the stream is reaped at the worker's *next pre-turn* (via the registry abort, before the turn's own spawns), so it never survives into the subsequent turn; its terminal output surfaces born-OPEN like any close (§exec-stream). {§exec-timeout} `P` (mark[1]) is the **poll cadence**, stored on the subscription: while the loop is *blocked on a `SEND[202]` wait* for that stream (the poll rides the subscription), the daemon arms a per-worker timer for the tightest open poll cadence and resumes the blocked loop every P seconds (floored by `PLURNK_SERVICE_EXEC_WAIT_MS` so it can't tick faster than a turn settles) to inspect progress (the same 202→100 resume a stream conclusion uses, §worker-lifecycle). It does **nothing while the loop is active** an active loop already gets the ambient folded stream deltas (§exec-stream), so the poll-wake matters only across a wait. An absent `P` on ANY unbounded park no longer sleeps blind: the daemon wakes the loop on an **exponential backoff** (`PLURNK_SERVICE_EXEC_POLL_SEC` base, doubling for `PLURNK_SERVICE_EXEC_POLL_TURNS` steps — 60,120,…,7680s — then holding at the cap), so **no park is ever blind** (#521, owner-ruled). This is UNIVERSAL — a hung exec AND a child-join park (blocking collect) wake on the same ladder — so a lost wake edge (a dropped stream conclusion or child terminal) self-heals within one step: the model regains a turn to read partial output and re-park a slow long-runner or **KILL** a stuck one (no auto-kill — only the model tells a silent deadlock from a silent `cargo build`). The primary wake edge still resumes it immediately when it fires; the backoff is the safety net beneath it. Non-striking (a correctly-waiting parent never strikes out). Explicit `<,P>` (P>0) wins with its fixed cadence; `<,0>` opts out (blind, an exec a model wants unwatched). {§exec-poll}
684
+ **Timeout and poll — `<T,P>` on the `<L>` slot (grammar 0.74.20).** EXEC repurposes the line-marker slot as `<timeout, poll>` in **seconds** (consistent with the `seconds=` stream-age render). `T` (mark[0]) caps the spawn's lifetime: at `T>0` the service aborts it (a bounded reap — polite signal then SIGKILL after `PLURNK_SERVICE_EXEC_KILL_GRACE_MS`) and stamps the stream **504**, distinct from a deliberate kill (499) or a clean exit (200). `-1` / absent → unbounded (loop-life bounded), the background-stream behavior. **`0` → turn-scoped**: the stream is reaped at the worker's *next pre-turn* (via the registry abort, before the turn's own spawns), so it never survives into the subsequent turn; its terminal output surfaces born-OPEN like any close (§exec-stream). {§exec-timeout} `P` (mark[1]) is the **poll cadence**, stored on the subscription: while the loop is *blocked on a `SEND[202]` wait* for that stream, the daemon arms a per-worker timer for the tightest open poll cadence and resumes the blocked loop every P seconds (floored by `PLURNK_SERVICE_EXEC_WAIT_MS` so it cannot tick faster than a turn settles) to inspect progress. It does **nothing while the loop is active** because ambient stream deltas already surface progress. An open stream without `P` uses exponential backoff (`PLURNK_SERVICE_EXEC_POLL_SEC` and `PLURNK_SERVICE_EXEC_POLL_TURNS`); explicit `<,P>` wins and `<,0>` disables polling. Child-only joins never use this timer: child settlement is their durable wake edge. {§exec-poll}
670
685
 
671
686
  **Effect-gating.** Each executor declares an `effect` (`pure` | `read` | `host`); the service maps it to policy (`EffectPolicy`). A `host` runtime (subprocess; file-backed sqlite) mutates the host → **propose** (lifecycle §proposal): the worker waits for a human gate, then spawns and writes stdout/stderr to channels of a `<runtime>:///<loop>/<turn>/<seq>` entry (the runtime tag is the URI scheme, §exec/#240; the coordinate matches the op's log-row coordinate, e.g. `sh:///1/1/2`), returning `102 Processing` immediately. Channel state transitions (`active` → `closed`/`errored`) drive what the model sees at subsequent turn boundaries (§channel-state). {§exec-host-proposes}
672
687
 
@@ -716,9 +731,14 @@ Streams are static content from the engine's perspective — content arrives ove
716
731
 
717
732
  ### §subscriptions Subscriptions
718
733
 
719
- READ on a streaming scheme is a subscription, not a one-shot. Scheme opens the connection (SSE/WS/subprocess), returns `102 Processing` immediately, stays alive. Engine records `(workspaceId, entryId) schemeName + handle` in a subscription registry so `SEND[499]` cancellation routes to the owning scheme. {§subscriptions-subscription-registry-routes-cancellation}
734
+ READ on a streaming scheme is a subscription, not a one-shot. Scheme opens the connection (SSE/WS/subprocess), returns `102 Processing` immediately, stays alive. The service records durable subscription identity and metadata in SQLite and retains the callable `SubscriptionHandle` only in its process-local live registry. `SEND[499]`, worker cancellation, turn-scoped reap, and shutdown all route through that one live registry; no handler-specific cancellation hook or database access is part of the plugin contract. {§subscriptions-subscription-registry-routes-cancellation}
735
+
736
+ The durable row is lifecycle evidence and the lookup key, not a serialized callback. `subscriptions.open()` establishes both halves before yielding; `subscriptions.close("done" | "error" | "cancelled")` settles channel state and status (200/500/499), closes the durable row, wakes the worker when appropriate, and unregisters the live handle. A durable open row without a live handle is an explicit lifecycle failure, never a fabricated cancellation success. Channel state (§channel-state) + log entries (§no-chunk-rows) carry lifecycle.
720
737
 
721
- Subscription registry is plurnk-service runtime state (its own SQLite table). Exists ONLY for cancellation routing. Channel state (§channel-state) + log entries (§no-chunk-rows) carry lifecycle.
738
+ At process restart every still-open row is necessarily missing its callable owner. Boot
739
+ settles it as interruption (`500`) and errors active channels before evaluating parked
740
+ loops (§worker-lifecycle-restart-recovery); it never reports cancellation (`499`) or
741
+ pretends to reconstruct an opaque plugin connection.
722
742
 
723
743
  FOLD/OPEN toggles `log_entries.expanded` (§open-fold) — a per-worker render bit, never the subscription registry. FOLDing a streaming entry's log row collapses its body out of the packet but leaves the live stream running: curation is render-only, never cancellation. {§subscriptions-fold-keeps-subscription}
724
744
 
@@ -738,7 +758,7 @@ Model sees lifecycle events in the `log` section per turn.
738
758
 
739
759
  ### §stream-control SEND for stream control
740
760
 
741
- - **Cancel:** `<<SEND[499](sse://feed/x)::SEND` — scheme tears down via AbortController.
761
+ - **Cancel:** `<<SEND[499](sse://feed/x)::SEND` — the service invokes the handle registered by `subscriptions.open()` and aborts the composed subscription signal.
742
762
  - **Write:** `<<SEND[200](wss://feed/x):body:SEND` — pipes body into active connection (WS, exec stdin, etc.).
743
763
 
744
764
  ### §stream-constraints Engine constraints
@@ -1006,7 +1026,7 @@ registry.registerMethod("loop.run", {
1006
1026
  | `loop.run` | `prompt: string`, `maxTurns?: number`, `alias?: string`, `model?: string`, `flags?: LoopFlags` | `{ loopId, action, finalStatus: 100 }` | Model-driven loop. **Accepts and returns immediately** (`finalStatus: 100`; `action` = `enqueued_new_loop` \| `injected_next_turn`) — it never blocks on the loop, which may block on a `SEND[202]` wait for its own spawned work (§worker-lifecycle-wake-liveness). The loop's outcome — `finalStatus`, `turnIds`, `hitMaxTurns`, `usage` — arrives on the **`loop/terminated`** event. **Per-loop model selection** (#414/#598): optional `model` (client-resolved `<provider>/<model>`, wins) or `alias` (a declared `PLURNK_MODEL_<alias>`) overrides the boot-time `PLURNK_MODEL` for a newly created loop. The fully resolved `{ alias, provider, model, baseUrl? }` is persisted on that loop and is immutable through every turn, queue claim, async wake, and daemon restart; no resume path may substitute the boot default. A prompt folded into an active or parked loop must resolve to the same selection; a conflicting selection fails loudly and requires the caller to conclude or cancel before opening a loop on another model. Provider instances are cached, an unresolvable spec fails before enqueue, and neither selector runs the boot default. Mid-loop switching is not an implicit side effect of prompt injection; a future such capability requires its own explicit atomic operation. Optional `flags` carries per-loop flags (`{auto?: boolean}`; see §engine-rails). Streams `log/entry` and `loop/proposal` during. `longRunning: false`. {§methods-loop-run} {§methods-loop-run-model} |
1007
1027
  | `proposal.list` | — | `{ proposals: [{logEntryId, workerId, loopId, turnId, op, suffix, target, body, attrs, flags, at}] }` | Every pending (`state='proposed'`) stop-the-world proposal in the attached workspace — the indefinite-wait ruling's mandatory companion: `loop/proposal` is a notification, so a client reconnecting during a stopped world (possibly days old) DISCOVERS it here and answers via the ordinary `loop.resolve`. `attrs` carries `{question, choices}` for [300] asks. {§proposal-list} |
1008
1028
  | `loop.resolve` | `logEntryId: number`, `decision: "accept" \| "reject" \| "cancel"`, `body?: string`, `outcome?: string` | `{ status, logEntryId }` | Resolve a pending proposal (status=202 log entry). Engine.dispatch unpauses on resolution. |
1009
- | `loop.cancel` | `reason?: string` | `{ cancelled, workerId, reason }` | Abort the attached worker's active drain. `{cancelled: true}` if a drain was running, `{false}` if idle. Cancelled loops close at 499; queued-but-unclaimed loops stay enqueued. Default reason `user_cancelled`. **The cancel is provenanced, never silent** (#380, owner ruling): the loop's terminal ROW is written (499 a dead loop must never read as live 102, the #311 rule applied to the cancel path) with `terminated_by='cancel'` and the reason as its abandonment message, and the `loop/terminated` broadcast carries the same `message` — an external cancel is allowed (the client owns its loops, even 202-waiting ones with live obligations), but who/why is always on the record. A PARKED (202) loop has no drain to observe the abort, so the cancel terminalizes it directly — same row, same broadcast — even as `cancelled` answers `false` (no in-flight drain existed). {§methods-loop-cancel} |
1029
+ | `loop.cancel` | `reason?: string` | `{ cancelled, workerId, reason }` | Cancel the attached worker's structured scope. Every unresolved loop (`100`, `102`, or `202`) in the worker subtree closes at 499 and every held subscription is reaped; descendants never detach implicitly. Default reason `user_cancelled`. `cancelled` reports whether the attached worker had process-local work when the request arrived; durable parked or queued work is still terminalized when it is `false`. Cancellation is provenanced: each affected row records `terminated_by='cancel'` and the reason, and each terminal event carries the same message. {§methods-loop-cancel} |
1010
1030
  | `providers.list` | none | `{ aliases: ProviderAlias[] }` | Lists configured `PLURNK_MODEL_<alias>` entries with `{alias, provider, model, active}`. Clients use to populate model-selection UI. |
1011
1031
 
1012
1032
  **Reads**
@@ -1022,7 +1042,10 @@ registry.registerMethod("loop.run", {
1022
1042
 
1023
1043
  Per the **Speak in DSL, not plumbing** rule (AGENTS.md): `op.*` methods construct DSL statements internally and dispatch through `Engine.dispatch`. {§methods-op-mirror} Param shapes are ergonomic (semantic names, not HEREDOC slots); semantics are the DSL's.
1024
1044
 
1025
- Each `op.*` call creates a turn in the connection's client loop (§connection-lifecycle), dispatches, fires `log/entry`, returns the dispatch result.
1045
+ Each client action creates one terminal journal segment (§connection-lifecycle). Every
1046
+ statement in that action creates an ordered turn inside the segment, dispatches, fires
1047
+ `log/entry`, and returns its result. `op.parse` therefore does not manufacture one loop
1048
+ per parsed statement.
1026
1049
 
1027
1050
  Naming: `target` = URI the op acts on; `scope` for FIND; `source`/`destination` for COPY/MOVE; `recipient` for SEND (or null = broadcast); `cwd` for EXEC. `path` is reserved for *identity* — never an RPC operand.
1028
1051
 
@@ -1052,7 +1075,7 @@ Future: `subscription.list`, `subscription.cancel` (the latter is `op.send({stat
1052
1075
  | Notification | Params | When fired |
1053
1076
  |--------------------|-------------------------------------|------------|
1054
1077
  | `log/entry` | `{ entry: LogEntry }` | Every `log_entries` write. {§notifications-log-entry-notify} |
1055
- | `loop/terminated` | `{ loopId, finalStatus, hitMaxTurns }` | Loop reaches terminal status. |
1078
+ | `loop/terminated` | `{ workerId, loopId, finalStatus, hitMaxTurns, turnIds, usage, message? }` | One loop reaches terminal status. `workerId` and `loopId` are an inseparable owning coordinate; transports bind completion to the exact loop they started or resumed and never infer either half from workspace traffic. |
1056
1079
  | `loop/proposal` | `{ logEntryId, workspaceId, workerId, loopId, turnId, op, target, body, attrs, flags }` | Dispatch pauses on status=202. Carries `flags` so a client can suppress review UI when loop-owned policy will resolve it. Client responds with `loop.resolve` when authority crosses the boundary (or `PLURNK_SERVICE_PROPOSAL_TIMEOUT_MS` fires). |
1057
1080
  | `workspace/created` | `{ id, name, projectRoot }` | Any client creates a workspace. |
1058
1081
  | `stream/event` | `{ entryId, channel, state, contentLength }` | Channel content grows or state transitions. {§notifications-stream-event-on-channel-change} |
@@ -1063,7 +1086,16 @@ Future: `subscription.list`, `subscription.cancel` (the latter is `op.send({stat
1063
1086
 
1064
1087
  ### §connection-lifecycle Client context
1065
1088
 
1066
- **The client's run.** A module client context is an actor (§machine-processes); its `op.*` write to its **own worker** — `origin = "client"`, one loop per context — and `log.read` reads that worker. Closing the context closes the loop's status; rows persist. Multiple contexts each get their own client worker.
1089
+ **Client action evidence.** A module client is an actor (§machine-processes); its
1090
+ side-effecting `op.*` actions write to its **own worker** with `origin = "client"`.
1091
+ One action owns one journal segment, and all statements parsed from that action are
1092
+ ordered turns inside it. A proposal may hold the segment open while the action crosses
1093
+ an AG-UI interrupt/resume boundary; resolution or failure closes it. These segments
1094
+ record durable action evidence but do not define client-visible lifecycle—AG-UI runs do.
1095
+ Observational actions create no turns or rows. `LOOK` retains a closed, rowless
1096
+ observation segment because the public scheme context and relative `log:///` addressing
1097
+ require an honest numeric loop coordinate; it never leaves active lifecycle behind.
1098
+ Multiple client actors have distinct workers.
1067
1099
 
1068
1100
  `loop.run` and `inject` target the **model's worker** — a separate worker holding the conversation, `origin = "model"`. Both workers share the workspace's one filesystem (§machine-processes); the packet renders only the model's worker, so the client's ops are structurally absent from it — no origin filter (§actor-boundary-isolation). The model worker (`Envelope.ensureModelWorker`) and the client context's worker are distinct, each lazily allocated on first use.
1069
1101
 
@@ -1188,7 +1220,7 @@ The CAS is the **hard backstop**, at the moment of writing, on every accept path
1188
1220
  - **One rule, every turn: fold the NEWEST memories — never history.** THE DOCTRINE, the project's animating narrative: the log is the model's memory and the model ALONE curates it (FOLD/KILL). The grinder never reaches back into history — it only blocks NEW memories from landing when there is no room, forcing the model to do its own housekeeping. On overflow it folds, in one set-op, the still-open rows of the **newest turn boundary**: the immediately-prior turn's emissions and the current turn's pre-model rows (foists, wake surfaces — every current-turn row at grind time is engine-written). Turn 1 is the **same rule**, not a case: no prior turn exists, so its own foists are the newest material. Folded, not deleted: rows and bodies persist and are re-OPENable, so log *history* is preserved while the render collapses to coordinates. {§grinder-layer1-rollback}
1189
1221
  - **Errors, the prompt, AND the plan are exempt.** The grinder never folds an `op='error'` row (the budget-overflow it just minted, a parse failure, an action failure) — errors are the model's durable, curatable record of what went wrong; folding them the moment they matter would blind it to a recurring failure. Nor does it fold the **user prompt** (`plurnk:///prompt/…`, #382): the task the engine foisted is FRAME, not the model's curatable memory — the engine never reclaims the definition of the task it set. Nor a **PLAN row** (#465, owner ruling): the checklist is the model's orientation surface at exactly the moment the grinder fires — folding the plan alongside the work it plans would collapse the reasoning thread a recovery turn steers by, and plans are concise by rule, so exempting them reclaims almost nothing. All three stay OPEN until the model itself FOLDs or KILLs them. {§grinder-errors-exempt}
1190
1222
  - **The hard overflow is a RECOVERY TURN first** {§grinder-hard-413-recovery} — (Q4, owner ruling: recoverable strike, NO margin). The overflow lives in foldable HISTORY the model owns, and the grinder never touches history (§grinder-layer1-rollback) — so the first hard overflow, when the packet is over the POLICY ceiling but still within PHYSICS (the provider's real window minus the decode reserve), is sent ANYWAY, once: a minted `budget_overflow` steer states the fact, the remedy (KILL/FOLD history; the budget table lists the heaviest), and the consequence — and the turn counts a strike (`budgetStruck`). The model curates → the next fitting turn clears the grant (a later overflow earns a fresh recovery; chronic overflow still strikes out via the rail). A recovery turn that CONCLUDES is a legitimate 200 — finishing is a way to stop overflowing. **No 95% margin**: the pointer fires at 100% of budget — a margin masks the signal, and the decode is separately reserved.
1191
- - **Hard stop.** A physically-unsendable packet (over the provider's real window too — physics doesn't negotiate), or a SECOND consecutive hard overflow after the recovery turn (the model was told and declined), abandons the loop at **413 Content Too Large** (`engine_loop_set_status`). Its sibling engine-imposed terminals are HTTP-precise too: `maxTurns` → 429, a strike-out → 500 (508 when cycle-driven) — no longer the old catch-all 499. No further passes. {§grinder-hard-413-abort}
1223
+ - **Hard stop.** A physically-unsendable packet (over the provider's real window too — physics doesn't negotiate), or a SECOND consecutive hard overflow after the recovery turn (the model was told and declined), abandons the loop at **413 Content Too Large**. Its sibling engine-imposed terminals are HTTP-precise too: `maxTurns` → 429, a strike-out → 500 (508 when cycle-driven) — no longer the old catch-all 499. No further passes. {§grinder-hard-413-abort}
1192
1224
 
1193
1225
  - **Output truncation states its cause** {§tokenomics-output-truncated} — a `finish=length` turn was guillotined at the decode pool (`REASONING + COMPLETION`, one undifferentiated `max_tokens` — §tokenomics-window-partition), and its parse errors are truncation ARTIFACTS: without the cause stated, the model reads "unclosed block" and fixes syntax forever instead of emitting less (run29: unclamped cloud reasoning + a 9-edit emission vs a 12288 pool; the binding cap was plurnk's own — `completion 12281`). One terse `output_truncated` row (413) leads the artifact rows it explains, naming the cap and distinguishing its two shapes so the model reads the right cause: content cut **mid-op** (the severed frame — see {§broken-packet-no-dispatch}) vs the pool consumed with **nothing emitted** (reasoning ran away — the parse `must begin with PLAN` is an artifact of the empty emission, not a malformed turn). The row states the fact, not a remedy.
1194
1226
 
@@ -1500,7 +1532,7 @@ Carried from the contract walk; durable.
1500
1532
  - **READ rx** prefixes each line with `N:` per §render-rule. `sliceLinesRaw` (used by COPY) returns the lines without prefix.
1501
1533
  - **FIND body matcher** applies to entry content (all dialects), per-candidate via the in-tree `Matcher.matchAgainstContent` (§matcher-dispatch; status 200 = content hit → entry selected). Scope + tags select candidates in SQL; the path-glob is the (target).
1502
1534
  - **OPEN/FOLD** operate on the **log** (`log:///`), not entries (§open-fold) — FOLD collapses a log row to its path, OPEN restores its body. Aimed at an entry scheme they return 501.
1503
- - **SEND[410]** deletes as a side-effect (not the model idiom; §move): with `#fragment`, that channel only; without, the whole entry. **SEND[499]** is owned by the streaming scheme that holds the subscription.
1535
+ - **SEND[410]** deletes as a side-effect (not the model idiom; §move): with `#fragment`, that channel only; without, the whole entry. **SEND[499]** resolves the durable open-subscription row and invokes that subscription's exact callable owner through the process-local live registry (§subscriptions).
1504
1536
  - **File scheme** reads disk content with mimetype detected via `Mimetypes.detect({ path })` (plumbed through `PlurnkSchemeContext.mimetypes`). Binary mimetypes → 415 on READ and EDIT.
1505
1537
 
1506
1538
  ### §send-status-policy Directed-SEND status code policy
@@ -1 +1 @@
1
- {"package":"@plurnk/plurnk-service","version":"1.3.1","revision":"5b26ea4fa10a6eee498012750fb2a48c955d0419","dirty":false}
1
+ {"package":"@plurnk/plurnk-service","version":"1.3.2","revision":"535b20fb8e1980ab2bdcc79ab7b7389942970c97","dirty":false}
@@ -41,7 +41,8 @@ export type InjectWorkerNotify = (args: {
41
41
  action: "injected_next_turn" | "enqueued_new_loop";
42
42
  loopId: number;
43
43
  }>;
44
- export type CancelWorkerNotify = (workerId: number) => boolean;
44
+ export type CancelWorkerNotify = (workerId: number, reason: string) => Promise<void>;
45
+ export type CancelDescendantsNotify = (workerId: number, reason: string) => Promise<void>;
45
46
  export interface TelemetryEventPayload {
46
47
  loopId: number;
47
48
  event: object;
@@ -1 +1 @@
1
- {"version":3,"file":"ChannelWrite.d.ts","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChannelWrite.d.ts","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,EAAE,EAAc,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAMtE,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAQzF,MAAM,WAAW,iBAAiB;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAUpE,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IAMf,KAAK,CAAC,EAAE,SAAS,CAAC;CACrB,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,oBAAoB,GAAG,mBAAmB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAOtF,MAAM,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AACrF,MAAM,MAAM,uBAAuB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAQ1F,MAAM,WAAW,qBAAqB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAWjG,MAAM,CAAC,OAAO,OAAO,YAAY;;IAqB7B,OAAa,eAAe,CACxB,EAAE,EAAE,EAAE,EACN,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;QAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7L,OAAO,CAAC,IAAI,CAAC,CAWf;IAID,OAAa,eAAe,CACxB,EAAE,EAAE,EAAE,EACN,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAC;QAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;QAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;KAAE,GACtK,OAAO,CAAC,IAAI,CAAC,CAOf;IAMD,OAAa,gBAAgB,CACzB,EAAE,EAAE,EAAE,EACN,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAAE;QAC9E,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAClE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACvF,GACF,OAAO,CAAC,MAAM,CAAC,CAQjB;IAED,OAAa,iBAAiB,CAC1B,EAAE,EAAE,EAAE,EACN,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACvE,OAAO,CAAC,IAAI,CAAC,CAEf;IAKD,OAAa,kBAAkB,CAC3B,EAAE,EAAE,EAAE,EACN,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACjG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;IAED,OAAa,sBAAsB,CAC/B,EAAE,EAAE,EAAE,EACN,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAC7D,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAGhE;IAMD,OAAa,8BAA8B,CACvC,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAEhD;IAKD,OAAa,wCAAwC,CACjD,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAEhD;CACJ"}
@@ -55,8 +55,10 @@ export default class ChannelWrite {
55
55
  return;
56
56
  notify(meta.workspace_id, { entryId, target: ChannelWrite.#targetUri(meta.scheme, meta.pathname), channel, state: meta.state, contentLength: meta.contentLength, mimetype: meta.mimetype, ...coordinate });
57
57
  }
58
- // The subscription registry open/find/close is how a stream's cancellation
59
- // (SEND[499] / KILL) routes to the right live subscription. §subscriptions-subscription-registry-routes-cancellation
58
+ // The durable half of subscription ownership. Its row identifies what is
59
+ // open; the process-local LiveSubscriptions registry owns the exact callable
60
+ // used by SEND[499] / KILL.
61
+ // §subscriptions-subscription-registry-routes-cancellation
60
62
  static async openSubscription(db, { workerId, entryId, scheme, handle, pollSeconds, turnScoped, publishedChannel }) {
61
63
  const row = await ChannelWrite.#openSubStmt(db).get({
62
64
  worker_id: workerId, entry_id: entryId, scheme, handle,
@@ -82,10 +84,9 @@ export default class ChannelWrite {
82
84
  return row ?? null;
83
85
  }
84
86
  // The worker's still-open subscriptions — the registry-routed reap
85
- // (§worker-lifecycle-total-reap). A cancel iterates these and aborts each via the
86
- // owning scheme, so a backgrounded exec is reaped regardless of in-process
87
- // AbortSignal-listener timing (R1): the registry is the source of truth, the
88
- // signal an optimization.
87
+ // (§worker-lifecycle-total-reap). A cancel iterates these durable identities
88
+ // and invokes each exact callable through LiveSubscriptions, so a
89
+ // backgrounded exec is reaped regardless of AbortSignal-listener timing.
89
90
  static async findOpenSubscriptionsForWorker(db, workerId) {
90
91
  return ChannelWrite.#openSubsForWorkerStmt(db).all({ worker_id: workerId });
91
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ChannelWrite.js","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChannelWrite.js","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Db } from "./Db.ts";
2
+ import type { Mimetypes } from "@plurnk/plurnk-mimetypes";
3
+ import type ExecutorRegistry from "./ExecutorRegistry.ts";
4
+ import type { InjectWorkerNotify, StreamEventNotify, WakeWorkerNotify } from "./ChannelWrite.ts";
5
+ import type { TelemetryEvent } from "./results.ts";
6
+ import type { PlurnkSchemeContext } from "./scheme-types.ts";
7
+ import type { SchemeCtx } from "@plurnk/plurnk-schemes";
8
+ import type LiveSubscriptions from "./LiveSubscriptions.ts";
9
+ export interface CoreSchemeServices {
10
+ readonly db: Db;
11
+ readonly mimetypes: Mimetypes;
12
+ readonly executors: () => ExecutorRegistry | undefined;
13
+ readonly tokenize: (text: string) => number;
14
+ readonly streamEventNotify: StreamEventNotify | undefined;
15
+ readonly wakeWorkerNotify: WakeWorkerNotify | undefined;
16
+ readonly injectWorker: InjectWorkerNotify | undefined;
17
+ readonly pushTelemetry: (workspaceId: number, loopId: number, event: TelemetryEvent) => void;
18
+ readonly defaultChannelFor: (scheme: string | null) => string;
19
+ readonly liveSubscriptions: LiveSubscriptions;
20
+ }
21
+ export interface CoreSchemeAdapter {
22
+ bindCore(services: CoreSchemeServices): void;
23
+ }
24
+ export type CoreSchemeCallContext = SchemeCtx | PlurnkSchemeContext;
25
+ export declare abstract class CoreSchemeAdapterBase implements CoreSchemeAdapter {
26
+ #private;
27
+ bindCore(services: CoreSchemeServices): void;
28
+ protected coreContext(ctx: CoreSchemeCallContext): PlurnkSchemeContext;
29
+ protected liveSubscriptions(): LiveSubscriptions;
30
+ }
31
+ //# sourceMappingURL=CoreSchemeServices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoreSchemeServices.d.ts","sourceRoot":"","sources":["../../src/core/CoreSchemeServices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,gBAAgB,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC1D,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACxD,QAAQ,CAAC,YAAY,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,aAAa,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7F,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;IAC9D,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;CACjD;AAED,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAChD;AAMD,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,mBAAmB,CAAC;AAEpE,8BAAsB,qBAAsB,YAAW,iBAAiB;;IAGpE,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAE3C;IAED,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,qBAAqB,GAAG,mBAAmB,CAqBrE;IAED,SAAS,CAAC,iBAAiB,IAAI,iBAAiB,CAI/C;CACJ"}
@@ -0,0 +1,37 @@
1
+ export class CoreSchemeAdapterBase {
2
+ #services;
3
+ bindCore(services) {
4
+ this.#services = services;
5
+ }
6
+ coreContext(ctx) {
7
+ if ("db" in ctx)
8
+ return ctx;
9
+ const services = this.#services;
10
+ if (services === undefined)
11
+ throw new Error(`${this.constructor.name}: core services are not bound`);
12
+ return {
13
+ db: services.db,
14
+ workspaceId: ctx.workspaceId,
15
+ workerId: ctx.workerId,
16
+ loopId: ctx.loopId,
17
+ turnId: ctx.turnId,
18
+ writer: ctx.writer,
19
+ signal: ctx.signal,
20
+ streamEventNotify: services.streamEventNotify,
21
+ wakeWorkerNotify: services.wakeWorkerNotify,
22
+ injectWorker: services.injectWorker,
23
+ mimetypes: services.mimetypes,
24
+ executors: services.executors(),
25
+ tokenize: services.tokenize,
26
+ defaultChannelFor: services.defaultChannelFor,
27
+ pushTelemetry: (event) => services.pushTelemetry(ctx.workspaceId, ctx.loopId, event),
28
+ };
29
+ }
30
+ liveSubscriptions() {
31
+ const services = this.#services;
32
+ if (services === undefined)
33
+ throw new Error(`${this.constructor.name}: core services are not bound`);
34
+ return services.liveSubscriptions;
35
+ }
36
+ }
37
+ //# sourceMappingURL=CoreSchemeServices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoreSchemeServices.js","sourceRoot":"","sources":["../../src/core/CoreSchemeServices.ts"],"names":[],"mappings":"AAgCA,MAAM,OAAgB,qBAAqB;IACvC,SAAS,CAAiC;IAE1C,QAAQ,CAAC,QAA4B;QACjC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAES,WAAW,CAAC,GAA0B;QAC5C,IAAI,IAAI,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,+BAA+B,CAAC,CAAC;QACrG,OAAO;YACH,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;YAC7C,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;YAC3C,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE;YAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;YAC7C,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC;SACvF,CAAC;IACN,CAAC;IAES,iBAAiB;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,+BAA+B,CAAC,CAAC;QACrG,OAAO,QAAQ,CAAC,iBAAiB,CAAC;IACtC,CAAC;CACJ"}
@@ -6,7 +6,8 @@ import type ExecutorRegistry from "./ExecutorRegistry.ts";
6
6
  import type TelemetryChannel from "./TelemetryChannel.ts";
7
7
  import type ProposalLifecycle from "./ProposalLifecycle.ts";
8
8
  import type { WriterTier } from "./scheme-types.ts";
9
- import type { StreamEventNotify, WakeWorkerNotify, InjectWorkerNotify, CancelWorkerNotify } from "./ChannelWrite.ts";
9
+ import { type StreamEventNotify, type WakeWorkerNotify, type InjectWorkerNotify, type CancelWorkerNotify, type CancelDescendantsNotify } from "./ChannelWrite.ts";
10
+ import type LiveSubscriptions from "./LiveSubscriptions.ts";
10
11
  export type DispatchContext = {
11
12
  statement: PlurnkStatement;
12
13
  workspaceId: number;
@@ -25,7 +26,7 @@ export type DispatchResult = {
25
26
  };
26
27
  export default class Dispatcher {
27
28
  #private;
28
- constructor({ db, schemes, mimetypes, tokenize, telemetry, proposals, executors, loopSignal, streamEventNotify, wakeWorkerNotify, injectWorker, cancelWorker, searchGate, parkDeadlines, joinTargets }: {
29
+ constructor({ db, schemes, mimetypes, tokenize, telemetry, proposals, executors, loopSignal, streamEventNotify, wakeWorkerNotify, injectWorker, cancelWorker, cancelDescendants, searchGate, parkDeadlines, joinTargets, liveSubscriptions }: {
29
30
  db: Db;
30
31
  schemes: SchemeRegistry;
31
32
  mimetypes: Mimetypes;
@@ -38,9 +39,11 @@ export default class Dispatcher {
38
39
  wakeWorkerNotify?: WakeWorkerNotify;
39
40
  injectWorker?: InjectWorkerNotify;
40
41
  cancelWorker?: CancelWorkerNotify;
42
+ cancelDescendants?: CancelDescendantsNotify;
41
43
  parkDeadlines?: Map<number, number>;
42
44
  searchGate?: import("./search-gate.ts").default;
43
45
  joinTargets?: Set<number>;
46
+ liveSubscriptions: LiveSubscriptions;
44
47
  });
45
48
  dispatch(context: DispatchContext): Promise<DispatchResult>;
46
49
  look(context: {
@@ -1 +1 @@
1
- {"version":3,"file":"Dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/Dispatcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/Dispatcher.ts"],"names":[],"mappings":"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"}