@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.js CHANGED
@@ -275,10 +275,10 @@ function readInjected(value) {
275
275
  }
276
276
  function getDaemonBuildInfo() {
277
277
  if (cached) return cached;
278
- const commit = readInjected(true ? "7b5b620e2df42c7c3beb8a2983e3cc076c25f832" : void 0) ?? "unknown";
279
- const commitShort = readInjected(true ? "7b5b620e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
280
- const version = readInjected(true ? "0.9.82-rc.292" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
281
- const builtAt = readInjected(true ? "2026-06-16T09:16:23.646Z" : void 0);
278
+ const commit = readInjected(true ? "6ee0e52b0b7347870577ebe598054d87127078fe" : void 0) ?? "unknown";
279
+ const commitShort = readInjected(true ? "6ee0e52b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
280
+ const version = readInjected(true ? "0.9.82-rc.294" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
281
+ const builtAt = readInjected(true ? "2026-06-16T12:15:42.290Z" : void 0);
282
282
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
283
283
  return cached;
284
284
  }
@@ -349,6 +349,15 @@ async function getGitRepoStatus(workspace, options = {}) {
349
349
  );
350
350
  }
351
351
  }
352
+ function isNonRuntimeRootFile(file) {
353
+ const base = file.slice(file.lastIndexOf("/") + 1);
354
+ if (/^\.(?:verify|marker|converge|ff-verify|patch-equiv|live-verify)\b/i.test(base)) return true;
355
+ if (/(?:^|\/)docs\//i.test(file)) return true;
356
+ if (/^(?:README|CHANGELOG|LICENSE|NOTICE|AUTHORS|CONTRIBUTING|CODEOWNERS)(?:\.[A-Za-z0-9]+)?$/i.test(base)) {
357
+ return true;
358
+ }
359
+ return false;
360
+ }
352
361
  async function classifyDaemonBuildChange(repoPath, buildCommit, options) {
353
362
  try {
354
363
  const diff = await runGit(repoPath, ["diff", "--name-only", `${buildCommit}..HEAD`], options);
@@ -357,18 +366,18 @@ async function classifyDaemonBuildChange(repoPath, buildCommit, options) {
357
366
  return { isDaemonAffecting: true, affectedPackages: [] };
358
367
  }
359
368
  const pkgs = /* @__PURE__ */ new Set();
360
- let sawNonPackageOrUnknown = false;
369
+ let sawRuntimeAmbiguousNonPackage = false;
361
370
  for (const file of files) {
362
371
  const match = file.match(/(?:^|\/)packages\/([^/]+)\//);
363
372
  if (!match) {
364
- sawNonPackageOrUnknown = true;
373
+ if (!isNonRuntimeRootFile(file)) sawRuntimeAmbiguousNonPackage = true;
365
374
  continue;
366
375
  }
367
376
  pkgs.add(match[1]);
368
377
  }
369
378
  const affectedPackages = [...pkgs].sort();
370
- const allWebOnly = !sawNonPackageOrUnknown && affectedPackages.length > 0 && affectedPackages.every((p) => WEB_ONLY_PACKAGES.has(p) && !DAEMON_RUNTIME_PACKAGES.has(p));
371
- return { isDaemonAffecting: !allWebOnly, affectedPackages };
379
+ const allBenign = !sawRuntimeAmbiguousNonPackage && affectedPackages.every((p) => WEB_ONLY_PACKAGES.has(p) && !DAEMON_RUNTIME_PACKAGES.has(p));
380
+ return { isDaemonAffecting: !allBenign, affectedPackages };
372
381
  } catch {
373
382
  return { isDaemonAffecting: true, affectedPackages: [] };
374
383
  }
@@ -395,7 +404,8 @@ async function detectDaemonBuildBehind(repo, submodules, options) {
395
404
  options
396
405
  );
397
406
  const scopeLabel = scope === "root" ? "workspace" : scope;
398
- 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.`;
407
+ const benignDetail = affectedPackages.length > 0 ? `only web packages changed (${affectedPackages.join(", ")})` : "only non-runtime files changed (markers/docs)";
408
+ 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.`;
399
409
  return {
400
410
  buildCommit: build.commit,
401
411
  buildCommitShort: build.commitShort,
@@ -1997,8 +2007,9 @@ function buildRulesSection(coordinatorCliType) {
1997
2007
  - **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.
1998
2008
  - **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.
1999
2009
  - **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
2000
- - **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.
2010
+ - **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).
2001
2011
  - **Check history first.** Call \`mesh_task_history\` at session start to avoid duplicate work and inform recovery. On failure, read task history before retrying.
2012
+ - **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.
2002
2013
  - **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\`.
2003
2014
  - **Refinery is config-driven.** \`mesh_refine_node\` must run validation from \`.adhdev/refine.{json,yaml,yml}\` or \`repo-mesh.refine.*\`. Heuristics are scaffolding only.
2004
2015
  - **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\`.
@@ -2051,7 +2062,7 @@ Before doing any coordinator work, confirm that the actual callable tool list in
2051
2062
  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.
2052
2063
  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.
2053
2064
  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.
2054
- 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\`.
2065
+ 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.
2055
2066
  5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
2056
2067
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
2057
2068
  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.
@@ -4395,6 +4406,34 @@ var init_mesh_runtime_store = __esm({
4395
4406
  ).get(meshId);
4396
4407
  return row?.cnt ?? 0;
4397
4408
  }
4409
+ /**
4410
+ * Mark specific pending-event rows drained by id (ack). Used by the
4411
+ * unresolved-delegate durable-forward outbox: an event is peeked (not drained)
4412
+ * while its push to the coordinator is unconfirmed, then marked drained ONLY
4413
+ * after the push is acked. A failed push leaves the row undrained so the next
4414
+ * reconcile tick retries it. Returns the number of rows newly marked drained.
4415
+ */
4416
+ markPendingEventsDrainedById(ids) {
4417
+ const idList = ids.filter((id) => typeof id === "string" && id.length > 0);
4418
+ if (idList.length === 0) return 0;
4419
+ const now = Date.now();
4420
+ return this.db.prepare(
4421
+ `UPDATE mesh_pending_events SET drained = 1, drained_at = ? WHERE drained = 0 AND id IN (${idList.map(() => "?").join(",")})`
4422
+ ).run(now, ...idList).changes;
4423
+ }
4424
+ /**
4425
+ * Hard-delete pending-event rows by id (including the dedup fingerprint history).
4426
+ * Used to expire an unresolved-delegate outbox entry that has exhausted its retry
4427
+ * budget — fully removing it frees the fingerprint so a genuinely new completion
4428
+ * for the same task could be re-queued later. Returns the number of rows deleted.
4429
+ */
4430
+ deletePendingEventsById(ids) {
4431
+ const idList = ids.filter((id) => typeof id === "string" && id.length > 0);
4432
+ if (idList.length === 0) return 0;
4433
+ return this.db.prepare(
4434
+ `DELETE FROM mesh_pending_events WHERE id IN (${idList.map(() => "?").join(",")})`
4435
+ ).run(...idList).changes;
4436
+ }
4398
4437
  };
4399
4438
  }
4400
4439
  });
@@ -4402,6 +4441,7 @@ var init_mesh_runtime_store = __esm({
4402
4441
  // src/mesh/mesh-missions.ts
4403
4442
  var mesh_missions_exports = {};
4404
4443
  __export(mesh_missions_exports, {
4444
+ GOAL_PREVIEW_MAX: () => GOAL_PREVIEW_MAX,
4405
4445
  MESH_MISSION_STATUSES: () => MESH_MISSION_STATUSES,
4406
4446
  buildMissionPromptSection: () => buildMissionPromptSection,
4407
4447
  getActiveMeshMissionSummaries: () => getActiveMeshMissionSummaries,
@@ -4473,12 +4513,23 @@ function summarizeMeshMission(meshId, mission) {
4473
4513
  function getActiveMeshMissionSummaries(meshId) {
4474
4514
  return getMeshMissions(meshId, ["active"]).map((mission) => summarizeMeshMission(meshId, mission));
4475
4515
  }
4516
+ function slimMissionSummary(summary) {
4517
+ const goal = typeof summary.goal === "string" ? summary.goal : "";
4518
+ const goalTruncated = goal.length > GOAL_PREVIEW_MAX;
4519
+ const { goal: _omitGoal, ...rest } = summary;
4520
+ return {
4521
+ ...rest,
4522
+ goalPreview: goalTruncated ? goal.slice(0, GOAL_PREVIEW_MAX) : goal,
4523
+ goalTruncated
4524
+ };
4525
+ }
4476
4526
  function getMeshStatusMissionSummaries(meshId, options) {
4477
4527
  const historyLimit = Math.max(0, options?.historyLimit ?? 10);
4478
4528
  const all = getMeshMissions(meshId);
4479
4529
  const live = all.filter((m) => m.status === "active" || m.status === "paused");
4480
4530
  const history = all.filter((m) => m.status === "completed" || m.status === "abandoned").sort((a, b) => (b.updatedAt || "").localeCompare(a.updatedAt || "")).slice(0, historyLimit);
4481
- return [...live, ...history].map((mission) => summarizeMeshMission(meshId, mission));
4531
+ const full = [...live, ...history].map((mission) => summarizeMeshMission(meshId, mission));
4532
+ return options?.verbose ? full : full.map(slimMissionSummary);
4482
4533
  }
4483
4534
  function buildMissionPromptSection(meshId) {
4484
4535
  const summaries = getActiveMeshMissionSummaries(meshId);
@@ -4498,7 +4549,7 @@ function buildMissionPromptSection(meshId) {
4498
4549
  );
4499
4550
  return lines.join("\n");
4500
4551
  }
4501
- var import_crypto6, MESH_MISSION_STATUSES;
4552
+ var import_crypto6, MESH_MISSION_STATUSES, GOAL_PREVIEW_MAX;
4502
4553
  var init_mesh_missions = __esm({
4503
4554
  "src/mesh/mesh-missions.ts"() {
4504
4555
  "use strict";
@@ -4506,6 +4557,7 @@ var init_mesh_missions = __esm({
4506
4557
  init_mesh_runtime_store();
4507
4558
  init_mesh_work_queue();
4508
4559
  MESH_MISSION_STATUSES = ["active", "paused", "completed", "abandoned"];
4560
+ GOAL_PREVIEW_MAX = 120;
4509
4561
  }
4510
4562
  });
4511
4563
 
@@ -7604,6 +7656,111 @@ var init_mesh_routing = __esm({
7604
7656
  }
7605
7657
  });
7606
7658
 
7659
+ // src/mesh/mesh-unresolved-forward-outbox.ts
7660
+ function getStore() {
7661
+ try {
7662
+ return MeshRuntimeStore.getInstance();
7663
+ } catch {
7664
+ return void 0;
7665
+ }
7666
+ }
7667
+ function enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, forwardPayload) {
7668
+ const target = readNonEmptyString2(coordinatorDaemonId);
7669
+ const event = readNonEmptyString2(eventName);
7670
+ if (!target || !event) return false;
7671
+ const store = getStore();
7672
+ if (!store) return false;
7673
+ const queuedAt = Date.now();
7674
+ const fingerprintSource = {
7675
+ event,
7676
+ meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
7677
+ nodeLabel: readNonEmptyString2(forwardPayload.nodeId) || readNonEmptyString2(forwardPayload.workspace) || "unresolved-delegate",
7678
+ nodeId: readNonEmptyString2(forwardPayload.nodeId) || void 0,
7679
+ workspace: readNonEmptyString2(forwardPayload.workspace) || void 0,
7680
+ metadataEvent: forwardPayload,
7681
+ queuedAt,
7682
+ targetCoordinatorDaemonId: target
7683
+ };
7684
+ const fingerprint = `${target}::${buildPendingEventFingerprint(fingerprintSource)}`;
7685
+ try {
7686
+ const inserted = store.insertPendingEvent({
7687
+ id: (0, import_crypto9.randomUUID)(),
7688
+ meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
7689
+ coordinatorDaemonId: target,
7690
+ event,
7691
+ // Store the flat forward payload + the queue timestamp so the retry tick can
7692
+ // rebuild the push args and apply age-based expiry without a schema change.
7693
+ payload: { forwardPayload, coordinatorDaemonId: target, queuedAt },
7694
+ fingerprint,
7695
+ queuedAt
7696
+ });
7697
+ if (inserted) {
7698
+ LOG.info("MeshEvents", `Durably queued unresolved-delegate ${event} for coordinator ${target} (outbox)`);
7699
+ }
7700
+ return true;
7701
+ } catch (e) {
7702
+ LOG.warn("MeshEvents", `Failed to persist unresolved-delegate forward to outbox: ${e?.message || e}`);
7703
+ return false;
7704
+ }
7705
+ }
7706
+ function peekUnresolvedDelegateForwards() {
7707
+ const store = getStore();
7708
+ if (!store) return [];
7709
+ let rows;
7710
+ try {
7711
+ rows = store.peekPendingEvents(UNRESOLVED_FORWARD_OUTBOX_MESH_ID);
7712
+ } catch {
7713
+ return [];
7714
+ }
7715
+ const out = [];
7716
+ for (const row of rows) {
7717
+ const stored = row.payload && typeof row.payload === "object" ? row.payload : {};
7718
+ const coordinatorDaemonId = readNonEmptyString2(stored.coordinatorDaemonId);
7719
+ const forwardPayload = stored.forwardPayload && typeof stored.forwardPayload === "object" ? stored.forwardPayload : void 0;
7720
+ if (!coordinatorDaemonId || !forwardPayload) continue;
7721
+ const queuedAt = typeof stored.queuedAt === "number" ? stored.queuedAt : 0;
7722
+ out.push({ id: row.id, coordinatorDaemonId, payload: forwardPayload, queuedAt });
7723
+ }
7724
+ return out;
7725
+ }
7726
+ function ackUnresolvedDelegateForward(id) {
7727
+ const store = getStore();
7728
+ if (!store) return;
7729
+ try {
7730
+ store.markPendingEventsDrainedById([id]);
7731
+ } catch {
7732
+ }
7733
+ }
7734
+ function expireStaleUnresolvedDelegateForwards(nowMs = Date.now()) {
7735
+ const entries = peekUnresolvedDelegateForwards();
7736
+ const staleIds = entries.filter((e) => e.queuedAt > 0 && nowMs - e.queuedAt >= UNRESOLVED_FORWARD_MAX_AGE_MS).map((e) => e.id);
7737
+ if (staleIds.length === 0) return 0;
7738
+ const store = getStore();
7739
+ if (!store) return 0;
7740
+ try {
7741
+ const removed = store.deletePendingEventsById(staleIds);
7742
+ if (removed > 0) {
7743
+ 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`);
7744
+ }
7745
+ return removed;
7746
+ } catch {
7747
+ return 0;
7748
+ }
7749
+ }
7750
+ var import_crypto9, UNRESOLVED_FORWARD_OUTBOX_MESH_ID, UNRESOLVED_FORWARD_MAX_AGE_MS;
7751
+ var init_mesh_unresolved_forward_outbox = __esm({
7752
+ "src/mesh/mesh-unresolved-forward-outbox.ts"() {
7753
+ "use strict";
7754
+ import_crypto9 = require("crypto");
7755
+ init_logger();
7756
+ init_mesh_runtime_store();
7757
+ init_mesh_events_pending();
7758
+ init_mesh_events_utils();
7759
+ UNRESOLVED_FORWARD_OUTBOX_MESH_ID = "__unresolved_forward_outbox__";
7760
+ UNRESOLVED_FORWARD_MAX_AGE_MS = 30 * 60 * 1e3;
7761
+ }
7762
+ });
7763
+
7607
7764
  // src/mesh/mesh-events-coordinator.ts
7608
7765
  function resolveCoordinatorDrainDaemonIds(components) {
7609
7766
  const ids = /* @__PURE__ */ new Set();
@@ -8738,12 +8895,25 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
8738
8895
  nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId) || void 0,
8739
8896
  workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
8740
8897
  };
8741
- Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).catch((e) => {
8742
- LOG.warn("MeshEvents", `Fallback forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e}`);
8898
+ const persisted = enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, payload);
8899
+ Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
8900
+ if (result && result.success === false) {
8901
+ LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
8902
+ return;
8903
+ }
8904
+ if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
8905
+ }).catch((e) => {
8906
+ LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued for retry`);
8743
8907
  });
8744
- LOG.info("MeshEvents", `Fallback-forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
8908
+ LOG.info("MeshEvents", `Durably forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
8745
8909
  return true;
8746
8910
  }
8911
+ function ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload) {
8912
+ const match = peekUnresolvedDelegateForwards().find(
8913
+ (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)
8914
+ );
8915
+ if (match) ackUnresolvedDelegateForward(match.id);
8916
+ }
8747
8917
  function setupMeshEventForwarding(components) {
8748
8918
  components.instanceManager.onEvent((event) => {
8749
8919
  if (event.event === "agent:ready" || event.event === "agent:generating_completed") {
@@ -8825,6 +8995,7 @@ var init_mesh_events_coordinator = __esm({
8825
8995
  init_mesh_runtime_store();
8826
8996
  init_mesh_events_pending();
8827
8997
  init_mesh_routing();
8998
+ init_mesh_unresolved_forward_outbox();
8828
8999
  init_repo_mesh_types();
8829
9000
  init_dist();
8830
9001
  init_mesh_events_stale();
@@ -8940,6 +9111,13 @@ async function runMeshReconcileTick(components) {
8940
9111
  return void 0;
8941
9112
  }
8942
9113
  })();
9114
+ if (dispatchMeshCommand) {
9115
+ try {
9116
+ await retryUnresolvedDelegateForwards(components);
9117
+ } catch (e) {
9118
+ LOG.warn("MeshReconcile", `Unresolved-delegate forward retry failed: ${e?.message || e}`);
9119
+ }
9120
+ }
8943
9121
  if (dispatchMeshCommand) {
8944
9122
  for (const mesh of listMeshes()) {
8945
9123
  const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
@@ -8993,6 +9171,28 @@ async function runMeshReconcileTick(components) {
8993
9171
  }
8994
9172
  }
8995
9173
  }
9174
+ async function retryUnresolvedDelegateForwards(components) {
9175
+ const dispatchMeshCommand = components.dispatchMeshCommand;
9176
+ if (!dispatchMeshCommand) return;
9177
+ expireStaleUnresolvedDelegateForwards();
9178
+ const entries = peekUnresolvedDelegateForwards();
9179
+ if (entries.length === 0) return;
9180
+ for (const entry of entries) {
9181
+ let result;
9182
+ try {
9183
+ result = await dispatchMeshCommand(entry.coordinatorDaemonId, "mesh_forward_event", entry.payload);
9184
+ } catch (e) {
9185
+ LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued`);
9186
+ continue;
9187
+ }
9188
+ if (result && result.success === false) {
9189
+ LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued`);
9190
+ continue;
9191
+ }
9192
+ ackUnresolvedDelegateForward(entry.id);
9193
+ LOG.info("MeshReconcile", `Retried+delivered unresolved-delegate ${readNonEmptyString2(entry.payload.event)} to coordinator ${entry.coordinatorDaemonId}`);
9194
+ }
9195
+ }
8996
9196
  async function pullRemoteNodeQueues(components, mesh, localDaemonId, candidateDaemonIds) {
8997
9197
  const dispatchMeshCommand = components.dispatchMeshCommand;
8998
9198
  if (!dispatchMeshCommand) return;
@@ -9069,6 +9269,7 @@ var init_mesh_reconcile_loop = __esm({
9069
9269
  init_mesh_events_pending();
9070
9270
  init_mesh_runtime_store();
9071
9271
  init_mesh_events_coordinator();
9272
+ init_mesh_unresolved_forward_outbox();
9072
9273
  init_mesh_events_utils();
9073
9274
  DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
9074
9275
  }
@@ -21712,22 +21913,160 @@ function isBoundedTailRequest(limit, offset, excludeRecentCount) {
21712
21913
  if (!Number.isFinite(numericOffset) || !Number.isFinite(numericExclude)) return false;
21713
21914
  return true;
21714
21915
  }
21916
+ var REVERSE_TAIL_SMALL_FILE_BYTES = 64 * 1024;
21917
+ var REVERSE_TAIL_CHUNK_BYTES = 64 * 1024;
21918
+ var TAIL_LINES_RETAINED = BOUNDED_TAIL_MAX_LIMIT + 2 * BOUNDED_TAIL_SLACK;
21919
+ var INCREMENTAL_TAIL_CACHE_MAX_ENTRIES = 64;
21920
+ var incrementalTailCache = /* @__PURE__ */ new Map();
21921
+ function evictIncrementalTailCache() {
21922
+ while (incrementalTailCache.size > INCREMENTAL_TAIL_CACHE_MAX_ENTRIES) {
21923
+ const oldest = incrementalTailCache.keys().next().value;
21924
+ if (oldest === void 0) break;
21925
+ incrementalTailCache.delete(oldest);
21926
+ }
21927
+ }
21928
+ function splitBufferLines(buf) {
21929
+ const lines = [];
21930
+ let lineEnd = buf.length;
21931
+ let firstNewline = -1;
21932
+ for (let i = buf.length - 1; i >= 0; i--) {
21933
+ if (buf[i] !== 10) continue;
21934
+ if (i + 1 < lineEnd) {
21935
+ lines.push(buf.toString("utf-8", i + 1, lineEnd));
21936
+ }
21937
+ lineEnd = i;
21938
+ firstNewline = i;
21939
+ }
21940
+ lines.reverse();
21941
+ const head = firstNewline >= 0 ? buf.subarray(0, firstNewline) : buf;
21942
+ return { head, lines };
21943
+ }
21944
+ function readReverseTailLines(filePath, needed) {
21945
+ const fd = fs5.openSync(filePath, "r");
21946
+ try {
21947
+ const stat2 = fs5.fstatSync(fd);
21948
+ const size = stat2.size;
21949
+ let position = size;
21950
+ let carry = Buffer.alloc(0);
21951
+ const collected = [];
21952
+ while (position > 0 && collected.length < needed) {
21953
+ const chunkSize = Math.min(REVERSE_TAIL_CHUNK_BYTES, position);
21954
+ position -= chunkSize;
21955
+ const chunk = Buffer.alloc(chunkSize);
21956
+ fs5.readSync(fd, chunk, 0, chunkSize, position);
21957
+ const combined = carry.length ? Buffer.concat([chunk, carry]) : chunk;
21958
+ const { head, lines } = splitBufferLines(combined);
21959
+ carry = head;
21960
+ for (let i = lines.length - 1; i >= 0; i--) {
21961
+ collected.push(lines[i]);
21962
+ }
21963
+ }
21964
+ const reachedStart = position <= 0;
21965
+ if (reachedStart && carry.length) {
21966
+ collected.push(carry.toString("utf-8"));
21967
+ }
21968
+ collected.reverse();
21969
+ return { lines: collected, coversWholeFile: reachedStart, size, mtimeMs: stat2.mtimeMs };
21970
+ } finally {
21971
+ fs5.closeSync(fd);
21972
+ }
21973
+ }
21974
+ function readFileTailLines(filePath, needed) {
21975
+ let stat2;
21976
+ try {
21977
+ stat2 = fs5.statSync(filePath);
21978
+ } catch {
21979
+ return { lines: [], coversWholeFile: true };
21980
+ }
21981
+ const size = stat2.size;
21982
+ const mtimeMs = stat2.mtimeMs;
21983
+ if (size === 0) {
21984
+ incrementalTailCache.delete(filePath);
21985
+ return { lines: [], coversWholeFile: true };
21986
+ }
21987
+ const cached2 = incrementalTailCache.get(filePath);
21988
+ if (cached2) {
21989
+ if (cached2.size === size && cached2.mtimeMs === mtimeMs) {
21990
+ incrementalTailCache.delete(filePath);
21991
+ incrementalTailCache.set(filePath, cached2);
21992
+ if (cached2.coversWholeFile || cached2.lines.length >= needed) {
21993
+ return { lines: cached2.lines, coversWholeFile: cached2.coversWholeFile };
21994
+ }
21995
+ } else if (size > cached2.size) {
21996
+ const incremental = tryIncrementalTailGrowth(filePath, cached2, size, mtimeMs, needed);
21997
+ if (incremental) return { lines: incremental.lines, coversWholeFile: incremental.coversWholeFile };
21998
+ }
21999
+ incrementalTailCache.delete(filePath);
22000
+ }
22001
+ if (size <= REVERSE_TAIL_SMALL_FILE_BYTES) {
22002
+ let content;
22003
+ try {
22004
+ content = fs5.readFileSync(filePath, "utf-8");
22005
+ } catch {
22006
+ return { lines: [], coversWholeFile: true };
22007
+ }
22008
+ const lines = content.split("\n");
22009
+ if (lines.length && lines[lines.length - 1] === "") lines.pop();
22010
+ storeIncrementalTailCache(filePath, size, mtimeMs, lines, true);
22011
+ return { lines, coversWholeFile: true };
22012
+ }
22013
+ let result;
22014
+ try {
22015
+ result = readReverseTailLines(filePath, needed);
22016
+ } catch {
22017
+ return { lines: [], coversWholeFile: true };
22018
+ }
22019
+ storeIncrementalTailCache(filePath, result.size, result.mtimeMs, result.lines, result.coversWholeFile);
22020
+ return { lines: result.lines, coversWholeFile: result.coversWholeFile };
22021
+ }
22022
+ function tryIncrementalTailGrowth(filePath, cached2, size, mtimeMs, needed) {
22023
+ const fd = fs5.openSync(filePath, "r");
22024
+ try {
22025
+ if (cached2.size > 0) {
22026
+ const boundary = Buffer.alloc(1);
22027
+ fs5.readSync(fd, boundary, 0, 1, cached2.size - 1);
22028
+ if (boundary[0] !== 10) return null;
22029
+ }
22030
+ const appendedLength = size - cached2.size;
22031
+ const appended = Buffer.alloc(appendedLength);
22032
+ fs5.readSync(fd, appended, 0, appendedLength, cached2.size);
22033
+ const newLines = appended.toString("utf-8").split("\n");
22034
+ if (newLines.length && newLines[newLines.length - 1] === "") newLines.pop();
22035
+ const merged = cached2.lines.concat(newLines);
22036
+ const trimmed = merged.length > TAIL_LINES_RETAINED ? merged.slice(merged.length - TAIL_LINES_RETAINED) : merged;
22037
+ const coversWholeFile = cached2.coversWholeFile && trimmed.length === merged.length;
22038
+ storeIncrementalTailCache(filePath, size, mtimeMs, trimmed, coversWholeFile);
22039
+ if (coversWholeFile || trimmed.length >= needed) {
22040
+ return { lines: trimmed, coversWholeFile };
22041
+ }
22042
+ return { lines: trimmed, coversWholeFile };
22043
+ } catch {
22044
+ return null;
22045
+ } finally {
22046
+ fs5.closeSync(fd);
22047
+ }
22048
+ }
22049
+ function storeIncrementalTailCache(filePath, size, mtimeMs, lines, coversWholeFile) {
22050
+ const retained = lines.length > TAIL_LINES_RETAINED ? lines.slice(lines.length - TAIL_LINES_RETAINED) : lines;
22051
+ const covers = coversWholeFile && retained.length === lines.length;
22052
+ incrementalTailCache.delete(filePath);
22053
+ incrementalTailCache.set(filePath, { size, mtimeMs, lines: retained, coversWholeFile: covers });
22054
+ evictIncrementalTailCache();
22055
+ }
21715
22056
  function readBoundedTailRecords(agentType, dir, files, needed) {
21716
22057
  const collected = [];
21717
22058
  const seen = /* @__PURE__ */ new Set();
21718
22059
  let readAllFiles = true;
21719
22060
  for (let f = 0; f < files.length; f++) {
21720
22061
  const filePath = path12.join(dir, files[f]);
21721
- let content;
21722
- try {
21723
- content = fs5.readFileSync(filePath, "utf-8");
21724
- } catch {
21725
- continue;
21726
- }
21727
- const lines = content.trim().split("\n").filter(Boolean);
22062
+ const remaining = Math.max(0, needed - collected.length);
22063
+ const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
22064
+ const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
21728
22065
  for (let i = lines.length - 1; i >= 0; i--) {
22066
+ const line = lines[i];
22067
+ if (!line) continue;
21729
22068
  try {
21730
- const parsed = JSON.parse(lines[i]);
22069
+ const parsed = JSON.parse(line);
21731
22070
  const sanitizedMessage = sanitizeHistoryMessage(agentType, parsed);
21732
22071
  if (!sanitizedMessage) continue;
21733
22072
  const hash = buildHistoryMessageHash(agentType, sanitizedMessage);
@@ -21737,6 +22076,10 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
21737
22076
  } catch {
21738
22077
  }
21739
22078
  }
22079
+ if (!coversWholeFile) {
22080
+ readAllFiles = false;
22081
+ break;
22082
+ }
21740
22083
  if (collected.length >= needed && f < files.length - 1) {
21741
22084
  readAllFiles = false;
21742
22085
  break;
@@ -22340,7 +22683,7 @@ var ExtensionProviderInstance = class {
22340
22683
  this.runtimeMessages = [];
22341
22684
  }
22342
22685
  updateSettings(newSettings) {
22343
- this.settings = { ...newSettings };
22686
+ this.settings = { ...this.settings, ...newSettings };
22344
22687
  this.monitor.updateConfig({
22345
22688
  approvalAlert: this.settings.approvalAlert !== false,
22346
22689
  longGeneratingAlert: this.settings.longGeneratingAlert !== false,
@@ -23007,7 +23350,7 @@ var IdeProviderInstance = class {
23007
23350
  this.extensions.clear();
23008
23351
  }
23009
23352
  updateSettings(newSettings) {
23010
- this.settings = { ...newSettings };
23353
+ this.settings = { ...this.settings, ...newSettings };
23011
23354
  this.monitor.updateConfig({
23012
23355
  approvalAlert: this.settings.approvalAlert !== false,
23013
23356
  longGeneratingAlert: this.settings.longGeneratingAlert !== false,
@@ -31693,12 +32036,14 @@ var SpecCliAdapter = class _SpecCliAdapter {
31693
32036
  }
31694
32037
  this.maybeClearResolvedClaudeTuiPrompt();
31695
32038
  this.maybeCaptureClaudeTuiPrompt();
32039
+ this.maybeUpgradeClaudeTuiMultiSelect();
31696
32040
  this.statusCallback?.();
31697
32041
  return;
31698
32042
  case "pty_data":
31699
32043
  this.detectInteractivePromptFromPtyChunk(ev.chunk);
31700
32044
  this.maybeClearResolvedClaudeTuiPrompt();
31701
32045
  this.maybeCaptureClaudeTuiPrompt();
32046
+ this.maybeUpgradeClaudeTuiMultiSelect();
31702
32047
  try {
31703
32048
  this.ptyDataCallback?.(ev.chunk);
31704
32049
  } catch {
@@ -31847,6 +32192,35 @@ var SpecCliAdapter = class _SpecCliAdapter {
31847
32192
  this.claudeTuiPromptCaptureInFlight = false;
31848
32193
  });
31849
32194
  }
32195
+ /**
32196
+ * The TUI prompt is captured on the FIRST frame that renders the
32197
+ * "Enter to select" footer. At that instant the option rows' checkbox
32198
+ * column may not have drawn yet, so `detectClaudeTuiMultiSelect` returns
32199
+ * false and the prompt is frozen as single-select — the dashboard then
32200
+ * renders radio buttons even though the picker is multi-select.
32201
+ *
32202
+ * While the same TUI prompt is still on screen, re-check the live snapshot:
32203
+ * if checkbox glyphs have since appeared, promote any single-select
32204
+ * question to multi-select and re-emit status. Promotion is one-way
32205
+ * (false→true only) — once a question is known multi-select we never demote
32206
+ * it, since the glyph column can scroll out of view on later frames.
32207
+ */
32208
+ maybeUpgradeClaudeTuiMultiSelect() {
32209
+ if (this.cliType !== "claude-cli" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
32210
+ const questions = this.activeInteractivePrompt.questions;
32211
+ if (questions.length !== 1) return;
32212
+ if (questions[0].multiSelect) return;
32213
+ let screenText = "";
32214
+ try {
32215
+ screenText = this.driver.snapshot();
32216
+ } catch {
32217
+ return;
32218
+ }
32219
+ if (!screenText.includes("Enter to select")) return;
32220
+ if (!detectClaudeTuiMultiSelect(screenText)) return;
32221
+ questions[0].multiSelect = true;
32222
+ this.statusCallback?.();
32223
+ }
31850
32224
  readClaudeTuiHeaders(screenText) {
31851
32225
  const navLine = screenText.split(/\r?\n/).find((line) => line.includes("\u2714 Submit") && /[☐☒]/.test(line));
31852
32226
  if (!navLine) return [];
@@ -31996,6 +32370,7 @@ function normalizeProviderSessionId(provider, providerSessionId) {
31996
32370
  }
31997
32371
 
31998
32372
  // src/providers/cli-provider-instance.ts
32373
+ var STATUS_HYDRATION_TAIL_LIMIT = 200;
31999
32374
  function isIdleStatus(value) {
32000
32375
  const status = typeof value === "string" ? value.trim().toLowerCase() : "";
32001
32376
  return !status || status === "idle" || status === "ready";
@@ -32555,22 +32930,7 @@ var CliProviderInstance = class _CliProviderInstance {
32555
32930
  };
32556
32931
  }
32557
32932
  updateSettings(newSettings) {
32558
- const runtimeMeshSettings = {};
32559
- for (const key of [
32560
- "meshNodeFor",
32561
- "meshNodeId",
32562
- "meshActiveTaskId",
32563
- "meshCoordinatorFor",
32564
- "meshCoordinatorDaemonId",
32565
- "meshCoordinatorNodeId",
32566
- "spawnedSessionVisibility",
32567
- "launchedByCoordinator"
32568
- ]) {
32569
- if (this.settings[key] !== void 0 && newSettings[key] === void 0) {
32570
- runtimeMeshSettings[key] = this.settings[key];
32571
- }
32572
- }
32573
- this.settings = { ...newSettings, ...runtimeMeshSettings };
32933
+ this.settings = { ...this.settings, ...newSettings };
32574
32934
  this.adapter.updateRuntimeSettings?.(this.settings);
32575
32935
  this.monitor.updateConfig({
32576
32936
  approvalAlert: this.settings.approvalAlert !== false,
@@ -33673,12 +34033,14 @@ ${effect.notification.body || ""}`.trim();
33673
34033
  const newestMessageAt = parsedMessages.reduce((newest, message) => Math.max(newest, getMessageTime(message)), 0);
33674
34034
  return newestMessageAt === 0;
33675
34035
  }
33676
- syncCanonicalSavedHistoryIfNeeded() {
34036
+ syncCanonicalSavedHistoryIfNeeded(options = {}) {
33677
34037
  if (!this.providerSessionId) return false;
33678
34038
  const canonicalHistory = this.provider.nativeHistory;
33679
34039
  if (!canonicalHistory) return false;
34040
+ const limit = options.full ? Number.MAX_SAFE_INTEGER : STATUS_HYDRATION_TAIL_LIMIT;
34041
+ const windowTag = options.full ? "full" : `tail:${STATUS_HYDRATION_TAIL_LIMIT}`;
33680
34042
  if (isNativeSourceCanonicalHistory(canonicalHistory)) {
33681
- const cacheKey = [this.type, this.providerSessionId, this.workingDir].join("\0");
34043
+ const cacheKey = [this.type, this.providerSessionId, this.workingDir, windowTag].join("\0");
33682
34044
  const now = Date.now();
33683
34045
  if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
33684
34046
  return true;
@@ -33690,7 +34052,7 @@ ${effect.notification.body || ""}`.trim();
33690
34052
  historySessionId: this.providerSessionId,
33691
34053
  workspace: this.workingDir,
33692
34054
  offset: 0,
33693
- limit: Number.MAX_SAFE_INTEGER,
34055
+ limit,
33694
34056
  historyBehavior: this.provider.historyBehavior,
33695
34057
  scripts: this.provider.scripts
33696
34058
  });
@@ -33706,7 +34068,7 @@ ${effect.notification.body || ""}`.trim();
33706
34068
  return true;
33707
34069
  }
33708
34070
  try {
33709
- const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror"].join("\0");
34071
+ const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror", windowTag].join("\0");
33710
34072
  const now = Date.now();
33711
34073
  if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
33712
34074
  return true;
@@ -33716,7 +34078,7 @@ ${effect.notification.body || ""}`.trim();
33716
34078
  if (!materializeProviderNativeHistory(this.type, canonicalHistory, this.providerSessionId, this.workingDir, this.provider.scripts)) {
33717
34079
  return false;
33718
34080
  }
33719
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
34081
+ const restoredHistory = readChatHistory(this.type, 0, limit, this.providerSessionId, 0, this.provider.historyBehavior);
33720
34082
  this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
33721
34083
  role: message.role,
33722
34084
  content: message.content,
@@ -33731,7 +34093,7 @@ ${effect.notification.body || ""}`.trim();
33731
34093
  }
33732
34094
  restorePersistedHistoryFromCurrentSession() {
33733
34095
  if (!this.providerSessionId) return;
33734
- this.syncCanonicalSavedHistoryIfNeeded();
34096
+ this.syncCanonicalSavedHistoryIfNeeded({ full: true });
33735
34097
  const restoredHistory = isNativeSourceCanonicalHistory(this.provider.nativeHistory) ? readProviderChatHistory(this.type, {
33736
34098
  canonicalHistory: this.provider.nativeHistory,
33737
34099
  historySessionId: this.providerSessionId,
@@ -46628,9 +46990,9 @@ ${hintLines.join("\n")}` : "",
46628
46990
  });
46629
46991
  let node;
46630
46992
  if (meshRecord.inline) {
46631
- const { randomUUID: randomUUID14 } = await import("crypto");
46993
+ const { randomUUID: randomUUID15 } = await import("crypto");
46632
46994
  node = {
46633
- id: `node_${randomUUID14().replace(/-/g, "")}`,
46995
+ id: `node_${randomUUID15().replace(/-/g, "")}`,
46634
46996
  workspace: result.worktreePath,
46635
46997
  repoRoot: result.worktreePath,
46636
46998
  daemonId: sourceNode.daemonId,
@@ -47404,10 +47766,11 @@ ${ptyResult.output.slice(-2e3)}`);
47404
47766
  if (!mesh) return { success: false, error: "Mesh not found" };
47405
47767
  const meshHost = resolveMeshHostStatus(mesh);
47406
47768
  const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
47769
+ const verboseMissions = args?.verbose === true || args?.compact === false;
47407
47770
  const peekScope = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : this.deps.statusInstanceId || void 0;
47408
47771
  const pendingCoordinatorEventCount = getPendingMeshCoordinatorEvents(meshId, peekScope).length;
47409
47772
  const hadAggregateCache = this.aggregateMeshStatusCache.has(meshId);
47410
- if (!refreshRequested && pendingCoordinatorEventCount === 0) {
47773
+ if (!refreshRequested && !verboseMissions && pendingCoordinatorEventCount === 0) {
47411
47774
  const cachedStatus = this.getCachedAggregateMeshStatus(meshId, mesh, { requireDirectPeerTruth: args?.requireDirectPeerTruth === true });
47412
47775
  if (cachedStatus) {
47413
47776
  logRepoMeshStatusDebug("return_cached", {
@@ -47710,7 +48073,7 @@ ${ptyResult.output.slice(-2e3)}`);
47710
48073
  liveSessionRecords: liveMeshSessions
47711
48074
  });
47712
48075
  const { getMeshStatusMissionSummaries: getMeshStatusMissionSummaries2 } = await Promise.resolve().then(() => (init_mesh_missions(), mesh_missions_exports));
47713
- const missions = getMeshStatusMissionSummaries2(meshId);
48076
+ const missions = getMeshStatusMissionSummaries2(meshId, { verbose: verboseMissions });
47714
48077
  const statusResult = {
47715
48078
  success: true,
47716
48079
  meshId: mesh.id,
@@ -47764,7 +48127,7 @@ ${ptyResult.output.slice(-2e3)}`);
47764
48127
  }))
47765
48128
  };
47766
48129
  const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, ...cacheableStatusResult } = statusResult;
47767
- const rememberedStatus = this.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
48130
+ const rememberedStatus = verboseMissions ? cacheableStatusResult : this.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
47768
48131
  const returnedStatus = {
47769
48132
  ...rememberedStatus,
47770
48133
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
@@ -55318,7 +55681,7 @@ var SessionHostPtyTransportFactory = class {
55318
55681
  };
55319
55682
 
55320
55683
  // src/cli-adapters/raw-terminal-io.ts
55321
- var import_crypto9 = require("crypto");
55684
+ var import_crypto10 = require("crypto");
55322
55685
  var import_session_host_core10 = require("@adhdev/session-host-core");
55323
55686
  var BASE_KEY_SEQUENCES = {
55324
55687
  enter: "\r",
@@ -55416,7 +55779,7 @@ var RawTerminalAttachment = class _RawTerminalAttachment {
55416
55779
  const sessionId = String(options.sessionId || "").trim();
55417
55780
  if (!sessionId) throw new Error("sessionId is required");
55418
55781
  const mode = options.mode || "read";
55419
- const clientId = options.clientId || `raw-terminal-${process.pid}-${(0, import_crypto9.randomUUID)().slice(0, 8)}`;
55782
+ const clientId = options.clientId || `raw-terminal-${process.pid}-${(0, import_crypto10.randomUUID)().slice(0, 8)}`;
55420
55783
  const client = options.client || new import_session_host_core10.SessionHostClient({ endpoint: options.endpoint });
55421
55784
  await client.connect();
55422
55785
  const attachResponse = await client.request({