@plurnk/plurnk-service 0.2.0 → 0.4.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 (133) hide show
  1. package/SPEC.md +98 -112
  2. package/dist/core/ChannelWrite.d.ts +10 -0
  3. package/dist/core/ChannelWrite.d.ts.map +1 -1
  4. package/dist/core/ChannelWrite.js.map +1 -1
  5. package/dist/core/Engine.d.ts +10 -2
  6. package/dist/core/Engine.d.ts.map +1 -1
  7. package/dist/core/Engine.js +410 -113
  8. package/dist/core/Engine.js.map +1 -1
  9. package/dist/core/ProviderRegistry.d.ts +1 -1
  10. package/dist/core/ProviderRegistry.d.ts.map +1 -1
  11. package/dist/core/ProviderRegistry.js.map +1 -1
  12. package/dist/core/line-marker.d.ts +23 -0
  13. package/dist/core/line-marker.d.ts.map +1 -0
  14. package/dist/core/line-marker.js +321 -0
  15. package/dist/core/line-marker.js.map +1 -0
  16. package/dist/core/matcher.d.ts +14 -0
  17. package/dist/core/matcher.d.ts.map +1 -0
  18. package/dist/core/matcher.js +195 -0
  19. package/dist/core/matcher.js.map +1 -0
  20. package/dist/core/mimetype-binary.d.ts +6 -0
  21. package/dist/core/mimetype-binary.d.ts.map +1 -0
  22. package/dist/core/mimetype-binary.js +82 -0
  23. package/dist/core/mimetype-binary.js.map +1 -0
  24. package/dist/core/packet-wire.d.ts.map +1 -1
  25. package/dist/core/packet-wire.js +174 -33
  26. package/dist/core/packet-wire.js.map +1 -1
  27. package/dist/core/path-mimetype.d.ts +3 -0
  28. package/dist/core/path-mimetype.d.ts.map +1 -0
  29. package/dist/core/path-mimetype.js +47 -0
  30. package/dist/core/path-mimetype.js.map +1 -0
  31. package/dist/core/scheme-types.d.ts +5 -0
  32. package/dist/core/scheme-types.d.ts.map +1 -1
  33. package/dist/core/scheme-types.js.map +1 -1
  34. package/dist/providers/Mock.d.ts +2 -2
  35. package/dist/providers/Mock.d.ts.map +1 -1
  36. package/dist/providers/Mock.js.map +1 -1
  37. package/dist/schemes/Exec.d.ts +30 -1
  38. package/dist/schemes/Exec.d.ts.map +1 -1
  39. package/dist/schemes/Exec.js +229 -6
  40. package/dist/schemes/Exec.js.map +1 -1
  41. package/dist/schemes/File.d.ts +8 -4
  42. package/dist/schemes/File.d.ts.map +1 -1
  43. package/dist/schemes/File.js +184 -68
  44. package/dist/schemes/File.js.map +1 -1
  45. package/dist/schemes/Known.js +1 -1
  46. package/dist/schemes/Known.js.map +1 -1
  47. package/dist/schemes/Log.d.ts +9 -1
  48. package/dist/schemes/Log.d.ts.map +1 -1
  49. package/dist/schemes/Log.js +120 -19
  50. package/dist/schemes/Log.js.map +1 -1
  51. package/dist/schemes/Plurnk.d.ts +15 -1
  52. package/dist/schemes/Plurnk.d.ts.map +1 -1
  53. package/dist/schemes/Plurnk.js +50 -8
  54. package/dist/schemes/Plurnk.js.map +1 -1
  55. package/dist/schemes/Skill.js +1 -1
  56. package/dist/schemes/Skill.js.map +1 -1
  57. package/dist/schemes/Unknown.js +1 -1
  58. package/dist/schemes/Unknown.js.map +1 -1
  59. package/dist/schemes/_entry-crud.d.ts +5 -3
  60. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  61. package/dist/schemes/_entry-crud.js +1 -0
  62. package/dist/schemes/_entry-crud.js.map +1 -1
  63. package/dist/schemes/_entry-find.d.ts.map +1 -1
  64. package/dist/schemes/_entry-find.js +64 -15
  65. package/dist/schemes/_entry-find.js.map +1 -1
  66. package/dist/schemes/_entry-ops.d.ts +3 -0
  67. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  68. package/dist/schemes/_entry-ops.js +269 -72
  69. package/dist/schemes/_entry-ops.js.map +1 -1
  70. package/dist/schemes/_entry-send.d.ts.map +1 -1
  71. package/dist/schemes/_entry-send.js +14 -7
  72. package/dist/schemes/_entry-send.js.map +1 -1
  73. package/dist/server/ClientConnection.d.ts +3 -2
  74. package/dist/server/ClientConnection.d.ts.map +1 -1
  75. package/dist/server/ClientConnection.js +10 -2
  76. package/dist/server/ClientConnection.js.map +1 -1
  77. package/dist/server/Daemon.d.ts +40 -1
  78. package/dist/server/Daemon.d.ts.map +1 -1
  79. package/dist/server/Daemon.js +319 -1
  80. package/dist/server/Daemon.js.map +1 -1
  81. package/dist/server/MethodRegistry.d.ts +29 -0
  82. package/dist/server/MethodRegistry.d.ts.map +1 -1
  83. package/dist/server/MethodRegistry.js.map +1 -1
  84. package/dist/server/dsl.d.ts +2 -2
  85. package/dist/server/dsl.d.ts.map +1 -1
  86. package/dist/server/dsl.js +10 -10
  87. package/dist/server/dsl.js.map +1 -1
  88. package/dist/server/envelope.d.ts +2 -1
  89. package/dist/server/envelope.d.ts.map +1 -1
  90. package/dist/server/envelope.js +11 -8
  91. package/dist/server/envelope.js.map +1 -1
  92. package/dist/server/logEntry.d.ts +9 -9
  93. package/dist/server/logEntry.d.ts.map +1 -1
  94. package/dist/server/logEntry.js +10 -10
  95. package/dist/server/logEntry.js.map +1 -1
  96. package/dist/server/methods/_dispatchAsClient.d.ts.map +1 -1
  97. package/dist/server/methods/_dispatchAsClient.js +7 -2
  98. package/dist/server/methods/_dispatchAsClient.js.map +1 -1
  99. package/dist/server/methods/entry_read.js +5 -5
  100. package/dist/server/methods/entry_read.js.map +1 -1
  101. package/dist/server/methods/loop_cancel.d.ts +3 -0
  102. package/dist/server/methods/loop_cancel.d.ts.map +1 -0
  103. package/dist/server/methods/loop_cancel.js +27 -0
  104. package/dist/server/methods/loop_cancel.js.map +1 -0
  105. package/dist/server/methods/loop_run.d.ts.map +1 -1
  106. package/dist/server/methods/loop_run.js +53 -49
  107. package/dist/server/methods/loop_run.js.map +1 -1
  108. package/dist/server/methods/op_edit.js +3 -3
  109. package/dist/server/methods/op_edit.js.map +1 -1
  110. package/dist/server/methods/op_hide.js +3 -3
  111. package/dist/server/methods/op_hide.js.map +1 -1
  112. package/dist/server/methods/op_read.js +3 -3
  113. package/dist/server/methods/op_read.js.map +1 -1
  114. package/dist/server/methods/op_show.js +3 -3
  115. package/dist/server/methods/op_show.js.map +1 -1
  116. package/migrations/001_schema.sql +324 -0
  117. package/package.json +19 -12
  118. package/migrations/001_sessions.sql +0 -11
  119. package/migrations/002_runs.sql +0 -16
  120. package/migrations/003_loops.sql +0 -12
  121. package/migrations/004_turns.sql +0 -18
  122. package/migrations/005_entries.sql +0 -44
  123. package/migrations/006_log_entries.sql +0 -51
  124. package/migrations/007_visibility.sql +0 -10
  125. package/migrations/008_schemes_providers.sql +0 -25
  126. package/migrations/009_cost_rollups.sql +0 -44
  127. package/migrations/010_subscriptions.sql +0 -36
  128. package/migrations/011_turn_call_metadata.sql +0 -7
  129. package/migrations/012_proposal_lifecycle.sql +0 -22
  130. package/migrations/013_log_entries_lifecycle_columns.sql +0 -22
  131. package/migrations/014_loop_flags.sql +0 -9
  132. package/migrations/015_sessions_project_root.sql +0 -6
  133. package/migrations/016_persona_columns.sql +0 -11
package/SPEC.md CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  Single source of truth for what plurnk-service IS — the contracts it exposes, the architecture it implements, the promises it makes to the rest of the constellation (`plurnk-grammar`, `plurnk-providers-*`, `plurnk-schemes-*`, `plurnk-mimetypes-*`, the user-facing `plurnk` CLI). `AGENTS.md` covers how we work on it; this file covers what we're working on.
4
4
 
5
- Section numbers are stable. Future anchor-to-test wiring binds individual promises here to integration / live / demo tests, giving semi-deterministic specification-testing alignment.
6
-
7
- Floor scope is green (capstone intg test exercises every non-EXEC DSL op end-to-end). Post-floor work landed in #123: PlurnkSchemeContext (#33), the engine rails (#38–#41), packet shape (§15), single-cap constraint (§7.8), ProviderRegistry (#58), and first sibling-package extraction (#47). This document evolves with each phase; the next refinements will come from Phase C (mimetype integration story) and Phase F (exec + streams).
5
+ Section numbers are stable. Anchor-to-test wiring binds individual promises here to integration / live / demo tests, giving semi-deterministic specification-testing alignment.
8
6
 
9
7
  **Promise anchors.** Individual contract assertions in this document carry a trailing `{§<id>}` marker. Tests reference these anchors in their names (`test("[§<id>] description", ...)`). An alignment test (`test/intg/spec-anchors.test.ts`) fails if a test cites a nonexistent anchor (orphan — typo or stale reference) and surfaces gaps (anchored promises with no test) informationally. The anchors are **grounding against drift**, not a forcing function on development — write the spec, write the test, jot the link, move on. Coverage grows organically.
10
8
 
@@ -86,7 +84,7 @@ Three independent axes on entries and channels. Confusion across them is a recur
86
84
  | Tier | Location | LLM | Substrate |
87
85
  |---|---|---|---|
88
86
  | **unit** | `src/**/*.test.ts` | No | Isolated logic, mocked boundaries |
89
- | **intg** | `test/intg/` | No (mock provider) | Real in-memory SqlRite, real engine |
87
+ | **intg** | `test/intg/` | No (mock provider) | Real file-backed SqlRite (per-test DB under `test/intg/.tmp/`), real engine |
90
88
  | **live** | `test/live/` | Real | Wire-level assertions |
91
89
  | **demo** | `test/demo/` | Real | Holistic outcome assertions |
92
90
 
@@ -342,20 +340,7 @@ Promises:
342
340
 
343
341
  ### §4.4 Bundled vs sibling handlers
344
342
 
345
- Only `text/plain` ships in `plurnk-service`'s `src/mimetypes/` the universal fallback that every deployment needs and that has no external dependency. Every other mimetype handler ships as a sibling `@plurnk/plurnk-mimetypes-*` package and registers via Daemon's plugin discovery scan (§9).
346
-
347
- The first such extraction is `@plurnk/plurnk-mimetypes-text-markdown`, separate repo since #47. Validates the "bundle minimally" pattern. `application/json` and the DSL mimetype (`text/vnd.plurnk` — grammar #6 closed in favor of this id) follow the same pattern when they have consumers.
348
-
349
- Locked glyph assignments for the standard set:
350
-
351
- | Mimetype | Glyph | Where |
352
- |-----------------------------------|-------|------------------------------------|
353
- | `text/plain` | 📄 | bundled (`src/mimetypes/`) |
354
- | `text/markdown` | 📝 | sibling (`@plurnk/plurnk-mimetypes-text-markdown`) |
355
- | `application/json` *(deferred)* | 🗂 | future sibling |
356
- | `text/vnd.plurnk` *(deferred)* | 📜 | future sibling |
357
-
358
- Deferred handlers reserve their glyphs now so external packages don't collide.
343
+ No mimetype handlers ship in-tree. Every handler is a sibling `@plurnk/plurnk-mimetypes-*` package; the framework (`@plurnk/plurnk-mimetypes`) is also a sibling and is the surface plurnk-service consumes via `Mimetypes.process()`. Handlers register at boot via plugin discovery (§9). The in-tree set is empty by design the framework is responsible for the universal fallback, not us.
359
344
 
360
345
  ---
361
346
 
@@ -365,14 +350,11 @@ Every entry has named channels. **Channels are append-only content stores** keye
365
350
 
366
351
  ### §5.1 Per-entry channels
367
352
 
368
- EDIT writes a minimum of two channels per entry, in one transaction: {§5.1-edit-writes-body-plus-preview}
369
-
370
- - **`body`** — the raw content.
371
- - **`preview`** — the render-time structural summary. The stored content here is the result of `mimetype.preview(body, budget)` for the body's mimetype. When the mimetype handler is unsophisticated (text/plain head-truncation), the preview is short. As handlers mature (markdown heading outline, JSON key tree, DSL op summary), the preview becomes structural. {§5.1-preview-is-handler-output}
353
+ EDIT writes one channel per call the channel resolved from the path's fragment (or the scheme's `defaultChannel` when no fragment). {§5.1-edit-writes-only-body}
372
354
 
373
- Whether preview is stored (write-time memoization) or computed fresh on each render is an implementation choice behind the contract both behave the same to callers. v0 implementation stores it (avoids per-render compute); future implementation may switch to compute-on-render with content-hash cache.
355
+ There is no stored `preview` channel. Preview is a **render-time output**, computed by passing the channel's content through `Mimetypes.process()` at packet-build time. The result lands in `packet.system.index[].channels[name].content`. {§5.1-preview-is-handler-output} The mimetype framework owns the preview pipeline; plurnk-service consumes the returned preview and never inspects the framework's internals.
374
356
 
375
- Schemes MAY declare additional channels (exec will declare `stdout`/`stderr`; file may declare an `outline` channel; SSE may declare per-event-type channels). Each additional channel goes in the scheme's `channels` manifest (§3.1) and has its mimetype pinned there.
357
+ Schemes MAY declare multiple channels (exec will declare `stdout`/`stderr`/`stdin`; http will declare `body`/`header`; SSE may declare per-event-type channels). Each channel goes in the scheme's `channels` manifest (§3.1) and has its mimetype pinned there. Each channel is rendered independently at packet-build time.
376
358
 
377
359
  ### §5.2 Visibility lattice
378
360
 
@@ -387,10 +369,6 @@ The mimetype of a channel is declared by the scheme's manifest (§3.1) or — fo
387
369
  Implications:
388
370
  - Cross-mimetype COPY/MOVE crashes (`415 Unsupported Media Type`) — never coerces. See §6.4.
389
371
 
390
- ### §5.4 Orientation hint
391
-
392
- The grammar's `SchemeRegistration.channel_orientations` declares each scheme's channels as `head` or `tail` — "which end of the content matters for preview." Mimetype handlers consult this hint when truncating. Channels not listed default to `head`.
393
-
394
372
  ### §5.5 Channel selection in the DSL
395
373
 
396
374
  The DSL targets a specific channel of an entry via the URL **fragment** — the `#name` segment of the path. Per the grammar's `UrlPath` shape (0.3.0+), every parsed path has a nullable `fragment` field; this section defines its semantic for the engine.
@@ -422,7 +400,16 @@ Implications for operations:
422
400
  - **SHOW / HIDE** flip visibility for the resolved channel only — channel-specific visibility is achievable via fragments. Fragment-less SHOW/HIDE flips ALL channels of the entry per §5.2 (existing behavior).
423
401
  - **COPY / MOVE** with a fragment is a per-channel operation; deferred design pass needed before specifying (out of scope for v0).
424
402
 
425
- The clean-shape RPC params (§13.5) carry the fragment naturally inside the `path` string: `{ path: "known://x#preview" }` works as expected. No new RPC parameter needed; the URL surface handles it.
403
+ The clean-shape RPC params (§13.5) carry the fragment naturally inside the `target` string: `{ target: "known://x#stderr" }` works as expected. No new RPC parameter needed; the URL surface handles it.
404
+
405
+ **Wire-rendering inverse: default channel is path-only.** When the engine projects entries to the model's view, the heredoc fence omits `#channel` whenever the channel name matches the scheme's `defaultChannel`. Single-channel entries (the channel IS the default) render path-only; multi-channel entries render the default channel path-only and only non-default channels carry `#name` in the fence. {§5.5-wire-omits-suffix-on-default-channel} Examples:
406
+
407
+ - `<<notes.md:...:notes.md` — file scheme renders bare (see §10 file note)
408
+ - `<<exec://run:...:exec://run` — exec's default (`stdout`)
409
+ - `<<exec://run#stderr:...:exec://run#stderr` — explicit non-default
410
+ - `<<log://1/1/0:...:log://1/1/0` — log responses (single-payload; no channel concept)
411
+
412
+ The absence of `#channel` IS the addressing of the default. This matches what models naturally emit and removes `#body` / `#rx` clutter from every packet.
426
413
 
427
414
  ### §5.6 Channel state — metadata, not gating
428
415
 
@@ -445,20 +432,19 @@ Per-op semantics for `FIND | READ | EDIT | COPY | MOVE | SHOW | HIDE | SEND | EX
445
432
 
446
433
  ### §6.1 EDIT
447
434
 
448
- AST: `{ op: "EDIT", path: ParsedPath, body: string | null, signal: tags | null, lineMarker?: LineMarker }`.
435
+ AST: `{ op: "EDIT", target: ParsedPath, body: string | null, signal: tags | null, lineMarker?: LineMarker }`.
449
436
 
450
437
  Engine dispatches to `scheme.edit(statement, ctx)`. Scheme:
451
438
  - Resolves the target channel from the path's fragment (§5.5). Fragment absent → scheme's `manifest.defaultChannel`. Unknown channel → 400. Channel manifest-undeclared → engine crashes per §5.3.
452
439
  - Writes the body to the resolved channel.
453
- - For entry-bearing schemes (known/unknown/skill), also writes the `preview` channel in the same transaction when writing `body`. Storage is verbatim body at write time; structural rendering happens at packet build time via `mimetype.preview(content, budget)` (§5.1).
454
- - Indexes the written channels in the current run (visibility = 1).
440
+ - Indexes the written channel in the current run (visibility = 1).
455
441
  - Returns `{ status: 201, entryId }` for new entries; `{ status: 200, entryId }` for updates.
456
442
  - `body: null` clears the content (writes empty string).
457
443
  - Tags from `signal[]` are applied via `entry_tags` (additive on update for the v0 entry schemes; final policy may vary by scheme).
458
444
 
459
445
  ### §6.2 READ
460
446
 
461
- AST: `{ op: "READ", path: ParsedPath, body: MatcherBody | null, signal: tags | null, lineMarker?: LineMarker }`.
447
+ AST: `{ op: "READ", target: ParsedPath, body: MatcherBody | null, signal: tags | null, lineMarker?: LineMarker }`.
462
448
 
463
449
  Engine dispatches to `scheme.read(statement, ctx)`. Scheme:
464
450
  - Returns the body channel content + mimetype for `path`, or `{ status: 404 }`.
@@ -467,7 +453,7 @@ Engine dispatches to `scheme.read(statement, ctx)`. Scheme:
467
453
 
468
454
  ### §6.3 SHOW / HIDE
469
455
 
470
- AST: `{ op: "SHOW"|"HIDE", path: ParsedPath, body: MatcherBody | null, signal: tags | null, lineMarker?: LineMarker }`.
456
+ AST: `{ op: "SHOW"|"HIDE", target: ParsedPath, body: MatcherBody | null, signal: tags | null, lineMarker?: LineMarker }`.
471
457
 
472
458
  Engine dispatches to `scheme.show(statement, ctx)` / `scheme.hide(statement, ctx)`. Scheme:
473
459
  - Flips `visibility.indexed` for every channel of the targeted entry to 1 (SHOW) or 0 (HIDE).
@@ -476,7 +462,7 @@ Engine dispatches to `scheme.show(statement, ctx)` / `scheme.hide(statement, ctx
476
462
 
477
463
  ### §6.4 COPY (engine-orchestrated)
478
464
 
479
- AST: `{ op: "COPY", path: ParsedPath (source), body: ParsedPath (destination), signal: tags | null, lineMarker?: LineMarker }`.
465
+ AST: `{ op: "COPY", target: ParsedPath (source), body: ParsedPath (destination), signal: tags | null, lineMarker?: LineMarker }`.
480
466
 
481
467
  Engine orchestrates over CRUD primitives (§3.2, §3.4):
482
468
 
@@ -493,7 +479,7 @@ Same- and cross-scheme COPY both go through this orchestrator. {§6.4-cross-sche
493
479
 
494
480
  ### §6.5 MOVE (engine-orchestrated)
495
481
 
496
- AST: `{ op: "MOVE", path: ParsedPath (source), body: ParsedPath | null (destination), signal: tags | null, lineMarker?: LineMarker }`.
482
+ AST: `{ op: "MOVE", target: ParsedPath (source), body: ParsedPath | null (destination), signal: tags | null, lineMarker?: LineMarker }`.
497
483
 
498
484
  Two modes:
499
485
 
@@ -501,11 +487,11 @@ Two modes:
501
487
 
502
488
  **Deletion** (`body` is null): engine runs `src_scheme.deleteEntry(source_pathname, ctx)` directly. The null-body MOVE expresses "relocate to nowhere" = delete. {§6.5-null-body-deletes} Returns 200 on success, 404 if source absent. {§6.5-missing-source-404}
503
489
 
504
- Log history is preserved through MOVE because `log_entries.target_*` columns store the path tuple as text, not FK to `entries.id`.
490
+ Log history is preserved through MOVE because `log_entries`' URI-bit columns (`scheme`, `pathname`, etc.) store the path tuple as text, not FK to `entries.id`.
505
491
 
506
492
  ### §6.6 FIND
507
493
 
508
- AST: `{ op: "FIND", path: ParsedPath (scope), body: MatcherBody | null (predicate), signal: tags | null (tag filter), lineMarker?: LineMarker }`.
494
+ AST: `{ op: "FIND", target: ParsedPath (scope), body: MatcherBody | null (predicate), signal: tags | null (tag filter), lineMarker?: LineMarker }`.
509
495
 
510
496
  Engine dispatches to `scheme.find(statement, ctx)`. Scheme:
511
497
  - Filters entries within the path's scope (scheme + pathname prefix). {§6.6-scope-prefix-filter}
@@ -516,7 +502,7 @@ Engine dispatches to `scheme.find(statement, ctx)`. Scheme:
516
502
 
517
503
  ### §6.7 SEND
518
504
 
519
- AST: `{ op: "SEND", path: ParsedPath | null, body: SendBody | null, signal: number | null }`.
505
+ AST: `{ op: "SEND", target: ParsedPath | null, body: SendBody | null, signal: number | null }`.
520
506
 
521
507
  Two modes:
522
508
 
@@ -530,7 +516,7 @@ Two modes:
530
516
 
531
517
  ### §6.8 EXEC
532
518
 
533
- AST: `{ op: "EXEC", path: ParsedPath (cwd), body: string | null (command), signal: string | null (runtime tag) }`.
519
+ AST: `{ op: "EXEC", target: ParsedPath (cwd), body: string | null (command), signal: string | null (runtime tag) }`.
534
520
 
535
521
  Deferred. The `exec` scheme is in §10's bundled set but lacks a working handler; calls return 501. Sandboxing design and process-lifecycle semantics are the substance to figure out, drawing on rummy's exec plugin as prior art.
536
522
 
@@ -647,40 +633,31 @@ Versioning: a `plurnkContractVersion` field on each plugin's `plurnk` manifest d
647
633
 
648
634
  ## §10 Bundled Set
649
635
 
650
- These ship in `plurnk-service` directly, not as separate `@plurnk/*` packages:
636
+ What ships in-tree vs. in sibling `@plurnk/*` packages. Plugin discovery (§9) finds every installed `@plurnk/*` package at boot and registers what they declare; the system runs against whatever is present in `node_modules`.
651
637
 
652
- **Providers:**
653
- - `mock` — fake provider used exclusively in `intg` for deterministic engine tests. Also serves as a minimal worked example for authors of external `@plurnk/plurnk-providers-*` packages.
638
+ **Providers in-tree (`src/providers/`):**
639
+ - `Mock` — fake provider used exclusively in `intg` for deterministic engine tests. Also serves as a minimal worked example for authors of external provider packages.
654
640
 
655
- **Mimetypes** (in `src/mimetypes/`):
656
- - `text/plain` — universal fallback. Identity validate; head-truncated preview. Stays bundled because every deployment needs it and it has no external dependency.
641
+ All real providers are siblings, registered via plugin discovery.
657
642
 
658
- **Schemes** (in `src/schemes/`):
659
- - `plurnk` — meta-scheme for scheme registration ops (manifest only; ops not implemented yet).
660
- - `log` — coordinate-addressed run/turn/action log reads.
643
+ **Mimetypes in-tree:** none. The framework (`@plurnk/plurnk-mimetypes`) and every handler are siblings.
644
+
645
+ **Schemes in-tree (`src/schemes/`):**
646
+ - `plurnk` — indexable scheme for internal model-interactions. Current use: `plurnk://prompt/<loop_id>` carries each loop's prompt as a body-channel entry written on loop start. Manifest-level writability is open (any origin); model-origin writes to `plurnk://prompt/*` are rejected in-handler (engine + client own those paths).
647
+ - `log` — coordinate-addressed log entries. Read returns a summary of the action at `log://<loop_seq>/<turn_seq>/<sequence>`; SHOW/HIDE toggle the row's `indexed` flag (log entries are not entries-table entries, but participate in the model's curation surface via URI dispatch). Each entry renders in the packet as a single JSON meta line — no fence, no body — with `path` = the log entry's own URI (`log://<L>/<T>/<S>/<op>`) and `target` = the URI the action acted on. Errors mirror to `packet.user.telemetry.errors[]` per §15.1; status ≥ 400 in the meta signals "look in telemetry."
661
648
  - `known` — primary narrative entries.
662
649
  - `unknown` — decomposition / open questions.
663
650
  - `skill` — sibling of known/unknown; semantics provisional.
664
- - `exec` — manifest only; subprocess invocation deferred to Phase F.
665
- - `file` — currently in-tree but flagged for extraction to `@plurnk/plurnk-schemes-file` once exec/streams phase shapes the file scheme's full surface.
666
-
667
- **Sibling repos** (live `@plurnk/*` packages we own):
668
- - **Mimetypes:** `@plurnk/plurnk-mimetypes-text-markdown` — first extraction (#47). Validates the "bundle minimally" pattern.
669
- - **Providers:** `@plurnk/plurnk-providers-openai` — talks to any OpenAI-compatible endpoint (OpenAI proper, llama-server, Ollama OpenAI-compat, etc.).
670
- - **Client:** `@plurnk/plurnk` — user-facing CLI/TUI (independent agent ownership since #57).
671
-
672
- **Future external** (separate repos, separate npm packages, optional install when written):
673
- - **Providers:** `openrouter`, `xai`, `google`, `ollama` (native API), `anthropic`, `cf` (Cloudflare). Phase D.
674
- - **Schemes:** `http(s)`, `ws(s)`, `sse`, `graphql`, `openapi`, `grpc`, `mailto`, `mcp`, `sftp`, `rest`, `search`. Streaming schemes land in Phase F.
675
- - **Mimetypes:** `application/json`, `text/vnd.plurnk`, anything beyond. Phase C.
651
+ - `exec` — manifest only; subprocess invocation not yet implemented.
652
+ - `file` — in-tree; extraction to a sibling repo is planned once the workspace + exec/streams work shapes the scheme's full surface. **The model is never trained on `file://` and never sees it in any rendered output.** Bare paths (`README.md`, `/abs/path.txt`) are the model-facing form; `file://` is accepted as an explicit input for absolute root paths but renders bare in the index, log, and every other model-facing surface.
676
653
 
677
- Plugin discovery (§9) finds every installed `@plurnk/*` package at boot and registers what they declare. The bundled set is the floor; siblings are what's installed; the system runs against whatever is present in `node_modules`.
654
+ In-tree schemes will move to siblings as their surfaces stabilize.
678
655
 
679
656
  ---
680
657
 
681
658
  ## §11 Grammar Dependency
682
659
 
683
- `@plurnk/plurnk-grammar@0.5.0` is the contract. Consumed via `github:plurnk/plurnk-grammar` HEAD during pre-1.0 iteration. Treat the grammar as authoritative; surface gaps to the user, don't redesign from this side.
660
+ `@plurnk/plurnk-grammar` is the contract. Treat it as authoritative; surface gaps to the user, don't redesign from this side. When a gap surfaces, file an issue upstream and adopt whatever lands.
684
661
 
685
662
  ### §11.1 What grammar provides
686
663
 
@@ -691,23 +668,13 @@ Plugin discovery (§9) finds every installed `@plurnk/*` package at boot and reg
691
668
 
692
669
  ### §11.2 What plurnk-service tracks in its own runtime state (NOT in the grammar)
693
670
 
694
- - Channel lifecycle (`active` / `closed` / `errored`) — subscription registry, not on `ChannelContent`. Was rejected as a contract field with good reason: streams are not a distinct paradigm at the contract layer; they're a runtime relationship between an entry and an open connection.
695
- - Render budget per channel (token count) — `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` operator config (§12).
671
+ - Channel lifecycle (`active` / `closed` / `errored`) — subscription registry, not on `ChannelContent`. Streams are not a distinct paradigm at the contract layer; they're a runtime relationship between an entry and an open connection.
672
+ - Render budget per channel — `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` operator config (§12); character-count today (§14.2).
696
673
  - Backpressure caps — none in v0 (§7.8). Providers/schemes/mimetypes own their own throttling.
697
674
  - Stream cancel verb — no dedicated cancel op or signal in the grammar. SEND[499] to the URI is the pattern (§7.7).
698
675
  - Delete verb — no dedicated DELETE op. SEND[410] to the URI is the pattern (§3.5, §6.5).
699
-
700
- ### §11.3 Grammar contract changes (resolved)
701
-
702
- All grammar issues filed against the upstream contract have closed and shipped. Service tracks the resolution:
703
-
704
- - **#6 `text/vnd.plurnk`** — closed; DSL mimetype identifier confirmed.
705
- - **#7 public `parsePath` helper** — closed; landed in grammar 0.3.2.
706
- - **#8 SEND broadcast vs directed clarification** — closed; grammar plurnk.md docs tightened.
707
- - **#9 packet contract + parse-error surface** — closed; grammar 0.4.0 renamed `packet.user.turn` → `packet.user.telemetry` and shipped the `{budget, errors}` shape. Service aligned in #123.
708
- - **#10 Run.name + dual-handle** — closed; grammar 0.5.0 added required `Run.name`. Service aligned in #123.
709
-
710
- When future gaps surface, they get filed as grammar issues (not redesigned in plurnk-service), and the relevant SPEC.md section notes the pending request.
676
+ - Per-loop flag plumbing — `loops.flags` JSON column. Engine plumbs the grammar's `LoopFlags` shape (yolo, mode, noWeb, noInteraction, noProposals) per-loop; today `yolo` is end-to-end, others are scheduled.
677
+ - Wire-rendering conventions on top of grammar fences — see §5.5 default-channel addressing.
711
678
 
712
679
  ---
713
680
 
@@ -729,8 +696,10 @@ Model selection uses a separate alias cascade managed by `ProviderRegistry` (`sr
729
696
  | `PLURNK_MAX_STRIKES` | `3` | enforced | Strike threshold + sudden-death lead time (§0.5). |
730
697
  | `PLURNK_MIN_CYCLES` | `3` | enforced | Min repetitions before cycle detection fires (§0.5). |
731
698
  | `PLURNK_MAX_CYCLE_PERIOD` | `4` | enforced | Max period length cycle detection examines (§0.5). |
732
- | `PLURNK_WORKSPACE_ROOT` | `""` | enforced | Filesystem root for `file://` scheme reads. Empty = `file://` returns 400. |
733
- | `PLURNK_REASON` | `0` | enforced | Reasoning-token budget. 0 = disabled. Positive = budget in tokens; provider modules translate to wire format (PROVIDERS.md §3.8). |
699
+ | `PLURNK_PERSONA` | `persona.md` | enforced | Path to the default persona file. Tail of the persona cascade: loops.persona > runs.persona > sessions.persona > this file. |
700
+ | `PLURNK_PROPOSAL_TIMEOUT_MS` | `300000` | enforced | ms wait for a proposed entry (status=202) to be resolved before timing out. |
701
+ | `PLURNK_REASON` | `0` | enforced | Reasoning-token budget. 0 = disabled. Positive = budget in tokens; provider modules translate to wire format. |
702
+ | `PLURNK_FETCH_TIMEOUT` | `600000` | enforced | Service-wide ms ceiling on any outbound request (providers, future http schemes). Module-specific overrides are allowed below the ceiling. |
734
703
  | `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` | `256` | enforced | Per-channel preview budget for index tiles (characters; §14.2). |
735
704
  | `PLURNK_DEBUG` | `0` | reserved | Schema-validation toggle. Not yet enforced. |
736
705
  | `PLURNK_LOG_LEVEL` | `info` | reserved | Stdout banner verbosity. Not yet enforced. |
@@ -838,21 +807,31 @@ The minimum v0 surface. Methods are grouped by concern.
838
807
 
839
808
  **Sessions**
840
809
 
841
- | Method | Params | Result | Notes |
842
- |-------------------|---------------------|-------------------|-------|
843
- | `session.create` | `name?: string` | `{ id, name }` | Creates new session; auto-name from timestamp if unprovided. |
844
- | `session.list` | none | `{ sessions: Session[] }` | Lists all sessions. |
845
- | `session.attach` | `id: number`, `runId?: number`, `runName?: string` | `{ id, name, runId, runName }` | Binds this connection to an existing session. Optional `runId` resumes that specific run (must belong to the session). Optional `runName` reuses-or-creates by name within the session. Both omitted → new auto-named run. |
846
- | `session.runs` | `id?: number` | `{ runs: Run[] }` | Lists runs in a session (defaults to attached session); most-recent first. |
810
+ | Method | Params | Result | Notes |
811
+ |------------------------|---------------------|-------------------|-------|
812
+ | `session.create` | `name?: string`, `projectRoot?: string`, `persona?: string` | `{ id, name, projectRoot, persona }` | Creates new session; auto-name if unprovided. Optional `projectRoot` pins the workspace (null/omitted = headless). Optional `persona` sets the session-level persona override. |
813
+ | `session.list` | none | `{ sessions: Session[] }` | Lists all sessions. |
814
+ | `session.attach` | `id: number`, `runId?: number`, `runName?: string`, `persona?: string` | `{ id, name, runId, runName }` | Binds this connection to an existing session. Optional `runId` resumes that specific run (must belong to the session). Optional `runName` reuses-or-creates by name within the session. Both omitted → new auto-named run. Optional `persona` sets run-level persona only when a NEW run is created. |
815
+ | `session.runs` | `id?: number` | `{ runs: Run[] }` | Lists runs in a session (defaults to attached session); most-recent first. |
816
+ | `session.set_root` | `projectRoot: string \| null` | `{ projectRoot }` | Update the workspace pointer on the attached session. Null reverts to headless. |
817
+ | `session.set_persona` | `persona: string \| null` | `{ persona }` | Update the session-level persona. Null clears the override (falls through to PLURNK_PERSONA file). |
847
818
 
848
819
  If a client issues a method requiring init (`requiresInit: true`) without first calling `session.attach` or `session.create`, the daemon auto-creates the envelope on demand: session → run → client loop, all persisted normally. Auto-creation is a convenience for one-off invocations (Telegram quick-queries, neovim ad-hoc dispatches, `plurnk "prompt"` CLI shots); the records carry through the same way explicitly-created ones do. **Auto-created ≠ auto-deleted.** Records persist for the log's forensic value. If a client wants active cleanup, that's a future `session.delete` / `session.archive` endpoint, opt-in.
849
820
 
850
821
  **Loops (model-driven)**
851
822
 
823
+ | Method | Params | Result | Notes |
824
+ |-------------------|-------------------------------------|------------------------|-------|
825
+ | `loop.run` | `prompt: string`, `maxTurns?: number`, `alias?: string`, `flags?: LoopFlags`, `persona?: string` | `{ loopId, turnIds, finalStatus, hitMaxTurns, reason }` | Model-driven loop. Optional `alias` overrides the boot-time `PLURNK_MODEL`. Optional `flags` carries per-loop flags (currently `{yolo?: boolean}`; more arrive as wired — see §0.5). Optional `persona` sets the loop-level persona (highest precedence in the cascade). Streams `log/entry` and `loop/proposal` notifications during. `longRunning: true`. |
826
+ | `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. |
827
+ | `providers.list` | none | `{ aliases: ProviderAlias[] }` | Lists configured `PLURNK_MODEL_<alias>` entries with `{alias, provider, model, active}`. Clients use to populate model-selection UI. |
828
+
829
+ **Reads**
830
+
852
831
  | Method | Params | Result | Notes |
853
832
  |---------------|-------------------------------------|------------------------|-------|
854
- | `loop.run` | `prompt`, `maxTurns?`, `alias?` | `{ loopId, turnIds, finalStatus, hitMaxTurns, reason }` | Model-driven loop. Optional `alias` overrides the daemon's boot-time `PLURNK_MODEL` for this call (resolves via `ProviderRegistry`); unknown alias error. Streams `log/entry` notifications during. `longRunning: true`. |
855
- | `providers.list` | none | `{ aliases: ProviderAlias[] }` | Lists configured `PLURNK_MODEL_<alias>` entries with `{alias, provider, model, active}`. Clients use to populate model-selection UI. |
833
+ | `entry.read` | `target: string` | `{ status, entry }` | Read the full entry shape (channels + tags + metadata) at the given URI. |
834
+ | `log.read` | `loopId?: number`, … | `{ entries: LogEntry[] }` | Read recent log entries from the attached session, optionally filtered by loop. |
856
835
 
857
836
  **DSL operations (client-driven, mirror the grammar)**
858
837
 
@@ -860,15 +839,17 @@ Per the **Speak in DSL, not plumbing** rule (AGENTS.md Standing Rules): RPC meth
860
839
 
861
840
  Each `op.*` call creates a turn in the connection's client loop (§13.7) with the constructed statement as a single action, dispatches it, fires a `log/entry` notification to attached clients of the session, returns the dispatch result.
862
841
 
842
+ Naming follows the uniform principle: `target` is the URI the op acts on (the operand); `scope` for FIND (the search root); `source`/`destination` for COPY/MOVE; `recipient` for SEND (or null = broadcast); `cwd` for EXEC. `path` is never an RPC operand here — that word is reserved for *identity* throughout plurnk (the URI of *this thing*).
843
+
863
844
  | Method | Params | Notes |
864
845
  |---------------|---------------------------------------------------------|-------|
865
846
  | `op.find` | `scope: string`, `matcher?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<FIND>>`. |
866
- | `op.read` | `path: string`, `matcher?: string`, `lineRange?: LineMarker`, `tags?: string[]` | Mirrors `<<READ>>`. |
867
- | `op.edit` | `path: string`, `content?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<EDIT>>`. |
847
+ | `op.read` | `target: string`, `matcher?: string`, `lineRange?: LineMarker`, `tags?: string[]` | Mirrors `<<READ>>`. |
848
+ | `op.edit` | `target: string`, `content?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<EDIT>>`. |
868
849
  | `op.copy` | `source: string`, `destination: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<COPY>>`. |
869
850
  | `op.move` | `source: string`, `destination?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<MOVE>>`. Missing `destination` = delete (null-body MOVE). |
870
- | `op.show` | `path: string`, `matcher?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<SHOW>>`. |
871
- | `op.hide` | `path: string`, `matcher?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<HIDE>>`. |
851
+ | `op.show` | `target: string`, `matcher?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<SHOW>>`. |
852
+ | `op.hide` | `target: string`, `matcher?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<HIDE>>`. |
872
853
  | `op.send` | `status: number`, `recipient?: string`, `body?: string` | Mirrors `<<SEND>>`. |
873
854
  | `op.exec` | `cwd?: string`, `runtime?: string`, `command?: string` | Mirrors `<<EXEC>>`. |
874
855
  | `op.dispatch` | `statement: PlurnkStatement` | Low-level path for clients that have a parsed AST already (e.g. the TUI when the user types raw HEREDOC at the prompt). |
@@ -879,7 +860,7 @@ All `op.*` methods return `{ status: number, ...op-specific-extras }`. They are
879
860
  Future-reserved (post-v0):
880
861
 
881
862
  - `subscription.list` — list active streaming subscriptions (§7).
882
- - `subscription.cancel` — analog of `SEND[499]` over RPC, though `op.send({status: 499, recipient: path})` does the same thing today.
863
+ - `subscription.cancel` — analog of `SEND[499]` over RPC, though `op.send({status: 499, recipient})` does the same thing today.
883
864
 
884
865
  ### §13.6 Notifications
885
866
 
@@ -889,10 +870,11 @@ Server-initiated events streamed to the client over the same WebSocket. Critical
889
870
  |--------------------|-------------------------------------|------------|
890
871
  | `log/entry` | `{ entry: LogEntry }` | Every time a `log_entries` row is written. |
891
872
  | `loop/terminated` | `{ loopId, finalStatus, hitMaxTurns }` | When a loop reaches a terminal status. |
892
- | `session/created` | `{ session: Session }` | When a session is created (any client's action; gives multi-client awareness). |
873
+ | `loop/proposal` | `{ logEntryId, sessionId, runId, loopId, turnId, op, target, body, attrs, flags }` | Fired when dispatch pauses on a status=202 proposed entry. Carries the proposal payload + the loop's `flags` so a client connected to a server-YOLO loop can suppress its review UI. Client responds with `loop.resolve` (or ignores, in which case the daemon's `PLURNK_PROPOSAL_TIMEOUT_MS` fires). |
874
+ | `session/created` | `{ id, name, projectRoot, persona }` | When a session is created (any client's action; gives multi-client awareness). |
893
875
  | `stream/event` | `{ entryId, channel, state, contentLength }` | When a channel's content grows or its state transitions. For clients rendering live; the model only sees state at turn boundaries. {§13.6-stream-event-on-channel-change} |
894
876
 
895
- The `stream/event` payload deliberately carries metadata, NOT content. Clients that want the new content call `entry.read({path})` to fetch — this avoids large notification payloads and gives the client agency over whether to refresh. Sample-driven (notifications include `contentLength` so clients can dedupe / batch).
877
+ The `stream/event` payload deliberately carries metadata, NOT content. Clients that want the new content call `entry.read({target})` to fetch — this avoids large notification payloads and gives the client agency over whether to refresh. Sample-driven (notifications include `contentLength` so clients can dedupe / batch).
896
878
 
897
879
  Notifications are scoped to the connection's attached session — a client attached to session A does NOT receive `log/entry` notifications for actions on session B. (Cross-session observation is a future feature; v0 keeps the scope tight.)
898
880
 
@@ -958,9 +940,7 @@ Error responses MAY include `data: { ... }` with structured context (the path th
958
940
 
959
941
  ### §13.9 Versioning
960
942
 
961
- `plurnk-service` exposes a `protocolVersion` field in `discover`'s response (semver). Major version mismatches are a contract break clients SHOULD refuse to operate on a major mismatch. Minor/patch increments are backward-compatible.
962
-
963
- Current: `protocolVersion: "0.1.0"`. The floor is green and the daemon has been exercised end-to-end via the `plurnk` TUI client (which now graduates to its own agent). Promotes to `1.0.0` when an independent external client (neovim plugin or Telegram bot) lands AND the mimetype/channel/transaction work below has settled.
943
+ Pre-interface-stabilization. The RPC surface evolves freely; clients track HEAD. No semver promises until we have an actual interface worth committing to.
964
944
 
965
945
  ---
966
946
 
@@ -982,24 +962,21 @@ Each entry: the question, the answer, the rationale, the migration path if revis
982
962
 
983
963
  **Migration path if revisited.** If a future plugin needs to inject a packet section (e.g., a `<turn>` metadata table per rummy SPEC §packet_structure), the engine grows a single `packet.augment` filter hook called after `#buildIndex` returns. Plugins subscribe with a priority; each returns a `system` and/or `user` augmentation object that gets merged into the packet shape. This is additive — the engine-direct base case stays; plugins augment.
984
964
 
985
- ### §14.2 Budget unit: character count for v0
965
+ ### §14.2 Budget unit: character count
986
966
 
987
- **Question.** `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` is named for tokens; current implementation in `Engine.#previewBudget` treats it as a character-count cap passed to `MimetypeHandler.preview(content, budget)`. The MIMETYPES.md contract documents budget as a number, semantic-agnostic. The env var name and the implementation disagree.
967
+ **Question.** `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` is named for tokens; the engine passes it as a character-count budget to mimetype processing. Env var name and implementation disagree.
988
968
 
989
- **Decision.** v0 treats budget as character count. The env var keeps its `_TOKENS` suffix as forward-naming for the eventual switch but currently means characters. {§14.2-budget-is-characters-v0}
969
+ **Decision.** Budget is character count. The env var name is a forward-naming placeholder for an eventual token unit; today it means characters. {§14.2-budget-is-characters-v0}
990
970
 
991
- **Rationale.**
992
- - Token counts require a per-provider tokenizer. PROVIDERS.md §11 marks `countTokens` as out of v0 contract; no provider currently exposes it.
993
- - Character count is a tokenizer-independent first approximation. Wrong by a factor of ~3-4× for English (1 token ≈ 3-4 chars), but consistent and zero-config.
994
- - Switching the unit later requires: (a) `countTokens` lands on the provider contract, (b) engine caches token counts per `(provider_id, content_hash)`, (c) mimetype.preview gets a tokenizer reference or returns content for engine to tokenize-and-truncate. Out of v0 scope.
971
+ **Rationale.** Mimetype handlers operate on strings. They have no tokenizer reference and shouldn't — tokenization is provider-bound (§2.3). Character-count is the tokenizer-independent budget that fits the handler's domain. Engine *could* post-tokenize the resulting preview for accounting (the provider's `countTokens` is available), but the budget passed *into* the handler is characters by design.
995
972
 
996
- **Migration path if revisited.** When provider `countTokens` lands and the engine has per-channel token accounting, `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` becomes literal tokens. Mimetype handlers either receive a tokenizer reference in `preview(content, budget, countTokens?)` or the engine post-processes character-bounded `preview` output through tokenizer + truncate. The MIMETYPES.md contract revision is non-breaking (signature stays `(content, budget) → string`); the semantic of `budget` changes from char-count to token-count.
973
+ **Migration path if revisited.** Either rename the env var to reflect characters, or change the budget semantic to tokens by handing handlers a tokenizer reference (`preview(content, budget, countTokens?)`). The latter conflates concerns and isn't appealing.
997
974
 
998
975
  ---
999
976
 
1000
977
  ## §15 Packet shape
1001
978
 
1002
- The canonical packet shape is defined by `@plurnk/plurnk-grammar` (`schema/Packet.json`, ≥0.4.0). Engine assembles in `Engine.#buildPacket`; plugins do not augment in v0 (§14.1). This section describes plurnk-service's responsibilities under that contract — see grammar for the authoritative schema.
979
+ The canonical packet shape is defined by `@plurnk/plurnk-grammar` (`schema/Packet.json`). Engine assembles in `Engine.#buildRequestPacket`; plugins do not augment in v0 (§14.1). This section describes plurnk-service's responsibilities under that contract — see grammar for the authoritative schema.
1003
980
 
1004
981
  ```ts
1005
982
  type Packet = {
@@ -1022,6 +999,8 @@ type Packet = {
1022
999
  };
1023
1000
  ```
1024
1001
 
1002
+ **Prompt as a first-class entry.** Each loop's prompt is written on loop start as a system-origin `EDIT` against `plurnk://prompt/<loop_id>` (indexable entry, body channel, text/markdown). The corresponding log row renders as `* {"op":"EDIT","origin":"system","path":"log://<L>/1/1/EDIT","status":201,"target":"plurnk://prompt/<L>"}` — `path` is the log row's own URI, `target` is the plurnk entry that got written. At render time, the *current* loop's `plurnk://prompt/<loop_id>` entry is foisted out of `packet.system.index` and materialized in `packet.user.prompt` — one section, one mechanism, no duplicate content rendering. Previous loops' prompt entries remain in the index and are addressable for the model to READ or HIDE. {§15-current-prompt-foist}
1003
+
1025
1004
  ### §15.1 user.telemetry — model-facing runtime telemetry
1026
1005
 
1027
1006
  The slot for telemetry the model MUST react to right now: budget pressure and last-turn failures that didn't produce an action-entry. Rendered prominently at the bottom of the user section so the model cannot ignore it. Errors here are transient — they appear on the turn AFTER the failure and clear once the model has seen them. The action-entries (`packet.system.log[]`) are the durable audit; `telemetry.errors[]` is the **alert**.
@@ -1034,12 +1013,19 @@ The slot for telemetry the model MUST react to right now: budget pressure and la
1034
1013
  **Plurnk-service rendering (v0):**
1035
1014
 
1036
1015
  - `budget` is rendered as a short markdown line. Unit follows §14.2 (character count); the exact rendering is engine-internal and may evolve without a schema change.
1037
- - `errors[]` carries one object per actionless failure from the previous turn. Service's working element shape (subject to tightening as needs solidify):
1038
- ```
1039
- { kind: "parse" | "dispatch_crash" | "no_send" | "watchdog" | "budget_overflow" | "rail",
1040
- message: string,
1041
- detail?: unknown }
1042
- ```
1043
- - Action-bound failures (handler returned 4xx/5xx or threw) are mirrored as a one-line summary object into `telemetry.errors[]` on the next packet — same forced-confrontation pattern. Full detail stays queryable via `log://`. {§15.1-no-error-scheme}
1016
+ - `errors[]` carries telemetry from the previous turn's dispatch + rail evaluation. Each element has a required `kind` discriminator and a required `message` string (human-readable, model-actionable). Additional kind-specific fields are flat on the element — there is NO nested `detail` envelope; canonical-JSON serialization sorts keys for prefix-cache friendliness.
1017
+ - Wire format: one `* {canonical-JSON}` line per error under `# Plurnk System Errors`, in push order. Buffer drains on read — each error appears in exactly one packet. {§15.1-drain-on-read}
1018
+
1019
+ **Kinds emitted by plurnk-service v0:**
1020
+
1021
+ | `kind` | Source | Required fields | Additional fields |
1022
+ |---|---|---|---|
1023
+ | `action_failure` | Log entry with `status_rx ≥ 400` from previous turn | `kind`, `message`, `coordinate` (`<L>/<T>/<S>`), `op`, `status` | `target` (URI or null) |
1024
+ | `no_ops` | Rail #41 — turn ended with zero ops | `kind`, `message` | — |
1025
+ | `strike` | Rail #38 — strike streak bumped (no_ops / recorded_failure / rail) | `kind`, `message`, `streak`, `maxStrikes`, `reason` | — |
1026
+ | `cycle` | Rail #39 — repeating turn fingerprint pattern detected | `kind`, `message`, `period`, `cycles` | — |
1027
+ | `sudden_death` | Rail #40 — entering the last `maxStrikes`-sized window before `maxTurns` | `kind`, `message`, `remaining` | — |
1028
+
1029
+ Action-bound failures (handler returned 4xx/5xx or threw) are mirrored as the `action_failure` kind on the next packet — same forced-confrontation pattern. Full detail stays queryable via `log://`. {§15.1-no-error-scheme}
1044
1030
 
1045
1031
  **No `error://` scheme.** Actionless failures route to telemetry, not to a queryable scheme namespace.
@@ -7,6 +7,16 @@ export interface StreamEventPayload {
7
7
  contentLength: number;
8
8
  }
9
9
  export type StreamEventNotify = (sessionId: number, event: StreamEventPayload) => void;
10
+ export interface WakeRunPayload {
11
+ sessionId: number;
12
+ runId: number;
13
+ entryId: number;
14
+ subscriptionId: number;
15
+ closeStatus: number;
16
+ scheme: string;
17
+ summary: string;
18
+ }
19
+ export type WakeRunNotify = (payload: WakeRunPayload) => void;
10
20
  export declare const appendToChannel: (db: Db, { entryId, channel, chunk, notify }: {
11
21
  entryId: number;
12
22
  channel: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ChannelWrite.d.ts","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,EAAc,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAevF,eAAO,MAAM,eAAe,GACxB,IAAI,EAAE,EACN,qCAAqC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAAE,KACrH,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,eAAO,MAAM,eAAe,GACxB,IAAI,EAAE,EACN,qCAAqC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAAE,KAC3H,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,eAAO,MAAM,gBAAgB,GACzB,IAAI,EAAE,EACN,oCAAoC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KACvG,OAAO,CAAC,MAAM,CAIhB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC1B,IAAI,EAAE,EACN,4BAA4B;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KACvE,OAAO,CAAC,IAAI,CAEd,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAC/B,IAAI,EAAE,EACN,oBAAoB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,KACvD,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAG/D,CAAC"}
1
+ {"version":3,"file":"ChannelWrite.d.ts","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,EAAc,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAQvF,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;AAe9D,eAAO,MAAM,eAAe,GACxB,IAAI,EAAE,EACN,qCAAqC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAAE,KACrH,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,eAAO,MAAM,eAAe,GACxB,IAAI,EAAE,EACN,qCAAqC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAAE,KAC3H,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,eAAO,MAAM,gBAAgB,GACzB,IAAI,EAAE,EACN,oCAAoC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KACvG,OAAO,CAAC,MAAM,CAIhB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC1B,IAAI,EAAE,EACN,4BAA4B;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KACvE,OAAO,CAAC,IAAI,CAEd,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAC/B,IAAI,EAAE,EACN,oBAAoB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,KACvD,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAG/D,CAAC"}
@@ -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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"}
@@ -3,6 +3,7 @@ import type SchemeRegistry from "./SchemeRegistry.ts";
3
3
  import { Mimetypes } from "@plurnk/plurnk-mimetypes";
4
4
  import type { Db } from "./Db.ts";
5
5
  import type { LoopFlags } from "./scheme-types.ts";
6
+ import type { StreamEventNotify, WakeRunNotify } from "./ChannelWrite.ts";
6
7
  type Origin = "model" | "client" | "system" | "plugin";
7
8
  type ChatMessage = {
8
9
  role: "system" | "user" | "assistant";
@@ -15,7 +16,7 @@ type DispatchContext = {
15
16
  runId: number;
16
17
  loopId: number;
17
18
  turnId: number;
18
- actionIndex: number;
19
+ sequence: number;
19
20
  origin: Origin;
20
21
  onDispatch?: (logEntryId: number) => void;
21
22
  };
@@ -55,10 +56,12 @@ export declare const detectCycle: (history: ReadonlyArray<string>, minCycles: nu
55
56
  };
56
57
  export default class Engine {
57
58
  #private;
58
- constructor({ db, schemes, mimetypes }: {
59
+ constructor({ db, schemes, mimetypes, streamEventNotify, wakeRunNotify }: {
59
60
  db: Db;
60
61
  schemes: SchemeRegistry;
61
62
  mimetypes?: Mimetypes;
63
+ streamEventNotify?: StreamEventNotify;
64
+ wakeRunNotify?: WakeRunNotify;
62
65
  });
63
66
  runLoop({ provider, messages, persona, sessionId, runId, loopId, maxTurns, maxStrikes, minCycles, maxCyclePeriod, origin, signal, onDispatch, }: {
64
67
  provider: Provider;
@@ -101,6 +104,11 @@ export default class Engine {
101
104
  dispatch(context: DispatchContext): Promise<DispatchResult>;
102
105
  resolveProposal(logEntryId: number, resolution: ProposalResolution): void;
103
106
  pendingProposalIds(): number[];
107
+ hasActiveLoopForRun(runId: number): Promise<boolean>;
108
+ inject(runId: number, prompt: string): Promise<{
109
+ loopId: number;
110
+ turnSeq: number;
111
+ } | null>;
104
112
  onProposalPending(listener: (event: ProposalPendingEvent) => void): void;
105
113
  }
106
114
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/core/Engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/core/Engine.ts"],"names":[],"mappings":"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"}