@adhdev/daemon-standalone 0.9.82-rc.57 → 0.9.82-rc.59

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
@@ -23390,6 +23390,7 @@ Follow these recovery rules:
23390
23390
  getSessionRecoveryContext: () => getSessionRecoveryContext,
23391
23391
  isIntentionalCleanupStopEntry: () => isIntentionalCleanupStopEntry,
23392
23392
  meshLedgerEvents: () => meshLedgerEvents,
23393
+ normalizeMeshWorkerResult: () => normalizeMeshWorkerResult,
23393
23394
  readLedgerEntries: () => readLedgerEntries,
23394
23395
  readLedgerSlice: () => readLedgerSlice
23395
23396
  });
@@ -23413,6 +23414,86 @@ Follow these recovery rules:
23413
23414
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
23414
23415
  return (0, import_path4.join)(getLedgerDir(), `${safe}.${index}.jsonl`);
23415
23416
  }
23417
+ function readNonEmptyString(value) {
23418
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
23419
+ }
23420
+ function readStringArray(value) {
23421
+ if (!Array.isArray(value)) return [];
23422
+ return value.map((item) => readNonEmptyString(item)).filter(Boolean);
23423
+ }
23424
+ function extractJsonObjectFromSummary(summary) {
23425
+ const text = readNonEmptyString(summary);
23426
+ if (!text) return void 0;
23427
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
23428
+ const candidates = [fenced?.[1], text].filter(Boolean);
23429
+ for (const candidate of candidates) {
23430
+ const trimmed = candidate.trim();
23431
+ if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) continue;
23432
+ try {
23433
+ const parsed = JSON.parse(trimmed);
23434
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
23435
+ } catch {
23436
+ }
23437
+ }
23438
+ return void 0;
23439
+ }
23440
+ function normalizeValidationResults(value) {
23441
+ if (!Array.isArray(value)) return [];
23442
+ return value.filter((item) => item && typeof item === "object" && !Array.isArray(item)).map((item) => {
23443
+ const status = ["passed", "failed", "skipped", "unknown"].includes(item.status) ? item.status : "unknown";
23444
+ return {
23445
+ ...readNonEmptyString(item.command) ? { command: readNonEmptyString(item.command) } : {},
23446
+ status,
23447
+ ...Number.isFinite(Number(item.durationMs)) ? { durationMs: Number(item.durationMs) } : {},
23448
+ ...readNonEmptyString(item.outputPath) ? { outputPath: readNonEmptyString(item.outputPath) } : {},
23449
+ ...readNonEmptyString(item.summary) ? { summary: readNonEmptyString(item.summary) } : {}
23450
+ };
23451
+ });
23452
+ }
23453
+ function normalizeProcessArtifacts(value) {
23454
+ if (!Array.isArray(value)) return [];
23455
+ const kinds = /* @__PURE__ */ new Set(["process", "log", "port", "window", "session", "file", "url", "other"]);
23456
+ return value.filter((item) => item && typeof item === "object" && !Array.isArray(item)).map((item) => ({
23457
+ kind: kinds.has(item.kind) ? item.kind : "other",
23458
+ ...readNonEmptyString(item.id) ? { id: readNonEmptyString(item.id) } : {},
23459
+ ...readNonEmptyString(item.label) ? { label: readNonEmptyString(item.label) } : {},
23460
+ ...readNonEmptyString(item.locator) ? { locator: readNonEmptyString(item.locator) } : {},
23461
+ ...Number.isFinite(Number(item.pid)) ? { pid: Number(item.pid) } : {},
23462
+ ...Number.isFinite(Number(item.port)) ? { port: Number(item.port) } : {},
23463
+ ...readNonEmptyString(item.url) ? { url: readNonEmptyString(item.url) } : {},
23464
+ ...readNonEmptyString(item.path) ? { path: readNonEmptyString(item.path) } : {},
23465
+ ...readNonEmptyString(item.sessionId) ? { sessionId: readNonEmptyString(item.sessionId) } : {},
23466
+ ...typeof item.keepRunning === "boolean" ? { keepRunning: item.keepRunning } : {},
23467
+ ...item.metadata && typeof item.metadata === "object" && !Array.isArray(item.metadata) ? { metadata: item.metadata } : {}
23468
+ }));
23469
+ }
23470
+ function normalizeMeshWorkerResult(input, source = "explicit_metadata") {
23471
+ const raw = input && typeof input === "object" ? input : {};
23472
+ const status = ["completed", "failed", "blocked", "partial", "unknown"].includes(String(raw.status)) ? raw.status : "unknown";
23473
+ const gitStatus = raw.gitStatus && typeof raw.gitStatus === "object" && !Array.isArray(raw.gitStatus) ? raw.gitStatus : void 0;
23474
+ return {
23475
+ status,
23476
+ ...readNonEmptyString(raw.classification) ? { classification: readNonEmptyString(raw.classification) } : {},
23477
+ changedFiles: readStringArray(raw.changedFiles),
23478
+ validationResults: normalizeValidationResults(raw.validationResults),
23479
+ ...gitStatus ? { gitStatus } : {},
23480
+ processArtifacts: normalizeProcessArtifacts(raw.processArtifacts),
23481
+ errors: readStringArray(raw.errors),
23482
+ ...readNonEmptyString(raw.nextAction) ? { nextAction: readNonEmptyString(raw.nextAction) } : {},
23483
+ requiresUserAction: raw.requiresUserAction === true,
23484
+ source
23485
+ };
23486
+ }
23487
+ function resolveWorkerResult(opts) {
23488
+ if (opts.workerResult && typeof opts.workerResult === "object") {
23489
+ return normalizeMeshWorkerResult(opts.workerResult, "explicit_metadata");
23490
+ }
23491
+ const parsed = extractJsonObjectFromSummary(opts.finalSummary);
23492
+ if (parsed) {
23493
+ return normalizeMeshWorkerResult(parsed, "final_summary_json");
23494
+ }
23495
+ return normalizeMeshWorkerResult(void 0, "default");
23496
+ }
23416
23497
  function buildTaskCompletionEvidence(opts) {
23417
23498
  const providerSessionId = opts.providerSessionId?.trim() || void 0;
23418
23499
  const providerType = opts.providerType?.trim() || void 0;
@@ -23429,6 +23510,7 @@ Follow these recovery rules:
23429
23510
  providerSessionId,
23430
23511
  finalSummaryAvailable: typeof opts.finalSummary === "string" && opts.finalSummary.trim().length > 0
23431
23512
  },
23513
+ workerResult: resolveWorkerResult(opts),
23432
23514
  git: {
23433
23515
  status: "deferred",
23434
23516
  reason: "ordinary_completion_git_status_not_checked"
@@ -23734,16 +23816,45 @@ Follow these recovery rules:
23734
23816
  __export2(mesh_work_queue_exports, {
23735
23817
  ACTIVE_MESH_QUEUE_STATUSES: () => ACTIVE_MESH_QUEUE_STATUSES,
23736
23818
  HISTORICAL_MESH_QUEUE_STATUSES: () => HISTORICAL_MESH_QUEUE_STATUSES,
23819
+ MESH_TASK_MODES: () => MESH_TASK_MODES,
23737
23820
  cancelTask: () => cancelTask,
23738
23821
  claimNextTask: () => claimNextTask,
23739
23822
  enqueueTask: () => enqueueTask,
23740
23823
  getMeshQueueStats: () => getMeshQueueStats,
23741
23824
  getQueue: () => getQueue,
23825
+ normalizeMeshTaskMode: () => normalizeMeshTaskMode,
23742
23826
  recordTaskAutoLaunch: () => recordTaskAutoLaunch,
23743
23827
  requeueTask: () => requeueTask,
23744
23828
  updateSessionTaskStatus: () => updateSessionTaskStatus,
23745
- updateTaskStatus: () => updateTaskStatus
23829
+ updateTaskStatus: () => updateTaskStatus,
23830
+ validateMeshTaskModeRequest: () => validateMeshTaskModeRequest
23746
23831
  });
23832
+ function normalizeMeshTaskMode(value) {
23833
+ if (typeof value !== "string") return void 0;
23834
+ const normalized = value.trim();
23835
+ return MESH_TASK_MODES.includes(normalized) ? normalized : void 0;
23836
+ }
23837
+ function validateMeshTaskModeRequest(mode, message) {
23838
+ const taskMode = normalizeMeshTaskMode(mode);
23839
+ if (!taskMode) {
23840
+ return { valid: true, violations: [] };
23841
+ }
23842
+ if (taskMode !== "live_debug_readonly") {
23843
+ return { valid: true, taskMode, violations: [] };
23844
+ }
23845
+ const violations = LIVE_DEBUG_READONLY_FORBIDDEN.filter((rule) => rule.pattern.test(message || "")).map((rule) => rule.label);
23846
+ return {
23847
+ valid: violations.length === 0,
23848
+ taskMode,
23849
+ violations,
23850
+ allowedOperations: [
23851
+ "process/log/window/port/session inspection",
23852
+ "read-only filesystem listing/reading",
23853
+ "status probes and keep-running handle reporting",
23854
+ "diagnostic summaries without source edits, commits, checkpoints, pushes, deploys, resets, rebases, or destructive cleanups"
23855
+ ]
23856
+ };
23857
+ }
23747
23858
  function getQueuePath(meshId) {
23748
23859
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
23749
23860
  return (0, import_path5.join)(getLedgerDir(), `${safe}.queue.json`);
@@ -23794,6 +23905,10 @@ Follow these recovery rules:
23794
23905
  }
23795
23906
  function enqueueTask(meshId, message, opts) {
23796
23907
  requireMeshHostQueueOwner(opts);
23908
+ const modeValidation = validateMeshTaskModeRequest(opts?.taskMode, message);
23909
+ if (!modeValidation.valid) {
23910
+ throw new Error(`live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`);
23911
+ }
23797
23912
  return withQueueLock(meshId, () => {
23798
23913
  const queue = readQueue(meshId);
23799
23914
  const entry = {
@@ -23801,6 +23916,7 @@ Follow these recovery rules:
23801
23916
  meshId,
23802
23917
  message,
23803
23918
  status: "pending",
23919
+ taskMode: modeValidation.taskMode,
23804
23920
  targetNodeId: opts?.targetNodeId,
23805
23921
  targetSessionId: opts?.targetSessionId,
23806
23922
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -23967,6 +24083,8 @@ Follow these recovery rules:
23967
24083
  var import_crypto5;
23968
24084
  var ACTIVE_MESH_QUEUE_STATUSES;
23969
24085
  var HISTORICAL_MESH_QUEUE_STATUSES;
24086
+ var MESH_TASK_MODES;
24087
+ var LIVE_DEBUG_READONLY_FORBIDDEN;
23970
24088
  var init_mesh_work_queue = __esm2({
23971
24089
  "src/mesh/mesh-work-queue.ts"() {
23972
24090
  "use strict";
@@ -23977,6 +24095,14 @@ Follow these recovery rules:
23977
24095
  init_mesh_host_ownership();
23978
24096
  ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
23979
24097
  HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
24098
+ MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
24099
+ LIVE_DEBUG_READONLY_FORBIDDEN = [
24100
+ { label: "source_edit", pattern: /\b(edit|modify|patch|apply\s+patch|write\s+(?:to\s+)?(?:file|source)|overwrite|delete\s+file|remove\s+file|create\s+file|touch\s+file)\b/i },
24101
+ { label: "git_mutation", pattern: /\b(?:git\s+(?:add|commit|push|reset|rebase|clean|checkout|switch|merge|tag|restore|rm|mv)|push\b)/i },
24102
+ { label: "checkpoint", pattern: /\b(checkpoint|mesh_checkpoint)\b/i },
24103
+ { label: "deploy_or_version_bump", pattern: /\b(deploy|wrangler\s+deploy|version[-\s]?bump|npm\s+version|release)\b/i },
24104
+ { label: "destructive_shell", pattern: /\b(rm\s+-rf|mv\s+\S+\s+\S+|truncate\s|tee\s+\S+|sed\s+-i)\b/i }
24105
+ ];
23980
24106
  }
23981
24107
  });
23982
24108
  function parseVersion(raw) {
@@ -24357,6 +24483,9 @@ Follow these recovery rules:
24357
24483
  triggerMeshQueue: () => triggerMeshQueue,
24358
24484
  tryAssignQueueTask: () => tryAssignQueueTask
24359
24485
  });
24486
+ function readWorkerResultMetadata(event) {
24487
+ return readRecord(event.workerResult) || readRecord(event.meshWorkerResult) || readRecord(event.structuredResult);
24488
+ }
24360
24489
  function sweepExpiredRemoteIdleSessions() {
24361
24490
  const now = Date.now();
24362
24491
  for (const [key, session] of remoteIdleSessions) {
@@ -24422,20 +24551,28 @@ Follow these recovery rules:
24422
24551
  } catch {
24423
24552
  }
24424
24553
  }
24425
- function readNonEmptyString(value) {
24554
+ function readNonEmptyString2(value) {
24426
24555
  return typeof value === "string" && value.trim() ? value.trim() : "";
24427
24556
  }
24557
+ function readRecord(value) {
24558
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
24559
+ }
24428
24560
  function resolveEventSessionId(event, fallback) {
24429
- return readNonEmptyString(event.targetSessionId) || readNonEmptyString(event.sessionId) || readNonEmptyString(event.instanceId) || readNonEmptyString(fallback);
24561
+ return readNonEmptyString2(event.targetSessionId) || readNonEmptyString2(event.sessionId) || readNonEmptyString2(event.instanceId) || readNonEmptyString2(fallback);
24430
24562
  }
24431
24563
  function isMeshCoordinatorEvent(eventName) {
24432
24564
  return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
24433
24565
  }
24434
24566
  function formatCompletionMetadata(event) {
24567
+ const completionDiagnostic = event.completionDiagnostic && typeof event.completionDiagnostic === "object" ? event.completionDiagnostic : null;
24568
+ const diagnosticReason = completionDiagnostic ? readNonEmptyString2(completionDiagnostic.blockReason) || "present" : "";
24569
+ const finalAssistantPresent = typeof completionDiagnostic?.finalAssistantPresent === "boolean" ? String(completionDiagnostic.finalAssistantPresent) : "";
24435
24570
  const parts = [
24436
- readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
24437
- readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
24438
- readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
24571
+ readNonEmptyString2(event.targetSessionId) ? `session_id=${readNonEmptyString2(event.targetSessionId)}` : "",
24572
+ readNonEmptyString2(event.providerType) ? `provider=${readNonEmptyString2(event.providerType)}` : "",
24573
+ readNonEmptyString2(event.providerSessionId) ? `provider_session_id=${readNonEmptyString2(event.providerSessionId)}` : "",
24574
+ diagnosticReason ? `completion_diagnostic=${diagnosticReason}` : "",
24575
+ finalAssistantPresent ? `final_assistant=${finalAssistantPresent}` : ""
24439
24576
  ].filter(Boolean);
24440
24577
  return parts.length > 0 ? ` (${parts.join("; ")})` : "";
24441
24578
  }
@@ -24477,7 +24614,7 @@ Follow these recovery rules:
24477
24614
  return null;
24478
24615
  }
24479
24616
  function buildMeshCompletionFingerprint(args) {
24480
- const timestampPart = Number.isFinite(args.timestamp) ? String(args.timestamp) : readNonEmptyString(args.finalSummary).slice(0, 200);
24617
+ const timestampPart = Number.isFinite(args.timestamp) ? String(args.timestamp) : readNonEmptyString2(args.finalSummary).slice(0, 200);
24481
24618
  return [
24482
24619
  args.meshId,
24483
24620
  args.event,
@@ -24555,7 +24692,7 @@ Follow these recovery rules:
24555
24692
  return ["stopped", "failed", "terminated", "exited", "closed"].includes(status);
24556
24693
  }
24557
24694
  function isIdleSessionState(state) {
24558
- const status = readNonEmptyString(state?.status).toLowerCase();
24695
+ const status = readNonEmptyString2(state?.status).toLowerCase();
24559
24696
  if (isTerminalSessionStatus(status)) return false;
24560
24697
  return status === "idle" || state?.activeChat?.status === "waiting_input";
24561
24698
  }
@@ -24564,15 +24701,15 @@ Follow these recovery rules:
24564
24701
  }
24565
24702
  function isLaunchableNode(node) {
24566
24703
  if (!node || node.status === "disabled" || node.status === "removed") return false;
24567
- const health = readNonEmptyString(node.health).toLowerCase();
24704
+ const health = readNonEmptyString2(node.health).toLowerCase();
24568
24705
  if (!health) return true;
24569
24706
  return health === "online" || health === "unknown";
24570
24707
  }
24571
24708
  function localAutoLaunchSkipReason(node) {
24572
- const daemonId = readNonEmptyString(node?.daemonId);
24573
- const machineId = readNonEmptyString(node?.machineId);
24709
+ const daemonId = readNonEmptyString2(node?.daemonId);
24710
+ const machineId = readNonEmptyString2(node?.machineId);
24574
24711
  const appConfig = loadConfig2();
24575
- const localMachineId = readNonEmptyString(appConfig.machineId) || readNonEmptyString(appConfig.registeredMachineId);
24712
+ const localMachineId = readNonEmptyString2(appConfig.machineId) || readNonEmptyString2(appConfig.registeredMachineId);
24576
24713
  const cloudDaemonId = localMachineId ? `daemon_${localMachineId}` : "";
24577
24714
  const standaloneDaemonId = localMachineId ? `standalone_${localMachineId}` : "";
24578
24715
  const daemonMatchesLocal = !daemonId || daemonId === cloudDaemonId || daemonId === standaloneDaemonId;
@@ -24595,10 +24732,10 @@ Follow these recovery rules:
24595
24732
  return components.instanceManager.getByCategory("cli").filter((inst) => {
24596
24733
  const state = inst.getState();
24597
24734
  const settings = state.settings || {};
24598
- if (readNonEmptyString(settings.meshNodeFor) !== meshId) return false;
24599
- const instNodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
24735
+ if (readNonEmptyString2(settings.meshNodeFor) !== meshId) return false;
24736
+ const instNodeId = readNonEmptyString2(settings.meshNodeId) || readNonEmptyString2(settings.nodeId);
24600
24737
  if (instNodeId !== nodeId) return false;
24601
- const status = readNonEmptyString(state.status).toLowerCase();
24738
+ const status = readNonEmptyString2(state.status).toLowerCase();
24602
24739
  return !isTerminalSessionStatus(status);
24603
24740
  }).length;
24604
24741
  }
@@ -24690,7 +24827,7 @@ Follow these recovery rules:
24690
24827
  continue;
24691
24828
  }
24692
24829
  for (const node of candidateNodes) {
24693
- const nodeId = readNonEmptyString(node?.id);
24830
+ const nodeId = readNonEmptyString2(node?.id);
24694
24831
  if (!nodeId) continue;
24695
24832
  const launchKey = `${meshId}:${nodeId}`;
24696
24833
  const cooldownUntil = autoLaunchCooldownUntil.get(launchKey) || 0;
@@ -24749,7 +24886,7 @@ Follow these recovery rules:
24749
24886
  autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
24750
24887
  return false;
24751
24888
  }
24752
- const sessionId = readNonEmptyString(launchResult.sessionId) || readNonEmptyString(launchResult.id) || readNonEmptyString(launchResult.runtimeSessionId);
24889
+ const sessionId = readNonEmptyString2(launchResult.sessionId) || readNonEmptyString2(launchResult.id) || readNonEmptyString2(launchResult.runtimeSessionId);
24753
24890
  if (!sessionId) {
24754
24891
  markAutoLaunch(meshId, task.id, { status: "failed", reason: "launch_missing_session_id", nodeId, providerType: resolved.providerType });
24755
24892
  autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
@@ -24776,13 +24913,13 @@ Follow these recovery rules:
24776
24913
  for (const inst of cliInstances) {
24777
24914
  const state = inst.getState();
24778
24915
  const settings = state.settings || {};
24779
- const instMeshId = readNonEmptyString(settings.meshNodeFor);
24916
+ const instMeshId = readNonEmptyString2(settings.meshNodeFor);
24780
24917
  if (instMeshId !== meshId) continue;
24781
- const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
24918
+ const nodeId = readNonEmptyString2(settings.meshNodeId) || readNonEmptyString2(settings.nodeId);
24782
24919
  if (!nodeId) continue;
24783
24920
  if (!isIdleSessionState(state)) continue;
24784
24921
  const sessionId = state.instanceId;
24785
- const providerType = state.type || readNonEmptyString(settings.providerType);
24922
+ const providerType = state.type || readNonEmptyString2(settings.providerType);
24786
24923
  if (providerType) {
24787
24924
  tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
24788
24925
  }
@@ -24844,7 +24981,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24844
24981
  }
24845
24982
  function injectMeshSystemMessage(components, args) {
24846
24983
  const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
24847
- const eventNodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
24984
+ const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
24848
24985
  const intentionalCleanupStop = shouldSuppressIntentionalCleanupStop({
24849
24986
  event: args.event,
24850
24987
  meshId: args.meshId,
@@ -24865,10 +25002,10 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24865
25002
  meshId: args.meshId,
24866
25003
  event: args.event,
24867
25004
  sessionId: eventSessionId,
24868
- providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
24869
- providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
25005
+ providerType: readNonEmptyString2(args.metadataEvent.providerType) || void 0,
25006
+ providerSessionId: readNonEmptyString2(args.metadataEvent.providerSessionId) || void 0,
24870
25007
  timestamp: eventTimestamp,
24871
- finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
25008
+ finalSummary: readNonEmptyString2(args.metadataEvent.finalSummary) || void 0
24872
25009
  });
24873
25010
  if (duplicateCompletion) {
24874
25011
  LOG2.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
@@ -24878,8 +25015,8 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24878
25015
  let completedTaskForLedger = null;
24879
25016
  if (args.event === "agent:generating_completed") {
24880
25017
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
24881
- const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
24882
- const providerType = readNonEmptyString(args.metadataEvent.providerType);
25018
+ const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
25019
+ const providerType = readNonEmptyString2(args.metadataEvent.providerType);
24883
25020
  if (sessionId) {
24884
25021
  const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed", {
24885
25022
  occurredAt: eventTimestamp !== null ? new Date(eventTimestamp).toISOString() : void 0
@@ -24893,8 +25030,11 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24893
25030
  }
24894
25031
  } else if (args.event === "agent:ready") {
24895
25032
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
24896
- const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
24897
- const providerType = readNonEmptyString(args.metadataEvent.providerType);
25033
+ const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
25034
+ const providerType = readNonEmptyString2(args.metadataEvent.providerType);
25035
+ const providerSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId) || void 0;
25036
+ const finalSummary = readNonEmptyString2(args.metadataEvent.finalSummary) || void 0;
25037
+ const workerResult = readWorkerResultMetadata(args.metadataEvent);
24898
25038
  const completedTask = sessionId ? updateSessionTaskStatus(args.meshId, sessionId, "completed") : null;
24899
25039
  if (completedTask) {
24900
25040
  completedTaskForLedger = { id: completedTask.id };
@@ -24909,15 +25049,17 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24909
25049
  nodeLabel: args.nodeLabel,
24910
25050
  taskId: completedTask.id,
24911
25051
  completedViaReady: true,
24912
- providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
24913
- finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0,
25052
+ providerSessionId,
25053
+ finalSummary,
25054
+ workerResult,
24914
25055
  evidence: buildTaskCompletionEvidence({
24915
25056
  event: "agent:ready",
24916
25057
  nodeId,
24917
25058
  sessionId,
24918
25059
  providerType: providerType || void 0,
24919
- providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
24920
- finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
25060
+ providerSessionId,
25061
+ finalSummary,
25062
+ workerResult
24921
25063
  })
24922
25064
  }
24923
25065
  });
@@ -24940,13 +25082,13 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24940
25082
  }
24941
25083
  } else if (args.event === "agent:generating_started") {
24942
25084
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
24943
- const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
25085
+ const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
24944
25086
  if (sessionId && nodeId) {
24945
25087
  remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
24946
25088
  }
24947
25089
  } else if (args.event === "agent:stopped") {
24948
25090
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
24949
- const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
25091
+ const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
24950
25092
  if (sessionId && nodeId) {
24951
25093
  remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
24952
25094
  }
@@ -24957,16 +25099,20 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24957
25099
  const ledgerKind = EVENT_TO_LEDGER_KIND[args.event];
24958
25100
  if (ledgerKind) {
24959
25101
  try {
24960
- const ledgerNodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0;
25102
+ const ledgerNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId) || void 0;
24961
25103
  const ledgerSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId) || void 0;
24962
- const ledgerProviderType = readNonEmptyString(args.metadataEvent.providerType) || void 0;
25104
+ const ledgerProviderType = readNonEmptyString2(args.metadataEvent.providerType) || void 0;
25105
+ const providerSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId) || void 0;
25106
+ const finalSummary = readNonEmptyString2(args.metadataEvent.finalSummary) || void 0;
25107
+ const workerResult = readWorkerResultMetadata(args.metadataEvent);
24963
25108
  const completionEvidence = ledgerKind === "task_completed" && ledgerNodeId && ledgerSessionId ? buildTaskCompletionEvidence({
24964
25109
  event: "agent:generating_completed",
24965
25110
  nodeId: ledgerNodeId,
24966
25111
  sessionId: ledgerSessionId,
24967
25112
  providerType: ledgerProviderType,
24968
- providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
24969
- finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
25113
+ providerSessionId,
25114
+ finalSummary,
25115
+ workerResult
24970
25116
  }) : void 0;
24971
25117
  appendLedgerEntry(args.meshId, {
24972
25118
  kind: ledgerKind,
@@ -24977,8 +25123,10 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24977
25123
  event: args.event,
24978
25124
  nodeLabel: args.nodeLabel,
24979
25125
  taskId: completedTaskForLedger?.id || void 0,
24980
- providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
24981
- finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0,
25126
+ providerSessionId,
25127
+ finalSummary,
25128
+ workerResult,
25129
+ completionDiagnostic: args.metadataEvent.completionDiagnostic && typeof args.metadataEvent.completionDiagnostic === "object" ? args.metadataEvent.completionDiagnostic : void 0,
24982
25130
  evidence: completionEvidence
24983
25131
  }
24984
25132
  });
@@ -24993,10 +25141,10 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24993
25141
  const maxRetries = mesh?.policy?.maxTaskRetries ?? 1;
24994
25142
  recoveryContext = getSessionRecoveryContext(args.meshId, {
24995
25143
  sessionId: resolveEventSessionId(args.metadataEvent, args.sourceInstanceId) || void 0,
24996
- nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
25144
+ nodeId: readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId) || void 0,
24997
25145
  maxRetries
24998
25146
  });
24999
- recoveryContext.failedProviderType = readNonEmptyString(args.metadataEvent.providerType) || null;
25147
+ recoveryContext.failedProviderType = readNonEmptyString2(args.metadataEvent.providerType) || null;
25000
25148
  if (recoveryContext.retryRecommended && recoveryContext.consecutiveNodeFailures > 0) {
25001
25149
  appendLedgerEntry(args.meshId, {
25002
25150
  kind: "recovery_attempted",
@@ -25052,7 +25200,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25052
25200
  meshId: args.meshId,
25053
25201
  nodeLabel: args.nodeLabel,
25054
25202
  nodeId: args.nodeId || void 0,
25055
- workspace: readNonEmptyString(args.metadataEvent.workspace),
25203
+ workspace: readNonEmptyString2(args.metadataEvent.workspace),
25056
25204
  metadataEvent: {
25057
25205
  ...args.metadataEvent,
25058
25206
  ...recoveryContext ? { recoveryContext } : {}
@@ -25078,14 +25226,14 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25078
25226
  return { success: true, forwarded: coordinatorInstances.length };
25079
25227
  }
25080
25228
  function handleMeshForwardEvent(components, payload) {
25081
- const eventName = readNonEmptyString(payload.event);
25229
+ const eventName = readNonEmptyString2(payload.event);
25082
25230
  if (!isMeshCoordinatorEvent(eventName)) {
25083
25231
  return { success: false, error: "unsupported mesh event" };
25084
25232
  }
25085
- const meshId = readNonEmptyString(payload.meshId);
25233
+ const meshId = readNonEmptyString2(payload.meshId);
25086
25234
  if (!meshId) return { success: false, error: "meshId required" };
25087
- const nodeId = readNonEmptyString(payload.nodeId);
25088
- const workspace = readNonEmptyString(payload.workspace);
25235
+ const nodeId = readNonEmptyString2(payload.nodeId);
25236
+ const workspace = readNonEmptyString2(payload.workspace);
25089
25237
  const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
25090
25238
  return injectMeshSystemMessage(components, {
25091
25239
  meshId,
@@ -25093,41 +25241,41 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25093
25241
  nodeLabel,
25094
25242
  event: eventName,
25095
25243
  metadataEvent: {
25096
- targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId) || readNonEmptyString(payload.instanceId),
25097
- providerType: readNonEmptyString(payload.providerType),
25098
- providerSessionId: readNonEmptyString(payload.providerSessionId),
25099
- finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary),
25244
+ targetSessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId) || readNonEmptyString2(payload.instanceId),
25245
+ providerType: readNonEmptyString2(payload.providerType),
25246
+ providerSessionId: readNonEmptyString2(payload.providerSessionId),
25247
+ finalSummary: readNonEmptyString2(payload.finalSummary) || readNonEmptyString2(payload.summary),
25100
25248
  ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
25101
25249
  intentional: payload.intentional === true,
25102
25250
  intentionalStop: payload.intentionalStop === true,
25103
25251
  operatorCleanup: payload.operatorCleanup === true,
25104
- reason: readNonEmptyString(payload.reason),
25105
- stopReason: readNonEmptyString(payload.stopReason),
25106
- cleanupReason: readNonEmptyString(payload.cleanupReason),
25107
- source: readNonEmptyString(payload.source)
25252
+ reason: readNonEmptyString2(payload.reason),
25253
+ stopReason: readNonEmptyString2(payload.stopReason),
25254
+ cleanupReason: readNonEmptyString2(payload.cleanupReason),
25255
+ source: readNonEmptyString2(payload.source)
25108
25256
  }
25109
25257
  });
25110
25258
  }
25111
25259
  function setupMeshEventForwarding(components) {
25112
25260
  components.instanceManager.onEvent((event) => {
25113
25261
  if (!isMeshCoordinatorEvent(event.event)) return;
25114
- const instanceId = readNonEmptyString(event.instanceId);
25262
+ const instanceId = readNonEmptyString2(event.instanceId);
25115
25263
  if (!instanceId) return;
25116
25264
  const sourceInstance = components.instanceManager.getInstance(instanceId);
25117
25265
  if (!sourceInstance || sourceInstance.category !== "cli") return;
25118
25266
  const state = sourceInstance.getState();
25119
- const workspace = readNonEmptyString(state.workspace);
25267
+ const workspace = readNonEmptyString2(state.workspace);
25120
25268
  if (!workspace) return;
25121
25269
  const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
25122
- if (readNonEmptyString(settings.meshCoordinatorFor)) return;
25123
- const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
25270
+ if (readNonEmptyString2(settings.meshCoordinatorFor)) return;
25271
+ const meshIdFromRuntime = readNonEmptyString2(settings.meshNodeFor);
25124
25272
  const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
25125
25273
  if (!isMeshDelegate) return;
25126
25274
  const mesh = meshIdFromRuntime ? getMeshWithCache(components, meshIdFromRuntime) : getMeshByRepo(workspace);
25127
- const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
25275
+ const meshId = meshIdFromRuntime || readNonEmptyString2(mesh?.id);
25128
25276
  if (!meshId) return;
25129
25277
  const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
25130
- const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
25278
+ const runtimeNodeId = readNonEmptyString2(settings.meshNodeId);
25131
25279
  const resolvedNodeId = targetNode?.id || runtimeNodeId;
25132
25280
  const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
25133
25281
  injectMeshSystemMessage(components, {
@@ -26067,7 +26215,9 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
26067
26215
  const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
26068
26216
  const binaryPath = findBinary(configuredCommand);
26069
26217
  const isWin = os10.platform() === "win32";
26070
- const allArgs = [...spawnConfig.args, ...extraArgs];
26218
+ const allArgs = [...spawnConfig.args, ...extraArgs].map(
26219
+ (arg) => typeof arg === "string" ? arg.replace(/\{\{workingDir\}\}/g, workingDir) : arg
26220
+ );
26071
26221
  let shellCmd;
26072
26222
  let shellArgs;
26073
26223
  const useShellUnix = !isWin && (!!spawnConfig.shell || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
@@ -28324,6 +28474,8 @@ ${lastSnapshot}`;
28324
28474
  buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
28325
28475
  buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
28326
28476
  buildMachineInfo: () => buildMachineInfo2,
28477
+ buildMeshActiveWork: () => buildMeshActiveWork,
28478
+ buildMeshActiveWorkSummary: () => buildMeshActiveWorkSummary,
28327
28479
  buildMeshHostRequiredFailure: () => buildMeshHostRequiredFailure,
28328
28480
  buildMeshLedgerReconciliationEvidence: () => buildMeshLedgerReconciliationEvidence,
28329
28481
  buildMeshLedgerReplicaEvidence: () => buildMeshLedgerReplicaEvidence,
@@ -28334,6 +28486,7 @@ ${lastSnapshot}`;
28334
28486
  buildSessionModalDeliverySignature: () => buildSessionModalDeliverySignature,
28335
28487
  buildStatusSnapshot: () => buildStatusSnapshot2,
28336
28488
  buildSystemChatMessage: () => buildSystemChatMessage,
28489
+ buildTaskCompletionEvidence: () => buildTaskCompletionEvidence,
28337
28490
  buildTerminalChatMessage: () => buildTerminalChatMessage,
28338
28491
  buildThoughtChatMessage: () => buildThoughtChatMessage,
28339
28492
  buildToolChatMessage: () => buildToolChatMessage,
@@ -28444,6 +28597,8 @@ ${lastSnapshot}`;
28444
28597
  normalizeInputEnvelope: () => normalizeInputEnvelope,
28445
28598
  normalizeManagedStatus: () => normalizeManagedStatus,
28446
28599
  normalizeMeshDaemonRole: () => normalizeMeshDaemonRole,
28600
+ normalizeMeshTaskMode: () => normalizeMeshTaskMode,
28601
+ normalizeMeshWorkerResult: () => normalizeMeshWorkerResult,
28447
28602
  normalizeMessageParts: () => normalizeMessageParts,
28448
28603
  normalizeRepoIdentity: () => normalizeRepoIdentity,
28449
28604
  normalizeSessionModalFields: () => normalizeSessionModalFields,
@@ -28499,7 +28654,8 @@ ${lastSnapshot}`;
28499
28654
  updateSessionTaskStatus: () => updateSessionTaskStatus,
28500
28655
  updateTaskStatus: () => updateTaskStatus,
28501
28656
  upsertSavedProviderSession: () => upsertSavedProviderSession,
28502
- validateMeshRefineConfig: () => validateMeshRefineConfig
28657
+ validateMeshRefineConfig: () => validateMeshRefineConfig,
28658
+ validateMeshTaskModeRequest: () => validateMeshTaskModeRequest
28503
28659
  });
28504
28660
  module2.exports = __toCommonJS2(index_exports);
28505
28661
  init_repo_mesh_types();
@@ -30888,6 +31044,148 @@ ${lastSnapshot}`;
30888
31044
  };
30889
31045
  }
30890
31046
  init_mesh_work_queue();
31047
+ var DIRECT_DISPATCH_VIA = /* @__PURE__ */ new Set(["p2p_direct", "local_direct", "mesh_send_task"]);
31048
+ var TERMINAL_LEDGER_KINDS = /* @__PURE__ */ new Set(["task_completed", "task_failed", "task_stalled"]);
31049
+ function readString2(value) {
31050
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
31051
+ }
31052
+ function summarizeMessage(message) {
31053
+ const oneLine = message.replace(/\s+/g, " ").trim();
31054
+ const title = oneLine.length > 96 ? `${oneLine.slice(0, 93)}...` : oneLine;
31055
+ return { title: title || "(untitled task)", summary: oneLine };
31056
+ }
31057
+ function elapsedSince(value, now) {
31058
+ const started = value ? new Date(value).getTime() : Number.NaN;
31059
+ return Number.isFinite(started) ? Math.max(0, now - started) : 0;
31060
+ }
31061
+ function sessionStatusFromNodes(nodes, nodeId, sessionId) {
31062
+ if (!nodeId || !sessionId || !Array.isArray(nodes)) return void 0;
31063
+ const node = nodes.find((item) => readString2(item?.id) === nodeId || readString2(item?.nodeId) === nodeId || readString2(item?.node_id) === nodeId);
31064
+ if (!node) return void 0;
31065
+ const candidates = [];
31066
+ for (const value of [node.sessions, node.activeSessions, node.active_sessions, node.lastProbe?.sessions, node.last_probe?.sessions, node.lastProbe?.status?.sessions, node.last_probe?.status?.sessions]) {
31067
+ if (Array.isArray(value)) candidates.push(...value);
31068
+ }
31069
+ for (const value of [node.activeSession, node.active_session, node.currentSession, node.current_session, node.runtimeSession, node.runtime_session, node.session]) {
31070
+ if (value && typeof value === "object") candidates.push(value);
31071
+ }
31072
+ const session = candidates.find((item) => {
31073
+ const id = readString2(item?.id) || readString2(item?.sessionId) || readString2(item?.session_id) || readString2(item?.runtimeSessionId) || readString2(item?.instanceId);
31074
+ return id === sessionId;
31075
+ });
31076
+ if (!session) return void 0;
31077
+ const raw = `${readString2(session.status) || ""} ${readString2(session.lifecycle) || ""} ${readString2(session.state) || ""} ${readString2(session.activeChat?.status) || ""}`.toLowerCase();
31078
+ if (raw.includes("approval")) return "awaiting_approval";
31079
+ if (raw.includes("generating") || raw.includes("running") || raw.includes("busy")) return "generating";
31080
+ if (raw.includes("failed") || raw.includes("stopped") || raw.includes("terminated") || raw.includes("exited")) return "failed";
31081
+ if (raw.includes("idle") || raw.includes("waiting_input") || raw.includes("ready")) return "idle";
31082
+ return void 0;
31083
+ }
31084
+ function isDirectDispatch(entry) {
31085
+ if (entry.kind !== "task_dispatched") return false;
31086
+ const payload = entry.payload || {};
31087
+ if (payload.source === "direct") return true;
31088
+ const via = readString2(payload.via);
31089
+ return Boolean(via && DIRECT_DISPATCH_VIA.has(via) && payload.source !== "queue");
31090
+ }
31091
+ function directDispatchTaskId(entry) {
31092
+ return readString2(entry.payload?.taskId) || entry.id;
31093
+ }
31094
+ function terminalMatchesDispatch(terminal, dispatch, taskId) {
31095
+ const terminalTaskId = readString2(terminal.payload?.taskId);
31096
+ if (terminalTaskId && terminalTaskId === taskId) return true;
31097
+ if (terminalTaskId && terminalTaskId !== taskId) return false;
31098
+ if (dispatch.sessionId && terminal.sessionId === dispatch.sessionId) return true;
31099
+ return Boolean(dispatch.nodeId && terminal.nodeId === dispatch.nodeId && !dispatch.sessionId);
31100
+ }
31101
+ function statusFromTerminal(entry) {
31102
+ if (entry.kind === "task_approval_needed") return "awaiting_approval";
31103
+ if (entry.kind === "task_completed") return "idle";
31104
+ return "failed";
31105
+ }
31106
+ function buildMeshActiveWorkSummary(activeWork) {
31107
+ const statusCounts = {
31108
+ pending: 0,
31109
+ assigned: 0,
31110
+ generating: 0,
31111
+ idle: 0,
31112
+ failed: 0,
31113
+ awaiting_approval: 0
31114
+ };
31115
+ const sourceCounts = { queue: 0, direct: 0 };
31116
+ for (const item of activeWork) {
31117
+ sourceCounts[item.source] += 1;
31118
+ statusCounts[item.status] += 1;
31119
+ }
31120
+ return {
31121
+ totalActiveCount: activeWork.length,
31122
+ queueActiveCount: sourceCounts.queue,
31123
+ directActiveCount: sourceCounts.direct,
31124
+ awaitingApprovalCount: statusCounts.awaiting_approval,
31125
+ generatingCount: statusCounts.generating,
31126
+ failedCount: statusCounts.failed,
31127
+ idleCount: statusCounts.idle,
31128
+ sourceCounts,
31129
+ statusCounts
31130
+ };
31131
+ }
31132
+ function buildMeshActiveWork(opts) {
31133
+ const now = opts.now ?? Date.now();
31134
+ const records = [];
31135
+ for (const task of opts.queue || []) {
31136
+ if (task.status !== "pending" && task.status !== "assigned") continue;
31137
+ const { title, summary } = summarizeMessage(task.message || "");
31138
+ records.push({
31139
+ taskId: task.id,
31140
+ source: "queue",
31141
+ status: task.status,
31142
+ nodeId: task.assignedNodeId || task.targetNodeId,
31143
+ sessionId: task.assignedSessionId || task.targetSessionId,
31144
+ taskTitle: title,
31145
+ taskSummary: summary,
31146
+ message: task.message,
31147
+ taskMode: task.taskMode,
31148
+ createdAt: task.createdAt,
31149
+ updatedAt: task.updatedAt,
31150
+ dispatchedAt: task.dispatchTimestamp,
31151
+ elapsedMs: elapsedSince(task.dispatchTimestamp || task.createdAt, now)
31152
+ });
31153
+ }
31154
+ const ledgerEntries = (opts.ledgerEntries || []).slice().sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
31155
+ const terminals = ledgerEntries.filter((entry) => TERMINAL_LEDGER_KINDS.has(entry.kind) || entry.kind === "task_approval_needed");
31156
+ for (const dispatch of ledgerEntries.filter(isDirectDispatch)) {
31157
+ const taskId = directDispatchTaskId(dispatch);
31158
+ const terminal = terminals.filter((entry) => new Date(entry.timestamp).getTime() >= new Date(dispatch.timestamp).getTime()).find((entry) => terminalMatchesDispatch(entry, dispatch, taskId));
31159
+ const terminalStatus = terminal ? statusFromTerminal(terminal) : void 0;
31160
+ const liveStatus = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
31161
+ const status = terminalStatus || liveStatus || "assigned";
31162
+ const terminalRow = Boolean(terminal && terminal.kind !== "task_approval_needed");
31163
+ if (terminalRow && opts.includeTerminalDirect !== true) continue;
31164
+ const message = readString2(dispatch.payload?.message) || readString2(dispatch.payload?.summary) || "";
31165
+ const { title, summary } = summarizeMessage(message);
31166
+ records.push({
31167
+ taskId,
31168
+ source: "direct",
31169
+ status,
31170
+ nodeId: dispatch.nodeId,
31171
+ sessionId: dispatch.sessionId,
31172
+ providerType: dispatch.providerType || readString2(dispatch.payload?.providerType),
31173
+ taskTitle: readString2(dispatch.payload?.taskTitle) || title,
31174
+ taskSummary: readString2(dispatch.payload?.taskSummary) || summary,
31175
+ message,
31176
+ taskMode: readString2(dispatch.payload?.taskMode),
31177
+ createdAt: dispatch.timestamp,
31178
+ updatedAt: terminal?.timestamp || dispatch.timestamp,
31179
+ dispatchedAt: dispatch.timestamp,
31180
+ elapsedMs: elapsedSince(dispatch.timestamp, now),
31181
+ terminal: terminalRow,
31182
+ terminalKind: terminal?.kind,
31183
+ terminalAt: terminal?.timestamp
31184
+ });
31185
+ }
31186
+ records.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
31187
+ return { activeWork: records, summary: buildMeshActiveWorkSummary(records) };
31188
+ }
30891
31189
  init_mesh_host_ownership();
30892
31190
  init_mesh_events();
30893
31191
  var NO_FALLBACK_REASON = "Repo Mesh command/data-plane is P2P-only; WS/REST command fallback is intentionally disabled to preserve the transport boundary.";
@@ -40787,6 +41085,44 @@ ${effect.notification.body || ""}`.trim();
40787
41085
  const content = lastVisible ? flattenContent(lastVisible.content).trim() : "";
40788
41086
  return role === "assistant" && !!content;
40789
41087
  }
41088
+ buildCompletedFinalizationDiagnostic(args) {
41089
+ let parsed = null;
41090
+ let parseError;
41091
+ try {
41092
+ parsed = this.adapter.getScriptParsedStatus();
41093
+ } catch (error48) {
41094
+ parseError = error48?.message || String(error48);
41095
+ }
41096
+ const visibleMessages = (Array.isArray(parsed?.messages) ? parsed.messages : []).filter((message) => isUserFacingChatMessage(message));
41097
+ const lastVisible = visibleMessages[visibleMessages.length - 1];
41098
+ const lastVisibleRole = typeof lastVisible?.role === "string" ? lastVisible.role.trim().toLowerCase() : null;
41099
+ const lastVisibleKind = typeof lastVisible?.kind === "string" ? lastVisible.kind : null;
41100
+ const lastVisibleContentLength = lastVisible ? flattenContent(lastVisible.content).trim().length : 0;
41101
+ return {
41102
+ providerType: this.type,
41103
+ sessionId: this.instanceId,
41104
+ providerSessionId: this.providerSessionId || null,
41105
+ workspace: this.workingDir,
41106
+ blockReason: args.blockReason,
41107
+ emittedAfterFinalizationTimeout: args.emittedAfterFinalizationTimeout,
41108
+ waitedMs: args.waitedMs,
41109
+ maxWaitMs: COMPLETED_FINALIZATION_MAX_WAIT_MS,
41110
+ adapterStatus: typeof args.latestStatus?.status === "string" ? args.latestStatus.status : null,
41111
+ latestVisibleStatus: args.latestVisibleStatus,
41112
+ parsedStatus: typeof parsed?.status === "string" ? parsed.status : parseError ? "parse_error" : "unknown",
41113
+ parseError: parseError || void 0,
41114
+ finalAssistantPresent: this.completionHasFinalAssistantMessage(parsed?.messages),
41115
+ visibleMessageCount: visibleMessages.length,
41116
+ lastVisibleRole,
41117
+ lastVisibleKind,
41118
+ lastVisibleContentLength,
41119
+ pendingStartedAt: this.generatingStartedAt || null,
41120
+ pendingFirstObservedAt: args.pending.firstObservedAt,
41121
+ pendingTimestamp: args.pending.timestamp,
41122
+ pendingDurationSec: args.pending.duration,
41123
+ previousBlockReason: args.pending.loggedBlockReason || null
41124
+ };
41125
+ }
40790
41126
  hasAdapterPendingResponse() {
40791
41127
  const adapterAny = this.adapter;
40792
41128
  if (adapterAny?.isWaitingForResponse === true) return true;
@@ -40859,7 +41195,23 @@ ${effect.notification.body || ""}`.trim();
40859
41195
  this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
40860
41196
  return;
40861
41197
  }
40862
- LOG2.warn("CLI", `[${this.type}] suppressed completed event after ${waitedMs}ms without finalized assistant turn (${blockReason})`);
41198
+ const completionDiagnostic = this.buildCompletedFinalizationDiagnostic({
41199
+ blockReason,
41200
+ latestStatus,
41201
+ latestVisibleStatus,
41202
+ waitedMs,
41203
+ pending,
41204
+ emittedAfterFinalizationTimeout: true
41205
+ });
41206
+ LOG2.warn("CLI", `[${this.type}] emitting completed event after ${waitedMs}ms without finalized assistant turn (${blockReason})`);
41207
+ this.pushEvent({
41208
+ event: "agent:generating_completed",
41209
+ chatTitle: pending.chatTitle,
41210
+ duration: pending.duration,
41211
+ timestamp: pending.timestamp,
41212
+ finalSummary: extractFinalSummaryFromMessages(this.adapter?.getScriptParsedStatus()?.messages),
41213
+ completionDiagnostic
41214
+ });
40863
41215
  this.completedDebouncePending = null;
40864
41216
  this.completedDebounceTimer = null;
40865
41217
  this.generatingStartedAt = 0;
@@ -47189,6 +47541,9 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
47189
47541
  const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
47190
47542
  const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
47191
47543
  if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
47544
+ const cachedUpdatedAt = Date.parse(readStringValue(cached2.updatedAt, cached2.updated_at) || "");
47545
+ const incomingUpdatedAt = Date.parse(readStringValue(incoming.updatedAt, incoming.updated_at) || "");
47546
+ const preserveCachedMembership = Number.isFinite(cachedUpdatedAt) && (!Number.isFinite(incomingUpdatedAt) || cachedUpdatedAt > incomingUpdatedAt);
47192
47547
  const cachedById = /* @__PURE__ */ new Map();
47193
47548
  for (const node of cachedNodes) {
47194
47549
  const nodeId = readInlineMeshNodeId(node);
@@ -47197,12 +47552,13 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
47197
47552
  const nodes = incomingNodes.map((incomingNode) => {
47198
47553
  const nodeId = readInlineMeshNodeId(incomingNode);
47199
47554
  const cachedNode = nodeId ? cachedById.get(nodeId) : void 0;
47555
+ if (!cachedNode && preserveCachedMembership) return null;
47200
47556
  if (!cachedNode) return incomingNode;
47201
47557
  if (hasInlineMeshTransientNodeState(incomingNode)) {
47202
47558
  return { ...cachedNode, ...incomingNode };
47203
47559
  }
47204
47560
  return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
47205
- });
47561
+ }).filter(Boolean);
47206
47562
  return {
47207
47563
  ...cached2,
47208
47564
  ...incoming,