@plurnk/plurnk-service 0.16.0 → 0.19.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 (83) hide show
  1. package/SPEC.md +17 -8
  2. package/dist/Paths.d.ts +1 -0
  3. package/dist/Paths.d.ts.map +1 -1
  4. package/dist/Paths.js +5 -0
  5. package/dist/Paths.js.map +1 -1
  6. package/dist/core/ChannelWrite.d.ts +4 -0
  7. package/dist/core/ChannelWrite.d.ts.map +1 -1
  8. package/dist/core/ChannelWrite.js +8 -0
  9. package/dist/core/ChannelWrite.js.map +1 -1
  10. package/dist/core/Engine.d.ts +5 -0
  11. package/dist/core/Engine.d.ts.map +1 -1
  12. package/dist/core/Engine.js +137 -18
  13. package/dist/core/Engine.js.map +1 -1
  14. package/dist/core/ExecutorRegistry.d.ts +9 -1
  15. package/dist/core/ExecutorRegistry.d.ts.map +1 -1
  16. package/dist/core/ExecutorRegistry.js +21 -28
  17. package/dist/core/ExecutorRegistry.js.map +1 -1
  18. package/dist/core/SchemeRegistry.d.ts +2 -0
  19. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  20. package/dist/core/SchemeRegistry.js +52 -0
  21. package/dist/core/SchemeRegistry.js.map +1 -1
  22. package/dist/core/git-membership.d.ts.map +1 -1
  23. package/dist/core/git-membership.js +10 -3
  24. package/dist/core/git-membership.js.map +1 -1
  25. package/dist/core/git-state.d.ts +15 -0
  26. package/dist/core/git-state.d.ts.map +1 -0
  27. package/dist/core/git-state.js +65 -0
  28. package/dist/core/git-state.js.map +1 -0
  29. package/dist/core/packet-wire.d.ts +1 -0
  30. package/dist/core/packet-wire.d.ts.map +1 -1
  31. package/dist/core/packet-wire.js +8 -1
  32. package/dist/core/packet-wire.js.map +1 -1
  33. package/dist/core/scheme-types.d.ts +9 -0
  34. package/dist/core/scheme-types.d.ts.map +1 -1
  35. package/dist/schemes/Exec.d.ts +4 -0
  36. package/dist/schemes/Exec.d.ts.map +1 -1
  37. package/dist/schemes/Exec.js +24 -1
  38. package/dist/schemes/Exec.js.map +1 -1
  39. package/dist/schemes/File.d.ts +8 -10
  40. package/dist/schemes/File.d.ts.map +1 -1
  41. package/dist/schemes/File.js +81 -114
  42. package/dist/schemes/File.js.map +1 -1
  43. package/dist/schemes/Log.d.ts +2 -10
  44. package/dist/schemes/Log.d.ts.map +1 -1
  45. package/dist/schemes/Log.js +42 -9
  46. package/dist/schemes/Log.js.map +1 -1
  47. package/dist/schemes/_entry-crud.d.ts +2 -0
  48. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  49. package/dist/schemes/_entry-crud.js +4 -0
  50. package/dist/schemes/_entry-crud.js.map +1 -1
  51. package/dist/schemes/_entry-find.d.ts.map +1 -1
  52. package/dist/schemes/_entry-find.js +15 -1
  53. package/dist/schemes/_entry-find.js.map +1 -1
  54. package/dist/schemes/_entry-graph.d.ts +11 -0
  55. package/dist/schemes/_entry-graph.d.ts.map +1 -0
  56. package/dist/schemes/_entry-graph.js +81 -0
  57. package/dist/schemes/_entry-graph.js.map +1 -0
  58. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  59. package/dist/schemes/_entry-manifest.js +32 -5
  60. package/dist/schemes/_entry-manifest.js.map +1 -1
  61. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  62. package/dist/schemes/_entry-ops.js +12 -1
  63. package/dist/schemes/_entry-ops.js.map +1 -1
  64. package/dist/server/ClientConnection.d.ts.map +1 -1
  65. package/dist/server/ClientConnection.js +5 -2
  66. package/dist/server/ClientConnection.js.map +1 -1
  67. package/dist/server/Daemon.d.ts.map +1 -1
  68. package/dist/server/Daemon.js +8 -0
  69. package/dist/server/Daemon.js.map +1 -1
  70. package/dist/server/MethodRegistry.d.ts +5 -0
  71. package/dist/server/MethodRegistry.d.ts.map +1 -1
  72. package/dist/server/MethodRegistry.js.map +1 -1
  73. package/dist/server/methods/loop_run.d.ts.map +1 -1
  74. package/dist/server/methods/loop_run.js +1 -0
  75. package/dist/server/methods/loop_run.js.map +1 -1
  76. package/dist/server/methods/session_attach.d.ts.map +1 -1
  77. package/dist/server/methods/session_attach.js +0 -3
  78. package/dist/server/methods/session_attach.js.map +1 -1
  79. package/dist/server/methods/session_create.d.ts.map +1 -1
  80. package/dist/server/methods/session_create.js +1 -3
  81. package/dist/server/methods/session_create.js.map +1 -1
  82. package/migrations/0000-00-00.01_schema.sql +39 -1
  83. package/package.json +109 -113
package/SPEC.md CHANGED
@@ -207,7 +207,7 @@ Directed SEND (non-null path) routes to scheme's `send`. Status = intent:
207
207
  - `SEND[200](path)` — write body into resource (WS message, exec stdin).
208
208
  - `SEND[499](path)` — cancel active subscription (§7).
209
209
 
210
- `SEND[410](path[#fragment])` also deletes the target entry/channel — an implemented side-effect, NOT taught to the model and with no live/demo surface. The model-facing delete idiom is MOVE to `/dev/null` (§6.5).
210
+ `SEND[410](path[#fragment])` also deletes the target entry/channel — an implemented side-effect, NOT taught to the model and with no live/demo surface. The model-facing delete idiom is KILL (the MOVE→`/dev/null` idiom is retired, §6.5).
211
211
 
212
212
  Other status codes return 501 from entry-bearing schemes by default. {§3.5-entry-schemes-501-on-non-410}
213
213
 
@@ -305,14 +305,15 @@ new Mimetypes({
305
305
 
306
306
  Fallback heuristic is a boot-before-provider-resolved tripwire.
307
307
 
308
- **Manifest build.** `EntryManifest.buildManifestBody` calls `process({ content, hint })` per channel and reads `result.totalLines` for the catalog's `lines`:
308
+ **Manifest build.** `EntryManifest.buildManifestBody` is the engine-side packet-assembly pass (the §4 firing point) that walks **every** entry. It calls `process({ content, hint })` per channel for the catalog's `lines` (`totalLines`) and, for the body channel, pulls `symbols`+`references` from the *same* call to (re)build the `@graph` symbol index (`symbol_defs`/`symbol_refs`) via `EntryGraph.populateFrom` — one parse, two projections:
309
309
 
310
310
  ```ts
311
- const result = await mimetypes.process({ content: r.content, hint: r.mimetype });
311
+ const result = await mimetypes.process({ content: r.content, hint: r.mimetype }, { channels: ["symbols", "references"] });
312
312
  entry.channels[r.channel] = { mimetype: r.mimetype, tokens: tokenize(r.content), lines: result.totalLines };
313
+ if (isBody) await EntryGraph.populateFrom(db, sessionId, r.entry_id, result.symbols ?? [], result.references ?? []);
313
314
  ```
314
315
 
315
- `hint` short-circuits detection. The service consumes only `totalLines` (extent) and the structural channels (`deepJson`/`deepXml`, for matcher dispatch); never a rendered preview — content reaches the model on READ.
316
+ `hint` short-circuits detection. The service consumes `totalLines` (extent), `symbols`/`references` (the `@graph` index), and `deepJson`/`deepXml` (matcher dispatch); never a rendered preview — content reaches the model on READ. Because this pass runs every assembly over every entry, any content change — by any writer — is reflected in the next packet's index. The `@graph` index is NOT engine *ranking* (the anti-pattern): it's a complete, unranked index the model queries via `FIND @<sym`, the manifest paradigm applied to structure, uniform across schemes (`file://` is the primary case).
316
317
 
317
318
  **Conformance.** Mimetype-specific behavioral tests live in each handler's own surface. plurnk-service intg covers integration: the engine routes through `Mimetypes.process` with the right hint and the catalog reflects `totalLines`; tests use auto-discovery (production handler set); a custom-handler test injects a stub `BaseHandler` via `loader + discovery`.
318
319
 
@@ -338,7 +339,7 @@ Every entry is uniformly listed in `plurnk://manifest.json` (§15) and READable
338
339
 
339
340
  Mimetype is declared by scheme manifest (§3.1) or supplied per-call for dynamic schemes. Writing a channel without a declared mimetype throws. No default mimetype anywhere.
340
341
 
341
- - Cross-mimetype COPY/MOVE → 415, never coerces (§6.4).
342
+ - Cross-mimetype COPY/MOVE → 415, never coerces (§6.4). {§5.3-cross-mimetype-415}
342
343
 
343
344
  ### §5.5 Channel selection in the DSL
344
345
 
@@ -436,8 +437,8 @@ Returns 201 on success. Same- and cross-scheme COPY share the orchestrator. {§6
436
437
 
437
438
  AST: `{ op: "MOVE", target (source), body: dest | null, signal: tags | null, lineMarker? }`.
438
439
 
439
- - **Relocation** (`body` non-null): COPY (§6.4) + `src_scheme.deleteEntry` in one transaction. 201 on success. {§6.5-relocation-deletes-source} Cross-scheme same as same-scheme. {§6.5-cross-scheme-move}
440
- - **Deletion** (`body: null`, or `body` = `/dev/null`): `src_scheme.deleteEntry` directly. {§6.5-null-body-deletes} 200 on success, 404 if absent. {§6.5-missing-source-404} `/dev/null` is the model-facing delete idiom the grammar teaches; a null body is its programmatic equivalent. {§6.5-dev-null-deletes}
440
+ - **Relocation** (`body` non-null, resolvable dest): COPY (§6.4) + `src_scheme.deleteEntry` in one transaction. 201 on success. {§6.5-relocation-deletes-source} Cross-scheme same as same-scheme. {§6.5-cross-scheme-move} Missing source → 404. {§6.5-missing-source-404}
441
+ - **MOVE never deletes.** A null body 400 (a destination is required). {§6.5-null-body-400} `/dev/null` carries no special meaning — the MOVE→/dev/null delete idiom is retired; KILL is the canonical delete. {§6.5-dev-null-not-special}
441
442
 
442
443
  Log history preserved — `log_entries` stores path tuple as text, not FK to `entries.id`.
443
444
 
@@ -730,12 +731,17 @@ registry.register("loop.run", {
730
731
 
731
732
  | Method | Params | Result | Notes |
732
733
  |------------------------|---------------------|-------------------|-------|
733
- | `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. |
734
+ | `session.create` | `name?: string`, `projectRoot?: string`, `persona?: string` | `{ id, name, runId, runName, projectRoot, persona }` | Creates new session + its first run; auto-name if unprovided. Returns the auto-created run's identity so clients skip the pending-dance ({§13.5-session-create}). Optional `projectRoot` pins the workspace (null/omitted = headless). Optional `persona` sets the session-level persona override. |
734
735
  | `session.list` | none | `{ sessions: Session[] }` | Lists all sessions. |
735
736
  | `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. {§13.5-session-attach} |
736
737
  | `session.runs` | `id?: number` | `{ runs: Run[] }` | Lists runs in a session (defaults to attached session); most-recent first. |
737
738
  | `session.set_root` | `projectRoot: string \| null` | `{ projectRoot }` | Update the workspace pointer on the attached session. Null reverts to headless. |
738
739
  | `session.set_persona` | `persona: string \| null` | `{ persona }` | Update the session-level persona. Null clears the override (falls through to PLURNK_PERSONA file). |
740
+ | `session.constrain` | `effect: "add" \| "ignore" \| "read-only"`, `glob: string` | `{ effect, glob }` | Add a workspace membership constraint (§14.3 overlay): `add` admits files git misses, `ignore` drops tracked matches, `read-only` admits for read but refuses edits. Immediate. |
741
+ | `session.unconstrain` | `effect: "add" \| "ignore" \| "read-only"`, `glob: string` | `{ effect, glob }` | Remove a membership constraint — the inverse of `session.constrain`. Immediate. |
742
+ | `session.constraints` | none | `{ constraints }` | List the attached session's membership constraints. |
743
+
744
+ **Re-binding.** `session.create` and `session.attach` may be called on a connection that already has a session attached — the connection switches in place, releasing the prior client loop (closed at 200). No reconnect needed to change session or run. {§13.5-rebind}
739
745
 
740
746
  **Auto-envelope.** Clients calling a `requiresInit: true` method without first attaching get auto-created session → run → client loop. Records persist normally; auto-created ≠ auto-deleted. Cleanup is a future `session.delete` / `session.archive` endpoint. {§13.5-auto-envelope}
741
747
 
@@ -745,6 +751,7 @@ registry.register("loop.run", {
745
751
  |-------------------|-------------------------------------|------------------------|-------|
746
752
  | `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`. {§13.5-loop-run} |
747
753
  | `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. |
754
+ | `loop.cancel` | `reason?: string` | `{ cancelled, runId, reason }` | Abort the attached run'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`. {§13.5-loop-cancel} |
748
755
  | `providers.list` | none | `{ aliases: ProviderAlias[] }` | Lists configured `PLURNK_MODEL_<alias>` entries with `{alias, provider, model, active}`. Clients use to populate model-selection UI. |
749
756
 
750
757
  **Reads**
@@ -791,6 +798,8 @@ Server-initiated events on the same WebSocket.
791
798
  | `loop/proposal` | `{ logEntryId, sessionId, runId, loopId, turnId, op, target, body, attrs, flags }` | Dispatch pauses on status=202. Carries `flags` so server-YOLO clients can suppress review UI. Client responds with `loop.resolve` (or `PLURNK_PROPOSAL_TIMEOUT_MS` fires). |
792
799
  | `session/created` | `{ id, name, projectRoot, persona }` | Any client creates a session. |
793
800
  | `stream/event` | `{ entryId, channel, state, contentLength }` | Channel content grows or state transitions. {§13.6-stream-event-on-channel-change} |
801
+ | `stream/concluded` | `{ entryId, target, subscriptionId, scheme, closeStatus, summary, wakeAction, wakeLoopId? }` | A streaming subscription closed (subprocess finished / errored / cancelled). `wakeAction` says whether the daemon opened a fresh loop to surface the conclusion to the model. {§13.6-stream-concluded} |
802
+ | `telemetry/event` | `{ loopId, event: TelemetryEvent }` | A TelemetryEvent (parse error, engine-rail strike/cycle/sudden-death, scheme/provider failure) was buffered — the same envelope the model sees on the next packet, delivered live for client surfacing. {§13.6-telemetry-event} |
794
803
 
795
804
  `stream/event` carries metadata only, never content. Clients fetch via `entry.read({target})`. **Every notification envelope carries its `sessionId`** (and `runId` where the emitter has it) so a multi-session client — one connection, many sessions — can route it ({§13.6-envelope-carries-sessionid}); the broadcast stays session-scoped too.
796
805
 
package/dist/Paths.d.ts CHANGED
@@ -2,6 +2,7 @@ export default class Paths {
2
2
  #private;
3
3
  static migrations: string;
4
4
  static instructionsSystem: string;
5
+ static grammarGbnf: string;
5
6
  static defaultPersona: string;
6
7
  static defaultRequirements: string;
7
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Paths.d.ts","sourceRoot":"","sources":["../src/Paths.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,OAAO,OAAO,KAAK;;IAItB,MAAM,CAAC,UAAU,SAA8C;IAC/D,MAAM,CAAC,kBAAkB,SAA6C;IAKtE,MAAM,CAAC,cAAc,SAAkC;IAIvD,MAAM,CAAC,mBAAmB,SAAuC;CAuBpE"}
1
+ {"version":3,"file":"Paths.d.ts","sourceRoot":"","sources":["../src/Paths.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,OAAO,OAAO,KAAK;;IAItB,MAAM,CAAC,UAAU,SAA8C;IAC/D,MAAM,CAAC,kBAAkB,SAA6C;IAKtE,MAAM,CAAC,WAAW,SAAoD;IAKtE,MAAM,CAAC,cAAc,SAAkC;IAIvD,MAAM,CAAC,mBAAmB,SAAuC;CAuBpE"}
package/dist/Paths.js CHANGED
@@ -14,6 +14,11 @@ export default class Paths {
14
14
  static #GRAMMAR_ROOT = dirname(fileURLToPath(import.meta.resolve("@plurnk/plurnk-grammar/package.json")));
15
15
  static migrations = resolve(Paths.#PACKAGE_ROOT, "migrations");
16
16
  static instructionsSystem = resolve(Paths.#GRAMMAR_ROOT, "plurnk.md");
17
+ // The GBNF artifact (the full multi-op root) for grammar-constrained
18
+ // sampling, resolved from the grammar package like the sysprompt above.
19
+ // Plumbed to the provider per generate() when PLURNK_PROVIDERS_GBNF is
20
+ // enabled; the service holds no opinion about its content or root.
21
+ static grammarGbnf = resolve(Paths.#GRAMMAR_ROOT, "dist/plurnk.gbnf");
17
22
  // packet.system.persona DEFAULT. Cascade at packet-build time is
18
23
  // loops.persona > runs.persona > sessions.persona > this file
19
24
  // RPC overrides on loop.run / session.attach / session.create populate
package/dist/Paths.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Paths.js","sourceRoot":"","sources":["../src/Paths.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,gDAAgD;AAChD,+EAA+E;AAC/E,6EAA6E;AAC7E,oCAAoC;AACpC,EAAE;AACF,8EAA8E;AAC9E,mDAAmD;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,CAAC,OAAO,OAAO,KAAK;IACtB,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9E,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC,CAAC,CAAC;IAE1G,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAC/D,MAAM,CAAC,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACtE,iEAAiE;IACjE,gEAAgE;IAChE,uEAAuE;IACvE,iEAAiE;IACjE,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC,sBAAsB,EAAE,CAAC;IACvD,uEAAuE;IACvE,uEAAuE;IACvE,0EAA0E;IAC1E,MAAM,CAAC,mBAAmB,GAAG,KAAK,CAAC,2BAA2B,EAAE,CAAC;IAEjE,yEAAyE;IACzE,kEAAkE;IAClE,mEAAmE;IACnE,oDAAoD;IACpD,MAAM,CAAC,sBAAsB;QACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5C,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACtD,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,CAAC,2BAA2B;QAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5C,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IAC3D,CAAC"}
1
+ {"version":3,"file":"Paths.js","sourceRoot":"","sources":["../src/Paths.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,gDAAgD;AAChD,+EAA+E;AAC/E,6EAA6E;AAC7E,oCAAoC;AACpC,EAAE;AACF,8EAA8E;AAC9E,mDAAmD;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,CAAC,OAAO,OAAO,KAAK;IACtB,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9E,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC,CAAC,CAAC;IAE1G,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAC/D,MAAM,CAAC,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACtE,qEAAqE;IACrE,wEAAwE;IACxE,uEAAuE;IACvE,mEAAmE;IACnE,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;IACtE,iEAAiE;IACjE,gEAAgE;IAChE,uEAAuE;IACvE,iEAAiE;IACjE,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC,sBAAsB,EAAE,CAAC;IACvD,uEAAuE;IACvE,uEAAuE;IACvE,0EAA0E;IAC1E,MAAM,CAAC,mBAAmB,GAAG,KAAK,CAAC,2BAA2B,EAAE,CAAC;IAEjE,yEAAyE;IACzE,kEAAkE;IAClE,mEAAmE;IACnE,oDAAoD;IACpD,MAAM,CAAC,sBAAsB;QACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5C,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACtD,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,CAAC,2BAA2B;QAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5C,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IAC3D,CAAC"}
@@ -48,6 +48,10 @@ export default class ChannelWrite {
48
48
  subscriptionId: number;
49
49
  status: number;
50
50
  }): Promise<void>;
51
+ static execTerminalStatus(db: Db, { sessionId, pathname }: {
52
+ sessionId: number;
53
+ pathname: string;
54
+ }): Promise<number | null>;
51
55
  static findActiveSubscription(db: Db, { runId, entryId }: {
52
56
  runId: number;
53
57
  entryId: number;
@@ -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,MAAM,EAAE,MAAM,CAAC;IACf,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,MAAM,EAAE,MAAM,CAAC;IACf,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;AAQ9D,MAAM,WAAW,qBAAqB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAU/F,MAAM,CAAC,OAAO,OAAO,YAAY;;WAehB,eAAe,CACxB,EAAE,EAAE,EAAE,EACN,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;KAAE,GACrH,OAAO,CAAC,IAAI,CAAC;WASH,eAAe,CACxB,EAAE,EAAE,EAAE,EACN,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAC;QAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;KAAE,GAC3H,OAAO,CAAC,IAAI,CAAC;WASH,gBAAgB,CACzB,EAAE,EAAE,EAAE,EACN,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACvG,OAAO,CAAC,MAAM,CAAC;WAML,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;WAIH,sBAAsB,CAC/B,EAAE,EAAE,EAAE,EACN,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GACvD,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAIpE"}
1
+ {"version":3,"file":"ChannelWrite.d.ts","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ export default class ChannelWrite {
12
12
  static #openSubStmt(db) { return db.open_subscription; }
13
13
  static #closeSubStmt(db) { return db.close_subscription; }
14
14
  static #findActiveStmt(db) { return db.find_active_subscription; }
15
+ static #execTerminalStmt(db) { return db.find_exec_close_status; }
15
16
  // The entry's target URI for stream notifications (#179). A NULL scheme is
16
17
  // a filesystem entry (the file scheme stores scheme=NULL), so it decodes to
17
18
  // file://.
@@ -49,6 +50,13 @@ export default class ChannelWrite {
49
50
  static async closeSubscription(db, { subscriptionId, status }) {
50
51
  await ChannelWrite.#closeSubStmt(db).run({ status, subscription_id: subscriptionId });
51
52
  }
53
+ // Terminal close_status of a finished exec stream, by coordinate pathname —
54
+ // the KILL-on-a-non-running-exec lookup (Exec.kill). null = no closed
55
+ // subscription for that coordinate (unknown exec).
56
+ static async execTerminalStatus(db, { sessionId, pathname }) {
57
+ const row = await ChannelWrite.#execTerminalStmt(db).get({ session_id: sessionId, pathname });
58
+ return row?.close_status ?? null;
59
+ }
52
60
  static async findActiveSubscription(db, { runId, entryId }) {
53
61
  const row = await ChannelWrite.#findActiveStmt(db).get({ run_id: runId, entry_id: entryId });
54
62
  return row ?? null;
@@ -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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"}
@@ -68,6 +68,11 @@ export default class Engine {
68
68
  tokenize?: (text: string) => number;
69
69
  });
70
70
  setExecutors(executors: ExecutorRegistry): void;
71
+ loopUsage(loopId: number): Promise<{
72
+ promptTokens: number;
73
+ completionTokens: number;
74
+ costPico: number;
75
+ }>;
71
76
  runLoop({ provider, messages, persona, requirements, sessionId, runId, loopId, maxTurns, maxStrikes, minCycles, maxCyclePeriod, origin, signal, onDispatch, }: {
72
77
  provider: Provider;
73
78
  messages: ChatMessage[];
@@ -1 +1 @@
1
- {"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/core/Engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAA4D,MAAM,wBAAwB,CAAC;AAMxH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAiB,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,EAAE,EAAc,MAAM,SAAS,CAAC;AAK9C,OAAO,KAAK,EAAmD,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAgDhG,KAAK,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEvD,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAG9E,OAAO,KAAK,EAAE,QAAQ,EAAsD,MAAM,0BAA0B,CAAC;AA4C7G,KAAK,eAAe,GAAG;IACnB,SAAS,EAAE,eAAe,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C,CAAC;AAEF,KAAK,cAAc,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAOjF,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC9D,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,gBAAgB,CAAC;IAK3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAKd,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD,MAAM,WAAW,oBAAoB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CACpB;AAuGD,MAAM,CAAC,OAAO,OAAO,MAAM;;IACvB,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAUhF,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,MAAM;IAQnE,MAAM,CAAC,WAAW,CACd,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,GACvB;QAAE,QAAQ,EAAE,KAAK,CAAA;KAAE,GAAG;QAAE,QAAQ,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;gBAmE/D,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,oBAAoB,EAAE,QAAQ,EAAE,EAAE;QACtG,EAAE,EAAE,EAAE,CAAC;QACP,OAAO,EAAE,cAAc,CAAC;QACxB,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;QACtC,aAAa,CAAC,EAAE,aAAa,CAAC;QAC9B,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;QAC5C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;KACvC;IAsBD,YAAY,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IA0CzC,OAAO,CAAC,EACV,QAAQ,EAAE,QAAQ,EAAE,OAAY,EAAE,YAAiB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAC7E,QAAa,EAAE,UAA6B,EAC5C,SAAoE,EACpE,cAAqF,EACrF,MAAgB,EAAE,MAAM,EAAE,UAAU,GACvC,EAAE;QACC,QAAQ,EAAE,QAAQ,CAAC;QACnB,QAAQ,EAAE,WAAW,EAAE,CAAC;QAIxB,OAAO,CAAC,EAAE,MAAM,CAAC;QAIjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;KAC7C,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,WAAW,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;IAqHzJ,OAAO,CAAC,EACV,QAAQ,EAAE,QAAQ,EAAE,OAAY,EAAE,YAAiB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAgB,EAAE,MAAM,EAAE,UAAU,EACnH,UAAc,EAAE,QAAa,GAChC,EAAE;QACC,QAAQ,EAAE,QAAQ,CAAC;QACnB,QAAQ,EAAE,WAAW,EAAE,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QACjD,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;QAK1C,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,CAAC;IAgkBlI,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAsKjE,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,GAAG,IAAI;IAYzE,kBAAkB,IAAI,MAAM,EAAE;IAQxB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBpD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAChD;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAC7C;IAgCD,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,IAAI;CAgZ3E"}
1
+ {"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/core/Engine.ts"],"names":[],"mappings":"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"}
@@ -4,15 +4,19 @@ import { Mimetypes, emptyRegistry } from "@plurnk/plurnk-mimetypes";
4
4
  import EntryCrud from "../schemes/_entry-crud.js";
5
5
  import EntryManifest from "../schemes/_entry-manifest.js";
6
6
  import GitMembership from "./git-membership.js";
7
+ import GitState from "./git-state.js";
7
8
  import { DEFAULT_LOOP_FLAGS } from "./scheme-types.js";
8
9
  import { LineMarkerOps, MimetypeBinary, editedSpan } from "../content/index.js";
10
+ import { readFile } from "node:fs/promises";
11
+ import Paths from "../Paths.js";
12
+ import SchemeCtxImpl from "./caps/SchemeCtxImpl.js";
9
13
  // Shared module imported by both Engine and bin/digest.ts, so wire
10
14
  // projection and digest projection are structurally one function — no
11
15
  // drift between wire and digest possible.
12
16
  import PacketWire from "./packet-wire.js";
13
17
  // SPEC §3.6: writer must be in target scheme's manifest.writableBy.
14
18
  // OPEN/FOLD/READ/FIND are not gated — they curate the log or read, never mutating an entry.
15
- const MUTATING_OPS = new Set(["EDIT", "SEND", "COPY", "MOVE", "EXEC"]);
19
+ const MUTATING_OPS = new Set(["EDIT", "SEND", "COPY", "MOVE", "EXEC", "KILL"]);
16
20
  const DEFAULT_MAX_STRIKES = 3;
17
21
  const DEFAULT_MAX_COMMANDS = 99;
18
22
  const DEFAULT_BUDGET_CEILING = 0.9;
@@ -228,6 +232,8 @@ class Engine {
228
232
  // status code but has no way to surface why the loop degraded.
229
233
  // Per-grammar 0.17.0 protocol — see SPEC §15.1.
230
234
  #telemetryEventNotify;
235
+ // Cached plurnk GBNF — read once on the first constrained generate (#189).
236
+ #gbnfCache = null;
231
237
  constructor({ db, schemes, mimetypes, streamEventNotify, wakeRunNotify, telemetryEventNotify, tokenize }) {
232
238
  this.#db = db;
233
239
  this.#schemes = schemes;
@@ -252,6 +258,28 @@ class Engine {
252
258
  setExecutors(executors) {
253
259
  this.#executors = executors;
254
260
  }
261
+ // Grammar-constrained sampling (#189): when PLURNK_PROVIDERS_GBNF is enabled
262
+ // (the only knob — default-on in .env.example), hand the provider the plurnk
263
+ // GBNF (the full shipped multi-op root, read once + cached). The provider
264
+ // attaches it iff the backend supports it and silently drops it otherwise —
265
+ // capability is providers' concern, not ours. Pure plumbing grammar→provider.
266
+ async #grammarConstraint() {
267
+ if (process.env.PLURNK_PROVIDERS_GBNF !== "1")
268
+ return undefined;
269
+ this.#gbnfCache ??= await readFile(Paths.grammarGbnf, "utf8");
270
+ return this.#gbnfCache;
271
+ }
272
+ // Per-loop usage totals (#197): SUM the loop's turns (usage is stored per
273
+ // turn, §14.2). Surfaced on loop.run + loop/terminated so clients render real
274
+ // token/cost numbers. costPico is the stored pico-dollar unit.
275
+ async loopUsage(loopId) {
276
+ const row = await this.#db.engine_loop_usage.get({ loop_id: loopId });
277
+ return {
278
+ promptTokens: row?.prompt ?? 0,
279
+ completionTokens: row?.completion ?? 0,
280
+ costPico: row?.cost_pico ?? 0,
281
+ };
282
+ }
255
283
  #pushTelemetry(sessionId, loopId, event) {
256
284
  const existing = this.#telemetryBuffer.get(loopId);
257
285
  if (existing === undefined)
@@ -450,7 +478,7 @@ class Engine {
450
478
  };
451
479
  await this.dispatch({
452
480
  statement: promptStmt, sessionId, runId, loopId, turnId,
453
- sequence: nextActionIndex, origin: "system",
481
+ sequence: nextActionIndex, origin: "system", onDispatch,
454
482
  });
455
483
  nextActionIndex++;
456
484
  }
@@ -487,19 +515,23 @@ class Engine {
487
515
  // reconciled) as system EDIT rows, before the packet composes; advance
488
516
  // the action index past them so model ops continue after.
489
517
  nextActionIndex += await this.#materializeEnvironmentDeltas({ sessionId, runId, loopId, turnId, fromSequence: nextActionIndex });
518
+ // SPEC §15.1 — git working-tree state for the telemetry section, read once
519
+ // (a service-side `git status` shell-out) and threaded into the budget
520
+ // rebuild too so it isn't re-shelled on overflow.
521
+ const gitStatus = await GitState.status(this.#db, sessionId, this.#loopAborts.get(loopId)?.signal);
490
522
  // Build the spec'd packet (Packet.json) request half. #buildLog
491
523
  // queries log_entries scoped to the run — the prompt entry just
492
524
  // written (if turn 1) is part of that query result.
493
525
  let requestPacket = await this.#buildRequestPacket({
494
526
  initialMessages: messages, persona, requirements, runId, loopId,
495
- currentTurnSeq: seq, provider,
527
+ currentTurnSeq: seq, provider, gitStatus,
496
528
  });
497
529
  // SPEC §14.4 — budget grinder, pre-LLM: reclaim window on actual overflow.
498
530
  const enforced = await this.#enforceBudget({
499
531
  packet: requestPacket, provider, runId, loopId, turnId, sessionId, turnNumber,
500
532
  rebuild: (telemetryErrors) => this.#buildRequestPacket({
501
533
  initialMessages: messages, persona, requirements, runId, loopId,
502
- currentTurnSeq: seq, provider, telemetryErrors,
534
+ currentTurnSeq: seq, provider, telemetryErrors, gitStatus,
503
535
  }),
504
536
  });
505
537
  requestPacket = enforced.packet;
@@ -515,7 +547,13 @@ class Engine {
515
547
  return { turnId, status: 413, statuses: [], fingerprint: "", budgetStruck: enforced.struck, budgetHardStop: true };
516
548
  }
517
549
  const modelMessages = this.#packetToWireMessages(requestPacket);
518
- const response = await provider.generate({ messages: modelMessages, signal });
550
+ // maxTokens = remaining context window (loop policy, plurnk-providers#10).
551
+ // The 0.28.0 EOS-forcing root terminates the turn at the status SEND, but a
552
+ // grammar can't bound degeneration *inside* a statement body — this caps the
553
+ // decode at the free window so a runaway can't reach the context wall.
554
+ const genCeiling = _a.computeCeiling(provider.contextSize, this.#budgetCeiling);
555
+ const maxTokens = genCeiling === null ? undefined : Math.max(1, genCeiling - requestPacket.system.tokens - requestPacket.user.tokens);
556
+ const response = await provider.generate({ messages: modelMessages, runId: String(runId), signal, grammar: await this.#grammarConstraint(), maxTokens });
519
557
  // Engine splits wire-level response: emission (content, reasoning,
520
558
  // parsed ops) → packet.assistant per Packet.json §assistant;
521
559
  // call-metadata (usage, finishReason, model) → Turn columns per
@@ -676,7 +714,7 @@ class Engine {
676
714
  // and §user) BEFORE the provider call. The same packet object is then
677
715
  // completed with assistant + assistantRaw after the model responds, so
678
716
  // the stored packet and the wire payload share one source of truth.
679
- async #buildRequestPacket({ initialMessages, persona: defaultPersona, requirements, runId, loopId, currentTurnSeq, provider, telemetryErrors: presetTelemetry, }) {
717
+ async #buildRequestPacket({ initialMessages, persona: defaultPersona, requirements, runId, loopId, currentTurnSeq, provider, gitStatus, telemetryErrors: presetTelemetry, }) {
680
718
  const byRole = (role) => initialMessages.filter((m) => m.role === role).map((m) => m.content).join("\n\n");
681
719
  const system_definition = byRole("system");
682
720
  // user.prompt sources from the loop's most recent prompt entry first
@@ -711,7 +749,7 @@ class Engine {
711
749
  const ceiling = _a.computeCeiling(provider.contextSize, this.#budgetCeiling);
712
750
  const scratch = {
713
751
  system: { system_definition, persona, log },
714
- user: { prompt, telemetry: { budget: "", errors: telemetryErrors }, system_requirements: requirements },
752
+ user: { prompt, telemetry: { budget: "", errors: telemetryErrors, git: gitStatus }, system_requirements: requirements },
715
753
  };
716
754
  const sections = PacketWire.measureBudgetSections(scratch, countTokens);
717
755
  scratch.user.telemetry.budget = this.#renderBudget(sections, ceiling);
@@ -725,7 +763,7 @@ class Engine {
725
763
  .replace(TOKEN_PERCENT_PLACEHOLDER, String(percent))
726
764
  .replace(TOKENS_FREE_PLACEHOLDER, String(tokensFree));
727
765
  const system = { tokens: 0, system_definition, persona, log };
728
- const user = { tokens: 0, prompt, telemetry: { budget, errors: telemetryErrors }, system_requirements: requirements };
766
+ const user = { tokens: 0, prompt, telemetry: { budget, errors: telemetryErrors, git: gitStatus }, system_requirements: requirements };
729
767
  system.tokens = countTokens(PacketWire.renderSystemContent(system));
730
768
  user.tokens = countTokens(PacketWire.renderUserContent(user));
731
769
  return { system, user };
@@ -955,6 +993,12 @@ class Engine {
955
993
  else if (statement.op === "MOVE") {
956
994
  result = await this.#handleMove(statement, schemeCtx);
957
995
  }
996
+ else if (statement.op === "KILL") {
997
+ result = await this.#handleKill(statement, schemeCtx);
998
+ }
999
+ else if (statement.op === "PLAN") {
1000
+ result = this.#handlePlan(statement);
1001
+ }
958
1002
  else if (statement.op === "EXEC") {
959
1003
  // EXEC's target slot is `cwd`, not a scheme address.
960
1004
  // Per plurnk.md the op routes unconditionally to the
@@ -1022,6 +1066,16 @@ class Engine {
1022
1066
  // with the failure outcome — engine treats it like a client
1023
1067
  // rejection.
1024
1068
  const effective = await this.#runApplyResolution(statement, result, resolution, { sessionId, runId, loopId, turnId });
1069
+ // MOVE into a proposed dest: the deferred source-delete fires ONLY now,
1070
+ // after the dest write landed (accept). On reject the source survives.
1071
+ if (effective.decision === "accept") {
1072
+ const moveSource = result.attrs?.moveSource;
1073
+ if (moveSource !== undefined) {
1074
+ const srcHandler = this.#schemes.get(moveSource.scheme);
1075
+ if (srcHandler !== undefined && typeof srcHandler.deleteEntry === "function")
1076
+ await srcHandler.deleteEntry(moveSource.pathname, schemeCtx);
1077
+ }
1078
+ }
1025
1079
  const post = await this.#applyResolution(logEntryId, effective);
1026
1080
  return post;
1027
1081
  }
@@ -1034,7 +1088,11 @@ class Engine {
1034
1088
  // EXEC routes to the exec scheme regardless of target (cwd, not
1035
1089
  // a scheme address). All other ops resolve their handler from
1036
1090
  // statement.target's scheme.
1037
- const schemeName = statement.op === "EXEC" ? "exec" : this.#schemeNameOf(statement.target);
1091
+ // COPY/MOVE write the DEST (statement.body), not the source (target): the
1092
+ // accept must reach the dest scheme's applyResolution (File writes disk).
1093
+ const schemeName = statement.op === "EXEC" ? "exec"
1094
+ : (statement.op === "COPY" || statement.op === "MOVE") ? this.#schemeNameOf(statement.body)
1095
+ : this.#schemeNameOf(statement.target);
1038
1096
  if (schemeName === null)
1039
1097
  return resolution;
1040
1098
  const handler = this.#schemes.get(schemeName);
@@ -1316,29 +1374,78 @@ class Engine {
1316
1374
  const dstPath = statement.body;
1317
1375
  if (srcPath === null)
1318
1376
  return { status: 400, error: "MOVE requires source path" };
1377
+ // MOVE is relocation only — deletion is KILL's job (§6.5). The /dev/null
1378
+ // and null-body delete-by-MOVE back-compat is retired: no silent debt.
1379
+ if (dstPath === null)
1380
+ return { status: 400, error: "MOVE requires a destination; use KILL to delete" };
1319
1381
  const srcSchemeName = this.#schemeNameOf(srcPath);
1320
1382
  if (srcSchemeName === null)
1321
1383
  return { status: 400, error: "MOVE source must be a URL path with a scheme" };
1322
1384
  const srcHandler = this.#schemes.get(srcSchemeName);
1323
1385
  if (srcHandler === undefined || typeof srcHandler.deleteEntry !== "function")
1324
1386
  return { status: 501 };
1325
- // MOVE to /dev/null (the grammar's idiomatic delete) or a null-body
1326
- // MOVE deletes the source entry. SPEC §6.5.
1327
- if (dstPath === null || pathnameFromPath(dstPath) === "/dev/null") {
1328
- const srcPathname = pathnameFromPath(srcPath);
1329
- const delResult = await srcHandler.deleteEntry(srcPathname, ctx);
1330
- return { status: delResult.status };
1331
- }
1332
- // Relocation: COPY then DELETE source
1387
+ // Relocation: COPY then DELETE source.
1333
1388
  const copyResult = await this.#copyOrchestration({ statement, srcPath, dstPath, ctx });
1334
1389
  if (copyResult.status >= 400)
1335
1390
  return copyResult;
1336
1391
  const srcPathname = pathnameFromPath(srcPath);
1392
+ // If the dest write is a pending proposal (file dest → §14.3 review), the
1393
+ // source-delete MUST wait until the dest actually lands — a rejected
1394
+ // proposal would otherwise lose the source. Thread it into the resolution:
1395
+ // dispatch deletes the source AFTER the dest applies on accept.
1396
+ if (copyResult.status === 202) {
1397
+ return { ...copyResult, attrs: { ...copyResult.attrs, moveSource: { scheme: srcSchemeName, pathname: srcPathname } } };
1398
+ }
1337
1399
  const delResult = await srcHandler.deleteEntry(srcPathname, ctx);
1338
1400
  if (delResult.status >= 400)
1339
1401
  return { status: delResult.status };
1340
1402
  return copyResult;
1341
1403
  }
1404
+ // KILL — scheme-polymorphic destroy (plurnk-grammar#203 / 0.28.0). Entry-KILL
1405
+ // permanently deletes the entry: the canonical delete now, MOVE→/dev/null
1406
+ // retired from the model's vocabulary. Process-KILL (exec://) aborts the
1407
+ // running spawn's controller (the same teardown loop.cancel rides), addressed
1408
+ // by coordinate pathname (#203). The KILL body is an opaque
1409
+ // annotation with no runtime meaning; it survives into the log row's tx for
1410
+ // free via the statement serialization. Status: 200 killed · 404 unknown ·
1411
+ // 405 log:// (append-only) · 403 writableBy (the #checkWritable gate, KILL ∈
1412
+ // MUTATING_OPS) · 200/410/304/404 exec (killed / killed-earlier / exited / unknown) · 501 no-kill/delete scheme.
1413
+ async #handleKill(statement, ctx) {
1414
+ if (statement.op !== "KILL")
1415
+ throw new Error("unreachable");
1416
+ const path = statement.target;
1417
+ if (path === null)
1418
+ return { status: 400, error: "KILL requires a target path" };
1419
+ const schemeName = this.#schemeNameOf(path);
1420
+ if (schemeName === null)
1421
+ return { status: 400, error: "KILL target must be a URL path with a scheme" };
1422
+ if (schemeName === "log")
1423
+ return { status: 405, error: "log:// is append-only; KILL must bounce" };
1424
+ if (schemeName === "exec") {
1425
+ const execHandler = this.#schemes.get("exec");
1426
+ if (execHandler === undefined || typeof execHandler.kill !== "function")
1427
+ return { status: 501 };
1428
+ return await execHandler.kill(pathnameFromPath(path), ctx);
1429
+ }
1430
+ const handler = this.#schemes.get(schemeName);
1431
+ if (handler === undefined || typeof handler.deleteEntry !== "function")
1432
+ return { status: 501 };
1433
+ const delResult = await handler.deleteEntry(pathnameFromPath(path), ctx);
1434
+ return { status: delResult.status };
1435
+ }
1436
+ // PLAN — undocumented reasoning op (plurnk-grammar 0.30.0, the 11th op). A pure
1437
+ // no-op: the body is the model's in-content reasoning, which lands in the log
1438
+ // row's tx for free via statement serialization, no runtime effect (PLAN ∉
1439
+ // MUTATING_OPS). NOT taught in plurnk.md by design — reserved for a future model
1440
+ // that must reason in the content field (no separate reasoning channel). gemma
1441
+ // reasons on its own channel via the relaxed root, is never shown PLAN, and never
1442
+ // emits it; this handler exists only so the op resolves cleanly if we ever
1443
+ // deliberately reach for it (which would also require a plurnk.md override).
1444
+ #handlePlan(statement) {
1445
+ if (statement.op !== "PLAN")
1446
+ throw new Error("unreachable");
1447
+ return { status: 200 };
1448
+ }
1342
1449
  async #copyOrchestration({ statement, srcPath, dstPath, ctx }) {
1343
1450
  const srcSchemeName = this.#schemeNameOf(srcPath);
1344
1451
  const dstSchemeName = this.#schemeNameOf(dstPath);
@@ -1410,6 +1517,10 @@ class Engine {
1410
1517
  return { status: 409, error: `COPY/MOVE destination exists: ${dstSchemeName}://${dstPathname}` };
1411
1518
  }
1412
1519
  const writeResult = await dstHandler.writeEntry(dstPathname, { channels, tags }, ctx);
1520
+ // A file dest returns 202 (disk write → §14.3 review): propagate the
1521
+ // proposal so dispatch runs the gate + routes applyResolution to the dest.
1522
+ if (writeResult.status === 202)
1523
+ return { status: 202, attrs: writeResult.attrs, body: writeResult.body };
1413
1524
  return { status: writeResult.status, entryId: writeResult.entryId, created: writeResult.created };
1414
1525
  }
1415
1526
  async #handleSendBroadcast(statement, loopId) {
@@ -1433,6 +1544,13 @@ class Engine {
1433
1544
  const method = handler[methodName];
1434
1545
  if (typeof method !== "function")
1435
1546
  return { status: 501 };
1547
+ // External @plurnk/plurnk-schemes-* siblings receive the DB-free SchemeCtx
1548
+ // (caps), never the raw PlurnkSchemeContext (schemes SPEC §5). The dynamic
1549
+ // dispatch is typed for in-tree schemes; the cast bridges the ctx shapes —
1550
+ // the sibling reads caps, the in-tree handler reads db.
1551
+ if (this.#schemes.isExternal(schemeName)) {
1552
+ return method.call(handler, statement, new SchemeCtxImpl(ctx, schemeName));
1553
+ }
1436
1554
  return method.call(handler, statement, ctx);
1437
1555
  }
1438
1556
  // Bare paths default to the file scheme per plurnk.md (grammar sysprompt):
@@ -1441,8 +1559,9 @@ class Engine {
1441
1559
  #schemeNameOf(path) {
1442
1560
  if (path === null)
1443
1561
  return null;
1562
+ // http + https are one scheme — the http sibling owns both prefixes (#195).
1444
1563
  if (path.kind === "url")
1445
- return path.scheme;
1564
+ return path.scheme === "https" ? "http" : path.scheme;
1446
1565
  return "file"; // local (bare) → file
1447
1566
  }
1448
1567
  async #writeLog({ statement, result, runId, loopId, turnId, sequence, origin, }) {