@adhdev/daemon-core 0.9.82-rc.292 → 0.9.82-rc.294

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.
package/dist/index.mjs CHANGED
@@ -270,10 +270,10 @@ function readInjected(value) {
270
270
  }
271
271
  function getDaemonBuildInfo() {
272
272
  if (cached) return cached;
273
- const commit = readInjected(true ? "7b5b620e2df42c7c3beb8a2983e3cc076c25f832" : void 0) ?? "unknown";
274
- const commitShort = readInjected(true ? "7b5b620e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
275
- const version = readInjected(true ? "0.9.82-rc.292" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
276
- const builtAt = readInjected(true ? "2026-06-16T09:16:23.646Z" : void 0);
273
+ const commit = readInjected(true ? "6ee0e52b0b7347870577ebe598054d87127078fe" : void 0) ?? "unknown";
274
+ const commitShort = readInjected(true ? "6ee0e52b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
275
+ const version = readInjected(true ? "0.9.82-rc.294" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
276
+ const builtAt = readInjected(true ? "2026-06-16T12:15:42.290Z" : void 0);
277
277
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
278
278
  return cached;
279
279
  }
@@ -344,6 +344,15 @@ async function getGitRepoStatus(workspace, options = {}) {
344
344
  );
345
345
  }
346
346
  }
347
+ function isNonRuntimeRootFile(file) {
348
+ const base = file.slice(file.lastIndexOf("/") + 1);
349
+ if (/^\.(?:verify|marker|converge|ff-verify|patch-equiv|live-verify)\b/i.test(base)) return true;
350
+ if (/(?:^|\/)docs\//i.test(file)) return true;
351
+ if (/^(?:README|CHANGELOG|LICENSE|NOTICE|AUTHORS|CONTRIBUTING|CODEOWNERS)(?:\.[A-Za-z0-9]+)?$/i.test(base)) {
352
+ return true;
353
+ }
354
+ return false;
355
+ }
347
356
  async function classifyDaemonBuildChange(repoPath, buildCommit, options) {
348
357
  try {
349
358
  const diff = await runGit(repoPath, ["diff", "--name-only", `${buildCommit}..HEAD`], options);
@@ -352,18 +361,18 @@ async function classifyDaemonBuildChange(repoPath, buildCommit, options) {
352
361
  return { isDaemonAffecting: true, affectedPackages: [] };
353
362
  }
354
363
  const pkgs = /* @__PURE__ */ new Set();
355
- let sawNonPackageOrUnknown = false;
364
+ let sawRuntimeAmbiguousNonPackage = false;
356
365
  for (const file of files) {
357
366
  const match = file.match(/(?:^|\/)packages\/([^/]+)\//);
358
367
  if (!match) {
359
- sawNonPackageOrUnknown = true;
368
+ if (!isNonRuntimeRootFile(file)) sawRuntimeAmbiguousNonPackage = true;
360
369
  continue;
361
370
  }
362
371
  pkgs.add(match[1]);
363
372
  }
364
373
  const affectedPackages = [...pkgs].sort();
365
- const allWebOnly = !sawNonPackageOrUnknown && affectedPackages.length > 0 && affectedPackages.every((p) => WEB_ONLY_PACKAGES.has(p) && !DAEMON_RUNTIME_PACKAGES.has(p));
366
- return { isDaemonAffecting: !allWebOnly, affectedPackages };
374
+ const allBenign = !sawRuntimeAmbiguousNonPackage && affectedPackages.every((p) => WEB_ONLY_PACKAGES.has(p) && !DAEMON_RUNTIME_PACKAGES.has(p));
375
+ return { isDaemonAffecting: !allBenign, affectedPackages };
367
376
  } catch {
368
377
  return { isDaemonAffecting: true, affectedPackages: [] };
369
378
  }
@@ -390,7 +399,8 @@ async function detectDaemonBuildBehind(repo, submodules, options) {
390
399
  options
391
400
  );
392
401
  const scopeLabel = scope === "root" ? "workspace" : scope;
393
- const warning = isDaemonAffecting ? `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}. Merged code is NOT live until the daemon is rebuilt/redeployed and restarted \u2014 a local dist rebuild alone does not update a cloud daemon.` : `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}, but only web packages changed (${(affectedPackages || []).join(", ") || "web"}). Daemon restart NOT required \u2014 redeploy the web app to reflect the change.`;
402
+ const benignDetail = affectedPackages.length > 0 ? `only web packages changed (${affectedPackages.join(", ")})` : "only non-runtime files changed (markers/docs)";
403
+ const warning = isDaemonAffecting ? `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}. Merged code is NOT live until the daemon is rebuilt/redeployed and restarted \u2014 a local dist rebuild alone does not update a cloud daemon.` : `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}, but ${benignDetail}. Daemon restart NOT required \u2014 redeploy the web app to reflect the change.`;
394
404
  return {
395
405
  buildCommit: build.commit,
396
406
  buildCommitShort: build.commitShort,
@@ -1995,8 +2005,9 @@ function buildRulesSection(coordinatorCliType) {
1995
2005
  - **Reuse idle sessions.** For follow-up, retry, commit/push, or cleanup on the same issue, send only the delta to the existing idle session. Start fresh only for independent work, provider mismatch, transcript contamination, or required worktree isolation.
1996
2006
  - **Respect explicit provider requests.** Map: Hermes \u2192 \`hermes-cli\`, Claude/Claude Code \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`, Antigravity \u2192 \`antigravity-cli\`. Never substitute the coordinator's own runtime.
1997
2007
  - **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
1998
- - **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing.
2008
+ - **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load \u2014 it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
1999
2009
  - **Check history first.** Call \`mesh_task_history\` at session start to avoid duplicate work and inform recovery. On failure, read task history before retrying.
2010
+ - **Sequence shared-base-moving merges.** Parallel dispatch is encouraged, but merging one worktree can advance another in-flight worktree's base \u2014 especially the oss submodule pointer \u2014 turning a clean fast-forward into a diverged rebase (patch-equivalence correctly blocks this). Before merging an in-flight worktree while siblings are also in flight, land in an intentional order, re-clone long-running worktrees from the advanced base, or expect to manually rebase + ff-only the laggards; merging an independent fix mid-flight can strand siblings into a rebase.
2000
2011
  - **Converge branches.** After worktree tasks: refine/fast-forward, or classify as \`pushed_feature_branch_needs_merge\` / \`blocked_review\` / \`cleanup_candidate\` / \`not_mergeable\`. Clean up with \`mesh_remove_node\`.
2001
2012
  - **Refinery is config-driven.** \`mesh_refine_node\` must run validation from \`.adhdev/refine.{json,yaml,yml}\` or \`repo-mesh.refine.*\`. Heuristics are scaffolding only.
2002
2013
  - **Submodule reachability = publish-needed.** \`submodule_reachability_failed\` \u2192 classify as \`blocked_review\`, request user approval to push to submodule main, then rerun \`mesh_refine_node\`.
@@ -2046,7 +2057,7 @@ Before doing any coordinator work, confirm that the actual callable tool list in
2046
2057
  c. **Targeted Tasks**: Use \`mesh_send_task\` only when you need to bypass the queue and force a specific node to execute a task immediately.
2047
2058
  d. For the first dispatch of a new task, provide a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
2048
2059
  e. For a continuation of the same issue in an existing session, send a concise **delta instruction**: current verified state, the exact failed/blocked step, the newly approved action, and final reporting requirements. Do not resend the full original task or open a new chat solely to continue the same work; that wastes coordinator and worker context.
2049
- 4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Do **not** repeatedly call \`mesh_status\` or \`mesh_view_queue\` just to wait for assigned/generating work. After dispatching a direct or queued task, send one progress update with the task/session handle, then stop. Wait for \`pendingCoordinatorEvents\` or another completion/approval/status signal, an explicit user status request, or a real timeout/stall signal before reading status/chat/queue again. Use at most one compact \`mesh_read_chat\` check after a terminal signal. Handle approvals via \`mesh_approve\`.
2060
+ 4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Do **not** repeatedly call \`mesh_status\` or \`mesh_view_queue\` just to wait for assigned/generating work. After dispatching a direct or queued task, send one progress update with the task/session handle, then stop. Wait for \`pendingCoordinatorEvents\` or another completion/approval/status signal, an explicit user status request, or a real timeout/stall signal before reading status/chat/queue again. Use at most one compact \`mesh_read_chat\` check after a terminal signal. Handle approvals via \`mesh_approve\`. **Proactively parallelize new work.** When the user reports a new bug or asks for new work, start it immediately if it is independent of in-flight tasks and there is headroom under \`maxParallelTasks\` \u2014 do not wait for a current task to finish or for the user to prompt you to parallelize. Read-only diagnosis (\`live_debug_readonly\`) has no isolation or merge cost, so dispatch it in parallel right away. The no-polling / concurrency-limit rules constrain *re-checking or duplicating already-dispatched work*; they are **not** a reason to defer starting a new, independent task.
2050
2061
  5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
2051
2062
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
2052
2063
  7. **Converge branches** \u2014 Before marking any task complete, classify every touched node/branch into exactly one final state: \`merged_to_main\`, \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\`. Use \`mesh_status\` branchConvergenceSummary. For obvious clean branch catch-up (ahead 0, behind > 0, upstream fresh, no dirty/stash/submodule issues), use \`mesh_fast_forward_node\` dry-run first and execute only when explicitly safe/approved; this avoids consuming an agent session. Use \`mesh_refine_node\` for clean worktree branches when safe. Before/refine merging root commits that contain submodule gitlink changes, require each submodule commit to be reachable from the configured submodule remote main branch, not merely present on a feature ref or local checkout. If \`mesh_refine_node\` returns \`submodule_reachability_failed\` or publish-required evidence, keep the public convergence bucket as \`blocked_review\`; unless \`allowAutoPublishSubmoduleMainCommits\` is explicitly enabled and Refinery reports successful non-force publish plus post-publish verification, ask the user for explicit approval to push/publish the unreachable submodule commit(s) to submodule main, then rerun \`mesh_refine_node\`. Do not merge the root branch until the submodule commit(s) are reachable from submodule origin/main. A task that remains on a non-main branch is not fully complete unless the final report names the follow-up state and next step.
@@ -4389,6 +4400,34 @@ var init_mesh_runtime_store = __esm({
4389
4400
  ).get(meshId);
4390
4401
  return row?.cnt ?? 0;
4391
4402
  }
4403
+ /**
4404
+ * Mark specific pending-event rows drained by id (ack). Used by the
4405
+ * unresolved-delegate durable-forward outbox: an event is peeked (not drained)
4406
+ * while its push to the coordinator is unconfirmed, then marked drained ONLY
4407
+ * after the push is acked. A failed push leaves the row undrained so the next
4408
+ * reconcile tick retries it. Returns the number of rows newly marked drained.
4409
+ */
4410
+ markPendingEventsDrainedById(ids) {
4411
+ const idList = ids.filter((id) => typeof id === "string" && id.length > 0);
4412
+ if (idList.length === 0) return 0;
4413
+ const now = Date.now();
4414
+ return this.db.prepare(
4415
+ `UPDATE mesh_pending_events SET drained = 1, drained_at = ? WHERE drained = 0 AND id IN (${idList.map(() => "?").join(",")})`
4416
+ ).run(now, ...idList).changes;
4417
+ }
4418
+ /**
4419
+ * Hard-delete pending-event rows by id (including the dedup fingerprint history).
4420
+ * Used to expire an unresolved-delegate outbox entry that has exhausted its retry
4421
+ * budget — fully removing it frees the fingerprint so a genuinely new completion
4422
+ * for the same task could be re-queued later. Returns the number of rows deleted.
4423
+ */
4424
+ deletePendingEventsById(ids) {
4425
+ const idList = ids.filter((id) => typeof id === "string" && id.length > 0);
4426
+ if (idList.length === 0) return 0;
4427
+ return this.db.prepare(
4428
+ `DELETE FROM mesh_pending_events WHERE id IN (${idList.map(() => "?").join(",")})`
4429
+ ).run(...idList).changes;
4430
+ }
4392
4431
  };
4393
4432
  }
4394
4433
  });
@@ -4396,6 +4435,7 @@ var init_mesh_runtime_store = __esm({
4396
4435
  // src/mesh/mesh-missions.ts
4397
4436
  var mesh_missions_exports = {};
4398
4437
  __export(mesh_missions_exports, {
4438
+ GOAL_PREVIEW_MAX: () => GOAL_PREVIEW_MAX,
4399
4439
  MESH_MISSION_STATUSES: () => MESH_MISSION_STATUSES,
4400
4440
  buildMissionPromptSection: () => buildMissionPromptSection,
4401
4441
  getActiveMeshMissionSummaries: () => getActiveMeshMissionSummaries,
@@ -4468,12 +4508,23 @@ function summarizeMeshMission(meshId, mission) {
4468
4508
  function getActiveMeshMissionSummaries(meshId) {
4469
4509
  return getMeshMissions(meshId, ["active"]).map((mission) => summarizeMeshMission(meshId, mission));
4470
4510
  }
4511
+ function slimMissionSummary(summary) {
4512
+ const goal = typeof summary.goal === "string" ? summary.goal : "";
4513
+ const goalTruncated = goal.length > GOAL_PREVIEW_MAX;
4514
+ const { goal: _omitGoal, ...rest } = summary;
4515
+ return {
4516
+ ...rest,
4517
+ goalPreview: goalTruncated ? goal.slice(0, GOAL_PREVIEW_MAX) : goal,
4518
+ goalTruncated
4519
+ };
4520
+ }
4471
4521
  function getMeshStatusMissionSummaries(meshId, options) {
4472
4522
  const historyLimit = Math.max(0, options?.historyLimit ?? 10);
4473
4523
  const all = getMeshMissions(meshId);
4474
4524
  const live = all.filter((m) => m.status === "active" || m.status === "paused");
4475
4525
  const history = all.filter((m) => m.status === "completed" || m.status === "abandoned").sort((a, b) => (b.updatedAt || "").localeCompare(a.updatedAt || "")).slice(0, historyLimit);
4476
- return [...live, ...history].map((mission) => summarizeMeshMission(meshId, mission));
4526
+ const full = [...live, ...history].map((mission) => summarizeMeshMission(meshId, mission));
4527
+ return options?.verbose ? full : full.map(slimMissionSummary);
4477
4528
  }
4478
4529
  function buildMissionPromptSection(meshId) {
4479
4530
  const summaries = getActiveMeshMissionSummaries(meshId);
@@ -4493,13 +4544,14 @@ function buildMissionPromptSection(meshId) {
4493
4544
  );
4494
4545
  return lines.join("\n");
4495
4546
  }
4496
- var MESH_MISSION_STATUSES;
4547
+ var MESH_MISSION_STATUSES, GOAL_PREVIEW_MAX;
4497
4548
  var init_mesh_missions = __esm({
4498
4549
  "src/mesh/mesh-missions.ts"() {
4499
4550
  "use strict";
4500
4551
  init_mesh_runtime_store();
4501
4552
  init_mesh_work_queue();
4502
4553
  MESH_MISSION_STATUSES = ["active", "paused", "completed", "abandoned"];
4554
+ GOAL_PREVIEW_MAX = 120;
4503
4555
  }
4504
4556
  });
4505
4557
 
@@ -7597,6 +7649,111 @@ var init_mesh_routing = __esm({
7597
7649
  }
7598
7650
  });
7599
7651
 
7652
+ // src/mesh/mesh-unresolved-forward-outbox.ts
7653
+ import { randomUUID as randomUUID9 } from "crypto";
7654
+ function getStore() {
7655
+ try {
7656
+ return MeshRuntimeStore.getInstance();
7657
+ } catch {
7658
+ return void 0;
7659
+ }
7660
+ }
7661
+ function enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, forwardPayload) {
7662
+ const target = readNonEmptyString2(coordinatorDaemonId);
7663
+ const event = readNonEmptyString2(eventName);
7664
+ if (!target || !event) return false;
7665
+ const store = getStore();
7666
+ if (!store) return false;
7667
+ const queuedAt = Date.now();
7668
+ const fingerprintSource = {
7669
+ event,
7670
+ meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
7671
+ nodeLabel: readNonEmptyString2(forwardPayload.nodeId) || readNonEmptyString2(forwardPayload.workspace) || "unresolved-delegate",
7672
+ nodeId: readNonEmptyString2(forwardPayload.nodeId) || void 0,
7673
+ workspace: readNonEmptyString2(forwardPayload.workspace) || void 0,
7674
+ metadataEvent: forwardPayload,
7675
+ queuedAt,
7676
+ targetCoordinatorDaemonId: target
7677
+ };
7678
+ const fingerprint = `${target}::${buildPendingEventFingerprint(fingerprintSource)}`;
7679
+ try {
7680
+ const inserted = store.insertPendingEvent({
7681
+ id: randomUUID9(),
7682
+ meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
7683
+ coordinatorDaemonId: target,
7684
+ event,
7685
+ // Store the flat forward payload + the queue timestamp so the retry tick can
7686
+ // rebuild the push args and apply age-based expiry without a schema change.
7687
+ payload: { forwardPayload, coordinatorDaemonId: target, queuedAt },
7688
+ fingerprint,
7689
+ queuedAt
7690
+ });
7691
+ if (inserted) {
7692
+ LOG.info("MeshEvents", `Durably queued unresolved-delegate ${event} for coordinator ${target} (outbox)`);
7693
+ }
7694
+ return true;
7695
+ } catch (e) {
7696
+ LOG.warn("MeshEvents", `Failed to persist unresolved-delegate forward to outbox: ${e?.message || e}`);
7697
+ return false;
7698
+ }
7699
+ }
7700
+ function peekUnresolvedDelegateForwards() {
7701
+ const store = getStore();
7702
+ if (!store) return [];
7703
+ let rows;
7704
+ try {
7705
+ rows = store.peekPendingEvents(UNRESOLVED_FORWARD_OUTBOX_MESH_ID);
7706
+ } catch {
7707
+ return [];
7708
+ }
7709
+ const out = [];
7710
+ for (const row of rows) {
7711
+ const stored = row.payload && typeof row.payload === "object" ? row.payload : {};
7712
+ const coordinatorDaemonId = readNonEmptyString2(stored.coordinatorDaemonId);
7713
+ const forwardPayload = stored.forwardPayload && typeof stored.forwardPayload === "object" ? stored.forwardPayload : void 0;
7714
+ if (!coordinatorDaemonId || !forwardPayload) continue;
7715
+ const queuedAt = typeof stored.queuedAt === "number" ? stored.queuedAt : 0;
7716
+ out.push({ id: row.id, coordinatorDaemonId, payload: forwardPayload, queuedAt });
7717
+ }
7718
+ return out;
7719
+ }
7720
+ function ackUnresolvedDelegateForward(id) {
7721
+ const store = getStore();
7722
+ if (!store) return;
7723
+ try {
7724
+ store.markPendingEventsDrainedById([id]);
7725
+ } catch {
7726
+ }
7727
+ }
7728
+ function expireStaleUnresolvedDelegateForwards(nowMs = Date.now()) {
7729
+ const entries = peekUnresolvedDelegateForwards();
7730
+ const staleIds = entries.filter((e) => e.queuedAt > 0 && nowMs - e.queuedAt >= UNRESOLVED_FORWARD_MAX_AGE_MS).map((e) => e.id);
7731
+ if (staleIds.length === 0) return 0;
7732
+ const store = getStore();
7733
+ if (!store) return 0;
7734
+ try {
7735
+ const removed = store.deletePendingEventsById(staleIds);
7736
+ if (removed > 0) {
7737
+ LOG.warn("MeshEvents", `Expired ${removed} unresolved-delegate forward(s) after ${Math.round(UNRESOLVED_FORWARD_MAX_AGE_MS / 6e4)}m of failed retries \u2014 coordinator unreachable, completion dropped`);
7738
+ }
7739
+ return removed;
7740
+ } catch {
7741
+ return 0;
7742
+ }
7743
+ }
7744
+ var UNRESOLVED_FORWARD_OUTBOX_MESH_ID, UNRESOLVED_FORWARD_MAX_AGE_MS;
7745
+ var init_mesh_unresolved_forward_outbox = __esm({
7746
+ "src/mesh/mesh-unresolved-forward-outbox.ts"() {
7747
+ "use strict";
7748
+ init_logger();
7749
+ init_mesh_runtime_store();
7750
+ init_mesh_events_pending();
7751
+ init_mesh_events_utils();
7752
+ UNRESOLVED_FORWARD_OUTBOX_MESH_ID = "__unresolved_forward_outbox__";
7753
+ UNRESOLVED_FORWARD_MAX_AGE_MS = 30 * 60 * 1e3;
7754
+ }
7755
+ });
7756
+
7600
7757
  // src/mesh/mesh-events-coordinator.ts
7601
7758
  import { existsSync as existsSync14 } from "fs";
7602
7759
  function resolveCoordinatorDrainDaemonIds(components) {
@@ -8732,12 +8889,25 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
8732
8889
  nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId) || void 0,
8733
8890
  workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
8734
8891
  };
8735
- Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).catch((e) => {
8736
- LOG.warn("MeshEvents", `Fallback forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e}`);
8892
+ const persisted = enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, payload);
8893
+ Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
8894
+ if (result && result.success === false) {
8895
+ LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
8896
+ return;
8897
+ }
8898
+ if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
8899
+ }).catch((e) => {
8900
+ LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued for retry`);
8737
8901
  });
8738
- LOG.info("MeshEvents", `Fallback-forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
8902
+ LOG.info("MeshEvents", `Durably forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
8739
8903
  return true;
8740
8904
  }
8905
+ function ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload) {
8906
+ const match = peekUnresolvedDelegateForwards().find(
8907
+ (entry) => entry.coordinatorDaemonId === coordinatorDaemonId && readNonEmptyString2(entry.payload.event) === eventName && readNonEmptyString2(entry.payload.targetSessionId || entry.payload.sessionId || entry.payload.instanceId) === readNonEmptyString2(payload.targetSessionId || payload.sessionId || payload.instanceId) && readNonEmptyString2(entry.payload.workspace) === readNonEmptyString2(payload.workspace)
8908
+ );
8909
+ if (match) ackUnresolvedDelegateForward(match.id);
8910
+ }
8741
8911
  function setupMeshEventForwarding(components) {
8742
8912
  components.instanceManager.onEvent((event) => {
8743
8913
  if (event.event === "agent:ready" || event.event === "agent:generating_completed") {
@@ -8818,6 +8988,7 @@ var init_mesh_events_coordinator = __esm({
8818
8988
  init_mesh_runtime_store();
8819
8989
  init_mesh_events_pending();
8820
8990
  init_mesh_routing();
8991
+ init_mesh_unresolved_forward_outbox();
8821
8992
  init_repo_mesh_types();
8822
8993
  init_dist();
8823
8994
  init_mesh_events_stale();
@@ -8933,6 +9104,13 @@ async function runMeshReconcileTick(components) {
8933
9104
  return void 0;
8934
9105
  }
8935
9106
  })();
9107
+ if (dispatchMeshCommand) {
9108
+ try {
9109
+ await retryUnresolvedDelegateForwards(components);
9110
+ } catch (e) {
9111
+ LOG.warn("MeshReconcile", `Unresolved-delegate forward retry failed: ${e?.message || e}`);
9112
+ }
9113
+ }
8936
9114
  if (dispatchMeshCommand) {
8937
9115
  for (const mesh of listMeshes()) {
8938
9116
  const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
@@ -8986,6 +9164,28 @@ async function runMeshReconcileTick(components) {
8986
9164
  }
8987
9165
  }
8988
9166
  }
9167
+ async function retryUnresolvedDelegateForwards(components) {
9168
+ const dispatchMeshCommand = components.dispatchMeshCommand;
9169
+ if (!dispatchMeshCommand) return;
9170
+ expireStaleUnresolvedDelegateForwards();
9171
+ const entries = peekUnresolvedDelegateForwards();
9172
+ if (entries.length === 0) return;
9173
+ for (const entry of entries) {
9174
+ let result;
9175
+ try {
9176
+ result = await dispatchMeshCommand(entry.coordinatorDaemonId, "mesh_forward_event", entry.payload);
9177
+ } catch (e) {
9178
+ LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued`);
9179
+ continue;
9180
+ }
9181
+ if (result && result.success === false) {
9182
+ LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued`);
9183
+ continue;
9184
+ }
9185
+ ackUnresolvedDelegateForward(entry.id);
9186
+ LOG.info("MeshReconcile", `Retried+delivered unresolved-delegate ${readNonEmptyString2(entry.payload.event)} to coordinator ${entry.coordinatorDaemonId}`);
9187
+ }
9188
+ }
8989
9189
  async function pullRemoteNodeQueues(components, mesh, localDaemonId, candidateDaemonIds) {
8990
9190
  const dispatchMeshCommand = components.dispatchMeshCommand;
8991
9191
  if (!dispatchMeshCommand) return;
@@ -9062,6 +9262,7 @@ var init_mesh_reconcile_loop = __esm({
9062
9262
  init_mesh_events_pending();
9063
9263
  init_mesh_runtime_store();
9064
9264
  init_mesh_events_coordinator();
9265
+ init_mesh_unresolved_forward_outbox();
9065
9266
  init_mesh_events_utils();
9066
9267
  DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
9067
9268
  }
@@ -21371,22 +21572,160 @@ function isBoundedTailRequest(limit, offset, excludeRecentCount) {
21371
21572
  if (!Number.isFinite(numericOffset) || !Number.isFinite(numericExclude)) return false;
21372
21573
  return true;
21373
21574
  }
21575
+ var REVERSE_TAIL_SMALL_FILE_BYTES = 64 * 1024;
21576
+ var REVERSE_TAIL_CHUNK_BYTES = 64 * 1024;
21577
+ var TAIL_LINES_RETAINED = BOUNDED_TAIL_MAX_LIMIT + 2 * BOUNDED_TAIL_SLACK;
21578
+ var INCREMENTAL_TAIL_CACHE_MAX_ENTRIES = 64;
21579
+ var incrementalTailCache = /* @__PURE__ */ new Map();
21580
+ function evictIncrementalTailCache() {
21581
+ while (incrementalTailCache.size > INCREMENTAL_TAIL_CACHE_MAX_ENTRIES) {
21582
+ const oldest = incrementalTailCache.keys().next().value;
21583
+ if (oldest === void 0) break;
21584
+ incrementalTailCache.delete(oldest);
21585
+ }
21586
+ }
21587
+ function splitBufferLines(buf) {
21588
+ const lines = [];
21589
+ let lineEnd = buf.length;
21590
+ let firstNewline = -1;
21591
+ for (let i = buf.length - 1; i >= 0; i--) {
21592
+ if (buf[i] !== 10) continue;
21593
+ if (i + 1 < lineEnd) {
21594
+ lines.push(buf.toString("utf-8", i + 1, lineEnd));
21595
+ }
21596
+ lineEnd = i;
21597
+ firstNewline = i;
21598
+ }
21599
+ lines.reverse();
21600
+ const head = firstNewline >= 0 ? buf.subarray(0, firstNewline) : buf;
21601
+ return { head, lines };
21602
+ }
21603
+ function readReverseTailLines(filePath, needed) {
21604
+ const fd = fs5.openSync(filePath, "r");
21605
+ try {
21606
+ const stat2 = fs5.fstatSync(fd);
21607
+ const size = stat2.size;
21608
+ let position = size;
21609
+ let carry = Buffer.alloc(0);
21610
+ const collected = [];
21611
+ while (position > 0 && collected.length < needed) {
21612
+ const chunkSize = Math.min(REVERSE_TAIL_CHUNK_BYTES, position);
21613
+ position -= chunkSize;
21614
+ const chunk = Buffer.alloc(chunkSize);
21615
+ fs5.readSync(fd, chunk, 0, chunkSize, position);
21616
+ const combined = carry.length ? Buffer.concat([chunk, carry]) : chunk;
21617
+ const { head, lines } = splitBufferLines(combined);
21618
+ carry = head;
21619
+ for (let i = lines.length - 1; i >= 0; i--) {
21620
+ collected.push(lines[i]);
21621
+ }
21622
+ }
21623
+ const reachedStart = position <= 0;
21624
+ if (reachedStart && carry.length) {
21625
+ collected.push(carry.toString("utf-8"));
21626
+ }
21627
+ collected.reverse();
21628
+ return { lines: collected, coversWholeFile: reachedStart, size, mtimeMs: stat2.mtimeMs };
21629
+ } finally {
21630
+ fs5.closeSync(fd);
21631
+ }
21632
+ }
21633
+ function readFileTailLines(filePath, needed) {
21634
+ let stat2;
21635
+ try {
21636
+ stat2 = fs5.statSync(filePath);
21637
+ } catch {
21638
+ return { lines: [], coversWholeFile: true };
21639
+ }
21640
+ const size = stat2.size;
21641
+ const mtimeMs = stat2.mtimeMs;
21642
+ if (size === 0) {
21643
+ incrementalTailCache.delete(filePath);
21644
+ return { lines: [], coversWholeFile: true };
21645
+ }
21646
+ const cached2 = incrementalTailCache.get(filePath);
21647
+ if (cached2) {
21648
+ if (cached2.size === size && cached2.mtimeMs === mtimeMs) {
21649
+ incrementalTailCache.delete(filePath);
21650
+ incrementalTailCache.set(filePath, cached2);
21651
+ if (cached2.coversWholeFile || cached2.lines.length >= needed) {
21652
+ return { lines: cached2.lines, coversWholeFile: cached2.coversWholeFile };
21653
+ }
21654
+ } else if (size > cached2.size) {
21655
+ const incremental = tryIncrementalTailGrowth(filePath, cached2, size, mtimeMs, needed);
21656
+ if (incremental) return { lines: incremental.lines, coversWholeFile: incremental.coversWholeFile };
21657
+ }
21658
+ incrementalTailCache.delete(filePath);
21659
+ }
21660
+ if (size <= REVERSE_TAIL_SMALL_FILE_BYTES) {
21661
+ let content;
21662
+ try {
21663
+ content = fs5.readFileSync(filePath, "utf-8");
21664
+ } catch {
21665
+ return { lines: [], coversWholeFile: true };
21666
+ }
21667
+ const lines = content.split("\n");
21668
+ if (lines.length && lines[lines.length - 1] === "") lines.pop();
21669
+ storeIncrementalTailCache(filePath, size, mtimeMs, lines, true);
21670
+ return { lines, coversWholeFile: true };
21671
+ }
21672
+ let result;
21673
+ try {
21674
+ result = readReverseTailLines(filePath, needed);
21675
+ } catch {
21676
+ return { lines: [], coversWholeFile: true };
21677
+ }
21678
+ storeIncrementalTailCache(filePath, result.size, result.mtimeMs, result.lines, result.coversWholeFile);
21679
+ return { lines: result.lines, coversWholeFile: result.coversWholeFile };
21680
+ }
21681
+ function tryIncrementalTailGrowth(filePath, cached2, size, mtimeMs, needed) {
21682
+ const fd = fs5.openSync(filePath, "r");
21683
+ try {
21684
+ if (cached2.size > 0) {
21685
+ const boundary = Buffer.alloc(1);
21686
+ fs5.readSync(fd, boundary, 0, 1, cached2.size - 1);
21687
+ if (boundary[0] !== 10) return null;
21688
+ }
21689
+ const appendedLength = size - cached2.size;
21690
+ const appended = Buffer.alloc(appendedLength);
21691
+ fs5.readSync(fd, appended, 0, appendedLength, cached2.size);
21692
+ const newLines = appended.toString("utf-8").split("\n");
21693
+ if (newLines.length && newLines[newLines.length - 1] === "") newLines.pop();
21694
+ const merged = cached2.lines.concat(newLines);
21695
+ const trimmed = merged.length > TAIL_LINES_RETAINED ? merged.slice(merged.length - TAIL_LINES_RETAINED) : merged;
21696
+ const coversWholeFile = cached2.coversWholeFile && trimmed.length === merged.length;
21697
+ storeIncrementalTailCache(filePath, size, mtimeMs, trimmed, coversWholeFile);
21698
+ if (coversWholeFile || trimmed.length >= needed) {
21699
+ return { lines: trimmed, coversWholeFile };
21700
+ }
21701
+ return { lines: trimmed, coversWholeFile };
21702
+ } catch {
21703
+ return null;
21704
+ } finally {
21705
+ fs5.closeSync(fd);
21706
+ }
21707
+ }
21708
+ function storeIncrementalTailCache(filePath, size, mtimeMs, lines, coversWholeFile) {
21709
+ const retained = lines.length > TAIL_LINES_RETAINED ? lines.slice(lines.length - TAIL_LINES_RETAINED) : lines;
21710
+ const covers = coversWholeFile && retained.length === lines.length;
21711
+ incrementalTailCache.delete(filePath);
21712
+ incrementalTailCache.set(filePath, { size, mtimeMs, lines: retained, coversWholeFile: covers });
21713
+ evictIncrementalTailCache();
21714
+ }
21374
21715
  function readBoundedTailRecords(agentType, dir, files, needed) {
21375
21716
  const collected = [];
21376
21717
  const seen = /* @__PURE__ */ new Set();
21377
21718
  let readAllFiles = true;
21378
21719
  for (let f = 0; f < files.length; f++) {
21379
21720
  const filePath = path12.join(dir, files[f]);
21380
- let content;
21381
- try {
21382
- content = fs5.readFileSync(filePath, "utf-8");
21383
- } catch {
21384
- continue;
21385
- }
21386
- const lines = content.trim().split("\n").filter(Boolean);
21721
+ const remaining = Math.max(0, needed - collected.length);
21722
+ const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
21723
+ const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
21387
21724
  for (let i = lines.length - 1; i >= 0; i--) {
21725
+ const line = lines[i];
21726
+ if (!line) continue;
21388
21727
  try {
21389
- const parsed = JSON.parse(lines[i]);
21728
+ const parsed = JSON.parse(line);
21390
21729
  const sanitizedMessage = sanitizeHistoryMessage(agentType, parsed);
21391
21730
  if (!sanitizedMessage) continue;
21392
21731
  const hash = buildHistoryMessageHash(agentType, sanitizedMessage);
@@ -21396,6 +21735,10 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
21396
21735
  } catch {
21397
21736
  }
21398
21737
  }
21738
+ if (!coversWholeFile) {
21739
+ readAllFiles = false;
21740
+ break;
21741
+ }
21399
21742
  if (collected.length >= needed && f < files.length - 1) {
21400
21743
  readAllFiles = false;
21401
21744
  break;
@@ -21999,7 +22342,7 @@ var ExtensionProviderInstance = class {
21999
22342
  this.runtimeMessages = [];
22000
22343
  }
22001
22344
  updateSettings(newSettings) {
22002
- this.settings = { ...newSettings };
22345
+ this.settings = { ...this.settings, ...newSettings };
22003
22346
  this.monitor.updateConfig({
22004
22347
  approvalAlert: this.settings.approvalAlert !== false,
22005
22348
  longGeneratingAlert: this.settings.longGeneratingAlert !== false,
@@ -22666,7 +23009,7 @@ var IdeProviderInstance = class {
22666
23009
  this.extensions.clear();
22667
23010
  }
22668
23011
  updateSettings(newSettings) {
22669
- this.settings = { ...newSettings };
23012
+ this.settings = { ...this.settings, ...newSettings };
22670
23013
  this.monitor.updateConfig({
22671
23014
  approvalAlert: this.settings.approvalAlert !== false,
22672
23015
  longGeneratingAlert: this.settings.longGeneratingAlert !== false,
@@ -24145,7 +24488,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
24145
24488
  import * as fs6 from "fs";
24146
24489
  import * as os8 from "os";
24147
24490
  import * as path13 from "path";
24148
- import { randomUUID as randomUUID10 } from "crypto";
24491
+ import { randomUUID as randomUUID11 } from "crypto";
24149
24492
  init_logger();
24150
24493
 
24151
24494
  // src/logging/debug-trace.ts
@@ -25686,7 +26029,7 @@ function safeBundleIdSegment(value, fallback) {
25686
26029
  function createChatDebugBundleId(targetSessionId) {
25687
26030
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "").replace("T", "T").replace("Z", "Z");
25688
26031
  const sessionSegment = safeBundleIdSegment(targetSessionId, "unknown-session");
25689
- return `chat-debug-${timestamp}-${sessionSegment}-${randomUUID10().slice(0, 8)}`;
26032
+ return `chat-debug-${timestamp}-${sessionSegment}-${randomUUID11().slice(0, 8)}`;
25690
26033
  }
25691
26034
  function buildChatDebugBundleSummary(bundle) {
25692
26035
  const target = bundle.target && typeof bundle.target === "object" ? bundle.target : {};
@@ -31352,12 +31695,14 @@ var SpecCliAdapter = class _SpecCliAdapter {
31352
31695
  }
31353
31696
  this.maybeClearResolvedClaudeTuiPrompt();
31354
31697
  this.maybeCaptureClaudeTuiPrompt();
31698
+ this.maybeUpgradeClaudeTuiMultiSelect();
31355
31699
  this.statusCallback?.();
31356
31700
  return;
31357
31701
  case "pty_data":
31358
31702
  this.detectInteractivePromptFromPtyChunk(ev.chunk);
31359
31703
  this.maybeClearResolvedClaudeTuiPrompt();
31360
31704
  this.maybeCaptureClaudeTuiPrompt();
31705
+ this.maybeUpgradeClaudeTuiMultiSelect();
31361
31706
  try {
31362
31707
  this.ptyDataCallback?.(ev.chunk);
31363
31708
  } catch {
@@ -31506,6 +31851,35 @@ var SpecCliAdapter = class _SpecCliAdapter {
31506
31851
  this.claudeTuiPromptCaptureInFlight = false;
31507
31852
  });
31508
31853
  }
31854
+ /**
31855
+ * The TUI prompt is captured on the FIRST frame that renders the
31856
+ * "Enter to select" footer. At that instant the option rows' checkbox
31857
+ * column may not have drawn yet, so `detectClaudeTuiMultiSelect` returns
31858
+ * false and the prompt is frozen as single-select — the dashboard then
31859
+ * renders radio buttons even though the picker is multi-select.
31860
+ *
31861
+ * While the same TUI prompt is still on screen, re-check the live snapshot:
31862
+ * if checkbox glyphs have since appeared, promote any single-select
31863
+ * question to multi-select and re-emit status. Promotion is one-way
31864
+ * (false→true only) — once a question is known multi-select we never demote
31865
+ * it, since the glyph column can scroll out of view on later frames.
31866
+ */
31867
+ maybeUpgradeClaudeTuiMultiSelect() {
31868
+ if (this.cliType !== "claude-cli" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
31869
+ const questions = this.activeInteractivePrompt.questions;
31870
+ if (questions.length !== 1) return;
31871
+ if (questions[0].multiSelect) return;
31872
+ let screenText = "";
31873
+ try {
31874
+ screenText = this.driver.snapshot();
31875
+ } catch {
31876
+ return;
31877
+ }
31878
+ if (!screenText.includes("Enter to select")) return;
31879
+ if (!detectClaudeTuiMultiSelect(screenText)) return;
31880
+ questions[0].multiSelect = true;
31881
+ this.statusCallback?.();
31882
+ }
31509
31883
  readClaudeTuiHeaders(screenText) {
31510
31884
  const navLine = screenText.split(/\r?\n/).find((line) => line.includes("\u2714 Submit") && /[☐☒]/.test(line));
31511
31885
  if (!navLine) return [];
@@ -31655,6 +32029,7 @@ function normalizeProviderSessionId(provider, providerSessionId) {
31655
32029
  }
31656
32030
 
31657
32031
  // src/providers/cli-provider-instance.ts
32032
+ var STATUS_HYDRATION_TAIL_LIMIT = 200;
31658
32033
  function isIdleStatus(value) {
31659
32034
  const status = typeof value === "string" ? value.trim().toLowerCase() : "";
31660
32035
  return !status || status === "idle" || status === "ready";
@@ -32214,22 +32589,7 @@ var CliProviderInstance = class _CliProviderInstance {
32214
32589
  };
32215
32590
  }
32216
32591
  updateSettings(newSettings) {
32217
- const runtimeMeshSettings = {};
32218
- for (const key of [
32219
- "meshNodeFor",
32220
- "meshNodeId",
32221
- "meshActiveTaskId",
32222
- "meshCoordinatorFor",
32223
- "meshCoordinatorDaemonId",
32224
- "meshCoordinatorNodeId",
32225
- "spawnedSessionVisibility",
32226
- "launchedByCoordinator"
32227
- ]) {
32228
- if (this.settings[key] !== void 0 && newSettings[key] === void 0) {
32229
- runtimeMeshSettings[key] = this.settings[key];
32230
- }
32231
- }
32232
- this.settings = { ...newSettings, ...runtimeMeshSettings };
32592
+ this.settings = { ...this.settings, ...newSettings };
32233
32593
  this.adapter.updateRuntimeSettings?.(this.settings);
32234
32594
  this.monitor.updateConfig({
32235
32595
  approvalAlert: this.settings.approvalAlert !== false,
@@ -33332,12 +33692,14 @@ ${effect.notification.body || ""}`.trim();
33332
33692
  const newestMessageAt = parsedMessages.reduce((newest, message) => Math.max(newest, getMessageTime(message)), 0);
33333
33693
  return newestMessageAt === 0;
33334
33694
  }
33335
- syncCanonicalSavedHistoryIfNeeded() {
33695
+ syncCanonicalSavedHistoryIfNeeded(options = {}) {
33336
33696
  if (!this.providerSessionId) return false;
33337
33697
  const canonicalHistory = this.provider.nativeHistory;
33338
33698
  if (!canonicalHistory) return false;
33699
+ const limit = options.full ? Number.MAX_SAFE_INTEGER : STATUS_HYDRATION_TAIL_LIMIT;
33700
+ const windowTag = options.full ? "full" : `tail:${STATUS_HYDRATION_TAIL_LIMIT}`;
33339
33701
  if (isNativeSourceCanonicalHistory(canonicalHistory)) {
33340
- const cacheKey = [this.type, this.providerSessionId, this.workingDir].join("\0");
33702
+ const cacheKey = [this.type, this.providerSessionId, this.workingDir, windowTag].join("\0");
33341
33703
  const now = Date.now();
33342
33704
  if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
33343
33705
  return true;
@@ -33349,7 +33711,7 @@ ${effect.notification.body || ""}`.trim();
33349
33711
  historySessionId: this.providerSessionId,
33350
33712
  workspace: this.workingDir,
33351
33713
  offset: 0,
33352
- limit: Number.MAX_SAFE_INTEGER,
33714
+ limit,
33353
33715
  historyBehavior: this.provider.historyBehavior,
33354
33716
  scripts: this.provider.scripts
33355
33717
  });
@@ -33365,7 +33727,7 @@ ${effect.notification.body || ""}`.trim();
33365
33727
  return true;
33366
33728
  }
33367
33729
  try {
33368
- const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror"].join("\0");
33730
+ const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror", windowTag].join("\0");
33369
33731
  const now = Date.now();
33370
33732
  if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
33371
33733
  return true;
@@ -33375,7 +33737,7 @@ ${effect.notification.body || ""}`.trim();
33375
33737
  if (!materializeProviderNativeHistory(this.type, canonicalHistory, this.providerSessionId, this.workingDir, this.provider.scripts)) {
33376
33738
  return false;
33377
33739
  }
33378
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
33740
+ const restoredHistory = readChatHistory(this.type, 0, limit, this.providerSessionId, 0, this.provider.historyBehavior);
33379
33741
  this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
33380
33742
  role: message.role,
33381
33743
  content: message.content,
@@ -33390,7 +33752,7 @@ ${effect.notification.body || ""}`.trim();
33390
33752
  }
33391
33753
  restorePersistedHistoryFromCurrentSession() {
33392
33754
  if (!this.providerSessionId) return;
33393
- this.syncCanonicalSavedHistoryIfNeeded();
33755
+ this.syncCanonicalSavedHistoryIfNeeded({ full: true });
33394
33756
  const restoredHistory = isNativeSourceCanonicalHistory(this.provider.nativeHistory) ? readProviderChatHistory(this.type, {
33395
33757
  canonicalHistory: this.provider.nativeHistory,
33396
33758
  historySessionId: this.providerSessionId,
@@ -46292,9 +46654,9 @@ ${hintLines.join("\n")}` : "",
46292
46654
  });
46293
46655
  let node;
46294
46656
  if (meshRecord.inline) {
46295
- const { randomUUID: randomUUID14 } = await import("crypto");
46657
+ const { randomUUID: randomUUID15 } = await import("crypto");
46296
46658
  node = {
46297
- id: `node_${randomUUID14().replace(/-/g, "")}`,
46659
+ id: `node_${randomUUID15().replace(/-/g, "")}`,
46298
46660
  workspace: result.worktreePath,
46299
46661
  repoRoot: result.worktreePath,
46300
46662
  daemonId: sourceNode.daemonId,
@@ -47068,10 +47430,11 @@ ${ptyResult.output.slice(-2e3)}`);
47068
47430
  if (!mesh) return { success: false, error: "Mesh not found" };
47069
47431
  const meshHost = resolveMeshHostStatus(mesh);
47070
47432
  const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
47433
+ const verboseMissions = args?.verbose === true || args?.compact === false;
47071
47434
  const peekScope = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : this.deps.statusInstanceId || void 0;
47072
47435
  const pendingCoordinatorEventCount = getPendingMeshCoordinatorEvents(meshId, peekScope).length;
47073
47436
  const hadAggregateCache = this.aggregateMeshStatusCache.has(meshId);
47074
- if (!refreshRequested && pendingCoordinatorEventCount === 0) {
47437
+ if (!refreshRequested && !verboseMissions && pendingCoordinatorEventCount === 0) {
47075
47438
  const cachedStatus = this.getCachedAggregateMeshStatus(meshId, mesh, { requireDirectPeerTruth: args?.requireDirectPeerTruth === true });
47076
47439
  if (cachedStatus) {
47077
47440
  logRepoMeshStatusDebug("return_cached", {
@@ -47374,7 +47737,7 @@ ${ptyResult.output.slice(-2e3)}`);
47374
47737
  liveSessionRecords: liveMeshSessions
47375
47738
  });
47376
47739
  const { getMeshStatusMissionSummaries: getMeshStatusMissionSummaries2 } = await Promise.resolve().then(() => (init_mesh_missions(), mesh_missions_exports));
47377
- const missions = getMeshStatusMissionSummaries2(meshId);
47740
+ const missions = getMeshStatusMissionSummaries2(meshId, { verbose: verboseMissions });
47378
47741
  const statusResult = {
47379
47742
  success: true,
47380
47743
  meshId: mesh.id,
@@ -47428,7 +47791,7 @@ ${ptyResult.output.slice(-2e3)}`);
47428
47791
  }))
47429
47792
  };
47430
47793
  const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, ...cacheableStatusResult } = statusResult;
47431
- const rememberedStatus = this.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
47794
+ const rememberedStatus = verboseMissions ? cacheableStatusResult : this.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
47432
47795
  const returnedStatus = {
47433
47796
  ...rememberedStatus,
47434
47797
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
@@ -54984,7 +55347,7 @@ var SessionHostPtyTransportFactory = class {
54984
55347
  };
54985
55348
 
54986
55349
  // src/cli-adapters/raw-terminal-io.ts
54987
- import { randomUUID as randomUUID13 } from "crypto";
55350
+ import { randomUUID as randomUUID14 } from "crypto";
54988
55351
  import {
54989
55352
  SessionHostClient as SessionHostClient2
54990
55353
  } from "@adhdev/session-host-core";
@@ -55084,7 +55447,7 @@ var RawTerminalAttachment = class _RawTerminalAttachment {
55084
55447
  const sessionId = String(options.sessionId || "").trim();
55085
55448
  if (!sessionId) throw new Error("sessionId is required");
55086
55449
  const mode = options.mode || "read";
55087
- const clientId = options.clientId || `raw-terminal-${process.pid}-${randomUUID13().slice(0, 8)}`;
55450
+ const clientId = options.clientId || `raw-terminal-${process.pid}-${randomUUID14().slice(0, 8)}`;
55088
55451
  const client = options.client || new SessionHostClient2({ endpoint: options.endpoint });
55089
55452
  await client.connect();
55090
55453
  const attachResponse = await client.request({