@coreplane/switchboard 1.260.5 → 1.261.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 (40) hide show
  1. package/dist/assets/deploy/cloudflare-memory/worker.ts +106 -4
  2. package/dist/assets/package-lock.json +3 -3
  3. package/dist/assets/package.json +1 -1
  4. package/dist/assets/source.json +3 -3
  5. package/dist/assets/src/core/budgets.ts +5 -0
  6. package/dist/assets/src/core/coordinator/driver.ts +43 -6
  7. package/dist/assets/src/core/pipelineStanding.ts +24 -0
  8. package/dist/assets/src/core/plane/decide.ts +25 -0
  9. package/dist/assets/src/core/refusal.ts +1 -1
  10. package/dist/assets/src/core/runEvents.ts +5 -0
  11. package/dist/assets/src/core/runFriction.ts +2 -0
  12. package/dist/assets/src/core/runLedger/decisions.ts +10 -1
  13. package/dist/assets/src/core/runLedger/types.ts +24 -0
  14. package/dist/assets/src/core/runLiveState.ts +205 -0
  15. package/dist/assets/src/core/runRecord.ts +4 -0
  16. package/dist/assets/src/core/ship/coordinator.ts +29 -6
  17. package/dist/assets/web/dist/.vite/manifest.json +67 -67
  18. package/dist/assets/web/dist/assets/{DeliveryPage-Cf1joUyA.js → DeliveryPage-BUJckSuW.js} +1 -1
  19. package/dist/assets/web/dist/assets/{HomePage-DZEAnCCv.js → HomePage-CBQpcnaW.js} +1 -1
  20. package/dist/assets/web/dist/assets/{PendingTurnRow-4B8JwETU.js → PendingTurnRow-DIC86uWA.js} +1 -1
  21. package/dist/assets/web/dist/assets/{PlanePage-CHU2szQs.js → PlanePage-CfrbMh8t.js} +1 -1
  22. package/dist/assets/web/dist/assets/{ResidentDetailPage-L5SRcN_O.js → ResidentDetailPage-C-SgOUTl.js} +1 -1
  23. package/dist/assets/web/dist/assets/{ResidentsIndexPage-BIFf8qyE.js → ResidentsIndexPage-CiDhvXok.js} +1 -1
  24. package/dist/assets/web/dist/assets/{RunFoldRow-DzPIshJx.js → RunFoldRow-DZ8huwUU.js} +1 -1
  25. package/dist/assets/web/dist/assets/{RunRoutePage-Cru5IVux.js → RunRoutePage-Cp6wicYc.js} +3 -3
  26. package/dist/assets/web/dist/assets/{RunsIndexPage-CBkdPAdj.js → RunsIndexPage-BPXtfwwx.js} +1 -1
  27. package/dist/assets/web/dist/assets/{ScheduledPage-D_R55BDk.js → ScheduledPage-DbvP48HI.js} +1 -1
  28. package/dist/assets/web/dist/assets/{SettingsPage-DlmZvAvf.js → SettingsPage-B87lZaiN.js} +1 -1
  29. package/dist/assets/web/dist/assets/{SilentTurn-PWMDMbMG.js → SilentTurn-CPED_XCV.js} +1 -1
  30. package/dist/assets/web/dist/assets/{StatusDot-Bq0mYMFo.js → StatusDot-CFLn-DZ2.js} +1 -1
  31. package/dist/assets/web/dist/assets/{Tooltip-Bs6zd7yE.js → Tooltip-Dx9YBVEx.js} +1 -1
  32. package/dist/assets/web/dist/assets/{UnitRoutePage-BMGEZCvn.js → UnitRoutePage-d4A2X_o7.js} +1 -1
  33. package/dist/assets/web/dist/assets/budgets-BQgcCyvb.js +1 -0
  34. package/dist/assets/web/dist/assets/{dist-EkKVbIM-.js → dist-Cn51vWpw.js} +1 -1
  35. package/dist/assets/web/dist/assets/{indexRow-5s3hNzZ9.js → indexRow-BsWcHHVh.js} +1 -1
  36. package/dist/assets/web/dist/assets/{main-Disot0n_.js → main-DYwRHh0F.js} +2 -2
  37. package/dist/assets/web/dist/assets/{sseReplay-9gcMpylx.js → sseReplay-DGRDRLua.js} +1 -1
  38. package/dist/cli.js +1673 -722
  39. package/package.json +1 -1
  40. package/dist/assets/web/dist/assets/budgets-0szUBIMv.js +0 -1
package/dist/cli.js CHANGED
@@ -597,7 +597,7 @@ function fit(pipeline) {
597
597
  const need = ALLOWANCES.provision + ASKS.coding + reserveMinutes({ kind: "coding", index: 0 }, pipeline);
598
598
  return { ok: pipeline.maxMinutes >= need, need, have: pipeline.maxMinutes };
599
599
  }
600
- var SECOND_MS, secondsToMs, MINUTE_MS, minutesToMs, DAY_MS, WEEK_MS, CONFIRMATION_TTL_MS, QUESTION_TTL_MS, AUTHOR_BINDING_TTL_MS, FIRST_ATTACH_WAIT_MS, ATTACH_REQUEST_MIN_MS, HARNESS_PROBE_WAIT_MS, DRAIN, INTAKE_WINDOW_MAX_MS, INTAKE_RECOVERY_WINDOW_MS, INTAKE_DELIVERY_CLAIM_MS, LOOP_PRESETS, ASKS, PRESET_FLOORS, FLOORS, PULL_SWEEP, PROVIDER_RETRY_BACKOFFS_MS, MODEL_STREAM_HEARTBEAT_MS, HOSTED_DEADLINE_MARGIN_MINUTES, SHIP_WAIT, RESTART_CLAIM_GRACE_MS, PLANE, PACE_WINDOW_MINUTES, ALLOWANCES, POST_STEP_MINUTES, WRAP_UP_WARNING, SANDBOX_CREDENTIAL_WRITE_TIMEOUT_MS, BASH_COMMAND, RUNAWAY_TURNS_PER_MINUTE, DEFAULT_GRANT, GRANT_RENEWALS_MAX, STRUCTURED_RETRIES_MAX, IDLE_DAYS_DEFAULT, IDLE_DAYS_MAX, IDLE_WAKES_MAX;
600
+ var SECOND_MS, secondsToMs, MINUTE_MS, minutesToMs, DAY_MS, WEEK_MS, CONFIRMATION_TTL_MS, QUESTION_TTL_MS, AUTHOR_BINDING_TTL_MS, FIRST_ATTACH_WAIT_MS, ATTACH_REQUEST_MIN_MS, HARNESS_PROBE_WAIT_MS, DRAIN, INTAKE_WINDOW_MAX_MS, INTAKE_RECOVERY_WINDOW_MS, INTAKE_DELIVERY_CLAIM_MS, LOOP_PRESETS, ASKS, PRESET_FLOORS, FLOORS, PULL_SWEEP, PROVIDER_RETRY_BACKOFFS_MS, MODEL_STREAM_HEARTBEAT_MS, HOSTED_DEADLINE_MARGIN_MINUTES, SHIP_WAIT, SHIP_RECORD_VISIBILITY, RESTART_CLAIM_GRACE_MS, PLANE, PACE_WINDOW_MINUTES, ALLOWANCES, POST_STEP_MINUTES, WRAP_UP_WARNING, SANDBOX_CREDENTIAL_WRITE_TIMEOUT_MS, BASH_COMMAND, RUNAWAY_TURNS_PER_MINUTE, DEFAULT_GRANT, GRANT_RENEWALS_MAX, STRUCTURED_RETRIES_MAX, IDLE_DAYS_DEFAULT, IDLE_DAYS_MAX, IDLE_WAKES_MAX;
601
601
  var init_budgets = __esm({
602
602
  "../../src/core/budgets.ts"() {
603
603
  "use strict";
@@ -676,6 +676,7 @@ var init_budgets = __esm({
676
676
  MODEL_STREAM_HEARTBEAT_MS = 15e3;
677
677
  HOSTED_DEADLINE_MARGIN_MINUTES = 60;
678
678
  SHIP_WAIT = { marginMinutes: 5, chunkMinutes: 5, mergeChunkMinutes: 5, busyRetryMinutes: 2 };
679
+ SHIP_RECORD_VISIBILITY = { retries: 3, retryMs: secondsToMs(1) };
679
680
  RESTART_CLAIM_GRACE_MS = minutesToMs(SHIP_WAIT.chunkMinutes);
680
681
  PLANE = {
681
682
  recentMinutes: 60,
@@ -4077,6 +4078,7 @@ function isHeadMaterial(event) {
4077
4078
  case "context":
4078
4079
  case "reference":
4079
4080
  case "run_meta":
4081
+ case "run_state":
4080
4082
  case "route":
4081
4083
  return true;
4082
4084
  case "run_note":
@@ -4846,7 +4848,7 @@ function analyzeRunFriction(events, opts = {}) {
4846
4848
  return;
4847
4849
  }
4848
4850
  if (ev.type === "artifact" && ev.direction === "out") outboundArtifacts++;
4849
- if (ev.type === "skill_use" || ev.type === "artifact" || ev.type === "review_artifact" || ev.type === "pr_description" || ev.type === "pr_opened" || ev.type === "coordinator_tag" || ev.type === "ship_handoff" || ev.type === "child_interrupted" || ev.type === "child_resumed" || ev.type === "review_posted" || ev.type === "ship_round" || ev.type === "ship_unit" || ev.type === "route" || ev.type === "operator" || ev.type === "refusal" || ev.type === "reference" || ev.type === "lease" || ev.type === "pushed_head") {
4851
+ if (ev.type === "skill_use" || ev.type === "artifact" || ev.type === "review_artifact" || ev.type === "pr_description" || ev.type === "pr_opened" || ev.type === "coordinator_tag" || ev.type === "ship_handoff" || ev.type === "child_interrupted" || ev.type === "child_resumed" || ev.type === "review_posted" || ev.type === "ship_round" || ev.type === "ship_unit" || ev.type === "route" || ev.type === "operator" || ev.type === "refusal" || ev.type === "reference" || ev.type === "run_state" || ev.type === "lease" || ev.type === "pushed_head") {
4850
4852
  sideFactEvents++;
4851
4853
  return;
4852
4854
  }
@@ -4928,6 +4930,7 @@ function analyzeRunFriction(events, opts = {}) {
4928
4930
  }
4929
4931
  return;
4930
4932
  }
4933
+ if (ev.type !== "run_note") return;
4931
4934
  switch (ev.kind) {
4932
4935
  case "wrap_up":
4933
4936
  wrapUp = { index, at: ev.at };
@@ -5881,6 +5884,26 @@ var init_contract2 = __esm({
5881
5884
  });
5882
5885
 
5883
5886
  // ../../src/core/pipelineStanding.ts
5887
+ function hostedStageDetail(stage) {
5888
+ switch (stage) {
5889
+ case "coding":
5890
+ return "coding a unit";
5891
+ case "review":
5892
+ return "reviewing a unit";
5893
+ case "fix":
5894
+ return "fixing review findings";
5895
+ case "approved":
5896
+ return "waiting for checks and merge";
5897
+ case "merge-ready":
5898
+ return "ready for a person to merge";
5899
+ case "merged":
5900
+ return "a unit merged";
5901
+ case "idle":
5902
+ return "waiting for the next pipeline step";
5903
+ case "ended":
5904
+ return "finishing the pipeline";
5905
+ }
5906
+ }
5884
5907
  function endingWordOf(kind) {
5885
5908
  return ENDING_WORDS[kind] ?? kind;
5886
5909
  }
@@ -6007,10 +6030,11 @@ function isPipelineSummaryShape(v) {
6007
6030
  }
6008
6031
  return true;
6009
6032
  }
6010
- var STAGES, OPEN_STAGES, ROUND_STAGE, ENDING_STAGE, ENDING_WORDS, ROUND_OUTCOME_WORDS, isFinite_;
6033
+ var HOSTED_PIPELINE_STARTING_DETAIL, STAGES, OPEN_STAGES, ROUND_STAGE, ENDING_STAGE, ENDING_WORDS, ROUND_OUTCOME_WORDS, isFinite_;
6011
6034
  var init_pipelineStanding = __esm({
6012
6035
  "../../src/core/pipelineStanding.ts"() {
6013
6036
  "use strict";
6037
+ HOSTED_PIPELINE_STARTING_DETAIL = "pipeline starting";
6014
6038
  STAGES = [
6015
6039
  "coding",
6016
6040
  "review",
@@ -15400,7 +15424,7 @@ var init_refusal = __esm({
15400
15424
  repo_not_onboarded: "request",
15401
15425
  repo_access: "policy",
15402
15426
  pr_head_unknown: "system",
15403
- branch_moved: "system",
15427
+ workspace_head_mismatch: "system",
15404
15428
  coordinator_thread_live: "system",
15405
15429
  live_agent_allowlist: "policy",
15406
15430
  follow_up_refused: "request",
@@ -16133,6 +16157,7 @@ var init_resident = __esm({
16133
16157
  * here: its `runtime-replaced` is the typed restart (`opWithReattach`). */
16134
16158
  runtimeReplacedStreak = 0;
16135
16159
  lastBinding;
16160
+ attachAttempt = 0;
16136
16161
  /** The thread's binding as the resident answered it on the most recent
16137
16162
  * successful attach — including a mid-run re-attach after an eviction, which
16138
16163
  * may land on a newer sha than the one the run started on. Undefined until
@@ -16299,6 +16324,7 @@ var init_resident = __esm({
16299
16324
  * an operation's wall clock is the command's, and a recovery attach is not
16300
16325
  * the command. */
16301
16326
  async attach(span, opts = {}) {
16327
+ this.attachAttempt++;
16302
16328
  const answer = await this.attachOnce(span, this.attachBoundMs("/attach"), opts.signal);
16303
16329
  if (answer.ok) return answer.binding;
16304
16330
  if (isDrainingRefusal(answer)) {
@@ -16347,14 +16373,16 @@ var init_resident = __esm({
16347
16373
  t0 + (left === void 0 ? DRAIN_WAIT_MAX_MS : Math.max(0, left - DRAIN_LEASE_RESERVE_MS))
16348
16374
  );
16349
16375
  let answer = first;
16350
- const note = (now) => this.opts.onSetupNote?.(
16351
- `waiting for the deploy to finish \xB7 ${Math.max(1, Math.round((now - t0) / MINUTE_MS))} min`
16352
- );
16376
+ await this.opts.onLiveStateObservation?.({
16377
+ state: "waiting_deploy",
16378
+ bound: deadline,
16379
+ reason: "deploy",
16380
+ attempt: this.attachAttempt
16381
+ });
16353
16382
  const waitSpan = span?.start("dispatch.workspace.attach.drain-wait");
16354
16383
  try {
16355
16384
  for (; ; ) {
16356
16385
  const now = systemClock();
16357
- note(now);
16358
16386
  if (now >= deadline)
16359
16387
  throw new ResidentDrainingError(this.opts.resource, now - t0, drainingUntil(answer), refusalWords(answer));
16360
16388
  await wakePause(Math.min(DRAIN_POLL_MS, deadline - now), opts.signal, "/attach");
@@ -16392,7 +16420,6 @@ var init_resident = __esm({
16392
16420
  }
16393
16421
  throw err2;
16394
16422
  } finally {
16395
- this.opts.onSetupNote?.(void 0);
16396
16423
  }
16397
16424
  }
16398
16425
  /** One `/attach`, answered rather than thrown: the binding on a 200, else
@@ -16699,6 +16726,13 @@ var init_resident = __esm({
16699
16726
  }
16700
16727
  };
16701
16728
  const t0 = systemClock();
16729
+ const wakeBound = t0 + wakeWaitBudget(opts.budgetMs);
16730
+ await this.opts.onLiveStateObservation?.({
16731
+ state: "waiting_repository",
16732
+ bound: wakeBound,
16733
+ reason: "repository_container",
16734
+ attempt: this.attachAttempt
16735
+ });
16702
16736
  let transient = opts.origin === "transient-refusal";
16703
16737
  const definite = (why) => residentWakeStrike(route2, refusal, why, "refused", opts.origin);
16704
16738
  const decide = (view) => transient && isUnansweredProbe(view) ? {
@@ -18412,7 +18446,7 @@ async function makeExecutor(opts, ctx, span) {
18412
18446
  resolveEnvs: () => gitIdentityEnvs(ctx.profile.identity, authorSourceOf(opts, ctx)),
18413
18447
  ...ctx.ownPr !== void 0 ? { ownPr: ctx.ownPr } : {},
18414
18448
  ...ctx.remainingMs !== void 0 ? { remainingMs: ctx.remainingMs } : {},
18415
- ...ctx.onSetupNote !== void 0 ? { onSetupNote: ctx.onSetupNote } : {}
18449
+ ...ctx.onLiveStateObservation !== void 0 ? { onLiveStateObservation: ctx.onLiveStateObservation } : {}
18416
18450
  },
18417
18451
  nonWarm,
18418
18452
  span,
@@ -18594,7 +18628,7 @@ async function reattachWorkspace(opts, ctx, recorded, span) {
18594
18628
  // resident holds its own credential, so the pairs alone ride.
18595
18629
  resolveEnvs: () => gitIdentityEnvs(ctx.profile.identity, authorSourceOf(opts, ctx)),
18596
18630
  ...ctx.remainingMs !== void 0 ? { remainingMs: ctx.remainingMs } : {},
18597
- ...ctx.onSetupNote !== void 0 ? { onSetupNote: ctx.onSetupNote } : {}
18631
+ ...ctx.onLiveStateObservation !== void 0 ? { onLiveStateObservation: ctx.onLiveStateObservation } : {}
18598
18632
  });
18599
18633
  let binding;
18600
18634
  try {
@@ -25399,6 +25433,199 @@ var init_frictionProposals = __esm({
25399
25433
  }
25400
25434
  });
25401
25435
 
25436
+ // ../../src/core/runLiveState.ts
25437
+ function safeLiveStateDetail(detail) {
25438
+ if (detail === void 0) return void 0;
25439
+ const line4 = oneLine(detail);
25440
+ if (line4 === "" || UNSAFE_DETAIL.test(line4)) return void 0;
25441
+ return redactAndCap(line4, LIVE_STATE_DETAIL_MAX - 1);
25442
+ }
25443
+ function assignRunLiveState(current, currentSeq, input) {
25444
+ if (input.expectedSeq !== currentSeq) return { ok: false, reason: "stale-sequence" };
25445
+ if (current === void 0 && input.state !== "admitted") return { ok: false, reason: "invalid-transition" };
25446
+ if (current?.state === "ended") return { ok: false, reason: "terminal" };
25447
+ if (input.state !== "ended") {
25448
+ if (input.bound === void 0) return { ok: false, reason: "bound-required" };
25449
+ if (!Number.isFinite(input.bound) || input.bound < input.at) return { ok: false, reason: "invalid-bound" };
25450
+ } else if (input.cause === void 0) return { ok: false, reason: "cause-required" };
25451
+ if (current !== void 0 && current.state !== input.state && !TRANSITIONS[current.state].includes(input.state))
25452
+ return { ok: false, reason: "invalid-transition" };
25453
+ const detail = safeLiveStateDetail(input.detail);
25454
+ const liveState = {
25455
+ state: input.state,
25456
+ since: current?.state === input.state ? current.since : input.at,
25457
+ ...input.state !== "ended" ? { bound: input.bound } : {},
25458
+ ...detail !== void 0 ? { detail } : {}
25459
+ };
25460
+ if (current?.state === input.state) return { ok: true, liveState };
25461
+ return {
25462
+ ok: true,
25463
+ liveState,
25464
+ event: {
25465
+ type: "run_state",
25466
+ ...liveState,
25467
+ ...input.state === "ended" ? { cause: input.cause } : {},
25468
+ at: input.at
25469
+ }
25470
+ };
25471
+ }
25472
+ function foldRunLiveState(events, materialized = {}) {
25473
+ let liveState = materialized.liveState;
25474
+ let liveStateSeq = materialized.liveStateSeq ?? 0;
25475
+ let leaseEndsAt;
25476
+ for (const event of [...events].sort((left, right) => (left.seq ?? 0) - (right.seq ?? 0))) {
25477
+ if (event.type === "lease" && event.endsAt !== void 0) leaseEndsAt = event.endsAt;
25478
+ const seq = event.seq ?? 0;
25479
+ if (seq <= liveStateSeq) continue;
25480
+ if (event.type === "run_state" && RUN_LIVE_STATE_NAMES.includes(event.state) && event.since !== void 0) {
25481
+ liveState = {
25482
+ state: event.state,
25483
+ since: event.since,
25484
+ ...event.bound !== void 0 ? { bound: event.bound } : {},
25485
+ ...event.detail !== void 0 ? { detail: event.detail } : {}
25486
+ };
25487
+ liveStateSeq = seq;
25488
+ continue;
25489
+ }
25490
+ if (event.type === "tool_call" && liveState?.state === "working" && event.at !== void 0 && event.boundMs !== void 0) {
25491
+ liveState = { ...liveState, bound: event.at + event.boundMs, detail: "running a tool" };
25492
+ liveStateSeq = seq;
25493
+ continue;
25494
+ }
25495
+ if (event.type === "tool_result" && liveState?.state === "working" && leaseEndsAt !== void 0) {
25496
+ liveState = { ...liveState, bound: leaseEndsAt, detail: "model turn" };
25497
+ liveStateSeq = seq;
25498
+ }
25499
+ }
25500
+ return {
25501
+ ...liveState !== void 0 ? { liveState } : {},
25502
+ ...liveStateSeq > 0 ? { liveStateSeq } : {}
25503
+ };
25504
+ }
25505
+ var RUN_LIVE_STATE_NAMES, LIVE_STATE_DETAIL_MAX, TRANSITIONS, UNSAFE_DETAIL;
25506
+ var init_runLiveState = __esm({
25507
+ "../../src/core/runLiveState.ts"() {
25508
+ "use strict";
25509
+ init_redact();
25510
+ RUN_LIVE_STATE_NAMES = [
25511
+ "admitted",
25512
+ "waiting_deploy",
25513
+ "waiting_repository",
25514
+ "falling_back",
25515
+ "preparing",
25516
+ "working",
25517
+ "waiting_provider",
25518
+ "wrapping_up",
25519
+ "ended"
25520
+ ];
25521
+ LIVE_STATE_DETAIL_MAX = 160;
25522
+ TRANSITIONS = {
25523
+ admitted: ["waiting_deploy", "waiting_repository", "falling_back", "preparing", "working", "wrapping_up", "ended"],
25524
+ waiting_deploy: ["waiting_repository", "falling_back", "preparing", "working", "wrapping_up", "ended"],
25525
+ waiting_repository: ["waiting_deploy", "falling_back", "preparing", "working", "wrapping_up", "ended"],
25526
+ falling_back: ["preparing", "working", "wrapping_up", "ended"],
25527
+ preparing: ["waiting_deploy", "waiting_repository", "falling_back", "working", "wrapping_up", "ended"],
25528
+ working: [
25529
+ "waiting_deploy",
25530
+ "waiting_repository",
25531
+ "falling_back",
25532
+ "preparing",
25533
+ "waiting_provider",
25534
+ "wrapping_up",
25535
+ "ended"
25536
+ ],
25537
+ waiting_provider: ["working", "wrapping_up", "ended"],
25538
+ wrapping_up: ["ended"],
25539
+ ended: []
25540
+ };
25541
+ UNSAFE_DETAIL = /(?:\bimage-stale\b|\battach-failed\b|\bparked-provider\b|<\/?(?:html|body|head)\b|\bbad gateway\b)/i;
25542
+ }
25543
+ });
25544
+
25545
+ // ../../src/core/plane/decide.ts
25546
+ function liveStateWords(state) {
25547
+ switch (state) {
25548
+ case "admitted":
25549
+ return "admitted";
25550
+ case "waiting_deploy":
25551
+ return "waiting for the current deploy";
25552
+ case "waiting_repository":
25553
+ return "waiting for the repository container";
25554
+ case "falling_back":
25555
+ return "switching to a fallback workspace";
25556
+ case "preparing":
25557
+ return "preparing the workspace";
25558
+ case "working":
25559
+ return "working";
25560
+ case "waiting_provider":
25561
+ return "waiting for the model provider";
25562
+ case "wrapping_up":
25563
+ return "wrapping up";
25564
+ case "ended":
25565
+ return "ended";
25566
+ }
25567
+ }
25568
+ function causeOfClose(status3, restarting) {
25569
+ switch (status3) {
25570
+ case "completed":
25571
+ return "completed";
25572
+ case "failed":
25573
+ return "failed";
25574
+ case "stopped_soft":
25575
+ case "stopped_hard":
25576
+ case "stopped":
25577
+ return "stopped";
25578
+ default:
25579
+ return restarting === true ? "resident_replaced" : "lease_lapsed";
25580
+ }
25581
+ }
25582
+ function endingCauseWords(cause) {
25583
+ switch (cause) {
25584
+ case "completed":
25585
+ return "it completed";
25586
+ case "failed":
25587
+ return "it failed";
25588
+ case "stopped":
25589
+ return "it was stopped";
25590
+ case "withdrawn":
25591
+ return "its wait was withdrawn";
25592
+ case "refused":
25593
+ return "its admission was refused";
25594
+ case "lease_lapsed":
25595
+ return "its lease lapsed with no heartbeat";
25596
+ case "resident_replaced":
25597
+ return "the resident container running it was replaced";
25598
+ case "runner_gone":
25599
+ return "the runner instance driving it is gone";
25600
+ }
25601
+ }
25602
+ function isReissueSteerText(text) {
25603
+ return /^the model provider .+ is answering again — re-issue the held turn and continue$/.test(text.trim());
25604
+ }
25605
+ function waitingWords(waiting2) {
25606
+ if (waiting2.length === 0) return "its turn";
25607
+ return waiting2.map(
25608
+ (c) => c.kind === "thread_free" ? "the thread's live run" : c.kind === "deploy_settled" ? "the pending deploy" : c.kind === "seat" ? `a seat on ${c.resident}` : c.kind === "memory" ? `memory on ${c.resident}` : c.kind === "provider_up" ? `the ${c.provider} provider` : `the ${c.window} window`
25609
+ ).join(", then ");
25610
+ }
25611
+ var PLANE_ENDING_CAUSES;
25612
+ var init_decide = __esm({
25613
+ "../../src/core/plane/decide.ts"() {
25614
+ "use strict";
25615
+ init_budgets();
25616
+ PLANE_ENDING_CAUSES = [
25617
+ "completed",
25618
+ "failed",
25619
+ "stopped",
25620
+ "withdrawn",
25621
+ "refused",
25622
+ "lease_lapsed",
25623
+ "resident_replaced",
25624
+ "runner_gone"
25625
+ ];
25626
+ }
25627
+ });
25628
+
25402
25629
  // ../../src/core/runEventLines.ts
25403
25630
  function parseRunEventLines(text) {
25404
25631
  const events = [];
@@ -25464,6 +25691,8 @@ function isRunEvent(v) {
25464
25691
  return typeof o.url === "string" && typeof o.number === "number" && typeof o.created === "boolean";
25465
25692
  case "pushed_head":
25466
25693
  return typeof o.ref === "string" && typeof o.sha === "string" && (o.by === "push" || o.by === "salvage");
25694
+ case "run_state":
25695
+ return typeof o.state === "string" && LIVE_STATES.has(o.state) && typeof o.since === "number" && (o.state === "ended" ? typeof o.cause === "string" && ENDING_CAUSES.has(o.cause) : typeof o.bound === "number");
25467
25696
  case "review_posted":
25468
25697
  return typeof o.repo === "string" && typeof o.number === "number" && typeof o.head === "string";
25469
25698
  case "ship_round":
@@ -25486,12 +25715,16 @@ function isRunEvent(v) {
25486
25715
  return false;
25487
25716
  }
25488
25717
  }
25489
- var NOTE_KINDS;
25718
+ var NOTE_KINDS, LIVE_STATES, ENDING_CAUSES;
25490
25719
  var init_runEventLines = __esm({
25491
25720
  "../../src/core/runEventLines.ts"() {
25492
25721
  "use strict";
25493
25722
  init_runEvents();
25723
+ init_runLiveState();
25724
+ init_decide();
25494
25725
  NOTE_KINDS = new Set(RUN_NOTE_KINDS);
25726
+ LIVE_STATES = new Set(RUN_LIVE_STATE_NAMES);
25727
+ ENDING_CAUSES = new Set(PLANE_ENDING_CAUSES);
25495
25728
  }
25496
25729
  });
25497
25730
 
@@ -29134,6 +29367,505 @@ var init_llmOutput = __esm({
29134
29367
  }
29135
29368
  });
29136
29369
 
29370
+ // ../../src/core/dispatch/handBack.ts
29371
+ function renderHandBackLine(line4) {
29372
+ return `${HAND_BACK_PREFIX}
29373
+ \`${line4}\``;
29374
+ }
29375
+ var HAND_BACK_PREFIX;
29376
+ var init_handBack = __esm({
29377
+ "../../src/core/dispatch/handBack.ts"() {
29378
+ "use strict";
29379
+ HAND_BACK_PREFIX = "To run this:";
29380
+ }
29381
+ });
29382
+
29383
+ // ../../src/core/statusCardFrame.ts
29384
+ function activityText(activity) {
29385
+ if (!activity) return void 0;
29386
+ if (activity.kind === "line") return activity.text;
29387
+ return `\u2192 $ ${activity.command.replace(/\s+/g, " ").trim()}`;
29388
+ }
29389
+ function createCardShell(opts) {
29390
+ const verbosity2 = opts.verbosity ?? DEFAULT_VERBOSITY;
29391
+ const notes = [];
29392
+ let link = opts.link;
29393
+ let frame2 = 0;
29394
+ let finishedAt;
29395
+ let setupLabel;
29396
+ const lead = opts.lead ?? [];
29397
+ const base = () => opts.model !== void 0 && shows(verbosity2, "verbose") ? `${opts.label} on \`${opts.model}\`` : opts.label;
29398
+ const label = () => [base(), ...notes.filter((n2) => shows(verbosity2, n2.level)).map((n2) => n2.text)].join(" \xB7 ");
29399
+ const elapsed2 = () => formatDuration((finishedAt ?? opts.now()) - opts.startedAt, "clock");
29400
+ const headline = (icon) => `${icon} ${label()} \xB7 ${elapsed2()}`;
29401
+ const closeDetail = (close, own) => [...shows(verbosity2, "debug") ? [close.shape, close.queued] : [], own].filter(Boolean).join("\n") || void 0;
29402
+ return {
29403
+ get label() {
29404
+ return label();
29405
+ },
29406
+ note(level, text) {
29407
+ notes.push({ level, text });
29408
+ },
29409
+ setLink(next) {
29410
+ link = next;
29411
+ },
29412
+ freeze(at) {
29413
+ finishedAt = at;
29414
+ },
29415
+ setSetupLabel(next) {
29416
+ setupLabel = next;
29417
+ },
29418
+ ack() {
29419
+ const detail = lead.join("\n");
29420
+ return { title: `\u{1F440} ${label()} \xB7 preparing workspace\u2026`, ...detail ? { detail } : {} };
29421
+ },
29422
+ live(parts = {}) {
29423
+ const glyph = SPINNER_GLYPHS[frame2++ % SPINNER_GLYPHS.length];
29424
+ const detail = [...lead, ...parts.detail ?? []].filter(Boolean).join("\n");
29425
+ return {
29426
+ title: headline(glyph) + (setupLabel ? ` \u2014 ${setupLabel}` : "") + (parts.suffix ?? "") + (parts.notice ? ` \xB7 ${parts.notice}` : ""),
29427
+ detail: detail || void 0,
29428
+ ...parts.activity ? { activity: parts.activity } : {},
29429
+ link
29430
+ };
29431
+ },
29432
+ close(close) {
29433
+ const detail = closeDetail(close, close.kind === "done" ? close.detail : void 0);
29434
+ switch (close.kind) {
29435
+ case "done":
29436
+ return { title: headline(close.icon), detail, link };
29437
+ case "not_started":
29438
+ return { title: `${close.icon} ${label()} \xB7 not started (${close.reason}) \xB7 ${elapsed2()}`, detail };
29439
+ case "refused":
29440
+ return { title: `${close.icon} ${label()} \xB7 ${close.reason} \xB7 ${elapsed2()}`, detail };
29441
+ case "setup_failed":
29442
+ return { title: `\u274C setup failed \xB7 ${close.reason} \xB7 ${elapsed2()}`, detail };
29443
+ }
29444
+ }
29445
+ };
29446
+ }
29447
+ var SPINNER_GLYPHS, LIVE_CARD_PREFIXES, ROUTE_REASON_PREFIX;
29448
+ var init_statusCardFrame = __esm({
29449
+ "../../src/core/statusCardFrame.ts"() {
29450
+ "use strict";
29451
+ init_formatDuration();
29452
+ init_verbosity();
29453
+ SPINNER_GLYPHS = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
29454
+ LIVE_CARD_PREFIXES = [...SPINNER_GLYPHS, "\u{1F440}"];
29455
+ ROUTE_REASON_PREFIX = "route reason:";
29456
+ }
29457
+ });
29458
+
29459
+ // ../../src/core/confirmations.ts
29460
+ import { randomUUID } from "node:crypto";
29461
+ import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "node:fs";
29462
+ import { dirname as dirname10, resolve as resolve9 } from "node:path";
29463
+ function newConfirmationId() {
29464
+ return randomUUID();
29465
+ }
29466
+ function renderOffer(offer) {
29467
+ if (offer.question) return `${offer.question.text}
29468
+ Did you mean:
29469
+ \`${offer.line}\`
29470
+
29471
+ ${offer.question.evidence}`;
29472
+ return [offer.line, ...offer.risk ? [offer.risk] : []].join("\n");
29473
+ }
29474
+ function confirmationMessageOf(msg) {
29475
+ const { images: _images, documents: _documents, staged: _staged, ...kept } = msg;
29476
+ return kept;
29477
+ }
29478
+ function isRecord3(v) {
29479
+ return typeof v === "object" && v !== null && !Array.isArray(v);
29480
+ }
29481
+ function isMessage(v) {
29482
+ return isRecord3(v) && typeof v.channelId === "string" && typeof v.userId === "string" && typeof v.threadKey === "string" && typeof v.text === "string";
29483
+ }
29484
+ function isRunShape(v) {
29485
+ return typeof v.id === "string" && isMessage(v.message) && typeof v.command === "string" && isRecord3(v.input) && typeof v.receipt === "string" && typeof v.risk === "string" && typeof v.model === "string";
29486
+ }
29487
+ function isRedispatchShape(v) {
29488
+ return typeof v.id === "string" && isMessage(v.message) && typeof v.line === "string" && typeof v.evidence === "string" && typeof v.code === "string";
29489
+ }
29490
+ function parsePendingConfirmation(v) {
29491
+ if (!isRecord3(v)) return void 0;
29492
+ if (v.kind === "redispatch")
29493
+ return isRedispatchShape(v) ? v : void 0;
29494
+ if (v.kind !== void 0 && v.kind !== "run") return void 0;
29495
+ return isRunShape(v) ? { ...v, kind: "run" } : void 0;
29496
+ }
29497
+ function parseConfirmation(v) {
29498
+ if (!isRecord3(v) || typeof v.expiresAt !== "number") return void 0;
29499
+ const pending2 = parsePendingConfirmation(v);
29500
+ return pending2 ? { ...pending2, expiresAt: v.expiresAt } : void 0;
29501
+ }
29502
+ function isRefusal(v) {
29503
+ return typeof v === "string" && CONFIRMATION_REFUSALS.includes(v);
29504
+ }
29505
+ function judge2(rows, id, actorIds, now, kind) {
29506
+ const row2 = rows.get(id);
29507
+ if (!row2) return { ok: false, refused: "used" };
29508
+ if (kind === "consume" && row2.expiresAt <= now) {
29509
+ rows.delete(id);
29510
+ return { ok: false, refused: "expired", row: row2 };
29511
+ }
29512
+ if (!actorIds.includes(row2.message.userId))
29513
+ return kind === "consume" ? { ok: false, refused: "foreign", row: row2 } : { ok: false, refused: "foreign" };
29514
+ rows.delete(id);
29515
+ return kind === "consume" ? { ok: true, row: row2 } : { ok: true };
29516
+ }
29517
+ function replaceThreadRow(rows, row2) {
29518
+ for (const [id, r] of rows) if (r.message.threadKey === row2.message.threadKey) rows.delete(id);
29519
+ rows.set(row2.id, row2);
29520
+ }
29521
+ function threadRowId(rows, threadKey) {
29522
+ for (const [id, r] of rows) if (r.message.threadKey === threadKey) return id;
29523
+ return void 0;
29524
+ }
29525
+ function buildConfirmationStore(config, secrets, opts) {
29526
+ const worker = config.config.runtimeOverrides?.worker;
29527
+ if (!worker) return new FileConfirmationStore(opts.path);
29528
+ const tokenEnv = worker.tokenEnv ?? "MEMORY_TOKEN";
29529
+ const token2 = secrets.named(tokenEnv);
29530
+ if (!token2) throw new Error(`runtimeOverrides.worker is configured but ${tokenEnv} is not set`);
29531
+ return new WorkerConfirmationStore({
29532
+ baseUrl: worker.baseUrl,
29533
+ token: token2.reveal(),
29534
+ ...opts.fetch ? { fetch: opts.fetch } : {}
29535
+ });
29536
+ }
29537
+ var CONFIRMATION_REFUSALS, UNSHOWABLE_LINE, STORE_UNREACHABLE_LINE, FileConfirmationStore, CONFIRMATION_WORKER_TIMEOUT_MS, WorkerConfirmationStore;
29538
+ var init_confirmations = __esm({
29539
+ "../../src/core/confirmations.ts"() {
29540
+ "use strict";
29541
+ init_clock();
29542
+ CONFIRMATION_REFUSALS = ["used", "expired", "foreign"];
29543
+ UNSHOWABLE_LINE = "this command carries a value that cannot be shown, so no confirmation can be offered; nothing ran";
29544
+ STORE_UNREACHABLE_LINE = "this command needs a confirmation click, and the confirmation store could not be reached; nothing ran \u2014 ask again for the button";
29545
+ FileConfirmationStore = class {
29546
+ path;
29547
+ clock;
29548
+ constructor(path, opts = {}) {
29549
+ this.path = resolve9(path);
29550
+ this.clock = opts.clock ?? systemClock;
29551
+ }
29552
+ read() {
29553
+ const rows = /* @__PURE__ */ new Map();
29554
+ if (!existsSync12(this.path)) return rows;
29555
+ const raw = JSON.parse(readFileSync14(this.path, "utf8"));
29556
+ for (const v of Array.isArray(raw.confirmations) ? raw.confirmations : []) {
29557
+ const row2 = parseConfirmation(v);
29558
+ if (row2) rows.set(row2.id, row2);
29559
+ }
29560
+ return rows;
29561
+ }
29562
+ write(rows) {
29563
+ mkdirSync9(dirname10(this.path), { recursive: true });
29564
+ writeFileSync8(this.path, JSON.stringify({ confirmations: [...rows.values()] }, null, 2));
29565
+ }
29566
+ async put(row2, ttlMs) {
29567
+ const rows = this.read();
29568
+ const stored = { ...row2, expiresAt: this.clock() + ttlMs };
29569
+ replaceThreadRow(rows, stored);
29570
+ this.write(rows);
29571
+ return stored;
29572
+ }
29573
+ async consume(id, actorIds) {
29574
+ const rows = this.read();
29575
+ const out = judge2(rows, id, actorIds, this.clock(), "consume");
29576
+ this.write(rows);
29577
+ return out;
29578
+ }
29579
+ async cancel(id, actorIds) {
29580
+ const rows = this.read();
29581
+ const out = judge2(rows, id, actorIds, this.clock(), "cancel");
29582
+ this.write(rows);
29583
+ return out;
29584
+ }
29585
+ async cancelByThread(threadKey, actorIds) {
29586
+ const rows = this.read();
29587
+ const id = threadRowId(rows, threadKey);
29588
+ if (id === void 0) return { ok: false, refused: "used" };
29589
+ const out = judge2(rows, id, actorIds, this.clock(), "cancel");
29590
+ this.write(rows);
29591
+ return out;
29592
+ }
29593
+ async pendingByThread(threadKey) {
29594
+ const rows = this.read();
29595
+ const id = threadRowId(rows, threadKey);
29596
+ const row2 = id === void 0 ? void 0 : rows.get(id);
29597
+ if (!row2 || row2.expiresAt <= this.clock()) return void 0;
29598
+ return row2;
29599
+ }
29600
+ describe() {
29601
+ return `file ${this.path}`;
29602
+ }
29603
+ };
29604
+ CONFIRMATION_WORKER_TIMEOUT_MS = 8e3;
29605
+ WorkerConfirmationStore = class {
29606
+ constructor(opts) {
29607
+ this.opts = opts;
29608
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
29609
+ this.fetchImpl = opts.fetch ?? fetch;
29610
+ }
29611
+ opts;
29612
+ baseUrl;
29613
+ fetchImpl;
29614
+ async put(row2, ttlMs) {
29615
+ const body = await this.post("/config/confirmations/put", {
29616
+ id: row2.id,
29617
+ threadKey: row2.message.threadKey,
29618
+ requester: row2.message.userId,
29619
+ body: row2,
29620
+ ttlMs
29621
+ });
29622
+ if (typeof body.expiresAt !== "number")
29623
+ throw new Error("confirmation store answered a put without the expiry it stamped");
29624
+ return { ...row2, expiresAt: body.expiresAt };
29625
+ }
29626
+ async consume(id, actorIds) {
29627
+ const body = await this.post("/config/confirmations/consume", { id, actorIds });
29628
+ const stored = isRecord3(body.row) ? body.row : void 0;
29629
+ const row2 = parseConfirmation(
29630
+ stored && isRecord3(stored.body) ? { ...stored.body, expiresAt: stored.expiresAt } : void 0
29631
+ );
29632
+ if (isRefusal(body.refused))
29633
+ return { ok: false, refused: body.refused, ...row2 ? { row: row2 } : {} };
29634
+ if (!row2) throw new Error("confirmation store answered a consume outside its contract");
29635
+ return { ok: true, row: row2 };
29636
+ }
29637
+ async cancel(id, actorIds) {
29638
+ const body = await this.post("/config/confirmations/cancel", { id, actorIds });
29639
+ if (body.ok === true) return { ok: true };
29640
+ if (body.refused === "used" || body.refused === "foreign") return { ok: false, refused: body.refused };
29641
+ throw new Error("confirmation store answered a cancel outside its contract");
29642
+ }
29643
+ async cancelByThread(threadKey, actorIds) {
29644
+ const body = await this.post("/config/confirmations/cancel-by-thread", { threadKey, actorIds });
29645
+ if (body.ok === true) return { ok: true };
29646
+ if (body.refused === "used" || body.refused === "foreign") return { ok: false, refused: body.refused };
29647
+ throw new Error("confirmation store answered a cancel-by-thread outside its contract");
29648
+ }
29649
+ async pendingByThread(threadKey) {
29650
+ const body = await this.post("/config/confirmations/pending-by-thread", { threadKey });
29651
+ if (body.row === null) return void 0;
29652
+ const stored = isRecord3(body.row) ? body.row : void 0;
29653
+ const row2 = parseConfirmation(
29654
+ stored && isRecord3(stored.body) ? { ...stored.body, expiresAt: stored.expiresAt } : void 0
29655
+ );
29656
+ if (!row2) throw new Error("confirmation store answered a pending-by-thread outside its contract");
29657
+ return row2;
29658
+ }
29659
+ describe() {
29660
+ return `state Worker ${this.baseUrl} (ConfigDO confirmations)`;
29661
+ }
29662
+ async post(path, payload2) {
29663
+ let res;
29664
+ try {
29665
+ res = await this.fetchImpl(`${this.baseUrl}${path}`, {
29666
+ method: "POST",
29667
+ headers: { authorization: `Bearer ${this.opts.token}`, "content-type": "application/json" },
29668
+ body: JSON.stringify(payload2),
29669
+ signal: AbortSignal.timeout(CONFIRMATION_WORKER_TIMEOUT_MS)
29670
+ });
29671
+ } catch (err2) {
29672
+ throw new Error(`confirmation store unreachable: ${err2 instanceof Error ? err2.message : String(err2)}`, {
29673
+ cause: err2
29674
+ });
29675
+ }
29676
+ if (!res.ok) throw new Error(`confirmation store answered HTTP ${res.status} on ${path}`);
29677
+ const body = await res.json().catch(() => void 0);
29678
+ if (!isRecord3(body)) throw new Error(`confirmation store returned a non-JSON body on ${path}`);
29679
+ return body;
29680
+ }
29681
+ };
29682
+ }
29683
+ });
29684
+
29685
+ // ../../src/core/dispatch/route.ts
29686
+ function outputCapWithReasoning(visibleAnswerTokens, opts = {}) {
29687
+ return opts.capField !== void 0 && REASONING_COUNTING_CAP_FIELDS.has(opts.capField) ? visibleAnswerTokens + REASONING_OUTPUT_TOKEN_ALLOWANCE : visibleAnswerTokens;
29688
+ }
29689
+ function outputCapRetry(current) {
29690
+ return Math.max(current * 2, REASONING_OUTPUT_TOKEN_ALLOWANCE);
29691
+ }
29692
+ function routedRunsAtOnce(def, confirm, input) {
29693
+ const radius = input === void 0 ? blastRadius(def) : boundBlastRadius(def, input);
29694
+ return radius === "read" || CONFIRM_ORDER[radius] < CONFIRM_ORDER[confirm];
29695
+ }
29696
+ function routeReceipt(def, input) {
29697
+ return redactAndCap(chatInvocation(def, input), ROUTE_RECEIPT_CAP);
29698
+ }
29699
+ function routablePresets() {
29700
+ return Object.values(AGENTS).filter((a) => a.routable !== false).map(({ name, description, machine, identity: identity2, maxMinutes }) => ({
29701
+ name,
29702
+ description,
29703
+ machine,
29704
+ identity: identity2,
29705
+ maxMinutes
29706
+ }));
29707
+ }
29708
+ function routableCommands(commands) {
29709
+ return commands.list().filter((cmd) => CommandRegistry.exposedTo(cmd, "chat")).map((cmd) => ({
29710
+ id: cmd.id,
29711
+ effect: cmd.effect,
29712
+ def: cmd,
29713
+ tool: { name: mcpToolName(cmd.id), description: cmd.describe, inputSchema: jsonSchemaFor(cmd) }
29714
+ }));
29715
+ }
29716
+ function renderPresetTable(presets) {
29717
+ const rows = presets.map(
29718
+ (p) => `| \`${p.name}\` | ${oneLine(p.description)} | ${p.machine} | ${p.identity} | ${p.maxMinutes} min |`
29719
+ );
29720
+ return ["| name | what it does | machine | credential | budget |", "|---|---|---|---|---|", ...rows].join("\n");
29721
+ }
29722
+ function quoteRequest(text) {
29723
+ const cap = 2e3;
29724
+ const bent = text.replace(/<(\/?)request>/gi, "\u2039$1request\u203A");
29725
+ if (bent.length <= cap) return bent;
29726
+ return `${bent.slice(0, cap)}
29727
+ \u2026[truncated: ${bent.length - cap} more characters]`;
29728
+ }
29729
+ function providerStructuredModel(provider, model, opts = {}) {
29730
+ const forced = (opts.answer ?? "tool") === "tool";
29731
+ return async (prompt, call2) => {
29732
+ const tools = [prompt.tool, ...prompt.tools ?? []];
29733
+ const toolChoice = prompt.open ? void 0 : tools.length > 1 ? { type: "any" } : { type: "tool", name: prompt.tool.name };
29734
+ const messages = [
29735
+ { role: "user", content: [{ type: "text", text: prompt.user }] },
29736
+ ...(prompt.retries ?? []).flatMap((r) => [
29737
+ { role: "assistant", content: [{ type: "text", text: r.answer }] },
29738
+ { role: "user", content: [{ type: "text", text: r.violation }] }
29739
+ ])
29740
+ ];
29741
+ const result = await provider.complete({
29742
+ model,
29743
+ system: prompt.system,
29744
+ messages,
29745
+ maxTokens: call2.maxTokens,
29746
+ signal: call2.signal,
29747
+ // The caller's configured effort, card-decided (`turnEffort`): intake's
29748
+ // `intake.effort` or the operator's `defaults.efforts.general`. Absent →
29749
+ // the model's own default.
29750
+ ...opts.effort ? { effort: opts.effort.effort, effortWord: opts.effort.effortWord } : {},
29751
+ ...forced ? { tools, toolChoice } : {}
29752
+ });
29753
+ if (result.stopReason === "max_tokens") throw new OutputCapError(call2.maxTokens);
29754
+ const calls = result.content.filter(
29755
+ (p) => p.type === "tool_use"
29756
+ );
29757
+ if (calls.length > 1) throw new MultiToolCallError(calls.map((c) => ({ tool: c.name, input: c.input })));
29758
+ if (calls.length === 1) return { tool: calls[0].name, input: calls[0].input };
29759
+ return result.content.filter((p) => p.type === "text").map((p) => p.text).join("");
29760
+ };
29761
+ }
29762
+ async function mintConfirmationOffer(args) {
29763
+ const { io, store, msg, origin, def, input, receipt, model } = args;
29764
+ if (!io.offer || !store) return { kind: "no_click" };
29765
+ const line4 = chatInvocation(def, input);
29766
+ if (redactSecrets(line4) !== line4) return { kind: "unshowable" };
29767
+ const risk = def.annotations?.risk?.(input, origin) ?? "";
29768
+ let row2;
29769
+ try {
29770
+ row2 = await store.put(
29771
+ {
29772
+ kind: "run",
29773
+ id: newConfirmationId(),
29774
+ message: confirmationMessageOf(msg),
29775
+ command: def.id,
29776
+ input,
29777
+ receipt,
29778
+ risk,
29779
+ model
29780
+ },
29781
+ CONFIRMATION_TTL_MS
29782
+ );
29783
+ } catch (err2) {
29784
+ console.warn(
29785
+ `[route] ${msg.threadKey} confirmation store unreachable at mint, handing back: ${err2 instanceof Error ? err2.message : String(err2)}`
29786
+ );
29787
+ return { kind: "store_unreachable" };
29788
+ }
29789
+ return { kind: "offered", shown: { id: row2.id, line: line4, risk, expiresAt: row2.expiresAt } };
29790
+ }
29791
+ function redactedInput(input) {
29792
+ const text = (s) => redactAndCap(redactSecrets(s), 200);
29793
+ const leaf = (v) => {
29794
+ if (typeof v === "string") return text(v);
29795
+ if (typeof v === "number" || typeof v === "boolean" || v === null) return v;
29796
+ return v === void 0 ? null : text(JSON.stringify(v) ?? String(v));
29797
+ };
29798
+ const leafOrList = (v) => Array.isArray(v) ? v.map(leaf) : leaf(v);
29799
+ const isRecord11 = (v) => typeof v === "object" && v !== null && (Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null);
29800
+ const entries = (v, of) => Object.fromEntries(
29801
+ Object.entries(v).filter(([, x]) => x !== void 0).map(([k, x]) => [k, of(x)])
29802
+ );
29803
+ const object1 = (v) => entries(v, leafOrList);
29804
+ const object2 = (v) => entries(v, (x) => isRecord11(x) ? object1(x) : leafOrList(x));
29805
+ const object3 = (v) => entries(v, (x) => isRecord11(x) ? object2(x) : leafOrList(x));
29806
+ return {
29807
+ ...input.args ? { args: input.args.map(leaf) } : {},
29808
+ ...input.options ? { options: object3(input.options) } : {}
29809
+ };
29810
+ }
29811
+ function routeReasonLabel(reason2, collapsed) {
29812
+ return `${ROUTE_REASON_PREFIX} ${reason2}${collapsed ? ` (compound collapsed: ${collapsed.presets.join("+")})` : ""}`;
29813
+ }
29814
+ function routedPartLines(parts) {
29815
+ return parts.map((p) => {
29816
+ const line4 = p.text.replace(/\s+/g, " ").trim();
29817
+ return `${p.preset}: ${line4.length > ROUTE_PART_LINE_CAP ? `${line4.slice(0, ROUTE_PART_LINE_CAP - 1)}\u2026` : line4}`;
29818
+ });
29819
+ }
29820
+ function compoundBrief(text, parts) {
29821
+ return [
29822
+ text,
29823
+ "",
29824
+ `${COMPOUND_BRIEF_HEADING}: ${parts.length} independent parts. Spawn exactly these children \u2014 one \`spawn_run\` per part, on the preset named, with the part's text as the child's whole prompt (add the repository where the preset needs one) \u2014 then \`await_runs\` them all and compile one answer. Do not merge, drop or add a part.`,
29825
+ ...parts.map((p, i) => `${i + 1}. \`${p.preset}\`: ${p.text}`)
29826
+ ].join("\n");
29827
+ }
29828
+ var REASONING_COUNTING_CAP_FIELDS, REASONING_OUTPUT_TOKEN_ALLOWANCE, OutputCapError, ROUTE_REASON_CAP, ROUTE_MIN_OUTPUT_TOKENS, ROUTE_TIMEOUT_MS, ROUTE_PART_LINE_CAP, ROUTE_RECEIPT_CAP, ROUTED_RECEIPT_PREFIX, COMPOUND_BRIEF_HEADING, MultiToolCallError;
29829
+ var init_route = __esm({
29830
+ "../../src/core/dispatch/route.ts"() {
29831
+ "use strict";
29832
+ init_registry();
29833
+ init_handBack();
29834
+ init_profile();
29835
+ init_redact();
29836
+ init_statusCardFrame();
29837
+ init_commandRegistry();
29838
+ init_commandSurface();
29839
+ init_budgets();
29840
+ init_confirmations();
29841
+ REASONING_COUNTING_CAP_FIELDS = /* @__PURE__ */ new Set(["max_tokens", "max_completion_tokens", "max_output_tokens"]);
29842
+ REASONING_OUTPUT_TOKEN_ALLOWANCE = 4096;
29843
+ OutputCapError = class extends Error {
29844
+ constructor(maxTokens) {
29845
+ super(`answer cut at the output cap (${maxTokens} tokens)`);
29846
+ this.maxTokens = maxTokens;
29847
+ this.name = "OutputCapError";
29848
+ }
29849
+ maxTokens;
29850
+ };
29851
+ ROUTE_REASON_CAP = 120;
29852
+ ROUTE_MIN_OUTPUT_TOKENS = 200;
29853
+ ROUTE_TIMEOUT_MS = 8e3;
29854
+ ROUTE_PART_LINE_CAP = 100;
29855
+ ROUTE_RECEIPT_CAP = 300;
29856
+ ROUTED_RECEIPT_PREFIX = "routed:";
29857
+ COMPOUND_BRIEF_HEADING = "Routed as a compound request";
29858
+ MultiToolCallError = class extends Error {
29859
+ constructor(calls) {
29860
+ super(`answer carried ${calls.length} tool calls; the route is one call`);
29861
+ this.calls = calls;
29862
+ this.name = "MultiToolCallError";
29863
+ }
29864
+ calls;
29865
+ };
29866
+ }
29867
+ });
29868
+
29137
29869
  // ../../src/core/memory/reflection.ts
29138
29870
  import { z as z15 } from "zod";
29139
29871
  function shouldReflect(input) {
@@ -29288,13 +30020,14 @@ async function reflect(deps) {
29288
30020
  const seen = /* @__PURE__ */ new Set();
29289
30021
  const existing = [...await windowP, ...hits].filter((r) => !seen.has(r.id) && (seen.add(r.id), true));
29290
30022
  const text = buildReflectionInput({ history: deps.history, request: deps.request, answer: deps.answer, existing });
30023
+ const maxTokens = outputCapWithReasoning(REFLECTION_MAX_TOKENS, { capField: deps.capField });
29291
30024
  let result;
29292
30025
  try {
29293
30026
  result = await deps.provider.complete({
29294
30027
  model: deps.model,
29295
30028
  system: REFLECTION_SYSTEM,
29296
30029
  messages: [{ role: "user", content: [{ type: "text", text }] }],
29297
- maxTokens: REFLECTION_MAX_TOKENS,
30030
+ maxTokens,
29298
30031
  ...deps.effort !== void 0 ? { effort: deps.effort } : {},
29299
30032
  ...deps.effortWord !== void 0 ? { effortWord: deps.effortWord } : {}
29300
30033
  });
@@ -29303,13 +30036,17 @@ async function reflect(deps) {
29303
30036
  warn(`reflection skipped: ${renderProviderFailure(failure2.cause)}`);
29304
30037
  return;
29305
30038
  }
30039
+ const truncated = result.stopReason === "max_tokens" ? `truncated at ${maxTokens} max tokens` : void 0;
30040
+ if (truncated) {
30041
+ warn(`reflection output rejected (${truncated}); nothing written`);
30042
+ return;
30043
+ }
29306
30044
  const reply = result.content.filter((p) => p.type === "text").map((p) => p.text).join("");
29307
30045
  const prov = { sourceThreadKey: deps.sourceThreadKey, sourceRunId: deps.sourceRunId };
29308
30046
  const parsed = parseReflection(reply, prov, new Set(existing.map((r) => r.id)));
29309
- const truncated = result.stopReason === "max_tokens" ? `truncated at ${REFLECTION_MAX_TOKENS} max tokens` : void 0;
29310
- const stopNote = truncated ?? (result.stopReason === "end_turn" ? void 0 : `stop: ${result.stopReason}`);
30047
+ const stopNote = result.stopReason === "end_turn" ? void 0 : `stop: ${result.stopReason}`;
29311
30048
  if (!parsed.ok) {
29312
- const why = truncated ?? (stopNote ? `${parsed.error}; ${stopNote}` : parsed.error);
30049
+ const why = stopNote ? `${parsed.error}; ${stopNote}` : parsed.error;
29313
30050
  warn(`reflection output rejected (${why}); nothing written`);
29314
30051
  return;
29315
30052
  }
@@ -29380,6 +30117,7 @@ var init_reflection = __esm({
29380
30117
  init_authz();
29381
30118
  init_runEvents();
29382
30119
  init_llmOutput();
30120
+ init_route();
29383
30121
  init_engine();
29384
30122
  init_scorer();
29385
30123
  init_scope2();
@@ -29622,10 +30360,13 @@ function scheduleReflection(input) {
29622
30360
  const info = (m) => console.log(`[memory] ${input.threadKey} ${m}`);
29623
30361
  let provider;
29624
30362
  let model;
30363
+ let capField;
29625
30364
  try {
29626
- const ref = parseModelRef(input.cfg.model ?? input.runModelRef);
30365
+ const modelRef3 = input.cfg.model ?? input.runModelRef;
30366
+ const ref = parseModelRef(modelRef3);
29627
30367
  provider = input.providers.get(ref.provider);
29628
30368
  model = ref.model;
30369
+ capField = resolveModelCard(modelRef3, input.providerBlocks ?? {}, installedModelRegistry).capField;
29629
30370
  } catch (err2) {
29630
30371
  warn(`reflection skipped: ${err2 instanceof Error ? err2.message : String(err2)}`);
29631
30372
  return;
@@ -29637,6 +30378,7 @@ function scheduleReflection(input) {
29637
30378
  provider,
29638
30379
  model,
29639
30380
  ...effort2.request ? { effort: effort2.request.effort, effortWord: effort2.request.effortWord } : {},
30381
+ ...capField !== void 0 ? { capField } : {},
29640
30382
  store: selectMemoryStore(input.cfg, input.store),
29641
30383
  scopeKeys: requestScopeKeys(input.organization, input.userId, { channelId: input.channelId, repo: input.repo }),
29642
30384
  actor: reflectionActor(input.actor, { channelId: input.channelId, repo: input.repo }),
@@ -29693,6 +30435,8 @@ var init_memory = __esm({
29693
30435
  "use strict";
29694
30436
  init_provider();
29695
30437
  init_turnEffort();
30438
+ init_installedModelRegistry();
30439
+ init_modelCard();
29696
30440
  init_scorer();
29697
30441
  init_scope2();
29698
30442
  init_stores();
@@ -31208,7 +31952,7 @@ ${line4}` : ""}`
31208
31952
  });
31209
31953
 
31210
31954
  // ../../src/core/reviewAbridge.ts
31211
- import { resolve as resolve9 } from "node:path";
31955
+ import { resolve as resolve10 } from "node:path";
31212
31956
  function meatArtifactOf(record2) {
31213
31957
  return record2.events.find((e) => isReadingDiff(e) && e.poweredBy === "meat");
31214
31958
  }
@@ -31253,7 +31997,7 @@ function reviewAbridgerFromConfig(config, store, secrets, env, dataDir, warn) {
31253
31997
  github: () => github,
31254
31998
  meat: meatOnHost({
31255
31999
  apiKey: () => anthropicApiKey(config().providers, secrets),
31256
- cacheDir: resolve9(dataDir, "meat-cache"),
32000
+ cacheDir: resolve10(dataDir, "meat-cache"),
31257
32001
  hostEnv: { PATH: env.PATH, HOME: env.HOME }
31258
32002
  }),
31259
32003
  defaultModel: () => {
@@ -31725,6 +32469,8 @@ function assembleRunRecord(input) {
31725
32469
  ...seal?.replyNote !== void 0 ? { replyNote: seal.replyNote } : {},
31726
32470
  ...snap !== null ? { stepCount: snap.stepCount } : {},
31727
32471
  status: input.status,
32472
+ ...snap?.liveState !== void 0 ? { liveState: snap.liveState } : {},
32473
+ ...snap?.liveStateSeq !== void 0 ? { liveStateSeq: snap.liveStateSeq } : {},
31728
32474
  eventCount: Math.max(snap?.eventCount ?? atFinish.length, seal?.eventCount ?? 0),
31729
32475
  storedEventCount: events.length,
31730
32476
  truncated: false,
@@ -31908,43 +32654,6 @@ var init_record = __esm({
31908
32654
  }
31909
32655
  });
31910
32656
 
31911
- // ../../src/core/plane/decide.ts
31912
- function endingCauseWords(cause) {
31913
- switch (cause) {
31914
- case "completed":
31915
- return "it completed";
31916
- case "failed":
31917
- return "it failed";
31918
- case "stopped":
31919
- return "it was stopped";
31920
- case "withdrawn":
31921
- return "its wait was withdrawn";
31922
- case "refused":
31923
- return "its admission was refused";
31924
- case "lease_lapsed":
31925
- return "its lease lapsed with no heartbeat";
31926
- case "resident_replaced":
31927
- return "the resident container running it was replaced";
31928
- case "runner_gone":
31929
- return "the runner instance driving it is gone";
31930
- }
31931
- }
31932
- function isReissueSteerText(text) {
31933
- return /^the model provider .+ is answering again — re-issue the held turn and continue$/.test(text.trim());
31934
- }
31935
- function waitingWords(waiting2) {
31936
- if (waiting2.length === 0) return "its turn";
31937
- return waiting2.map(
31938
- (c) => c.kind === "thread_free" ? "the thread's live run" : c.kind === "deploy_settled" ? "the pending deploy" : c.kind === "seat" ? `a seat on ${c.resident}` : c.kind === "memory" ? `memory on ${c.resident}` : c.kind === "provider_up" ? `the ${c.provider} provider` : `the ${c.window} window`
31939
- ).join(", then ");
31940
- }
31941
- var init_decide = __esm({
31942
- "../../src/core/plane/decide.ts"() {
31943
- "use strict";
31944
- init_budgets();
31945
- }
31946
- });
31947
-
31948
32657
  // ../../src/core/runsService.ts
31949
32658
  function runResource(view) {
31950
32659
  return {
@@ -31981,6 +32690,8 @@ function ledgerView(row2, events) {
31981
32690
  ...m.repo !== void 0 ? { repo: m.repo } : {},
31982
32691
  startedAt: row2.startedAt,
31983
32692
  finished: false,
32693
+ ...row2.liveState !== void 0 ? { liveState: row2.liveState } : {},
32694
+ ...row2.liveStateSeq !== void 0 ? { liveStateSeq: row2.liveStateSeq } : {},
31984
32695
  eventCount: events.length,
31985
32696
  ...activity !== void 0 ? { activity } : {},
31986
32697
  ...m.sourceUrl !== void 0 ? { sourceUrl: m.sourceUrl } : {},
@@ -32019,6 +32730,8 @@ function liveView(s) {
32019
32730
  ...s.stepCount !== void 0 ? { stepCount: s.stepCount } : {},
32020
32731
  ...s.schema !== void 0 ? { schema: s.schema } : {},
32021
32732
  ...s.status !== void 0 ? { status: s.status } : {},
32733
+ ...s.liveState !== void 0 ? { liveState: s.liveState } : {},
32734
+ ...s.liveStateSeq !== void 0 ? { liveStateSeq: s.liveStateSeq } : {},
32022
32735
  eventCount: s.eventCount,
32023
32736
  ...s.stop ? { stop: s.stop } : {},
32024
32737
  ...s.activity !== void 0 ? { activity: s.activity } : {},
@@ -32116,7 +32829,7 @@ function createRunsService(deps) {
32116
32829
  const prices = deps.prices ?? NO_PRICES;
32117
32830
  const clock4 = deps.clock ?? systemClock;
32118
32831
  const warn = deps.warn ?? ((m) => console.warn(m));
32119
- const describe12 = (err2) => err2 instanceof Error ? err2.message : String(err2);
32832
+ const describe13 = (err2) => err2 instanceof Error ? err2.message : String(err2);
32120
32833
  let listing;
32121
32834
  const liveRows = () => {
32122
32835
  if (!ledger) return null;
@@ -32136,7 +32849,7 @@ function createRunsService(deps) {
32136
32849
  try {
32137
32850
  rows = await pending2;
32138
32851
  } catch (err2) {
32139
- warn(`[runs] run ledger list failed \u2014 showing this process's runs only: ${describe12(err2)}`);
32852
+ warn(`[runs] run ledger list failed \u2014 showing this process's runs only: ${describe13(err2)}`);
32140
32853
  return [];
32141
32854
  }
32142
32855
  const foreign = rows.filter((row2) => !registry.getById(row2.runId));
@@ -32146,7 +32859,7 @@ function createRunsService(deps) {
32146
32859
  try {
32147
32860
  events = await ledger.readEvents(row2.runId);
32148
32861
  } catch (err2) {
32149
- warn(`[runs] run ledger events read failed for ${row2.runId}: ${describe12(err2)}`);
32862
+ warn(`[runs] run ledger events read failed for ${row2.runId}: ${describe13(err2)}`);
32150
32863
  }
32151
32864
  return ledgerView(row2, events);
32152
32865
  })
@@ -32160,7 +32873,7 @@ function createRunsService(deps) {
32160
32873
  if (!row2) return null;
32161
32874
  return { row: row2, events: await ledger.readEvents(id) };
32162
32875
  } catch (err2) {
32163
- warn(`[runs] run ledger read failed for ${id}: ${describe12(err2)}`);
32876
+ warn(`[runs] run ledger read failed for ${id}: ${describe13(err2)}`);
32164
32877
  return null;
32165
32878
  }
32166
32879
  };
@@ -32183,7 +32896,7 @@ function createRunsService(deps) {
32183
32896
  activity: row2.state === "waiting" ? `queued at position ${row2.position} \u2014 waiting on ${waiting2}` : row2.state === "admitted" ? "admitted \u2014 starting" : "withdrawn"
32184
32897
  };
32185
32898
  } catch (err2) {
32186
- warn(`[runs] plane queued read failed for ${id}: ${describe12(err2)}`);
32899
+ warn(`[runs] plane queued read failed for ${id}: ${describe13(err2)}`);
32187
32900
  return null;
32188
32901
  }
32189
32902
  };
@@ -32201,7 +32914,7 @@ function createRunsService(deps) {
32201
32914
  row2 = await storeSummary(id);
32202
32915
  } catch (err2) {
32203
32916
  warn(
32204
- `[runs] history store read failed for ${id} \u2014 serving the registry row without its record: ${describe12(err2)}`
32917
+ `[runs] history store read failed for ${id} \u2014 serving the registry row without its record: ${describe13(err2)}`
32205
32918
  );
32206
32919
  return {};
32207
32920
  }
@@ -32246,12 +32959,12 @@ function createRunsService(deps) {
32246
32959
  if (marked.ok) runnerStopped = true;
32247
32960
  else warn(`[runs] the runner's stop mark was refused for ${id} (${marked.reason})`);
32248
32961
  } catch (err2) {
32249
- warn(`[runs] the runner's stop mark failed for ${id}: ${describe12(err2)}`);
32962
+ warn(`[runs] the runner's stop mark failed for ${id}: ${describe13(err2)}`);
32250
32963
  }
32251
32964
  try {
32252
32965
  unitRows = await units.listUnits(instanceId);
32253
32966
  } catch (err2) {
32254
- warn(`[runs] unit rows unavailable for the hard stop of ${id}: ${describe12(err2)}`);
32967
+ warn(`[runs] unit rows unavailable for the hard stop of ${id}: ${describe13(err2)}`);
32255
32968
  }
32256
32969
  }
32257
32970
  registry.publish(id, { type: "answer", text: hostedSealAnswer(unitRows, runnerStopped), at: clock4() });
@@ -32297,7 +33010,7 @@ function createRunsService(deps) {
32297
33010
  if (!done.ok) warn(`[runs] run ledger finish refused for ${id} (${done.reason ?? "unknown"})`);
32298
33011
  }
32299
33012
  } catch (err2) {
32300
- warn(`[runs] run ledger finish failed for ${id}: ${describe12(err2)}`);
33013
+ warn(`[runs] run ledger finish failed for ${id}: ${describe13(err2)}`);
32301
33014
  }
32302
33015
  }
32303
33016
  return { ok: true, value: { id, mode: "hard", state: "stopping" } };
@@ -32476,7 +33189,7 @@ function createRunsService(deps) {
32476
33189
  const r = await ledger.requestStop(id, mode);
32477
33190
  if (r.ok) return { ok: true, value: { id, mode, state: "stopping" } };
32478
33191
  } catch (err2) {
32479
- warn(`[runs] run ledger stop failed for ${id}: ${describe12(err2)}`);
33192
+ warn(`[runs] run ledger stop failed for ${id}: ${describe13(err2)}`);
32480
33193
  }
32481
33194
  }
32482
33195
  if (await storeSummary(id)) return conflict;
@@ -32486,7 +33199,7 @@ function createRunsService(deps) {
32486
33199
  if (r.withdrawn) return { ok: true, value: { id, mode, state: "withdrawn" } };
32487
33200
  if (await ledger.planeQueued(id) !== null) return conflict;
32488
33201
  } catch (err2) {
32489
- warn(`[runs] plane withdraw failed for ${id}: ${describe12(err2)}`);
33202
+ warn(`[runs] plane withdraw failed for ${id}: ${describe13(err2)}`);
32490
33203
  }
32491
33204
  }
32492
33205
  return notFound;
@@ -34417,6 +35130,11 @@ var init_runLedgerWorker = __esm({
34417
35130
  if (events.length === 0) return { ok: true };
34418
35131
  return this.fenceResult(await this.post("/runs/append", { storeKey: this.opts.storeKey, runId: runId3, gen, events }));
34419
35132
  }
35133
+ async assignLiveState(runId3, gen, assignment) {
35134
+ this.checkIds(runId3, gen);
35135
+ const r = await this.post("/runs/live-state", { storeKey: this.opts.storeKey, runId: runId3, gen, assignment });
35136
+ return r.data;
35137
+ }
34420
35138
  async setState(runId3, gen, state) {
34421
35139
  this.checkIds(runId3, gen);
34422
35140
  return this.fenceResult(await this.post("/runs/state", { storeKey: this.opts.storeKey, runId: runId3, gen, state }));
@@ -34611,7 +35329,7 @@ var init_githubRepoInspect = __esm({
34611
35329
  });
34612
35330
 
34613
35331
  // ../../src/core/commandCatalogue.ts
34614
- import { existsSync as existsSync12, readFileSync as readFileSync14 } from "node:fs";
35332
+ import { existsSync as existsSync13, readFileSync as readFileSync15 } from "node:fs";
34615
35333
  import { readFile as readFile2 } from "node:fs/promises";
34616
35334
  function unstampedStatus() {
34617
35335
  let version2 = "unknown";
@@ -34636,10 +35354,10 @@ function defaultOperations(config, secrets, caller) {
34636
35354
  return null;
34637
35355
  }
34638
35356
  function readSource(source2) {
34639
- return Promise.resolve(readFileSync14(source2 === "-" ? 0 : source2, "utf8"));
35357
+ return Promise.resolve(readFileSync15(source2 === "-" ? 0 : source2, "utf8"));
34640
35358
  }
34641
35359
  async function readOptionalFile(path) {
34642
- return existsSync12(path) ? readFile2(path, "utf8") : void 0;
35360
+ return existsSync13(path) ? readFile2(path, "utf8") : void 0;
34643
35361
  }
34644
35362
  function once(provided) {
34645
35363
  if (typeof provided !== "function") {
@@ -35116,232 +35834,6 @@ var init_trace = __esm({
35116
35834
  }
35117
35835
  });
35118
35836
 
35119
- // ../../src/core/confirmations.ts
35120
- import { randomUUID } from "node:crypto";
35121
- import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
35122
- import { dirname as dirname10, resolve as resolve10 } from "node:path";
35123
- function newConfirmationId() {
35124
- return randomUUID();
35125
- }
35126
- function renderOffer(offer) {
35127
- if (offer.question) return `${offer.question.text}
35128
- Did you mean:
35129
- \`${offer.line}\`
35130
-
35131
- ${offer.question.evidence}`;
35132
- return [offer.line, ...offer.risk ? [offer.risk] : []].join("\n");
35133
- }
35134
- function confirmationMessageOf(msg) {
35135
- const { images: _images, documents: _documents, staged: _staged, ...kept } = msg;
35136
- return kept;
35137
- }
35138
- function isRecord3(v) {
35139
- return typeof v === "object" && v !== null && !Array.isArray(v);
35140
- }
35141
- function isMessage(v) {
35142
- return isRecord3(v) && typeof v.channelId === "string" && typeof v.userId === "string" && typeof v.threadKey === "string" && typeof v.text === "string";
35143
- }
35144
- function isRunShape(v) {
35145
- return typeof v.id === "string" && isMessage(v.message) && typeof v.command === "string" && isRecord3(v.input) && typeof v.receipt === "string" && typeof v.risk === "string" && typeof v.model === "string";
35146
- }
35147
- function isRedispatchShape(v) {
35148
- return typeof v.id === "string" && isMessage(v.message) && typeof v.line === "string" && typeof v.evidence === "string" && typeof v.code === "string";
35149
- }
35150
- function parsePendingConfirmation(v) {
35151
- if (!isRecord3(v)) return void 0;
35152
- if (v.kind === "redispatch")
35153
- return isRedispatchShape(v) ? v : void 0;
35154
- if (v.kind !== void 0 && v.kind !== "run") return void 0;
35155
- return isRunShape(v) ? { ...v, kind: "run" } : void 0;
35156
- }
35157
- function parseConfirmation(v) {
35158
- if (!isRecord3(v) || typeof v.expiresAt !== "number") return void 0;
35159
- const pending2 = parsePendingConfirmation(v);
35160
- return pending2 ? { ...pending2, expiresAt: v.expiresAt } : void 0;
35161
- }
35162
- function isRefusal(v) {
35163
- return typeof v === "string" && CONFIRMATION_REFUSALS.includes(v);
35164
- }
35165
- function judge2(rows, id, actorIds, now, kind) {
35166
- const row2 = rows.get(id);
35167
- if (!row2) return { ok: false, refused: "used" };
35168
- if (kind === "consume" && row2.expiresAt <= now) {
35169
- rows.delete(id);
35170
- return { ok: false, refused: "expired", row: row2 };
35171
- }
35172
- if (!actorIds.includes(row2.message.userId))
35173
- return kind === "consume" ? { ok: false, refused: "foreign", row: row2 } : { ok: false, refused: "foreign" };
35174
- rows.delete(id);
35175
- return kind === "consume" ? { ok: true, row: row2 } : { ok: true };
35176
- }
35177
- function replaceThreadRow(rows, row2) {
35178
- for (const [id, r] of rows) if (r.message.threadKey === row2.message.threadKey) rows.delete(id);
35179
- rows.set(row2.id, row2);
35180
- }
35181
- function threadRowId(rows, threadKey) {
35182
- for (const [id, r] of rows) if (r.message.threadKey === threadKey) return id;
35183
- return void 0;
35184
- }
35185
- function buildConfirmationStore(config, secrets, opts) {
35186
- const worker = config.config.runtimeOverrides?.worker;
35187
- if (!worker) return new FileConfirmationStore(opts.path);
35188
- const tokenEnv = worker.tokenEnv ?? "MEMORY_TOKEN";
35189
- const token2 = secrets.named(tokenEnv);
35190
- if (!token2) throw new Error(`runtimeOverrides.worker is configured but ${tokenEnv} is not set`);
35191
- return new WorkerConfirmationStore({
35192
- baseUrl: worker.baseUrl,
35193
- token: token2.reveal(),
35194
- ...opts.fetch ? { fetch: opts.fetch } : {}
35195
- });
35196
- }
35197
- var CONFIRMATION_REFUSALS, UNSHOWABLE_LINE, STORE_UNREACHABLE_LINE, FileConfirmationStore, CONFIRMATION_WORKER_TIMEOUT_MS, WorkerConfirmationStore;
35198
- var init_confirmations = __esm({
35199
- "../../src/core/confirmations.ts"() {
35200
- "use strict";
35201
- init_clock();
35202
- CONFIRMATION_REFUSALS = ["used", "expired", "foreign"];
35203
- UNSHOWABLE_LINE = "this command carries a value that cannot be shown, so no confirmation can be offered; nothing ran";
35204
- STORE_UNREACHABLE_LINE = "this command needs a confirmation click, and the confirmation store could not be reached; nothing ran \u2014 ask again for the button";
35205
- FileConfirmationStore = class {
35206
- path;
35207
- clock;
35208
- constructor(path, opts = {}) {
35209
- this.path = resolve10(path);
35210
- this.clock = opts.clock ?? systemClock;
35211
- }
35212
- read() {
35213
- const rows = /* @__PURE__ */ new Map();
35214
- if (!existsSync13(this.path)) return rows;
35215
- const raw = JSON.parse(readFileSync15(this.path, "utf8"));
35216
- for (const v of Array.isArray(raw.confirmations) ? raw.confirmations : []) {
35217
- const row2 = parseConfirmation(v);
35218
- if (row2) rows.set(row2.id, row2);
35219
- }
35220
- return rows;
35221
- }
35222
- write(rows) {
35223
- mkdirSync9(dirname10(this.path), { recursive: true });
35224
- writeFileSync8(this.path, JSON.stringify({ confirmations: [...rows.values()] }, null, 2));
35225
- }
35226
- async put(row2, ttlMs) {
35227
- const rows = this.read();
35228
- const stored = { ...row2, expiresAt: this.clock() + ttlMs };
35229
- replaceThreadRow(rows, stored);
35230
- this.write(rows);
35231
- return stored;
35232
- }
35233
- async consume(id, actorIds) {
35234
- const rows = this.read();
35235
- const out = judge2(rows, id, actorIds, this.clock(), "consume");
35236
- this.write(rows);
35237
- return out;
35238
- }
35239
- async cancel(id, actorIds) {
35240
- const rows = this.read();
35241
- const out = judge2(rows, id, actorIds, this.clock(), "cancel");
35242
- this.write(rows);
35243
- return out;
35244
- }
35245
- async cancelByThread(threadKey, actorIds) {
35246
- const rows = this.read();
35247
- const id = threadRowId(rows, threadKey);
35248
- if (id === void 0) return { ok: false, refused: "used" };
35249
- const out = judge2(rows, id, actorIds, this.clock(), "cancel");
35250
- this.write(rows);
35251
- return out;
35252
- }
35253
- async pendingByThread(threadKey) {
35254
- const rows = this.read();
35255
- const id = threadRowId(rows, threadKey);
35256
- const row2 = id === void 0 ? void 0 : rows.get(id);
35257
- if (!row2 || row2.expiresAt <= this.clock()) return void 0;
35258
- return row2;
35259
- }
35260
- describe() {
35261
- return `file ${this.path}`;
35262
- }
35263
- };
35264
- CONFIRMATION_WORKER_TIMEOUT_MS = 8e3;
35265
- WorkerConfirmationStore = class {
35266
- constructor(opts) {
35267
- this.opts = opts;
35268
- this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
35269
- this.fetchImpl = opts.fetch ?? fetch;
35270
- }
35271
- opts;
35272
- baseUrl;
35273
- fetchImpl;
35274
- async put(row2, ttlMs) {
35275
- const body = await this.post("/config/confirmations/put", {
35276
- id: row2.id,
35277
- threadKey: row2.message.threadKey,
35278
- requester: row2.message.userId,
35279
- body: row2,
35280
- ttlMs
35281
- });
35282
- if (typeof body.expiresAt !== "number")
35283
- throw new Error("confirmation store answered a put without the expiry it stamped");
35284
- return { ...row2, expiresAt: body.expiresAt };
35285
- }
35286
- async consume(id, actorIds) {
35287
- const body = await this.post("/config/confirmations/consume", { id, actorIds });
35288
- const stored = isRecord3(body.row) ? body.row : void 0;
35289
- const row2 = parseConfirmation(
35290
- stored && isRecord3(stored.body) ? { ...stored.body, expiresAt: stored.expiresAt } : void 0
35291
- );
35292
- if (isRefusal(body.refused))
35293
- return { ok: false, refused: body.refused, ...row2 ? { row: row2 } : {} };
35294
- if (!row2) throw new Error("confirmation store answered a consume outside its contract");
35295
- return { ok: true, row: row2 };
35296
- }
35297
- async cancel(id, actorIds) {
35298
- const body = await this.post("/config/confirmations/cancel", { id, actorIds });
35299
- if (body.ok === true) return { ok: true };
35300
- if (body.refused === "used" || body.refused === "foreign") return { ok: false, refused: body.refused };
35301
- throw new Error("confirmation store answered a cancel outside its contract");
35302
- }
35303
- async cancelByThread(threadKey, actorIds) {
35304
- const body = await this.post("/config/confirmations/cancel-by-thread", { threadKey, actorIds });
35305
- if (body.ok === true) return { ok: true };
35306
- if (body.refused === "used" || body.refused === "foreign") return { ok: false, refused: body.refused };
35307
- throw new Error("confirmation store answered a cancel-by-thread outside its contract");
35308
- }
35309
- async pendingByThread(threadKey) {
35310
- const body = await this.post("/config/confirmations/pending-by-thread", { threadKey });
35311
- if (body.row === null) return void 0;
35312
- const stored = isRecord3(body.row) ? body.row : void 0;
35313
- const row2 = parseConfirmation(
35314
- stored && isRecord3(stored.body) ? { ...stored.body, expiresAt: stored.expiresAt } : void 0
35315
- );
35316
- if (!row2) throw new Error("confirmation store answered a pending-by-thread outside its contract");
35317
- return row2;
35318
- }
35319
- describe() {
35320
- return `state Worker ${this.baseUrl} (ConfigDO confirmations)`;
35321
- }
35322
- async post(path, payload2) {
35323
- let res;
35324
- try {
35325
- res = await this.fetchImpl(`${this.baseUrl}${path}`, {
35326
- method: "POST",
35327
- headers: { authorization: `Bearer ${this.opts.token}`, "content-type": "application/json" },
35328
- body: JSON.stringify(payload2),
35329
- signal: AbortSignal.timeout(CONFIRMATION_WORKER_TIMEOUT_MS)
35330
- });
35331
- } catch (err2) {
35332
- throw new Error(`confirmation store unreachable: ${err2 instanceof Error ? err2.message : String(err2)}`, {
35333
- cause: err2
35334
- });
35335
- }
35336
- if (!res.ok) throw new Error(`confirmation store answered HTTP ${res.status} on ${path}`);
35337
- const body = await res.json().catch(() => void 0);
35338
- if (!isRecord3(body)) throw new Error(`confirmation store returned a non-JSON body on ${path}`);
35339
- return body;
35340
- }
35341
- };
35342
- }
35343
- });
35344
-
35345
35837
  // ../../src/core/markdownDocument.ts
35346
35838
  function toMarkdownDocument(text) {
35347
35839
  return text.replace(/[\uE000\uE001]/g, "").split(/(```[\s\S]*?```)/g).map((seg, i) => i % 2 === 1 ? seg : hardBreaks(convertProse(seg))).join("");
@@ -35471,6 +35963,9 @@ function activityLine(e) {
35471
35963
  case "lease":
35472
35964
  return "lease started";
35473
35965
  // the harness's clocks: head material the run loop keeps off the card — never arrives here
35966
+ case "run_state":
35967
+ return "";
35968
+ // Existing renderers stay until the surface cutover to the shared wording table.
35474
35969
  case "skill_use":
35475
35970
  return `\u{1F4DA} skill ${e.skill} loaded`;
35476
35971
  case "artifact":
@@ -36414,7 +36909,7 @@ async function attachRoundWorkspace(input) {
36414
36909
  ...input.round.stopSignal !== void 0 ? { stopSignal: input.round.stopSignal } : {},
36415
36910
  ...input.round.remainingMs !== void 0 ? { remainingMs: input.round.remainingMs } : {},
36416
36911
  ...input.round.requester !== void 0 ? { requester: input.round.requester } : {},
36417
- ...input.round.onSetupNote !== void 0 ? { onSetupNote: input.round.onSetupNote } : {}
36912
+ ...input.round.onLiveStateObservation !== void 0 ? { onLiveStateObservation: input.round.onLiveStateObservation } : {}
36418
36913
  },
36419
36914
  input.span
36420
36915
  );
@@ -36463,30 +36958,62 @@ function checkPrHeadPreflight(input) {
36463
36958
  async function guardAttachedHead(input) {
36464
36959
  const expected = normalizeHead(input.expectedHeadSha);
36465
36960
  if (!expected) return { outcome: "unverified" };
36466
- const attached = normalizeHead(input.attached.sha);
36467
- const source2 = input.attached.source ?? "workspace-observed";
36468
36961
  const where = `${input.pr.repo}#${input.pr.number}`;
36469
- const branch2 = input.attached.ref ?? input.fallbackRef;
36470
- const namedSource = source2 === "resident binding" ? branch2 ? `${source2} for ${branch2}` : source2 : branch2 ? `${source2} HEAD for ${branch2}` : `${source2} HEAD`;
36471
- if (!attached) {
36472
- console.log(`[review] ${input.logKey} not started: ${namedSource} unreadable, PR head ${expected} (${where})`);
36962
+ const namedSource = (observed) => {
36963
+ const source3 = observed.source ?? "workspace-observed";
36964
+ const branch2 = observed.ref ?? input.fallbackRef;
36965
+ return source3 === "resident binding" ? branch2 ? `${source3} for ${branch2}` : source3 : branch2 ? `${source3} HEAD for ${branch2}` : `${source3} HEAD`;
36966
+ };
36967
+ const first = normalizeHead(input.attached.sha);
36968
+ if (first && sameCommit(expected, first)) return { outcome: "verified" };
36969
+ if (first) {
36970
+ const current = normalizeHead(await input.fetchPrHead(input.pr).catch(() => void 0));
36971
+ if (current && sameCommit(first, current)) {
36972
+ console.log(
36973
+ `[review] ${input.logKey} PR head moved since resolution: ${expected} \u2192 ${current}; the ${namedSource(input.attached)} is at the current head \u2014 reviewing it (${where})`
36974
+ );
36975
+ return { outcome: "adopted", headSha: current };
36976
+ }
36977
+ }
36978
+ let retried;
36979
+ let reprovisionFailed = false;
36980
+ try {
36981
+ retried = await input.reprovision(expected);
36982
+ } catch {
36983
+ reprovisionFailed = true;
36984
+ retried = { sha: void 0 };
36985
+ }
36986
+ const checked = normalizeHead(retried.sha);
36987
+ if (checked && sameCommit(expected, checked)) {
36988
+ console.log(`[review] ${input.logKey} workspace reprovisioned at reviewed head ${expected} (${where})`);
36989
+ return { outcome: "verified" };
36990
+ }
36991
+ const initial = first ? `the initial ${namedSource(input.attached)} was at ${first}` : `the initial ${namedSource(input.attached)} could not be read`;
36992
+ if (reprovisionFailed) {
36993
+ console.log(
36994
+ `[review] ${input.logKey} not started: ${initial}; reprovision failed before retry HEAD observation, expected reviewed head ${expected} (${where})`
36995
+ );
36473
36996
  return {
36474
36997
  outcome: "refused",
36475
- reply: `\u{1F500} Review of ${where} not started: ${namedSource} could not be read, so the workspace cannot be verified against PR head ${expected}. This is a bug: the infrastructure failure was not retried automatically. It is not a finding, and nothing was posted to GitHub.`
36998
+ reply: `\u{1F500} Review of ${where} not started: ${initial}, and the automatic reprovision failed before a retry HEAD could be observed; the expected reviewed head is ${expected}. It is not a finding, and nothing was posted to GitHub.`
36476
36999
  };
36477
37000
  }
36478
- if (sameCommit(expected, attached)) return { outcome: "verified" };
36479
- const current = normalizeHead(await input.fetchPrHead(input.pr).catch(() => void 0));
36480
- if (current && sameCommit(attached, current)) {
37001
+ const source2 = namedSource(retried);
37002
+ if (!checked) {
36481
37003
  console.log(
36482
- `[review] ${input.logKey} PR head moved since resolution: ${expected} \u2192 ${current}; the ${namedSource} is at the current head \u2014 reviewing it (${where})`
37004
+ `[review] ${input.logKey} not started: ${initial}; ${source2} unreadable after reprovision, expected reviewed head ${expected} (${where})`
36483
37005
  );
36484
- return { outcome: "adopted", headSha: current };
37006
+ return {
37007
+ outcome: "refused",
37008
+ reply: `\u{1F500} Review of ${where} not started: ${initial}, and the ${source2} could not be read after one automatic reprovision, so it could not be verified; the expected reviewed head is ${expected}. It is not a finding, and nothing was posted to GitHub.`
37009
+ };
36485
37010
  }
36486
- console.log(`[review] ${input.logKey} not started: ${namedSource} ${attached}, PR head ${expected} (${where})`);
37011
+ console.log(
37012
+ `[review] ${input.logKey} not started: ${source2} ${checked} after reprovision, expected reviewed head ${expected} (${where})`
37013
+ );
36487
37014
  return {
36488
37015
  outcome: "refused",
36489
- reply: `\u{1F500} Review of ${where} not started: the ${namedSource} is at ${attached}, but the PR head is ${expected} \u2014 the branch moved while the workspace was being prepared (a push or force-push). This is a bug: the workspace was not reprovisioned automatically at the new head. It is not a finding, and nothing was posted to GitHub.`
37016
+ reply: `\u{1F500} Review of ${where} not started: after one automatic reprovision, the ${source2} is at ${checked}, but the expected reviewed head is ${expected}. It is not a finding, and nothing was posted to GitHub.`
36490
37017
  };
36491
37018
  }
36492
37019
  function makeSystemComposer(input) {
@@ -36964,14 +37491,19 @@ async function authorizePrHead(ctx) {
36964
37491
  }
36965
37492
  return { kind: "allowed" };
36966
37493
  }
37494
+ function reviewCheckoutFacts(repoCtx) {
37495
+ return {
37496
+ remote: `https://github.com/${repoCtx.repo}.git`,
37497
+ helper: `!f() { test -n "$GH_TOKEN" || exit 1; printf '%s\\n' 'username=x-access-token' "password=$GH_TOKEN"; }; f`,
37498
+ refspecs: [
37499
+ "+HEAD:refs/remotes/origin/HEAD",
37500
+ `+refs/pull/${repoCtx.pr}/head:refs/remotes/origin/pull/${repoCtx.pr}/head`,
37501
+ ...repoCtx.baseRef ? [`+refs/heads/${repoCtx.baseRef}:refs/remotes/origin/${repoCtx.baseRef}`] : []
37502
+ ]
37503
+ };
37504
+ }
36967
37505
  function coldReviewCheckoutCommand(repoCtx) {
36968
- const remote = `https://github.com/${repoCtx.repo}.git`;
36969
- const helper = `!f() { test -n "$GH_TOKEN" || exit 1; printf '%s\\n' 'username=x-access-token' "password=$GH_TOKEN"; }; f`;
36970
- const refspecs = [
36971
- "+HEAD:refs/remotes/origin/HEAD",
36972
- `+refs/pull/${repoCtx.pr}/head:refs/remotes/origin/pull/${repoCtx.pr}/head`,
36973
- ...repoCtx.baseRef ? [`+refs/heads/${repoCtx.baseRef}:refs/remotes/origin/${repoCtx.baseRef}`] : []
36974
- ];
37506
+ const { remote, helper, refspecs } = reviewCheckoutFacts(repoCtx);
36975
37507
  return [
36976
37508
  "set -eu",
36977
37509
  "find . -mindepth 1 -maxdepth 1 ! -name attachments -exec rm -rf -- {} +",
@@ -36981,6 +37513,15 @@ function coldReviewCheckoutCommand(repoCtx) {
36981
37513
  `git checkout --detach --force ${shellQuote(repoCtx.headSha)}`
36982
37514
  ].join("\n");
36983
37515
  }
37516
+ function seededReviewCheckoutCommand(repoCtx, workspace) {
37517
+ const { helper, refspecs } = reviewCheckoutFacts(repoCtx);
37518
+ const git2 = `git -C ${shellQuote(workspace)}`;
37519
+ return [
37520
+ "set -eu",
37521
+ `${git2} -c credential.helper= -c credential.helper=${shellQuote(helper)} fetch --force --no-tags origin ${refspecs.map(shellQuote).join(" ")}`,
37522
+ `${git2} checkout --detach --force ${shellQuote(repoCtx.headSha)}`
37523
+ ].join("\n");
37524
+ }
36984
37525
  async function authorizeAttachedHead(deps, ctx) {
36985
37526
  const { msg, refuse: refuse3, card, shell, closeLines, clock: clock4, agent, resume, selection, root } = ctx;
36986
37527
  const { executor, resident, binding } = selection;
@@ -36991,7 +37532,6 @@ async function authorizeAttachedHead(deps, ctx) {
36991
37532
  const pr = { repo: repoCtx.repo, number: repoCtx.pr };
36992
37533
  const expectedHeadSha = repoCtx.headSha;
36993
37534
  const guard = await root.span("dispatch.gate.attached_head", async (span) => {
36994
- const source2 = resident && binding?.sha !== void 0 ? "resident binding" : "workspace-observed";
36995
37535
  const command2 = selection.seeded?.workspace ? `git -C ${shellQuote(selection.seeded.workspace)} rev-parse HEAD` : "git rev-parse HEAD";
36996
37536
  if (!resident && selection.seeded === void 0 && expectedHeadSha !== void 0) {
36997
37537
  await executor.exec(
@@ -36999,13 +37539,48 @@ async function authorizeAttachedHead(deps, ctx) {
36999
37539
  { timeoutMs: BASH_TIMEOUT_MAX_MS }
37000
37540
  );
37001
37541
  }
37002
- const sha = source2 === "resident binding" ? binding?.sha : await executor.exec(command2, { timeoutMs: 3e4 }).then(parseRevParseOutput).catch(() => void 0);
37542
+ const observeHead = () => executor.exec(command2, { timeoutMs: 3e4, span }).then(parseRevParseOutput).catch(() => void 0);
37543
+ const sha = await observeHead();
37003
37544
  const g = await guardAttachedHead({
37004
37545
  pr,
37005
37546
  expectedHeadSha,
37006
- attached: { sha, ref: binding?.ref ?? repoCtx.ref, source: source2 },
37547
+ attached: { sha, ref: binding?.ref ?? repoCtx.ref, source: "workspace-observed" },
37007
37548
  fallbackRef: repoCtx.ref,
37008
37549
  fetchPrHead: deps.fetchPrHead ?? currentPrHeadSha,
37550
+ reprovision: async (headSha) => {
37551
+ if (executor.moveTo) {
37552
+ await executor.moveTo(headSha, { span });
37553
+ const observedSha = await observeHead();
37554
+ if (selection.binding && observedSha !== void 0) {
37555
+ selection.binding = {
37556
+ ...selection.binding,
37557
+ ref: repoCtx.ref ?? selection.binding.ref,
37558
+ sha: observedSha
37559
+ };
37560
+ }
37561
+ return {
37562
+ sha: observedSha,
37563
+ ref: repoCtx.ref,
37564
+ source: "workspace-observed"
37565
+ };
37566
+ }
37567
+ if (selection.seeded?.workspace) {
37568
+ await executor.exec(
37569
+ seededReviewCheckoutCommand(
37570
+ { ...repoCtx, repo: pr.repo, pr: pr.number, headSha },
37571
+ selection.seeded.workspace
37572
+ ),
37573
+ { timeoutMs: BASH_TIMEOUT_MAX_MS, span }
37574
+ );
37575
+ } else {
37576
+ await executor.exec(coldReviewCheckoutCommand({ ...repoCtx, repo: pr.repo, pr: pr.number, headSha }), {
37577
+ timeoutMs: BASH_TIMEOUT_MAX_MS,
37578
+ span
37579
+ });
37580
+ }
37581
+ const retried = await observeHead();
37582
+ return { sha: retried, ref: repoCtx.ref, source: "workspace-observed" };
37583
+ },
37009
37584
  logKey: msg.threadKey
37010
37585
  });
37011
37586
  span.setAttrs({ outcome: g.outcome });
@@ -37018,14 +37593,19 @@ async function authorizeAttachedHead(deps, ctx) {
37018
37593
  verifiedAtAttach = true;
37019
37594
  headAdopted = true;
37020
37595
  } else if (guard.outcome === "refused") {
37021
- await refuse3(refusalOf("branch_moved", guard.reply), async () => {
37596
+ await refuse3(refusalOf("workspace_head_mismatch", guard.reply), async () => {
37022
37597
  if (executor.release) await executor.release("always").catch(() => {
37023
37598
  });
37024
37599
  await card.done(
37025
- shell.close({ kind: "not_started", icon: "\u{1F500}", reason: "branch moved", ...closeLines(clock4(), false) })
37600
+ shell.close({
37601
+ kind: "not_started",
37602
+ icon: "\u{1F500}",
37603
+ reason: "workspace head mismatch",
37604
+ ...closeLines(clock4(), false)
37605
+ })
37026
37606
  );
37027
37607
  });
37028
- return { kind: "refused", reason: "branch_moved" };
37608
+ return { kind: "refused", reason: "workspace_head_mismatch" };
37029
37609
  }
37030
37610
  }
37031
37611
  return { kind: "allowed", repoCtx, verifiedAtAttach, headAdopted };
@@ -37418,6 +37998,10 @@ var init_threadAdmission = __esm({
37418
37998
  get size() {
37419
37999
  return this.pending.length;
37420
38000
  }
38001
+ /** The ledger seqs of the follow-ups still pending, oldest first. */
38002
+ get pendingSeqs() {
38003
+ return this.pending.flatMap((input) => input.ledgerSeq !== void 0 ? [input.ledgerSeq] : []);
38004
+ }
37421
38005
  };
37422
38006
  ThreadAdmission = class {
37423
38007
  live = /* @__PURE__ */ new Map();
@@ -38085,279 +38669,6 @@ var init_commandChat = __esm({
38085
38669
  }
38086
38670
  });
38087
38671
 
38088
- // ../../src/core/dispatch/handBack.ts
38089
- function renderHandBackLine(line4) {
38090
- return `${HAND_BACK_PREFIX}
38091
- \`${line4}\``;
38092
- }
38093
- var HAND_BACK_PREFIX;
38094
- var init_handBack = __esm({
38095
- "../../src/core/dispatch/handBack.ts"() {
38096
- "use strict";
38097
- HAND_BACK_PREFIX = "To run this:";
38098
- }
38099
- });
38100
-
38101
- // ../../src/core/statusCardFrame.ts
38102
- function activityText(activity) {
38103
- if (!activity) return void 0;
38104
- if (activity.kind === "line") return activity.text;
38105
- return `\u2192 $ ${activity.command.replace(/\s+/g, " ").trim()}`;
38106
- }
38107
- function createCardShell(opts) {
38108
- const verbosity2 = opts.verbosity ?? DEFAULT_VERBOSITY;
38109
- const notes = [];
38110
- let link = opts.link;
38111
- let frame2 = 0;
38112
- let finishedAt;
38113
- let setupLabel;
38114
- const lead = opts.lead ?? [];
38115
- const base = () => opts.model !== void 0 && shows(verbosity2, "verbose") ? `${opts.label} on \`${opts.model}\`` : opts.label;
38116
- const label = () => [base(), ...notes.filter((n2) => shows(verbosity2, n2.level)).map((n2) => n2.text)].join(" \xB7 ");
38117
- const elapsed2 = () => formatDuration((finishedAt ?? opts.now()) - opts.startedAt, "clock");
38118
- const headline = (icon) => `${icon} ${label()} \xB7 ${elapsed2()}`;
38119
- const closeDetail = (close, own) => [...shows(verbosity2, "debug") ? [close.shape, close.queued] : [], own].filter(Boolean).join("\n") || void 0;
38120
- return {
38121
- get label() {
38122
- return label();
38123
- },
38124
- note(level, text) {
38125
- notes.push({ level, text });
38126
- },
38127
- setLink(next) {
38128
- link = next;
38129
- },
38130
- freeze(at) {
38131
- finishedAt = at;
38132
- },
38133
- setSetupLabel(next) {
38134
- setupLabel = next;
38135
- },
38136
- ack() {
38137
- const detail = lead.join("\n");
38138
- return { title: `\u{1F440} ${label()} \xB7 preparing workspace\u2026`, ...detail ? { detail } : {} };
38139
- },
38140
- live(parts = {}) {
38141
- const glyph = SPINNER_GLYPHS[frame2++ % SPINNER_GLYPHS.length];
38142
- const detail = [...lead, ...parts.detail ?? []].filter(Boolean).join("\n");
38143
- return {
38144
- title: headline(glyph) + (setupLabel ? ` \u2014 ${setupLabel}` : "") + (parts.suffix ?? "") + (parts.notice ? ` \xB7 ${parts.notice}` : ""),
38145
- detail: detail || void 0,
38146
- ...parts.activity ? { activity: parts.activity } : {},
38147
- link
38148
- };
38149
- },
38150
- close(close) {
38151
- const detail = closeDetail(close, close.kind === "done" ? close.detail : void 0);
38152
- switch (close.kind) {
38153
- case "done":
38154
- return { title: headline(close.icon), detail, link };
38155
- case "not_started":
38156
- return { title: `${close.icon} ${label()} \xB7 not started (${close.reason}) \xB7 ${elapsed2()}`, detail };
38157
- case "refused":
38158
- return { title: `${close.icon} ${label()} \xB7 ${close.reason} \xB7 ${elapsed2()}`, detail };
38159
- case "setup_failed":
38160
- return { title: `\u274C setup failed \xB7 ${close.reason} \xB7 ${elapsed2()}`, detail };
38161
- }
38162
- }
38163
- };
38164
- }
38165
- var SPINNER_GLYPHS, LIVE_CARD_PREFIXES, ROUTE_REASON_PREFIX;
38166
- var init_statusCardFrame = __esm({
38167
- "../../src/core/statusCardFrame.ts"() {
38168
- "use strict";
38169
- init_formatDuration();
38170
- init_verbosity();
38171
- SPINNER_GLYPHS = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
38172
- LIVE_CARD_PREFIXES = [...SPINNER_GLYPHS, "\u{1F440}"];
38173
- ROUTE_REASON_PREFIX = "route reason:";
38174
- }
38175
- });
38176
-
38177
- // ../../src/core/dispatch/route.ts
38178
- function outputCapWithReasoning(visibleAnswerTokens, opts = {}) {
38179
- return opts.capField !== void 0 && REASONING_COUNTING_CAP_FIELDS.has(opts.capField) ? visibleAnswerTokens + REASONING_OUTPUT_TOKEN_ALLOWANCE : visibleAnswerTokens;
38180
- }
38181
- function outputCapRetry(current) {
38182
- return Math.max(current * 2, REASONING_OUTPUT_TOKEN_ALLOWANCE);
38183
- }
38184
- function routedRunsAtOnce(def, confirm, input) {
38185
- const radius = input === void 0 ? blastRadius(def) : boundBlastRadius(def, input);
38186
- return radius === "read" || CONFIRM_ORDER[radius] < CONFIRM_ORDER[confirm];
38187
- }
38188
- function routeReceipt(def, input) {
38189
- return redactAndCap(chatInvocation(def, input), ROUTE_RECEIPT_CAP);
38190
- }
38191
- function routablePresets() {
38192
- return Object.values(AGENTS).filter((a) => a.routable !== false).map(({ name, description, machine, identity: identity2, maxMinutes }) => ({
38193
- name,
38194
- description,
38195
- machine,
38196
- identity: identity2,
38197
- maxMinutes
38198
- }));
38199
- }
38200
- function routableCommands(commands) {
38201
- return commands.list().filter((cmd) => CommandRegistry.exposedTo(cmd, "chat")).map((cmd) => ({
38202
- id: cmd.id,
38203
- effect: cmd.effect,
38204
- def: cmd,
38205
- tool: { name: mcpToolName(cmd.id), description: cmd.describe, inputSchema: jsonSchemaFor(cmd) }
38206
- }));
38207
- }
38208
- function renderPresetTable(presets) {
38209
- const rows = presets.map(
38210
- (p) => `| \`${p.name}\` | ${oneLine(p.description)} | ${p.machine} | ${p.identity} | ${p.maxMinutes} min |`
38211
- );
38212
- return ["| name | what it does | machine | credential | budget |", "|---|---|---|---|---|", ...rows].join("\n");
38213
- }
38214
- function quoteRequest(text) {
38215
- const cap = 2e3;
38216
- const bent = text.replace(/<(\/?)request>/gi, "\u2039$1request\u203A");
38217
- if (bent.length <= cap) return bent;
38218
- return `${bent.slice(0, cap)}
38219
- \u2026[truncated: ${bent.length - cap} more characters]`;
38220
- }
38221
- function providerStructuredModel(provider, model, opts = {}) {
38222
- const forced = (opts.answer ?? "tool") === "tool";
38223
- return async (prompt, call2) => {
38224
- const tools = [prompt.tool, ...prompt.tools ?? []];
38225
- const toolChoice = prompt.open ? void 0 : tools.length > 1 ? { type: "any" } : { type: "tool", name: prompt.tool.name };
38226
- const messages = [
38227
- { role: "user", content: [{ type: "text", text: prompt.user }] },
38228
- ...(prompt.retries ?? []).flatMap((r) => [
38229
- { role: "assistant", content: [{ type: "text", text: r.answer }] },
38230
- { role: "user", content: [{ type: "text", text: r.violation }] }
38231
- ])
38232
- ];
38233
- const result = await provider.complete({
38234
- model,
38235
- system: prompt.system,
38236
- messages,
38237
- maxTokens: call2.maxTokens,
38238
- signal: call2.signal,
38239
- // The caller's configured effort, card-decided (`turnEffort`): intake's
38240
- // `intake.effort` or the operator's `defaults.efforts.general`. Absent →
38241
- // the model's own default.
38242
- ...opts.effort ? { effort: opts.effort.effort, effortWord: opts.effort.effortWord } : {},
38243
- ...forced ? { tools, toolChoice } : {}
38244
- });
38245
- if (result.stopReason === "max_tokens") throw new OutputCapError(call2.maxTokens);
38246
- const calls = result.content.filter(
38247
- (p) => p.type === "tool_use"
38248
- );
38249
- if (calls.length > 1) throw new MultiToolCallError(calls.map((c) => ({ tool: c.name, input: c.input })));
38250
- if (calls.length === 1) return { tool: calls[0].name, input: calls[0].input };
38251
- return result.content.filter((p) => p.type === "text").map((p) => p.text).join("");
38252
- };
38253
- }
38254
- async function mintConfirmationOffer(args) {
38255
- const { io, store, msg, origin, def, input, receipt, model } = args;
38256
- if (!io.offer || !store) return { kind: "no_click" };
38257
- const line4 = chatInvocation(def, input);
38258
- if (redactSecrets(line4) !== line4) return { kind: "unshowable" };
38259
- const risk = def.annotations?.risk?.(input, origin) ?? "";
38260
- let row2;
38261
- try {
38262
- row2 = await store.put(
38263
- {
38264
- kind: "run",
38265
- id: newConfirmationId(),
38266
- message: confirmationMessageOf(msg),
38267
- command: def.id,
38268
- input,
38269
- receipt,
38270
- risk,
38271
- model
38272
- },
38273
- CONFIRMATION_TTL_MS
38274
- );
38275
- } catch (err2) {
38276
- console.warn(
38277
- `[route] ${msg.threadKey} confirmation store unreachable at mint, handing back: ${err2 instanceof Error ? err2.message : String(err2)}`
38278
- );
38279
- return { kind: "store_unreachable" };
38280
- }
38281
- return { kind: "offered", shown: { id: row2.id, line: line4, risk, expiresAt: row2.expiresAt } };
38282
- }
38283
- function redactedInput(input) {
38284
- const text = (s) => redactAndCap(redactSecrets(s), 200);
38285
- const leaf = (v) => {
38286
- if (typeof v === "string") return text(v);
38287
- if (typeof v === "number" || typeof v === "boolean" || v === null) return v;
38288
- return v === void 0 ? null : text(JSON.stringify(v) ?? String(v));
38289
- };
38290
- const leafOrList = (v) => Array.isArray(v) ? v.map(leaf) : leaf(v);
38291
- const isRecord11 = (v) => typeof v === "object" && v !== null && (Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null);
38292
- const entries = (v, of) => Object.fromEntries(
38293
- Object.entries(v).filter(([, x]) => x !== void 0).map(([k, x]) => [k, of(x)])
38294
- );
38295
- const object1 = (v) => entries(v, leafOrList);
38296
- const object2 = (v) => entries(v, (x) => isRecord11(x) ? object1(x) : leafOrList(x));
38297
- const object3 = (v) => entries(v, (x) => isRecord11(x) ? object2(x) : leafOrList(x));
38298
- return {
38299
- ...input.args ? { args: input.args.map(leaf) } : {},
38300
- ...input.options ? { options: object3(input.options) } : {}
38301
- };
38302
- }
38303
- function routeReasonLabel(reason2, collapsed) {
38304
- return `${ROUTE_REASON_PREFIX} ${reason2}${collapsed ? ` (compound collapsed: ${collapsed.presets.join("+")})` : ""}`;
38305
- }
38306
- function routedPartLines(parts) {
38307
- return parts.map((p) => {
38308
- const line4 = p.text.replace(/\s+/g, " ").trim();
38309
- return `${p.preset}: ${line4.length > ROUTE_PART_LINE_CAP ? `${line4.slice(0, ROUTE_PART_LINE_CAP - 1)}\u2026` : line4}`;
38310
- });
38311
- }
38312
- function compoundBrief(text, parts) {
38313
- return [
38314
- text,
38315
- "",
38316
- `${COMPOUND_BRIEF_HEADING}: ${parts.length} independent parts. Spawn exactly these children \u2014 one \`spawn_run\` per part, on the preset named, with the part's text as the child's whole prompt (add the repository where the preset needs one) \u2014 then \`await_runs\` them all and compile one answer. Do not merge, drop or add a part.`,
38317
- ...parts.map((p, i) => `${i + 1}. \`${p.preset}\`: ${p.text}`)
38318
- ].join("\n");
38319
- }
38320
- var REASONING_COUNTING_CAP_FIELDS, REASONING_OUTPUT_TOKEN_ALLOWANCE, OutputCapError, ROUTE_REASON_CAP, ROUTE_MIN_OUTPUT_TOKENS, ROUTE_TIMEOUT_MS, ROUTE_PART_LINE_CAP, ROUTE_RECEIPT_CAP, ROUTED_RECEIPT_PREFIX, COMPOUND_BRIEF_HEADING, MultiToolCallError;
38321
- var init_route = __esm({
38322
- "../../src/core/dispatch/route.ts"() {
38323
- "use strict";
38324
- init_registry();
38325
- init_handBack();
38326
- init_profile();
38327
- init_redact();
38328
- init_statusCardFrame();
38329
- init_commandRegistry();
38330
- init_commandSurface();
38331
- init_budgets();
38332
- init_confirmations();
38333
- REASONING_COUNTING_CAP_FIELDS = /* @__PURE__ */ new Set(["max_tokens", "max_completion_tokens", "max_output_tokens"]);
38334
- REASONING_OUTPUT_TOKEN_ALLOWANCE = 4096;
38335
- OutputCapError = class extends Error {
38336
- constructor(maxTokens) {
38337
- super(`answer cut at the output cap (${maxTokens} tokens)`);
38338
- this.maxTokens = maxTokens;
38339
- this.name = "OutputCapError";
38340
- }
38341
- maxTokens;
38342
- };
38343
- ROUTE_REASON_CAP = 120;
38344
- ROUTE_MIN_OUTPUT_TOKENS = 200;
38345
- ROUTE_TIMEOUT_MS = 8e3;
38346
- ROUTE_PART_LINE_CAP = 100;
38347
- ROUTE_RECEIPT_CAP = 300;
38348
- ROUTED_RECEIPT_PREFIX = "routed:";
38349
- COMPOUND_BRIEF_HEADING = "Routed as a compound request";
38350
- MultiToolCallError = class extends Error {
38351
- constructor(calls) {
38352
- super(`answer carried ${calls.length} tool calls; the route is one call`);
38353
- this.calls = calls;
38354
- this.name = "MultiToolCallError";
38355
- }
38356
- calls;
38357
- };
38358
- }
38359
- });
38360
-
38361
38672
  // ../../src/core/runRegistry/runControl.ts
38362
38673
  var RunControl;
38363
38674
  var init_runControl = __esm({
@@ -38484,6 +38795,8 @@ function summaryOf(run2, now) {
38484
38795
  ...m?.hosted ? { hosted: true } : {},
38485
38796
  ...run2.instanceId !== void 0 ? { instanceId: run2.instanceId } : {},
38486
38797
  ...run2.pipeline !== void 0 ? { pipeline: run2.pipeline } : {},
38798
+ ...run2.liveState !== void 0 ? { liveState: run2.liveState } : {},
38799
+ ...run2.liveStateSeq !== void 0 ? { liveStateSeq: run2.liveStateSeq } : {},
38487
38800
  finished: run2.finished,
38488
38801
  startedAt: run2.startedAt,
38489
38802
  ...run2.finishedAt !== void 0 ? { finishedAt: run2.finishedAt } : {},
@@ -38519,7 +38832,9 @@ function snapshotOf(run2) {
38519
38832
  ...run2.meta?.receivedAt !== void 0 ? { receivedAt: run2.meta.receivedAt } : {},
38520
38833
  eventCount: run2.eventCount,
38521
38834
  stepCount: run2.stepCount,
38522
- truncated: run2.eventCount > run2.backlog.length
38835
+ truncated: run2.eventCount > run2.backlog.length,
38836
+ ...run2.liveState !== void 0 ? { liveState: run2.liveState } : {},
38837
+ ...run2.liveStateSeq !== void 0 ? { liveStateSeq: run2.liveStateSeq } : {}
38523
38838
  };
38524
38839
  }
38525
38840
  function sealResultOf(run2) {
@@ -38603,6 +38918,7 @@ var init_runRegistry = __esm({
38603
38918
  init_projections();
38604
38919
  init_indexFeed();
38605
38920
  init_runPace();
38921
+ init_runLiveState();
38606
38922
  PACE_RING_CAP = 1200;
38607
38923
  UNSEALED_HOLD_MS = 15 * 6e4;
38608
38924
  RUN_LABEL_MAX2 = 200;
@@ -38676,6 +38992,10 @@ var init_runRegistry = __esm({
38676
38992
  if (!isSpanRecord(event)) run2.stepCount++;
38677
38993
  appendToBacklog(run2, this.bounds, { ...event, seq });
38678
38994
  }
38995
+ const replayedLiveState = foldRunLiveState(opts.replay ?? [], opts.liveState);
38996
+ const folded = opts.resetLiveState ? { liveStateSeq: replayedLiveState.liveStateSeq } : replayedLiveState;
38997
+ run2.liveState = folded.liveState;
38998
+ run2.liveStateSeq = folded.liveStateSeq;
38679
38999
  this.index.notify({ type: "upsert", run: summaryOf(run2, this.now()) });
38680
39000
  return { id, token: token2, control: run2.control, ...stored !== void 0 ? { label: stored } : {} };
38681
39001
  }
@@ -38764,6 +39084,32 @@ var init_runRegistry = __esm({
38764
39084
  }
38765
39085
  if (!span) this.index.notify({ type: "upsert", run: summaryOf(run2, this.now()) });
38766
39086
  }
39087
+ /** Apply an assignment only after its durable transaction acknowledged. The
39088
+ * boundary keeps the ledger-assigned stream sequence; subscribers cannot
39089
+ * observe either half before this call. */
39090
+ commitLiveState(id, committed) {
39091
+ const run2 = this.runs.get(id);
39092
+ if (!run2 || run2.finished || run2.sealedAt !== void 0) return false;
39093
+ const event = committed.event;
39094
+ if (event !== void 0) {
39095
+ const seq = event.seq;
39096
+ if (seq === void 0 || seq !== run2.eventCount + 1) return false;
39097
+ run2.eventCount = seq;
39098
+ run2.stepCount++;
39099
+ const stamped = { ...event, seq };
39100
+ appendToBacklog(run2, this.bounds, stamped);
39101
+ for (const sub of run2.subscribers) {
39102
+ try {
39103
+ sub.onEvent(stamped, seq);
39104
+ } catch {
39105
+ }
39106
+ }
39107
+ }
39108
+ run2.liveState = committed.liveState;
39109
+ run2.liveStateSeq = committed.liveStateSeq;
39110
+ this.index.notify({ type: "upsert", run: summaryOf(run2, this.now()) });
39111
+ return true;
39112
+ }
38767
39113
  /** Mark a run finished — the agent stopped: stamp `finishedAt`, send every
38768
39114
  * attached subscriber the `finished` frame WITHOUT detaching it (span records
38769
39115
  * still flow until the seal), and upsert the index. `status` is the terminal
@@ -41765,6 +42111,47 @@ var init_customInstructions = __esm({
41765
42111
  }
41766
42112
  });
41767
42113
 
42114
+ // ../../src/core/runEventLane.ts
42115
+ var RunEventLane;
42116
+ var init_runEventLane = __esm({
42117
+ "../../src/core/runEventLane.ts"() {
42118
+ "use strict";
42119
+ RunEventLane = class {
42120
+ constructor(publishNow) {
42121
+ this.publishNow = publishNow;
42122
+ }
42123
+ publishNow;
42124
+ tail;
42125
+ /** Publish synchronously while idle; otherwise preserve order behind the active write. */
42126
+ publish(event) {
42127
+ if (!this.tail) {
42128
+ this.publishNow(event);
42129
+ return;
42130
+ }
42131
+ void this.write(() => this.publishNow(event));
42132
+ }
42133
+ /** Queue one operation after every event or operation already accepted. */
42134
+ write(work) {
42135
+ const previous = this.tail ?? Promise.resolve();
42136
+ const next = previous.then(work);
42137
+ const settled = next.then(
42138
+ () => void 0,
42139
+ () => void 0
42140
+ );
42141
+ this.tail = settled;
42142
+ void settled.then(() => {
42143
+ if (this.tail === settled) this.tail = void 0;
42144
+ });
42145
+ return next;
42146
+ }
42147
+ /** Wait until every operation accepted so far has settled. */
42148
+ async drain() {
42149
+ await this.tail;
42150
+ }
42151
+ };
42152
+ }
42153
+ });
42154
+
41768
42155
  // ../../src/core/statusCoalescer.ts
41769
42156
  function coalesceStatus(inner, minIntervalMs, now = Date.now, schedule = setTimeout) {
41770
42157
  let lastSentAt = -Infinity;
@@ -41937,22 +42324,24 @@ async function registerRun(deps, ctx) {
41937
42324
  {
41938
42325
  id: runId3,
41939
42326
  startedAt,
41940
- ...resume ? { replay: resume.events } : ctx.restartCarried ? { replay: ctx.restartCarried.events, token: ctx.restartCarried.token } : {}
42327
+ ...carriedRow?.liveState !== void 0 ? { liveState: { liveState: carriedRow.liveState, liveStateSeq: carriedRow.liveStateSeq } } : {},
42328
+ ...resume ? { replay: resume.events } : ctx.restartCarried ? { replay: ctx.restartCarried.events, token: ctx.restartCarried.token, resetLiveState: true } : {}
41941
42329
  }
41942
42330
  );
42331
+ const events = new RunEventLane((event) => registry.publish(run2.id, event));
41943
42332
  if (ctx.restartCarried)
41944
- registry.publish(run2.id, { type: "run_note", kind: "resumed", summary: ctx.restartCarried.note, at: clock4() });
42333
+ events.publish({ type: "run_note", kind: "resumed", summary: ctx.restartCarried.note, at: clock4() });
41945
42334
  const liveUrl = liveViewLink(run2.id, run2.token);
41946
42335
  shell.setLink(liveUrl ? { url: liveUrl, label: "Live run" } : void 0);
41947
42336
  if (liveUrl) admitted.runLink = liveUrl;
41948
42337
  io.runStarted?.({ id: run2.id });
41949
- trace.bindRun(run2.id, (e) => registry.publish(run2.id, e));
42338
+ trace.bindRun(run2.id, (event) => events.publish(event));
41950
42339
  const publishText = (type, text, source3, raw) => {
41951
42340
  const redacted = redactSecrets(text);
41952
42341
  const body = { text: redacted, ...source3 ? { source: source3 } : {}, at: clock4() };
41953
42342
  const event = type === "input" ? { type, messageId: messageIdOf(msg, run2.id), ...body } : { type, ...body };
41954
42343
  const withRaw = raw !== void 0 ? { ...event, raw: redactSecrets(raw) } : event;
41955
- registry.publish(run2.id, utf8ByteLength(JSON.stringify(withRaw)) <= MAX_EVENT_BYTES ? withRaw : event);
42344
+ events.publish(utf8ByteLength(JSON.stringify(withRaw)) <= MAX_EVENT_BYTES ? withRaw : event);
41956
42345
  console.log(`[event] ${msg.threadKey} type=${type} bytes=${utf8ByteLength(redacted)}`);
41957
42346
  };
41958
42347
  const humanize = isMrkdwnChannel(msg.channelId);
@@ -41972,7 +42361,7 @@ async function registerRun(deps, ctx) {
41972
42361
  if (!resume && ctx.references) {
41973
42362
  const { conversations, blocks } = ctx.references;
41974
42363
  conversations.forEach((rc, i) => {
41975
- registry.publish(run2.id, {
42364
+ events.publish({
41976
42365
  type: "reference",
41977
42366
  url: rc.permalink,
41978
42367
  channelId: rc.ref.channelId,
@@ -41984,7 +42373,7 @@ async function registerRun(deps, ctx) {
41984
42373
  console.log(`[event] ${msg.threadKey} type=reference channel=${rc.ref.channelId} messages=${rc.messages.length}`);
41985
42374
  });
41986
42375
  }
41987
- const publishMeta = (repoCtx2) => registry.publish(run2.id, {
42376
+ const publishMeta = (repoCtx2) => events.publish({
41988
42377
  type: "run_meta",
41989
42378
  agent: agent.name,
41990
42379
  agentSource,
@@ -42016,7 +42405,7 @@ async function registerRun(deps, ctx) {
42016
42405
  if (!resume)
42017
42406
  for (const d of cardDecisions ?? []) {
42018
42407
  if (d.outcome !== "degraded") continue;
42019
- registry.publish(run2.id, {
42408
+ events.publish({
42020
42409
  type: "run_note",
42021
42410
  kind: "control_degraded",
42022
42411
  summary: oneLine(
@@ -42030,12 +42419,12 @@ async function registerRun(deps, ctx) {
42030
42419
  at: clock4()
42031
42420
  });
42032
42421
  }
42033
- if (!resume && route2) registry.publish(run2.id, { type: "route", ...route2, at: clock4() });
42034
- if (!resume && ctx.operator) registry.publish(run2.id, { type: "operator", ...ctx.operator, at: clock4() });
42422
+ if (!resume && route2) events.publish({ type: "route", ...route2, at: clock4() });
42423
+ if (!resume && ctx.operator) events.publish({ type: "operator", ...ctx.operator, at: clock4() });
42035
42424
  if (!resume && deps.config.config.runHistory?.includeContext !== false) {
42036
42425
  for (const text of contextMessageTexts(seedTurns ?? history, humanize)) publishText("context", text);
42037
42426
  }
42038
- return { run: run2, runId: runId3, channelVisibility, liveUrl, publishText, publishMeta };
42427
+ return { run: run2, runId: runId3, channelVisibility, liveUrl, events, publishText, publishMeta };
42039
42428
  }
42040
42429
  async function reserveRun(deps, ctx) {
42041
42430
  const {
@@ -42111,8 +42500,8 @@ async function reserveRun(deps, ctx) {
42111
42500
  }
42112
42501
  async function attachRound(deps, ctx) {
42113
42502
  const { threadKey, agent, profile, repoCtx, root, clock: clock4, reattach, stopSignal, remainingMs, requester } = ctx;
42114
- const { onSetupNote } = ctx;
42115
- const ownPr = ownPrOf(repoCtx);
42503
+ const { onLiveStateObservation } = ctx;
42504
+ const ownPr = agent.name === "review" ? void 0 : ownPrOf(repoCtx);
42116
42505
  return root.span("dispatch.workspace.attach", async (span) => {
42117
42506
  const graft = (steps, residentTotalMs) => graftResidentSteps(steps, {
42118
42507
  parent: span,
@@ -42147,7 +42536,7 @@ async function attachRound(deps, ctx) {
42147
42536
  ...stopSignal !== void 0 ? { stopSignal } : {},
42148
42537
  ...remainingMs !== void 0 ? { remainingMs } : {},
42149
42538
  ...requester !== void 0 ? { requester } : {},
42150
- ...onSetupNote !== void 0 ? { onSetupNote } : {}
42539
+ ...onLiveStateObservation !== void 0 ? { onLiveStateObservation } : {}
42151
42540
  },
42152
42541
  logKey: threadKey,
42153
42542
  span
@@ -42204,10 +42593,10 @@ async function attachWorkspace(deps, ctx) {
42204
42593
  clock: clock4,
42205
42594
  // The requester whose binding names the author pair (record 0062).
42206
42595
  requester: msg.userId,
42207
- // A run admitted onto a drained fleet says so (issue 2044): the drain
42208
- // wait paints its one line here, and its end restores the attach label
42209
- // the card sink painted at the span's start.
42210
- onSetupNote: (note) => shell.setSetupLabel(note ?? `${displayNameOf("dispatch.workspace.attach")}\u2026`),
42596
+ onLiveStateObservation: async (observation) => {
42597
+ await ctx.onLiveStateObservation?.(observation);
42598
+ shell.setSetupLabel(`${liveStateWords(observation.state)}\u2026`);
42599
+ },
42211
42600
  ...reattach !== void 0 ? { reattach } : {},
42212
42601
  ...stopSignal !== void 0 ? { stopSignal } : {},
42213
42602
  ...remainingMs !== void 0 ? { remainingMs } : {}
@@ -42374,7 +42763,6 @@ var init_provision = __esm({
42374
42763
  init_factory();
42375
42764
  init_executor();
42376
42765
  init_residentTrace();
42377
- init_displayNames();
42378
42766
  init_resident();
42379
42767
  init_memory();
42380
42768
  init_budgets();
@@ -42387,12 +42775,14 @@ var init_provision = __esm({
42387
42775
  init_reviewRound();
42388
42776
  init_repoContext();
42389
42777
  init_runEvents();
42778
+ init_runEventLane();
42390
42779
  init_redact();
42391
42780
  init_runRecord();
42392
42781
  init_inboxMessage();
42393
42782
  init_statusCardFrame();
42394
42783
  init_statusCoalescer();
42395
42784
  init_types5();
42785
+ init_decide();
42396
42786
  init_record();
42397
42787
  init_reply();
42398
42788
  init_refusal();
@@ -45718,6 +46108,18 @@ function decisionRecordTaskKey(...parts) {
45718
46108
  }
45719
46109
  return hash.toString(16).padStart(16, "0");
45720
46110
  }
46111
+ function durableDecisionRecordReservation(store) {
46112
+ return async (repo, taskKey, claimed2, existing) => {
46113
+ try {
46114
+ const reserved = await store.reserveDecisionRecord(repo, taskKey, claimed2, existing);
46115
+ if (!reserved.ok) throw new DecisionRecordReservationUnavailableError();
46116
+ return reserved.number;
46117
+ } catch (error) {
46118
+ if (error instanceof DecisionRecordReservationUnavailableError) throw error;
46119
+ throw new DecisionRecordReservationUnavailableError();
46120
+ }
46121
+ };
46122
+ }
45721
46123
  var DECISION_RECORD_ENV, RECORD_MARKER, POSITIVE_RECORD_INSTRUCTION, NEGATED_INSTRUCTION, DECISION_RECORD_STORE_REFUSAL, DecisionRecordReservationUnavailableError, DecisionRecordAllocator;
45722
46124
  var init_decisionRecordReservation = __esm({
45723
46125
  "../../src/core/decisionRecordReservation.ts"() {
@@ -48601,6 +49003,11 @@ var init_mirror = __esm({
48601
49003
  seedEchoPending = false;
48602
49004
  mirroredTail;
48603
49005
  iteration = 0;
49006
+ /** The loop counters on the last transcript-bearing step. A cursor-only
49007
+ * checkpoint repeats them so a post-loop turn cannot become part of the
49008
+ * resumable model loop merely by consuming a control row. */
49009
+ lastTurn = 0;
49010
+ lastIteration = 0;
48604
49011
  /** The rows written since the mirror started, and the compaction entries
48605
49012
  * among them by position — kept whether or not the ledger is wired, so
48606
49013
  * the harness holds this generation's copy of the record it wrote
@@ -48614,6 +49021,11 @@ var init_mirror = __esm({
48614
49021
  compactionRows = [];
48615
49022
  /** The highest ledger inbox seq folded in so far (run-history item 40). */
48616
49023
  inboxConsumedSeq = 0;
49024
+ /** The owed seqs the cursor has already passed, ascending; absent when none. */
49025
+ inboxDeferred() {
49026
+ const deferred = [...new Set(this.deps.owedInboxSeqs?.() ?? [])].filter((seq) => seq <= this.inboxConsumedSeq).sort((a, b) => a - b);
49027
+ return deferred.length > 0 ? { inboxDeferredSeqs: deferred } : {};
49028
+ }
48617
49029
  /** Whether a report is owed: the mirror is wired and something happened. */
48618
49030
  get wired() {
48619
49031
  return this.deps.onStep !== void 0;
@@ -48702,8 +49114,11 @@ var init_mirror = __esm({
48702
49114
  turn,
48703
49115
  iteration: this.iteration++,
48704
49116
  remainingMs: Math.max(0, this.deps.remainingMs()),
48705
- inboxConsumedSeq: this.inboxConsumedSeq
49117
+ inboxConsumedSeq: this.inboxConsumedSeq,
49118
+ ...this.inboxDeferred()
48706
49119
  };
49120
+ this.lastTurn = report2.turn;
49121
+ this.lastIteration = report2.iteration;
48707
49122
  this.idx += turns.length;
48708
49123
  this.lastAssistantIdx = this.idx - 1;
48709
49124
  this.rows.push(...turns);
@@ -48729,8 +49144,11 @@ var init_mirror = __esm({
48729
49144
  turn,
48730
49145
  iteration: this.iteration,
48731
49146
  remainingMs: Math.max(0, this.deps.remainingMs()),
48732
- inboxConsumedSeq: this.inboxConsumedSeq
49147
+ inboxConsumedSeq: this.inboxConsumedSeq,
49148
+ ...this.inboxDeferred()
48733
49149
  };
49150
+ this.lastTurn = report2.turn;
49151
+ this.lastIteration = report2.iteration;
48734
49152
  this.idx += turns.length + 1;
48735
49153
  this.rows.push(...turns);
48736
49154
  this.compactionRows.push({ before: this.rows.length, entry });
@@ -48738,6 +49156,22 @@ var init_mirror = __esm({
48738
49156
  await this.deps.onStep(report2);
48739
49157
  return true;
48740
49158
  }
49159
+ /** Persist only the inbox cursor and its deferred exceptions. Post-loop
49160
+ * turns deliberately stay out of the resumable transcript, but a control
49161
+ * row they consume must survive a bot restart just as a loop step does. */
49162
+ async checkpointInbox() {
49163
+ if (!this.deps.onStep) return;
49164
+ await this.deps.onStep({
49165
+ turns: [],
49166
+ firstIdx: this.idx,
49167
+ inFlight: [],
49168
+ turn: this.lastTurn,
49169
+ iteration: this.lastIteration,
49170
+ remainingMs: Math.max(0, this.deps.remainingMs()),
49171
+ inboxConsumedSeq: this.inboxConsumedSeq,
49172
+ ...this.inboxDeferred()
49173
+ });
49174
+ }
48741
49175
  };
48742
49176
  }
48743
49177
  });
@@ -49813,6 +50247,7 @@ async function runPiHarnessOpen(deps, run2) {
49813
50247
  let paths;
49814
50248
  let requeueUnechoed = () => {
49815
50249
  };
50250
+ let unechoedSeqs = () => [];
49816
50251
  let dropHeld = () => {
49817
50252
  };
49818
50253
  let loopEnded = false;
@@ -49847,7 +50282,10 @@ async function runPiHarnessOpen(deps, run2) {
49847
50282
  onStep: run2.onStep,
49848
50283
  seedLength: run2.resume ? run2.resume.messages.length + (run2.resume.compactions?.length ?? 0) : run2.messages.length,
49849
50284
  remainingMs: () => deadline - now(),
49850
- ...tail ? { mirroredTail: tail } : {}
50285
+ ...tail ? { mirroredTail: tail } : {},
50286
+ // The rows pi has not read yet: the cursor can pass one when a later row
50287
+ // is consumed first (the plane's provider-up beside an ordinary steer).
50288
+ owedInboxSeqs: () => [...run2.inbox?.pendingSeqs ?? [], ...unechoedSeqs()]
49851
50289
  });
49852
50290
  mirror.inboxConsumedSeq = run2.resume?.inboxConsumedSeq ?? 0;
49853
50291
  placed = (event) => {
@@ -50254,6 +50692,7 @@ async function runPiHarnessOpen(deps, run2) {
50254
50692
  const [echoed] = unechoed.splice(at, 1);
50255
50693
  if (echoed.seq > mirror.inboxConsumedSeq) mirror.inboxConsumedSeq = echoed.seq;
50256
50694
  };
50695
+ unechoedSeqs = () => unechoed.flatMap((u) => u.inputs.flatMap((i) => i.ledgerSeq !== void 0 ? [i.ledgerSeq] : []));
50257
50696
  requeueUnechoed = () => {
50258
50697
  pendingReissue = [];
50259
50698
  run2.inbox?.requeue(unechoed.splice(0).flatMap((u) => u.inputs));
@@ -50262,6 +50701,7 @@ async function runPiHarnessOpen(deps, run2) {
50262
50701
  let parkSettled = false;
50263
50702
  let pendingReissue = [];
50264
50703
  let reissueInFlight;
50704
+ let reissueInFlightRows = [];
50265
50705
  let reissues = 0;
50266
50706
  let providerRetryReady = false;
50267
50707
  let providerRetryWait;
@@ -50274,20 +50714,21 @@ async function runPiHarnessOpen(deps, run2) {
50274
50714
  providerRetryWait = void 0;
50275
50715
  providerRetryGeneration += 1;
50276
50716
  pendingReissue = [];
50717
+ reissueInFlightRows = [];
50277
50718
  };
50278
50719
  const maybeReissue = () => {
50279
50720
  if (heldTurn === void 0 || !parkSettled || reissueInFlight !== void 0 || retryInFlight !== void 0)
50280
50721
  return;
50281
50722
  if (pendingReissue.length === 0) return;
50282
50723
  if (loopEnded || hardStopped || writeUp !== void 0 || finaleAborted) return;
50283
- const batch = pendingReissue.splice(0);
50724
+ reissueInFlightRows = pendingReissue.splice(0);
50284
50725
  reissues += 1;
50285
50726
  const id = reissues === 1 ? `${ids.prompt}:reissue` : `${ids.prompt}:reissue:${reissues}`;
50286
50727
  reissueInFlight = id;
50287
50728
  unechoed.push({
50288
50729
  message: REISSUE_PROMPT,
50289
- seq: Math.max(0, ...batch.map((i) => i.ledgerSeq ?? 0)),
50290
- inputs: batch
50730
+ seq: Math.max(0, ...reissueInFlightRows.map((i) => i.ledgerSeq ?? 0)),
50731
+ inputs: reissueInFlightRows
50291
50732
  });
50292
50733
  sends.send({ id, type: "prompt", message: REISSUE_PROMPT });
50293
50734
  };
@@ -50548,16 +50989,29 @@ ${stagedLine}` : prompt;
50548
50989
  save();
50549
50990
  }
50550
50991
  if (reissueInFlight !== void 0 && r.id === reissueInFlight) {
50551
- reissueInFlight = void 0;
50552
50992
  if (r.success === false) {
50993
+ reissueInFlight = void 0;
50553
50994
  parkSettled = false;
50554
50995
  const at = unechoed.findIndex((u) => u.message === REISSUE_PROMPT);
50555
- if (at >= 0) pendingReissue.push(...unechoed.splice(at, 1)[0].inputs);
50996
+ if (at >= 0) unechoed.splice(at, 1);
50997
+ pendingReissue.push(...reissueInFlightRows);
50998
+ reissueInFlightRows = [];
50556
50999
  note(
50557
51000
  "harness_error",
50558
51001
  `the reissue prompt was refused (${String(r.error ?? "no reason")}); the turn stays held for the next settle`
50559
51002
  );
50560
51003
  } else {
51004
+ drainFollowUps2();
51005
+ await steers;
51006
+ const at = unechoed.findIndex((u) => u.message === REISSUE_PROMPT);
51007
+ if (at >= 0) unechoed.splice(at, 1);
51008
+ mirror.inboxConsumedSeq = Math.max(
51009
+ mirror.inboxConsumedSeq,
51010
+ ...reissueInFlightRows.map((item) => item.ledgerSeq ?? 0),
51011
+ ...pendingReissue.map((item) => item.ledgerSeq ?? 0)
51012
+ );
51013
+ await mirror.checkpointInbox();
51014
+ reissueInFlight = void 0;
50561
51015
  clearProviderHold();
50562
51016
  }
50563
51017
  }
@@ -50566,7 +51020,16 @@ ${stagedLine}` : prompt;
50566
51020
  if (r.success === false) {
50567
51021
  parkSettled = false;
50568
51022
  note("harness_error", "the model retry prompt was refused; the transport failure remains held");
50569
- } else clearProviderHold();
51023
+ } else {
51024
+ drainFollowUps2();
51025
+ await steers;
51026
+ mirror.inboxConsumedSeq = Math.max(
51027
+ mirror.inboxConsumedSeq,
51028
+ ...pendingReissue.map((item) => item.ledgerSeq ?? 0)
51029
+ );
51030
+ await mirror.checkpointInbox();
51031
+ clearProviderHold();
51032
+ }
50570
51033
  }
50571
51034
  if (r.id === ids.prompt) {
50572
51035
  catchingUp = false;
@@ -50923,10 +51386,13 @@ ${stagedLine}` : prompt;
50923
51386
  `the follow-up turn's reissue prompt was refused (${String(obs.response.error ?? "no reason")}); the turn stays held for the next settle`
50924
51387
  );
50925
51388
  } else {
51389
+ drainTurnReissues();
50926
51390
  mirror.inboxConsumedSeq = Math.max(
50927
51391
  mirror.inboxConsumedSeq,
50928
- ...turnReissueInFlightRows.map((item) => item.ledgerSeq ?? 0)
51392
+ ...turnReissueInFlightRows.map((item) => item.ledgerSeq ?? 0),
51393
+ ...turnReissueRows.map((item) => item.ledgerSeq ?? 0)
50929
51394
  );
51395
+ await mirror.checkpointInbox();
50930
51396
  clearTurnProviderHold();
50931
51397
  }
50932
51398
  }
@@ -50935,7 +51401,15 @@ ${stagedLine}` : prompt;
50935
51401
  if (obs.response.success === false) {
50936
51402
  turnParkSettled = false;
50937
51403
  note("harness_error", "the follow-up turn's model retry prompt was refused; the failure remains held");
50938
- } else clearTurnProviderHold();
51404
+ } else {
51405
+ drainTurnReissues();
51406
+ mirror.inboxConsumedSeq = Math.max(
51407
+ mirror.inboxConsumedSeq,
51408
+ ...turnReissueRows.map((item) => item.ledgerSeq ?? 0)
51409
+ );
51410
+ await mirror.checkpointInbox();
51411
+ clearTurnProviderHold();
51412
+ }
50939
51413
  }
50940
51414
  }
50941
51415
  if (obs.response?.id === id && obs.response.success === false)
@@ -52266,6 +52740,7 @@ async function runLoop(deps, ctx) {
52266
52740
  coordinator,
52267
52741
  seed
52268
52742
  } = ctx;
52743
+ const events = ctx.events ?? new RunEventLane((event) => registry.publish(run2.id, event));
52269
52744
  const agent = budgetedAgent(ctx.agent, profile);
52270
52745
  const { round: round2 } = ctx;
52271
52746
  let { executor } = round2.selection;
@@ -52339,13 +52814,11 @@ async function runLoop(deps, ctx) {
52339
52814
  const pushes = trackPushedBranch(typeof restored.pushedBranch === "string" ? restored.pushedBranch : void 0);
52340
52815
  let budgetEnded = false;
52341
52816
  let recordedPushedBranch;
52342
- const onEvent = (e) => {
52817
+ let modelBudgetEndsAt;
52818
+ const publishEvent = (e, startsRunBudget) => {
52343
52819
  registry.publish(run2.id, e);
52344
52820
  if (isSpanRecord(e)) return;
52345
- if (e.type === "lease") {
52346
- run2.control.startLease(() => e.endsAt - clock4());
52347
- return;
52348
- }
52821
+ if (startsRunBudget) return;
52349
52822
  if (e.type === "tool_call") toolCalls++;
52350
52823
  if (e.type === "run_note" && e.kind === "time_budget_exhausted") budgetEnded = true;
52351
52824
  if (isCodingPrRun) {
@@ -52365,6 +52838,47 @@ async function runLoop(deps, ctx) {
52365
52838
  lastActivity = bookkeeping && !showBookkeeping ? void 0 : cardActivity(e);
52366
52839
  card.update(currentFrame());
52367
52840
  };
52841
+ const onEvent = (e) => {
52842
+ const startsRunBudget = e.type === "lease";
52843
+ if (startsRunBudget) {
52844
+ modelBudgetEndsAt = e.endsAt;
52845
+ run2.control.startLease(() => e.endsAt - clock4());
52846
+ }
52847
+ void events.write(async () => {
52848
+ if ((e.type === "tool_call" || e.type === "tool_result") && typeof registry.commitLiveState === "function") {
52849
+ const summary = registry.getById(run2.id);
52850
+ if (summary?.liveState?.state === "working") {
52851
+ const at = e.at ?? clock4();
52852
+ const bound = e.type === "tool_call" && e.boundMs !== void 0 ? at + e.boundMs : modelBudgetEndsAt ?? summary.liveState.bound;
52853
+ if (bound !== void 0) {
52854
+ const sourceSeq = summary.eventCount + 1;
52855
+ const assignment = {
52856
+ expectedSeq: summary.liveStateSeq ?? 0,
52857
+ at,
52858
+ state: "working",
52859
+ bound,
52860
+ detail: e.type === "tool_call" ? "running a tool" : "model turn",
52861
+ sourceEvents: [{ ...e, seq: sourceSeq }]
52862
+ };
52863
+ try {
52864
+ if (ledgerRun?.tracked()) {
52865
+ const committed = await ledgerRun.assignLiveState(assignment);
52866
+ if (committed.ok) registry.commitLiveState(run2.id, committed);
52867
+ } else {
52868
+ const local = assignRunLiveState(summary.liveState, summary.liveStateSeq ?? 0, assignment);
52869
+ if (local.ok) registry.commitLiveState(run2.id, { ...local, liveStateSeq: sourceSeq });
52870
+ }
52871
+ } catch (err2) {
52872
+ console.warn(
52873
+ `[run] ${msg.threadKey} live-state projection failed: ${err2 instanceof Error ? err2.message : String(err2)}`
52874
+ );
52875
+ }
52876
+ }
52877
+ }
52878
+ }
52879
+ publishEvent(e, startsRunBudget);
52880
+ });
52881
+ };
52368
52882
  for (const s of mcpForRun?.servers ?? []) {
52369
52883
  if (s.unavailable !== void 0)
52370
52884
  onEvent({
@@ -52387,14 +52901,14 @@ async function runLoop(deps, ctx) {
52387
52901
  descriptionArtifact = startReviewDescription({
52388
52902
  store: deps.runStore,
52389
52903
  repoCtx,
52390
- publish: (e) => registry.publish(run2.id, e)
52904
+ publish: (event) => events.publish(event)
52391
52905
  });
52392
52906
  readingDiffBaseline = startReviewReadingDiff({
52393
52907
  executor,
52394
52908
  cfg: deps.config.config.review?.readingDiff,
52395
52909
  env: publicEnv(),
52396
52910
  baseRef: repoCtx.baseRef,
52397
- publish: (e) => registry.publish(run2.id, e),
52911
+ publish: (event) => events.publish(event),
52398
52912
  parent: root
52399
52913
  }).baseline.then((published) => {
52400
52914
  console.log(`[reading-diff] ${msg.threadKey} baseline ${published ? "published" : "none"}`);
@@ -52466,10 +52980,11 @@ async function runLoop(deps, ctx) {
52466
52980
  if (interrupted === void 0) runFailed = true;
52467
52981
  throw err2;
52468
52982
  } finally {
52983
+ await events.drain();
52469
52984
  const calls = callsInFlight(recordEvents(), statusNow());
52470
52985
  commandInFlight = calls.length > 0;
52471
52986
  if (commandInFlight)
52472
- registry.publish(run2.id, {
52987
+ events.publish({
52473
52988
  type: "run_note",
52474
52989
  kind: "workspace_torn_down",
52475
52990
  summary: redactAndCap(
@@ -52543,12 +53058,12 @@ async function runLoop(deps, ctx) {
52543
53058
  let reviewStoppedBeforeStart = false;
52544
53059
  const latchReviewStoppedBeforeStart = () => {
52545
53060
  if (reviewStoppedBeforeStart || agent.name !== "review") return reviewStoppedBeforeStart;
52546
- const events = recordEvents();
52547
- const stopAt = events.findIndex(
53061
+ const events2 = recordEvents();
53062
+ const stopAt = events2.findIndex(
52548
53063
  (event) => event.type === "run_note" && (event.kind === "stop_requested" || event.kind === "stopped")
52549
53064
  );
52550
53065
  if (stopAt < 0) return false;
52551
- reviewStoppedBeforeStart = !events.slice(0, stopAt).some((event) => event.type === "tool_call" && event.tool !== "update_status");
53066
+ reviewStoppedBeforeStart = !events2.slice(0, stopAt).some((event) => event.type === "tool_call" && event.tool !== "update_status");
52552
53067
  return reviewStoppedBeforeStart;
52553
53068
  };
52554
53069
  const clearStoppedReviewTail = () => {
@@ -52563,8 +53078,8 @@ async function runLoop(deps, ctx) {
52563
53078
  };
52564
53079
  const tailSkipped = () => run2.control.requested === "hard" || relaunchEndedRun || latchReviewStoppedBeforeStart();
52565
53080
  const releaseWorkspace = (span) => {
52566
- const events = recordEvents();
52567
- const pushed = pushedBranchesOf(events);
53081
+ const events2 = recordEvents();
53082
+ const pushed = pushedBranchesOf(events2);
52568
53083
  return round2.release({
52569
53084
  hardStopped: run2.control.requested === "hard",
52570
53085
  commandInFlight,
@@ -52582,7 +53097,7 @@ async function runLoop(deps, ctx) {
52582
53097
  const staged = await stageIntoWorkspace(files, {
52583
53098
  store: deps.artifacts,
52584
53099
  threadKey: msg.threadKey,
52585
- publish: (e) => registry.publish(run2.id, e),
53100
+ publish: (event) => events.publish(event),
52586
53101
  nextIndex: nextStagedIndex,
52587
53102
  executor,
52588
53103
  resident: round2.selection.resident !== void 0
@@ -53028,7 +53543,7 @@ async function runLoop(deps, ctx) {
53028
53543
  return { workspace, description: prDescription !== void 0 ? "submitted" : "not_submitted" };
53029
53544
  };
53030
53545
  if (leftBehind) {
53031
- registry.publish(run2.id, {
53546
+ events.publish({
53032
53547
  type: "run_note",
53033
53548
  kind: "work_left_behind",
53034
53549
  summary: oneLine(workLeftBehindSummary(leftBehind)),
@@ -53037,7 +53552,7 @@ async function runLoop(deps, ctx) {
53037
53552
  shell.note("quiet", workLeftBehindLabel(leftBehind));
53038
53553
  }
53039
53554
  if (prDescription) {
53040
- registry.publish(run2.id, {
53555
+ events.publish({
53041
53556
  type: "pr_description",
53042
53557
  description: redactPrDescription(prDescription),
53043
53558
  at: clock4()
@@ -53073,7 +53588,7 @@ async function runLoop(deps, ctx) {
53073
53588
  }
53074
53589
  } : {},
53075
53590
  descriptionTurnRan,
53076
- publish: (e) => registry.publish(run2.id, e),
53591
+ publish: (event) => events.publish(event),
53077
53592
  logKey: msg.threadKey
53078
53593
  })
53079
53594
  );
@@ -53111,7 +53626,7 @@ async function runLoop(deps, ctx) {
53111
53626
  fetchPrHead: deps.fetchPrHead ?? currentPrHeadSha,
53112
53627
  reply: (text) => io.reply(text),
53113
53628
  ack: (text) => replyAck(io, resolved.verbosity, text),
53114
- publish: (e) => registry.publish(run2.id, e),
53629
+ publish: (event) => events.publish(event),
53115
53630
  logKey: msg.threadKey
53116
53631
  })
53117
53632
  );
@@ -53122,7 +53637,7 @@ async function runLoop(deps, ctx) {
53122
53637
  gateBypassed = err2 instanceof HarnessGateBypassedError;
53123
53638
  if (err2 instanceof ModelPolicyRefusedError) failure2 = { kind: "policy_refusal" };
53124
53639
  else if (err2 instanceof ModelTransientFailureError) failure2 = { kind: "provider_transient" };
53125
- registry.publish(run2.id, {
53640
+ events.publish({
53126
53641
  type: "run_note",
53127
53642
  kind: "run_failed",
53128
53643
  summary: redactAndCap(err2 instanceof Error ? err2.message : String(err2), ENDING_NOTE_MAX)
@@ -53131,7 +53646,7 @@ async function runLoop(deps, ctx) {
53131
53646
  await endHarness().catch((endErr) => {
53132
53647
  const detail = `the harness session's end failed after the loop's own error: ${endErr instanceof Error ? endErr.message : String(endErr)}`;
53133
53648
  console.warn(`[run] ${msg.threadKey} ${detail}`);
53134
- registry.publish(run2.id, {
53649
+ events.publish({
53135
53650
  type: "run_note",
53136
53651
  kind: "harness_error",
53137
53652
  summary: redactAndCap(detail, ENDING_NOTE_MAX),
@@ -53140,13 +53655,13 @@ async function runLoop(deps, ctx) {
53140
53655
  });
53141
53656
  await preserveCodingChildWork("ending").catch((salvageErr) => {
53142
53657
  const summary = `the interrupted-work checkpoint failed before teardown: ${salvageErr instanceof Error ? salvageErr.message : String(salvageErr)}`;
53143
- registry.publish(run2.id, { type: "run_note", kind: "work_salvage", summary, at: clock4() });
53658
+ events.publish({ type: "run_note", kind: "work_salvage", summary, at: clock4() });
53144
53659
  shell.note("quiet", summary);
53145
53660
  });
53146
53661
  await root.span("post.workspace_release", (span) => releaseWorkspace(span));
53147
53662
  if (!interrupted) throw err2;
53148
53663
  if (coordinator !== void 0)
53149
- registry.publish(run2.id, {
53664
+ events.publish({
53150
53665
  type: "child_interrupted",
53151
53666
  parentInstanceId: coordinator.parentInstanceId,
53152
53667
  reason: redactAndCap(interrupted.message, ENDING_NOTE_MAX),
@@ -53161,12 +53676,49 @@ async function runLoop(deps, ctx) {
53161
53676
  };
53162
53677
  } finally {
53163
53678
  clearInterval(heartbeat);
53679
+ await events.drain();
53164
53680
  const status3 = statusNow();
53681
+ if (typeof registry.commitLiveState === "function") {
53682
+ const commitBoundary = async (state, at2) => {
53683
+ const summary = registry.getById(run2.id);
53684
+ if (!summary) return;
53685
+ const eventSeq = summary.eventCount + 1;
53686
+ const assignment = state === "ended" ? {
53687
+ expectedSeq: summary.liveStateSeq ?? 0,
53688
+ eventSeq,
53689
+ at: at2,
53690
+ state,
53691
+ cause: causeOfClose(status3, interrupted !== void 0)
53692
+ } : {
53693
+ expectedSeq: summary.liveStateSeq ?? 0,
53694
+ eventSeq,
53695
+ at: at2,
53696
+ state,
53697
+ bound: summary.liveState?.bound ?? at2,
53698
+ detail: "writing the final answer"
53699
+ };
53700
+ if (ledgerRun?.tracked()) {
53701
+ const committed = await ledgerRun.assignLiveState(assignment);
53702
+ if (committed.ok) registry.commitLiveState(run2.id, committed);
53703
+ return;
53704
+ }
53705
+ const local = assignRunLiveState(summary.liveState, summary.liveStateSeq ?? 0, assignment);
53706
+ if (!local.ok || !local.event) return;
53707
+ registry.commitLiveState(run2.id, {
53708
+ ...local,
53709
+ event: { ...local.event, seq: eventSeq },
53710
+ liveStateSeq: eventSeq
53711
+ });
53712
+ };
53713
+ const at = clock4();
53714
+ await commitBoundary("wrapping_up", at);
53715
+ await commitBoundary("ended", clock4());
53716
+ }
53165
53717
  registry.finish(run2.id, status3);
53166
53718
  const snap = registry.snapshot(run2.id, run2.token);
53167
- const events = snap?.events ?? [];
53719
+ const recordEventList = snap?.events ?? [];
53168
53720
  const finishedAt = snap?.finishedAt ?? clock4();
53169
- const diagnosis = analyzeRunFriction(events, {
53721
+ const diagnosis = analyzeRunFriction(recordEventList, {
53170
53722
  finished: true,
53171
53723
  truncated: snap?.truncated ?? false,
53172
53724
  window: { start: snap?.receivedAt ?? startedAt, end: finishedAt }
@@ -53299,10 +53851,13 @@ var init_runLoop = __esm({
53299
53851
  init_readingDiff();
53300
53852
  init_reviewDescription();
53301
53853
  init_runEvents();
53854
+ init_runEventLane();
53302
53855
  init_redact();
53303
53856
  init_runFriction();
53304
53857
  init_llmOutput();
53305
53858
  init_runRecord();
53859
+ init_runLiveState();
53860
+ init_decide();
53306
53861
  init_statusCardLabel();
53307
53862
  init_runPace();
53308
53863
  init_statusCardFrame();
@@ -54254,6 +54809,34 @@ async function runShipBranch(deps, msg, io, ctx) {
54254
54809
  ...REPLAY_EVERYTHING
54255
54810
  });
54256
54811
  }
54812
+ const admittedAt = clock4();
54813
+ const admittedEventSeq = (registry.getById(run2.id)?.eventCount ?? 0) + 1;
54814
+ const admittedAssignment = {
54815
+ expectedSeq: 0,
54816
+ eventSeq: admittedEventSeq,
54817
+ at: admittedAt,
54818
+ state: "admitted",
54819
+ bound: admittedAt + minutesToMs(profile.minutes),
54820
+ detail: "waiting for the pipeline to start"
54821
+ };
54822
+ if (ledgerRun) {
54823
+ const committed = await ledgerRun.assignLiveState(admittedAssignment);
54824
+ if (!committed.ok || !registry.commitLiveState(run2.id, committed))
54825
+ throw new RefusalError(
54826
+ refusalOf(
54827
+ "setup_failed",
54828
+ `hosted live state start was not committed (${committed.ok ? "registry sequence" : committed.reason})`
54829
+ )
54830
+ );
54831
+ } else {
54832
+ const local = assignRunLiveState(void 0, 0, admittedAssignment);
54833
+ if (local.ok && local.event)
54834
+ registry.commitLiveState(run2.id, {
54835
+ ...local,
54836
+ event: { ...local.event, seq: admittedEventSeq },
54837
+ liveStateSeq: admittedEventSeq
54838
+ });
54839
+ }
54257
54840
  const hostRefused = opened.kind === "untracked" && opened.why === "thread-live";
54258
54841
  const liveUrl = liveViewLink(run2.id, run2.token);
54259
54842
  ctx.live.runId = run2.id;
@@ -54324,7 +54907,23 @@ async function runShipBranch(deps, msg, io, ctx) {
54324
54907
  instanceId: outcome.instanceId,
54325
54908
  until: clock4() + minutesToMs(caps.maxMinutes + HOSTED_DEADLINE_MARGIN_MINUTES)
54326
54909
  };
54327
- ledgerRun.setState({ hosting });
54910
+ const summary = registry.getById(run2.id);
54911
+ const committed = await ledgerRun.assignLiveState({
54912
+ expectedSeq: summary?.liveStateSeq ?? 0,
54913
+ eventSeq: (summary?.eventCount ?? 0) + 1,
54914
+ at: clock4(),
54915
+ state: "working",
54916
+ bound: hosting.until,
54917
+ detail: HOSTED_PIPELINE_STARTING_DETAIL,
54918
+ statePatch: { hosting }
54919
+ });
54920
+ if (!committed.ok || !registry.commitLiveState(run2.id, committed))
54921
+ throw new RefusalError(
54922
+ refusalOf(
54923
+ "setup_failed",
54924
+ `hosted live state transition was not committed (${committed.ok ? "registry sequence" : committed.reason})`
54925
+ )
54926
+ );
54328
54927
  registry.publish(run2.id, {
54329
54928
  type: "run_meta",
54330
54929
  agent: agent.name,
@@ -54432,6 +55031,8 @@ var init_ship = __esm({
54432
55031
  init_runFriction();
54433
55032
  init_run2();
54434
55033
  init_runRegistry();
55034
+ init_runLiveState();
55035
+ init_pipelineStanding();
54435
55036
  init_statusCardFrame();
54436
55037
  init_types5();
54437
55038
  init_refusal();
@@ -55611,12 +56212,12 @@ async function dispatch(deps, msg, io, opts = {}) {
55611
56212
  ...operatorEvent ? { operator: operatorEvent } : {},
55612
56213
  ...references.conversations.length > 0 ? { references } : {}
55613
56214
  });
55614
- const { run: run2, runId: runId3, channelVisibility, liveUrl, publishText, publishMeta } = registration;
56215
+ const { run: run2, runId: runId3, channelVisibility, liveUrl, events, publishText, publishMeta } = registration;
55615
56216
  registered = run2;
55616
56217
  for (const summary of seedNotes)
55617
- registry.publish(run2.id, { type: "run_note", kind: "seed", summary: oneLine(summary), at: clock4() });
56218
+ events.publish({ type: "run_note", kind: "seed", summary: oneLine(summary), at: clock4() });
55618
56219
  if (opts.redispatch)
55619
- registry.publish(run2.id, {
56220
+ events.publish({
55620
56221
  type: "run_note",
55621
56222
  kind: "redispatch",
55622
56223
  summary: `confirmed after question ${opts.redispatch.code}`,
@@ -55631,7 +56232,7 @@ async function dispatch(deps, msg, io, opts = {}) {
55631
56232
  threadKey: msg.threadKey,
55632
56233
  nextIndex: nextStagedIndex,
55633
56234
  preserveWorkspaceIndexes: true,
55634
- publish: (e) => registry.publish(runId3, e)
56235
+ publish: (event) => events.publish(event)
55635
56236
  }) : void 0;
55636
56237
  const threadAssets = !resume && deps.artifacts && thread && thread.length > 0 ? readThreadAssets({ runs: runsService, store: deps.artifacts }, msg.threadKey).then(
55637
56238
  (assets) => assets.filter((a) => a.runId !== runId3)
@@ -55642,7 +56243,7 @@ async function dispatch(deps, msg, io, opts = {}) {
55642
56243
  {
55643
56244
  nextIndex: nextStagedIndex,
55644
56245
  messageId: messageIdOf(msg, runId3),
55645
- publish: (e) => registry.publish(runId3, e)
56246
+ publish: (event) => events.publish(event)
55646
56247
  }
55647
56248
  )
55648
56249
  ) : void 0;
@@ -55674,7 +56275,7 @@ async function dispatch(deps, msg, io, opts = {}) {
55674
56275
  reserved = reservation.reserved;
55675
56276
  requestRow = reservation.requestRow;
55676
56277
  if (reservation.untrackedWhy !== void 0) {
55677
- registry.publish(runId3, {
56278
+ events.publish({
55678
56279
  type: "run_note",
55679
56280
  kind: "ledger_untracked",
55680
56281
  summary: redactAndCap(
@@ -55688,6 +56289,100 @@ async function dispatch(deps, msg, io, opts = {}) {
55688
56289
  shell.note("debug", "untracked by the ledger");
55689
56290
  }
55690
56291
  }
56292
+ if (typeof registry.commitLiveState === "function") {
56293
+ await events.write(async () => {
56294
+ const current = registry.getById(runId3);
56295
+ if (current && current.liveState === void 0) {
56296
+ const at = clock4();
56297
+ const eventSeq = current.eventCount + 1;
56298
+ const assignment = {
56299
+ expectedSeq: 0,
56300
+ eventSeq,
56301
+ at,
56302
+ state: "admitted",
56303
+ bound: resume ? at + resume.plan.remainingMs : Math.max(startedAt + minutesToMs(profile.minutes), at + minutesToMs(profile.minutes)),
56304
+ detail: "waiting to attach the workspace",
56305
+ // A reservation is not subscribed to the registry until promotion.
56306
+ // Commit the setup stream that already exists with admission, or
56307
+ // advancing its ledger cursor here would make promotion skip it.
56308
+ ...reserved ? {
56309
+ sourceEvents: (registry.snapshotById(runId3)?.events ?? []).map((event) => ({
56310
+ ...event,
56311
+ seq: event.seq
56312
+ }))
56313
+ } : {},
56314
+ ...(current.liveStateSeq ?? 0) > 0 ? { restart: true } : {}
56315
+ };
56316
+ const tracked = reserved ?? ledgerRun;
56317
+ if (tracked?.tracked()) {
56318
+ let committed = await tracked.assignLiveState(assignment);
56319
+ if (!committed.ok && committed.reason === "stale-sequence" && (current.liveStateSeq ?? 0) > 0)
56320
+ committed = await tracked.assignLiveState({
56321
+ ...assignment,
56322
+ expectedSeq: current.liveStateSeq ?? 0,
56323
+ sourceEvents: void 0,
56324
+ restart: true
56325
+ });
56326
+ if (!committed.ok || !registry.commitLiveState(runId3, committed))
56327
+ throw new Error(
56328
+ `live state admission was not committed (${committed.ok ? "registry sequence" : committed.reason})`
56329
+ );
56330
+ } else {
56331
+ const expectedSeq = current.liveStateSeq ?? 0;
56332
+ const local = assignRunLiveState(void 0, expectedSeq, { ...assignment, expectedSeq });
56333
+ if (!local.ok || !local.event) throw new Error("live state admission was invalid");
56334
+ registry.commitLiveState(runId3, {
56335
+ ...local,
56336
+ event: { ...local.event, seq: eventSeq },
56337
+ liveStateSeq: eventSeq
56338
+ });
56339
+ }
56340
+ }
56341
+ });
56342
+ }
56343
+ const assignLive = async (next, at, detail) => {
56344
+ if (typeof registry.commitLiveState !== "function") return true;
56345
+ let accepted = false;
56346
+ await events.write(async () => {
56347
+ const summary = registry.getById(runId3);
56348
+ if (!summary) return;
56349
+ const eventSeq = summary.eventCount + 1;
56350
+ const assignment = {
56351
+ expectedSeq: summary.liveStateSeq ?? 0,
56352
+ eventSeq,
56353
+ at,
56354
+ state: next.state,
56355
+ bound: next.bound,
56356
+ ...detail !== void 0 ? { detail } : {}
56357
+ };
56358
+ const tracked = ledgerRun ?? reserved;
56359
+ if (tracked) {
56360
+ const committed = await tracked.assignLiveState(assignment);
56361
+ accepted = committed.ok && (registry.commitLiveState?.(runId3, committed) ?? true);
56362
+ return;
56363
+ }
56364
+ const local = assignRunLiveState(summary.liveState, summary.liveStateSeq ?? 0, assignment);
56365
+ if (!local.ok) return;
56366
+ accepted = registry.commitLiveState?.(runId3, {
56367
+ ...local,
56368
+ ...local.event ? { event: { ...local.event, seq: eventSeq } } : {},
56369
+ liveStateSeq: local.event ? eventSeq : summary.liveStateSeq ?? 0
56370
+ }) ?? true;
56371
+ });
56372
+ return accepted;
56373
+ };
56374
+ let residentAttachAttempt = 0;
56375
+ const observeResidentLiveState = async (observation) => {
56376
+ if (observation.attempt < residentAttachAttempt) return;
56377
+ residentAttachAttempt = observation.attempt;
56378
+ const accepted = await assignLive(
56379
+ { state: observation.state, bound: observation.bound },
56380
+ clock4(),
56381
+ liveStateWords(observation.state)
56382
+ );
56383
+ if (!accepted) throw new Error("resident live-state observation was stale or could not be committed");
56384
+ shell.setSetupLabel(`${liveStateWords(observation.state)}\u2026`);
56385
+ };
55691
56386
  const reattach = resume ? carriedWorkspaceBinding(resume.row) : void 0;
55692
56387
  const control = registered?.control;
55693
56388
  const attach = await attachWorkspace(deps, {
@@ -55707,7 +56402,8 @@ async function dispatch(deps, msg, io, opts = {}) {
55707
56402
  // during the attach ends its wake wait at once, and once the harness
55708
56403
  // starts the lease every attach the executor opens is clipped to the
55709
56404
  // run's remaining clock (execution.md item 9).
55710
- ...control ? { stopSignal: control.hardSignal, remainingMs: () => control.remainingMs() } : {}
56405
+ ...control ? { stopSignal: control.hardSignal, remainingMs: () => control.remainingMs() } : {},
56406
+ onLiveStateObservation: observeResidentLiveState
55711
56407
  });
55712
56408
  if (attach.kind === "refused") return ended;
55713
56409
  if (attach.kind === "stopped") {
@@ -55759,6 +56455,17 @@ async function dispatch(deps, msg, io, opts = {}) {
55759
56455
  return ended;
55760
56456
  }
55761
56457
  const { round: round2 } = attach;
56458
+ if (typeof registry.commitLiveState === "function") {
56459
+ const summary = registry.getById(runId3);
56460
+ const bound2 = summary?.liveState?.bound ?? startedAt + minutesToMs(profile.minutes);
56461
+ if (summary?.liveState && (summary.liveState.state === "waiting_deploy" || summary.liveState.state === "waiting_repository") && round2.selection.backend !== "resident") {
56462
+ if (!await assignLive({ state: "falling_back", bound: bound2 }, clock4(), "switching to a fallback workspace"))
56463
+ throw new Error("fallback live state could not be committed");
56464
+ }
56465
+ if (!await assignLive({ state: "preparing", bound: bound2 }, clock4(), "preparing the workspace"))
56466
+ throw new Error("preparation live state could not be committed");
56467
+ shell.setSetupLabel(`${liveStateWords("preparing")}\u2026`);
56468
+ }
55762
56469
  if (resume && ledgerRun) {
55763
56470
  const rebound = workspaceBindingFor(round2.selection, profile.machine);
55764
56471
  if (rebound !== void 0) ledgerRun.setState({ binding: rebound });
@@ -55940,6 +56647,12 @@ async function dispatch(deps, msg, io, opts = {}) {
55940
56647
  markUntracked: () => shell.note("debug", "untracked by the ledger"),
55941
56648
  ...seedActors !== void 0 ? { seedActors } : {}
55942
56649
  });
56650
+ if (typeof registry.commitLiveState === "function") {
56651
+ const summary = registry.getById(runId3);
56652
+ const bound2 = summary?.liveState?.bound ?? startedAt + minutesToMs(profile.minutes);
56653
+ if (!await assignLive({ state: "working", bound: bound2 }, clock4(), "model turn"))
56654
+ throw new Error("working live state could not be committed");
56655
+ }
55943
56656
  const sessionTools = sessionCapabilityFor(
55944
56657
  ledgerRun,
55945
56658
  deps.runLedger,
@@ -55981,6 +56694,7 @@ async function dispatch(deps, msg, io, opts = {}) {
55981
56694
  mcpForRun,
55982
56695
  run: run2,
55983
56696
  registry,
56697
+ events,
55984
56698
  round: round2,
55985
56699
  admitted,
55986
56700
  ledgerRun,
@@ -56309,6 +57023,8 @@ var init_dispatcher = __esm({
56309
57023
  init_registry();
56310
57024
  init_budgets();
56311
57025
  init_trace();
57026
+ init_runLiveState();
57027
+ init_decide();
56312
57028
  init_requestTrace();
56313
57029
  init_runShape();
56314
57030
  init_runEvents();
@@ -56806,6 +57522,7 @@ function createLedgerWriteThrough(opts) {
56806
57522
  turnIndex: report2.firstIdx + turns.length,
56807
57523
  inFlight: report2.inFlight,
56808
57524
  inboxConsumedSeq: report2.inboxConsumedSeq,
57525
+ ...report2.inboxDeferredSeqs?.length ? { inboxDeferredSeqs: report2.inboxDeferredSeqs } : {},
56809
57526
  remainingMs: report2.remainingMs,
56810
57527
  turn: report2.turn,
56811
57528
  iteration: report2.iteration
@@ -56839,7 +57556,7 @@ function createLedgerWriteThrough(opts) {
56839
57556
  }
56840
57557
  }
56841
57558
  event(event, seq) {
56842
- if (this.detached || this.finished) return;
57559
+ if (this.detached || this.finished || seq <= this.lastSeq) return;
56843
57560
  this.lastSeq = seq;
56844
57561
  const e = event;
56845
57562
  if (typeof e.at === "number") this.factLastEventAt = e.at;
@@ -56860,6 +57577,30 @@ function createLedgerWriteThrough(opts) {
56860
57577
  };
56861
57578
  this.flusher.push({ ...event, seq });
56862
57579
  }
57580
+ async assignLiveState(assignment) {
57581
+ if (this.detached || this.finished) return { ok: false, reason: "unknown-run" };
57582
+ await this.flusher.flush();
57583
+ await this.stateSending;
57584
+ try {
57585
+ const result = await ledger.assignLiveState(this.runId, gen, assignment);
57586
+ if (!result.ok) {
57587
+ if (result.reason === "fenced" || result.reason === "unknown-run")
57588
+ this.detach(`live state refused (${result.reason})`);
57589
+ return result;
57590
+ }
57591
+ this.state = {
57592
+ ...this.state,
57593
+ ...assignment.statePatch,
57594
+ liveState: result.liveState,
57595
+ liveStateSeq: result.liveStateSeq
57596
+ };
57597
+ this.lastSeq = Math.max(this.lastSeq, result.liveStateSeq);
57598
+ return result;
57599
+ } catch (err2) {
57600
+ warn(`[ledger] ${this.threadKey} live state not written: ${describe9(err2)}`);
57601
+ return { ok: false, reason: "unknown-run" };
57602
+ }
57603
+ }
56863
57604
  setState(patch) {
56864
57605
  if (this.detached) return;
56865
57606
  this.state = { ...this.state, ...patch };
@@ -57244,6 +57985,9 @@ var init_writeThrough = __esm({
57244
57985
  }
57245
57986
  event(_event, _seq) {
57246
57987
  }
57988
+ async assignLiveState(_assignment) {
57989
+ return { ok: false, reason: "unknown-run" };
57990
+ }
57247
57991
  setState(_patch) {
57248
57992
  }
57249
57993
  async finishing() {
@@ -63023,14 +63767,23 @@ var init_configBoot = __esm({
63023
63767
  });
63024
63768
 
63025
63769
  // ../../src/intakeModel.ts
63770
+ function intakeDecisionDeps(completion, deps) {
63771
+ return {
63772
+ model: completion.model,
63773
+ ...completion.capField !== void 0 ? { capField: completion.capField } : {},
63774
+ ...deps
63775
+ };
63776
+ }
63026
63777
  function intakeCompletion(config, completions, log = console.log) {
63027
63778
  const modelRef3 = intakeModelRef(config);
63028
63779
  if (!modelRef3) return void 0;
63029
63780
  const ref = parseModelRef(modelRef3);
63781
+ const card = resolveModelCard(modelRef3, config.providers, installedModelRegistry);
63030
63782
  const effort2 = turnEffort(modelRef3, config.intake?.effort, config.providers);
63031
63783
  if (effort2.note) log(`[intake] effort: ${effort2.note}`);
63032
63784
  return {
63033
63785
  modelRef: modelRef3,
63786
+ capField: card.capField,
63034
63787
  model: providerStructuredModel(completions.get(ref.provider), ref.model, {
63035
63788
  ...effort2.request ? { effort: effort2.request } : {}
63036
63789
  })
@@ -63042,6 +63795,8 @@ var init_intakeModel = __esm({
63042
63795
  init_config2();
63043
63796
  init_route();
63044
63797
  init_turnEffort();
63798
+ init_installedModelRegistry();
63799
+ init_modelCard();
63045
63800
  init_provider();
63046
63801
  }
63047
63802
  });
@@ -63164,7 +63919,10 @@ async function askModel(input, deps) {
63164
63919
  floor: (violation) => ({ verdict: "silent", reason: violation, source: "error" })
63165
63920
  },
63166
63921
  deps.model,
63167
- { maxTokens: ROUTE_MIN_OUTPUT_TOKENS, signal: AbortSignal.timeout(deps.timeoutMs ?? ROUTE_TIMEOUT_MS) }
63922
+ {
63923
+ maxTokens: outputCapWithReasoning(ROUTE_MIN_OUTPUT_TOKENS, { capField: deps.capField }),
63924
+ signal: AbortSignal.timeout(deps.timeoutMs ?? ROUTE_TIMEOUT_MS)
63925
+ }
63168
63926
  );
63169
63927
  return { ...seam.value, attempts: seam.attempts };
63170
63928
  } catch (err2) {
@@ -63173,8 +63931,18 @@ async function askModel(input, deps) {
63173
63931
  if (timedOut) {
63174
63932
  return {
63175
63933
  verdict: "silent",
63176
- reason: tidyReason("the intake call timed out"),
63934
+ reason: renderProviderFailure("transient", "ended"),
63177
63935
  source: "timeout",
63936
+ providerFailure: "transient",
63937
+ ...attempts ? { attempts } : {}
63938
+ };
63939
+ }
63940
+ const outputCapError = err2 instanceof OutputCapError ? err2 : err2 instanceof StructuredAskError && err2.cause instanceof OutputCapError ? err2.cause : void 0;
63941
+ if (outputCapError) {
63942
+ return {
63943
+ verdict: "silent",
63944
+ reason: tidyReason(outputCapError.message),
63945
+ source: "error",
63178
63946
  ...attempts ? { attempts } : {}
63179
63947
  };
63180
63948
  }
@@ -70068,7 +70836,13 @@ async function launchResumes(deps, resumable, opts) {
70068
70836
  const handle2 = registry.create(row2.meta.label, rehostMeta(row2), {
70069
70837
  id: row2.runId,
70070
70838
  startedAt: row2.startedAt,
70071
- replay: run2.events
70839
+ replay: run2.events,
70840
+ ...row2.liveState !== void 0 ? {
70841
+ liveState: {
70842
+ liveState: row2.liveState,
70843
+ ...row2.liveStateSeq !== void 0 ? { liveStateSeq: row2.liveStateSeq } : {}
70844
+ }
70845
+ } : {}
70072
70846
  });
70073
70847
  const adopted = deps.runLedger.adopt({
70074
70848
  runId: row2.runId,
@@ -70509,6 +71283,72 @@ var init_adminModelProxy = __esm({
70509
71283
  }
70510
71284
  });
70511
71285
 
71286
+ // ../../src/core/providerLiveStateCoordinator.ts
71287
+ function createProviderLiveStateCoordinator(deps) {
71288
+ let tail = Promise.resolve();
71289
+ const enqueue = (label, work) => {
71290
+ const next = tail.then(work).catch((error) => {
71291
+ deps.warn(`${label} failed: ${describe11(error)}`);
71292
+ });
71293
+ tail = next;
71294
+ return next;
71295
+ };
71296
+ return {
71297
+ level: (provider, side, cause) => enqueue(`provider ${side} report for ${provider}`, async () => {
71298
+ await deps.runLedger.planeLevel({
71299
+ provider,
71300
+ name: "provider",
71301
+ side,
71302
+ ...side === "down" && cause !== void 0 ? { cause } : {}
71303
+ });
71304
+ if (side !== "up" || !deps.ledger) return;
71305
+ const rows = await deps.ledger.listLive();
71306
+ for (const row2 of rows) {
71307
+ if (row2.state.liveProvider !== provider || row2.liveState?.state !== "waiting_provider") continue;
71308
+ const tracked = deps.runLedger.liveRuns().find((run2) => run2.runId === row2.runId);
71309
+ const summary = deps.registry.getById(row2.runId);
71310
+ if (!tracked || !summary || row2.liveState.bound === void 0) continue;
71311
+ const committed = await tracked.assignLiveState({
71312
+ expectedSeq: summary.liveStateSeq ?? 0,
71313
+ eventSeq: summary.eventCount + 1,
71314
+ at: deps.clock(),
71315
+ state: "working",
71316
+ bound: row2.liveState.bound,
71317
+ detail: "model turn",
71318
+ statePatch: { liveProvider: void 0 }
71319
+ });
71320
+ if (committed.ok) deps.registry.commitLiveState(row2.runId, committed);
71321
+ }
71322
+ }),
71323
+ park: (runId3, provider) => enqueue(`provider park for ${runId3}`, async () => {
71324
+ await deps.runLedger.planePark(runId3, provider);
71325
+ const summary = deps.registry.getById(runId3);
71326
+ const tracked = deps.runLedger.liveRuns().find((run2) => run2.runId === runId3);
71327
+ const events = deps.registry.snapshotById(runId3)?.events ?? [];
71328
+ let leaseEndsAt;
71329
+ for (const event of events) if (event.type === "lease") leaseEndsAt = event.endsAt;
71330
+ if (!summary || !tracked || leaseEndsAt === void 0) return;
71331
+ const committed = await tracked.assignLiveState({
71332
+ expectedSeq: summary.liveStateSeq ?? 0,
71333
+ eventSeq: summary.eventCount + 1,
71334
+ at: deps.clock(),
71335
+ state: "waiting_provider",
71336
+ bound: leaseEndsAt,
71337
+ detail: "waiting for the model provider",
71338
+ statePatch: { liveProvider: provider }
71339
+ });
71340
+ if (committed.ok) deps.registry.commitLiveState(runId3, committed);
71341
+ })
71342
+ };
71343
+ }
71344
+ var describe11;
71345
+ var init_providerLiveStateCoordinator = __esm({
71346
+ "../../src/core/providerLiveStateCoordinator.ts"() {
71347
+ "use strict";
71348
+ describe11 = (error) => error instanceof Error ? error.message : String(error);
71349
+ }
71350
+ });
71351
+
70512
71352
  // ../../src/channels/adminTraceLog.ts
70513
71353
  function parseTraceLogQuery(search) {
70514
71354
  const query = {};
@@ -71018,7 +71858,7 @@ async function openThreadFromRequester(deps, instance, lead, at) {
71018
71858
  }
71019
71859
  };
71020
71860
  } catch (err2) {
71021
- return { ok: false, response: json3(502, { ok: false, error: "thread_failed", message: describe11(err2), at }) };
71861
+ return { ok: false, response: json3(502, { ok: false, error: "thread_failed", message: describe12(err2), at }) };
71022
71862
  }
71023
71863
  }
71024
71864
  function authorizeStep(headers, step, deps) {
@@ -71142,8 +71982,8 @@ async function spawn6(body, deps) {
71142
71982
  try {
71143
71983
  turn = await composeChild(req.brief, instance, row2, briefReaders(deps, instance));
71144
71984
  } catch (err2) {
71145
- log(`[coordinator] ${instance.id} ${req.step}: the brief could not be composed: ${describe11(err2)}`);
71146
- return json3(502, { ok: false, error: "brief_failed", message: describe11(err2), at });
71985
+ log(`[coordinator] ${instance.id} ${req.step}: the brief could not be composed: ${describe12(err2)}`);
71986
+ return json3(502, { ok: false, error: "brief_failed", message: describe12(err2), at });
71147
71987
  }
71148
71988
  } else {
71149
71989
  turn = { prompt: req.prompt };
@@ -71213,7 +72053,7 @@ ${foldThreadEvents(folded)}` };
71213
72053
  });
71214
72054
  } catch (err2) {
71215
72055
  releaseAdmission();
71216
- return json3(502, { ok: false, error: "spawn_failed", message: describe11(err2), at });
72056
+ return json3(502, { ok: false, error: "spawn_failed", message: describe12(err2), at });
71217
72057
  }
71218
72058
  const settled = dispatching.then(
71219
72059
  (outcome) => ({ kind: "ended", outcome }),
@@ -71222,7 +72062,7 @@ ${foldThreadEvents(folded)}` };
71222
72062
  void settled.then((end) => {
71223
72063
  releaseAdmission();
71224
72064
  if (end.kind === "threw")
71225
- log(`[coordinator] ${instance.id} ${req.step}: the child's dispatch threw: ${describe11(end.err)}`);
72065
+ log(`[coordinator] ${instance.id} ${req.step}: the child's dispatch threw: ${describe12(end.err)}`);
71226
72066
  });
71227
72067
  const first = await Promise.race([started.then((id) => ({ kind: "started", id })), settled]);
71228
72068
  if (first.kind === "started" || startedId !== void 0) {
@@ -71232,7 +72072,7 @@ ${foldThreadEvents(folded)}` };
71232
72072
  { instanceId: instance.id, unit: row2.unit },
71233
72073
  folded.map((e) => e.seq),
71234
72074
  req.step
71235
- ).catch((err2) => log(`[coordinator] ${instance.id} ${req.step}: the consumed marks failed: ${describe11(err2)}`));
72075
+ ).catch((err2) => log(`[coordinator] ${instance.id} ${req.step}: the consumed marks failed: ${describe12(err2)}`));
71236
72076
  log(
71237
72077
  `[coordinator] ${instance.id} ${req.step}: folded ${folded.length} thread event(s) into the ${req.preset} child`
71238
72078
  );
@@ -71240,7 +72080,7 @@ ${foldThreadEvents(folded)}` };
71240
72080
  log(`[coordinator] ${instance.id} ${req.step}: spawned ${req.preset} run ${runId3} in ${threadKey}`);
71241
72081
  return json3(200, { ok: true, runId: runId3, threadKey, at });
71242
72082
  }
71243
- if (first.kind === "threw") return json3(502, { ok: false, error: "spawn_failed", message: describe11(first.err), at });
72083
+ if (first.kind === "threw") return json3(502, { ok: false, error: "spawn_failed", message: describe12(first.err), at });
71244
72084
  const refusal = first.outcome.refusal;
71245
72085
  if (refusal === "coordinator_thread_live") {
71246
72086
  const now = await liveOnThread(deps.runs, instance, threadKey);
@@ -71424,6 +72264,25 @@ async function childPullRequestState(deps, instance, unit) {
71424
72264
  if (state === void 0) throw new Error(headBranchStateError(instance.repo, row2.pr.number));
71425
72265
  return state;
71426
72266
  }
72267
+ async function isEarlierAttemptRun(deps, current, view, unit) {
72268
+ if (current?.plan === void 0 || view.parentInstanceId === void 0 || unit === void 0) return false;
72269
+ if (unitOfIdempotencyKey(view.idempotencyKey ?? "") !== unit) return false;
72270
+ const prior = await deps.instances.get(view.parentInstanceId);
72271
+ if (prior?.plan === void 0) return false;
72272
+ const currentAttempt = current.attempt ?? 1;
72273
+ const priorAttempt = prior.attempt ?? 1;
72274
+ if (currentAttempt <= priorAttempt || current.plan.id !== prior.plan.id || current.plan.path !== prior.plan.path || current.repo !== prior.repo)
72275
+ return false;
72276
+ const [nextAttempt, currentUnits, priorUnits] = await Promise.all([
72277
+ deps.instances.get(planInstanceId(current.plan.id, currentAttempt + 1)),
72278
+ deps.instances.listUnits(current.id),
72279
+ deps.instances.listUnits(prior.id)
72280
+ ]);
72281
+ if (nextAttempt !== null) return false;
72282
+ const currentUnit = currentUnits.find((row2) => row2.unit === unit);
72283
+ const priorUnit = priorUnits.find((row2) => row2.unit === unit);
72284
+ return currentUnit !== void 0 && priorUnit !== void 0 && currentUnit.branch === priorUnit.branch;
72285
+ }
71427
72286
  async function readRecord(body, deps) {
71428
72287
  const id = parseInstanceId(body.parentInstanceId);
71429
72288
  if (!id.ok) return json3(400, { ok: false, error: id.error });
@@ -71432,15 +72291,16 @@ async function readRecord(body, deps) {
71432
72291
  if (body.unit !== void 0 && (typeof body.unit !== "string" || !UNIT_ID.test(body.unit)))
71433
72292
  return json3(400, { ok: false, error: "unit must be a unit id" });
71434
72293
  const at = (deps.clock ?? systemClock)();
71435
- const res = await deps.runs.getRun(body.runId);
71436
- if (!res.ok || res.value.parentInstanceId !== id.value) return json3(404, { ok: false, error: "not_found" });
72294
+ const [res, instanceRow] = await Promise.all([deps.runs.getRun(body.runId), deps.instances.get(id.value)]);
72295
+ if (!res.ok) return json3(404, { ok: false, error: "not_found" });
71437
72296
  const view = res.value;
71438
- const instanceRow = await deps.instances.get(id.value);
72297
+ if (view.parentInstanceId !== id.value && !await isEarlierAttemptRun(deps, instanceRow, view, typeof body.unit === "string" ? body.unit : void 0))
72298
+ return json3(404, { ok: false, error: "not_found" });
71439
72299
  let pullRequest;
71440
72300
  try {
71441
72301
  pullRequest = await childPullRequestState(deps, instanceRow, typeof body.unit === "string" ? body.unit : void 0);
71442
72302
  } catch (err2) {
71443
- return json3(502, { ok: false, error: "github_unavailable", message: describe11(err2), at });
72303
+ return json3(502, { ok: false, error: "github_unavailable", message: describe12(err2), at });
71444
72304
  }
71445
72305
  if (!view.finished)
71446
72306
  return json3(200, {
@@ -71756,7 +72616,7 @@ async function prCheck(body, deps) {
71756
72616
  if (recover === void 0) {
71757
72617
  const ahead = instance.base === void 0 ? void 0 : await deps.commitsOverBase(instance.repo, instance.base, branch2).catch((err2) => {
71758
72618
  (deps.log ?? console.log)(
71759
- `[coordinator] ${instance.id} pr-check: the compare of ${branch2} over ${instance.base} could not be read: ${describe11(err2)}`
72619
+ `[coordinator] ${instance.id} pr-check: the compare of ${branch2} over ${instance.base} could not be read: ${describe12(err2)}`
71760
72620
  );
71761
72621
  return void 0;
71762
72622
  });
@@ -71780,7 +72640,7 @@ async function prCheck(body, deps) {
71780
72640
  if (state?.state !== "merged") throw new Error(`${instance.repo}#${merged.number} no longer reads merged`);
71781
72641
  return json3(200, { ok: true, ...state, at });
71782
72642
  } catch (err2) {
71783
- return json3(502, { ok: false, error: "github_unavailable", message: describe11(err2), at });
72643
+ return json3(502, { ok: false, error: "github_unavailable", message: describe12(err2), at });
71784
72644
  }
71785
72645
  }
71786
72646
  async function hostRunOf(deps, instance) {
@@ -71793,14 +72653,68 @@ async function hostRunOf(deps, instance) {
71793
72653
  return { kind: "not_host" };
71794
72654
  return { kind: "untracked" };
71795
72655
  }
71796
- function hostPublish(deps, instance, runId3, events, at) {
71797
- for (const event of events) deps.registry.publish(runId3, event);
72656
+ async function hostPublish(deps, instance, runId3, events, at) {
71798
72657
  const caps = instance.caps ?? resolveShipCaps(void 0);
71799
72658
  const hosting = {
71800
72659
  instanceId: instance.id,
71801
72660
  until: at + minutesToMs(caps.maxMinutes + HOSTED_DEADLINE_MARGIN_MINUTES)
71802
72661
  };
71803
- deps.ledgerRuns().find((run2) => run2.runId === runId3)?.setState({ hosting });
72662
+ const ledgerRun = deps.ledgerRuns().find((run2) => run2.runId === runId3);
72663
+ let summary = deps.registry.getById(runId3);
72664
+ if (ledgerRun && summary) {
72665
+ if (summary.liveState === void 0) {
72666
+ const admitted = await ledgerRun.assignLiveState({
72667
+ expectedSeq: 0,
72668
+ eventSeq: summary.eventCount + 1,
72669
+ at,
72670
+ state: "admitted",
72671
+ bound: hosting.until,
72672
+ detail: "waiting for the pipeline hand-off"
72673
+ });
72674
+ if (!admitted.ok || !deps.registry.commitLiveState(runId3, admitted))
72675
+ throw new Error(
72676
+ `hosted live state backfill was not committed (${admitted.ok ? "registry sequence" : admitted.reason})`
72677
+ );
72678
+ summary = deps.registry.getById(runId3);
72679
+ if (!summary) throw new Error("hosted run disappeared during live-state backfill");
72680
+ const working = await ledgerRun.assignLiveState({
72681
+ expectedSeq: summary.liveStateSeq ?? 0,
72682
+ eventSeq: summary.eventCount + 1,
72683
+ at,
72684
+ state: "working",
72685
+ bound: hosting.until,
72686
+ detail: "pipeline starting",
72687
+ statePatch: { hosting }
72688
+ });
72689
+ if (!working.ok || !deps.registry.commitLiveState(runId3, working))
72690
+ throw new Error(
72691
+ `hosted working backfill was not committed (${working.ok ? "registry sequence" : working.reason})`
72692
+ );
72693
+ summary = deps.registry.getById(runId3);
72694
+ if (!summary) throw new Error("hosted run disappeared after live-state backfill");
72695
+ }
72696
+ const firstSeq = summary.eventCount + 1;
72697
+ const sourceEvents = events.map((event, index) => ({ ...event, seq: firstSeq + index }));
72698
+ const prior = deps.registry.snapshotById(runId3)?.events.filter((event) => event.type === "ship_round" || event.type === "ship_unit") ?? [];
72699
+ const standing = pipelineStandingOf([...prior, ...events]);
72700
+ const stage = standing.changes.at(-1)?.stage ?? "idle";
72701
+ const committed = await ledgerRun.assignLiveState({
72702
+ expectedSeq: summary.liveStateSeq ?? 0,
72703
+ at,
72704
+ state: "working",
72705
+ bound: hosting.until,
72706
+ detail: hostedStageDetail(stage),
72707
+ statePatch: { hosting },
72708
+ sourceEvents
72709
+ });
72710
+ if (!committed.ok || !deps.registry.commitLiveState(runId3, committed))
72711
+ throw new Error(
72712
+ `hosted live state refresh was not committed (${committed.ok ? "registry sequence" : committed.reason})`
72713
+ );
72714
+ } else {
72715
+ ledgerRun?.setState({ hosting });
72716
+ }
72717
+ for (const event of events) deps.registry.publish(runId3, event);
71804
72718
  }
71805
72719
  function namesForeignRun(instance, body) {
71806
72720
  return typeof body.runId === "string" && body.runId !== instance.runId;
@@ -71886,7 +72800,7 @@ async function unitStart(body, deps) {
71886
72800
  row2 = { ...row2, startedAt: row2.startedAt ?? at };
71887
72801
  await deps.instances.putUnits([row2]);
71888
72802
  if (host.kind === "host")
71889
- hostPublish(
72803
+ await hostPublish(
71890
72804
  deps,
71891
72805
  instance,
71892
72806
  host.runId,
@@ -71935,7 +72849,7 @@ async function branch(body, deps) {
71935
72849
  await deps.createBranchRef(instance.repo, name, base);
71936
72850
  return json3(200, { ok: true, branch: name, base, at });
71937
72851
  } catch (err2) {
71938
- return json3(200, { ok: false, reason: describe11(err2), at });
72852
+ return json3(200, { ok: false, reason: describe12(err2), at });
71939
72853
  }
71940
72854
  }
71941
72855
  function unitLines(units, generated, severity) {
@@ -72016,7 +72930,7 @@ async function round(body, deps) {
72016
72930
  await deps.instances.putUnits([updated]);
72017
72931
  if (host.kind === "host") {
72018
72932
  const thread = unitThread(instance, updated, units.length);
72019
- hostPublish(
72933
+ await hostPublish(
72020
72934
  deps,
72021
72935
  instance,
72022
72936
  host.runId,
@@ -72050,7 +72964,7 @@ async function round(body, deps) {
72050
72964
  instance,
72051
72965
  units.map((u) => u.unit === updated.unit ? updated : u)
72052
72966
  ).catch(
72053
- (err2) => (deps.log ?? console.warn)(`[coordinator] ${instance.id}: the card could not be redrawn: ${describe11(err2)}`)
72967
+ (err2) => (deps.log ?? console.warn)(`[coordinator] ${instance.id}: the card could not be redrawn: ${describe12(err2)}`)
72054
72968
  );
72055
72969
  return json3(200, { ok: true, at });
72056
72970
  }
@@ -72224,7 +73138,7 @@ async function unitWake(body, deps) {
72224
73138
  instance,
72225
73139
  units.map((u) => u.unit === visible.unit ? visible : u)
72226
73140
  ).catch(
72227
- (err2) => (deps.log ?? console.warn)(`[coordinator] ${instance.id}: the card could not be redrawn: ${describe11(err2)}`)
73141
+ (err2) => (deps.log ?? console.warn)(`[coordinator] ${instance.id}: the card could not be redrawn: ${describe12(err2)}`)
72228
73142
  );
72229
73143
  return json3(200, { ok: true, answer, at });
72230
73144
  }
@@ -72287,7 +73201,7 @@ async function unitEnd(body, deps) {
72287
73201
  deps.runnerOwnership?.release(instance.repo, updated.pr.number);
72288
73202
  const thread = unitThread(instance, updated, units.length);
72289
73203
  if (host.kind === "host")
72290
- hostPublish(
73204
+ await hostPublish(
72291
73205
  deps,
72292
73206
  instance,
72293
73207
  host.runId,
@@ -72318,7 +73232,7 @@ async function unitEnd(body, deps) {
72318
73232
  `unit-end:${row2.unit}`
72319
73233
  ).catch(
72320
73234
  (err2) => (deps.log ?? console.warn)(
72321
- `[coordinator] ${instance.id} ${row2.unit}: the leftover marks failed: ${describe11(err2)}`
73235
+ `[coordinator] ${instance.id} ${row2.unit}: the leftover marks failed: ${describe12(err2)}`
72322
73236
  )
72323
73237
  );
72324
73238
  const freshTurn = {
@@ -72336,7 +73250,7 @@ async function unitEnd(body, deps) {
72336
73250
  };
72337
73251
  void deps.dispatch(freshTurn, io).catch(
72338
73252
  (err2) => (deps.log ?? console.warn)(
72339
- `[coordinator] ${instance.id} ${row2.unit}: the leftovers' fresh turn threw: ${describe11(err2)}`
73253
+ `[coordinator] ${instance.id} ${row2.unit}: the leftovers' fresh turn threw: ${describe12(err2)}`
72340
73254
  )
72341
73255
  );
72342
73256
  (deps.log ?? console.log)(
@@ -72353,7 +73267,7 @@ async function unitEnd(body, deps) {
72353
73267
  told = true;
72354
73268
  } catch (err2) {
72355
73269
  (deps.log ?? console.warn)(
72356
- `[coordinator] ${instance.id} ${row2.unit}: the report could not be posted: ${describe11(err2)}`
73270
+ `[coordinator] ${instance.id} ${row2.unit}: the report could not be posted: ${describe12(err2)}`
72357
73271
  );
72358
73272
  }
72359
73273
  }
@@ -72367,7 +73281,7 @@ ${ending.report}` + (rendered !== void 0 ? `
72367
73281
  ${rendered}` : "");
72368
73282
  await deps.github.commentIssue(instance.repo, row2.issue, comment).catch(
72369
73283
  (err2) => (deps.log ?? console.warn)(
72370
- `[coordinator] ${instance.id} ${row2.unit}: the board comment could not be posted: ${describe11(err2)}`
73284
+ `[coordinator] ${instance.id} ${row2.unit}: the board comment could not be posted: ${describe12(err2)}`
72371
73285
  )
72372
73286
  );
72373
73287
  }
@@ -72378,7 +73292,7 @@ ${rendered}` : "");
72378
73292
 
72379
73293
  ${ending.report}`).catch(
72380
73294
  (err2) => (deps.log ?? console.warn)(
72381
- `[coordinator] ${instance.id} ${row2.unit}: the human-gated report could not be posted on the pull request: ${describe11(err2)}`
73295
+ `[coordinator] ${instance.id} ${row2.unit}: the human-gated report could not be posted on the pull request: ${describe12(err2)}`
72382
73296
  )
72383
73297
  );
72384
73298
  }
@@ -72440,7 +73354,7 @@ async function rebaseStep(body, deps) {
72440
73354
  at
72441
73355
  });
72442
73356
  } catch (err2) {
72443
- return json3(200, { ok: true, outcome: "refused", reason: describe11(err2), at });
73357
+ return json3(200, { ok: true, outcome: "refused", reason: describe12(err2), at });
72444
73358
  }
72445
73359
  }
72446
73360
  async function merge(body, deps, subject2) {
@@ -72478,7 +73392,7 @@ async function merge(body, deps, subject2) {
72478
73392
  try {
72479
73393
  facts2 = await deps.fetchPrFacts(pr);
72480
73394
  } catch (err2) {
72481
- return json3(502, { ok: false, error: "github_unavailable", message: describe11(err2), at });
73395
+ return json3(502, { ok: false, error: "github_unavailable", message: describe12(err2), at });
72482
73396
  }
72483
73397
  if (facts2 === void 0)
72484
73398
  return json3(502, { ok: false, error: "github_unavailable", message: `${where} could not be read`, at });
@@ -72604,7 +73518,7 @@ async function merge(body, deps, subject2) {
72604
73518
  try {
72605
73519
  queued = await deps.enqueuePullRequest(pr, { sha: headSha });
72606
73520
  } catch (err2) {
72607
- return json3(502, { ok: false, error: "github_unavailable", message: describe11(err2), at });
73521
+ return json3(502, { ok: false, error: "github_unavailable", message: describe12(err2), at });
72608
73522
  }
72609
73523
  if (!queued.ok) return refused7(`GitHub refused to enqueue ${where}: ${queued.reason}`);
72610
73524
  log(
@@ -72621,7 +73535,7 @@ async function merge(body, deps, subject2) {
72621
73535
  title: facts2.title ?? `Merge pull request #${pr.number}`
72622
73536
  });
72623
73537
  } catch (err2) {
72624
- return json3(502, { ok: false, error: "github_unavailable", message: describe11(err2), at });
73538
+ return json3(502, { ok: false, error: "github_unavailable", message: describe12(err2), at });
72625
73539
  }
72626
73540
  if (!merged.ok) {
72627
73541
  if (merged.status === 405 && MERGE_QUEUE_405.test(merged.reason)) return enqueue();
@@ -72732,13 +73646,54 @@ async function finish(body, deps) {
72732
73646
  if (host.kind === "not_host") return json3(409, { ok: false, error: "not_host", at });
72733
73647
  const units = await deps.instances.listUnits(instance.id);
72734
73648
  if (host.kind === "host") {
72735
- hostPublish(
72736
- deps,
72737
- instance,
72738
- host.runId,
72739
- [{ type: "answer", text: planSummary(units, isGenerated2(instance)), at }],
72740
- at
72741
- );
73649
+ const ledgerRun = deps.ledgerRuns().find((run2) => run2.runId === host.runId);
73650
+ let summary = deps.registry.getById(host.runId);
73651
+ if (ledgerRun && summary) {
73652
+ if (summary.liveState === void 0) {
73653
+ await hostPublish(deps, instance, host.runId, [], at);
73654
+ summary = deps.registry.getById(host.runId);
73655
+ if (!summary) throw new Error("hosted run disappeared during finish backfill");
73656
+ }
73657
+ const bound = summary.liveState?.bound ?? at + minutesToMs(HOSTED_DEADLINE_MARGIN_MINUTES);
73658
+ const wrapping = await ledgerRun.assignLiveState({
73659
+ expectedSeq: summary.liveStateSeq ?? 0,
73660
+ eventSeq: summary.eventCount + 1,
73661
+ at,
73662
+ state: "wrapping_up",
73663
+ bound,
73664
+ detail: "writing the pipeline summary"
73665
+ });
73666
+ if (!wrapping.ok || !deps.registry.commitLiveState(host.runId, wrapping))
73667
+ throw new Error(`hosted wrap-up was not committed (${wrapping.ok ? "registry sequence" : wrapping.reason})`);
73668
+ summary = deps.registry.getById(host.runId);
73669
+ if (!summary) throw new Error("hosted run disappeared during wrap-up");
73670
+ const answer = { type: "answer", text: planSummary(units, isGenerated2(instance)), at };
73671
+ const answerSeq = summary.eventCount + 1;
73672
+ const refreshed = await ledgerRun.assignLiveState({
73673
+ expectedSeq: summary.liveStateSeq ?? 0,
73674
+ at,
73675
+ state: "wrapping_up",
73676
+ bound,
73677
+ detail: "writing the pipeline summary",
73678
+ sourceEvents: [{ ...answer, seq: answerSeq }]
73679
+ });
73680
+ if (!refreshed.ok || !deps.registry.commitLiveState(host.runId, refreshed))
73681
+ throw new Error(`hosted summary was not committed (${refreshed.ok ? "registry sequence" : refreshed.reason})`);
73682
+ deps.registry.publish(host.runId, answer);
73683
+ summary = deps.registry.getById(host.runId);
73684
+ if (!summary) throw new Error("hosted run disappeared before ending");
73685
+ const ended = await ledgerRun.assignLiveState({
73686
+ expectedSeq: summary.liveStateSeq ?? 0,
73687
+ eventSeq: summary.eventCount + 1,
73688
+ at,
73689
+ state: "ended",
73690
+ cause: body.outcome === "completed" ? "completed" : "failed"
73691
+ });
73692
+ if (!ended.ok || !deps.registry.commitLiveState(host.runId, ended))
73693
+ throw new Error(`hosted ending was not committed (${ended.ok ? "registry sequence" : ended.reason})`);
73694
+ } else {
73695
+ deps.registry.publish(host.runId, { type: "answer", text: planSummary(units, isGenerated2(instance)), at });
73696
+ }
72742
73697
  deps.registry.finish(host.runId, body.outcome);
72743
73698
  }
72744
73699
  await drawCard(deps, instance, units, { icon: body.outcome === "completed" ? "\u2705" : "\u26A0\uFE0F" }).catch(() => {
@@ -72900,13 +73855,13 @@ function createAdminCoordinatorHandler(deps) {
72900
73855
  }
72901
73856
  write(res, await answerCoordinatorStep(door, read.body, deps));
72902
73857
  } catch (err2) {
72903
- (deps.log ?? console.error)(`[coordinator] ${describe11(err2)}`);
73858
+ (deps.log ?? console.error)(`[coordinator] ${describe12(err2)}`);
72904
73859
  write(res, json3(500, { ok: false, error: "internal error" }));
72905
73860
  }
72906
73861
  })();
72907
73862
  };
72908
73863
  }
72909
- var COORDINATOR_ADMIN_PREFIX, MAX_SPAWN_PROMPT_CHARS, FINISHED_LOOKBACK_PAGES, MAX_ADMIN_BODY_BYTES, UNIT_ID, PRESETS_OF_KIND, invalid, json3, describe11, isGenerated2, EVERY_RUN, REVIEW_POSTED_CHECKS, REVIEW_POSTED_RECHECK_MS, githubSecondStart, CHILD_SUPERSESSION_REASONS, ROUND_OUTCOMES, ENDING_ICON, STEPS;
73864
+ var COORDINATOR_ADMIN_PREFIX, MAX_SPAWN_PROMPT_CHARS, FINISHED_LOOKBACK_PAGES, MAX_ADMIN_BODY_BYTES, UNIT_ID, PRESETS_OF_KIND, invalid, json3, describe12, isGenerated2, EVERY_RUN, REVIEW_POSTED_CHECKS, REVIEW_POSTED_RECHECK_MS, githubSecondStart, CHILD_SUPERSESSION_REASONS, ROUND_OUTCOMES, ENDING_ICON, STEPS;
72910
73865
  var init_adminCoordinator = __esm({
72911
73866
  "../../src/channels/adminCoordinator.ts"() {
72912
73867
  "use strict";
@@ -72953,7 +73908,7 @@ var init_adminCoordinator = __esm({
72953
73908
  };
72954
73909
  invalid = (error) => ({ ok: false, error });
72955
73910
  json3 = (status3, body) => ({ status: status3, body });
72956
- describe11 = (err2) => err2 instanceof Error ? err2.message : String(err2);
73911
+ describe12 = (err2) => err2 instanceof Error ? err2.message : String(err2);
72957
73912
  isGenerated2 = (instance) => instance.plan?.path === void 0;
72958
73913
  EVERY_RUN = { kind: "all" };
72959
73914
  REVIEW_POSTED_CHECKS = 3;
@@ -73824,11 +74779,7 @@ async function runBot() {
73824
74779
  const coordinatorInstances = buildCoordinatorInstanceStore(runHistoryCfg, processSecrets);
73825
74780
  const decisionRecordAllocator = new DecisionRecordAllocator(
73826
74781
  fetchDecisionRecordClaims,
73827
- async (repo, taskKey, claimed2, existing) => {
73828
- const reserved = await coordinatorInstances.reserveDecisionRecord(repo, taskKey, claimed2, existing);
73829
- if (!reserved.ok) throw new DecisionRecordReservationUnavailableError();
73830
- return reserved.number;
73831
- }
74782
+ durableDecisionRecordReservation(coordinatorInstances)
73832
74783
  );
73833
74784
  let planeAdmitPass;
73834
74785
  const planeEffectExecutor = {
@@ -74100,9 +75051,7 @@ async function runBot() {
74100
75051
  slackIntake = wireIntakeGate({
74101
75052
  intakeModeFor: (threadKey, userId, channelId) => config.intakeModeFor(threadKey, userId, channelId),
74102
75053
  deps: {
74103
- model: intake.model,
74104
- ledger: intakeLedger,
74105
- now: systemClock
75054
+ ...intakeDecisionDeps(intake, { ledger: intakeLedger, now: systemClock })
74106
75055
  },
74107
75056
  modelRef: intake.modelRef,
74108
75057
  gen: PROCESS_STARTED_AT,
@@ -74194,6 +75143,13 @@ async function runBot() {
74194
75143
  if (process.env.PORT) {
74195
75144
  const ingress = createIngressHandler(deps, { auth, publicBaseUrl: process.env.PUBLIC_BASE_URL, personByEmail });
74196
75145
  const mcp2 = createMcpHandler(deps, { auth, commands, grantsFor: (id) => config.grantsFor(id), personByEmail });
75146
+ const providerLiveState = createProviderLiveStateCoordinator({
75147
+ runLedger,
75148
+ ledger: ledgerClient,
75149
+ registry: defaultRunRegistry,
75150
+ clock: systemClock,
75151
+ warn: (message4) => console.warn(`[provider-state] ${message4}`)
75152
+ });
74197
75153
  const modelProxy = createModelProxyHandler({
74198
75154
  bearers: runBearers,
74199
75155
  providers: () => config.config.providers,
@@ -74202,17 +75158,11 @@ async function runBot() {
74202
75158
  ...costsCfg?.prices ? { prices: () => costsCfg.prices } : {},
74203
75159
  secrets: processSecrets,
74204
75160
  clock: systemClock,
74205
- // The plane's provider seam (model-proxy item 12a; record 0064): a level
74206
- // and a park land on the write-through's plane routes, fire and forget —
74207
- // the null write-through swallows both where no ledger is configured.
75161
+ // The plane's provider seam (model-proxy item 12a; record 0064): one
75162
+ // coordinator sequences level and park writes; the proxy never waits.
74208
75163
  plane: {
74209
- level: (provider, side, cause) => void runLedger.planeLevel({
74210
- provider,
74211
- name: "provider",
74212
- side,
74213
- ...side === "down" && cause !== void 0 ? { cause } : {}
74214
- }),
74215
- park: (runId3, provider) => void runLedger.planePark(runId3, provider)
75164
+ level: (provider, side, cause) => void providerLiveState.level(provider, side, cause),
75165
+ park: (runId3, provider) => void providerLiveState.park(runId3, provider)
74216
75166
  }
74217
75167
  });
74218
75168
  const harnessRoutes = createHarnessRoutesHandler({ bearers: runBearers, harnesses, takeover });
@@ -74956,6 +75906,7 @@ var init_index = __esm({
74956
75906
  init_adminModelProxy();
74957
75907
  init_modelProxy();
74958
75908
  init_runBearers();
75909
+ init_providerLiveStateCoordinator();
74959
75910
  init_piHarness();
74960
75911
  init_harness2();
74961
75912
  init_relay();