llm-relay 0.85.0 → 0.86.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 (185) hide show
  1. package/README.md +39 -62
  2. package/THIRD_PARTY_NOTICES.md +5 -4
  3. package/dist/accounting-state.js.map +1 -1
  4. package/dist/accounting-store-schema.js.map +1 -1
  5. package/dist/accounting-store.js.map +1 -1
  6. package/dist/accounting.js.map +1 -1
  7. package/dist/authEnv.js.map +1 -1
  8. package/dist/availability-snapshot.js.map +1 -1
  9. package/dist/availability.js.map +1 -1
  10. package/dist/backend.js.map +1 -1
  11. package/dist/benchmarks.js.map +1 -1
  12. package/dist/breaker-persistence.js.map +1 -1
  13. package/dist/candidate-runner.d.ts +6 -12
  14. package/dist/candidate-runner.js +16 -4
  15. package/dist/candidate-runner.js.map +1 -1
  16. package/dist/candidates.js.map +1 -1
  17. package/dist/catalog.js.map +1 -1
  18. package/dist/circuit-breaker.d.ts +14 -17
  19. package/dist/circuit-breaker.js +46 -6
  20. package/dist/circuit-breaker.js.map +1 -1
  21. package/dist/claude-hook.js.map +1 -1
  22. package/dist/cli.d.ts +4 -1
  23. package/dist/cli.js +127 -12
  24. package/dist/cli.js.map +1 -1
  25. package/dist/config/routing-parser.d.ts +3 -13
  26. package/dist/config/routing-parser.js +16 -10
  27. package/dist/config/routing-parser.js.map +1 -1
  28. package/dist/config-reload.d.ts +34 -0
  29. package/dist/config-reload.js +180 -0
  30. package/dist/config-reload.js.map +1 -0
  31. package/dist/config-types.d.ts +26 -65
  32. package/dist/config-types.js.map +1 -1
  33. package/dist/config.d.ts +1 -1
  34. package/dist/config.js +1 -1
  35. package/dist/config.js.map +1 -1
  36. package/dist/configured-lane-execution-launcher.d.ts +36 -0
  37. package/dist/configured-lane-execution-launcher.js +133 -0
  38. package/dist/configured-lane-execution-launcher.js.map +1 -0
  39. package/dist/context-limits.js.map +1 -1
  40. package/dist/control-authorization.js.map +1 -1
  41. package/dist/cooldown-clear.js.map +1 -1
  42. package/dist/credential-fleet.js.map +1 -1
  43. package/dist/credential-select.js.map +1 -1
  44. package/dist/daemon-dispatch-view.d.ts +21 -0
  45. package/dist/daemon-dispatch-view.js +16 -0
  46. package/dist/daemon-dispatch-view.js.map +1 -0
  47. package/dist/dashboard/.vite/dashboard-bundle-graph.json +2 -1
  48. package/dist/dashboard/.vite/manifest.json +2 -2
  49. package/dist/dashboard/assets/index-BoSmrF3q.js +123 -0
  50. package/dist/dashboard/assets/index-DKPeE07T.css +1 -0
  51. package/dist/dashboard/index.html +2 -2
  52. package/dist/dashboard-auth.js.map +1 -1
  53. package/dist/dashboard-contract.d.ts +2 -2
  54. package/dist/dashboard-routes.js.map +1 -1
  55. package/dist/dashboard-snapshot.js.map +1 -1
  56. package/dist/dashboard-static.js.map +1 -1
  57. package/dist/delegate-gate/cli.js.map +1 -1
  58. package/dist/dispatch-exhaustion-persistence.d.ts +1 -0
  59. package/dist/dispatch-exhaustion-persistence.js +7 -2
  60. package/dist/dispatch-exhaustion-persistence.js.map +1 -1
  61. package/dist/dispatch-lane-stats.d.ts +10 -17
  62. package/dist/dispatch-lane-stats.js +0 -5
  63. package/dist/dispatch-lane-stats.js.map +1 -1
  64. package/dist/dispatch.d.ts +32 -78
  65. package/dist/dispatch.js +51 -54
  66. package/dist/dispatch.js.map +1 -1
  67. package/dist/documents.js.map +1 -1
  68. package/dist/dotenv.js.map +1 -1
  69. package/dist/dynamic-pools.js.map +1 -1
  70. package/dist/executable-lookup.d.ts +2 -0
  71. package/dist/executable-lookup.js +7 -4
  72. package/dist/executable-lookup.js.map +1 -1
  73. package/dist/host-routing.js.map +1 -1
  74. package/dist/installed-hosts.js.map +1 -1
  75. package/dist/json-shape.js.map +1 -1
  76. package/dist/key-checker.js.map +1 -1
  77. package/dist/key-import.js.map +1 -1
  78. package/dist/keys-cli.js.map +1 -1
  79. package/dist/keystore.js.map +1 -1
  80. package/dist/lane-activity.d.ts +8 -0
  81. package/dist/lane-activity.js +27 -2
  82. package/dist/lane-activity.js.map +1 -1
  83. package/dist/lane-affinity.d.ts +4 -4
  84. package/dist/lane-affinity.js.map +1 -1
  85. package/dist/lane-cadence.js.map +1 -1
  86. package/dist/lane-execution-broker.d.ts +124 -0
  87. package/dist/lane-execution-broker.js +479 -0
  88. package/dist/lane-execution-broker.js.map +1 -0
  89. package/dist/lane-launch-env.d.ts +14 -0
  90. package/dist/lane-launch-env.js +52 -0
  91. package/dist/lane-launch-env.js.map +1 -0
  92. package/dist/lane-manifest.js.map +1 -1
  93. package/dist/lane-probe.js.map +1 -1
  94. package/dist/lane-quota-probe.js.map +1 -1
  95. package/dist/log.js.map +1 -1
  96. package/dist/mcp/job-archive.d.ts +12 -9
  97. package/dist/mcp/job-archive.js +44 -37
  98. package/dist/mcp/job-archive.js.map +1 -1
  99. package/dist/mcp/job-journal.d.ts +42 -2
  100. package/dist/mcp/job-journal.js +212 -32
  101. package/dist/mcp/job-journal.js.map +1 -1
  102. package/dist/mcp/lane-execution-client.d.ts +26 -0
  103. package/dist/mcp/lane-execution-client.js +117 -0
  104. package/dist/mcp/lane-execution-client.js.map +1 -0
  105. package/dist/mcp/lane-runner.d.ts +140 -25
  106. package/dist/mcp/lane-runner.js +361 -49
  107. package/dist/mcp/lane-runner.js.map +1 -1
  108. package/dist/mcp/persistence-lock.d.ts +13 -0
  109. package/dist/mcp/persistence-lock.js +4 -0
  110. package/dist/mcp/persistence-lock.js.map +1 -0
  111. package/dist/mcp/process-cpu.d.ts +18 -0
  112. package/dist/mcp/process-cpu.js +133 -0
  113. package/dist/mcp/process-cpu.js.map +1 -0
  114. package/dist/mcp/readonly-boundary.js.map +1 -1
  115. package/dist/mcp/server.d.ts +97 -3
  116. package/dist/mcp/server.js +547 -61
  117. package/dist/mcp/server.js.map +1 -1
  118. package/dist/mcp/tree-delta.js.map +1 -1
  119. package/dist/mcp/windows-npm-shim.d.ts +32 -0
  120. package/dist/mcp/windows-npm-shim.js +92 -0
  121. package/dist/mcp/windows-npm-shim.js.map +1 -0
  122. package/dist/metadata.js.map +1 -1
  123. package/dist/openai-dialect.js.map +1 -1
  124. package/dist/openai-request.js.map +1 -1
  125. package/dist/os-keyring.js.map +1 -1
  126. package/dist/ping/cadence.js.map +1 -1
  127. package/dist/ping/metrics.js.map +1 -1
  128. package/dist/ping/ping.js.map +1 -1
  129. package/dist/ping/probe-cache.js.map +1 -1
  130. package/dist/ping/quota.js.map +1 -1
  131. package/dist/ping/runtime-telemetry.js.map +1 -1
  132. package/dist/pool-health.js.map +1 -1
  133. package/dist/process-safety-net.js +18 -10
  134. package/dist/process-safety-net.js.map +1 -1
  135. package/dist/quota-observation.js.map +1 -1
  136. package/dist/rate-limits.js.map +1 -1
  137. package/dist/refusal-interpretation.js.map +1 -1
  138. package/dist/registry.js.map +1 -1
  139. package/dist/request-log.js.map +1 -1
  140. package/dist/reshaper.js.map +1 -1
  141. package/dist/resolved-attempt.js.map +1 -1
  142. package/dist/responses-request.js.map +1 -1
  143. package/dist/routes/admin.d.ts +8 -0
  144. package/dist/routes/admin.js +54 -8
  145. package/dist/routes/admin.js.map +1 -1
  146. package/dist/routes/messages.js +10 -10
  147. package/dist/routes/messages.js.map +1 -1
  148. package/dist/routes/openai-front.js +4 -4
  149. package/dist/routes/openai-front.js.map +1 -1
  150. package/dist/secret-file-acl.js.map +1 -1
  151. package/dist/self-update.js.map +1 -1
  152. package/dist/server.d.ts +19 -0
  153. package/dist/server.js +70 -4
  154. package/dist/server.js.map +1 -1
  155. package/dist/session-pin.js.map +1 -1
  156. package/dist/setup-claude.d.ts +6 -1
  157. package/dist/setup-claude.js +3 -3
  158. package/dist/setup-claude.js.map +1 -1
  159. package/dist/spend-headroom.js.map +1 -1
  160. package/dist/sse.js.map +1 -1
  161. package/dist/state-paths.js.map +1 -1
  162. package/dist/storage/file-lock.d.ts +26 -0
  163. package/dist/storage/file-lock.js +127 -0
  164. package/dist/storage/file-lock.js.map +1 -0
  165. package/dist/storage/json-store.d.ts +33 -0
  166. package/dist/storage/json-store.js +68 -1
  167. package/dist/storage/json-store.js.map +1 -1
  168. package/dist/stream-commit.js.map +1 -1
  169. package/dist/stream-pipeline.js.map +1 -1
  170. package/dist/target-facts.js.map +1 -1
  171. package/dist/telemetry.d.ts +3 -1
  172. package/dist/telemetry.js +2 -1
  173. package/dist/telemetry.js.map +1 -1
  174. package/dist/tier-data.js.map +1 -1
  175. package/dist/tool-dialects.js.map +1 -1
  176. package/dist/usage-observer.js.map +1 -1
  177. package/dist/winenv.js.map +1 -1
  178. package/docs/README.md +4 -2
  179. package/docs/dashboard-bundle-inventory.json +5 -4
  180. package/package.json +15 -14
  181. package/scripts/install-skill.mjs +4 -2
  182. package/skills/llm-relay/SKILL.md +10 -8
  183. package/skills/llm-relay/references/dispatch-lanes.md +18 -1
  184. package/dist/dashboard/assets/index-C-I6hPeY.js +0 -403
  185. package/dist/dashboard/assets/index-CrSNlLMD.css +0 -1
@@ -1,5 +1,8 @@
1
- import { type JobJournal } from "./job-journal.js";
1
+ import { type WindowsNpmShimDeps, type WindowsNpmShimResolution } from "./windows-npm-shim.js";
2
+ import { type JobJournal, type JournalRow, type JournalStartingTree } from "./job-journal.js";
3
+ import type { LaneExecutionSnapshot } from "../lane-execution-broker.js";
2
4
  import { type JobArchive } from "./job-archive.js";
5
+ import type { TreeSnapshot } from "./tree-delta.js";
3
6
  import type { DispatchLaneStatus } from "../dispatch-lane-stats.js";
4
7
  /** Depth marker written into every child's environment, read back to bound recursion. */
5
8
  export declare const DEPTH_ENV = "LLM_RELAY_DISPATCH_DEPTH";
@@ -126,6 +129,33 @@ export declare function classifyLaneAttempt(run: LaneRunResult, opts?: {
126
129
  abandoned?: boolean | undefined;
127
130
  semanticFailure?: string | undefined;
128
131
  }): DispatchLaneStatus;
132
+ export type LaneActivityState = "starting" | "active" | "quiet" | "advancing" | "unmonitored";
133
+ export type LaneWalkVerdict = "keep-running" | "no-idle-stop";
134
+ /**
135
+ * The walk's OWN liveness decision for the attempt running now.
136
+ *
137
+ * This is a published snapshot, not a second activity probe. `mcp/server.ts` computes it while
138
+ * making the same keep/stop decision the walk already has to make, then `dispatch_status` merely
139
+ * renders it. A status read must never call the relay-traffic, process-CPU or working-tree readers:
140
+ * those readers carry baselines/state and consuming them from a poll could change routing.
141
+ */
142
+ export interface LaneLiveness {
143
+ activity: LaneActivityState;
144
+ verdict: LaneWalkVerdict;
145
+ /** When the walk last evaluated/published this snapshot. */
146
+ checkedAt: number;
147
+ /**
148
+ * Timestamp the idle timer is anchored to. Starts at attempt launch so a new lane gets a full
149
+ * idle window even before it emits observable activity; moves forward when real activity arrives.
150
+ */
151
+ idleBaselineAt: number;
152
+ /** Newest REAL activity timestamp the walk accepted for this attempt, or null before any. */
153
+ lastActivityAt: number | null;
154
+ /** What established the current idle baseline: attempt-start or a first-party activity signal. */
155
+ source: string;
156
+ /** Idle cutoff applied to this attempt; null means the walk will not idle-stop it. */
157
+ idleMs: number | null;
158
+ }
129
159
  export interface LaneJob {
130
160
  id: string;
131
161
  status: JobStatus;
@@ -172,9 +202,10 @@ export interface LaneJob {
172
202
  forcedLane?: boolean;
173
203
  /**
174
204
  * How long the lane now running usually takes to ANSWER in this dispatch's mode, from that
175
- * lane's own completed runs — rendered on every poll so a caller can tell a slow lane from a
176
- * stuck one. 23 of the 182 unanswered dispatches in the 2026-09-10 transcript sweep ended with
177
- * the caller simply no longer polling. Absent when the lane has no completed run on record.
205
+ * lane's own completed runs. Diagnostic only: it gives duration context, but the caller follows
206
+ * `liveness.verdict` rather than deciding "stuck" from history. 23 of the 182 unanswered
207
+ * dispatches in the 2026-09-10 transcript sweep ended with the caller simply no longer polling.
208
+ * Absent when the lane has no completed run on record.
178
209
  */
179
210
  expected?: {
180
211
  medianMs: number | null;
@@ -194,6 +225,11 @@ export interface LaneJob {
194
225
  relay?: RelayAnnouncements;
195
226
  /** Set when the job's dispatch view came from a fallback rather than the live daemon. */
196
227
  dispatchSource?: "daemon" | "fallback";
228
+ /**
229
+ * Who owns the currently-running agent process tree. Absent preserves the pre-D1/local shape for
230
+ * embeds and answer-mode jobs. `local-fallback` is explicit because it does NOT survive MCP exit.
231
+ */
232
+ executionOwner?: "relay-daemon" | "local-fallback";
197
233
  /**
198
234
  * What this dispatcher started for this job, and what became of it — written once, when the job
199
235
  * reaches a terminal state. See `LaneProcessReport`.
@@ -234,14 +270,10 @@ export interface LaneJob {
234
270
  */
235
271
  treeDelta?: string;
236
272
  /**
237
- * The newest activity the walk saw for the lane now running (relay traffic, output, a file
238
- * change), with its source. Replaced per lane; the walk stops a lane when this is older than
239
- * `routing.dispatchWalk.idleMs`.
273
+ * The walk's authoritative liveness snapshot for the lane now running. Replaced per lane and
274
+ * removed when the job becomes terminal; terminal attempt records already say how the lane ended.
240
275
  */
241
- lastActive?: {
242
- at: number;
243
- source: string;
244
- };
276
+ liveness?: LaneLiveness;
245
277
  }
246
278
  /**
247
279
  * Output progress of the attempt now running. Byte counts and timestamps only — never the bytes.
@@ -250,8 +282,8 @@ export interface LaneJob {
250
282
  * `relay` rung takes in agent mode, i.e. the free pool itself — buffers its whole answer until
251
283
  * exit (module header), so "zero bytes after N seconds" is the ordinary shape of a healthy run on
252
284
  * the most-used lane. A threshold that killed on it would manufacture the false failure the backlog
253
- * item names as worse than a slow honest status. The figure lets the CALLER decide, which is the
254
- * property's second branch.
285
+ * item names as worse than a slow honest status. This figure is diagnostic only; the caller follows
286
+ * the walk's published liveness verdict instead of interpreting silence.
255
287
  */
256
288
  export interface LaneActivity {
257
289
  /** When the running attempt was spawned. */
@@ -411,7 +443,11 @@ type LaneExecError = Error & {
411
443
  killed?: boolean | undefined;
412
444
  code?: unknown;
413
445
  };
414
- /** Terminate a full process tree (on Windows via taskkill /T /F, on POSIX via process group / signal). */
446
+ /**
447
+ * Terminate a full process tree (Windows: taskkill /T /F; POSIX: the process group created by
448
+ * `createLaneSpawner`). The positive-pid fallback is defence for an injected/legacy child that was
449
+ * not started as a group leader; the real POSIX spawner always owns group `pid`.
450
+ */
415
451
  export declare function terminateProcessTree(pid: number, platform?: NodeJS.Platform): void;
416
452
  /** A readable the spawner can watch for progress; the `data` event is all it subscribes to. */
417
453
  export interface LaneOutputStream {
@@ -432,6 +468,18 @@ export interface LaneChildProcess {
432
468
  stderr?: LaneOutputStream | null | undefined;
433
469
  kill: () => boolean;
434
470
  }
471
+ /** Spawn options for the POSIX process-group path. */
472
+ export interface LaneSpawnProcessOptions {
473
+ cwd: string;
474
+ env: NodeJS.ProcessEnv;
475
+ windowsHide: true;
476
+ detached: true;
477
+ }
478
+ /** Child events the POSIX buffered spawn path consumes. */
479
+ export interface LaneSpawnedProcess extends LaneChildProcess {
480
+ on(event: "error", listener: (err: Error) => void): unknown;
481
+ on(event: "close", listener: (code: number | null, signal: NodeJS.Signals | null) => void): unknown;
482
+ }
435
483
  /** Spawn options common to the direct and Windows shell-fallback paths. */
436
484
  export interface LaneExecOptions {
437
485
  encoding: "utf8";
@@ -447,7 +495,11 @@ export interface LaneProcessApi {
447
495
  platform: NodeJS.Platform;
448
496
  execFile: (command: string, args: string[], opts: LaneExecOptions, callback: LaneExecCallback) => LaneChildProcess;
449
497
  exec: (command: string, opts: LaneExecOptions, callback: LaneExecCallback) => LaneChildProcess;
498
+ /** POSIX-only real spawn seam: `detached` is supported by spawn, not execFile. */
499
+ spawn?: (command: string, args: string[], opts: LaneSpawnProcessOptions) => LaneSpawnedProcess;
450
500
  }
501
+ /** Injectable npm-shim resolver so unit tests never inspect the host filesystem. */
502
+ export type WindowsNpmShimResolver = (command: string, args: readonly string[], deps: WindowsNpmShimDeps) => WindowsNpmShimResolution;
451
503
  /**
452
504
  * The real spawner.
453
505
  *
@@ -459,7 +511,7 @@ export interface LaneProcessApi {
459
511
  * `winenv.ts`, `os-keyring.ts` and `lane-quota-probe.ts`: a test run must never spend real quota
460
512
  * or touch the operator's live agent sessions.
461
513
  */
462
- export declare function createLaneSpawner(processApi: LaneProcessApi, hostEnv?: NodeJS.ProcessEnv): LaneSpawner;
514
+ export declare function createLaneSpawner(processApi: LaneProcessApi, hostEnv?: NodeJS.ProcessEnv, resolveNpmShim?: WindowsNpmShimResolver): LaneSpawner;
463
515
  export declare const defaultLaneSpawner: LaneSpawner;
464
516
  /**
465
517
  * The answer-mode HTTP seam — a direct POST to the running relay's own `/v1/messages`,
@@ -499,8 +551,19 @@ export interface RecentJob {
499
551
  elsewhere: boolean;
500
552
  label?: string;
501
553
  }
502
- /** Raise the counter to at least `seq`; never lowers it. */
503
- export declare function seedJobCounter(seq: number): void;
554
+ /**
555
+ * Build one process-local job-id allocator.
556
+ *
557
+ * The old allocator read a shared max sequence and then incremented a process-local counter. Two
558
+ * MCP processes could both read N before either wrote N+1, so both handed out the same handle.
559
+ *
560
+ * New ids keep the established `job-<digits>` wire shape but replace the shared sequence with a
561
+ * 128-bit random PROCESS instance plus a local monotonic suffix. Independent processes need no
562
+ * coordination. The leading 9 plus fixed-width 39-digit instance guarantees every new id is
563
+ * outside JavaScript's safe-integer range, so `jobSeqOf` can continue recognizing only legacy
564
+ * sequential ids in old archive files.
565
+ */
566
+ export declare function createJobIdFactory(entropy?: Uint8Array): () => string;
504
567
  /**
505
568
  * The job store.
506
569
  *
@@ -526,7 +589,14 @@ export declare class LaneJobStore {
526
589
  isAlive: (pid: number) => boolean;
527
590
  private readonly journal;
528
591
  private readonly archive;
529
- constructor(journal?: JobJournal, archive?: JobArchive);
592
+ /** Starting trees carried off ordinary killed rows before the journal drops them on its next write. */
593
+ private readonly adoptedStartingTrees;
594
+ /** Dead-MCP rows whose actual process owner is the daemon, atomically claimed for reconciliation. */
595
+ private readonly brokerOrphans;
596
+ /** Running/recovered jobs whose process tree is owned by the daemon rather than this MCP process. */
597
+ private readonly brokerExecutions;
598
+ private readonly nextJobId;
599
+ constructor(journal?: JobJournal, archive?: JobArchive, nextJobId?: () => string);
530
600
  /**
531
601
  * The finished jobs a previous process archived, read back so `dispatch_status`/`dispatch_result`
532
602
  * answer for them after a restart instead of `unknown jobId`. Marked `restored` so the rendering
@@ -552,6 +622,8 @@ export declare class LaneJobStore {
552
622
  * reaches a terminal state and so what it owned is reportable afterwards.
553
623
  */
554
624
  registerProcess(id: string, handle: OwnedProcess): void;
625
+ /** Root pids currently owned by a still-running job, through the same handle the reaper uses. */
626
+ runningPids(id: string): number[];
555
627
  /**
556
628
  * Register a bare kill callback — the pre-existing seam, kept because a caller that owns no OS
557
629
  * process (an answer-mode job's direct HTTP call, or a test double) still has something to stop.
@@ -597,6 +669,49 @@ export declare class LaneJobStore {
597
669
  beginAttemptActivity(id: string, now: number): void;
598
670
  /** The running attempt wrote `bytes` to `stream` at `now`. Ignored once the attempt is over. */
599
671
  noteOutput(id: string, stream: "stdout" | "stderr", bytes: number, now: number): void;
672
+ /** Persist the job-wide starting tree while the job is still running. */
673
+ noteStartingTree(id: string, tree: TreeSnapshot, scope: readonly string[] | undefined): void;
674
+ /**
675
+ * Return, once, daemon-backed orphan rows this process atomically claimed. The server owns the
676
+ * broker client, so reconciliation is asynchronous and deliberately outside this synchronous store.
677
+ */
678
+ takeBrokerOrphans(): JournalRow[];
679
+ /** Broker execution id for a job this process is collecting, if any. */
680
+ brokerExecution(id: string): string | undefined;
681
+ /** Record which execution boundary owns the current attempt. */
682
+ noteExecutionOwner(id: string, owner: LaneJob["executionOwner"]): void;
683
+ /**
684
+ * Clear an attempt-scoped daemon execution after it is definitively terminal and the walk will
685
+ * continue. The job itself stays running; the journal row is rewritten without broker metadata.
686
+ */
687
+ clearBrokerExecution(id: string): void;
688
+ /**
689
+ * Bind a live job to the daemon execution that now owns its process tree, and persist the opaque
690
+ * reference before the broker start request is sent. Used by the later ownership switchover.
691
+ */
692
+ noteBrokerExecution(id: string, executionId: string): void;
693
+ /**
694
+ * Materialize a claimed broker row as a running job while the daemon is queried/retried.
695
+ * The daemon, not this process, owns its process tree; no local kill handle is registered.
696
+ */
697
+ adoptBrokerRunning(row: JournalRow, snapshot?: LaneExecutionSnapshot): LaneJob | undefined;
698
+ /**
699
+ * Apply one identity-checked daemon snapshot to an adopted broker job.
700
+ * Returns false on mismatch/inconsistent terminal data; callers then retain the row and retry
701
+ * rather than turn malformed transport data into a death claim.
702
+ */
703
+ applyBrokerSnapshot(id: string, snapshot: LaneExecutionSnapshot): boolean;
704
+ /** Definitive reachable-daemon 404: the broker no longer knows the execution. */
705
+ markBrokerKilled(id: string, message: string): boolean;
706
+ /**
707
+ * Return, once, the starting trees carried by jobs adopted as killed after a restart. The server
708
+ * owns the git reader, so the store cannot render their deltas synchronously during construction.
709
+ */
710
+ takeAdoptedStartingTrees(): Array<{
711
+ jobId: string;
712
+ cwd: string;
713
+ startingTree: JournalStartingTree;
714
+ }>;
600
715
  /** Record the read-only tool binding the lane now running was given, so the reply can state it. */
601
716
  noteReadOnly(id: string, laneId: string, binding: string): void;
602
717
  /** Record what the launcher changed for the lane now running, so the reply can state it. */
@@ -605,8 +720,8 @@ export declare class LaneJobStore {
605
720
  * the second `git status` returns — and the archive row is then written again so it carries it.
606
721
  */
607
722
  noteTreeDelta(id: string, text: string): void;
608
- /** Record the newest activity the walk saw for the running lane. */
609
- noteLastActivity(id: string, at: number, source: string): void;
723
+ /** Publish the walk's liveness decision for the attempt now running. Pure status data only. */
724
+ noteLiveness(id: string, liveness: LaneLiveness): void;
610
725
  noteLaunch(id: string, notes: readonly string[]): void;
611
726
  /**
612
727
  * Append one tried lane to the walk's record. Appended for EVERY attempt, the winner included,
@@ -651,11 +766,11 @@ export declare class LaneJobStore {
651
766
  * Passing the asking job's own id excludes it, so this answers "how many OTHER jobs are running
652
767
  * this lane right now" — the question a skip check actually needs.
653
768
  *
654
- * ⚠ Per-process by construction, and that is the whole design, not a limitation to work around:
655
- * the daemon never spawns a lane, so the only process that ever knows a `cli` rung's process is
656
- * running is the one that spawned it. Two host sessions each running their own `llm-relay mcp`
657
- * can together exceed a rung's `maxConcurrent` — this bounds one host's own concurrency, and
658
- * `docs/reference.md` says so rather than implying a machine-wide guarantee this cannot make.
769
+ * ⚠ Per MCP SERVER PROCESS by design. D1 moves the physical child into the daemon, but this
770
+ * admission policy still counts the jobs THIS MCP store owns or recovered. Another simultaneously
771
+ * live MCP process is not folded into the number, so two host sessions can together exceed a
772
+ * rung's `maxConcurrent`. This preserves the documented per-host cap rather than silently turning
773
+ * it into a machine-wide semaphore.
659
774
  */
660
775
  inFlight(laneId: string, excludeJobId?: string): number;
661
776
  /** A job THIS store holds. The walk reads this; it never needs another process's job. */